aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux
diff options
context:
space:
mode:
authorAndrea Adami <andrea.adami@gmail.com>2010-10-03 18:53:04 +0200
committerAndrea Adami <andrea.adami@gmail.com>2010-10-03 20:58:33 +0200
commit69d8c962b4656e1f8d8a15c510583cead5e7f9a6 (patch)
tree80b07a12c337579efed76d182bc09074f7558827 /recipes/linux
parent65e34b9c63d661a52abcbf952bcc1c7c78a0c8da (diff)
downloadopenembedded-69d8c962b4656e1f8d8a15c510583cead5e7f9a6.tar.gz
opensimpad-kernels: move unmaintained recipes to obsolete
Diffstat (limited to 'recipes/linux')
-rw-r--r--recipes/linux/files/iw240_we18-5.diff421
-rw-r--r--recipes/linux/files/iw241_we16-6.diff667
-rw-r--r--recipes/linux/files/iw249_we17-13.diff768
-rw-r--r--recipes/linux/files/mipv6-1.1-v2.4.25.patch19832
-rw-r--r--recipes/linux/files/mipv6-1.1-v2.4.27.patch19736
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1-jpm1.patch8760
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1.patch39937
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2.patch86979
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/defconfig-simpad1281
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mppe-20040216.patch1225
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/scrolling-area.patch18
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff801
-rw-r--r--recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-pm-updates.patch47
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-mh1.patch1134
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1-jpm1.patch8760
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1.patch40457
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1.patch90901
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/defconfig-simpad1302
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-apm.patch805
-rw-r--r--recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-pm-updates.patch35
-rw-r--r--recipes/linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb10
-rw-r--r--recipes/linux/opensimpad-64+0_2.4.27-vrs1-pxa1-jpm1.bb14
-rw-r--r--recipes/linux/opensimpad/disable-pcmcia-probe.patch17
-rw-r--r--recipes/linux/opensimpad/mkdep.patch16
-rw-r--r--recipes/linux/opensimpad/mmc-spi.patch885
-rw-r--r--recipes/linux/opensimpad/mppe-20040216.patch1225
-rw-r--r--recipes/linux/opensimpad/sa1100-usb-tcl1.patch216
-rw-r--r--recipes/linux/opensimpad/simpad-backlight-if.patch102
-rw-r--r--recipes/linux/opensimpad/simpad-proc-sys-board.patch317
-rw-r--r--recipes/linux/opensimpad/simpad-serial.patch267
-rw-r--r--recipes/linux/opensimpad/simpad-switches-input.patch131
-rw-r--r--recipes/linux/opensimpad/simpad-switches-input2.patch41
-rw-r--r--recipes/linux/opensimpad/simpad-ts-noninput.patch16
-rw-r--r--recipes/linux/opensimpad/sound-volume-reversed.patch16
-rw-r--r--recipes/linux/opensimpad/support-128mb-ram.patch35
-rw-r--r--recipes/linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb87
-rw-r--r--recipes/linux/opensimpad_2.4.27-vrs1-pxa1-jpm1.bb96
37 files changed, 0 insertions, 327357 deletions
diff --git a/recipes/linux/files/iw240_we18-5.diff b/recipes/linux/files/iw240_we18-5.diff
deleted file mode 100644
index f65987588d..0000000000
--- a/recipes/linux/files/iw240_we18-5.diff
+++ /dev/null
@@ -1,421 +0,0 @@
-diff -u -p linux/include/linux/wireless.we17.h linux/include/linux/wireless.h
---- linux/include/linux/wireless.we17.h 2005-05-20 11:25:49.000000000 -0700
-+++ linux/include/linux/wireless.h 2005-05-20 11:29:05.000000000 -0700
-@@ -1,10 +1,10 @@
- /*
- * This file define a set of standard wireless extensions
- *
-- * Version : 17 21.6.04
-+ * Version : 18 12.3.05
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
- */
-
- #ifndef _LINUX_WIRELESS_H
-@@ -82,7 +82,7 @@
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
--#define WIRELESS_EXT 17
-+#define WIRELESS_EXT 18
-
- /*
- * Changes :
-@@ -182,6 +182,21 @@
- * - Document (struct iw_quality *)->updated, add new flags (INVALID)
- * - Wireless Event capability in struct iw_range
- * - Add support for relative TxPower (yick !)
-+ *
-+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
-+ * ----------
-+ * - Add support for WPA/WPA2
-+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
-+ * SIOCGIWENCODEEXT)
-+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
-+ * - Add SIOCSIWMLME
-+ * - Add SIOCSIWPMKSA
-+ * - Add struct iw_range bit field for supported encoding capabilities
-+ * - Add optional scan request parameters for SIOCSIWSCAN
-+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
-+ * related parameters (extensible up to 4096 parameter values)
-+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
-+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
- */
-
- /**************************** CONSTANTS ****************************/
-@@ -256,6 +271,30 @@
- #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
- #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
-
-+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
-+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
-+ * fields. More than one IE may be included in the request. Setting the generic
-+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
-+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
-+ * are required to report the used IE as a wireless event, e.g., when
-+ * associating with an AP. */
-+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
-+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
-+
-+/* WPA : IEEE 802.11 MLME requests */
-+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
-+ * struct iw_mlme */
-+/* WPA : Authentication mode parameters */
-+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
-+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
-+
-+/* WPA : Extended version of encoding configuration */
-+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
-+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
-+
-+/* WPA2 : PMKSA cache management */
-+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
-+
- /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
-
- /* These 32 ioctl are wireless device private, for 16 commands.
-@@ -297,6 +336,34 @@
- #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
- #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
- #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
-+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
-+ * (scan results); This includes id and
-+ * length fields. One IWEVGENIE may
-+ * contain more than one IE. Scan
-+ * results may contain one or more
-+ * IWEVGENIE events. */
-+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
-+ * (struct iw_michaelmicfailure)
-+ */
-+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
-+ * The data includes id and length
-+ * fields and may contain more than one
-+ * IE. This event is required in
-+ * Managed mode if the driver
-+ * generates its own WPA/RSN IE. This
-+ * should be sent just before
-+ * IWEVREGISTERED event for the
-+ * association. */
-+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
-+ * Response. The data includes id and
-+ * length fields and may contain more
-+ * than one IE. This may be sent
-+ * between IWEVASSOCREQIE and
-+ * IWEVREGISTERED events for the
-+ * association. */
-+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
-+ * pre-authentication
-+ * (struct iw_pmkid_cand) */
-
- #define IWEVFIRST 0x8C00
-
-@@ -432,12 +499,94 @@
- #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
- #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
- #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
-+/* struct iw_scan_req scan_type */
-+#define IW_SCAN_TYPE_ACTIVE 0
-+#define IW_SCAN_TYPE_PASSIVE 1
- /* Maximum size of returned data */
- #define IW_SCAN_MAX_DATA 4096 /* In bytes */
-
- /* Max number of char in custom event - use multiple of them if needed */
- #define IW_CUSTOM_MAX 256 /* In bytes */
-
-+/* Generic information element */
-+#define IW_GENERIC_IE_MAX 1024
-+
-+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
-+#define IW_MLME_DEAUTH 0
-+#define IW_MLME_DISASSOC 1
-+
-+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
-+#define IW_AUTH_INDEX 0x0FFF
-+#define IW_AUTH_FLAGS 0xF000
-+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
-+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
-+ * parameter that is being set/get to; value will be read/written to
-+ * struct iw_param value field) */
-+#define IW_AUTH_WPA_VERSION 0
-+#define IW_AUTH_CIPHER_PAIRWISE 1
-+#define IW_AUTH_CIPHER_GROUP 2
-+#define IW_AUTH_KEY_MGMT 3
-+#define IW_AUTH_TKIP_COUNTERMEASURES 4
-+#define IW_AUTH_DROP_UNENCRYPTED 5
-+#define IW_AUTH_80211_AUTH_ALG 6
-+#define IW_AUTH_WPA_ENABLED 7
-+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
-+#define IW_AUTH_ROAMING_CONTROL 9
-+#define IW_AUTH_PRIVACY_INVOKED 10
-+
-+/* IW_AUTH_WPA_VERSION values (bit field) */
-+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
-+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
-+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
-+
-+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
-+#define IW_AUTH_CIPHER_NONE 0x00000001
-+#define IW_AUTH_CIPHER_WEP40 0x00000002
-+#define IW_AUTH_CIPHER_TKIP 0x00000004
-+#define IW_AUTH_CIPHER_CCMP 0x00000008
-+#define IW_AUTH_CIPHER_WEP104 0x00000010
-+
-+/* IW_AUTH_KEY_MGMT values (bit field) */
-+#define IW_AUTH_KEY_MGMT_802_1X 1
-+#define IW_AUTH_KEY_MGMT_PSK 2
-+
-+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
-+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
-+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
-+#define IW_AUTH_ALG_LEAP 0x00000004
-+
-+/* IW_AUTH_ROAMING_CONTROL values */
-+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
-+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
-+ * control */
-+
-+/* SIOCSIWENCODEEXT definitions */
-+#define IW_ENCODE_SEQ_MAX_SIZE 8
-+/* struct iw_encode_ext ->alg */
-+#define IW_ENCODE_ALG_NONE 0
-+#define IW_ENCODE_ALG_WEP 1
-+#define IW_ENCODE_ALG_TKIP 2
-+#define IW_ENCODE_ALG_CCMP 3
-+/* struct iw_encode_ext ->ext_flags */
-+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
-+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
-+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
-+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
-+
-+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
-+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
-+#define IW_MICFAILURE_GROUP 0x00000004
-+#define IW_MICFAILURE_PAIRWISE 0x00000008
-+#define IW_MICFAILURE_STAKEY 0x00000010
-+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
-+ */
-+
-+/* Bit field values for enc_capa in struct iw_range */
-+#define IW_ENC_CAPA_WPA 0x00000001
-+#define IW_ENC_CAPA_WPA2 0x00000002
-+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
-+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
-+
- /* Event capability macros - in (struct iw_range *)->event_capa
- * Because we have more than 32 possible events, we use an array of
- * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
-@@ -546,6 +695,132 @@ struct iw_thrspy
- struct iw_quality high; /* High threshold */
- };
-
-+/*
-+ * Optional data for scan request
-+ *
-+ * Note: these optional parameters are controlling parameters for the
-+ * scanning behavior, these do not apply to getting scan results
-+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
-+ * provide a merged results with all BSSes even if the previous scan
-+ * request limited scanning to a subset, e.g., by specifying an SSID.
-+ * Especially, scan results are required to include an entry for the
-+ * current BSS if the driver is in Managed mode and associated with an AP.
-+ */
-+struct iw_scan_req
-+{
-+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
-+ __u8 essid_len;
-+ __u8 num_channels; /* num entries in channel_list;
-+ * 0 = scan all allowed channels */
-+ __u8 flags; /* reserved as padding; use zero, this may
-+ * be used in the future for adding flags
-+ * to request different scan behavior */
-+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
-+ * individual address of a specific BSS */
-+
-+ /*
-+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
-+ * the current ESSID. This allows scan requests for specific ESSID
-+ * without having to change the current ESSID and potentially breaking
-+ * the current association.
-+ */
-+ __u8 essid[IW_ESSID_MAX_SIZE];
-+
-+ /*
-+ * Optional parameters for changing the default scanning behavior.
-+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
-+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
-+ * reasonable default values. min_channel_time defines the time that
-+ * will be used to wait for the first reply on each channel. If no
-+ * replies are received, next channel will be scanned after this. If
-+ * replies are received, total time waited on the channel is defined by
-+ * max_channel_time.
-+ */
-+ __u32 min_channel_time; /* in TU */
-+ __u32 max_channel_time; /* in TU */
-+
-+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
-+};
-+
-+/* ------------------------- WPA SUPPORT ------------------------- */
-+
-+/*
-+ * Extended data structure for get/set encoding (this is used with
-+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
-+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
-+ * only the data contents changes (key data -> this structure, including
-+ * key data).
-+ *
-+ * If the new key is the first group key, it will be set as the default
-+ * TX key. Otherwise, default TX key index is only changed if
-+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
-+ *
-+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
-+ * special "change TX key index" operation which is indicated by setting
-+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
-+ *
-+ * tx_seq/rx_seq are only used when respective
-+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
-+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
-+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
-+ * used only by an Authenticator (AP or an IBSS station) to get the
-+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
-+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
-+ * debugging/testing.
-+ */
-+struct iw_encode_ext
-+{
-+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
-+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
-+ * (group) keys or unicast address for
-+ * individual keys */
-+ __u16 alg; /* IW_ENCODE_ALG_* */
-+ __u16 key_len;
-+ __u8 key[0];
-+};
-+
-+/* SIOCSIWMLME data */
-+struct iw_mlme
-+{
-+ __u16 cmd; /* IW_MLME_* */
-+ __u16 reason_code;
-+ struct sockaddr addr;
-+};
-+
-+/* SIOCSIWPMKSA data */
-+#define IW_PMKSA_ADD 1
-+#define IW_PMKSA_REMOVE 2
-+#define IW_PMKSA_FLUSH 3
-+
-+#define IW_PMKID_LEN 16
-+
-+struct iw_pmksa
-+{
-+ __u32 cmd; /* IW_PMKSA_* */
-+ struct sockaddr bssid;
-+ __u8 pmkid[IW_PMKID_LEN];
-+};
-+
-+/* IWEVMICHAELMICFAILURE data */
-+struct iw_michaelmicfailure
-+{
-+ __u32 flags;
-+ struct sockaddr src_addr;
-+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-+};
-+
-+/* IWEVPMKIDCAND data */
-+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
-+struct iw_pmkid_cand
-+{
-+ __u32 flags; /* IW_PMKID_CAND_* */
-+ __u32 index; /* the smaller the index, the higher the
-+ * priority */
-+ struct sockaddr bssid;
-+};
-+
- /* ------------------------ WIRELESS STATS ------------------------ */
- /*
- * Wireless statistics (used for /proc/net/wireless)
-@@ -725,6 +1000,8 @@ struct iw_range
- struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
- /* Note : this frequency list doesn't need to fit channel numbers,
- * because each entry contain its channel index */
-+
-+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
- };
-
- /*
-diff -u -p linux/net/core/wireless.we17.c linux/net/core/wireless.c
---- linux/net/core/wireless.we17.c 2005-05-20 11:26:11.000000000 -0700
-+++ linux/net/core/wireless.c 2005-05-20 15:37:09.000000000 -0700
-@@ -2,7 +2,7 @@
- * This file implement the Wireless Extensions APIs.
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
- *
- * (As all part of the Linux kernel, this file is GPL)
- */
-@@ -137,12 +137,12 @@ static const struct iw_ioctl_description
- { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
- /* SIOCGIWAP */
- { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-- /* -- hole -- */
-- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWMLME */
-+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_mlme), sizeof(struct iw_mlme), 0},
- /* SIOCGIWAPLIST */
- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
- /* SIOCSIWSCAN */
-- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_scan_req), 0},
- /* SIOCGIWSCAN */
- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
- /* SIOCSIWESSID */
-@@ -185,6 +185,25 @@ static const struct iw_ioctl_description
- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
- /* SIOCGIWPOWER */
- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWGENIE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
-+ /* SIOCGIWGENIE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
-+ /* SIOCSIWAUTH */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWAUTH */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWENCODEEXT */
-+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
-+ /* SIOCGIWENCODEEXT */
-+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_encode_ext), sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, 0},
-+ /* SIOCSIWPMKSA */
-+ { IW_HEADER_TYPE_POINT, 0, 1, sizeof(struct iw_pmksa), sizeof(struct iw_pmksa), 0},
-+ /* -- hole -- */
- };
- static const int standard_ioctl_num = (sizeof(standard_ioctl) /
- sizeof(struct iw_ioctl_description));
-@@ -204,6 +223,16 @@ static const struct iw_ioctl_description
- { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
- /* IWEVEXPIRED */
- { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
-+ /* IWEVGENIE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
-+ /* IWEVMICHAELMICFAILURE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_michaelmicfailure), 0},
-+ /* IWEVASSOCREQIE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
-+ /* IWEVASSOCRESPIE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_GENERIC_IE_MAX, 0},
-+ /* IWEVPMKIDCAND */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_pmkid_cand), 0},
- };
- static const int standard_event_num = (sizeof(standard_event) /
- sizeof(struct iw_ioctl_description));
diff --git a/recipes/linux/files/iw241_we16-6.diff b/recipes/linux/files/iw241_we16-6.diff
deleted file mode 100644
index 71cb4c08f6..0000000000
--- a/recipes/linux/files/iw241_we16-6.diff
+++ /dev/null
@@ -1,667 +0,0 @@
-diff -u -p linux/include/linux/wireless.15.h linux/include/linux/wireless.h
---- linux/include/linux/wireless.15.h Fri Jan 10 16:55:07 2003
-+++ linux/include/linux/wireless.h Wed Apr 2 16:33:31 2003
-@@ -1,7 +1,7 @@
- /*
- * This file define a set of standard wireless extensions
- *
-- * Version : 15 12.7.02
-+ * Version : 16 2.4.03
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
-@@ -69,6 +69,8 @@
-
- /***************************** INCLUDES *****************************/
-
-+/* To minimise problems in user space, I might remove those headers
-+ * at some point. Jean II */
- #include <linux/types.h> /* for "caddr_t" et al */
- #include <linux/socket.h> /* for "struct sockaddr" et al */
- #include <linux/if.h> /* for IFNAMSIZ and co... */
-@@ -80,7 +82,7 @@
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
--#define WIRELESS_EXT 15
-+#define WIRELESS_EXT 16
-
- /*
- * Changes :
-@@ -163,6 +165,16 @@
- * - Add IW_TXPOW_RANGE for range of Tx Powers
- * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
- * - Add IW_MODE_MONITOR for passive monitor
-+ *
-+ * V15 to V16
-+ * ----------
-+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
-+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
-+ * - Reshuffle struct iw_range for increases, add filler
-+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
-+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
-+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
-+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
- */
-
- /**************************** CONSTANTS ****************************/
-@@ -196,9 +208,11 @@
- /* SIOCGIWSTATS is strictly used between user space and the kernel, and
- * is never passed to the driver (i.e. the driver will never see it). */
-
--/* Mobile IP support (statistics per MAC address) */
-+/* Spy support (statistics per MAC address - used for Mobile IP support) */
- #define SIOCSIWSPY 0x8B10 /* set spy addresses */
- #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
-+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
-+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
-
- /* Access Point manipulation */
- #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
-@@ -294,7 +308,7 @@
- #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
- #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
-
--#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */
-+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
-
- #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
-
-@@ -306,13 +320,13 @@
- /* ----------------------- OTHER CONSTANTS ----------------------- */
-
- /* Maximum frequencies in the range struct */
--#define IW_MAX_FREQUENCIES 16
-+#define IW_MAX_FREQUENCIES 32
- /* Note : if you have something like 80 frequencies,
- * don't increase this constant and don't fill the frequency list.
- * The user will be able to set by channel anyway... */
-
- /* Maximum bit rates in the range struct */
--#define IW_MAX_BITRATES 8
-+#define IW_MAX_BITRATES 32
-
- /* Maximum tx powers in the range struct */
- #define IW_MAX_TXPOWER 8
-@@ -320,8 +334,7 @@
- * a few of them in the struct iw_range. */
-
- /* Maximum of address that you may set with SPY */
--#define IW_MAX_SPY 8 /* set */
--#define IW_MAX_GET_SPY 64 /* get */
-+#define IW_MAX_SPY 8
-
- /* Maximum of address that you may get in the
- list of access points in range */
-@@ -354,7 +367,8 @@
- #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
- #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
- #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
--#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
-+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
-+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
-
- /* Power management flags available (along with the value, if any) */
- #define IW_POWER_ON 0x0000 /* No details... */
-@@ -482,6 +496,17 @@ struct iw_missed
- __u32 beacon; /* Missed beacons/superframe */
- };
-
-+/*
-+ * Quality range (for spy threshold)
-+ */
-+struct iw_thrspy
-+{
-+ struct sockaddr addr; /* Source address (hw/mac) */
-+ struct iw_quality qual; /* Quality of the link */
-+ struct iw_quality low; /* Low threshold */
-+ struct iw_quality high; /* High threshold */
-+};
-+
- /* ------------------------ WIRELESS STATS ------------------------ */
- /*
- * Wireless statistics (used for /proc/net/wireless)
-@@ -534,7 +559,7 @@ union iwreq_data
- struct iw_quality qual; /* Quality part of statistics */
-
- struct sockaddr ap_addr; /* Access point address */
-- struct sockaddr addr; /* Destination address (hw) */
-+ struct sockaddr addr; /* Destination address (hw/mac) */
-
- struct iw_param param; /* Other small parameters */
- struct iw_point data; /* Other large parameters */
-@@ -582,17 +607,31 @@ struct iw_range
- __u32 min_nwid; /* Minimal NWID we are able to set */
- __u32 max_nwid; /* Maximal NWID we are able to set */
-
-- /* Frequency */
-- __u16 num_channels; /* Number of channels [0; num - 1] */
-- __u8 num_frequency; /* Number of entry in the list */
-- struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
-- /* Note : this frequency list doesn't need to fit channel numbers */
-+ /* Old Frequency (backward compat - moved lower ) */
-+ __u16 old_num_channels;
-+ __u8 old_num_frequency;
-+ /* Filler to keep "version" at the same offset */
-+ __s32 old_freq[6];
-
- /* signal level threshold range */
- __s32 sensitivity;
-
- /* Quality of link & SNR stuff */
-+ /* Quality range (link, level, noise)
-+ * If the quality is absolute, it will be in the range [0 ; max_qual],
-+ * if the quality is dBm, it will be in the range [max_qual ; 0].
-+ * Don't forget that we use 8 bit arithmetics... */
- struct iw_quality max_qual; /* Quality of the link */
-+ /* This should contain the average/typical values of the quality
-+ * indicator. This should be the threshold between a "good" and
-+ * a "bad" link (example : monitor going from green to orange).
-+ * Currently, user space apps like quality monitors don't have any
-+ * way to calibrate the measurement. With this, they can split
-+ * the range between 0 and max_qual in different quality level
-+ * (using a geometric subdivision centered on the average).
-+ * I expect that people doing the user space apps will feedback
-+ * us on which value we need to put in each driver... */
-+ struct iw_quality avg_qual; /* Quality of the link */
-
- /* Rates */
- __u8 num_bitrates; /* Number of entries in the list */
-@@ -619,6 +658,8 @@ struct iw_range
- __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
- __u8 num_encoding_sizes; /* Number of entry in the list */
- __u8 max_encoding_tokens; /* Max number of tokens */
-+ /* For drivers that need a "login/passwd" form */
-+ __u8 encoding_login_index; /* token index for login token */
-
- /* Transmit power */
- __u16 txpower_capa; /* What options are supported */
-@@ -638,18 +679,12 @@ struct iw_range
- __s32 min_r_time; /* Minimal retry lifetime */
- __s32 max_r_time; /* Maximal retry lifetime */
-
-- /* Average quality of link & SNR */
-- struct iw_quality avg_qual; /* Quality of the link */
-- /* This should contain the average/typical values of the quality
-- * indicator. This should be the threshold between a "good" and
-- * a "bad" link (example : monitor going from green to orange).
-- * Currently, user space apps like quality monitors don't have any
-- * way to calibrate the measurement. With this, they can split
-- * the range between 0 and max_qual in different quality level
-- * (using a geometric subdivision centered on the average).
-- * I expect that people doing the user space apps will feedback
-- * us on which value we need to put in each driver...
-- */
-+ /* Frequency */
-+ __u16 num_channels; /* Number of channels [0; num - 1] */
-+ __u8 num_frequency; /* Number of entry in the list */
-+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
-+ /* Note : this frequency list doesn't need to fit channel numbers,
-+ * because each entry contain its channel index */
- };
-
- /*
-diff -u -p linux/include/net/iw_handler.15.h linux/include/net/iw_handler.h
---- linux/include/net/iw_handler.15.h Fri Jan 10 16:55:17 2003
-+++ linux/include/net/iw_handler.h Fri Jan 10 17:02:13 2003
-@@ -1,7 +1,7 @@
- /*
- * This file define the new driver API for Wireless Extensions
- *
-- * Version : 4 21.6.02
-+ * Version : 5 4.12.02
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
-@@ -206,7 +206,7 @@
- * will be needed...
- * I just plan to increment with each new version.
- */
--#define IW_HANDLER_VERSION 4
-+#define IW_HANDLER_VERSION 5
-
- /*
- * Changes :
-@@ -220,10 +220,18 @@
- * V3 to V4
- * --------
- * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
-+ *
-+ * V4 to V5
-+ * --------
-+ * - Add new spy support : struct iw_spy_data & prototypes
- */
-
- /**************************** CONSTANTS ****************************/
-
-+/* Enable enhanced spy support. Disable to reduce footprint */
-+#define IW_WIRELESS_SPY
-+#define IW_WIRELESS_THRSPY
-+
- /* Special error message for the driver to indicate that we
- * should do a commit after return from the iw_handler */
- #define EIWCOMMIT EINPROGRESS
-@@ -315,6 +323,9 @@ struct iw_handler_def
- * We will automatically export that to user space... */
- struct iw_priv_args * private_args;
-
-+ /* Driver enhanced spy support */
-+ long spy_offset; /* Spy data offset */
-+
- /* In the long term, get_wireless_stats will move from
- * 'struct net_device' to here, to minimise bloat. */
- };
-@@ -350,6 +361,33 @@ struct iw_ioctl_description
-
- /* Need to think of short header translation table. Later. */
-
-+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
-+/*
-+ * In the old days, the driver was handling spy support all by itself.
-+ * Now, the driver can delegate this task to Wireless Extensions.
-+ * It needs to include this struct in its private part and use the
-+ * standard spy iw_handler.
-+ */
-+
-+/*
-+ * Instance specific spy data, i.e. addresses spied and quality for them.
-+ */
-+struct iw_spy_data
-+{
-+#ifdef IW_WIRELESS_SPY
-+ /* --- Standard spy support --- */
-+ int spy_number;
-+ u_char spy_address[IW_MAX_SPY][ETH_ALEN];
-+ struct iw_quality spy_stat[IW_MAX_SPY];
-+#ifdef IW_WIRELESS_THRSPY
-+ /* --- Enhanced spy support (event) */
-+ struct iw_quality spy_thr_low; /* Low threshold */
-+ struct iw_quality spy_thr_high; /* High threshold */
-+ u_char spy_thr_under[IW_MAX_SPY];
-+#endif /* IW_WIRELESS_THRSPY */
-+#endif /* IW_WIRELESS_SPY */
-+};
-+
- /**************************** PROTOTYPES ****************************/
- /*
- * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
-@@ -375,6 +413,31 @@ extern void wireless_send_event(struct n
-
- /* We may need a function to send a stream of events to user space.
- * More on that later... */
-+
-+/* Standard handler for SIOCSIWSPY */
-+extern int iw_handler_set_spy(struct net_device * dev,
-+ struct iw_request_info * info,
-+ union iwreq_data * wrqu,
-+ char * extra);
-+/* Standard handler for SIOCGIWSPY */
-+extern int iw_handler_get_spy(struct net_device * dev,
-+ struct iw_request_info * info,
-+ union iwreq_data * wrqu,
-+ char * extra);
-+/* Standard handler for SIOCSIWTHRSPY */
-+extern int iw_handler_set_thrspy(struct net_device * dev,
-+ struct iw_request_info *info,
-+ union iwreq_data * wrqu,
-+ char * extra);
-+/* Standard handler for SIOCGIWTHRSPY */
-+extern int iw_handler_get_thrspy(struct net_device * dev,
-+ struct iw_request_info *info,
-+ union iwreq_data * wrqu,
-+ char * extra);
-+/* Driver call to update spy records */
-+extern void wireless_spy_update(struct net_device * dev,
-+ unsigned char * address,
-+ struct iw_quality * wstats);
-
- /************************* INLINE FUNTIONS *************************/
- /*
-diff -u -p linux/net/core/wireless.15.c linux/net/core/wireless.c
---- linux/net/core/wireless.15.c Fri Jan 10 16:56:16 2003
-+++ linux/net/core/wireless.c Fri Jan 10 16:59:55 2003
-@@ -2,7 +2,7 @@
- * This file implement the Wireless Extensions APIs.
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
- *
- * (As all part of the Linux kernel, this file is GPL)
- */
-@@ -43,6 +43,11 @@
- * o Turn on WE_STRICT_WRITE by default + kernel warning
- * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
- * o Fix off-by-one in test (extra_size <= IFNAMSIZ)
-+ *
-+ * v6 - 9.01.03 - Jean II
-+ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
-+ * o Add enhanced spy support : iw_handler_set_thrspy() and event.
-+ * o Add WIRELESS_EXT version display in /proc/net/wireless
- */
-
- /***************************** INCLUDES *****************************/
-@@ -52,6 +57,7 @@
- #include <linux/types.h> /* off_t */
- #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
- #include <linux/rtnetlink.h> /* rtnetlink stuff */
-+#include <linux/if_arp.h> /* ARPHRD_ETHER */
-
- #include <linux/wireless.h> /* Pretty obvious */
- #include <net/iw_handler.h> /* New driver API */
-@@ -65,6 +71,7 @@
- /* Debuging stuff */
- #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
- #undef WE_EVENT_DEBUG /* Debug Event dispatcher */
-+#undef WE_SPY_DEBUG /* Debug enhanced spy support */
-
- /* Options */
- #define WE_EVENT_NETLINK /* Propagate events using rtnetlink */
-@@ -72,7 +79,7 @@
-
- /************************* GLOBAL VARIABLES *************************/
- /*
-- * You should not use global variables, because or re-entrancy.
-+ * You should not use global variables, because of re-entrancy.
- * On our case, it's only const, so it's OK...
- */
- /*
-@@ -115,11 +122,11 @@ static const struct iw_ioctl_description
- /* SIOCSIWSPY */
- { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
- /* SIOCGIWSPY */
-- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
-- /* -- hole -- */
-- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-- /* -- hole -- */
-- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
-+ /* SIOCSIWTHRSPY */
-+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
-+ /* SIOCGIWTHRSPY */
-+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
- /* SIOCSIWAP */
- { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
- /* SIOCGIWAP */
-@@ -377,9 +384,9 @@ int dev_get_wireless_info(char * buffer,
- struct net_device * dev;
-
- size = sprintf(buffer,
-- "Inter-| sta-| Quality | Discarded packets | Missed\n"
-- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
-- );
-+ "Inter-| sta-| Quality | Discarded packets | Missed | WE\n"
-+ " face | tus | link level noise | nwid crypt frag retry misc | beacon | %d\n",
-+ WIRELESS_EXT);
-
- pos += size;
- len += size;
-@@ -1023,4 +1030,253 @@ void wireless_send_event(struct net_devi
- kfree(event);
-
- return; /* Always success, I guess ;-) */
-+}
-+
-+/********************** ENHANCED IWSPY SUPPORT **********************/
-+/*
-+ * In the old days, the driver was handling spy support all by itself.
-+ * Now, the driver can delegate this task to Wireless Extensions.
-+ * It needs to use those standard spy iw_handler in struct iw_handler_def,
-+ * push data to us via XXX and include struct iw_spy_data in its
-+ * private part.
-+ * One of the main advantage of centralising spy support here is that
-+ * it becomes much easier to improve and extend it without having to touch
-+ * the drivers. One example is the addition of the Spy-Threshold events.
-+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
-+ */
-+
-+/*------------------------------------------------------------------*/
-+/*
-+ * Standard Wireless Handler : set Spy List
-+ */
-+int iw_handler_set_spy(struct net_device * dev,
-+ struct iw_request_info * info,
-+ union iwreq_data * wrqu,
-+ char * extra)
-+{
-+#ifdef IW_WIRELESS_SPY
-+ struct iw_spy_data * spydata = (dev->priv +
-+ dev->wireless_handlers->spy_offset);
-+ struct sockaddr * address = (struct sockaddr *) extra;
-+
-+ /* Disable spy collection while we copy the addresses.
-+ * As we don't disable interrupts, we need to do this to avoid races.
-+ * As we are the only writer, this is good enough. */
-+ spydata->spy_number = 0;
-+
-+ /* Are there are addresses to copy? */
-+ if(wrqu->data.length > 0) {
-+ int i;
-+
-+ /* Copy addresses */
-+ for(i = 0; i < wrqu->data.length; i++)
-+ memcpy(spydata->spy_address[i], address[i].sa_data,
-+ ETH_ALEN);
-+ /* Reset stats */
-+ memset(spydata->spy_stat, 0,
-+ sizeof(struct iw_quality) * IW_MAX_SPY);
-+
-+#ifdef WE_SPY_DEBUG
-+ printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
-+ for (i = 0; i < wrqu->data.length; i++)
-+ printk(KERN_DEBUG
-+ "%02X:%02X:%02X:%02X:%02X:%02X \n",
-+ spydata->spy_address[i][0],
-+ spydata->spy_address[i][1],
-+ spydata->spy_address[i][2],
-+ spydata->spy_address[i][3],
-+ spydata->spy_address[i][4],
-+ spydata->spy_address[i][5]);
-+#endif /* WE_SPY_DEBUG */
-+ }
-+ /* Enable addresses */
-+ spydata->spy_number = wrqu->data.length;
-+
-+ return 0;
-+#else /* IW_WIRELESS_SPY */
-+ return -EOPNOTSUPP;
-+#endif /* IW_WIRELESS_SPY */
-+}
-+
-+/*------------------------------------------------------------------*/
-+/*
-+ * Standard Wireless Handler : get Spy List
-+ */
-+int iw_handler_get_spy(struct net_device * dev,
-+ struct iw_request_info * info,
-+ union iwreq_data * wrqu,
-+ char * extra)
-+{
-+#ifdef IW_WIRELESS_SPY
-+ struct iw_spy_data * spydata = (dev->priv +
-+ dev->wireless_handlers->spy_offset);
-+ struct sockaddr * address = (struct sockaddr *) extra;
-+ int i;
-+
-+ wrqu->data.length = spydata->spy_number;
-+
-+ /* Copy addresses. */
-+ for(i = 0; i < spydata->spy_number; i++) {
-+ memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
-+ address[i].sa_family = AF_UNIX;
-+ }
-+ /* Copy stats to the user buffer (just after). */
-+ if(spydata->spy_number > 0)
-+ memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number),
-+ spydata->spy_stat,
-+ sizeof(struct iw_quality) * spydata->spy_number);
-+ /* Reset updated flags. */
-+ for(i = 0; i < spydata->spy_number; i++)
-+ spydata->spy_stat[i].updated = 0;
-+ return 0;
-+#else /* IW_WIRELESS_SPY */
-+ return -EOPNOTSUPP;
-+#endif /* IW_WIRELESS_SPY */
-+}
-+
-+/*------------------------------------------------------------------*/
-+/*
-+ * Standard Wireless Handler : set spy threshold
-+ */
-+int iw_handler_set_thrspy(struct net_device * dev,
-+ struct iw_request_info *info,
-+ union iwreq_data * wrqu,
-+ char * extra)
-+{
-+#ifdef IW_WIRELESS_THRSPY
-+ struct iw_spy_data * spydata = (dev->priv +
-+ dev->wireless_handlers->spy_offset);
-+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
-+
-+ /* Just do it */
-+ memcpy(&(spydata->spy_thr_low), &(threshold->low),
-+ 2 * sizeof(struct iw_quality));
-+
-+ /* Clear flag */
-+ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
-+
-+#ifdef WE_SPY_DEBUG
-+ printk(KERN_DEBUG "iw_handler_set_thrspy() : low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
-+#endif /* WE_SPY_DEBUG */
-+
-+ return 0;
-+#else /* IW_WIRELESS_THRSPY */
-+ return -EOPNOTSUPP;
-+#endif /* IW_WIRELESS_THRSPY */
-+}
-+
-+/*------------------------------------------------------------------*/
-+/*
-+ * Standard Wireless Handler : get spy threshold
-+ */
-+int iw_handler_get_thrspy(struct net_device * dev,
-+ struct iw_request_info *info,
-+ union iwreq_data * wrqu,
-+ char * extra)
-+{
-+#ifdef IW_WIRELESS_THRSPY
-+ struct iw_spy_data * spydata = (dev->priv +
-+ dev->wireless_handlers->spy_offset);
-+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
-+
-+ /* Just do it */
-+ memcpy(&(threshold->low), &(spydata->spy_thr_low),
-+ 2 * sizeof(struct iw_quality));
-+
-+ return 0;
-+#else /* IW_WIRELESS_THRSPY */
-+ return -EOPNOTSUPP;
-+#endif /* IW_WIRELESS_THRSPY */
-+}
-+
-+#ifdef IW_WIRELESS_THRSPY
-+/*------------------------------------------------------------------*/
-+/*
-+ * Prepare and send a Spy Threshold event
-+ */
-+static void iw_send_thrspy_event(struct net_device * dev,
-+ struct iw_spy_data * spydata,
-+ unsigned char * address,
-+ struct iw_quality * wstats)
-+{
-+ union iwreq_data wrqu;
-+ struct iw_thrspy threshold;
-+
-+ /* Init */
-+ wrqu.data.length = 1;
-+ wrqu.data.flags = 0;
-+ /* Copy address */
-+ memcpy(threshold.addr.sa_data, address, ETH_ALEN);
-+ threshold.addr.sa_family = ARPHRD_ETHER;
-+ /* Copy stats */
-+ memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
-+ /* Copy also thresholds */
-+ memcpy(&(threshold.low), &(spydata->spy_thr_low),
-+ 2 * sizeof(struct iw_quality));
-+
-+#ifdef WE_SPY_DEBUG
-+ printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
-+ threshold.addr.sa_data[0],
-+ threshold.addr.sa_data[1],
-+ threshold.addr.sa_data[2],
-+ threshold.addr.sa_data[3],
-+ threshold.addr.sa_data[4],
-+ threshold.addr.sa_data[5], threshold.qual.level);
-+#endif /* WE_SPY_DEBUG */
-+
-+ /* Send event to user space */
-+ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
-+}
-+#endif /* IW_WIRELESS_THRSPY */
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Call for the driver to update the spy data.
-+ * For now, the spy data is a simple array. As the size of the array is
-+ * small, this is good enough. If we wanted to support larger number of
-+ * spy addresses, we should use something more efficient...
-+ */
-+void wireless_spy_update(struct net_device * dev,
-+ unsigned char * address,
-+ struct iw_quality * wstats)
-+{
-+#ifdef IW_WIRELESS_SPY
-+ struct iw_spy_data * spydata = (dev->priv +
-+ dev->wireless_handlers->spy_offset);
-+ int i;
-+ int match = -1;
-+
-+#ifdef WE_SPY_DEBUG
-+ printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
-+#endif /* WE_SPY_DEBUG */
-+
-+ /* Update all records that match */
-+ for(i = 0; i < spydata->spy_number; i++)
-+ if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
-+ memcpy(&(spydata->spy_stat[i]), wstats,
-+ sizeof(struct iw_quality));
-+ match = i;
-+ }
-+#ifdef IW_WIRELESS_THRSPY
-+ /* Generate an event if we cross the spy threshold.
-+ * To avoid event storms, we have a simple hysteresis : we generate
-+ * event only when we go under the low threshold or above the
-+ * high threshold. */
-+ if(match >= 0) {
-+ if(spydata->spy_thr_under[match]) {
-+ if(wstats->level > spydata->spy_thr_high.level) {
-+ spydata->spy_thr_under[match] = 0;
-+ iw_send_thrspy_event(dev, spydata,
-+ address, wstats);
-+ }
-+ } else {
-+ if(wstats->level < spydata->spy_thr_low.level) {
-+ spydata->spy_thr_under[match] = 1;
-+ iw_send_thrspy_event(dev, spydata,
-+ address, wstats);
-+ }
-+ }
-+ }
-+#endif /* IW_WIRELESS_THRSPY */
-+#endif /* IW_WIRELESS_SPY */
- }
-diff -u -p linux/net/netsyms.15.c linux/net/netsyms.c
---- linux/net/netsyms.15.c Fri Jan 10 16:56:32 2003
-+++ linux/net/netsyms.c Fri Jan 10 17:01:09 2003
-@@ -594,6 +594,11 @@ EXPORT_SYMBOL(softnet_data);
- #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
- #include <net/iw_handler.h>
- EXPORT_SYMBOL(wireless_send_event);
-+EXPORT_SYMBOL(iw_handler_set_spy);
-+EXPORT_SYMBOL(iw_handler_get_spy);
-+EXPORT_SYMBOL(iw_handler_set_thrspy);
-+EXPORT_SYMBOL(iw_handler_get_thrspy);
-+EXPORT_SYMBOL(wireless_spy_update);
- #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
-
- #endif /* CONFIG_NET */
diff --git a/recipes/linux/files/iw249_we17-13.diff b/recipes/linux/files/iw249_we17-13.diff
deleted file mode 100644
index 674f4ffbc0..0000000000
--- a/recipes/linux/files/iw249_we17-13.diff
+++ /dev/null
@@ -1,768 +0,0 @@
-diff -u -p linux/include/linux/netdevice.we16.h linux/include/linux/netdevice.h
---- linux/include/linux/netdevice.we16.h 2005-02-03 14:54:56.000000000 -0800
-+++ linux/include/linux/netdevice.h 2005-02-03 15:43:30.000000000 -0800
-@@ -295,7 +295,9 @@ struct net_device
-
- /* List of functions to handle Wireless Extensions (instead of ioctl).
- * See <net/iw_handler.h> for details. Jean II */
-- struct iw_handler_def * wireless_handlers;
-+ const struct iw_handler_def * wireless_handlers;
-+ /* Instance data managed by the core of Wireless Extensions. */
-+ struct iw_public_data * wireless_data;
-
- struct ethtool_ops *ethtool_ops;
-
-diff -u -p linux/include/linux/wireless.we16.h linux/include/linux/wireless.h
---- linux/include/linux/wireless.we16.h 2005-02-03 14:55:04.000000000 -0800
-+++ linux/include/linux/wireless.h 2005-02-03 15:44:48.000000000 -0800
-@@ -1,10 +1,10 @@
- /*
- * This file define a set of standard wireless extensions
- *
-- * Version : 16 2.4.03
-+ * Version : 17 21.6.04
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
- */
-
- #ifndef _LINUX_WIRELESS_H
-@@ -47,12 +47,12 @@
- * # include/net/iw_handler.h
- *
- * Note as well that /proc/net/wireless implementation has now moved in :
-- * # include/linux/wireless.c
-+ * # net/core/wireless.c
- *
- * Wireless Events (2002 -> onward) :
- * --------------------------------
- * Events are defined at the end of this file, and implemented in :
-- * # include/linux/wireless.c
-+ * # net/core/wireless.c
- *
- * Other comments :
- * --------------
-@@ -82,7 +82,7 @@
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
--#define WIRELESS_EXT 16
-+#define WIRELESS_EXT 17
-
- /*
- * Changes :
-@@ -175,6 +175,13 @@
- * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
- * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
- * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
-+ *
-+ * V16 to V17
-+ * ----------
-+ * - Add flags to frequency -> auto/fixed
-+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
-+ * - Wireless Event capability in struct iw_range
-+ * - Add support for relative TxPower (yick !)
- */
-
- /**************************** CONSTANTS ****************************/
-@@ -251,7 +258,7 @@
-
- /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
-
--/* These 16 ioctl are wireless device private.
-+/* These 32 ioctl are wireless device private, for 16 commands.
- * Each driver is free to use them for whatever purpose it chooses,
- * however the driver *must* export the description of those ioctls
- * with SIOCGIWPRIV and *must* use arguments as defined below.
-@@ -266,8 +273,8 @@
- * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
- * content of ifr/iwr to user (but you are not obliged to use the set/get
-- * convention, just use every other two command).
-- * And I repeat : you are not obliged to use them with iwspy, but you
-+ * convention, just use every other two command). More details in iwpriv.c.
-+ * And I repeat : you are not forced to use them with iwpriv, but you
- * must be compliant with it.
- */
-
-@@ -352,6 +359,18 @@
- #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
- #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
-
-+/* Statistics flags (bitmask in updated) */
-+#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */
-+#define IW_QUAL_LEVEL_UPDATED 0x2
-+#define IW_QUAL_NOISE_UPDATED 0x4
-+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
-+#define IW_QUAL_LEVEL_INVALID 0x20
-+#define IW_QUAL_NOISE_INVALID 0x40
-+
-+/* Frequency flags */
-+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
-+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
-+
- /* Maximum number of size of encoding token available
- * they are listed in the range structure */
- #define IW_MAX_ENCODING_SIZES 8
-@@ -390,6 +409,7 @@
- #define IW_TXPOW_TYPE 0x00FF /* Type of value */
- #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
- #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
-+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
- #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
-
- /* Retry limits and lifetime flags available */
-@@ -418,6 +438,25 @@
- /* Max number of char in custom event - use multiple of them if needed */
- #define IW_CUSTOM_MAX 256 /* In bytes */
-
-+/* Event capability macros - in (struct iw_range *)->event_capa
-+ * Because we have more than 32 possible events, we use an array of
-+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
-+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
-+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
-+ (cmd - SIOCSIWCOMMIT))
-+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
-+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
-+/* Event capability constants - event autogenerated by the kernel
-+ * This list is valid for most 802.11 devices, customise as needed... */
-+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
-+ IW_EVENT_CAPA_MASK(0x8B06) | \
-+ IW_EVENT_CAPA_MASK(0x8B1A))
-+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
-+/* "Easy" macro to set events in iw_range (less efficient) */
-+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
-+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
-+
-+
- /****************************** TYPES ******************************/
-
- /* --------------------------- SUBTYPES --------------------------- */
-@@ -456,7 +495,7 @@ struct iw_freq
- __s32 m; /* Mantissa */
- __s16 e; /* Exponent */
- __u8 i; /* List index (when in range struct) */
-- __u8 pad; /* Unused - just for alignement */
-+ __u8 flags; /* Flags (fixed/auto) */
- };
-
- /*
-@@ -610,11 +649,12 @@ struct iw_range
- /* Old Frequency (backward compat - moved lower ) */
- __u16 old_num_channels;
- __u8 old_num_frequency;
-- /* Filler to keep "version" at the same offset */
-- __s32 old_freq[6];
-+
-+ /* Wireless event capability bitmasks */
-+ __u32 event_capa[6];
-
- /* signal level threshold range */
-- __s32 sensitivity;
-+ __s32 sensitivity;
-
- /* Quality of link & SNR stuff */
- /* Quality range (link, level, noise)
-diff -u -p linux/include/net/iw_handler.we16.h linux/include/net/iw_handler.h
---- linux/include/net/iw_handler.we16.h 2005-02-03 14:55:26.000000000 -0800
-+++ linux/include/net/iw_handler.h 2005-02-03 15:47:04.000000000 -0800
-@@ -1,10 +1,10 @@
- /*
- * This file define the new driver API for Wireless Extensions
- *
-- * Version : 5 4.12.02
-+ * Version : 6 21.6.04
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved.
- */
-
- #ifndef _IW_HANDLER_H
-@@ -206,7 +206,7 @@
- * will be needed...
- * I just plan to increment with each new version.
- */
--#define IW_HANDLER_VERSION 5
-+#define IW_HANDLER_VERSION 6
-
- /*
- * Changes :
-@@ -224,11 +224,18 @@
- * V4 to V5
- * --------
- * - Add new spy support : struct iw_spy_data & prototypes
-+ *
-+ * V5 to V6
-+ * --------
-+ * - Change the way we get to spy_data method for added safety
-+ * - Remove spy #ifdef, they are always on -> cleaner code
-+ * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
-+ * - Start migrating get_wireless_stats to struct iw_handler_def
- */
-
- /**************************** CONSTANTS ****************************/
-
--/* Enable enhanced spy support. Disable to reduce footprint */
-+/* Enhanced spy support available */
- #define IW_WIRELESS_SPY
- #define IW_WIRELESS_THRSPY
-
-@@ -258,6 +265,7 @@
- #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
- #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
- /* SET : Omit payload from generated iwevent */
-+#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
- /* Driver level flags */
- #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
-
-@@ -311,23 +319,25 @@ struct iw_handler_def
- /* Array of handlers for standard ioctls
- * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
- */
-- iw_handler * standard;
-+ const iw_handler * standard;
-
- /* Array of handlers for private ioctls
- * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
- */
-- iw_handler * private;
-+ const iw_handler * private;
-
- /* Arguments of private handler. This one is just a list, so you
- * can put it in any order you want and should not leave holes...
- * We will automatically export that to user space... */
-- struct iw_priv_args * private_args;
-+ const struct iw_priv_args * private_args;
-
-- /* Driver enhanced spy support */
-- long spy_offset; /* Spy data offset */
-+ /* This field will be *removed* in the next version of WE */
-+ long spy_offset; /* DO NOT USE */
-
-- /* In the long term, get_wireless_stats will move from
-- * 'struct net_device' to here, to minimise bloat. */
-+ /* New location of get_wireless_stats, to de-bloat struct net_device.
-+ * The old pointer in struct net_device will be gradually phased
-+ * out, and drivers are encouraged to use this one... */
-+ struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
- };
-
- /* ---------------------- IOCTL DESCRIPTION ---------------------- */
-@@ -374,18 +384,29 @@ struct iw_ioctl_description
- */
- struct iw_spy_data
- {
--#ifdef IW_WIRELESS_SPY
- /* --- Standard spy support --- */
- int spy_number;
- u_char spy_address[IW_MAX_SPY][ETH_ALEN];
- struct iw_quality spy_stat[IW_MAX_SPY];
--#ifdef IW_WIRELESS_THRSPY
- /* --- Enhanced spy support (event) */
- struct iw_quality spy_thr_low; /* Low threshold */
- struct iw_quality spy_thr_high; /* High threshold */
- u_char spy_thr_under[IW_MAX_SPY];
--#endif /* IW_WIRELESS_THRSPY */
--#endif /* IW_WIRELESS_SPY */
-+};
-+
-+/* --------------------- DEVICE WIRELESS DATA --------------------- */
-+/*
-+ * This is all the wireless data specific to a device instance that
-+ * is managed by the core of Wireless Extensions.
-+ * We only keep pointer to those structures, so that a driver is free
-+ * to share them between instances.
-+ * This structure should be initialised before registering the device.
-+ * Access to this data follow the same rules as any other struct net_device
-+ * data (i.e. valid as long as struct net_device exist, same locking rules).
-+ */
-+struct iw_public_data {
-+ /* Driver enhanced spy support */
-+ struct iw_spy_data * spy_data;
- };
-
- /**************************** PROTOTYPES ****************************/
-diff -u -p linux/net/core/dev.we16.c linux/net/core/dev.c
---- linux/net/core/dev.we16.c 2005-02-03 14:55:56.000000000 -0800
-+++ linux/net/core/dev.c 2005-02-03 15:28:48.000000000 -0800
-@@ -2426,7 +2426,7 @@ int dev_ioctl(unsigned int cmd, void *ar
- /* Follow me in net/core/wireless.c */
- ret = wireless_process_ioctl(&ifr, cmd);
- rtnl_unlock();
-- if (!ret && IW_IS_GET(cmd) &&
-+ if (IW_IS_GET(cmd) &&
- copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- return -EFAULT;
- return ret;
-diff -u -p linux/net/core/wireless.we16.c linux/net/core/wireless.c
---- linux/net/core/wireless.we16.c 2005-02-03 14:56:09.000000000 -0800
-+++ linux/net/core/wireless.c 2005-02-03 16:33:22.000000000 -0800
-@@ -2,7 +2,7 @@
- * This file implement the Wireless Extensions APIs.
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-- * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
-+ * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
- *
- * (As all part of the Linux kernel, this file is GPL)
- */
-@@ -48,6 +48,16 @@
- * o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
- * o Add enhanced spy support : iw_handler_set_thrspy() and event.
- * o Add WIRELESS_EXT version display in /proc/net/wireless
-+ *
-+ * v6 - 18.06.04 - Jean II
-+ * o Change get_spydata() method for added safety
-+ * o Remove spy #ifdef, they are always on -> cleaner code
-+ * o Allow any size GET request if user specifies length > max
-+ * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV
-+ * o Start migrating get_wireless_stats to struct iw_handler_def
-+ * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus
-+ * Based on patch from Pavel Roskin <proski@gnu.org> :
-+ * o Fix kernel data leak to user space in private handler handling
- */
-
- /***************************** INCLUDES *****************************/
-@@ -64,11 +74,7 @@
-
- /**************************** CONSTANTS ****************************/
-
--/* Enough lenience, let's make sure things are proper... */
--#define WE_STRICT_WRITE /* Check write buffer size */
--/* I'll probably drop both the define and kernel message in the next version */
--
--/* Debuging stuff */
-+/* Debugging stuff */
- #undef WE_IOCTL_DEBUG /* Debug IOCTL API */
- #undef WE_EVENT_DEBUG /* Debug Event dispatcher */
- #undef WE_SPY_DEBUG /* Debug enhanced spy support */
-@@ -134,11 +140,11 @@ static const struct iw_ioctl_description
- /* -- hole -- */
- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
- /* SIOCGIWAPLIST */
-- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
-+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, IW_DESCR_FLAG_NOMAX},
- /* SIOCSIWSCAN */
- { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
- /* SIOCGIWSCAN */
-- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0},
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, IW_DESCR_FLAG_NOMAX},
- /* SIOCSIWESSID */
- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT},
- /* SIOCGIWESSID */
-@@ -203,7 +209,7 @@ static const int standard_event_num = (s
- sizeof(struct iw_ioctl_description));
-
- /* Size (in bytes) of the various private data types */
--static const char priv_type_size[] = {
-+static const char iw_priv_type_size[] = {
- 0, /* IW_PRIV_TYPE_NONE */
- 1, /* IW_PRIV_TYPE_BYTE */
- 1, /* IW_PRIV_TYPE_CHAR */
-@@ -270,12 +276,15 @@ static inline iw_handler get_handler(str
- */
- static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
- {
-+ /* New location */
-+ if((dev->wireless_handlers != NULL) &&
-+ (dev->wireless_handlers->get_wireless_stats != NULL))
-+ return dev->wireless_handlers->get_wireless_stats(dev);
-+
-+ /* Old location, will be phased out in next WE */
- return (dev->get_wireless_stats ?
- dev->get_wireless_stats(dev) :
- (struct iw_statistics *) NULL);
-- /* In the future, get_wireless_stats may move from 'struct net_device'
-- * to 'struct iw_handler_def', to de-bloat struct net_device.
-- * Definitely worse a thought... */
- }
-
- /* ---------------------------------------------------------------- */
-@@ -310,14 +319,32 @@ static inline int call_commit_handler(st
-
- /* ---------------------------------------------------------------- */
- /*
-- * Number of private arguments
-+ * Calculate size of private arguments
- */
- static inline int get_priv_size(__u16 args)
- {
- int num = args & IW_PRIV_SIZE_MASK;
- int type = (args & IW_PRIV_TYPE_MASK) >> 12;
-
-- return num * priv_type_size[type];
-+ return num * iw_priv_type_size[type];
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Re-calculate the size of private arguments
-+ */
-+static inline int adjust_priv_size(__u16 args,
-+ union iwreq_data * wrqu)
-+{
-+ int num = wrqu->data.length;
-+ int max = args & IW_PRIV_SIZE_MASK;
-+ int type = (args & IW_PRIV_TYPE_MASK) >> 12;
-+
-+ /* Make sure the driver doesn't goof up */
-+ if (max < num)
-+ num = max;
-+
-+ return num * iw_priv_type_size[type];
- }
-
-
-@@ -350,11 +377,14 @@ static inline int sprintf_wireless_stats
- dev->name,
- stats->status,
- stats->qual.qual,
-- stats->qual.updated & 1 ? '.' : ' ',
-+ stats->qual.updated & IW_QUAL_QUAL_UPDATED
-+ ? '.' : ' ',
- ((__u8) stats->qual.level),
-- stats->qual.updated & 2 ? '.' : ' ',
-+ stats->qual.updated & IW_QUAL_LEVEL_UPDATED
-+ ? '.' : ' ',
- ((__u8) stats->qual.noise),
-- stats->qual.updated & 4 ? '.' : ' ',
-+ stats->qual.updated & IW_QUAL_NOISE_UPDATED
-+ ? '.' : ' ',
- stats->discard.nwid,
- stats->discard.code,
- stats->discard.fragment,
-@@ -470,13 +500,15 @@ static inline int ioctl_export_private(s
- /* Check NULL pointer */
- if(iwr->u.data.pointer == NULL)
- return -EFAULT;
--#ifdef WE_STRICT_WRITE
-+
- /* Check if there is enough buffer up there */
- if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
-- printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);
-+ /* User space can't know in advance how large the buffer
-+ * needs to be. Give it a hint, so that we can support
-+ * any size buffer we want somewhat efficiently... */
-+ iwr->u.data.length = dev->wireless_handlers->num_private_args;
- return -E2BIG;
- }
--#endif /* WE_STRICT_WRITE */
-
- /* Set the number of available ioctls. */
- iwr->u.data.length = dev->wireless_handlers->num_private_args;
-@@ -505,7 +537,6 @@ static inline int ioctl_standard_call(st
- const struct iw_ioctl_description * descr;
- struct iw_request_info info;
- int ret = -EINVAL;
-- int user_size = 0;
-
- /* Get the description of the IOCTL */
- if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
-@@ -536,8 +567,14 @@ static inline int ioctl_standard_call(st
- #endif /* WE_SET_EVENT */
- } else {
- char * extra;
-+ int extra_size;
-+ int user_length = 0;
- int err;
-
-+ /* Calculate space needed by arguments. Always allocate
-+ * for max space. Easier, and won't last long... */
-+ extra_size = descr->max_tokens * descr->token_size;
-+
- /* Check what user space is giving us */
- if(IW_IS_SET(cmd)) {
- /* Check NULL pointer */
-@@ -554,18 +591,33 @@ static inline int ioctl_standard_call(st
- if(iwr->u.data.pointer == NULL)
- return -EFAULT;
- /* Save user space buffer size for checking */
-- user_size = iwr->u.data.length;
-+ user_length = iwr->u.data.length;
-+
-+ /* Don't check if user_length > max to allow forward
-+ * compatibility. The test user_length < min is
-+ * implied by the test at the end. */
-+
-+ /* Support for very large requests */
-+ if((descr->flags & IW_DESCR_FLAG_NOMAX) &&
-+ (user_length > descr->max_tokens)) {
-+ /* Allow userspace to GET more than max so
-+ * we can support any size GET requests.
-+ * There is still a limit : -ENOMEM. */
-+ extra_size = user_length * descr->token_size;
-+ /* Note : user_length is originally a __u16,
-+ * and token_size is controlled by us,
-+ * so extra_size won't get negative and
-+ * won't overflow... */
-+ }
- }
-
- #ifdef WE_IOCTL_DEBUG
- printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",
-- dev->name, descr->max_tokens * descr->token_size);
-+ dev->name, extra_size);
- #endif /* WE_IOCTL_DEBUG */
-
-- /* Always allocate for max space. Easier, and won't last
-- * long... */
-- extra = kmalloc(descr->max_tokens * descr->token_size,
-- GFP_KERNEL);
-+ /* Create the kernel buffer */
-+ extra = kmalloc(extra_size, GFP_KERNEL);
- if (extra == NULL) {
- return -ENOMEM;
- }
-@@ -591,14 +643,11 @@ static inline int ioctl_standard_call(st
-
- /* If we have something to return to the user */
- if (!ret && IW_IS_GET(cmd)) {
--#ifdef WE_STRICT_WRITE
- /* Check if there is enough buffer up there */
-- if(user_size < iwr->u.data.length) {
-- printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
-+ if(user_length < iwr->u.data.length) {
- kfree(extra);
- return -E2BIG;
- }
--#endif /* WE_STRICT_WRITE */
-
- err = copy_to_user(iwr->u.data.pointer, extra,
- iwr->u.data.length *
-@@ -661,7 +710,7 @@ static inline int ioctl_private_call(str
- iw_handler handler)
- {
- struct iwreq * iwr = (struct iwreq *) ifr;
-- struct iw_priv_args * descr = NULL;
-+ const struct iw_priv_args * descr = NULL;
- struct iw_request_info info;
- int extra_size = 0;
- int i;
-@@ -701,7 +750,7 @@ static inline int ioctl_private_call(str
- ((extra_size + offset) <= IFNAMSIZ))
- extra_size = 0;
- } else {
-- /* Size of set arguments */
-+ /* Size of get arguments */
- extra_size = get_priv_size(descr->get_args);
-
- /* Does it fits in iwr ? */
-@@ -771,6 +820,14 @@ static inline int ioctl_private_call(str
-
- /* If we have something to return to the user */
- if (!ret && IW_IS_GET(cmd)) {
-+
-+ /* Adjust for the actual length if it's variable,
-+ * avoid leaking kernel bits outside. */
-+ if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) {
-+ extra_size = adjust_priv_size(descr->get_args,
-+ &(iwr->u));
-+ }
-+
- err = copy_to_user(iwr->u.data.pointer, extra,
- extra_size);
- if (err)
-@@ -1042,9 +1099,25 @@ void wireless_send_event(struct net_devi
- * One of the main advantage of centralising spy support here is that
- * it becomes much easier to improve and extend it without having to touch
- * the drivers. One example is the addition of the Spy-Threshold events.
-- * Note : IW_WIRELESS_SPY is defined in iw_handler.h
- */
-
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Return the pointer to the spy data in the driver.
-+ * Because this is called on the Rx path via wireless_spy_update(),
-+ * we want it to be efficient...
-+ */
-+static inline struct iw_spy_data * get_spydata(struct net_device *dev)
-+{
-+ /* This is the new way */
-+ if(dev->wireless_data)
-+ return(dev->wireless_data->spy_data);
-+
-+ /* This is the old way. Doesn't work for multi-headed drivers.
-+ * It will be removed in the next version of WE. */
-+ return (dev->priv + dev->wireless_handlers->spy_offset);
-+}
-+
- /*------------------------------------------------------------------*/
- /*
- * Standard Wireless Handler : set Spy List
-@@ -1054,16 +1127,26 @@ int iw_handler_set_spy(struct net_device
- union iwreq_data * wrqu,
- char * extra)
- {
--#ifdef IW_WIRELESS_SPY
-- struct iw_spy_data * spydata = (dev->priv +
-- dev->wireless_handlers->spy_offset);
-+ struct iw_spy_data * spydata = get_spydata(dev);
- struct sockaddr * address = (struct sockaddr *) extra;
-
-+ /* Make sure driver is not buggy or using the old API */
-+ if(!spydata)
-+ return -EOPNOTSUPP;
-+
- /* Disable spy collection while we copy the addresses.
-- * As we don't disable interrupts, we need to do this to avoid races.
-- * As we are the only writer, this is good enough. */
-+ * While we copy addresses, any call to wireless_spy_update()
-+ * will NOP. This is OK, as anyway the addresses are changing. */
- spydata->spy_number = 0;
-
-+ /* We want to operate without locking, because wireless_spy_update()
-+ * most likely will happen in the interrupt handler, and therefore
-+ * have its own locking constraints and needs performance.
-+ * The rtnl_lock() make sure we don't race with the other iw_handlers.
-+ * This make sure wireless_spy_update() "see" that the spy list
-+ * is temporarily disabled. */
-+ wmb();
-+
- /* Are there are addresses to copy? */
- if(wrqu->data.length > 0) {
- int i;
-@@ -1089,13 +1172,14 @@ int iw_handler_set_spy(struct net_device
- spydata->spy_address[i][5]);
- #endif /* WE_SPY_DEBUG */
- }
-+
-+ /* Make sure above is updated before re-enabling */
-+ wmb();
-+
- /* Enable addresses */
- spydata->spy_number = wrqu->data.length;
-
- return 0;
--#else /* IW_WIRELESS_SPY */
-- return -EOPNOTSUPP;
--#endif /* IW_WIRELESS_SPY */
- }
-
- /*------------------------------------------------------------------*/
-@@ -1107,12 +1191,14 @@ int iw_handler_get_spy(struct net_device
- union iwreq_data * wrqu,
- char * extra)
- {
--#ifdef IW_WIRELESS_SPY
-- struct iw_spy_data * spydata = (dev->priv +
-- dev->wireless_handlers->spy_offset);
-+ struct iw_spy_data * spydata = get_spydata(dev);
- struct sockaddr * address = (struct sockaddr *) extra;
- int i;
-
-+ /* Make sure driver is not buggy or using the old API */
-+ if(!spydata)
-+ return -EOPNOTSUPP;
-+
- wrqu->data.length = spydata->spy_number;
-
- /* Copy addresses. */
-@@ -1129,9 +1215,6 @@ int iw_handler_get_spy(struct net_device
- for(i = 0; i < spydata->spy_number; i++)
- spydata->spy_stat[i].updated = 0;
- return 0;
--#else /* IW_WIRELESS_SPY */
-- return -EOPNOTSUPP;
--#endif /* IW_WIRELESS_SPY */
- }
-
- /*------------------------------------------------------------------*/
-@@ -1143,11 +1226,13 @@ int iw_handler_set_thrspy(struct net_dev
- union iwreq_data * wrqu,
- char * extra)
- {
--#ifdef IW_WIRELESS_THRSPY
-- struct iw_spy_data * spydata = (dev->priv +
-- dev->wireless_handlers->spy_offset);
-+ struct iw_spy_data * spydata = get_spydata(dev);
- struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
-
-+ /* Make sure driver is not buggy or using the old API */
-+ if(!spydata)
-+ return -EOPNOTSUPP;
-+
- /* Just do it */
- memcpy(&(spydata->spy_thr_low), &(threshold->low),
- 2 * sizeof(struct iw_quality));
-@@ -1160,9 +1245,6 @@ int iw_handler_set_thrspy(struct net_dev
- #endif /* WE_SPY_DEBUG */
-
- return 0;
--#else /* IW_WIRELESS_THRSPY */
-- return -EOPNOTSUPP;
--#endif /* IW_WIRELESS_THRSPY */
- }
-
- /*------------------------------------------------------------------*/
-@@ -1174,22 +1256,20 @@ int iw_handler_get_thrspy(struct net_dev
- union iwreq_data * wrqu,
- char * extra)
- {
--#ifdef IW_WIRELESS_THRSPY
-- struct iw_spy_data * spydata = (dev->priv +
-- dev->wireless_handlers->spy_offset);
-+ struct iw_spy_data * spydata = get_spydata(dev);
- struct iw_thrspy * threshold = (struct iw_thrspy *) extra;
-
-+ /* Make sure driver is not buggy or using the old API */
-+ if(!spydata)
-+ return -EOPNOTSUPP;
-+
- /* Just do it */
- memcpy(&(threshold->low), &(spydata->spy_thr_low),
- 2 * sizeof(struct iw_quality));
-
- return 0;
--#else /* IW_WIRELESS_THRSPY */
-- return -EOPNOTSUPP;
--#endif /* IW_WIRELESS_THRSPY */
- }
-
--#ifdef IW_WIRELESS_THRSPY
- /*------------------------------------------------------------------*/
- /*
- * Prepare and send a Spy Threshold event
-@@ -1227,7 +1307,6 @@ static void iw_send_thrspy_event(struct
- /* Send event to user space */
- wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
- }
--#endif /* IW_WIRELESS_THRSPY */
-
- /* ---------------------------------------------------------------- */
- /*
-@@ -1240,12 +1319,14 @@ void wireless_spy_update(struct net_devi
- unsigned char * address,
- struct iw_quality * wstats)
- {
--#ifdef IW_WIRELESS_SPY
-- struct iw_spy_data * spydata = (dev->priv +
-- dev->wireless_handlers->spy_offset);
-+ struct iw_spy_data * spydata = get_spydata(dev);
- int i;
- int match = -1;
-
-+ /* Make sure driver is not buggy or using the old API */
-+ if(!spydata)
-+ return;
-+
- #ifdef WE_SPY_DEBUG
- printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
- #endif /* WE_SPY_DEBUG */
-@@ -1257,7 +1338,7 @@ void wireless_spy_update(struct net_devi
- sizeof(struct iw_quality));
- match = i;
- }
--#ifdef IW_WIRELESS_THRSPY
-+
- /* Generate an event if we cross the spy threshold.
- * To avoid event storms, we have a simple hysteresis : we generate
- * event only when we go under the low threshold or above the
-@@ -1277,6 +1358,4 @@ void wireless_spy_update(struct net_devi
- }
- }
- }
--#endif /* IW_WIRELESS_THRSPY */
--#endif /* IW_WIRELESS_SPY */
- }
diff --git a/recipes/linux/files/mipv6-1.1-v2.4.25.patch b/recipes/linux/files/mipv6-1.1-v2.4.25.patch
deleted file mode 100644
index b7f9b8fc8a..0000000000
--- a/recipes/linux/files/mipv6-1.1-v2.4.25.patch
+++ /dev/null
@@ -1,19832 +0,0 @@
-diff -uprN linux-2.4.25.old/Documentation/Configure.help linux-2.4.25/Documentation/Configure.help
---- linux-2.4.25.old/Documentation/Configure.help 2004-06-26 11:22:00.000000000 +0100
-+++ linux-2.4.25/Documentation/Configure.help 2004-06-26 11:29:29.000000000 +0100
-@@ -6204,6 +6204,57 @@ CONFIG_IPV6
-
- It is safe to say N here for now.
-
-+IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL)
-+CONFIG_IPV6_TUNNEL
-+ Experimental IP6-IP6 tunneling. You must select this, if you want
-+ to use CONFIG_IPV6_MOBILITY. More information in MIPL Mobile IPv6
-+ instructions.
-+
-+ If you don't want IP6-IP6 tunnels and Mobile IPv6, say N.
-+
-+IPv6: Mobility Support (EXPERIMENTAL)
-+CONFIG_IPV6_MOBILITY
-+ This is experimental support for the upcoming specification of
-+ Mobile IPv6. Mobile IPv6 allows nodes to seamlessly move between
-+ networks without changing their IP addresses, thus allowing them to
-+ maintain upper layer connections (e.g. TCP). Selecting this option
-+ allows your computer to act as a Correspondent Node (CN). A MIPv6
-+ Mobile Node will be able to communicate with the CN and use route
-+ optimization.
-+
-+ For more information and configuration details, see
-+ http://www.mipl.mediapoli.com/.
-+
-+ If unsure, say N.
-+
-+MIPv6: Mobile Node Support
-+CONFIG_IPV6_MOBILITY_MN
-+ If you want your computer to be a MIPv6 Mobile Node (MN), select
-+ this option. You must configure MN using the userspace tools
-+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/.
-+
-+ If your computer is stationary, or you are unsure if you need this,
-+ say N. Note that you will need a properly configured MIPv6 Home
-+ Agent to use any Mobile Nodes.
-+
-+MIPv6: Home Agent Support
-+CONFIG_IPV6_MOBILITY_HA
-+ If you want your router to serve as a MIPv6 Home Agent (HA), select
-+ this option. You must configure HA using the userspace tools
-+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/.
-+
-+ If your computer is not a router, or you are unsure if you need
-+ this, say N.
-+
-+MIPv6: Debug messages
-+CONFIG_IPV6_MOBILITY_DEBUG
-+ MIPL Mobile IPv6 can produce a lot of debugging messages. There are
-+ eight debug levels (0 through 7) and the level is controlled via
-+ /proc/sys/net/ipv6/mobility/debuglevel. Since MIPL is still
-+ experimental, you might want to say Y here.
-+
-+ Be sure to say Y and record debug messages when submitting a bug
-+ report.
- The SCTP Protocol (EXPERIMENTAL)
- CONFIG_IP_SCTP
- Stream Control Transmission Protocol
-diff -uprN linux-2.4.25.old/Documentation/DocBook/Makefile linux-2.4.25/Documentation/DocBook/Makefile
---- linux-2.4.25.old/Documentation/DocBook/Makefile 2002-11-28 23:53:08.000000000 +0000
-+++ linux-2.4.25/Documentation/DocBook/Makefile 2004-06-26 11:29:29.000000000 +0100
-@@ -2,7 +2,7 @@ BOOKS := wanbook.sgml z8530book.sgml mca
- kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
- kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
- deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
-- journal-api.sgml
-+ journal-api.sgml mip6-func.sgml
-
- PS := $(patsubst %.sgml, %.ps, $(BOOKS))
- PDF := $(patsubst %.sgml, %.pdf, $(BOOKS))
-@@ -86,6 +86,9 @@ videobook.sgml: videobook.tmpl $(TOPDIR)
- procfs-guide.sgml: procfs-guide.tmpl procfs_example.sgml
- $(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@
-
-+mip6-func.sgml: mip6-func.tmpl
-+ $(TOPDIR)/scripts/docgen <$< >$@
-+
- APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
- $(TOPDIR)/arch/i386/kernel/irq.c \
- $(TOPDIR)/arch/i386/kernel/mca.c \
-diff -uprN linux-2.4.25.old/Documentation/DocBook/mip6-func.tmpl linux-2.4.25/Documentation/DocBook/mip6-func.tmpl
---- linux-2.4.25.old/Documentation/DocBook/mip6-func.tmpl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/Documentation/DocBook/mip6-func.tmpl 2004-06-26 11:29:29.000000000 +0100
-@@ -0,0 +1,756 @@
-+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
-+<book id="LinuxMobileIPv6">
-+ <bookinfo>
-+ <title>MIPL Mobile IPv6 Function Reference Guide</title>
-+
-+ <authorgroup>
-+ <author>
-+ <othername>MIPL Mobile IPv6 for Linux Team</othername>
-+ <affiliation>
-+ <orgname>Helsinki University of Technology</orgname>
-+ <orgdiv>Telecommunications Software and Multimedia Lab</orgdiv>
-+ <address>
-+ <pob>PO BOX 9201</pob>
-+ <postcode>FIN-02015 HUT</postcode>
-+ <country>Finland</country>
-+ <email>mipl@list.mipl.mediapoli.com</email>
-+ </address>
-+ </affiliation>
-+ </author>
-+ </authorgroup>
-+
-+ <copyright>
-+ <year>2000-2001</year>
-+ <holder>Helsinki University of Technology</holder>
-+ </copyright>
-+
-+ <legalnotice>
-+ <para>
-+ Copyright (c) 2001, 2002 MIPL Mobile IPv6 for Linux Team.
-+ </para>
-+ <para>
-+ Permission is granted to copy, distribute and/or modify this
-+ document under the terms of the GNU Free Documentation License,
-+ Version 1.1 published by the Free Software Foundation; with the
-+ Invariant Sections being "Introduction", with the Front-Cover
-+ Texts being "MIPL Mobile IPv6 Function Reference Guide", "MIPL
-+ Mobile IPv6 for Linux Team" and "Helsinki University of
-+ Technology". A copy of the license is included in <xref
-+ linkend="gfdl">.
-+ </para>
-+
-+ </legalnotice>
-+ </bookinfo>
-+
-+<toc></toc>
-+
-+ <preface id="intro">
-+ <title>Introduction</title>
-+
-+ <para>
-+ MIPL Mobile IPv6 for Linux is an implementation of Mobility
-+ Support in IPv6 IETF mobile-ip working groups Internet-Draft
-+ (draft-ietf-mobileip-ipv6). This implementation has been
-+ developed in the Telecommunications Software and Multimedia
-+ Laboratory at Helsinki University of Technology.
-+ </para>
-+
-+ <para>
-+ MIPL is fully open source, licensed under the GNU General
-+ Public License. Latest source for MIPL can be downloaded from
-+ the MIPL website at:
-+ </para>
-+ <programlisting>
-+ http://www.mipl.mediapoli.com/.
-+ </programlisting>
-+ <para>
-+ Developers and users interested in MIPL can subscribe to the
-+ MIPL mailing list by sending e-mail to
-+ <email>majordomo@list.mipl.mediapoli.com</email> with
-+ </para>
-+ <programlisting>
-+ subscribe mipl
-+ </programlisting>
-+ <para>
-+ in the body of the message.
-+ </para>
-+
-+ <para>
-+ This document is a reference guide to MIPL functions. Intended
-+ audience is developers wishing to contribute to the project.
-+ Hopefully this document will make it easier and quicker to
-+ understand and adopt the inner workings of MIPL Mobile IPv6.
-+ </para>
-+
-+ <para>
-+ MIPL Mobile IPv6 for Linux Team members (past and present):
-+
-+ <itemizedlist>
-+ <listitem>
-+ <address>
-+ Sami Kivisaari <email>Sami.Kivisaari@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Niklas Kampe <email>Niklas.Kampe@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Juha Mynttinen <email>Juha.Mynttinen@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Toni Nykanen <email>Toni.Nykanen@iki.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Henrik Petander <email>Henrik.Petander@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Antti Tuominen <email>ajtuomin@tml.hut.fi</email>
-+ </address>
-+ </listitem>
-+ </itemizedlist>
-+
-+ <itemizedlist>
-+ <listitem>
-+ <address>
-+ Marko Myllynen
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Ville Nuorvala <email>vnuorval@tcs.hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Jaakko Laine <email>Jaakko.Laine@hut.fi</email>
-+ </address>
-+ </listitem>
-+ </itemizedlist>
-+ </para>
-+
-+ </preface>
-+
-+ <chapter id="common">
-+ <title>Common functions for all entities</title>
-+
-+ <sect1><title>Low-level functions</title>
-+ <para>
-+ These functions implement memory allocation used by others.
-+ Hashlist functions implement a linked list with hash lookup,
-+ which is used with Binding Update List, Binding Cache, Home
-+ Agents List etc.
-+ </para>
-+!Inet/ipv6/mobile_ip6/mempool.h
-+!Inet/ipv6/mobile_ip6/hashlist.h
-+ </sect1>
-+
-+ <sect1><title>Debug functions</title>
-+ <para>
-+ Debug and utility functions. These functions are available if
-+ <constant>CONFIG_IPV6_MOBILITY_DEBUG</constant> is set.
-+ Otherwise macros expand to no operation.
-+ </para>
-+!Inet/ipv6/mobile_ip6/debug.h
-+!Inet/ipv6/mobile_ip6/mipv6.c
-+ </sect1>
-+
-+ <sect1><title>Extension Header functions</title>
-+ <para>
-+ These functions create and handle extension headers that are
-+ specific to MIPv6.
-+ </para>
-+!Inet/ipv6/mobile_ip6/exthdrs.c
-+ </sect1>
-+
-+ <sect1><title>Mobility Header functions</title>
-+ <para>
-+ MIPv6 specifies a new protocol called Mobility Header.
-+ Mobility Header has several message types. Messages may also
-+ carry Mobility Options. These functions are used to create and
-+ handle Mobility Headers and Mobility Options.
-+ </para>
-+!Inet/ipv6/mobile_ip6/sendopts.c
-+!Inet/ipv6/mobile_ip6/mh_recv.c
-+!Inet/ipv6/mobile_ip6/auth_subopt.c
-+ </sect1>
-+
-+ <sect1><title>Binding Cache</title>
-+ <para>
-+ All Mobile IPv6 entities have a binding cache. These functions
-+ provide easy manipulation of the binding cache.
-+ </para>
-+!Inet/ipv6/mobile_ip6/bcache.c
-+ </sect1>
-+
-+ <sect1><title>Security</title>
-+
-+ <para>
-+ These functions are common authentication functions and
-+ implement Draft 13 style IPSec AH support for Binding Updates.
-+ </para>
-+!Inet/ipv6/mobile_ip6/ah_algo.c
-+!Inet/ipv6/mobile_ip6/sadb.c
-+!Inet/ipv6/mobile_ip6/ah.c
-+ </sect1>
-+
-+ <sect1><title>Utility functions</title>
-+
-+ <para>
-+ These functions are general utility functions commonly used by
-+ all entities.
-+ </para>
-+!Inet/ipv6/mobile_ip6/util.c
-+ </sect1>
-+
-+ </chapter>
-+
-+ <chapter id="mn">
-+ <title>Mobile Node functions</title>
-+ <sect1><title>General functions</title>
-+ <para>
-+ </para>
-+!Inet/ipv6/mobile_ip6/mn.c
-+ </sect1>
-+
-+ <sect1><title>Binding Update List</title>
-+ <para>
-+ Mobile Node keeps track of sent binding updates in Binding
-+ Update List.
-+ </para>
-+!Inet/ipv6/mobile_ip6/bul.c
-+ </sect1>
-+
-+ <sect1><title>Movement detection</title>
-+
-+ <para>
-+ These functions are used by the mobile node for movement
-+ detection.
-+ </para>
-+!Inet/ipv6/mobile_ip6/mdetect.c
-+ </sect1>
-+ </chapter>
-+
-+ <chapter id="ha">
-+ <title>Home Agent functions</title>
-+ <sect1><title>General functions</title>
-+ <para>
-+ </para>
-+!Inet/ipv6/mobile_ip6/ha.c
-+ </sect1>
-+
-+ <sect1><title>Duplicate Address Detection functions</title>
-+ <para>
-+ Home Agent does Duplicate Address Detection for Mobile Nodes'
-+ addresses. These functions implement MIPv6 specific DAD
-+ functionality.
-+ </para>
-+!Inet/ipv6/mobile_ip6/dad.c
-+ </sect1>
-+
-+ </chapter>
-+ <appendix id="gfdl">
-+ <title>GNU Free Documentation License</title>
-+
-+ <para>
-+ Version 1.1, March 2000
-+ </para>
-+
-+ <programlisting>
-+ Copyright (C) 2000 Free Software Foundation, Inc.
-+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+ </programlisting>
-+
-+ <sect1><title>0. PREAMBLE</title>
-+
-+ <para>
-+ The purpose of this License is to make a manual, textbook, or
-+ other written document "free" in the sense of freedom: to
-+ assure everyone the effective freedom to copy and redistribute
-+ it, with or without modifying it, either commercially or
-+ noncommercially. Secondarily, this License preserves for the
-+ author and publisher a way to get credit for their work, while
-+ not being considered responsible for modifications made by
-+ others.
-+ </para>
-+
-+ <para>
-+ This License is a kind of "copyleft", which means that
-+ derivative works of the document must themselves be free in the
-+ same sense. It complements the GNU General Public License,
-+ which is a copyleft license designed for free software.
-+ </para>
-+
-+ <para>
-+ We have designed this License in order to use it for manuals
-+ for free software, because free software needs free
-+ documentation: a free program should come with manuals
-+ providing the same freedoms that the software does. But this
-+ License is not limited to software manuals; it can be used for
-+ any textual work, regardless of subject matter or whether it is
-+ published as a printed book. We recommend this License
-+ principally for works whose purpose is instruction or
-+ reference.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>1. APPLICABILITY AND DEFINITIONS</title>
-+
-+ <para>
-+ This License applies to any manual or other work that contains
-+ a notice placed by the copyright holder saying it can be
-+ distributed under the terms of this License. The "Document",
-+ below, refers to any such manual or work. Any member of the
-+ public is a licensee, and is addressed as "you".
-+ </para>
-+
-+ <para>
-+ A "Modified Version" of the Document means any work containing
-+ the Document or a portion of it, either copied verbatim, or
-+ with modifications and/or translated into another language.
-+ </para>
-+
-+ <para>
-+ A "Secondary Section" is a named appendix or a front-matter
-+ section of the Document that deals exclusively with the
-+ relationship of the publishers or authors of the Document to
-+ the Document's overall subject (or to related matters) and
-+ contains nothing that could fall directly within that overall
-+ subject. (For example, if the Document is in part a textbook of
-+ mathematics, a Secondary Section may not explain any
-+ mathematics.) The relationship could be a matter of historical
-+ connection with the subject or with related matters, or of
-+ legal, commercial, philosophical, ethical or political position
-+ regarding them.
-+ </para>
-+
-+ <para>
-+ The "Invariant Sections" are certain Secondary Sections whose
-+ titles are designated, as being those of Invariant Sections, in
-+ the notice that says that the Document is released under this
-+ License.
-+ </para>
-+
-+ <para>
-+ The "Cover Texts" are certain short passages of text that are
-+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
-+ that says that the Document is released under this License.
-+ </para>
-+
-+ <para>
-+ A "Transparent" copy of the Document means a machine-readable
-+ copy, represented in a format whose specification is available
-+ to the general public, whose contents can be viewed and edited
-+ directly and straightforwardly with generic text editors or
-+ (for images composed of pixels) generic paint programs or (for
-+ drawings) some widely available drawing editor, and that is
-+ suitable for input to text formatters or for automatic
-+ translation to a variety of formats suitable for input to text
-+ formatters. A copy made in an otherwise Transparent file format
-+ whose markup has been designed to thwart or discourage
-+ subsequent modification by readers is not Transparent. A copy
-+ that is not "Transparent" is called "Opaque".
-+ </para>
-+
-+ <para>
-+ Examples of suitable formats for Transparent copies include
-+ plain ASCII without markup, Texinfo input format, LaTeX input
-+ format, SGML or XML using a publicly available DTD, and
-+ standard-conforming simple HTML designed for human
-+ modification. Opaque formats include PostScript, PDF,
-+ proprietary formats that can be read and edited only by
-+ proprietary word processors, SGML or XML for which the DTD
-+ and/or processing tools are not generally available, and the
-+ machine-generated HTML produced by some word processors for
-+ output purposes only.
-+ </para>
-+
-+ <para>
-+ The "Title Page" means, for a printed book, the title page
-+ itself, plus such following pages as are needed to hold,
-+ legibly, the material this License requires to appear in the
-+ title page. For works in formats which do not have any title
-+ page as such, "Title Page" means the text near the most
-+ prominent appearance of the work's title, preceding the
-+ beginning of the body of the text.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>2. VERBATIM COPYING</title>
-+
-+ <para>
-+ You may copy and distribute the Document in any medium, either
-+ commercially or noncommercially, provided that this License,
-+ the copyright notices, and the license notice saying this
-+ License applies to the Document are reproduced in all copies,
-+ and that you add no other conditions whatsoever to those of
-+ this License. You may not use technical measures to obstruct or
-+ control the reading or further copying of the copies you make
-+ or distribute. However, you may accept compensation in exchange
-+ for copies. If you distribute a large enough number of copies
-+ you must also follow the conditions in section 3.
-+ </para>
-+
-+ <para>
-+ You may also lend copies, under the same conditions stated
-+ above, and you may publicly display copies.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>3. COPYING IN QUANTITY</title>
-+
-+ <para>
-+ If you publish printed copies of the Document numbering more
-+ than 100, and the Document's license notice requires Cover
-+ Texts, you must enclose the copies in covers that carry,
-+ clearly and legibly, all these Cover Texts: Front-Cover Texts
-+ on the front cover, and Back-Cover Texts on the back
-+ cover. Both covers must also clearly and legibly identify you
-+ as the publisher of these copies. The front cover must present
-+ the full title with all words of the title equally prominent
-+ and visible. You may add other material on the covers in
-+ addition. Copying with changes limited to the covers, as long
-+ as they preserve the title of the Document and satisfy these
-+ conditions, can be treated as verbatim copying in other
-+ respects.
-+ </para>
-+
-+ <para>
-+ If the required texts for either cover are too voluminous to
-+ fit legibly, you should put the first ones listed (as many as
-+ fit reasonably) on the actual cover, and continue the rest onto
-+ adjacent pages.
-+ </para>
-+
-+ <para>
-+ If you publish or distribute Opaque copies of the Document
-+ numbering more than 100, you must either include a
-+ machine-readable Transparent copy along with each Opaque copy,
-+ or state in or with each Opaque copy a publicly-accessible
-+ computer-network location containing a complete Transparent
-+ copy of the Document, free of added material, which the general
-+ network-using public has access to download anonymously at no
-+ charge using public-standard network protocols. If you use the
-+ latter option, you must take reasonably prudent steps, when you
-+ begin distribution of Opaque copies in quantity, to ensure that
-+ this Transparent copy will remain thus accessible at the stated
-+ location until at least one year after the last time you
-+ distribute an Opaque copy (directly or through your agents or
-+ retailers) of that edition to the public.
-+ </para>
-+
-+ <para>
-+ It is requested, but not required, that you contact the authors
-+ of the Document well before redistributing any large number of
-+ copies, to give them a chance to provide you with an updated
-+ version of the Document.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>4. MODIFICATIONS</title>
-+
-+ <para>
-+ You may copy and distribute a Modified Version of the Document
-+ under the conditions of sections 2 and 3 above, provided that
-+ you release the Modified Version under precisely this License,
-+ with the Modified Version filling the role of the Document,
-+ thus licensing distribution and modification of the Modified
-+ Version to whoever possesses a copy of it. In addition, you
-+ must do these things in the Modified Version:
-+ </para>
-+
-+ <para>
-+ <itemizedlist spacing=compact>
-+ <listitem>
-+ <para>
-+ A. Use in the Title Page (and on the covers, if any) a title
-+ distinct from that of the Document, and from those of previous
-+ versions (which should, if there were any, be listed in the
-+ History section of the Document). You may use the same title
-+ as a previous version if the original publisher of that
-+ version gives permission.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ B. List on the Title Page, as authors, one or more persons
-+ or entities responsible for authorship of the modifications in
-+ the Modified Version, together with at least five of the
-+ principal authors of the Document (all of its principal
-+ authors, if it has less than five).
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ C. State on the Title page the name of the publisher of the
-+ Modified Version, as the publisher.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ D. Preserve all the copyright notices of the Document.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ E. Add an appropriate copyright notice for your
-+ modifications adjacent to the other copyright notices.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ F. Include, immediately after the copyright notices, a
-+ license notice giving the public permission to use the
-+ Modified Version under the terms of this License, in the form
-+ shown in the Addendum below.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ G. Preserve in that license notice the full lists of
-+ Invariant Sections and required Cover Texts given in the
-+ Document's license notice.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ H. Include an unaltered copy of this License.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ I. Preserve the section entitled "History", and its title,
-+ and add to it an item stating at least the title, year, new
-+ authors, and publisher of the Modified Version as given on the
-+ Title Page. If there is no section entitled "History" in the
-+ Document, create one stating the title, year, authors, and
-+ publisher of the Document as given on its Title Page, then add
-+ an item describing the Modified Version as stated in the
-+ previous sentence.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ J. Preserve the network location, if any, given in the
-+ Document for public access to a Transparent copy of the
-+ Document, and likewise the network locations given in the
-+ Document for previous versions it was based on. These may be
-+ placed in the "History" section. You may omit a network
-+ location for a work that was published at least four years
-+ before the Document itself, or if the original publisher of
-+ the version it refers to gives permission.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ K. In any section entitled "Acknowledgements" or
-+ "Dedications", preserve the section's title, and preserve in
-+ the section all the substance and tone of each of the
-+ contributor acknowledgements and/or dedications given therein.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ L. Preserve all the Invariant Sections of the Document,
-+ unaltered in their text and in their titles. Section numbers
-+ or the equivalent are not considered part of the section
-+ titles.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ M. Delete any section entitled "Endorsements". Such a
-+ section may not be included in the Modified Version.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ N. Do not retitle any existing section as "Endorsements" or
-+ to conflict in title with any Invariant Section.
-+ </para>
-+ </listitem>
-+ </itemizedlist>
-+ </para>
-+
-+ <para>
-+ If the Modified Version includes new front-matter sections or
-+ appendices that qualify as Secondary Sections and contain no
-+ material copied from the Document, you may at your option
-+ designate some or all of these sections as invariant. To do
-+ this, add their titles to the list of Invariant Sections in the
-+ Modified Version's license notice. These titles must be
-+ distinct from any other section titles.
-+ </para>
-+
-+ <para>
-+ You may add a section entitled "Endorsements", provided it
-+ contains nothing but endorsements of your Modified Version by
-+ various parties--for example, statements of peer review or that
-+ the text has been approved by an organization as the
-+ authoritative definition of a standard.
-+ </para>
-+
-+ <para>
-+ You may add a passage of up to five words as a Front-Cover
-+ Text, and a passage of up to 25 words as a Back-Cover Text, to
-+ the end of the list of Cover Texts in the Modified
-+ Version. Only one passage of Front-Cover Text and one of
-+ Back-Cover Text may be added by (or through arrangements made
-+ by) any one entity. If the Document already includes a cover
-+ text for the same cover, previously added by you or by
-+ arrangement made by the same entity you are acting on behalf
-+ of, you may not add another; but you may replace the old one,
-+ on explicit permission from the previous publisher that added
-+ the old one.
-+ </para>
-+
-+ <para>
-+ The author(s) and publisher(s) of the Document do not by this
-+ License give permission to use their names for publicity for or
-+ to assert or imply endorsement of any Modified Version.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>5. COMBINING DOCUMENTS</title>
-+
-+ <para>
-+ You may combine the Document with other documents released
-+ under this License, under the terms defined in section 4 above
-+ for modified versions, provided that you include in the
-+ combination all of the Invariant Sections of all of the
-+ original documents, unmodified, and list them all as Invariant
-+ Sections of your combined work in its license notice.
-+ </para>
-+
-+ <para>
-+ The combined work need only contain one copy of this License,
-+ and multiple identical Invariant Sections may be replaced with
-+ a single copy. If there are multiple Invariant Sections with
-+ the same name but different contents, make the title of each
-+ such section unique by adding at the end of it, in parentheses,
-+ the name of the original author or publisher of that section if
-+ known, or else a unique number. Make the same adjustment to the
-+ section titles in the list of Invariant Sections in the license
-+ notice of the combined work.
-+ </para>
-+
-+ <para>
-+ In the combination, you must combine any sections entitled
-+ "History" in the various original documents, forming one
-+ section entitled "History"; likewise combine any sections
-+ entitled "Acknowledgements", and any sections entitled
-+ "Dedications". You must delete all sections entitled
-+ "Endorsements."
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>6. COLLECTIONS OF DOCUMENTS</title>
-+
-+ <para>
-+ You may make a collection consisting of the Document and other
-+ documents released under this License, and replace the
-+ individual copies of this License in the various documents with
-+ a single copy that is included in the collection, provided that
-+ you follow the rules of this License for verbatim copying of
-+ each of the documents in all other respects.
-+ </para>
-+
-+ <para>
-+ You may extract a single document from such a collection, and
-+ distribute it individually under this License, provided you
-+ insert a copy of this License into the extracted document, and
-+ follow this License in all other respects regarding verbatim
-+ copying of that document.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>7. AGGREGATION WITH INDEPENDENT WORKS</title>
-+
-+ <para>
-+ A compilation of the Document or its derivatives with other
-+ separate and independent documents or works, in or on a volume
-+ of a storage or distribution medium, does not as a whole count
-+ as a Modified Version of the Document, provided no compilation
-+ copyright is claimed for the compilation. Such a compilation is
-+ called an "aggregate", and this License does not apply to the
-+ other self-contained works thus compiled with the Document, on
-+ account of their being thus compiled, if they are not
-+ themselves derivative works of the Document.
-+ </para>
-+
-+ <para>
-+ If the Cover Text requirement of section 3 is applicable to
-+ these copies of the Document, then if the Document is less than
-+ one quarter of the entire aggregate, the Document's Cover Texts
-+ may be placed on covers that surround only the Document within
-+ the aggregate. Otherwise they must appear on covers around the
-+ whole aggregate.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>8. TRANSLATION</title>
-+
-+ <para>
-+ Translation is considered a kind of modification, so you may
-+ distribute translations of the Document under the terms of
-+ section 4. Replacing Invariant Sections with translations
-+ requires special permission from their copyright holders, but
-+ you may include translations of some or all Invariant Sections
-+ in addition to the original versions of these Invariant
-+ Sections. You may include a translation of this License
-+ provided that you also include the original English version of
-+ this License. In case of a disagreement between the translation
-+ and the original English version of this License, the original
-+ English version will prevail.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>9. TERMINATION</title>
-+
-+ <para>
-+ You may not copy, modify, sublicense, or distribute the
-+ Document except as expressly provided for under this
-+ License. Any other attempt to copy, modify, sublicense or
-+ distribute the Document is void, and will automatically
-+ terminate your rights under this License. However, parties who
-+ have received copies, or rights, from you under this License
-+ will not have their licenses terminated so long as such parties
-+ remain in full compliance.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>10. FUTURE REVISIONS OF THIS LICENSE</title>
-+
-+ <para>
-+ The Free Software Foundation may publish new, revised versions
-+ of the GNU Free Documentation License from time to time. Such
-+ new versions will be similar in spirit to the present version,
-+ but may differ in detail to address new problems or
-+ concerns. See http://www.gnu.org/copyleft/.
-+ </para>
-+
-+ <para>
-+ Each version of the License is given a distinguishing version
-+ number. If the Document specifies that a particular numbered
-+ version of this License "or any later version" applies to it,
-+ you have the option of following the terms and conditions
-+ either of that specified version or of any later version that
-+ has been published (not as a draft) by the Free Software
-+ Foundation. If the Document does not specify a version number
-+ of this License, you may choose any version ever published (not
-+ as a draft) by the Free Software Foundation.
-+ </para>
-+
-+ </sect1>
-+ </appendix>
-+</book>
-diff -uprN linux-2.4.25.old/include/linux/icmpv6.h linux-2.4.25/include/linux/icmpv6.h
---- linux-2.4.25.old/include/linux/icmpv6.h 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/include/linux/icmpv6.h 2004-06-26 11:29:29.000000000 +0100
-@@ -40,14 +40,16 @@ struct icmp6hdr {
- struct icmpv6_nd_ra {
- __u8 hop_limit;
- #if defined(__LITTLE_ENDIAN_BITFIELD)
-- __u8 reserved:6,
-+ __u8 reserved:5,
-+ home_agent:1,
- other:1,
- managed:1;
-
- #elif defined(__BIG_ENDIAN_BITFIELD)
- __u8 managed:1,
- other:1,
-- reserved:6;
-+ home_agent:1,
-+ reserved:5;
- #else
- #error "Please fix <asm/byteorder.h>"
- #endif
-@@ -70,6 +72,7 @@ struct icmp6hdr {
- #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
- #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
- #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
-+#define icmp6_home_agent icmp6_dataun.u_nd_ra.home_agent
- };
-
-
-diff -uprN linux-2.4.25.old/include/linux/if_arp.h linux-2.4.25/include/linux/if_arp.h
---- linux-2.4.25.old/include/linux/if_arp.h 2002-02-25 19:38:13.000000000 +0000
-+++ linux-2.4.25/include/linux/if_arp.h 2004-06-26 11:29:29.000000000 +0100
-@@ -59,7 +59,7 @@
- #define ARPHRD_RAWHDLC 518 /* Raw HDLC */
-
- #define ARPHRD_TUNNEL 768 /* IPIP tunnel */
--#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */
-+#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
- #define ARPHRD_FRAD 770 /* Frame Relay Access Device */
- #define ARPHRD_SKIP 771 /* SKIP vif */
- #define ARPHRD_LOOPBACK 772 /* Loopback device */
-diff -uprN linux-2.4.25.old/include/linux/in6.h linux-2.4.25/include/linux/in6.h
---- linux-2.4.25.old/include/linux/in6.h 2003-06-13 15:51:38.000000000 +0100
-+++ linux-2.4.25/include/linux/in6.h 2004-06-26 11:29:29.000000000 +0100
-@@ -142,6 +142,11 @@ struct in6_flowlabel_req
- #define IPV6_TLV_JUMBO 194
-
- /*
-+ * Mobile IPv6 TLV options.
-+ */
-+#define MIPV6_TLV_HOMEADDR 201
-+
-+/*
- * IPV6 socket options
- */
-
-diff -uprN linux-2.4.25.old/include/linux/ipv6.h linux-2.4.25/include/linux/ipv6.h
---- linux-2.4.25.old/include/linux/ipv6.h 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/include/linux/ipv6.h 2004-06-26 11:29:29.000000000 +0100
-@@ -29,6 +29,7 @@ struct in6_ifreq {
-
- #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
- #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
-+#define IPV6_SRCRT_TYPE_2 2 /* type 2 for Mobile IPv6 */
-
- /*
- * routing header
-@@ -71,6 +72,19 @@ struct rt0_hdr {
- struct in6_addr addr[0];
-
- #define rt0_type rt_hdr.type
-+
-+};
-+
-+/*
-+ * routing header type 2
-+ */
-+
-+struct rt2_hdr {
-+ struct ipv6_rt_hdr rt_hdr;
-+ __u32 reserved;
-+ struct in6_addr addr;
-+
-+#define rt2_type rt_hdr.type;
- };
-
- /*
-@@ -156,12 +170,16 @@ enum {
- struct inet6_skb_parm
- {
- int iif;
-+ __u8 mipv6_flags;
- __u16 ra;
- __u16 hop;
- __u16 auth;
- __u16 dst0;
- __u16 srcrt;
-+ __u16 srcrt2;
-+ __u16 hao;
- __u16 dst1;
-+ struct in6_addr hoa;
- };
-
- #endif
-diff -uprN linux-2.4.25.old/include/linux/ipv6_route.h linux-2.4.25/include/linux/ipv6_route.h
---- linux-2.4.25.old/include/linux/ipv6_route.h 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/include/linux/ipv6_route.h 2004-06-26 11:29:29.000000000 +0100
-@@ -33,6 +33,7 @@ enum
- #define RTF_CACHE 0x01000000 /* cache entry */
- #define RTF_FLOW 0x02000000 /* flow significant route */
- #define RTF_POLICY 0x04000000 /* policy route */
-+#define RTF_MOBILENODE 0x10000000 /* for routing to Mobile Node */
-
- #define RTF_LOCAL 0x80000000
-
-diff -uprN linux-2.4.25.old/include/linux/ipv6_tunnel.h linux-2.4.25/include/linux/ipv6_tunnel.h
---- linux-2.4.25.old/include/linux/ipv6_tunnel.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/include/linux/ipv6_tunnel.h 2004-06-26 11:29:29.000000000 +0100
-@@ -0,0 +1,34 @@
-+/*
-+ * $Id$
-+ */
-+
-+#ifndef _IPV6_TUNNEL_H
-+#define _IPV6_TUNNEL_H
-+
-+#define IPV6_TLV_TNL_ENCAP_LIMIT 4
-+#define IPV6_DEFAULT_TNL_ENCAP_LIMIT 4
-+
-+/* don't add encapsulation limit if one isn't present in inner packet */
-+#define IP6_TNL_F_IGN_ENCAP_LIMIT 0x1
-+/* copy the traffic class field from the inner packet */
-+#define IP6_TNL_F_USE_ORIG_TCLASS 0x2
-+/* copy the flowlabel from the inner packet */
-+#define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4
-+/* created and maintained from within the kernel */
-+#define IP6_TNL_F_KERNEL_DEV 0x8
-+/* being used for Mobile IPv6 */
-+#define IP6_TNL_F_MIP6_DEV 0x10
-+
-+struct ip6_tnl_parm {
-+ char name[IFNAMSIZ]; /* name of tunnel device */
-+ int link; /* ifindex of underlying L2 interface */
-+ __u8 proto; /* tunnel protocol */
-+ __u8 encap_limit; /* encapsulation limit for tunnel */
-+ __u8 hop_limit; /* hop limit for tunnel */
-+ __u32 flowinfo; /* traffic class and flowlabel for tunnel */
-+ __u32 flags; /* tunnel flags */
-+ struct in6_addr laddr; /* local tunnel end-point address */
-+ struct in6_addr raddr; /* remote tunnel end-point address */
-+};
-+
-+#endif
-diff -uprN linux-2.4.25.old/include/linux/rtnetlink.h linux-2.4.25/include/linux/rtnetlink.h
---- linux-2.4.25.old/include/linux/rtnetlink.h 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/include/linux/rtnetlink.h 2004-06-26 11:29:29.000000000 +0100
-@@ -309,15 +309,17 @@ enum
- IFA_LABEL,
- IFA_BROADCAST,
- IFA_ANYCAST,
-- IFA_CACHEINFO
-+ IFA_CACHEINFO,
-+ IFA_HOMEAGENT
- };
-
--#define IFA_MAX IFA_CACHEINFO
-+#define IFA_MAX IFA_HOMEAGENT
-
- /* ifa_flags */
-
- #define IFA_F_SECONDARY 0x01
-
-+#define IFA_F_HOMEADDR 0x10
- #define IFA_F_DEPRECATED 0x20
- #define IFA_F_TENTATIVE 0x40
- #define IFA_F_PERMANENT 0x80
-diff -uprN linux-2.4.25.old/include/linux/skbuff.h linux-2.4.25/include/linux/skbuff.h
---- linux-2.4.25.old/include/linux/skbuff.h 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/include/linux/skbuff.h 2004-06-26 11:29:29.000000000 +0100
-@@ -177,7 +177,7 @@ struct sk_buff {
- * want to keep them across layers you have to do a skb_clone()
- * first. This is owned by whoever has the skb queued ATM.
- */
-- char cb[48];
-+ char cb[64];
-
- unsigned int len; /* Length of actual data */
- unsigned int data_len;
-diff -uprN linux-2.4.25.old/include/linux/sysctl.h linux-2.4.25/include/linux/sysctl.h
---- linux-2.4.25.old/include/linux/sysctl.h 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/include/linux/sysctl.h 2004-06-26 11:29:29.000000000 +0100
-@@ -387,7 +387,24 @@ enum {
- NET_IPV6_NEIGH=17,
- NET_IPV6_ROUTE=18,
- NET_IPV6_ICMP=19,
-- NET_IPV6_BINDV6ONLY=20
-+ NET_IPV6_BINDV6ONLY=20,
-+ NET_IPV6_MOBILITY=26
-+};
-+
-+/* /proc/sys/net/ipv6/mobility */
-+enum {
-+ NET_IPV6_MOBILITY_DEBUG=1,
-+ NET_IPV6_MOBILITY_TUNNEL_SITELOCAL=2,
-+ NET_IPV6_MOBILITY_ROUTER_SOLICITATION_MAX_SENDTIME=3,
-+ NET_IPV6_MOBILITY_ROUTER_REACH=4,
-+ NET_IPV6_MOBILITY_MDETECT_MECHANISM=5,
-+ NET_IPV6_MOBILITY_RETROUT=6,
-+ NET_IPV6_MOBILITY_MAX_TNLS=7,
-+ NET_IPV6_MOBILITY_MIN_TNLS=8,
-+ NET_IPV6_MOBILITY_BINDING_REFRESH=9,
-+ NET_IPV6_MOBILITY_BU_F_LLADDR=10,
-+ NET_IPV6_MOBILITY_BU_F_KEYMGM=11,
-+ NET_IPV6_MOBILITY_BU_F_CN_ACK=12
- };
-
- enum {
-diff -uprN linux-2.4.25.old/include/net/addrconf.h linux-2.4.25/include/net/addrconf.h
---- linux-2.4.25.old/include/net/addrconf.h 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/include/net/addrconf.h 2004-06-26 11:29:29.000000000 +0100
-@@ -16,9 +16,11 @@ struct prefix_info {
- #if defined(__BIG_ENDIAN_BITFIELD)
- __u8 onlink : 1,
- autoconf : 1,
-- reserved : 6;
-+ router_address : 1,
-+ reserved : 5;
- #elif defined(__LITTLE_ENDIAN_BITFIELD)
-- __u8 reserved : 6,
-+ __u8 reserved : 5,
-+ router_address : 1,
- autoconf : 1,
- onlink : 1;
- #else
-@@ -55,6 +57,7 @@ extern int ipv6_chk_addr(struct in6_ad
- struct net_device *dev);
- extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
- struct net_device *dev);
-+extern void ipv6_del_addr(struct inet6_ifaddr *ifp);
- extern int ipv6_get_saddr(struct dst_entry *dst,
- struct in6_addr *daddr,
- struct in6_addr *saddr);
-@@ -85,7 +88,9 @@ extern void ipv6_mc_up(struct inet6_dev
- extern void ipv6_mc_down(struct inet6_dev *idev);
- extern void ipv6_mc_init_dev(struct inet6_dev *idev);
- extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
-+extern void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
- extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
-+extern void addrconf_dad_completed(struct inet6_ifaddr *ifp);
-
- extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
- struct in6_addr *src_addr);
-@@ -116,6 +121,9 @@ extern int ipv6_chk_acast_addr(struct
- extern int register_inet6addr_notifier(struct notifier_block *nb);
- extern int unregister_inet6addr_notifier(struct notifier_block *nb);
-
-+extern int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
-+extern int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev);
-+
- static inline struct inet6_dev *
- __in6_dev_get(struct net_device *dev)
- {
-diff -uprN linux-2.4.25.old/include/net/ip6_route.h linux-2.4.25/include/net/ip6_route.h
---- linux-2.4.25.old/include/net/ip6_route.h 2003-06-13 15:51:39.000000000 +0100
-+++ linux-2.4.25/include/net/ip6_route.h 2004-06-26 11:29:29.000000000 +0100
-@@ -2,6 +2,7 @@
- #define _NET_IP6_ROUTE_H
-
- #define IP6_RT_PRIO_FW 16
-+#define IP6_RT_PRIO_MIPV6 64
- #define IP6_RT_PRIO_USER 1024
- #define IP6_RT_PRIO_ADDRCONF 256
- #define IP6_RT_PRIO_KERN 512
-@@ -40,6 +41,9 @@ extern int ipv6_route_ioctl(unsigned i
-
- extern int ip6_route_add(struct in6_rtmsg *rtmsg,
- struct nlmsghdr *);
-+
-+extern int ip6_route_del(struct in6_rtmsg *rtmsg,
-+ struct nlmsghdr *);
- extern int ip6_del_rt(struct rt6_info *,
- struct nlmsghdr *);
-
-@@ -99,7 +103,8 @@ extern rwlock_t rt6_lock;
- */
-
- static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
-- struct in6_addr *daddr)
-+ struct in6_addr *daddr,
-+ struct in6_addr *saddr)
- {
- struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
- struct rt6_info *rt = (struct rt6_info *) dst;
-@@ -107,6 +112,9 @@ static inline void ip6_dst_store(struct
- write_lock(&sk->dst_lock);
- __sk_dst_set(sk, dst);
- np->daddr_cache = daddr;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ np->saddr_cache = saddr;
-+#endif
- np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
- write_unlock(&sk->dst_lock);
- }
-diff -uprN linux-2.4.25.old/include/net/ipv6.h linux-2.4.25/include/net/ipv6.h
---- linux-2.4.25.old/include/net/ipv6.h 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/include/net/ipv6.h 2004-06-26 11:29:29.000000000 +0100
-@@ -37,6 +37,7 @@
- #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
- #define NEXTHDR_NONE 59 /* No next header */
- #define NEXTHDR_DEST 60 /* Destination options header. */
-+#define NEXTHDR_MH 135 /* Mobility header, RFC 3775 */
-
- #define NEXTHDR_MAX 255
-
-@@ -145,9 +146,12 @@ struct ipv6_txoptions
- __u16 opt_flen; /* after fragment hdr */
- __u16 opt_nflen; /* before fragment hdr */
-
-+ __u8 mipv6_flags; /* flags set by MIPv6 */
-+
- struct ipv6_opt_hdr *hopopt;
- struct ipv6_opt_hdr *dst0opt;
-- struct ipv6_rt_hdr *srcrt; /* Routing Header */
-+ struct ipv6_rt_hdr *srcrt; /* Routing Header Type 0 */
-+ struct ipv6_rt_hdr *srcrt2; /* Routing Header Type 2 */
- struct ipv6_opt_hdr *auth;
- struct ipv6_opt_hdr *dst1opt;
-
-@@ -256,6 +260,38 @@ static inline int ipv6_addr_any(const st
- a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
- }
-
-+static inline void ipv6_addr_prefix(struct in6_addr *pfx,
-+ const struct in6_addr *addr, int plen)
-+{
-+ /* caller must guarantee 0 <= plen <= 128 */
-+ int o = plen >> 3,
-+ b = plen & 0x7;
-+
-+ memcpy(pfx->s6_addr, addr, o);
-+ if (b != 0) {
-+ pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
-+ o++;
-+ }
-+ if (o < 16)
-+ memset(pfx->s6_addr + o, 0, 16 - o);
-+}
-+
-+static inline int ipv6_prefix_cmp(const struct in6_addr *p1,
-+ const struct in6_addr *p2, int plen)
-+{
-+ int b = plen&0x7;
-+ int o = plen>>3;
-+ int res = 0;
-+
-+ if (o > 0)
-+ res = memcmp(&p1->s6_addr[0], &p2->s6_addr[0], o);
-+ if (res == 0 && b > 0) {
-+ __u8 m = (0xff00 >> b) & 0xff;
-+ res = (p1->s6_addr[o] & m) - (p2->s6_addr[o] & m);
-+ }
-+ return res;
-+}
-+
- /*
- * Prototypes exported by ipv6
- */
-diff -uprN linux-2.4.25.old/include/net/ipv6_tunnel.h linux-2.4.25/include/net/ipv6_tunnel.h
---- linux-2.4.25.old/include/net/ipv6_tunnel.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/include/net/ipv6_tunnel.h 2004-06-26 11:29:29.000000000 +0100
-@@ -0,0 +1,92 @@
-+/*
-+ * $Id$
-+ */
-+
-+#ifndef _NET_IPV6_TUNNEL_H
-+#define _NET_IPV6_TUNNEL_H
-+
-+#include <linux/ipv6.h>
-+#include <linux/netdevice.h>
-+#include <linux/ipv6_tunnel.h>
-+#include <linux/skbuff.h>
-+#include <asm/atomic.h>
-+
-+/* capable of sending packets */
-+#define IP6_TNL_F_CAP_XMIT 0x10000
-+/* capable of receiving packets */
-+#define IP6_TNL_F_CAP_RCV 0x20000
-+
-+#define IP6_TNL_MAX 128
-+
-+/* IPv6 tunnel */
-+
-+struct ip6_tnl {
-+ struct ip6_tnl *next; /* next tunnel in list */
-+ struct net_device *dev; /* virtual device associated with tunnel */
-+ struct net_device_stats stat; /* statistics for tunnel device */
-+ int recursion; /* depth of hard_start_xmit recursion */
-+ struct ip6_tnl_parm parms; /* tunnel configuration paramters */
-+ struct flowi fl; /* flowi template for xmit */
-+ atomic_t refcnt; /* nr of identical tunnels used by kernel */
-+ struct socket *sock;
-+};
-+
-+#define IP6_TNL_PRE_ENCAP 0
-+#define IP6_TNL_PRE_DECAP 1
-+#define IP6_TNL_MAXHOOKS 2
-+
-+#define IP6_TNL_DROP 0
-+#define IP6_TNL_ACCEPT 1
-+
-+typedef int ip6_tnl_hookfn(struct ip6_tnl *t, struct sk_buff *skb);
-+
-+struct ip6_tnl_hook_ops {
-+ struct list_head list;
-+ unsigned int hooknum;
-+ int priority;
-+ ip6_tnl_hookfn *hook;
-+};
-+
-+enum ip6_tnl_hook_priorities {
-+ IP6_TNL_PRI_FIRST = INT_MIN,
-+ IP6_TNL_PRI_LAST = INT_MAX
-+};
-+
-+/* Tunnel encapsulation limit destination sub-option */
-+
-+struct ipv6_tlv_tnl_enc_lim {
-+ __u8 type; /* type-code for option */
-+ __u8 length; /* option length */
-+ __u8 encap_limit; /* tunnel encapsulation limit */
-+} __attribute__ ((packed));
-+
-+#ifdef __KERNEL__
-+extern int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt);
-+
-+extern struct ip6_tnl *ip6ip6_tnl_lookup(struct in6_addr *remote,
-+ struct in6_addr *local);
-+
-+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p);
-+
-+extern int ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p);
-+
-+extern int ip6ip6_kernel_tnl_del(struct ip6_tnl *t);
-+
-+extern unsigned int ip6ip6_tnl_inc_max_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_dec_max_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_inc_min_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_dec_min_kdev_count(unsigned int n);
-+
-+extern void ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg);
-+
-+extern void ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg);
-+
-+#ifdef CONFIG_IPV6_TUNNEL
-+extern int __init ip6_tunnel_init(void);
-+extern void ip6_tunnel_cleanup(void);
-+#endif
-+#endif
-+#endif
-diff -uprN linux-2.4.25.old/include/net/mipglue.h linux-2.4.25/include/net/mipglue.h
---- linux-2.4.25.old/include/net/mipglue.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/include/net/mipglue.h 2004-06-26 11:29:29.000000000 +0100
-@@ -0,0 +1,266 @@
-+/*
-+ * Glue for Mobility support integration to IPv6
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _NET_MIPGLUE_H
-+#define _NET_MIPGLUE_H
-+
-+#ifndef USE_IPV6_MOBILITY
-+#if defined(CONFIG_IPV6_MOBILITY) || defined(CONFIG_IPV6_MOBILITY_MODULE)
-+#define USE_IPV6_MOBILITY
-+#endif
-+#endif
-+
-+/* symbols to indicate whether destination options received should take
-+ * effect or not (see exthdrs.c, procrcv.c)
-+ */
-+#define MIPV6_DSTOPTS_ACCEPT 1
-+#define MIPV6_DSTOPTS_DISCARD 0
-+
-+#define MIPV6_IGN_RTR 0
-+#define MIPV6_ADD_RTR 1
-+#define MIPV6_CHG_RTR 2
-+
-+/* MIPV6: Approximate maximum for mobile IPv6 options and headers */
-+#define MIPV6_HEADERS 48
-+
-+#ifdef __KERNEL__
-+#include <net/mipv6.h>
-+#include <linux/slab.h>
-+#include <net/ipv6.h>
-+
-+struct sk_buff;
-+struct ndisc_options;
-+struct sock;
-+struct ipv6_txoptions;
-+struct flowi;
-+struct dst_entry;
-+struct in6_addr;
-+struct inet6_ifaddr;
-+
-+#ifdef USE_IPV6_MOBILITY
-+
-+/* calls a procedure from mipv6-module */
-+#define MIPV6_CALLPROC(X) if(mipv6_functions.X) mipv6_functions.X
-+
-+/* calls a function from mipv6-module, default-value if function not defined
-+ */
-+#define MIPV6_CALLFUNC(X,Y) (!mipv6_functions.X)?(Y):mipv6_functions.X
-+
-+/* sets a handler-function to process a call */
-+#define MIPV6_SETCALL(X,Y) if(mipv6_functions.X) printk("mipv6: Warning, function assigned twice!\n"); \
-+ mipv6_functions.X = Y
-+#define MIPV6_RESETCALL(X) mipv6_functions.X = NULL
-+
-+/* pointers to mipv6 callable functions */
-+struct mipv6_callable_functions {
-+ void (*mipv6_initialize_dstopt_rcv) (struct sk_buff *skb);
-+ int (*mipv6_finalize_dstopt_rcv) (int process);
-+ int (*mipv6_handle_homeaddr) (struct sk_buff *skb, int optoff);
-+ int (*mipv6_ra_rcv) (struct sk_buff *skb,
-+ struct ndisc_options *ndopts);
-+ void (*mipv6_icmp_rcv) (struct sk_buff *skb);
-+ struct ipv6_txoptions * (*mipv6_modify_txoptions) (
-+ struct sock *sk,
-+ struct sk_buff *skb,
-+ struct ipv6_txoptions *opt,
-+ struct flowi *fl,
-+ struct dst_entry **dst);
-+ void (*mipv6_set_home) (int ifindex, struct in6_addr *homeaddr,
-+ int plen, struct in6_addr *homeagent,
-+ int plen2);
-+ void (*mipv6_get_home_address) (struct in6_addr *home_addr);
-+ void (*mipv6_get_care_of_address)(struct in6_addr *homeaddr,
-+ struct in6_addr *coa);
-+ int (*mipv6_is_home_addr)(struct in6_addr *addr);
-+ void (*mipv6_change_router)(void);
-+ void (*mipv6_check_dad)(struct in6_addr *home_addr);
-+ void (*mipv6_icmp_swap_addrs)(struct sk_buff *skb);
-+ int (*mipv6_forward)(struct sk_buff *skb);
-+ int (*mipv6_mn_ha_probe)(struct inet6_ifaddr *ifp, u8 *lladdr);
-+};
-+
-+extern struct mipv6_callable_functions mipv6_functions;
-+
-+extern void mipv6_invalidate_calls(void);
-+
-+extern int mipv6_handle_dstopt(struct sk_buff *skb, int optoff);
-+
-+static inline int
-+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ return MIPV6_CALLFUNC(mipv6_mn_ha_probe, 0)(ifp, lladdr);
-+}
-+
-+/* Must only be called for HA, no checks here */
-+static inline int ip6_mipv6_forward(struct sk_buff *skb)
-+{
-+ return MIPV6_CALLFUNC(mipv6_forward, 0)(skb);
-+}
-+
-+/*
-+ * Avoid adding new default routers if the old one is still in use
-+ */
-+
-+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb,
-+ struct ndisc_options *ndopts)
-+{
-+ return MIPV6_CALLFUNC(mipv6_ra_rcv, MIPV6_ADD_RTR)(skb, ndopts);
-+}
-+
-+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr)
-+{
-+ return MIPV6_CALLFUNC(mipv6_is_home_addr, 0)(addr);
-+}
-+
-+static inline void ndisc_mipv6_change_router(int change_rtr)
-+{
-+ if (change_rtr == MIPV6_CHG_RTR)
-+ MIPV6_CALLPROC(mipv6_change_router)();
-+}
-+
-+static inline void ndisc_check_mipv6_dad(struct in6_addr *target)
-+{
-+ MIPV6_CALLPROC(mipv6_check_dad)(target);
-+}
-+
-+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb)
-+{
-+ MIPV6_CALLPROC(mipv6_icmp_swap_addrs)(skb);
-+}
-+
-+static inline void mipv6_icmp_rcv(struct sk_buff *skb)
-+{
-+ MIPV6_CALLPROC(mipv6_icmp_rcv)(skb);
-+}
-+
-+static inline int tcp_v6_get_mipv6_header_len(void)
-+{
-+ return MIPV6_HEADERS;
-+}
-+
-+static inline struct in6_addr *
-+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr)
-+{
-+ return daddr;
-+}
-+
-+static inline void
-+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int plen2)
-+{
-+ MIPV6_CALLPROC(mipv6_set_home)(ifindex, homeaddr, plen, homeagent, plen2);
-+}
-+
-+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr)
-+{
-+ MIPV6_CALLPROC(mipv6_get_home_address)(saddr);
-+}
-+
-+static inline struct ipv6_txoptions *
-+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ return MIPV6_CALLFUNC(mipv6_modify_txoptions, opt)(sk, skb, opt, fl, dst);
-+
-+}
-+
-+static inline void
-+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt;
-+ if (txopt) {
-+ opt = (struct inet6_skb_parm *)skb->cb;
-+ opt->mipv6_flags = txopt->mipv6_flags;
-+ }
-+}
-+
-+static inline void
-+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt,
-+ struct ipv6_txoptions *orig_opt)
-+{
-+ if (opt && opt != orig_opt)
-+ kfree(opt);
-+}
-+
-+#else /* USE_IPV6_MOBILITY */
-+
-+#define mipv6_handle_dstopt ip6_tlvopt_unknown
-+
-+static inline int
-+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ return 0;
-+}
-+
-+static inline int ip6_mipv6_forward(struct sk_buff *skb)
-+{
-+ return 0;
-+}
-+
-+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb,
-+ struct ndisc_options *ndopts)
-+{
-+ return MIPV6_ADD_RTR;
-+}
-+
-+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr)
-+{
-+ return 0;
-+}
-+
-+static inline void ndisc_mipv6_change_router(int change_rtr) {}
-+
-+static inline void ndisc_check_mipv6_dad(struct in6_addr *target) {}
-+
-+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb) {}
-+
-+static inline void mipv6_icmp_rcv(struct sk_buff *skb) {}
-+
-+static inline int tcp_v6_get_mipv6_header_len(void)
-+{
-+ return 0;
-+}
-+
-+static inline struct in6_addr *
-+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr)
-+{
-+ return hdaddr;
-+}
-+
-+static inline void
-+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int plen2) {}
-+
-+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr) {}
-+
-+static inline struct ipv6_txoptions *
-+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ return opt;
-+}
-+
-+static inline void
-+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb) {}
-+
-+static inline void
-+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt,
-+ struct ipv6_txoptions *orig_opt) {}
-+
-+#endif /* USE_IPV6_MOBILITY */
-+#endif /* __KERNEL__ */
-+#endif /* _NET_MIPGLUE_H */
-diff -uprN linux-2.4.25.old/include/net/mipv6.h linux-2.4.25/include/net/mipv6.h
---- linux-2.4.25.old/include/net/mipv6.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/include/net/mipv6.h 2004-06-26 11:29:29.000000000 +0100
-@@ -0,0 +1,258 @@
-+/*
-+ * Mobile IPv6 header-file
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _NET_MIPV6_H
-+#define _NET_MIPV6_H
-+
-+#include <linux/types.h>
-+#include <asm/byteorder.h>
-+#include <linux/in6.h>
-+
-+/*
-+ *
-+ * Mobile IPv6 Protocol constants
-+ *
-+ */
-+#define DHAAD_RETRIES 4 /* transmissions */
-+#define INITIAL_BINDACK_TIMEOUT 1 /* seconds */
-+#define INITIAL_DHAAD_TIMEOUT 3 /* seconds */
-+#define INITIAL_SOLICIT_TIMER 3 /* seconds */
-+#define MAX_BINDACK_TIMEOUT 32 /* seconds */
-+#define MAX_NONCE_LIFE 240 /* seconds */
-+#define MAX_TOKEN_LIFE 210 /* seconds */
-+#define MAX_RR_BINDING_LIFE 420 /* seconds */
-+#define MAX_UPDATE_RATE 3 /* 1/s (min delay=1s) */
-+#define PREFIX_ADV_RETRIES 3 /* transmissions */
-+#define PREFIX_ADV_TIMEOUT 3 /* seconds */
-+
-+#define MAX_FAST_UPDATES 5 /* transmissions */
-+#define MAX_PFX_ADV_DELAY 1000 /* seconds */
-+#define SLOW_UPDATE_RATE 10 /* 1/10s (max delay=10s)*/
-+#define INITIAL_BINDACK_DAD_TIMEOUT 2 /* seconds */
-+
-+/*
-+ *
-+ * Mobile IPv6 (RFC 3775) Protocol configuration variable defaults
-+ *
-+ */
-+#define DefHomeRtrAdvInterval 1000 /* seconds */
-+#define DefMaxMobPfxAdvInterval 86400 /* seconds */
-+#define DefMinDelayBetweenRAs 3 /* seconds (min 0.03) */
-+#define DefMinMobPfxAdvInterval 600 /* seconds */
-+#define DefInitialBindackTimeoutFirstReg 1.5 /* seconds */
-+
-+/* This is not actually specified in the draft, but is needed to avoid
-+ * prefix solicitation storm when valid lifetime of a prefix is smaller
-+ * than MAX_PFX_ADV_DELAY
-+ */
-+#define MIN_PFX_SOL_DELAY 5 /* seconds */
-+
-+/* Mobile IPv6 ICMP types */
-+/*
-+ * Official numbers from RFC 3775
-+ */
-+#define MIPV6_DHAAD_REQUEST 144
-+#define MIPV6_DHAAD_REPLY 145
-+#define MIPV6_PREFIX_SOLICIT 146
-+#define MIPV6_PREFIX_ADV 147
-+
-+/* Binding update flag codes */
-+#define MIPV6_BU_F_ACK 0x80
-+#define MIPV6_BU_F_HOME 0x40
-+#define MIPV6_BU_F_LLADDR 0x20
-+#define MIPV6_BU_F_KEYMGM 0x10
-+
-+/* Binding ackknowledgment flag codes */
-+#define MIPV6_BA_F_KEYMGM 0x80
-+
-+/* Binding error status */
-+#define MIPV6_BE_HAO_WO_BINDING 1
-+#define MIPV6_BE_UNKNOWN_MH_TYPE 2
-+
-+/* Mobility Header */
-+struct mipv6_mh
-+{
-+ __u8 payload; /* Payload Protocol */
-+ __u8 length; /* MH Length */
-+ __u8 type; /* MH Type */
-+ __u8 reserved; /* Reserved */
-+ __u16 checksum; /* Checksum */
-+ __u8 data[0]; /* Message specific data */
-+} __attribute__ ((packed));
-+
-+/* Mobility Header type */
-+#define IPPROTO_MOBILITY 135 /* RFC 3775*/
-+/* Mobility Header Message Types */
-+
-+#define MIPV6_MH_BRR 0
-+#define MIPV6_MH_HOTI 1
-+#define MIPV6_MH_COTI 2
-+#define MIPV6_MH_HOT 3
-+#define MIPV6_MH_COT 4
-+#define MIPV6_MH_BU 5
-+#define MIPV6_MH_BA 6
-+#define MIPV6_MH_BE 7
-+
-+/*
-+ * Status codes for Binding Acknowledgements
-+ */
-+#define SUCCESS 0
-+#define REASON_UNSPECIFIED 128
-+#define ADMINISTRATIVELY_PROHIBITED 129
-+#define INSUFFICIENT_RESOURCES 130
-+#define HOME_REGISTRATION_NOT_SUPPORTED 131
-+#define NOT_HOME_SUBNET 132
-+#define NOT_HA_FOR_MN 133
-+#define DUPLICATE_ADDR_DETECT_FAIL 134
-+#define SEQUENCE_NUMBER_OUT_OF_WINDOW 135
-+#define EXPIRED_HOME_NONCE_INDEX 136
-+#define EXPIRED_CAREOF_NONCE_INDEX 137
-+#define EXPIRED_NONCES 138
-+#define REG_TYPE_CHANGE_FORBIDDEN 139
-+/*
-+ * Values for mipv6_flags in struct inet6_skb_parm
-+ */
-+
-+#define MIPV6_RCV_TUNNEL 0x1
-+#define MIPV6_SND_HAO 0x2
-+#define MIPV6_SND_BU 0x4
-+
-+/*
-+ * Mobility Header Message structures
-+ */
-+
-+struct mipv6_mh_brr
-+{
-+ __u16 reserved;
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_bu
-+{
-+ __u16 sequence; /* sequence number of BU */
-+ __u8 flags; /* flags */
-+ __u8 reserved; /* reserved bits */
-+ __u16 lifetime; /* lifetime of BU */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_ba
-+{
-+ __u8 status; /* statuscode */
-+ __u8 reserved; /* reserved bits */
-+ __u16 sequence; /* sequence number of BA */
-+ __u16 lifetime; /* lifetime in CN's bcache */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_be
-+{
-+ __u8 status;
-+ __u8 reserved;
-+ struct in6_addr home_addr;
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_addr_ti
-+{
-+ __u16 reserved; /* Reserved */
-+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_addr_test
-+{
-+ __u16 nonce_index; /* Home/Care-of Nonce Index */
-+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */
-+ u_int8_t kgen_token[8]; /* Home/Care-of key generation token */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+/*
-+ * Mobility Options for various MH types.
-+ */
-+#define MIPV6_OPT_PAD1 0x00
-+#define MIPV6_OPT_PADN 0x01
-+#define MIPV6_OPT_BIND_REFRESH_ADVICE 0x02
-+#define MIPV6_OPT_ALTERNATE_COA 0x03
-+#define MIPV6_OPT_NONCE_INDICES 0x04
-+#define MIPV6_OPT_AUTH_DATA 0x05
-+
-+#define MIPV6_SEQ_GT(x,y) \
-+ ((short int)(((__u16)(x)) - ((__u16)(y))) > 0)
-+
-+/*
-+ * Mobility Option structures
-+ */
-+
-+struct mipv6_mo
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 value[0]; /* type specific data */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_pad1
-+{
-+ __u8 type;
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_padn
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_alt_coa
-+{
-+ __u8 type;
-+ __u8 length;
-+ struct in6_addr addr; /* alternate care-of-address */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_nonce_indices
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u16 home_nonce_i; /* Home Nonce Index */
-+ __u16 careof_nonce_i; /* Careof Nonce Index */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_bauth_data
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_br_advice
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u16 refresh_interval; /* Refresh Interval */
-+} __attribute__ ((packed));
-+
-+/*
-+ * Home Address Destination Option structure
-+ */
-+struct mipv6_dstopt_homeaddr
-+{
-+ __u8 type; /* type-code for option */
-+ __u8 length; /* option length */
-+ struct in6_addr addr; /* home address */
-+} __attribute__ ((packed));
-+
-+#endif /* _NET_MIPV6_H */
-diff -uprN linux-2.4.25.old/include/net/ndisc.h linux-2.4.25/include/net/ndisc.h
---- linux-2.4.25.old/include/net/ndisc.h 2002-11-28 23:53:15.000000000 +0000
-+++ linux-2.4.25/include/net/ndisc.h 2004-06-26 11:29:29.000000000 +0100
-@@ -21,6 +21,10 @@
- #define ND_OPT_REDIRECT_HDR 4
- #define ND_OPT_MTU 5
-
-+/* Mobile IPv6 specific ndisc options */
-+#define ND_OPT_RTR_ADV_INTERVAL 7
-+#define ND_OPT_HOME_AGENT_INFO 8
-+
- #define MAX_RTR_SOLICITATION_DELAY HZ
-
- #define ND_REACHABLE_TIME (30*HZ)
-@@ -57,7 +61,7 @@ struct nd_opt_hdr {
- } __attribute__((__packed__));
-
- struct ndisc_options {
-- struct nd_opt_hdr *nd_opt_array[7];
-+ struct nd_opt_hdr *nd_opt_array[10];
- struct nd_opt_hdr *nd_opt_piend;
- };
-
-@@ -67,6 +71,8 @@ struct ndisc_options {
- #define nd_opts_pi_end nd_opt_piend
- #define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
- #define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
-+#define nd_opts_rai nd_opt_array[ND_OPT_RTR_ADV_INTERVAL]
-+#define nd_opts_hai nd_opt_array[ND_OPT_HOME_AGENT_INFO]
-
- extern struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, struct nd_opt_hdr *end);
- extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, struct ndisc_options *ndopts);
-@@ -83,6 +89,15 @@ extern void ndisc_send_ns(struct net_d
- struct in6_addr *daddr,
- struct in6_addr *saddr);
-
-+extern void ndisc_send_na(struct net_device *dev,
-+ struct neighbour *neigh,
-+ struct in6_addr *daddr,
-+ struct in6_addr *solicited_addr,
-+ int router,
-+ int solicited,
-+ int override,
-+ int inc_opt);
-+
- extern void ndisc_send_rs(struct net_device *dev,
- struct in6_addr *saddr,
- struct in6_addr *daddr);
-diff -uprN linux-2.4.25.old/include/net/sock.h linux-2.4.25/include/net/sock.h
---- linux-2.4.25.old/include/net/sock.h 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/include/net/sock.h 2004-06-26 11:29:30.000000000 +0100
-@@ -149,7 +149,9 @@ struct ipv6_pinfo {
- struct in6_addr rcv_saddr;
- struct in6_addr daddr;
- struct in6_addr *daddr_cache;
--
-+#if defined(CONFIG_IPV6_SUBTREES)
-+ struct in6_addr *saddr_cache;
-+#endif
- __u32 flow_label;
- __u32 frag_size;
- int hop_limit;
-diff -uprN linux-2.4.25.old/net/Makefile linux-2.4.25/net/Makefile
---- linux-2.4.25.old/net/Makefile 2004-06-26 11:22:00.000000000 +0100
-+++ linux-2.4.25/net/Makefile 2004-06-26 11:29:30.000000000 +0100
-@@ -7,7 +7,7 @@
-
- O_TARGET := network.o
-
--mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp
-+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp ipv6
- export-objs := netsyms.o
-
- subdir-y := core ethernet
-@@ -25,6 +25,7 @@ subdir-$(CONFIG_IP_SCTP) += sctp
- ifneq ($(CONFIG_IPV6),n)
- ifneq ($(CONFIG_IPV6),)
- subdir-$(CONFIG_NETFILTER) += ipv6/netfilter
-+subdir-$(CONFIG_IPV6_MOBILITY) += ipv6/mobile_ip6
- endif
- endif
-
-diff -uprN linux-2.4.25.old/net/core/neighbour.c linux-2.4.25/net/core/neighbour.c
---- linux-2.4.25.old/net/core/neighbour.c 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/net/core/neighbour.c 2004-06-26 11:29:30.000000000 +0100
-@@ -386,7 +386,7 @@ struct pneigh_entry * pneigh_lookup(stru
- if (!creat)
- return NULL;
-
-- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
-+ n = kmalloc(sizeof(*n) + key_len, GFP_ATOMIC);
- if (n == NULL)
- return NULL;
-
-diff -uprN linux-2.4.25.old/net/ipv6/Config.in linux-2.4.25/net/ipv6/Config.in
---- linux-2.4.25.old/net/ipv6/Config.in 2001-12-21 17:42:05.000000000 +0000
-+++ linux-2.4.25/net/ipv6/Config.in 2004-06-26 11:29:30.000000000 +0100
-@@ -1,10 +1,16 @@
- #
- # IPv6 configuration
- #
--
-+bool ' IPv6: routing by source address (EXPERIMENTAL)' CONFIG_IPV6_SUBTREES
- #bool ' IPv6: flow policy support' CONFIG_RT6_POLICY
- #bool ' IPv6: firewall support' CONFIG_IPV6_FIREWALL
-
-+if [ "$CONFIG_IPV6" != "n" ]; then
-+ dep_tristate ' IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL)' CONFIG_IPV6_TUNNEL $CONFIG_IPV6
-+fi
-+
-+source net/ipv6/mobile_ip6/Config.in
-+
- if [ "$CONFIG_NETFILTER" != "n" ]; then
- source net/ipv6/netfilter/Config.in
- fi
-diff -uprN linux-2.4.25.old/net/ipv6/Makefile linux-2.4.25/net/ipv6/Makefile
---- linux-2.4.25.old/net/ipv6/Makefile 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/Makefile 2004-06-26 11:29:30.000000000 +0100
-@@ -6,18 +6,28 @@
- # unless it's something special (ie not a .c file).
- #
-
-+export-objs := ipv6_syms.o ipv6_tunnel.o
-
--O_TARGET := ipv6.o
-+#list-multi := ipv6.o ipv6_tunnel.o
-
--obj-y := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
-- route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
-- protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
-- exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
-- ip6_flowlabel.o ipv6_syms.o
-+ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
-+ sit.o route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o \
-+ raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
-+ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
-+ ip6_flowlabel.o ipv6_syms.o
-+
-+ifneq ($(CONFIG_IPV6_MOBILITY),n)
-+ifneq ($(CONFIG_IPV6_MOBILITY),)
-+ipv6-objs += mipglue.o
-+endif
-+endif
-
--export-objs := ipv6_syms.o
-+obj-$(CONFIG_IPV6) += ipv6.o
-+obj-$(CONFIG_IPV6_TUNNEL) += ipv6_tunnel.o
-+
-+ipv6.o: $(ipv6-objs)
-+ $(LD) -r -o $@ $(ipv6-objs)
-
--obj-m := $(O_TARGET)
-
- #obj-$(CONFIG_IPV6_FIREWALL) += ip6_fw.o
-
-diff -uprN linux-2.4.25.old/net/ipv6/addrconf.c linux-2.4.25/net/ipv6/addrconf.c
---- linux-2.4.25.old/net/ipv6/addrconf.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/addrconf.c 2004-06-26 11:29:30.000000000 +0100
-@@ -68,6 +68,8 @@
-
- #include <asm/uaccess.h>
-
-+#include <net/mipglue.h>
-+
- #define IPV6_MAX_ADDRESSES 16
-
- /* Set to 3 to get tracing... */
-@@ -103,9 +105,9 @@ static spinlock_t addrconf_verify_lock =
-
- static int addrconf_ifdown(struct net_device *dev, int how);
-
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
-+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
- static void addrconf_dad_timer(unsigned long data);
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
-+void addrconf_dad_completed(struct inet6_ifaddr *ifp);
- static void addrconf_rs_timer(unsigned long data);
- static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
-
-@@ -330,38 +332,6 @@ static struct inet6_dev * ipv6_find_idev
- return idev;
- }
-
--void ipv6_addr_prefix(struct in6_addr *prefix,
-- struct in6_addr *addr, int prefix_len)
--{
-- unsigned long mask;
-- int ncopy, nbits;
--
-- memset(prefix, 0, sizeof(*prefix));
--
-- if (prefix_len <= 0)
-- return;
-- if (prefix_len > 128)
-- prefix_len = 128;
--
-- ncopy = prefix_len / 32;
-- switch (ncopy) {
-- case 4: prefix->s6_addr32[3] = addr->s6_addr32[3];
-- case 3: prefix->s6_addr32[2] = addr->s6_addr32[2];
-- case 2: prefix->s6_addr32[1] = addr->s6_addr32[1];
-- case 1: prefix->s6_addr32[0] = addr->s6_addr32[0];
-- case 0: break;
-- }
-- nbits = prefix_len % 32;
-- if (nbits == 0)
-- return;
--
-- mask = ~((1 << (32 - nbits)) - 1);
-- mask = htonl(mask);
--
-- prefix->s6_addr32[ncopy] = addr->s6_addr32[ncopy] & mask;
--}
--
--
- static void dev_forward_change(struct inet6_dev *idev)
- {
- struct net_device *dev;
-@@ -513,7 +483,7 @@ ipv6_add_addr(struct inet6_dev *idev, co
-
- /* This function wants to get referenced ifp and releases it before return */
-
--static void ipv6_del_addr(struct inet6_ifaddr *ifp)
-+void ipv6_del_addr(struct inet6_ifaddr *ifp)
- {
- struct inet6_ifaddr *ifa, **ifap;
- struct inet6_dev *idev = ifp->idev;
-@@ -662,6 +632,12 @@ out:
- if (match)
- in6_ifa_put(match);
-
-+ /* The home address is always used as source address in
-+ * MIPL mobile IPv6
-+ */
-+ if (scope != IFA_HOST && scope != IFA_LINK)
-+ addrconf_get_mipv6_home_address(saddr);
-+
- return err;
- }
-
-@@ -815,7 +791,7 @@ void addrconf_leave_solict(struct net_de
- }
-
-
--static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
-+int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
- {
- switch (dev->type) {
- case ARPHRD_ETHER:
-@@ -840,7 +816,7 @@ static int ipv6_generate_eui64(u8 *eui,
- return -1;
- }
-
--static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
-+int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
- {
- int err = -1;
- struct inet6_ifaddr *ifp;
-@@ -1407,6 +1383,24 @@ static void addrconf_sit_config(struct n
- sit_route_add(dev);
- }
-
-+/**
-+ * addrconf_ipv6_tunnel_config - configure IPv6 tunnel device
-+ * @dev: tunnel device
-+ **/
-+
-+static void addrconf_ipv6_tunnel_config(struct net_device *dev)
-+{
-+ struct inet6_dev *idev;
-+
-+ ASSERT_RTNL();
-+
-+ /* Assign inet6_dev structure to tunnel device */
-+ if ((idev = ipv6_find_idev(dev)) == NULL) {
-+ printk(KERN_DEBUG "init ipv6 tunnel: add_dev failed\n");
-+ return;
-+ }
-+}
-+
-
- int addrconf_notify(struct notifier_block *this, unsigned long event,
- void * data)
-@@ -1421,6 +1415,10 @@ int addrconf_notify(struct notifier_bloc
- addrconf_sit_config(dev);
- break;
-
-+ case ARPHRD_TUNNEL6:
-+ addrconf_ipv6_tunnel_config(dev);
-+ break;
-+
- case ARPHRD_LOOPBACK:
- init_loopback(dev);
- break;
-@@ -1602,7 +1600,7 @@ out:
- /*
- * Duplicate Address Detection
- */
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
-+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
- {
- struct net_device *dev;
- unsigned long rand_num;
-@@ -1667,7 +1665,7 @@ static void addrconf_dad_timer(unsigned
- in6_ifa_put(ifp);
- }
-
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
-+void addrconf_dad_completed(struct inet6_ifaddr *ifp)
- {
- struct net_device * dev = ifp->idev->dev;
-
-@@ -1676,7 +1674,7 @@ static void addrconf_dad_completed(struc
- */
-
- ipv6_ifa_notify(RTM_NEWADDR, ifp);
--
-+ notifier_call_chain(&inet6addr_chain,NETDEV_UP,ifp);
- /* If added prefix is link local and forwarding is off,
- start sending router solicitations.
- */
-@@ -1877,8 +1875,20 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
- if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
- return -EINVAL;
-+ if (ifm->ifa_flags & IFA_F_HOMEADDR && !rta[IFA_HOMEAGENT-1])
-+ return -EINVAL;
- pfx = RTA_DATA(rta[IFA_LOCAL-1]);
- }
-+ if (rta[IFA_HOMEAGENT-1]) {
-+ struct in6_addr *ha;
-+ if (pfx == NULL || !(ifm->ifa_flags & IFA_F_HOMEADDR))
-+ return -EINVAL;
-+ if (RTA_PAYLOAD(rta[IFA_HOMEAGENT-1]) < sizeof(*ha))
-+ return -EINVAL;
-+ ha = RTA_DATA(rta[IFA_HOMEAGENT-1]);
-+ addrconf_set_mipv6_mn_home(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
-+ ha, ifm->ifa_prefixlen);
-+ }
- if (pfx == NULL)
- return -EINVAL;
-
-diff -uprN linux-2.4.25.old/net/ipv6/af_inet6.c linux-2.4.25/net/ipv6/af_inet6.c
---- linux-2.4.25.old/net/ipv6/af_inet6.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/af_inet6.c 2004-06-26 11:29:30.000000000 +0100
-@@ -58,6 +58,9 @@
- #include <net/transp_v6.h>
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-+#ifdef CONFIG_IPV6_TUNNEL
-+#include <net/ipv6_tunnel.h>
-+#endif
-
- #include <asm/uaccess.h>
- #include <asm/system.h>
-@@ -646,6 +649,11 @@ static int __init inet6_init(void)
- err = ndisc_init(&inet6_family_ops);
- if (err)
- goto ndisc_fail;
-+#ifdef CONFIG_IPV6_TUNNEL
-+ err = ip6_tunnel_init();
-+ if (err)
-+ goto ip6_tunnel_fail;
-+#endif
- err = igmp6_init(&inet6_family_ops);
- if (err)
- goto igmp_fail;
-@@ -698,6 +706,10 @@ proc_raw6_fail:
- #endif
- igmp_fail:
- ndisc_cleanup();
-+#ifdef CONFIG_IPV6_TUNNEL
-+ ip6_tunnel_cleanup();
-+ip6_tunnel_fail:
-+#endif
- ndisc_fail:
- icmpv6_cleanup();
- icmp_fail:
-@@ -730,6 +742,9 @@ static void inet6_exit(void)
- ip6_route_cleanup();
- ipv6_packet_cleanup();
- igmp6_cleanup();
-+#ifdef CONFIG_IPV6_TUNNEL
-+ ip6_tunnel_cleanup();
-+#endif
- ndisc_cleanup();
- icmpv6_cleanup();
- #ifdef CONFIG_SYSCTL
-diff -uprN linux-2.4.25.old/net/ipv6/exthdrs.c linux-2.4.25/net/ipv6/exthdrs.c
---- linux-2.4.25.old/net/ipv6/exthdrs.c 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/net/ipv6/exthdrs.c 2004-06-26 11:29:30.000000000 +0100
-@@ -41,6 +41,9 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-
-+#include <net/mipglue.h>
-+#include <net/mipv6.h>
-+
- #include <asm/uaccess.h>
-
- /*
-@@ -160,7 +163,8 @@ bad:
- *****************************/
-
- struct tlvtype_proc tlvprocdestopt_lst[] = {
-- /* No destination options are defined now */
-+ /* Mobility Support destination options */
-+ {MIPV6_TLV_HOMEADDR, mipv6_handle_dstopt},
- {-1, NULL}
- };
-
-@@ -210,6 +214,7 @@ static int ipv6_routing_header(struct sk
-
- struct ipv6_rt_hdr *hdr;
- struct rt0_hdr *rthdr;
-+ struct rt2_hdr *rt2hdr;
-
- if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
- !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-@@ -225,17 +230,25 @@ static int ipv6_routing_header(struct sk
- kfree_skb(skb);
- return -1;
- }
--
-+ /* Silently discard invalid packets containing RTH type 2 */
-+ if (hdr->type == IPV6_SRCRT_TYPE_2 &&
-+ (hdr->hdrlen != 2 || hdr->segments_left != 1)) {
-+ kfree_skb(skb);
-+ return -1;
-+ }
- looped_back:
- if (hdr->segments_left == 0) {
-- opt->srcrt = skb->h.raw - skb->nh.raw;
-+ if (hdr->type == IPV6_SRCRT_TYPE_0)
-+ opt->srcrt = skb->h.raw - skb->nh.raw;
-+ else if (hdr->type == IPV6_SRCRT_TYPE_2)
-+ opt->srcrt2 = skb->h.raw - skb->nh.raw;
- skb->h.raw += (hdr->hdrlen + 1) << 3;
- opt->dst0 = opt->dst1;
- opt->dst1 = 0;
- return (&hdr->nexthdr) - skb->nh.raw;
- }
-
-- if (hdr->type != IPV6_SRCRT_TYPE_0) {
-+ if (hdr->type != IPV6_SRCRT_TYPE_0 && hdr->type != IPV6_SRCRT_TYPE_2) {
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
- return -1;
- }
-@@ -275,9 +288,20 @@ looped_back:
-
- i = n - --hdr->segments_left;
-
-- rthdr = (struct rt0_hdr *) hdr;
-- addr = rthdr->addr;
-- addr += i - 1;
-+ if (hdr->type == IPV6_SRCRT_TYPE_0) {
-+ rthdr = (struct rt0_hdr *) hdr;
-+ addr = rthdr->addr;
-+ addr += i - 1;
-+ } else {
-+ /* check that address is this node's home address */
-+ rt2hdr = (struct rt2_hdr *) hdr;
-+ addr = &rt2hdr->addr;
-+ if (!ipv6_chk_addr(addr, NULL) ||
-+ !ipv6_chk_mip_home_addr(addr)) {
-+ kfree_skb(skb);
-+ return -1;
-+ }
-+ }
-
- addr_type = ipv6_addr_type(addr);
-
-@@ -330,6 +354,10 @@ looped_back:
- temporary (or permanent) backdoor.
- If listening socket set IPV6_RTHDR to 2, then we invert header.
- --ANK (980729)
-+
-+ By the Mobile IPv6 specification Type 2 routing header MUST NOT be
-+ inverted.
-+ --AJT (20020917)
- */
-
- struct ipv6_txoptions *
-@@ -352,6 +380,18 @@ ipv6_invert_rthdr(struct sock *sk, struc
- struct ipv6_txoptions *opt;
- int hdrlen = ipv6_optlen(hdr);
-
-+ if (hdr->type == IPV6_SRCRT_TYPE_2) {
-+ opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
-+ if (opt == NULL)
-+ return NULL;
-+ memset(opt, 0, sizeof(*opt));
-+ opt->tot_len = sizeof(*opt) + hdrlen;
-+ opt->srcrt = (void*)(opt+1);
-+ opt->opt_nflen = hdrlen;
-+ memcpy(opt->srcrt, hdr, sizeof(struct rt2_hdr));
-+ return opt;
-+ }
-+
- if (hdr->segments_left ||
- hdr->type != IPV6_SRCRT_TYPE_0 ||
- hdr->hdrlen & 0x01)
-@@ -622,8 +662,18 @@ u8 *ipv6_build_nfrag_opts(struct sk_buff
- if (opt) {
- if (opt->dst0opt)
- prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
-- if (opt->srcrt)
-- prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
-+ if (opt->srcrt) {
-+ if (opt->srcrt2) {
-+ struct in6_addr *rt2_hop = &((struct rt2_hdr *)opt->srcrt2)->addr;
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, rt2_hop);
-+ } else
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
-+ }
-+ if (opt->srcrt2) {
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb;
-+ ipv6_addr_copy(&parm->hoa, daddr);
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt2, daddr);
-+ }
- }
- return prev_hdr;
- }
-@@ -684,6 +734,11 @@ void ipv6_push_nfrag_opts(struct sk_buff
- u8 *proto,
- struct in6_addr **daddr)
- {
-+ if (opt->srcrt2) {
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb;
-+ ipv6_addr_copy(&parm->hoa, *daddr);
-+ ipv6_push_rthdr(skb, proto, opt->srcrt2, daddr);
-+ }
- if (opt->srcrt)
- ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
- if (opt->dst0opt)
-@@ -719,6 +774,8 @@ ipv6_dup_options(struct sock *sk, struct
- *((char**)&opt2->auth) += dif;
- if (opt2->srcrt)
- *((char**)&opt2->srcrt) += dif;
-+ if (opt2->srcrt2)
-+ *((char**)&opt2->srcrt2) += dif;
- }
- return opt2;
- }
-diff -uprN linux-2.4.25.old/net/ipv6/icmp.c linux-2.4.25/net/ipv6/icmp.c
---- linux-2.4.25.old/net/ipv6/icmp.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/icmp.c 2004-06-26 11:29:30.000000000 +0100
-@@ -61,6 +61,8 @@
- #include <net/addrconf.h>
- #include <net/icmp.h>
-
-+#include <net/mipglue.h>
-+
- #include <asm/uaccess.h>
- #include <asm/system.h>
-
-@@ -364,6 +366,8 @@ void icmpv6_send(struct sk_buff *skb, in
-
- msg.len = len;
-
-+ icmpv6_swap_mipv6_addrs(skb);
-+
- ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
- MSG_DONTWAIT);
- if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-@@ -562,13 +566,13 @@ int icmpv6_rcv(struct sk_buff *skb)
- rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
- ntohl(hdr->icmp6_mtu));
-
-- /*
-- * Drop through to notify
-- */
-+ icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
-+ break;
-
- case ICMPV6_DEST_UNREACH:
-- case ICMPV6_TIME_EXCEED:
- case ICMPV6_PARAMPROB:
-+ mipv6_icmp_rcv(skb);
-+ case ICMPV6_TIME_EXCEED:
- icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
- break;
-
-@@ -597,6 +601,13 @@ int icmpv6_rcv(struct sk_buff *skb)
- case ICMPV6_MGM_REDUCTION:
- break;
-
-+ case MIPV6_DHAAD_REQUEST:
-+ case MIPV6_DHAAD_REPLY:
-+ case MIPV6_PREFIX_SOLICIT:
-+ case MIPV6_PREFIX_ADV:
-+ mipv6_icmp_rcv(skb);
-+ break;
-+
- default:
- if (net_ratelimit())
- printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
-diff -uprN linux-2.4.25.old/net/ipv6/ip6_fib.c linux-2.4.25/net/ipv6/ip6_fib.c
---- linux-2.4.25.old/net/ipv6/ip6_fib.c 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/net/ipv6/ip6_fib.c 2004-06-26 11:29:30.000000000 +0100
-@@ -18,6 +18,7 @@
- * Yuji SEKIYA @USAGI: Support default route on router node;
- * remove ip6_null_entry from the top of
- * routing table.
-+ * Ville Nuorvala: Fixes to source address based routing
- */
- #include <linux/config.h>
- #include <linux/errno.h>
-@@ -40,7 +41,6 @@
- #include <net/ip6_route.h>
-
- #define RT6_DEBUG 2
--#undef CONFIG_IPV6_SUBTREES
-
- #if RT6_DEBUG >= 3
- #define RT6_TRACE(x...) printk(KERN_DEBUG x)
-@@ -500,6 +500,8 @@ static __inline__ void fib6_start_gc(str
- mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
- }
-
-+static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
-+
- /*
- * Add routing information to the routing tree.
- * <destination addr>/<source addr>
-@@ -508,17 +510,19 @@ static __inline__ void fib6_start_gc(str
-
- int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh)
- {
-- struct fib6_node *fn;
-+ struct fib6_node *fn = root;
- int err = -ENOMEM;
-
-- fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-- rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct fib6_node *pn = NULL;
-
-+ fn = fib6_add_1(root, &rt->rt6i_src.addr, sizeof(struct in6_addr),
-+ rt->rt6i_src.plen, (u8*) &rt->rt6i_src - (u8*) rt);
-+
- if (fn == NULL)
- goto out;
-
--#ifdef CONFIG_IPV6_SUBTREES
-- if (rt->rt6i_src.plen) {
-+ if (rt->rt6i_dst.plen) {
- struct fib6_node *sn;
-
- if (fn->subtree == NULL) {
-@@ -546,9 +550,9 @@ int fib6_add(struct fib6_node *root, str
-
- /* Now add the first leaf node to new subtree */
-
-- sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
-- sizeof(struct in6_addr), rt->rt6i_src.plen,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ sn = fib6_add_1(sfn, &rt->rt6i_dst.addr,
-+ sizeof(struct in6_addr), rt->rt6i_dst.plen,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-
- if (sn == NULL) {
- /* If it is failed, discard just allocated
-@@ -562,21 +566,30 @@ int fib6_add(struct fib6_node *root, str
- /* Now link new subtree to main tree */
- sfn->parent = fn;
- fn->subtree = sfn;
-- if (fn->leaf == NULL) {
-- fn->leaf = rt;
-- atomic_inc(&rt->rt6i_ref);
-- }
- } else {
-- sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
-- sizeof(struct in6_addr), rt->rt6i_src.plen,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ sn = fib6_add_1(fn->subtree, &rt->rt6i_dst.addr,
-+ sizeof(struct in6_addr), rt->rt6i_dst.plen,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-
- if (sn == NULL)
- goto st_failure;
- }
-
-+ /* fib6_add_1 might have cleared the old leaf pointer */
-+ if (fn->leaf == NULL) {
-+ fn->leaf = rt;
-+ atomic_inc(&rt->rt6i_ref);
-+ }
-+
-+ pn = fn;
- fn = sn;
- }
-+#else
-+ fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-+ rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
-+
-+ if (fn == NULL)
-+ goto out;
- #endif
-
- err = fib6_add_rt2node(fn, rt, nlh);
-@@ -588,8 +601,30 @@ int fib6_add(struct fib6_node *root, str
- }
-
- out:
-- if (err)
-+ if (err) {
-+#ifdef CONFIG_IPV6_SUBTREES
-+
-+ /* If fib6_add_1 has cleared the old leaf pointer in the
-+ super-tree leaf node, we have to find a new one for it.
-+
-+ This situation will never arise in the sub-tree since
-+ the node will at least have the route that caused
-+ fib6_add_rt2node to fail.
-+ */
-+
-+ if (pn && !(pn->fn_flags & RTN_RTINFO)) {
-+ pn->leaf = fib6_find_prefix(pn);
-+#if RT6_DEBUG >= 2
-+ if (!pn->leaf) {
-+ BUG_TRAP(pn->leaf);
-+ pn->leaf = &ip6_null_entry;
-+ }
-+#endif
-+ atomic_inc(&pn->leaf->rt6i_ref);
-+ }
-+#endif
- dst_free(&rt->u.dst);
-+ }
- return err;
-
- #ifdef CONFIG_IPV6_SUBTREES
-@@ -597,8 +632,8 @@ out:
- is orphan. If it is, shoot it.
- */
- st_failure:
-- if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT))
-- fib_repair_tree(fn);
-+ if (fn && !(fn->fn_flags & (RTN_RTINFO | RTN_ROOT)))
-+ fib6_repair_tree(fn);
- dst_free(&rt->u.dst);
- return err;
- #endif
-@@ -641,22 +676,28 @@ static struct fib6_node * fib6_lookup_1(
- break;
- }
-
-- while ((fn->fn_flags & RTN_ROOT) == 0) {
-+ for (;;) {
- #ifdef CONFIG_IPV6_SUBTREES
- if (fn->subtree) {
-- struct fib6_node *st;
-- struct lookup_args *narg;
--
-- narg = args + 1;
--
-- if (narg->addr) {
-- st = fib6_lookup_1(fn->subtree, narg);
-+ struct rt6key *key;
-
-- if (st && !(st->fn_flags & RTN_ROOT))
-- return st;
-+ key = (struct rt6key *) ((u8 *) fn->leaf +
-+ args->offset);
-+
-+ if (addr_match(&key->addr, args->addr, key->plen)) {
-+ struct fib6_node *st;
-+ struct lookup_args *narg = args + 1;
-+ if (!ipv6_addr_any(narg->addr)) {
-+ st = fib6_lookup_1(fn->subtree, narg);
-+
-+ if (st && !(st->fn_flags & RTN_ROOT))
-+ return st;
-+ }
- }
- }
- #endif
-+ if (fn->fn_flags & RTN_ROOT)
-+ break;
-
- if (fn->fn_flags & RTN_RTINFO) {
- struct rt6key *key;
-@@ -680,13 +721,22 @@ struct fib6_node * fib6_lookup(struct fi
- struct lookup_args args[2];
- struct rt6_info *rt = NULL;
- struct fib6_node *fn;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct in6_addr saddr_buf;
-+#endif
-
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (saddr == NULL) {
-+ memset(&saddr_buf, 0, sizeof(struct in6_addr));
-+ saddr = &saddr_buf;
-+ }
-+ args[0].offset = (u8*) &rt->rt6i_src - (u8*) rt;
-+ args[0].addr = saddr;
-+ args[1].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
-+ args[1].addr = daddr;
-+#else
- args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
- args[0].addr = daddr;
--
--#ifdef CONFIG_IPV6_SUBTREES
-- args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt;
-- args[1].addr = saddr;
- #endif
-
- fn = fib6_lookup_1(root, args);
-@@ -739,19 +789,25 @@ struct fib6_node * fib6_locate(struct fi
- {
- struct rt6_info *rt = NULL;
- struct fib6_node *fn;
--
-- fn = fib6_locate_1(root, daddr, dst_len,
-- (u8*) &rt->rt6i_dst - (u8*) rt);
--
- #ifdef CONFIG_IPV6_SUBTREES
-- if (src_len) {
-- BUG_TRAP(saddr!=NULL);
-- if (fn == NULL)
-- fn = fn->subtree;
-+ struct in6_addr saddr_buf;
-+
-+ if (saddr == NULL) {
-+ memset(&saddr_buf, 0, sizeof(struct in6_addr));
-+ saddr = &saddr_buf;
-+ }
-+ fn = fib6_locate_1(root, saddr, src_len,
-+ (u8*) &rt->rt6i_src - (u8*) rt);
-+ if (dst_len) {
- if (fn)
-- fn = fib6_locate_1(fn, saddr, src_len,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ fn = fib6_locate_1(fn->subtree, daddr, dst_len,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-+ else
-+ return NULL;
- }
-+#else
-+ fn = fib6_locate_1(root, daddr, dst_len,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
- #endif
-
- if (fn && fn->fn_flags&RTN_RTINFO)
-@@ -939,7 +995,7 @@ static void fib6_del_route(struct fib6_n
- }
- fn = fn->parent;
- }
-- /* No more references are possiible at this point. */
-+ /* No more references are possible at this point. */
- if (atomic_read(&rt->rt6i_ref) != 1) BUG();
- }
-
-diff -uprN linux-2.4.25.old/net/ipv6/ip6_input.c linux-2.4.25/net/ipv6/ip6_input.c
---- linux-2.4.25.old/net/ipv6/ip6_input.c 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/net/ipv6/ip6_input.c 2004-06-26 11:29:30.000000000 +0100
-@@ -40,13 +40,42 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-
-+static inline int ip6_proxy_chk(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *hdr = skb->nh.ipv6h;
-
--
-+ if (ipv6_addr_type(&hdr->daddr)&IPV6_ADDR_UNICAST &&
-+ pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
-+ u8 nexthdr = hdr->nexthdr;
-+ int offset;
-+ struct icmp6hdr msg;
-+
-+ if (ipv6_ext_hdr(nexthdr)) {
-+ offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr,
-+ skb->len - sizeof(*hdr));
-+ if (offset < 0)
-+ return 0;
-+ } else
-+ offset = sizeof(*hdr);
-+
-+ /* capture unicast NUD probes on behalf of the proxied node */
-+
-+ if (nexthdr == IPPROTO_ICMPV6 &&
-+ !skb_copy_bits(skb, offset, &msg, sizeof(msg)) &&
-+ msg.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
- static inline int ip6_rcv_finish( struct sk_buff *skb)
- {
-- if (skb->dst == NULL)
-- ip6_route_input(skb);
--
-+ if (skb->dst == NULL) {
-+ if (ip6_proxy_chk(skb))
-+ return ip6_input(skb);
-+ ip6_route_input(skb);
-+ }
- return skb->dst->input(skb);
- }
-
-diff -uprN linux-2.4.25.old/net/ipv6/ip6_output.c linux-2.4.25/net/ipv6/ip6_output.c
---- linux-2.4.25.old/net/ipv6/ip6_output.c 2003-08-25 12:44:44.000000000 +0100
-+++ linux-2.4.25/net/ipv6/ip6_output.c 2004-06-26 11:29:30.000000000 +0100
-@@ -50,6 +50,8 @@
- #include <net/rawv6.h>
- #include <net/icmp.h>
-
-+#include <net/mipglue.h>
-+
- static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
- {
- static u32 ipv6_fragmentation_id = 1;
-@@ -194,7 +196,14 @@ int ip6_xmit(struct sock *sk, struct sk_
- u8 proto = fl->proto;
- int seg_len = skb->len;
- int hlimit;
-+ int retval;
-+ struct ipv6_txoptions *orig_opt = opt;
-+
-+ opt = ip6_add_mipv6_txoptions(sk, skb, orig_opt, fl, &dst);
-
-+ if(orig_opt && !opt)
-+ return -ENOMEM;
-+
- if (opt) {
- int head_room;
-
-@@ -209,8 +218,11 @@ int ip6_xmit(struct sock *sk, struct sk_
- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
- kfree_skb(skb);
- skb = skb2;
-- if (skb == NULL)
-+ if (skb == NULL) {
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return -ENOBUFS;
-+ }
- if (sk)
- skb_set_owner_w(skb, sk);
- }
-@@ -242,7 +254,10 @@ int ip6_xmit(struct sock *sk, struct sk_
-
- if (skb->len <= dst->pmtu) {
- IP6_INC_STATS(Ip6OutRequests);
-- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
-+ ip6_mark_mipv6_packet(opt, skb);
-+ retval = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+ return retval;
- }
-
- if (net_ratelimit())
-@@ -250,6 +265,9 @@ int ip6_xmit(struct sock *sk, struct sk_
- skb->dev = dst->dev;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
- kfree_skb(skb);
-+
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return -EMSGSIZE;
- }
-
-@@ -473,6 +491,7 @@ static int ip6_frag_xmit(struct sock *sk
-
- IP6_INC_STATS(Ip6FragCreates);
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, skb);
- err = NF_HOOK(PF_INET6,NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
- if (err) {
- kfree_skb(last_skb);
-@@ -499,6 +518,7 @@ static int ip6_frag_xmit(struct sock *sk
- IP6_INC_STATS(Ip6FragCreates);
- IP6_INC_STATS(Ip6FragOKs);
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, last_skb);
- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, last_skb, NULL,dst->dev, ip6_maybe_reroute);
- }
-
-@@ -509,26 +529,43 @@ int ip6_build_xmit(struct sock *sk, inet
- struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
- struct in6_addr *final_dst = NULL;
- struct dst_entry *dst;
-+ struct rt6_info *rt;
- int err = 0;
- unsigned int pktlength, jumbolen, mtu;
- struct in6_addr saddr;
-+ struct ipv6_txoptions *orig_opt = opt;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct dst_entry *org_dst;
-+#endif
-+
-+ opt = ip6_add_mipv6_txoptions(sk, NULL, orig_opt, fl, NULL);
-+
-+ if(orig_opt && !opt)
-+ return -ENOMEM;
-
- if (opt && opt->srcrt) {
- struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
- final_dst = fl->fl6_dst;
- fl->fl6_dst = rt0->addr;
-- }
-+ } else if (opt && opt->srcrt2) {
-+ struct rt2_hdr *rt2 = (struct rt2_hdr *) opt->srcrt2;
-+ final_dst = fl->fl6_dst;
-+ fl->fl6_dst = &rt2->addr;
-+ }
-
- if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr))
- fl->oif = np->mcast_oif;
-
- dst = __sk_dst_check(sk, np->dst_cookie);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ org_dst = dst;
-+#endif
- if (dst) {
-- struct rt6_info *rt = (struct rt6_info*)dst;
-+ rt = (struct rt6_info*)dst;
-
- /* Yes, checking route validity in not connected
- case is not very simple. Take into account,
-- that we do not support routing by source, TOS,
-+ that we do not support routing by TOS,
- and MSG_DONTROUTE --ANK (980726)
-
- 1. If route was host route, check that
-@@ -548,6 +585,13 @@ int ip6_build_xmit(struct sock *sk, inet
- ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr))
- && (np->daddr_cache == NULL ||
- ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache)))
-+#ifdef CONFIG_IPV6_SUBTREES
-+ || (fl->fl6_src != NULL
-+ && (rt->rt6i_src.plen != 128 ||
-+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr))
-+ && (np->saddr_cache == NULL ||
-+ ipv6_addr_cmp(fl->fl6_src, np->saddr_cache)))
-+#endif
- || (fl->oif && fl->oif != dst->dev->ifindex)) {
- dst = NULL;
- } else
-@@ -560,21 +604,42 @@ int ip6_build_xmit(struct sock *sk, inet
- if (dst->error) {
- IP6_INC_STATS(Ip6OutNoRoutes);
- dst_release(dst);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
- return -ENETUNREACH;
- }
-
- if (fl->fl6_src == NULL) {
- err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr);
--
- if (err) {
- #if IP6_DEBUG >= 2
- printk(KERN_DEBUG "ip6_build_xmit: "
- "no available source address\n");
- #endif
-+
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (dst != org_dst) {
-+ dst_release(dst);
-+ dst = org_dst;
-+ }
-+#endif
- goto out;
- }
- fl->fl6_src = &saddr;
- }
-+#ifdef CONFIG_IPV6_SUBTREES
-+ rt = (struct rt6_info*)dst;
-+ if (dst != org_dst || rt->rt6i_src.plen != 128 ||
-+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr)) {
-+ dst_release(dst);
-+ dst = ip6_route_output(sk, fl);
-+ if (dst->error) {
-+ IP6_INC_STATS(Ip6OutNoRoutes);
-+ dst_release(dst);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+ return -ENETUNREACH;
-+ }
-+ }
-+#endif
- pktlength = length;
-
- if (hlimit < 0) {
-@@ -667,6 +732,7 @@ int ip6_build_xmit(struct sock *sk, inet
-
- if (!err) {
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, skb);
- err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
- } else {
- err = -EFAULT;
-@@ -688,9 +754,14 @@ int ip6_build_xmit(struct sock *sk, inet
- * cleanup
- */
- out:
-- ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL);
-+ ip6_dst_store(sk, dst,
-+ fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL,
-+ fl->nl_u.ip6_u.saddr == &np->saddr ? &np->saddr : NULL);
- if (err > 0)
- err = np->recverr ? net_xmit_errno(err) : 0;
-+
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return err;
- }
-
-@@ -769,6 +840,15 @@ int ip6_forward(struct sk_buff *skb)
- return -ETIMEDOUT;
- }
-
-+ /* The proxying router can't forward traffic sent to a link-local
-+ address, so signal the sender and discard the packet. This
-+ behavior is required by the MIPv6 specification. */
-+
-+ if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL &&
-+ skb->dev && pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
-+ dst_link_failure(skb);
-+ goto drop;
-+ }
- /* IPv6 specs say nothing about it, but it is clear that we cannot
- send redirects to source routed frames.
- */
-diff -uprN linux-2.4.25.old/net/ipv6/ipv6_syms.c linux-2.4.25/net/ipv6/ipv6_syms.c
---- linux-2.4.25.old/net/ipv6/ipv6_syms.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/ipv6_syms.c 2004-06-26 11:29:30.000000000 +0100
-@@ -6,6 +6,8 @@
- #include <net/ipv6.h>
- #include <net/addrconf.h>
- #include <net/ip6_route.h>
-+#include <net/ndisc.h>
-+#include <net/mipglue.h>
-
- EXPORT_SYMBOL(ipv6_addr_type);
- EXPORT_SYMBOL(icmpv6_send);
-@@ -33,3 +35,48 @@ EXPORT_SYMBOL(inet6_ioctl);
- EXPORT_SYMBOL(ipv6_get_saddr);
- EXPORT_SYMBOL(ipv6_chk_addr);
- EXPORT_SYMBOL(in6_dev_finish_destroy);
-+
-+#if defined(CONFIG_IPV6_TUNNEL_MODULE) || defined(CONFIG_IPV6_MOBILITY_MODULE)
-+EXPORT_SYMBOL(ip6_build_xmit);
-+EXPORT_SYMBOL(rt6_lookup);
-+EXPORT_SYMBOL(ipv6_ext_hdr);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MODULE
-+EXPORT_SYMBOL(mipv6_functions);
-+EXPORT_SYMBOL(mipv6_invalidate_calls);
-+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE)
-+EXPORT_SYMBOL(ip6_route_add);
-+EXPORT_SYMBOL(ip6_route_del);
-+EXPORT_SYMBOL(ipv6_get_lladdr);
-+EXPORT_SYMBOL(ipv6_get_ifaddr);
-+EXPORT_SYMBOL(nd_tbl);
-+EXPORT_SYMBOL(ndisc_send_ns);
-+EXPORT_SYMBOL(ndisc_send_na);
-+EXPORT_SYMBOL(ndisc_next_option);
-+EXPORT_SYMBOL(inet6_ifa_finish_destroy);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE
-+EXPORT_SYMBOL(ipv6_dev_ac_dec);
-+EXPORT_SYMBOL(ipv6_dev_ac_inc);
-+EXPORT_SYMBOL(ipv6_dev_mc_dec);
-+EXPORT_SYMBOL(ipv6_dev_mc_inc);
-+EXPORT_SYMBOL(ip6_forward);
-+EXPORT_SYMBOL(ip6_input);
-+EXPORT_SYMBOL(ipv6_chk_acast_addr);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE
-+#endif
-+EXPORT_SYMBOL(addrconf_add_ifaddr);
-+EXPORT_SYMBOL(addrconf_del_ifaddr);
-+EXPORT_SYMBOL(addrconf_dad_start);
-+EXPORT_SYMBOL(ip6_del_rt);
-+EXPORT_SYMBOL(ip6_routing_table);
-+EXPORT_SYMBOL(rt6_get_dflt_router);
-+EXPORT_SYMBOL(rt6_purge_dflt_routers);
-+EXPORT_SYMBOL(rt6_lock);
-+EXPORT_SYMBOL(ndisc_send_rs);
-+EXPORT_SYMBOL(fib6_clean_tree);
-+EXPORT_SYMBOL(ipv6_del_addr);
-+EXPORT_SYMBOL(ipv6_generate_eui64);
-+EXPORT_SYMBOL(ipv6_inherit_eui64);
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/ipv6_tunnel.c linux-2.4.25/net/ipv6/ipv6_tunnel.c
---- linux-2.4.25.old/net/ipv6/ipv6_tunnel.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/ipv6_tunnel.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,1604 @@
-+/*
-+ * IPv6 over IPv6 tunnel device
-+ * Linux INET6 implementation
-+ *
-+ * Authors:
-+ * Ville Nuorvala <vnuorval@tcs.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * Based on:
-+ * linux/net/ipv6/sit.c
-+ *
-+ * RFC 2473
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/errno.h>
-+#include <linux/types.h>
-+#include <linux/socket.h>
-+#include <linux/sockios.h>
-+#include <linux/if.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/if_tunnel.h>
-+#include <linux/net.h>
-+#include <linux/in6.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/icmpv6.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/tqueue.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/atomic.h>
-+
-+#include <net/sock.h>
-+#include <net/ipv6.h>
-+#include <net/protocol.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/ipv6_tunnel.h>
-+
-+MODULE_AUTHOR("Ville Nuorvala");
-+MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
-+MODULE_LICENSE("GPL");
-+
-+#define IPV6_TLV_TEL_DST_SIZE 8
-+
-+#ifdef IP6_TNL_DEBUG
-+#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__)
-+#else
-+#define IP6_TNL_TRACE(x...) do {;} while(0)
-+#endif
-+
-+#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
-+
-+#define HASH_SIZE 32
-+
-+#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \
-+ (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
-+ (HASH_SIZE - 1))
-+
-+static int ip6ip6_fb_tnl_dev_init(struct net_device *dev);
-+static int ip6ip6_tnl_dev_init(struct net_device *dev);
-+
-+/* the IPv6 IPv6 tunnel fallback device */
-+static struct net_device ip6ip6_fb_tnl_dev = {
-+ name: "ip6tnl0",
-+ init: ip6ip6_fb_tnl_dev_init
-+};
-+
-+/* the IPv6 IPv6 fallback tunnel */
-+static struct ip6_tnl ip6ip6_fb_tnl = {
-+ dev: &ip6ip6_fb_tnl_dev,
-+ parms:{name: "ip6tnl0", proto: IPPROTO_IPV6}
-+};
-+
-+/* lists for storing tunnels in use */
-+static struct ip6_tnl *tnls_r_l[HASH_SIZE];
-+static struct ip6_tnl *tnls_wc[1];
-+static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l };
-+
-+/* list for unused cached kernel tunnels */
-+static struct ip6_tnl *tnls_kernel[1];
-+/* maximum number of cached kernel tunnels */
-+static unsigned int max_kdev_count = 0;
-+/* minimum number of cached kernel tunnels */
-+static unsigned int min_kdev_count = 0;
-+/* current number of cached kernel tunnels */
-+static unsigned int kdev_count = 0;
-+
-+/* lists for tunnel hook functions */
-+static struct list_head hooks[IP6_TNL_MAXHOOKS];
-+
-+/* locks for the different lists */
-+static rwlock_t ip6ip6_lock = RW_LOCK_UNLOCKED;
-+static rwlock_t ip6ip6_kernel_lock = RW_LOCK_UNLOCKED;
-+static rwlock_t ip6ip6_hook_lock = RW_LOCK_UNLOCKED;
-+
-+/* flag indicating if the module is being removed */
-+static int shutdown = 0;
-+
-+/**
-+ * ip6ip6_tnl_lookup - fetch tunnel matching the end-point addresses
-+ * @remote: the address of the tunnel exit-point
-+ * @local: the address of the tunnel entry-point
-+ *
-+ * Return:
-+ * tunnel matching given end-points if found,
-+ * else fallback tunnel if its device is up,
-+ * else %NULL
-+ **/
-+
-+struct ip6_tnl *
-+ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
-+{
-+ unsigned h0 = HASH(remote);
-+ unsigned h1 = HASH(local);
-+ struct ip6_tnl *t;
-+
-+ for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) {
-+ if (!ipv6_addr_cmp(local, &t->parms.laddr) &&
-+ !ipv6_addr_cmp(remote, &t->parms.raddr) &&
-+ (t->dev->flags & IFF_UP))
-+ return t;
-+ }
-+ if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
-+ return t;
-+
-+ return NULL;
-+}
-+
-+/**
-+ * ip6ip6_bucket - get head of list matching given tunnel parameters
-+ * @p: parameters containing tunnel end-points
-+ *
-+ * Description:
-+ * ip6ip6_bucket() returns the head of the list matching the
-+ * &struct in6_addr entries laddr and raddr in @p.
-+ *
-+ * Return: head of IPv6 tunnel list
-+ **/
-+
-+static struct ip6_tnl **
-+ip6ip6_bucket(struct ip6_tnl_parm *p)
-+{
-+ struct in6_addr *remote = &p->raddr;
-+ struct in6_addr *local = &p->laddr;
-+ unsigned h = 0;
-+ int prio = 0;
-+
-+ if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) {
-+ prio = 1;
-+ h = HASH(remote) ^ HASH(local);
-+ }
-+ return &tnls[prio][h];
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_link - add new kernel tunnel to cache
-+ * @t: kernel tunnel
-+ *
-+ * Note:
-+ * %IP6_TNL_F_KERNEL_DEV is assumed to be raised in t->parms.flags.
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+static inline void
-+ip6ip6_kernel_tnl_link(struct ip6_tnl *t)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ t->next = tnls_kernel[0];
-+ tnls_kernel[0] = t;
-+ kdev_count++;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_unlink - remove first kernel tunnel from cache
-+ *
-+ * Return: first free kernel tunnel
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+static inline struct ip6_tnl *
-+ip6ip6_kernel_tnl_unlink(void)
-+{
-+ struct ip6_tnl *t;
-+
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ if ((t = tnls_kernel[0]) != NULL) {
-+ tnls_kernel[0] = t->next;
-+ kdev_count--;
-+ }
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ return t;
-+}
-+
-+/**
-+ * ip6ip6_tnl_link - add tunnel to hash table
-+ * @t: tunnel to be added
-+ **/
-+
-+static void
-+ip6ip6_tnl_link(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl **tp = ip6ip6_bucket(&t->parms);
-+
-+ write_lock_bh(&ip6ip6_lock);
-+ t->next = *tp;
-+ *tp = t;
-+ write_unlock_bh(&ip6ip6_lock);
-+}
-+
-+/**
-+ * ip6ip6_tnl_unlink - remove tunnel from hash table
-+ * @t: tunnel to be removed
-+ **/
-+
-+static void
-+ip6ip6_tnl_unlink(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl **tp;
-+
-+ write_lock_bh(&ip6ip6_lock);
-+ for (tp = ip6ip6_bucket(&t->parms); *tp; tp = &(*tp)->next) {
-+ if (t == *tp) {
-+ *tp = t->next;
-+ break;
-+ }
-+ }
-+ write_unlock_bh(&ip6ip6_lock);
-+}
-+
-+/**
-+ * ip6ip6_tnl_create() - create a new tunnel
-+ * @p: tunnel parameters
-+ * @pt: pointer to new tunnel
-+ *
-+ * Description:
-+ * Create tunnel matching given parameters. New kernel managed devices are
-+ * not put in the normal hash structure, but are instead cached for later
-+ * use.
-+ *
-+ * Return:
-+ * 0 on success
-+ **/
-+
-+
-+static int __ip6ip6_tnl_create(struct ip6_tnl_parm *p,
-+ struct ip6_tnl **pt,
-+ int kernel_list)
-+{
-+ struct net_device *dev;
-+ int err = -ENOBUFS;
-+ struct ip6_tnl *t;
-+
-+ MOD_INC_USE_COUNT;
-+ dev = kmalloc(sizeof (*dev) + sizeof (*t), GFP_KERNEL);
-+ if (!dev) {
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+ }
-+ memset(dev, 0, sizeof (*dev) + sizeof (*t));
-+ dev->priv = (void *) (dev + 1);
-+ t = (struct ip6_tnl *) dev->priv;
-+ t->dev = dev;
-+ dev->init = ip6ip6_tnl_dev_init;
-+ dev->features |= NETIF_F_DYNALLOC;
-+ if (kernel_list) {
-+ memcpy(t->parms.name, p->name, IFNAMSIZ - 1);
-+ t->parms.proto = IPPROTO_IPV6;
-+ t->parms.flags = IP6_TNL_F_KERNEL_DEV;
-+ } else {
-+ memcpy(&t->parms, p, sizeof (*p));
-+ }
-+ t->parms.name[IFNAMSIZ - 1] = '\0';
-+ strcpy(dev->name, t->parms.name);
-+ if (!dev->name[0]) {
-+ int i;
-+ for (i = 0; i < IP6_TNL_MAX; i++) {
-+ sprintf(dev->name, "ip6tnl%d", i);
-+ if (__dev_get_by_name(dev->name) == NULL)
-+ break;
-+ }
-+
-+ if (i == IP6_TNL_MAX) {
-+ goto failed;
-+ }
-+ memcpy(t->parms.name, dev->name, IFNAMSIZ);
-+ }
-+ if ((err = register_netdevice(dev)) < 0) {
-+ goto failed;
-+ }
-+ dev_hold(dev);
-+ if (kernel_list) {
-+ ip6ip6_kernel_tnl_link(t);
-+ } else {
-+ ip6ip6_tnl_link(t);
-+ }
-+ *pt = t;
-+ return 0;
-+failed:
-+ kfree(dev);
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+
-+int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
-+{
-+ return __ip6ip6_tnl_create(p, pt, 0);
-+}
-+
-+
-+static void manage_kernel_tnls(void *foo);
-+
-+static struct tq_struct manager_task = {
-+ routine:manage_kernel_tnls,
-+ data:NULL
-+};
-+
-+/**
-+ * manage_kernel_tnls() - create and destroy kernel tunnels
-+ *
-+ * Description:
-+ * manage_kernel_tnls() creates new kernel devices if there
-+ * are less than $min_kdev_count of them and deletes old ones if
-+ * there are less than $max_kdev_count of them in the cache
-+ *
-+ * Note:
-+ * Schedules itself to be run later in process context if called from
-+ * interrupt. Therefore only works synchronously when called from process
-+ * context.
-+ **/
-+
-+static void
-+manage_kernel_tnls(void *foo)
-+{
-+ struct ip6_tnl *t = NULL;
-+ struct ip6_tnl_parm parm;
-+
-+ /* We can't do this processing in interrupt
-+ context so schedule it for later */
-+ if (in_interrupt()) {
-+ read_lock(&ip6ip6_kernel_lock);
-+ if (!shutdown &&
-+ (kdev_count < min_kdev_count ||
-+ kdev_count > max_kdev_count)) {
-+ schedule_task(&manager_task);
-+ }
-+ read_unlock(&ip6ip6_kernel_lock);
-+ return;
-+ }
-+
-+ rtnl_lock();
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ memset(&parm, 0, sizeof (parm));
-+ parm.flags = IP6_TNL_F_KERNEL_DEV;
-+ /* Create tunnels until there are at least min_kdev_count */
-+ while (kdev_count < min_kdev_count) {
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+ if (!__ip6ip6_tnl_create(&parm, &t, 1)) {
-+ dev_open(t->dev);
-+ } else {
-+ goto err;
-+ }
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ }
-+
-+ /* Destroy tunnels until there are at most max_kdev_count */
-+ while (kdev_count > max_kdev_count) {
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+ if ((t = ip6ip6_kernel_tnl_unlink()) != NULL) {
-+ unregister_netdevice(t->dev);
-+ } else {
-+ goto err;
-+ }
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ }
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+err:
-+ rtnl_unlock();
-+}
-+
-+/**
-+ * ip6ip6_tnl_inc_max_kdev_count() - increase max kernel dev cache size
-+ * @n: size increase
-+ * Description:
-+ * Increase the upper limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_inc_max_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ max_kdev_count += n;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return max_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dec_max_kdev_count() - decrease max kernel dev cache size
-+ * @n: size decrement
-+ * Description:
-+ * Decrease the upper limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_dec_max_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ max_kdev_count -= min(max_kdev_count, n);
-+ if (max_kdev_count < min_kdev_count)
-+ min_kdev_count = max_kdev_count;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return max_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_inc_min_kdev_count() - increase min kernel dev cache size
-+ * @n: size increase
-+ * Description:
-+ * Increase the lower limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_inc_min_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ min_kdev_count += n;
-+ if (min_kdev_count > max_kdev_count)
-+ max_kdev_count = min_kdev_count;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return min_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dec_min_kdev_count() - decrease min kernel dev cache size
-+ * @n: size decrement
-+ * Description:
-+ * Decrease the lower limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_dec_min_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ min_kdev_count -= min(min_kdev_count, n);
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return min_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_locate - find or create tunnel matching given parameters
-+ * @p: tunnel parameters
-+ * @create: != 0 if allowed to create new tunnel if no match found
-+ *
-+ * Description:
-+ * ip6ip6_tnl_locate() first tries to locate an existing tunnel
-+ * based on @parms. If this is unsuccessful, but @create is set a new
-+ * tunnel device is created and registered for use.
-+ *
-+ * Return:
-+ * 0 if tunnel located or created,
-+ * -EINVAL if parameters incorrect,
-+ * -ENODEV if no matching tunnel available
-+ **/
-+
-+int ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create)
-+{
-+ struct in6_addr *remote = &p->raddr;
-+ struct in6_addr *local = &p->laddr;
-+ struct ip6_tnl *t;
-+
-+ if (p->proto != IPPROTO_IPV6)
-+ return -EINVAL;
-+
-+ for (t = *ip6ip6_bucket(p); t; t = t->next) {
-+ if (!ipv6_addr_cmp(local, &t->parms.laddr) &&
-+ !ipv6_addr_cmp(remote, &t->parms.raddr)) {
-+ *pt = t;
-+ return (create ? -EEXIST : 0);
-+ }
-+ }
-+ return ip6ip6_tnl_create(p, pt);
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_destructor - tunnel device destructor
-+ * @dev: the device to be destroyed
-+ **/
-+
-+static void
-+ip6ip6_tnl_dev_destructor(struct net_device *dev)
-+{
-+ if (dev != &ip6ip6_fb_tnl_dev) {
-+ MOD_DEC_USE_COUNT;
-+ }
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_uninit - tunnel device uninitializer
-+ * @dev: the device to be destroyed
-+ *
-+ * Description:
-+ * ip6ip6_tnl_dev_uninit() removes tunnel from its list
-+ **/
-+
-+static void
-+ip6ip6_tnl_dev_uninit(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ write_lock_bh(&ip6ip6_lock);
-+ tnls_wc[0] = NULL;
-+ write_unlock_bh(&ip6ip6_lock);
-+ } else {
-+ ip6ip6_tnl_unlink(t);
-+ }
-+ sock_release(t->sock);
-+ dev_put(dev);
-+}
-+
-+/**
-+ * parse_tvl_tnl_enc_lim - handle encapsulation limit option
-+ * @skb: received socket buffer
-+ *
-+ * Return:
-+ * 0 if none was found,
-+ * else index to encapsulation limit
-+ **/
-+
-+static __u16
-+parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
-+{
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) raw;
-+ __u8 nexthdr = ipv6h->nexthdr;
-+ __u16 off = sizeof (*ipv6h);
-+
-+ while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-+ __u16 optlen = 0;
-+ struct ipv6_opt_hdr *hdr;
-+ if (raw + off + sizeof (*hdr) > skb->data &&
-+ !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
-+ break;
-+
-+ hdr = (struct ipv6_opt_hdr *) (raw + off);
-+ if (nexthdr == NEXTHDR_FRAGMENT) {
-+ struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
-+ if (frag_hdr->frag_off)
-+ break;
-+ optlen = 8;
-+ } else if (nexthdr == NEXTHDR_AUTH) {
-+ optlen = (hdr->hdrlen + 2) << 2;
-+ } else {
-+ optlen = ipv6_optlen(hdr);
-+ }
-+ if (nexthdr == NEXTHDR_DEST) {
-+ __u16 i = off + 2;
-+ while (1) {
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+
-+ /* No more room for encapsulation limit */
-+ if (i + sizeof (*tel) > off + optlen)
-+ break;
-+
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
-+ /* return index of option if found and valid */
-+ if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
-+ tel->length == 1)
-+ return i;
-+ /* else jump to next option */
-+ if (tel->type)
-+ i += tel->length + 2;
-+ else
-+ i++;
-+ }
-+ }
-+ nexthdr = hdr->nexthdr;
-+ off += optlen;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_err - tunnel error handler
-+ *
-+ * Description:
-+ * ip6ip6_err() should handle errors in the tunnel according
-+ * to the specifications in RFC 2473.
-+ **/
-+
-+void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-+ int type, int code, int offset, __u32 info)
-+{
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
-+ struct ip6_tnl *t;
-+ int rel_msg = 0;
-+ int rel_type = ICMPV6_DEST_UNREACH;
-+ int rel_code = ICMPV6_ADDR_UNREACH;
-+ __u32 rel_info = 0;
-+ __u16 len;
-+
-+ /* If the packet doesn't contain the original IPv6 header we are
-+ in trouble since we might need the source address for furter
-+ processing of the error. */
-+
-+ read_lock(&ip6ip6_lock);
-+ if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
-+ goto out;
-+
-+ switch (type) {
-+ __u32 teli;
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ __u32 mtu;
-+ case ICMPV6_DEST_UNREACH:
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Path to destination invalid "
-+ "or inactive!\n", t->parms.name);
-+ rel_msg = 1;
-+ break;
-+ case ICMPV6_TIME_EXCEED:
-+ if (code == ICMPV6_EXC_HOPLIMIT) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Too small hop limit or "
-+ "routing loop in tunnel!\n",
-+ t->parms.name);
-+ rel_msg = 1;
-+ }
-+ break;
-+ case ICMPV6_PARAMPROB:
-+ /* ignore if parameter problem not caused by a tunnel
-+ encapsulation limit sub-option */
-+ if (code != ICMPV6_HDR_FIELD) {
-+ break;
-+ }
-+ teli = parse_tlv_tnl_enc_lim(skb, skb->data);
-+
-+ if (teli && teli == ntohl(info) - 2) {
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
-+ if (tel->encap_limit == 0) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Too small encapsulation "
-+ "limit or routing loop in "
-+ "tunnel!\n", t->parms.name);
-+ rel_msg = 1;
-+ }
-+ }
-+ break;
-+ case ICMPV6_PKT_TOOBIG:
-+ mtu = ntohl(info) - offset;
-+ if (mtu < IPV6_MIN_MTU)
-+ mtu = IPV6_MIN_MTU;
-+ t->dev->mtu = mtu;
-+
-+ if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) {
-+ rel_type = ICMPV6_PKT_TOOBIG;
-+ rel_code = 0;
-+ rel_info = mtu;
-+ rel_msg = 1;
-+ }
-+ break;
-+ }
-+ if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) {
-+ struct rt6_info *rt;
-+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (!skb2)
-+ goto out;
-+
-+ dst_release(skb2->dst);
-+ skb2->dst = NULL;
-+ skb_pull(skb2, offset);
-+ skb2->nh.raw = skb2->data;
-+
-+ /* Try to guess incoming interface */
-+ rt = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0);
-+
-+ if (rt && rt->rt6i_dev)
-+ skb2->dev = rt->rt6i_dev;
-+
-+ icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev);
-+
-+ if (rt)
-+ dst_release(&rt->u.dst);
-+
-+ kfree_skb(skb2);
-+ }
-+out:
-+ read_unlock(&ip6ip6_lock);
-+}
-+
-+/**
-+ * call_hooks - call ipv6 tunnel hooks
-+ * @hooknum: hook number, either %IP6_TNL_PRE_ENCAP, or
-+ * %IP6_TNL_PRE_DECAP
-+ * @t: the current tunnel
-+ * @skb: the tunneled packet
-+ *
-+ * Description:
-+ * Pass packet to all the hook functions until %IP6_TNL_DROP
-+ *
-+ * Return:
-+ * %IP6_TNL_ACCEPT or %IP6_TNL_DROP
-+ **/
-+
-+static inline int
-+call_hooks(unsigned int hooknum, struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ struct ip6_tnl_hook_ops *h;
-+ int accept = IP6_TNL_ACCEPT;
-+
-+ if (hooknum < IP6_TNL_MAXHOOKS) {
-+ struct list_head *i;
-+ read_lock(&ip6ip6_hook_lock);
-+ for (i = hooks[hooknum].next; i != &hooks[hooknum]; i = i->next) {
-+ h = (struct ip6_tnl_hook_ops *) i;
-+
-+ if (h->hook) {
-+ accept = h->hook(t, skb);
-+
-+ if (accept != IP6_TNL_ACCEPT)
-+ break;
-+ }
-+ }
-+ read_unlock(&ip6ip6_hook_lock);
-+ }
-+ return accept;
-+}
-+
-+/**
-+ * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
-+ * @skb: received socket buffer
-+ *
-+ * Return: 0
-+ **/
-+
-+int ip6ip6_rcv(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *ipv6h;
-+ struct ip6_tnl *t;
-+
-+ if (!pskb_may_pull(skb, sizeof (*ipv6h)))
-+ goto discard;
-+
-+ ipv6h = skb->nh.ipv6h;
-+
-+ read_lock(&ip6ip6_lock);
-+
-+ if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
-+ if (!(t->parms.flags & IP6_TNL_F_CAP_RCV) ||
-+ call_hooks(IP6_TNL_PRE_DECAP, t, skb) != IP6_TNL_ACCEPT) {
-+ t->stat.rx_dropped++;
-+ read_unlock(&ip6ip6_lock);
-+ goto discard;
-+ }
-+ skb->mac.raw = skb->nh.raw;
-+ skb->nh.raw = skb->data;
-+ skb->protocol = htons(ETH_P_IPV6);
-+ skb->pkt_type = PACKET_HOST;
-+ memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
-+ skb->dev = t->dev;
-+ dst_release(skb->dst);
-+ skb->dst = NULL;
-+ t->stat.rx_packets++;
-+ t->stat.rx_bytes += skb->len;
-+ netif_rx(skb);
-+ read_unlock(&ip6ip6_lock);
-+ return 0;
-+ }
-+ read_unlock(&ip6ip6_lock);
-+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-+discard:
-+ kfree_skb(skb);
-+ return 0;
-+}
-+
-+static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
-+{
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ struct ipv6_txoptions *opt;
-+ __u8 *raw;
-+
-+ int opt_len = sizeof(*opt) + IPV6_TLV_TEL_DST_SIZE;
-+
-+ if (!(opt = kmalloc(opt_len, GFP_ATOMIC))) {
-+ return NULL;
-+ }
-+ memset(opt, 0, opt_len);
-+ opt->tot_len = opt_len;
-+ opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1);
-+ opt->opt_nflen = 8;
-+
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1);
-+ tel->type = IPV6_TLV_TNL_ENCAP_LIMIT;
-+ tel->length = 1;
-+ tel->encap_limit = encap_limit;
-+
-+ raw = (__u8 *) opt->dst0opt;
-+ raw[5] = IPV6_TLV_PADN;
-+ raw[6] = 1;
-+
-+ return opt;
-+}
-+
-+static int
-+ip6ip6_getfrag(const void *data, struct in6_addr *addr,
-+ char *buff, unsigned int offset, unsigned int len)
-+{
-+ memcpy(buff, data + offset, len);
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
-+ * @t: the outgoing tunnel device
-+ * @hdr: IPv6 header from the incoming packet
-+ *
-+ * Description:
-+ * Avoid trivial tunneling loop by checking that tunnel exit-point
-+ * doesn't match source of incoming packet.
-+ *
-+ * Return:
-+ * 1 if conflict,
-+ * 0 else
-+ **/
-+
-+static inline int
-+ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
-+{
-+ return !ipv6_addr_cmp(&t->parms.raddr, &hdr->saddr);
-+}
-+
-+/**
-+ * ip6ip6_tnl_xmit - encapsulate packet and send
-+ * @skb: the outgoing socket buffer
-+ * @dev: the outgoing tunnel device
-+ *
-+ * Description:
-+ * Build new header and do some sanity checks on the packet before sending
-+ * it to ip6_build_xmit().
-+ *
-+ * Return:
-+ * 0
-+ **/
-+
-+int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ struct net_device_stats *stats = &t->stat;
-+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
-+ struct ipv6_txoptions *opt = NULL;
-+ int encap_limit = -1;
-+ __u16 offset;
-+ struct flowi fl;
-+ int err = 0;
-+ struct dst_entry *dst;
-+ struct sock *sk = t->sock->sk;
-+ struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
-+ int mtu;
-+
-+ if (t->recursion++) {
-+ stats->collisions++;
-+ goto tx_err;
-+ }
-+ if (skb->protocol != htons(ETH_P_IPV6) ||
-+ !(t->parms.flags & IP6_TNL_F_CAP_XMIT) ||
-+ ip6ip6_tnl_addr_conflict(t, ipv6h)) {
-+ goto tx_err;
-+ }
-+ if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) {
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset];
-+ if (tel->encap_limit == 0) {
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, offset + 2, skb->dev);
-+ goto tx_err;
-+ }
-+ encap_limit = tel->encap_limit - 1;
-+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
-+ encap_limit = t->parms.encap_limit;
-+ }
-+ if (call_hooks(IP6_TNL_PRE_ENCAP, t, skb) != IP6_TNL_ACCEPT)
-+ goto discard;
-+ memcpy(&fl, &t->fl, sizeof (fl));
-+
-+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
-+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
-+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK);
-+
-+ if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL)
-+ goto tx_err;
-+
-+ dst = __sk_dst_check(sk, np->dst_cookie);
-+
-+ if (dst) {
-+ if (np->daddr_cache == NULL ||
-+ ipv6_addr_cmp(fl.fl6_dst, np->daddr_cache) ||
-+#ifdef CONFIG_IPV6_SUBTREES
-+ np->saddr_cache == NULL ||
-+ ipv6_addr_cmp(fl.fl6_src, np->saddr_cache) ||
-+#endif
-+ (fl.oif && fl.oif != dst->dev->ifindex)) {
-+ dst = NULL;
-+ } else {
-+ dst_hold(dst);
-+ }
-+ }
-+ if (dst == NULL) {
-+ dst = ip6_route_output(sk, &fl);
-+ if (dst->error) {
-+ stats->tx_carrier_errors++;
-+ dst_link_failure(skb);
-+ goto tx_err_dst_release;
-+ }
-+ /* local routing loop */
-+ if (dst->dev == dev) {
-+ stats->collisions++;
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Local routing loop detected!\n",
-+ t->parms.name);
-+ goto tx_err_dst_release;
-+ }
-+ }
-+ mtu = dst->pmtu - sizeof (*ipv6h);
-+ if (opt) {
-+ mtu -= (opt->opt_nflen + opt->opt_flen);
-+ }
-+ if (mtu < IPV6_MIN_MTU)
-+ mtu = IPV6_MIN_MTU;
-+ if (skb->dst && mtu < skb->dst->pmtu) {
-+ struct rt6_info *rt = (struct rt6_info *) skb->dst;
-+ rt->rt6i_flags |= RTF_MODIFIED;
-+ rt->u.dst.pmtu = mtu;
-+ }
-+ if (skb->len > mtu) {
-+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
-+ goto tx_err_dst_release;
-+ }
-+ ip6_dst_store(sk, dst, &np->daddr, &np->saddr);
-+ err = ip6_build_xmit(sk, ip6ip6_getfrag, (void *) skb->nh.raw,
-+ &fl, skb->len, opt, t->parms.hop_limit,
-+ MSG_DONTWAIT);
-+
-+ if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) {
-+ stats->tx_bytes += skb->len;
-+ stats->tx_packets++;
-+ } else {
-+ stats->tx_errors++;
-+ stats->tx_aborted_errors++;
-+ }
-+ if (opt)
-+ kfree(opt);
-+ kfree_skb(skb);
-+ t->recursion--;
-+ return 0;
-+tx_err_dst_release:
-+ dst_release(dst);
-+ if (opt)
-+ kfree(opt);
-+tx_err:
-+ stats->tx_errors++;
-+discard:
-+ stats->tx_dropped++;
-+ kfree_skb(skb);
-+ t->recursion--;
-+ return 0;
-+}
-+
-+static void ip6_tnl_set_cap(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl_parm *p = &t->parms;
-+ struct in6_addr *laddr = &p->laddr;
-+ struct in6_addr *raddr = &p->raddr;
-+ int ltype = ipv6_addr_type(laddr);
-+ int rtype = ipv6_addr_type(raddr);
-+
-+ p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV);
-+
-+ if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY &&
-+ ((ltype|rtype) &
-+ (IPV6_ADDR_UNICAST|
-+ IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL|
-+ IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) {
-+ struct net_device *ldev = NULL;
-+ int l_ok = 1;
-+ int r_ok = 1;
-+
-+ if (p->link)
-+ ldev = dev_get_by_index(p->link);
-+
-+ if ((ltype&IPV6_ADDR_UNICAST) && !ipv6_chk_addr(laddr, ldev))
-+ l_ok = 0;
-+
-+ if ((rtype&IPV6_ADDR_UNICAST) && ipv6_chk_addr(raddr, NULL))
-+ r_ok = 0;
-+
-+ if (l_ok && r_ok) {
-+ if (ltype&IPV6_ADDR_UNICAST)
-+ p->flags |= IP6_TNL_F_CAP_XMIT;
-+ if (rtype&IPV6_ADDR_UNICAST)
-+ p->flags |= IP6_TNL_F_CAP_RCV;
-+ }
-+ if (ldev)
-+ dev_put(ldev);
-+ }
-+}
-+
-+static void ip6ip6_tnl_link_config(struct ip6_tnl *t)
-+{
-+ struct net_device *dev = t->dev;
-+ struct ip6_tnl_parm *p = &t->parms;
-+ struct flowi *fl = &t->fl;
-+
-+ /* Set up flowi template */
-+ fl->fl6_src = &p->laddr;
-+ fl->fl6_dst = &p->raddr;
-+ fl->oif = p->link;
-+ fl->fl6_flowlabel = 0;
-+
-+ if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
-+ fl->fl6_flowlabel |= IPV6_TCLASS_MASK & htonl(p->flowinfo);
-+ if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL))
-+ fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & htonl(p->flowinfo);
-+
-+ ip6_tnl_set_cap(t);
-+
-+ if (p->flags&IP6_TNL_F_CAP_XMIT && p->flags&IP6_TNL_F_CAP_RCV)
-+ dev->flags |= IFF_POINTOPOINT;
-+ else
-+ dev->flags &= ~IFF_POINTOPOINT;
-+
-+ if (p->flags & IP6_TNL_F_CAP_XMIT) {
-+ struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
-+ p->link, 0);
-+
-+ if (rt == NULL)
-+ return;
-+
-+ if (rt->rt6i_dev) {
-+ dev->iflink = rt->rt6i_dev->ifindex;
-+
-+ dev->hard_header_len = rt->rt6i_dev->hard_header_len +
-+ sizeof (struct ipv6hdr);
-+
-+ dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr);
-+
-+ if (dev->mtu < IPV6_MIN_MTU)
-+ dev->mtu = IPV6_MIN_MTU;
-+ }
-+ dst_release(&rt->u.dst);
-+ }
-+}
-+
-+/**
-+ * __ip6ip6_tnl_change - update the tunnel parameters
-+ * @t: tunnel to be changed
-+ * @p: tunnel configuration parameters
-+ *
-+ * Description:
-+ * __ip6ip6_tnl_change() updates the tunnel parameters
-+ **/
-+
-+static void
-+__ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
-+{
-+ ipv6_addr_copy(&t->parms.laddr, &p->laddr);
-+ ipv6_addr_copy(&t->parms.raddr, &p->raddr);
-+ t->parms.flags = p->flags;
-+ t->parms.hop_limit = p->hop_limit;
-+ t->parms.encap_limit = p->encap_limit;
-+ t->parms.flowinfo = p->flowinfo;
-+ ip6ip6_tnl_link_config(t);
-+}
-+
-+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
-+{
-+ ip6ip6_tnl_unlink(t);
-+ __ip6ip6_tnl_change(t, p);
-+ ip6ip6_tnl_link(t);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_add - configure and add kernel tunnel to hash
-+ * @p: kernel tunnel configuration parameters
-+ *
-+ * Description:
-+ * ip6ip6_kernel_tnl_add() fetches an unused kernel tunnel configures
-+ * it according to @p and places it among the active tunnels.
-+ *
-+ * Return:
-+ * number of references to tunnel on success,
-+ * %-EEXIST if there is already a device matching description
-+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised,
-+ * %-ENODEV if there are no unused kernel tunnels available
-+ *
-+ * Note:
-+ * The code for creating, opening, closing and destroying network devices
-+ * must be called from process context, while the Mobile IP code, which
-+ * needs the tunnel devices, unfortunately runs in interrupt context.
-+ *
-+ * The devices must be created and opened in advance, then placed in a
-+ * list where the kernel can fetch and ready them for use at a later time.
-+ *
-+ **/
-+
-+int
-+ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p)
-+{
-+ struct ip6_tnl *t;
-+
-+ if (!(p->flags & IP6_TNL_F_KERNEL_DEV))
-+ return -EINVAL;
-+ if ((t = ip6ip6_tnl_lookup(&p->raddr, &p->laddr)) != NULL &&
-+ t != &ip6ip6_fb_tnl) {
-+ /* Handle duplicate tunnels by incrementing
-+ reference count */
-+ atomic_inc(&t->refcnt);
-+ goto out;
-+ }
-+ if ((t = ip6ip6_kernel_tnl_unlink()) == NULL)
-+ return -ENODEV;
-+ __ip6ip6_tnl_change(t, p);
-+
-+ atomic_inc(&t->refcnt);
-+
-+ ip6ip6_tnl_link(t);
-+
-+ manage_kernel_tnls(NULL);
-+out:
-+ return atomic_read(&t->refcnt);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_del - delete no longer needed kernel tunnel
-+ * @t: kernel tunnel to be removed from hash
-+ *
-+ * Description:
-+ * ip6ip6_kernel_tnl_del() removes and deconfigures the tunnel @t
-+ * and places it among the unused kernel devices.
-+ *
-+ * Return:
-+ * number of references on success,
-+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised,
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+int
-+ip6ip6_kernel_tnl_del(struct ip6_tnl *t)
-+{
-+ if (!t)
-+ return -ENODEV;
-+
-+ if (!(t->parms.flags & IP6_TNL_F_KERNEL_DEV))
-+ return -EINVAL;
-+
-+ if (atomic_dec_and_test(&t->refcnt)) {
-+ struct ip6_tnl_parm p;
-+ ip6ip6_tnl_unlink(t);
-+ memset(&p, 0, sizeof (p));
-+ p.flags = IP6_TNL_F_KERNEL_DEV;
-+
-+ __ip6ip6_tnl_change(t, &p);
-+
-+ ip6ip6_kernel_tnl_link(t);
-+
-+ manage_kernel_tnls(NULL);
-+ }
-+ return atomic_read(&t->refcnt);
-+}
-+
-+/**
-+ * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace
-+ * @dev: virtual device associated with tunnel
-+ * @ifr: parameters passed from userspace
-+ * @cmd: command to be performed
-+ *
-+ * Description:
-+ * ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels
-+ * from userspace.
-+ *
-+ * The possible commands are the following:
-+ * %SIOCGETTUNNEL: get tunnel parameters for device
-+ * %SIOCADDTUNNEL: add tunnel matching given tunnel parameters
-+ * %SIOCCHGTUNNEL: change tunnel parameters to those given
-+ * %SIOCDELTUNNEL: delete tunnel
-+ *
-+ * The fallback device "ip6tnl0", created during module
-+ * initialization, can be used for creating other tunnel devices.
-+ *
-+ * Return:
-+ * 0 on success,
-+ * %-EFAULT if unable to copy data to or from userspace,
-+ * %-EPERM if current process hasn't %CAP_NET_ADMIN set or attempting
-+ * to configure kernel devices from userspace,
-+ * %-EINVAL if passed tunnel parameters are invalid,
-+ * %-EEXIST if changing a tunnel's parameters would cause a conflict
-+ * %-ENODEV if attempting to change or delete a nonexisting device
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information
-+ * about kernel tunnels.
-+ * **/
-+
-+static int
-+ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-+{
-+ int err = 0;
-+ int create;
-+ struct ip6_tnl_parm p;
-+ struct ip6_tnl *t = NULL;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ switch (cmd) {
-+ case SIOCGETTUNNEL:
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ if (copy_from_user(&p,
-+ ifr->ifr_ifru.ifru_data,
-+ sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV)
-+ t = (struct ip6_tnl *) dev->priv;
-+ else if (err)
-+ break;
-+ } else
-+ t = (struct ip6_tnl *) dev->priv;
-+
-+ memcpy(&p, &t->parms, sizeof (p));
-+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
-+ err = -EFAULT;
-+ }
-+ break;
-+ case SIOCADDTUNNEL:
-+ case SIOCCHGTUNNEL:
-+ err = -EPERM;
-+ create = (cmd == SIOCADDTUNNEL);
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ if (p.flags & IP6_TNL_F_KERNEL_DEV) {
-+ break;
-+ }
-+ if (!create && dev != &ip6ip6_fb_tnl_dev) {
-+ t = (struct ip6_tnl *) dev->priv;
-+ }
-+ if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) {
-+ break;
-+ }
-+ if (cmd == SIOCCHGTUNNEL) {
-+ if (t->dev != dev) {
-+ err = -EEXIST;
-+ break;
-+ }
-+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV) {
-+ err = -EPERM;
-+ break;
-+ }
-+ ip6ip6_tnl_change(t, &p);
-+ netdev_state_change(dev);
-+ }
-+ if (copy_to_user(ifr->ifr_ifru.ifru_data,
-+ &t->parms, sizeof (p))) {
-+ err = -EFAULT;
-+ } else {
-+ err = 0;
-+ }
-+ break;
-+ case SIOCDELTUNNEL:
-+ err = -EPERM;
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data,
-+ sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ err = ip6ip6_tnl_locate(&p, &t, 0);
-+ if (err)
-+ break;
-+ if (t == &ip6ip6_fb_tnl) {
-+ err = -EPERM;
-+ break;
-+ }
-+ } else {
-+ t = (struct ip6_tnl *) dev->priv;
-+ }
-+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV)
-+ err = -EPERM;
-+ else
-+ err = unregister_netdevice(t->dev);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+/**
-+ * ip6ip6_tnl_get_stats - return the stats for tunnel device
-+ * @dev: virtual device associated with tunnel
-+ *
-+ * Return: stats for device
-+ **/
-+
-+static struct net_device_stats *
-+ip6ip6_tnl_get_stats(struct net_device *dev)
-+{
-+ return &(((struct ip6_tnl *) dev->priv)->stat);
-+}
-+
-+/**
-+ * ip6ip6_tnl_change_mtu - change mtu manually for tunnel device
-+ * @dev: virtual device associated with tunnel
-+ * @new_mtu: the new mtu
-+ *
-+ * Return:
-+ * 0 on success,
-+ * %-EINVAL if mtu too small
-+ **/
-+
-+static int
-+ip6ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
-+{
-+ if (new_mtu < IPV6_MIN_MTU) {
-+ return -EINVAL;
-+ }
-+ dev->mtu = new_mtu;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_init_gen - general initializer for all tunnel devices
-+ * @dev: virtual device associated with tunnel
-+ *
-+ * Description:
-+ * Set function pointers and initialize the &struct flowi template used
-+ * by the tunnel.
-+ **/
-+
-+static int
-+ip6ip6_tnl_dev_init_gen(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ struct flowi *fl = &t->fl;
-+ int err;
-+ struct sock *sk;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_IPV6, &t->sock))) {
-+ printk(KERN_ERR
-+ "Failed to create IPv6 tunnel socket (err %d).\n", err);
-+ return err;
-+ }
-+ t->sock->inode->i_uid = 0;
-+ t->sock->inode->i_gid = 0;
-+
-+ sk = t->sock->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->net_pinfo.af_inet6.hop_limit = 254;
-+ sk->net_pinfo.af_inet6.mc_loop = 0;
-+ sk->prot->unhash(sk);
-+
-+ memset(fl, 0, sizeof (*fl));
-+ fl->proto = IPPROTO_IPV6;
-+
-+ dev->destructor = ip6ip6_tnl_dev_destructor;
-+ dev->uninit = ip6ip6_tnl_dev_uninit;
-+ dev->hard_start_xmit = ip6ip6_tnl_xmit;
-+ dev->get_stats = ip6ip6_tnl_get_stats;
-+ dev->do_ioctl = ip6ip6_tnl_ioctl;
-+ dev->change_mtu = ip6ip6_tnl_change_mtu;
-+
-+ dev->type = ARPHRD_TUNNEL6;
-+ dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
-+ dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
-+ dev->flags |= IFF_NOARP;
-+ dev->iflink = 0;
-+ /* Hmm... MAX_ADDR_LEN is 8, so the ipv6 addresses can't be
-+ copied to dev->dev_addr and dev->broadcast, like the ipv4
-+ addresses were in ipip.c, ip_gre.c and sit.c. */
-+ dev->addr_len = 0;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_init - initializer for all non fallback tunnel devices
-+ * @dev: virtual device associated with tunnel
-+ **/
-+
-+static int
-+ip6ip6_tnl_dev_init(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ ip6ip6_tnl_dev_init_gen(dev);
-+ ip6ip6_tnl_link_config(t);
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+
-+/**
-+ * ip6ip6_fb_tnl_open - function called when fallback device opened
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+static int
-+ip6ip6_fb_tnl_open(struct net_device *dev)
-+{
-+ MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_fb_tnl_close - function called when fallback device closed
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+static int
-+ip6ip6_fb_tnl_close(struct net_device *dev)
-+{
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+#endif
-+
-+/**
-+ * ip6ip6_fb_tnl_dev_init - initializer for fallback tunnel device
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+int __init
-+ip6ip6_fb_tnl_dev_init(struct net_device *dev)
-+{
-+ ip6ip6_tnl_dev_init_gen(dev);
-+#ifdef MODULE
-+ dev->open = ip6ip6_fb_tnl_open;
-+ dev->stop = ip6ip6_fb_tnl_close;
-+#endif
-+ dev_hold(dev);
-+ tnls_wc[0] = &ip6ip6_fb_tnl;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_register_hook - add hook for processing of tunneled packets
-+ * @reg: hook function and its parameters
-+ *
-+ * Description:
-+ * Add a netfilter like hook function for special handling of tunneled
-+ * packets. The hook functions are called before encapsulation
-+ * (%IP6_TNL_PRE_ENCAP) and before decapsulation
-+ * (%IP6_TNL_PRE_DECAP). The possible return values by the hook
-+ * functions are %IP6_TNL_DROP, %IP6_TNL_ACCEPT and
-+ * %IP6_TNL_STOLEN (in case the hook function took care of the packet
-+ * and it doesn't have to be processed any further).
-+ **/
-+
-+void
-+ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg)
-+{
-+ if (reg->hooknum < IP6_TNL_MAXHOOKS) {
-+ struct list_head *i;
-+
-+ write_lock_bh(&ip6ip6_hook_lock);
-+ for (i = hooks[reg->hooknum].next;
-+ i != &hooks[reg->hooknum]; i = i->next) {
-+ if (reg->priority <
-+ ((struct ip6_tnl_hook_ops *) i)->priority) {
-+ break;
-+ }
-+ }
-+ list_add(&reg->list, i->prev);
-+ write_unlock_bh(&ip6ip6_hook_lock);
-+ }
-+}
-+
-+/**
-+ * ip6ip6_tnl_unregister_hook - remove tunnel hook
-+ * @reg: hook function and its parameters
-+ **/
-+
-+void
-+ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg)
-+{
-+ if (reg->hooknum < IP6_TNL_MAXHOOKS) {
-+ write_lock_bh(&ip6ip6_hook_lock);
-+ list_del(&reg->list);
-+ write_unlock_bh(&ip6ip6_hook_lock);
-+ }
-+}
-+
-+
-+/* the IPv6 over IPv6 protocol structure */
-+static struct inet6_protocol ip6ip6_protocol = {
-+ ip6ip6_rcv, /* IPv6 handler */
-+ ip6ip6_err, /* IPv6 error control */
-+ NULL, /* next */
-+ IPPROTO_IPV6, /* protocol ID */
-+ 0, /* copy */
-+ NULL, /* data */
-+ "IPv6 over IPv6" /* name */
-+};
-+
-+/**
-+ * ip6_tunnel_init - register protocol and reserve needed resources
-+ *
-+ * Return: 0 on success
-+ **/
-+
-+int __init ip6_tunnel_init(void)
-+{
-+ int i, err;
-+
-+ ip6ip6_fb_tnl_dev.priv = (void *) &ip6ip6_fb_tnl;
-+
-+ for (i = 0; i < IP6_TNL_MAXHOOKS; i++) {
-+ INIT_LIST_HEAD(&hooks[i]);
-+ }
-+ if ((err = register_netdev(&ip6ip6_fb_tnl_dev)))
-+ return err;
-+
-+ inet6_add_protocol(&ip6ip6_protocol);
-+ return 0;
-+}
-+
-+/**
-+ * ip6_tunnel_cleanup - free resources and unregister protocol
-+ **/
-+
-+void ip6_tunnel_cleanup(void)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ shutdown = 1;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ flush_scheduled_tasks();
-+ manage_kernel_tnls(NULL);
-+ inet6_del_protocol(&ip6ip6_protocol);
-+ unregister_netdev(&ip6ip6_fb_tnl_dev);
-+}
-+
-+#ifdef MODULE
-+module_init(ip6_tunnel_init);
-+module_exit(ip6_tunnel_cleanup);
-+#endif
-+
-+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE)
-+EXPORT_SYMBOL(ip6ip6_tnl_register_hook);
-+EXPORT_SYMBOL(ip6ip6_tnl_unregister_hook);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE
-+EXPORT_SYMBOL(ip6ip6_tnl_dec_max_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_inc_max_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_dec_min_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_inc_min_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_kernel_tnl_add);
-+EXPORT_SYMBOL(ip6ip6_kernel_tnl_del);
-+EXPORT_SYMBOL(ip6ip6_tnl_lookup);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE
-+EXPORT_SYMBOL(ip6ip6_tnl_create);
-+EXPORT_SYMBOL(ip6ip6_tnl_change);
-+#endif
-+
-diff -uprN linux-2.4.25.old/net/ipv6/mipglue.c linux-2.4.25/net/ipv6/mipglue.c
---- linux-2.4.25.old/net/ipv6/mipglue.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mipglue.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,63 @@
-+/*
-+ * Glue for Mobility support integration to IPv6
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/sched.h>
-+
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+#include <net/mipglue.h>
-+
-+extern int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff);
-+
-+/* Initialize all zero */
-+struct mipv6_callable_functions mipv6_functions = { NULL };
-+
-+/* Sets mipv6_functions struct to zero to invalidate all successive
-+ * calls to mipv6 functions. Used on module unload. */
-+
-+void mipv6_invalidate_calls(void)
-+{
-+ memset(&mipv6_functions, 0, sizeof(mipv6_functions));
-+}
-+
-+
-+/* Selects correct handler for tlv encoded destination option. Called
-+ * by ip6_parse_tlv. Checks if mipv6 calls are valid before calling. */
-+
-+int mipv6_handle_dstopt(struct sk_buff *skb, int optoff)
-+{
-+ int ret;
-+
-+ switch (skb->nh.raw[optoff]) {
-+ case MIPV6_TLV_HOMEADDR:
-+ ret = MIPV6_CALLFUNC(mipv6_handle_homeaddr, 0)(skb, optoff);
-+ break;
-+ default:
-+ /* Should never happen */
-+ printk(KERN_ERR __FILE__ ": Invalid destination option code (%d)\n",
-+ skb->nh.raw[optoff]);
-+ ret = 1;
-+ break;
-+ }
-+
-+ /* If mipv6 handlers are not valid, pass the packet to
-+ * ip6_tlvopt_unknown() for correct handling. */
-+ if (!ret)
-+ return ip6_tlvopt_unknown(skb, optoff);
-+
-+ return ret;
-+}
-+
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/Config.in linux-2.4.25/net/ipv6/mobile_ip6/Config.in
---- linux-2.4.25.old/net/ipv6/mobile_ip6/Config.in 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/Config.in 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,12 @@
-+#
-+# Mobile IPv6 Configuration
-+#
-+dep_tristate ' IPv6: Mobility Support (Correspondent Node)' CONFIG_IPV6_MOBILITY $CONFIG_IPV6
-+if [ "$CONFIG_IPV6_IPV6_TUNNEL" != "n" ]; then
-+ dep_tristate ' MIPv6: Mobile Node Support' CONFIG_IPV6_MOBILITY_MN $CONFIG_IPV6_MOBILITY
-+
-+ dep_tristate ' MIPv6: Home Agent Support' CONFIG_IPV6_MOBILITY_HA $CONFIG_IPV6_MOBILITY
-+fi
-+if [ "$CONFIG_IPV6_MOBILITY" != "n" ]; then
-+ bool ' MIPv6: Debug messages' CONFIG_IPV6_MOBILITY_DEBUG
-+fi
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/Makefile linux-2.4.25/net/ipv6/mobile_ip6/Makefile
---- linux-2.4.25.old/net/ipv6/mobile_ip6/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/Makefile 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,35 @@
-+#
-+# Makefile for the MIPL Mobile IPv6 for Linux.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+
-+
-+O_TARGET := mip6_base.o
-+
-+list-multi := mip6_ha.o mip6_mn.o
-+
-+obj-y := hashlist.o bcache.o mobhdr_common.o stats.o exthdrs.o \
-+ rr_crypto.o hmac.o auth_opt.o mipv6_icmp.o module_cn.o
-+
-+obj-m := $(O_TARGET)
-+
-+mip6_ha-objs := halist.o mipv6_icmp_ha.o tunnel_ha.o \
-+ ndisc_ha.o ha.o module_ha.o
-+
-+mip6_mn-objs := mipv6_icmp_mn.o ioctl_mn.o tunnel_mn.o \
-+ mdetect.o bul.o multiaccess_ctl.o mobhdr_mn.o mn.o \
-+ module_mn.o
-+
-+obj-$(CONFIG_IPV6_MOBILITY_HA) += mip6_ha.o
-+obj-$(CONFIG_IPV6_MOBILITY_MN) += mip6_mn.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+mip6_ha.o: $(mip6_ha-objs)
-+ $(LD) -r -o $@ $(mip6_ha-objs)
-+
-+mip6_mn.o: $(mip6_mn-objs)
-+ $(LD) -r -o $@ $(mip6_mn-objs)
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/README linux-2.4.25/net/ipv6/mobile_ip6/README
---- linux-2.4.25.old/net/ipv6/mobile_ip6/README 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/README 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,15 @@
-+MIPL Mobile IPv6 for Linux
-+
-+More information at http://www.mipl.mediapoli.com/.
-+
-+To join MIPL Mobile IPv6 for Linux mailing lists go to:
-+
-+ http://www.mipl.mediapoli.com/cgi-bin/mailman/listinfo
-+
-+Or send mail with subject "subscribe" for the general list to:
-+
-+ mipl-request@list.mipl.mediapoli.com
-+
-+or for the developer list to:
-+
-+ mipl-devel-request@list.mail.mediapoli.com
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/auth_opt.c linux-2.4.25/net/ipv6/mobile_ip6/auth_opt.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/auth_opt.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/auth_opt.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,121 @@
-+/*
-+ * MIPv6 Binding Authentication Data Option functions
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/icmpv6.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "hmac.h"
-+#include "mobhdr.h"
-+
-+#define DBG_KEY 5
-+
-+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *mh, __u8 *aud_data, __u8 *k_bu)
-+{
-+ /* First look up the peer from sadb based on his address */
-+ struct ah_processing ahp;
-+
-+ /* Don't add any other options or this system is screwed */
-+
-+ __u8 buf[MAX_HASH_LENGTH];
-+
-+
-+ if (!k_bu) {
-+ DEBUG(DBG_ERROR, "k_bu missing, aborting");
-+ return -1;
-+ }
-+ DEBUG(DBG_KEY, "Key for building authenticator:");
-+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE);
-+
-+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hmac sha1");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_KEY, "coa: ");
-+ debug_print_buffer(DBG_KEY, coa, 16);
-+ DEBUG(DBG_KEY, "cn_addr: ");
-+ debug_print_buffer(DBG_KEY, cn_addr, 16);
-+ DEBUG(DBG_KEY, "MH contents: ");
-+ debug_print_buffer(DBG_KEY, mh, aud_data - mh);
-+
-+ /* First the common part */
-+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, mh, aud_data - mh);
-+ ah_hmac_sha1_result(&ahp, buf);
-+
-+ memcpy(aud_data, buf, MIPV6_RR_MAC_LENGTH);
-+
-+ return 0;
-+}
-+
-+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 optlen,
-+ struct mipv6_mo_bauth_data *aud, __u8 *k_bu)
-+{
-+ int ret = -1;
-+ struct ah_processing ahp;
-+ __u8 htarget[MAX_HASH_LENGTH];
-+
-+ /* Look up peer by home address */
-+ if (!k_bu) {
-+ DEBUG(DBG_ERROR, "k_bu missing, aborting");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_KEY, "Key for checking authenticator:");
-+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE);
-+
-+ if (!aud || !coa) {
-+ DEBUG(DBG_INFO, "%s is NULL", aud ? "coa" : "aud");
-+ goto out;
-+ }
-+
-+ if (aud->length != MIPV6_RR_MAC_LENGTH) {
-+ DEBUG(DBG_ERROR,
-+ ": Incorrect authentication option length %d", aud->length);
-+ goto out;
-+ }
-+
-+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR,
-+ "internal error in initialization of authentication algorithm");
-+ goto out;
-+ }
-+ DEBUG(DBG_KEY, "coa: ");
-+ debug_print_buffer(DBG_KEY, coa, 16);
-+ DEBUG(DBG_KEY, "cn_addr: ");
-+ debug_print_buffer(DBG_KEY, cn_addr, 16);
-+ DEBUG(DBG_KEY, "MH contents: ");
-+ debug_print_buffer(DBG_KEY, opt, (u8*) aud->data - opt);
-+
-+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr));
-+
-+ /*
-+ * Process MH + options till the start of the authenticator in
-+ * Auth. data option
-+ */
-+ ah_hmac_sha1_loop(&ahp, opt, (u8 *)aud->data - opt);
-+ ah_hmac_sha1_result(&ahp, htarget);
-+ if (memcmp(htarget, aud->data, MIPV6_RR_MAC_LENGTH) == 0)
-+ ret = 0;
-+
-+ DEBUG(DBG_ERROR, "returning %d", ret);
-+out:
-+ return ret;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.c linux-2.4.25/net/ipv6/mobile_ip6/bcache.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/bcache.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,746 @@
-+/*
-+ * Binding Cache
-+ *
-+ * Authors:
-+ * Juha Mynttinen <jmynttin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Timer code cleaned up, active socket
-+ * test rewritten
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/proc_fs.h>
-+#include <linux/ipv6_route.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "bcache.h"
-+#include "hashlist.h"
-+#include "debug.h"
-+#include "mobhdr.h"
-+#include "tunnel.h"
-+#include "config.h"
-+
-+#define TIMERDELAY HZ/10
-+
-+struct mipv6_bcache {
-+ struct hashlist *entries;
-+ __u32 size;
-+ struct timer_list callback_timer;
-+};
-+
-+struct in6_addr_pair {
-+ struct in6_addr *a1;
-+ struct in6_addr *a2;
-+};
-+
-+static rwlock_t bcache_lock = RW_LOCK_UNLOCKED;
-+
-+static struct mipv6_bcache bcache;
-+
-+static int bcache_proc_info(char *buffer, char **start, off_t offset,
-+ int length);
-+
-+#define MIPV6_BCACHE_HASHSIZE 32
-+
-+/* Moment of transmission of a BR, in seconds before bcache entry expiry */
-+#define BCACHE_BR_SEND_LEAD 3
-+
-+#define MIPV6_MAX_BRR 3 /* Send 3 BRRs before deleting BC entry */
-+#define MIPV6_BRR_RATE HZ /* Send BRRs once per second */
-+
-+/*
-+ * Internal functions.
-+ */
-+
-+struct cache_entry_iterator_args {
-+ struct mipv6_bce **entry;
-+};
-+
-+static int find_first_cache_entry_iterator(void *data, void *args,
-+ unsigned long *lifetime)
-+{
-+ struct mipv6_bce *entry =
-+ (struct mipv6_bce *) data;
-+ struct cache_entry_iterator_args *state =
-+ (struct cache_entry_iterator_args *) args;
-+
-+ ASSERT(entry != NULL);
-+
-+ if (entry->type == CACHE_ENTRY) {
-+ *(state->entry) = entry;
-+ return ITERATOR_STOP; /* stop iteration */
-+ } else {
-+ return ITERATOR_CONT; /* continue iteration */
-+ }
-+}
-+
-+
-+/*
-+ * Get memory for a new bcache entry. If bcache is full, a cache
-+ * entry may be deleted to get space for a home registration, but not
-+ * vice versa.
-+ */
-+static struct mipv6_bce *mipv6_bce_alloc(__u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ struct cache_entry_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ entry = (struct mipv6_bce *)
-+ hashlist_alloc(bcache.entries, SLAB_ATOMIC);
-+
-+ /* Cache replacement policy: always replace the CACHE_ENTRY
-+ closest to expiration. Type HOME_REGISTRATION entry may
-+ never be deleted before expiration. */
-+ if (entry == NULL) {
-+ /* cache full, try to delete a CACHE_ENTRY */
-+ args.entry = &entry;
-+ hashlist_iterate(bcache.entries, &args,
-+ find_first_cache_entry_iterator);
-+ if (entry == NULL)
-+ return NULL;
-+ hashlist_delete(bcache.entries,
-+ (struct hashlist_entry *)entry);
-+ entry = (struct mipv6_bce *)
-+ hashlist_alloc(bcache.entries, SLAB_ATOMIC);
-+ }
-+ return entry;
-+}
-+
-+/*
-+ * Frees entry's memory allocated with mipv6_bce_alloc
-+ */
-+static void mipv6_bce_free(struct mipv6_bce *entry)
-+{
-+ hashlist_free(bcache.entries, (void *) entry);
-+}
-+
-+/*
-+ * Removes all expired entries
-+ */
-+static void expire(void)
-+{
-+ struct mipv6_bce *entry;
-+ struct br_addrs {
-+ struct in6_addr daddr;
-+ struct in6_addr saddr;
-+ struct br_addrs *next;
-+ };
-+ struct br_addrs *br_info = NULL;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&bcache_lock);
-+
-+ while ((entry = (struct mipv6_bce *)
-+ hashlist_get_first(bcache.entries)) != NULL) {
-+ struct rt6_info *rt;
-+ if (time_after_eq(jiffies, entry->callback_time)) {
-+
-+ DEBUG(DBG_INFO, "an entry expired");
-+
-+ if (entry->type & HOME_REGISTRATION) {
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ }
-+ hashlist_delete(bcache.entries, (void *)entry);
-+ mipv6_bce_free(entry);
-+ entry = NULL;
-+ } else if (entry->br_callback_time != 0 &&
-+ time_after_eq(jiffies, entry->br_callback_time) &&
-+ entry->br_count < MIPV6_MAX_BRR &&
-+ (rt = rt6_lookup(&entry->home_addr, &entry->our_addr, 0, 0)) != NULL){
-+ /* Do we have a destination cache entry for the home address */
-+ if (rt->rt6i_flags & RTF_CACHE) {
-+ struct br_addrs *tmp;
-+ tmp = br_info;
-+ DEBUG(DBG_INFO,
-+ "bcache entry recently used. Sending BR.");
-+ /* queue for sending */
-+ br_info = kmalloc(sizeof(struct br_addrs),
-+ GFP_ATOMIC);
-+ if (br_info) {
-+ ipv6_addr_copy(&br_info->saddr,
-+ &entry->our_addr);
-+ ipv6_addr_copy(&br_info->daddr,
-+ &entry->home_addr);
-+ br_info->next = tmp;
-+ entry->last_br = jiffies;
-+ entry->br_callback_time = jiffies + MIPV6_BRR_RATE;
-+ entry->br_count++;
-+ } else {
-+ br_info = tmp;
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ }
-+
-+ } else
-+ entry->br_callback_time = 0;
-+ dst_release(&rt->u.dst);
-+ } else {
-+ entry->br_callback_time = 0;
-+ break;
-+ }
-+ }
-+ write_unlock(&bcache_lock);
-+
-+ while (br_info) {
-+ struct br_addrs *tmp = br_info->next;
-+ if (mipv6_send_brr(&br_info->saddr, &br_info->daddr, NULL) < 0)
-+ DEBUG(DBG_WARNING,
-+ "BR send for %x:%x:%x:%x:%x:%x:%x:%x failed",
-+ NIPV6ADDR(&br_info->daddr));
-+ kfree(br_info);
-+ br_info = tmp;
-+ }
-+}
-+
-+static void set_timer(void)
-+{
-+ struct mipv6_bce *entry;
-+ unsigned long callback_time;
-+
-+ DEBUG_FUNC();
-+
-+ entry = (struct mipv6_bce *)
-+ hashlist_get_first(bcache.entries);
-+ if (entry != NULL) {
-+ if (entry->br_callback_time > 0 &&
-+ time_after(entry->br_callback_time, jiffies))
-+ callback_time = entry->br_callback_time;
-+ else if (time_after(entry->callback_time, jiffies))
-+ callback_time = entry->callback_time;
-+ else {
-+ DEBUG(DBG_WARNING,
-+ "bcache timer attempted to schedule"
-+ " for a historical jiffies count!");
-+ callback_time = jiffies + TIMERDELAY;
-+ }
-+
-+ DEBUG(DBG_INFO, "setting timer to now");
-+ mod_timer(&bcache.callback_timer, callback_time);
-+ } else {
-+ del_timer(&bcache.callback_timer);
-+ DEBUG(DBG_INFO, "BC empty, not setting a new timer");
-+ }
-+}
-+
-+/*
-+ * The function that is scheduled to do the callback functions. May be
-+ * modified e.g to allow Binding Requests, now only calls expire() and
-+ * schedules a new timer.
-+ */
-+static void timer_handler(unsigned long dummy)
-+{
-+ expire();
-+ write_lock(&bcache_lock);
-+ set_timer();
-+ write_unlock(&bcache_lock);
-+}
-+
-+/*
-+ * Interface functions visible to other modules
-+ */
-+
-+/**
-+ * mipv6_bcache_add - add Binding Cache entry
-+ * @ifindex: interface index
-+ * @our_addr: own address
-+ * @home_addr_org: MN's home address
-+ * @coa: MN's care-of address
-+ * @lifetime: lifetime for this binding
-+ * @prefix: prefix length
-+ * @seq: sequence number
-+ * @flags: flags received in BU
-+ * @type: type of entry
-+ *
-+ * Adds an entry for this @home_addr_org in the Binding Cache. If entry
-+ * already exists, old entry is updated. @type may be %CACHE_ENTRY or
-+ * %HOME_REGISTRATION.
-+ **/
-+int mipv6_bcache_add(int ifindex,
-+ struct in6_addr *our_addr,
-+ struct in6_addr *home_addr,
-+ struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ int update = 0;
-+ int create_tunnel = 0;
-+ unsigned long now = jiffies;
-+ struct in6_addr_pair hashkey;
-+ int ret = -1;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+
-+ if (type == HOME_REGISTRATION && !(mip6node_cnf.capabilities&CAP_HA))
-+ return 0;
-+
-+ if (unlikely(bcache.entries == NULL)) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ if ((entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ /* if an entry for this home_addr exists (with smaller
-+ * seq than the new seq), update it by removing it
-+ * first
-+ */
-+ if (!MIPV6_SEQ_GT(seq, entry->seq)) {
-+ DEBUG(DBG_INFO, "smaller seq than existing, not updating");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "updating an existing entry");
-+ update = 1;
-+
-+ /* H-flag is already checked in BU handler. */
-+ /* XXX: Should we care about the other flags?*/
-+ if (flags != entry->flags) {
-+ DEBUG(DBG_INFO, "entry/BU flag mismatch");
-+ }
-+
-+ if (type == HOME_REGISTRATION) {
-+ create_tunnel = (ipv6_addr_cmp(&entry->coa, coa) ||
-+ entry->ifindex != ifindex);
-+ }
-+ } else {
-+ /* no entry for this home_addr, try to create a new entry */
-+ DEBUG(DBG_INFO, "creating a new entry");
-+ update = 0;
-+
-+ entry = mipv6_bce_alloc(type);
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "cache full, entry not added");
-+ goto err;
-+ }
-+
-+ create_tunnel = (type == HOME_REGISTRATION);
-+ }
-+
-+ if (create_tunnel) {
-+ if (update)
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ if (mip6_fn.proxy_create(flags, ifindex, coa, our_addr, home_addr) < 0) {
-+ goto err_proxy;
-+ }
-+ }
-+
-+ ipv6_addr_copy(&(entry->our_addr), our_addr);
-+ ipv6_addr_copy(&(entry->home_addr), home_addr);
-+ ipv6_addr_copy(&(entry->coa), coa);
-+ entry->ifindex = ifindex;
-+ entry->seq = seq;
-+ entry->type = type;
-+ entry->flags = flags;
-+
-+ entry->last_br = 0;
-+ entry->destunr_count = 0;
-+ entry->callback_time = now + lifetime * HZ;
-+ if (entry->type & HOME_REGISTRATION)
-+ entry->br_callback_time = 0;
-+ else
-+ entry->br_callback_time = now +
-+ (lifetime - BCACHE_BR_SEND_LEAD) * HZ;
-+
-+ if (update) {
-+ DEBUG(DBG_INFO, "updating entry : %x", entry);
-+ hashlist_reposition(bcache.entries, (void *)entry,
-+ entry->callback_time);
-+ } else {
-+ DEBUG(DBG_INFO, "adding entry: %x", entry);
-+ if ((hashlist_add(bcache.entries,
-+ &hashkey,
-+ entry->callback_time, entry)) < 0) {
-+
-+ DEBUG(DBG_ERROR, "Hash add failed");
-+ goto err_hashlist;
-+ }
-+ }
-+
-+ set_timer();
-+
-+out:
-+ write_unlock(&bcache_lock);
-+ return 0;
-+
-+err_hashlist:
-+ if (create_tunnel) {
-+ mip6_fn.proxy_del(home_addr, entry);
-+ }
-+err_proxy:
-+ if (update) {
-+ hashlist_delete(bcache.entries, (void *)entry);
-+ }
-+ mipv6_bce_free(entry);
-+err:
-+ write_unlock(&bcache_lock);
-+ return ret;
-+}
-+
-+int mipv6_bcache_icmp_err(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ int destunr_count)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ int ret = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+ if (unlikely(bcache.entries == NULL)) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ if ((entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ entry->last_destunr = jiffies;
-+ entry->destunr_count = destunr_count;
-+ ret = 0;
-+ }
-+err:
-+ write_unlock(&bcache_lock);
-+ return ret;
-+}
-+
-+
-+/**
-+ * mipv6_bcache_delete - delete Binding Cache entry
-+ * @home_addr: MN's home address
-+ * @our_addr: our address
-+ * @type: type of entry
-+ *
-+ * Deletes an entry associated with @home_addr from Binding Cache.
-+ * Valid values for @type are %CACHE_ENTRY, %HOME_REGISTRATION and
-+ * %ANY_ENTRY. %ANY_ENTRY deletes any type of entry.
-+ **/
-+int mipv6_bcache_delete(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr, __u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+ int err = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL) {
-+ DEBUG(DBG_INFO, "error in arguments");
-+ return -EINVAL;
-+ }
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+
-+ if (unlikely(bcache.entries == NULL) ||
-+ (entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) == NULL ||
-+ !(entry->type & type)) {
-+ DEBUG(DBG_INFO, "No matching entry found");
-+ err = -ENOENT;
-+ goto out;
-+ }
-+
-+ hashlist_delete(bcache.entries, (void *) entry);
-+ mipv6_bce_free(entry);
-+
-+ set_timer();
-+out:
-+ write_unlock(&bcache_lock);
-+ return err;
-+}
-+
-+/**
-+ * mipv6_bcache_exists - check if entry exists
-+ * @home_addr: home address to check
-+ * @our_addr: our address
-+ *
-+ * Determines if a binding exists for @home_addr. Returns type of the
-+ * entry or negative if entry does not exist.
-+ **/
-+int mipv6_bcache_exists(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+ int type = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL)
-+ return -EINVAL;
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ read_lock(&bcache_lock);
-+ if (likely(bcache.entries != NULL) &&
-+ (entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ type = entry->type;
-+ }
-+ read_unlock(&bcache_lock);
-+
-+ return type;
-+}
-+
-+/**
-+ * mipv6_bcache_get - get entry from Binding Cache
-+ * @home_addr: home address to search
-+ * @our_addr: our address
-+ * @entry: pointer to buffer
-+ *
-+ * Gets a copy of Binding Cache entry for @home_addr. If entry
-+ * exists entry is copied to @entry and zero is returned.
-+ * Otherwise returns negative.
-+ **/
-+int mipv6_bcache_get(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ struct mipv6_bce *entry)
-+{
-+ struct mipv6_bce *entry2;
-+ struct in6_addr_pair hashkey;
-+ int ret = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL || entry == NULL)
-+ return -EINVAL;
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ read_lock_bh(&bcache_lock);
-+
-+ entry2 = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey);
-+ if (entry2 != NULL) {
-+ memcpy(entry, entry2, sizeof(struct mipv6_bce));
-+ ret = 0;
-+ }
-+ read_unlock_bh(&bcache_lock);
-+ return ret;
-+}
-+
-+int mipv6_bcache_iterate(hashlist_iterator_t func, void *args)
-+{
-+ int ret;
-+
-+ read_lock_bh(&bcache_lock);
-+ ret = hashlist_iterate(bcache.entries, args, func);
-+ read_unlock_bh(&bcache_lock);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Proc-filesystem functions
-+ */
-+
-+#define BC_INFO_LEN 80
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args, unsigned long *pref)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *) args;
-+ struct mipv6_bce *entry =
-+ (struct mipv6_bce *) data;
-+
-+ ASSERT(entry != NULL);
-+
-+ if (arg->skip < arg->offset / BC_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ /* HoA CoA CallbackInSecs Type */
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%08x%08x%08x%08x %08x%08x%08x%08x %010lu %02d\n",
-+ ntohl(entry->home_addr.s6_addr32[0]),
-+ ntohl(entry->home_addr.s6_addr32[1]),
-+ ntohl(entry->home_addr.s6_addr32[2]),
-+ ntohl(entry->home_addr.s6_addr32[3]),
-+ ntohl(entry->coa.s6_addr32[0]),
-+ ntohl(entry->coa.s6_addr32[1]),
-+ ntohl(entry->coa.s6_addr32[2]),
-+ ntohl(entry->coa.s6_addr32[3]),
-+ ((entry->callback_time) - jiffies) / HZ,
-+ (int) entry->type);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+ /*
-+ * Callback function for proc filesystem.
-+ */
-+static int bcache_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&bcache_lock);
-+ hashlist_iterate(bcache.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&bcache_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % BC_INFO_LEN;
-+
-+ args.len -= offset % BC_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+static int bcache_compare(void *data, void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey;
-+ struct mipv6_bce *e = (struct mipv6_bce *) data;
-+
-+ if (ipv6_addr_cmp(&e->home_addr, p->a1) == 0
-+ && ipv6_addr_cmp(&e->our_addr, p->a2) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+static __u32 bcache_hash(void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey;
-+
-+ return p->a1->s6_addr32[0] ^ p->a1->s6_addr32[1] ^
-+ p->a2->s6_addr32[2] ^ p->a2->s6_addr32[3];
-+}
-+
-+/*
-+ * Initialization and shutdown functions
-+ */
-+
-+int __init mipv6_bcache_init(__u32 size)
-+{
-+ if (size < 1) {
-+ DEBUG(DBG_ERROR, "Binding cache size must be at least 1");
-+ return -EINVAL;
-+ }
-+ bcache.entries = hashlist_create(MIPV6_BCACHE_HASHSIZE, size,
-+ sizeof(struct mipv6_bce),
-+ "mip6_bcache", NULL, NULL,
-+ bcache_compare, bcache_hash);
-+
-+ if (bcache.entries == NULL) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hashlist");
-+ return -ENOMEM;
-+ }
-+
-+ init_timer(&bcache.callback_timer);
-+ bcache.callback_timer.data = 0;
-+ bcache.callback_timer.function = timer_handler;
-+ bcache.size = size;
-+
-+ proc_net_create("mip6_bcache", 0, bcache_proc_info);
-+
-+ DEBUG(DBG_INFO, "Binding cache initialized");
-+ return 0;
-+}
-+
-+static int
-+bce_cleanup_iterator(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ int type = (int) args;
-+ struct mipv6_bce *entry = (struct mipv6_bce *) rawentry;
-+ if (entry->type == type) {
-+ if (entry->type & HOME_REGISTRATION) {
-+ if (unlikely(mip6_fn.proxy_del == NULL))
-+ DEBUG(DBG_ERROR, "proxy_del unitialized");
-+ else
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ return ITERATOR_CONT;
-+
-+}
-+
-+void mipv6_bcache_cleanup(int type)
-+{
-+ write_lock_bh(&bcache_lock);
-+ hashlist_iterate(bcache.entries,(void *) type, bce_cleanup_iterator);
-+ write_unlock_bh(&bcache_lock);
-+}
-+
-+int __exit mipv6_bcache_exit(void)
-+{
-+ struct hashlist *entries;
-+
-+ DEBUG_FUNC();
-+
-+ proc_net_remove("mip6_bcache");
-+
-+ write_lock_bh(&bcache_lock);
-+ DEBUG(DBG_INFO, "Stopping the bcache timer");
-+ del_timer(&bcache.callback_timer);
-+ hashlist_iterate(bcache.entries,(void *)CACHE_ENTRY,
-+ bce_cleanup_iterator);
-+
-+ entries = bcache.entries;
-+ bcache.entries = NULL;
-+ write_unlock_bh(&bcache_lock);
-+
-+ hashlist_destroy(entries);
-+ return 0;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.h linux-2.4.25/net/ipv6/mobile_ip6/bcache.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/bcache.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/bcache.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,72 @@
-+/*
-+ * MIPL Mobile IPv6 Binding Cache header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _BCACHE_H
-+#define _BCACHE_H
-+
-+#include <linux/in6.h>
-+#include <linux/timer.h>
-+#include "hashlist.h"
-+
-+#define CACHE_ENTRY 1 /* this and HOME_REGISTRATION are the entry types */
-+#define HOME_REGISTRATION 2
-+#define ANY_ENTRY 3
-+
-+#define MIPV6_MAX_DESTUNREACH 5 /* Delete CN BCEs after 5 destination unreachables */
-+#define MIPV6_DEST_UNR_IVAL 10 /* What is the max interval of destination
-+ unreacahable error messages for them to be persistent*/
-+
-+struct mipv6_bce {
-+ struct hashlist_entry e;
-+ int ifindex; /* Interface identifier */
-+ struct in6_addr our_addr; /* our address (as seen by the MN) */
-+ struct in6_addr home_addr; /* MN home address */
-+ struct in6_addr coa; /* MN care-of address */
-+ unsigned long callback_time; /* time of expiration (in jiffies) */
-+ unsigned long br_callback_time; /* time for sending a BR (in jiffies) */
-+ int (*callback_function)(struct mipv6_bce *entry);
-+ __u8 type; /* home registration */
-+ __u8 router; /* mn is router */
-+ __u8 flags; /* flags received in BU */
-+ __u16 seq; /* sequence number */
-+ unsigned long last_br; /* time when last BR sent */
-+ unsigned long last_destunr; /* time when last ICMP destination unreachable received */
-+ int br_count; /* How many BRRs have sent */
-+ int destunr_count; /* Number of destination unreachables received */
-+};
-+
-+int mipv6_bcache_add(int ifindex, struct in6_addr *our_addr,
-+ struct in6_addr *home_addr, struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type);
-+
-+int mipv6_bcache_icmp_err(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ int destunr_count);
-+
-+int mipv6_bcache_delete(struct in6_addr *home_addr, struct in6_addr *our_addr,
-+ __u8 type);
-+
-+int mipv6_bcache_exists(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr);
-+
-+int mipv6_bcache_get(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ struct mipv6_bce *entry);
-+
-+int mipv6_bcache_iterate(int (*func)(void *, void *, unsigned long *), void *args);
-+
-+void mipv6_bcache_cleanup(int type);
-+
-+int mipv6_bcache_init(__u32 size);
-+
-+int mipv6_bcache_exit(void);
-+
-+#endif /* _BCACHE_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bul.c linux-2.4.25/net/ipv6/mobile_ip6/bul.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/bul.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/bul.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,634 @@
-+/*
-+ * Binding update list
-+ *
-+ * Authors:
-+ * Juha Mynttinen <jmynttin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Timer code cleaned up
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <net/ipv6.h>
-+#include <net/mipv6.h>
-+#include <linux/proc_fs.h>
-+
-+#include "bul.h"
-+#include "debug.h"
-+#include "hashlist.h"
-+#include "tunnel_mn.h"
-+#include "mobhdr.h"
-+
-+#define MIPV6_BUL_HASHSIZE 32
-+
-+rwlock_t bul_lock = RW_LOCK_UNLOCKED;
-+
-+struct mipv6_bul {
-+ struct hashlist *entries;
-+ struct timer_list callback_timer;
-+};
-+
-+static struct mipv6_bul bul;
-+
-+struct in6_addr_pair {
-+ struct in6_addr *a1;
-+ struct in6_addr *a2;
-+};
-+
-+/**********************************************************************
-+ *
-+ * Private functions
-+ *
-+ **********************************************************************/
-+
-+static int bul_compare(void *data, void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey;
-+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data;
-+
-+ if (ipv6_addr_cmp(&e->cn_addr, p->a1) == 0
-+ && ipv6_addr_cmp(&e->home_addr, p->a2) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+struct test_keys {
-+ struct in6_addr *addr;
-+ u8 *cookie;
-+};
-+
-+static int bul_compare_cookie(void *data, void *keys)
-+{
-+ struct test_keys *p = (struct test_keys *)keys;
-+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data;
-+
-+ if (ipv6_addr_cmp(&e->cn_addr, p->addr) == 0 && e->rr
-+ && memcmp(&e->rr->cot_cookie, p->cookie, 8) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+static u32 bul_hash(void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey;
-+
-+ return p->a1->s6_addr32[0] ^
-+ p->a1->s6_addr32[1] ^
-+ p->a1->s6_addr32[2] ^
-+ p->a1->s6_addr32[3];
-+}
-+
-+static int bul_proc_info(char *buffer, char **start, off_t offset,
-+ int length);
-+
-+static struct mipv6_bul_entry *mipv6_bul_get_entry(void)
-+{
-+ DEBUG_FUNC();
-+ return ((struct mipv6_bul_entry *)
-+ hashlist_alloc(bul.entries, SLAB_ATOMIC));
-+}
-+
-+static void mipv6_bul_entry_free(struct mipv6_bul_entry *entry)
-+{
-+ DEBUG_FUNC();
-+
-+ if (entry->rr) {
-+ if (entry->rr->kbu)
-+ kfree(entry->rr->kbu);
-+ kfree(entry->rr);
-+ }
-+ if (entry->ops)
-+ kfree(entry->ops);
-+ hashlist_free(bul.entries, (void *)entry);
-+}
-+
-+static __inline__ int del_bul_entry_tnl(struct mipv6_bul_entry *entry)
-+{
-+ if (entry->flags & MIPV6_BU_F_HOME) {
-+ return mipv6_mv_tnl_to_ha(&entry->cn_addr,
-+ &entry->coa,
-+ &entry->home_addr);
-+ }
-+ return 0;
-+}
-+
-+static void timer_update(void)
-+{
-+ struct mipv6_bul_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ entry = hashlist_get_first(bul.entries);
-+
-+ while (entry && time_after_eq(jiffies, entry->callback_time)) {
-+ if (time_after_eq(jiffies, entry->expire) ||
-+ entry->callback(entry) != 0) {
-+ /*
-+ * Either the entry has expired, or the callback
-+ * indicated that it should be deleted.
-+ */
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+ mipv6_bul_entry_free(entry);
-+ DEBUG(DBG_INFO, "Entry deleted (was expired) from "
-+ "binding update list");
-+ } else {
-+ /* move entry to its right place in the hashlist */
-+ DEBUG(DBG_INFO, "Rescheduling");
-+ hashlist_reposition(bul.entries, (void *)entry,
-+ entry->callback_time);
-+ }
-+ entry = (struct mipv6_bul_entry *)
-+ hashlist_get_first(bul.entries);
-+ }
-+
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "bul empty, not setting a new timer");
-+ del_timer(&bul.callback_timer);
-+ } else {
-+ mod_timer(&bul.callback_timer, entry->callback_time);
-+ }
-+}
-+
-+static void timer_handler(unsigned long dummy)
-+{
-+ DEBUG_FUNC();
-+
-+ write_lock(&bul_lock);
-+ timer_update();
-+ write_unlock(&bul_lock);
-+}
-+
-+/**********************************************************************
-+ *
-+ * Public interface functions
-+ *
-+ **********************************************************************/
-+
-+/**
-+ * mipv6_bul_iterate - apply interator function to all entries
-+ * @func: function to apply
-+ * @args: extra arguments for iterator
-+ *
-+ * Applies @func for each entry in Binding Update List. Extra
-+ * arguments given in @args are also passed to the iterator function.
-+ * Caller must hold @bul_lock.
-+ **/
-+int mipv6_bul_iterate(hashlist_iterator_t func, void *args)
-+{
-+ DEBUG_FUNC();
-+
-+ return hashlist_iterate(bul.entries, args, func);
-+}
-+
-+/**
-+ * mipv6_bul_exists - check if Binding Update List entry exists
-+ * @cn: address to check
-+ *
-+ * Checks if Binding Update List has an entry for @cn. Returns true
-+ * if entry exists, false otherwise. Caller may not hold @bul_lock.
-+ **/
-+int mipv6_bul_exists(struct in6_addr *cn, struct in6_addr *haddr)
-+{
-+ int exists;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = cn;
-+ hashkey.a2 = haddr;
-+
-+ read_lock_bh(&bul_lock);
-+
-+ if (unlikely(bul.entries == NULL))
-+ exists = 0;
-+ else
-+ exists = (hashlist_get(bul.entries, &hashkey) != NULL);
-+
-+ read_unlock_bh(&bul_lock);
-+ return exists;
-+}
-+
-+/**
-+ * mipv6_bul_get - get Binding Update List entry
-+ * @cn_addr: CN address to search
-+ * @home_addr: home address to search
-+ *
-+ * Returns Binding Update List entry for @cn_addr if it exists.
-+ * Otherwise returns %NULL. Caller must hold @bul_lock.
-+ **/
-+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cn_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL)) {
-+ return NULL;
-+ }
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey);
-+
-+ return entry;
-+}
-+
-+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie(
-+ struct in6_addr *cn_addr, u8 *cookie)
-+{
-+ struct test_keys key;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL))
-+ return NULL;
-+ key.addr = cn_addr;
-+ key.cookie = cookie;
-+
-+ return (struct mipv6_bul_entry *)
-+ hashlist_get_ex(bul.entries, &key,
-+ bul_compare_cookie);
-+}
-+
-+/**
-+ * mipv6_bul_reschedule - reschedule Binding Update List entry
-+ * @entry: entry to reschedule
-+ *
-+ * Reschedules a Binding Update List entry. Must be called after
-+ * modifying entry lifetime. Caller must hold @bul_lock (write).
-+ **/
-+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry)
-+{
-+ DEBUG_FUNC();
-+
-+ hashlist_reposition(bul.entries,
-+ (void *)entry,
-+ entry->callback_time);
-+ timer_update();
-+}
-+
-+/**
-+ * mipv6_bul_add - add binding update to Binding Update List
-+ * @cn_addr: IPv6 address where BU was sent
-+ * @home_addr: Home address for this binding
-+ * @coa: Care-of address for this binding
-+ * @lifetime: expiration time of the binding in seconds
-+ * @seq: sequence number of the BU
-+ * @flags: %MIPV6_BU_F_* flags
-+ * @callback: callback function called on expiration
-+ * @callback_time: expiration time for callback
-+ * @state: binding send state
-+ * @delay: retransmission delay
-+ * @maxdelay: retransmission maximum delay
-+ * @ops: Mobility header options for BU
-+ * @rr: Return routability information
-+ *
-+ * Adds a binding update sent to @cn_addr for @home_addr to the
-+ * Binding Update List. If entry already exists, it is updated.
-+ * Entry is set to expire in @lifetime seconds. Entry has a callback
-+ * function @callback that is called at @callback_time. Entry @state
-+ * controls resending of this binding update and it can be set to
-+ * %ACK_OK, %RESEND_EXP or %ACK_ERROR. Returns a pointer to the newly
-+ * created or updated entry. Caller must hold @bul_lock (write).
-+ **/
-+struct mipv6_bul_entry *mipv6_bul_add(
-+ struct in6_addr *cn_addr, struct in6_addr *home_addr,
-+ struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags,
-+ int (*callback)(struct mipv6_bul_entry *entry),
-+ __u32 callback_time,
-+ __u8 state, __u32 delay, __u32 maxdelay,
-+ struct mipv6_mh_opt *ops,
-+ struct mipv6_rr_info *rr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ int update = 0;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL))
-+ return NULL;
-+
-+ if (cn_addr == NULL || home_addr == NULL || coa == NULL ||
-+ lifetime < 0 || callback == NULL || callback_time < 0 ||
-+ (state != ACK_OK && state != RESEND_EXP && state != ACK_ERROR) ||
-+ delay < 0 || maxdelay < 0) {
-+ DEBUG(DBG_ERROR, "invalid arguments");
-+ return NULL;
-+ }
-+ DEBUG(DBG_INFO, "cn_addr: %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "home_addr: %x:%x:%x:%x:%x:%x:%x:%x"
-+ "coaddr: %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(cn_addr),
-+ NIPV6ADDR(home_addr), NIPV6ADDR(coa));
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ /*
-+ * decide whether to add a new entry or update existing, also
-+ * check if there's room for a new entry when adding a new
-+ * entry (latter is handled by mipv6_bul_get_entry()
-+ */
-+ if ((entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey)) != NULL) {
-+ /* if an entry for this cn_addr exists (with smaller
-+ * seq than the new entry's seq), update it */
-+
-+ if (MIPV6_SEQ_GT(seq, entry->seq)) {
-+ DEBUG(DBG_INFO, "updating an existing entry");
-+ update = 1;
-+ } else {
-+ DEBUG(DBG_INFO, "smaller seq than existing, not updating");
-+ return NULL;
-+ }
-+ } else {
-+ entry = mipv6_bul_get_entry();
-+ if (entry == NULL) {
-+ DEBUG(DBG_WARNING, "binding update list full, can't add!!!");
-+ return NULL;
-+ }
-+ memset(entry, 0, sizeof(*entry));
-+ /* First BU send happens here, save count in the entry */
-+ entry->consecutive_sends = 1;
-+ }
-+
-+ if (!update) {
-+ ipv6_addr_copy(&(entry->cn_addr), cn_addr);
-+ ipv6_addr_copy(&(entry->home_addr), home_addr);
-+ entry->ops = ops;
-+ }
-+ /* Add Return Routability info to bul entry */
-+ if (rr) {
-+ if(entry->rr)
-+ kfree(entry->rr);
-+ entry->rr = rr;
-+ }
-+
-+ ipv6_addr_copy(&(entry->coa), coa);
-+ entry->lifetime = lifetime;
-+ if (lifetime)
-+ entry->expire = jiffies + lifetime * HZ;
-+ else if (flags & MIPV6_BU_F_ACK)
-+ entry->expire = jiffies + HOME_RESEND_EXPIRE * HZ;
-+ entry->seq = seq;
-+ entry->flags = flags;
-+ entry->lastsend = jiffies; /* current time = last use of the entry */
-+ entry->state = state;
-+ entry->delay = delay;
-+ entry->maxdelay = maxdelay;
-+ entry->callback_time = jiffies + callback_time * HZ;
-+ entry->callback = callback;
-+
-+ if (flags & MIPV6_BU_F_HOME &&
-+ mipv6_mv_tnl_to_ha(cn_addr, coa, home_addr)) {
-+ DEBUG(DBG_ERROR, "reconfiguration of the tunnel failed");
-+ }
-+ if (update) {
-+ DEBUG(DBG_INFO, "updating entry: %x", entry);
-+ hashlist_reposition(bul.entries, (void *)entry,
-+ entry->callback_time);
-+ } else {
-+ DEBUG(DBG_INFO, "adding entry: %x", entry);
-+
-+ hashkey.a1 = &entry->cn_addr;
-+ hashkey.a2 = &entry->home_addr;
-+
-+ if ((hashlist_add(bul.entries, &hashkey,
-+ entry->callback_time,
-+ entry)) < 0) {
-+ DEBUG(DBG_ERROR, "Hash add failed");
-+ mipv6_bul_entry_free(entry);
-+ return NULL;
-+ }
-+ }
-+ timer_update();
-+
-+ return entry;
-+}
-+
-+/**
-+ * mipv6_bul_delete - delete Binding Update List entry
-+ * @cn_addr: address for entry to delete
-+ *
-+ * Deletes the entry for @cn_addr from the Binding Update List.
-+ * Returns zero if entry was deleted succesfully, otherwise returns
-+ * negative. Caller may not hold @bul_lock.
-+ **/
-+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ write_lock(&bul_lock);
-+
-+ if (unlikely(bul.entries == NULL) ||
-+ (entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey)) == NULL) {
-+ write_unlock(&bul_lock);
-+ DEBUG(DBG_INFO, "No such entry");
-+ return -ENOENT;
-+ }
-+
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+
-+ mipv6_bul_entry_free(entry);
-+ timer_update();
-+ write_unlock(&bul_lock);
-+
-+ DEBUG(DBG_INFO, "Binding update list entry deleted");
-+
-+ return 0;
-+}
-+
-+/**********************************************************************
-+ *
-+ * Proc interface functions
-+ *
-+ **********************************************************************/
-+
-+#define BUL_INFO_LEN 152
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args,
-+ unsigned long *sortkey)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *)args;
-+ struct mipv6_bul_entry *entry =
-+ (struct mipv6_bul_entry *)data;
-+ unsigned long callback_seconds;
-+
-+ DEBUG_FUNC();
-+
-+ if (entry == NULL) return ITERATOR_ERR;
-+
-+ if (time_after(jiffies, entry->callback_time))
-+ callback_seconds = 0;
-+ else
-+ callback_seconds = (entry->callback_time - jiffies) / HZ;
-+
-+ if (arg->skip < arg->offset / BUL_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ /* CN HoA CoA ExpInSecs SeqNum State Delay MaxDelay CallbackInSecs */
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%08x%08x%08x%08x %08x%08x%08x%08x %08x%08x%08x%08x\n"
-+ "%010lu %05d %02d %010d %010d %010lu\n",
-+ ntohl(entry->cn_addr.s6_addr32[0]),
-+ ntohl(entry->cn_addr.s6_addr32[1]),
-+ ntohl(entry->cn_addr.s6_addr32[2]),
-+ ntohl(entry->cn_addr.s6_addr32[3]),
-+ ntohl(entry->home_addr.s6_addr32[0]),
-+ ntohl(entry->home_addr.s6_addr32[1]),
-+ ntohl(entry->home_addr.s6_addr32[2]),
-+ ntohl(entry->home_addr.s6_addr32[3]),
-+ ntohl(entry->coa.s6_addr32[0]),
-+ ntohl(entry->coa.s6_addr32[1]),
-+ ntohl(entry->coa.s6_addr32[2]),
-+ ntohl(entry->coa.s6_addr32[3]),
-+ (entry->expire - jiffies) / HZ,
-+ entry->seq, entry->state, entry->delay,
-+ entry->maxdelay, callback_seconds);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+
-+/*
-+ * Callback function for proc filesystem.
-+ */
-+static int bul_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&bul_lock);
-+ hashlist_iterate(bul.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&bul_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % BUL_INFO_LEN;
-+
-+ args.len -= offset % BUL_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+/**********************************************************************
-+ *
-+ * Code module init/fini functions
-+ *
-+ **********************************************************************/
-+
-+int __init mipv6_bul_init(__u32 size)
-+{
-+ DEBUG_FUNC();
-+
-+ if (size < 1) {
-+ DEBUG(DBG_CRITICAL,
-+ "Binding update list size must be at least 1");
-+ return -EINVAL;
-+ }
-+ bul.entries = hashlist_create(MIPV6_BUL_HASHSIZE, size,
-+ sizeof(struct mipv6_bul_entry),
-+ "mip6_bul", NULL, NULL,
-+ bul_compare, bul_hash);
-+
-+ if (bul.entries == NULL) {
-+ DEBUG(DBG_CRITICAL, "Couldn't allocate memory for "
-+ "hashlist when creating a binding update list");
-+ return -ENOMEM;
-+ }
-+ init_timer(&bul.callback_timer);
-+ bul.callback_timer.data = 0;
-+ bul.callback_timer.function = timer_handler;
-+ proc_net_create("mip6_bul", 0, bul_proc_info);
-+ DEBUG(DBG_INFO, "Binding update list initialized");
-+ return 0;
-+}
-+
-+void __exit mipv6_bul_exit()
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct hashlist *entries;
-+
-+ DEBUG_FUNC();
-+
-+ proc_net_remove("mip6_bul");
-+
-+ write_lock_bh(&bul_lock);
-+
-+ DEBUG(DBG_INFO, "Stopping the bul timer");
-+ del_timer(&bul.callback_timer);
-+
-+ while ((entry = (struct mipv6_bul_entry *)
-+ hashlist_get_first(bul.entries)) != NULL) {
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+
-+ mipv6_bul_entry_free(entry);
-+ }
-+ entries = bul.entries;
-+ bul.entries = NULL;
-+ write_unlock_bh(&bul_lock);
-+
-+ hashlist_destroy(entries);
-+
-+ DEBUG(DBG_INFO, "binding update list destroyed");
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/bul.h linux-2.4.25/net/ipv6/mobile_ip6/bul.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/bul.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/bul.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,91 @@
-+/*
-+ * MIPL Mobile IPv6 Binding Update List header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _BUL_H
-+#define _BUL_H
-+
-+#include "hashlist.h"
-+
-+#define ACK_OK 0x01
-+#define RESEND_EXP 0x02
-+#define ACK_ERROR 0x04
-+
-+#define HOME_RESEND_EXPIRE 3600
-+#define MIPV6_COOKIE_LEN 8
-+struct mipv6_rr_info {
-+ /* RR information */
-+ u16 rr_state; /* State of the RR */
-+ u16 rr_flags; /* Flags for the RR */
-+ u8 hot_cookie[MIPV6_COOKIE_LEN]; /* HoT Cookie */
-+ u8 cot_cookie[MIPV6_COOKIE_LEN]; /* CoT Cookie */
-+ u8 home_cookie[MIPV6_COOKIE_LEN]; /* Home Cookie */
-+ u8 careof_cookie[MIPV6_COOKIE_LEN]; /* Careof Cookie */
-+ u32 lastsend_hoti; /* When HoTI was last sent (jiffies) */
-+ u32 lastsend_coti; /* When CoTI was last sent (jiffies) */
-+ u32 home_time; /* when Care-of cookie was received */
-+ u32 careof_time; /* when Home cookie was received */
-+ int home_nonce_index; /* Home cookie nonce index */
-+ int careof_nonce_index; /* Care-of cookie nonce index */
-+ u8 *kbu; /* Binding authentication key */
-+};
-+struct mipv6_bul_entry {
-+ struct hashlist_entry e;
-+ struct in6_addr cn_addr; /* CN to which BU was sent */
-+ struct in6_addr home_addr; /* home address of this binding */
-+ struct in6_addr coa; /* care-of address of the sent BU */
-+
-+ unsigned long expire; /* entry's expiration time (jiffies) */
-+ __u32 lifetime; /* lifetime sent in this BU */
-+ __u32 lastsend; /* last time when BU sent (jiffies) */
-+ __u32 consecutive_sends; /* Number of consecutive BU's sent */
-+ __u16 seq; /* sequence number of the latest BU */
-+ __u8 flags; /* BU send flags */
-+ __u8 state; /* resend state */
-+ __u32 initdelay; /* initial ack wait */
-+ __u32 delay; /* current ack wait */
-+ __u32 maxdelay; /* maximum ack wait */
-+
-+ struct mipv6_rr_info *rr;
-+ struct mipv6_mh_opt *ops; /* saved option values */
-+
-+ unsigned long callback_time;
-+ int (*callback)(struct mipv6_bul_entry *entry);
-+};
-+
-+extern rwlock_t bul_lock;
-+
-+int mipv6_bul_init(__u32 size);
-+
-+void mipv6_bul_exit(void);
-+
-+struct mipv6_bul_entry *mipv6_bul_add(
-+ struct in6_addr *cn_addr, struct in6_addr *home_addr,
-+ struct in6_addr *coa, __u32 lifetime, __u16 seq, __u8 flags,
-+ int (*callback)(struct mipv6_bul_entry *entry), __u32 callback_time,
-+ __u8 state, __u32 delay, __u32 maxdelay, struct mipv6_mh_opt *ops,
-+ struct mipv6_rr_info *rr);
-+
-+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr);
-+
-+int mipv6_bul_exists(struct in6_addr *cnaddr, struct in6_addr *home_addr);
-+
-+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cnaddr,
-+ struct in6_addr *home_addr);
-+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie(struct in6_addr *cn_addr,
-+ u8 *cookie);
-+
-+int bul_entry_expired(struct mipv6_bul_entry *bulentry);
-+
-+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry);
-+
-+int mipv6_bul_iterate(int (*func)(void *, void *, unsigned long *), void *args);
-+
-+#endif /* BUL_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/config.h linux-2.4.25/net/ipv6/mobile_ip6/config.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/config.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/config.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,72 @@
-+/*
-+ * Configuration parameters
-+ *
-+ * $Id$
-+ */
-+
-+#define MIPV6VERSION "D24"
-+#define MIPLVERSION "v1.0"
-+
-+#define CAP_CN 0x01
-+#define CAP_HA 0x02
-+#define CAP_MN 0x04
-+
-+struct mip6_conf {
-+ int capabilities;
-+ int debug_level;
-+ int accept_ret_rout;
-+ int max_rtr_reachable_time;
-+ int eager_cell_switching;
-+ int max_num_tunnels;
-+ int min_num_tunnels;
-+ int binding_refresh_advice;
-+ int bu_lladdr;
-+ int bu_keymgm;
-+ int bu_cn_ack;
-+};
-+
-+extern struct mip6_conf mip6node_cnf;
-+
-+struct mipv6_bce;
-+
-+struct mip6_func {
-+ void (*bce_home_add) (int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+ void (*bce_cache_add) (int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+ void (*bce_home_del) (struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu);
-+ void (*bce_cache_del) (struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu);
-+
-+ int (*bce_tnl_rt_add) (struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+ void (*bce_tnl_rt_del) (struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+ void (*proxy_del) (struct in6_addr *home_addr, struct mipv6_bce *entry);
-+ int (*proxy_create) (int flags, int ifindex, struct in6_addr *coa,
-+ struct in6_addr *our_addr, struct in6_addr *home_addr);
-+
-+ int (*icmpv6_dhaad_rep_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_dhaad_req_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_pfxadv_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_pfxsol_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_paramprob_rcv) (struct sk_buff *skb);
-+
-+ int (*mn_use_hao) (struct in6_addr *daddr, struct in6_addr *saddr);
-+ void (*mn_check_tunneled_packet) (struct sk_buff *skb);
-+};
-+
-+extern struct mip6_func mip6_fn;
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/debug.h linux-2.4.25/net/ipv6/mobile_ip6/debug.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/debug.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/debug.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,112 @@
-+/*
-+ * MIPL Mobile IPv6 Debugging macros and functions
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _DEBUG_H
-+#define _DEBUG_H
-+
-+#include <linux/autoconf.h>
-+
-+/* priorities for different debug conditions */
-+
-+#define DBG_CRITICAL 0 /* unrecoverable error */
-+#define DBG_ERROR 1 /* error (recoverable) */
-+#define DBG_WARNING 2 /* unusual situation but not a real error */
-+#define DBG_INFO 3 /* generally useful information */
-+#define DBG_EXTRA 4 /* extra information */
-+#define DBG_FUNC_ENTRY 6 /* use to indicate function entry and exit */
-+#define DBG_DATADUMP 7 /* packet dumps, etc. lots of flood */
-+
-+/**
-+ * NIPV6ADDR - macro for IPv6 addresses
-+ * @addr: Network byte order IPv6 address
-+ *
-+ * Macro for printing IPv6 addresses. Used in conjunction with
-+ * printk() or derivatives (such as DEBUG macro).
-+ **/
-+#define NIPV6ADDR(addr) \
-+ ntohs(((u16 *)addr)[0]), \
-+ ntohs(((u16 *)addr)[1]), \
-+ ntohs(((u16 *)addr)[2]), \
-+ ntohs(((u16 *)addr)[3]), \
-+ ntohs(((u16 *)addr)[4]), \
-+ ntohs(((u16 *)addr)[5]), \
-+ ntohs(((u16 *)addr)[6]), \
-+ ntohs(((u16 *)addr)[7])
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+extern int mipv6_debug;
-+
-+/**
-+ * debug_print - print debug message
-+ * @debug_level: message priority
-+ * @fname: calling function's name
-+ * @fmt: printf-style formatting string
-+ *
-+ * Prints a debug message to system log if @debug_level is less or
-+ * equal to @mipv6_debug. Should always be called using DEBUG()
-+ * macro, not directly.
-+ **/
-+static void debug_print(int debug_level, const char *fname, const char* fmt, ...)
-+{
-+ char s[1024];
-+ va_list args;
-+
-+ if (mipv6_debug < debug_level)
-+ return;
-+
-+ va_start(args, fmt);
-+ vsprintf(s, fmt, args);
-+ printk("mip6[%s]: %s\n", fname, s);
-+ va_end(args);
-+}
-+
-+/**
-+ * debug_print_buffer - print arbitrary buffer to system log
-+ * @debug_level: message priority
-+ * @data: pointer to buffer
-+ * @len: number of bytes to print
-+ *
-+ * Prints @len bytes from buffer @data to system log. @debug_level
-+ * tells on which debug level message gets printed. For
-+ * debug_print_buffer() priority %DBG_DATADUMP should be used.
-+ **/
-+#define debug_print_buffer(debug_level,data,len) { \
-+ if (mipv6_debug >= debug_level) { \
-+ int i; \
-+ for (i=0; i<len; i++) { \
-+ if (i%16 == 0) printk("\n%04x: ", i); \
-+ printk("%02x ", ((unsigned char *)data)[i]); \
-+ } \
-+ printk("\n\n"); \
-+ } \
-+}
-+
-+#define DEBUG(x,y,z...) debug_print(x,__FUNCTION__,y,##z)
-+#define DEBUG_FUNC() \
-+DEBUG(DBG_FUNC_ENTRY, "%s(%d)/%s: ", __FILE__,__LINE__,__FUNCTION__)
-+
-+#else
-+#define DEBUG(x,y,z...)
-+#define DEBUG_FUNC()
-+#define debug_print_buffer(x,y,z)
-+#endif
-+
-+#undef ASSERT
-+#define ASSERT(expression) { \
-+ if (!(expression)) { \
-+ (void)printk(KERN_ERR \
-+ "Assertion \"%s\" failed: file \"%s\", function \"%s\", line %d\n", \
-+ #expression, __FILE__, __FUNCTION__, __LINE__); \
-+ BUG(); \
-+ } \
-+}
-+
-+#endif /* _DEBUG_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.c linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,394 @@
-+/*
-+ * Extension Header handling and adding code
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/types.h>
-+#include <linux/slab.h>
-+
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "stats.h"
-+#include "mobhdr.h"
-+#include "bcache.h"
-+#include "config.h"
-+
-+/**
-+ * mipv6_append_home_addr - Add Home Address Option
-+ * @opt: buffer for Home Address Option
-+ * @offset: offset from beginning of @opt
-+ * @addr: address for HAO
-+ *
-+ * Adds a Home Address Option to a packet. Option is stored in
-+ * @offset from beginning of @opt. The option is created but the
-+ * original source address in IPv6 header is left intact. The source
-+ * address will be changed from home address to CoA after the checksum
-+ * has been calculated in getfrag. Padding is done automatically, and
-+ * @opt must have allocated space for both actual option and pad.
-+ * Returns offset from @opt to end of options.
-+ **/
-+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr)
-+{
-+ int pad;
-+ struct mipv6_dstopt_homeaddr *ho;
-+
-+ DEBUG(DBG_DATADUMP, "HAO: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(addr));
-+
-+ pad = (6 - offset) & 7;
-+ mipv6_add_pad(opt + offset, pad);
-+
-+ ho = (struct mipv6_dstopt_homeaddr *)(opt + offset + pad);
-+ ho->type = MIPV6_TLV_HOMEADDR;
-+ ho->length = sizeof(*ho) - 2;
-+ ipv6_addr_copy(&ho->addr, addr);
-+
-+ return offset + pad + sizeof(*ho);
-+}
-+static inline int check_hao_validity(struct mipv6_dstopt_homeaddr *haopt,
-+ u8 *dst1,
-+ struct in6_addr *saddr,
-+ struct in6_addr *daddr)
-+{
-+ int addr_type = ipv6_addr_type(&haopt->addr);
-+ struct mipv6_bce bc_entry;
-+
-+ if (addr_type & IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type & IPV6_ADDR_UNICAST)) {
-+ DEBUG(DBG_INFO, "HAO with link local or non-unicast HoA, "
-+ "not sending BE to "
-+ "home address "
-+ "%x:%x:%x:%x:%x:%x:%x:%x ",
-+ "care-of address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&haopt->addr),
-+ NIPV6ADDR(saddr));
-+ return -EINVAL;
-+ } else if (dst1[0] != IPPROTO_MOBILITY &&
-+ (mipv6_bcache_get(&haopt->addr,
-+ daddr, &bc_entry) != 0 ||
-+ ipv6_addr_cmp(saddr, &bc_entry.coa))) {
-+ DEBUG(DBG_INFO, "HAO without binding or incorrect CoA, "
-+ "sending BE code 1: "
-+ "home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ "to care-of address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&haopt->addr),
-+ NIPV6ADDR(saddr));
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+/**
-+ * mipv6_handle_homeaddr - Home Address Destination Option handler
-+ * @skb: packet buffer
-+ * @optoff: offset to where option begins
-+ *
-+ * Handles Home Address Option in IPv6 Destination Option header.
-+ * Packet and offset to option are passed. If HAO is used without
-+ * binding, sends a Binding Error code 1. When sending BE, notify bit
-+ * is cleared to prevent IPv6 error handling from sending ICMP
-+ * Parameter Problem. Returns 1 on success, otherwise zero.
-+ **/
-+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff)
-+{
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr coaddr;
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
-+ struct mipv6_dstopt_homeaddr *haopt =
-+ (struct mipv6_dstopt_homeaddr *) &skb->nh.raw[optoff];
-+ u8 *dst1;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ if (haopt->length != sizeof(*haopt) - 2) {
-+ DEBUG(DBG_WARNING, "HAO has invalid length");
-+ MIPV6_INC_STATS(n_ha_drop.invalid);
-+ return 0;
-+ }
-+ dst1 = (u8 *)skb->h.raw;
-+ err = check_hao_validity(haopt, dst1, saddr, &skb->nh.ipv6h->daddr);
-+
-+ if (err) {
-+ haopt->type &= ~(0x80); /* clear notify bit */
-+ if (err == -ENOENT)
-+ mipv6_send_be(&skb->nh.ipv6h->daddr, saddr,
-+ &haopt->addr, MIPV6_BE_HAO_WO_BINDING);
-+ MIPV6_INC_STATS(n_ha_drop.misc);
-+ return 0;
-+ }
-+ ipv6_addr_copy(&coaddr, saddr);
-+ ipv6_addr_copy(saddr, &haopt->addr);
-+ ipv6_addr_copy(&haopt->addr, &coaddr);
-+ opt->hao = optoff;
-+ if (mip6_fn.mn_check_tunneled_packet != NULL)
-+ mip6_fn.mn_check_tunneled_packet(skb);
-+
-+ MIPV6_INC_STATS(n_ha_rcvd);
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_icmp_swap_addrs - Switch HAO and src and RT2 and dest for ICMP errors
-+ * @skb: packet buffer
-+ *
-+ * Reset the source address and the Home Address option in skb before
-+ * appending it to an ICMP error message, so original packet appears
-+ * in the error message rather than mangled.
-+ **/
-+void mipv6_icmp_swap_addrs(struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct in6_addr tmp;
-+ struct in6_addr *hoa;
-+ DEBUG_FUNC();
-+ if (opt->srcrt2) {
-+ struct rt2_hdr *rt2;
-+ rt2 = (struct rt2_hdr *)(skb->nh.raw + opt->srcrt2);
-+ hoa = &rt2->addr;
-+
-+ ipv6_addr_copy(&tmp, hoa);
-+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->daddr);
-+ ipv6_addr_copy(&skb->nh.ipv6h->daddr, &tmp);
-+ rt2->rt_hdr.segments_left++;
-+ skb->nh.ipv6h->hop_limit++;
-+ }
-+ if (opt->hao) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao);
-+ hoa = &hao->addr;
-+
-+ ipv6_addr_copy(&tmp, hoa);
-+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->saddr);
-+ ipv6_addr_copy(&skb->nh.ipv6h->saddr, &tmp);
-+ }
-+}
-+
-+/**
-+ * mipv6_append_rt2hdr - Add Type 2 Routing Header
-+ * @rt: buffer for new routing header
-+ * @addr: intermediate hop address
-+ *
-+ * Adds a Routing Header Type 2 in a packet. Stores newly created
-+ * routing header in buffer @rt. Type 2 RT only carries one address,
-+ * so there is no need to process old routing header. @rt must have
-+ * allocated space for 24 bytes.
-+ **/
-+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *rt, struct in6_addr *addr)
-+{
-+ struct rt2_hdr *rt2 = (struct rt2_hdr *)rt;
-+
-+ DEBUG(DBG_DATADUMP, "RT2: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(addr));
-+
-+ if (ipv6_addr_type(addr) == IPV6_ADDR_MULTICAST) {
-+ DEBUG(DBG_ERROR, "destination address not unicast");
-+ return;
-+ }
-+
-+ memset(rt2, 0, sizeof(*rt2));
-+ rt2->rt_hdr.type = 2;
-+ rt2->rt_hdr.hdrlen = 2;
-+ rt2->rt_hdr.segments_left = 1;
-+ ipv6_addr_copy(&rt2->addr, addr);
-+}
-+
-+/**
-+ * mipv6_append_dst1opts - Add Destination Option (1) Headers
-+ * @dst1opt: buffer for new destination options
-+ * @saddr: address for Home Address Option
-+ * @old_dst1opt: old destination options
-+ * @len: length of options
-+ *
-+ * Adds Destination Option (1) Header to a packet. New options are
-+ * stored in @dst1opt. If old destination options exist, they are
-+ * copied from @old_dst1opt. Only Home Address Option is destination
-+ * option. @dstopt must have allocated space for @len bytes. @len
-+ * includes Destination Option Header (2 bytes), Home Address Option
-+ * (18 bytes) and possible HAO pad (8n+6).
-+ **/
-+/*
-+ * ISSUE: Home Address Destination Option should really be added to a
-+ * new destination option header specified in Mobile IPv6 spec which
-+ * should be placed after routing header(s), but before fragmentation
-+ * header. Putting HAO in DO1 works for now, but support for the new
-+ * placement should be added to the IPv6 stack.
-+ */
-+void
-+mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr,
-+ struct ipv6_opt_hdr *old_dst1opt, int len)
-+{
-+ int offset;
-+
-+ if (old_dst1opt) {
-+ memcpy(dst1opt, old_dst1opt, ipv6_optlen(old_dst1opt));
-+ offset = ipv6_optlen(old_dst1opt);
-+ } else {
-+ offset = sizeof (*dst1opt);
-+ }
-+ dst1opt->hdrlen = (len >> 3) - 1;
-+ mipv6_append_home_addr((__u8 *) dst1opt, offset, saddr);
-+}
-+
-+/**
-+ * mipv6_modify_txoptions - Modify outgoing packets
-+ * @sk: socket
-+ * @skb: packet buffer for outgoing packet
-+ * @old_opt: transmit options
-+ * @fl: packet flow structure
-+ * @dst: pointer to destination cache entry
-+ *
-+ * Adds Home Address Option (for MN packets, when not at home) and
-+ * Routing Header Type 2 (for CN packets when sending to an MN) to
-+ * data packets. Old extension headers are copied from @old_opt (if
-+ * any). Extension headers are _explicitly_ added for packets with
-+ * Mobility Header. Returns the new header structure, or old if no
-+ * changes.
-+ **/
-+struct ipv6_txoptions *
-+mipv6_modify_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *old_opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ struct ipv6_opt_hdr *old_hopopt = NULL;
-+ struct ipv6_opt_hdr *old_dst1opt = NULL;
-+ struct ipv6_rt_hdr *old_srcrt = NULL;
-+
-+ int srcrtlen = 0, dst1len = 0;
-+ int tot_len, use_hao = 0;
-+ struct ipv6_txoptions *opt;
-+ struct mipv6_bce bc_entry;
-+ struct in6_addr tmpaddr, *saddr, *daddr, coaddr;
-+ __u8 *opt_ptr;
-+
-+ DEBUG_FUNC();
-+
-+ if (fl->proto == IPPROTO_MOBILITY) return old_opt;
-+ /*
-+ * we have to be prepared to the fact that saddr might not be present,
-+ * if that is the case, we acquire saddr just as kernel does.
-+ */
-+ saddr = fl ? fl->fl6_src : NULL;
-+ daddr = fl ? fl->fl6_dst : NULL;
-+
-+ if (daddr == NULL)
-+ return old_opt;
-+ if (saddr == NULL) {
-+ int err = ipv6_get_saddr(NULL, daddr, &tmpaddr);
-+ if (err)
-+ return old_opt;
-+ else
-+ saddr = &tmpaddr;
-+ }
-+
-+ DEBUG(DBG_DATADUMP,
-+ "dest. address of packet: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(daddr));
-+ DEBUG(DBG_DATADUMP, " and src. address: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(saddr));
-+
-+ if (old_opt) {
-+ old_hopopt = old_opt->hopopt;
-+ old_dst1opt = old_opt->dst1opt;
-+ old_srcrt = old_opt->srcrt;
-+ }
-+
-+ if (mip6_fn.mn_use_hao != NULL)
-+ use_hao = mip6_fn.mn_use_hao(daddr, saddr);
-+
-+ if (use_hao) {
-+ if (old_dst1opt)
-+ dst1len = ipv6_optlen(old_dst1opt);
-+ dst1len += sizeof(struct mipv6_dstopt_homeaddr) +
-+ ((6 - dst1len) & 7); /* padding */
-+ }
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0)
-+ srcrtlen = sizeof(struct rt2_hdr);
-+
-+ if ((tot_len = srcrtlen + dst1len) == 0) {
-+ return old_opt;
-+ }
-+
-+ tot_len += sizeof(*opt);
-+
-+ if (!(opt = kmalloc(tot_len, GFP_ATOMIC))) {
-+ return NULL;
-+ }
-+ memset(opt, 0, tot_len);
-+ opt->tot_len = tot_len;
-+ opt_ptr = (__u8 *) (opt + 1);
-+
-+ if (old_srcrt) {
-+ opt->srcrt = old_srcrt;
-+ opt->opt_nflen += ipv6_optlen(old_srcrt);
-+ }
-+
-+ if (srcrtlen) {
-+ DEBUG(DBG_DATADUMP, "Binding exists. Adding routing header");
-+
-+ opt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
-+ opt->opt_nflen += srcrtlen;
-+ opt_ptr += srcrtlen;
-+
-+ /*
-+ * Append care-of-address to routing header (original
-+ * destination address is home address, the first
-+ * source route segment gets put to the destination
-+ * address and the home address gets to the last
-+ * segment of source route (just as it should))
-+ */
-+
-+ ipv6_addr_copy(&coaddr, &bc_entry.coa);
-+
-+ mipv6_append_rt2hdr(opt->srcrt2, &coaddr);
-+
-+ /*
-+ * reroute output (we have to do this in case of TCP
-+ * segment) unless a routing header of type 0 is also added
-+ */
-+ if (dst && !opt->srcrt) {
-+ struct in6_addr *tmp = fl->fl6_dst;
-+ fl->fl6_dst = &coaddr;
-+
-+ dst_release(*dst);
-+ *dst = ip6_route_output(sk, fl);
-+ if (skb)
-+ skb->dst = *dst;
-+ fl->fl6_dst = tmp;
-+
-+ DEBUG(DBG_DATADUMP, "Rerouted outgoing packet");
-+ }
-+ }
-+
-+ /* Only home address option is inserted to first dst opt header */
-+ if (dst1len) {
-+ opt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
-+ opt->opt_flen += dst1len;
-+ opt_ptr += dst1len;
-+ mipv6_append_dst1opts(opt->dst1opt, saddr,
-+ old_dst1opt, dst1len);
-+ opt->mipv6_flags = MIPV6_SND_HAO;
-+ } else if (old_dst1opt) {
-+ opt->dst1opt = old_dst1opt;
-+ opt->opt_flen += ipv6_optlen(old_dst1opt);
-+ }
-+ if (old_hopopt) {
-+ opt->hopopt = old_hopopt;
-+ opt->opt_nflen += ipv6_optlen(old_hopopt);
-+ }
-+
-+ return opt;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.h linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/exthdrs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/exthdrs.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,47 @@
-+/*
-+ * MIPL Mobile IPv6 Extension Headers header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MIPV6_EXTHDRS_H
-+#define _MIPV6_EXTHDRS_H
-+
-+struct in6_addr;
-+struct sk_buff;
-+struct ipv6_rt_hdr;
-+struct ipv6_opt_hdr;
-+struct ipv6_txoptions;
-+struct flowi;
-+struct dst_entry;
-+/*
-+ * Home Address Destination Option function prototypes
-+ */
-+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr);
-+
-+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff);
-+
-+void mipv6_icmp_swap_addrs(struct sk_buff *skb);
-+
-+/*
-+ * Creates a routing header of type 2.
-+ */
-+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *srcrt, struct in6_addr *addr);
-+
-+/* Function to add the first destination option header, which may
-+ * include a home address option.
-+ */
-+void mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr,
-+ struct ipv6_opt_hdr *old_dst1opt, int len);
-+
-+struct ipv6_txoptions *mipv6_modify_txoptions(
-+ struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *old_opt, struct flowi *fl,
-+ struct dst_entry **dst);
-+
-+#endif /* _MIPV6_EXTHDRS_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ha.c linux-2.4.25/net/ipv6/mobile_ip6/ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/ha.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,553 @@
-+/*
-+ * Home-agent functionality
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Henrik Petander <lpetande@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes: Venkata Jagana,
-+ * Krishna Kumar : Statistics fix
-+ * Masahide Nakamura : Use of mipv6_forward
-+ *
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_ether.h>
-+#include <linux/netdevice.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv6.h>
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif
-+
-+#include <net/neighbour.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_fib.h>
-+#include <net/ip6_route.h>
-+#include <net/ndisc.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+
-+#include "tunnel_ha.h"
-+#include "bcache.h"
-+#include "stats.h"
-+#include "debug.h"
-+#include "util.h"
-+#include "ha.h"
-+#include "config.h"
-+#include "mobhdr.h"
-+
-+static int mipv6_ha_tunnel_sitelocal = 0;
-+
-+#ifdef CONFIG_SYSCTL
-+
-+static struct ctl_table_header *mipv6_ha_sysctl_header;
-+
-+static struct mipv6_ha_sysctl_table
-+{
-+ struct ctl_table_header *sysctl_header;
-+ ctl_table mipv6_vars[3];
-+ ctl_table mipv6_mobility_table[2];
-+ ctl_table mipv6_proto_table[2];
-+ ctl_table mipv6_root_table[2];
-+} mipv6_ha_sysctl = {
-+ NULL,
-+
-+ {{NET_IPV6_MOBILITY_TUNNEL_SITELOCAL, "tunnel_sitelocal",
-+ &mipv6_ha_tunnel_sitelocal, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {0}},
-+
-+ {{NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_vars}, {0}},
-+ {{NET_IPV6, "ipv6", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_mobility_table}, {0}},
-+ {{CTL_NET, "net", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_proto_table}, {0}}
-+};
-+
-+#endif /* CONFIG_SYSCTL */
-+
-+
-+/* this is defined in kernel IPv6 module (sockglue.c) */
-+extern struct packet_type ipv6_packet_type;
-+
-+/* mipv6_forward: Intercept NS packets destined to home address of MN */
-+int mipv6_forward(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *ipv6h;
-+ struct in6_addr *daddr, *saddr;
-+ __u8 nexthdr;
-+ int nhoff;
-+
-+ if (skb == NULL) return 0;
-+
-+ ipv6h = skb->nh.ipv6h;
-+ daddr = &ipv6h->daddr;
-+ saddr = &ipv6h->saddr;
-+
-+ nexthdr = ipv6h->nexthdr;
-+ nhoff = sizeof(*ipv6h);
-+
-+ if (ipv6_ext_hdr(nexthdr))
-+ nhoff = ipv6_skip_exthdr(skb, nhoff, &nexthdr,
-+ skb->len - sizeof(*ipv6h));
-+
-+ /* Do not to forward Neighbor Solicitation to Home Address of MN */
-+ if (nexthdr == IPPROTO_ICMPV6) {
-+ struct icmp6hdr *icmp6h;
-+ int dest_type;
-+
-+ if (nhoff < 0 || !pskb_may_pull(skb, nhoff +
-+ sizeof(struct icmp6hdr))) {
-+ kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ dest_type = ipv6_addr_type(daddr);
-+ icmp6h = (struct icmp6hdr *)&skb->nh.raw[nhoff];
-+
-+ /* Intercepts NS to HoA of MN */
-+
-+ if ((icmp6h->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) ||
-+ ((dest_type & IPV6_ADDR_MULTICAST) &&
-+ (icmp6h->icmp6_type == NDISC_ROUTER_ADVERTISEMENT))) {
-+ ip6_input(skb);
-+ } else {
-+ ip6_forward(skb);
-+ }
-+ } else {
-+ ip6_forward(skb);
-+ }
-+ return 0;
-+}
-+
-+
-+/**
-+ * mipv6_proxy_nd_rem - stop acting as a proxy for @home_address
-+ * @home_addr: address to remove
-+ * @ha_addr: home agent's address on home link
-+ * @linklocal: link-local compatibility bit
-+ *
-+ * When Home Agent acts as a proxy for an address it must leave the
-+ * solicited node multicast group for that address and stop responding
-+ * to neighbour solicitations.
-+ **/
-+static int mipv6_proxy_nd_rem(struct in6_addr *home_addr,
-+ int ifindex, int linklocal)
-+{
-+ /* When MN returns home HA leaves the solicited mcast groups
-+ * for MNs home addresses
-+ */
-+ int err;
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_ERROR, "couldn't get dev");
-+ return -ENODEV;
-+ }
-+#if 1 /* TEST */
-+ /* Remove link-local entry */
-+ if (linklocal) {
-+ struct in6_addr ll_addr;
-+ mipv6_generate_ll_addr(&ll_addr, home_addr);
-+ if ((err = pneigh_delete(&nd_tbl, &ll_addr, dev)) < 0) {
-+ DEBUG(DBG_INFO,
-+ "peigh_delete failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&ll_addr));
-+ }
-+ }
-+#endif
-+ /* Remove global (or site-local) entry */
-+ if ((err = pneigh_delete(&nd_tbl, home_addr, dev)) < 0) {
-+ DEBUG(DBG_INFO,
-+ "peigh_delete failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ }
-+ dev_put(dev);
-+ return err;
-+}
-+
-+/**
-+ * mipv6_proxy_nd - join multicast group for this address
-+ * @home_addr: address to defend
-+ * @ha_addr: home agent's address on home link
-+ * @linklocal: link-local compatibility bit
-+ *
-+ * While Mobile Node is away from home, Home Agent acts as a proxy for
-+ * @home_address. HA responds to neighbour solicitations for @home_address
-+ * thus getting all packets destined to home address of MN.
-+ **/
-+static int mipv6_proxy_nd(struct in6_addr *home_addr,
-+ int ifindex, int linklocal)
-+{
-+ /* The HA sends a proxy ndisc_na message to all hosts on MN's
-+ * home subnet by sending a neighbor advertisement with the
-+ * home address or all addresses of the mobile node if the
-+ * prefix is not 0. The addresses are formed by combining the
-+ * suffix or the host part of the address with each subnet
-+ * prefix that exists in the home subnet
-+ */
-+
-+ /* Since no previous entry for MN exists a proxy_nd advertisement
-+ * is sent to all nodes link local multicast address
-+ */
-+ int err = -1;
-+
-+ struct net_device *dev;
-+ struct in6_addr na_saddr;
-+ struct in6_addr ll_addr;
-+ struct pneigh_entry *ll_pneigh;
-+ struct in6_addr mcdest;
-+ int send_ll_na = 0;
-+ int inc_opt = 1;
-+ int solicited = 0;
-+ int override = 1;
-+
-+ DEBUG_FUNC();
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_ERROR, "couldn't get dev");
-+ return -ENODEV;
-+ }
-+
-+ if (!pneigh_lookup(&nd_tbl, home_addr, dev, 1)) {
-+ DEBUG(DBG_INFO,
-+ "peigh_lookup failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ goto free_dev;
-+ }
-+#if 1 /* TEST */
-+ if (linklocal) {
-+ mipv6_generate_ll_addr(&ll_addr, home_addr);
-+
-+ if ((ll_pneigh = pneigh_lookup(&nd_tbl, &ll_addr,
-+ dev, 1)) == NULL) {
-+ DEBUG(DBG_INFO,
-+ "peigh_lookup failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&ll_addr));
-+ pneigh_delete(&nd_tbl, home_addr, dev);
-+ goto free_dev;
-+ } else {
-+ send_ll_na = 1;
-+ }
-+ } else {
-+ ll_pneigh = NULL;
-+ }
-+#endif
-+ /* Proxy neighbor advertisement of MN's home address
-+ * to all nodes solicited multicast address
-+ */
-+ if (!ipv6_get_lladdr(dev, &na_saddr)) {
-+ ipv6_addr_all_nodes(&mcdest);
-+ ndisc_send_na(dev, NULL, &mcdest, home_addr, 0,
-+ solicited, override, inc_opt);
-+#if 1 /* TEST */
-+ if (send_ll_na) {
-+ ndisc_send_na(dev, NULL, &mcdest, &ll_addr,
-+ 0, solicited, override, inc_opt);
-+ }
-+#endif
-+ err = 0;
-+ } else {
-+ DEBUG(DBG_ERROR, "failed to get link local address for sending proxy NA");
-+ }
-+free_dev:
-+ dev_put(dev);
-+ return err;
-+
-+}
-+
-+struct inet6_ifaddr *is_on_link_ipv6_address(struct in6_addr *mn_haddr,
-+ struct in6_addr *ha_addr)
-+{
-+ struct inet6_ifaddr *ifp;
-+ struct inet6_dev *in6_dev;
-+ struct inet6_ifaddr *oifp = NULL;
-+
-+ if ((ifp = ipv6_get_ifaddr(ha_addr, 0)) == NULL)
-+ return NULL;
-+
-+ if ((in6_dev = ifp->idev) != NULL) {
-+ in6_dev_hold(in6_dev);
-+ oifp = in6_dev->addr_list;
-+ while (oifp != NULL) {
-+ spin_lock(&oifp->lock);
-+ if (mipv6_prefix_compare(&oifp->addr, mn_haddr,
-+ oifp->prefix_len) &&
-+ !(oifp->flags & IFA_F_TENTATIVE)) {
-+ spin_unlock(&oifp->lock);
-+ DEBUG(DBG_INFO, "Home Addr Opt: on-link");
-+ in6_ifa_hold(oifp);
-+ break;
-+ }
-+ spin_unlock(&oifp->lock);
-+ oifp = oifp->if_next;
-+ }
-+ in6_dev_put(in6_dev);
-+ }
-+ in6_ifa_put(ifp);
-+/* DEBUG(DBG_WARNING, "Home Addr Opt NOT on-link"); */
-+ return oifp;
-+
-+}
-+
-+/*
-+ * Lifetime checks. ifp->valid_lft >= ifp->prefered_lft always (see addrconf.c)
-+ * Returned value is in seconds.
-+ */
-+
-+static __u32 get_min_lifetime(struct inet6_ifaddr *ifp, __u32 lifetime)
-+{
-+ __u32 rem_lifetime = 0;
-+ unsigned long now = jiffies;
-+
-+ if (ifp->valid_lft == 0) {
-+ rem_lifetime = lifetime;
-+ } else {
-+ __u32 valid_lft_left =
-+ ifp->valid_lft - ((now - ifp->tstamp) / HZ);
-+ rem_lifetime =
-+ min_t(unsigned long, valid_lft_left, lifetime);
-+ }
-+
-+ return rem_lifetime;
-+}
-+
-+#define MAX_LIFETIME 1000
-+
-+/**
-+ * mipv6_lifetime_check - check maximum lifetime is not exceeded
-+ * @lifetime: lifetime to check
-+ *
-+ * Checks @lifetime does not exceed %MAX_LIFETIME. Returns @lifetime
-+ * if not exceeded, otherwise returns %MAX_LIFETIME.
-+ **/
-+static int mipv6_lifetime_check(int lifetime)
-+{
-+ return (lifetime > MAX_LIFETIME) ? MAX_LIFETIME : lifetime;
-+}
-+
-+/* Generic routine handling finish of BU processing */
-+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex, __u8 ba_status,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ int err;
-+
-+ if (ba_status >= REASON_UNSPECIFIED) {
-+ /* DAD failed */
-+ goto out;
-+ }
-+
-+ ba_lifetime = get_min_lifetime(ifp, ba_lifetime);
-+ ba_lifetime = mipv6_lifetime_check(ba_lifetime);
-+
-+ if ((err = mipv6_bcache_add(ifindex, daddr, haddr, coa,
-+ ba_lifetime, sequence, flags,
-+ HOME_REGISTRATION)) != 0 ) {
-+ DEBUG(DBG_WARNING, "home reg failed.");
-+
-+ if (err == -ENOMEDIUM)
-+ return;
-+
-+ ba_status = INSUFFICIENT_RESOURCES;
-+ } else {
-+ DEBUG(DBG_INFO, "home reg succeeded.");
-+ }
-+
-+ DEBUG(DBG_DATADUMP, "home_addr: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(haddr));
-+ DEBUG(DBG_DATADUMP, "coa: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(coa));
-+ DEBUG(DBG_DATADUMP, "lifet:%d, seq:%d", ba_lifetime, sequence);
-+out:
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence,
-+ ba_lifetime, k_bu);
-+}
-+
-+static int ha_proxy_create(int flags, int ifindex, struct in6_addr *coa,
-+ struct in6_addr *our_addr, struct in6_addr *home_addr)
-+{
-+ int ret;
-+
-+ if ((ret = mipv6_add_tnl_to_mn(coa, our_addr, home_addr)) <= 0) {
-+ if (ret != -ENOMEDIUM) {
-+ DEBUG(DBG_ERROR, "unable to configure tunnel to MN!");
-+ }
-+ return -1;
-+ }
-+ if (mipv6_proxy_nd(home_addr, ifindex,
-+ flags & MIPV6_BU_F_LLADDR) != 0) {
-+ DEBUG(DBG_ERROR, "mipv6_proxy_nd failed!");
-+ mipv6_del_tnl_to_mn(coa, our_addr, home_addr);
-+ return -2;
-+ }
-+ return 0;
-+}
-+
-+static void ha_proxy_del(struct in6_addr *home_addr, struct mipv6_bce *entry)
-+{
-+ if (mipv6_proxy_nd_rem(&entry->home_addr, entry->ifindex,
-+ entry->flags & MIPV6_BU_F_LLADDR) == 0) {
-+ DEBUG(DBG_INFO, "proxy_nd succ");
-+ } else {
-+ DEBUG(DBG_INFO, "proxy_nd fail");
-+ }
-+ mipv6_del_tnl_to_mn(&entry->coa, &entry->our_addr, home_addr);
-+}
-+
-+static void bc_home_add(int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 lifetime, __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+ struct inet6_ifaddr *ifp = NULL;
-+ __u8 ba_status = SUCCESS;
-+
-+ DEBUG_FUNC();
-+
-+ ifp = is_on_link_ipv6_address(haddr, daddr);
-+
-+ if (ifp == NULL) {
-+ ba_status = NOT_HOME_SUBNET;
-+ } else if (((ipv6_addr_type(haddr) & IPV6_ADDR_SITELOCAL) ||
-+ (ipv6_addr_type(coa) & IPV6_ADDR_SITELOCAL))
-+ && !mipv6_ha_tunnel_sitelocal) {
-+ /* Site-local home or care-of addresses are not
-+ accepted by default */
-+ ba_status = ADMINISTRATIVELY_PROHIBITED;
-+ } else {
-+ int ret;
-+
-+ ifindex = ifp->idev->dev->ifindex;
-+
-+ if ((ret = mipv6_dad_start(ifp, ifindex, daddr,
-+ haddr, coa, rep_coa, lifetime,
-+ sequence, flags)) < 0) {
-+ /* An error occurred */
-+ ba_status = -ret;
-+ } else if (ret) {
-+ /* DAD is needed to be performed. */
-+ in6_ifa_put(ifp);
-+ return;
-+ }
-+ }
-+
-+ mipv6_bu_finish(ifp, ifindex, ba_status, daddr, haddr, coa,
-+ rep_coa, lifetime, sequence, flags, k_bu);
-+ if (ifp)
-+ in6_ifa_put(ifp);
-+}
-+
-+static void bc_home_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ __u8 status = SUCCESS;
-+ struct mipv6_bce bce;
-+
-+ /* Primary Care-of Address Deregistration */
-+ if (mipv6_bcache_get(haddr, daddr, &bce) < 0) {
-+ DEBUG(DBG_INFO, "entry is not in cache");
-+ status = NOT_HA_FOR_MN;
-+ } else {
-+ ha_proxy_del(&bce.home_addr, &bce);
-+ mipv6_bcache_delete(haddr, daddr, HOME_REGISTRATION);
-+ }
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence, 0, k_bu);
-+}
-+
-+extern int mipv6_ra_rcv_ptr(struct sk_buff *skb, struct icmp6hdr *msg);
-+
-+
-+static int
-+mipv6_ha_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_encapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_ha_tnl_xmit_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_ENCAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_ha_tnl_xmit_stats_hook
-+};
-+
-+static int
-+mipv6_ha_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_decapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_ha_tnl_rcv_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_ha_tnl_rcv_stats_hook
-+};
-+
-+static struct mip6_func old;
-+
-+int __init mipv6_ha_init(void)
-+{
-+ DEBUG_FUNC();
-+
-+#ifdef CONFIG_SYSCTL
-+ if (!(mipv6_ha_sysctl_header =
-+ register_sysctl_table(mipv6_ha_sysctl.mipv6_root_table, 0)))
-+ printk(KERN_ERR "Failed to register sysctl handlers!");
-+#endif
-+ memcpy(&old, &mip6_fn, sizeof(struct mip6_func));
-+ mip6_fn.bce_home_add = bc_home_add;
-+ mip6_fn.bce_home_del = bc_home_delete;
-+ mip6_fn.proxy_del = ha_proxy_del;
-+ mip6_fn.proxy_create = ha_proxy_create;
-+ /* register packet interception hooks */
-+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_rcv_stats_ops);
-+ return 0;
-+}
-+
-+void __exit mipv6_ha_exit(void)
-+{
-+ DEBUG_FUNC();
-+
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_ha_sysctl_header);
-+#endif
-+
-+ /* remove packet interception hooks */
-+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_rcv_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_xmit_stats_ops);
-+
-+ mip6_fn.bce_home_add = old.bce_home_add;
-+ mip6_fn.bce_home_del = old.bce_home_del;
-+ mip6_fn.proxy_del = old.proxy_del;
-+ mip6_fn.proxy_create = old.proxy_create;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ha.h linux-2.4.25/net/ipv6/mobile_ip6/ha.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/ha.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/ha.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,39 @@
-+/*
-+ * MIPL Mobile IPv6 Home Agent header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HA_H
-+#define _HA_H
-+
-+int mipv6_ha_init(void);
-+void mipv6_ha_exit(void);
-+
-+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags);
-+
-+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex,
-+ __u8 ba_status, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 ba_lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+
-+
-+static __inline__ void mipv6_generate_ll_addr(struct in6_addr *ll_addr,
-+ struct in6_addr *addr)
-+{
-+ ll_addr->s6_addr32[0] = htonl(0xfe800000);
-+ ll_addr->s6_addr32[1] = 0;
-+ ll_addr->s6_addr32[2] = addr->s6_addr32[2];
-+ ll_addr->s6_addr32[3] = addr->s6_addr32[3];
-+}
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/halist.c linux-2.4.25/net/ipv6/mobile_ip6/halist.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/halist.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/halist.c 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,507 @@
-+/*
-+ * Home Agents List
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#define PREF_BASE 0xffff /* MAX value for u16 field in RA */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/proc_fs.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+
-+#include "hashlist.h"
-+#include "util.h"
-+#include "debug.h"
-+
-+struct mipv6_halist {
-+ struct hashlist *entries;
-+ struct timer_list expire_timer;
-+};
-+
-+static rwlock_t home_agents_lock = RW_LOCK_UNLOCKED;
-+
-+static struct mipv6_halist home_agents;
-+
-+struct mipv6_halist_entry {
-+ struct hashlist_entry e;
-+ int ifindex; /* Link identifier */
-+ struct in6_addr link_local_addr; /* HA's link-local address */
-+ struct in6_addr global_addr; /* HA's Global address */
-+ int plen;
-+ long preference; /* The preference for this HA */
-+ unsigned long expire; /* expiration time (jiffies) */
-+};
-+
-+static inline void mipv6_ha_ac_add(struct in6_addr *ll_addr, int ifindex,
-+ struct in6_addr *glob_addr, int plen)
-+{
-+ struct net_device *dev;
-+
-+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) {
-+ struct in6_addr addr;
-+ mipv6_ha_anycast(&addr, glob_addr, plen);
-+ ipv6_dev_ac_inc(dev, &addr);
-+ }
-+}
-+
-+static inline void mipv6_ha_ac_del(struct in6_addr *ll_addr, int ifindex,
-+ struct in6_addr *glob_addr, int plen)
-+{
-+ struct net_device *dev;
-+
-+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) {
-+ struct in6_addr addr;
-+ mipv6_ha_anycast(&addr, glob_addr, plen);
-+ ipv6_dev_ac_dec(dev, &addr);
-+ }
-+}
-+
-+struct preflist_iterator_args {
-+ int count;
-+ int requested;
-+ int ifindex;
-+ struct in6_addr *list;
-+};
-+
-+static int preflist_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct preflist_iterator_args *state =
-+ (struct preflist_iterator_args *)args;
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ struct in6_addr *newaddr =
-+ (struct in6_addr *)state->list + state->count;
-+
-+ if (state->count >= state->requested)
-+ return ITERATOR_STOP;
-+
-+ if (time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ DEBUG(DBG_INFO, "preflist_iterator: Deleting entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr));
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ if (state->ifindex != entry->ifindex)
-+ return ITERATOR_CONT;
-+
-+ ipv6_addr_copy(newaddr, &entry->global_addr);
-+ DEBUG(DBG_INFO, "preflist_iterator: adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr));
-+ state->count++;
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int gc_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+
-+ int *type = (int *)args;
-+
-+ if (*type == 1 || time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int mipv6_halist_gc(int type)
-+{
-+ DEBUG_FUNC();
-+ hashlist_iterate(home_agents.entries, &type, gc_iterator);
-+ return 0;
-+}
-+
-+static void mipv6_halist_expire(unsigned long dummy)
-+{
-+ DEBUG_FUNC();
-+
-+ write_lock(&home_agents_lock);
-+ mipv6_halist_gc(0);
-+ write_unlock(&home_agents_lock);
-+}
-+
-+
-+static struct mipv6_halist_entry *mipv6_halist_new_entry(void)
-+{
-+ struct mipv6_halist_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ entry = hashlist_alloc(home_agents.entries, SLAB_ATOMIC);
-+
-+ return entry;
-+}
-+
-+
-+
-+/**
-+ * mipv6_halist_add - Add new home agent to the Home Agents List
-+ * @ifindex: interface identifier
-+ * @glob_addr: home agent's global address
-+ * @ll_addr: home agent's link-local address
-+ * @pref: relative preference for this home agent
-+ * @lifetime: lifetime for the entry
-+ *
-+ * Adds new home agent to the Home Agents List. The list is interface
-+ * specific and @ifindex tells through which interface the home agent
-+ * was heard. Returns zero on success and negative on failure.
-+ **/
-+
-+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen,
-+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime)
-+{
-+ int update = 0, ret = 0;
-+ unsigned int mpref;
-+ struct mipv6_halist_entry *entry = NULL;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&home_agents_lock);
-+
-+ if (glob_addr == NULL || lifetime <= 0) {
-+ DEBUG(DBG_WARNING, "invalid arguments");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ mpref = PREF_BASE - pref;
-+ if ((entry = (struct mipv6_halist_entry *)
-+ hashlist_get(home_agents.entries, glob_addr)) != NULL) {
-+ if (entry->ifindex == ifindex) {
-+ DEBUG(DBG_DATADUMP, "updating old entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr));
-+ update = 1;
-+ } else {
-+ DEBUG(DBG_INFO, "halist_add : adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr));
-+ update = 0;
-+ }
-+ }
-+ if (update) {
-+ entry->expire = jiffies + lifetime * HZ;
-+ if (entry->preference != mpref) {
-+ entry->preference = mpref;
-+ ret = hashlist_reposition(home_agents.entries,
-+ (void *)entry, mpref);
-+ }
-+ } else {
-+ entry = mipv6_halist_new_entry();
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "list full");
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ entry->ifindex = ifindex;
-+ if (ll_addr) {
-+ ipv6_addr_copy(&entry->link_local_addr, ll_addr);
-+ mipv6_ha_ac_add(ll_addr, ifindex, glob_addr, plen);
-+ } else
-+ ipv6_addr_set(&entry->link_local_addr, 0, 0, 0, 0);
-+
-+ ipv6_addr_copy(&entry->global_addr, glob_addr);
-+ entry->plen = plen;
-+ entry->preference = mpref;
-+ entry->expire = jiffies + lifetime * HZ;
-+ ret = hashlist_add(home_agents.entries, glob_addr, mpref,
-+ entry);
-+ }
-+out:
-+ write_unlock(&home_agents_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_halist_delete - delete home agent from Home Agents List
-+ * @glob_addr: home agent's global address
-+ *
-+ * Deletes entry for home agent @glob_addr from the Home Agent List.
-+ **/
-+int mipv6_halist_delete(struct in6_addr *glob_addr)
-+{
-+ struct hashlist_entry *e;
-+ struct mipv6_halist_entry *entry;
-+ DEBUG_FUNC();
-+
-+ if (glob_addr == NULL) {
-+ DEBUG(DBG_WARNING, "invalid glob addr");
-+ return -EINVAL;
-+ }
-+ write_lock(&home_agents_lock);
-+ if ((e = hashlist_get(home_agents.entries, glob_addr)) == NULL) {
-+ write_unlock(&home_agents_lock);
-+ return -ENOENT;
-+ }
-+ hashlist_delete(home_agents.entries, e);
-+ entry = (struct mipv6_halist_entry *)e;
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr, entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ hashlist_free(home_agents.entries, e);
-+ write_unlock(&home_agents_lock);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_ha_get_pref_list - Get list of preferred home agents
-+ * @ifindex: interface identifier
-+ * @addrs: pointer to a buffer to store the list
-+ * @max: maximum number of home agents to return
-+ *
-+ * Creates a list of @max preferred (or all known if less than @max)
-+ * home agents. Home Agents List is interface specific so you must
-+ * supply @ifindex. Stores list in addrs and returns number of home
-+ * agents stored. On failure, returns a negative value.
-+ **/
-+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max)
-+{
-+ struct preflist_iterator_args args;
-+
-+ DEBUG_FUNC();
-+ if (max <= 0) {
-+ *addrs = NULL;
-+ return 0;
-+ }
-+
-+ args.count = 0;
-+ args.requested = max;
-+ args.ifindex = ifindex;
-+ args.list = kmalloc(max * sizeof(struct in6_addr), GFP_ATOMIC);
-+
-+ if (args.list == NULL) return -ENOMEM;
-+
-+ read_lock(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, preflist_iterator);
-+ read_unlock(&home_agents_lock);
-+
-+ if (args.count >= 0) {
-+ *addrs = args.list;
-+ } else {
-+ kfree(args.list);
-+ *addrs = NULL;
-+ }
-+
-+ return args.count;
-+}
-+
-+struct getaddr_iterator_args {
-+ struct net_device *dev;
-+ struct in6_addr *addr;
-+};
-+
-+static int getaddr_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ struct getaddr_iterator_args *state =
-+ (struct getaddr_iterator_args *)args;
-+
-+ if (entry->ifindex != state->dev->ifindex)
-+ return ITERATOR_CONT;
-+
-+ if (ipv6_chk_addr(&entry->global_addr, state->dev)) {
-+ ipv6_addr_copy(state->addr, &entry->global_addr);
-+ return ITERATOR_STOP;
-+ }
-+ return ITERATOR_CONT;
-+}
-+
-+/*
-+ * Get Home Agent Address for given interface. If node is not serving
-+ * as a HA for this interface returns negative error value.
-+ */
-+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr)
-+{
-+ struct getaddr_iterator_args args;
-+ struct net_device *dev;
-+
-+ if (ifindex <= 0)
-+ return -EINVAL;
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL)
-+ return -ENODEV;
-+
-+ memset(addr, 0, sizeof(struct in6_addr));
-+ args.dev = dev;
-+ args.addr = addr;
-+ read_lock(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, getaddr_iterator);
-+ read_unlock(&home_agents_lock);
-+ dev_put(dev);
-+
-+ if (ipv6_addr_any(addr))
-+ return -ENOENT;
-+
-+ return 0;
-+}
-+
-+#define HALIST_INFO_LEN 81
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *)args;
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ unsigned long int expire;
-+
-+ DEBUG_FUNC();
-+
-+ if (entry == NULL) return ITERATOR_ERR;
-+
-+ if (time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ if (arg->skip < arg->offset / HALIST_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ expire = (entry->expire - jiffies) / HZ;
-+
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%02d %08x%08x%08x%08x %08x%08x%08x%08x %05ld %05ld\n",
-+ entry->ifindex,
-+ ntohl(entry->global_addr.s6_addr32[0]),
-+ ntohl(entry->global_addr.s6_addr32[1]),
-+ ntohl(entry->global_addr.s6_addr32[2]),
-+ ntohl(entry->global_addr.s6_addr32[3]),
-+ ntohl(entry->link_local_addr.s6_addr32[0]),
-+ ntohl(entry->link_local_addr.s6_addr32[1]),
-+ ntohl(entry->link_local_addr.s6_addr32[2]),
-+ ntohl(entry->link_local_addr.s6_addr32[3]),
-+ -(entry->preference - PREF_BASE), expire);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int halist_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&home_agents_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % HALIST_INFO_LEN;
-+
-+ args.len -= offset % HALIST_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+static int halist_compare(void *data, void *hashkey)
-+{
-+ struct mipv6_halist_entry *e = (struct mipv6_halist_entry *)data;
-+ struct in6_addr *key = (struct in6_addr *)hashkey;
-+
-+ return ipv6_addr_cmp(&e->global_addr, key);
-+}
-+
-+static __u32 halist_hash(void *hashkey)
-+{
-+ struct in6_addr *key = (struct in6_addr *)hashkey;
-+ __u32 hash;
-+
-+ hash = key->s6_addr32[0] ^
-+ key->s6_addr32[1] ^
-+ key->s6_addr32[2] ^
-+ key->s6_addr32[3];
-+
-+ return hash;
-+}
-+
-+int __init mipv6_halist_init(__u32 size)
-+{
-+ DEBUG_FUNC();
-+
-+ if (size <= 0) {
-+ DEBUG(DBG_ERROR, "size must be at least 1");
-+ return -EINVAL;
-+ }
-+ init_timer(&home_agents.expire_timer);
-+ home_agents.expire_timer.data = 0;
-+ home_agents.expire_timer.function = mipv6_halist_expire;
-+ home_agents_lock = RW_LOCK_UNLOCKED;
-+
-+ home_agents.entries = hashlist_create(16, size, sizeof(struct mipv6_halist_entry),
-+ "mip6_halist", NULL, NULL,
-+ halist_compare, halist_hash);
-+
-+ if (home_agents.entries == NULL) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hashlist");
-+ return -ENOMEM;
-+ }
-+
-+ proc_net_create("mip6_home_agents", 0, halist_proc_info);
-+ DEBUG(DBG_INFO, "Home Agents List initialized");
-+ return 0;
-+}
-+
-+void __exit mipv6_halist_exit(void)
-+{
-+ DEBUG_FUNC();
-+ proc_net_remove("mip6_home_agents");
-+ write_lock_bh(&home_agents_lock);
-+ DEBUG(DBG_INFO, "Stopping the halist timer");
-+ del_timer(&home_agents.expire_timer);
-+ mipv6_halist_gc(1);
-+ write_unlock_bh(&home_agents_lock);
-+ hashlist_destroy(home_agents.entries);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/halist.h linux-2.4.25/net/ipv6/mobile_ip6/halist.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/halist.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/halist.h 2004-06-26 11:29:30.000000000 +0100
-@@ -0,0 +1,28 @@
-+/*
-+ * MIPL Mobile IPv6 Home Agents List header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HALIST_H
-+#define _HALIST_H
-+
-+int mipv6_halist_init(__u32 size);
-+
-+void mipv6_halist_exit(void);
-+
-+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen,
-+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime);
-+
-+int mipv6_halist_delete(struct in6_addr *glob_addr);
-+
-+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max);
-+
-+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr);
-+
-+#endif /* _HALIST_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.c linux-2.4.25/net/ipv6/mobile_ip6/hashlist.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/hashlist.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,351 @@
-+/*
-+ * Generic hashtable with chaining. Supports secodary sort order
-+ * with doubly linked-list.
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id: s.hashlist.c 1.21 02/10/07 19:31:52+03:00 antti@traci.mipl.mediapoli.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.
-+ */
-+
-+#include <linux/slab.h>
-+#include "hashlist.h"
-+#include "debug.h"
-+
-+struct hashlist {
-+ int count; /* entry count */
-+ int maxcount; /* max entries */
-+ __u32 bucketnum; /* hash buckets */
-+
-+ kmem_cache_t *kmem;
-+
-+ struct list_head *hashtable;
-+ struct list_head sortedlist;
-+
-+ int (*compare)(void *data, void *hashkey);
-+ __u32 (*hash_function)(void *hashkey);
-+};
-+
-+/**
-+ * hashlist_create - Create new hashlist
-+ * @bucketnum: number of hash buckets
-+ * @maxentries: maximum number of entries (0 = no limit)
-+ * @size: entry size in bytes
-+ * @name: name for kmem_cache_t
-+ * @ctor: kmem_cache_t constructor
-+ * @dtor: kmem_cache_t destructor
-+ * @compare: compare function for key
-+ * @hash_function: hash function
-+ *
-+ * Creates a hashlist structure with @max_entries entries of @size
-+ * bytes. User must supply @hash_function and @compare function for
-+ * the hashlist. User can also supply @ctor and @dtor for kmem_cache.
-+ **/
-+struct hashlist *hashlist_create(int bucketnum, int max_entries, size_t size,
-+ char *name,
-+ void (*ctor)(void *, kmem_cache_t *, unsigned long),
-+ void (*dtor)(void *, kmem_cache_t *, unsigned long),
-+ int (*compare)(void *data, void *hashkey),
-+ __u32 (*hash_function)(void *hashkey))
-+{
-+ int i;
-+ struct hashlist *hl;
-+
-+ if (!compare || !hash_function)
-+ goto hlfailed;
-+
-+ hl = kmalloc(sizeof(struct hashlist), GFP_ATOMIC);
-+ if (!hl) goto hlfailed;
-+
-+ hl->kmem = kmem_cache_create(name, size, 0, 0, ctor, dtor);
-+ if (!hl->kmem) goto poolfailed;
-+
-+ hl->hashtable = kmalloc(
-+ sizeof(struct list_head) * bucketnum, GFP_ATOMIC);
-+ if (!hl->hashtable) goto hashfailed;
-+
-+ for (i = 0; i < bucketnum; i++)
-+ INIT_LIST_HEAD(&hl->hashtable[i]);
-+
-+ INIT_LIST_HEAD(&hl->sortedlist);
-+
-+ hl->maxcount = max_entries;
-+ hl->count = 0;
-+ hl->bucketnum = bucketnum;
-+ hl->compare = compare;
-+ hl->hash_function = hash_function;
-+
-+ return hl;
-+
-+hashfailed:
-+ kmem_cache_destroy(hl->kmem);
-+ hl->kmem = NULL;
-+
-+poolfailed:
-+ kfree(hl);
-+
-+hlfailed:
-+ DEBUG(DBG_ERROR, "could not create hashlist");
-+
-+ return NULL;
-+}
-+
-+/**
-+ * hashlist_destroy - Destroy hashlist
-+ * @hashlist: hashlist to destroy
-+ *
-+ * Frees all memory allocated for a hashlist.
-+ **/
-+void hashlist_destroy(struct hashlist *hashlist)
-+{
-+ DEBUG_FUNC();
-+
-+ if (hashlist == NULL) return;
-+
-+ if (hashlist->hashtable) {
-+ kfree(hashlist->hashtable);
-+ hashlist->hashtable = NULL;
-+ }
-+
-+ if (hashlist->kmem) {
-+ kmem_cache_destroy(hashlist->kmem);
-+ hashlist->kmem = NULL;
-+ }
-+
-+ kfree(hashlist);
-+
-+ return;
-+}
-+
-+/*
-+ * Insert a chain of entries to hashlist into correct order. The
-+ * entries are assumed to have valid hashkeys. We use time_after_eq
-+ * for comparing, since it handles wrap-around correctly, and the
-+ * sortkey is usually jiffies.
-+ */
-+static void sorted_insert(struct list_head *lh, struct hashlist_entry *he)
-+{
-+ struct list_head *p;
-+ struct hashlist_entry *hlp = NULL;
-+ unsigned long sortkey = he->sortkey;
-+
-+ if (list_empty(lh)) {
-+ list_add(&he->sorted, lh);
-+ return;
-+ }
-+
-+ list_for_each(p, lh) {
-+ hlp = list_entry(p, typeof(*hlp), sorted);
-+ if (time_after_eq(hlp->sortkey, sortkey)) {
-+ list_add(&he->sorted, hlp->sorted.prev);
-+ return;
-+ }
-+ }
-+ list_add(&he->sorted, &hlp->sorted);
-+}
-+
-+/**
-+ * hashlist_iterate - Apply function for all elements in a hash list
-+ * @hashlist: pointer to hashlist
-+ * @args: data to pass to the function
-+ * @func: pointer to a function
-+ *
-+ * Apply arbitrary function @func to all elements in a hash list.
-+ * @func must be a pointer to a function with the following prototype:
-+ * int func(void *entry, void *arg, struct in6_addr *hashkey, unsigned
-+ * long *sortkey). Function must return %ITERATOR_STOP,
-+ * %ITERATOR_CONT or %ITERATOR_DELETE_ENTRY. %ITERATOR_STOP stops
-+ * iterator and returns last return value from the function.
-+ * %ITERATOR_CONT continues with iteration. %ITERATOR_DELETE_ENTRY
-+ * deletes current entry from the hashlist. If function changes
-+ * hashlist element's sortkey, iterator automatically schedules
-+ * element to be reinserted after all elements have been processed.
-+ */
-+int hashlist_iterate(
-+ struct hashlist *hashlist, void *args,
-+ hashlist_iterator_t func)
-+{
-+ int res = ITERATOR_CONT;
-+ unsigned long skey;
-+ struct list_head *p, *n, repos;
-+ struct hashlist_entry *he;
-+
-+ DEBUG_FUNC();
-+ INIT_LIST_HEAD(&repos);
-+
-+ list_for_each_safe(p, n, &hashlist->sortedlist) {
-+ he = list_entry(p, typeof(*he), sorted);
-+ if (res == ITERATOR_STOP)
-+ break;
-+ skey = he->sortkey;
-+ res = func(he, args, &he->sortkey);
-+ if (res == ITERATOR_DELETE_ENTRY) {
-+ hashlist_delete(hashlist, he);
-+ hashlist_free(hashlist, he);
-+ } else if (skey != he->sortkey) {
-+ /* iterator changed the sortkey, schedule for
-+ * repositioning */
-+ list_move(&he->sorted, &repos);
-+ }
-+ }
-+ list_for_each_safe(p, n, &repos) {
-+ he = list_entry(p, typeof(*he), sorted);
-+ sorted_insert(&hashlist->sortedlist, he);
-+ }
-+ return res;
-+}
-+
-+/**
-+ * hashlist_alloc - Allocate memory for a hashlist entry
-+ * @hashlist: hashlist for allocated entry
-+ * @size: size of entry in bytes
-+ *
-+ * Allocates @size bytes memory from @hashlist->kmem.
-+ **/
-+void *hashlist_alloc(struct hashlist *hashlist, int type)
-+{
-+ if (hashlist == NULL) return NULL;
-+ return kmem_cache_alloc(hashlist->kmem, type);
-+}
-+
-+/**
-+ * hashlist_free - Free hashlist entry
-+ * @hashlist: hashlist where @he is
-+ * @he: entry to free
-+ *
-+ * Frees an allocated hashlist entry.
-+ **/
-+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he)
-+{
-+ kmem_cache_free(hashlist->kmem, he);
-+}
-+
-+/**
-+ * hashlist_add - Add element to hashlist
-+ * @hashlist: pointer to hashlist
-+ * @hashkey: hashkey for the element
-+ * @sortkey: key for sorting
-+ * @data: element data
-+ *
-+ * Add element to hashlist. Hashlist is also sorted in a linked list
-+ * by @sortkey.
-+ */
-+int hashlist_add(struct hashlist *hashlist, void *hashkey,
-+ unsigned long sortkey, void *entry)
-+{
-+ struct hashlist_entry *he = (struct hashlist_entry *)entry;
-+ unsigned int hash;
-+
-+ if (hashlist->count >= hashlist->maxcount)
-+ return -1;
-+
-+ hashlist->count++;
-+
-+ /* link the entry to sorted order */
-+ he->sortkey = sortkey;
-+ sorted_insert(&hashlist->sortedlist, he);
-+
-+ /* hash the entry */
-+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum;
-+ list_add(&he->hashlist, &hashlist->hashtable[hash]);
-+
-+ return 0;
-+}
-+
-+/**
-+ * hashlist_get_ex - Get element from hashlist
-+ * @hashlist: hashlist
-+ * @hashkey: hashkey of the desired entry
-+ *
-+ * Lookup entry with @hashkey from the hash table using @compare
-+ * function for entry comparison. Returns entry on success, otherwise
-+ * %NULL.
-+ **/
-+struct hashlist_entry *hashlist_get_ex(
-+ struct hashlist *hashlist, void *hashkey,
-+ int (*compare)(void *data, void *hashkey))
-+{
-+ struct list_head *p, *bkt;
-+ __u32 hash;
-+
-+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum;
-+ bkt = &hashlist->hashtable[hash];
-+
-+ /* scan the entries within the same hashbucket */
-+ list_for_each(p, bkt) {
-+ struct hashlist_entry *he = list_entry(p, typeof(*he),
-+ hashlist);
-+ if (compare(he, hashkey) == 0)
-+ return he;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * hashlist_get - Get element from hashlist
-+ * @hashlist: hashlist
-+ * @hashkey: hashkey of the desired entry
-+ *
-+ * Lookup entry with @hashkey from the hash table. Returns entry on
-+ * success, otherwise %NULL.
-+ **/
-+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey)
-+{
-+ return hashlist_get_ex(hashlist, hashkey, hashlist->compare);
-+}
-+
-+/**
-+ * hashlist_reposition - set entry to new position in the list
-+ * @hashlist: hashlist
-+ * @he: entry to reposition
-+ * @sortkey: new sortkey of the entry
-+ *
-+ * If secondary order sortkey changes, entry must be repositioned in
-+ * the sorted list.
-+ **/
-+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he,
-+ unsigned long sortkey)
-+{
-+ list_del(&he->sorted);
-+ he->sortkey = sortkey;
-+ sorted_insert(&hashlist->sortedlist, he);
-+
-+ return 0;
-+}
-+
-+/**
-+ * hashlist_delete - Delete entry from hashlist
-+ * @hashlist: hashlist where entry is
-+ * @he: entry to delete
-+ *
-+ * Deletes an entry from the hashlist and sorted list.
-+ **/
-+void hashlist_delete(struct hashlist *hashlist,
-+ struct hashlist_entry *he)
-+{
-+ list_del_init(&he->hashlist);
-+ list_del_init(&he->sorted);
-+
-+ hashlist->count--;
-+}
-+
-+/**
-+ * hashlist_get_first - Get first item from sorted list
-+ * @hashlist: pointer to hashlist
-+ *
-+ * Returns first item in the secondary sort order.
-+ **/
-+void * hashlist_get_first(struct hashlist *hashlist)
-+{
-+ if (list_empty(&hashlist->sortedlist))
-+ return NULL;
-+
-+ return list_entry(hashlist->sortedlist.next, struct hashlist_entry, sorted);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.h linux-2.4.25/net/ipv6/mobile_ip6/hashlist.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/hashlist.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/hashlist.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,63 @@
-+/*
-+ * MIPL Mobile IPv6 Hashlist header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HASHLIST_H
-+#define _HASHLIST_H
-+
-+#define ITERATOR_ERR -1
-+#define ITERATOR_CONT 0
-+#define ITERATOR_STOP 1
-+#define ITERATOR_DELETE_ENTRY 2
-+
-+struct kmem_cache_t;
-+
-+struct hashlist_entry {
-+ unsigned long sortkey;
-+ struct list_head sorted;
-+ struct list_head hashlist;
-+};
-+
-+struct hashlist * hashlist_create(
-+ int bucketnum, int max_entries, size_t size, char *name,
-+ void (*ctor)(void *, kmem_cache_t *, unsigned long),
-+ void (*dtor)(void *, kmem_cache_t *, unsigned long),
-+ int (*compare)(void *data, void *hashkey),
-+ __u32 (*hash_function)(void *hashkey));
-+
-+void hashlist_destroy(struct hashlist *hashlist);
-+
-+void *hashlist_alloc(struct hashlist *hashlist, int type);
-+
-+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he);
-+
-+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey);
-+
-+struct hashlist_entry *hashlist_get_ex(
-+ struct hashlist *hashlist, void *hashkey,
-+ int (*compare)(void *data, void *hashkey));
-+
-+int hashlist_add(struct hashlist *hashlist, void *hashkey,
-+ unsigned long sortkey, void *data);
-+
-+void hashlist_delete(struct hashlist *hashlist, struct hashlist_entry *he);
-+
-+/* iterator function */
-+typedef int (*hashlist_iterator_t)(void *, void *, unsigned long *);
-+
-+int hashlist_iterate(struct hashlist *hashlist, void *args,
-+ hashlist_iterator_t func);
-+
-+void * hashlist_get_first(struct hashlist *hashlist);
-+
-+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he,
-+ unsigned long sortkey);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.c linux-2.4.25/net/ipv6/mobile_ip6/hmac.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/hmac.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,658 @@
-+/* Authentication algorithms
-+ *
-+ * Authors:
-+ * Alexis Olivereau <Alexis.Olivereau@crm.mot.com>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes:
-+ * Henrik Petander : Cleaned up unused parts
-+ *
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/tty.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/in6.h>
-+
-+#include "hmac.h"
-+#define LROLL(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
-+
-+/* MD5 */
-+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
-+#define H(x, y, z) ((x) ^ (y) ^ (z))
-+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-+
-+#define FF(a, b, c, d, m, s, t) { \
-+ (a) += F ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define GG(a, b, c, d, m, s, t) { \
-+ (a) += G ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define HH(a, b, c, d, m, s, t) { \
-+ (a) += H ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define II(a, b, c, d, m, s, t) { \
-+ (a) += I ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+
-+#define s11 7
-+#define s12 12
-+#define s13 17
-+#define s14 22
-+#define s21 5
-+#define s22 9
-+#define s23 14
-+#define s24 20
-+#define s31 4
-+#define s32 11
-+#define s33 16
-+#define s34 23
-+#define s41 6
-+#define s42 10
-+#define s43 15
-+#define s44 21
-+
-+/* SHA-1 */
-+#define f(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define g(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-+#define h(x, y, z) ((x) ^ (y) ^ (z))
-+
-+#define K1 0x5a827999
-+#define K2 0x6ed9eba1
-+#define K3 0x8f1bbcdc
-+#define K4 0xca62c1d6
-+
-+int ah_hmac_md5_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len)
-+{
-+ int i;
-+ int key_up4;
-+ uint32_t ipad = 0x36363636;
-+ uint8_t extkey[64];
-+
-+ ahp->key_auth = key;
-+ ahp->key_auth_len = key_len;
-+ ahp->context = (void *) kmalloc(sizeof(MD5_CTX), GFP_ATOMIC);
-+ if (ahp->context == NULL)
-+ return -1;
-+ md5_init((MD5_CTX *) ahp->context);
-+ if ((64 * sizeof(uint8_t)) < ahp->key_auth_len) {
-+ printk("buffer overflow!");
-+ return -1;
-+ }
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = ipad;
-+
-+ md5_compute((MD5_CTX *) ahp->context, extkey, 64);
-+ return 0;
-+}
-+
-+void ah_hmac_md5_loop(struct ah_processing *ahp, void *str, uint32_t len)
-+{
-+ md5_compute((MD5_CTX *) ahp->context, str, len);
-+}
-+
-+void ah_hmac_md5_result(struct ah_processing *ahp, char *digest)
-+{
-+ uint8_t inner[HMAC_MD5_HASH_LEN];
-+ int i;
-+ int key_up4;
-+ uint32_t opad = 0x5c5c5c5c;
-+ uint8_t extkey[64];
-+
-+ md5_final((MD5_CTX *) ahp->context, inner);
-+ md5_init((MD5_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = opad;
-+
-+ md5_compute((MD5_CTX *) ahp->context, extkey, 64);
-+ md5_compute((MD5_CTX *) ahp->context, inner, HMAC_MD5_HASH_LEN);
-+
-+ md5_final((MD5_CTX *) ahp->context, digest);
-+
-+ kfree(ahp->context);
-+}
-+
-+int ah_hmac_sha1_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len)
-+{
-+ int i;
-+ int key_up4;
-+ uint32_t ipad = 0x36363636;
-+ uint8_t extkey[64];
-+
-+ ahp->key_auth = key;
-+ ahp->key_auth_len = key_len;
-+
-+ ahp->context = (void *) kmalloc(sizeof(SHA1_CTX), GFP_ATOMIC);
-+ //if (ahp->context == NULL)
-+ // return -1;
-+
-+ sha1_init((SHA1_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = ipad;
-+
-+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64);
-+ return 0;
-+}
-+
-+void ah_hmac_sha1_loop(struct ah_processing *ahp, void *str, uint32_t len)
-+{
-+ if (!ahp)
-+ return;
-+ sha1_compute((SHA1_CTX *) ahp->context, str, len);
-+}
-+
-+void ah_hmac_sha1_result(struct ah_processing *ahp, char *digest)
-+{
-+ uint8_t inner[HMAC_SHA1_HASH_LEN];
-+ int i;
-+ int key_up4;
-+ uint32_t opad = 0x5c5c5c5c;
-+ uint8_t extkey[64];
-+
-+ if (!ahp)
-+ return;
-+ sha1_final((SHA1_CTX *) ahp->context, inner);
-+ sha1_init((SHA1_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = opad;
-+
-+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64);
-+ sha1_compute((SHA1_CTX *) ahp->context, inner,
-+ HMAC_SHA1_HASH_LEN);
-+
-+ sha1_final((SHA1_CTX *) ahp->context, digest);
-+
-+ kfree(ahp->context);
-+}
-+
-+void md5_init(MD5_CTX * ctx)
-+{
-+ ctx->A = 0x67452301;
-+ ctx->B = 0xefcdab89;
-+ ctx->C = 0x98badcfe;
-+ ctx->D = 0x10325476;
-+ ctx->buf_cur = ctx->buf;
-+ ctx->bitlen[0] = ctx->bitlen[1] = 0;
-+ memset(ctx->buf, 0, 64);
-+}
-+
-+void md5_over_block(MD5_CTX * ctx, uint8_t * data)
-+{
-+ uint32_t M[16];
-+ uint32_t a = ctx->A;
-+ uint32_t b = ctx->B;
-+ uint32_t c = ctx->C;
-+ uint32_t d = ctx->D;
-+
-+ create_M_blocks(M, data);
-+
-+ /* Round 1 */
-+ FF(a, b, c, d, M[0], s11, 0xd76aa478); /* 1 */
-+ FF(d, a, b, c, M[1], s12, 0xe8c7b756); /* 2 */
-+ FF(c, d, a, b, M[2], s13, 0x242070db); /* 3 */
-+ FF(b, c, d, a, M[3], s14, 0xc1bdceee); /* 4 */
-+ FF(a, b, c, d, M[4], s11, 0xf57c0faf); /* 5 */
-+ FF(d, a, b, c, M[5], s12, 0x4787c62a); /* 6 */
-+ FF(c, d, a, b, M[6], s13, 0xa8304613); /* 7 */
-+ FF(b, c, d, a, M[7], s14, 0xfd469501); /* 8 */
-+ FF(a, b, c, d, M[8], s11, 0x698098d8); /* 9 */
-+ FF(d, a, b, c, M[9], s12, 0x8b44f7af); /* 10 */
-+ FF(c, d, a, b, M[10], s13, 0xffff5bb1); /* 11 */
-+ FF(b, c, d, a, M[11], s14, 0x895cd7be); /* 12 */
-+ FF(a, b, c, d, M[12], s11, 0x6b901122); /* 13 */
-+ FF(d, a, b, c, M[13], s12, 0xfd987193); /* 14 */
-+ FF(c, d, a, b, M[14], s13, 0xa679438e); /* 15 */
-+ FF(b, c, d, a, M[15], s14, 0x49b40821); /* 16 */
-+
-+ /* Round 2 */
-+ GG(a, b, c, d, M[1], s21, 0xf61e2562); /* 17 */
-+ GG(d, a, b, c, M[6], s22, 0xc040b340); /* 18 */
-+ GG(c, d, a, b, M[11], s23, 0x265e5a51); /* 19 */
-+ GG(b, c, d, a, M[0], s24, 0xe9b6c7aa); /* 20 */
-+ GG(a, b, c, d, M[5], s21, 0xd62f105d); /* 21 */
-+ GG(d, a, b, c, M[10], s22, 0x02441453); /* 22 */
-+ GG(c, d, a, b, M[15], s23, 0xd8a1e681); /* 23 */
-+ GG(b, c, d, a, M[4], s24, 0xe7d3fbc8); /* 24 */
-+ GG(a, b, c, d, M[9], s21, 0x21e1cde6); /* 25 */
-+ GG(d, a, b, c, M[14], s22, 0xc33707d6); /* 26 */
-+ GG(c, d, a, b, M[3], s23, 0xf4d50d87); /* 27 */
-+ GG(b, c, d, a, M[8], s24, 0x455a14ed); /* 28 */
-+ GG(a, b, c, d, M[13], s21, 0xa9e3e905); /* 29 */
-+ GG(d, a, b, c, M[2], s22, 0xfcefa3f8); /* 30 */
-+ GG(c, d, a, b, M[7], s23, 0x676f02d9); /* 31 */
-+ GG(b, c, d, a, M[12], s24, 0x8d2a4c8a); /* 32 */
-+
-+ /* Round 3 */
-+ HH(a, b, c, d, M[5], s31, 0xfffa3942); /* 33 */
-+ HH(d, a, b, c, M[8], s32, 0x8771f681); /* 34 */
-+ HH(c, d, a, b, M[11], s33, 0x6d9d6122); /* 35 */
-+ HH(b, c, d, a, M[14], s34, 0xfde5380c); /* 36 */
-+ HH(a, b, c, d, M[1], s31, 0xa4beea44); /* 37 */
-+ HH(d, a, b, c, M[4], s32, 0x4bdecfa9); /* 38 */
-+ HH(c, d, a, b, M[7], s33, 0xf6bb4b60); /* 39 */
-+ HH(b, c, d, a, M[10], s34, 0xbebfbc70); /* 40 */
-+ HH(a, b, c, d, M[13], s31, 0x289b7ec6); /* 41 */
-+ HH(d, a, b, c, M[0], s32, 0xeaa127fa); /* 42 */
-+ HH(c, d, a, b, M[3], s33, 0xd4ef3085); /* 43 */
-+ HH(b, c, d, a, M[6], s34, 0x4881d05); /* 44 */
-+ HH(a, b, c, d, M[9], s31, 0xd9d4d039); /* 45 */
-+ HH(d, a, b, c, M[12], s32, 0xe6db99e5); /* 46 */
-+ HH(c, d, a, b, M[15], s33, 0x1fa27cf8); /* 47 */
-+ HH(b, c, d, a, M[2], s34, 0xc4ac5665); /* 48 */
-+
-+ /* Round 4 */
-+ II(a, b, c, d, M[0], s41, 0xf4292244); /* 49 */
-+ II(d, a, b, c, M[7], s42, 0x432aff97); /* 50 */
-+ II(c, d, a, b, M[14], s43, 0xab9423a7); /* 51 */
-+ II(b, c, d, a, M[5], s44, 0xfc93a039); /* 52 */
-+ II(a, b, c, d, M[12], s41, 0x655b59c3); /* 53 */
-+ II(d, a, b, c, M[3], s42, 0x8f0ccc92); /* 54 */
-+ II(c, d, a, b, M[10], s43, 0xffeff47d); /* 55 */
-+ II(b, c, d, a, M[1], s44, 0x85845dd1); /* 56 */
-+ II(a, b, c, d, M[8], s41, 0x6fa87e4f); /* 57 */
-+ II(d, a, b, c, M[15], s42, 0xfe2ce6e0); /* 58 */
-+ II(c, d, a, b, M[6], s43, 0xa3014314); /* 59 */
-+ II(b, c, d, a, M[13], s44, 0x4e0811a1); /* 60 */
-+ II(a, b, c, d, M[4], s41, 0xf7537e82); /* 61 */
-+ II(d, a, b, c, M[11], s42, 0xbd3af235); /* 62 */
-+ II(c, d, a, b, M[2], s43, 0x2ad7d2bb); /* 63 */
-+ II(b, c, d, a, M[9], s44, 0xeb86d391); /* 64 */
-+
-+ ctx->A += a;
-+ ctx->B += b;
-+ ctx->C += c;
-+ ctx->D += d;
-+}
-+
-+void create_M_blocks(uint32_t * M, uint8_t * data)
-+{
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy((uint8_t *) M, data, 64);
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ int i;
-+ for (i = 0; i < 16; i++, data += 4) {
-+ ((uint8_t *) (&M[i]))[0] = data[3];
-+ ((uint8_t *) (&M[i]))[1] = data[2];
-+ ((uint8_t *) (&M[i]))[2] = data[1];
-+ ((uint8_t *) (&M[i]))[3] = data[0];
-+ }
-+#endif /* HAVE_BIG_ENDIAN */
-+}
-+
-+void md5_compute(MD5_CTX * ctx, uint8_t * data, uint32_t len)
-+{
-+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f);
-+
-+ /* First we update the bit length */
-+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3))
-+ ctx->bitlen[1]++;
-+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */
-+
-+ if (pos) {
-+ /* Buffer is not empty */
-+ if (64 - pos >= len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ pos += len;
-+ if (pos == 64) {
-+ /* The current block is over */
-+ md5_over_block(ctx, ctx->buf);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ return;
-+ } else {
-+ memcpy(ctx->buf_cur, data, 64 - pos);
-+ md5_over_block(ctx, ctx->buf);
-+ len -= (64 - pos);
-+ data += (64 - pos);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ }
-+ while (len >= 64) {
-+ md5_over_block(ctx, data);
-+ len -= 64;
-+ data += 64;
-+ }
-+ if (len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ }
-+}
-+
-+void md5_final(MD5_CTX * ctx, uint8_t * digest)
-+{
-+ uint32_t rem_size;
-+ uint8_t *buf_cur = ctx->buf_cur;
-+ int i;
-+
-+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f);
-+ *(buf_cur++) = 0x80;
-+
-+ if (rem_size > 8 + 1) {
-+ /* We have enough room in the current block */
-+ for (i = 0; i < rem_size - 8 - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ } else {
-+ /* We do not have enough room and need therefore to add a new
-+ 64-byte block */
-+ for (i = 0; i < rem_size - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ md5_over_block(ctx, ctx->buf);
-+
-+ buf_cur = ctx->buf;
-+ for (i = 0; i < 64 - 8; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ }
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8);
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff;
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+ md5_over_block(ctx, ctx->buf);
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t));
-+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t));
-+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t));
-+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t));
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ digest[0] = ((ctx->A) >> 24) & 0xff;
-+ digest[1] = ((ctx->A) >> 16) & 0xff;
-+ digest[2] = ((ctx->A) >> 8) & 0xff;
-+ digest[3] = ((ctx->A) >> 0) & 0xff;
-+ digest[4] = ((ctx->B) >> 24) & 0xff;
-+ digest[5] = ((ctx->B) >> 16) & 0xff;
-+ digest[6] = ((ctx->B) >> 8) & 0xff;
-+ digest[7] = ((ctx->B) >> 0) & 0xff;
-+ digest[8] = ((ctx->C) >> 24) & 0xff;
-+ digest[9] = ((ctx->C) >> 16) & 0xff;
-+ digest[10] = ((ctx->C) >> 8) & 0xff;
-+ digest[11] = ((ctx->C) >> 0) & 0xff;
-+ digest[12] = ((ctx->D) >> 24) & 0xff;
-+ digest[13] = ((ctx->D) >> 16) & 0xff;
-+ digest[14] = ((ctx->D) >> 8) & 0xff;
-+ digest[15] = ((ctx->D) >> 0) & 0xff;
-+#endif /* HAVE_BIG_ENDIAN */
-+}
-+
-+void sha1_init(SHA1_CTX * ctx)
-+{
-+ ctx->A = 0x67452301;
-+ ctx->B = 0xefcdab89;
-+ ctx->C = 0x98badcfe;
-+ ctx->D = 0x10325476;
-+ ctx->E = 0xc3d2e1f0;
-+ ctx->buf_cur = ctx->buf;
-+ ctx->bitlen[0] = ctx->bitlen[1] = 0;
-+ memset(ctx->buf, 0, 64);
-+}
-+
-+void sha1_over_block(SHA1_CTX * ctx, uint8_t * data)
-+{
-+ int i;
-+ uint32_t W[80];
-+ uint32_t a = ctx->A;
-+ uint32_t b = ctx->B;
-+ uint32_t c = ctx->C;
-+ uint32_t d = ctx->D;
-+ uint32_t e = ctx->E;
-+ uint32_t temp;
-+
-+ create_W_blocks(W, data);
-+
-+ /* Round 1 */
-+ for (i = 0; i < 20; i++) {
-+ temp = LROLL(a, 5) + f(b, c, d) + e + W[i] + K1;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 2 */
-+ for (i = 20; i < 40; i++) {
-+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K2;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 3 */
-+ for (i = 40; i < 60; i++) {
-+ temp = LROLL(a, 5) + g(b, c, d) + e + W[i] + K3;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 4 */
-+ for (i = 60; i < 80; i++) {
-+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K4;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ ctx->A += a;
-+ ctx->B += b;
-+ ctx->C += c;
-+ ctx->D += d;
-+ ctx->E += e;
-+}
-+
-+void create_W_blocks(uint32_t * W, uint8_t * data)
-+{
-+ int i;
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy((uint8_t *) W, data, 64);
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ for (i = 0; i < 16; i++, data += 4) {
-+ ((uint8_t *) (&W[i]))[0] = data[3];
-+ ((uint8_t *) (&W[i]))[1] = data[2];
-+ ((uint8_t *) (&W[i]))[2] = data[1];
-+ ((uint8_t *) (&W[i]))[3] = data[0];
-+ }
-+#endif /* HAVE_LITTLE_ENDIAN */
-+ for (i = 16; i < 80; i++) {
-+ W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
-+ W[i] = LROLL(W[i], 1);
-+ }
-+}
-+
-+void sha1_compute(SHA1_CTX * ctx, uint8_t * data, uint32_t len)
-+{
-+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f);
-+
-+ /* First we update the bit length */
-+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3))
-+ ctx->bitlen[1]++;
-+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */
-+
-+ if (pos) {
-+ /* Buffer is not empty */
-+ if (64 - pos >= len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ pos += len;
-+ if (pos == 64) {
-+ /* The current block is over */
-+ sha1_over_block(ctx, ctx->buf);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ return;
-+ } else {
-+ memcpy(ctx->buf_cur, data, 64 - pos);
-+ sha1_over_block(ctx, ctx->buf);
-+ len -= (64 - pos);
-+ data += (64 - pos);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ }
-+ while (len >= 64) {
-+ sha1_over_block(ctx, data);
-+ len -= 64;
-+ data += 64;
-+ }
-+ if (len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ }
-+}
-+
-+void sha1_final(SHA1_CTX * ctx, uint8_t * digest)
-+{
-+ uint32_t rem_size;
-+ uint8_t *buf_cur = ctx->buf_cur;
-+ int i;
-+
-+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f);
-+ *(buf_cur++) = 0x80;
-+
-+ if (rem_size > 8 + 1) {
-+ /* We have enough room in the current block */
-+ for (i = 0; i < rem_size - 8 - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ } else {
-+ /* We do not have enough room and need therefore to add a new
-+ 64-byte block */
-+ for (i = 0; i < rem_size - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ sha1_over_block(ctx, ctx->buf);
-+
-+ buf_cur = ctx->buf;
-+ for (i = 0; i < 64 - 8; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ }
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8);
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff;
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+ sha1_over_block(ctx, ctx->buf);
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t));
-+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t));
-+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t));
-+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t));
-+ memcpy(digest + 16, (uint8_t *) (&(ctx->E)), sizeof(uint32_t));
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ digest[0] = ((ctx->A) >> 24) & 0xff;
-+ digest[1] = ((ctx->A) >> 16) & 0xff;
-+ digest[2] = ((ctx->A) >> 8) & 0xff;
-+ digest[3] = ((ctx->A) >> 0) & 0xff;
-+ digest[4] = ((ctx->B) >> 24) & 0xff;
-+ digest[5] = ((ctx->B) >> 16) & 0xff;
-+ digest[6] = ((ctx->B) >> 8) & 0xff;
-+ digest[7] = ((ctx->B) >> 0) & 0xff;
-+ digest[8] = ((ctx->C) >> 24) & 0xff;
-+ digest[9] = ((ctx->C) >> 16) & 0xff;
-+ digest[10] = ((ctx->C) >> 8) & 0xff;
-+ digest[11] = ((ctx->C) >> 0) & 0xff;
-+ digest[12] = ((ctx->D) >> 24) & 0xff;
-+ digest[13] = ((ctx->D) >> 16) & 0xff;
-+ digest[14] = ((ctx->D) >> 8) & 0xff;
-+ digest[15] = ((ctx->D) >> 0) & 0xff;
-+ digest[16] = ((ctx->E) >> 24) & 0xff;
-+ digest[17] = ((ctx->E) >> 16) & 0xff;
-+ digest[18] = ((ctx->E) >> 8) & 0xff;
-+ digest[19] = ((ctx->E) >> 0) & 0xff;
-+#endif /* HAVE_LITTLE_ENDIAN */
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.h linux-2.4.25/net/ipv6/mobile_ip6/hmac.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/hmac.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/hmac.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,94 @@
-+/*
-+ * MIPL Mobile IPv6 Message authentication algorithms
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HMAC_H
-+#define _HMAC_H
-+
-+#include <linux/types.h>
-+#include <linux/in6.h>
-+
-+#define HAVE_LITTLE_ENDIAN
-+
-+#define NO_EXPIRY 1 /* For sec_as */
-+
-+#define ALG_AUTH_NONE 0
-+#define ALG_AUTH_HMAC_MD5 1
-+#define ALG_AUTH_HMAC_SHA1 2
-+
-+struct sec_as;
-+struct ah_processing {
-+ void *context;
-+ struct sec_as *sas;
-+ u_int8_t *key_auth;
-+ u_int32_t key_auth_len;
-+};
-+
-+struct antireplay {
-+ u_int32_t count;
-+ u_int32_t bitmap;
-+};
-+
-+typedef struct {
-+ u_int32_t A, B, C, D;
-+ u_int32_t bitlen[2];
-+ u_int8_t* buf_cur;
-+ u_int8_t buf[64];
-+} MD5_CTX;
-+
-+typedef struct {
-+ u_int32_t A, B, C, D, E;
-+ u_int32_t bitlen[2];
-+ u_int8_t* buf_cur;
-+ u_int8_t buf[64];
-+} SHA1_CTX;
-+
-+
-+
-+int ah_hmac_md5_init (struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len);
-+void ah_hmac_md5_loop(struct ah_processing*, void*, u_int32_t);
-+void ah_hmac_md5_result(struct ah_processing*, char*);
-+int ah_hmac_sha1_init(struct ah_processing*, u_int8_t *key, u_int32_t key_len);
-+void ah_hmac_sha1_loop(struct ah_processing*, void*, u_int32_t);
-+void ah_hmac_sha1_result(struct ah_processing*, char*);
-+
-+
-+#define AH_HDR_LEN 12 /* # of bytes for Next Header, Payload Length,
-+ RESERVED, Security Parameters Index and
-+
-+ Sequence Number Field */
-+
-+void md5_init(MD5_CTX *ctx);
-+void md5_over_block(MD5_CTX *ctx, u_int8_t* data);
-+void create_M_blocks(u_int32_t* M, u_int8_t* data);
-+void md5_compute(MD5_CTX *ctx, u_int8_t* data, u_int32_t len);
-+void md5_final(MD5_CTX *ctx, u_int8_t* digest);
-+
-+void sha1_init(SHA1_CTX *ctx);
-+void sha1_over_block(SHA1_CTX *ctx, u_int8_t* data);
-+void create_W_blocks(u_int32_t* W, u_int8_t* data);
-+void sha1_compute(SHA1_CTX *ctx, u_int8_t* data, u_int32_t len);
-+void sha1_final(SHA1_CTX *ctx, u_int8_t* digest);
-+
-+struct mipv6_acq {
-+ struct in6_addr coa;
-+ struct in6_addr haddr;
-+ struct in6_addr peer;
-+ u_int32_t spi;
-+};
-+#define MIPV6_MAX_AUTH_DATA 20
-+
-+#define HMAC_MD5_HASH_LEN 16
-+#define HMAC_SHA1_HASH_LEN 20
-+#define HMAC_SHA1_KEY_SIZE 20
-+#define HMAC_MD5_ICV_LEN 12 /* RFC 2403 */
-+#define HMAC_SHA1_ICV_LEN 12 /* RFC 2404 */
-+
-+#endif /* _HMAC_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ioctl_mn.c linux-2.4.25/net/ipv6/mobile_ip6/ioctl_mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/ioctl_mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/ioctl_mn.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,142 @@
-+/*
-+ * Mobile Node IOCTL Control device
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/fs.h>
-+#include <linux/poll.h>
-+#include <linux/ioctl.h>
-+#include <net/ipv6.h>
-+#include <asm/uaccess.h>
-+
-+#include "debug.h"
-+#include "mdetect.h"
-+#include "multiaccess_ctl.h"
-+
-+/* Reserved for local / experimental use */
-+#define MAJOR_NUM 0xf9
-+
-+/* Get Care-of address information for Mobile Node */
-+#define IOCTL_GET_CAREOFADDR _IOWR(MAJOR_NUM, 9, void *)
-+
-+#define MA_IOCTL_SET_IFACE_PREFERENCE _IOR (MAJOR_NUM, 13, void *)
-+
-+/* The name of the device file */
-+#define CTLFILE "mipv6_dev"
-+
-+static int inuse = 0;
-+
-+static int mipv6_open(struct inode *inode, struct file *file)
-+{
-+ DEBUG(DBG_INFO, "(%p)\n", file);
-+
-+ if (inuse)
-+ return -EBUSY;
-+
-+ inuse++;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+static int mipv6_close(struct inode *inode, struct file *file)
-+{
-+ DEBUG(DBG_INFO, "(%p,%p)\n", inode, file);
-+ inuse--;
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+int mipv6_ioctl(struct inode *inode, struct file *file,
-+ unsigned int ioctl_num, /* The number of the ioctl */
-+ unsigned long arg) /* The parameter to it */
-+{
-+ struct in6_addr careofaddr;
-+
-+ /* Switch according to the ioctl called */
-+ switch (ioctl_num) {
-+ case IOCTL_GET_CAREOFADDR:
-+ DEBUG(DBG_DATADUMP, "IOCTL_GET_CAREOFADDR");
-+ /* First get home address from user and then look up
-+ * the care-of address and return it
-+ */
-+ if (copy_from_user(&careofaddr, (struct in6_addr *)arg,
-+ sizeof(struct in6_addr)) < 0) {
-+ DEBUG(DBG_WARNING, "Copy from user failed");
-+ return -EFAULT;
-+ }
-+ mipv6_get_care_of_address(&careofaddr, &careofaddr);
-+ if (copy_to_user((struct in6_addr *)arg, &careofaddr,
-+ sizeof(struct in6_addr)) < 0) {
-+ DEBUG(DBG_WARNING, "copy_to_user failed");
-+ return -EFAULT;
-+ }
-+ break;
-+ case MA_IOCTL_SET_IFACE_PREFERENCE:
-+ DEBUG(DBG_INFO, "MA_IOCTL_SET_IFACE_PREFERENCE");
-+ ma_ctl_set_preference(arg);
-+ break;
-+
-+ default:
-+ DEBUG(DBG_WARNING, "Unknown ioctl cmd (%d)", ioctl_num);
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+
-+struct file_operations Fops = {
-+ owner: THIS_MODULE,
-+ read: NULL,
-+ write: NULL,
-+ poll: NULL,
-+ ioctl: mipv6_ioctl,
-+ open: mipv6_open,
-+ release: mipv6_close
-+};
-+
-+
-+/* Initialize the module - Register the character device */
-+int mipv6_ioctl_mn_init(void)
-+{
-+ int ret_val;
-+
-+ /* Register the character device (atleast try) */
-+ ret_val = register_chrdev(MAJOR_NUM, CTLFILE, &Fops);
-+
-+ /* Negative values signify an error */
-+ if (ret_val < 0) {
-+ DEBUG(DBG_ERROR, "failed registering char device (err=%d)",
-+ ret_val);
-+ return ret_val;
-+ }
-+
-+ DEBUG(DBG_INFO, "Device number %x, success", MAJOR_NUM);
-+ return 0;
-+}
-+
-+
-+/* Cleanup - unregister the appropriate file from /proc */
-+void mipv6_ioctl_mn_exit(void)
-+{
-+ int ret;
-+ /* Unregister the device */
-+ ret = unregister_chrdev(MAJOR_NUM, CTLFILE);
-+
-+ /* If there's an error, report it */
-+ if (ret < 0)
-+ DEBUG(DBG_ERROR, "errorcode: %d\n", ret);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.c linux-2.4.25/net/ipv6/mobile_ip6/mdetect.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mdetect.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,1153 @@
-+/*
-+ * Movement Detection Module
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Handles the L3 movement detection of mobile node and also
-+ * changing of its routes.
-+ *
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Locking fixes
-+ * Venkata Jagana : Locking fix
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/if_arp.h>
-+#include <linux/route.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipglue.h>
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include "util.h"
-+#include "mdetect.h"
-+#include "mn.h"
-+#include "debug.h"
-+#include "multiaccess_ctl.h"
-+
-+#define START 0
-+#define CONTINUE 1
-+#define OK 2
-+#define DEBUG_MDETECT 7
-+
-+#define DEF_RTR_POLL_IVAL 5 /* In seconds */
-+
-+#define NO_RTR 0
-+#define RTR_SUSPECT 1
-+#define CURR_RTR_OK 2
-+
-+#define RA_RCVD 0
-+#define NA_RCVD 1
-+#define TIMEOUT 2
-+
-+#define MIPV6_MDF_NONE 0x0
-+#define MIPV6_MDF_HAS_RTR_PREV 0x1
-+
-+#define ROUTER_REACHABLE 1
-+#define RADV_MISSED 2
-+#define NOT_REACHABLE 3
-+
-+/* R_TIME_OUT paramater is used to make the decision when to change the
-+ * default router, if the current one is unreachable. 2s is pretty aggressive
-+ * and may result in hopping between two routers. OTOH a small value enhances
-+ * the performance
-+ */
-+#define R_TIME_OUT 30*HZ
-+
-+/* maximum RA interval for router unreachability detection */
-+#define MAX_RADV_INTERVAL 6*HZ /* 6000 ms... */
-+
-+/* Threshold for exponential resending of router solicitations */
-+#define RS_RESEND_LINEAR 10*HZ
-+
-+#define EAGER_CELL_SWITCHING 1
-+#define LAZY_CELL_SWITCHING 0
-+#define RESPECT_DAD 1
-+
-+#define ROUTER_ADDRESS 0x20
-+
-+/* RA flags */
-+#define ND_RA_FLAG_MANAGED 0x80
-+#define ND_RA_FLAG_OTHER 0x40
-+#define ND_RA_FLAG_HA 0x20
-+
-+/* DAD flags for global and link local addresses */
-+
-+#define COA_TENTATIVE 0x10
-+#define LLADDR_TENTATIVE 0x01
-+
-+struct router {
-+ struct list_head list;
-+ struct in6_addr ll_addr;
-+ struct in6_addr raddr; /* Also contains prefix */
-+ __u8 link_addr[MAX_ADDR_LEN]; /* link layer address */
-+ __u8 link_addr_len;
-+ __u8 state;
-+ __u8 is_current;
-+ __u8 reachable;
-+ int ifindex;
-+ int pfix_len; /* Length of the network prefix */
-+ unsigned long lifetime; /* from ra */
-+ __u32 last_ns_sent;
-+ __u32 last_ra_rcvd;
-+ __u32 interval; /* ra interval in milliseconds, 0 if not set */
-+ int glob_addr; /*Whether raddr contains also routers global address*/
-+ __u8 flags; /* RA flags, for example ha */
-+ struct in6_addr CoA; /* care-off address used with this router */
-+ int extra_addr_route;
-+};
-+
-+/* dad could also be RESPECT_DAD for duplicate address detection of
-+ new care-of addresses */
-+static int dad = 0;
-+
-+/* Only one choice, nothing else implemented */
-+int max_rtr_reach_time = DEF_RTR_POLL_IVAL;
-+
-+
-+int eager_cell_switching = EAGER_CELL_SWITCHING; /* Can be set to 0 via proc */
-+static spinlock_t router_lock;
-+static spinlock_t ho_lock;
-+
-+static void coa_timer_handler(unsigned long arg);
-+static void timer_handler(unsigned long foo);
-+static struct router *curr_router = NULL, *next_router = NULL;
-+static struct timer_list r_timer = { function: timer_handler };
-+static struct timer_list coa_timer = { function: coa_timer_handler };
-+#define MAX_ROUTERS 1000
-+static LIST_HEAD(rtr_list);
-+static int num_routers = 0;
-+static struct handoff *_ho = NULL;
-+/*
-+ * Functions for handling the default router list, which movement
-+ * detection uses for avoiding loops etc.
-+ */
-+
-+/* TODO: Send NS to router after MAX interval has passed from last RA */
-+static int mipv6_router_state(struct router *rtr) {
-+ if (rtr->interval) {
-+ if (time_before(jiffies, (rtr->last_ra_rcvd + (rtr->interval * HZ) / 1000)))
-+ return ROUTER_REACHABLE;
-+ else
-+ return NOT_REACHABLE;
-+ }
-+ else
-+ if (time_after(jiffies, rtr->last_ra_rcvd + (rtr->lifetime * HZ)))
-+ return NOT_REACHABLE;
-+ return ROUTER_REACHABLE;
-+}
-+
-+/* searches for a specific router or any router that is reachable,
-+ * if address is NULL. Also deletes obsolete routers.
-+ */
-+static void mipv6_router_gc(void)
-+{
-+ struct router *curr = NULL;
-+ struct list_head *lh, *lh_tmp;
-+
-+ DEBUG_FUNC();
-+
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ curr = list_entry(lh, struct router, list);
-+ if (mipv6_router_state(curr) == NOT_REACHABLE && !curr->is_current) {
-+ num_routers--;
-+ list_del_init(&curr->list);
-+ DEBUG(DBG_DATADUMP, "Deleting unreachable router %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr->raddr));
-+ kfree(curr);
-+ }
-+ else {
-+ DEBUG(DBG_DATADUMP, "NOT Deleting router %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr->raddr));
-+ }
-+ }
-+}
-+
-+static struct router *mipv6_rtr_get(struct in6_addr *search_addr)
-+{
-+ struct router *rtr = NULL;
-+ struct list_head *lh;
-+
-+ DEBUG_FUNC();
-+
-+ if (search_addr == NULL)
-+ return NULL;
-+ list_for_each(lh, &rtr_list) {
-+ rtr = list_entry(lh, struct router, list);
-+ if(!ipv6_addr_cmp(search_addr, &rtr->raddr)) {
-+ return rtr;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * Adds router to list
-+ */
-+static struct router *mipv6_rtr_add(struct router *nrt)
-+{
-+
-+ struct router *rptr;
-+
-+ DEBUG_FUNC();
-+
-+ /* check if someone is trying DoS attack, or we just have some
-+ memory leaks... */
-+ if (num_routers > MAX_ROUTERS) {
-+ DEBUG(DBG_CRITICAL,
-+ "failed to add new router, MAX_ROUTERS exceeded");
-+ return NULL;
-+ }
-+
-+ rptr = kmalloc(sizeof(struct router), GFP_ATOMIC);
-+ if (rptr) {
-+ memcpy(rptr, nrt, sizeof(struct router));
-+ list_add(&rptr->list, &rtr_list);
-+ num_routers++;
-+ }
-+ DEBUG(DBG_INFO, "Adding router: %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "lifetime : %d sec, adv.interval: %d millisec",
-+ NIPV6ADDR(&rptr->raddr), rptr->lifetime, rptr->interval);
-+
-+ DEBUG(DBG_INFO, "num_routers after addition: %d", num_routers);
-+ return rptr;
-+}
-+
-+/* Cleans up the list */
-+static void list_free(struct router **curr_router_p)
-+{
-+ struct router *tmp;
-+ struct list_head *lh, *lh_tmp;
-+
-+ DEBUG_FUNC();
-+
-+ DEBUG(DBG_INFO, "Freeing the router list");
-+ /* set curr_router->prev_router and curr_router NULL */
-+ *curr_router_p = NULL;
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ tmp = list_entry(lh, struct router, list);
-+ DEBUG(DBG_INFO, "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&tmp->ll_addr));
-+ list_del(&tmp->list);
-+ kfree(tmp);
-+ num_routers--;
-+ }
-+}
-+
-+int rs_state = START;
-+
-+/* Sends router solicitations to all valid devices
-+ * source = link local address (of sending interface)
-+ * dstaddr = all routers multicast address
-+ * Solicitations are sent at an exponentially decreasing rate
-+ *
-+ * TODO: send solicitation first at a normal rate (from ipv6) and
-+ * after that use the exponentially increasing intervals
-+ */
-+static int rs_send(void)
-+{
-+ struct net_device *dev;
-+ struct in6_addr raddr, lladdr;
-+ struct inet6_dev *in6_dev = NULL;
-+ static int num_rs;
-+
-+ if (rs_state == START) {
-+ num_rs = 0;
-+ rs_state = CONTINUE;
-+ } else if (num_rs++ > MAX_RTR_SOLICITATIONS)
-+ return HZ;
-+
-+ ipv6_addr_all_routers(&raddr);
-+ read_lock(&dev_base_lock);
-+
-+ /* Send router solicitations to all interfaces */
-+ for (dev = dev_base; dev; dev = dev->next) {
-+ if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ETHER) {
-+ DEBUG(DBG_DATADUMP, "Sending RS to device %s",
-+ dev->name);
-+ if (!ipv6_get_lladdr(dev, &lladdr)) {
-+ ndisc_send_rs(dev, &lladdr, &raddr);
-+ in6_dev = in6_dev_get(dev);
-+ in6_dev->if_flags |= IF_RS_SENT;
-+ in6_dev_put(in6_dev);
-+ } else {
-+ DEBUG(DBG_DATADUMP, "%s: device doesn't have link-local address!\n", dev->name);
-+ continue;
-+ }
-+ }
-+
-+ }
-+ read_unlock(&dev_base_lock);
-+ return RTR_SOLICITATION_INTERVAL;
-+}
-+
-+/* Create a new CoA for MN and also add a route to it if it is still tentative
-+ to allow MN to get packets to the address immediately
-+ */
-+static int form_coa(struct in6_addr *coa, struct in6_addr *pfix,
-+ int plen, int ifindex)
-+{
-+ struct net_device *dev;
-+ struct inet6_dev *in6_dev;
-+ int ret = 0;
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_WARNING, "Device is not present");
-+ return -1;
-+ }
-+ if ((in6_dev = in6_dev_get(dev)) == NULL) {
-+ DEBUG(DBG_WARNING, "inet6_dev is not present");
-+ dev_put(dev);
-+ return -1;
-+ }
-+ coa->s6_addr32[0] = pfix->s6_addr32[0];
-+ coa->s6_addr32[1] = pfix->s6_addr32[1];
-+
-+ if (ipv6_generate_eui64(coa->s6_addr + 8, dev) &&
-+ ipv6_inherit_eui64(coa->s6_addr + 8, in6_dev)) {
-+ in6_dev_put(in6_dev);
-+ dev_put(dev);
-+ return -1;
-+ }
-+ if (ipv6_chk_addr(coa, dev) == 0) {
-+ DEBUG(DBG_WARNING, "care-of address still tentative");
-+ ret = 1;
-+ }
-+ DEBUG(DBG_INFO, "Formed new CoA: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(coa));
-+
-+ in6_dev_put(in6_dev);
-+ dev_put(dev);
-+ return ret;
-+}
-+
-+static inline int rtr_is_gw(struct router *rtr, struct rt6_info *rt)
-+{
-+ return ((rt->rt6i_flags & RTF_GATEWAY) &&
-+ !ipv6_addr_cmp(&rt->rt6i_gateway, &rtr->ll_addr));
-+}
-+
-+static inline int is_prefix_route(struct router *rtr, struct rt6_info *rt)
-+{
-+ return (!(rt->rt6i_flags & RTF_GATEWAY) &&
-+ mipv6_prefix_compare(&rt->rt6i_dst.addr, &rtr->raddr,
-+ rtr->pfix_len));
-+}
-+
-+/*
-+ * Function that determines whether given rt6_info should be destroyed
-+ * (negative => destroy rt6_info, zero or positive => do nothing)
-+ */
-+static int mn_route_cleaner(struct rt6_info *rt, void *arg)
-+{
-+ int type;
-+
-+ struct router *rtr = (struct router *)arg;
-+
-+ int ret = -1;
-+
-+ DEBUG_FUNC();
-+
-+ if (!rt || !rtr) {
-+ DEBUG(DBG_ERROR, "mn_route_cleaner: rt or rtr NULL");
-+ return 0;
-+ }
-+
-+ /* Do not delete routes to local addresses or to multicast
-+ * addresses, since we need them to get router advertisements
-+ * etc. Multicast addresses are more tricky, but we don't
-+ * delete them in any case. The routing mechanism is not optimal for
-+ * multihoming.
-+ *
-+ * Also keep all new prefix routes, gateway routes through rtr and
-+ * all remaining default routes (including those used for reverse
-+ * tunneling)
-+ */
-+ type = ipv6_addr_type(&rt->rt6i_dst.addr);
-+
-+ if ((type & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)) ||
-+ rt->rt6i_dev == &loopback_dev || rtr_is_gw(rtr, rt) ||
-+ is_prefix_route(rtr, rt) || (rt->rt6i_flags & RTF_DEFAULT))
-+ ret = 0;
-+
-+ /* delete all others */
-+
-+ if (rt->rt6i_dev != &loopback_dev) {
-+ DEBUG(DEBUG_MDETECT,
-+ "%s route:\n"
-+ "dev: %s,\n"
-+ "gw: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "flags: %x,\n"
-+ "metric: %d,\n"
-+ "src: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "dst: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "plen: %d\n",
-+ (ret ? "Deleting" : "Keeping"),
-+ rt->rt6i_dev->name,
-+ NIPV6ADDR(&rt->rt6i_gateway),
-+ rt->rt6i_flags,
-+ rt->rt6i_metric,
-+ NIPV6ADDR(&rt->rt6i_src.addr),
-+ NIPV6ADDR(&rt->rt6i_dst.addr),
-+ rt->rt6i_dst.plen);
-+ }
-+ return ret;
-+}
-+
-+/*
-+ * Deletes old routes
-+ */
-+static __inline__ void delete_routes(struct router *rtr)
-+{
-+ DEBUG_FUNC();
-+
-+ /* Routing table is locked to ensure that nobody uses its */
-+ write_lock_bh(&rt6_lock);
-+ DEBUG(DBG_INFO, "mipv6: Purging routes");
-+ /* TODO: Does not prune, should it? */
-+ fib6_clean_tree(&ip6_routing_table,
-+ mn_route_cleaner, 0, rtr);
-+ write_unlock_bh(&rt6_lock);
-+
-+}
-+
-+
-+static __inline__ void delete_coas(struct router *rtr)
-+{
-+ struct net_device *dev;
-+ struct inet6_dev *idev;
-+ struct inet6_ifaddr *ifa;
-+
-+ dev = dev_get_by_index(rtr->ifindex);
-+ if (!dev)
-+ return;
-+
-+ idev = in6_dev_get(dev);
-+
-+ if (idev) {
-+ read_lock_bh(&idev->lock);
-+ ifa = idev->addr_list;
-+ while (ifa) {
-+ int keep;
-+ spin_lock(&ifa->lock);
-+
-+ keep = (ifa->flags&(IFA_F_PERMANENT|IFA_F_HOMEADDR) ||
-+ !ipv6_addr_cmp(&ifa->addr, &rtr->CoA));
-+
-+ spin_unlock(&ifa->lock);
-+
-+ if (keep)
-+ ifa = ifa->if_next;
-+ else {
-+ in6_ifa_hold(ifa);
-+ read_unlock_bh(&idev->lock);
-+
-+ ipv6_del_addr(ifa);
-+
-+ read_lock_bh(&idev->lock);
-+ ifa = idev->addr_list;
-+ }
-+ }
-+ read_unlock_bh(&idev->lock);
-+ in6_dev_put(idev);
-+ }
-+ dev_put(dev);
-+}
-+
-+int next_mdet_state[3][3] = {{CURR_RTR_OK, NO_RTR, NO_RTR},
-+ {CURR_RTR_OK, CURR_RTR_OK, NO_RTR},
-+ {CURR_RTR_OK, CURR_RTR_OK, RTR_SUSPECT}};
-+
-+char *states[3] = {"NO_RTR", "RTR_SUSPECT", "CURR_RTR_OK"};
-+char *events[3] = {"RA_RCVD", "NA_RCVD", "TIMEOUT"};
-+
-+/* State transitions
-+ * NO_RTR, RA_RCVD -> CURR_RTR_OK
-+ * NO_RTR, NA_RCVD -> NO_RTR
-+ * NO_RTR, TIMEOUT -> NO_RTR
-+
-+ * RTR_SUSPECT, RA_RCVD -> CURR_RTR_OK
-+ * RTR_SUSPECT, NA_RCVD -> CURR_RTR_OK
-+ * RTR_SUSPECT, TIMEOUT -> NO_RTR
-+
-+ * CURR_RTR_OK, RA_RCVD -> CURR_RTR_OK
-+ * CURR_RTR_OK, NA_RCVD -> CURR_RTR_OK
-+ * CURR_RTR_OK, TIMEOUT -> RTR_SUSPECT
-+ */
-+static int _curr_state = NO_RTR;
-+
-+#if 0
-+static int get_mdet_state(void){
-+ int state;
-+ spin_lock_bh(&router_lock);
-+ state = _curr_state;
-+ spin_unlock_bh(&router_lock);
-+ return state;
-+}
-+#endif
-+
-+/* Needs to be called with router_lock locked */
-+static int mdet_statemachine(int event)
-+{
-+
-+ if (event > 2 || _curr_state > 2) {
-+ DEBUG(DBG_ERROR, "Got illegal event or curr_state");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_DATADUMP, "Got event %s and curr_state is %s",
-+ events[event], states[_curr_state]);
-+
-+ _curr_state = next_mdet_state[_curr_state][event];
-+ DEBUG(DBG_DATADUMP, "Next state is %s", states[_curr_state]);
-+ return _curr_state;
-+}
-+
-+static void mipv6_do_ll_dad(int ifindex)
-+{
-+ struct net_device *dev = dev_get_by_index(ifindex);
-+ if (dev) {
-+ struct in6_addr lladdr;
-+ struct inet6_ifaddr *ifa;
-+ if (!ipv6_get_lladdr(dev, &lladdr) &&
-+ (ifa = ipv6_get_ifaddr(&lladdr, dev)) != NULL) {
-+ spin_lock_bh(&ifa->lock);
-+ if (!(ifa->flags & IFA_F_TENTATIVE)) {
-+ ifa->flags |= IFA_F_TENTATIVE;
-+ spin_unlock_bh(&ifa->lock);
-+ addrconf_dad_start(ifa, 0);
-+ } else
-+ spin_unlock_bh(&ifa->lock);
-+
-+ }
-+ dev_put(dev);
-+ }
-+}
-+/*
-+ * Changes the router, called from ndisc.c if mipv6_router_event
-+ * returns true.
-+ */
-+
-+static void mipv6_change_router(void)
-+{
-+ struct in6_addr coa;
-+ int ret, ifindex;
-+
-+ DEBUG_FUNC();
-+
-+
-+ if (next_router == NULL)
-+ return;
-+
-+ spin_lock(&router_lock);
-+
-+
-+ if (curr_router != NULL &&
-+ !ipv6_addr_cmp(&curr_router->ll_addr, &next_router->ll_addr)) {
-+ DEBUG(DBG_INFO,"Trying to handoff from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr_router->ll_addr));
-+ DEBUG(DBG_INFO,"Trying to handoff to: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&next_router->ll_addr));
-+ next_router = NULL; /* Let's not leave dangling pointers */
-+ spin_unlock(&router_lock);
-+ return;
-+ }
-+ ret = form_coa(&next_router->CoA, &next_router->raddr,
-+ next_router->pfix_len, next_router->ifindex);
-+ if (ret < 0) {
-+ DEBUG(DBG_ERROR, "handoff: Creation of coa failed");
-+ spin_unlock(&router_lock);
-+ return;
-+ } else if (ret > 0)
-+ next_router->flags |= COA_TENTATIVE;
-+
-+ mdet_statemachine(RA_RCVD); /* TODO: What if DAD fails... */
-+ if (next_router->interval)
-+ mod_timer(&r_timer, jiffies +
-+ (next_router->interval * HZ)/1000);
-+ else
-+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ);
-+
-+
-+ if (ret == 0) {
-+ ipv6_addr_copy(&coa, &next_router->CoA);
-+ ifindex = next_router->ifindex;
-+ spin_unlock(&router_lock);
-+ mipv6_mdet_finalize_ho(&coa, ifindex);
-+ return;
-+ }
-+ spin_unlock(&router_lock);
-+
-+}
-+static unsigned long ns_send(void)
-+{
-+ struct neighbour *neigh;
-+ struct net_device *dev;
-+ struct in6_addr *raddr;
-+
-+ DEBUG(DBG_DATADUMP, "Sending Neighbour solicitation to default router to verify its reachability");
-+ if (!curr_router)
-+ return HZ;
-+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL)
-+ return HZ;
-+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) {
-+ dev_put(dev);
-+ return HZ;
-+ }
-+ if (curr_router->glob_addr)
-+ raddr = &curr_router->raddr;
-+ else
-+ raddr = &curr_router->ll_addr;
-+
-+ curr_router->last_ns_sent = jiffies;
-+ ndisc_send_ns(dev, neigh, raddr, raddr, NULL);
-+
-+ neigh_release(neigh);
-+ dev_put(dev);
-+ return HZ/5; /* Wait 200ms for a reply */
-+}
-+
-+static int na_rcvd(void)
-+{
-+ int neigh_ok = 0;
-+ struct neighbour *neigh;
-+ struct net_device *dev;
-+
-+ if (!curr_router)
-+ return 0;
-+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL)
-+ return 0;
-+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) {
-+ dev_put(dev);
-+ return 0;
-+ }
-+ if (neigh->flags & NTF_ROUTER &&
-+ (time_after(neigh->confirmed, curr_router->last_ns_sent) ||
-+ neigh->confirmed == curr_router->last_ns_sent)) {
-+ neigh_ok = 1;
-+ DEBUG(DBG_DATADUMP, "Mdetect event: NA rcvd from curr rtr");
-+ } else
-+ DEBUG(DBG_DATADUMP, "Mdetect event: NA NOT rcvd from curr rtr within time limit");
-+ neigh_release(neigh);
-+ dev_put(dev);
-+ return neigh_ok;
-+}
-+
-+static void coa_timer_handler(unsigned long dummy)
-+{
-+
-+ spin_lock_bh(&ho_lock);
-+ if (_ho) {
-+ DEBUG(DBG_INFO, "Starting handoff after DAD");
-+ mipv6_mobile_node_moved(_ho);
-+ kfree(_ho);
-+ _ho = NULL;
-+ }
-+ spin_unlock_bh(&ho_lock);
-+}
-+static void timer_handler(unsigned long foo)
-+{
-+ unsigned long timeout;
-+ int state;
-+ spin_lock_bh(&router_lock);
-+
-+ if (_curr_state != NO_RTR)
-+ rs_state = START;
-+
-+ if (_curr_state == RTR_SUSPECT && na_rcvd()) {
-+ state = mdet_statemachine(NA_RCVD);
-+ timeout = curr_router->interval ? curr_router->interval : max_rtr_reach_time * HZ;
-+ } else {
-+ state = mdet_statemachine(TIMEOUT);
-+ if (state == NO_RTR)
-+ timeout = rs_send();
-+ else /* RTR_SUSPECT */
-+ timeout = ns_send();
-+ }
-+ if (!timeout)
-+ timeout = HZ;
-+
-+ mipv6_router_gc();
-+ mod_timer(&r_timer, jiffies + timeout);
-+ spin_unlock_bh(&router_lock);
-+}
-+
-+/**
-+ * mipv6_get_care_of_address - get node's care-of primary address
-+ * @homeaddr: one of node's home addresses
-+ * @coaddr: buffer to store care-of address
-+ *
-+ * Stores the current care-of address in the @coaddr, assumes
-+ * addresses in EUI-64 format. Since node might have several home
-+ * addresses caller MUST supply @homeaddr. If node is at home
-+ * @homeaddr is stored in @coaddr. Returns 0 on success, otherwise a
-+ * negative value.
-+ **/
-+int mipv6_get_care_of_address(
-+ struct in6_addr *homeaddr, struct in6_addr *coaddr)
-+{
-+
-+ DEBUG_FUNC();
-+
-+ if (homeaddr == NULL)
-+ return -1;
-+ spin_lock_bh(&router_lock);
-+ if (curr_router == NULL || mipv6_mn_is_at_home(homeaddr) ||
-+ mipv6_prefix_compare(homeaddr, &curr_router->raddr, 64) ||
-+ curr_router->flags&COA_TENTATIVE) {
-+ DEBUG(DBG_INFO,
-+ "mipv6_get_care_of_address: returning home address");
-+ ipv6_addr_copy(coaddr, homeaddr);
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+
-+ }
-+
-+ /* At home or address check failure probably due to dad wait */
-+ if (mipv6_prefix_compare(&curr_router->raddr, homeaddr,
-+ curr_router->pfix_len)
-+ || (dad == RESPECT_DAD &&
-+ (ipv6_chk_addr(coaddr, NULL) == 0))) {
-+ ipv6_addr_copy(coaddr, homeaddr);
-+ } else {
-+ ipv6_addr_copy(coaddr, &curr_router->CoA);
-+ }
-+
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+
-+int mipv6_mdet_del_if(int ifindex)
-+{
-+ struct router *curr = NULL;
-+ struct list_head *lh, *lh_tmp;
-+
-+ spin_lock_bh(&router_lock);
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ curr = list_entry(lh, struct router, list);
-+ if (curr->ifindex == ifindex) {
-+ num_routers--;
-+ list_del_init(&curr->list);
-+ DEBUG(DBG_DATADUMP, "Deleting router %x:%x:%x:%x:%x:%x:%x:%x on interface %d",
-+ NIPV6ADDR(&curr->raddr), ifindex);
-+ if (curr_router == curr)
-+ curr_router = NULL;
-+ kfree(curr);
-+ }
-+ }
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+
-+void mipv6_mdet_retrigger_ho(void)
-+{
-+ struct handoff ho;
-+
-+ spin_lock_bh(&router_lock);
-+ if (curr_router != NULL) {
-+ ho.coa = &curr_router->CoA;
-+ ho.plen = curr_router->pfix_len;
-+ ho.ifindex = curr_router->ifindex;
-+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr);
-+ ho.home_address = (curr_router->glob_addr &&
-+ curr_router->flags&ND_RA_FLAG_HA);
-+ }
-+ spin_unlock_bh(&router_lock);
-+ mipv6_mobile_node_moved(&ho);
-+}
-+
-+void mipv6_mdet_set_curr_rtr_reachable(int reachable)
-+{
-+ spin_lock_bh(&router_lock);
-+ if (curr_router != NULL) {
-+ curr_router->reachable = reachable;
-+ }
-+ spin_unlock_bh(&router_lock);
-+
-+}
-+
-+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex)
-+{
-+ int dummy;
-+ struct handoff ho;
-+ struct router *tmp;
-+ struct net_device *dev;
-+ struct in6_addr ll_addr;
-+
-+ spin_lock_bh(&router_lock);
-+
-+ if (!next_router) {
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+ }
-+
-+ dev = dev_get_by_index(next_router->ifindex);
-+
-+ if (ipv6_get_lladdr(dev, &ll_addr) == 0) {
-+ if (ipv6_addr_cmp(&ll_addr, coa) == 0)
-+ DEBUG(DBG_INFO, "DAD for link local address completed");
-+ next_router->flags &= ~LLADDR_TENTATIVE;
-+ }
-+
-+ dev_put(dev);
-+
-+ if (mipv6_prefix_compare(coa, &next_router->CoA,
-+ next_router->pfix_len)) {
-+ DEBUG(DBG_INFO, "DAD for Care-of address completed");
-+ next_router->flags &= ~COA_TENTATIVE;
-+ }
-+ if (!(next_router->flags&LLADDR_TENTATIVE) && !(next_router->flags&COA_TENTATIVE)) {
-+ DEBUG(DBG_INFO, "%s: Proceeding with handoff after DAD\n", __FUNCTION__);
-+ tmp = curr_router;
-+ curr_router = next_router;
-+ curr_router->is_current = 1;
-+ next_router = NULL;
-+ curr_router->flags &= ~COA_TENTATIVE;
-+ delete_routes(curr_router);
-+ delete_coas(curr_router);
-+ if (tmp) {
-+ struct net_device *dev_old = dev_get_by_index(tmp->ifindex);
-+ struct rt6_info *rt = NULL;
-+ if (dev_old) {
-+ rt = rt6_get_dflt_router(&tmp->ll_addr, dev_old);
-+ dev_put(dev_old);
-+ }
-+ if (rt)
-+ ip6_del_rt(rt, NULL);
-+ tmp->is_current = 0;
-+ }
-+
-+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy);
-+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy);
-+
-+
-+ ho.coa = &curr_router->CoA;
-+ ho.plen = curr_router->pfix_len;
-+ ho.ifindex = curr_router->ifindex;
-+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr);
-+ ho.home_address = (curr_router->glob_addr &&
-+ curr_router->flags&ND_RA_FLAG_HA);
-+
-+ spin_unlock_bh(&router_lock);
-+ mipv6_mobile_node_moved(&ho);
-+ } else
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+/* Decides whether router candidate is the same router as current rtr
-+ * based on prefix / global addresses of the routers and their link local
-+ * addresses
-+ */
-+static int is_current_rtr(struct router *nrt, struct router *crt)
-+{
-+ DEBUG_FUNC();
-+
-+ DEBUG(DEBUG_MDETECT, "Current router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x and", NIPV6ADDR(&crt->raddr));
-+ DEBUG(DEBUG_MDETECT, "Candidate router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&nrt->raddr));
-+
-+ return (!ipv6_addr_cmp(&nrt->raddr,&crt->raddr) &&
-+ !ipv6_addr_cmp(&nrt->ll_addr, &crt->ll_addr));
-+}
-+
-+/*
-+ * Change next router to nrtr
-+ * Returns 1, if router has been changed.
-+ */
-+
-+static int change_next_rtr(struct router *nrtr, struct router *ortr)
-+{
-+ int changed = 0;
-+ DEBUG_FUNC();
-+
-+ if (!next_router || ipv6_addr_cmp(&nrtr->raddr, &next_router->raddr)) {
-+ changed = 1;
-+ }
-+ next_router = nrtr;
-+ return changed;
-+}
-+static int clean_ncache(struct router *nrt, struct router *ort, int same_if)
-+{
-+ struct net_device *ortdev;
-+ DEBUG_FUNC();
-+
-+ /* Always call ifdown after a handoff to ensure proper routing */
-+
-+ if (!ort)
-+ return 0;
-+ if ((ortdev = dev_get_by_index(ort->ifindex)) == NULL) {
-+ DEBUG(DBG_WARNING, "Device is not present");
-+ return -1;
-+ }
-+ neigh_ifdown(&nd_tbl, ortdev);
-+ dev_put(ortdev);
-+ return 0;
-+}
-+
-+static int mdet_get_if_preference(int ifi)
-+{
-+ int pref = 0;
-+
-+ DEBUG_FUNC();
-+
-+ pref = ma_ctl_get_preference(ifi);
-+
-+ DEBUG(DEBUG_MDETECT, "ifi: %d preference %d", ifi, pref);
-+
-+ return pref;
-+}
-+
-+/*
-+ * Called from mipv6_mn_ra_rcv to determine whether to do a handoff.
-+ */
-+static int mipv6_router_event(struct router *rptr)
-+{
-+ struct router *nrt = NULL;
-+ int new_router = 0, same_if = 1;
-+ int oldstate = _curr_state;
-+ int addrtype = ipv6_addr_type(&rptr->raddr);
-+
-+ DEBUG_FUNC();
-+
-+ if (rptr->lifetime == 0)
-+ return MIPV6_IGN_RTR;
-+ DEBUG(DEBUG_MDETECT, "Received a RA from router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&rptr->raddr));
-+ spin_lock(&router_lock);
-+
-+ /* Add or update router entry */
-+ if ((nrt = mipv6_rtr_get(&rptr->raddr)) == NULL) {
-+ if (addrtype == IPV6_ADDR_ANY || (nrt = mipv6_rtr_add(rptr)) == NULL) {
-+ spin_unlock(&router_lock);
-+ return MIPV6_IGN_RTR;
-+ }
-+ DEBUG(DBG_INFO, "Router not on list,adding it to the list");
-+ new_router = 1;
-+ }
-+ nrt->last_ra_rcvd = jiffies;
-+ nrt->state = ROUTER_REACHABLE;
-+ nrt->interval = rptr->interval;
-+ nrt->lifetime = rptr->lifetime;
-+ nrt->ifindex = rptr->ifindex;
-+ nrt->flags = rptr->flags;
-+ nrt->glob_addr = rptr->glob_addr;
-+
-+ /* Whether from current router */
-+ if (curr_router && curr_router->reachable &&
-+ is_current_rtr(nrt, curr_router)) {
-+ if (nrt->interval)
-+ mod_timer(&r_timer, jiffies + (nrt->interval * HZ)/1000);
-+ else
-+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ);
-+ mdet_statemachine(RA_RCVD);
-+ spin_unlock(&router_lock);
-+ return MIPV6_ADD_RTR;
-+ } else if (oldstate == NO_RTR) {
-+ rt6_purge_dflt_routers(0); /* For multiple interface case */
-+ DEBUG(DBG_INFO, "No router or router not reachable, switching to new one");
-+ goto handoff;
-+ }
-+ if (!curr_router) {
-+ /* Startup */
-+ goto handoff;
-+ }
-+ /* Router behind same interface as current one ?*/
-+ same_if = (nrt->ifindex == curr_router->ifindex);
-+ /* Switch to new router behind same interface if eager cell
-+ * switching is used or if the interface is preferred
-+ */
-+ if ((new_router && eager_cell_switching && same_if) ||
-+ (mdet_get_if_preference(nrt->ifindex) >
-+ mdet_get_if_preference(curr_router->ifindex))) {
-+ DEBUG(DBG_INFO, "Switching to new router.");
-+ goto handoff;
-+ }
-+
-+ /* No handoff, don't add default route */
-+ DEBUG(DEBUG_MDETECT, "Ignoring RA");
-+ spin_unlock(&router_lock);
-+ return MIPV6_IGN_RTR;
-+handoff:
-+ clean_ncache(nrt, curr_router, same_if);
-+ nrt->reachable = 1;
-+ if (same_if && change_next_rtr(nrt, curr_router)) {
-+ mipv6_do_ll_dad(nrt->ifindex);
-+ nrt->flags |= LLADDR_TENTATIVE;
-+ }
-+ spin_unlock(&router_lock);
-+
-+ return MIPV6_CHG_RTR;
-+}
-+
-+/*
-+ * Called from ndisc.c's router_discovery.
-+ */
-+
-+static inline int ret_to_ha(struct in6_addr *addr)
-+{
-+ int res = 0;
-+ struct mn_info *minfo;
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_ha(addr);
-+ if (minfo != NULL) {
-+ spin_lock(&minfo->lock);
-+ if (minfo->has_home_reg) {
-+ res = 1;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock(&mn_info_lock);
-+ return res;
-+}
-+
-+static int mipv6_mn_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts)
-+{
-+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif;
-+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct router nrt;
-+ struct in6_addr *ha = NULL;
-+ u8 *lladdr = NULL;
-+ int res;
-+ DEBUG_FUNC();
-+
-+ memset(&nrt, 0, sizeof(struct router));
-+
-+ if (ra->icmph.icmp6_home_agent) {
-+ nrt.flags |= ND_RA_FLAG_HA;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_HA up");
-+ }
-+
-+ if (ra->icmph.icmp6_addrconf_managed) {
-+ nrt.flags |= ND_RA_FLAG_MANAGED;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_MANAGED up");
-+ }
-+
-+ if (ra->icmph.icmp6_addrconf_other) {
-+ nrt.flags |= ND_RA_FLAG_OTHER;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_OTHER up");
-+ }
-+
-+ ipv6_addr_copy(&nrt.ll_addr, saddr);
-+ nrt.ifindex = ifi;
-+ nrt.lifetime = ntohs(ra->icmph.icmp6_rt_lifetime);
-+
-+ if (ndopts->nd_opts_src_lladdr) {
-+ lladdr = (u8 *) ndopts->nd_opts_src_lladdr+2;
-+ nrt.link_addr_len = skb->dev->addr_len;
-+ memcpy(nrt.link_addr, lladdr, nrt.link_addr_len);
-+ }
-+ if (ndopts->nd_opts_pi) {
-+ struct nd_opt_hdr *p;
-+ for (p = ndopts->nd_opts_pi;
-+ p;
-+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) {
-+ struct prefix_info *pinfo;
-+ int update = 0;
-+
-+ pinfo = (struct prefix_info *) p;
-+
-+ if (!pinfo->autoconf)
-+ continue;
-+
-+ if ((pinfo->router_address &&
-+ (update = ret_to_ha(&pinfo->prefix))) ||
-+ ipv6_addr_type(&nrt.raddr) != IPV6_ADDR_UNICAST) {
-+ ipv6_addr_copy(&nrt.raddr, &pinfo->prefix);
-+ nrt.pfix_len = pinfo->prefix_len;
-+ if (pinfo->router_address)
-+ nrt.glob_addr = 1;
-+ else
-+ nrt.glob_addr = 0;
-+ if (update)
-+ ha = &pinfo->prefix;
-+ DEBUG(DBG_DATADUMP, "Address of the received "
-+ "prefix info option: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&nrt.raddr));
-+ DEBUG(DBG_DATADUMP, "the length of the prefix is %d",
-+ nrt.pfix_len);
-+ }
-+ }
-+ }
-+ if (ndopts->nd_opts_rai) {
-+ nrt.interval = ntohl(*(__u32 *)(ndopts->nd_opts_rai+4));
-+ DEBUG(DBG_DATADUMP,
-+ "received router interval option with interval : %d ",
-+ nrt.interval / HZ);
-+
-+ if (nrt.interval > MAX_RADV_INTERVAL) {
-+ nrt.interval = 0;
-+ DEBUG(DBG_DATADUMP, "but we are using: %d, "
-+ "because interval>MAX_RADV_INTERVAL",
-+ nrt.interval / HZ);
-+ }
-+ }
-+
-+ res = mipv6_router_event(&nrt);
-+
-+ if (ha && lladdr) {
-+ mipv6_mn_ha_nd_update(__dev_get_by_index(ifi), ha, lladdr);
-+ }
-+ return res;
-+}
-+
-+int __init mipv6_initialize_mdetect(void)
-+{
-+
-+ DEBUG_FUNC();
-+
-+ spin_lock_init(&router_lock);
-+ spin_lock_init(&ho_lock);
-+ init_timer(&coa_timer);
-+ init_timer(&r_timer);
-+ r_timer.expires = jiffies + HZ;
-+ add_timer(&r_timer);
-+
-+ /* Actual HO, also deletes old routes after the addition of new ones
-+ in ndisc */
-+ MIPV6_SETCALL(mipv6_change_router, mipv6_change_router);
-+
-+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_mn_ra_rcv);
-+
-+ return 0;
-+}
-+
-+int __exit mipv6_shutdown_mdetect()
-+{
-+
-+ DEBUG_FUNC();
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_change_router);
-+ spin_lock_bh(&router_lock);
-+ spin_lock(&ho_lock);
-+ del_timer(&coa_timer);
-+ del_timer(&r_timer);
-+ /* Free the memory allocated by router list */
-+ list_free(&curr_router);
-+ if (_ho)
-+ kfree(_ho);
-+ spin_unlock(&ho_lock);
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.h linux-2.4.25/net/ipv6/mobile_ip6/mdetect.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mdetect.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mdetect.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,37 @@
-+/*
-+ * MIPL Mobile IPv6 Movement detection module header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MDETECT_H
-+#define _MDETECT_H
-+
-+struct handoff {
-+ int home_address; /* Is the coa a home address */
-+ int ifindex;
-+ int plen;
-+ struct in6_addr *coa;
-+ struct in6_addr rtr_addr; /* Prefix or rtr address if coa is home address */
-+};
-+
-+int mipv6_initialize_mdetect(void);
-+
-+int mipv6_shutdown_mdetect(void);
-+
-+int mipv6_get_care_of_address(struct in6_addr *homeaddr, struct in6_addr *coa);
-+
-+int mipv6_mdet_del_if(int ifindex);
-+
-+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex);
-+
-+void mipv6_mdet_retrigger_ho(void);
-+
-+void mipv6_mdet_set_curr_rtr_reachable(int reachable);
-+
-+#endif /* _MDETECT_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,342 @@
-+/**
-+ * Generic icmp routines
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>,
-+ * Ville Nuorvala <vnuorval@tcs.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <net/checksum.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+#include <net/mipglue.h>
-+
-+#include "debug.h"
-+#include "bcache.h"
-+#include "mipv6_icmp.h"
-+#include "config.h"
-+
-+struct mipv6_icmpv6_msg {
-+ struct icmp6hdr icmph;
-+ __u8 *data;
-+ struct in6_addr *daddr;
-+ int len;
-+ __u32 csum;
-+};
-+
-+#define MIPV6_ICMP_HOP_LIMIT 64
-+
-+static struct socket *mipv6_icmpv6_socket = NULL;
-+static __u16 identifier = 0;
-+
-+int mipv6_icmpv6_no_rcv(struct sk_buff *skb)
-+{
-+ return 0;
-+}
-+
-+static int mipv6_icmpv6_xmit_holder = -1;
-+
-+static int mipv6_icmpv6_xmit_lock_bh(void)
-+{
-+ if (!spin_trylock(&mipv6_icmpv6_socket->sk->lock.slock)) {
-+ if (mipv6_icmpv6_xmit_holder == smp_processor_id())
-+ return -EAGAIN;
-+ spin_lock(&mipv6_icmpv6_socket->sk->lock.slock);
-+ }
-+ mipv6_icmpv6_xmit_holder = smp_processor_id();
-+ return 0;
-+}
-+
-+static __inline__ int mipv6_icmpv6_xmit_lock(void)
-+{
-+ int ret;
-+ local_bh_disable();
-+ ret = mipv6_icmpv6_xmit_lock_bh();
-+ if (ret)
-+ local_bh_enable();
-+ return ret;
-+}
-+
-+static void mipv6_icmpv6_xmit_unlock_bh(void)
-+{
-+ mipv6_icmpv6_xmit_holder = -1;
-+ spin_unlock(&mipv6_icmpv6_socket->sk->lock.slock);
-+}
-+
-+static __inline__ void mipv6_icmpv6_xmit_unlock(void)
-+{
-+ mipv6_icmpv6_xmit_unlock_bh();
-+ local_bh_enable();
-+}
-+
-+
-+/**
-+ * mipv6_icmpv6_dest_unreach - Destination Unreachable ICMP error message handler
-+ * @skb: buffer containing ICMP error message
-+ *
-+ * Special Mobile IPv6 ICMP handling. If Correspondent Node receives
-+ * persistent ICMP Destination Unreachable messages for a destination
-+ * in its Binding Cache, the binding should be deleted. See draft
-+ * section 8.8.
-+ **/
-+static int mipv6_icmpv6_rcv_dest_unreach(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) (icmph + 1);
-+ int left = (skb->tail - skb->h.raw) - sizeof(*icmph)- sizeof(ipv6h);
-+ struct ipv6_opt_hdr *eh;
-+ struct rt2_hdr *rt2h = NULL;
-+ struct in6_addr *daddr = &ipv6h->daddr;
-+ struct in6_addr *saddr = &ipv6h->saddr;
-+ int hdrlen, nexthdr = ipv6h->nexthdr;
-+ struct mipv6_bce bce;
-+ DEBUG_FUNC();
-+
-+ eh = (struct ipv6_opt_hdr *) (ipv6h + 1);
-+
-+ while (left > 0) {
-+ if (nexthdr != NEXTHDR_HOP && nexthdr != NEXTHDR_DEST &&
-+ nexthdr != NEXTHDR_ROUTING)
-+ return 0;
-+
-+ hdrlen = ipv6_optlen(eh);
-+ if (hdrlen > left)
-+ return 0;
-+
-+ if (nexthdr == NEXTHDR_ROUTING) {
-+ struct ipv6_rt_hdr *rth = (struct ipv6_rt_hdr *) eh;
-+
-+ if (rth->type == IPV6_SRCRT_TYPE_2) {
-+ if (hdrlen != sizeof(struct rt2_hdr))
-+ return 0;
-+
-+ rt2h = (struct rt2_hdr *) rth;
-+
-+ if (rt2h->rt_hdr.segments_left > 0)
-+ daddr = &rt2h->addr;
-+ break;
-+ }
-+ }
-+ /* check for home address option in case this node is a MN */
-+ if (nexthdr == NEXTHDR_DEST) {
-+ __u8 *raw = (__u8 *) eh;
-+ __u16 i = 2;
-+ while (1) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+
-+ if (i + sizeof (*hao) > hdrlen)
-+ break;
-+
-+ hao = (struct mipv6_dstopt_homeaddr *) &raw[i];
-+
-+ if (hao->type == MIPV6_TLV_HOMEADDR &&
-+ hao->length == sizeof(struct in6_addr)) {
-+ saddr = &hao->addr;
-+ break;
-+ }
-+ if (hao->type)
-+ i += hao->length + 2;
-+ else
-+ i++;
-+ }
-+
-+ }
-+ nexthdr = eh->nexthdr;
-+ eh = (struct ipv6_opt_hdr *) ((u8 *) eh + hdrlen);
-+ left -= hdrlen;
-+ }
-+ if (rt2h == NULL) return 0;
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bce) == 0 && !(bce.flags&HOME_REGISTRATION)) {
-+ /* A primitive algorithm for detecting persistent ICMP destination unreachable messages */
-+ if (bce.destunr_count &&
-+ time_after(jiffies,
-+ bce.last_destunr + MIPV6_DEST_UNR_IVAL*HZ))
-+ bce.destunr_count = 0;
-+
-+ bce.destunr_count++;
-+
-+ mipv6_bcache_icmp_err(daddr, saddr, bce.destunr_count);
-+
-+ if (bce.destunr_count > MIPV6_MAX_DESTUNREACH && mipv6_bcache_delete(daddr, saddr, CACHE_ENTRY) == 0) {
-+ DEBUG(DBG_INFO, "Deleted bcache entry "
-+ "%x:%x:%x:%x:%x:%x:%x:%x "
-+ "%x:%x:%x:%x:%x:%x:%x:%x (reason: "
-+ "%d dest unreachables) ",
-+ NIPV6ADDR(daddr), NIPV6ADDR(saddr), bce.destunr_count);
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int mipv6_icmpv6_getfrag(const void *data, struct in6_addr *saddr,
-+ char *buff, unsigned int offset,
-+ unsigned int len)
-+{
-+ struct mipv6_icmpv6_msg *msg = (struct mipv6_icmpv6_msg *) data;
-+ struct icmp6hdr *icmph;
-+ __u32 csum;
-+
-+ if (offset) {
-+ msg->csum = csum_partial_copy_nocheck(msg->data + offset -
-+ sizeof(*icmph), buff,
-+ len, msg->csum);
-+ return 0;
-+ }
-+
-+ csum = csum_partial_copy_nocheck((__u8 *) &msg->icmph, buff,
-+ sizeof(*icmph), msg->csum);
-+
-+ csum = csum_partial_copy_nocheck(msg->data, buff + sizeof(*icmph),
-+ len - sizeof(*icmph), csum);
-+
-+ icmph = (struct icmp6hdr *) buff;
-+
-+ icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
-+ IPPROTO_ICMPV6, csum);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_icmpv6_send - generic icmpv6 message send
-+ * @daddr: destination address
-+ * @saddr: source address
-+ * @type: icmp type
-+ * @code: icmp code
-+ * @id: packet identifier. If null, uses internal counter to get new id
-+ * @data: packet data
-+ * @datalen: length of data in bytes
-+ */
-+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr, int type,
-+ int code, __u16 *id, __u16 flags, void *data, int datalen)
-+{
-+ struct sock *sk = mipv6_icmpv6_socket->sk;
-+ struct flowi fl;
-+ struct mipv6_icmpv6_msg msg;
-+
-+ DEBUG_FUNC();
-+
-+ fl.proto = IPPROTO_ICMPV6;
-+ fl.fl6_dst = daddr;
-+ fl.fl6_src = saddr;
-+ fl.fl6_flowlabel = 0;
-+ fl.uli_u.icmpt.type = type;
-+ fl.uli_u.icmpt.code = code;
-+
-+ msg.icmph.icmp6_type = type;
-+ msg.icmph.icmp6_code = code;
-+ msg.icmph.icmp6_cksum = 0;
-+
-+ if (id)
-+ msg.icmph.icmp6_identifier = htons(*id);
-+ else
-+ msg.icmph.icmp6_identifier = htons(identifier++);
-+
-+ msg.icmph.icmp6_sequence = htons(flags);
-+ msg.data = data;
-+ msg.csum = 0;
-+ msg.len = datalen + sizeof(struct icmp6hdr);
-+ msg.daddr = daddr;
-+
-+ if (mipv6_icmpv6_xmit_lock())
-+ return;
-+
-+ ip6_build_xmit(sk, mipv6_icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1,
-+ MSG_DONTWAIT);
-+
-+ ICMP6_INC_STATS_BH(Icmp6OutMsgs);
-+ mipv6_icmpv6_xmit_unlock();
-+}
-+
-+/**
-+ * icmp6_rcv - ICMPv6 receive and multiplex
-+ * @skb: buffer containing ICMP message
-+ *
-+ * Generic ICMPv6 receive function to multiplex messages to approriate
-+ * handlers. Only used for ICMP messages with special handling in
-+ * Mobile IPv6.
-+ **/
-+static void icmp6_rcv(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *hdr;
-+
-+ if (skb_is_nonlinear(skb) &&
-+ skb_linearize(skb, GFP_ATOMIC) != 0) {
-+ kfree_skb(skb);
-+ return;
-+ }
-+ __skb_push(skb, skb->data-skb->h.raw);
-+
-+ hdr = (struct icmp6hdr *) skb->h.raw;
-+
-+ switch (hdr->icmp6_type) {
-+ case ICMPV6_DEST_UNREACH:
-+ mipv6_icmpv6_rcv_dest_unreach(skb);
-+ break;
-+
-+ case ICMPV6_PARAMPROB:
-+ mip6_fn.icmpv6_paramprob_rcv(skb);
-+ break;
-+
-+ case MIPV6_DHAAD_REPLY:
-+ mip6_fn.icmpv6_dhaad_rep_rcv(skb);
-+ break;
-+
-+ case MIPV6_PREFIX_ADV:
-+ mip6_fn.icmpv6_pfxadv_rcv(skb);
-+ break;
-+
-+ case MIPV6_DHAAD_REQUEST:
-+ mip6_fn.icmpv6_dhaad_req_rcv(skb);
-+ break;
-+
-+ case MIPV6_PREFIX_SOLICIT:
-+ mip6_fn.icmpv6_pfxsol_rcv(skb);
-+ break;
-+ }
-+}
-+
-+int mipv6_icmpv6_init(void)
-+{
-+ struct sock *sk;
-+ int err;
-+
-+ if ((mipv6_icmpv6_socket = sock_alloc()) == NULL) {
-+ DEBUG(DBG_ERROR, "Cannot allocate mipv6_icmpv6_socket");
-+ return -1;
-+ }
-+ mipv6_icmpv6_socket->type = SOCK_RAW;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMP,
-+ &mipv6_icmpv6_socket)) < 0) {
-+ DEBUG(DBG_ERROR, "Cannot initialize mipv6_icmpv6_socket");
-+ sock_release(mipv6_icmpv6_socket);
-+ mipv6_icmpv6_socket = NULL; /* For safety */
-+ return err;
-+ }
-+ sk = mipv6_icmpv6_socket->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->prot->unhash(sk);
-+
-+ /* Register our ICMP handler */
-+ MIPV6_SETCALL(mipv6_icmp_rcv, icmp6_rcv);
-+ return 0;
-+}
-+
-+void mipv6_icmpv6_exit(void)
-+{
-+ MIPV6_RESETCALL(mipv6_icmp_rcv);
-+ if (mipv6_icmpv6_socket)
-+ sock_release(mipv6_icmpv6_socket);
-+ mipv6_icmpv6_socket = NULL; /* For safety */
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.h linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,43 @@
-+/*
-+ * MIPL Mobile IPv6 ICMP send and receive prototypes
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MIPV6_ICMP
-+#define _MIPV6_ICMP
-+
-+#include <linux/config.h>
-+#include <linux/in6.h>
-+
-+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int type, int code, __u16 *id, __u16 flags,
-+ void *data, int datalen);
-+
-+void mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id);
-+
-+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr);
-+/* No handling */
-+int mipv6_icmpv6_no_rcv(struct sk_buff *skb);
-+
-+/* Receive DHAAD Reply message */
-+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb);
-+/* Receive Parameter Problem message */
-+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb);
-+/* Receive prefix advertisements */
-+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb);
-+
-+/* Receive DHAAD Request message */
-+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb);
-+/* Receive prefix solicitations */
-+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb);
-+
-+int mipv6_icmpv6_init(void);
-+void mipv6_icmpv6_exit(void);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_ha.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_ha.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,158 @@
-+/*
-+ * Home Agent specific ICMP routines
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/sched.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "halist.h"
-+#include "debug.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+
-+/* Is this the easiest way of checking on
-+ * which interface an anycast address is ?
-+ */
-+static int find_ac_dev(struct in6_addr *addr)
-+{
-+ int ifindex = 0;
-+ struct net_device *dev;
-+ read_lock(&dev_base_lock);
-+ for (dev=dev_base; dev; dev=dev->next) {
-+ if (ipv6_chk_acast_addr(dev, addr)) {
-+ ifindex = dev->ifindex;
-+ break;
-+ }
-+ }
-+ read_unlock(&dev_base_lock);
-+ return ifindex;
-+}
-+
-+/**
-+ * mipv6_icmpv6_send_dhaad_rep - Reply to DHAAD Request
-+ * @ifindex: index of interface request was received from
-+ * @id: request's identification number
-+ * @daddr: requester's IPv6 address
-+ *
-+ * When Home Agent receives Dynamic Home Agent Address Discovery
-+ * request, it replies with a list of home agents available on the
-+ * home link.
-+ */
-+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr)
-+{
-+ __u8 *data = NULL;
-+ struct in6_addr home, *ha_addrs = NULL;
-+ int addr_count, max_addrs, size = 0;
-+
-+ if (daddr == NULL)
-+ return;
-+
-+ if (mipv6_ha_get_addr(ifindex, &home) < 0) {
-+ DEBUG(DBG_INFO, "Not Home Agent in this interface");
-+ return;
-+ }
-+
-+ /* We send all available HA addresses, not exceeding a maximum
-+ * number we can fit in a packet with minimum IPv6 MTU (to
-+ * avoid fragmentation).
-+ */
-+ max_addrs = 76;
-+ addr_count = mipv6_ha_get_pref_list(ifindex, &ha_addrs, max_addrs);
-+
-+ if (addr_count < 0) return;
-+
-+ if (addr_count != 0 && ha_addrs == NULL) {
-+ DEBUG(DBG_ERROR, "addr_count = %d but return no addresses",
-+ addr_count);
-+ return;
-+ }
-+ data = (u8 *)ha_addrs;
-+
-+ size = addr_count * sizeof(struct in6_addr);
-+
-+ mipv6_icmpv6_send(daddr, &home, MIPV6_DHAAD_REPLY,
-+ 0, &id, 0, data, size);
-+ if (ha_addrs) {
-+ data = NULL;
-+ kfree(ha_addrs);
-+ }
-+}
-+
-+/**
-+ * mipv6_icmpv6_dhaad_req - Home Agent Address Discovery Request ICMP handler
-+ * @skb: buffer containing ICMP information message
-+ *
-+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent
-+ * Address Discovery Request messages.
-+ **/
-+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ __u16 identifier;
-+ int ifindex = 0;
-+
-+ DEBUG_FUNC();
-+
-+ /* Invalid packet checks. */
-+ if (phdr->icmp6_code != 0)
-+ return 0;
-+
-+ identifier = ntohs(phdr->icmp6_identifier);
-+
-+ /*
-+ * Make sure we have the right ifindex (if the
-+ * req came through another interface.
-+ */
-+ ifindex = find_ac_dev(daddr);
-+ if (ifindex == 0) {
-+ DEBUG(DBG_WARNING, "received dhaad request to anycast address %x:%x:%x:%x:%x:%x:%x:%x"
-+ " on which prefix we are not HA",
-+ NIPV6ADDR(daddr));
-+ return 0;
-+ }
-+
-+ /*
-+ * send reply with list
-+ */
-+ mipv6_icmpv6_send_dhaad_rep(ifindex, identifier, saddr);
-+ return 1;
-+}
-+#if 0
-+/**
-+ * mipv6_icmpv6_handle_pfx_sol - handle prefix solicitations
-+ * @skb: sk_buff including the icmp6 message
-+ */
-+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb)
-+{
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ struct inet6_ifaddr *ifp;
-+
-+ DEBUG_FUNC();
-+
-+ if (!(ifp = ipv6_get_ifaddr(daddr, NULL)))
-+ return -1;
-+
-+ in6_ifa_put(ifp);
-+ mipv6_pfx_cancel_send(saddr, -1);
-+
-+ return 0;
-+}
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_mn.c linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mipv6_icmp_mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mipv6_icmp_mn.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,273 @@
-+/*
-+ * Mobile Node specific ICMP routines
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/sched.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "mn.h"
-+#include "bul.h"
-+#include "mdetect.h"
-+#include "debug.h"
-+#include "mipv6_icmp.h"
-+#include "util.h"
-+//#include "prefix.h"
-+
-+#define INFINITY 0xffffffff
-+
-+/**
-+ * mipv6_icmpv6_paramprob - Parameter Problem ICMP error message handler
-+ * @skb: buffer containing ICMP error message
-+ *
-+ * Special Mobile IPv6 ICMP handling. If Mobile Node receives ICMP
-+ * Parameter Problem message when using a Home Address Option,
-+ * offending node should be logged and error message dropped. If
-+ * error is received because of a Binding Update, offending node
-+ * should be recorded in Binding Update List and no more Binding
-+ * Updates should be sent to this destination. See RFC 3775 section
-+ * 10.15.
-+ **/
-+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = skb ? &skb->nh.ipv6h->saddr : NULL;
-+ struct in6_addr *daddr = skb ? &skb->nh.ipv6h->daddr : NULL;
-+ struct ipv6hdr *hdr = (struct ipv6hdr *) (phdr + 1);
-+ int ulen = (skb->tail - (unsigned char *) (phdr + 1));
-+
-+ int errptr;
-+ __u8 *off_octet;
-+
-+ DEBUG_FUNC();
-+
-+ /* We only handle code 1 & 2 messages. */
-+ if (phdr->icmp6_code != ICMPV6_UNK_NEXTHDR &&
-+ phdr->icmp6_code != ICMPV6_UNK_OPTION)
-+ return 0;
-+
-+ /* Find offending octet in the original packet. */
-+ errptr = ntohl(phdr->icmp6_pointer);
-+
-+ /* There is not enough of the original packet left to figure
-+ * out what went wrong. Bail out. */
-+ if (ulen <= errptr)
-+ return 0;
-+
-+ off_octet = ((__u8 *) hdr + errptr);
-+ DEBUG(DBG_INFO, "Parameter problem: offending octet %d [0x%2x]",
-+ errptr, *off_octet);
-+
-+ /* If CN did not understand Mobility Header, set BUL entry to
-+ * ACK_ERROR so no further BUs are sumbitted to this CN. */
-+ if (phdr->icmp6_code == ICMPV6_UNK_NEXTHDR &&
-+ *off_octet == IPPROTO_MOBILITY) {
-+ struct bul_inval_args args;
-+ args.all_rr_states = 1;
-+ args.cn = saddr;
-+ args.mn = daddr;
-+ write_lock(&bul_lock);
-+ mipv6_bul_iterate(mn_bul_invalidate, &args);
-+ write_unlock(&bul_lock);
-+ }
-+
-+ /* If CN did not understand Home Address Option, we log an
-+ * error and discard the error message. */
-+ if (phdr->icmp6_code == ICMPV6_UNK_OPTION &&
-+ *off_octet == MIPV6_TLV_HOMEADDR) {
-+ DEBUG(DBG_WARNING, "Correspondent node does not "
-+ "implement Home Address Option receipt.");
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_mn_dhaad_send_req - Send DHAAD Request to home network
-+ * @home_addr: address to do DHAAD for
-+ * @plen: prefix length for @home_addr
-+ *
-+ * Send Dynamic Home Agent Address Discovery Request to the Home
-+ * Agents anycast address in the nodes home network.
-+ **/
-+void
-+mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id)
-+{
-+ struct in6_addr ha_anycast;
-+ struct in6_addr careofaddr;
-+
-+ if (mipv6_get_care_of_address(home_addr, &careofaddr) < 0) {
-+ DEBUG(DBG_WARNING, "Could not get node's Care-of Address");
-+ return;
-+ }
-+
-+ if (mipv6_ha_anycast(&ha_anycast, home_addr, plen) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "Could not get Home Agent Anycast address for home address %x:%x.%x:%x:%x:%x:%x:%x/%d",
-+ NIPV6ADDR(home_addr), plen);
-+ return;
-+ }
-+
-+ mipv6_icmpv6_send(&ha_anycast, &careofaddr, MIPV6_DHAAD_REQUEST, 0,
-+ &dhaad_id, 0, NULL, 0);
-+
-+}
-+
-+/**
-+ * mipv6_icmpv6_dhaad_rep - Home Agent Address Discovery Reply ICMP handler
-+ * @skb: buffer containing ICMP information message
-+ *
-+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent
-+ * Address Discovery Reply messages.
-+ **/
-+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *address;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ __u16 identifier;
-+ int ulen = (skb->tail - (unsigned char *) ((__u32 *) phdr + 2));
-+ int i;
-+ struct in6_addr home_addr, coa;
-+ struct in6_addr *first_ha = NULL;
-+ struct mn_info *minfo;
-+ int n_addr = ulen / sizeof(struct in6_addr);
-+
-+ DEBUG_FUNC();
-+
-+ /* Invalid packet checks. */
-+ if (ulen % sizeof(struct in6_addr) != 0)
-+ return 0;
-+
-+ if (phdr->icmp6_code != 0)
-+ return 0;
-+
-+ identifier = ntohs(phdr->icmp6_identifier);
-+ if (ulen > 0) {
-+ address = (struct in6_addr *) ((__u32 *) phdr + 2);
-+ } else {
-+ address = saddr;
-+ n_addr = 1;
-+ }
-+
-+ /* receive list of home agent addresses
-+ * add to home agents list
-+ */
-+ DEBUG(DBG_INFO, "DHAAD: got %d home agents", n_addr);
-+
-+ first_ha = address;
-+
-+ /* lookup H@ with identifier */
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_id(identifier);
-+ if (!minfo) {
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_INFO, "no mninfo with id %d",
-+ identifier);
-+ return 0;
-+ }
-+ spin_lock(&minfo->lock);
-+
-+ /* Logic:
-+ * 1. if old HA on list, prefer it
-+ * 2. otherwise first HA on list prefered
-+ */
-+ for (i = 0; i < n_addr; i++) {
-+ DEBUG(DBG_INFO, "HA[%d] %x:%x:%x:%x:%x:%x:%x:%x",
-+ i, NIPV6ADDR(address));
-+ if (ipv6_addr_cmp(&minfo->ha, address) == 0) {
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+ return 0;
-+ }
-+ address++;
-+ }
-+ ipv6_addr_copy(&minfo->ha, first_ha);
-+ spin_unlock(&minfo->lock);
-+ ipv6_addr_copy(&home_addr, &minfo->home_addr);
-+ read_unlock(&mn_info_lock);
-+
-+ mipv6_get_care_of_address(&home_addr, &coa);
-+ init_home_registration(&home_addr, &coa);
-+
-+ return 1;
-+}
-+#if 0
-+/**
-+ * mipv6_icmpv6_handle_pfx_adv - handle prefix advertisements
-+ * @skb: sk_buff including the icmp6 message
-+ */
-+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ __u8 *opt = (__u8 *) (hdr + 1);
-+ int optlen = (skb->tail - opt);
-+ unsigned long min_expire = INFINITY;
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *) skb->cb;
-+
-+ DEBUG_FUNC();
-+
-+ while (optlen > 0) {
-+ int len = opt[1] << 3;
-+ if (len == 0)
-+ goto set_timer;
-+
-+ if (opt[0] == ND_OPT_PREFIX_INFO) {
-+ int ifindex;
-+ unsigned long expire;
-+ struct prefix_info *pinfo =
-+ (struct prefix_info *) opt;
-+ struct net_device *dev;
-+ struct mn_info *mninfo;
-+
-+ read_lock(&mn_info_lock);
-+ mninfo = mipv6_mninfo_get_by_ha(saddr);
-+ if (mninfo == NULL) {
-+ ifindex = 0;
-+ } else {
-+ spin_lock(&mninfo->lock);
-+ ifindex = mninfo->ifindex;
-+ spin_unlock(&mninfo->lock);
-+ mninfo = NULL;
-+ }
-+ read_unlock(&mn_info_lock);
-+
-+ if (!(dev = dev_get_by_index(ifindex))) {
-+ DEBUG(DBG_WARNING, "Cannot find device by index %d", parm->iif);
-+ goto nextopt;
-+ }
-+
-+ expire = ntohl(pinfo->valid);
-+ expire = expire == 0 ? INFINITY : expire;
-+
-+ min_expire = expire < min_expire ? expire : min_expire;
-+
-+ dev_put(dev);
-+ }
-+
-+nextopt:
-+ optlen -= len;
-+ opt += len;
-+ }
-+
-+set_timer:
-+
-+ mipv6_pfx_add_home(parm->iif, saddr, daddr, min_expire);
-+ return 0;
-+}
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mn.c linux-2.4.25/net/ipv6/mobile_ip6/mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mn.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,1521 @@
-+/*
-+ * Mobile-node functionality
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/ipsec.h>
-+#include <linux/notifier.h>
-+#include <linux/list.h>
-+#include <linux/route.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv6.h>
-+#include <linux/tqueue.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/uaccess.h>
-+
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+#include <net/ndisc.h>
-+#include <net/ip6_route.h>
-+#include <net/mipglue.h>
-+
-+#include "util.h"
-+#include "mdetect.h"
-+#include "bul.h"
-+#include "mobhdr.h"
-+#include "debug.h"
-+#include "mn.h"
-+#include "mipv6_icmp.h"
-+#include "multiaccess_ctl.h"
-+//#include "prefix.h"
-+#include "tunnel_mn.h"
-+#include "stats.h"
-+#include "config.h"
-+
-+#define MIPV6_BUL_SIZE 128
-+
-+static LIST_HEAD(mn_info_list);
-+
-+/* Lock for list of MN infos */
-+rwlock_t mn_info_lock = RW_LOCK_UNLOCKED;
-+
-+static spinlock_t ifrh_lock = SPIN_LOCK_UNLOCKED;
-+
-+struct ifr_holder {
-+ struct list_head list;
-+ struct in6_ifreq ifr;
-+ int old_ifi;
-+ struct handoff *ho;
-+};
-+
-+LIST_HEAD(ifrh_list);
-+
-+static struct tq_struct mv_home_addr_task;
-+
-+/* Determines whether manually configured home addresses are preferred as
-+ * source addresses over dynamically configured ones
-+ */
-+int mipv6_use_preconfigured_hoaddr = 1;
-+
-+/* Determines whether home addresses, which are at home are preferred as
-+ * source addresses over other home addresses
-+ */
-+int mipv6_use_topol_corr_hoaddr = 0;
-+
-+static spinlock_t icmpv6_id_lock = SPIN_LOCK_UNLOCKED;
-+static __u16 icmpv6_id = 0;
-+
-+static inline __u16 mipv6_get_dhaad_id(void)
-+{
-+ __u16 ret;
-+ spin_lock_bh(&icmpv6_id_lock);
-+ ret = ++icmpv6_id;
-+ spin_unlock_bh(&icmpv6_id_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_home - Returns mn_info for a home address
-+ * @haddr: home address of MN
-+ *
-+ * Returns mn_info on success %NULL otherwise. Caller MUST hold
-+ * @mn_info_lock (read or write).
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+
-+ DEBUG_FUNC();
-+
-+ if (!haddr)
-+ return NULL;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (!ipv6_addr_cmp(&minfo->home_addr, haddr)) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_ha - Lookup mn_info with Home Agent address
-+ * @home_agent: Home Agent address
-+ *
-+ * Searches for a mn_info entry with @ha set to @home_agent. You MUST
-+ * hold @mn_info_lock when calling this function. Returns pointer to
-+ * mn_info entry or %NULL on failure.
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+
-+ if (!home_agent)
-+ return NULL;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (!ipv6_addr_cmp(&minfo->ha, home_agent)) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_id - Lookup mn_info with id
-+ * @id: DHAAD identifier
-+ *
-+ * Searches for a mn_info entry with @dhaad_id set to @id. You MUST
-+ * hold @mn_info_lock when calling this function. Returns pointer to
-+ * mn_info entry or %NULL on failure.
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo = 0;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (minfo->dhaad_id == id) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_add - Adds a new home info for MN
-+ * @ifindex: Interface for home address
-+ * @home_addr: Home address of MN, must be set
-+ * @plen: prefix length of the home address, must be set
-+ * @isathome : home address at home
-+ * @lifetime: lifetime of the home address, 0 is infinite
-+ * @ha: home agent for the home address
-+ * @ha_plen: prefix length of home agent's address, can be zero
-+ * @ha_lifetime: Lifetime of the home address, 0 is infinite
-+ *
-+ * The function adds a new home info entry for MN, allowing it to
-+ * register the home address with the home agent. Starts home
-+ * registration process. If @ha is %ADDRANY, DHAAD is performed to
-+ * find a home agent. Returns 0 on success, a negative value
-+ * otherwise. Caller MUST NOT hold @mn_info_lock or
-+ * @addrconf_hash_lock.
-+ **/
-+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen,
-+ int isathome, unsigned long lifetime, struct in6_addr *ha,
-+ int ha_plen, unsigned long ha_lifetime, int man_conf)
-+{
-+ struct mn_info *minfo;
-+ struct in6_addr coa;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL){
-+ DEBUG(1, "MN info already exists");
-+ write_unlock_bh(&mn_info_lock);
-+ return;
-+ }
-+ minfo = kmalloc(sizeof(struct mn_info), GFP_ATOMIC);
-+ if (!minfo) {
-+ write_unlock_bh(&mn_info_lock);
-+ return;
-+ }
-+ memset(minfo, 0, sizeof(struct mn_info));
-+ spin_lock_init(&minfo->lock);
-+
-+
-+ ipv6_addr_copy(&minfo->home_addr, home_addr);
-+
-+ if (ha)
-+ ipv6_addr_copy(&minfo->ha, ha);
-+ if (ha_plen < 128 && ha_plen > 0)
-+ minfo->home_plen = ha_plen;
-+ else minfo->home_plen = 64;
-+
-+ minfo->ifindex_user = ifindex; /* Ifindex for tunnel interface */
-+ minfo->ifindex = ifindex; /* Interface on which home address is currently conf'd */
-+ /* TODO: we should get home address lifetime from somewhere */
-+ /* minfo->home_addr_expires = jiffies + lifetime * HZ; */
-+
-+ /* manual configuration flag cannot be unset by dynamic updates
-+ * from prefix advertisements
-+ */
-+ if (!minfo->man_conf) minfo->man_conf = man_conf;
-+ minfo->is_at_home = isathome;
-+
-+ list_add(&minfo->list, &mn_info_list);
-+ write_unlock_bh(&mn_info_lock);
-+
-+ if (mipv6_get_care_of_address(home_addr, &coa) == 0)
-+ init_home_registration(home_addr, &coa);
-+}
-+
-+/**
-+ * mipv6_mninfo_del - Delete home info for MN
-+ * @home_addr : Home address or prefix
-+ * @del_dyn_only : Delete only dynamically created home entries
-+ *
-+ * Deletes every mn_info entry that matches the first plen bits of
-+ * @home_addr. Returns number of deleted entries on success and a
-+ * negative value otherwise. Caller MUST NOT hold @mn_info_lock.
-+ **/
-+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only)
-+{
-+ struct list_head *lh, *next;
-+ struct mn_info *minfo;
-+ int ret = -1;
-+ if (!home_addr)
-+ return -1;
-+
-+ write_lock(&mn_info_lock);
-+
-+ list_for_each_safe(lh, next, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if (ipv6_addr_cmp(&minfo->home_addr, home_addr) == 0
-+ && ((!minfo->man_conf && del_dyn_only) || !del_dyn_only)){
-+ list_del(&minfo->list);
-+ kfree(minfo);
-+ ret++;
-+ }
-+ }
-+ write_unlock(&mn_info_lock);
-+ return ret;
-+}
-+
-+void mipv6_mn_set_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int ha_plen)
-+{
-+ mipv6_mninfo_add(ifindex, homeaddr, plen, 0, 0,
-+ homeagent, ha_plen, 0, 1);
-+}
-+
-+static int skip_dad(struct in6_addr *addr)
-+{
-+ struct mn_info *minfo;
-+ int ret = 0;
-+
-+ if (addr == NULL) {
-+ DEBUG(DBG_CRITICAL, "Null argument");
-+ return 0;
-+ }
-+ read_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(addr)) != NULL) {
-+ if ((minfo->is_at_home != MN_NOT_AT_HOME) && (minfo->has_home_reg))
-+ ret = 1;
-+ DEBUG(DBG_INFO, "minfo->is_at_home = %d, minfo->has_home_reg = %d",
-+ minfo->is_at_home, minfo->has_home_reg);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ return ret;
-+}
-+/**
-+ * mipv6_mn_is_home_addr - Determines if addr is node's home address
-+ * @addr: IPv6 address
-+ *
-+ * Returns 1 if addr is node's home address. Otherwise returns zero.
-+ **/
-+int mipv6_mn_is_home_addr(struct in6_addr *addr)
-+{
-+ int ret = 0;
-+
-+ if (addr == NULL) {
-+ DEBUG(DBG_CRITICAL, "Null argument");
-+ return -1;
-+ }
-+ read_lock_bh(&mn_info_lock);
-+ if (mipv6_mninfo_get_by_home(addr))
-+ ret = 1;
-+ read_unlock_bh(&mn_info_lock);
-+
-+ return (ret);
-+}
-+
-+/**
-+ * mipv6_mn_is_at_home - determine if node is home for a home address
-+ * @home_addr : home address of MN
-+ *
-+ * Returns 1 if home address in question is in the home network, 0
-+ * otherwise. Caller MUST NOT not hold @mn_info_lock.
-+ **/
-+int mipv6_mn_is_at_home(struct in6_addr *home_addr)
-+{
-+ struct mn_info *minfo;
-+ int ret = 0;
-+ read_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) {
-+ spin_lock(&minfo->lock);
-+ ret = (minfo->is_at_home == MN_AT_HOME);
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return ret;
-+}
-+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg)
-+{
-+ struct mn_info *minfo;
-+ read_lock_bh(&mn_info_lock);
-+
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) {
-+ spin_lock(&minfo->lock);
-+ minfo->has_home_reg = has_home_reg;
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+}
-+
-+static int mn_inet6addr_event(
-+ struct notifier_block *nb, unsigned long event, void *ptr)
-+{
-+ struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)ptr;
-+
-+ switch (event) {
-+ case NETDEV_UP:
-+ /* Is address a valid coa ?*/
-+ if (!(ifp->flags & IFA_F_TENTATIVE))
-+ mipv6_mdet_finalize_ho(&ifp->addr,
-+ ifp->idev->dev->ifindex);
-+ else if(skip_dad(&ifp->addr))
-+ ifp->flags &= ~IFA_F_TENTATIVE;
-+ break;
-+ case NETDEV_DOWN:
-+#if 0
-+ /* This is useless with manually configured home
-+ addresses, which will not expire
-+ */
-+ mipv6_mninfo_del(&ifp->addr, 0);
-+#endif
-+ break;
-+
-+ }
-+
-+ return NOTIFY_DONE;
-+}
-+
-+struct notifier_block mipv6_mn_inet6addr_notifier = {
-+ mn_inet6addr_event,
-+ NULL,
-+ 0 /* check if using zero is ok */
-+};
-+
-+static void mipv6_get_saddr_hook(struct in6_addr *homeaddr)
-+{
-+ int found = 0, reiter = 0;
-+ struct list_head *lh;
-+ struct mn_info *minfo = NULL;
-+ struct in6_addr coa;
-+
-+ read_lock_bh(&mn_info_lock);
-+restart:
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if ((ipv6_addr_scope(homeaddr) != ipv6_addr_scope(&minfo->home_addr))
-+ || ipv6_chk_addr(&minfo->home_addr, NULL) == 0)
-+ continue;
-+
-+ spin_lock(&minfo->lock);
-+ if (minfo->is_at_home == MN_AT_HOME || minfo->has_home_reg) {
-+ if ((mipv6_use_topol_corr_hoaddr &&
-+ minfo->is_at_home == MN_AT_HOME) ||
-+ (mipv6_use_preconfigured_hoaddr &&
-+ minfo->man_conf) ||
-+ (!(mipv6_use_preconfigured_hoaddr ||
-+ mipv6_use_topol_corr_hoaddr) || reiter)) {
-+ spin_unlock(&minfo->lock);
-+ ipv6_addr_copy(homeaddr, &minfo->home_addr);
-+ found = 1;
-+ break;
-+ }
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ if (!found && !reiter) {
-+ reiter = 1;
-+ goto restart;
-+ }
-+
-+ if (!found && minfo &&
-+ !mipv6_get_care_of_address(&minfo->home_addr, &coa)) {
-+ ipv6_addr_copy(homeaddr, &coa);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ DEBUG(DBG_DATADUMP, "Source address selection: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(homeaddr));
-+ return;
-+}
-+
-+static void mv_home_addr(void *arg)
-+{
-+ mm_segment_t oldfs;
-+ int err = 0, new_if = 0;
-+ struct list_head *lh, *next;
-+ struct ifr_holder *ifrh;
-+ LIST_HEAD(list);
-+
-+ DEBUG(DBG_INFO, "mipv6 move home address task");
-+
-+ spin_lock_bh(&ifrh_lock);
-+ list_splice_init(&ifrh_list, &list);
-+ spin_unlock_bh(&ifrh_lock);
-+
-+ oldfs = get_fs(); set_fs(KERNEL_DS);
-+ list_for_each_safe(lh, next, &list) {
-+ ifrh = list_entry(lh, struct ifr_holder, list);
-+ if (ifrh->old_ifi) {
-+ new_if = ifrh->ifr.ifr6_ifindex;
-+ ifrh->ifr.ifr6_ifindex = ifrh->old_ifi;
-+ err = addrconf_del_ifaddr(&ifrh->ifr);
-+ ifrh->ifr.ifr6_ifindex = new_if;
-+ if (err < 0)
-+ DEBUG(DBG_WARNING, "removal of home address %x:%x:%x:%x:%x:%x:%x:%x from"
-+ " old interface %d failed with status %d",
-+ NIPV6ADDR(&ifrh->ifr.ifr6_addr), ifrh->old_ifi, err);
-+ }
-+ if(!err) {
-+ err = addrconf_add_ifaddr(&ifrh->ifr);
-+ }
-+ if (ifrh->ho) {
-+ DEBUG(DBG_INFO, "Calling mobile_node moved after moving home address to new if");
-+ mipv6_mobile_node_moved(ifrh->ho);
-+ }
-+ list_del(&ifrh->list);
-+ kfree(ifrh);
-+ }
-+ set_fs(oldfs);
-+
-+ if (err < 0)
-+ DEBUG(DBG_WARNING, "adding of home address to a new interface %d failed %d", new_if, err);
-+ else {
-+ DEBUG(DBG_WARNING, "adding of home address to a new interface OK");
-+ }
-+}
-+
-+struct dhaad_halist {
-+ struct list_head list;
-+ struct in6_addr addr;
-+ int retry;
-+};
-+
-+/* clear all has from candidate list. do this when a new dhaad reply
-+ * is received. */
-+int mipv6_mn_flush_ha_candidate(struct list_head *ha)
-+{
-+ struct list_head *p, *tmp;
-+ struct dhaad_halist *e;
-+
-+ list_for_each_safe(p, tmp, ha) {
-+ e = list_entry(p, struct dhaad_halist, list);
-+ list_del(p);
-+ kfree(e);
-+ e = NULL;
-+ }
-+ return 0;
-+}
-+
-+/* add new ha to candidates. only done when dhaad reply is received. */
-+int mipv6_mn_add_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct dhaad_halist *e;
-+
-+ e = kmalloc(sizeof(*e), GFP_ATOMIC);
-+ memset(e, 0, sizeof(*e));
-+ ipv6_addr_copy(&e->addr, addr);
-+
-+ list_add_tail(&e->list, ha);
-+ return 0;
-+}
-+
-+#define MAX_RETRIES_PER_HA 3
-+
-+/* get next ha candidate. this is done when dhaad reply has been
-+ * received and we want to register with the best available ha. */
-+int mipv6_mn_get_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct list_head *p;
-+
-+ list_for_each(p, ha) {
-+ struct dhaad_halist *e;
-+ e = list_entry(p, typeof(*e), list);
-+ if (e->retry >= 0 && e->retry < MAX_RETRIES_PER_HA) {
-+ ipv6_addr_copy(addr, &e->addr);
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/* change candidate status. if registration with ha fails, we
-+ * increase retry for ha candidate. if retry is >= 3 we set it to -1
-+ * (failed), do get_ha_candidate() again */
-+int mipv6_mn_try_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct list_head *p;
-+
-+ list_for_each(p, ha) {
-+ struct dhaad_halist *e;
-+ e = list_entry(p, typeof(*e), list);
-+ if (ipv6_addr_cmp(addr, &e->addr) == 0) {
-+ if (e->retry >= MAX_RETRIES_PER_HA) e->retry = -1;
-+ else if (e->retry >= 0) e->retry++;
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_mn_get_bulifetime - Get lifetime for a binding update
-+ * @home_addr: home address for BU
-+ * @coa: care-of address for BU
-+ * @flags: flags used for BU
-+ *
-+ * Returns maximum lifetime for BUs determined by the lifetime of
-+ * care-of address and the lifetime of home address.
-+ **/
-+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr, struct in6_addr *coa,
-+ __u8 flags)
-+{
-+ struct inet6_ifaddr *ifp_hoa, *ifp_coa;
-+ __u32 lifetime = (flags & MIPV6_BU_F_HOME ?
-+ HA_BU_DEF_LIFETIME : CN_BU_DEF_LIFETIME);
-+
-+ ifp_hoa = ipv6_get_ifaddr(home_addr, NULL);
-+ if(!ifp_hoa) {
-+ DEBUG(DBG_INFO, "home address missing");
-+ return 0;
-+ }
-+ if (!(ifp_hoa->flags & IFA_F_PERMANENT)){
-+ if (ifp_hoa->valid_lft)
-+ lifetime = min_t(__u32, lifetime, ifp_hoa->valid_lft);
-+ else
-+ DEBUG(DBG_ERROR, "Zero lifetime for home address");
-+ }
-+ in6_ifa_put(ifp_hoa);
-+
-+ ifp_coa = ipv6_get_ifaddr(coa, NULL);
-+ if (!ifp_coa) {
-+ DEBUG(DBG_INFO, "care-of address missing");
-+ return 0;
-+ }
-+ if (!(ifp_coa->flags & IFA_F_PERMANENT)) {
-+ if(ifp_coa->valid_lft)
-+ lifetime = min_t(__u32, lifetime, ifp_coa->valid_lft);
-+ else
-+ DEBUG(DBG_ERROR,
-+ "Zero lifetime for care-of address");
-+ }
-+ in6_ifa_put(ifp_coa);
-+
-+ DEBUG(DBG_INFO, "Lifetime for binding is %ld", lifetime);
-+ return lifetime;
-+}
-+
-+static int
-+mipv6_mn_tnl_rcv_send_bu_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ struct ipv6hdr *inner;
-+ struct ipv6hdr *outer = skb->nh.ipv6h;
-+ struct mn_info *minfo = NULL;
-+ __u32 lifetime;
-+ __u8 user_flags = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if (!is_mip6_tnl(t))
-+ return IP6_TNL_ACCEPT;
-+
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled"
-+ " not doing route optimization");
-+ return IP6_TNL_ACCEPT;
-+ }
-+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*inner)))
-+ return IP6_TNL_DROP;
-+
-+ inner = (struct ipv6hdr *)skb->h.raw;
-+
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(&inner->daddr);
-+
-+ if (!minfo) {
-+ DEBUG(DBG_WARNING, "MN info missing");
-+ read_unlock(&mn_info_lock);
-+ return IP6_TNL_ACCEPT;
-+ }
-+ DEBUG(DBG_DATADUMP, "MIPV6 MN: Received a tunneled IPv6 packet"
-+ " to %x:%x:%x:%x:%x:%x:%x:%x,"
-+ " from %x:%x:%x:%x:%x:%x:%x:%x with\n tunnel header"
-+ "daddr: %x:%x:%x:%x:%x:%x:%x:%x,"
-+ "saddr: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&inner->daddr), NIPV6ADDR(&inner->saddr),
-+ NIPV6ADDR(&outer->daddr), NIPV6ADDR(&outer->saddr));
-+
-+ spin_lock(&minfo->lock);
-+
-+ /* We don't send bus in response to all tunneled packets */
-+
-+ if (!ipv6_addr_cmp(&minfo->ha, &inner->saddr)) {
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_ERROR, "HA BUG: Received a tunneled packet "
-+ "originally sent by home agent, not sending BU");
-+ return IP6_TNL_ACCEPT;
-+ }
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+
-+ DEBUG(DBG_DATADUMP, "Sending BU to correspondent node");
-+
-+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0;
-+
-+ if (inner->nexthdr != IPPROTO_DSTOPTS &&
-+ inner->nexthdr != IPPROTO_MOBILITY) {
-+ struct in6_addr coa;
-+ /* Don't start RR when receiving ICMP error messages */
-+ if (inner->nexthdr == IPPROTO_ICMPV6) {
-+ int ptr = (u8*)(inner+1) - skb->data;
-+ u8 type;
-+
-+ if (skb_copy_bits(skb,
-+ ptr+offsetof(struct icmp6hdr,
-+ icmp6_type),
-+ &type, 1)
-+ || !(type & ICMPV6_INFOMSG_MASK)) {
-+ return IP6_TNL_ACCEPT;
-+ }
-+ }
-+ lifetime = mipv6_mn_get_bulifetime(&inner->daddr,
-+ &outer->daddr, 0);
-+ if (lifetime &&
-+ !mipv6_get_care_of_address(&inner->daddr, &coa)) {
-+ write_lock(&bul_lock);
-+ mipv6_send_bu(&inner->daddr, &inner->saddr, &coa,
-+ INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1,
-+ user_flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ }
-+ }
-+ DEBUG(DBG_DATADUMP, "setting rcv_tunnel flag in skb");
-+ skb->security |= MIPV6_RCV_TUNNEL;
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_send_bu_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_FIRST,
-+ mipv6_mn_tnl_rcv_send_bu_hook
-+};
-+
-+static int
-+mipv6_mn_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_encapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_xmit_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_ENCAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_mn_tnl_xmit_stats_hook
-+};
-+
-+static int
-+mipv6_mn_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_decapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_mn_tnl_rcv_stats_hook
-+};
-+
-+static void mn_check_tunneled_packet(struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ /* If tunnel flag was set */
-+ if (skb->security & MIPV6_RCV_TUNNEL) {
-+ struct in6_addr coa;
-+ __u32 lifetime;
-+ __u8 user_flags = 0;
-+ int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
-+ int len = skb->len - ptr;
-+ __u8 nexthdr = skb->nh.ipv6h->nexthdr;
-+
-+ if (len < 0)
-+ return;
-+
-+ ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
-+ if (ptr < 0)
-+ return;
-+
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled");
-+ return;
-+ }
-+ if (nexthdr == IPPROTO_MOBILITY)
-+ return;
-+
-+ /* Don't start RR when receiving ICMP error messages */
-+ if (nexthdr == IPPROTO_ICMPV6) {
-+ u8 type;
-+
-+ if (skb_copy_bits(skb,
-+ ptr+offsetof(struct icmp6hdr,
-+ icmp6_type),
-+ &type, 1)
-+ || !(type & ICMPV6_INFOMSG_MASK)) {
-+ return;
-+ }
-+ }
-+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0;
-+ mipv6_get_care_of_address(&skb->nh.ipv6h->daddr, &coa);
-+ lifetime = mipv6_mn_get_bulifetime(&skb->nh.ipv6h->daddr,
-+ &coa, 0);
-+
-+ DEBUG(DBG_WARNING, "packet to address %x:%x:%x:%x:%x:%x:%x:%x"
-+ "was tunneled. Sending BU to CN"
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&skb->nh.ipv6h->daddr),
-+ NIPV6ADDR(&skb->nh.ipv6h->saddr));
-+ /* This should work also with home address option */
-+
-+ write_lock(&bul_lock);
-+ mipv6_send_bu(&skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr,
-+ &coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, user_flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ }
-+}
-+
-+static int sched_mv_home_addr_task(struct in6_addr *haddr, int plen_new,
-+ int newif, int oldif, struct handoff *ho)
-+{
-+ int alloc_size;
-+ struct ifr_holder *ifrh;
-+
-+ alloc_size = sizeof(*ifrh) + (ho ? sizeof(*ho): 0);
-+ if ((ifrh = kmalloc(alloc_size, GFP_ATOMIC)) == NULL) {
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ return -1;
-+ }
-+ if (ho) {
-+ ifrh->ho = (struct handoff *)((struct ifr_holder *)(ifrh + 1));
-+ memcpy(ifrh->ho, ho, sizeof(*ho));
-+ } else
-+ ifrh->ho = NULL;
-+
-+ /* must queue task to avoid deadlock with rtnl */
-+ ifrh->ifr.ifr6_ifindex = newif;
-+ ifrh->ifr.ifr6_prefixlen = plen_new;
-+ ipv6_addr_copy(&ifrh->ifr.ifr6_addr, haddr);
-+ ifrh->old_ifi = oldif;
-+
-+ spin_lock_bh(&ifrh_lock);
-+ list_add_tail(&ifrh->list, &ifrh_list);
-+ spin_unlock_bh(&ifrh_lock);
-+
-+ schedule_task(&mv_home_addr_task);
-+
-+ return 0;
-+}
-+
-+static void send_ret_home_ns(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ int ifindex)
-+{
-+ struct in6_addr nil;
-+ struct in6_addr mcaddr;
-+ struct net_device *dev = dev_get_by_index(ifindex);
-+ if (!dev)
-+ return;
-+ memset(&nil, 0, sizeof(nil));
-+ addrconf_addr_solict_mult(home_addr, &mcaddr);
-+ ndisc_send_ns(dev, NULL, home_addr, &mcaddr, &nil);
-+ dev_put(dev);
-+}
-+
-+static inline int ha_is_reachable(int ifindex, struct in6_addr *ha)
-+{
-+ struct net_device *dev;
-+ int reachable = 0;
-+
-+ dev = dev_get_by_index(ifindex);
-+ if (dev) {
-+ struct neighbour *neigh;
-+ if ((neigh = ndisc_get_neigh(dev, ha)) != NULL) {
-+ read_lock_bh(&neigh->lock);
-+ if (neigh->nud_state&NUD_VALID)
-+ reachable = 1;
-+ read_unlock_bh(&neigh->lock);
-+ neigh_release(neigh);
-+ }
-+ dev_put(dev);
-+ }
-+ return reachable;
-+}
-+
-+static int mn_ha_handoff(struct handoff *ho)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+ struct in6_addr *coa= ho->coa;
-+ int wait_mv_home = 0;
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(lh, &mn_info_list) {
-+ __u8 has_home_reg;
-+ int ifindex;
-+ struct in6_addr ha;
-+ __u8 athome;
-+ __u32 lifetime;
-+ struct mipv6_bul_entry *entry = NULL;
-+
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ has_home_reg = minfo->has_home_reg;
-+ ifindex = minfo->ifindex;
-+ ipv6_addr_copy(&ha, &minfo->ha);
-+
-+ if (mipv6_prefix_compare(&ho->rtr_addr, &minfo->home_addr,
-+ ho->plen)) {
-+ if (minfo->has_home_reg)
-+ athome = minfo->is_at_home = MN_RETURNING_HOME;
-+ else
-+ athome = minfo->is_at_home = MN_AT_HOME;
-+ coa = &minfo->home_addr;
-+
-+ spin_unlock(&minfo->lock);
-+#if 0
-+ /* Cancel prefix solicitation, rtr is our HA */
-+ mipv6_pfx_cancel_send(&ho->rtr_addr, ifindex);
-+#endif
-+ minfo->ifindex = ho->ifindex;
-+
-+ if (minfo->has_home_reg &&
-+ !ha_is_reachable(ho->ifindex, &minfo->ha)) {
-+ send_ret_home_ns(&minfo->ha,
-+ &minfo->home_addr,
-+ ho->ifindex);
-+ mipv6_mdet_set_curr_rtr_reachable(0);
-+ wait_mv_home++;
-+ }
-+ if (ifindex != ho->ifindex){
-+ wait_mv_home++;
-+ DEBUG(DBG_INFO,
-+ "Moving home address back to "
-+ "the home interface");
-+ sched_mv_home_addr_task(&minfo->home_addr,
-+ 128,
-+ ho->ifindex,
-+ ifindex, ho);
-+ }
-+ if (!has_home_reg || wait_mv_home)
-+ continue;
-+
-+ lifetime = 0;
-+
-+ } else {
-+ athome = minfo->is_at_home = MN_NOT_AT_HOME;
-+ if (minfo->ifindex_user != minfo->ifindex) {
-+ DEBUG(DBG_INFO, "Scheduling home address move to virtual interface");
-+ sched_mv_home_addr_task(&minfo->home_addr,
-+ 128,
-+ minfo->ifindex_user,
-+ minfo->ifindex, ho); /* Is minfo->ifindex correct */
-+
-+ wait_mv_home++;
-+ }
-+ minfo->ifindex = minfo->ifindex_user;
-+ spin_unlock(&minfo->lock);
-+ if (wait_mv_home)
-+ continue;
-+ if (!has_home_reg &&
-+ init_home_registration(&minfo->home_addr,
-+ ho->coa)) {
-+ continue;
-+ }
-+ lifetime = mipv6_mn_get_bulifetime(&minfo->home_addr,
-+ ho->coa,
-+ MIPV6_BU_F_HOME);
-+
-+ }
-+ write_lock(&bul_lock);
-+ if (!(entry = mipv6_bul_get(&ha, &minfo->home_addr)) ||
-+ !(entry->flags & MIPV6_BU_F_HOME)) {
-+ DEBUG(DBG_ERROR,
-+ "Unable to find home registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x!\n",
-+ NIPV6ADDR(&minfo->home_addr));
-+ write_unlock(&bul_lock);
-+ continue;
-+ }
-+ DEBUG(DBG_INFO, "Sending home de ? %d registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n"
-+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "with lifetime %ld",
-+ (athome != MN_NOT_AT_HOME),
-+ NIPV6ADDR(&entry->home_addr),
-+ NIPV6ADDR(&entry->cn_addr), lifetime);
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return wait_mv_home;
-+}
-+/**
-+ * mn_cn_handoff - called for every bul entry to send BU to CN
-+ * @rawentry: bul entry
-+ * @args: handoff event
-+ * @sortkey:
-+ *
-+ * Since MN can have many home addresses and home networks, every BUL
-+ * entry needs to be checked
-+ **/
-+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bul_entry *entry = (struct mipv6_bul_entry *)rawentry;
-+ struct in6_addr *coa = (struct in6_addr *)args;
-+
-+ DEBUG_FUNC();
-+
-+ /* Home registrations already handled by mn_ha_handoff */
-+ if (entry->flags & MIPV6_BU_F_HOME)
-+ return ITERATOR_CONT;
-+
-+ /* BUL is locked by mipv6_mobile_node_moved which calls us
-+ through mipv6_bul_iterate */
-+
-+ if (mipv6_prefix_compare(coa,
-+ &entry->home_addr,
-+ 64)) {
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ &entry->home_addr, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags, 0,
-+ NULL);
-+ } else {
-+ u32 lifetime = mipv6_mn_get_bulifetime(&entry->home_addr,
-+ coa,
-+ entry->flags);
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags,
-+ lifetime, NULL);
-+ }
-+ return ITERATOR_CONT;
-+}
-+
-+
-+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bul_entry *bul = (struct mipv6_bul_entry *)rawentry;
-+ struct bul_inval_args *arg = (struct bul_inval_args *)args;
-+
-+ DEBUG_FUNC();
-+
-+ if (!ipv6_addr_cmp(arg->cn, &bul->cn_addr) &&
-+ (!ipv6_addr_cmp(arg->mn, &bul->home_addr) ||
-+ !ipv6_addr_cmp(arg->mn, &bul->coa))) {
-+ if (arg->all_rr_states || !bul->rr ||
-+ (bul->rr->rr_state != RR_INIT &&
-+ bul->rr->rr_state != RR_DONE)) {
-+ bul->state = ACK_ERROR;
-+ bul->callback = bul_entry_expired;
-+ bul->callback_time = jiffies +
-+ DUMB_CN_BU_LIFETIME * HZ;
-+ bul->expire = bul->callback_time;
-+ DEBUG(DBG_INFO, "BUL entry set to ACK_ERROR");
-+ mipv6_bul_reschedule(bul);
-+ }
-+ }
-+ return ITERATOR_CONT;
-+}
-+/**
-+ * init_home_registration - start Home Registration process
-+ * @home_addr: home address
-+ * @coa: care-of address
-+ *
-+ * Checks whether we have a Home Agent address for this home address.
-+ * If not starts Dynamic Home Agent Address Discovery. Otherwise
-+ * tries to register with home agent if not already registered.
-+ * Returns 1, if home registration process is started and 0 otherwise
-+ **/
-+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa)
-+{
-+ struct mn_info *hinfo;
-+ struct in6_addr ha;
-+ __u8 man_conf;
-+ int ifindex;
-+ __u32 lifetime;
-+ __u8 user_flags = 0, flags;
-+
-+ DEBUG_FUNC();
-+
-+ read_lock_bh(&mn_info_lock);
-+ if ((hinfo = mipv6_mninfo_get_by_home(home_addr)) == NULL) {
-+ DEBUG(DBG_ERROR, "No mn_info found for address: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ read_unlock_bh(&mn_info_lock);
-+ return -ENOENT;
-+ }
-+ spin_lock(&hinfo->lock);
-+ if (mipv6_prefix_compare(&hinfo->home_addr, coa, hinfo->home_plen)) {
-+ spin_unlock(&hinfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+ DEBUG(DBG_INFO, "Adding home address, MN at home");
-+ return 1;
-+ }
-+ if (ipv6_addr_any(&hinfo->ha)) {
-+ int dhaad_id = mipv6_get_dhaad_id();
-+ hinfo->dhaad_id = dhaad_id;
-+ spin_unlock(&hinfo->lock);
-+ mipv6_icmpv6_send_dhaad_req(home_addr, hinfo->home_plen, dhaad_id);
-+ read_unlock_bh(&mn_info_lock);
-+ DEBUG(DBG_INFO,
-+ "Home Agent address not set, initiating DHAAD");
-+ return 1;
-+ }
-+ ipv6_addr_copy(&ha, &hinfo->ha);
-+ man_conf = hinfo->man_conf;
-+ ifindex = hinfo->ifindex;
-+ spin_unlock(&hinfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+#if 0
-+ if (man_conf)
-+ mipv6_pfx_add_ha(&ha, coa, ifindex);
-+#endif
-+ if (mipv6_bul_exists(&ha, home_addr)) {
-+ DEBUG(DBG_INFO, "BU already sent to HA");
-+ return 0;
-+ }
-+ /* user flags received through sysctl */
-+ user_flags |= mip6node_cnf.bu_lladdr ? MIPV6_BU_F_LLADDR : 0;
-+ user_flags |= mip6node_cnf.bu_keymgm ? MIPV6_BU_F_KEYMGM : 0;
-+
-+ flags = MIPV6_BU_F_HOME | MIPV6_BU_F_ACK | user_flags;
-+
-+ lifetime = mipv6_mn_get_bulifetime(home_addr, coa, flags);
-+
-+ DEBUG(DBG_INFO, "Sending initial home registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n"
-+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "with lifetime %ld, prefixlength %d",
-+ NIPV6ADDR(home_addr), NIPV6ADDR(&ha), lifetime, 0);
-+
-+ write_lock_bh(&bul_lock);
-+ mipv6_send_bu(home_addr, &ha, coa, INITIAL_BINDACK_DAD_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, flags, lifetime, NULL);
-+ write_unlock_bh(&bul_lock);
-+
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_mobile_node_moved - Send BUs to all HAs and CNs
-+ * @ho: handoff structure contains the new and previous routers
-+ *
-+ * Event for handoff. Sends BUs everyone on Binding Update List.
-+ **/
-+int mipv6_mobile_node_moved(struct handoff *ho)
-+{
-+#if 0
-+ int bu_to_prev_router = 1;
-+#endif
-+ int dummy;
-+
-+ DEBUG_FUNC();
-+
-+ ma_ctl_upd_iface(ho->ifindex,
-+ MA_IFACE_CURRENT | MA_IFACE_HAS_ROUTER, &dummy);
-+
-+ /* First send BU to HA, then to all other nodes that are on BU list */
-+ if (mn_ha_handoff(ho) != 0)
-+ return 0; /* Wait for move home address task */
-+#if 0
-+ /* Add current care-of address to mn_info list, if current router acts
-+ as a HA.*/
-+
-+ if (ho->home_address && bu_to_prev_router)
-+ mipv6_mninfo_add(ho->coa, ho->plen,
-+ MN_AT_HOME, 0, &ho->rtr_addr,
-+ ho->plen, ROUTER_BU_DEF_LIFETIME,
-+ 0);
-+
-+#endif
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_mn_send_home_na - send NA when returning home
-+ * @haddr: home address to advertise
-+ *
-+ * After returning home, MN must advertise all its valid addresses in
-+ * home link to all nodes.
-+ **/
-+void mipv6_mn_send_home_na(struct in6_addr *haddr)
-+{
-+ struct net_device *dev = NULL;
-+ struct in6_addr mc_allnodes;
-+ struct mn_info *hinfo = NULL;
-+
-+ read_lock(&mn_info_lock);
-+ hinfo = mipv6_mninfo_get_by_home(haddr);
-+ if (!hinfo) {
-+ read_unlock(&mn_info_lock);
-+ return;
-+ }
-+ spin_lock(&hinfo->lock);
-+ hinfo->is_at_home = MN_AT_HOME;
-+ dev = dev_get_by_index(hinfo->ifindex);
-+ spin_unlock(&hinfo->lock);
-+ read_unlock(&mn_info_lock);
-+ if (dev == NULL) {
-+ DEBUG(DBG_ERROR, "Send home_na: device not found.");
-+ return;
-+ }
-+
-+ ipv6_addr_all_nodes(&mc_allnodes);
-+ ndisc_send_na(dev, NULL, &mc_allnodes, haddr, 0, 0, 1, 1);
-+ dev_put(dev);
-+}
-+
-+static int mn_use_hao(struct in6_addr *daddr, struct in6_addr *saddr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct mn_info *minfo = NULL;
-+ int add_ha = 0;
-+
-+ read_lock_bh(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(saddr);
-+ if (minfo && minfo->is_at_home != MN_AT_HOME) {
-+ read_lock_bh(&bul_lock);
-+ if ((entry = mipv6_bul_get(daddr, saddr)) == NULL) {
-+ read_unlock_bh(&bul_lock);
-+ read_unlock_bh(&mn_info_lock);
-+ return add_ha;
-+ }
-+ add_ha = (entry->state != ACK_ERROR &&
-+ (!entry->rr || entry->rr->rr_state == RR_DONE ||
-+ entry->flags & MIPV6_BU_F_HOME));
-+ read_unlock_bh(&bul_lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return add_ha;
-+}
-+
-+static int
-+mn_dev_event(struct notifier_block *nb, unsigned long event, void *ptr)
-+{
-+ struct net_device *dev = ptr;
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+ int newif = 0;
-+
-+ /* here are probably the events we need to worry about */
-+ switch (event) {
-+ case NETDEV_UP:
-+ DEBUG(DBG_DATADUMP, "New netdevice %s registered.", dev->name);
-+ if (dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev))
-+ ma_ctl_add_iface(dev->ifindex);
-+
-+ break;
-+ case NETDEV_GOING_DOWN:
-+ DEBUG(DBG_DATADUMP, "Netdevice %s disappeared.", dev->name);
-+ /*
-+ * Go through mn_info list and move all home addresses on the
-+ * netdev going down to a new device. This will make it
-+ * practically impossible for the home address to return home,
-+ * but allow MN to retain its connections using the address.
-+ */
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (minfo->ifindex == dev->ifindex) {
-+ if (sched_mv_home_addr_task(&minfo->home_addr, 128,
-+ minfo->ifindex_user,
-+ 0, NULL) < 0) {
-+ minfo->ifindex = 0;
-+ spin_unlock(&minfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+ return NOTIFY_DONE;
-+ } else {
-+ minfo->ifindex = minfo->ifindex_user;
-+ if (minfo->is_at_home) {
-+ minfo->is_at_home = 0;
-+
-+ }
-+ newif = minfo->ifindex_user;
-+ }
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+
-+ read_unlock_bh(&mn_info_lock);
-+ }
-+ ma_ctl_upd_iface(dev->ifindex, MA_IFACE_NOT_PRESENT, &newif);
-+ mipv6_mdet_del_if(dev->ifindex);
-+
-+ return NOTIFY_DONE;
-+}
-+
-+struct notifier_block mipv6_mn_dev_notifier = {
-+ mn_dev_event,
-+ NULL,
-+ 0 /* check if using zero is ok */
-+};
-+
-+static void deprecate_addr(struct mn_info *minfo)
-+{
-+ /*
-+ * Lookup address from IPv6 address list and set deprecated flag
-+ */
-+
-+}
-+
-+/*
-+ * Required because we can only modify addresses after the packet is
-+ * constructed. We otherwise mess with higher level protocol
-+ * pseudoheaders. With strict protocol layering life would be SO much
-+ * easier!
-+ */
-+static unsigned int modify_xmit_addrs(unsigned int hooknum,
-+ struct sk_buff **pskb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn) (struct sk_buff *))
-+{
-+ struct sk_buff *skb = *pskb;
-+
-+ DEBUG_FUNC();
-+
-+ if (skb) {
-+ struct ipv6hdr *hdr = skb->nh.ipv6h;
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct mipv6_bul_entry *bule;
-+ struct in6_addr *daddr;
-+
-+ if (!ipv6_addr_any(&opt->hoa))
-+ daddr = &opt->hoa;
-+ else
-+ daddr = &hdr->daddr;
-+
-+ /* We don't consult bul when sending a BU to avoid deadlock, since
-+ * BUL is already locked.
-+ */
-+
-+
-+ if (opt->mipv6_flags & MIPV6_SND_HAO &&
-+ !(opt->mipv6_flags & MIPV6_SND_BU)) {
-+ write_lock(&bul_lock);
-+ bule = mipv6_bul_get(daddr, &hdr->saddr);
-+ if (!bule) {
-+ write_unlock(&bul_lock);
-+ return NF_ACCEPT;
-+ }
-+ if (!bule->rr || bule->rr->rr_state == RR_DONE ||
-+ bule->flags & MIPV6_BU_F_HOME) {
-+ DEBUG(DBG_DATADUMP,
-+ "Replace source address with CoA and reroute");
-+ ipv6_addr_copy(&hdr->saddr, &bule->coa);
-+ skb->nfcache |= NFC_ALTERED;
-+ }
-+ write_unlock(&bul_lock);
-+ } else if (opt->mipv6_flags & MIPV6_SND_HAO) {
-+ mipv6_get_care_of_address(&hdr->saddr, &hdr->saddr);
-+ skb->nfcache |= NFC_ALTERED;
-+ }
-+ }
-+ return NF_ACCEPT;
-+}
-+
-+/* We set a netfilter hook so that we can modify outgoing packet's
-+ * source addresses
-+ */
-+struct nf_hook_ops addr_modify_hook_ops = {
-+ {NULL, NULL}, /* List head, no predecessor, no successor */
-+ modify_xmit_addrs,
-+ PF_INET6,
-+ NF_IP6_LOCAL_OUT,
-+ NF_IP6_PRI_FIRST /* Should be of EXTREMELY high priority since we
-+ * do not want to mess with IPSec (possibly
-+ * implemented as packet filter)
-+ */
-+};
-+
-+#define MN_INFO_LEN 77
-+
-+static int mn_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct list_head *p;
-+ struct mn_info *minfo;
-+ int len = 0, skip = 0;
-+
-+ DEBUG_FUNC();
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(p, &mn_info_list) {
-+ if (len < offset / MN_INFO_LEN) {
-+ skip++;
-+ continue;
-+ }
-+ if (len >= length)
-+ break;
-+ minfo = list_entry(p, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ len += sprintf(buffer + len, "%02d %08x%08x%08x%08x %02x "
-+ "%08x%08x%08x%08x %d %d\n",
-+ minfo->ifindex,
-+ ntohl(minfo->home_addr.s6_addr32[0]),
-+ ntohl(minfo->home_addr.s6_addr32[1]),
-+ ntohl(minfo->home_addr.s6_addr32[2]),
-+ ntohl(minfo->home_addr.s6_addr32[3]),
-+ minfo->home_plen,
-+ ntohl(minfo->ha.s6_addr32[0]),
-+ ntohl(minfo->ha.s6_addr32[1]),
-+ ntohl(minfo->ha.s6_addr32[2]),
-+ ntohl(minfo->ha.s6_addr32[3]),
-+ minfo->is_at_home, minfo->has_home_reg);
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % MN_INFO_LEN;
-+
-+ len -= offset % MN_INFO_LEN;
-+
-+ if (len > length)
-+ len = length;
-+ if (len < 0)
-+ len = 0;
-+
-+ return len;
-+}
-+
-+int mipv6_mn_ha_nd_update(struct net_device *dev,
-+ struct in6_addr *ha, u8 *lladdr)
-+{
-+ int valid = 0;
-+ struct neighbour *neigh;
-+ if ((neigh = ndisc_get_neigh(dev, ha))) {
-+ read_lock(&neigh->lock);
-+ valid = neigh->nud_state & NUD_VALID;
-+ read_unlock(&neigh->lock);
-+ if (!valid && lladdr)
-+ neigh_update(neigh, lladdr, NUD_REACHABLE, 0, 1);
-+ neigh_release(neigh);
-+ }
-+ return valid;
-+}
-+
-+int mipv6_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ struct mn_info *minfo;
-+
-+ if (!(minfo = mipv6_mninfo_get_by_home(&ifp->addr)) ||
-+ ipv6_addr_any(&minfo->ha))
-+ return 0;
-+
-+ if (mipv6_mn_ha_nd_update(ifp->idev->dev, &minfo->ha, lladdr))
-+ mipv6_mdet_retrigger_ho();
-+ return 1;
-+}
-+
-+int __init mipv6_mn_init(void)
-+{
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ if (mipv6_add_tnl_to_ha())
-+ return -ENODEV;
-+
-+ mipv6_bul_init(MIPV6_BUL_SIZE);
-+ mip6_fn.mn_use_hao = mn_use_hao;
-+ mip6_fn.mn_check_tunneled_packet = mn_check_tunneled_packet;
-+ INIT_TQUEUE(&mv_home_addr_task, mv_home_addr, NULL);
-+
-+ ma_ctl_init();
-+ for (dev = dev_base; dev; dev = dev->next) {
-+ if (dev->flags & IFF_UP &&
-+ dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev)) {
-+ ma_ctl_add_iface(dev->ifindex);
-+ }
-+ }
-+ DEBUG(DBG_INFO, "Multiaccess support initialized");
-+
-+ register_netdevice_notifier(&mipv6_mn_dev_notifier);
-+ register_inet6addr_notifier(&mipv6_mn_inet6addr_notifier);
-+
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_send_bu_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_stats_ops);
-+
-+ MIPV6_SETCALL(mipv6_set_home, mipv6_mn_set_home);
-+
-+ mipv6_initialize_mdetect();
-+
-+ /* COA to home transformation hook */
-+ MIPV6_SETCALL(mipv6_get_home_address, mipv6_get_saddr_hook);
-+ MIPV6_SETCALL(mipv6_mn_ha_probe, mipv6_mn_ha_probe);
-+ MIPV6_SETCALL(mipv6_is_home_addr, mipv6_mn_is_home_addr);
-+ proc_net_create("mip6_mninfo", 0, mn_proc_info);
-+ /* Set packet modification hook (source addresses) */
-+ nf_register_hook(&addr_modify_hook_ops);
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mn_exit(void)
-+{
-+ struct list_head *lh, *tmp;
-+ struct mn_info *minfo;
-+ DEBUG_FUNC();
-+
-+ mip6_fn.mn_use_hao = NULL;
-+ mip6_fn.mn_check_tunneled_packet = NULL;
-+
-+ MIPV6_RESETCALL(mipv6_set_home);
-+ MIPV6_RESETCALL(mipv6_get_home_address);
-+ MIPV6_RESETCALL(mipv6_mn_ha_probe);
-+ MIPV6_RESETCALL(mipv6_is_home_addr);
-+ nf_unregister_hook(&addr_modify_hook_ops);
-+ proc_net_remove("mip6_mninfo");
-+ mipv6_shutdown_mdetect();
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_send_bu_ops);
-+ ma_ctl_clean();
-+
-+ unregister_inet6addr_notifier(&mipv6_mn_inet6addr_notifier);
-+ unregister_netdevice_notifier(&mipv6_mn_dev_notifier);
-+ write_lock_bh(&mn_info_lock);
-+
-+ list_for_each_safe(lh, tmp, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if (minfo->is_at_home == MN_NOT_AT_HOME)
-+ deprecate_addr(minfo);
-+ list_del(&minfo->list);
-+ kfree(minfo);
-+ }
-+ write_unlock_bh(&mn_info_lock);
-+ mipv6_bul_exit();
-+ flush_scheduled_tasks();
-+ mipv6_del_tnl_to_ha();
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mn.h linux-2.4.25/net/ipv6/mobile_ip6/mn.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mn.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mn.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,96 @@
-+/*
-+ * MIPL Mobile IPv6 Mobile Node header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MN_H
-+#define _MN_H
-+
-+#include <linux/in6.h>
-+
-+/* constants for sending of BUs*/
-+#define HA_BU_DEF_LIFETIME 10000
-+#define CN_BU_DEF_LIFETIME 420 /* Max lifetime for RR bindings from RFC 3775 */
-+#define DUMB_CN_BU_LIFETIME 600 /* BUL entry lifetime in case of dumb CN */
-+#define ROUTER_BU_DEF_LIFETIME 30 /* For packet forwarding from previous coa */
-+#define ERROR_DEF_LIFETIME DUMB_CN_BU_LIFETIME
-+
-+extern rwlock_t mn_info_lock;
-+
-+#define MN_NOT_AT_HOME 0
-+#define MN_RETURNING_HOME 1
-+#define MN_AT_HOME 2
-+
-+/*
-+ * Mobile Node information record
-+ */
-+struct mn_info {
-+ struct in6_addr home_addr;
-+ struct in6_addr ha;
-+ __u8 home_plen;
-+ __u8 is_at_home;
-+ __u8 has_home_reg;
-+ __u8 man_conf;
-+ int ifindex;
-+ int ifindex_user;
-+ unsigned long home_addr_expires;
-+ unsigned short dhaad_id;
-+ struct list_head list;
-+ spinlock_t lock;
-+};
-+
-+/* prototypes for interface functions */
-+int mipv6_mn_init(void);
-+void mipv6_mn_exit(void);
-+
-+struct handoff;
-+
-+/* Interface to movement detection */
-+int mipv6_mobile_node_moved(struct handoff *ho);
-+
-+void mipv6_mn_send_home_na(struct in6_addr *haddr);
-+/* Init home reg. with coa */
-+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa);
-+
-+/* mn_info functions that require locking by caller */
-+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr);
-+
-+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent);
-+
-+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id);
-+
-+/* "safe" mn_info functions */
-+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen,
-+ int isathome, unsigned long lifetime, struct in6_addr *ha,
-+ int ha_plen, unsigned long ha_lifetime, int man_conf);
-+
-+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only);
-+
-+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg);
-+
-+int mipv6_mn_is_at_home(struct in6_addr *addr);
-+
-+int mipv6_mn_is_home_addr(struct in6_addr *addr);
-+
-+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr,
-+ struct in6_addr *coa, __u8 flags);
-+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey);
-+
-+int mipv6_mn_ha_nd_update(struct net_device *dev,
-+ struct in6_addr *ha, u8 *lladdr);
-+
-+struct bul_inval_args {
-+ int all_rr_states;
-+ struct in6_addr *cn;
-+ struct in6_addr *mn;
-+};
-+
-+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey);
-+
-+#endif /* _MN_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr.h linux-2.4.25/net/ipv6/mobile_ip6/mobhdr.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,101 @@
-+/*
-+ * MIPL Mobile IPv6 Mobility Header send and receive
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MOBHDR_H
-+#define _MOBHDR_H
-+
-+#include <net/mipv6.h>
-+
-+/* RR states for mipv6_send_bu() */
-+#define RR_INIT 0x00
-+#define RR_WAITH 0x01
-+#define RR_WAITC 0x02
-+#define RR_WAITHC 0x13
-+#define RR_DONE 0x10
-+
-+#define MH_UNKNOWN_CN 1
-+#define MH_AUTH_FAILED 2
-+#define MH_SEQUENCE_MISMATCH 3
-+
-+struct mipv6_bul_entry;
-+struct sk_buff;
-+
-+int mipv6_mh_common_init(void);
-+void mipv6_mh_common_exit(void);
-+int mipv6_mh_mn_init(void);
-+void mipv6_mh_mn_exit(void);
-+
-+struct mipv6_mh_opt {
-+ struct mipv6_mo_alt_coa *alt_coa;
-+ struct mipv6_mo_nonce_indices *nonce_indices;
-+ struct mipv6_mo_bauth_data *auth_data;
-+ struct mipv6_mo_br_advice *br_advice;
-+ int freelen;
-+ int totlen;
-+ u8 *next_free;
-+ u8 data[0];
-+};
-+
-+struct mobopt {
-+ struct mipv6_mo_alt_coa *alt_coa;
-+ struct mipv6_mo_nonce_indices *nonce_indices;
-+ struct mipv6_mo_bauth_data *auth_data;
-+ struct mipv6_mo_br_advice *br_advice;
-+};
-+
-+struct mipv6_mh_opt *alloc_mh_opts(int totlen);
-+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data);
-+int parse_mo_tlv(void *mos, int len, struct mobopt *opts);
-+int mipv6_add_pad(u8 *data, int n);
-+
-+struct mipv6_auth_parm {
-+ struct in6_addr *coa;
-+ struct in6_addr *cn_addr;
-+ __u8 *k_bu;
-+};
-+
-+int send_mh(struct in6_addr *daddr, struct in6_addr *saddr,
-+ u8 msg_type, u8 msg_len, u8 *msg,
-+ struct in6_addr *hao_addr, struct in6_addr *rth_addr,
-+ struct mipv6_mh_opt *ops, struct mipv6_auth_parm *parm);
-+
-+int mipv6_mh_register(int type, int (*func)(struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *));
-+
-+void mipv6_mh_unregister(int type);
-+
-+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct mipv6_mh_opt *ops);
-+
-+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *coa, __u32 initdelay,
-+ __u32 maxackdelay, __u8 exp, __u8 flags,
-+ __u32 lifetime, struct mipv6_mh_opt *ops);
-+
-+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *home, __u8 status);
-+
-+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *auth_coa, struct in6_addr *rep_coa,
-+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu);
-+
-+/* Binding Authentication Data Option routines */
-+#define MAX_HASH_LENGTH 20
-+#define MIPV6_RR_MAC_LENGTH 12
-+
-+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 *aud_data, __u8 *k_bu);
-+
-+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 optlen, struct mipv6_mo_bauth_data *aud,
-+ __u8 *k_bu);
-+#endif /* _MOBHDR_H */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_common.c linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_common.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_common.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_common.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,1210 @@
-+/*
-+ * Mobile IPv6 Mobility Header Common Functions
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id: s.mh_recv.c 1.159 02/10/16 15:01:29+03:00 antti@traci.mipl.mediapoli.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.
-+ *
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/types.h>
-+#include <linux/in6.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipsec.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+#include <net/checksum.h>
-+#include <net/protocol.h>
-+
-+#include "stats.h"
-+#include "debug.h"
-+#include "mobhdr.h"
-+#include "bcache.h"
-+
-+#include "rr_crypto.h"
-+#include "exthdrs.h"
-+#include "config.h"
-+
-+#define MIPV6_MH_MAX MIPV6_MH_BE
-+struct mh_proto {
-+ int (*func) (struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct mipv6_mh *);
-+};
-+
-+static struct mh_proto mh_rcv[MIPV6_MH_MAX];
-+
-+int mipv6_mh_register(int type, int (*func)(struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *))
-+{
-+ if (mh_rcv[type].func != NULL)
-+ return -1;
-+
-+ mh_rcv[type].func = func;
-+
-+ return 0;
-+}
-+
-+void mipv6_mh_unregister(int type)
-+{
-+ if (type < 0 || type > MIPV6_MH_MAX)
-+ return;
-+
-+ mh_rcv[type].func = NULL;
-+}
-+
-+struct socket *mipv6_mh_socket = NULL;
-+
-+/* TODO: Fix fragmentation */
-+static int dstopts_getfrag(
-+ const void *data, struct in6_addr *addr,
-+ char *buff, unsigned int offset, unsigned int len)
-+{
-+ memcpy(buff, data + offset, len);
-+ return 0;
-+}
-+
-+struct mipv6_mh_opt *alloc_mh_opts(int totlen)
-+{
-+ struct mipv6_mh_opt *ops;
-+
-+ ops = kmalloc(sizeof(*ops) + totlen, GFP_ATOMIC);
-+ if (ops == NULL)
-+ return NULL;
-+
-+ memset(ops, 0, sizeof(*ops));
-+ ops->next_free = ops->data;
-+ ops->freelen = totlen;
-+
-+ return ops;
-+}
-+
-+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data)
-+{
-+ struct mipv6_mo *mo;
-+
-+ if (ops->next_free == NULL) {
-+ DEBUG(DBG_ERROR, "No free room for option");
-+ return -ENOMEM;
-+ }
-+ if (ops->freelen < len + 2) {
-+ DEBUG(DBG_ERROR, "No free room for option");
-+ return -ENOMEM;
-+ }
-+ else {
-+ ops->freelen -= (len + 2);
-+ ops->totlen += (len + 2);
-+ }
-+
-+ mo = (struct mipv6_mo *)ops->next_free;
-+ mo->type = type;
-+ mo->length = len;
-+
-+ switch (type) {
-+ case MIPV6_OPT_ALTERNATE_COA:
-+ ops->alt_coa = (struct mipv6_mo_alt_coa *)mo;
-+ ipv6_addr_copy(&ops->alt_coa->addr, (struct in6_addr *)data);
-+ break;
-+ case MIPV6_OPT_NONCE_INDICES:
-+ DEBUG(DBG_INFO, "Added nonce indices pointer");
-+ ops->nonce_indices = (struct mipv6_mo_nonce_indices *)mo;
-+ ops->nonce_indices->home_nonce_i = *(__u16 *)data;
-+ ops->nonce_indices->careof_nonce_i = *((__u16 *)data + 1);
-+ break;
-+ case MIPV6_OPT_AUTH_DATA:
-+ DEBUG(DBG_INFO, "Added opt auth_data pointer");
-+ ops->auth_data = (struct mipv6_mo_bauth_data *)mo;
-+ break;
-+ case MIPV6_OPT_BIND_REFRESH_ADVICE:
-+ ops->br_advice = (struct mipv6_mo_br_advice *)mo;
-+ ops->br_advice->refresh_interval = htons(*(u16 *)data);
-+ break;
-+ default:
-+ DEBUG(DBG_ERROR, "Unknow option type");
-+ break;
-+ }
-+
-+ if (ops->freelen == 0)
-+ ops->next_free = NULL;
-+ else
-+ ops->next_free += (len + 2);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Calculates required padding with xn + y requirement with offset
-+ */
-+static inline int optpad(int xn, int y, int offset)
-+{
-+ return ((y - offset) & (xn - 1));
-+}
-+
-+static int option_pad(int type, int offset)
-+{
-+ if (type == MIPV6_OPT_ALTERNATE_COA)
-+ return optpad(8, 6, offset); /* 8n + 6 */
-+ if (type == MIPV6_OPT_BIND_REFRESH_ADVICE ||
-+ type == MIPV6_OPT_NONCE_INDICES)
-+ return optpad(2, 0, offset); /* 2n */
-+ return 0;
-+}
-+
-+/*
-+ * Add Pad1 or PadN option to data
-+ */
-+int mipv6_add_pad(u8 *data, int n)
-+{
-+ struct mipv6_mo_padn *padn;
-+
-+ if (n <= 0) return 0;
-+ if (n == 1) {
-+ *data = MIPV6_OPT_PAD1;
-+ return 1;
-+ }
-+ padn = (struct mipv6_mo_padn *)data;
-+ padn->type = MIPV6_OPT_PADN;
-+ padn->length = n - 2;
-+ memset(padn->data, 0, n - 2);
-+ return n;
-+}
-+
-+/*
-+ * Write options to mobility header buffer
-+ */
-+static int prepare_mh_opts(u8 *optdata, int off, struct mipv6_mh_opt *ops)
-+{
-+ u8 *nextopt = optdata;
-+ int offset = off, pad = 0;
-+
-+ if (ops == NULL) {
-+ nextopt = NULL;
-+ return -1;
-+ }
-+
-+ if (ops->alt_coa) {
-+ pad = option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->alt_coa, sizeof(struct mipv6_mo_alt_coa));
-+ nextopt += sizeof(struct mipv6_mo_alt_coa);
-+ offset += pad + sizeof(struct mipv6_mo_alt_coa);
-+ }
-+
-+ if (ops->br_advice) {
-+ pad = option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->br_advice, sizeof(struct mipv6_mo_br_advice));
-+ nextopt += sizeof(struct mipv6_mo_br_advice);
-+ offset += pad + sizeof(struct mipv6_mo_br_advice);
-+ }
-+
-+ if (ops->nonce_indices) {
-+ pad = option_pad(MIPV6_OPT_NONCE_INDICES, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->nonce_indices, sizeof(struct mipv6_mo_nonce_indices));
-+ nextopt += sizeof(struct mipv6_mo_nonce_indices);
-+ offset += pad + sizeof(struct mipv6_mo_nonce_indices);
-+ }
-+
-+ if (ops->auth_data) {
-+ /* This option should always be the last. Header
-+ * length must be a multiple of 8 octects, so we pad
-+ * if necessary. */
-+ pad = optpad(8, 0, offset + ops->auth_data->length + 2);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->auth_data, ops->auth_data->length + 2);
-+ nextopt += ops->auth_data->length + 2;
-+ }
-+ nextopt = NULL;
-+
-+ return 0;
-+}
-+
-+static int calculate_mh_opts(struct mipv6_mh_opt *ops, int mh_len)
-+{
-+ int offset = mh_len;
-+
-+ if (ops == NULL)
-+ return 0;
-+
-+ if (ops->alt_coa)
-+ offset += sizeof(struct mipv6_mo_alt_coa)
-+ + option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
-+
-+ if (ops->br_advice)
-+ offset += sizeof(struct mipv6_mo_br_advice)
-+ + option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
-+
-+ if (ops->nonce_indices)
-+ offset += sizeof(struct mipv6_mo_nonce_indices)
-+ + option_pad(MIPV6_OPT_NONCE_INDICES, offset);
-+
-+ if (ops->auth_data) /* no alignment */
-+ offset += ops->auth_data->length + 2;
-+
-+ return offset - mh_len;
-+}
-+
-+/*
-+ *
-+ * Mobility Header Message send functions
-+ *
-+ */
-+
-+/**
-+ * send_mh - builds and sends a MH msg
-+ *
-+ * @daddr: destination address for packet
-+ * @saddr: source address for packet
-+ * @msg_type: type of MH
-+ * @msg_len: message length
-+ * @msg: MH type specific data
-+ * @hao_addr: home address for home address option
-+ * @rth_addr: routing header address
-+ * @ops: mobility options
-+ * @parm: auth data
-+ *
-+ * Builds MH, appends the type specific msg data to the header and
-+ * sends the packet with a home address option, if a home address was
-+ * given. Returns 0, if everything succeeded and a negative error code
-+ * otherwise.
-+ **/
-+int send_mh(struct in6_addr *daddr,
-+ struct in6_addr *saddr,
-+ u8 msg_type, u8 msg_len, u8 *msg,
-+ struct in6_addr *hao_addr,
-+ struct in6_addr *rth_addr,
-+ struct mipv6_mh_opt *ops,
-+ struct mipv6_auth_parm *parm)
-+{
-+ struct flowi fl;
-+ struct mipv6_mh *mh;
-+ struct sock *sk = mipv6_mh_socket->sk;
-+ struct ipv6_txoptions *txopt = NULL;
-+ int tot_len = sizeof(struct mipv6_mh) + msg_len;
-+ int padded_len = 0, txopt_len = 0;
-+
-+ DEBUG_FUNC();
-+ /* Add length of options */
-+ tot_len += calculate_mh_opts(ops, tot_len);
-+ /* Needs to be a multiple of 8 octets */
-+ padded_len = tot_len + optpad(8, 0, tot_len);
-+
-+ mh = sock_kmalloc(sk, padded_len, GFP_ATOMIC);
-+ if (!mh) {
-+ DEBUG(DBG_ERROR, "memory allocation failed");
-+ return -ENOMEM;
-+ }
-+
-+ memset(&fl, 0, sizeof(fl));
-+ fl.proto = IPPROTO_MOBILITY;
-+ fl.fl6_dst = daddr;
-+ fl.fl6_src = saddr;
-+ fl.fl6_flowlabel = 0;
-+ fl.oif = sk->bound_dev_if;
-+
-+ if (hao_addr || rth_addr) {
-+ __u8 *opt_ptr;
-+
-+ if (hao_addr)
-+ txopt_len += sizeof(struct mipv6_dstopt_homeaddr) + 6;
-+ if (rth_addr)
-+ txopt_len += sizeof(struct rt2_hdr);
-+
-+ txopt_len += sizeof(*txopt);
-+ txopt = sock_kmalloc(sk, txopt_len, GFP_ATOMIC);
-+ if (txopt == NULL) {
-+ DEBUG(DBG_ERROR, "No socket space left");
-+ sock_kfree_s(sk, mh, padded_len);
-+ return -ENOMEM;
-+ }
-+ memset(txopt, 0, txopt_len);
-+ txopt->tot_len = txopt_len;
-+ opt_ptr = (__u8 *) (txopt + 1);
-+ if (hao_addr) {
-+ int holen = sizeof(struct mipv6_dstopt_homeaddr) + 6;
-+ txopt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
-+ txopt->opt_flen += holen;
-+ opt_ptr += holen;
-+ mipv6_append_dst1opts(txopt->dst1opt, saddr,
-+ NULL, holen);
-+ txopt->mipv6_flags = MIPV6_SND_HAO | MIPV6_SND_BU;
-+ }
-+ if (rth_addr) {
-+ int rtlen = sizeof(struct rt2_hdr);
-+ txopt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
-+ txopt->opt_nflen += rtlen;
-+ opt_ptr += rtlen;
-+ mipv6_append_rt2hdr(txopt->srcrt2, rth_addr);
-+ }
-+ }
-+
-+ /* Fill in the fields of MH */
-+ mh->payload = NEXTHDR_NONE;
-+ mh->length = (padded_len >> 3) - 1; /* Units of 8 octets - 1 */
-+ mh->type = msg_type;
-+ mh->reserved = 0;
-+ mh->checksum = 0;
-+
-+ memcpy(mh->data, msg, msg_len);
-+ prepare_mh_opts(mh->data + msg_len, msg_len + sizeof(*mh), ops);
-+ /* If BAD is present, this is already done. */
-+ mipv6_add_pad((u8 *)mh + tot_len, padded_len - tot_len);
-+
-+ if (parm && parm->k_bu && ops && ops->auth_data) {
-+ /* Calculate the position of the authorization data before adding checksum*/
-+ mipv6_auth_build(parm->cn_addr, parm->coa, (__u8 *)mh,
-+ (__u8 *)mh + padded_len - MIPV6_RR_MAC_LENGTH, parm->k_bu);
-+ }
-+ /* Calculate the MH checksum */
-+ mh->checksum = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst,
-+ padded_len, IPPROTO_MOBILITY,
-+ csum_partial((char *)mh, padded_len, 0));
-+ ip6_build_xmit(sk, dstopts_getfrag, mh, &fl, padded_len, txopt, 255,
-+ MSG_DONTWAIT);
-+ /* dst cache must be cleared so RR messages can be routed through
-+ different interfaces */
-+ sk_dst_reset(sk);
-+
-+ if (txopt_len)
-+ sock_kfree_s(sk, txopt, txopt_len);
-+ sock_kfree_s(sk, mh, padded_len);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_brr - send a Binding Refresh Request
-+ * @saddr: source address for BRR
-+ * @daddr: destination address for BRR
-+ * @ops: mobility options
-+ *
-+ * Sends a binding request. On a mobile node, use the mobile node's
-+ * home address for @saddr. Returns 0 on success, negative on
-+ * failure.
-+ **/
-+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct mipv6_mh_opt *ops)
-+{
-+ struct mipv6_mh_brr br;
-+
-+ memset(&br, 0, sizeof(br));
-+ /* We don't need to explicitly add a RH to brr, since it will be
-+ * included automatically, if a BCE exists
-+ */
-+ MIPV6_INC_STATS(n_brr_sent);
-+ return send_mh(daddr, saddr, MIPV6_MH_BRR, sizeof(br), (u8 *)&br,
-+ NULL, NULL, ops, NULL);
-+}
-+
-+/**
-+ * mipv6_send_ba - send a Binding Acknowledgement
-+ * @saddr: source address for BA
-+ * @daddr: destination address for BA
-+ * @reply_coa: destination care-of address of MN
-+ * @auth_coa: care-of address of MN used for authentication
-+ * @status: status field value
-+ * @sequence: sequence number from BU
-+ * @lifetime: granted lifetime for binding in seconds
-+ * @ops: mobility options
-+ *
-+ * Send a binding acknowledgement. On a mobile node, use the mobile
-+ * node's home address for saddr. Returns 0 on success, non-zero on
-+ * failure.
-+ **/
-+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *auth_coa, struct in6_addr *rep_coa,
-+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu)
-+{
-+ struct mipv6_mh_ba ba;
-+ struct mipv6_auth_parm parm;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ops_len = 0, ret = 0;
-+ struct mipv6_bce bc_entry;
-+ int coming_home = 0;
-+ int bypass_tnl = 0;
-+
-+ memset(&ba, 0, sizeof(ba));
-+
-+ ba.status = status;
-+ ba.sequence = htons(sequence);
-+ ba.lifetime = htons(lifetime >> 2);
-+
-+ DEBUG(DBG_INFO, "sending a status %d BA %s authenticator to MN \n"
-+ "%x:%x:%x:%x:%x:%x:%x:%x at care of address \n"
-+ "%x:%x:%x:%x:%x:%x:%x:%x : with lifetime %d and \n"
-+ " sequence number %d",
-+ status, k_bu ? "with" : "without",
-+ NIPV6ADDR(daddr), NIPV6ADDR(auth_coa), lifetime, sequence);
-+
-+ memset(&parm, 0, sizeof(parm));
-+ parm.coa = auth_coa;
-+ parm.cn_addr = saddr;
-+
-+ if (k_bu) {
-+ ops_len += sizeof(struct mipv6_mo_bauth_data) +
-+ MIPV6_RR_MAC_LENGTH;
-+ parm.k_bu = k_bu;
-+ }
-+
-+ if (mip6node_cnf.binding_refresh_advice) {
-+ ops_len += sizeof(struct mipv6_mo_br_advice);
-+ }
-+ if (ops_len) {
-+ ops = alloc_mh_opts(ops_len);
-+ if (ops == NULL) {
-+ DEBUG(DBG_WARNING, "Out of memory");
-+ return -ENOMEM;
-+ }
-+ if (mip6node_cnf.binding_refresh_advice > 0) {
-+ if (append_mh_opt(ops, MIPV6_OPT_BIND_REFRESH_ADVICE, 2,
-+ &mip6node_cnf.binding_refresh_advice) < 0) {
-+ DEBUG(DBG_WARNING, "Adding BRA failed");
-+ if (ops)
-+ kfree(ops);
-+ return -ENOMEM;
-+ }
-+ }
-+ if (k_bu) {
-+ if (append_mh_opt(ops, MIPV6_OPT_AUTH_DATA,
-+ MIPV6_RR_MAC_LENGTH, NULL) < 0) {
-+ DEBUG(DBG_WARNING, "Adding BAD failed");
-+ if (ops)
-+ kfree(ops);
-+ return -ENOMEM;
-+ }
-+ }
-+ }
-+ coming_home = !ipv6_addr_cmp(rep_coa, daddr);
-+
-+ bypass_tnl = (coming_home &&
-+ !mipv6_bcache_get(daddr, saddr, &bc_entry) &&
-+ bc_entry.flags&MIPV6_BU_F_HOME &&
-+ status >= 128);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del)
-+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (coming_home)
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
-+ NULL, NULL, ops, &parm);
-+ else
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
-+ NULL, rep_coa, ops, &parm);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add)
-+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (ret == 0) {
-+ if (status < 128) {
-+ MIPV6_INC_STATS(n_ba_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_ban_sent);
-+ }
-+ }
-+
-+ if (ops)
-+ kfree(ops);
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_be - send a Binding Error message
-+ * @saddr: source address for BE
-+ * @daddr: destination address for BE
-+ * @home: Home Address in offending packet (if any)
-+ *
-+ * Sends a binding error. On a mobile node, use the mobile node's
-+ * home address for @saddr. Returns 0 on success, negative on
-+ * failure.
-+ **/
-+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *home, __u8 status)
-+{
-+ struct mipv6_mh_be be;
-+ int ret = 0;
-+ struct mipv6_bce bc_entry;
-+ int bypass_tnl = 0;
-+
-+ if (ipv6_addr_is_multicast(daddr))
-+ return -EINVAL;
-+
-+ memset(&be, 0, sizeof(be));
-+ be.status = status;
-+ if (home)
-+ ipv6_addr_copy(&be.home_addr, home);
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0 &&
-+ bc_entry.flags&MIPV6_BU_F_HOME)
-+ bypass_tnl = 1;
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del)
-+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BE, sizeof(be), (u8 *)&be,
-+ NULL, NULL, NULL, NULL);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add)
-+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (ret == 0)
-+ MIPV6_INC_STATS(n_be_sent);
-+
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_send_addr_test - send a HoT or CoT message
-+ * @saddr: source address
-+ * @daddr: destination address
-+ * @msg_type: HoT or CoT message
-+ * @init: HoTI or CoTI message
-+ *
-+ * Send a reply to HoTI or CoTI message.
-+ **/
-+static int mipv6_send_addr_test(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ int msg_type,
-+ struct mipv6_mh_addr_ti *init)
-+{
-+ u_int8_t *kgen_token = NULL;
-+ struct mipv6_mh_addr_test addr_test;
-+ struct mipv6_rr_nonce *nonce;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ret = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if ((nonce = mipv6_rr_get_new_nonce())== NULL) {
-+ DEBUG(DBG_WARNING, "Nonce creation failed");
-+ return 0;
-+ }
-+ if (mipv6_rr_cookie_create(daddr, &kgen_token, nonce->index)) {
-+ DEBUG(DBG_WARNING, "No cookie");
-+ return 0;
-+ }
-+
-+ addr_test.nonce_index = nonce->index;
-+ memcpy(addr_test.init_cookie, init->init_cookie,
-+ MIPV6_RR_COOKIE_LENGTH);
-+ memcpy(addr_test.kgen_token, kgen_token,
-+ MIPV6_RR_COOKIE_LENGTH);
-+
-+ /* No options defined */
-+ ret = send_mh(daddr, saddr, msg_type, sizeof(addr_test),
-+ (u8 *)&addr_test, NULL, NULL, ops, NULL);
-+
-+ if (ret == 0) {
-+ if (msg_type == MIPV6_MH_HOT) {
-+ MIPV6_INC_STATS(n_hot_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_cot_sent);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void bc_cache_add(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ __u8 ba_status = SUCCESS;
-+
-+ if (lifetime > MAX_RR_BINDING_LIFE)
-+ lifetime = MAX_RR_BINDING_LIFE;
-+
-+ if (mipv6_bcache_add(ifindex, daddr, haddr, coa, lifetime,
-+ sequence, flags, CACHE_ENTRY) != 0) {
-+ DEBUG(DBG_ERROR, "binding failed.");
-+ ba_status = INSUFFICIENT_RESOURCES;
-+ }
-+
-+ if (flags & MIPV6_BU_F_ACK) {
-+ DEBUG(DBG_INFO, "sending ack (code=%d)", ba_status);
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence,
-+ lifetime, k_bu);
-+ }
-+}
-+
-+static void bc_cn_home_add(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa,
-+ HOME_REGISTRATION_NOT_SUPPORTED,
-+ sequence, lifetime, k_bu);
-+}
-+
-+static void bc_cache_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+ __u8 status = SUCCESS;
-+
-+ /* Cached Care-of Address Deregistration */
-+ if (mipv6_bcache_exists(haddr, daddr) == CACHE_ENTRY) {
-+ mipv6_bcache_delete(haddr, daddr, CACHE_ENTRY);
-+ } else {
-+ DEBUG(DBG_INFO, "entry is not in cache");
-+ status = REASON_UNSPECIFIED;
-+ }
-+ if (flags & MIPV6_BU_F_ACK) {
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence,
-+ 0, k_bu);
-+ }
-+}
-+
-+static void bc_cn_home_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+}
-+
-+/**
-+ * parse_mo_tlv - Parse TLV-encoded Mobility Options
-+ * @mos: pointer to Mobility Options
-+ * @len: total length of options
-+ * @opts: structure to store option pointers
-+ *
-+ * Parses Mobility Options passed in @mos. Stores pointers in @opts
-+ * to all valid mobility options found in @mos. Unknown options and
-+ * padding (%MIPV6_OPT_PAD1 and %MIPV6_OPT_PADN) is ignored and
-+ * skipped.
-+ **/
-+int parse_mo_tlv(void *mos, int len, struct mobopt *opts)
-+{
-+ struct mipv6_mo *curr = (struct mipv6_mo *)mos;
-+ int left = len;
-+
-+ while (left > 0) {
-+ int optlen = 0;
-+ if (curr->type == MIPV6_OPT_PAD1)
-+ optlen = 1;
-+ else
-+ optlen = 2 + curr->length;
-+
-+ if (optlen > left)
-+ goto bad;
-+
-+ switch (curr->type) {
-+ case MIPV6_OPT_PAD1:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PAD1 at %x", curr);
-+ break;
-+ case MIPV6_OPT_PADN:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PADN at %x", curr);
-+ break;
-+ case MIPV6_OPT_ALTERNATE_COA:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_ACOA at %x", curr);
-+ opts->alt_coa = (struct mipv6_mo_alt_coa *)curr;
-+ break;
-+ case MIPV6_OPT_NONCE_INDICES:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_NONCE_INDICES at %x", curr);
-+ opts->nonce_indices =
-+ (struct mipv6_mo_nonce_indices *)curr;
-+ break;
-+ case MIPV6_OPT_AUTH_DATA:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_AUTH_DATA at %x", curr);
-+ opts->auth_data = (struct mipv6_mo_bauth_data *)curr;
-+ break;
-+ case MIPV6_OPT_BIND_REFRESH_ADVICE:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_BIND_REFRESH_ADVICE at %x", curr);
-+ opts->br_advice = (struct mipv6_mo_br_advice *)curr;
-+ break;
-+ default:
-+ DEBUG(DBG_INFO, "MO Unknown option type %d at %x, ignoring.",
-+ curr->type, curr);
-+ /* unknown mobility option, ignore and skip */
-+ }
-+
-+ (u8 *)curr += optlen;
-+ left -= optlen;
-+ }
-+
-+ if (left == 0)
-+ return 0;
-+ bad:
-+ return -1;
-+}
-+
-+/*
-+ *
-+ * Mobility Header Message handlers
-+ *
-+ */
-+
-+static int mipv6_handle_mh_testinit(struct sk_buff *skb,
-+ struct in6_addr *cn,
-+ struct in6_addr *lcoa,
-+ struct in6_addr *saddr,
-+ struct in6_addr *fcoa,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_addr_ti *ti = (struct mipv6_mh_addr_ti *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*ti);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than H/C TestInit");
-+ return -1;
-+ }
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled");
-+ return -1;
-+ }
-+ if (lcoa || fcoa) {
-+ DEBUG(DBG_INFO, "H/C TestInit has HAO or RTH2, dropped.");
-+ return -1;
-+ }
-+
-+ if (mh->type == MIPV6_MH_HOTI) {
-+ MIPV6_INC_STATS(n_hoti_rcvd);
-+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_HOT, ti);
-+ } else if (mh->type == MIPV6_MH_COTI) {
-+ MIPV6_INC_STATS(n_coti_rcvd);
-+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_COT, ti);
-+ } else
-+ return -1; /* Impossible to get here */
-+}
-+
-+/**
-+ * mipv6_handle_mh_bu - Binding Update handler
-+ * @src: care-of address of sender
-+ * @dst: our address
-+ * @haddr: home address of sender
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ * Handles Binding Update. Packet and offset to option are passed.
-+ * Returns 0 on success, otherwise negative.
-+ **/
-+static int mipv6_handle_mh_bu(struct sk_buff *skb,
-+ struct in6_addr *dst,
-+ struct in6_addr *unused,
-+ struct in6_addr *haddr,
-+ struct in6_addr *coaddr,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_bu *bu = (struct mipv6_mh_bu *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ int auth = 0;
-+ int dereg; /* Is this deregistration? */
-+ int addr_type;
-+
-+ struct mipv6_bce bc_entry;
-+ struct in6_addr *coa, *reply_coa;
-+ __u8 *key_bu = NULL; /* RR BU authentication key */
-+ __u8 flags = bu->flags;
-+ __u16 sequence;
-+ __u32 lifetime;
-+ __u16 nonce_ind = (__u16) -1;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*bu);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than BU");
-+ MIPV6_INC_STATS(n_bu_drop.invalid);
-+ return -1;
-+ }
-+
-+ addr_type = ipv6_addr_type(haddr);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL || !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+
-+ /* If HAO not present, CoA == HAddr */
-+ if (coaddr == NULL)
-+ coa = haddr;
-+ else {
-+ coa = coaddr;
-+ addr_type = ipv6_addr_type(coa);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+ }
-+ reply_coa = coa;
-+
-+ sequence = ntohs(bu->sequence);
-+ if (bu->lifetime == 0xffff)
-+ lifetime = 0xffffffff;
-+ else
-+ lifetime = ntohs(bu->lifetime) << 2;
-+
-+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
-+
-+ if (opt_len > 0) {
-+ struct mobopt opts;
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(bu + 1, opt_len, &opts) < 0) {
-+ MIPV6_INC_STATS(n_bu_drop.invalid);
-+ return -1;
-+ }
-+ /*
-+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_NONCE_INDICES,
-+ * MIPV6_OPT_ALT_COA
-+ */
-+ if (opts.alt_coa) {
-+ coa = &opts.alt_coa->addr;
-+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
-+ }
-+ addr_type = ipv6_addr_type(coa);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+
-+ if (flags & MIPV6_BU_F_HOME) {
-+ if (opts.nonce_indices)
-+ return -1;
-+ } else {
-+ u8 ba_status = 0;
-+ u8 *h_ckie = NULL, *c_ckie = NULL; /* Home and care-of cookies */
-+
-+ /* BUs to CN MUST include authorization data and nonce indices options */
-+ if (!opts.auth_data || !opts.nonce_indices) {
-+ DEBUG(DBG_WARNING,
-+ "Route optimization BU without authorization material, aborting processing");
-+ return MH_AUTH_FAILED;
-+ }
-+ if (mipv6_rr_cookie_create(
-+ haddr, &h_ckie, opts.nonce_indices->home_nonce_i) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "mipv6_rr_cookie_create failed for home cookie");
-+ ba_status = EXPIRED_HOME_NONCE_INDEX;
-+ }
-+ nonce_ind = opts.nonce_indices->home_nonce_i;
-+ /* Don't create the care-of cookie, if MN deregisters */
-+ if (!dereg && mipv6_rr_cookie_create(
-+ coa, &c_ckie,
-+ opts.nonce_indices->careof_nonce_i) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "mipv6_rr_cookie_create failed for coa cookie");
-+ if (ba_status == 0)
-+ ba_status = EXPIRED_CAREOF_NONCE_INDEX;
-+ else
-+ ba_status = EXPIRED_NONCES;
-+ }
-+ if (ba_status == 0) {
-+ if (dereg)
-+ key_bu = mipv6_rr_key_calc(h_ckie, NULL);
-+ else
-+ key_bu = mipv6_rr_key_calc(h_ckie, c_ckie);
-+ mh->checksum = 0;/* TODO: Don't mangle the packet */
-+ if (key_bu && mipv6_auth_check(
-+ dst, coa, (__u8 *)mh, msg_len + sizeof(*mh), opts.auth_data, key_bu) == 0) {
-+ DEBUG(DBG_INFO, "mipv6_auth_check OK for BU");
-+ auth = 1;
-+ } else {
-+ DEBUG(DBG_WARNING,
-+ "BU Authentication failed");
-+ }
-+ }
-+ if (h_ckie)
-+ kfree(h_ckie);
-+ if (c_ckie)
-+ kfree(c_ckie);
-+ if (ba_status != 0) {
-+ MIPV6_INC_STATS(n_bu_drop.auth);
-+ mipv6_send_ba(dst, haddr, coa,
-+ reply_coa, ba_status,
-+ sequence, 0, NULL);
-+ goto out;
-+ }
-+ }
-+
-+ }
-+ /* Require authorization option for RO, home reg is protected by IPsec */
-+ if (!(flags & MIPV6_BU_F_HOME) && !auth) {
-+ MIPV6_INC_STATS(n_bu_drop.auth);
-+ if (key_bu)
-+ kfree(key_bu);
-+ return MH_AUTH_FAILED;
-+ }
-+
-+ if (mipv6_bcache_get(haddr, dst, &bc_entry) == 0) {
-+ if ((bc_entry.flags&MIPV6_BU_F_HOME) !=
-+ (flags&MIPV6_BU_F_HOME)) {
-+ DEBUG(DBG_INFO,
-+ "Registration type change. Sending BA REG_TYPE_CHANGE_FORBIDDEN");
-+ mipv6_send_ba(dst, haddr, coa, reply_coa,
-+ REG_TYPE_CHANGE_FORBIDDEN,
-+ sequence, lifetime, key_bu);
-+ goto out;
-+ }
-+ if (!MIPV6_SEQ_GT(sequence, bc_entry.seq)) {
-+ DEBUG(DBG_INFO,
-+ "Sequence number mismatch. Sending BA SEQUENCE_NUMBER_OUT_OF_WINDOW");
-+ mipv6_send_ba(dst, haddr, coa, reply_coa,
-+ SEQUENCE_NUMBER_OUT_OF_WINDOW,
-+ bc_entry.seq, lifetime, key_bu);
-+ goto out;
-+ }
-+ }
-+
-+ if (!dereg) {
-+ int ifindex;
-+ struct rt6_info *rt;
-+
-+ /* Avoid looping binding cache entries */
-+ if (mipv6_bcache_get(coa, dst, &bc_entry) == 0) {
-+ DEBUG(DBG_WARNING, "Looped BU, dropping the packet");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "calling bu_add.");
-+ if ((rt = rt6_lookup(haddr, dst, 0, 0)) != NULL) {
-+ ifindex = rt->rt6i_dev->ifindex;
-+ dst_release(&rt->u.dst);
-+ } else {
-+ /*
-+ * Can't process the BU since the right interface is
-+ * not found.
-+ */
-+ DEBUG(DBG_WARNING, "No route entry found for handling "
-+ "a BU request, (using 0 as index)");
-+ ifindex = 0;
-+ }
-+ if (flags & MIPV6_BU_F_HOME)
-+ mip6_fn.bce_home_add(ifindex, dst, haddr, coa,
-+ reply_coa, lifetime, sequence,
-+ flags, key_bu);
-+ else
-+ mip6_fn.bce_cache_add(ifindex, dst, haddr, coa,
-+ reply_coa, lifetime, sequence,
-+ flags, key_bu);
-+ } else {
-+ DEBUG(DBG_INFO, "calling BCE delete.");
-+
-+ if (flags & MIPV6_BU_F_HOME)
-+ mip6_fn.bce_home_del(dst, haddr, coa, reply_coa,
-+ sequence, flags, key_bu);
-+ else {
-+ mipv6_rr_invalidate_nonce(nonce_ind);
-+ mip6_fn.bce_cache_del(dst, haddr, coa, reply_coa,
-+ sequence, flags, key_bu);
-+ }
-+ }
-+ out:
-+ MIPV6_INC_STATS(n_bu_rcvd);
-+ if (key_bu)
-+ kfree(key_bu);
-+ return 0;
-+}
-+
-+static int mipv6_mh_rcv(struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct mipv6_mh *mh;
-+ struct in6_addr *lhome, *fhome, *lcoa = NULL, *fcoa = NULL;
-+ int ret = 0;
-+
-+ fhome = &skb->nh.ipv6h->saddr;
-+ lhome = &skb->nh.ipv6h->daddr;
-+
-+ if (opt->hao != 0) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao);
-+ fcoa = &hao->addr;
-+ }
-+
-+ if (opt->srcrt2 != 0) {
-+ struct rt2_hdr *rt2;
-+ rt2 = (struct rt2_hdr *)((u8 *)skb->nh.raw + opt->srcrt2);
-+ lcoa = &rt2->addr;
-+ }
-+
-+ /* Verify checksum is correct */
-+ if (skb->ip_summed == CHECKSUM_HW) {
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
-+ skb->csum)) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "MIPv6 MH hw checksum failed\n");
-+ skb->ip_summed = CHECKSUM_NONE;
-+ }
-+ }
-+ if (skb->ip_summed == CHECKSUM_NONE) {
-+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
-+ skb_checksum(skb, 0, skb->len, 0))) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "MIPv6 MH checksum failed\n");
-+ goto bad;
-+ }
-+ }
-+
-+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*mh)) ||
-+ !pskb_may_pull(skb,
-+ skb->h.raw-skb->data+((skb->h.raw[1]+1)<<3))) {
-+ DEBUG(DBG_INFO, "MIPv6 MH invalid length");
-+ kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ mh = (struct mipv6_mh *) skb->h.raw;
-+
-+ /* Verify there are no more headers after the MH */
-+ if (mh->payload != NEXTHDR_NONE) {
-+ __u32 pos = (__u32)&mh->payload - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "MIPv6 MH error");
-+ goto bad;
-+ }
-+
-+ if (mh->type > MIPV6_MH_MAX) {
-+ /* send binding error */
-+ printk("Invalid mobility header type (%d)\n", mh->type);
-+ mipv6_send_be(lhome, fcoa ? fcoa : fhome,
-+ fcoa ? fhome : NULL,
-+ MIPV6_BE_UNKNOWN_MH_TYPE);
-+ goto bad;
-+ }
-+ if (mh_rcv[mh->type].func != NULL) {
-+ ret = mh_rcv[mh->type].func(skb, lhome, lcoa, fhome, fcoa, mh);
-+ } else {
-+ DEBUG(DBG_INFO, "No handler for MH Type %d", mh->type);
-+ goto bad;
-+ }
-+
-+ kfree_skb(skb);
-+ return 0;
-+
-+bad:
-+ MIPV6_INC_STATS(n_mh_in_error);
-+ kfree_skb(skb);
-+ return 0;
-+
-+}
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+struct inet6_protocol mipv6_mh_protocol =
-+{
-+ mipv6_mh_rcv, /* handler */
-+ NULL /* error control */
-+};
-+#else
-+struct inet6_protocol mipv6_mh_protocol =
-+{
-+ mipv6_mh_rcv, /* handler */
-+ NULL, /* error control */
-+ NULL, /* next */
-+ IPPROTO_MOBILITY, /* protocol ID */
-+ 0, /* copy */
-+ NULL, /* data */
-+ "MIPv6 MH" /* name */
-+};
-+#endif
-+
-+/*
-+ *
-+ * Code module init/exit functions
-+ *
-+ */
-+
-+int __init mipv6_mh_common_init(void)
-+{
-+ struct sock *sk;
-+ int err;
-+
-+ mip6_fn.bce_home_add = bc_cn_home_add;
-+ mip6_fn.bce_cache_add = bc_cache_add;
-+ mip6_fn.bce_home_del = bc_cn_home_delete;
-+ mip6_fn.bce_cache_del = bc_cache_delete;
-+
-+ mipv6_mh_socket = sock_alloc();
-+ if (mipv6_mh_socket == NULL) {
-+ printk(KERN_ERR
-+ "Failed to create the MIP6 MH control socket.\n");
-+ return -1;
-+ }
-+ mipv6_mh_socket->type = SOCK_RAW;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_MOBILITY,
-+ &mipv6_mh_socket)) < 0) {
-+ printk(KERN_ERR
-+ "Failed to initialize the MIP6 MH control socket (err %d).\n",
-+ err);
-+ sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL; /* for safety */
-+ return err;
-+ }
-+
-+ sk = mipv6_mh_socket->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->sndbuf = 64 * 1024 + sizeof(struct sk_buff);
-+ sk->prot->unhash(sk);
-+
-+ memset(&mh_rcv, 0, sizeof(mh_rcv));
-+ mh_rcv[MIPV6_MH_HOTI].func = mipv6_handle_mh_testinit;
-+ mh_rcv[MIPV6_MH_COTI].func = mipv6_handle_mh_testinit;
-+ mh_rcv[MIPV6_MH_BU].func = mipv6_handle_mh_bu;
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+ if (inet6_add_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY) < 0) {
-+ printk(KERN_ERR "Failed to register MOBILITY protocol\n");
-+ sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL;
-+ return -EAGAIN;
-+ }
-+#else
-+ inet6_add_protocol(&mipv6_mh_protocol);
-+#endif
-+ /* To disable the use of dst_cache,
-+ * which slows down the sending of BUs ??
-+ */
-+ sk->dst_cache=NULL;
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mh_common_exit(void)
-+{
-+ if (mipv6_mh_socket) sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL; /* For safety. */
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+ inet6_del_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY);
-+#else
-+ inet6_del_protocol(&mipv6_mh_protocol);
-+#endif
-+ memset(&mh_rcv, 0, sizeof(mh_rcv));
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_mn.c linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/mobhdr_mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/mobhdr_mn.c 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,1155 @@
-+/*
-+ * Mobile IPv6 Mobility Header Functions for Mobile Node
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Niklas Kämpe <nhkampe@cc.hut.fi>
-+ * Henrik Petander <henrik.petander@hut.fi>
-+ *
-+ * $Id:$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/types.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "mobhdr.h"
-+#include "mn.h"
-+#include "bul.h"
-+#include "rr_crypto.h"
-+#include "debug.h"
-+#include "util.h"
-+#include "stats.h"
-+
-+int rr_configured = 1;
-+
-+/* Return value of mipv6_rr_state() */
-+#define NO_RR 0
-+#define DO_RR 1
-+#define RR_FOR_COA 2
-+#define INPROGRESS_RR 3
-+
-+/**
-+ * send_bu_msg - sends a Binding Update
-+ * @bulentry : BUL entry with the information for building a BU
-+ *
-+ * Function builds a BU msg based on the contents of a bul entry.
-+ * Does not change the bul entry.
-+ **/
-+static int send_bu_msg(struct mipv6_bul_entry *binding)
-+{
-+ int auth = 0; /* Use auth */
-+ int ret = 0;
-+ struct mipv6_auth_parm parm;
-+ struct mipv6_mh_bu bu;
-+
-+ if (!binding) {
-+ DEBUG(DBG_ERROR, "called with a null bul entry");
-+ return -1;
-+ }
-+
-+ memset(&parm, 0, sizeof(parm));
-+ if (mipv6_prefix_compare(&binding->coa, &binding->home_addr, 64))
-+ parm.coa = &binding->home_addr;
-+ else
-+ parm.coa = &binding->coa;
-+ parm.cn_addr = &binding->cn_addr;
-+
-+ if (binding->rr && binding->rr->kbu) {
-+ DEBUG(DBG_INFO, "Binding with key");
-+ auth = 1;
-+ parm.k_bu = binding->rr->kbu;
-+ }
-+ memset(&bu, 0, sizeof(bu));
-+ bu.flags = binding->flags;
-+ bu.sequence = htons(binding->seq);
-+ bu.lifetime = htons(binding->lifetime >> 2);
-+ bu.reserved = 0;
-+
-+ ret = send_mh(&binding->cn_addr, &binding->home_addr,
-+ MIPV6_MH_BU, sizeof(bu), (u8 *)&bu,
-+ &binding->home_addr, NULL,
-+ binding->ops, &parm);
-+
-+ if (ret == 0)
-+ MIPV6_INC_STATS(n_bu_sent);
-+
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_send_addr_test_init - send a HoTI or CoTI message
-+ * @saddr: source address for H/CoTI
-+ * @daddr: destination address for H/CoTI
-+ * @msg_type: Identifies whether HoTI or CoTI
-+ * @init_cookie: the HoTi or CoTi init cookie
-+ *
-+ * The message will be retransmitted till we get a HoT or CoT message, since
-+ * our caller (mipv6_RR_start) has entered this message in the BUL with
-+ * exponential backoff retramission set.
-+ */
-+static int mipv6_send_addr_test_init(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ u8 msg_type,
-+ u8 *init_cookie)
-+{
-+ struct mipv6_mh_addr_ti ti;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ret = 0;
-+
-+ /* Set reserved and copy the cookie from address test init msg */
-+ ti.reserved = 0;
-+ mipv6_rr_mn_cookie_create(init_cookie);
-+ memcpy(ti.init_cookie, init_cookie, MIPV6_RR_COOKIE_LENGTH);
-+
-+ ret = send_mh(daddr, saddr, msg_type, sizeof(ti), (u8 *)&ti,
-+ NULL, NULL, ops, NULL);
-+ if (ret == 0) {
-+ if (msg_type == MIPV6_MH_HOTI) {
-+ MIPV6_INC_STATS(n_hoti_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_coti_sent);
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ *
-+ * Callback handlers for binding update list
-+ *
-+ */
-+
-+/* Return value 0 means keep entry, non-zero means discard entry. */
-+
-+/* Callback for BUs not requiring acknowledgement
-+ */
-+int bul_entry_expired(struct mipv6_bul_entry *bulentry)
-+{
-+ /* Lifetime expired, delete entry. */
-+ DEBUG(DBG_INFO, "bul entry 0x%p lifetime expired, deleting entry",
-+ bulentry);
-+ return 1;
-+}
-+
-+/* Callback for BUs requiring acknowledgement with exponential resending
-+ * scheme */
-+static int bul_resend_exp(struct mipv6_bul_entry *bulentry)
-+{
-+ unsigned long now = jiffies;
-+
-+ DEBUG(DBG_INFO, "(0x%x) resending bu", (int) bulentry);
-+
-+
-+ /* If sending a de-registration, do not care about the
-+ * lifetime value, as de-registrations are normally sent with
-+ * a zero lifetime value. If the entry is a home entry get the
-+ * current lifetime.
-+ */
-+
-+ if (bulentry->lifetime != 0) {
-+ bulentry->lifetime = mipv6_mn_get_bulifetime(
-+ &bulentry->home_addr, &bulentry->coa, bulentry->flags);
-+
-+ bulentry->expire = now + bulentry->lifetime * HZ;
-+ } else {
-+ bulentry->expire = now + HOME_RESEND_EXPIRE * HZ;
-+ }
-+ if (bulentry->rr) {
-+ /* Redo RR, if cookies have expired */
-+ if (time_after(jiffies, bulentry->rr->home_time + MAX_TOKEN_LIFE * HZ))
-+ bulentry->rr->rr_state |= RR_WAITH;
-+ if (time_after(jiffies, bulentry->rr->careof_time + MAX_NONCE_LIFE * HZ))
-+ bulentry->rr->rr_state |= RR_WAITC;
-+
-+ if (bulentry->rr->rr_state & RR_WAITH) {
-+ /* Resend HoTI directly */
-+ mipv6_send_addr_test_init(&bulentry->home_addr,
-+ &bulentry->cn_addr, MIPV6_MH_HOTI,
-+ bulentry->rr->hot_cookie);
-+ }
-+ if (bulentry->rr->rr_state & RR_WAITC) {
-+ /* Resend CoTI directly */
-+ mipv6_send_addr_test_init(&bulentry->coa,
-+ &bulentry->cn_addr, MIPV6_MH_COTI,
-+ bulentry->rr->cot_cookie);
-+ }
-+ goto out;
-+ }
-+
-+ bulentry->seq++;
-+
-+ if (send_bu_msg(bulentry) < 0)
-+ DEBUG(DBG_ERROR, "Resending of BU failed");
-+
-+out:
-+ /* Schedule next retransmission */
-+ if (bulentry->delay < bulentry->maxdelay) {
-+ bulentry->delay = 2 * bulentry->delay;
-+ if (bulentry->delay > bulentry->maxdelay) {
-+ /* can happen if maxdelay is not power(mindelay, 2) */
-+ bulentry->delay = bulentry->maxdelay;
-+ }
-+ } else if (bulentry->flags & MIPV6_BU_F_HOME) {
-+ /* Home registration - continue sending BU at maxdelay rate */
-+ DEBUG(DBG_INFO, "Sending BU to HA after max ack wait time "
-+ "reached(0x%x)", (int) bulentry);
-+ bulentry->delay = bulentry->maxdelay;
-+ } else if (!(bulentry->flags & MIPV6_BU_F_HOME)) {
-+ /* Failed to get BA from a CN */
-+ bulentry->callback_time = now;
-+ return -1;
-+ }
-+
-+ bulentry->callback_time = now + bulentry->delay * HZ;
-+ return 0;
-+}
-+
-+
-+
-+/* Callback for sending a registration refresh BU
-+ */
-+static int bul_refresh(struct mipv6_bul_entry *bulentry)
-+{
-+ unsigned long now = jiffies;
-+
-+ /* Refresh interval passed, send new BU */
-+ DEBUG(DBG_INFO, "bul entry 0x%x refresh interval passed, sending new BU", (int) bulentry);
-+ if (bulentry->lifetime == 0)
-+ return 0;
-+
-+ /* Set new maximum lifetime and expiration time */
-+ bulentry->lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr,
-+ &bulentry->coa,
-+ bulentry->flags);
-+ bulentry->expire = now + bulentry->lifetime * HZ;
-+ bulentry->seq++;
-+ /* Send update */
-+ if (send_bu_msg(bulentry) < 0)
-+ DEBUG(DBG_ERROR, "Resending of BU failed");
-+
-+ if (time_after_eq(now, bulentry->expire)) {
-+ /* Sanity check */
-+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs", ERROR_DEF_LIFETIME);
-+ bulentry->lifetime = ERROR_DEF_LIFETIME;
-+ bulentry->expire = now + ERROR_DEF_LIFETIME*HZ;
-+ }
-+
-+ /* Set up retransmission */
-+ bulentry->state = RESEND_EXP;
-+ bulentry->callback = bul_resend_exp;
-+ bulentry->callback_time = now + INITIAL_BINDACK_TIMEOUT*HZ;
-+ bulentry->delay = INITIAL_BINDACK_TIMEOUT;
-+ bulentry->maxdelay = MAX_BINDACK_TIMEOUT;
-+
-+ return 0;
-+}
-+
-+static int mipv6_send_RR_bu(struct mipv6_bul_entry *bulentry)
-+{
-+ int ret;
-+ int ops_len = 0;
-+ u16 nonces[2];
-+
-+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x "
-+ "for home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&bulentry->cn_addr), NIPV6ADDR(&bulentry->home_addr));
-+ nonces[0] = bulentry->rr->home_nonce_index;
-+ nonces[1] = bulentry->rr->careof_nonce_index;
-+ ops_len = sizeof(struct mipv6_mo_bauth_data) + MIPV6_RR_MAC_LENGTH +
-+ sizeof(struct mipv6_mo_nonce_indices);
-+ if (bulentry->ops) {
-+ DEBUG(DBG_WARNING, "Bul entry had existing mobility options, freeing them");
-+ kfree(bulentry->ops);
-+ }
-+ bulentry->ops = alloc_mh_opts(ops_len);
-+
-+ if (!bulentry->ops)
-+ return -ENOMEM;
-+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_NONCE_INDICES,
-+ sizeof(struct mipv6_mo_nonce_indices) - 2, nonces) < 0)
-+ return -ENOMEM;
-+
-+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_AUTH_DATA,
-+ MIPV6_RR_MAC_LENGTH, NULL) < 0)
-+ return -ENOMEM;
-+ /* RR procedure is over, send a BU */
-+ if (!(bulentry->flags & MIPV6_BU_F_ACK)) {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired");
-+ bulentry->state = ACK_OK;
-+ bulentry->callback = bul_entry_expired;
-+ bulentry->callback_time = jiffies + HZ * bulentry->lifetime;
-+ bulentry->expire = jiffies + HZ * bulentry->lifetime;
-+ }
-+ else {
-+ bulentry->callback_time = jiffies + HZ;
-+ bulentry->expire = jiffies + HZ * bulentry->lifetime;
-+ }
-+
-+ ret = send_bu_msg(bulentry);
-+ mipv6_bul_reschedule(bulentry);
-+ return ret;
-+}
-+
-+static int mipv6_rr_state(struct mipv6_bul_entry *bul, struct in6_addr *saddr,
-+ struct in6_addr *coa, __u8 flags)
-+{
-+ if (!rr_configured)
-+ return NO_RR;
-+ if (flags & MIPV6_BU_F_HOME) {
-+ /* We don't need RR, this is a Home Registration */
-+ return NO_RR;
-+ }
-+ if (!bul || !bul->rr) {
-+ /* First time BU to CN, need RR */
-+ return DO_RR;
-+ }
-+
-+ switch (bul->rr->rr_state) {
-+ case RR_INIT:
-+ /* Need RR if first BU to CN */
-+ return DO_RR;
-+ case RR_DONE:
-+ /* If MN moves to a new coa, do RR for it */
-+ if (!ipv6_addr_cmp(&bul->coa, coa))
-+ return NO_RR;
-+ else
-+ return DO_RR;
-+ default:
-+ /*
-+ * We are in the middle of RR, the HoTI and CoTI have been
-+ * sent. But we haven't got HoT and CoT from the CN, so
-+ * don't do anything more at this time.
-+ */
-+ return INPROGRESS_RR;
-+ }
-+}
-+
-+/**
-+ * mipv6_RR_start - Start Return Routability procedure
-+ * @home_addr: home address
-+ * @cn_addr: correspondent address
-+ * @coa: care-of address
-+ * @entry: binding update list entry (if any)
-+ * @initdelay: initial ack timeout
-+ * @maxackdelay: maximum ack timeout
-+ * @flags: flags
-+ * @lifetime: lifetime of binding
-+ * @ops: mobility options
-+ *
-+ * Caller must hold @bul_lock (write).
-+ **/
-+static int mipv6_RR_start(struct in6_addr *home_addr, struct in6_addr *cn_addr,
-+ struct in6_addr *coa, struct mipv6_bul_entry *entry,
-+ __u32 initdelay, __u32 maxackdelay, __u8 flags,
-+ __u32 lifetime, struct mipv6_mh_opt *ops)
-+{
-+ int ret = -1;
-+ struct mipv6_bul_entry *bulentry = entry;
-+ struct mipv6_rr_info *rr = NULL;
-+ int seq = 0;
-+ DEBUG_FUNC();
-+
-+ /* Do RR procedure only for care-of address after handoff,
-+ if home cookie is still valid */
-+ if (bulentry && bulentry->rr) {
-+ if (time_before(jiffies, bulentry->rr->home_time + MAX_NONCE_LIFE * HZ) &&
-+ lifetime && !(ipv6_addr_cmp(home_addr, coa) == 0)) {
-+ mipv6_rr_mn_cookie_create(bulentry->rr->cot_cookie);
-+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for CoA");
-+ ipv6_addr_copy(&bulentry->coa, coa);
-+ bulentry->rr->rr_state |= RR_WAITC;
-+ } else if (!lifetime) { /* Send only HoTi when returning home */
-+ mipv6_rr_mn_cookie_create(bulentry->rr->hot_cookie);
-+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for HoA");
-+ ipv6_addr_copy(&bulentry->coa, coa); /* Home address as CoA */
-+ bulentry->rr->rr_state |= RR_WAITH;
-+ }
-+ } else {
-+ DEBUG(DBG_INFO, "Doing RR for both HoA and CoA");
-+ rr = kmalloc(sizeof(*rr), GFP_ATOMIC);
-+ memset(rr, 0, sizeof(*rr));
-+ rr->rr_state = RR_WAITHC;
-+ }
-+ if (bulentry) {
-+ if (bulentry->state == ACK_ERROR)
-+ goto out;
-+ seq = bulentry->seq + 1;
-+ } else
-+ seq = 0;
-+ /* Save the info in the BUL to retransmit the BU after RR is done */
-+ /* Caller must hold bul_lock (write) since we don't */
-+
-+ if ((bulentry = mipv6_bul_add(cn_addr, home_addr, coa,
-+ min_t(__u32, lifetime, MAX_RR_BINDING_LIFE),
-+ seq, flags, bul_resend_exp, initdelay,
-+ RESEND_EXP, initdelay,
-+ maxackdelay, ops,
-+ rr)) == NULL) {
-+ DEBUG(DBG_INFO, "couldn't update BUL for HoTi");
-+ goto out;
-+ }
-+
-+ rr = bulentry->rr;
-+ if (rr->rr_state&RR_WAITH)
-+ mipv6_send_addr_test_init(home_addr, cn_addr, MIPV6_MH_HOTI,
-+ rr->hot_cookie);
-+ if (ipv6_addr_cmp(home_addr, coa) && lifetime)
-+ mipv6_send_addr_test_init(coa, cn_addr, MIPV6_MH_COTI, rr->cot_cookie);
-+ else {
-+ bulentry->rr->rr_state &= ~RR_WAITC;
-+ }
-+ ret = 0;
-+out:
-+ return ret;
-+}
-+
-+/*
-+ * Status codes for mipv6_ba_rcvd()
-+ */
-+#define STATUS_UPDATE 0
-+#define STATUS_REMOVE 1
-+
-+/**
-+ * mipv6_ba_rcvd - Update BUL for this Binding Acknowledgement
-+ * @ifindex: interface BA came from
-+ * @cnaddr: sender IPv6 address
-+ * @home_addr: home address
-+ * @sequence: sequence number
-+ * @lifetime: lifetime granted by Home Agent in seconds
-+ * @refresh: recommended resend interval
-+ * @status: %STATUS_UPDATE (ack) or %STATUS_REMOVE (nack)
-+ *
-+ * This function must be called to notify the module of the receipt of
-+ * a binding acknowledgement so that it can cease retransmitting the
-+ * option. The caller must have validated the acknowledgement before calling
-+ * this function. 'status' can be either STATUS_UPDATE in which case the
-+ * binding acknowledgement is assumed to be valid and the corresponding
-+ * binding update list entry is updated, or STATUS_REMOVE in which case
-+ * the corresponding binding update list entry is removed (this can be
-+ * used upon receiving a negative acknowledgement).
-+ * Returns 0 if a matching binding update has been sent or non-zero if
-+ * not.
-+ */
-+static int mipv6_ba_rcvd(int ifindex, struct in6_addr *cnaddr,
-+ struct in6_addr *home_addr,
-+ u16 sequence, u32 lifetime,
-+ u32 refresh, int status)
-+{
-+ struct mipv6_bul_entry *bulentry;
-+ unsigned long now = jiffies;
-+ struct in6_addr coa;
-+
-+ DEBUG(DBG_INFO, "BA received with sequence number 0x%x, status: %d",
-+ (int) sequence, status);
-+
-+ /* Find corresponding entry in binding update list. */
-+ write_lock(&bul_lock);
-+ if ((bulentry = mipv6_bul_get(cnaddr, home_addr)) == NULL) {
-+ DEBUG(DBG_INFO, "- discarded, no entry in bul matches BA source address");
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+
-+ ipv6_addr_copy(&coa, &bulentry->coa);
-+ if (status == SEQUENCE_NUMBER_OUT_OF_WINDOW) {
-+ __u32 lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr,
-+ &bulentry->coa,
-+ bulentry->flags);
-+ bulentry->seq = sequence;
-+
-+ mipv6_send_bu(&bulentry->home_addr, &bulentry->cn_addr,
-+ &bulentry->coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, bulentry->flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ return 0;
-+ } else if (status >= REASON_UNSPECIFIED) {
-+ int err;
-+ int at_home = MN_NOT_AT_HOME;
-+ DEBUG(DBG_WARNING, "- NACK - BA status: %d, deleting bul entry", status);
-+ if (bulentry->flags & MIPV6_BU_F_HOME) {
-+ struct mn_info *minfo;
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(home_addr);
-+ if (minfo) {
-+ spin_lock(&minfo->lock);
-+ if (minfo->is_at_home != MN_NOT_AT_HOME)
-+ minfo->is_at_home = MN_AT_HOME;
-+ at_home = minfo->is_at_home;
-+ minfo->has_home_reg = 0;
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_ERROR, "Home registration failed: BA status: %d, deleting bul entry", status);
-+ }
-+ write_unlock(&bul_lock);
-+ err = mipv6_bul_delete(cnaddr, home_addr);
-+ if (at_home == MN_AT_HOME) {
-+ mipv6_mn_send_home_na(home_addr);
-+ write_lock_bh(&bul_lock);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ write_unlock_bh(&bul_lock);
-+ }
-+ return err;
-+ }
-+ bulentry->state = ACK_OK;
-+
-+ if (bulentry->flags & MIPV6_BU_F_HOME && lifetime > 0) {
-+ /* For home registrations: schedule a refresh binding update.
-+ * Use the refresh interval given by home agent or 80%
-+ * of lifetime, whichever is less.
-+ *
-+ * Adjust binding lifetime if 'granted' lifetime
-+ * (lifetime value in received binding acknowledgement)
-+ * is shorter than 'requested' lifetime (lifetime
-+ * value sent in corresponding binding update).
-+ * max((L_remain - (L_update - L_ack)), 0)
-+ */
-+ if (lifetime * HZ < (bulentry->expire - bulentry->lastsend)) {
-+ bulentry->expire =
-+ max_t(__u32, bulentry->expire -
-+ ((bulentry->expire - bulentry->lastsend) -
-+ lifetime * HZ), jiffies +
-+ ERROR_DEF_LIFETIME * HZ);
-+ }
-+ if (refresh > lifetime || refresh == 0)
-+ refresh = 4 * lifetime / 5;
-+ DEBUG(DBG_INFO, "setting callback for expiration of"
-+ " a Home Registration: lifetime:%d, refresh:%d",
-+ lifetime, refresh);
-+ bulentry->callback = bul_refresh;
-+ bulentry->callback_time = now + refresh * HZ;
-+ bulentry->expire = now + lifetime * HZ;
-+ bulentry->lifetime = lifetime;
-+ if (time_after_eq(jiffies, bulentry->expire)) {
-+ /* Sanity check */
-+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs",
-+ ERROR_DEF_LIFETIME);
-+ bulentry->expire = jiffies + ERROR_DEF_LIFETIME * HZ;
-+ }
-+ mipv6_mn_set_home_reg(home_addr, 1);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ } else if ((bulentry->flags & MIPV6_BU_F_HOME) && bulentry->lifetime == 0) {
-+ write_unlock(&bul_lock);
-+ DEBUG(DBG_INFO, "Got BA for deregistration BU");
-+ mipv6_mn_set_home_reg(home_addr, 0);
-+ mipv6_bul_delete(cnaddr, home_addr);
-+ mipv6_mn_send_home_na(home_addr);
-+
-+ write_lock_bh(&bul_lock);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ write_unlock_bh(&bul_lock);
-+ return 0;
-+ }
-+
-+ mipv6_bul_reschedule(bulentry);
-+ write_unlock(&bul_lock);
-+
-+ return 0;
-+}
-+
-+static int mipv6_handle_mh_HC_test(struct sk_buff *skb,
-+ struct in6_addr *saddr,
-+ struct in6_addr *fcoa,
-+ struct in6_addr *cn,
-+ struct in6_addr *lcoa,
-+ struct mipv6_mh *mh)
-+{
-+ int ret = 0;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ struct mipv6_mh_addr_test *tm = (struct mipv6_mh_addr_test *)mh->data;
-+ struct mipv6_bul_entry *bulentry;
-+
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*tm);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than H/C Test");
-+ return -1;
-+ }
-+ if (fcoa || lcoa) {
-+ DEBUG(DBG_INFO, "H/C Test has HAO or RTH2, dropped.");
-+ return -1;
-+ }
-+ write_lock(&bul_lock);
-+
-+ /* We need to get the home address, since CoT only has the CoA*/
-+ if (mh->type == MIPV6_MH_COT) {
-+ if ((bulentry = mipv6_bul_get_by_ccookie(cn, tm->init_cookie)) == NULL) {
-+ DEBUG(DBG_ERROR, "has no BUL or RR state for "
-+ "source:%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(cn));
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ } else { /* HoT has the home address */
-+ if (((bulentry = mipv6_bul_get(cn, saddr)) == NULL) || !bulentry->rr) {
-+ DEBUG(DBG_ERROR, "has no BUL or RR state for "
-+ "source:%x:%x:%x:%x:%x:%x:%x:%x "
-+ "dest:%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(cn), NIPV6ADDR(saddr));
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ }
-+
-+ switch (mh->type) {
-+ case MIPV6_MH_HOT:
-+ if ((bulentry->rr->rr_state & RR_WAITH) == 0) {
-+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message");
-+ goto out;
-+ }
-+ /*
-+ * Make sure no home cookies have been received yet.
-+ * TODO: Check not being put in at this time since subsequent
-+ * BU's after this time will have home cookie stored.
-+ */
-+
-+ /* Check if the cookie received is the right one */
-+ if (!mipv6_equal_cookies(tm->init_cookie,
-+ bulentry->rr->hot_cookie)) {
-+ /* Invalid cookie, might be an old cookie */
-+ DEBUG(DBG_WARNING, "Received HoT cookie does not match stored cookie");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "Got Care-of Test message");
-+ bulentry->rr->rr_state &= ~RR_WAITH;
-+ memcpy(bulentry->rr->home_cookie, tm->kgen_token, MIPV6_COOKIE_LEN);
-+ bulentry->rr->home_nonce_index = tm->nonce_index;
-+ bulentry->rr->home_time = jiffies;
-+ ret = 1;
-+ break;
-+
-+ case MIPV6_MH_COT:
-+ if ((bulentry->rr->rr_state & RR_WAITC) == 0) {
-+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message");
-+ goto out;
-+ }
-+ /*
-+ * Make sure no home cookies have been received yet.
-+ * TODO: Check not being put in at this time since subsequent
-+ * BU's at this time will have careof cookie stored.
-+ */
-+
-+ /* Check if the cookie received is the right one */
-+ if (!mipv6_equal_cookies(tm->init_cookie,
-+ bulentry->rr->cot_cookie)) {
-+ DEBUG(DBG_INFO, "Received CoT cookie does not match stored cookie");
-+ goto out;
-+ }
-+ bulentry->rr->rr_state &= ~RR_WAITC;
-+ memcpy(bulentry->rr->careof_cookie, tm->kgen_token, MIPV6_COOKIE_LEN);
-+ bulentry->rr->careof_nonce_index = tm->nonce_index;
-+ bulentry->rr->careof_time = jiffies;
-+ ret = 1;
-+ break;
-+ default:
-+ /* Impossible to get here */
-+ break;
-+ }
-+out:
-+ if (bulentry->rr->rr_state == RR_DONE) {
-+ if (bulentry->rr->kbu) /* First free any old keys */
-+ kfree(bulentry->rr->kbu);
-+ /* Store the session key to be used in BU's */
-+ if (ipv6_addr_cmp(&bulentry->coa, &bulentry->home_addr) && bulentry->lifetime)
-+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie,
-+ bulentry->rr->careof_cookie);
-+ else
-+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie,
-+ NULL);
-+ /* RR procedure is over, send a BU */
-+ mipv6_send_RR_bu(bulentry);
-+ }
-+ write_unlock(&bul_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_handle_mh_brr - Binding Refresh Request handler
-+ * @home: home address
-+ * @coa: care-of address
-+ * @cn: source of this packet
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ * Handles Binding Refresh Request. Packet and offset to option are
-+ * passed. Returns 0 on success, otherwise negative.
-+ **/
-+static int mipv6_handle_mh_brr(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *unused1,
-+ struct in6_addr *cn,
-+ struct in6_addr *unused2,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_brr *brr = (struct mipv6_mh_brr *)mh->data;
-+ struct mipv6_bul_entry *binding;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*brr);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BRR");
-+ MIPV6_INC_STATS(n_brr_drop.invalid);
-+ return -1;
-+ }
-+
-+ /* check we know src, else drop */
-+ write_lock(&bul_lock);
-+ if ((binding = mipv6_bul_get(cn, home)) == NULL) {
-+ MIPV6_INC_STATS(n_brr_drop.misc);
-+ write_unlock(&bul_lock);
-+ return MH_UNKNOWN_CN;
-+ }
-+
-+ MIPV6_INC_STATS(n_brr_rcvd);
-+
-+ if (opt_len > 0) {
-+ struct mobopt opts;
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(brr + 1, opt_len, &opts) < 0) {
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ /*
-+ * MIPV6_OPT_AUTH_DATA
-+ */
-+ }
-+
-+ /* must hold bul_lock (write) */
-+ mipv6_RR_start(home, cn, &binding->coa, binding, binding->delay,
-+ binding->maxdelay, binding->flags,
-+ binding->lifetime, binding->ops);
-+
-+ write_unlock(&bul_lock);
-+ /* MAY also decide to delete binding and send zero lifetime BU
-+ with alt-coa set to home address */
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_handle_mh_ba - Binding Acknowledgement handler
-+ * @src: source of this packet
-+ * @coa: care-of address
-+ * @home: home address
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ **/
-+static int mipv6_handle_mh_ba(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *coa,
-+ struct in6_addr *src,
-+ struct in6_addr *unused,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_ba *ba = (struct mipv6_mh_ba *)mh->data;
-+ struct mipv6_bul_entry *binding = NULL;
-+ struct mobopt opts;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ int auth = 1, req_auth = 1, refresh = -1, ifindex = 0;
-+ u32 lifetime, sequence;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*ba);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BA");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ return -1;
-+ }
-+
-+ lifetime = ntohs(ba->lifetime) << 2;
-+ sequence = ntohs(ba->sequence);
-+
-+ if (opt_len > 0) {
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(ba + 1, opt_len, &opts) < 0)
-+ return -1;
-+ /*
-+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_BR_ADVICE
-+ */
-+ if (opts.br_advice)
-+ refresh = ntohs(opts.br_advice->refresh_interval);
-+ }
-+
-+ if (ba->status >= EXPIRED_HOME_NONCE_INDEX &&
-+ ba->status <= EXPIRED_NONCES)
-+ req_auth = 0;
-+
-+ write_lock(&bul_lock);
-+ binding = mipv6_bul_get(src, home);
-+ if (!binding) {
-+ DEBUG(DBG_INFO, "No binding, BA dropped.");
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+
-+ if (opts.auth_data && binding->rr &&
-+ (mipv6_auth_check(src, coa, (__u8 *)mh, msg_len,
-+ opts.auth_data, binding->rr->kbu) == 0))
-+ auth = 1;
-+
-+ if (req_auth && binding->rr && !auth) {
-+ DEBUG(DBG_INFO, "BA Authentication failed.");
-+ MIPV6_INC_STATS(n_ba_drop.auth);
-+ write_unlock(&bul_lock);
-+ return MH_AUTH_FAILED;
-+ }
-+
-+ if (ba->status == SEQUENCE_NUMBER_OUT_OF_WINDOW) {
-+ DEBUG(DBG_INFO,
-+ "Sequence number out of window, setting seq to %d",
-+ sequence);
-+ } else if (binding->seq != sequence) {
-+ DEBUG(DBG_INFO, "BU/BA Sequence Number mismatch %d != %d",
-+ binding->seq, sequence);
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ write_unlock(&bul_lock);
-+ return MH_SEQUENCE_MISMATCH;
-+ }
-+ if (ba->status == EXPIRED_HOME_NONCE_INDEX || ba->status == EXPIRED_NONCES) {
-+ if (binding->rr) {
-+ /* Need to resend home test init to CN */
-+ binding->rr->rr_state |= RR_WAITH;
-+ mipv6_send_addr_test_init(&binding->home_addr,
-+ &binding->cn_addr,
-+ MIPV6_MH_HOTI,
-+ binding->rr->hot_cookie);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ } else {
-+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_NONCE_INDEX"
-+ "for non-RR BU");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ }
-+ write_unlock(&bul_lock);
-+ return 0;
-+ }
-+ if (ba->status == EXPIRED_CAREOF_NONCE_INDEX || ba->status == EXPIRED_NONCES) {
-+ if (binding->rr) {
-+ /* Need to resend care-of test init to CN */
-+ binding->rr->rr_state |= RR_WAITC;
-+ mipv6_send_addr_test_init(&binding->coa,
-+ &binding->cn_addr,
-+ MIPV6_MH_COTI,
-+ binding->rr->cot_cookie);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ } else {
-+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_CAREOF_INDEX"
-+ "for non-RR BU");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ }
-+ write_unlock(&bul_lock);
-+ return 0;
-+ }
-+ write_unlock(&bul_lock);
-+
-+ if (ba->status >= REASON_UNSPECIFIED) {
-+ DEBUG(DBG_INFO, "Binding Ack status : %d indicates error", ba->status);
-+ mipv6_ba_rcvd(ifindex, src, home, sequence, lifetime,
-+ refresh, ba->status);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ return 0;
-+ }
-+ MIPV6_INC_STATS(n_ba_rcvd);
-+ if (mipv6_ba_rcvd(ifindex, src, home, ntohs(ba->sequence), lifetime,
-+ refresh, ba->status)) {
-+ DEBUG(DBG_WARNING, "mipv6_ba_rcvd failed");
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_handle_mh_be - Binding Error handler
-+ * @cn: source of this packet
-+ * @coa: care-of address
-+ * @home: home address
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ **/
-+
-+static int mipv6_handle_mh_be(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *coa,
-+ struct in6_addr *cn,
-+ struct in6_addr *unused,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_be *be = (struct mipv6_mh_be *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ struct in6_addr *hoa;
-+ struct bul_inval_args args;
-+
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*be);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BE");
-+ MIPV6_INC_STATS(n_be_drop.invalid);
-+ return -1;
-+ }
-+
-+
-+ if (!ipv6_addr_any(&be->home_addr))
-+ hoa = &be->home_addr;
-+ else
-+ hoa = home;
-+
-+ MIPV6_INC_STATS(n_be_rcvd);
-+
-+ args.all_rr_states = 0;
-+ args.cn = cn;
-+ args.mn = hoa;
-+
-+ switch (be->status) {
-+ case 1: /* Home Address Option used without a binding */
-+ /* Get ULP information about CN-MN communication. If
-+ nothing in progress, MUST delete. Otherwise MAY
-+ ignore. */
-+ args.all_rr_states = 1;
-+ case 2: /* Received unknown MH type */
-+ /* If not expecting ack, SHOULD ignore. If MH
-+ extension in use, stop it. If not, stop RO for
-+ this CN. */
-+ write_lock(&bul_lock);
-+ mipv6_bul_iterate(mn_bul_invalidate, &args);
-+ write_unlock(&bul_lock);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * mipv6_bu_rate_limit() : Takes a bulentry, a COA and 'flags' to check
-+ * whether BU being sent is for Home Registration or not.
-+ *
-+ * If the number of BU's sent is fewer than MAX_FAST_UPDATES, this BU
-+ * is allowed to be sent at the MAX_UPDATE_RATE.
-+ * If the number of BU's sent is greater than or equal to MAX_FAST_UPDATES,
-+ * this BU is allowed to be sent at the SLOW_UPDATE_RATE.
-+ *
-+ * Assumption : This function is not re-entrant. and the caller holds the
-+ * bulentry lock (by calling mipv6_bul_get()) to stop races with other
-+ * CPU's executing this same function.
-+ *
-+ * Side-Effects. Either of the following could on success :
-+ * 1. Sets consecutive_sends to 1 if the entry is a Home agent
-+ * registration or the COA has changed.
-+ * 2. Increments consecutive_sends if the number of BU's sent so
-+ * far is less than MAX_FAST_UPDATES, and this BU is being sent
-+ * atleast MAX_UPDATE_RATE after previous one.
-+ *
-+ * Return Value : 0 on Success, -1 on Failure
-+ */
-+static int mipv6_bu_rate_limit(struct mipv6_bul_entry *bulentry,
-+ struct in6_addr *coa, __u8 flags)
-+{
-+ if ((flags & MIPV6_BU_F_HOME) || ipv6_addr_cmp(&bulentry->coa, coa)) {
-+ /* Home Agent Registration or different COA - restart from 1 */
-+ bulentry->consecutive_sends = 1;
-+ return 0;
-+ }
-+
-+ if (bulentry->consecutive_sends < MAX_FAST_UPDATES) {
-+ /* First MAX_FAST_UPDATES can be sent at MAX_UPDATE_RATE */
-+ if (jiffies - bulentry->lastsend < MAX_UPDATE_RATE * HZ) {
-+ return -1;
-+ }
-+ bulentry->consecutive_sends ++;
-+ } else {
-+ /* Remaining updates SHOULD be sent at SLOW_UPDATE_RATE */
-+ if (jiffies - bulentry->lastsend < SLOW_UPDATE_RATE * HZ) {
-+ return -1;
-+ }
-+ /* Don't inc 'consecutive_sends' to avoid overflow to zero */
-+ }
-+ /* OK to send a BU */
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_bu - send a Binding Update
-+ * @saddr: source address for BU
-+ * @daddr: destination address for BU
-+ * @coa: care-of address for MN
-+ * @initdelay: initial BA wait timeout
-+ * @maxackdelay: maximum BA wait timeout
-+ * @exp: exponention back off
-+ * @flags: flags for BU
-+ * @lifetime: granted lifetime for binding
-+ * @ops: mobility options
-+ *
-+ * Send a binding update. 'flags' may contain any of %MIPV6_BU_F_ACK,
-+ * %MIPV6_BU_F_HOME, %MIPV6_BU_F_ROUTER bitwise ORed. If
-+ * %MIPV6_BU_F_ACK is included retransmission will be attempted until
-+ * the update has been acknowledged. Retransmission is done if no
-+ * acknowledgement is received within @initdelay seconds. @exp
-+ * specifies whether to use exponential backoff (@exp != 0) or linear
-+ * backoff (@exp == 0). For exponential backoff the time to wait for
-+ * an acknowledgement is doubled on each retransmission until a delay
-+ * of @maxackdelay, after which retransmission is no longer attempted.
-+ * For linear backoff the delay is kept constant and @maxackdelay
-+ * specifies the maximum number of retransmissions instead. If
-+ * sub-options are present ops must contain all sub-options to be
-+ * added. On a mobile node, use the mobile node's home address for
-+ * @saddr. Returns 0 on success, non-zero on failure.
-+ *
-+ * Caller may not hold @bul_lock.
-+ **/
-+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *coa, u32 initdelay,
-+ u32 maxackdelay, u8 exp, u8 flags, u32 lifetime,
-+ struct mipv6_mh_opt *ops)
-+{
-+ int ret;
-+ __u8 state;
-+ __u16 seq = 0;
-+ int (*callback)(struct mipv6_bul_entry *);
-+ __u32 callback_time;
-+ struct mipv6_bul_entry *bulentry;
-+
-+ /* First a sanity check: don't send BU to local addresses */
-+ if(ipv6_chk_addr(daddr, NULL)) {
-+ DEBUG(DBG_ERROR, "BUG: Trying to send BU to local address");
-+ return -1;
-+ }
-+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x "
-+ "for home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(daddr), NIPV6ADDR(saddr));
-+
-+ if ((bulentry = mipv6_bul_get(daddr, saddr)) != NULL) {
-+ if (bulentry->state == ACK_ERROR) {
-+ /*
-+ * Don't send any more BU's to nodes which don't
-+ * understanding one.
-+ */
-+ DEBUG(DBG_INFO, "Not sending BU to node which doesn't"
-+ " understand one");
-+ return -1;
-+ }
-+ if (mipv6_bu_rate_limit(bulentry, coa, flags) < 0) {
-+ DEBUG(DBG_DATADUMP, "Limiting BU sent.");
-+ return 0;
-+ }
-+ }
-+
-+ switch (mipv6_rr_state(bulentry, saddr, coa, flags)) {
-+ case INPROGRESS_RR:
-+ /* We are already doing RR, don't do BU at this time, it is
-+ * done automatically later */
-+ DEBUG(DBG_INFO, "RR in progress not sending BU");
-+ return 0;
-+
-+ case DO_RR:
-+ /* Just do RR and return, BU is done automatically later */
-+ DEBUG(DBG_INFO, "starting RR" );
-+ mipv6_RR_start(saddr, daddr, coa, bulentry, initdelay,
-+ maxackdelay, flags, lifetime, ops);
-+ return 0;
-+
-+ case NO_RR:
-+ DEBUG(DBG_DATADUMP, "No RR necessary" );
-+ default:
-+ break;
-+ }
-+
-+ if (bulentry)
-+ seq = bulentry->seq + 1;
-+
-+ /* Add to binding update list */
-+
-+ if (flags & MIPV6_BU_F_ACK) {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_resend_exp");
-+ /* Send using exponential backoff */
-+ state = RESEND_EXP;
-+ callback = bul_resend_exp;
-+ callback_time = initdelay;
-+ } else {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired");
-+ /* No acknowledgement/resending required */
-+ state = ACK_OK; /* pretend we got an ack */
-+ callback = bul_entry_expired;
-+ callback_time = lifetime;
-+ }
-+
-+ /* BU only for the home address */
-+ /* We must hold bul_lock (write) while calling add */
-+ if ((bulentry = mipv6_bul_add(daddr, saddr, coa, lifetime, seq,
-+ flags, callback, callback_time,
-+ state, initdelay, maxackdelay, ops,
-+ NULL)) == NULL) {
-+ DEBUG(DBG_INFO, "couldn't update BUL");
-+ return 0;
-+ }
-+ ret = send_bu_msg(bulentry);
-+
-+ return ret;
-+}
-+
-+int __init mipv6_mh_mn_init(void)
-+{
-+ mipv6_mh_register(MIPV6_MH_HOT, mipv6_handle_mh_HC_test);
-+ mipv6_mh_register(MIPV6_MH_COT, mipv6_handle_mh_HC_test);
-+ mipv6_mh_register(MIPV6_MH_BA, mipv6_handle_mh_ba);
-+ mipv6_mh_register(MIPV6_MH_BRR, mipv6_handle_mh_brr);
-+ mipv6_mh_register(MIPV6_MH_BE, mipv6_handle_mh_be);
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mh_mn_exit(void)
-+{
-+ mipv6_mh_unregister(MIPV6_MH_HOT);
-+ mipv6_mh_unregister(MIPV6_MH_COT);
-+ mipv6_mh_unregister(MIPV6_MH_BA);
-+ mipv6_mh_unregister(MIPV6_MH_BRR);
-+ mipv6_mh_unregister(MIPV6_MH_BE);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_cn.c linux-2.4.25/net/ipv6/mobile_ip6/module_cn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_cn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/module_cn.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,167 @@
-+/*
-+ * Mobile IPv6 Common Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+
-+#include "bcache.h"
-+#include "mipv6_icmp.h"
-+#include "stats.h"
-+#include "mobhdr.h"
-+#include "exthdrs.h"
-+
-+int mipv6_debug = 1;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(mipv6_debug, "i");
-+#endif
-+
-+#include "config.h"
-+
-+struct mip6_func mip6_fn;
-+struct mip6_conf mip6node_cnf = {
-+ capabilities: CAP_CN,
-+ accept_ret_rout: 1,
-+ max_rtr_reachable_time: 0,
-+ eager_cell_switching: 0,
-+ max_num_tunnels: 0,
-+ min_num_tunnels: 0,
-+ binding_refresh_advice: 0,
-+ bu_lladdr: 0,
-+ bu_keymgm: 0,
-+ bu_cn_ack: 0
-+};
-+
-+#define MIPV6_BCACHE_SIZE 128
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 CN Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_DEBUG, "debuglevel",
-+ &mipv6_debug, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {NET_IPV6_MOBILITY_RETROUT, "accept_return_routability",
-+ &mip6node_cnf.accept_ret_rout, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+extern void mipv6_rr_init(void);
-+
-+/* Initialize the module */
-+static int __init mip6_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Correspondent Node %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+ if ((err = mipv6_bcache_init(MIPV6_BCACHE_SIZE)) < 0)
-+ goto bcache_fail;
-+
-+ if ((err = mipv6_icmpv6_init()) < 0)
-+ goto icmp_fail;
-+
-+ if ((err = mipv6_stats_init()) < 0)
-+ goto stats_fail;
-+ mipv6_rr_init();
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+
-+ if ((err = mipv6_mh_common_init()) < 0)
-+ goto mh_fail;
-+
-+ MIPV6_SETCALL(mipv6_modify_txoptions, mipv6_modify_txoptions);
-+
-+ MIPV6_SETCALL(mipv6_handle_homeaddr, mipv6_handle_homeaddr);
-+ MIPV6_SETCALL(mipv6_icmp_swap_addrs, mipv6_icmp_swap_addrs);
-+
-+ return 0;
-+
-+mh_fail:
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ mipv6_stats_exit();
-+stats_fail:
-+ mipv6_icmpv6_exit();
-+icmp_fail:
-+ mipv6_bcache_exit();
-+bcache_fail:
-+ return err;
-+}
-+module_init(mip6_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_exit(void)
-+{
-+ printk(KERN_INFO "mip6_base.o exiting.\n");
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+
-+ /* Invalidate all custom kernel hooks. No need to do this
-+ separately for all hooks. */
-+ mipv6_invalidate_calls();
-+
-+ mipv6_mh_common_exit();
-+ mipv6_stats_exit();
-+ mipv6_icmpv6_exit();
-+ mipv6_bcache_exit();
-+}
-+module_exit(mip6_exit);
-+#endif /* MODULE */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_ha.c linux-2.4.25/net/ipv6/mobile_ip6/module_ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/module_ha.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,264 @@
-+/*
-+ * Mobile IPv6 Home Agent Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+#include <net/addrconf.h>
-+
-+#include "mobhdr.h"
-+#include "tunnel_ha.h"
-+#include "ha.h"
-+#include "halist.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+#include "bcache.h"
-+#include "debug.h"
-+
-+int mipv6_use_auth = 0;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6 Home Agent");
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+#include "config.h"
-+
-+#define MIPV6_HALIST_SIZE 128
-+struct ha_info_opt {
-+ u8 type;
-+ u8 len;
-+ u16 res;
-+ u16 pref;
-+ u16 ltime;
-+};
-+/*
-+ * Called from ndisc.c's router_discovery.
-+ */
-+static int mipv6_ha_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts)
-+{
-+ unsigned int ha_info_pref = 0, ha_info_lifetime;
-+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif;
-+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr ll_addr;
-+ struct hal {
-+ struct in6_addr prefix;
-+ int plen;
-+ struct hal *next;
-+ };
-+
-+ DEBUG_FUNC();
-+
-+ ha_info_lifetime = ntohs(ra->icmph.icmp6_rt_lifetime);
-+ ipv6_addr_copy(&ll_addr, saddr);
-+
-+ if (ndopts->nd_opts_hai) {
-+ struct ha_info_opt *hai = (struct ha_info_opt *)ndopts->nd_opts_hai;
-+ ha_info_pref = ntohs(hai->pref);
-+ ha_info_lifetime = ntohs(hai->ltime);
-+ DEBUG(DBG_DATADUMP,
-+ "received home agent info with preference : %d and lifetime : %d",
-+ ha_info_pref, ha_info_lifetime);
-+ }
-+ if (ndopts->nd_opts_pi) {
-+ struct nd_opt_hdr *p;
-+ for (p = ndopts->nd_opts_pi;
-+ p;
-+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) {
-+ struct prefix_info *pinfo;
-+
-+ pinfo = (struct prefix_info *) p;
-+
-+ if (pinfo->router_address) {
-+ DEBUG(DBG_DATADUMP, "Adding router address to "
-+ "ha queue \n");
-+ /* If RA has H bit set and Prefix Info
-+ * Option R bit set, queue this
-+ * address to be added to Home Agents
-+ * List.
-+ */
-+ if (ipv6_addr_type(&pinfo->prefix) &
-+ IPV6_ADDR_LINKLOCAL)
-+ continue;
-+ if (!ra->icmph.icmp6_home_agent || !ha_info_lifetime) {
-+ mipv6_halist_delete(&pinfo->prefix);
-+ continue;
-+ } else {
-+
-+ mipv6_halist_add(ifi, &pinfo->prefix,
-+ pinfo->prefix_len, &ll_addr,
-+ ha_info_pref, ha_info_lifetime);
-+ }
-+
-+ }
-+
-+ }
-+ }
-+ return MIPV6_ADD_RTR;
-+}
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+extern int
-+mipv6_max_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+extern int
-+mipv6_min_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+int max_adv = ~(u16)0;
-+int min_zero = 0;
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_BINDING_REFRESH, "binding_refresh_advice",
-+ &mip6node_cnf.binding_refresh_advice, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_adv},
-+
-+ {NET_IPV6_MOBILITY_MAX_TNLS, "max_tnls", &mipv6_max_tnls, sizeof(int),
-+ 0644, NULL, &mipv6_max_tnls_sysctl},
-+ {NET_IPV6_MOBILITY_MIN_TNLS, "min_tnls", &mipv6_min_tnls, sizeof(int),
-+ 0644, NULL, &mipv6_min_tnls_sysctl},
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+extern void mipv6_check_dad(struct in6_addr *haddr);
-+extern void mipv6_dad_init(void);
-+extern void mipv6_dad_exit(void);
-+extern int mipv6_forward(struct sk_buff *);
-+
-+/* Initialize the module */
-+static int __init mip6_ha_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Home Agent %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+ mip6node_cnf.capabilities = CAP_CN | CAP_HA;
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_rcv_dhaad_req;
-+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_no_rcv;
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+ mipv6_initialize_tunnel();
-+
-+ if ((err = mipv6_ha_init()) < 0)
-+ goto ha_fail;
-+
-+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_ha_ra_rcv);
-+ MIPV6_SETCALL(mipv6_forward, mipv6_forward);
-+ mipv6_dad_init();
-+ MIPV6_SETCALL(mipv6_check_dad, mipv6_check_dad);
-+
-+ if ((err = mipv6_halist_init(MIPV6_HALIST_SIZE)) < 0)
-+ goto halist_fail;
-+
-+// mipv6_initialize_pfx_icmpv6();
-+
-+ return 0;
-+
-+halist_fail:
-+ mipv6_dad_exit();
-+ mipv6_ha_exit();
-+ha_fail:
-+ mipv6_shutdown_tunnel();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_forward);
-+ MIPV6_RESETCALL(mipv6_check_dad);
-+
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ return err;
-+}
-+module_init(mip6_ha_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_ha_exit(void)
-+{
-+ printk(KERN_INFO "mip6_ha.o exiting.\n");
-+ mip6node_cnf.capabilities &= ~(int)CAP_HA;
-+
-+ mipv6_bcache_cleanup(HOME_REGISTRATION);
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_forward);
-+ MIPV6_RESETCALL(mipv6_check_dad);
-+
-+ mipv6_halist_exit();
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_dad_exit();
-+ mipv6_ha_exit();
-+ mipv6_shutdown_tunnel();
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+}
-+module_exit(mip6_ha_exit);
-+#endif /* MODULE */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/module_mn.c linux-2.4.25/net/ipv6/mobile_ip6/module_mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/module_mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/module_mn.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,188 @@
-+/*
-+ * Mobile IPv6 Mobile Node Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+
-+extern int mipv6_debug;
-+int mipv6_use_auth = 0;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6 Mobile Node");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(mipv6_debug, "i");
-+#endif
-+
-+#include "config.h"
-+
-+#include "mobhdr.h"
-+#include "mn.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+
-+/* TODO: These will go as soon as we get rid of the last two ioctls */
-+extern int mipv6_ioctl_mn_init(void);
-+extern void mipv6_ioctl_mn_exit(void);
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+
-+extern int max_rtr_reach_time;
-+extern int eager_cell_switching;
-+
-+static int max_reach = 1000;
-+static int min_reach = 1;
-+static int max_one = 1;
-+static int min_zero = 0;
-+
-+extern int
-+mipv6_mdetect_mech_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+extern int
-+mipv6_router_reach_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_BU_F_LLADDR, "bu_flag_lladdr",
-+ &mip6node_cnf.bu_lladdr, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+ {NET_IPV6_MOBILITY_BU_F_KEYMGM, "bu_flag_keymgm",
-+ &mip6node_cnf.bu_keymgm, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+ {NET_IPV6_MOBILITY_BU_F_CN_ACK, "bu_flag_cn_ack",
-+ &mip6node_cnf.bu_cn_ack, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+
-+ {NET_IPV6_MOBILITY_ROUTER_REACH, "max_router_reachable_time",
-+ &max_rtr_reach_time, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_reach, &max_reach},
-+
-+ {NET_IPV6_MOBILITY_MDETECT_MECHANISM, "eager_cell_switching",
-+ &eager_cell_switching, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+/* Initialize the module */
-+static int __init mip6_mn_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Mobile Node %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+ mip6node_cnf.capabilities = CAP_CN | CAP_MN;
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+ if ((err = mipv6_mn_init()) < 0)
-+ goto mn_fail;
-+
-+ mipv6_mh_mn_init();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_rcv_dhaad_rep;
-+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_rcv_paramprob;
-+
-+// mipv6_initialize_pfx_icmpv6();
-+
-+ if ((err = mipv6_ioctl_mn_init()) < 0)
-+ goto ioctl_fail;
-+
-+ return 0;
-+
-+ioctl_fail:
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_mh_mn_exit();
-+ mipv6_mn_exit();
-+mn_fail:
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ return err;
-+}
-+module_init(mip6_mn_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_mn_exit(void)
-+{
-+ printk(KERN_INFO "mip6_mn.o exiting.\n");
-+ mip6node_cnf.capabilities &= ~(int)CAP_MN;
-+
-+ mipv6_ioctl_mn_exit();
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_mn_exit();
-+
-+/* common cleanup */
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+}
-+module_exit(mip6_mn_exit);
-+#endif /* MODULE */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.c linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,287 @@
-+/*
-+ * 2001 (c) Oy L M Ericsson Ab
-+ *
-+ * Author: NomadicLab / Ericsson Research <ipv6@nomadiclab.com>
-+ *
-+ * $Id$
-+ *
-+ */
-+
-+/*
-+ * Vertical hand-off information manager
-+ */
-+
-+#include <linux/netdevice.h>
-+#include <linux/in6.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <linux/list.h>
-+#include "multiaccess_ctl.h"
-+#include "debug.h"
-+
-+/*
-+ * Local variables
-+ */
-+static LIST_HEAD(if_list);
-+
-+/* Internal interface information list */
-+struct ma_if_info {
-+ struct list_head list;
-+ int interface_id;
-+ int preference;
-+ __u8 status;
-+};
-+
-+/**
-+ * ma_ctl_get_preference - get preference value for interface
-+ * @ifi: interface index
-+ *
-+ * Returns integer value preference for given interface.
-+ **/
-+int ma_ctl_get_preference(int ifi)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ int pref = 0;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == ifi) {
-+ pref = info->preference;
-+ return pref;
-+ }
-+ }
-+ return -1;
-+}
-+/**
-+ * ma_ctl_get_preference - get preference value for interface
-+ * @ifi: interface index
-+ *
-+ * Returns integer value interface index for interface with highest preference.
-+ **/
-+int ma_ctl_get_preferred_if(void)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info, *pref_if = NULL;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (!pref_if || (info->preference > pref_if->preference)) {
-+ pref_if = info;
-+ }
-+ }
-+ if (pref_if) return pref_if->interface_id;
-+ return 0;
-+}
-+/**
-+ * ma_ctl_set_preference - set preference for interface
-+ * @arg: ioctl args
-+ *
-+ * Sets preference of an existing interface (called by ioctl).
-+ **/
-+void ma_ctl_set_preference(unsigned long arg)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ struct ma_if_uinfo uinfo;
-+
-+ memset(&uinfo, 0, sizeof(struct ma_if_uinfo));
-+ if (copy_from_user(&uinfo, (struct ma_if_uinfo *)arg,
-+ sizeof(struct ma_if_uinfo)) < 0) {
-+ DEBUG(DBG_WARNING, "copy_from_user failed");
-+ return;
-+ }
-+
-+ /* check if the interface exists */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == uinfo.interface_id) {
-+ info->preference = uinfo.preference;
-+ return;
-+ }
-+ }
-+}
-+
-+/**
-+ * ma_ctl_add_iface - add new interface to list
-+ * @if_index: interface index
-+ *
-+ * Adds new interface entry to preference list. Preference is set to
-+ * the same value as @if_index. Entry @status is set to
-+ * %MA_IFACE_NOT_USED.
-+ **/
-+void ma_ctl_add_iface(int if_index)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+
-+ DEBUG_FUNC();
-+
-+ /* check if the interface already exists */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == if_index) {
-+ info->status = MA_IFACE_NOT_USED;
-+ info->preference = if_index;
-+ return;
-+ }
-+ }
-+
-+ info = kmalloc(sizeof(struct ma_if_info), GFP_ATOMIC);
-+ if (info == NULL) {
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ return;
-+ }
-+ memset(info, 0, sizeof(struct ma_if_info));
-+ info->interface_id = if_index;
-+ info->preference = if_index;
-+ info->status = MA_IFACE_NOT_USED;
-+ list_add(&info->list, &if_list);
-+}
-+
-+/**
-+ * ma_ctl_del_iface - remove entry from the list
-+ * @if_index: interface index
-+ *
-+ * Removes entry for interface @if_index from preference list.
-+ **/
-+int ma_ctl_del_iface(int if_index)
-+{
-+ struct list_head *lh, *next;
-+ struct ma_if_info *info;
-+
-+ DEBUG_FUNC();
-+
-+ /* if the iface exists, change availability to 0 */
-+ list_for_each_safe(lh, next, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == if_index) {
-+ list_del(&info->list);
-+ kfree(info);
-+ return 0;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+/**
-+ * ma_ctl_upd_iface - update entry (and list)
-+ * @if_index: interface to update
-+ * @status: new status for interface
-+ * @change_if_index: new interface
-+ *
-+ * Updates @if_index entry on preference list. Entry status is set to
-+ * @status. If new @status is %MA_IFACE_CURRENT, updates list to have
-+ * only one current device. If @status is %MA_IFACE_NOT_PRESENT,
-+ * entry is deleted and further if entry had %MA_IFACE_CURRENT set,
-+ * new current device is looked up and returned in @change_if_index.
-+ * New preferred interface is also returned if current device changes
-+ * to %MA_IFACE_NOT_USED. Returns 0 on success, otherwise negative.
-+ **/
-+int ma_ctl_upd_iface(int if_index, int status, int *change_if_index)
-+{
-+ struct list_head *lh, *tmp;
-+ struct ma_if_info *info, *pref = NULL;
-+ int found = 0;
-+
-+ DEBUG_FUNC();
-+
-+ *change_if_index = 0;
-+
-+ /* check if the interface exists */
-+ list_for_each_safe(lh, tmp, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (status == MA_IFACE_NOT_PRESENT) {
-+ if (info->interface_id == if_index) {
-+ list_del_init(&info->list);
-+ kfree(info);
-+ found = 1;
-+ break;
-+ }
-+ } else if (status == MA_IFACE_CURRENT) {
-+ if (info->interface_id == if_index) {
-+ info->status |= MA_IFACE_CURRENT;
-+ found = 1;
-+ } else {
-+ info->status |= MA_IFACE_NOT_USED;
-+ }
-+ } else if (status == MA_IFACE_NOT_USED) {
-+ if (info->interface_id == if_index) {
-+ if (info->status | MA_IFACE_CURRENT) {
-+ found = 1;
-+ }
-+ info->status &= !MA_IFACE_CURRENT;
-+ info->status |= MA_IFACE_NOT_USED;
-+ info->status &= !MA_IFACE_HAS_ROUTER;
-+ }
-+ break;
-+ } else if (status == MA_IFACE_HAS_ROUTER) {
-+ if (info->interface_id == if_index) {
-+ info->status |= MA_IFACE_HAS_ROUTER;
-+ }
-+ return 0;
-+ }
-+ }
-+
-+ if (status & (MA_IFACE_NOT_USED|MA_IFACE_NOT_PRESENT) && found) {
-+ /* select new interface */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (pref == NULL || ((info->preference > pref->preference) &&
-+ info->status & MA_IFACE_HAS_ROUTER))
-+ pref = info;
-+ }
-+ if (pref) {
-+ *change_if_index = pref->interface_id;
-+ pref->status |= MA_IFACE_CURRENT;
-+ } else {
-+ *change_if_index = -1;
-+ }
-+ return 0;
-+ }
-+
-+ if (found) return 0;
-+
-+ return -1;
-+}
-+
-+static int if_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ int len = 0;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ len += sprintf(buffer + len, "%02d %010d %1d %1d\n",
-+ info->interface_id, info->preference,
-+ !!(info->status & MA_IFACE_HAS_ROUTER),
-+ !!(info->status & MA_IFACE_CURRENT));
-+ }
-+
-+ *start = buffer + offset;
-+
-+ len -= offset;
-+
-+ if (len > length) len = length;
-+
-+ return len;
-+
-+}
-+
-+void ma_ctl_init(void)
-+{
-+ proc_net_create("mip6_iface", 0, if_proc_info);
-+}
-+
-+void ma_ctl_clean(void)
-+{
-+ proc_net_remove("mip6_iface");
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.h linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/multiaccess_ctl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/multiaccess_ctl.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,77 @@
-+/*
-+ * 2001 (c) Oy L M Ericsson Ab
-+ *
-+ * Author: NomadicLab / Ericsson Research <ipv6@nomadiclab.com>
-+ *
-+ * $Id$
-+ *
-+ */
-+
-+#ifndef _MULTIACCESS_CTL_H
-+#define _MULTIACCESS_CTL_H
-+
-+/* status */
-+#define MA_IFACE_NOT_PRESENT 0x01
-+#define MA_IFACE_NOT_USED 0x02
-+#define MA_IFACE_HAS_ROUTER 0x04
-+#define MA_IFACE_CURRENT 0x10
-+
-+struct ma_if_uinfo {
-+ int interface_id;
-+ int preference;
-+ __u8 status;
-+};
-+/*
-+ * @ma_ctl_get_preferred_id: returns most preferred interface id
-+ */
-+int ma_ctl_get_preferred_if(void);
-+
-+/* @ma_ctl_get_preference: returns preference for an interface
-+ * @name: name of the interface (dev->name)
-+ */
-+int ma_ctl_get_preference(int ifi);
-+
-+/*
-+ * Public function: ma_ctl_set_preference
-+ * Description: Set preference of an existing interface (called by ioctl)
-+ * Returns:
-+ */
-+void ma_ctl_set_preference(unsigned long);
-+
-+/*
-+ * Public function: ma_ctl_add_iface
-+ * Description: Inform control module to insert a new interface
-+ * Returns: 0 if success, any other number means an error
-+ */
-+void ma_ctl_add_iface(int);
-+
-+/*
-+ * Public function: ma_ctl_del_iface
-+ * Description: Inform control module to remove an obsolete interface
-+ * Returns: 0 if success, any other number means an error
-+ */
-+int ma_ctl_del_iface(int);
-+
-+/*
-+ * Public function: ma_ctl_upd_iface
-+ * Description: Inform control module of status change.
-+ * Returns: 0 if success, any other number means an error
-+ */
-+int ma_ctl_upd_iface(int, int, int *);
-+
-+/*
-+ * Public function: ma_ctl_init
-+ * Description: XXX
-+ * Returns: XXX
-+ */
-+void ma_ctl_init(void);
-+
-+/*
-+ * Public function: ma_ctl_clean
-+ * Description: XXX
-+ * Returns: -
-+ */
-+void ma_ctl_clean(void);
-+
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/ndisc_ha.c linux-2.4.25/net/ipv6/mobile_ip6/ndisc_ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/ndisc_ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/ndisc_ha.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,596 @@
-+/*
-+ * Mobile IPv6 Duplicate Address Detection Functions
-+ *
-+ * Authors:
-+ * Krishna Kumar <krkumar@us.ibm.com>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/in6.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "bcache.h"
-+#include "ha.h" /* mipv6_generate_ll_addr */
-+
-+/*
-+ * Binding Updates from MN are cached in this structure till DAD is performed.
-+ * This structure is used to retrieve a pending Binding Update for the HA to
-+ * reply to after performing DAD. The first cell is different from the rest as
-+ * follows :
-+ * 1. The first cell is used to chain the remaining cells.
-+ * 2. The timeout of the first cell is used to delete expired entries
-+ * in the list of cells, while the timeout of the other cells are
-+ * used for timing out a NS request so as to reply to a BU.
-+ * 3. The only elements of the first cell that are used are :
-+ * next, prev, and callback_timer.
-+ *
-+ * TODO : Don't we need to do pneigh_lookup on the Link Local address ?
-+ */
-+struct mipv6_dad_cell {
-+ /* Information needed for DAD management */
-+ struct mipv6_dad_cell *next; /* Next element on the DAD list */
-+ struct mipv6_dad_cell *prev; /* Prev element on the DAD list */
-+ __u16 probes; /* Number of times to probe for addr */
-+ __u16 flags; /* Entry flags - see below */
-+ struct timer_list callback_timer; /* timeout for entry */
-+
-+ /* Information needed for performing DAD */
-+ struct inet6_ifaddr *ifp;
-+ int ifindex;
-+ struct in6_addr daddr;
-+ struct in6_addr haddr; /* home address */
-+ struct in6_addr ll_haddr; /* Link Local value of haddr */
-+ struct in6_addr coa;
-+ struct in6_addr rep_coa;
-+ __u32 ba_lifetime;
-+ __u16 sequence;
-+ __u8 bu_flags;
-+};
-+
-+/* Values for the 'flags' field in the mipv6_dad_cell */
-+#define DAD_INIT_ENTRY 0
-+#define DAD_DUPLICATE_ADDRESS 1
-+#define DAD_UNIQUE_ADDRESS 2
-+
-+/* Head of the pending DAD list */
-+static struct mipv6_dad_cell dad_cell_head;
-+
-+/* Lock to access the pending DAD list */
-+static rwlock_t dad_lock = RW_LOCK_UNLOCKED;
-+
-+/* Timer routine which deletes 'expired' entries in the DAD list */
-+static void mipv6_dad_delete_old_entries(unsigned long unused)
-+{
-+ struct mipv6_dad_cell *curr, *next;
-+ unsigned long next_time = 0;
-+
-+ write_lock(&dad_lock);
-+ curr = dad_cell_head.next;
-+ while (curr != &dad_cell_head) {
-+ next = curr->next;
-+ if (curr->flags != DAD_INIT_ENTRY) {
-+ if (curr->callback_timer.expires <= jiffies) {
-+ /* Entry has expired, free it up. */
-+ curr->next->prev = curr->prev;
-+ curr->prev->next = curr->next;
-+ in6_ifa_put(curr->ifp);
-+ kfree(curr);
-+ } else if (next_time <
-+ curr->callback_timer.expires) {
-+ next_time = curr->callback_timer.expires;
-+ }
-+ }
-+ curr = next;
-+ }
-+ write_unlock(&dad_lock);
-+ if (next_time) {
-+ /*
-+ * Start another timer if more cells need to be removed at
-+ * a later stage.
-+ */
-+ dad_cell_head.callback_timer.expires = next_time;
-+ add_timer(&dad_cell_head.callback_timer);
-+ }
-+}
-+
-+/*
-+ * Queue a timeout routine to clean up 'expired' DAD entries.
-+ */
-+static void mipv6_start_dad_head_timer(struct mipv6_dad_cell *cell)
-+{
-+ unsigned long expire = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time * 10;
-+
-+ if (!timer_pending(&dad_cell_head.callback_timer) ||
-+ expire < dad_cell_head.callback_timer.expires) {
-+ /*
-+ * Add timer if none pending, or mod the timer if new
-+ * cell needs to be expired before existing timer runs.
-+ *
-+ * We let the cell remain as long as possible, so that
-+ * new BU's as part of retransmissions don't have to go
-+ * through DAD before replying.
-+ */
-+ dad_cell_head.callback_timer.expires = expire;
-+
-+ /*
-+ * Keep the cell around for atleast some time to handle
-+ * retransmissions or BU's due to fast MN movement. This
-+ * is needed otherwise a previous timeout can delete all
-+ * expired entries including this new one.
-+ */
-+ cell->callback_timer.expires = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time * 5;
-+ if (!timer_pending(&dad_cell_head.callback_timer)) {
-+ add_timer(&dad_cell_head.callback_timer);
-+ } else {
-+ mod_timer(&dad_cell_head.callback_timer, expire);
-+ }
-+ }
-+}
-+
-+
-+/* Join solicited node MC address */
-+static inline void mipv6_join_sol_mc_addr(struct in6_addr *addr,
-+ struct net_device *dev)
-+{
-+ struct in6_addr maddr;
-+
-+ /* Join solicited node MC address */
-+ addrconf_addr_solict_mult(addr, &maddr);
-+ ipv6_dev_mc_inc(dev, &maddr);
-+}
-+
-+/* Leave solicited node MC address */
-+static inline void mipv6_leave_sol_mc_addr(struct in6_addr *addr,
-+ struct net_device *dev)
-+{
-+ struct in6_addr maddr;
-+
-+ addrconf_addr_solict_mult(addr, &maddr);
-+ ipv6_dev_mc_dec(dev, &maddr);
-+}
-+
-+/* Send a NS */
-+static inline void mipv6_dad_send_ns(struct inet6_ifaddr *ifp,
-+ struct in6_addr *haddr)
-+{
-+ struct in6_addr unspec;
-+ struct in6_addr mcaddr;
-+
-+ ipv6_addr_set(&unspec, 0, 0, 0, 0);
-+ addrconf_addr_solict_mult(haddr, &mcaddr);
-+
-+ /* addr is 'unspec' since we treat this address as transient */
-+ ndisc_send_ns(ifp->idev->dev, NULL, haddr, &mcaddr, &unspec);
-+}
-+
-+/*
-+ * Search for a home address in the list of pending DAD's. Called from
-+ * Neighbor Advertisement
-+ * Return values :
-+ * -1 : No DAD entry found for this advertisement, or entry already
-+ * finished processing.
-+ * 0 : Entry found waiting for DAD to finish.
-+ */
-+static int dad_search_haddr(struct in6_addr *ll_haddr,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 * seq, struct inet6_ifaddr **ifp)
-+{
-+ struct mipv6_dad_cell *cell;
-+
-+ read_lock(&dad_lock);
-+ cell = dad_cell_head.next;
-+ while (cell != &dad_cell_head &&
-+ ipv6_addr_cmp(&cell->ll_haddr, ll_haddr) &&
-+ ipv6_addr_cmp(&cell->haddr, ll_haddr)) {
-+ cell = cell->next;
-+ }
-+ if (cell == &dad_cell_head || cell->flags != DAD_INIT_ENTRY) {
-+ /* Not found element, or element already finished processing */
-+ if (cell != &dad_cell_head) {
-+ /*
-+ * Set the state to DUPLICATE, even if it was UNIQUE
-+ * earlier. It is not needed to setup timer via
-+ * mipv6_start_dad_head_timer since this must have
-+ * already been done.
-+ */
-+ cell->flags = DAD_DUPLICATE_ADDRESS;
-+ }
-+ read_unlock(&dad_lock);
-+ return -1;
-+ }
-+
-+ /*
-+ * The NA found an unprocessed entry in the DAD list. Expire this
-+ * entry since another node advertised this address. Caller should
-+ * reject BU (DAD failed).
-+ */
-+ ipv6_addr_copy(daddr, &cell->daddr);
-+ ipv6_addr_copy(haddr, &cell->haddr);
-+ ipv6_addr_copy(coa, &cell->coa);
-+ ipv6_addr_copy(rep_coa, &cell->rep_coa);
-+ *seq = cell->sequence;
-+ *ifp = cell->ifp;
-+
-+ if (del_timer(&cell->callback_timer) == 0) {
-+ /* Timer already deleted, race with Timeout Handler */
-+ /* No action needed */
-+ }
-+
-+ cell->flags = DAD_DUPLICATE_ADDRESS;
-+
-+ /* Now leave this address to avoid future processing of NA's */
-+ mipv6_leave_sol_mc_addr(&cell->ll_haddr, cell->ifp->idev->dev);
-+ /* Leave also global address, if link local address was in use */
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr, cell->ifp->idev->dev);
-+ /* Start dad_head timer to remove this entry */
-+ mipv6_start_dad_head_timer(cell);
-+
-+ read_unlock(&dad_lock);
-+
-+ return 0;
-+}
-+
-+/* ENTRY routine called via Neighbor Advertisement */
-+void mipv6_check_dad(struct in6_addr *ll_haddr)
-+{
-+ struct in6_addr daddr, haddr, coa, rep_coa;
-+ struct inet6_ifaddr *ifp;
-+ __u16 seq;
-+
-+ if (dad_search_haddr(ll_haddr, &daddr, &haddr, &coa, &rep_coa, &seq,
-+ &ifp) < 0) {
-+ /*
-+ * Didn't find entry, or no action needed (the action has
-+ * already been performed).
-+ */
-+ return;
-+ }
-+
-+ /*
-+ * A DAD cell was present, meaning that there is a pending BU
-+ * request for 'haddr' - reject the BU.
-+ */
-+ mipv6_bu_finish(ifp, 0, DUPLICATE_ADDR_DETECT_FAIL,
-+ &daddr, &haddr, &coa, &rep_coa, 0, seq, 0, NULL);
-+ return;
-+}
-+
-+/*
-+ * Check if the passed 'cell' is in the list of pending DAD's. Called from
-+ * the Timeout Handler.
-+ *
-+ * Assumes that the caller is holding the dad_lock in reader mode.
-+ */
-+static int dad_search_cell(struct mipv6_dad_cell *cell)
-+{
-+ struct mipv6_dad_cell *tmp;
-+
-+ tmp = dad_cell_head.next;
-+ while (tmp != &dad_cell_head && tmp != cell) {
-+ tmp = tmp->next;
-+ }
-+ if (tmp == cell) {
-+ if (cell->flags == DAD_INIT_ENTRY) {
-+ /* Found valid entry */
-+ if (--cell->probes == 0) {
-+ /*
-+ * Retransmission's are over - return success.
-+ */
-+ cell->flags = DAD_UNIQUE_ADDRESS;
-+
-+ /*
-+ * Leave this address to avoid future
-+ * processing of NA's.
-+ */
-+ mipv6_leave_sol_mc_addr(&cell->ll_haddr,
-+ cell->ifp->idev->
-+ dev);
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr,
-+ cell->ifp->idev->dev);
-+ /* start timeout to delete this cell. */
-+ mipv6_start_dad_head_timer(cell);
-+ return 0;
-+ }
-+ /*
-+ * Retransmission not finished, send another NS and
-+ * return failure.
-+ */
-+ mipv6_dad_send_ns(cell->ifp, &cell->ll_haddr);
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr,
-+ cell->ifp->idev->dev);
-+ cell->callback_timer.expires = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time;
-+ add_timer(&cell->callback_timer);
-+ } else {
-+ /*
-+ * This means that an NA was received before the
-+ * timeout and when the state changed from
-+ * DAD_INIT_ENTRY, the BU got failed as a result.
-+ * There is nothing to be done.
-+ */
-+ }
-+ }
-+ return -1;
-+}
-+
-+/* ENTRY routine called via Timeout */
-+static void mipv6_dad_timeout(unsigned long arg)
-+{
-+ __u8 ba_status = SUCCESS;
-+ struct in6_addr daddr;
-+ struct in6_addr haddr;
-+ struct in6_addr coa;
-+ struct in6_addr rep_coa;
-+ struct inet6_ifaddr *ifp;
-+ int ifindex;
-+ __u32 ba_lifetime;
-+ __u16 sequence;
-+ __u8 flags;
-+ struct mipv6_dad_cell *cell = (struct mipv6_dad_cell *) arg;
-+
-+ /*
-+ * If entry is not in the list, we have already sent BU Failure
-+ * after getting a NA.
-+ */
-+ read_lock(&dad_lock);
-+ if (dad_search_cell(cell) < 0) {
-+ /*
-+ * 'cell' is no longer valid (may not be in the list or
-+ * is already processed, due to NA processing), or NS
-+ * retransmissions are not yet over.
-+ */
-+ read_unlock(&dad_lock);
-+ return;
-+ }
-+
-+ /* This is the final Timeout. Send Bind Ack Success */
-+
-+ ifp = cell->ifp;
-+ ifindex = cell->ifindex;
-+ ba_lifetime = cell->ba_lifetime;
-+ sequence = cell->sequence;
-+ flags = cell->bu_flags;
-+
-+ ipv6_addr_copy(&daddr, &cell->daddr);
-+ ipv6_addr_copy(&haddr, &cell->haddr);
-+ ipv6_addr_copy(&coa, &cell->coa);
-+ ipv6_addr_copy(&rep_coa, &cell->rep_coa);
-+ read_unlock(&dad_lock);
-+
-+ /* Send BU Acknowledgement Success */
-+ mipv6_bu_finish(ifp, ifindex, ba_status,
-+ &daddr, &haddr, &coa, &rep_coa,
-+ ba_lifetime, sequence, flags, NULL);
-+ return;
-+}
-+
-+/*
-+ * Check if original home address exists in our DAD pending list, if so return
-+ * the cell.
-+ *
-+ * Assumes that the caller is holding the dad_lock in writer mode.
-+ */
-+static struct mipv6_dad_cell *mipv6_dad_get_cell(struct in6_addr *haddr)
-+{
-+ struct mipv6_dad_cell *cell;
-+
-+ cell = dad_cell_head.next;
-+ while (cell != &dad_cell_head
-+ && ipv6_addr_cmp(&cell->haddr, haddr)) {
-+ cell = cell->next;
-+ }
-+ if (cell == &dad_cell_head) {
-+ /* Not found element */
-+ return NULL;
-+ }
-+ return cell;
-+}
-+
-+/*
-+ * Save all parameters needed for doing a Bind Ack in the mipv6_dad_cell
-+ * structure.
-+ */
-+static void mipv6_dad_save_cell(struct mipv6_dad_cell *cell,
-+ struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr,
-+ struct in6_addr *haddr,
-+ struct in6_addr *coa,
-+ struct in6_addr *rep_coa,
-+ __u32 ba_lifetime,
-+ __u16 sequence, __u8 flags)
-+{
-+ in6_ifa_hold(ifp);
-+ cell->ifp = ifp;
-+ cell->ifindex = ifindex;
-+
-+ ipv6_addr_copy(&cell->daddr, daddr);
-+ ipv6_addr_copy(&cell->haddr, haddr);
-+ ipv6_addr_copy(&cell->coa, coa);
-+ ipv6_addr_copy(&cell->rep_coa, rep_coa);
-+
-+ /* Convert cell->ll_haddr to Link Local address */
-+ if (flags & MIPV6_BU_F_LLADDR)
-+ mipv6_generate_ll_addr(&cell->ll_haddr, haddr);
-+ else
-+ ipv6_addr_copy(&cell->ll_haddr, haddr);
-+
-+ cell->ba_lifetime = ba_lifetime;
-+ cell->sequence = sequence;
-+ cell->bu_flags = flags;
-+}
-+
-+/*
-+ * Top level DAD routine for performing DAD.
-+ *
-+ * Return values
-+ * 0 : Don't need to do DAD.
-+ * 1 : Need to do DAD.
-+ * -n : Error, where 'n' is the reason for the error.
-+ *
-+ * Assumption : DAD process has been optimized by using cached values upto
-+ * some time. However sometimes this can cause problems. Eg. when the first
-+ * BU was received, DAD might have failed. Before the second BU arrived,
-+ * the node using MN's home address might have stopped using it, but still
-+ * we will return DAD_DUPLICATE_ADDRESS based on the first DAD's result. Or
-+ * this can go the other way around. However, it is a very small possibility
-+ * and thus optimization is turned on by default. It is possible to change
-+ * this feature (needs a little code-rewriting in this routine), but
-+ * currently DAD result is being cached for performance reasons.
-+ */
-+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags)
-+{
-+ int found;
-+ struct mipv6_dad_cell *cell;
-+ struct mipv6_bce bc_entry;
-+
-+ if (ifp->idev->cnf.dad_transmits == 0) {
-+ /* DAD is not configured on the HA, return SUCCESS */
-+ return 0;
-+ }
-+
-+ if (mipv6_bcache_get(haddr, daddr, &bc_entry) == 0) {
-+ /*
-+ * We already have an entry in our cache - don't need to
-+ * do DAD as we are already defending this home address.
-+ */
-+ return 0;
-+ }
-+
-+ write_lock(&dad_lock);
-+ if ((cell = mipv6_dad_get_cell(haddr)) != NULL) {
-+ /*
-+ * An existing entry for BU was found in our cache due
-+ * to retransmission of the BU or a new COA registration.
-+ */
-+ switch (cell->flags) {
-+ case DAD_INIT_ENTRY:
-+ /* Old entry is waiting for DAD to complete */
-+ break;
-+ case DAD_UNIQUE_ADDRESS:
-+ /* DAD is finished successfully - return success. */
-+ write_unlock(&dad_lock);
-+ return 0;
-+ case DAD_DUPLICATE_ADDRESS:
-+ /*
-+ * DAD is finished and we got a NA while doing BU -
-+ * return failure.
-+ */
-+ write_unlock(&dad_lock);
-+ return -DUPLICATE_ADDR_DETECT_FAIL;
-+ default:
-+ /* Unknown state - should never happen */
-+ DEBUG(DBG_WARNING,
-+ "cell entry in unknown state : %d",
-+ cell->flags);
-+ write_unlock(&dad_lock);
-+ return -REASON_UNSPECIFIED;
-+ }
-+ found = 1;
-+ } else {
-+ if ((cell = (struct mipv6_dad_cell *)
-+ kmalloc(sizeof(struct mipv6_dad_cell), GFP_ATOMIC))
-+ == NULL) {
-+ return -INSUFFICIENT_RESOURCES;
-+ }
-+ found = 0;
-+ }
-+
-+ mipv6_dad_save_cell(cell, ifp, ifindex, daddr, haddr, coa, rep_coa,
-+ ba_lifetime, sequence, flags);
-+
-+ if (!found) {
-+ cell->flags = DAD_INIT_ENTRY;
-+ cell->probes = ifp->idev->cnf.dad_transmits;
-+
-+ /* Insert element on dad_cell_head list */
-+ dad_cell_head.prev->next = cell;
-+ cell->next = &dad_cell_head;
-+ cell->prev = dad_cell_head.prev;
-+ dad_cell_head.prev = cell;
-+ write_unlock(&dad_lock);
-+ if (flags & MIPV6_BU_F_LLADDR) {
-+ /* join the solicited node MC of the global homeaddr.*/
-+ mipv6_join_sol_mc_addr(&cell->haddr, ifp->idev->dev);
-+ /* Send a NS */
-+ mipv6_dad_send_ns(ifp, &cell->haddr);
-+ }
-+ /* join the solicited node MC of the homeaddr. */
-+ mipv6_join_sol_mc_addr(&cell->ll_haddr, ifp->idev->dev);
-+
-+ /* Send a NS */
-+ mipv6_dad_send_ns(ifp, &cell->ll_haddr);
-+
-+ /* Initialize timer for this cell to timeout the NS. */
-+ init_timer(&cell->callback_timer);
-+ cell->callback_timer.data = (unsigned long) cell;
-+ cell->callback_timer.function = mipv6_dad_timeout;
-+ cell->callback_timer.expires = jiffies +
-+ ifp->idev->nd_parms->retrans_time;
-+ add_timer(&cell->callback_timer);
-+ } else {
-+ write_unlock(&dad_lock);
-+ }
-+ return 1;
-+}
-+
-+void __init mipv6_dad_init(void)
-+{
-+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head;
-+ init_timer(&dad_cell_head.callback_timer);
-+ dad_cell_head.callback_timer.data = 0;
-+ dad_cell_head.callback_timer.function =
-+ mipv6_dad_delete_old_entries;
-+}
-+
-+void __exit mipv6_dad_exit(void)
-+{
-+ struct mipv6_dad_cell *curr, *next;
-+
-+ write_lock_bh(&dad_lock);
-+ del_timer(&dad_cell_head.callback_timer);
-+
-+ curr = dad_cell_head.next;
-+ while (curr != &dad_cell_head) {
-+ next = curr->next;
-+ del_timer(&curr->callback_timer);
-+ if (curr->flags == DAD_INIT_ENTRY) {
-+ /*
-+ * We were in DAD_INIT state and listening to the
-+ * solicited node MC address - need to stop that.
-+ */
-+ mipv6_leave_sol_mc_addr(&curr->ll_haddr,
-+ curr->ifp->idev->dev);
-+ if (ipv6_addr_cmp(&curr->ll_haddr, &curr->haddr))
-+ mipv6_leave_sol_mc_addr(&curr->haddr,
-+ curr->ifp->idev->dev);
-+ }
-+ in6_ifa_put(curr->ifp);
-+ kfree(curr);
-+ curr = next;
-+ }
-+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head;
-+ write_unlock_bh(&dad_lock);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.c linux-2.4.25/net/ipv6/mobile_ip6/prefix.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,217 @@
-+/**
-+ * Prefix solicitation and advertisement
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <linux/net.h>
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <linux/netdevice.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "mipv6_icmp.h"
-+#include "debug.h"
-+#include "sortedlist.h"
-+#include "prefix.h"
-+#include "config.h"
-+
-+#define INFINITY 0xffffffff
-+
-+struct timer_list pfx_timer;
-+
-+struct list_head pfx_list;
-+rwlock_t pfx_list_lock = RW_LOCK_UNLOCKED;
-+
-+int compare_pfx_list_entry(const void *data1, const void *data2,
-+ int datalen)
-+{
-+ struct pfx_list_entry *e1 = (struct pfx_list_entry *) data1;
-+ struct pfx_list_entry *e2 = (struct pfx_list_entry *) data2;
-+
-+ return ((ipv6_addr_cmp(&e1->daddr, &e2->daddr) == 0)
-+ && (e2->ifindex == -1 || e1->ifindex == e2->ifindex));
-+}
-+
-+/**
-+ * mipv6_pfx_cancel_send - cancel pending items to daddr from saddr
-+ * @daddr: Destination address
-+ * @ifindex: pending items on this interface will be canceled
-+ *
-+ * if ifindex == -1, all items to daddr will be removed
-+ */
-+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry entry;
-+
-+ DEBUG_FUNC();
-+
-+ /* We'll just be comparing these parts... */
-+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr));
-+ entry.ifindex = ifindex;
-+
-+ write_lock_bh(&pfx_list_lock);
-+
-+ while (mipv6_slist_del_item(&pfx_list, &entry,
-+ compare_pfx_list_entry) == 0)
-+ ;
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ write_unlock_bh(&pfx_list_lock);
-+}
-+
-+/**
-+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to
-+ * @daddr: address of HA
-+ * @saddr: our address to use as source address
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int ifindex)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry entry;
-+
-+ DEBUG_FUNC();
-+
-+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr));
-+ memcpy(&entry.saddr, saddr, sizeof(struct in6_addr));
-+ entry.retries = 0;
-+ entry.ifindex = ifindex;
-+
-+ write_lock_bh(&pfx_list_lock);
-+ if (mipv6_slist_modify(&pfx_list, &entry, sizeof(struct pfx_list_entry),
-+ jiffies + INITIAL_SOLICIT_TIMER * HZ,
-+ compare_pfx_list_entry))
-+ DEBUG(DBG_WARNING, "Cannot add new HA to pfx list");
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
-+
-+int mipv6_pfx_add_home(int ifindex, struct in6_addr *saddr,
-+ struct in6_addr *daddr, unsigned long min_expire)
-+{
-+ unsigned long tmp;
-+
-+ write_lock(&pfx_list_lock);
-+
-+ if (min_expire != INFINITY) {
-+ unsigned long expire;
-+ struct pfx_list_entry entry;
-+
-+ memcpy(&entry.daddr, saddr, sizeof(struct in6_addr));
-+ memcpy(&entry.saddr, daddr, sizeof(struct in6_addr));
-+ entry.retries = 0;
-+ entry.ifindex = ifindex;
-+
-+ /* This is against the RFC 3775, but we need to set
-+ * a minimum interval for a prefix solicitation.
-+ * Otherwise a prefix solicitation storm will
-+ * result if valid lifetime of the prefix is
-+ * smaller than MAX_PFX_ADV_DELAY
-+ */
-+ min_expire -= MAX_PFX_ADV_DELAY;
-+ min_expire = min_expire < MIN_PFX_SOL_DELAY ? MIN_PFX_SOL_DELAY : min_expire;
-+
-+ expire = jiffies + min_expire * HZ;
-+
-+ if (mipv6_slist_modify(&pfx_list, &entry,
-+ sizeof(struct pfx_list_entry),
-+ expire,
-+ compare_pfx_list_entry) != 0)
-+ DEBUG(DBG_WARNING, "Cannot add new entry to pfx_list");
-+ }
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ write_unlock(&pfx_list_lock);
-+
-+ return 0;
-+}
-+
-+/**
-+ * set_ha_pfx_list - manipulate pfx_list for HA when timer goes off
-+ * @entry: pfx_list_entry that is due
-+ */
-+static void set_ha_pfx_list(struct pfx_list_entry *entry)
-+{
-+}
-+
-+/**
-+ * set_mn_pfx_list - manipulate pfx_list for MN when timer goes off
-+ * @entry: pfx_list_entry that is due
-+ */
-+static void set_mn_pfx_list(struct pfx_list_entry *entry)
-+{
-+}
-+
-+/**
-+ * pfx_timer_handler - general timer handler
-+ * @dummy: dummy
-+ *
-+ * calls set_ha_pfx_list and set_mn_pfx_list to do the thing when
-+ * a timer goes off
-+ */
-+static void pfx_timer_handler(unsigned long dummy)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&pfx_list_lock);
-+ if (!(entry = mipv6_slist_get_first(&pfx_list)))
-+ goto out;
-+
-+ if (mip6node_cnf.capabilities & CAP_HA)
-+ set_ha_pfx_list(entry);
-+ if (mip6node_cnf.capabilities & CAP_MN)
-+ set_mn_pfx_list(entry);
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ out:
-+ write_unlock(&pfx_list_lock);
-+}
-+
-+int mipv6_initialize_pfx_icmpv6(void)
-+{
-+ INIT_LIST_HEAD(&pfx_list);
-+
-+ init_timer(&pfx_timer);
-+ pfx_timer.function = pfx_timer_handler;
-+
-+ return 0;
-+}
-+
-+void mipv6_shutdown_pfx_icmpv6(void)
-+{
-+ struct prefix_info *tmp;
-+
-+ if (timer_pending(&pfx_timer))
-+ del_timer(&pfx_timer);
-+
-+ write_lock_bh(&pfx_list_lock);
-+ while ((tmp = mipv6_slist_del_first(&pfx_list)))
-+ kfree(tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.h linux-2.4.25/net/ipv6/mobile_ip6/prefix.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,57 @@
-+/*
-+ * MIPL Mobile IPv6 Prefix solicitation and advertisement
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _PREFIX_H
-+#define _PREFIX_H
-+
-+#include <net/addrconf.h>
-+
-+struct pfx_list_entry {
-+ struct in6_addr daddr;
-+ struct in6_addr saddr;
-+ int retries;
-+ int ifindex;
-+};
-+
-+extern struct list_head pfx_list;
-+extern rwlock_t pfx_list_lock;
-+extern struct timer_list pfx_timer;
-+
-+int compare_pfx_list_entry(const void *data1, const void *data2,
-+ int datalen);
-+
-+/**
-+ * mipv6_pfx_cancel_send - cancel pending pfx_advs/sols to daddr
-+ * @daddr: destination address
-+ * @ifindex: pending items on this interface will be canceled
-+ *
-+ * if ifindex == -1, all items to daddr will be removed
-+ */
-+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex);
-+
-+/**
-+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to
-+ * @daddr: address of HA
-+ * @saddr: our address to use as source address
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int ifindex);
-+
-+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex);
-+
-+int mipv6_pfx_add_home(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *saddr, unsigned long min_expire);
-+
-+int mipv6_initialize_pfx_icmpv6(void);
-+void mipv6_shutdown_pfx_icmpv6(void);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/prefix_ha.c linux-2.4.25/net/ipv6/mobile_ip6/prefix_ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/prefix_ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/prefix_ha.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,122 @@
-+/**
-+ * Prefix advertisement for Home Agent
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <linux/net.h>
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <linux/netdevice.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "mipv6_icmp.h"
-+#include "debug.h"
-+#include "sortedlist.h"
-+#include "util.h"
-+#include "bcache.h"
-+#include "config.h"
-+#include "prefix.h"
-+
-+/**
-+ * pfx_adv_iterator - modify pfx_list entries according to new prefix info
-+ * @data: MN's home registration bcache_entry
-+ * @args: new prefix info
-+ * @sortkey: ignored
-+ */
-+static int pfx_adv_iterator(void *data, void *args, unsigned long sortkey)
-+{
-+ struct mipv6_bce *bc_entry = (struct mipv6_bce *) data;
-+ struct prefix_info *pinfo = (struct prefix_info *) args;
-+
-+ if (mipv6_prefix_compare(&bc_entry->coa, &pinfo->prefix,
-+ pinfo->prefix_len) == 0) {
-+ struct pfx_list_entry pfx_entry;
-+
-+ memcpy(&pfx_entry.daddr, &bc_entry->coa,
-+ sizeof(struct in6_addr));
-+ memcpy(&pfx_entry.daddr, &bc_entry->our_addr,
-+ sizeof(struct in6_addr));
-+ pfx_entry.retries = 0;
-+ pfx_entry.ifindex = bc_entry->ifindex;
-+
-+ mipv6_slist_modify(&pfx_list, &pfx_entry,
-+ sizeof(struct pfx_list_entry),
-+ jiffies +
-+ net_random() % (MAX_PFX_ADV_DELAY * HZ),
-+ compare_pfx_list_entry);
-+ }
-+
-+ return 0;
-+}
-+
-+struct homereg_iterator_args {
-+ struct list_head *head;
-+ int count;
-+};
-+
-+static int homereg_iterator(void *data, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bce *entry = (struct mipv6_bce *) data;
-+ struct homereg_iterator_args *state =
-+ (struct homereg_iterator_args *) args;
-+
-+ if (entry->type == HOME_REGISTRATION) {
-+ mipv6_slist_add(state->head, entry,
-+ sizeof(struct mipv6_bce),
-+ state->count);
-+ state->count++;
-+ }
-+ return 0;
-+}
-+
-+static int mipv6_bcache_get_homeregs(struct list_head *head)
-+{
-+ struct homereg_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.count = 0;
-+ args.head = head;
-+
-+ mipv6_bcache_iterate(homereg_iterator, &args);
-+ return args.count;
-+}
-+
-+/**
-+ * mipv6_prefix_added - prefix was added to interface, act accordingly
-+ * @pinfo: prefix_info that was added
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex)
-+{
-+ int count;
-+ unsigned long tmp;
-+ struct list_head home_regs;
-+
-+ DEBUG_FUNC();
-+
-+ INIT_LIST_HEAD(&home_regs);
-+
-+ if (!(count = mipv6_bcache_get_homeregs(&home_regs)))
-+ return;
-+
-+ write_lock_bh(&pfx_list_lock);
-+ mipv6_slist_for_each(&home_regs, pinfo, pfx_adv_iterator);
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.c linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,255 @@
-+/*
-+ * rr_cookie.c - Mobile IPv6 return routability crypto
-+ * Author : Henrik Petander <henrik.petander@hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/kernel.h>
-+#include <linux/types.h>
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/random.h>
-+
-+#include <net/ipv6.h>
-+
-+#include "debug.h"
-+#include "hmac.h"
-+#include "rr_crypto.h"
-+
-+#define DBG_RR 5
-+
-+u8 k_CN[HMAC_SHA1_KEY_SIZE]; // secret key of CN
-+
-+u16 curr_index = 0;
-+
-+struct nonce_timestamp nonce_table[MAX_NONCES];
-+spinlock_t nonce_lock = SPIN_LOCK_UNLOCKED;
-+void update_nonces(void);
-+
-+/** nonce_is_fresh - whether the nonce was generated recently
-+ *
-+ * @non_ts : table entry containing the nonce and a timestamp
-+ * @interval : if nonce was generated within interval seconds it is fresh
-+ *
-+ * Returns 1 if the nonce is fresh, 0 otherwise.
-+ */
-+static int nonce_is_fresh(struct nonce_timestamp *non_ts, unsigned long interval)
-+{
-+ if (time_before(jiffies, non_ts->timestamp + interval * HZ) && !non_ts->invalid)
-+ return 1;
-+ return 0;
-+}
-+void mipv6_rr_invalidate_nonce(u16 nonce_ind)
-+{
-+ spin_lock_bh(&nonce_lock);
-+ if (nonce_ind > MAX_NONCES) {
-+ spin_unlock_bh(&nonce_lock);
-+ return;
-+ }
-+ nonce_table[nonce_ind].invalid = 1;
-+ spin_unlock_bh(&nonce_lock);
-+}
-+/* Returns a pointer to a new nonce */
-+struct mipv6_rr_nonce * mipv6_rr_get_new_nonce(void)
-+{
-+ struct mipv6_rr_nonce *nce = kmalloc(sizeof(*nce), GFP_ATOMIC);
-+
-+ if (!nce)
-+ return NULL;
-+ // Lock nonces here
-+ spin_lock_bh(&nonce_lock);
-+ // If nonce is not fresh create new one
-+ if (!nonce_is_fresh(&nonce_table[curr_index], MIPV6_RR_NONCE_LIFETIME)) {
-+ // increment the last nonce pointer and create new nonce
-+ curr_index++;
-+ // Wrap around
-+ if (curr_index == MAX_NONCES)
-+ curr_index = 0;
-+ // Get random data to fill the nonce data
-+ get_random_bytes(nonce_table[curr_index].nonce.data, MIPV6_RR_NONCE_DATA_LENGTH);
-+ // Fill the index field
-+ nonce_table[curr_index].nonce.index = curr_index;
-+ nonce_table[curr_index].invalid = 0;
-+ nonce_table[curr_index].timestamp = jiffies;
-+ }
-+ spin_unlock_bh(&nonce_lock);
-+ memcpy(nce, &nonce_table[curr_index].nonce, sizeof(*nce));
-+ // Unlock nonces
-+ return nce;
-+}
-+/** mipv6_rr_nonce_get_by_index - returns a nonce for index
-+ * @nonce_ind : index of the nonce
-+ *
-+ * Returns a nonce or NULL if the nonce index was invalid or the nonce
-+ * for the index was not fresh.
-+ */
-+struct mipv6_rr_nonce * mipv6_rr_nonce_get_by_index(u16 nonce_ind)
-+{
-+ struct mipv6_rr_nonce *nce = NULL;
-+
-+ spin_lock_bh(&nonce_lock);
-+ if (nonce_ind >= MAX_NONCES) {
-+ DEBUG(DBG_WARNING, "Nonce index field from BU invalid");
-+
-+ /* Here a double of the nonce_lifetime is used for freshness
-+ * verification, since the nonces
-+ * are not created in response to every initiator packet
-+ */
-+ } else if (nonce_is_fresh(&nonce_table[nonce_ind], 2 * MIPV6_RR_NONCE_LIFETIME)) {
-+ nce = kmalloc(sizeof(*nce), GFP_ATOMIC);
-+ memcpy(nce, &nonce_table[nonce_ind].nonce, sizeof(*nce));
-+ }
-+ spin_unlock_bh(&nonce_lock);
-+
-+ return nce;
-+}
-+
-+/* Fills rr test init cookies with random bytes */
-+void mipv6_rr_mn_cookie_create(u8 *cookie)
-+{
-+ get_random_bytes(cookie, MIPV6_RR_COOKIE_LENGTH);
-+}
-+
-+/** mipv6_rr_cookie_create - builds a home or care-of cookie
-+ *
-+ * @addr : the home or care-of address from HoTI or CoTI
-+ * @ckie : memory where the cookie is copied to
-+ * @nce : pointer to a nonce used for the calculation, nce is freed during the function
-+ *
-+ */
-+int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie,
-+ u16 nonce_index)
-+{
-+ struct ah_processing ah_proc;
-+ u8 digest[HMAC_SHA1_HASH_LEN];
-+ struct mipv6_rr_nonce *nce;
-+
-+ if ((nce = mipv6_rr_nonce_get_by_index(nonce_index))== NULL)
-+ return -1;
-+
-+ if (*ckie == NULL && (*ckie = kmalloc(MIPV6_RR_COOKIE_LENGTH,
-+ GFP_ATOMIC)) == NULL) {
-+ kfree(nce);
-+ return -1;
-+ }
-+ /* Calculate the full hmac-sha1 digest from address and nonce using the secret key of cn */
-+
-+ if (ah_hmac_sha1_init(&ah_proc, k_CN, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR, "Hmac sha1 initialization failed");
-+ kfree(nce);
-+ return -1;
-+ }
-+
-+ ah_hmac_sha1_loop(&ah_proc, addr, sizeof(*addr));
-+ ah_hmac_sha1_loop(&ah_proc, nce->data, MIPV6_RR_NONCE_DATA_LENGTH);
-+ ah_hmac_sha1_result(&ah_proc, digest);
-+
-+
-+ /* clean up nonce */
-+ kfree(nce);
-+
-+ /* Copy first 64 bits of hash target to the cookie */
-+ memcpy(*ckie, digest, MIPV6_RR_COOKIE_LENGTH);
-+ return 0;
-+}
-+
-+/** mipv6_rr_key_calc - creates BU authentication key
-+ *
-+ * @hoc : Home Cookie
-+ * @coc : Care-of Cookie
-+ *
-+ * Returns BU authentication key of length HMAC_SHA1_KEY_SIZE or NULL in error cases,
-+ * caller needs to free the key.
-+ */
-+u8 *mipv6_rr_key_calc(u8 *hoc, u8 *coc)
-+{
-+
-+ u8 *key_bu = kmalloc(HMAC_SHA1_KEY_SIZE, GFP_ATOMIC);
-+ SHA1_CTX c;
-+
-+ if (!key_bu) {
-+ DEBUG(DBG_CRITICAL, "Memory allocation failed, could nort create BU authentication key");
-+ return NULL;
-+ }
-+
-+ /* Calculate the key from home and care-of cookies
-+ * Kbu = sha1(home_cookie | care-of cookie)
-+ * or KBu = sha1(home_cookie), if MN deregisters
-+ */
-+ sha1_init(&c);
-+ sha1_compute(&c, hoc, MIPV6_RR_COOKIE_LENGTH);
-+ if (coc)
-+ sha1_compute(&c, coc, MIPV6_RR_COOKIE_LENGTH);
-+ sha1_final(&c, key_bu);
-+ DEBUG(DBG_RR, "Home and Care-of cookies used for calculating key ");
-+ debug_print_buffer(DBG_RR, hoc, MIPV6_RR_COOKIE_LENGTH);
-+ if (coc)
-+ debug_print_buffer(DBG_RR, coc, MIPV6_RR_COOKIE_LENGTH);
-+
-+ return key_bu;
-+}
-+
-+void mipv6_rr_init(void)
-+{
-+ get_random_bytes(k_CN, HMAC_SHA1_KEY_SIZE);
-+ memset(nonce_table, 0, MAX_NONCES * sizeof(struct nonce_timestamp));
-+}
-+
-+#ifdef TEST_MIPV6_RR_CRYPTO
-+void mipv6_test_rr(void)
-+{
-+ struct mipv6_rr_nonce *nonce;
-+ struct in6_addr a1, a2;
-+ int ind1, ind2;
-+ u8 *ckie1 = NULL, *ckie2 = NULL;
-+ u8 *key_mn = NULL, *key_cn = NULL;
-+ mipv6_init_rr();
-+
-+ nonce = mipv6_rr_get_new_nonce();
-+ if (!nonce) {
-+ printk("mipv6_rr_get_new_nonce() failed, at 1! \n");
-+ return;
-+ }
-+ mipv6_rr_cookie_create(&a1, &ckie1, nonce->index);
-+ ind1 = nonce->index;
-+ kfree(nonce);
-+
-+ nonce = mipv6_rr_get_new_nonce();
-+ if (!nonce) {
-+ printk("mipv6_rr_get_new_nonce() failed, at 2! \n");
-+ return;
-+ }
-+
-+ mipv6_rr_cookie_create(&a2, &ckie2, nonce->index);
-+ ind2 = nonce->index;
-+ key_mn = mipv6_rr_key_calc(ckie1, ckie2);
-+
-+ /* Create home and coa cookies based on indices */
-+ mipv6_rr_cookie_create(&a1, &ckie1, ind1);
-+ mipv6_rr_cookie_create(&a2, &ckie2, ind2);
-+ key_cn = mipv6_rr_key_calc(ckie1, ckie2);
-+ if (!key_cn || !key_mn) {
-+ printk("creation of secret key failed!\n");
-+ return;
-+ }
-+ if(memcmp(key_cn, key_mn, HMAC_SHA1_KEY_SIZE))
-+ printk("mipv6_rr_key_calc produced different keys for MN and CN \n");
-+ else
-+ printk("mipv6_rr_crypto test OK\n");
-+ kfree(nonce);
-+ kfree(key_cn);
-+ kfree(key_mn);
-+}
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.h linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/rr_crypto.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/rr_crypto.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,72 @@
-+/*
-+ * MIPL Mobile IPv6 Return routability crypto prototypes
-+ *
-+ * $Id:$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _RR_CRYPTO
-+#define _RR_CRYPTO
-+
-+#include <linux/in6.h>
-+
-+/* Macros and data structures */
-+
-+#define MIPV6_RR_NONCE_LIFETIME 60
-+#define MIPV6_RR_NONCE_DATA_LENGTH 8
-+#define MIPV6_RR_COOKIE_LENGTH 8
-+#define COOKIE_SIZE 8
-+#define MAX_NONCES 4
-+#define HMAC_SHA1_KEY_SIZE 20
-+
-+struct mipv6_rr_nonce {
-+ u_int16_t index;
-+ u_int8_t data[MIPV6_RR_NONCE_DATA_LENGTH];
-+};
-+
-+struct nonce_timestamp {
-+ struct mipv6_rr_nonce nonce;
-+ unsigned long timestamp;
-+ u_int8_t invalid;
-+};
-+
-+/* Function definitions */
-+
-+/* Return 1 if equal, 0 if not */
-+static __inline__ int mipv6_equal_cookies(u8 *c1, u8 *c2)
-+{
-+ return (memcmp(c1, c2, MIPV6_RR_COOKIE_LENGTH) == 0);
-+}
-+
-+/* Function declarations */
-+
-+/* Create cookie for HoTi and CoTi */
-+extern void mipv6_rr_mn_cookie_create(u8 *cookie);
-+
-+/* Create cookie for HoT and CoT */
-+extern int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie, u16 nonce_index);
-+
-+/* Calculate return routability key from home and care-of cookies, key length is
-+ * HMAC_SHA1_KEY_SIZE
-+ */
-+extern u_int8_t *mipv6_rr_key_calc(u8 *hoc, u8 *coc);
-+
-+extern struct mipv6_rr_nonce *mipv6_rr_get_new_nonce(void);
-+
-+/* For avoiding replay attacks when MN deregisters */
-+extern void mipv6_rr_invalidate_nonce(u16 nonce_index);
-+/*
-+ * initializes the return routability crypto
-+ */
-+
-+void mipv6_rr_init(void);
-+
-+#ifdef TEST_MIPV6_RR_CRYPTO
-+void mipv6_test_rr(void);
-+#endif /* TEST_MIPV6_RR_CRYPTO */
-+
-+#endif /* RR_CRYPTO */
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.c linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.c 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,349 @@
-+/**
-+ * Sorted list - linked list with sortkey.
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/kernel.h>
-+#include <linux/types.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+
-+struct mipv6_sorted_list_entry {
-+ struct list_head list;
-+ void *data;
-+ int datalen;
-+ unsigned long sortkey;
-+};
-+
-+/**
-+ * compare - compares two arbitrary data items
-+ * @data1: first data item
-+ * @data2: second data item
-+ * @datalen: length of data items in bits
-+ *
-+ * datalen is in bits!
-+ */
-+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen)
-+{
-+ int n = datalen;
-+ __u8 * ptr1 = (__u8 *)data1;
-+ __u8 * ptr2 = (__u8 *)data2;
-+
-+ for (; n>=0; n-=8, ptr1++, ptr2++) {
-+ if (n >= 8) {
-+ if (*ptr1 != *ptr2)
-+ return 0;
-+ } else {
-+ if ((*ptr1 ^ *ptr2) & ((~0) << (8 - n)))
-+ return 0;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_slist_add - add an entry to sorted list
-+ * @head: list_head of the sorted list
-+ * @data: item to store
-+ * @datalen: length of data (in bytes)
-+ * @key: sortkey of item
-+ *
-+ * Allocates memory for entry and data
-+ */
-+int mipv6_slist_add(struct list_head *head, void *data, int datalen,
-+ unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry, *tmp, *next;
-+
-+ entry = kmalloc(sizeof(struct mipv6_sorted_list_entry), GFP_ATOMIC);
-+
-+ if (!entry)
-+ return -1;
-+
-+ entry->data = kmalloc(datalen, GFP_ATOMIC);
-+
-+ if (!entry->data) {
-+ kfree(entry);
-+ return -1;
-+ }
-+
-+ memcpy(entry->data, data, datalen);
-+ entry->datalen = datalen;
-+ entry->sortkey = sortkey;
-+
-+ if ((pos = head->next) == head) {
-+ list_add(&entry->list, head);
-+ return 0;
-+ }
-+
-+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey < tmp->sortkey) {
-+ list_add(&entry->list, head);
-+ return 0;
-+ }
-+
-+ for (; pos != head; pos = pos->next) {
-+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (pos->next == head) {
-+ list_add(&entry->list, &tmp->list);
-+ return 0;
-+ }
-+ next = list_entry(pos->next, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey >= tmp->sortkey && entry->sortkey < next->sortkey) {
-+ list_add(&entry->list, &tmp->list);
-+ return 0;
-+ }
-+ }
-+
-+ /* never reached */
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_slist_get_first - get the first data item in the list
-+ * @head: list_head of the sorted list
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_first(struct list_head *head)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return NULL;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ return entry->data;
-+}
-+
-+/**
-+ * mipv6_slist_del_first - delete (and get) the first item in list
-+ * @head: list_head of the sorted list
-+ *
-+ * Remember to kfree the item
-+ */
-+void *mipv6_slist_del_first(struct list_head *head)
-+{
-+ void *tmp;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return NULL;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ tmp = entry->data;
-+
-+ list_del(head->next);
-+ kfree(entry);
-+
-+ return tmp;
-+}
-+
-+/**
-+ * mipv6_slist_del_item - delete entry
-+ * @head: list_head of the sorted list
-+ * @data: item to delete
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+int mipv6_slist_del_item(struct list_head *head, void *data,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for(pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, entry->datalen)) {
-+ list_del(pos);
-+ kfree(entry->data);
-+ kfree(entry);
-+ return 0;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_slist_get_first_key - get sortkey of the first item
-+ * @head: list_head of the sorted list
-+ */
-+unsigned long mipv6_slist_get_first_key(struct list_head *head)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return 0;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ return entry->sortkey;
-+}
-+
-+/**
-+ * mipv6_slist_get_key - get sortkey of the data item
-+ * @head: list_head of the sorted list
-+ * @data: the item to search for
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+unsigned long mipv6_slist_get_key(struct list_head *head, void *data,
-+ int (*compare)(const void *data1,
-+ const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for(pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, entry->datalen))
-+ return entry->sortkey;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_slist_get_data - get the data item identified by sortkey
-+ * @head: list_head of the sorted list
-+ * @key: sortkey of the item
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_for_each(pos, head) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey == sortkey)
-+ return entry->data;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * reorder_entry - move an entry to a new position according to sortkey
-+ * @head: list_head of the sorted list
-+ * @entry_pos: current place of the entry
-+ * @key: new sortkey
-+ */
-+static void reorder_entry(struct list_head *head, struct list_head *entry_pos,
-+ unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_del(entry_pos);
-+
-+ for (pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (sortkey >= entry->sortkey) {
-+ list_add(entry_pos, &entry->list);
-+ return;
-+ }
-+ }
-+
-+ list_add(entry_pos, head);
-+}
-+
-+/**
-+ * mipv6_slist_modify - modify data item
-+ * @head: list_head of the sorted list
-+ * @data: item, whose sortkey is to be modified
-+ * @datalen: datalen in bytes
-+ * @new_key: new sortkey
-+ * @compare: function used for comparing the data items
-+ *
-+ * Compies the new data on top of the old one, if compare function returns
-+ * true. If there's no matching entry, new one will be created.
-+ * Compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+int mipv6_slist_modify(struct list_head *head, void *data, int datalen,
-+ unsigned long new_key,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for (pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, datalen)) {
-+ memcpy(entry->data, data, datalen);
-+ entry->sortkey = new_key;
-+ reorder_entry(head, &entry->list, new_key);
-+ return 0;
-+ }
-+ }
-+
-+ return mipv6_slist_add(head, data, datalen, new_key);
-+}
-+
-+/**
-+ * mipv6_slist_push_first - move the first entry to place indicated by new_key
-+ * @head: list_head of the sorted list
-+ * @new_key: new sortkey
-+ */
-+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return -1;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ entry->sortkey = new_key;
-+
-+ reorder_entry(head, head->next, new_key);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_slist_for_each - apply func to every item in list
-+ * @head: list_head of the sorted list
-+ * @args: args to pass to func
-+ * @func: function to use
-+ *
-+ * function must be of type
-+ * int (*func)(void *data, void *args, unsigned long sortkey)
-+ * List iteration will stop once func has been applied to every item
-+ * or when func returns true
-+ */
-+int mipv6_slist_for_each(struct list_head *head, void *args,
-+ int (*func)(void *data, void *args,
-+ unsigned long sortkey))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_for_each(pos, head) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (func(entry->data, args, entry->sortkey))
-+ break;
-+ }
-+
-+ return 0;
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.h linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/sortedlist.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/sortedlist.h 2004-06-26 11:29:31.000000000 +0100
-@@ -0,0 +1,133 @@
-+/*
-+ * Sorted list - linked list with sortkey
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/**
-+ * compare - compares two arbitrary data items
-+ * @data1: first data item
-+ * @data2: second data item
-+ * @datalen: length of data items in bits
-+ *
-+ * datalen is in bits!
-+ */
-+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen);
-+
-+/**
-+ * mipv6_slist_add - add an entry to sorted list
-+ * @head: list_head of the sorted list
-+ * @data: item to store
-+ * @datalen: length of data (in bytes)
-+ * @key: sortkey of item
-+ *
-+ * Allocates memory for entry and data
-+ */
-+int mipv6_slist_add(struct list_head *head, void *data, int datalen,
-+ unsigned long sortkey);
-+
-+/**
-+ * mipv6_slist_get_first - get the first data item in the list
-+ * @head: list_head of the sorted list
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_first(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_del_first - delete (and get) the first item in list
-+ * @head: list_head of the sorted list
-+ *
-+ * Remember to kfree the item
-+ */
-+void *mipv6_slist_del_first(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_del_item - delete entry
-+ * @head: list_head of the sorted list
-+ * @data: item to delete
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits
-+ */
-+int mipv6_slist_del_item(struct list_head *head, void *data,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_get_first_key - get sortkey of the first item
-+ * @head: list_head of the sorted list
-+ */
-+unsigned long mipv6_slist_get_first_key(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_get_key - get sortkey of the data item
-+ * @head: list_head of the sorted list
-+ * @data: the item to search for
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits
-+ */
-+unsigned long mipv6_slist_get_key(struct list_head *head, void *data,
-+ int (*compare)(const void *data1,
-+ const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_get_data - get the data item identified by sortkey
-+ * @head: list_head of the sorted list
-+ * @key: sortkey of the item
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey);
-+
-+/**
-+ * mipv6_slist_modify - modify data item
-+ * @head: list_head of the sorted list
-+ * @data: item, whose sortkey is to be modified
-+ * @datalen: datalen in bytes
-+ * @new_key: new sortkey
-+ * @compare: function used for comparing the data items
-+ *
-+ * Compies the new data on top of the old one, if compare function returns
-+ * non-negative. If there's no matching entry, new one will be created.
-+ * Compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits.
-+ */
-+int mipv6_slist_modify(struct list_head *head, void *data, int datalen,
-+ unsigned long new_key,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_push_first - move the first entry to place indicated by new_key
-+ * @head: list_head of the sorted list
-+ * @new_key: new sortkey
-+ */
-+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key);
-+
-+/**
-+ * mipv6_slist_for_each - apply func to every item in list
-+ * @head: list_head of the sorted list
-+ * @args: args to pass to func
-+ * @func: function to use
-+ *
-+ * function must be of type
-+ * int (*func)(void *data, void *args, unsigned long sortkey)
-+ * List iteration will stop once func has been applied to every item
-+ * or when func returns true
-+ */
-+int mipv6_slist_for_each(struct list_head *head, void *args,
-+ int (*func)(void *data, void *args,
-+ unsigned long sortkey));
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/stats.c linux-2.4.25/net/ipv6/mobile_ip6/stats.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/stats.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/stats.c 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,90 @@
-+/*
-+ * Statistics module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes:
-+ * Krishna Kumar,
-+ * Venkata Jagana : SMP locking fix
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/proc_fs.h>
-+#include "stats.h"
-+
-+struct mipv6_statistics mipv6_stats;
-+
-+static int proc_info_dump(
-+ char *buffer, char **start,
-+ off_t offset, int length)
-+{
-+ struct inf {
-+ char *name;
-+ int *value;
-+ } int_stats[] = {
-+ {"NEncapsulations", &mipv6_stats.n_encapsulations},
-+ {"NDecapsulations", &mipv6_stats.n_decapsulations},
-+ {"NBindRefreshRqsRcvd", &mipv6_stats.n_brr_rcvd},
-+ {"NHomeTestInitsRcvd", &mipv6_stats.n_hoti_rcvd},
-+ {"NCareofTestInitsRcvd", &mipv6_stats.n_coti_rcvd},
-+ {"NHomeTestRcvd", &mipv6_stats.n_hot_rcvd},
-+ {"NCareofTestRcvd", &mipv6_stats.n_cot_rcvd},
-+ {"NBindUpdatesRcvd", &mipv6_stats.n_bu_rcvd},
-+ {"NBindAcksRcvd", &mipv6_stats.n_ba_rcvd},
-+ {"NBindNAcksRcvd", &mipv6_stats.n_ban_rcvd},
-+ {"NBindErrorsRcvd", &mipv6_stats.n_be_rcvd},
-+ {"NBindRefreshRqsSent", &mipv6_stats.n_brr_sent},
-+ {"NHomeTestInitsSent", &mipv6_stats.n_hoti_sent},
-+ {"NCareofTestInitsSent", &mipv6_stats.n_coti_sent},
-+ {"NHomeTestSent", &mipv6_stats.n_hot_sent},
-+ {"NCareofTestSent", &mipv6_stats.n_cot_sent},
-+ {"NBindUpdatesSent", &mipv6_stats.n_bu_sent},
-+ {"NBindAcksSent", &mipv6_stats.n_ba_sent},
-+ {"NBindNAcksSent", &mipv6_stats.n_ban_sent},
-+ {"NBindErrorsSent", &mipv6_stats.n_be_sent},
-+ {"NBindUpdatesDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindUpdatesDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindUpdatesDropMisc", &mipv6_stats.n_bu_drop.misc},
-+ {"NBindAcksDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindAcksDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindAcksDropMisc", &mipv6_stats.n_bu_drop.misc},
-+ {"NBindRqsDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindRqsDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindRqsDropMisc", &mipv6_stats.n_bu_drop.misc}
-+ };
-+
-+ int i;
-+ int len = 0;
-+ for(i=0; i<sizeof(int_stats) / sizeof(struct inf); i++) {
-+ len += sprintf(buffer + len, "%s = %d\n",
-+ int_stats[i].name, *int_stats[i].value);
-+ }
-+
-+ *start = buffer + offset;
-+
-+ len -= offset;
-+
-+ if(len > length) len = length;
-+
-+ return len;
-+}
-+
-+int mipv6_stats_init(void)
-+{
-+ memset(&mipv6_stats, 0, sizeof(struct mipv6_statistics));
-+ proc_net_create("mip6_stat", 0, proc_info_dump);
-+ return 0;
-+}
-+
-+void mipv6_stats_exit(void)
-+{
-+ proc_net_remove("mip6_stat");
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/stats.h linux-2.4.25/net/ipv6/mobile_ip6/stats.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/stats.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/stats.h 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,71 @@
-+/*
-+ * MIPL Mobile IPv6 Statistics header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _STATS_H
-+#define _STATS_H
-+
-+struct mipv6_drop {
-+ __u32 auth;
-+ __u32 invalid;
-+ __u32 misc;
-+};
-+
-+struct mipv6_statistics {
-+ int n_encapsulations;
-+ int n_decapsulations;
-+ int n_mh_in_msg;
-+ int n_mh_in_error;
-+ int n_mh_out_msg;
-+ int n_mh_out_error;
-+
-+ int n_brr_rcvd;
-+ int n_hoti_rcvd;
-+ int n_coti_rcvd;
-+ int n_hot_rcvd;
-+ int n_cot_rcvd;
-+ int n_bu_rcvd;
-+ int n_ba_rcvd;
-+ int n_ban_rcvd;
-+ int n_be_rcvd;
-+
-+ int n_brr_sent;
-+ int n_hoti_sent;
-+ int n_coti_sent;
-+ int n_hot_sent;
-+ int n_cot_sent;
-+ int n_bu_sent;
-+ int n_ba_sent;
-+ int n_ban_sent;
-+ int n_be_sent;
-+
-+ int n_ha_rcvd;
-+ int n_ha_sent;
-+
-+ struct mipv6_drop n_bu_drop;
-+ struct mipv6_drop n_ba_drop;
-+ struct mipv6_drop n_brr_drop;
-+ struct mipv6_drop n_be_drop;
-+ struct mipv6_drop n_ha_drop;
-+};
-+
-+extern struct mipv6_statistics mipv6_stats;
-+
-+#ifdef CONFIG_SMP
-+/* atomic_t is max 24 bits long */
-+#define MIPV6_INC_STATS(X) atomic_inc((atomic_t *)&mipv6_stats.X);
-+#else
-+#define MIPV6_INC_STATS(X) mipv6_stats.X++;
-+#endif
-+
-+int mipv6_stats_init(void);
-+void mipv6_stats_exit(void);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel.h 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,35 @@
-+/*
-+ * MIPL Mobile IPv6 IP6-IP6 tunneling header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _TUNNEL_H
-+#define _TUNNEL_H
-+
-+#include <linux/in6.h>
-+#include <linux/if_arp.h>
-+#include <net/ipv6_tunnel.h>
-+
-+static __inline__ int is_mip6_tnl(struct ip6_tnl *t)
-+{
-+ return (t != NULL &&
-+ t->parms.flags & IP6_TNL_F_KERNEL_DEV &&
-+ t->parms.flags & IP6_TNL_F_MIP6_DEV);
-+
-+}
-+
-+static __inline__ int dev_is_mip6_tnl(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *)dev->priv;
-+ return (dev->type == ARPHRD_TUNNEL6 && is_mip6_tnl(t));
-+}
-+
-+
-+#endif
-+
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.c linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.c 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,264 @@
-+/*
-+ * IPv6-IPv6 tunneling module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Ville Nuorvala <vnuorval@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/netdevice.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/ipv6_route.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/protocol.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/dst.h>
-+#include <net/addrconf.h>
-+
-+#include "tunnel.h"
-+#include "debug.h"
-+#include "stats.h"
-+#include "config.h"
-+
-+#define MIPV6_TNL_MAX IP6_TNL_MAX
-+#define MIPV6_TNL_MIN 1
-+
-+int mipv6_max_tnls = 3;
-+int mipv6_min_tnls = 1;
-+
-+DECLARE_MUTEX(tnl_sem);
-+
-+int mipv6_max_tnls_sysctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ down(&tnl_sem);
-+ if (write) {
-+ int diff;
-+ int old_max_tnls = mipv6_max_tnls;
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ if (err < 0)
-+ goto out;
-+ if (mipv6_max_tnls < mipv6_min_tnls ||
-+ mipv6_max_tnls > MIPV6_TNL_MAX) {
-+ mipv6_max_tnls = old_max_tnls;
-+ goto out;
-+ }
-+ if (mipv6_max_tnls < old_max_tnls) {
-+ diff = old_max_tnls - mipv6_max_tnls;
-+ ip6ip6_tnl_dec_max_kdev_count(diff);
-+ } else if (mipv6_max_tnls > old_max_tnls) {
-+ diff = mipv6_max_tnls - old_max_tnls;
-+ ip6ip6_tnl_inc_max_kdev_count(diff);
-+ }
-+ } else {
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ }
-+out:
-+ up(&tnl_sem);
-+ return err;
-+}
-+
-+int mipv6_min_tnls_sysctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ down(&tnl_sem);
-+ if (write) {
-+ int diff;
-+ int old_min_tnls = mipv6_min_tnls;
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ if (err < 0)
-+ goto out;
-+ if (mipv6_min_tnls > mipv6_max_tnls ||
-+ mipv6_min_tnls < MIPV6_TNL_MIN) {
-+ mipv6_min_tnls = old_min_tnls;
-+ goto out;
-+ }
-+ if (mipv6_min_tnls < old_min_tnls) {
-+ diff = old_min_tnls - mipv6_min_tnls;
-+ ip6ip6_tnl_dec_min_kdev_count(diff);
-+ } else if (mipv6_min_tnls > old_min_tnls) {
-+ diff = mipv6_min_tnls - old_min_tnls;
-+ ip6ip6_tnl_inc_min_kdev_count(diff);
-+ }
-+ } else {
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ }
-+out:
-+ up(&tnl_sem);
-+ return err;
-+}
-+
-+static __inline__ int mipv6_tnl_add(struct in6_addr *remote,
-+ struct in6_addr *local)
-+{
-+ struct ip6_tnl_parm p;
-+ int ret;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ ipv6_addr_copy(&p.laddr, local);
-+ ipv6_addr_copy(&p.raddr, remote);
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+
-+ ret = ip6ip6_kernel_tnl_add(&p);
-+ if (ret > 0) {
-+ DEBUG(DBG_INFO, "added tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+ } else {
-+ DEBUG(DBG_WARNING, "unable to add tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+ }
-+ return ret;
-+}
-+
-+static __inline__ int mipv6_tnl_del(struct in6_addr *remote,
-+ struct in6_addr *local)
-+{
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(remote, local);
-+
-+ DEBUG_FUNC();
-+
-+ if (t != NULL && (t->parms.flags & IP6_TNL_F_MIP6_DEV)) {
-+ DEBUG(DBG_INFO, "deleting tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+
-+ return ip6ip6_kernel_tnl_del(t);
-+ }
-+ return 0;
-+}
-+
-+static int add_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct in6_rtmsg rtmsg;
-+ int err;
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr);
-+
-+ if (!is_mip6_tnl(t)) {
-+ DEBUG(DBG_CRITICAL,"Tunnel missing");
-+ return -ENODEV;
-+ }
-+
-+ DEBUG(DBG_INFO, "adding route to: %x:%x:%x:%x:%x:%x:%x:%x via "
-+ "tunnel device", NIPV6ADDR(home_addr));
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr);
-+ rtmsg.rtmsg_dst_len = 128;
-+ rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-+ rtmsg.rtmsg_flags = RTF_UP | RTF_NONEXTHOP | RTF_HOST | RTF_MOBILENODE;
-+ rtmsg.rtmsg_ifindex = t->dev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) {
-+ err = 0;
-+ }
-+ return err;
-+}
-+
-+static void del_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr);
-+
-+ DEBUG_FUNC();
-+
-+ if (is_mip6_tnl(t)) {
-+ struct in6_rtmsg rtmsg;
-+
-+ DEBUG(DBG_INFO, "deleting route to: %x:%x:%x:%x:%x:%x:%x:%x "
-+ " via tunnel device", NIPV6ADDR(home_addr));
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr);
-+ rtmsg.rtmsg_dst_len = 128;
-+ rtmsg.rtmsg_ifindex = t->dev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ ip6_route_del(&rtmsg, NULL);
-+ }
-+}
-+
-+
-+int mipv6_add_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ int ret;
-+
-+ DEBUG_FUNC();
-+
-+ ret = mipv6_tnl_add(coa, ha_addr);
-+
-+ if (ret > 0) {
-+ int err = add_route_to_mn(coa, ha_addr, home_addr);
-+ if (err) {
-+ if (err != -ENODEV) {
-+ mipv6_tnl_del(coa, ha_addr);
-+ }
-+ return err;
-+ }
-+ }
-+ return ret;
-+}
-+
-+int mipv6_del_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ DEBUG_FUNC();
-+ del_route_to_mn(coa, ha_addr, home_addr);
-+ return mipv6_tnl_del(coa, ha_addr);
-+}
-+
-+__init void mipv6_initialize_tunnel(void)
-+{
-+ down(&tnl_sem);
-+ ip6ip6_tnl_inc_max_kdev_count(mipv6_max_tnls);
-+ ip6ip6_tnl_inc_min_kdev_count(mipv6_min_tnls);
-+ up(&tnl_sem);
-+ mip6_fn.bce_tnl_rt_add = add_route_to_mn;
-+ mip6_fn.bce_tnl_rt_del = del_route_to_mn;
-+}
-+
-+__exit void mipv6_shutdown_tunnel(void)
-+{
-+ mip6_fn.bce_tnl_rt_del = NULL;
-+ mip6_fn.bce_tnl_rt_add = NULL;
-+ down(&tnl_sem);
-+ ip6ip6_tnl_dec_min_kdev_count(mipv6_min_tnls);
-+ ip6ip6_tnl_dec_max_kdev_count(mipv6_max_tnls);
-+ up(&tnl_sem);
-+}
-+
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_ha.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_ha.h 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,20 @@
-+#ifndef _TUNNEL_HA_H
-+#define _TUNNEL_HA_H
-+
-+#include "tunnel.h"
-+
-+extern int mipv6_max_tnls;
-+extern int mipv6_min_tnls;
-+
-+extern void mipv6_initialize_tunnel(void);
-+extern void mipv6_shutdown_tunnel(void);
-+
-+extern int mipv6_add_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+extern int mipv6_del_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.c linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.c
---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.c 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,160 @@
-+/*
-+ * IPv6-IPv6 tunneling module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Ville Nuorvala <vnuorval@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/netdevice.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/ipv6_route.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/protocol.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/dst.h>
-+#include <net/addrconf.h>
-+
-+#include "tunnel.h"
-+#include "debug.h"
-+#include "stats.h"
-+
-+static struct net_device *mn_ha_tdev;
-+
-+static spinlock_t mn_ha_lock = SPIN_LOCK_UNLOCKED;
-+
-+static __inline__ int add_reverse_route(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ struct net_device *tdev)
-+{
-+ struct in6_rtmsg rtmsg;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr);
-+ rtmsg.rtmsg_src_len = 128;
-+ rtmsg.rtmsg_flags = RTF_UP | RTF_DEFAULT;
-+ rtmsg.rtmsg_ifindex = tdev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) {
-+ return 0;
-+ }
-+ return err;
-+}
-+
-+static __inline__ void del_reverse_route(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ struct net_device *tdev)
-+{
-+ struct in6_rtmsg rtmsg;
-+
-+ DEBUG(DBG_INFO, "removing reverse route via tunnel device");
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr);
-+ rtmsg.rtmsg_src_len = 128;
-+ rtmsg.rtmsg_ifindex = tdev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ ip6_route_del(&rtmsg, NULL);
-+}
-+
-+int mipv6_add_tnl_to_ha(void)
-+{
-+ struct ip6_tnl_parm p;
-+ struct ip6_tnl *t;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+ strcpy(p.name, "mip6mnha1");
-+
-+ rtnl_lock();
-+ if ((err = ip6ip6_tnl_create(&p, &t))) {
-+ rtnl_unlock();
-+ return err;
-+ }
-+ spin_lock_bh(&mn_ha_lock);
-+
-+ if (!mn_ha_tdev) {
-+ mn_ha_tdev = t->dev;
-+ dev_hold(mn_ha_tdev);
-+ }
-+ spin_unlock_bh(&mn_ha_lock);
-+ dev_open(t->dev);
-+ rtnl_unlock();
-+ return 0;
-+}
-+
-+int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr,
-+ struct in6_addr *coa,
-+ struct in6_addr *home_addr)
-+{
-+ int err = -ENODEV;
-+
-+ DEBUG_FUNC();
-+
-+ spin_lock_bh(&mn_ha_lock);
-+ if (mn_ha_tdev) {
-+ struct ip6_tnl_parm p;
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ ipv6_addr_copy(&p.laddr, coa);
-+ ipv6_addr_copy(&p.raddr, ha_addr);
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+
-+ ip6ip6_tnl_change((struct ip6_tnl *) mn_ha_tdev->priv, &p);
-+ if (ipv6_addr_cmp(coa, home_addr)) {
-+ err = add_reverse_route(ha_addr, home_addr,
-+ mn_ha_tdev);
-+ } else {
-+ del_reverse_route(ha_addr, home_addr, mn_ha_tdev);
-+ err = 0;
-+ }
-+ }
-+ spin_unlock_bh(&mn_ha_lock);
-+ return err;
-+}
-+
-+void mipv6_del_tnl_to_ha(void)
-+{
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ rtnl_lock();
-+ spin_lock_bh(&mn_ha_lock);
-+ dev = mn_ha_tdev;
-+ mn_ha_tdev = NULL;
-+ spin_unlock_bh(&mn_ha_lock);
-+ dev_put(dev);
-+ unregister_netdevice(dev);
-+ rtnl_unlock();
-+}
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.h linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/tunnel_mn.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/tunnel_mn.h 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,14 @@
-+#ifndef _TUNNEL_MN_H
-+#define _TUNNEL_MN_H
-+
-+#include "tunnel.h"
-+
-+extern int mipv6_add_tnl_to_ha(void);
-+
-+extern int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr,
-+ struct in6_addr *coa,
-+ struct in6_addr *home_addr);
-+
-+extern int mipv6_del_tnl_to_ha(void);
-+
-+#endif
-diff -uprN linux-2.4.25.old/net/ipv6/mobile_ip6/util.h linux-2.4.25/net/ipv6/mobile_ip6/util.h
---- linux-2.4.25.old/net/ipv6/mobile_ip6/util.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.25/net/ipv6/mobile_ip6/util.h 2004-06-26 11:29:32.000000000 +0100
-@@ -0,0 +1,91 @@
-+/*
-+ * MIPL Mobile IPv6 Utility functions
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _UTIL_H
-+#define _UTIL_H
-+
-+#include <linux/in6.h>
-+#include <asm/byteorder.h>
-+
-+/**
-+ * mipv6_prefix_compare - Compare two IPv6 prefixes
-+ * @addr: IPv6 address
-+ * @prefix: IPv6 address
-+ * @nprefix: number of bits to compare
-+ *
-+ * Perform prefix comparison bitwise for the @nprefix first bits
-+ * Returns 1, if the prefixes are the same, 0 otherwise
-+ **/
-+static inline int mipv6_prefix_compare(const struct in6_addr *addr,
-+ const struct in6_addr *prefix,
-+ const unsigned int pfix_len)
-+{
-+ int i;
-+ unsigned int nprefix = pfix_len;
-+
-+ if (nprefix > 128)
-+ return 0;
-+
-+ for (i = 0; nprefix > 0; nprefix -= 32, i++) {
-+ if (nprefix >= 32) {
-+ if (addr->s6_addr32[i] != prefix->s6_addr32[i])
-+ return 0;
-+ } else {
-+ if (((addr->s6_addr32[i] ^ prefix->s6_addr32[i]) &
-+ ((~0) << (32 - nprefix))) != 0)
-+ return 0;
-+ return 1;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/**
-+ * homeagent_anycast - Compute Home Agent anycast address
-+ * @ac_addr: append home agent anycast suffix to passed prefix
-+ * @prefix: prefix ha anycast address is generated from
-+ * @plen: length of prefix in bits
-+ *
-+ * Calculate corresponding Home Agent Anycast Address (RFC2526) in a
-+ * given subnet.
-+ */
-+static inline int
-+mipv6_ha_anycast(struct in6_addr *ac_addr, struct in6_addr *prefix, int plen)
-+{
-+ if (plen <= 0 || plen > 120) {
-+ /* error, interface id should be minimum 8 bits */
-+ return -1;
-+ }
-+ ipv6_addr_copy(ac_addr, prefix);
-+
-+ if (plen < 32)
-+ ac_addr->s6_addr32[0] |= htonl((u32)(~0) >> plen);
-+ if (plen < 64)
-+ ac_addr->s6_addr32[1] |= htonl((u32)(~0) >> (plen > 32 ? plen % 32 : 0));
-+ if (plen < 92)
-+ ac_addr->s6_addr32[2] |= htonl((u32)(~0) >> (plen > 64 ? plen % 32 : 0));
-+ if (plen <= 120)
-+ ac_addr->s6_addr32[3] |= htonl((u32)(~0) >> (plen > 92 ? plen % 32 : 0));
-+
-+ /* RFC2526: for interface identifiers in EUI-64
-+ * format, the universal/local bit in the interface
-+ * identifier MUST be set to 0. */
-+ if (plen == 64) {
-+ ac_addr->s6_addr32[2] &= (int)htonl(0xfdffffff);
-+ }
-+ /* Mobile IPv6 Home-Agents anycast id (0x7e) */
-+ ac_addr->s6_addr32[3] &= (int)htonl(0xfffffffe);
-+
-+ return 0;
-+}
-+
-+#endif /* _UTIL_H */
-diff -uprN linux-2.4.25.old/net/ipv6/ndisc.c linux-2.4.25/net/ipv6/ndisc.c
---- linux-2.4.25.old/net/ipv6/ndisc.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/ndisc.c 2004-06-26 11:29:32.000000000 +0100
-@@ -23,6 +23,7 @@
- * and moved to net/core.
- * Pekka Savola : RFC2461 validation
- * YOSHIFUJI Hideaki @USAGI : Verify ND options properly
-+ * Ville Nuorvala : RFC2461 fixes to proxy ND
- */
-
- /* Set to 3 to get tracing... */
-@@ -70,6 +71,7 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
- #include <net/icmp.h>
-+#include <net/mipglue.h>
-
- #include <net/checksum.h>
- #include <linux/proc_fs.h>
-@@ -187,6 +189,8 @@ struct ndisc_options *ndisc_parse_option
- case ND_OPT_TARGET_LL_ADDR:
- case ND_OPT_MTU:
- case ND_OPT_REDIRECT_HDR:
-+ case ND_OPT_RTR_ADV_INTERVAL:
-+ case ND_OPT_HOME_AGENT_INFO:
- if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
- ND_PRINTK2((KERN_WARNING
- "ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
-@@ -372,8 +376,8 @@ ndisc_build_ll_hdr(struct sk_buff *skb,
- */
-
- void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
-- struct in6_addr *daddr, struct in6_addr *solicited_addr,
-- int router, int solicited, int override, int inc_opt)
-+ struct in6_addr *daddr, struct in6_addr *solicited_addr,
-+ int router, int solicited, int override, int inc_opt)
- {
- static struct in6_addr tmpaddr;
- struct inet6_ifaddr *ifp;
-@@ -766,7 +770,8 @@ void ndisc_recv_ns(struct sk_buff *skb)
- int addr_type = ipv6_addr_type(saddr);
-
- if (in6_dev && in6_dev->cnf.forwarding &&
-- (addr_type & IPV6_ADDR_UNICAST) &&
-+ (addr_type & IPV6_ADDR_UNICAST ||
-+ addr_type == IPV6_ADDR_ANY) &&
- pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
- int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;
-
-@@ -778,13 +783,21 @@ void ndisc_recv_ns(struct sk_buff *skb)
- nd_tbl.stats.rcv_probes_mcast++;
- else
- nd_tbl.stats.rcv_probes_ucast++;
--
-- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-
-- if (neigh) {
-- ndisc_send_na(dev, neigh, saddr, &msg->target,
-- 0, 1, 0, 1);
-- neigh_release(neigh);
-+ if (addr_type & IPV6_ADDR_UNICAST) {
-+ neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-+
-+ if (neigh) {
-+ ndisc_send_na(dev, neigh, saddr, &msg->target,
-+ 0, 1, 0, 1);
-+ neigh_release(neigh);
-+ }
-+ } else {
-+ /* the proxy should also protect against DAD */
-+ struct in6_addr maddr;
-+ ipv6_addr_all_nodes(&maddr);
-+ ndisc_send_na(dev, NULL, &maddr, &msg->target,
-+ 0, 0, 0, 1);
- }
- } else {
- struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
-@@ -849,6 +862,9 @@ void ndisc_recv_na(struct sk_buff *skb)
- if (ifp->flags & IFA_F_TENTATIVE) {
- addrconf_dad_failure(ifp);
- return;
-+ } else if (ndisc_mip_mn_ha_probe(ifp, lladdr)) {
-+ in6_ifa_put(ifp);
-+ return;
- }
- /* What should we make now? The advertisement
- is invalid, but ndisc specs say nothing
-@@ -887,6 +903,7 @@ void ndisc_recv_na(struct sk_buff *skb)
- msg->icmph.icmp6_override, 1);
- neigh_release(neigh);
- }
-+ ndisc_check_mipv6_dad(&msg->target);
- }
-
- static void ndisc_router_discovery(struct sk_buff *skb)
-@@ -894,6 +911,7 @@ static void ndisc_router_discovery(struc
- struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
- struct neighbour *neigh;
- struct inet6_dev *in6_dev;
-+ int change_rtr;
- struct rt6_info *rt;
- int lifetime;
- struct ndisc_options ndopts;
-@@ -923,10 +941,6 @@ static void ndisc_router_discovery(struc
- ND_PRINTK1("RA: can't find in6 device\n");
- return;
- }
-- if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
-- in6_dev_put(in6_dev);
-- return;
-- }
-
- if (!ndisc_parse_options(opt, optlen, &ndopts)) {
- in6_dev_put(in6_dev);
-@@ -935,7 +949,12 @@ static void ndisc_router_discovery(struc
- "ICMP6 RA: invalid ND option, ignored.\n");
- return;
- }
-+ change_rtr = ndisc_mipv6_ra_rcv(skb, &ndopts);
-
-+ if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
-+ in6_dev_put(in6_dev);
-+ return;
-+ }
- if (in6_dev->if_flags & IF_RS_SENT) {
- /*
- * flag that an RA was received after an RS was sent
-@@ -963,8 +982,7 @@ static void ndisc_router_discovery(struc
- ip6_del_rt(rt, NULL);
- rt = NULL;
- }
--
-- if (rt == NULL && lifetime) {
-+ if (rt == NULL && lifetime && change_rtr) {
- ND_PRINTK2("ndisc_rdisc: adding default router\n");
-
- rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
-@@ -1087,6 +1105,8 @@ out:
- if (rt)
- dst_release(&rt->u.dst);
- in6_dev_put(in6_dev);
-+
-+ ndisc_mipv6_change_router(change_rtr);
- }
-
- static void ndisc_redirect_rcv(struct sk_buff *skb)
-diff -uprN linux-2.4.25.old/net/ipv6/raw.c linux-2.4.25/net/ipv6/raw.c
---- linux-2.4.25.old/net/ipv6/raw.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/raw.c 2004-06-26 11:29:32.000000000 +0100
-@@ -43,6 +43,7 @@
- #include <net/transp_v6.h>
- #include <net/udp.h>
- #include <net/inet_common.h>
-+#include <net/mipglue.h>
-
- #include <net/rawv6.h>
-
-@@ -636,6 +637,7 @@ static int rawv6_sendmsg(struct sock *sk
- hdr.daddr = daddr;
- else
- hdr.daddr = NULL;
-+ hdr.daddr = mipv6_get_fake_hdr_daddr(hdr.daddr, daddr);
-
- err = ip6_build_xmit(sk, rawv6_frag_cksum, &hdr, &fl, len,
- opt, hlimit, msg->msg_flags);
-diff -uprN linux-2.4.25.old/net/ipv6/route.c linux-2.4.25/net/ipv6/route.c
---- linux-2.4.25.old/net/ipv6/route.c 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/net/ipv6/route.c 2004-06-26 11:29:32.000000000 +0100
-@@ -49,6 +49,7 @@
- #include <net/addrconf.h>
- #include <net/tcp.h>
- #include <linux/rtnetlink.h>
-+#include <net/mipglue.h>
-
- #include <asm/uaccess.h>
-
-@@ -363,12 +364,8 @@ static struct rt6_info *rt6_cow(struct r
- rt->u.dst.flags |= DST_HOST;
-
- #ifdef CONFIG_IPV6_SUBTREES
-- if (rt->rt6i_src.plen && saddr) {
-- ipv6_addr_copy(&rt->rt6i_src.addr, saddr);
-- rt->rt6i_src.plen = 128;
-- }
-+ rt->rt6i_src.plen = ort->rt6i_src.plen;
- #endif
--
- rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
-
- dst_hold(&rt->u.dst);
-@@ -511,14 +508,19 @@ struct dst_entry * ip6_route_output(stru
- struct rt6_info *rt;
- int strict;
- int attempts = 3;
-+ struct in6_addr *saddr;
-
-+ if (ipv6_chk_addr(fl->nl_u.ip6_u.daddr, NULL))
-+ saddr = NULL;
-+ else
-+ saddr = fl->nl_u.ip6_u.saddr;
-+
- strict = ipv6_addr_type(fl->nl_u.ip6_u.daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL);
-
- relookup:
- read_lock_bh(&rt6_lock);
-
-- fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr,
-- fl->nl_u.ip6_u.saddr);
-+ fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, saddr);
-
- restart:
- rt = fn->leaf;
-@@ -663,25 +665,6 @@ out:
- return (atomic_read(&ip6_dst_ops.entries) > ip6_rt_max_size);
- }
-
--/* Clean host part of a prefix. Not necessary in radix tree,
-- but results in cleaner routing tables.
--
-- Remove it only when all the things will work!
-- */
--
--static void ipv6_addr_prefix(struct in6_addr *pfx,
-- const struct in6_addr *addr, int plen)
--{
-- int b = plen&0x7;
-- int o = plen>>3;
--
-- memcpy(pfx->s6_addr, addr, o);
-- if (o < 16)
-- memset(pfx->s6_addr + o, 0, 16 - o);
-- if (b != 0)
-- pfx->s6_addr[o] = addr->s6_addr[o]&(0xff00 >> b);
--}
--
- static int ipv6_get_mtu(struct net_device *dev)
- {
- int mtu = IPV6_MIN_MTU;
-@@ -810,7 +793,7 @@ int ip6_route_add(struct in6_rtmsg *rtms
- if (!(gwa_type&IPV6_ADDR_UNICAST))
- goto out;
-
-- grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1);
-+ grt = rt6_lookup(gw_addr, &rtmsg->rtmsg_src, rtmsg->rtmsg_ifindex, 1);
-
- err = -EHOSTUNREACH;
- if (grt == NULL)
-@@ -848,7 +831,15 @@ int ip6_route_add(struct in6_rtmsg *rtms
- goto out;
- }
- }
--
-+#ifdef USE_IPV6_MOBILITY
-+ /* If destination is mobile node, add special skb->dst->input
-+ * function for proxy ND.
-+ */
-+ if (rtmsg->rtmsg_flags & RTF_MOBILENODE) {
-+ rt->u.dst.input = ip6_mipv6_forward;
-+ }
-+#endif /* CONFIG_IPV6_MOBILITY */
-+
- if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
- rt->rt6i_hoplimit = IPV6_DEFAULT_MCASTHOPS;
- else
-@@ -936,7 +927,7 @@ void rt6_redirect(struct in6_addr *dest,
- struct rt6_info *rt, *nrt;
-
- /* Locate old route to this destination. */
-- rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1);
-+ rt = rt6_lookup(dest, saddr, neigh->dev->ifindex, 1);
-
- if (rt == NULL)
- return;
-@@ -1003,6 +994,9 @@ source_ok:
- nrt = ip6_rt_copy(rt);
- if (nrt == NULL)
- goto out;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ nrt->rt6i_src.plen = rt->rt6i_src.plen;
-+#endif
-
- nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
- if (on_link)
-@@ -1104,6 +1098,9 @@ void rt6_pmtu_discovery(struct in6_addr
- nrt = ip6_rt_copy(rt);
- if (nrt == NULL)
- goto out;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ nrt->rt6i_src.plen = rt->rt6i_src.plen;
-+#endif
- ipv6_addr_copy(&nrt->rt6i_dst.addr, daddr);
- nrt->rt6i_dst.plen = 128;
- nrt->u.dst.flags |= DST_HOST;
-diff -uprN linux-2.4.25.old/net/ipv6/tcp_ipv6.c linux-2.4.25/net/ipv6/tcp_ipv6.c
---- linux-2.4.25.old/net/ipv6/tcp_ipv6.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/ipv6/tcp_ipv6.c 2004-06-26 11:29:32.000000000 +0100
-@@ -50,6 +50,7 @@
- #include <net/addrconf.h>
- #include <net/ip6_route.h>
- #include <net/inet_ecn.h>
-+#include <net/mipglue.h>
-
- #include <asm/uaccess.h>
-
-@@ -557,6 +558,7 @@ static int tcp_v6_connect(struct sock *s
- struct flowi fl;
- struct dst_entry *dst;
- int addr_type;
-+ int reroute = 0;
- int err;
-
- if (addr_len < SIN6_LEN_RFC2133)
-@@ -660,7 +662,7 @@ static int tcp_v6_connect(struct sock *s
-
- fl.proto = IPPROTO_TCP;
- fl.fl6_dst = &np->daddr;
-- fl.fl6_src = saddr;
-+ fl.fl6_src = saddr;
- fl.oif = sk->bound_dev_if;
- fl.uli_u.ports.dport = usin->sin6_port;
- fl.uli_u.ports.sport = sk->sport;
-@@ -669,31 +671,46 @@ static int tcp_v6_connect(struct sock *s
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- fl.nl_u.ip6_u.daddr = rt0->addr;
- }
--
- dst = ip6_route_output(sk, &fl);
--
-+#ifdef CONFIG_IPV6_SUBTREES
-+ reroute = (saddr == NULL);
-+#endif
- if ((err = dst->error) != 0) {
- dst_release(dst);
- goto failure;
- }
--
-- ip6_dst_store(sk, dst, NULL);
-- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
--
-+ if (!reroute) {
-+ ip6_dst_store(sk, dst, NULL, NULL);
-+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-+ }
- if (saddr == NULL) {
- err = ipv6_get_saddr(dst, &np->daddr, &saddr_buf);
-+
-+ if (reroute)
-+ dst_release(dst);
- if (err)
- goto failure;
-
- saddr = &saddr_buf;
-+ ipv6_addr_copy(&np->rcv_saddr, saddr);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ fl.fl6_src = saddr;
-+ dst = ip6_route_output(sk, &fl);
-+
-+ if ((err = dst->error) != 0) {
-+ dst_release(dst);
-+ goto failure;
-+ }
-+ ip6_dst_store(sk, dst, NULL, NULL);
-+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-+#endif
- }
-
- /* set the source address */
-- ipv6_addr_copy(&np->rcv_saddr, saddr);
- ipv6_addr_copy(&np->saddr, saddr);
- sk->rcv_saddr= LOOPBACK4_IPV6;
-
-- tp->ext_header_len = 0;
-+ tp->ext_header_len = tcp_v6_get_mipv6_header_len();
- if (np->opt)
- tp->ext_header_len = np->opt->opt_flen+np->opt->opt_nflen;
- tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
-@@ -1338,7 +1355,7 @@ static struct sock * tcp_v6_syn_recv_soc
- #endif
- MOD_INC_USE_COUNT;
-
-- ip6_dst_store(newsk, dst, NULL);
-+ ip6_dst_store(newsk, dst, NULL, NULL);
- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-
- newtp = &(newsk->tp_pinfo.af_tcp);
-@@ -1383,7 +1400,7 @@ static struct sock * tcp_v6_syn_recv_soc
- sock_kfree_s(sk, opt, opt->tot_len);
- }
-
-- newtp->ext_header_len = 0;
-+ newtp->ext_header_len = tcp_v6_get_mipv6_header_len();
- if (np->opt)
- newtp->ext_header_len = np->opt->opt_nflen + np->opt->opt_flen;
-
-@@ -1710,7 +1727,7 @@ static int tcp_v6_rebuild_header(struct
- return err;
- }
-
-- ip6_dst_store(sk, dst, NULL);
-+ ip6_dst_store(sk, dst, NULL, NULL);
- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
- }
-
-@@ -1749,7 +1766,7 @@ static int tcp_v6_xmit(struct sk_buff *s
- return -sk->err_soft;
- }
-
-- ip6_dst_store(sk, dst, NULL);
-+ ip6_dst_store(sk, dst, NULL, NULL);
- }
-
- skb->dst = dst_clone(dst);
-diff -uprN linux-2.4.25.old/net/ipv6/udp.c linux-2.4.25/net/ipv6/udp.c
---- linux-2.4.25.old/net/ipv6/udp.c 2004-02-18 13:36:32.000000000 +0000
-+++ linux-2.4.25/net/ipv6/udp.c 2004-06-26 11:29:32.000000000 +0100
-@@ -48,6 +48,7 @@
- #include <net/ip.h>
- #include <net/udp.h>
- #include <net/inet_common.h>
-+#include <net/mipglue.h>
-
- #include <net/checksum.h>
-
-@@ -232,6 +233,7 @@ int udpv6_connect(struct sock *sk, struc
- struct ip6_flowlabel *flowlabel = NULL;
- int addr_type;
- int err;
-+ int reroute = 0;
-
- if (usin->sin6_family == AF_INET) {
- if (__ipv6_only_sock(sk))
-@@ -331,7 +333,7 @@ ipv4_connected:
-
- fl.proto = IPPROTO_UDP;
- fl.fl6_dst = &np->daddr;
-- fl.fl6_src = &saddr;
-+ fl.fl6_src = NULL;
- fl.oif = sk->bound_dev_if;
- fl.uli_u.ports.dport = sk->dport;
- fl.uli_u.ports.sport = sk->sport;
-@@ -348,29 +350,44 @@ ipv4_connected:
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- fl.fl6_dst = rt0->addr;
- }
--
- dst = ip6_route_output(sk, &fl);
--
- if ((err = dst->error) != 0) {
- dst_release(dst);
- fl6_sock_release(flowlabel);
-- return err;
-- }
--
-- ip6_dst_store(sk, dst, fl.fl6_dst);
--
-+ return err;
-+ }
-+#ifdef CONFIG_IPV6_SUBTREES
-+ reroute = (fl.fl6_src == NULL);
-+#endif
- /* get the source adddress used in the apropriate device */
-
- err = ipv6_get_saddr(dst, daddr, &saddr);
-
-+ if (reroute)
-+ dst_release(dst);
-+
- if (err == 0) {
-- if(ipv6_addr_any(&np->saddr))
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (reroute) {
-+ fl.fl6_src = &saddr;
-+ dst = ip6_route_output(sk, &fl);
-+ if ((err = dst->error) != 0) {
-+ dst_release(dst);
-+ fl6_sock_release(flowlabel);
-+ return err;
-+ }
-+ }
-+#endif
-+ if(ipv6_addr_any(&np->saddr)) {
- ipv6_addr_copy(&np->saddr, &saddr);
--
-+ fl.fl6_src = &np->saddr;
-+ }
- if(ipv6_addr_any(&np->rcv_saddr)) {
- ipv6_addr_copy(&np->rcv_saddr, &saddr);
- sk->rcv_saddr = LOOPBACK4_IPV6;
- }
-+ ip6_dst_store(sk, dst, fl.fl6_dst,
-+ fl.fl6_src == &np->saddr ? fl.fl6_src : NULL);
- sk->state = TCP_ESTABLISHED;
- }
- fl6_sock_release(flowlabel);
-@@ -894,6 +911,7 @@ static int udpv6_sendmsg(struct sock *sk
- opt = fl6_merge_options(&opt_space, flowlabel, opt);
- if (opt && opt->srcrt)
- udh.daddr = daddr;
-+ udh.daddr = mipv6_get_fake_hdr_daddr(udh.daddr, daddr);
-
- udh.uh.source = sk->sport;
- udh.uh.len = len < 0x10000 ? htons(len) : 0;
-diff -uprN linux-2.4.25.old/net/netsyms.c linux-2.4.25/net/netsyms.c
---- linux-2.4.25.old/net/netsyms.c 2003-11-28 18:26:21.000000000 +0000
-+++ linux-2.4.25/net/netsyms.c 2004-06-26 11:29:32.000000000 +0100
-@@ -190,6 +190,7 @@ EXPORT_SYMBOL(neigh_sysctl_register);
- #endif
- EXPORT_SYMBOL(pneigh_lookup);
- EXPORT_SYMBOL(pneigh_enqueue);
-+EXPORT_SYMBOL(pneigh_delete);
- EXPORT_SYMBOL(neigh_destroy);
- EXPORT_SYMBOL(neigh_parms_alloc);
- EXPORT_SYMBOL(neigh_parms_release);
diff --git a/recipes/linux/files/mipv6-1.1-v2.4.27.patch b/recipes/linux/files/mipv6-1.1-v2.4.27.patch
deleted file mode 100644
index b8fb071d28..0000000000
--- a/recipes/linux/files/mipv6-1.1-v2.4.27.patch
+++ /dev/null
@@ -1,19736 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/Documentation/Configure.help~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/Documentation/Configure.help
-@@ -6308,6 +6308,57 @@
-
- It is safe to say N here for now.
-
-+IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL)
-+CONFIG_IPV6_TUNNEL
-+ Experimental IP6-IP6 tunneling. You must select this, if you want
-+ to use CONFIG_IPV6_MOBILITY. More information in MIPL Mobile IPv6
-+ instructions.
-+
-+ If you don't want IP6-IP6 tunnels and Mobile IPv6, say N.
-+
-+IPv6: Mobility Support (EXPERIMENTAL)
-+CONFIG_IPV6_MOBILITY
-+ This is experimental support for the upcoming specification of
-+ Mobile IPv6. Mobile IPv6 allows nodes to seamlessly move between
-+ networks without changing their IP addresses, thus allowing them to
-+ maintain upper layer connections (e.g. TCP). Selecting this option
-+ allows your computer to act as a Correspondent Node (CN). A MIPv6
-+ Mobile Node will be able to communicate with the CN and use route
-+ optimization.
-+
-+ For more information and configuration details, see
-+ http://www.mipl.mediapoli.com/.
-+
-+ If unsure, say N.
-+
-+MIPv6: Mobile Node Support
-+CONFIG_IPV6_MOBILITY_MN
-+ If you want your computer to be a MIPv6 Mobile Node (MN), select
-+ this option. You must configure MN using the userspace tools
-+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/.
-+
-+ If your computer is stationary, or you are unsure if you need this,
-+ say N. Note that you will need a properly configured MIPv6 Home
-+ Agent to use any Mobile Nodes.
-+
-+MIPv6: Home Agent Support
-+CONFIG_IPV6_MOBILITY_HA
-+ If you want your router to serve as a MIPv6 Home Agent (HA), select
-+ this option. You must configure HA using the userspace tools
-+ available at http://www.mipl.mediapoli.com/download/mipv6-tools/.
-+
-+ If your computer is not a router, or you are unsure if you need
-+ this, say N.
-+
-+MIPv6: Debug messages
-+CONFIG_IPV6_MOBILITY_DEBUG
-+ MIPL Mobile IPv6 can produce a lot of debugging messages. There are
-+ eight debug levels (0 through 7) and the level is controlled via
-+ /proc/sys/net/ipv6/mobility/debuglevel. Since MIPL is still
-+ experimental, you might want to say Y here.
-+
-+ Be sure to say Y and record debug messages when submitting a bug
-+ report.
- The SCTP Protocol (EXPERIMENTAL)
- CONFIG_IP_SCTP
- Stream Control Transmission Protocol
---- linux-2.4.27/Documentation/DocBook/Makefile~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/Documentation/DocBook/Makefile
-@@ -2,7 +2,7 @@
- kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
- kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
- deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
-- journal-api.sgml libata.sgml
-+ journal-api.sgml libata.sgml mip6-func.sgml
-
- PS := $(patsubst %.sgml, %.ps, $(BOOKS))
- PDF := $(patsubst %.sgml, %.pdf, $(BOOKS))
-@@ -96,6 +96,9 @@
- procfs-guide.sgml: procfs-guide.tmpl procfs_example.sgml
- $(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@
-
-+mip6-func.sgml: mip6-func.tmpl
-+ $(TOPDIR)/scripts/docgen <$< >$@
-+
- APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
- $(TOPDIR)/arch/i386/kernel/irq.c \
- $(TOPDIR)/arch/i386/kernel/mca.c \
---- /dev/null
-+++ linux-2.4.27/Documentation/DocBook/mip6-func.tmpl
-@@ -0,0 +1,756 @@
-+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
-+<book id="LinuxMobileIPv6">
-+ <bookinfo>
-+ <title>MIPL Mobile IPv6 Function Reference Guide</title>
-+
-+ <authorgroup>
-+ <author>
-+ <othername>MIPL Mobile IPv6 for Linux Team</othername>
-+ <affiliation>
-+ <orgname>Helsinki University of Technology</orgname>
-+ <orgdiv>Telecommunications Software and Multimedia Lab</orgdiv>
-+ <address>
-+ <pob>PO BOX 9201</pob>
-+ <postcode>FIN-02015 HUT</postcode>
-+ <country>Finland</country>
-+ <email>mipl@list.mipl.mediapoli.com</email>
-+ </address>
-+ </affiliation>
-+ </author>
-+ </authorgroup>
-+
-+ <copyright>
-+ <year>2000-2001</year>
-+ <holder>Helsinki University of Technology</holder>
-+ </copyright>
-+
-+ <legalnotice>
-+ <para>
-+ Copyright (c) 2001, 2002 MIPL Mobile IPv6 for Linux Team.
-+ </para>
-+ <para>
-+ Permission is granted to copy, distribute and/or modify this
-+ document under the terms of the GNU Free Documentation License,
-+ Version 1.1 published by the Free Software Foundation; with the
-+ Invariant Sections being "Introduction", with the Front-Cover
-+ Texts being "MIPL Mobile IPv6 Function Reference Guide", "MIPL
-+ Mobile IPv6 for Linux Team" and "Helsinki University of
-+ Technology". A copy of the license is included in <xref
-+ linkend="gfdl">.
-+ </para>
-+
-+ </legalnotice>
-+ </bookinfo>
-+
-+<toc></toc>
-+
-+ <preface id="intro">
-+ <title>Introduction</title>
-+
-+ <para>
-+ MIPL Mobile IPv6 for Linux is an implementation of Mobility
-+ Support in IPv6 IETF mobile-ip working groups Internet-Draft
-+ (draft-ietf-mobileip-ipv6). This implementation has been
-+ developed in the Telecommunications Software and Multimedia
-+ Laboratory at Helsinki University of Technology.
-+ </para>
-+
-+ <para>
-+ MIPL is fully open source, licensed under the GNU General
-+ Public License. Latest source for MIPL can be downloaded from
-+ the MIPL website at:
-+ </para>
-+ <programlisting>
-+ http://www.mipl.mediapoli.com/.
-+ </programlisting>
-+ <para>
-+ Developers and users interested in MIPL can subscribe to the
-+ MIPL mailing list by sending e-mail to
-+ <email>majordomo@list.mipl.mediapoli.com</email> with
-+ </para>
-+ <programlisting>
-+ subscribe mipl
-+ </programlisting>
-+ <para>
-+ in the body of the message.
-+ </para>
-+
-+ <para>
-+ This document is a reference guide to MIPL functions. Intended
-+ audience is developers wishing to contribute to the project.
-+ Hopefully this document will make it easier and quicker to
-+ understand and adopt the inner workings of MIPL Mobile IPv6.
-+ </para>
-+
-+ <para>
-+ MIPL Mobile IPv6 for Linux Team members (past and present):
-+
-+ <itemizedlist>
-+ <listitem>
-+ <address>
-+ Sami Kivisaari <email>Sami.Kivisaari@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Niklas Kampe <email>Niklas.Kampe@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Juha Mynttinen <email>Juha.Mynttinen@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Toni Nykanen <email>Toni.Nykanen@iki.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Henrik Petander <email>Henrik.Petander@hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Antti Tuominen <email>ajtuomin@tml.hut.fi</email>
-+ </address>
-+ </listitem>
-+ </itemizedlist>
-+
-+ <itemizedlist>
-+ <listitem>
-+ <address>
-+ Marko Myllynen
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Ville Nuorvala <email>vnuorval@tcs.hut.fi</email>
-+ </address>
-+ </listitem>
-+ <listitem>
-+ <address>
-+ Jaakko Laine <email>Jaakko.Laine@hut.fi</email>
-+ </address>
-+ </listitem>
-+ </itemizedlist>
-+ </para>
-+
-+ </preface>
-+
-+ <chapter id="common">
-+ <title>Common functions for all entities</title>
-+
-+ <sect1><title>Low-level functions</title>
-+ <para>
-+ These functions implement memory allocation used by others.
-+ Hashlist functions implement a linked list with hash lookup,
-+ which is used with Binding Update List, Binding Cache, Home
-+ Agents List etc.
-+ </para>
-+!Inet/ipv6/mobile_ip6/mempool.h
-+!Inet/ipv6/mobile_ip6/hashlist.h
-+ </sect1>
-+
-+ <sect1><title>Debug functions</title>
-+ <para>
-+ Debug and utility functions. These functions are available if
-+ <constant>CONFIG_IPV6_MOBILITY_DEBUG</constant> is set.
-+ Otherwise macros expand to no operation.
-+ </para>
-+!Inet/ipv6/mobile_ip6/debug.h
-+!Inet/ipv6/mobile_ip6/mipv6.c
-+ </sect1>
-+
-+ <sect1><title>Extension Header functions</title>
-+ <para>
-+ These functions create and handle extension headers that are
-+ specific to MIPv6.
-+ </para>
-+!Inet/ipv6/mobile_ip6/exthdrs.c
-+ </sect1>
-+
-+ <sect1><title>Mobility Header functions</title>
-+ <para>
-+ MIPv6 specifies a new protocol called Mobility Header.
-+ Mobility Header has several message types. Messages may also
-+ carry Mobility Options. These functions are used to create and
-+ handle Mobility Headers and Mobility Options.
-+ </para>
-+!Inet/ipv6/mobile_ip6/sendopts.c
-+!Inet/ipv6/mobile_ip6/mh_recv.c
-+!Inet/ipv6/mobile_ip6/auth_subopt.c
-+ </sect1>
-+
-+ <sect1><title>Binding Cache</title>
-+ <para>
-+ All Mobile IPv6 entities have a binding cache. These functions
-+ provide easy manipulation of the binding cache.
-+ </para>
-+!Inet/ipv6/mobile_ip6/bcache.c
-+ </sect1>
-+
-+ <sect1><title>Security</title>
-+
-+ <para>
-+ These functions are common authentication functions and
-+ implement Draft 13 style IPSec AH support for Binding Updates.
-+ </para>
-+!Inet/ipv6/mobile_ip6/ah_algo.c
-+!Inet/ipv6/mobile_ip6/sadb.c
-+!Inet/ipv6/mobile_ip6/ah.c
-+ </sect1>
-+
-+ <sect1><title>Utility functions</title>
-+
-+ <para>
-+ These functions are general utility functions commonly used by
-+ all entities.
-+ </para>
-+!Inet/ipv6/mobile_ip6/util.c
-+ </sect1>
-+
-+ </chapter>
-+
-+ <chapter id="mn">
-+ <title>Mobile Node functions</title>
-+ <sect1><title>General functions</title>
-+ <para>
-+ </para>
-+!Inet/ipv6/mobile_ip6/mn.c
-+ </sect1>
-+
-+ <sect1><title>Binding Update List</title>
-+ <para>
-+ Mobile Node keeps track of sent binding updates in Binding
-+ Update List.
-+ </para>
-+!Inet/ipv6/mobile_ip6/bul.c
-+ </sect1>
-+
-+ <sect1><title>Movement detection</title>
-+
-+ <para>
-+ These functions are used by the mobile node for movement
-+ detection.
-+ </para>
-+!Inet/ipv6/mobile_ip6/mdetect.c
-+ </sect1>
-+ </chapter>
-+
-+ <chapter id="ha">
-+ <title>Home Agent functions</title>
-+ <sect1><title>General functions</title>
-+ <para>
-+ </para>
-+!Inet/ipv6/mobile_ip6/ha.c
-+ </sect1>
-+
-+ <sect1><title>Duplicate Address Detection functions</title>
-+ <para>
-+ Home Agent does Duplicate Address Detection for Mobile Nodes'
-+ addresses. These functions implement MIPv6 specific DAD
-+ functionality.
-+ </para>
-+!Inet/ipv6/mobile_ip6/dad.c
-+ </sect1>
-+
-+ </chapter>
-+ <appendix id="gfdl">
-+ <title>GNU Free Documentation License</title>
-+
-+ <para>
-+ Version 1.1, March 2000
-+ </para>
-+
-+ <programlisting>
-+ Copyright (C) 2000 Free Software Foundation, Inc.
-+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+ </programlisting>
-+
-+ <sect1><title>0. PREAMBLE</title>
-+
-+ <para>
-+ The purpose of this License is to make a manual, textbook, or
-+ other written document "free" in the sense of freedom: to
-+ assure everyone the effective freedom to copy and redistribute
-+ it, with or without modifying it, either commercially or
-+ noncommercially. Secondarily, this License preserves for the
-+ author and publisher a way to get credit for their work, while
-+ not being considered responsible for modifications made by
-+ others.
-+ </para>
-+
-+ <para>
-+ This License is a kind of "copyleft", which means that
-+ derivative works of the document must themselves be free in the
-+ same sense. It complements the GNU General Public License,
-+ which is a copyleft license designed for free software.
-+ </para>
-+
-+ <para>
-+ We have designed this License in order to use it for manuals
-+ for free software, because free software needs free
-+ documentation: a free program should come with manuals
-+ providing the same freedoms that the software does. But this
-+ License is not limited to software manuals; it can be used for
-+ any textual work, regardless of subject matter or whether it is
-+ published as a printed book. We recommend this License
-+ principally for works whose purpose is instruction or
-+ reference.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>1. APPLICABILITY AND DEFINITIONS</title>
-+
-+ <para>
-+ This License applies to any manual or other work that contains
-+ a notice placed by the copyright holder saying it can be
-+ distributed under the terms of this License. The "Document",
-+ below, refers to any such manual or work. Any member of the
-+ public is a licensee, and is addressed as "you".
-+ </para>
-+
-+ <para>
-+ A "Modified Version" of the Document means any work containing
-+ the Document or a portion of it, either copied verbatim, or
-+ with modifications and/or translated into another language.
-+ </para>
-+
-+ <para>
-+ A "Secondary Section" is a named appendix or a front-matter
-+ section of the Document that deals exclusively with the
-+ relationship of the publishers or authors of the Document to
-+ the Document's overall subject (or to related matters) and
-+ contains nothing that could fall directly within that overall
-+ subject. (For example, if the Document is in part a textbook of
-+ mathematics, a Secondary Section may not explain any
-+ mathematics.) The relationship could be a matter of historical
-+ connection with the subject or with related matters, or of
-+ legal, commercial, philosophical, ethical or political position
-+ regarding them.
-+ </para>
-+
-+ <para>
-+ The "Invariant Sections" are certain Secondary Sections whose
-+ titles are designated, as being those of Invariant Sections, in
-+ the notice that says that the Document is released under this
-+ License.
-+ </para>
-+
-+ <para>
-+ The "Cover Texts" are certain short passages of text that are
-+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
-+ that says that the Document is released under this License.
-+ </para>
-+
-+ <para>
-+ A "Transparent" copy of the Document means a machine-readable
-+ copy, represented in a format whose specification is available
-+ to the general public, whose contents can be viewed and edited
-+ directly and straightforwardly with generic text editors or
-+ (for images composed of pixels) generic paint programs or (for
-+ drawings) some widely available drawing editor, and that is
-+ suitable for input to text formatters or for automatic
-+ translation to a variety of formats suitable for input to text
-+ formatters. A copy made in an otherwise Transparent file format
-+ whose markup has been designed to thwart or discourage
-+ subsequent modification by readers is not Transparent. A copy
-+ that is not "Transparent" is called "Opaque".
-+ </para>
-+
-+ <para>
-+ Examples of suitable formats for Transparent copies include
-+ plain ASCII without markup, Texinfo input format, LaTeX input
-+ format, SGML or XML using a publicly available DTD, and
-+ standard-conforming simple HTML designed for human
-+ modification. Opaque formats include PostScript, PDF,
-+ proprietary formats that can be read and edited only by
-+ proprietary word processors, SGML or XML for which the DTD
-+ and/or processing tools are not generally available, and the
-+ machine-generated HTML produced by some word processors for
-+ output purposes only.
-+ </para>
-+
-+ <para>
-+ The "Title Page" means, for a printed book, the title page
-+ itself, plus such following pages as are needed to hold,
-+ legibly, the material this License requires to appear in the
-+ title page. For works in formats which do not have any title
-+ page as such, "Title Page" means the text near the most
-+ prominent appearance of the work's title, preceding the
-+ beginning of the body of the text.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>2. VERBATIM COPYING</title>
-+
-+ <para>
-+ You may copy and distribute the Document in any medium, either
-+ commercially or noncommercially, provided that this License,
-+ the copyright notices, and the license notice saying this
-+ License applies to the Document are reproduced in all copies,
-+ and that you add no other conditions whatsoever to those of
-+ this License. You may not use technical measures to obstruct or
-+ control the reading or further copying of the copies you make
-+ or distribute. However, you may accept compensation in exchange
-+ for copies. If you distribute a large enough number of copies
-+ you must also follow the conditions in section 3.
-+ </para>
-+
-+ <para>
-+ You may also lend copies, under the same conditions stated
-+ above, and you may publicly display copies.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>3. COPYING IN QUANTITY</title>
-+
-+ <para>
-+ If you publish printed copies of the Document numbering more
-+ than 100, and the Document's license notice requires Cover
-+ Texts, you must enclose the copies in covers that carry,
-+ clearly and legibly, all these Cover Texts: Front-Cover Texts
-+ on the front cover, and Back-Cover Texts on the back
-+ cover. Both covers must also clearly and legibly identify you
-+ as the publisher of these copies. The front cover must present
-+ the full title with all words of the title equally prominent
-+ and visible. You may add other material on the covers in
-+ addition. Copying with changes limited to the covers, as long
-+ as they preserve the title of the Document and satisfy these
-+ conditions, can be treated as verbatim copying in other
-+ respects.
-+ </para>
-+
-+ <para>
-+ If the required texts for either cover are too voluminous to
-+ fit legibly, you should put the first ones listed (as many as
-+ fit reasonably) on the actual cover, and continue the rest onto
-+ adjacent pages.
-+ </para>
-+
-+ <para>
-+ If you publish or distribute Opaque copies of the Document
-+ numbering more than 100, you must either include a
-+ machine-readable Transparent copy along with each Opaque copy,
-+ or state in or with each Opaque copy a publicly-accessible
-+ computer-network location containing a complete Transparent
-+ copy of the Document, free of added material, which the general
-+ network-using public has access to download anonymously at no
-+ charge using public-standard network protocols. If you use the
-+ latter option, you must take reasonably prudent steps, when you
-+ begin distribution of Opaque copies in quantity, to ensure that
-+ this Transparent copy will remain thus accessible at the stated
-+ location until at least one year after the last time you
-+ distribute an Opaque copy (directly or through your agents or
-+ retailers) of that edition to the public.
-+ </para>
-+
-+ <para>
-+ It is requested, but not required, that you contact the authors
-+ of the Document well before redistributing any large number of
-+ copies, to give them a chance to provide you with an updated
-+ version of the Document.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>4. MODIFICATIONS</title>
-+
-+ <para>
-+ You may copy and distribute a Modified Version of the Document
-+ under the conditions of sections 2 and 3 above, provided that
-+ you release the Modified Version under precisely this License,
-+ with the Modified Version filling the role of the Document,
-+ thus licensing distribution and modification of the Modified
-+ Version to whoever possesses a copy of it. In addition, you
-+ must do these things in the Modified Version:
-+ </para>
-+
-+ <para>
-+ <itemizedlist spacing=compact>
-+ <listitem>
-+ <para>
-+ A. Use in the Title Page (and on the covers, if any) a title
-+ distinct from that of the Document, and from those of previous
-+ versions (which should, if there were any, be listed in the
-+ History section of the Document). You may use the same title
-+ as a previous version if the original publisher of that
-+ version gives permission.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ B. List on the Title Page, as authors, one or more persons
-+ or entities responsible for authorship of the modifications in
-+ the Modified Version, together with at least five of the
-+ principal authors of the Document (all of its principal
-+ authors, if it has less than five).
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ C. State on the Title page the name of the publisher of the
-+ Modified Version, as the publisher.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ D. Preserve all the copyright notices of the Document.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ E. Add an appropriate copyright notice for your
-+ modifications adjacent to the other copyright notices.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ F. Include, immediately after the copyright notices, a
-+ license notice giving the public permission to use the
-+ Modified Version under the terms of this License, in the form
-+ shown in the Addendum below.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ G. Preserve in that license notice the full lists of
-+ Invariant Sections and required Cover Texts given in the
-+ Document's license notice.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ H. Include an unaltered copy of this License.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ I. Preserve the section entitled "History", and its title,
-+ and add to it an item stating at least the title, year, new
-+ authors, and publisher of the Modified Version as given on the
-+ Title Page. If there is no section entitled "History" in the
-+ Document, create one stating the title, year, authors, and
-+ publisher of the Document as given on its Title Page, then add
-+ an item describing the Modified Version as stated in the
-+ previous sentence.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ J. Preserve the network location, if any, given in the
-+ Document for public access to a Transparent copy of the
-+ Document, and likewise the network locations given in the
-+ Document for previous versions it was based on. These may be
-+ placed in the "History" section. You may omit a network
-+ location for a work that was published at least four years
-+ before the Document itself, or if the original publisher of
-+ the version it refers to gives permission.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ K. In any section entitled "Acknowledgements" or
-+ "Dedications", preserve the section's title, and preserve in
-+ the section all the substance and tone of each of the
-+ contributor acknowledgements and/or dedications given therein.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ L. Preserve all the Invariant Sections of the Document,
-+ unaltered in their text and in their titles. Section numbers
-+ or the equivalent are not considered part of the section
-+ titles.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ M. Delete any section entitled "Endorsements". Such a
-+ section may not be included in the Modified Version.
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
-+ N. Do not retitle any existing section as "Endorsements" or
-+ to conflict in title with any Invariant Section.
-+ </para>
-+ </listitem>
-+ </itemizedlist>
-+ </para>
-+
-+ <para>
-+ If the Modified Version includes new front-matter sections or
-+ appendices that qualify as Secondary Sections and contain no
-+ material copied from the Document, you may at your option
-+ designate some or all of these sections as invariant. To do
-+ this, add their titles to the list of Invariant Sections in the
-+ Modified Version's license notice. These titles must be
-+ distinct from any other section titles.
-+ </para>
-+
-+ <para>
-+ You may add a section entitled "Endorsements", provided it
-+ contains nothing but endorsements of your Modified Version by
-+ various parties--for example, statements of peer review or that
-+ the text has been approved by an organization as the
-+ authoritative definition of a standard.
-+ </para>
-+
-+ <para>
-+ You may add a passage of up to five words as a Front-Cover
-+ Text, and a passage of up to 25 words as a Back-Cover Text, to
-+ the end of the list of Cover Texts in the Modified
-+ Version. Only one passage of Front-Cover Text and one of
-+ Back-Cover Text may be added by (or through arrangements made
-+ by) any one entity. If the Document already includes a cover
-+ text for the same cover, previously added by you or by
-+ arrangement made by the same entity you are acting on behalf
-+ of, you may not add another; but you may replace the old one,
-+ on explicit permission from the previous publisher that added
-+ the old one.
-+ </para>
-+
-+ <para>
-+ The author(s) and publisher(s) of the Document do not by this
-+ License give permission to use their names for publicity for or
-+ to assert or imply endorsement of any Modified Version.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>5. COMBINING DOCUMENTS</title>
-+
-+ <para>
-+ You may combine the Document with other documents released
-+ under this License, under the terms defined in section 4 above
-+ for modified versions, provided that you include in the
-+ combination all of the Invariant Sections of all of the
-+ original documents, unmodified, and list them all as Invariant
-+ Sections of your combined work in its license notice.
-+ </para>
-+
-+ <para>
-+ The combined work need only contain one copy of this License,
-+ and multiple identical Invariant Sections may be replaced with
-+ a single copy. If there are multiple Invariant Sections with
-+ the same name but different contents, make the title of each
-+ such section unique by adding at the end of it, in parentheses,
-+ the name of the original author or publisher of that section if
-+ known, or else a unique number. Make the same adjustment to the
-+ section titles in the list of Invariant Sections in the license
-+ notice of the combined work.
-+ </para>
-+
-+ <para>
-+ In the combination, you must combine any sections entitled
-+ "History" in the various original documents, forming one
-+ section entitled "History"; likewise combine any sections
-+ entitled "Acknowledgements", and any sections entitled
-+ "Dedications". You must delete all sections entitled
-+ "Endorsements."
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>6. COLLECTIONS OF DOCUMENTS</title>
-+
-+ <para>
-+ You may make a collection consisting of the Document and other
-+ documents released under this License, and replace the
-+ individual copies of this License in the various documents with
-+ a single copy that is included in the collection, provided that
-+ you follow the rules of this License for verbatim copying of
-+ each of the documents in all other respects.
-+ </para>
-+
-+ <para>
-+ You may extract a single document from such a collection, and
-+ distribute it individually under this License, provided you
-+ insert a copy of this License into the extracted document, and
-+ follow this License in all other respects regarding verbatim
-+ copying of that document.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>7. AGGREGATION WITH INDEPENDENT WORKS</title>
-+
-+ <para>
-+ A compilation of the Document or its derivatives with other
-+ separate and independent documents or works, in or on a volume
-+ of a storage or distribution medium, does not as a whole count
-+ as a Modified Version of the Document, provided no compilation
-+ copyright is claimed for the compilation. Such a compilation is
-+ called an "aggregate", and this License does not apply to the
-+ other self-contained works thus compiled with the Document, on
-+ account of their being thus compiled, if they are not
-+ themselves derivative works of the Document.
-+ </para>
-+
-+ <para>
-+ If the Cover Text requirement of section 3 is applicable to
-+ these copies of the Document, then if the Document is less than
-+ one quarter of the entire aggregate, the Document's Cover Texts
-+ may be placed on covers that surround only the Document within
-+ the aggregate. Otherwise they must appear on covers around the
-+ whole aggregate.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>8. TRANSLATION</title>
-+
-+ <para>
-+ Translation is considered a kind of modification, so you may
-+ distribute translations of the Document under the terms of
-+ section 4. Replacing Invariant Sections with translations
-+ requires special permission from their copyright holders, but
-+ you may include translations of some or all Invariant Sections
-+ in addition to the original versions of these Invariant
-+ Sections. You may include a translation of this License
-+ provided that you also include the original English version of
-+ this License. In case of a disagreement between the translation
-+ and the original English version of this License, the original
-+ English version will prevail.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>9. TERMINATION</title>
-+
-+ <para>
-+ You may not copy, modify, sublicense, or distribute the
-+ Document except as expressly provided for under this
-+ License. Any other attempt to copy, modify, sublicense or
-+ distribute the Document is void, and will automatically
-+ terminate your rights under this License. However, parties who
-+ have received copies, or rights, from you under this License
-+ will not have their licenses terminated so long as such parties
-+ remain in full compliance.
-+ </para>
-+
-+ </sect1>
-+ <sect1><title>10. FUTURE REVISIONS OF THIS LICENSE</title>
-+
-+ <para>
-+ The Free Software Foundation may publish new, revised versions
-+ of the GNU Free Documentation License from time to time. Such
-+ new versions will be similar in spirit to the present version,
-+ but may differ in detail to address new problems or
-+ concerns. See http://www.gnu.org/copyleft/.
-+ </para>
-+
-+ <para>
-+ Each version of the License is given a distinguishing version
-+ number. If the Document specifies that a particular numbered
-+ version of this License "or any later version" applies to it,
-+ you have the option of following the terms and conditions
-+ either of that specified version or of any later version that
-+ has been published (not as a draft) by the Free Software
-+ Foundation. If the Document does not specify a version number
-+ of this License, you may choose any version ever published (not
-+ as a draft) by the Free Software Foundation.
-+ </para>
-+
-+ </sect1>
-+ </appendix>
-+</book>
---- linux-2.4.27/include/linux/icmpv6.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/icmpv6.h
-@@ -40,14 +40,16 @@
- struct icmpv6_nd_ra {
- __u8 hop_limit;
- #if defined(__LITTLE_ENDIAN_BITFIELD)
-- __u8 reserved:6,
-+ __u8 reserved:5,
-+ home_agent:1,
- other:1,
- managed:1;
-
- #elif defined(__BIG_ENDIAN_BITFIELD)
- __u8 managed:1,
- other:1,
-- reserved:6;
-+ home_agent:1,
-+ reserved:5;
- #else
- #error "Please fix <asm/byteorder.h>"
- #endif
-@@ -70,6 +72,7 @@
- #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
- #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
- #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
-+#define icmp6_home_agent icmp6_dataun.u_nd_ra.home_agent
- };
-
-
---- linux-2.4.27/include/linux/if_arp.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/if_arp.h
-@@ -59,7 +59,7 @@
- #define ARPHRD_RAWHDLC 518 /* Raw HDLC */
-
- #define ARPHRD_TUNNEL 768 /* IPIP tunnel */
--#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */
-+#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
- #define ARPHRD_FRAD 770 /* Frame Relay Access Device */
- #define ARPHRD_SKIP 771 /* SKIP vif */
- #define ARPHRD_LOOPBACK 772 /* Loopback device */
---- linux-2.4.27/include/linux/in6.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/in6.h
-@@ -142,6 +142,11 @@
- #define IPV6_TLV_JUMBO 194
-
- /*
-+ * Mobile IPv6 TLV options.
-+ */
-+#define MIPV6_TLV_HOMEADDR 201
-+
-+/*
- * IPV6 socket options
- */
-
---- linux-2.4.27/include/linux/ipv6.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/ipv6.h
-@@ -29,6 +29,7 @@
-
- #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
- #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
-+#define IPV6_SRCRT_TYPE_2 2 /* type 2 for Mobile IPv6 */
-
- /*
- * routing header
-@@ -71,6 +72,19 @@
- struct in6_addr addr[0];
-
- #define rt0_type rt_hdr.type
-+
-+};
-+
-+/*
-+ * routing header type 2
-+ */
-+
-+struct rt2_hdr {
-+ struct ipv6_rt_hdr rt_hdr;
-+ __u32 reserved;
-+ struct in6_addr addr;
-+
-+#define rt2_type rt_hdr.type;
- };
-
- /*
-@@ -156,12 +170,16 @@
- struct inet6_skb_parm
- {
- int iif;
-+ __u8 mipv6_flags;
- __u16 ra;
- __u16 hop;
- __u16 auth;
- __u16 dst0;
- __u16 srcrt;
-+ __u16 srcrt2;
-+ __u16 hao;
- __u16 dst1;
-+ struct in6_addr hoa;
- };
-
- #endif
---- linux-2.4.27/include/linux/ipv6_route.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/ipv6_route.h
-@@ -33,6 +33,7 @@
- #define RTF_CACHE 0x01000000 /* cache entry */
- #define RTF_FLOW 0x02000000 /* flow significant route */
- #define RTF_POLICY 0x04000000 /* policy route */
-+#define RTF_MOBILENODE 0x10000000 /* for routing to Mobile Node */
-
- #define RTF_LOCAL 0x80000000
-
---- /dev/null
-+++ linux-2.4.27/include/linux/ipv6_tunnel.h
-@@ -0,0 +1,34 @@
-+/*
-+ * $Id$
-+ */
-+
-+#ifndef _IPV6_TUNNEL_H
-+#define _IPV6_TUNNEL_H
-+
-+#define IPV6_TLV_TNL_ENCAP_LIMIT 4
-+#define IPV6_DEFAULT_TNL_ENCAP_LIMIT 4
-+
-+/* don't add encapsulation limit if one isn't present in inner packet */
-+#define IP6_TNL_F_IGN_ENCAP_LIMIT 0x1
-+/* copy the traffic class field from the inner packet */
-+#define IP6_TNL_F_USE_ORIG_TCLASS 0x2
-+/* copy the flowlabel from the inner packet */
-+#define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4
-+/* created and maintained from within the kernel */
-+#define IP6_TNL_F_KERNEL_DEV 0x8
-+/* being used for Mobile IPv6 */
-+#define IP6_TNL_F_MIP6_DEV 0x10
-+
-+struct ip6_tnl_parm {
-+ char name[IFNAMSIZ]; /* name of tunnel device */
-+ int link; /* ifindex of underlying L2 interface */
-+ __u8 proto; /* tunnel protocol */
-+ __u8 encap_limit; /* encapsulation limit for tunnel */
-+ __u8 hop_limit; /* hop limit for tunnel */
-+ __u32 flowinfo; /* traffic class and flowlabel for tunnel */
-+ __u32 flags; /* tunnel flags */
-+ struct in6_addr laddr; /* local tunnel end-point address */
-+ struct in6_addr raddr; /* remote tunnel end-point address */
-+};
-+
-+#endif
---- linux-2.4.27/include/linux/rtnetlink.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/rtnetlink.h
-@@ -315,6 +315,7 @@
- IFA_BROADCAST,
- IFA_ANYCAST,
- IFA_CACHEINFO,
-+ IFA_HOMEAGENT,
- __IFA_MAX
- };
-
-@@ -324,6 +325,7 @@
-
- #define IFA_F_SECONDARY 0x01
-
-+#define IFA_F_HOMEADDR 0x10
- #define IFA_F_DEPRECATED 0x20
- #define IFA_F_TENTATIVE 0x40
- #define IFA_F_PERMANENT 0x80
---- linux-2.4.27/include/linux/skbuff.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/skbuff.h
-@@ -177,7 +177,7 @@
- * want to keep them across layers you have to do a skb_clone()
- * first. This is owned by whoever has the skb queued ATM.
- */
-- char cb[48];
-+ char cb[64];
-
- unsigned int len; /* Length of actual data */
- unsigned int data_len;
---- linux-2.4.27/include/linux/sysctl.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/linux/sysctl.h
-@@ -404,6 +404,23 @@
- NET_IPV6_ICMP=19,
- NET_IPV6_BINDV6ONLY=20,
- NET_IPV6_MLD_MAX_MSF=25,
-+ NET_IPV6_MOBILITY=26
-+};
-+
-+/* /proc/sys/net/ipv6/mobility */
-+enum {
-+ NET_IPV6_MOBILITY_DEBUG=1,
-+ NET_IPV6_MOBILITY_TUNNEL_SITELOCAL=2,
-+ NET_IPV6_MOBILITY_ROUTER_SOLICITATION_MAX_SENDTIME=3,
-+ NET_IPV6_MOBILITY_ROUTER_REACH=4,
-+ NET_IPV6_MOBILITY_MDETECT_MECHANISM=5,
-+ NET_IPV6_MOBILITY_RETROUT=6,
-+ NET_IPV6_MOBILITY_MAX_TNLS=7,
-+ NET_IPV6_MOBILITY_MIN_TNLS=8,
-+ NET_IPV6_MOBILITY_BINDING_REFRESH=9,
-+ NET_IPV6_MOBILITY_BU_F_LLADDR=10,
-+ NET_IPV6_MOBILITY_BU_F_KEYMGM=11,
-+ NET_IPV6_MOBILITY_BU_F_CN_ACK=12
- };
-
- enum {
---- linux-2.4.27/include/net/addrconf.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/net/addrconf.h
-@@ -16,9 +16,11 @@
- #if defined(__BIG_ENDIAN_BITFIELD)
- __u8 onlink : 1,
- autoconf : 1,
-- reserved : 6;
-+ router_address : 1,
-+ reserved : 5;
- #elif defined(__LITTLE_ENDIAN_BITFIELD)
-- __u8 reserved : 6,
-+ __u8 reserved : 5,
-+ router_address : 1,
- autoconf : 1,
- onlink : 1;
- #else
-@@ -55,6 +57,7 @@
- struct net_device *dev);
- extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
- struct net_device *dev);
-+extern void ipv6_del_addr(struct inet6_ifaddr *ifp);
- extern int ipv6_get_saddr(struct dst_entry *dst,
- struct in6_addr *daddr,
- struct in6_addr *saddr);
-@@ -85,7 +88,9 @@
- extern void ipv6_mc_down(struct inet6_dev *idev);
- extern void ipv6_mc_init_dev(struct inet6_dev *idev);
- extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
-+extern void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
- extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
-+extern void addrconf_dad_completed(struct inet6_ifaddr *ifp);
-
- extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
- struct in6_addr *src_addr);
-@@ -116,6 +121,9 @@
- extern int register_inet6addr_notifier(struct notifier_block *nb);
- extern int unregister_inet6addr_notifier(struct notifier_block *nb);
-
-+extern int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
-+extern int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev);
-+
- static inline struct inet6_dev *
- __in6_dev_get(struct net_device *dev)
- {
---- linux-2.4.27/include/net/ip6_route.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/net/ip6_route.h
-@@ -2,6 +2,7 @@
- #define _NET_IP6_ROUTE_H
-
- #define IP6_RT_PRIO_FW 16
-+#define IP6_RT_PRIO_MIPV6 64
- #define IP6_RT_PRIO_USER 1024
- #define IP6_RT_PRIO_ADDRCONF 256
- #define IP6_RT_PRIO_KERN 512
-@@ -40,6 +41,9 @@
-
- extern int ip6_route_add(struct in6_rtmsg *rtmsg,
- struct nlmsghdr *);
-+
-+extern int ip6_route_del(struct in6_rtmsg *rtmsg,
-+ struct nlmsghdr *);
- extern int ip6_del_rt(struct rt6_info *,
- struct nlmsghdr *);
-
-@@ -99,7 +103,8 @@
- */
-
- static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
-- struct in6_addr *daddr)
-+ struct in6_addr *daddr,
-+ struct in6_addr *saddr)
- {
- struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
- struct rt6_info *rt = (struct rt6_info *) dst;
-@@ -107,6 +112,9 @@
- write_lock(&sk->dst_lock);
- __sk_dst_set(sk, dst);
- np->daddr_cache = daddr;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ np->saddr_cache = saddr;
-+#endif
- np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
- write_unlock(&sk->dst_lock);
- }
---- linux-2.4.27/include/net/ipv6.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/net/ipv6.h
-@@ -37,6 +37,7 @@
- #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
- #define NEXTHDR_NONE 59 /* No next header */
- #define NEXTHDR_DEST 60 /* Destination options header. */
-+#define NEXTHDR_MH 135 /* Mobility header, RFC 3775 */
-
- #define NEXTHDR_MAX 255
-
-@@ -146,9 +147,12 @@
- __u16 opt_flen; /* after fragment hdr */
- __u16 opt_nflen; /* before fragment hdr */
-
-+ __u8 mipv6_flags; /* flags set by MIPv6 */
-+
- struct ipv6_opt_hdr *hopopt;
- struct ipv6_opt_hdr *dst0opt;
-- struct ipv6_rt_hdr *srcrt; /* Routing Header */
-+ struct ipv6_rt_hdr *srcrt; /* Routing Header Type 0 */
-+ struct ipv6_rt_hdr *srcrt2; /* Routing Header Type 2 */
- struct ipv6_opt_hdr *auth;
- struct ipv6_opt_hdr *dst1opt;
-
-@@ -257,6 +261,38 @@
- a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
- }
-
-+static inline void ipv6_addr_prefix(struct in6_addr *pfx,
-+ const struct in6_addr *addr, int plen)
-+{
-+ /* caller must guarantee 0 <= plen <= 128 */
-+ int o = plen >> 3,
-+ b = plen & 0x7;
-+
-+ memcpy(pfx->s6_addr, addr, o);
-+ if (b != 0) {
-+ pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
-+ o++;
-+ }
-+ if (o < 16)
-+ memset(pfx->s6_addr + o, 0, 16 - o);
-+}
-+
-+static inline int ipv6_prefix_cmp(const struct in6_addr *p1,
-+ const struct in6_addr *p2, int plen)
-+{
-+ int b = plen&0x7;
-+ int o = plen>>3;
-+ int res = 0;
-+
-+ if (o > 0)
-+ res = memcmp(&p1->s6_addr[0], &p2->s6_addr[0], o);
-+ if (res == 0 && b > 0) {
-+ __u8 m = (0xff00 >> b) & 0xff;
-+ res = (p1->s6_addr[o] & m) - (p2->s6_addr[o] & m);
-+ }
-+ return res;
-+}
-+
- /*
- * Prototypes exported by ipv6
- */
---- /dev/null
-+++ linux-2.4.27/include/net/ipv6_tunnel.h
-@@ -0,0 +1,92 @@
-+/*
-+ * $Id$
-+ */
-+
-+#ifndef _NET_IPV6_TUNNEL_H
-+#define _NET_IPV6_TUNNEL_H
-+
-+#include <linux/ipv6.h>
-+#include <linux/netdevice.h>
-+#include <linux/ipv6_tunnel.h>
-+#include <linux/skbuff.h>
-+#include <asm/atomic.h>
-+
-+/* capable of sending packets */
-+#define IP6_TNL_F_CAP_XMIT 0x10000
-+/* capable of receiving packets */
-+#define IP6_TNL_F_CAP_RCV 0x20000
-+
-+#define IP6_TNL_MAX 128
-+
-+/* IPv6 tunnel */
-+
-+struct ip6_tnl {
-+ struct ip6_tnl *next; /* next tunnel in list */
-+ struct net_device *dev; /* virtual device associated with tunnel */
-+ struct net_device_stats stat; /* statistics for tunnel device */
-+ int recursion; /* depth of hard_start_xmit recursion */
-+ struct ip6_tnl_parm parms; /* tunnel configuration paramters */
-+ struct flowi fl; /* flowi template for xmit */
-+ atomic_t refcnt; /* nr of identical tunnels used by kernel */
-+ struct socket *sock;
-+};
-+
-+#define IP6_TNL_PRE_ENCAP 0
-+#define IP6_TNL_PRE_DECAP 1
-+#define IP6_TNL_MAXHOOKS 2
-+
-+#define IP6_TNL_DROP 0
-+#define IP6_TNL_ACCEPT 1
-+
-+typedef int ip6_tnl_hookfn(struct ip6_tnl *t, struct sk_buff *skb);
-+
-+struct ip6_tnl_hook_ops {
-+ struct list_head list;
-+ unsigned int hooknum;
-+ int priority;
-+ ip6_tnl_hookfn *hook;
-+};
-+
-+enum ip6_tnl_hook_priorities {
-+ IP6_TNL_PRI_FIRST = INT_MIN,
-+ IP6_TNL_PRI_LAST = INT_MAX
-+};
-+
-+/* Tunnel encapsulation limit destination sub-option */
-+
-+struct ipv6_tlv_tnl_enc_lim {
-+ __u8 type; /* type-code for option */
-+ __u8 length; /* option length */
-+ __u8 encap_limit; /* tunnel encapsulation limit */
-+} __attribute__ ((packed));
-+
-+#ifdef __KERNEL__
-+extern int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt);
-+
-+extern struct ip6_tnl *ip6ip6_tnl_lookup(struct in6_addr *remote,
-+ struct in6_addr *local);
-+
-+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p);
-+
-+extern int ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p);
-+
-+extern int ip6ip6_kernel_tnl_del(struct ip6_tnl *t);
-+
-+extern unsigned int ip6ip6_tnl_inc_max_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_dec_max_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_inc_min_kdev_count(unsigned int n);
-+
-+extern unsigned int ip6ip6_tnl_dec_min_kdev_count(unsigned int n);
-+
-+extern void ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg);
-+
-+extern void ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg);
-+
-+#ifdef CONFIG_IPV6_TUNNEL
-+extern int __init ip6_tunnel_init(void);
-+extern void ip6_tunnel_cleanup(void);
-+#endif
-+#endif
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/net/mipglue.h
-@@ -0,0 +1,266 @@
-+/*
-+ * Glue for Mobility support integration to IPv6
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _NET_MIPGLUE_H
-+#define _NET_MIPGLUE_H
-+
-+#ifndef USE_IPV6_MOBILITY
-+#if defined(CONFIG_IPV6_MOBILITY) || defined(CONFIG_IPV6_MOBILITY_MODULE)
-+#define USE_IPV6_MOBILITY
-+#endif
-+#endif
-+
-+/* symbols to indicate whether destination options received should take
-+ * effect or not (see exthdrs.c, procrcv.c)
-+ */
-+#define MIPV6_DSTOPTS_ACCEPT 1
-+#define MIPV6_DSTOPTS_DISCARD 0
-+
-+#define MIPV6_IGN_RTR 0
-+#define MIPV6_ADD_RTR 1
-+#define MIPV6_CHG_RTR 2
-+
-+/* MIPV6: Approximate maximum for mobile IPv6 options and headers */
-+#define MIPV6_HEADERS 48
-+
-+#ifdef __KERNEL__
-+#include <net/mipv6.h>
-+#include <linux/slab.h>
-+#include <net/ipv6.h>
-+
-+struct sk_buff;
-+struct ndisc_options;
-+struct sock;
-+struct ipv6_txoptions;
-+struct flowi;
-+struct dst_entry;
-+struct in6_addr;
-+struct inet6_ifaddr;
-+
-+#ifdef USE_IPV6_MOBILITY
-+
-+/* calls a procedure from mipv6-module */
-+#define MIPV6_CALLPROC(X) if(mipv6_functions.X) mipv6_functions.X
-+
-+/* calls a function from mipv6-module, default-value if function not defined
-+ */
-+#define MIPV6_CALLFUNC(X,Y) (!mipv6_functions.X)?(Y):mipv6_functions.X
-+
-+/* sets a handler-function to process a call */
-+#define MIPV6_SETCALL(X,Y) if(mipv6_functions.X) printk("mipv6: Warning, function assigned twice!\n"); \
-+ mipv6_functions.X = Y
-+#define MIPV6_RESETCALL(X) mipv6_functions.X = NULL
-+
-+/* pointers to mipv6 callable functions */
-+struct mipv6_callable_functions {
-+ void (*mipv6_initialize_dstopt_rcv) (struct sk_buff *skb);
-+ int (*mipv6_finalize_dstopt_rcv) (int process);
-+ int (*mipv6_handle_homeaddr) (struct sk_buff *skb, int optoff);
-+ int (*mipv6_ra_rcv) (struct sk_buff *skb,
-+ struct ndisc_options *ndopts);
-+ void (*mipv6_icmp_rcv) (struct sk_buff *skb);
-+ struct ipv6_txoptions * (*mipv6_modify_txoptions) (
-+ struct sock *sk,
-+ struct sk_buff *skb,
-+ struct ipv6_txoptions *opt,
-+ struct flowi *fl,
-+ struct dst_entry **dst);
-+ void (*mipv6_set_home) (int ifindex, struct in6_addr *homeaddr,
-+ int plen, struct in6_addr *homeagent,
-+ int plen2);
-+ void (*mipv6_get_home_address) (struct in6_addr *home_addr);
-+ void (*mipv6_get_care_of_address)(struct in6_addr *homeaddr,
-+ struct in6_addr *coa);
-+ int (*mipv6_is_home_addr)(struct in6_addr *addr);
-+ void (*mipv6_change_router)(void);
-+ void (*mipv6_check_dad)(struct in6_addr *home_addr);
-+ void (*mipv6_icmp_swap_addrs)(struct sk_buff *skb);
-+ int (*mipv6_forward)(struct sk_buff *skb);
-+ int (*mipv6_mn_ha_probe)(struct inet6_ifaddr *ifp, u8 *lladdr);
-+};
-+
-+extern struct mipv6_callable_functions mipv6_functions;
-+
-+extern void mipv6_invalidate_calls(void);
-+
-+extern int mipv6_handle_dstopt(struct sk_buff *skb, int optoff);
-+
-+static inline int
-+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ return MIPV6_CALLFUNC(mipv6_mn_ha_probe, 0)(ifp, lladdr);
-+}
-+
-+/* Must only be called for HA, no checks here */
-+static inline int ip6_mipv6_forward(struct sk_buff *skb)
-+{
-+ return MIPV6_CALLFUNC(mipv6_forward, 0)(skb);
-+}
-+
-+/*
-+ * Avoid adding new default routers if the old one is still in use
-+ */
-+
-+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb,
-+ struct ndisc_options *ndopts)
-+{
-+ return MIPV6_CALLFUNC(mipv6_ra_rcv, MIPV6_ADD_RTR)(skb, ndopts);
-+}
-+
-+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr)
-+{
-+ return MIPV6_CALLFUNC(mipv6_is_home_addr, 0)(addr);
-+}
-+
-+static inline void ndisc_mipv6_change_router(int change_rtr)
-+{
-+ if (change_rtr == MIPV6_CHG_RTR)
-+ MIPV6_CALLPROC(mipv6_change_router)();
-+}
-+
-+static inline void ndisc_check_mipv6_dad(struct in6_addr *target)
-+{
-+ MIPV6_CALLPROC(mipv6_check_dad)(target);
-+}
-+
-+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb)
-+{
-+ MIPV6_CALLPROC(mipv6_icmp_swap_addrs)(skb);
-+}
-+
-+static inline void mipv6_icmp_rcv(struct sk_buff *skb)
-+{
-+ MIPV6_CALLPROC(mipv6_icmp_rcv)(skb);
-+}
-+
-+static inline int tcp_v6_get_mipv6_header_len(void)
-+{
-+ return MIPV6_HEADERS;
-+}
-+
-+static inline struct in6_addr *
-+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr)
-+{
-+ return daddr;
-+}
-+
-+static inline void
-+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int plen2)
-+{
-+ MIPV6_CALLPROC(mipv6_set_home)(ifindex, homeaddr, plen, homeagent, plen2);
-+}
-+
-+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr)
-+{
-+ MIPV6_CALLPROC(mipv6_get_home_address)(saddr);
-+}
-+
-+static inline struct ipv6_txoptions *
-+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ return MIPV6_CALLFUNC(mipv6_modify_txoptions, opt)(sk, skb, opt, fl, dst);
-+
-+}
-+
-+static inline void
-+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt;
-+ if (txopt) {
-+ opt = (struct inet6_skb_parm *)skb->cb;
-+ opt->mipv6_flags = txopt->mipv6_flags;
-+ }
-+}
-+
-+static inline void
-+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt,
-+ struct ipv6_txoptions *orig_opt)
-+{
-+ if (opt && opt != orig_opt)
-+ kfree(opt);
-+}
-+
-+#else /* USE_IPV6_MOBILITY */
-+
-+#define mipv6_handle_dstopt ip6_tlvopt_unknown
-+
-+static inline int
-+ndisc_mip_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ return 0;
-+}
-+
-+static inline int ip6_mipv6_forward(struct sk_buff *skb)
-+{
-+ return 0;
-+}
-+
-+static inline int ndisc_mipv6_ra_rcv(struct sk_buff *skb,
-+ struct ndisc_options *ndopts)
-+{
-+ return MIPV6_ADD_RTR;
-+}
-+
-+static inline int ipv6_chk_mip_home_addr(struct in6_addr *addr)
-+{
-+ return 0;
-+}
-+
-+static inline void ndisc_mipv6_change_router(int change_rtr) {}
-+
-+static inline void ndisc_check_mipv6_dad(struct in6_addr *target) {}
-+
-+static inline void icmpv6_swap_mipv6_addrs(struct sk_buff *skb) {}
-+
-+static inline void mipv6_icmp_rcv(struct sk_buff *skb) {}
-+
-+static inline int tcp_v6_get_mipv6_header_len(void)
-+{
-+ return 0;
-+}
-+
-+static inline struct in6_addr *
-+mipv6_get_fake_hdr_daddr(struct in6_addr *hdaddr, struct in6_addr *daddr)
-+{
-+ return hdaddr;
-+}
-+
-+static inline void
-+addrconf_set_mipv6_mn_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int plen2) {}
-+
-+static inline void addrconf_get_mipv6_home_address(struct in6_addr *saddr) {}
-+
-+static inline struct ipv6_txoptions *
-+ip6_add_mipv6_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ return opt;
-+}
-+
-+static inline void
-+ip6_mark_mipv6_packet(struct ipv6_txoptions *txopt, struct sk_buff *skb) {}
-+
-+static inline void
-+ip6_free_mipv6_txoptions(struct ipv6_txoptions *opt,
-+ struct ipv6_txoptions *orig_opt) {}
-+
-+#endif /* USE_IPV6_MOBILITY */
-+#endif /* __KERNEL__ */
-+#endif /* _NET_MIPGLUE_H */
---- /dev/null
-+++ linux-2.4.27/include/net/mipv6.h
-@@ -0,0 +1,258 @@
-+/*
-+ * Mobile IPv6 header-file
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef _NET_MIPV6_H
-+#define _NET_MIPV6_H
-+
-+#include <linux/types.h>
-+#include <asm/byteorder.h>
-+#include <linux/in6.h>
-+
-+/*
-+ *
-+ * Mobile IPv6 Protocol constants
-+ *
-+ */
-+#define DHAAD_RETRIES 4 /* transmissions */
-+#define INITIAL_BINDACK_TIMEOUT 1 /* seconds */
-+#define INITIAL_DHAAD_TIMEOUT 3 /* seconds */
-+#define INITIAL_SOLICIT_TIMER 3 /* seconds */
-+#define MAX_BINDACK_TIMEOUT 32 /* seconds */
-+#define MAX_NONCE_LIFE 240 /* seconds */
-+#define MAX_TOKEN_LIFE 210 /* seconds */
-+#define MAX_RR_BINDING_LIFE 420 /* seconds */
-+#define MAX_UPDATE_RATE 3 /* 1/s (min delay=1s) */
-+#define PREFIX_ADV_RETRIES 3 /* transmissions */
-+#define PREFIX_ADV_TIMEOUT 3 /* seconds */
-+
-+#define MAX_FAST_UPDATES 5 /* transmissions */
-+#define MAX_PFX_ADV_DELAY 1000 /* seconds */
-+#define SLOW_UPDATE_RATE 10 /* 1/10s (max delay=10s)*/
-+#define INITIAL_BINDACK_DAD_TIMEOUT 2 /* seconds */
-+
-+/*
-+ *
-+ * Mobile IPv6 (RFC 3775) Protocol configuration variable defaults
-+ *
-+ */
-+#define DefHomeRtrAdvInterval 1000 /* seconds */
-+#define DefMaxMobPfxAdvInterval 86400 /* seconds */
-+#define DefMinDelayBetweenRAs 3 /* seconds (min 0.03) */
-+#define DefMinMobPfxAdvInterval 600 /* seconds */
-+#define DefInitialBindackTimeoutFirstReg 1.5 /* seconds */
-+
-+/* This is not actually specified in the draft, but is needed to avoid
-+ * prefix solicitation storm when valid lifetime of a prefix is smaller
-+ * than MAX_PFX_ADV_DELAY
-+ */
-+#define MIN_PFX_SOL_DELAY 5 /* seconds */
-+
-+/* Mobile IPv6 ICMP types */
-+/*
-+ * Official numbers from RFC 3775
-+ */
-+#define MIPV6_DHAAD_REQUEST 144
-+#define MIPV6_DHAAD_REPLY 145
-+#define MIPV6_PREFIX_SOLICIT 146
-+#define MIPV6_PREFIX_ADV 147
-+
-+/* Binding update flag codes */
-+#define MIPV6_BU_F_ACK 0x80
-+#define MIPV6_BU_F_HOME 0x40
-+#define MIPV6_BU_F_LLADDR 0x20
-+#define MIPV6_BU_F_KEYMGM 0x10
-+
-+/* Binding ackknowledgment flag codes */
-+#define MIPV6_BA_F_KEYMGM 0x80
-+
-+/* Binding error status */
-+#define MIPV6_BE_HAO_WO_BINDING 1
-+#define MIPV6_BE_UNKNOWN_MH_TYPE 2
-+
-+/* Mobility Header */
-+struct mipv6_mh
-+{
-+ __u8 payload; /* Payload Protocol */
-+ __u8 length; /* MH Length */
-+ __u8 type; /* MH Type */
-+ __u8 reserved; /* Reserved */
-+ __u16 checksum; /* Checksum */
-+ __u8 data[0]; /* Message specific data */
-+} __attribute__ ((packed));
-+
-+/* Mobility Header type */
-+#define IPPROTO_MOBILITY 135 /* RFC 3775*/
-+/* Mobility Header Message Types */
-+
-+#define MIPV6_MH_BRR 0
-+#define MIPV6_MH_HOTI 1
-+#define MIPV6_MH_COTI 2
-+#define MIPV6_MH_HOT 3
-+#define MIPV6_MH_COT 4
-+#define MIPV6_MH_BU 5
-+#define MIPV6_MH_BA 6
-+#define MIPV6_MH_BE 7
-+
-+/*
-+ * Status codes for Binding Acknowledgements
-+ */
-+#define SUCCESS 0
-+#define REASON_UNSPECIFIED 128
-+#define ADMINISTRATIVELY_PROHIBITED 129
-+#define INSUFFICIENT_RESOURCES 130
-+#define HOME_REGISTRATION_NOT_SUPPORTED 131
-+#define NOT_HOME_SUBNET 132
-+#define NOT_HA_FOR_MN 133
-+#define DUPLICATE_ADDR_DETECT_FAIL 134
-+#define SEQUENCE_NUMBER_OUT_OF_WINDOW 135
-+#define EXPIRED_HOME_NONCE_INDEX 136
-+#define EXPIRED_CAREOF_NONCE_INDEX 137
-+#define EXPIRED_NONCES 138
-+#define REG_TYPE_CHANGE_FORBIDDEN 139
-+/*
-+ * Values for mipv6_flags in struct inet6_skb_parm
-+ */
-+
-+#define MIPV6_RCV_TUNNEL 0x1
-+#define MIPV6_SND_HAO 0x2
-+#define MIPV6_SND_BU 0x4
-+
-+/*
-+ * Mobility Header Message structures
-+ */
-+
-+struct mipv6_mh_brr
-+{
-+ __u16 reserved;
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_bu
-+{
-+ __u16 sequence; /* sequence number of BU */
-+ __u8 flags; /* flags */
-+ __u8 reserved; /* reserved bits */
-+ __u16 lifetime; /* lifetime of BU */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_ba
-+{
-+ __u8 status; /* statuscode */
-+ __u8 reserved; /* reserved bits */
-+ __u16 sequence; /* sequence number of BA */
-+ __u16 lifetime; /* lifetime in CN's bcache */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_be
-+{
-+ __u8 status;
-+ __u8 reserved;
-+ struct in6_addr home_addr;
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_addr_ti
-+{
-+ __u16 reserved; /* Reserved */
-+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mh_addr_test
-+{
-+ __u16 nonce_index; /* Home/Care-of Nonce Index */
-+ u_int8_t init_cookie[8]; /* HoT/CoT Init Cookie */
-+ u_int8_t kgen_token[8]; /* Home/Care-of key generation token */
-+ /* Mobility options */
-+} __attribute__ ((packed));
-+
-+/*
-+ * Mobility Options for various MH types.
-+ */
-+#define MIPV6_OPT_PAD1 0x00
-+#define MIPV6_OPT_PADN 0x01
-+#define MIPV6_OPT_BIND_REFRESH_ADVICE 0x02
-+#define MIPV6_OPT_ALTERNATE_COA 0x03
-+#define MIPV6_OPT_NONCE_INDICES 0x04
-+#define MIPV6_OPT_AUTH_DATA 0x05
-+
-+#define MIPV6_SEQ_GT(x,y) \
-+ ((short int)(((__u16)(x)) - ((__u16)(y))) > 0)
-+
-+/*
-+ * Mobility Option structures
-+ */
-+
-+struct mipv6_mo
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 value[0]; /* type specific data */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_pad1
-+{
-+ __u8 type;
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_padn
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_alt_coa
-+{
-+ __u8 type;
-+ __u8 length;
-+ struct in6_addr addr; /* alternate care-of-address */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_nonce_indices
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u16 home_nonce_i; /* Home Nonce Index */
-+ __u16 careof_nonce_i; /* Careof Nonce Index */
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_bauth_data
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct mipv6_mo_br_advice
-+{
-+ __u8 type;
-+ __u8 length;
-+ __u16 refresh_interval; /* Refresh Interval */
-+} __attribute__ ((packed));
-+
-+/*
-+ * Home Address Destination Option structure
-+ */
-+struct mipv6_dstopt_homeaddr
-+{
-+ __u8 type; /* type-code for option */
-+ __u8 length; /* option length */
-+ struct in6_addr addr; /* home address */
-+} __attribute__ ((packed));
-+
-+#endif /* _NET_MIPV6_H */
---- linux-2.4.27/include/net/ndisc.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/net/ndisc.h
-@@ -21,6 +21,10 @@
- #define ND_OPT_REDIRECT_HDR 4
- #define ND_OPT_MTU 5
-
-+/* Mobile IPv6 specific ndisc options */
-+#define ND_OPT_RTR_ADV_INTERVAL 7
-+#define ND_OPT_HOME_AGENT_INFO 8
-+
- #define MAX_RTR_SOLICITATION_DELAY HZ
-
- #define ND_REACHABLE_TIME (30*HZ)
-@@ -57,7 +61,7 @@
- } __attribute__((__packed__));
-
- struct ndisc_options {
-- struct nd_opt_hdr *nd_opt_array[7];
-+ struct nd_opt_hdr *nd_opt_array[10];
- struct nd_opt_hdr *nd_opt_piend;
- };
-
-@@ -67,6 +71,8 @@
- #define nd_opts_pi_end nd_opt_piend
- #define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
- #define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
-+#define nd_opts_rai nd_opt_array[ND_OPT_RTR_ADV_INTERVAL]
-+#define nd_opts_hai nd_opt_array[ND_OPT_HOME_AGENT_INFO]
-
- extern struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, struct nd_opt_hdr *end);
- extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, struct ndisc_options *ndopts);
-@@ -83,6 +89,15 @@
- struct in6_addr *daddr,
- struct in6_addr *saddr);
-
-+extern void ndisc_send_na(struct net_device *dev,
-+ struct neighbour *neigh,
-+ struct in6_addr *daddr,
-+ struct in6_addr *solicited_addr,
-+ int router,
-+ int solicited,
-+ int override,
-+ int inc_opt);
-+
- extern void ndisc_send_rs(struct net_device *dev,
- struct in6_addr *saddr,
- struct in6_addr *daddr);
---- linux-2.4.27/include/net/sock.h~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/include/net/sock.h
-@@ -149,7 +149,9 @@
- struct in6_addr rcv_saddr;
- struct in6_addr daddr;
- struct in6_addr *daddr_cache;
--
-+#if defined(CONFIG_IPV6_SUBTREES)
-+ struct in6_addr *saddr_cache;
-+#endif
- __u32 flow_label;
- __u32 frag_size;
- int hop_limit;
---- linux-2.4.27/net/Makefile~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/Makefile
-@@ -7,7 +7,7 @@
-
- O_TARGET := network.o
-
--mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp 802
-+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core sctp 802 ipv6
- export-objs := netsyms.o
-
- subdir-y := core ethernet
-@@ -25,6 +25,7 @@
- ifneq ($(CONFIG_IPV6),n)
- ifneq ($(CONFIG_IPV6),)
- subdir-$(CONFIG_NETFILTER) += ipv6/netfilter
-+subdir-$(CONFIG_IPV6_MOBILITY) += ipv6/mobile_ip6
- endif
- endif
-
---- linux-2.4.27/net/core/neighbour.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/core/neighbour.c
-@@ -386,7 +386,7 @@
- if (!creat)
- return NULL;
-
-- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
-+ n = kmalloc(sizeof(*n) + key_len, GFP_ATOMIC);
- if (n == NULL)
- return NULL;
-
---- linux-2.4.27/net/ipv6/Config.in~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/Config.in
-@@ -1,10 +1,16 @@
- #
- # IPv6 configuration
- #
--
-+bool ' IPv6: routing by source address (EXPERIMENTAL)' CONFIG_IPV6_SUBTREES
- #bool ' IPv6: flow policy support' CONFIG_RT6_POLICY
- #bool ' IPv6: firewall support' CONFIG_IPV6_FIREWALL
-
-+if [ "$CONFIG_IPV6" != "n" ]; then
-+ dep_tristate ' IPv6: IPv6 over IPv6 Tunneling (EXPERIMENTAL)' CONFIG_IPV6_TUNNEL $CONFIG_IPV6
-+fi
-+
-+source net/ipv6/mobile_ip6/Config.in
-+
- if [ "$CONFIG_NETFILTER" != "n" ]; then
- source net/ipv6/netfilter/Config.in
- fi
---- linux-2.4.27/net/ipv6/Makefile~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/Makefile
-@@ -6,18 +6,28 @@
- # unless it's something special (ie not a .c file).
- #
-
-+export-objs := ipv6_syms.o ipv6_tunnel.o
-
--O_TARGET := ipv6.o
-+#list-multi := ipv6.o ipv6_tunnel.o
-
--obj-y := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
-- route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
-- protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
-- exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
-- ip6_flowlabel.o ipv6_syms.o
-+ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
-+ sit.o route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o \
-+ raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
-+ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
-+ ip6_flowlabel.o ipv6_syms.o
-
--export-objs := ipv6_syms.o
-+ifneq ($(CONFIG_IPV6_MOBILITY),n)
-+ifneq ($(CONFIG_IPV6_MOBILITY),)
-+ipv6-objs += mipglue.o
-+endif
-+endif
-+
-+obj-$(CONFIG_IPV6) += ipv6.o
-+obj-$(CONFIG_IPV6_TUNNEL) += ipv6_tunnel.o
-+
-+ipv6.o: $(ipv6-objs)
-+ $(LD) -r -o $@ $(ipv6-objs)
-
--obj-m := $(O_TARGET)
-
- #obj-$(CONFIG_IPV6_FIREWALL) += ip6_fw.o
-
---- linux-2.4.27/net/ipv6/addrconf.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/addrconf.c
-@@ -68,6 +68,8 @@
-
- #include <asm/uaccess.h>
-
-+#include <net/mipglue.h>
-+
- #define IPV6_MAX_ADDRESSES 16
-
- /* Set to 3 to get tracing... */
-@@ -103,9 +105,9 @@
-
- static int addrconf_ifdown(struct net_device *dev, int how);
-
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
-+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
- static void addrconf_dad_timer(unsigned long data);
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
-+void addrconf_dad_completed(struct inet6_ifaddr *ifp);
- static void addrconf_rs_timer(unsigned long data);
- static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
-
-@@ -330,38 +332,6 @@
- return idev;
- }
-
--void ipv6_addr_prefix(struct in6_addr *prefix,
-- struct in6_addr *addr, int prefix_len)
--{
-- unsigned long mask;
-- int ncopy, nbits;
--
-- memset(prefix, 0, sizeof(*prefix));
--
-- if (prefix_len <= 0)
-- return;
-- if (prefix_len > 128)
-- prefix_len = 128;
--
-- ncopy = prefix_len / 32;
-- switch (ncopy) {
-- case 4: prefix->s6_addr32[3] = addr->s6_addr32[3];
-- case 3: prefix->s6_addr32[2] = addr->s6_addr32[2];
-- case 2: prefix->s6_addr32[1] = addr->s6_addr32[1];
-- case 1: prefix->s6_addr32[0] = addr->s6_addr32[0];
-- case 0: break;
-- }
-- nbits = prefix_len % 32;
-- if (nbits == 0)
-- return;
--
-- mask = ~((1 << (32 - nbits)) - 1);
-- mask = htonl(mask);
--
-- prefix->s6_addr32[ncopy] = addr->s6_addr32[ncopy] & mask;
--}
--
--
- static void dev_forward_change(struct inet6_dev *idev)
- {
- struct net_device *dev;
-@@ -513,7 +483,7 @@
-
- /* This function wants to get referenced ifp and releases it before return */
-
--static void ipv6_del_addr(struct inet6_ifaddr *ifp)
-+void ipv6_del_addr(struct inet6_ifaddr *ifp)
- {
- struct inet6_ifaddr *ifa, **ifap;
- struct inet6_dev *idev = ifp->idev;
-@@ -662,6 +632,12 @@
- if (match)
- in6_ifa_put(match);
-
-+ /* The home address is always used as source address in
-+ * MIPL mobile IPv6
-+ */
-+ if (scope != IFA_HOST && scope != IFA_LINK)
-+ addrconf_get_mipv6_home_address(saddr);
-+
- return err;
- }
-
-@@ -815,7 +791,7 @@
- }
-
-
--static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
-+int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
- {
- switch (dev->type) {
- case ARPHRD_ETHER:
-@@ -840,7 +816,7 @@
- return -1;
- }
-
--static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
-+int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
- {
- int err = -1;
- struct inet6_ifaddr *ifp;
-@@ -1407,6 +1383,24 @@
- sit_route_add(dev);
- }
-
-+/**
-+ * addrconf_ipv6_tunnel_config - configure IPv6 tunnel device
-+ * @dev: tunnel device
-+ **/
-+
-+static void addrconf_ipv6_tunnel_config(struct net_device *dev)
-+{
-+ struct inet6_dev *idev;
-+
-+ ASSERT_RTNL();
-+
-+ /* Assign inet6_dev structure to tunnel device */
-+ if ((idev = ipv6_find_idev(dev)) == NULL) {
-+ printk(KERN_DEBUG "init ipv6 tunnel: add_dev failed\n");
-+ return;
-+ }
-+}
-+
-
- int addrconf_notify(struct notifier_block *this, unsigned long event,
- void * data)
-@@ -1421,6 +1415,10 @@
- addrconf_sit_config(dev);
- break;
-
-+ case ARPHRD_TUNNEL6:
-+ addrconf_ipv6_tunnel_config(dev);
-+ break;
-+
- case ARPHRD_LOOPBACK:
- init_loopback(dev);
- break;
-@@ -1602,7 +1600,7 @@
- /*
- * Duplicate Address Detection
- */
--static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
-+void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
- {
- struct net_device *dev;
- unsigned long rand_num;
-@@ -1667,7 +1665,7 @@
- in6_ifa_put(ifp);
- }
-
--static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
-+void addrconf_dad_completed(struct inet6_ifaddr *ifp)
- {
- struct net_device * dev = ifp->idev->dev;
-
-@@ -1676,7 +1674,7 @@
- */
-
- ipv6_ifa_notify(RTM_NEWADDR, ifp);
--
-+ notifier_call_chain(&inet6addr_chain,NETDEV_UP,ifp);
- /* If added prefix is link local and forwarding is off,
- start sending router solicitations.
- */
-@@ -1877,8 +1875,20 @@
- if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
- return -EINVAL;
-+ if (ifm->ifa_flags & IFA_F_HOMEADDR && !rta[IFA_HOMEAGENT-1])
-+ return -EINVAL;
- pfx = RTA_DATA(rta[IFA_LOCAL-1]);
- }
-+ if (rta[IFA_HOMEAGENT-1]) {
-+ struct in6_addr *ha;
-+ if (pfx == NULL || !(ifm->ifa_flags & IFA_F_HOMEADDR))
-+ return -EINVAL;
-+ if (RTA_PAYLOAD(rta[IFA_HOMEAGENT-1]) < sizeof(*ha))
-+ return -EINVAL;
-+ ha = RTA_DATA(rta[IFA_HOMEAGENT-1]);
-+ addrconf_set_mipv6_mn_home(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
-+ ha, ifm->ifa_prefixlen);
-+ }
- if (pfx == NULL)
- return -EINVAL;
-
---- linux-2.4.27/net/ipv6/af_inet6.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/af_inet6.c
-@@ -58,6 +58,9 @@
- #include <net/transp_v6.h>
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-+#ifdef CONFIG_IPV6_TUNNEL
-+#include <net/ipv6_tunnel.h>
-+#endif
-
- #include <asm/uaccess.h>
- #include <asm/system.h>
-@@ -646,6 +649,11 @@
- err = ndisc_init(&inet6_family_ops);
- if (err)
- goto ndisc_fail;
-+#ifdef CONFIG_IPV6_TUNNEL
-+ err = ip6_tunnel_init();
-+ if (err)
-+ goto ip6_tunnel_fail;
-+#endif
- err = igmp6_init(&inet6_family_ops);
- if (err)
- goto igmp_fail;
-@@ -698,6 +706,10 @@
- #endif
- igmp_fail:
- ndisc_cleanup();
-+#ifdef CONFIG_IPV6_TUNNEL
-+ ip6_tunnel_cleanup();
-+ip6_tunnel_fail:
-+#endif
- ndisc_fail:
- icmpv6_cleanup();
- icmp_fail:
-@@ -730,6 +742,9 @@
- ip6_route_cleanup();
- ipv6_packet_cleanup();
- igmp6_cleanup();
-+#ifdef CONFIG_IPV6_TUNNEL
-+ ip6_tunnel_cleanup();
-+#endif
- ndisc_cleanup();
- icmpv6_cleanup();
- #ifdef CONFIG_SYSCTL
---- linux-2.4.27/net/ipv6/exthdrs.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/exthdrs.c
-@@ -41,6 +41,9 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-
-+#include <net/mipglue.h>
-+#include <net/mipv6.h>
-+
- #include <asm/uaccess.h>
-
- /*
-@@ -160,7 +163,8 @@
- *****************************/
-
- struct tlvtype_proc tlvprocdestopt_lst[] = {
-- /* No destination options are defined now */
-+ /* Mobility Support destination options */
-+ {MIPV6_TLV_HOMEADDR, mipv6_handle_dstopt},
- {-1, NULL}
- };
-
-@@ -210,6 +214,7 @@
-
- struct ipv6_rt_hdr *hdr;
- struct rt0_hdr *rthdr;
-+ struct rt2_hdr *rt2hdr;
-
- if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
- !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-@@ -225,17 +230,25 @@
- kfree_skb(skb);
- return -1;
- }
--
-+ /* Silently discard invalid packets containing RTH type 2 */
-+ if (hdr->type == IPV6_SRCRT_TYPE_2 &&
-+ (hdr->hdrlen != 2 || hdr->segments_left != 1)) {
-+ kfree_skb(skb);
-+ return -1;
-+ }
- looped_back:
- if (hdr->segments_left == 0) {
-- opt->srcrt = skb->h.raw - skb->nh.raw;
-+ if (hdr->type == IPV6_SRCRT_TYPE_0)
-+ opt->srcrt = skb->h.raw - skb->nh.raw;
-+ else if (hdr->type == IPV6_SRCRT_TYPE_2)
-+ opt->srcrt2 = skb->h.raw - skb->nh.raw;
- skb->h.raw += (hdr->hdrlen + 1) << 3;
- opt->dst0 = opt->dst1;
- opt->dst1 = 0;
- return (&hdr->nexthdr) - skb->nh.raw;
- }
-
-- if (hdr->type != IPV6_SRCRT_TYPE_0) {
-+ if (hdr->type != IPV6_SRCRT_TYPE_0 && hdr->type != IPV6_SRCRT_TYPE_2) {
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
- return -1;
- }
-@@ -275,9 +288,20 @@
-
- i = n - --hdr->segments_left;
-
-- rthdr = (struct rt0_hdr *) hdr;
-- addr = rthdr->addr;
-- addr += i - 1;
-+ if (hdr->type == IPV6_SRCRT_TYPE_0) {
-+ rthdr = (struct rt0_hdr *) hdr;
-+ addr = rthdr->addr;
-+ addr += i - 1;
-+ } else {
-+ /* check that address is this node's home address */
-+ rt2hdr = (struct rt2_hdr *) hdr;
-+ addr = &rt2hdr->addr;
-+ if (!ipv6_chk_addr(addr, NULL) ||
-+ !ipv6_chk_mip_home_addr(addr)) {
-+ kfree_skb(skb);
-+ return -1;
-+ }
-+ }
-
- addr_type = ipv6_addr_type(addr);
-
-@@ -330,6 +354,10 @@
- temporary (or permanent) backdoor.
- If listening socket set IPV6_RTHDR to 2, then we invert header.
- --ANK (980729)
-+
-+ By the Mobile IPv6 specification Type 2 routing header MUST NOT be
-+ inverted.
-+ --AJT (20020917)
- */
-
- struct ipv6_txoptions *
-@@ -352,6 +380,18 @@
- struct ipv6_txoptions *opt;
- int hdrlen = ipv6_optlen(hdr);
-
-+ if (hdr->type == IPV6_SRCRT_TYPE_2) {
-+ opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
-+ if (opt == NULL)
-+ return NULL;
-+ memset(opt, 0, sizeof(*opt));
-+ opt->tot_len = sizeof(*opt) + hdrlen;
-+ opt->srcrt = (void*)(opt+1);
-+ opt->opt_nflen = hdrlen;
-+ memcpy(opt->srcrt, hdr, sizeof(struct rt2_hdr));
-+ return opt;
-+ }
-+
- if (hdr->segments_left ||
- hdr->type != IPV6_SRCRT_TYPE_0 ||
- hdr->hdrlen & 0x01)
-@@ -622,8 +662,18 @@
- if (opt) {
- if (opt->dst0opt)
- prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
-- if (opt->srcrt)
-- prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
-+ if (opt->srcrt) {
-+ if (opt->srcrt2) {
-+ struct in6_addr *rt2_hop = &((struct rt2_hdr *)opt->srcrt2)->addr;
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, rt2_hop);
-+ } else
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
-+ }
-+ if (opt->srcrt2) {
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb;
-+ ipv6_addr_copy(&parm->hoa, daddr);
-+ prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt2, daddr);
-+ }
- }
- return prev_hdr;
- }
-@@ -684,6 +734,11 @@
- u8 *proto,
- struct in6_addr **daddr)
- {
-+ if (opt->srcrt2) {
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *)skb->cb;
-+ ipv6_addr_copy(&parm->hoa, *daddr);
-+ ipv6_push_rthdr(skb, proto, opt->srcrt2, daddr);
-+ }
- if (opt->srcrt)
- ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
- if (opt->dst0opt)
-@@ -719,6 +774,8 @@
- *((char**)&opt2->auth) += dif;
- if (opt2->srcrt)
- *((char**)&opt2->srcrt) += dif;
-+ if (opt2->srcrt2)
-+ *((char**)&opt2->srcrt2) += dif;
- }
- return opt2;
- }
---- linux-2.4.27/net/ipv6/icmp.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/icmp.c
-@@ -61,6 +61,8 @@
- #include <net/addrconf.h>
- #include <net/icmp.h>
-
-+#include <net/mipglue.h>
-+
- #include <asm/uaccess.h>
- #include <asm/system.h>
-
-@@ -364,6 +366,8 @@
-
- msg.len = len;
-
-+ icmpv6_swap_mipv6_addrs(skb);
-+
- ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
- MSG_DONTWAIT);
- if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-@@ -562,13 +566,13 @@
- rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
- ntohl(hdr->icmp6_mtu));
-
-- /*
-- * Drop through to notify
-- */
-+ icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
-+ break;
-
- case ICMPV6_DEST_UNREACH:
-- case ICMPV6_TIME_EXCEED:
- case ICMPV6_PARAMPROB:
-+ mipv6_icmp_rcv(skb);
-+ case ICMPV6_TIME_EXCEED:
- icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
- break;
-
-@@ -598,6 +602,13 @@
- case ICMPV6_MLD2_REPORT:
- break;
-
-+ case MIPV6_DHAAD_REQUEST:
-+ case MIPV6_DHAAD_REPLY:
-+ case MIPV6_PREFIX_SOLICIT:
-+ case MIPV6_PREFIX_ADV:
-+ mipv6_icmp_rcv(skb);
-+ break;
-+
- default:
- if (net_ratelimit())
- printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
---- linux-2.4.27/net/ipv6/ip6_fib.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/ip6_fib.c
-@@ -18,6 +18,7 @@
- * Yuji SEKIYA @USAGI: Support default route on router node;
- * remove ip6_null_entry from the top of
- * routing table.
-+ * Ville Nuorvala: Fixes to source address based routing
- */
- #include <linux/config.h>
- #include <linux/errno.h>
-@@ -40,7 +41,6 @@
- #include <net/ip6_route.h>
-
- #define RT6_DEBUG 2
--#undef CONFIG_IPV6_SUBTREES
-
- #if RT6_DEBUG >= 3
- #define RT6_TRACE(x...) printk(KERN_DEBUG x)
-@@ -500,6 +500,8 @@
- mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
- }
-
-+static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
-+
- /*
- * Add routing information to the routing tree.
- * <destination addr>/<source addr>
-@@ -508,17 +510,19 @@
-
- int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh)
- {
-- struct fib6_node *fn;
-+ struct fib6_node *fn = root;
- int err = -ENOMEM;
-
-- fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-- rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct fib6_node *pn = NULL;
-
-+ fn = fib6_add_1(root, &rt->rt6i_src.addr, sizeof(struct in6_addr),
-+ rt->rt6i_src.plen, (u8*) &rt->rt6i_src - (u8*) rt);
-+
- if (fn == NULL)
- goto out;
-
--#ifdef CONFIG_IPV6_SUBTREES
-- if (rt->rt6i_src.plen) {
-+ if (rt->rt6i_dst.plen) {
- struct fib6_node *sn;
-
- if (fn->subtree == NULL) {
-@@ -546,9 +550,9 @@
-
- /* Now add the first leaf node to new subtree */
-
-- sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
-- sizeof(struct in6_addr), rt->rt6i_src.plen,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ sn = fib6_add_1(sfn, &rt->rt6i_dst.addr,
-+ sizeof(struct in6_addr), rt->rt6i_dst.plen,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-
- if (sn == NULL) {
- /* If it is failed, discard just allocated
-@@ -562,21 +566,30 @@
- /* Now link new subtree to main tree */
- sfn->parent = fn;
- fn->subtree = sfn;
-- if (fn->leaf == NULL) {
-- fn->leaf = rt;
-- atomic_inc(&rt->rt6i_ref);
-- }
- } else {
-- sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
-- sizeof(struct in6_addr), rt->rt6i_src.plen,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ sn = fib6_add_1(fn->subtree, &rt->rt6i_dst.addr,
-+ sizeof(struct in6_addr), rt->rt6i_dst.plen,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-
- if (sn == NULL)
- goto st_failure;
- }
-
-+ /* fib6_add_1 might have cleared the old leaf pointer */
-+ if (fn->leaf == NULL) {
-+ fn->leaf = rt;
-+ atomic_inc(&rt->rt6i_ref);
-+ }
-+
-+ pn = fn;
- fn = sn;
- }
-+#else
-+ fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-+ rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
-+
-+ if (fn == NULL)
-+ goto out;
- #endif
-
- err = fib6_add_rt2node(fn, rt, nlh);
-@@ -588,8 +601,30 @@
- }
-
- out:
-- if (err)
-+ if (err) {
-+#ifdef CONFIG_IPV6_SUBTREES
-+
-+ /* If fib6_add_1 has cleared the old leaf pointer in the
-+ super-tree leaf node, we have to find a new one for it.
-+
-+ This situation will never arise in the sub-tree since
-+ the node will at least have the route that caused
-+ fib6_add_rt2node to fail.
-+ */
-+
-+ if (pn && !(pn->fn_flags & RTN_RTINFO)) {
-+ pn->leaf = fib6_find_prefix(pn);
-+#if RT6_DEBUG >= 2
-+ if (!pn->leaf) {
-+ BUG_TRAP(pn->leaf);
-+ pn->leaf = &ip6_null_entry;
-+ }
-+#endif
-+ atomic_inc(&pn->leaf->rt6i_ref);
-+ }
-+#endif
- dst_free(&rt->u.dst);
-+ }
- return err;
-
- #ifdef CONFIG_IPV6_SUBTREES
-@@ -597,8 +632,8 @@
- is orphan. If it is, shoot it.
- */
- st_failure:
-- if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT))
-- fib_repair_tree(fn);
-+ if (fn && !(fn->fn_flags & (RTN_RTINFO | RTN_ROOT)))
-+ fib6_repair_tree(fn);
- dst_free(&rt->u.dst);
- return err;
- #endif
-@@ -641,22 +676,28 @@
- break;
- }
-
-- while ((fn->fn_flags & RTN_ROOT) == 0) {
-+ for (;;) {
- #ifdef CONFIG_IPV6_SUBTREES
- if (fn->subtree) {
-- struct fib6_node *st;
-- struct lookup_args *narg;
--
-- narg = args + 1;
--
-- if (narg->addr) {
-- st = fib6_lookup_1(fn->subtree, narg);
-+ struct rt6key *key;
-
-- if (st && !(st->fn_flags & RTN_ROOT))
-- return st;
-+ key = (struct rt6key *) ((u8 *) fn->leaf +
-+ args->offset);
-+
-+ if (addr_match(&key->addr, args->addr, key->plen)) {
-+ struct fib6_node *st;
-+ struct lookup_args *narg = args + 1;
-+ if (!ipv6_addr_any(narg->addr)) {
-+ st = fib6_lookup_1(fn->subtree, narg);
-+
-+ if (st && !(st->fn_flags & RTN_ROOT))
-+ return st;
-+ }
- }
- }
- #endif
-+ if (fn->fn_flags & RTN_ROOT)
-+ break;
-
- if (fn->fn_flags & RTN_RTINFO) {
- struct rt6key *key;
-@@ -680,13 +721,22 @@
- struct lookup_args args[2];
- struct rt6_info *rt = NULL;
- struct fib6_node *fn;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct in6_addr saddr_buf;
-+#endif
-
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (saddr == NULL) {
-+ memset(&saddr_buf, 0, sizeof(struct in6_addr));
-+ saddr = &saddr_buf;
-+ }
-+ args[0].offset = (u8*) &rt->rt6i_src - (u8*) rt;
-+ args[0].addr = saddr;
-+ args[1].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
-+ args[1].addr = daddr;
-+#else
- args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
- args[0].addr = daddr;
--
--#ifdef CONFIG_IPV6_SUBTREES
-- args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt;
-- args[1].addr = saddr;
- #endif
-
- fn = fib6_lookup_1(root, args);
-@@ -739,19 +789,25 @@
- {
- struct rt6_info *rt = NULL;
- struct fib6_node *fn;
--
-- fn = fib6_locate_1(root, daddr, dst_len,
-- (u8*) &rt->rt6i_dst - (u8*) rt);
--
- #ifdef CONFIG_IPV6_SUBTREES
-- if (src_len) {
-- BUG_TRAP(saddr!=NULL);
-- if (fn == NULL)
-- fn = fn->subtree;
-+ struct in6_addr saddr_buf;
-+
-+ if (saddr == NULL) {
-+ memset(&saddr_buf, 0, sizeof(struct in6_addr));
-+ saddr = &saddr_buf;
-+ }
-+ fn = fib6_locate_1(root, saddr, src_len,
-+ (u8*) &rt->rt6i_src - (u8*) rt);
-+ if (dst_len) {
- if (fn)
-- fn = fib6_locate_1(fn, saddr, src_len,
-- (u8*) &rt->rt6i_src - (u8*) rt);
-+ fn = fib6_locate_1(fn->subtree, daddr, dst_len,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
-+ else
-+ return NULL;
- }
-+#else
-+ fn = fib6_locate_1(root, daddr, dst_len,
-+ (u8*) &rt->rt6i_dst - (u8*) rt);
- #endif
-
- if (fn && fn->fn_flags&RTN_RTINFO)
-@@ -939,7 +995,7 @@
- }
- fn = fn->parent;
- }
-- /* No more references are possiible at this point. */
-+ /* No more references are possible at this point. */
- if (atomic_read(&rt->rt6i_ref) != 1) BUG();
- }
-
---- linux-2.4.27/net/ipv6/ip6_input.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/ip6_input.c
-@@ -40,13 +40,42 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
-
-+static inline int ip6_proxy_chk(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *hdr = skb->nh.ipv6h;
-+
-+ if (ipv6_addr_type(&hdr->daddr)&IPV6_ADDR_UNICAST &&
-+ pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
-+ u8 nexthdr = hdr->nexthdr;
-+ int offset;
-+ struct icmp6hdr msg;
-
-+ if (ipv6_ext_hdr(nexthdr)) {
-+ offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr,
-+ skb->len - sizeof(*hdr));
-+ if (offset < 0)
-+ return 0;
-+ } else
-+ offset = sizeof(*hdr);
-+
-+ /* capture unicast NUD probes on behalf of the proxied node */
-
-+ if (nexthdr == IPPROTO_ICMPV6 &&
-+ !skb_copy_bits(skb, offset, &msg, sizeof(msg)) &&
-+ msg.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
- static inline int ip6_rcv_finish( struct sk_buff *skb)
- {
-- if (skb->dst == NULL)
-- ip6_route_input(skb);
--
-+ if (skb->dst == NULL) {
-+ if (ip6_proxy_chk(skb))
-+ return ip6_input(skb);
-+ ip6_route_input(skb);
-+ }
- return skb->dst->input(skb);
- }
-
---- linux-2.4.27/net/ipv6/ip6_output.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/ip6_output.c
-@@ -50,6 +50,8 @@
- #include <net/rawv6.h>
- #include <net/icmp.h>
-
-+#include <net/mipglue.h>
-+
- static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
- {
- static u32 ipv6_fragmentation_id = 1;
-@@ -194,7 +196,14 @@
- u8 proto = fl->proto;
- int seg_len = skb->len;
- int hlimit;
-+ int retval;
-+ struct ipv6_txoptions *orig_opt = opt;
-+
-+ opt = ip6_add_mipv6_txoptions(sk, skb, orig_opt, fl, &dst);
-
-+ if(orig_opt && !opt)
-+ return -ENOMEM;
-+
- if (opt) {
- int head_room;
-
-@@ -209,8 +218,11 @@
- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
- kfree_skb(skb);
- skb = skb2;
-- if (skb == NULL)
-+ if (skb == NULL) {
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return -ENOBUFS;
-+ }
- if (sk)
- skb_set_owner_w(skb, sk);
- }
-@@ -242,7 +254,10 @@
-
- if (skb->len <= dst->pmtu) {
- IP6_INC_STATS(Ip6OutRequests);
-- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
-+ ip6_mark_mipv6_packet(opt, skb);
-+ retval = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+ return retval;
- }
-
- if (net_ratelimit())
-@@ -250,6 +265,9 @@
- skb->dev = dst->dev;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
- kfree_skb(skb);
-+
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return -EMSGSIZE;
- }
-
-@@ -473,6 +491,7 @@
-
- IP6_INC_STATS(Ip6FragCreates);
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, skb);
- err = NF_HOOK(PF_INET6,NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
- if (err) {
- kfree_skb(last_skb);
-@@ -499,6 +518,7 @@
- IP6_INC_STATS(Ip6FragCreates);
- IP6_INC_STATS(Ip6FragOKs);
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, last_skb);
- return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, last_skb, NULL,dst->dev, ip6_maybe_reroute);
- }
-
-@@ -509,26 +529,43 @@
- struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
- struct in6_addr *final_dst = NULL;
- struct dst_entry *dst;
-+ struct rt6_info *rt;
- int err = 0;
- unsigned int pktlength, jumbolen, mtu;
- struct in6_addr saddr;
-+ struct ipv6_txoptions *orig_opt = opt;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ struct dst_entry *org_dst;
-+#endif
-+
-+ opt = ip6_add_mipv6_txoptions(sk, NULL, orig_opt, fl, NULL);
-+
-+ if(orig_opt && !opt)
-+ return -ENOMEM;
-
- if (opt && opt->srcrt) {
- struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
- final_dst = fl->fl6_dst;
- fl->fl6_dst = rt0->addr;
-- }
-+ } else if (opt && opt->srcrt2) {
-+ struct rt2_hdr *rt2 = (struct rt2_hdr *) opt->srcrt2;
-+ final_dst = fl->fl6_dst;
-+ fl->fl6_dst = &rt2->addr;
-+ }
-
- if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr))
- fl->oif = np->mcast_oif;
-
- dst = __sk_dst_check(sk, np->dst_cookie);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ org_dst = dst;
-+#endif
- if (dst) {
-- struct rt6_info *rt = (struct rt6_info*)dst;
-+ rt = (struct rt6_info*)dst;
-
- /* Yes, checking route validity in not connected
- case is not very simple. Take into account,
-- that we do not support routing by source, TOS,
-+ that we do not support routing by TOS,
- and MSG_DONTROUTE --ANK (980726)
-
- 1. If route was host route, check that
-@@ -548,6 +585,13 @@
- ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr))
- && (np->daddr_cache == NULL ||
- ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache)))
-+#ifdef CONFIG_IPV6_SUBTREES
-+ || (fl->fl6_src != NULL
-+ && (rt->rt6i_src.plen != 128 ||
-+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr))
-+ && (np->saddr_cache == NULL ||
-+ ipv6_addr_cmp(fl->fl6_src, np->saddr_cache)))
-+#endif
- || (fl->oif && fl->oif != dst->dev->ifindex)) {
- dst = NULL;
- } else
-@@ -560,21 +604,42 @@
- if (dst->error) {
- IP6_INC_STATS(Ip6OutNoRoutes);
- dst_release(dst);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
- return -ENETUNREACH;
- }
-
- if (fl->fl6_src == NULL) {
- err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr);
--
- if (err) {
- #if IP6_DEBUG >= 2
- printk(KERN_DEBUG "ip6_build_xmit: "
- "no available source address\n");
- #endif
-+
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (dst != org_dst) {
-+ dst_release(dst);
-+ dst = org_dst;
-+ }
-+#endif
- goto out;
- }
- fl->fl6_src = &saddr;
- }
-+#ifdef CONFIG_IPV6_SUBTREES
-+ rt = (struct rt6_info*)dst;
-+ if (dst != org_dst || rt->rt6i_src.plen != 128 ||
-+ ipv6_addr_cmp(fl->fl6_src, &rt->rt6i_src.addr)) {
-+ dst_release(dst);
-+ dst = ip6_route_output(sk, fl);
-+ if (dst->error) {
-+ IP6_INC_STATS(Ip6OutNoRoutes);
-+ dst_release(dst);
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+ return -ENETUNREACH;
-+ }
-+ }
-+#endif
- pktlength = length;
-
- if (hlimit < 0) {
-@@ -667,6 +732,7 @@
-
- if (!err) {
- IP6_INC_STATS(Ip6OutRequests);
-+ ip6_mark_mipv6_packet(opt, skb);
- err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
- } else {
- err = -EFAULT;
-@@ -688,9 +754,14 @@
- * cleanup
- */
- out:
-- ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL);
-+ ip6_dst_store(sk, dst,
-+ fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL,
-+ fl->nl_u.ip6_u.saddr == &np->saddr ? &np->saddr : NULL);
- if (err > 0)
- err = np->recverr ? net_xmit_errno(err) : 0;
-+
-+ ip6_free_mipv6_txoptions(opt, orig_opt);
-+
- return err;
- }
-
-@@ -769,6 +840,15 @@
- return -ETIMEDOUT;
- }
-
-+ /* The proxying router can't forward traffic sent to a link-local
-+ address, so signal the sender and discard the packet. This
-+ behavior is required by the MIPv6 specification. */
-+
-+ if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL &&
-+ skb->dev && pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
-+ dst_link_failure(skb);
-+ goto drop;
-+ }
- /* IPv6 specs say nothing about it, but it is clear that we cannot
- send redirects to source routed frames.
- */
---- linux-2.4.27/net/ipv6/ipv6_syms.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/ipv6_syms.c
-@@ -6,6 +6,8 @@
- #include <net/ipv6.h>
- #include <net/addrconf.h>
- #include <net/ip6_route.h>
-+#include <net/ndisc.h>
-+#include <net/mipglue.h>
-
- EXPORT_SYMBOL(ipv6_addr_type);
- EXPORT_SYMBOL(icmpv6_send);
-@@ -35,3 +37,47 @@
- EXPORT_SYMBOL(in6_dev_finish_destroy);
- EXPORT_SYMBOL(ipv6_skip_exthdr);
-
-+#if defined(CONFIG_IPV6_TUNNEL_MODULE) || defined(CONFIG_IPV6_MOBILITY_MODULE)
-+EXPORT_SYMBOL(ip6_build_xmit);
-+EXPORT_SYMBOL(rt6_lookup);
-+EXPORT_SYMBOL(ipv6_ext_hdr);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MODULE
-+EXPORT_SYMBOL(mipv6_functions);
-+EXPORT_SYMBOL(mipv6_invalidate_calls);
-+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE)
-+EXPORT_SYMBOL(ip6_route_add);
-+EXPORT_SYMBOL(ip6_route_del);
-+EXPORT_SYMBOL(ipv6_get_lladdr);
-+EXPORT_SYMBOL(ipv6_get_ifaddr);
-+EXPORT_SYMBOL(nd_tbl);
-+EXPORT_SYMBOL(ndisc_send_ns);
-+EXPORT_SYMBOL(ndisc_send_na);
-+EXPORT_SYMBOL(ndisc_next_option);
-+EXPORT_SYMBOL(inet6_ifa_finish_destroy);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE
-+EXPORT_SYMBOL(ipv6_dev_ac_dec);
-+EXPORT_SYMBOL(ipv6_dev_ac_inc);
-+EXPORT_SYMBOL(ipv6_dev_mc_dec);
-+EXPORT_SYMBOL(ipv6_dev_mc_inc);
-+EXPORT_SYMBOL(ip6_forward);
-+EXPORT_SYMBOL(ip6_input);
-+EXPORT_SYMBOL(ipv6_chk_acast_addr);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE
-+#endif
-+EXPORT_SYMBOL(addrconf_add_ifaddr);
-+EXPORT_SYMBOL(addrconf_del_ifaddr);
-+EXPORT_SYMBOL(addrconf_dad_start);
-+EXPORT_SYMBOL(ip6_del_rt);
-+EXPORT_SYMBOL(ip6_routing_table);
-+EXPORT_SYMBOL(rt6_get_dflt_router);
-+EXPORT_SYMBOL(rt6_purge_dflt_routers);
-+EXPORT_SYMBOL(rt6_lock);
-+EXPORT_SYMBOL(ndisc_send_rs);
-+EXPORT_SYMBOL(fib6_clean_tree);
-+EXPORT_SYMBOL(ipv6_del_addr);
-+EXPORT_SYMBOL(ipv6_generate_eui64);
-+EXPORT_SYMBOL(ipv6_inherit_eui64);
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/ipv6_tunnel.c
-@@ -0,0 +1,1604 @@
-+/*
-+ * IPv6 over IPv6 tunnel device
-+ * Linux INET6 implementation
-+ *
-+ * Authors:
-+ * Ville Nuorvala <vnuorval@tcs.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * Based on:
-+ * linux/net/ipv6/sit.c
-+ *
-+ * RFC 2473
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/errno.h>
-+#include <linux/types.h>
-+#include <linux/socket.h>
-+#include <linux/sockios.h>
-+#include <linux/if.h>
-+#include <linux/in.h>
-+#include <linux/ip.h>
-+#include <linux/if_tunnel.h>
-+#include <linux/net.h>
-+#include <linux/in6.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/icmpv6.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/tqueue.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/atomic.h>
-+
-+#include <net/sock.h>
-+#include <net/ipv6.h>
-+#include <net/protocol.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/ipv6_tunnel.h>
-+
-+MODULE_AUTHOR("Ville Nuorvala");
-+MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
-+MODULE_LICENSE("GPL");
-+
-+#define IPV6_TLV_TEL_DST_SIZE 8
-+
-+#ifdef IP6_TNL_DEBUG
-+#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__)
-+#else
-+#define IP6_TNL_TRACE(x...) do {;} while(0)
-+#endif
-+
-+#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
-+
-+#define HASH_SIZE 32
-+
-+#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \
-+ (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \
-+ (HASH_SIZE - 1))
-+
-+static int ip6ip6_fb_tnl_dev_init(struct net_device *dev);
-+static int ip6ip6_tnl_dev_init(struct net_device *dev);
-+
-+/* the IPv6 IPv6 tunnel fallback device */
-+static struct net_device ip6ip6_fb_tnl_dev = {
-+ name: "ip6tnl0",
-+ init: ip6ip6_fb_tnl_dev_init
-+};
-+
-+/* the IPv6 IPv6 fallback tunnel */
-+static struct ip6_tnl ip6ip6_fb_tnl = {
-+ dev: &ip6ip6_fb_tnl_dev,
-+ parms:{name: "ip6tnl0", proto: IPPROTO_IPV6}
-+};
-+
-+/* lists for storing tunnels in use */
-+static struct ip6_tnl *tnls_r_l[HASH_SIZE];
-+static struct ip6_tnl *tnls_wc[1];
-+static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l };
-+
-+/* list for unused cached kernel tunnels */
-+static struct ip6_tnl *tnls_kernel[1];
-+/* maximum number of cached kernel tunnels */
-+static unsigned int max_kdev_count = 0;
-+/* minimum number of cached kernel tunnels */
-+static unsigned int min_kdev_count = 0;
-+/* current number of cached kernel tunnels */
-+static unsigned int kdev_count = 0;
-+
-+/* lists for tunnel hook functions */
-+static struct list_head hooks[IP6_TNL_MAXHOOKS];
-+
-+/* locks for the different lists */
-+static rwlock_t ip6ip6_lock = RW_LOCK_UNLOCKED;
-+static rwlock_t ip6ip6_kernel_lock = RW_LOCK_UNLOCKED;
-+static rwlock_t ip6ip6_hook_lock = RW_LOCK_UNLOCKED;
-+
-+/* flag indicating if the module is being removed */
-+static int shutdown = 0;
-+
-+/**
-+ * ip6ip6_tnl_lookup - fetch tunnel matching the end-point addresses
-+ * @remote: the address of the tunnel exit-point
-+ * @local: the address of the tunnel entry-point
-+ *
-+ * Return:
-+ * tunnel matching given end-points if found,
-+ * else fallback tunnel if its device is up,
-+ * else %NULL
-+ **/
-+
-+struct ip6_tnl *
-+ip6ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
-+{
-+ unsigned h0 = HASH(remote);
-+ unsigned h1 = HASH(local);
-+ struct ip6_tnl *t;
-+
-+ for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) {
-+ if (!ipv6_addr_cmp(local, &t->parms.laddr) &&
-+ !ipv6_addr_cmp(remote, &t->parms.raddr) &&
-+ (t->dev->flags & IFF_UP))
-+ return t;
-+ }
-+ if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
-+ return t;
-+
-+ return NULL;
-+}
-+
-+/**
-+ * ip6ip6_bucket - get head of list matching given tunnel parameters
-+ * @p: parameters containing tunnel end-points
-+ *
-+ * Description:
-+ * ip6ip6_bucket() returns the head of the list matching the
-+ * &struct in6_addr entries laddr and raddr in @p.
-+ *
-+ * Return: head of IPv6 tunnel list
-+ **/
-+
-+static struct ip6_tnl **
-+ip6ip6_bucket(struct ip6_tnl_parm *p)
-+{
-+ struct in6_addr *remote = &p->raddr;
-+ struct in6_addr *local = &p->laddr;
-+ unsigned h = 0;
-+ int prio = 0;
-+
-+ if (!ipv6_addr_any(remote) || !ipv6_addr_any(local)) {
-+ prio = 1;
-+ h = HASH(remote) ^ HASH(local);
-+ }
-+ return &tnls[prio][h];
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_link - add new kernel tunnel to cache
-+ * @t: kernel tunnel
-+ *
-+ * Note:
-+ * %IP6_TNL_F_KERNEL_DEV is assumed to be raised in t->parms.flags.
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+static inline void
-+ip6ip6_kernel_tnl_link(struct ip6_tnl *t)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ t->next = tnls_kernel[0];
-+ tnls_kernel[0] = t;
-+ kdev_count++;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_unlink - remove first kernel tunnel from cache
-+ *
-+ * Return: first free kernel tunnel
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+static inline struct ip6_tnl *
-+ip6ip6_kernel_tnl_unlink(void)
-+{
-+ struct ip6_tnl *t;
-+
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ if ((t = tnls_kernel[0]) != NULL) {
-+ tnls_kernel[0] = t->next;
-+ kdev_count--;
-+ }
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ return t;
-+}
-+
-+/**
-+ * ip6ip6_tnl_link - add tunnel to hash table
-+ * @t: tunnel to be added
-+ **/
-+
-+static void
-+ip6ip6_tnl_link(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl **tp = ip6ip6_bucket(&t->parms);
-+
-+ write_lock_bh(&ip6ip6_lock);
-+ t->next = *tp;
-+ *tp = t;
-+ write_unlock_bh(&ip6ip6_lock);
-+}
-+
-+/**
-+ * ip6ip6_tnl_unlink - remove tunnel from hash table
-+ * @t: tunnel to be removed
-+ **/
-+
-+static void
-+ip6ip6_tnl_unlink(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl **tp;
-+
-+ write_lock_bh(&ip6ip6_lock);
-+ for (tp = ip6ip6_bucket(&t->parms); *tp; tp = &(*tp)->next) {
-+ if (t == *tp) {
-+ *tp = t->next;
-+ break;
-+ }
-+ }
-+ write_unlock_bh(&ip6ip6_lock);
-+}
-+
-+/**
-+ * ip6ip6_tnl_create() - create a new tunnel
-+ * @p: tunnel parameters
-+ * @pt: pointer to new tunnel
-+ *
-+ * Description:
-+ * Create tunnel matching given parameters. New kernel managed devices are
-+ * not put in the normal hash structure, but are instead cached for later
-+ * use.
-+ *
-+ * Return:
-+ * 0 on success
-+ **/
-+
-+
-+static int __ip6ip6_tnl_create(struct ip6_tnl_parm *p,
-+ struct ip6_tnl **pt,
-+ int kernel_list)
-+{
-+ struct net_device *dev;
-+ int err = -ENOBUFS;
-+ struct ip6_tnl *t;
-+
-+ MOD_INC_USE_COUNT;
-+ dev = kmalloc(sizeof (*dev) + sizeof (*t), GFP_KERNEL);
-+ if (!dev) {
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+ }
-+ memset(dev, 0, sizeof (*dev) + sizeof (*t));
-+ dev->priv = (void *) (dev + 1);
-+ t = (struct ip6_tnl *) dev->priv;
-+ t->dev = dev;
-+ dev->init = ip6ip6_tnl_dev_init;
-+ dev->features |= NETIF_F_DYNALLOC;
-+ if (kernel_list) {
-+ memcpy(t->parms.name, p->name, IFNAMSIZ - 1);
-+ t->parms.proto = IPPROTO_IPV6;
-+ t->parms.flags = IP6_TNL_F_KERNEL_DEV;
-+ } else {
-+ memcpy(&t->parms, p, sizeof (*p));
-+ }
-+ t->parms.name[IFNAMSIZ - 1] = '\0';
-+ strcpy(dev->name, t->parms.name);
-+ if (!dev->name[0]) {
-+ int i;
-+ for (i = 0; i < IP6_TNL_MAX; i++) {
-+ sprintf(dev->name, "ip6tnl%d", i);
-+ if (__dev_get_by_name(dev->name) == NULL)
-+ break;
-+ }
-+
-+ if (i == IP6_TNL_MAX) {
-+ goto failed;
-+ }
-+ memcpy(t->parms.name, dev->name, IFNAMSIZ);
-+ }
-+ if ((err = register_netdevice(dev)) < 0) {
-+ goto failed;
-+ }
-+ dev_hold(dev);
-+ if (kernel_list) {
-+ ip6ip6_kernel_tnl_link(t);
-+ } else {
-+ ip6ip6_tnl_link(t);
-+ }
-+ *pt = t;
-+ return 0;
-+failed:
-+ kfree(dev);
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+
-+int ip6ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
-+{
-+ return __ip6ip6_tnl_create(p, pt, 0);
-+}
-+
-+
-+static void manage_kernel_tnls(void *foo);
-+
-+static struct tq_struct manager_task = {
-+ routine:manage_kernel_tnls,
-+ data:NULL
-+};
-+
-+/**
-+ * manage_kernel_tnls() - create and destroy kernel tunnels
-+ *
-+ * Description:
-+ * manage_kernel_tnls() creates new kernel devices if there
-+ * are less than $min_kdev_count of them and deletes old ones if
-+ * there are less than $max_kdev_count of them in the cache
-+ *
-+ * Note:
-+ * Schedules itself to be run later in process context if called from
-+ * interrupt. Therefore only works synchronously when called from process
-+ * context.
-+ **/
-+
-+static void
-+manage_kernel_tnls(void *foo)
-+{
-+ struct ip6_tnl *t = NULL;
-+ struct ip6_tnl_parm parm;
-+
-+ /* We can't do this processing in interrupt
-+ context so schedule it for later */
-+ if (in_interrupt()) {
-+ read_lock(&ip6ip6_kernel_lock);
-+ if (!shutdown &&
-+ (kdev_count < min_kdev_count ||
-+ kdev_count > max_kdev_count)) {
-+ schedule_task(&manager_task);
-+ }
-+ read_unlock(&ip6ip6_kernel_lock);
-+ return;
-+ }
-+
-+ rtnl_lock();
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ memset(&parm, 0, sizeof (parm));
-+ parm.flags = IP6_TNL_F_KERNEL_DEV;
-+ /* Create tunnels until there are at least min_kdev_count */
-+ while (kdev_count < min_kdev_count) {
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+ if (!__ip6ip6_tnl_create(&parm, &t, 1)) {
-+ dev_open(t->dev);
-+ } else {
-+ goto err;
-+ }
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ }
-+
-+ /* Destroy tunnels until there are at most max_kdev_count */
-+ while (kdev_count > max_kdev_count) {
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+ if ((t = ip6ip6_kernel_tnl_unlink()) != NULL) {
-+ unregister_netdevice(t->dev);
-+ } else {
-+ goto err;
-+ }
-+ read_lock_bh(&ip6ip6_kernel_lock);
-+ }
-+ read_unlock_bh(&ip6ip6_kernel_lock);
-+err:
-+ rtnl_unlock();
-+}
-+
-+/**
-+ * ip6ip6_tnl_inc_max_kdev_count() - increase max kernel dev cache size
-+ * @n: size increase
-+ * Description:
-+ * Increase the upper limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_inc_max_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ max_kdev_count += n;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return max_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dec_max_kdev_count() - decrease max kernel dev cache size
-+ * @n: size decrement
-+ * Description:
-+ * Decrease the upper limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_dec_max_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ max_kdev_count -= min(max_kdev_count, n);
-+ if (max_kdev_count < min_kdev_count)
-+ min_kdev_count = max_kdev_count;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return max_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_inc_min_kdev_count() - increase min kernel dev cache size
-+ * @n: size increase
-+ * Description:
-+ * Increase the lower limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_inc_min_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ min_kdev_count += n;
-+ if (min_kdev_count > max_kdev_count)
-+ max_kdev_count = min_kdev_count;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return min_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dec_min_kdev_count() - decrease min kernel dev cache size
-+ * @n: size decrement
-+ * Description:
-+ * Decrease the lower limit for the number of kernel devices allowed in the
-+ * cache at any on time.
-+ **/
-+
-+unsigned int
-+ip6ip6_tnl_dec_min_kdev_count(unsigned int n)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ min_kdev_count -= min(min_kdev_count, n);
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ manage_kernel_tnls(NULL);
-+ return min_kdev_count;
-+}
-+
-+/**
-+ * ip6ip6_tnl_locate - find or create tunnel matching given parameters
-+ * @p: tunnel parameters
-+ * @create: != 0 if allowed to create new tunnel if no match found
-+ *
-+ * Description:
-+ * ip6ip6_tnl_locate() first tries to locate an existing tunnel
-+ * based on @parms. If this is unsuccessful, but @create is set a new
-+ * tunnel device is created and registered for use.
-+ *
-+ * Return:
-+ * 0 if tunnel located or created,
-+ * -EINVAL if parameters incorrect,
-+ * -ENODEV if no matching tunnel available
-+ **/
-+
-+int ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create)
-+{
-+ struct in6_addr *remote = &p->raddr;
-+ struct in6_addr *local = &p->laddr;
-+ struct ip6_tnl *t;
-+
-+ if (p->proto != IPPROTO_IPV6)
-+ return -EINVAL;
-+
-+ for (t = *ip6ip6_bucket(p); t; t = t->next) {
-+ if (!ipv6_addr_cmp(local, &t->parms.laddr) &&
-+ !ipv6_addr_cmp(remote, &t->parms.raddr)) {
-+ *pt = t;
-+ return (create ? -EEXIST : 0);
-+ }
-+ }
-+ return ip6ip6_tnl_create(p, pt);
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_destructor - tunnel device destructor
-+ * @dev: the device to be destroyed
-+ **/
-+
-+static void
-+ip6ip6_tnl_dev_destructor(struct net_device *dev)
-+{
-+ if (dev != &ip6ip6_fb_tnl_dev) {
-+ MOD_DEC_USE_COUNT;
-+ }
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_uninit - tunnel device uninitializer
-+ * @dev: the device to be destroyed
-+ *
-+ * Description:
-+ * ip6ip6_tnl_dev_uninit() removes tunnel from its list
-+ **/
-+
-+static void
-+ip6ip6_tnl_dev_uninit(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ write_lock_bh(&ip6ip6_lock);
-+ tnls_wc[0] = NULL;
-+ write_unlock_bh(&ip6ip6_lock);
-+ } else {
-+ ip6ip6_tnl_unlink(t);
-+ }
-+ sock_release(t->sock);
-+ dev_put(dev);
-+}
-+
-+/**
-+ * parse_tvl_tnl_enc_lim - handle encapsulation limit option
-+ * @skb: received socket buffer
-+ *
-+ * Return:
-+ * 0 if none was found,
-+ * else index to encapsulation limit
-+ **/
-+
-+static __u16
-+parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
-+{
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) raw;
-+ __u8 nexthdr = ipv6h->nexthdr;
-+ __u16 off = sizeof (*ipv6h);
-+
-+ while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-+ __u16 optlen = 0;
-+ struct ipv6_opt_hdr *hdr;
-+ if (raw + off + sizeof (*hdr) > skb->data &&
-+ !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
-+ break;
-+
-+ hdr = (struct ipv6_opt_hdr *) (raw + off);
-+ if (nexthdr == NEXTHDR_FRAGMENT) {
-+ struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
-+ if (frag_hdr->frag_off)
-+ break;
-+ optlen = 8;
-+ } else if (nexthdr == NEXTHDR_AUTH) {
-+ optlen = (hdr->hdrlen + 2) << 2;
-+ } else {
-+ optlen = ipv6_optlen(hdr);
-+ }
-+ if (nexthdr == NEXTHDR_DEST) {
-+ __u16 i = off + 2;
-+ while (1) {
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+
-+ /* No more room for encapsulation limit */
-+ if (i + sizeof (*tel) > off + optlen)
-+ break;
-+
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
-+ /* return index of option if found and valid */
-+ if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
-+ tel->length == 1)
-+ return i;
-+ /* else jump to next option */
-+ if (tel->type)
-+ i += tel->length + 2;
-+ else
-+ i++;
-+ }
-+ }
-+ nexthdr = hdr->nexthdr;
-+ off += optlen;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_err - tunnel error handler
-+ *
-+ * Description:
-+ * ip6ip6_err() should handle errors in the tunnel according
-+ * to the specifications in RFC 2473.
-+ **/
-+
-+void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-+ int type, int code, int offset, __u32 info)
-+{
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
-+ struct ip6_tnl *t;
-+ int rel_msg = 0;
-+ int rel_type = ICMPV6_DEST_UNREACH;
-+ int rel_code = ICMPV6_ADDR_UNREACH;
-+ __u32 rel_info = 0;
-+ __u16 len;
-+
-+ /* If the packet doesn't contain the original IPv6 header we are
-+ in trouble since we might need the source address for furter
-+ processing of the error. */
-+
-+ read_lock(&ip6ip6_lock);
-+ if ((t = ip6ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
-+ goto out;
-+
-+ switch (type) {
-+ __u32 teli;
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ __u32 mtu;
-+ case ICMPV6_DEST_UNREACH:
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Path to destination invalid "
-+ "or inactive!\n", t->parms.name);
-+ rel_msg = 1;
-+ break;
-+ case ICMPV6_TIME_EXCEED:
-+ if (code == ICMPV6_EXC_HOPLIMIT) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Too small hop limit or "
-+ "routing loop in tunnel!\n",
-+ t->parms.name);
-+ rel_msg = 1;
-+ }
-+ break;
-+ case ICMPV6_PARAMPROB:
-+ /* ignore if parameter problem not caused by a tunnel
-+ encapsulation limit sub-option */
-+ if (code != ICMPV6_HDR_FIELD) {
-+ break;
-+ }
-+ teli = parse_tlv_tnl_enc_lim(skb, skb->data);
-+
-+ if (teli && teli == ntohl(info) - 2) {
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
-+ if (tel->encap_limit == 0) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Too small encapsulation "
-+ "limit or routing loop in "
-+ "tunnel!\n", t->parms.name);
-+ rel_msg = 1;
-+ }
-+ }
-+ break;
-+ case ICMPV6_PKT_TOOBIG:
-+ mtu = ntohl(info) - offset;
-+ if (mtu < IPV6_MIN_MTU)
-+ mtu = IPV6_MIN_MTU;
-+ t->dev->mtu = mtu;
-+
-+ if ((len = sizeof (*ipv6h) + ipv6h->payload_len) > mtu) {
-+ rel_type = ICMPV6_PKT_TOOBIG;
-+ rel_code = 0;
-+ rel_info = mtu;
-+ rel_msg = 1;
-+ }
-+ break;
-+ }
-+ if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) {
-+ struct rt6_info *rt;
-+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (!skb2)
-+ goto out;
-+
-+ dst_release(skb2->dst);
-+ skb2->dst = NULL;
-+ skb_pull(skb2, offset);
-+ skb2->nh.raw = skb2->data;
-+
-+ /* Try to guess incoming interface */
-+ rt = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0);
-+
-+ if (rt && rt->rt6i_dev)
-+ skb2->dev = rt->rt6i_dev;
-+
-+ icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev);
-+
-+ if (rt)
-+ dst_release(&rt->u.dst);
-+
-+ kfree_skb(skb2);
-+ }
-+out:
-+ read_unlock(&ip6ip6_lock);
-+}
-+
-+/**
-+ * call_hooks - call ipv6 tunnel hooks
-+ * @hooknum: hook number, either %IP6_TNL_PRE_ENCAP, or
-+ * %IP6_TNL_PRE_DECAP
-+ * @t: the current tunnel
-+ * @skb: the tunneled packet
-+ *
-+ * Description:
-+ * Pass packet to all the hook functions until %IP6_TNL_DROP
-+ *
-+ * Return:
-+ * %IP6_TNL_ACCEPT or %IP6_TNL_DROP
-+ **/
-+
-+static inline int
-+call_hooks(unsigned int hooknum, struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ struct ip6_tnl_hook_ops *h;
-+ int accept = IP6_TNL_ACCEPT;
-+
-+ if (hooknum < IP6_TNL_MAXHOOKS) {
-+ struct list_head *i;
-+ read_lock(&ip6ip6_hook_lock);
-+ for (i = hooks[hooknum].next; i != &hooks[hooknum]; i = i->next) {
-+ h = (struct ip6_tnl_hook_ops *) i;
-+
-+ if (h->hook) {
-+ accept = h->hook(t, skb);
-+
-+ if (accept != IP6_TNL_ACCEPT)
-+ break;
-+ }
-+ }
-+ read_unlock(&ip6ip6_hook_lock);
-+ }
-+ return accept;
-+}
-+
-+/**
-+ * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
-+ * @skb: received socket buffer
-+ *
-+ * Return: 0
-+ **/
-+
-+int ip6ip6_rcv(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *ipv6h;
-+ struct ip6_tnl *t;
-+
-+ if (!pskb_may_pull(skb, sizeof (*ipv6h)))
-+ goto discard;
-+
-+ ipv6h = skb->nh.ipv6h;
-+
-+ read_lock(&ip6ip6_lock);
-+
-+ if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
-+ if (!(t->parms.flags & IP6_TNL_F_CAP_RCV) ||
-+ call_hooks(IP6_TNL_PRE_DECAP, t, skb) != IP6_TNL_ACCEPT) {
-+ t->stat.rx_dropped++;
-+ read_unlock(&ip6ip6_lock);
-+ goto discard;
-+ }
-+ skb->mac.raw = skb->nh.raw;
-+ skb->nh.raw = skb->data;
-+ skb->protocol = htons(ETH_P_IPV6);
-+ skb->pkt_type = PACKET_HOST;
-+ memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
-+ skb->dev = t->dev;
-+ dst_release(skb->dst);
-+ skb->dst = NULL;
-+ t->stat.rx_packets++;
-+ t->stat.rx_bytes += skb->len;
-+ netif_rx(skb);
-+ read_unlock(&ip6ip6_lock);
-+ return 0;
-+ }
-+ read_unlock(&ip6ip6_lock);
-+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-+discard:
-+ kfree_skb(skb);
-+ return 0;
-+}
-+
-+static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
-+{
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ struct ipv6_txoptions *opt;
-+ __u8 *raw;
-+
-+ int opt_len = sizeof(*opt) + IPV6_TLV_TEL_DST_SIZE;
-+
-+ if (!(opt = kmalloc(opt_len, GFP_ATOMIC))) {
-+ return NULL;
-+ }
-+ memset(opt, 0, opt_len);
-+ opt->tot_len = opt_len;
-+ opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1);
-+ opt->opt_nflen = 8;
-+
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1);
-+ tel->type = IPV6_TLV_TNL_ENCAP_LIMIT;
-+ tel->length = 1;
-+ tel->encap_limit = encap_limit;
-+
-+ raw = (__u8 *) opt->dst0opt;
-+ raw[5] = IPV6_TLV_PADN;
-+ raw[6] = 1;
-+
-+ return opt;
-+}
-+
-+static int
-+ip6ip6_getfrag(const void *data, struct in6_addr *addr,
-+ char *buff, unsigned int offset, unsigned int len)
-+{
-+ memcpy(buff, data + offset, len);
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
-+ * @t: the outgoing tunnel device
-+ * @hdr: IPv6 header from the incoming packet
-+ *
-+ * Description:
-+ * Avoid trivial tunneling loop by checking that tunnel exit-point
-+ * doesn't match source of incoming packet.
-+ *
-+ * Return:
-+ * 1 if conflict,
-+ * 0 else
-+ **/
-+
-+static inline int
-+ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
-+{
-+ return !ipv6_addr_cmp(&t->parms.raddr, &hdr->saddr);
-+}
-+
-+/**
-+ * ip6ip6_tnl_xmit - encapsulate packet and send
-+ * @skb: the outgoing socket buffer
-+ * @dev: the outgoing tunnel device
-+ *
-+ * Description:
-+ * Build new header and do some sanity checks on the packet before sending
-+ * it to ip6_build_xmit().
-+ *
-+ * Return:
-+ * 0
-+ **/
-+
-+int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ struct net_device_stats *stats = &t->stat;
-+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
-+ struct ipv6_txoptions *opt = NULL;
-+ int encap_limit = -1;
-+ __u16 offset;
-+ struct flowi fl;
-+ int err = 0;
-+ struct dst_entry *dst;
-+ struct sock *sk = t->sock->sk;
-+ struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
-+ int mtu;
-+
-+ if (t->recursion++) {
-+ stats->collisions++;
-+ goto tx_err;
-+ }
-+ if (skb->protocol != htons(ETH_P_IPV6) ||
-+ !(t->parms.flags & IP6_TNL_F_CAP_XMIT) ||
-+ ip6ip6_tnl_addr_conflict(t, ipv6h)) {
-+ goto tx_err;
-+ }
-+ if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) {
-+ struct ipv6_tlv_tnl_enc_lim *tel;
-+ tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset];
-+ if (tel->encap_limit == 0) {
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, offset + 2, skb->dev);
-+ goto tx_err;
-+ }
-+ encap_limit = tel->encap_limit - 1;
-+ } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
-+ encap_limit = t->parms.encap_limit;
-+ }
-+ if (call_hooks(IP6_TNL_PRE_ENCAP, t, skb) != IP6_TNL_ACCEPT)
-+ goto discard;
-+ memcpy(&fl, &t->fl, sizeof (fl));
-+
-+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
-+ if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
-+ fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK);
-+
-+ if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL)
-+ goto tx_err;
-+
-+ dst = __sk_dst_check(sk, np->dst_cookie);
-+
-+ if (dst) {
-+ if (np->daddr_cache == NULL ||
-+ ipv6_addr_cmp(fl.fl6_dst, np->daddr_cache) ||
-+#ifdef CONFIG_IPV6_SUBTREES
-+ np->saddr_cache == NULL ||
-+ ipv6_addr_cmp(fl.fl6_src, np->saddr_cache) ||
-+#endif
-+ (fl.oif && fl.oif != dst->dev->ifindex)) {
-+ dst = NULL;
-+ } else {
-+ dst_hold(dst);
-+ }
-+ }
-+ if (dst == NULL) {
-+ dst = ip6_route_output(sk, &fl);
-+ if (dst->error) {
-+ stats->tx_carrier_errors++;
-+ dst_link_failure(skb);
-+ goto tx_err_dst_release;
-+ }
-+ /* local routing loop */
-+ if (dst->dev == dev) {
-+ stats->collisions++;
-+ if (net_ratelimit())
-+ printk(KERN_WARNING
-+ "%s: Local routing loop detected!\n",
-+ t->parms.name);
-+ goto tx_err_dst_release;
-+ }
-+ }
-+ mtu = dst->pmtu - sizeof (*ipv6h);
-+ if (opt) {
-+ mtu -= (opt->opt_nflen + opt->opt_flen);
-+ }
-+ if (mtu < IPV6_MIN_MTU)
-+ mtu = IPV6_MIN_MTU;
-+ if (skb->dst && mtu < skb->dst->pmtu) {
-+ struct rt6_info *rt = (struct rt6_info *) skb->dst;
-+ rt->rt6i_flags |= RTF_MODIFIED;
-+ rt->u.dst.pmtu = mtu;
-+ }
-+ if (skb->len > mtu) {
-+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
-+ goto tx_err_dst_release;
-+ }
-+ ip6_dst_store(sk, dst, &np->daddr, &np->saddr);
-+ err = ip6_build_xmit(sk, ip6ip6_getfrag, (void *) skb->nh.raw,
-+ &fl, skb->len, opt, t->parms.hop_limit,
-+ MSG_DONTWAIT);
-+
-+ if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) {
-+ stats->tx_bytes += skb->len;
-+ stats->tx_packets++;
-+ } else {
-+ stats->tx_errors++;
-+ stats->tx_aborted_errors++;
-+ }
-+ if (opt)
-+ kfree(opt);
-+ kfree_skb(skb);
-+ t->recursion--;
-+ return 0;
-+tx_err_dst_release:
-+ dst_release(dst);
-+ if (opt)
-+ kfree(opt);
-+tx_err:
-+ stats->tx_errors++;
-+discard:
-+ stats->tx_dropped++;
-+ kfree_skb(skb);
-+ t->recursion--;
-+ return 0;
-+}
-+
-+static void ip6_tnl_set_cap(struct ip6_tnl *t)
-+{
-+ struct ip6_tnl_parm *p = &t->parms;
-+ struct in6_addr *laddr = &p->laddr;
-+ struct in6_addr *raddr = &p->raddr;
-+ int ltype = ipv6_addr_type(laddr);
-+ int rtype = ipv6_addr_type(raddr);
-+
-+ p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV);
-+
-+ if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY &&
-+ ((ltype|rtype) &
-+ (IPV6_ADDR_UNICAST|
-+ IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL|
-+ IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) {
-+ struct net_device *ldev = NULL;
-+ int l_ok = 1;
-+ int r_ok = 1;
-+
-+ if (p->link)
-+ ldev = dev_get_by_index(p->link);
-+
-+ if ((ltype&IPV6_ADDR_UNICAST) && !ipv6_chk_addr(laddr, ldev))
-+ l_ok = 0;
-+
-+ if ((rtype&IPV6_ADDR_UNICAST) && ipv6_chk_addr(raddr, NULL))
-+ r_ok = 0;
-+
-+ if (l_ok && r_ok) {
-+ if (ltype&IPV6_ADDR_UNICAST)
-+ p->flags |= IP6_TNL_F_CAP_XMIT;
-+ if (rtype&IPV6_ADDR_UNICAST)
-+ p->flags |= IP6_TNL_F_CAP_RCV;
-+ }
-+ if (ldev)
-+ dev_put(ldev);
-+ }
-+}
-+
-+static void ip6ip6_tnl_link_config(struct ip6_tnl *t)
-+{
-+ struct net_device *dev = t->dev;
-+ struct ip6_tnl_parm *p = &t->parms;
-+ struct flowi *fl = &t->fl;
-+
-+ /* Set up flowi template */
-+ fl->fl6_src = &p->laddr;
-+ fl->fl6_dst = &p->raddr;
-+ fl->oif = p->link;
-+ fl->fl6_flowlabel = 0;
-+
-+ if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
-+ fl->fl6_flowlabel |= IPV6_TCLASS_MASK & htonl(p->flowinfo);
-+ if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL))
-+ fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & htonl(p->flowinfo);
-+
-+ ip6_tnl_set_cap(t);
-+
-+ if (p->flags&IP6_TNL_F_CAP_XMIT && p->flags&IP6_TNL_F_CAP_RCV)
-+ dev->flags |= IFF_POINTOPOINT;
-+ else
-+ dev->flags &= ~IFF_POINTOPOINT;
-+
-+ if (p->flags & IP6_TNL_F_CAP_XMIT) {
-+ struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
-+ p->link, 0);
-+
-+ if (rt == NULL)
-+ return;
-+
-+ if (rt->rt6i_dev) {
-+ dev->iflink = rt->rt6i_dev->ifindex;
-+
-+ dev->hard_header_len = rt->rt6i_dev->hard_header_len +
-+ sizeof (struct ipv6hdr);
-+
-+ dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr);
-+
-+ if (dev->mtu < IPV6_MIN_MTU)
-+ dev->mtu = IPV6_MIN_MTU;
-+ }
-+ dst_release(&rt->u.dst);
-+ }
-+}
-+
-+/**
-+ * __ip6ip6_tnl_change - update the tunnel parameters
-+ * @t: tunnel to be changed
-+ * @p: tunnel configuration parameters
-+ *
-+ * Description:
-+ * __ip6ip6_tnl_change() updates the tunnel parameters
-+ **/
-+
-+static void
-+__ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
-+{
-+ ipv6_addr_copy(&t->parms.laddr, &p->laddr);
-+ ipv6_addr_copy(&t->parms.raddr, &p->raddr);
-+ t->parms.flags = p->flags;
-+ t->parms.hop_limit = p->hop_limit;
-+ t->parms.encap_limit = p->encap_limit;
-+ t->parms.flowinfo = p->flowinfo;
-+ ip6ip6_tnl_link_config(t);
-+}
-+
-+void ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
-+{
-+ ip6ip6_tnl_unlink(t);
-+ __ip6ip6_tnl_change(t, p);
-+ ip6ip6_tnl_link(t);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_add - configure and add kernel tunnel to hash
-+ * @p: kernel tunnel configuration parameters
-+ *
-+ * Description:
-+ * ip6ip6_kernel_tnl_add() fetches an unused kernel tunnel configures
-+ * it according to @p and places it among the active tunnels.
-+ *
-+ * Return:
-+ * number of references to tunnel on success,
-+ * %-EEXIST if there is already a device matching description
-+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised,
-+ * %-ENODEV if there are no unused kernel tunnels available
-+ *
-+ * Note:
-+ * The code for creating, opening, closing and destroying network devices
-+ * must be called from process context, while the Mobile IP code, which
-+ * needs the tunnel devices, unfortunately runs in interrupt context.
-+ *
-+ * The devices must be created and opened in advance, then placed in a
-+ * list where the kernel can fetch and ready them for use at a later time.
-+ *
-+ **/
-+
-+int
-+ip6ip6_kernel_tnl_add(struct ip6_tnl_parm *p)
-+{
-+ struct ip6_tnl *t;
-+
-+ if (!(p->flags & IP6_TNL_F_KERNEL_DEV))
-+ return -EINVAL;
-+ if ((t = ip6ip6_tnl_lookup(&p->raddr, &p->laddr)) != NULL &&
-+ t != &ip6ip6_fb_tnl) {
-+ /* Handle duplicate tunnels by incrementing
-+ reference count */
-+ atomic_inc(&t->refcnt);
-+ goto out;
-+ }
-+ if ((t = ip6ip6_kernel_tnl_unlink()) == NULL)
-+ return -ENODEV;
-+ __ip6ip6_tnl_change(t, p);
-+
-+ atomic_inc(&t->refcnt);
-+
-+ ip6ip6_tnl_link(t);
-+
-+ manage_kernel_tnls(NULL);
-+out:
-+ return atomic_read(&t->refcnt);
-+}
-+
-+/**
-+ * ip6ip6_kernel_tnl_del - delete no longer needed kernel tunnel
-+ * @t: kernel tunnel to be removed from hash
-+ *
-+ * Description:
-+ * ip6ip6_kernel_tnl_del() removes and deconfigures the tunnel @t
-+ * and places it among the unused kernel devices.
-+ *
-+ * Return:
-+ * number of references on success,
-+ * %-EINVAL if p->flags doesn't have %IP6_TNL_F_KERNEL_DEV raised,
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information.
-+ **/
-+
-+int
-+ip6ip6_kernel_tnl_del(struct ip6_tnl *t)
-+{
-+ if (!t)
-+ return -ENODEV;
-+
-+ if (!(t->parms.flags & IP6_TNL_F_KERNEL_DEV))
-+ return -EINVAL;
-+
-+ if (atomic_dec_and_test(&t->refcnt)) {
-+ struct ip6_tnl_parm p;
-+ ip6ip6_tnl_unlink(t);
-+ memset(&p, 0, sizeof (p));
-+ p.flags = IP6_TNL_F_KERNEL_DEV;
-+
-+ __ip6ip6_tnl_change(t, &p);
-+
-+ ip6ip6_kernel_tnl_link(t);
-+
-+ manage_kernel_tnls(NULL);
-+ }
-+ return atomic_read(&t->refcnt);
-+}
-+
-+/**
-+ * ip6ip6_tnl_ioctl - configure ipv6 tunnels from userspace
-+ * @dev: virtual device associated with tunnel
-+ * @ifr: parameters passed from userspace
-+ * @cmd: command to be performed
-+ *
-+ * Description:
-+ * ip6ip6_tnl_ioctl() is used for managing IPv6 tunnels
-+ * from userspace.
-+ *
-+ * The possible commands are the following:
-+ * %SIOCGETTUNNEL: get tunnel parameters for device
-+ * %SIOCADDTUNNEL: add tunnel matching given tunnel parameters
-+ * %SIOCCHGTUNNEL: change tunnel parameters to those given
-+ * %SIOCDELTUNNEL: delete tunnel
-+ *
-+ * The fallback device "ip6tnl0", created during module
-+ * initialization, can be used for creating other tunnel devices.
-+ *
-+ * Return:
-+ * 0 on success,
-+ * %-EFAULT if unable to copy data to or from userspace,
-+ * %-EPERM if current process hasn't %CAP_NET_ADMIN set or attempting
-+ * to configure kernel devices from userspace,
-+ * %-EINVAL if passed tunnel parameters are invalid,
-+ * %-EEXIST if changing a tunnel's parameters would cause a conflict
-+ * %-ENODEV if attempting to change or delete a nonexisting device
-+ *
-+ * Note:
-+ * See the comments on ip6ip6_kernel_tnl_add() for more information
-+ * about kernel tunnels.
-+ * **/
-+
-+static int
-+ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-+{
-+ int err = 0;
-+ int create;
-+ struct ip6_tnl_parm p;
-+ struct ip6_tnl *t = NULL;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ switch (cmd) {
-+ case SIOCGETTUNNEL:
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ if (copy_from_user(&p,
-+ ifr->ifr_ifru.ifru_data,
-+ sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV)
-+ t = (struct ip6_tnl *) dev->priv;
-+ else if (err)
-+ break;
-+ } else
-+ t = (struct ip6_tnl *) dev->priv;
-+
-+ memcpy(&p, &t->parms, sizeof (p));
-+ if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
-+ err = -EFAULT;
-+ }
-+ break;
-+ case SIOCADDTUNNEL:
-+ case SIOCCHGTUNNEL:
-+ err = -EPERM;
-+ create = (cmd == SIOCADDTUNNEL);
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ if (p.flags & IP6_TNL_F_KERNEL_DEV) {
-+ break;
-+ }
-+ if (!create && dev != &ip6ip6_fb_tnl_dev) {
-+ t = (struct ip6_tnl *) dev->priv;
-+ }
-+ if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) {
-+ break;
-+ }
-+ if (cmd == SIOCCHGTUNNEL) {
-+ if (t->dev != dev) {
-+ err = -EEXIST;
-+ break;
-+ }
-+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV) {
-+ err = -EPERM;
-+ break;
-+ }
-+ ip6ip6_tnl_change(t, &p);
-+ netdev_state_change(dev);
-+ }
-+ if (copy_to_user(ifr->ifr_ifru.ifru_data,
-+ &t->parms, sizeof (p))) {
-+ err = -EFAULT;
-+ } else {
-+ err = 0;
-+ }
-+ break;
-+ case SIOCDELTUNNEL:
-+ err = -EPERM;
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+
-+ if (dev == &ip6ip6_fb_tnl_dev) {
-+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data,
-+ sizeof (p))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+ err = ip6ip6_tnl_locate(&p, &t, 0);
-+ if (err)
-+ break;
-+ if (t == &ip6ip6_fb_tnl) {
-+ err = -EPERM;
-+ break;
-+ }
-+ } else {
-+ t = (struct ip6_tnl *) dev->priv;
-+ }
-+ if (t->parms.flags & IP6_TNL_F_KERNEL_DEV)
-+ err = -EPERM;
-+ else
-+ err = unregister_netdevice(t->dev);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+/**
-+ * ip6ip6_tnl_get_stats - return the stats for tunnel device
-+ * @dev: virtual device associated with tunnel
-+ *
-+ * Return: stats for device
-+ **/
-+
-+static struct net_device_stats *
-+ip6ip6_tnl_get_stats(struct net_device *dev)
-+{
-+ return &(((struct ip6_tnl *) dev->priv)->stat);
-+}
-+
-+/**
-+ * ip6ip6_tnl_change_mtu - change mtu manually for tunnel device
-+ * @dev: virtual device associated with tunnel
-+ * @new_mtu: the new mtu
-+ *
-+ * Return:
-+ * 0 on success,
-+ * %-EINVAL if mtu too small
-+ **/
-+
-+static int
-+ip6ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
-+{
-+ if (new_mtu < IPV6_MIN_MTU) {
-+ return -EINVAL;
-+ }
-+ dev->mtu = new_mtu;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_init_gen - general initializer for all tunnel devices
-+ * @dev: virtual device associated with tunnel
-+ *
-+ * Description:
-+ * Set function pointers and initialize the &struct flowi template used
-+ * by the tunnel.
-+ **/
-+
-+static int
-+ip6ip6_tnl_dev_init_gen(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ struct flowi *fl = &t->fl;
-+ int err;
-+ struct sock *sk;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_IPV6, &t->sock))) {
-+ printk(KERN_ERR
-+ "Failed to create IPv6 tunnel socket (err %d).\n", err);
-+ return err;
-+ }
-+ t->sock->inode->i_uid = 0;
-+ t->sock->inode->i_gid = 0;
-+
-+ sk = t->sock->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->net_pinfo.af_inet6.hop_limit = 254;
-+ sk->net_pinfo.af_inet6.mc_loop = 0;
-+ sk->prot->unhash(sk);
-+
-+ memset(fl, 0, sizeof (*fl));
-+ fl->proto = IPPROTO_IPV6;
-+
-+ dev->destructor = ip6ip6_tnl_dev_destructor;
-+ dev->uninit = ip6ip6_tnl_dev_uninit;
-+ dev->hard_start_xmit = ip6ip6_tnl_xmit;
-+ dev->get_stats = ip6ip6_tnl_get_stats;
-+ dev->do_ioctl = ip6ip6_tnl_ioctl;
-+ dev->change_mtu = ip6ip6_tnl_change_mtu;
-+
-+ dev->type = ARPHRD_TUNNEL6;
-+ dev->hard_header_len = LL_MAX_HEADER + sizeof (struct ipv6hdr);
-+ dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
-+ dev->flags |= IFF_NOARP;
-+ dev->iflink = 0;
-+ /* Hmm... MAX_ADDR_LEN is 8, so the ipv6 addresses can't be
-+ copied to dev->dev_addr and dev->broadcast, like the ipv4
-+ addresses were in ipip.c, ip_gre.c and sit.c. */
-+ dev->addr_len = 0;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_dev_init - initializer for all non fallback tunnel devices
-+ * @dev: virtual device associated with tunnel
-+ **/
-+
-+static int
-+ip6ip6_tnl_dev_init(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
-+ ip6ip6_tnl_dev_init_gen(dev);
-+ ip6ip6_tnl_link_config(t);
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+
-+/**
-+ * ip6ip6_fb_tnl_open - function called when fallback device opened
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+static int
-+ip6ip6_fb_tnl_open(struct net_device *dev)
-+{
-+ MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_fb_tnl_close - function called when fallback device closed
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+static int
-+ip6ip6_fb_tnl_close(struct net_device *dev)
-+{
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+#endif
-+
-+/**
-+ * ip6ip6_fb_tnl_dev_init - initializer for fallback tunnel device
-+ * @dev: fallback device
-+ *
-+ * Return: 0
-+ **/
-+
-+int __init
-+ip6ip6_fb_tnl_dev_init(struct net_device *dev)
-+{
-+ ip6ip6_tnl_dev_init_gen(dev);
-+#ifdef MODULE
-+ dev->open = ip6ip6_fb_tnl_open;
-+ dev->stop = ip6ip6_fb_tnl_close;
-+#endif
-+ dev_hold(dev);
-+ tnls_wc[0] = &ip6ip6_fb_tnl;
-+ return 0;
-+}
-+
-+/**
-+ * ip6ip6_tnl_register_hook - add hook for processing of tunneled packets
-+ * @reg: hook function and its parameters
-+ *
-+ * Description:
-+ * Add a netfilter like hook function for special handling of tunneled
-+ * packets. The hook functions are called before encapsulation
-+ * (%IP6_TNL_PRE_ENCAP) and before decapsulation
-+ * (%IP6_TNL_PRE_DECAP). The possible return values by the hook
-+ * functions are %IP6_TNL_DROP, %IP6_TNL_ACCEPT and
-+ * %IP6_TNL_STOLEN (in case the hook function took care of the packet
-+ * and it doesn't have to be processed any further).
-+ **/
-+
-+void
-+ip6ip6_tnl_register_hook(struct ip6_tnl_hook_ops *reg)
-+{
-+ if (reg->hooknum < IP6_TNL_MAXHOOKS) {
-+ struct list_head *i;
-+
-+ write_lock_bh(&ip6ip6_hook_lock);
-+ for (i = hooks[reg->hooknum].next;
-+ i != &hooks[reg->hooknum]; i = i->next) {
-+ if (reg->priority <
-+ ((struct ip6_tnl_hook_ops *) i)->priority) {
-+ break;
-+ }
-+ }
-+ list_add(&reg->list, i->prev);
-+ write_unlock_bh(&ip6ip6_hook_lock);
-+ }
-+}
-+
-+/**
-+ * ip6ip6_tnl_unregister_hook - remove tunnel hook
-+ * @reg: hook function and its parameters
-+ **/
-+
-+void
-+ip6ip6_tnl_unregister_hook(struct ip6_tnl_hook_ops *reg)
-+{
-+ if (reg->hooknum < IP6_TNL_MAXHOOKS) {
-+ write_lock_bh(&ip6ip6_hook_lock);
-+ list_del(&reg->list);
-+ write_unlock_bh(&ip6ip6_hook_lock);
-+ }
-+}
-+
-+
-+/* the IPv6 over IPv6 protocol structure */
-+static struct inet6_protocol ip6ip6_protocol = {
-+ ip6ip6_rcv, /* IPv6 handler */
-+ ip6ip6_err, /* IPv6 error control */
-+ NULL, /* next */
-+ IPPROTO_IPV6, /* protocol ID */
-+ 0, /* copy */
-+ NULL, /* data */
-+ "IPv6 over IPv6" /* name */
-+};
-+
-+/**
-+ * ip6_tunnel_init - register protocol and reserve needed resources
-+ *
-+ * Return: 0 on success
-+ **/
-+
-+int __init ip6_tunnel_init(void)
-+{
-+ int i, err;
-+
-+ ip6ip6_fb_tnl_dev.priv = (void *) &ip6ip6_fb_tnl;
-+
-+ for (i = 0; i < IP6_TNL_MAXHOOKS; i++) {
-+ INIT_LIST_HEAD(&hooks[i]);
-+ }
-+ if ((err = register_netdev(&ip6ip6_fb_tnl_dev)))
-+ return err;
-+
-+ inet6_add_protocol(&ip6ip6_protocol);
-+ return 0;
-+}
-+
-+/**
-+ * ip6_tunnel_cleanup - free resources and unregister protocol
-+ **/
-+
-+void ip6_tunnel_cleanup(void)
-+{
-+ write_lock_bh(&ip6ip6_kernel_lock);
-+ shutdown = 1;
-+ write_unlock_bh(&ip6ip6_kernel_lock);
-+ flush_scheduled_tasks();
-+ manage_kernel_tnls(NULL);
-+ inet6_del_protocol(&ip6ip6_protocol);
-+ unregister_netdev(&ip6ip6_fb_tnl_dev);
-+}
-+
-+#ifdef MODULE
-+module_init(ip6_tunnel_init);
-+module_exit(ip6_tunnel_cleanup);
-+#endif
-+
-+#if defined(CONFIG_IPV6_MOBILITY_HA_MODULE) || defined(CONFIG_IPV6_MOBILITY_MN_MODULE)
-+EXPORT_SYMBOL(ip6ip6_tnl_register_hook);
-+EXPORT_SYMBOL(ip6ip6_tnl_unregister_hook);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_HA_MODULE
-+EXPORT_SYMBOL(ip6ip6_tnl_dec_max_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_inc_max_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_dec_min_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_tnl_inc_min_kdev_count);
-+EXPORT_SYMBOL(ip6ip6_kernel_tnl_add);
-+EXPORT_SYMBOL(ip6ip6_kernel_tnl_del);
-+EXPORT_SYMBOL(ip6ip6_tnl_lookup);
-+#endif
-+#ifdef CONFIG_IPV6_MOBILITY_MN_MODULE
-+EXPORT_SYMBOL(ip6ip6_tnl_create);
-+EXPORT_SYMBOL(ip6ip6_tnl_change);
-+#endif
-+
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mipglue.c
-@@ -0,0 +1,63 @@
-+/*
-+ * Glue for Mobility support integration to IPv6
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/sched.h>
-+
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+#include <net/mipglue.h>
-+
-+extern int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff);
-+
-+/* Initialize all zero */
-+struct mipv6_callable_functions mipv6_functions = { NULL };
-+
-+/* Sets mipv6_functions struct to zero to invalidate all successive
-+ * calls to mipv6 functions. Used on module unload. */
-+
-+void mipv6_invalidate_calls(void)
-+{
-+ memset(&mipv6_functions, 0, sizeof(mipv6_functions));
-+}
-+
-+
-+/* Selects correct handler for tlv encoded destination option. Called
-+ * by ip6_parse_tlv. Checks if mipv6 calls are valid before calling. */
-+
-+int mipv6_handle_dstopt(struct sk_buff *skb, int optoff)
-+{
-+ int ret;
-+
-+ switch (skb->nh.raw[optoff]) {
-+ case MIPV6_TLV_HOMEADDR:
-+ ret = MIPV6_CALLFUNC(mipv6_handle_homeaddr, 0)(skb, optoff);
-+ break;
-+ default:
-+ /* Should never happen */
-+ printk(KERN_ERR __FILE__ ": Invalid destination option code (%d)\n",
-+ skb->nh.raw[optoff]);
-+ ret = 1;
-+ break;
-+ }
-+
-+ /* If mipv6 handlers are not valid, pass the packet to
-+ * ip6_tlvopt_unknown() for correct handling. */
-+ if (!ret)
-+ return ip6_tlvopt_unknown(skb, optoff);
-+
-+ return ret;
-+}
-+
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/Config.in
-@@ -0,0 +1,12 @@
-+#
-+# Mobile IPv6 Configuration
-+#
-+dep_tristate ' IPv6: Mobility Support (Correspondent Node)' CONFIG_IPV6_MOBILITY $CONFIG_IPV6
-+if [ "$CONFIG_IPV6_IPV6_TUNNEL" != "n" ]; then
-+ dep_tristate ' MIPv6: Mobile Node Support' CONFIG_IPV6_MOBILITY_MN $CONFIG_IPV6_MOBILITY
-+
-+ dep_tristate ' MIPv6: Home Agent Support' CONFIG_IPV6_MOBILITY_HA $CONFIG_IPV6_MOBILITY
-+fi
-+if [ "$CONFIG_IPV6_MOBILITY" != "n" ]; then
-+ bool ' MIPv6: Debug messages' CONFIG_IPV6_MOBILITY_DEBUG
-+fi
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/Makefile
-@@ -0,0 +1,35 @@
-+#
-+# Makefile for the MIPL Mobile IPv6 for Linux.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+
-+
-+O_TARGET := mip6_base.o
-+
-+list-multi := mip6_ha.o mip6_mn.o
-+
-+obj-y := hashlist.o bcache.o mobhdr_common.o stats.o exthdrs.o \
-+ rr_crypto.o hmac.o auth_opt.o mipv6_icmp.o module_cn.o
-+
-+obj-m := $(O_TARGET)
-+
-+mip6_ha-objs := halist.o mipv6_icmp_ha.o tunnel_ha.o \
-+ ndisc_ha.o ha.o module_ha.o
-+
-+mip6_mn-objs := mipv6_icmp_mn.o ioctl_mn.o tunnel_mn.o \
-+ mdetect.o bul.o multiaccess_ctl.o mobhdr_mn.o mn.o \
-+ module_mn.o
-+
-+obj-$(CONFIG_IPV6_MOBILITY_HA) += mip6_ha.o
-+obj-$(CONFIG_IPV6_MOBILITY_MN) += mip6_mn.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+mip6_ha.o: $(mip6_ha-objs)
-+ $(LD) -r -o $@ $(mip6_ha-objs)
-+
-+mip6_mn.o: $(mip6_mn-objs)
-+ $(LD) -r -o $@ $(mip6_mn-objs)
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/README
-@@ -0,0 +1,15 @@
-+MIPL Mobile IPv6 for Linux
-+
-+More information at http://www.mipl.mediapoli.com/.
-+
-+To join MIPL Mobile IPv6 for Linux mailing lists go to:
-+
-+ http://www.mipl.mediapoli.com/cgi-bin/mailman/listinfo
-+
-+Or send mail with subject "subscribe" for the general list to:
-+
-+ mipl-request@list.mipl.mediapoli.com
-+
-+or for the developer list to:
-+
-+ mipl-devel-request@list.mail.mediapoli.com
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/auth_opt.c
-@@ -0,0 +1,121 @@
-+/*
-+ * MIPv6 Binding Authentication Data Option functions
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/icmpv6.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "hmac.h"
-+#include "mobhdr.h"
-+
-+#define DBG_KEY 5
-+
-+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *mh, __u8 *aud_data, __u8 *k_bu)
-+{
-+ /* First look up the peer from sadb based on his address */
-+ struct ah_processing ahp;
-+
-+ /* Don't add any other options or this system is screwed */
-+
-+ __u8 buf[MAX_HASH_LENGTH];
-+
-+
-+ if (!k_bu) {
-+ DEBUG(DBG_ERROR, "k_bu missing, aborting");
-+ return -1;
-+ }
-+ DEBUG(DBG_KEY, "Key for building authenticator:");
-+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE);
-+
-+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hmac sha1");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_KEY, "coa: ");
-+ debug_print_buffer(DBG_KEY, coa, 16);
-+ DEBUG(DBG_KEY, "cn_addr: ");
-+ debug_print_buffer(DBG_KEY, cn_addr, 16);
-+ DEBUG(DBG_KEY, "MH contents: ");
-+ debug_print_buffer(DBG_KEY, mh, aud_data - mh);
-+
-+ /* First the common part */
-+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, mh, aud_data - mh);
-+ ah_hmac_sha1_result(&ahp, buf);
-+
-+ memcpy(aud_data, buf, MIPV6_RR_MAC_LENGTH);
-+
-+ return 0;
-+}
-+
-+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 optlen,
-+ struct mipv6_mo_bauth_data *aud, __u8 *k_bu)
-+{
-+ int ret = -1;
-+ struct ah_processing ahp;
-+ __u8 htarget[MAX_HASH_LENGTH];
-+
-+ /* Look up peer by home address */
-+ if (!k_bu) {
-+ DEBUG(DBG_ERROR, "k_bu missing, aborting");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_KEY, "Key for checking authenticator:");
-+ debug_print_buffer(DBG_KEY, k_bu, HMAC_SHA1_KEY_SIZE);
-+
-+ if (!aud || !coa) {
-+ DEBUG(DBG_INFO, "%s is NULL", aud ? "coa" : "aud");
-+ goto out;
-+ }
-+
-+ if (aud->length != MIPV6_RR_MAC_LENGTH) {
-+ DEBUG(DBG_ERROR,
-+ ": Incorrect authentication option length %d", aud->length);
-+ goto out;
-+ }
-+
-+ if (ah_hmac_sha1_init(&ahp, k_bu, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR,
-+ "internal error in initialization of authentication algorithm");
-+ goto out;
-+ }
-+ DEBUG(DBG_KEY, "coa: ");
-+ debug_print_buffer(DBG_KEY, coa, 16);
-+ DEBUG(DBG_KEY, "cn_addr: ");
-+ debug_print_buffer(DBG_KEY, cn_addr, 16);
-+ DEBUG(DBG_KEY, "MH contents: ");
-+ debug_print_buffer(DBG_KEY, opt, (u8*) aud->data - opt);
-+
-+ ah_hmac_sha1_loop(&ahp, coa, sizeof(struct in6_addr));
-+ ah_hmac_sha1_loop(&ahp, cn_addr, sizeof(struct in6_addr));
-+
-+ /*
-+ * Process MH + options till the start of the authenticator in
-+ * Auth. data option
-+ */
-+ ah_hmac_sha1_loop(&ahp, opt, (u8 *)aud->data - opt);
-+ ah_hmac_sha1_result(&ahp, htarget);
-+ if (memcmp(htarget, aud->data, MIPV6_RR_MAC_LENGTH) == 0)
-+ ret = 0;
-+
-+ DEBUG(DBG_ERROR, "returning %d", ret);
-+out:
-+ return ret;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/bcache.c
-@@ -0,0 +1,746 @@
-+/*
-+ * Binding Cache
-+ *
-+ * Authors:
-+ * Juha Mynttinen <jmynttin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Timer code cleaned up, active socket
-+ * test rewritten
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/proc_fs.h>
-+#include <linux/ipv6_route.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "bcache.h"
-+#include "hashlist.h"
-+#include "debug.h"
-+#include "mobhdr.h"
-+#include "tunnel.h"
-+#include "config.h"
-+
-+#define TIMERDELAY HZ/10
-+
-+struct mipv6_bcache {
-+ struct hashlist *entries;
-+ __u32 size;
-+ struct timer_list callback_timer;
-+};
-+
-+struct in6_addr_pair {
-+ struct in6_addr *a1;
-+ struct in6_addr *a2;
-+};
-+
-+static rwlock_t bcache_lock = RW_LOCK_UNLOCKED;
-+
-+static struct mipv6_bcache bcache;
-+
-+static int bcache_proc_info(char *buffer, char **start, off_t offset,
-+ int length);
-+
-+#define MIPV6_BCACHE_HASHSIZE 32
-+
-+/* Moment of transmission of a BR, in seconds before bcache entry expiry */
-+#define BCACHE_BR_SEND_LEAD 3
-+
-+#define MIPV6_MAX_BRR 3 /* Send 3 BRRs before deleting BC entry */
-+#define MIPV6_BRR_RATE HZ /* Send BRRs once per second */
-+
-+/*
-+ * Internal functions.
-+ */
-+
-+struct cache_entry_iterator_args {
-+ struct mipv6_bce **entry;
-+};
-+
-+static int find_first_cache_entry_iterator(void *data, void *args,
-+ unsigned long *lifetime)
-+{
-+ struct mipv6_bce *entry =
-+ (struct mipv6_bce *) data;
-+ struct cache_entry_iterator_args *state =
-+ (struct cache_entry_iterator_args *) args;
-+
-+ ASSERT(entry != NULL);
-+
-+ if (entry->type == CACHE_ENTRY) {
-+ *(state->entry) = entry;
-+ return ITERATOR_STOP; /* stop iteration */
-+ } else {
-+ return ITERATOR_CONT; /* continue iteration */
-+ }
-+}
-+
-+
-+/*
-+ * Get memory for a new bcache entry. If bcache is full, a cache
-+ * entry may be deleted to get space for a home registration, but not
-+ * vice versa.
-+ */
-+static struct mipv6_bce *mipv6_bce_alloc(__u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ struct cache_entry_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ entry = (struct mipv6_bce *)
-+ hashlist_alloc(bcache.entries, SLAB_ATOMIC);
-+
-+ /* Cache replacement policy: always replace the CACHE_ENTRY
-+ closest to expiration. Type HOME_REGISTRATION entry may
-+ never be deleted before expiration. */
-+ if (entry == NULL) {
-+ /* cache full, try to delete a CACHE_ENTRY */
-+ args.entry = &entry;
-+ hashlist_iterate(bcache.entries, &args,
-+ find_first_cache_entry_iterator);
-+ if (entry == NULL)
-+ return NULL;
-+ hashlist_delete(bcache.entries,
-+ (struct hashlist_entry *)entry);
-+ entry = (struct mipv6_bce *)
-+ hashlist_alloc(bcache.entries, SLAB_ATOMIC);
-+ }
-+ return entry;
-+}
-+
-+/*
-+ * Frees entry's memory allocated with mipv6_bce_alloc
-+ */
-+static void mipv6_bce_free(struct mipv6_bce *entry)
-+{
-+ hashlist_free(bcache.entries, (void *) entry);
-+}
-+
-+/*
-+ * Removes all expired entries
-+ */
-+static void expire(void)
-+{
-+ struct mipv6_bce *entry;
-+ struct br_addrs {
-+ struct in6_addr daddr;
-+ struct in6_addr saddr;
-+ struct br_addrs *next;
-+ };
-+ struct br_addrs *br_info = NULL;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&bcache_lock);
-+
-+ while ((entry = (struct mipv6_bce *)
-+ hashlist_get_first(bcache.entries)) != NULL) {
-+ struct rt6_info *rt;
-+ if (time_after_eq(jiffies, entry->callback_time)) {
-+
-+ DEBUG(DBG_INFO, "an entry expired");
-+
-+ if (entry->type & HOME_REGISTRATION) {
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ }
-+ hashlist_delete(bcache.entries, (void *)entry);
-+ mipv6_bce_free(entry);
-+ entry = NULL;
-+ } else if (entry->br_callback_time != 0 &&
-+ time_after_eq(jiffies, entry->br_callback_time) &&
-+ entry->br_count < MIPV6_MAX_BRR &&
-+ (rt = rt6_lookup(&entry->home_addr, &entry->our_addr, 0, 0)) != NULL){
-+ /* Do we have a destination cache entry for the home address */
-+ if (rt->rt6i_flags & RTF_CACHE) {
-+ struct br_addrs *tmp;
-+ tmp = br_info;
-+ DEBUG(DBG_INFO,
-+ "bcache entry recently used. Sending BR.");
-+ /* queue for sending */
-+ br_info = kmalloc(sizeof(struct br_addrs),
-+ GFP_ATOMIC);
-+ if (br_info) {
-+ ipv6_addr_copy(&br_info->saddr,
-+ &entry->our_addr);
-+ ipv6_addr_copy(&br_info->daddr,
-+ &entry->home_addr);
-+ br_info->next = tmp;
-+ entry->last_br = jiffies;
-+ entry->br_callback_time = jiffies + MIPV6_BRR_RATE;
-+ entry->br_count++;
-+ } else {
-+ br_info = tmp;
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ }
-+
-+ } else
-+ entry->br_callback_time = 0;
-+ dst_release(&rt->u.dst);
-+ } else {
-+ entry->br_callback_time = 0;
-+ break;
-+ }
-+ }
-+ write_unlock(&bcache_lock);
-+
-+ while (br_info) {
-+ struct br_addrs *tmp = br_info->next;
-+ if (mipv6_send_brr(&br_info->saddr, &br_info->daddr, NULL) < 0)
-+ DEBUG(DBG_WARNING,
-+ "BR send for %x:%x:%x:%x:%x:%x:%x:%x failed",
-+ NIPV6ADDR(&br_info->daddr));
-+ kfree(br_info);
-+ br_info = tmp;
-+ }
-+}
-+
-+static void set_timer(void)
-+{
-+ struct mipv6_bce *entry;
-+ unsigned long callback_time;
-+
-+ DEBUG_FUNC();
-+
-+ entry = (struct mipv6_bce *)
-+ hashlist_get_first(bcache.entries);
-+ if (entry != NULL) {
-+ if (entry->br_callback_time > 0 &&
-+ time_after(entry->br_callback_time, jiffies))
-+ callback_time = entry->br_callback_time;
-+ else if (time_after(entry->callback_time, jiffies))
-+ callback_time = entry->callback_time;
-+ else {
-+ DEBUG(DBG_WARNING,
-+ "bcache timer attempted to schedule"
-+ " for a historical jiffies count!");
-+ callback_time = jiffies + TIMERDELAY;
-+ }
-+
-+ DEBUG(DBG_INFO, "setting timer to now");
-+ mod_timer(&bcache.callback_timer, callback_time);
-+ } else {
-+ del_timer(&bcache.callback_timer);
-+ DEBUG(DBG_INFO, "BC empty, not setting a new timer");
-+ }
-+}
-+
-+/*
-+ * The function that is scheduled to do the callback functions. May be
-+ * modified e.g to allow Binding Requests, now only calls expire() and
-+ * schedules a new timer.
-+ */
-+static void timer_handler(unsigned long dummy)
-+{
-+ expire();
-+ write_lock(&bcache_lock);
-+ set_timer();
-+ write_unlock(&bcache_lock);
-+}
-+
-+/*
-+ * Interface functions visible to other modules
-+ */
-+
-+/**
-+ * mipv6_bcache_add - add Binding Cache entry
-+ * @ifindex: interface index
-+ * @our_addr: own address
-+ * @home_addr_org: MN's home address
-+ * @coa: MN's care-of address
-+ * @lifetime: lifetime for this binding
-+ * @prefix: prefix length
-+ * @seq: sequence number
-+ * @flags: flags received in BU
-+ * @type: type of entry
-+ *
-+ * Adds an entry for this @home_addr_org in the Binding Cache. If entry
-+ * already exists, old entry is updated. @type may be %CACHE_ENTRY or
-+ * %HOME_REGISTRATION.
-+ **/
-+int mipv6_bcache_add(int ifindex,
-+ struct in6_addr *our_addr,
-+ struct in6_addr *home_addr,
-+ struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ int update = 0;
-+ int create_tunnel = 0;
-+ unsigned long now = jiffies;
-+ struct in6_addr_pair hashkey;
-+ int ret = -1;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+
-+ if (type == HOME_REGISTRATION && !(mip6node_cnf.capabilities&CAP_HA))
-+ return 0;
-+
-+ if (unlikely(bcache.entries == NULL)) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ if ((entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ /* if an entry for this home_addr exists (with smaller
-+ * seq than the new seq), update it by removing it
-+ * first
-+ */
-+ if (!MIPV6_SEQ_GT(seq, entry->seq)) {
-+ DEBUG(DBG_INFO, "smaller seq than existing, not updating");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "updating an existing entry");
-+ update = 1;
-+
-+ /* H-flag is already checked in BU handler. */
-+ /* XXX: Should we care about the other flags?*/
-+ if (flags != entry->flags) {
-+ DEBUG(DBG_INFO, "entry/BU flag mismatch");
-+ }
-+
-+ if (type == HOME_REGISTRATION) {
-+ create_tunnel = (ipv6_addr_cmp(&entry->coa, coa) ||
-+ entry->ifindex != ifindex);
-+ }
-+ } else {
-+ /* no entry for this home_addr, try to create a new entry */
-+ DEBUG(DBG_INFO, "creating a new entry");
-+ update = 0;
-+
-+ entry = mipv6_bce_alloc(type);
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "cache full, entry not added");
-+ goto err;
-+ }
-+
-+ create_tunnel = (type == HOME_REGISTRATION);
-+ }
-+
-+ if (create_tunnel) {
-+ if (update)
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ if (mip6_fn.proxy_create(flags, ifindex, coa, our_addr, home_addr) < 0) {
-+ goto err_proxy;
-+ }
-+ }
-+
-+ ipv6_addr_copy(&(entry->our_addr), our_addr);
-+ ipv6_addr_copy(&(entry->home_addr), home_addr);
-+ ipv6_addr_copy(&(entry->coa), coa);
-+ entry->ifindex = ifindex;
-+ entry->seq = seq;
-+ entry->type = type;
-+ entry->flags = flags;
-+
-+ entry->last_br = 0;
-+ entry->destunr_count = 0;
-+ entry->callback_time = now + lifetime * HZ;
-+ if (entry->type & HOME_REGISTRATION)
-+ entry->br_callback_time = 0;
-+ else
-+ entry->br_callback_time = now +
-+ (lifetime - BCACHE_BR_SEND_LEAD) * HZ;
-+
-+ if (update) {
-+ DEBUG(DBG_INFO, "updating entry : %x", entry);
-+ hashlist_reposition(bcache.entries, (void *)entry,
-+ entry->callback_time);
-+ } else {
-+ DEBUG(DBG_INFO, "adding entry: %x", entry);
-+ if ((hashlist_add(bcache.entries,
-+ &hashkey,
-+ entry->callback_time, entry)) < 0) {
-+
-+ DEBUG(DBG_ERROR, "Hash add failed");
-+ goto err_hashlist;
-+ }
-+ }
-+
-+ set_timer();
-+
-+out:
-+ write_unlock(&bcache_lock);
-+ return 0;
-+
-+err_hashlist:
-+ if (create_tunnel) {
-+ mip6_fn.proxy_del(home_addr, entry);
-+ }
-+err_proxy:
-+ if (update) {
-+ hashlist_delete(bcache.entries, (void *)entry);
-+ }
-+ mipv6_bce_free(entry);
-+err:
-+ write_unlock(&bcache_lock);
-+ return ret;
-+}
-+
-+int mipv6_bcache_icmp_err(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ int destunr_count)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ int ret = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+ if (unlikely(bcache.entries == NULL)) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ if ((entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ entry->last_destunr = jiffies;
-+ entry->destunr_count = destunr_count;
-+ ret = 0;
-+ }
-+err:
-+ write_unlock(&bcache_lock);
-+ return ret;
-+}
-+
-+
-+/**
-+ * mipv6_bcache_delete - delete Binding Cache entry
-+ * @home_addr: MN's home address
-+ * @our_addr: our address
-+ * @type: type of entry
-+ *
-+ * Deletes an entry associated with @home_addr from Binding Cache.
-+ * Valid values for @type are %CACHE_ENTRY, %HOME_REGISTRATION and
-+ * %ANY_ENTRY. %ANY_ENTRY deletes any type of entry.
-+ **/
-+int mipv6_bcache_delete(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr, __u8 type)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+ int err = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL) {
-+ DEBUG(DBG_INFO, "error in arguments");
-+ return -EINVAL;
-+ }
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ write_lock(&bcache_lock);
-+
-+ if (unlikely(bcache.entries == NULL) ||
-+ (entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) == NULL ||
-+ !(entry->type & type)) {
-+ DEBUG(DBG_INFO, "No matching entry found");
-+ err = -ENOENT;
-+ goto out;
-+ }
-+
-+ hashlist_delete(bcache.entries, (void *) entry);
-+ mipv6_bce_free(entry);
-+
-+ set_timer();
-+out:
-+ write_unlock(&bcache_lock);
-+ return err;
-+}
-+
-+/**
-+ * mipv6_bcache_exists - check if entry exists
-+ * @home_addr: home address to check
-+ * @our_addr: our address
-+ *
-+ * Determines if a binding exists for @home_addr. Returns type of the
-+ * entry or negative if entry does not exist.
-+ **/
-+int mipv6_bcache_exists(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr)
-+{
-+ struct mipv6_bce *entry;
-+ struct in6_addr_pair hashkey;
-+ int type = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL)
-+ return -EINVAL;
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ read_lock(&bcache_lock);
-+ if (likely(bcache.entries != NULL) &&
-+ (entry = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey)) != NULL) {
-+ type = entry->type;
-+ }
-+ read_unlock(&bcache_lock);
-+
-+ return type;
-+}
-+
-+/**
-+ * mipv6_bcache_get - get entry from Binding Cache
-+ * @home_addr: home address to search
-+ * @our_addr: our address
-+ * @entry: pointer to buffer
-+ *
-+ * Gets a copy of Binding Cache entry for @home_addr. If entry
-+ * exists entry is copied to @entry and zero is returned.
-+ * Otherwise returns negative.
-+ **/
-+int mipv6_bcache_get(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ struct mipv6_bce *entry)
-+{
-+ struct mipv6_bce *entry2;
-+ struct in6_addr_pair hashkey;
-+ int ret = -ENOENT;
-+
-+ DEBUG_FUNC();
-+
-+ if (home_addr == NULL || our_addr == NULL || entry == NULL)
-+ return -EINVAL;
-+
-+ hashkey.a1 = home_addr;
-+ hashkey.a2 = our_addr;
-+
-+ read_lock_bh(&bcache_lock);
-+
-+ entry2 = (struct mipv6_bce *)
-+ hashlist_get(bcache.entries, &hashkey);
-+ if (entry2 != NULL) {
-+ memcpy(entry, entry2, sizeof(struct mipv6_bce));
-+ ret = 0;
-+ }
-+ read_unlock_bh(&bcache_lock);
-+ return ret;
-+}
-+
-+int mipv6_bcache_iterate(hashlist_iterator_t func, void *args)
-+{
-+ int ret;
-+
-+ read_lock_bh(&bcache_lock);
-+ ret = hashlist_iterate(bcache.entries, args, func);
-+ read_unlock_bh(&bcache_lock);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Proc-filesystem functions
-+ */
-+
-+#define BC_INFO_LEN 80
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args, unsigned long *pref)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *) args;
-+ struct mipv6_bce *entry =
-+ (struct mipv6_bce *) data;
-+
-+ ASSERT(entry != NULL);
-+
-+ if (arg->skip < arg->offset / BC_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ /* HoA CoA CallbackInSecs Type */
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%08x%08x%08x%08x %08x%08x%08x%08x %010lu %02d\n",
-+ ntohl(entry->home_addr.s6_addr32[0]),
-+ ntohl(entry->home_addr.s6_addr32[1]),
-+ ntohl(entry->home_addr.s6_addr32[2]),
-+ ntohl(entry->home_addr.s6_addr32[3]),
-+ ntohl(entry->coa.s6_addr32[0]),
-+ ntohl(entry->coa.s6_addr32[1]),
-+ ntohl(entry->coa.s6_addr32[2]),
-+ ntohl(entry->coa.s6_addr32[3]),
-+ ((entry->callback_time) - jiffies) / HZ,
-+ (int) entry->type);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+ /*
-+ * Callback function for proc filesystem.
-+ */
-+static int bcache_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&bcache_lock);
-+ hashlist_iterate(bcache.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&bcache_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % BC_INFO_LEN;
-+
-+ args.len -= offset % BC_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+static int bcache_compare(void *data, void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey;
-+ struct mipv6_bce *e = (struct mipv6_bce *) data;
-+
-+ if (ipv6_addr_cmp(&e->home_addr, p->a1) == 0
-+ && ipv6_addr_cmp(&e->our_addr, p->a2) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+static __u32 bcache_hash(void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *) hashkey;
-+
-+ return p->a1->s6_addr32[0] ^ p->a1->s6_addr32[1] ^
-+ p->a2->s6_addr32[2] ^ p->a2->s6_addr32[3];
-+}
-+
-+/*
-+ * Initialization and shutdown functions
-+ */
-+
-+int __init mipv6_bcache_init(__u32 size)
-+{
-+ if (size < 1) {
-+ DEBUG(DBG_ERROR, "Binding cache size must be at least 1");
-+ return -EINVAL;
-+ }
-+ bcache.entries = hashlist_create(MIPV6_BCACHE_HASHSIZE, size,
-+ sizeof(struct mipv6_bce),
-+ "mip6_bcache", NULL, NULL,
-+ bcache_compare, bcache_hash);
-+
-+ if (bcache.entries == NULL) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hashlist");
-+ return -ENOMEM;
-+ }
-+
-+ init_timer(&bcache.callback_timer);
-+ bcache.callback_timer.data = 0;
-+ bcache.callback_timer.function = timer_handler;
-+ bcache.size = size;
-+
-+ proc_net_create("mip6_bcache", 0, bcache_proc_info);
-+
-+ DEBUG(DBG_INFO, "Binding cache initialized");
-+ return 0;
-+}
-+
-+static int
-+bce_cleanup_iterator(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ int type = (int) args;
-+ struct mipv6_bce *entry = (struct mipv6_bce *) rawentry;
-+ if (entry->type == type) {
-+ if (entry->type & HOME_REGISTRATION) {
-+ if (unlikely(mip6_fn.proxy_del == NULL))
-+ DEBUG(DBG_ERROR, "proxy_del unitialized");
-+ else
-+ mip6_fn.proxy_del(&entry->home_addr, entry);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ return ITERATOR_CONT;
-+
-+}
-+
-+void mipv6_bcache_cleanup(int type)
-+{
-+ write_lock_bh(&bcache_lock);
-+ hashlist_iterate(bcache.entries,(void *) type, bce_cleanup_iterator);
-+ write_unlock_bh(&bcache_lock);
-+}
-+
-+int __exit mipv6_bcache_exit(void)
-+{
-+ struct hashlist *entries;
-+
-+ DEBUG_FUNC();
-+
-+ proc_net_remove("mip6_bcache");
-+
-+ write_lock_bh(&bcache_lock);
-+ DEBUG(DBG_INFO, "Stopping the bcache timer");
-+ del_timer(&bcache.callback_timer);
-+ hashlist_iterate(bcache.entries,(void *)CACHE_ENTRY,
-+ bce_cleanup_iterator);
-+
-+ entries = bcache.entries;
-+ bcache.entries = NULL;
-+ write_unlock_bh(&bcache_lock);
-+
-+ hashlist_destroy(entries);
-+ return 0;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/bcache.h
-@@ -0,0 +1,72 @@
-+/*
-+ * MIPL Mobile IPv6 Binding Cache header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _BCACHE_H
-+#define _BCACHE_H
-+
-+#include <linux/in6.h>
-+#include <linux/timer.h>
-+#include "hashlist.h"
-+
-+#define CACHE_ENTRY 1 /* this and HOME_REGISTRATION are the entry types */
-+#define HOME_REGISTRATION 2
-+#define ANY_ENTRY 3
-+
-+#define MIPV6_MAX_DESTUNREACH 5 /* Delete CN BCEs after 5 destination unreachables */
-+#define MIPV6_DEST_UNR_IVAL 10 /* What is the max interval of destination
-+ unreacahable error messages for them to be persistent*/
-+
-+struct mipv6_bce {
-+ struct hashlist_entry e;
-+ int ifindex; /* Interface identifier */
-+ struct in6_addr our_addr; /* our address (as seen by the MN) */
-+ struct in6_addr home_addr; /* MN home address */
-+ struct in6_addr coa; /* MN care-of address */
-+ unsigned long callback_time; /* time of expiration (in jiffies) */
-+ unsigned long br_callback_time; /* time for sending a BR (in jiffies) */
-+ int (*callback_function)(struct mipv6_bce *entry);
-+ __u8 type; /* home registration */
-+ __u8 router; /* mn is router */
-+ __u8 flags; /* flags received in BU */
-+ __u16 seq; /* sequence number */
-+ unsigned long last_br; /* time when last BR sent */
-+ unsigned long last_destunr; /* time when last ICMP destination unreachable received */
-+ int br_count; /* How many BRRs have sent */
-+ int destunr_count; /* Number of destination unreachables received */
-+};
-+
-+int mipv6_bcache_add(int ifindex, struct in6_addr *our_addr,
-+ struct in6_addr *home_addr, struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags, __u8 type);
-+
-+int mipv6_bcache_icmp_err(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ int destunr_count);
-+
-+int mipv6_bcache_delete(struct in6_addr *home_addr, struct in6_addr *our_addr,
-+ __u8 type);
-+
-+int mipv6_bcache_exists(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr);
-+
-+int mipv6_bcache_get(struct in6_addr *home_addr,
-+ struct in6_addr *our_addr,
-+ struct mipv6_bce *entry);
-+
-+int mipv6_bcache_iterate(int (*func)(void *, void *, unsigned long *), void *args);
-+
-+void mipv6_bcache_cleanup(int type);
-+
-+int mipv6_bcache_init(__u32 size);
-+
-+int mipv6_bcache_exit(void);
-+
-+#endif /* _BCACHE_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/bul.c
-@@ -0,0 +1,634 @@
-+/*
-+ * Binding update list
-+ *
-+ * Authors:
-+ * Juha Mynttinen <jmynttin@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Timer code cleaned up
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <net/ipv6.h>
-+#include <net/mipv6.h>
-+#include <linux/proc_fs.h>
-+
-+#include "bul.h"
-+#include "debug.h"
-+#include "hashlist.h"
-+#include "tunnel_mn.h"
-+#include "mobhdr.h"
-+
-+#define MIPV6_BUL_HASHSIZE 32
-+
-+rwlock_t bul_lock = RW_LOCK_UNLOCKED;
-+
-+struct mipv6_bul {
-+ struct hashlist *entries;
-+ struct timer_list callback_timer;
-+};
-+
-+static struct mipv6_bul bul;
-+
-+struct in6_addr_pair {
-+ struct in6_addr *a1;
-+ struct in6_addr *a2;
-+};
-+
-+/**********************************************************************
-+ *
-+ * Private functions
-+ *
-+ **********************************************************************/
-+
-+static int bul_compare(void *data, void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey;
-+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data;
-+
-+ if (ipv6_addr_cmp(&e->cn_addr, p->a1) == 0
-+ && ipv6_addr_cmp(&e->home_addr, p->a2) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+struct test_keys {
-+ struct in6_addr *addr;
-+ u8 *cookie;
-+};
-+
-+static int bul_compare_cookie(void *data, void *keys)
-+{
-+ struct test_keys *p = (struct test_keys *)keys;
-+ struct mipv6_bul_entry *e = (struct mipv6_bul_entry *)data;
-+
-+ if (ipv6_addr_cmp(&e->cn_addr, p->addr) == 0 && e->rr
-+ && memcmp(&e->rr->cot_cookie, p->cookie, 8) == 0)
-+ return 0;
-+ else
-+ return -1;
-+}
-+
-+static u32 bul_hash(void *hashkey)
-+{
-+ struct in6_addr_pair *p = (struct in6_addr_pair *)hashkey;
-+
-+ return p->a1->s6_addr32[0] ^
-+ p->a1->s6_addr32[1] ^
-+ p->a1->s6_addr32[2] ^
-+ p->a1->s6_addr32[3];
-+}
-+
-+static int bul_proc_info(char *buffer, char **start, off_t offset,
-+ int length);
-+
-+static struct mipv6_bul_entry *mipv6_bul_get_entry(void)
-+{
-+ DEBUG_FUNC();
-+ return ((struct mipv6_bul_entry *)
-+ hashlist_alloc(bul.entries, SLAB_ATOMIC));
-+}
-+
-+static void mipv6_bul_entry_free(struct mipv6_bul_entry *entry)
-+{
-+ DEBUG_FUNC();
-+
-+ if (entry->rr) {
-+ if (entry->rr->kbu)
-+ kfree(entry->rr->kbu);
-+ kfree(entry->rr);
-+ }
-+ if (entry->ops)
-+ kfree(entry->ops);
-+ hashlist_free(bul.entries, (void *)entry);
-+}
-+
-+static __inline__ int del_bul_entry_tnl(struct mipv6_bul_entry *entry)
-+{
-+ if (entry->flags & MIPV6_BU_F_HOME) {
-+ return mipv6_mv_tnl_to_ha(&entry->cn_addr,
-+ &entry->coa,
-+ &entry->home_addr);
-+ }
-+ return 0;
-+}
-+
-+static void timer_update(void)
-+{
-+ struct mipv6_bul_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ entry = hashlist_get_first(bul.entries);
-+
-+ while (entry && time_after_eq(jiffies, entry->callback_time)) {
-+ if (time_after_eq(jiffies, entry->expire) ||
-+ entry->callback(entry) != 0) {
-+ /*
-+ * Either the entry has expired, or the callback
-+ * indicated that it should be deleted.
-+ */
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+ mipv6_bul_entry_free(entry);
-+ DEBUG(DBG_INFO, "Entry deleted (was expired) from "
-+ "binding update list");
-+ } else {
-+ /* move entry to its right place in the hashlist */
-+ DEBUG(DBG_INFO, "Rescheduling");
-+ hashlist_reposition(bul.entries, (void *)entry,
-+ entry->callback_time);
-+ }
-+ entry = (struct mipv6_bul_entry *)
-+ hashlist_get_first(bul.entries);
-+ }
-+
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "bul empty, not setting a new timer");
-+ del_timer(&bul.callback_timer);
-+ } else {
-+ mod_timer(&bul.callback_timer, entry->callback_time);
-+ }
-+}
-+
-+static void timer_handler(unsigned long dummy)
-+{
-+ DEBUG_FUNC();
-+
-+ write_lock(&bul_lock);
-+ timer_update();
-+ write_unlock(&bul_lock);
-+}
-+
-+/**********************************************************************
-+ *
-+ * Public interface functions
-+ *
-+ **********************************************************************/
-+
-+/**
-+ * mipv6_bul_iterate - apply interator function to all entries
-+ * @func: function to apply
-+ * @args: extra arguments for iterator
-+ *
-+ * Applies @func for each entry in Binding Update List. Extra
-+ * arguments given in @args are also passed to the iterator function.
-+ * Caller must hold @bul_lock.
-+ **/
-+int mipv6_bul_iterate(hashlist_iterator_t func, void *args)
-+{
-+ DEBUG_FUNC();
-+
-+ return hashlist_iterate(bul.entries, args, func);
-+}
-+
-+/**
-+ * mipv6_bul_exists - check if Binding Update List entry exists
-+ * @cn: address to check
-+ *
-+ * Checks if Binding Update List has an entry for @cn. Returns true
-+ * if entry exists, false otherwise. Caller may not hold @bul_lock.
-+ **/
-+int mipv6_bul_exists(struct in6_addr *cn, struct in6_addr *haddr)
-+{
-+ int exists;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = cn;
-+ hashkey.a2 = haddr;
-+
-+ read_lock_bh(&bul_lock);
-+
-+ if (unlikely(bul.entries == NULL))
-+ exists = 0;
-+ else
-+ exists = (hashlist_get(bul.entries, &hashkey) != NULL);
-+
-+ read_unlock_bh(&bul_lock);
-+ return exists;
-+}
-+
-+/**
-+ * mipv6_bul_get - get Binding Update List entry
-+ * @cn_addr: CN address to search
-+ * @home_addr: home address to search
-+ *
-+ * Returns Binding Update List entry for @cn_addr if it exists.
-+ * Otherwise returns %NULL. Caller must hold @bul_lock.
-+ **/
-+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cn_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL)) {
-+ return NULL;
-+ }
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey);
-+
-+ return entry;
-+}
-+
-+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie(
-+ struct in6_addr *cn_addr, u8 *cookie)
-+{
-+ struct test_keys key;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL))
-+ return NULL;
-+ key.addr = cn_addr;
-+ key.cookie = cookie;
-+
-+ return (struct mipv6_bul_entry *)
-+ hashlist_get_ex(bul.entries, &key,
-+ bul_compare_cookie);
-+}
-+
-+/**
-+ * mipv6_bul_reschedule - reschedule Binding Update List entry
-+ * @entry: entry to reschedule
-+ *
-+ * Reschedules a Binding Update List entry. Must be called after
-+ * modifying entry lifetime. Caller must hold @bul_lock (write).
-+ **/
-+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry)
-+{
-+ DEBUG_FUNC();
-+
-+ hashlist_reposition(bul.entries,
-+ (void *)entry,
-+ entry->callback_time);
-+ timer_update();
-+}
-+
-+/**
-+ * mipv6_bul_add - add binding update to Binding Update List
-+ * @cn_addr: IPv6 address where BU was sent
-+ * @home_addr: Home address for this binding
-+ * @coa: Care-of address for this binding
-+ * @lifetime: expiration time of the binding in seconds
-+ * @seq: sequence number of the BU
-+ * @flags: %MIPV6_BU_F_* flags
-+ * @callback: callback function called on expiration
-+ * @callback_time: expiration time for callback
-+ * @state: binding send state
-+ * @delay: retransmission delay
-+ * @maxdelay: retransmission maximum delay
-+ * @ops: Mobility header options for BU
-+ * @rr: Return routability information
-+ *
-+ * Adds a binding update sent to @cn_addr for @home_addr to the
-+ * Binding Update List. If entry already exists, it is updated.
-+ * Entry is set to expire in @lifetime seconds. Entry has a callback
-+ * function @callback that is called at @callback_time. Entry @state
-+ * controls resending of this binding update and it can be set to
-+ * %ACK_OK, %RESEND_EXP or %ACK_ERROR. Returns a pointer to the newly
-+ * created or updated entry. Caller must hold @bul_lock (write).
-+ **/
-+struct mipv6_bul_entry *mipv6_bul_add(
-+ struct in6_addr *cn_addr, struct in6_addr *home_addr,
-+ struct in6_addr *coa,
-+ __u32 lifetime, __u16 seq, __u8 flags,
-+ int (*callback)(struct mipv6_bul_entry *entry),
-+ __u32 callback_time,
-+ __u8 state, __u32 delay, __u32 maxdelay,
-+ struct mipv6_mh_opt *ops,
-+ struct mipv6_rr_info *rr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ int update = 0;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ if (unlikely(bul.entries == NULL))
-+ return NULL;
-+
-+ if (cn_addr == NULL || home_addr == NULL || coa == NULL ||
-+ lifetime < 0 || callback == NULL || callback_time < 0 ||
-+ (state != ACK_OK && state != RESEND_EXP && state != ACK_ERROR) ||
-+ delay < 0 || maxdelay < 0) {
-+ DEBUG(DBG_ERROR, "invalid arguments");
-+ return NULL;
-+ }
-+ DEBUG(DBG_INFO, "cn_addr: %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "home_addr: %x:%x:%x:%x:%x:%x:%x:%x"
-+ "coaddr: %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(cn_addr),
-+ NIPV6ADDR(home_addr), NIPV6ADDR(coa));
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ /*
-+ * decide whether to add a new entry or update existing, also
-+ * check if there's room for a new entry when adding a new
-+ * entry (latter is handled by mipv6_bul_get_entry()
-+ */
-+ if ((entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey)) != NULL) {
-+ /* if an entry for this cn_addr exists (with smaller
-+ * seq than the new entry's seq), update it */
-+
-+ if (MIPV6_SEQ_GT(seq, entry->seq)) {
-+ DEBUG(DBG_INFO, "updating an existing entry");
-+ update = 1;
-+ } else {
-+ DEBUG(DBG_INFO, "smaller seq than existing, not updating");
-+ return NULL;
-+ }
-+ } else {
-+ entry = mipv6_bul_get_entry();
-+ if (entry == NULL) {
-+ DEBUG(DBG_WARNING, "binding update list full, can't add!!!");
-+ return NULL;
-+ }
-+ memset(entry, 0, sizeof(*entry));
-+ /* First BU send happens here, save count in the entry */
-+ entry->consecutive_sends = 1;
-+ }
-+
-+ if (!update) {
-+ ipv6_addr_copy(&(entry->cn_addr), cn_addr);
-+ ipv6_addr_copy(&(entry->home_addr), home_addr);
-+ entry->ops = ops;
-+ }
-+ /* Add Return Routability info to bul entry */
-+ if (rr) {
-+ if(entry->rr)
-+ kfree(entry->rr);
-+ entry->rr = rr;
-+ }
-+
-+ ipv6_addr_copy(&(entry->coa), coa);
-+ entry->lifetime = lifetime;
-+ if (lifetime)
-+ entry->expire = jiffies + lifetime * HZ;
-+ else if (flags & MIPV6_BU_F_ACK)
-+ entry->expire = jiffies + HOME_RESEND_EXPIRE * HZ;
-+ entry->seq = seq;
-+ entry->flags = flags;
-+ entry->lastsend = jiffies; /* current time = last use of the entry */
-+ entry->state = state;
-+ entry->delay = delay;
-+ entry->maxdelay = maxdelay;
-+ entry->callback_time = jiffies + callback_time * HZ;
-+ entry->callback = callback;
-+
-+ if (flags & MIPV6_BU_F_HOME &&
-+ mipv6_mv_tnl_to_ha(cn_addr, coa, home_addr)) {
-+ DEBUG(DBG_ERROR, "reconfiguration of the tunnel failed");
-+ }
-+ if (update) {
-+ DEBUG(DBG_INFO, "updating entry: %x", entry);
-+ hashlist_reposition(bul.entries, (void *)entry,
-+ entry->callback_time);
-+ } else {
-+ DEBUG(DBG_INFO, "adding entry: %x", entry);
-+
-+ hashkey.a1 = &entry->cn_addr;
-+ hashkey.a2 = &entry->home_addr;
-+
-+ if ((hashlist_add(bul.entries, &hashkey,
-+ entry->callback_time,
-+ entry)) < 0) {
-+ DEBUG(DBG_ERROR, "Hash add failed");
-+ mipv6_bul_entry_free(entry);
-+ return NULL;
-+ }
-+ }
-+ timer_update();
-+
-+ return entry;
-+}
-+
-+/**
-+ * mipv6_bul_delete - delete Binding Update List entry
-+ * @cn_addr: address for entry to delete
-+ *
-+ * Deletes the entry for @cn_addr from the Binding Update List.
-+ * Returns zero if entry was deleted succesfully, otherwise returns
-+ * negative. Caller may not hold @bul_lock.
-+ **/
-+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct in6_addr_pair hashkey;
-+
-+ DEBUG_FUNC();
-+
-+ hashkey.a1 = cn_addr;
-+ hashkey.a2 = home_addr;
-+
-+ write_lock(&bul_lock);
-+
-+ if (unlikely(bul.entries == NULL) ||
-+ (entry = (struct mipv6_bul_entry *)
-+ hashlist_get(bul.entries, &hashkey)) == NULL) {
-+ write_unlock(&bul_lock);
-+ DEBUG(DBG_INFO, "No such entry");
-+ return -ENOENT;
-+ }
-+
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+
-+ mipv6_bul_entry_free(entry);
-+ timer_update();
-+ write_unlock(&bul_lock);
-+
-+ DEBUG(DBG_INFO, "Binding update list entry deleted");
-+
-+ return 0;
-+}
-+
-+/**********************************************************************
-+ *
-+ * Proc interface functions
-+ *
-+ **********************************************************************/
-+
-+#define BUL_INFO_LEN 152
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args,
-+ unsigned long *sortkey)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *)args;
-+ struct mipv6_bul_entry *entry =
-+ (struct mipv6_bul_entry *)data;
-+ unsigned long callback_seconds;
-+
-+ DEBUG_FUNC();
-+
-+ if (entry == NULL) return ITERATOR_ERR;
-+
-+ if (time_after(jiffies, entry->callback_time))
-+ callback_seconds = 0;
-+ else
-+ callback_seconds = (entry->callback_time - jiffies) / HZ;
-+
-+ if (arg->skip < arg->offset / BUL_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ /* CN HoA CoA ExpInSecs SeqNum State Delay MaxDelay CallbackInSecs */
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%08x%08x%08x%08x %08x%08x%08x%08x %08x%08x%08x%08x\n"
-+ "%010lu %05d %02d %010d %010d %010lu\n",
-+ ntohl(entry->cn_addr.s6_addr32[0]),
-+ ntohl(entry->cn_addr.s6_addr32[1]),
-+ ntohl(entry->cn_addr.s6_addr32[2]),
-+ ntohl(entry->cn_addr.s6_addr32[3]),
-+ ntohl(entry->home_addr.s6_addr32[0]),
-+ ntohl(entry->home_addr.s6_addr32[1]),
-+ ntohl(entry->home_addr.s6_addr32[2]),
-+ ntohl(entry->home_addr.s6_addr32[3]),
-+ ntohl(entry->coa.s6_addr32[0]),
-+ ntohl(entry->coa.s6_addr32[1]),
-+ ntohl(entry->coa.s6_addr32[2]),
-+ ntohl(entry->coa.s6_addr32[3]),
-+ (entry->expire - jiffies) / HZ,
-+ entry->seq, entry->state, entry->delay,
-+ entry->maxdelay, callback_seconds);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+
-+/*
-+ * Callback function for proc filesystem.
-+ */
-+static int bul_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&bul_lock);
-+ hashlist_iterate(bul.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&bul_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % BUL_INFO_LEN;
-+
-+ args.len -= offset % BUL_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+/**********************************************************************
-+ *
-+ * Code module init/fini functions
-+ *
-+ **********************************************************************/
-+
-+int __init mipv6_bul_init(__u32 size)
-+{
-+ DEBUG_FUNC();
-+
-+ if (size < 1) {
-+ DEBUG(DBG_CRITICAL,
-+ "Binding update list size must be at least 1");
-+ return -EINVAL;
-+ }
-+ bul.entries = hashlist_create(MIPV6_BUL_HASHSIZE, size,
-+ sizeof(struct mipv6_bul_entry),
-+ "mip6_bul", NULL, NULL,
-+ bul_compare, bul_hash);
-+
-+ if (bul.entries == NULL) {
-+ DEBUG(DBG_CRITICAL, "Couldn't allocate memory for "
-+ "hashlist when creating a binding update list");
-+ return -ENOMEM;
-+ }
-+ init_timer(&bul.callback_timer);
-+ bul.callback_timer.data = 0;
-+ bul.callback_timer.function = timer_handler;
-+ proc_net_create("mip6_bul", 0, bul_proc_info);
-+ DEBUG(DBG_INFO, "Binding update list initialized");
-+ return 0;
-+}
-+
-+void __exit mipv6_bul_exit()
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct hashlist *entries;
-+
-+ DEBUG_FUNC();
-+
-+ proc_net_remove("mip6_bul");
-+
-+ write_lock_bh(&bul_lock);
-+
-+ DEBUG(DBG_INFO, "Stopping the bul timer");
-+ del_timer(&bul.callback_timer);
-+
-+ while ((entry = (struct mipv6_bul_entry *)
-+ hashlist_get_first(bul.entries)) != NULL) {
-+ hashlist_delete(bul.entries, (void *)entry);
-+
-+ del_bul_entry_tnl(entry);
-+
-+ mipv6_bul_entry_free(entry);
-+ }
-+ entries = bul.entries;
-+ bul.entries = NULL;
-+ write_unlock_bh(&bul_lock);
-+
-+ hashlist_destroy(entries);
-+
-+ DEBUG(DBG_INFO, "binding update list destroyed");
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/bul.h
-@@ -0,0 +1,91 @@
-+/*
-+ * MIPL Mobile IPv6 Binding Update List header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _BUL_H
-+#define _BUL_H
-+
-+#include "hashlist.h"
-+
-+#define ACK_OK 0x01
-+#define RESEND_EXP 0x02
-+#define ACK_ERROR 0x04
-+
-+#define HOME_RESEND_EXPIRE 3600
-+#define MIPV6_COOKIE_LEN 8
-+struct mipv6_rr_info {
-+ /* RR information */
-+ u16 rr_state; /* State of the RR */
-+ u16 rr_flags; /* Flags for the RR */
-+ u8 hot_cookie[MIPV6_COOKIE_LEN]; /* HoT Cookie */
-+ u8 cot_cookie[MIPV6_COOKIE_LEN]; /* CoT Cookie */
-+ u8 home_cookie[MIPV6_COOKIE_LEN]; /* Home Cookie */
-+ u8 careof_cookie[MIPV6_COOKIE_LEN]; /* Careof Cookie */
-+ u32 lastsend_hoti; /* When HoTI was last sent (jiffies) */
-+ u32 lastsend_coti; /* When CoTI was last sent (jiffies) */
-+ u32 home_time; /* when Care-of cookie was received */
-+ u32 careof_time; /* when Home cookie was received */
-+ int home_nonce_index; /* Home cookie nonce index */
-+ int careof_nonce_index; /* Care-of cookie nonce index */
-+ u8 *kbu; /* Binding authentication key */
-+};
-+struct mipv6_bul_entry {
-+ struct hashlist_entry e;
-+ struct in6_addr cn_addr; /* CN to which BU was sent */
-+ struct in6_addr home_addr; /* home address of this binding */
-+ struct in6_addr coa; /* care-of address of the sent BU */
-+
-+ unsigned long expire; /* entry's expiration time (jiffies) */
-+ __u32 lifetime; /* lifetime sent in this BU */
-+ __u32 lastsend; /* last time when BU sent (jiffies) */
-+ __u32 consecutive_sends; /* Number of consecutive BU's sent */
-+ __u16 seq; /* sequence number of the latest BU */
-+ __u8 flags; /* BU send flags */
-+ __u8 state; /* resend state */
-+ __u32 initdelay; /* initial ack wait */
-+ __u32 delay; /* current ack wait */
-+ __u32 maxdelay; /* maximum ack wait */
-+
-+ struct mipv6_rr_info *rr;
-+ struct mipv6_mh_opt *ops; /* saved option values */
-+
-+ unsigned long callback_time;
-+ int (*callback)(struct mipv6_bul_entry *entry);
-+};
-+
-+extern rwlock_t bul_lock;
-+
-+int mipv6_bul_init(__u32 size);
-+
-+void mipv6_bul_exit(void);
-+
-+struct mipv6_bul_entry *mipv6_bul_add(
-+ struct in6_addr *cn_addr, struct in6_addr *home_addr,
-+ struct in6_addr *coa, __u32 lifetime, __u16 seq, __u8 flags,
-+ int (*callback)(struct mipv6_bul_entry *entry), __u32 callback_time,
-+ __u8 state, __u32 delay, __u32 maxdelay, struct mipv6_mh_opt *ops,
-+ struct mipv6_rr_info *rr);
-+
-+int mipv6_bul_delete(struct in6_addr *cn_addr, struct in6_addr *home_addr);
-+
-+int mipv6_bul_exists(struct in6_addr *cnaddr, struct in6_addr *home_addr);
-+
-+struct mipv6_bul_entry *mipv6_bul_get(struct in6_addr *cnaddr,
-+ struct in6_addr *home_addr);
-+struct mipv6_bul_entry *mipv6_bul_get_by_ccookie(struct in6_addr *cn_addr,
-+ u8 *cookie);
-+
-+int bul_entry_expired(struct mipv6_bul_entry *bulentry);
-+
-+void mipv6_bul_reschedule(struct mipv6_bul_entry *entry);
-+
-+int mipv6_bul_iterate(int (*func)(void *, void *, unsigned long *), void *args);
-+
-+#endif /* BUL_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/config.h
-@@ -0,0 +1,72 @@
-+/*
-+ * Configuration parameters
-+ *
-+ * $Id$
-+ */
-+
-+#define MIPV6VERSION "D24"
-+#define MIPLVERSION "v1.0"
-+
-+#define CAP_CN 0x01
-+#define CAP_HA 0x02
-+#define CAP_MN 0x04
-+
-+struct mip6_conf {
-+ int capabilities;
-+ int debug_level;
-+ int accept_ret_rout;
-+ int max_rtr_reachable_time;
-+ int eager_cell_switching;
-+ int max_num_tunnels;
-+ int min_num_tunnels;
-+ int binding_refresh_advice;
-+ int bu_lladdr;
-+ int bu_keymgm;
-+ int bu_cn_ack;
-+};
-+
-+extern struct mip6_conf mip6node_cnf;
-+
-+struct mipv6_bce;
-+
-+struct mip6_func {
-+ void (*bce_home_add) (int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+ void (*bce_cache_add) (int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+ void (*bce_home_del) (struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu);
-+ void (*bce_cache_del) (struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu);
-+
-+ int (*bce_tnl_rt_add) (struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+ void (*bce_tnl_rt_del) (struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+ void (*proxy_del) (struct in6_addr *home_addr, struct mipv6_bce *entry);
-+ int (*proxy_create) (int flags, int ifindex, struct in6_addr *coa,
-+ struct in6_addr *our_addr, struct in6_addr *home_addr);
-+
-+ int (*icmpv6_dhaad_rep_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_dhaad_req_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_pfxadv_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_pfxsol_rcv) (struct sk_buff *skb);
-+ int (*icmpv6_paramprob_rcv) (struct sk_buff *skb);
-+
-+ int (*mn_use_hao) (struct in6_addr *daddr, struct in6_addr *saddr);
-+ void (*mn_check_tunneled_packet) (struct sk_buff *skb);
-+};
-+
-+extern struct mip6_func mip6_fn;
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/debug.h
-@@ -0,0 +1,112 @@
-+/*
-+ * MIPL Mobile IPv6 Debugging macros and functions
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _DEBUG_H
-+#define _DEBUG_H
-+
-+#include <linux/autoconf.h>
-+
-+/* priorities for different debug conditions */
-+
-+#define DBG_CRITICAL 0 /* unrecoverable error */
-+#define DBG_ERROR 1 /* error (recoverable) */
-+#define DBG_WARNING 2 /* unusual situation but not a real error */
-+#define DBG_INFO 3 /* generally useful information */
-+#define DBG_EXTRA 4 /* extra information */
-+#define DBG_FUNC_ENTRY 6 /* use to indicate function entry and exit */
-+#define DBG_DATADUMP 7 /* packet dumps, etc. lots of flood */
-+
-+/**
-+ * NIPV6ADDR - macro for IPv6 addresses
-+ * @addr: Network byte order IPv6 address
-+ *
-+ * Macro for printing IPv6 addresses. Used in conjunction with
-+ * printk() or derivatives (such as DEBUG macro).
-+ **/
-+#define NIPV6ADDR(addr) \
-+ ntohs(((u16 *)addr)[0]), \
-+ ntohs(((u16 *)addr)[1]), \
-+ ntohs(((u16 *)addr)[2]), \
-+ ntohs(((u16 *)addr)[3]), \
-+ ntohs(((u16 *)addr)[4]), \
-+ ntohs(((u16 *)addr)[5]), \
-+ ntohs(((u16 *)addr)[6]), \
-+ ntohs(((u16 *)addr)[7])
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+extern int mipv6_debug;
-+
-+/**
-+ * debug_print - print debug message
-+ * @debug_level: message priority
-+ * @fname: calling function's name
-+ * @fmt: printf-style formatting string
-+ *
-+ * Prints a debug message to system log if @debug_level is less or
-+ * equal to @mipv6_debug. Should always be called using DEBUG()
-+ * macro, not directly.
-+ **/
-+static void debug_print(int debug_level, const char *fname, const char* fmt, ...)
-+{
-+ char s[1024];
-+ va_list args;
-+
-+ if (mipv6_debug < debug_level)
-+ return;
-+
-+ va_start(args, fmt);
-+ vsprintf(s, fmt, args);
-+ printk("mip6[%s]: %s\n", fname, s);
-+ va_end(args);
-+}
-+
-+/**
-+ * debug_print_buffer - print arbitrary buffer to system log
-+ * @debug_level: message priority
-+ * @data: pointer to buffer
-+ * @len: number of bytes to print
-+ *
-+ * Prints @len bytes from buffer @data to system log. @debug_level
-+ * tells on which debug level message gets printed. For
-+ * debug_print_buffer() priority %DBG_DATADUMP should be used.
-+ **/
-+#define debug_print_buffer(debug_level,data,len) { \
-+ if (mipv6_debug >= debug_level) { \
-+ int i; \
-+ for (i=0; i<len; i++) { \
-+ if (i%16 == 0) printk("\n%04x: ", i); \
-+ printk("%02x ", ((unsigned char *)data)[i]); \
-+ } \
-+ printk("\n\n"); \
-+ } \
-+}
-+
-+#define DEBUG(x,y,z...) debug_print(x,__FUNCTION__,y,##z)
-+#define DEBUG_FUNC() \
-+DEBUG(DBG_FUNC_ENTRY, "%s(%d)/%s: ", __FILE__,__LINE__,__FUNCTION__)
-+
-+#else
-+#define DEBUG(x,y,z...)
-+#define DEBUG_FUNC()
-+#define debug_print_buffer(x,y,z)
-+#endif
-+
-+#undef ASSERT
-+#define ASSERT(expression) { \
-+ if (!(expression)) { \
-+ (void)printk(KERN_ERR \
-+ "Assertion \"%s\" failed: file \"%s\", function \"%s\", line %d\n", \
-+ #expression, __FILE__, __FUNCTION__, __LINE__); \
-+ BUG(); \
-+ } \
-+}
-+
-+#endif /* _DEBUG_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/exthdrs.c
-@@ -0,0 +1,394 @@
-+/*
-+ * Extension Header handling and adding code
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/types.h>
-+#include <linux/slab.h>
-+
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "stats.h"
-+#include "mobhdr.h"
-+#include "bcache.h"
-+#include "config.h"
-+
-+/**
-+ * mipv6_append_home_addr - Add Home Address Option
-+ * @opt: buffer for Home Address Option
-+ * @offset: offset from beginning of @opt
-+ * @addr: address for HAO
-+ *
-+ * Adds a Home Address Option to a packet. Option is stored in
-+ * @offset from beginning of @opt. The option is created but the
-+ * original source address in IPv6 header is left intact. The source
-+ * address will be changed from home address to CoA after the checksum
-+ * has been calculated in getfrag. Padding is done automatically, and
-+ * @opt must have allocated space for both actual option and pad.
-+ * Returns offset from @opt to end of options.
-+ **/
-+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr)
-+{
-+ int pad;
-+ struct mipv6_dstopt_homeaddr *ho;
-+
-+ DEBUG(DBG_DATADUMP, "HAO: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(addr));
-+
-+ pad = (6 - offset) & 7;
-+ mipv6_add_pad(opt + offset, pad);
-+
-+ ho = (struct mipv6_dstopt_homeaddr *)(opt + offset + pad);
-+ ho->type = MIPV6_TLV_HOMEADDR;
-+ ho->length = sizeof(*ho) - 2;
-+ ipv6_addr_copy(&ho->addr, addr);
-+
-+ return offset + pad + sizeof(*ho);
-+}
-+static inline int check_hao_validity(struct mipv6_dstopt_homeaddr *haopt,
-+ u8 *dst1,
-+ struct in6_addr *saddr,
-+ struct in6_addr *daddr)
-+{
-+ int addr_type = ipv6_addr_type(&haopt->addr);
-+ struct mipv6_bce bc_entry;
-+
-+ if (addr_type & IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type & IPV6_ADDR_UNICAST)) {
-+ DEBUG(DBG_INFO, "HAO with link local or non-unicast HoA, "
-+ "not sending BE to "
-+ "home address "
-+ "%x:%x:%x:%x:%x:%x:%x:%x ",
-+ "care-of address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&haopt->addr),
-+ NIPV6ADDR(saddr));
-+ return -EINVAL;
-+ } else if (dst1[0] != IPPROTO_MOBILITY &&
-+ (mipv6_bcache_get(&haopt->addr,
-+ daddr, &bc_entry) != 0 ||
-+ ipv6_addr_cmp(saddr, &bc_entry.coa))) {
-+ DEBUG(DBG_INFO, "HAO without binding or incorrect CoA, "
-+ "sending BE code 1: "
-+ "home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ "to care-of address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&haopt->addr),
-+ NIPV6ADDR(saddr));
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+/**
-+ * mipv6_handle_homeaddr - Home Address Destination Option handler
-+ * @skb: packet buffer
-+ * @optoff: offset to where option begins
-+ *
-+ * Handles Home Address Option in IPv6 Destination Option header.
-+ * Packet and offset to option are passed. If HAO is used without
-+ * binding, sends a Binding Error code 1. When sending BE, notify bit
-+ * is cleared to prevent IPv6 error handling from sending ICMP
-+ * Parameter Problem. Returns 1 on success, otherwise zero.
-+ **/
-+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff)
-+{
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr coaddr;
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
-+ struct mipv6_dstopt_homeaddr *haopt =
-+ (struct mipv6_dstopt_homeaddr *) &skb->nh.raw[optoff];
-+ u8 *dst1;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ if (haopt->length != sizeof(*haopt) - 2) {
-+ DEBUG(DBG_WARNING, "HAO has invalid length");
-+ MIPV6_INC_STATS(n_ha_drop.invalid);
-+ return 0;
-+ }
-+ dst1 = (u8 *)skb->h.raw;
-+ err = check_hao_validity(haopt, dst1, saddr, &skb->nh.ipv6h->daddr);
-+
-+ if (err) {
-+ haopt->type &= ~(0x80); /* clear notify bit */
-+ if (err == -ENOENT)
-+ mipv6_send_be(&skb->nh.ipv6h->daddr, saddr,
-+ &haopt->addr, MIPV6_BE_HAO_WO_BINDING);
-+ MIPV6_INC_STATS(n_ha_drop.misc);
-+ return 0;
-+ }
-+ ipv6_addr_copy(&coaddr, saddr);
-+ ipv6_addr_copy(saddr, &haopt->addr);
-+ ipv6_addr_copy(&haopt->addr, &coaddr);
-+ opt->hao = optoff;
-+ if (mip6_fn.mn_check_tunneled_packet != NULL)
-+ mip6_fn.mn_check_tunneled_packet(skb);
-+
-+ MIPV6_INC_STATS(n_ha_rcvd);
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_icmp_swap_addrs - Switch HAO and src and RT2 and dest for ICMP errors
-+ * @skb: packet buffer
-+ *
-+ * Reset the source address and the Home Address option in skb before
-+ * appending it to an ICMP error message, so original packet appears
-+ * in the error message rather than mangled.
-+ **/
-+void mipv6_icmp_swap_addrs(struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct in6_addr tmp;
-+ struct in6_addr *hoa;
-+ DEBUG_FUNC();
-+ if (opt->srcrt2) {
-+ struct rt2_hdr *rt2;
-+ rt2 = (struct rt2_hdr *)(skb->nh.raw + opt->srcrt2);
-+ hoa = &rt2->addr;
-+
-+ ipv6_addr_copy(&tmp, hoa);
-+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->daddr);
-+ ipv6_addr_copy(&skb->nh.ipv6h->daddr, &tmp);
-+ rt2->rt_hdr.segments_left++;
-+ skb->nh.ipv6h->hop_limit++;
-+ }
-+ if (opt->hao) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao);
-+ hoa = &hao->addr;
-+
-+ ipv6_addr_copy(&tmp, hoa);
-+ ipv6_addr_copy(hoa, &skb->nh.ipv6h->saddr);
-+ ipv6_addr_copy(&skb->nh.ipv6h->saddr, &tmp);
-+ }
-+}
-+
-+/**
-+ * mipv6_append_rt2hdr - Add Type 2 Routing Header
-+ * @rt: buffer for new routing header
-+ * @addr: intermediate hop address
-+ *
-+ * Adds a Routing Header Type 2 in a packet. Stores newly created
-+ * routing header in buffer @rt. Type 2 RT only carries one address,
-+ * so there is no need to process old routing header. @rt must have
-+ * allocated space for 24 bytes.
-+ **/
-+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *rt, struct in6_addr *addr)
-+{
-+ struct rt2_hdr *rt2 = (struct rt2_hdr *)rt;
-+
-+ DEBUG(DBG_DATADUMP, "RT2: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(addr));
-+
-+ if (ipv6_addr_type(addr) == IPV6_ADDR_MULTICAST) {
-+ DEBUG(DBG_ERROR, "destination address not unicast");
-+ return;
-+ }
-+
-+ memset(rt2, 0, sizeof(*rt2));
-+ rt2->rt_hdr.type = 2;
-+ rt2->rt_hdr.hdrlen = 2;
-+ rt2->rt_hdr.segments_left = 1;
-+ ipv6_addr_copy(&rt2->addr, addr);
-+}
-+
-+/**
-+ * mipv6_append_dst1opts - Add Destination Option (1) Headers
-+ * @dst1opt: buffer for new destination options
-+ * @saddr: address for Home Address Option
-+ * @old_dst1opt: old destination options
-+ * @len: length of options
-+ *
-+ * Adds Destination Option (1) Header to a packet. New options are
-+ * stored in @dst1opt. If old destination options exist, they are
-+ * copied from @old_dst1opt. Only Home Address Option is destination
-+ * option. @dstopt must have allocated space for @len bytes. @len
-+ * includes Destination Option Header (2 bytes), Home Address Option
-+ * (18 bytes) and possible HAO pad (8n+6).
-+ **/
-+/*
-+ * ISSUE: Home Address Destination Option should really be added to a
-+ * new destination option header specified in Mobile IPv6 spec which
-+ * should be placed after routing header(s), but before fragmentation
-+ * header. Putting HAO in DO1 works for now, but support for the new
-+ * placement should be added to the IPv6 stack.
-+ */
-+void
-+mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr,
-+ struct ipv6_opt_hdr *old_dst1opt, int len)
-+{
-+ int offset;
-+
-+ if (old_dst1opt) {
-+ memcpy(dst1opt, old_dst1opt, ipv6_optlen(old_dst1opt));
-+ offset = ipv6_optlen(old_dst1opt);
-+ } else {
-+ offset = sizeof (*dst1opt);
-+ }
-+ dst1opt->hdrlen = (len >> 3) - 1;
-+ mipv6_append_home_addr((__u8 *) dst1opt, offset, saddr);
-+}
-+
-+/**
-+ * mipv6_modify_txoptions - Modify outgoing packets
-+ * @sk: socket
-+ * @skb: packet buffer for outgoing packet
-+ * @old_opt: transmit options
-+ * @fl: packet flow structure
-+ * @dst: pointer to destination cache entry
-+ *
-+ * Adds Home Address Option (for MN packets, when not at home) and
-+ * Routing Header Type 2 (for CN packets when sending to an MN) to
-+ * data packets. Old extension headers are copied from @old_opt (if
-+ * any). Extension headers are _explicitly_ added for packets with
-+ * Mobility Header. Returns the new header structure, or old if no
-+ * changes.
-+ **/
-+struct ipv6_txoptions *
-+mipv6_modify_txoptions(struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *old_opt, struct flowi *fl,
-+ struct dst_entry **dst)
-+{
-+ struct ipv6_opt_hdr *old_hopopt = NULL;
-+ struct ipv6_opt_hdr *old_dst1opt = NULL;
-+ struct ipv6_rt_hdr *old_srcrt = NULL;
-+
-+ int srcrtlen = 0, dst1len = 0;
-+ int tot_len, use_hao = 0;
-+ struct ipv6_txoptions *opt;
-+ struct mipv6_bce bc_entry;
-+ struct in6_addr tmpaddr, *saddr, *daddr, coaddr;
-+ __u8 *opt_ptr;
-+
-+ DEBUG_FUNC();
-+
-+ if (fl->proto == IPPROTO_MOBILITY) return old_opt;
-+ /*
-+ * we have to be prepared to the fact that saddr might not be present,
-+ * if that is the case, we acquire saddr just as kernel does.
-+ */
-+ saddr = fl ? fl->fl6_src : NULL;
-+ daddr = fl ? fl->fl6_dst : NULL;
-+
-+ if (daddr == NULL)
-+ return old_opt;
-+ if (saddr == NULL) {
-+ int err = ipv6_get_saddr(NULL, daddr, &tmpaddr);
-+ if (err)
-+ return old_opt;
-+ else
-+ saddr = &tmpaddr;
-+ }
-+
-+ DEBUG(DBG_DATADUMP,
-+ "dest. address of packet: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(daddr));
-+ DEBUG(DBG_DATADUMP, " and src. address: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(saddr));
-+
-+ if (old_opt) {
-+ old_hopopt = old_opt->hopopt;
-+ old_dst1opt = old_opt->dst1opt;
-+ old_srcrt = old_opt->srcrt;
-+ }
-+
-+ if (mip6_fn.mn_use_hao != NULL)
-+ use_hao = mip6_fn.mn_use_hao(daddr, saddr);
-+
-+ if (use_hao) {
-+ if (old_dst1opt)
-+ dst1len = ipv6_optlen(old_dst1opt);
-+ dst1len += sizeof(struct mipv6_dstopt_homeaddr) +
-+ ((6 - dst1len) & 7); /* padding */
-+ }
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0)
-+ srcrtlen = sizeof(struct rt2_hdr);
-+
-+ if ((tot_len = srcrtlen + dst1len) == 0) {
-+ return old_opt;
-+ }
-+
-+ tot_len += sizeof(*opt);
-+
-+ if (!(opt = kmalloc(tot_len, GFP_ATOMIC))) {
-+ return NULL;
-+ }
-+ memset(opt, 0, tot_len);
-+ opt->tot_len = tot_len;
-+ opt_ptr = (__u8 *) (opt + 1);
-+
-+ if (old_srcrt) {
-+ opt->srcrt = old_srcrt;
-+ opt->opt_nflen += ipv6_optlen(old_srcrt);
-+ }
-+
-+ if (srcrtlen) {
-+ DEBUG(DBG_DATADUMP, "Binding exists. Adding routing header");
-+
-+ opt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
-+ opt->opt_nflen += srcrtlen;
-+ opt_ptr += srcrtlen;
-+
-+ /*
-+ * Append care-of-address to routing header (original
-+ * destination address is home address, the first
-+ * source route segment gets put to the destination
-+ * address and the home address gets to the last
-+ * segment of source route (just as it should))
-+ */
-+
-+ ipv6_addr_copy(&coaddr, &bc_entry.coa);
-+
-+ mipv6_append_rt2hdr(opt->srcrt2, &coaddr);
-+
-+ /*
-+ * reroute output (we have to do this in case of TCP
-+ * segment) unless a routing header of type 0 is also added
-+ */
-+ if (dst && !opt->srcrt) {
-+ struct in6_addr *tmp = fl->fl6_dst;
-+ fl->fl6_dst = &coaddr;
-+
-+ dst_release(*dst);
-+ *dst = ip6_route_output(sk, fl);
-+ if (skb)
-+ skb->dst = *dst;
-+ fl->fl6_dst = tmp;
-+
-+ DEBUG(DBG_DATADUMP, "Rerouted outgoing packet");
-+ }
-+ }
-+
-+ /* Only home address option is inserted to first dst opt header */
-+ if (dst1len) {
-+ opt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
-+ opt->opt_flen += dst1len;
-+ opt_ptr += dst1len;
-+ mipv6_append_dst1opts(opt->dst1opt, saddr,
-+ old_dst1opt, dst1len);
-+ opt->mipv6_flags = MIPV6_SND_HAO;
-+ } else if (old_dst1opt) {
-+ opt->dst1opt = old_dst1opt;
-+ opt->opt_flen += ipv6_optlen(old_dst1opt);
-+ }
-+ if (old_hopopt) {
-+ opt->hopopt = old_hopopt;
-+ opt->opt_nflen += ipv6_optlen(old_hopopt);
-+ }
-+
-+ return opt;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/exthdrs.h
-@@ -0,0 +1,47 @@
-+/*
-+ * MIPL Mobile IPv6 Extension Headers header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MIPV6_EXTHDRS_H
-+#define _MIPV6_EXTHDRS_H
-+
-+struct in6_addr;
-+struct sk_buff;
-+struct ipv6_rt_hdr;
-+struct ipv6_opt_hdr;
-+struct ipv6_txoptions;
-+struct flowi;
-+struct dst_entry;
-+/*
-+ * Home Address Destination Option function prototypes
-+ */
-+int mipv6_append_home_addr(__u8 *opt, int offset, struct in6_addr *addr);
-+
-+int mipv6_handle_homeaddr(struct sk_buff *skb, int optoff);
-+
-+void mipv6_icmp_swap_addrs(struct sk_buff *skb);
-+
-+/*
-+ * Creates a routing header of type 2.
-+ */
-+void mipv6_append_rt2hdr(struct ipv6_rt_hdr *srcrt, struct in6_addr *addr);
-+
-+/* Function to add the first destination option header, which may
-+ * include a home address option.
-+ */
-+void mipv6_append_dst1opts(struct ipv6_opt_hdr *dst1opt, struct in6_addr *saddr,
-+ struct ipv6_opt_hdr *old_dst1opt, int len);
-+
-+struct ipv6_txoptions *mipv6_modify_txoptions(
-+ struct sock *sk, struct sk_buff *skb,
-+ struct ipv6_txoptions *old_opt, struct flowi *fl,
-+ struct dst_entry **dst);
-+
-+#endif /* _MIPV6_EXTHDRS_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/ha.c
-@@ -0,0 +1,553 @@
-+/*
-+ * Home-agent functionality
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Henrik Petander <lpetande@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes: Venkata Jagana,
-+ * Krishna Kumar : Statistics fix
-+ * Masahide Nakamura : Use of mipv6_forward
-+ *
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_ether.h>
-+#include <linux/netdevice.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv6.h>
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif
-+
-+#include <net/neighbour.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_fib.h>
-+#include <net/ip6_route.h>
-+#include <net/ndisc.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+
-+#include "tunnel_ha.h"
-+#include "bcache.h"
-+#include "stats.h"
-+#include "debug.h"
-+#include "util.h"
-+#include "ha.h"
-+#include "config.h"
-+#include "mobhdr.h"
-+
-+static int mipv6_ha_tunnel_sitelocal = 0;
-+
-+#ifdef CONFIG_SYSCTL
-+
-+static struct ctl_table_header *mipv6_ha_sysctl_header;
-+
-+static struct mipv6_ha_sysctl_table
-+{
-+ struct ctl_table_header *sysctl_header;
-+ ctl_table mipv6_vars[3];
-+ ctl_table mipv6_mobility_table[2];
-+ ctl_table mipv6_proto_table[2];
-+ ctl_table mipv6_root_table[2];
-+} mipv6_ha_sysctl = {
-+ NULL,
-+
-+ {{NET_IPV6_MOBILITY_TUNNEL_SITELOCAL, "tunnel_sitelocal",
-+ &mipv6_ha_tunnel_sitelocal, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {0}},
-+
-+ {{NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_vars}, {0}},
-+ {{NET_IPV6, "ipv6", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_mobility_table}, {0}},
-+ {{CTL_NET, "net", NULL, 0, 0555,
-+ mipv6_ha_sysctl.mipv6_proto_table}, {0}}
-+};
-+
-+#endif /* CONFIG_SYSCTL */
-+
-+
-+/* this is defined in kernel IPv6 module (sockglue.c) */
-+extern struct packet_type ipv6_packet_type;
-+
-+/* mipv6_forward: Intercept NS packets destined to home address of MN */
-+int mipv6_forward(struct sk_buff *skb)
-+{
-+ struct ipv6hdr *ipv6h;
-+ struct in6_addr *daddr, *saddr;
-+ __u8 nexthdr;
-+ int nhoff;
-+
-+ if (skb == NULL) return 0;
-+
-+ ipv6h = skb->nh.ipv6h;
-+ daddr = &ipv6h->daddr;
-+ saddr = &ipv6h->saddr;
-+
-+ nexthdr = ipv6h->nexthdr;
-+ nhoff = sizeof(*ipv6h);
-+
-+ if (ipv6_ext_hdr(nexthdr))
-+ nhoff = ipv6_skip_exthdr(skb, nhoff, &nexthdr,
-+ skb->len - sizeof(*ipv6h));
-+
-+ /* Do not to forward Neighbor Solicitation to Home Address of MN */
-+ if (nexthdr == IPPROTO_ICMPV6) {
-+ struct icmp6hdr *icmp6h;
-+ int dest_type;
-+
-+ if (nhoff < 0 || !pskb_may_pull(skb, nhoff +
-+ sizeof(struct icmp6hdr))) {
-+ kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ dest_type = ipv6_addr_type(daddr);
-+ icmp6h = (struct icmp6hdr *)&skb->nh.raw[nhoff];
-+
-+ /* Intercepts NS to HoA of MN */
-+
-+ if ((icmp6h->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) ||
-+ ((dest_type & IPV6_ADDR_MULTICAST) &&
-+ (icmp6h->icmp6_type == NDISC_ROUTER_ADVERTISEMENT))) {
-+ ip6_input(skb);
-+ } else {
-+ ip6_forward(skb);
-+ }
-+ } else {
-+ ip6_forward(skb);
-+ }
-+ return 0;
-+}
-+
-+
-+/**
-+ * mipv6_proxy_nd_rem - stop acting as a proxy for @home_address
-+ * @home_addr: address to remove
-+ * @ha_addr: home agent's address on home link
-+ * @linklocal: link-local compatibility bit
-+ *
-+ * When Home Agent acts as a proxy for an address it must leave the
-+ * solicited node multicast group for that address and stop responding
-+ * to neighbour solicitations.
-+ **/
-+static int mipv6_proxy_nd_rem(struct in6_addr *home_addr,
-+ int ifindex, int linklocal)
-+{
-+ /* When MN returns home HA leaves the solicited mcast groups
-+ * for MNs home addresses
-+ */
-+ int err;
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_ERROR, "couldn't get dev");
-+ return -ENODEV;
-+ }
-+#if 1 /* TEST */
-+ /* Remove link-local entry */
-+ if (linklocal) {
-+ struct in6_addr ll_addr;
-+ mipv6_generate_ll_addr(&ll_addr, home_addr);
-+ if ((err = pneigh_delete(&nd_tbl, &ll_addr, dev)) < 0) {
-+ DEBUG(DBG_INFO,
-+ "peigh_delete failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&ll_addr));
-+ }
-+ }
-+#endif
-+ /* Remove global (or site-local) entry */
-+ if ((err = pneigh_delete(&nd_tbl, home_addr, dev)) < 0) {
-+ DEBUG(DBG_INFO,
-+ "peigh_delete failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ }
-+ dev_put(dev);
-+ return err;
-+}
-+
-+/**
-+ * mipv6_proxy_nd - join multicast group for this address
-+ * @home_addr: address to defend
-+ * @ha_addr: home agent's address on home link
-+ * @linklocal: link-local compatibility bit
-+ *
-+ * While Mobile Node is away from home, Home Agent acts as a proxy for
-+ * @home_address. HA responds to neighbour solicitations for @home_address
-+ * thus getting all packets destined to home address of MN.
-+ **/
-+static int mipv6_proxy_nd(struct in6_addr *home_addr,
-+ int ifindex, int linklocal)
-+{
-+ /* The HA sends a proxy ndisc_na message to all hosts on MN's
-+ * home subnet by sending a neighbor advertisement with the
-+ * home address or all addresses of the mobile node if the
-+ * prefix is not 0. The addresses are formed by combining the
-+ * suffix or the host part of the address with each subnet
-+ * prefix that exists in the home subnet
-+ */
-+
-+ /* Since no previous entry for MN exists a proxy_nd advertisement
-+ * is sent to all nodes link local multicast address
-+ */
-+ int err = -1;
-+
-+ struct net_device *dev;
-+ struct in6_addr na_saddr;
-+ struct in6_addr ll_addr;
-+ struct pneigh_entry *ll_pneigh;
-+ struct in6_addr mcdest;
-+ int send_ll_na = 0;
-+ int inc_opt = 1;
-+ int solicited = 0;
-+ int override = 1;
-+
-+ DEBUG_FUNC();
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_ERROR, "couldn't get dev");
-+ return -ENODEV;
-+ }
-+
-+ if (!pneigh_lookup(&nd_tbl, home_addr, dev, 1)) {
-+ DEBUG(DBG_INFO,
-+ "peigh_lookup failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ goto free_dev;
-+ }
-+#if 1 /* TEST */
-+ if (linklocal) {
-+ mipv6_generate_ll_addr(&ll_addr, home_addr);
-+
-+ if ((ll_pneigh = pneigh_lookup(&nd_tbl, &ll_addr,
-+ dev, 1)) == NULL) {
-+ DEBUG(DBG_INFO,
-+ "peigh_lookup failed for "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&ll_addr));
-+ pneigh_delete(&nd_tbl, home_addr, dev);
-+ goto free_dev;
-+ } else {
-+ send_ll_na = 1;
-+ }
-+ } else {
-+ ll_pneigh = NULL;
-+ }
-+#endif
-+ /* Proxy neighbor advertisement of MN's home address
-+ * to all nodes solicited multicast address
-+ */
-+ if (!ipv6_get_lladdr(dev, &na_saddr)) {
-+ ipv6_addr_all_nodes(&mcdest);
-+ ndisc_send_na(dev, NULL, &mcdest, home_addr, 0,
-+ solicited, override, inc_opt);
-+#if 1 /* TEST */
-+ if (send_ll_na) {
-+ ndisc_send_na(dev, NULL, &mcdest, &ll_addr,
-+ 0, solicited, override, inc_opt);
-+ }
-+#endif
-+ err = 0;
-+ } else {
-+ DEBUG(DBG_ERROR, "failed to get link local address for sending proxy NA");
-+ }
-+free_dev:
-+ dev_put(dev);
-+ return err;
-+
-+}
-+
-+struct inet6_ifaddr *is_on_link_ipv6_address(struct in6_addr *mn_haddr,
-+ struct in6_addr *ha_addr)
-+{
-+ struct inet6_ifaddr *ifp;
-+ struct inet6_dev *in6_dev;
-+ struct inet6_ifaddr *oifp = NULL;
-+
-+ if ((ifp = ipv6_get_ifaddr(ha_addr, 0)) == NULL)
-+ return NULL;
-+
-+ if ((in6_dev = ifp->idev) != NULL) {
-+ in6_dev_hold(in6_dev);
-+ oifp = in6_dev->addr_list;
-+ while (oifp != NULL) {
-+ spin_lock(&oifp->lock);
-+ if (mipv6_prefix_compare(&oifp->addr, mn_haddr,
-+ oifp->prefix_len) &&
-+ !(oifp->flags & IFA_F_TENTATIVE)) {
-+ spin_unlock(&oifp->lock);
-+ DEBUG(DBG_INFO, "Home Addr Opt: on-link");
-+ in6_ifa_hold(oifp);
-+ break;
-+ }
-+ spin_unlock(&oifp->lock);
-+ oifp = oifp->if_next;
-+ }
-+ in6_dev_put(in6_dev);
-+ }
-+ in6_ifa_put(ifp);
-+/* DEBUG(DBG_WARNING, "Home Addr Opt NOT on-link"); */
-+ return oifp;
-+
-+}
-+
-+/*
-+ * Lifetime checks. ifp->valid_lft >= ifp->prefered_lft always (see addrconf.c)
-+ * Returned value is in seconds.
-+ */
-+
-+static __u32 get_min_lifetime(struct inet6_ifaddr *ifp, __u32 lifetime)
-+{
-+ __u32 rem_lifetime = 0;
-+ unsigned long now = jiffies;
-+
-+ if (ifp->valid_lft == 0) {
-+ rem_lifetime = lifetime;
-+ } else {
-+ __u32 valid_lft_left =
-+ ifp->valid_lft - ((now - ifp->tstamp) / HZ);
-+ rem_lifetime =
-+ min_t(unsigned long, valid_lft_left, lifetime);
-+ }
-+
-+ return rem_lifetime;
-+}
-+
-+#define MAX_LIFETIME 1000
-+
-+/**
-+ * mipv6_lifetime_check - check maximum lifetime is not exceeded
-+ * @lifetime: lifetime to check
-+ *
-+ * Checks @lifetime does not exceed %MAX_LIFETIME. Returns @lifetime
-+ * if not exceeded, otherwise returns %MAX_LIFETIME.
-+ **/
-+static int mipv6_lifetime_check(int lifetime)
-+{
-+ return (lifetime > MAX_LIFETIME) ? MAX_LIFETIME : lifetime;
-+}
-+
-+/* Generic routine handling finish of BU processing */
-+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex, __u8 ba_status,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ int err;
-+
-+ if (ba_status >= REASON_UNSPECIFIED) {
-+ /* DAD failed */
-+ goto out;
-+ }
-+
-+ ba_lifetime = get_min_lifetime(ifp, ba_lifetime);
-+ ba_lifetime = mipv6_lifetime_check(ba_lifetime);
-+
-+ if ((err = mipv6_bcache_add(ifindex, daddr, haddr, coa,
-+ ba_lifetime, sequence, flags,
-+ HOME_REGISTRATION)) != 0 ) {
-+ DEBUG(DBG_WARNING, "home reg failed.");
-+
-+ if (err == -ENOMEDIUM)
-+ return;
-+
-+ ba_status = INSUFFICIENT_RESOURCES;
-+ } else {
-+ DEBUG(DBG_INFO, "home reg succeeded.");
-+ }
-+
-+ DEBUG(DBG_DATADUMP, "home_addr: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(haddr));
-+ DEBUG(DBG_DATADUMP, "coa: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(coa));
-+ DEBUG(DBG_DATADUMP, "lifet:%d, seq:%d", ba_lifetime, sequence);
-+out:
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence,
-+ ba_lifetime, k_bu);
-+}
-+
-+static int ha_proxy_create(int flags, int ifindex, struct in6_addr *coa,
-+ struct in6_addr *our_addr, struct in6_addr *home_addr)
-+{
-+ int ret;
-+
-+ if ((ret = mipv6_add_tnl_to_mn(coa, our_addr, home_addr)) <= 0) {
-+ if (ret != -ENOMEDIUM) {
-+ DEBUG(DBG_ERROR, "unable to configure tunnel to MN!");
-+ }
-+ return -1;
-+ }
-+ if (mipv6_proxy_nd(home_addr, ifindex,
-+ flags & MIPV6_BU_F_LLADDR) != 0) {
-+ DEBUG(DBG_ERROR, "mipv6_proxy_nd failed!");
-+ mipv6_del_tnl_to_mn(coa, our_addr, home_addr);
-+ return -2;
-+ }
-+ return 0;
-+}
-+
-+static void ha_proxy_del(struct in6_addr *home_addr, struct mipv6_bce *entry)
-+{
-+ if (mipv6_proxy_nd_rem(&entry->home_addr, entry->ifindex,
-+ entry->flags & MIPV6_BU_F_LLADDR) == 0) {
-+ DEBUG(DBG_INFO, "proxy_nd succ");
-+ } else {
-+ DEBUG(DBG_INFO, "proxy_nd fail");
-+ }
-+ mipv6_del_tnl_to_mn(&entry->coa, &entry->our_addr, home_addr);
-+}
-+
-+static void bc_home_add(int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 lifetime, __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+ struct inet6_ifaddr *ifp = NULL;
-+ __u8 ba_status = SUCCESS;
-+
-+ DEBUG_FUNC();
-+
-+ ifp = is_on_link_ipv6_address(haddr, daddr);
-+
-+ if (ifp == NULL) {
-+ ba_status = NOT_HOME_SUBNET;
-+ } else if (((ipv6_addr_type(haddr) & IPV6_ADDR_SITELOCAL) ||
-+ (ipv6_addr_type(coa) & IPV6_ADDR_SITELOCAL))
-+ && !mipv6_ha_tunnel_sitelocal) {
-+ /* Site-local home or care-of addresses are not
-+ accepted by default */
-+ ba_status = ADMINISTRATIVELY_PROHIBITED;
-+ } else {
-+ int ret;
-+
-+ ifindex = ifp->idev->dev->ifindex;
-+
-+ if ((ret = mipv6_dad_start(ifp, ifindex, daddr,
-+ haddr, coa, rep_coa, lifetime,
-+ sequence, flags)) < 0) {
-+ /* An error occurred */
-+ ba_status = -ret;
-+ } else if (ret) {
-+ /* DAD is needed to be performed. */
-+ in6_ifa_put(ifp);
-+ return;
-+ }
-+ }
-+
-+ mipv6_bu_finish(ifp, ifindex, ba_status, daddr, haddr, coa,
-+ rep_coa, lifetime, sequence, flags, k_bu);
-+ if (ifp)
-+ in6_ifa_put(ifp);
-+}
-+
-+static void bc_home_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ __u8 status = SUCCESS;
-+ struct mipv6_bce bce;
-+
-+ /* Primary Care-of Address Deregistration */
-+ if (mipv6_bcache_get(haddr, daddr, &bce) < 0) {
-+ DEBUG(DBG_INFO, "entry is not in cache");
-+ status = NOT_HA_FOR_MN;
-+ } else {
-+ ha_proxy_del(&bce.home_addr, &bce);
-+ mipv6_bcache_delete(haddr, daddr, HOME_REGISTRATION);
-+ }
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence, 0, k_bu);
-+}
-+
-+extern int mipv6_ra_rcv_ptr(struct sk_buff *skb, struct icmp6hdr *msg);
-+
-+
-+static int
-+mipv6_ha_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_encapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_ha_tnl_xmit_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_ENCAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_ha_tnl_xmit_stats_hook
-+};
-+
-+static int
-+mipv6_ha_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_decapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_ha_tnl_rcv_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_ha_tnl_rcv_stats_hook
-+};
-+
-+static struct mip6_func old;
-+
-+int __init mipv6_ha_init(void)
-+{
-+ DEBUG_FUNC();
-+
-+#ifdef CONFIG_SYSCTL
-+ if (!(mipv6_ha_sysctl_header =
-+ register_sysctl_table(mipv6_ha_sysctl.mipv6_root_table, 0)))
-+ printk(KERN_ERR "Failed to register sysctl handlers!");
-+#endif
-+ memcpy(&old, &mip6_fn, sizeof(struct mip6_func));
-+ mip6_fn.bce_home_add = bc_home_add;
-+ mip6_fn.bce_home_del = bc_home_delete;
-+ mip6_fn.proxy_del = ha_proxy_del;
-+ mip6_fn.proxy_create = ha_proxy_create;
-+ /* register packet interception hooks */
-+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_ha_tnl_rcv_stats_ops);
-+ return 0;
-+}
-+
-+void __exit mipv6_ha_exit(void)
-+{
-+ DEBUG_FUNC();
-+
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_ha_sysctl_header);
-+#endif
-+
-+ /* remove packet interception hooks */
-+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_rcv_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_ha_tnl_xmit_stats_ops);
-+
-+ mip6_fn.bce_home_add = old.bce_home_add;
-+ mip6_fn.bce_home_del = old.bce_home_del;
-+ mip6_fn.proxy_del = old.proxy_del;
-+ mip6_fn.proxy_create = old.proxy_create;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/ha.h
-@@ -0,0 +1,39 @@
-+/*
-+ * MIPL Mobile IPv6 Home Agent header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HA_H
-+#define _HA_H
-+
-+int mipv6_ha_init(void);
-+void mipv6_ha_exit(void);
-+
-+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags);
-+
-+void mipv6_bu_finish(struct inet6_ifaddr *ifp, int ifindex,
-+ __u8 ba_status, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 ba_lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu);
-+
-+
-+static __inline__ void mipv6_generate_ll_addr(struct in6_addr *ll_addr,
-+ struct in6_addr *addr)
-+{
-+ ll_addr->s6_addr32[0] = htonl(0xfe800000);
-+ ll_addr->s6_addr32[1] = 0;
-+ ll_addr->s6_addr32[2] = addr->s6_addr32[2];
-+ ll_addr->s6_addr32[3] = addr->s6_addr32[3];
-+}
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/halist.c
-@@ -0,0 +1,507 @@
-+/*
-+ * Home Agents List
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#define PREF_BASE 0xffff /* MAX value for u16 field in RA */
-+
-+#include <linux/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/proc_fs.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+
-+#include "hashlist.h"
-+#include "util.h"
-+#include "debug.h"
-+
-+struct mipv6_halist {
-+ struct hashlist *entries;
-+ struct timer_list expire_timer;
-+};
-+
-+static rwlock_t home_agents_lock = RW_LOCK_UNLOCKED;
-+
-+static struct mipv6_halist home_agents;
-+
-+struct mipv6_halist_entry {
-+ struct hashlist_entry e;
-+ int ifindex; /* Link identifier */
-+ struct in6_addr link_local_addr; /* HA's link-local address */
-+ struct in6_addr global_addr; /* HA's Global address */
-+ int plen;
-+ long preference; /* The preference for this HA */
-+ unsigned long expire; /* expiration time (jiffies) */
-+};
-+
-+static inline void mipv6_ha_ac_add(struct in6_addr *ll_addr, int ifindex,
-+ struct in6_addr *glob_addr, int plen)
-+{
-+ struct net_device *dev;
-+
-+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) {
-+ struct in6_addr addr;
-+ mipv6_ha_anycast(&addr, glob_addr, plen);
-+ ipv6_dev_ac_inc(dev, &addr);
-+ }
-+}
-+
-+static inline void mipv6_ha_ac_del(struct in6_addr *ll_addr, int ifindex,
-+ struct in6_addr *glob_addr, int plen)
-+{
-+ struct net_device *dev;
-+
-+ if ((dev = __dev_get_by_index(ifindex)) && ipv6_chk_addr(ll_addr, dev)) {
-+ struct in6_addr addr;
-+ mipv6_ha_anycast(&addr, glob_addr, plen);
-+ ipv6_dev_ac_dec(dev, &addr);
-+ }
-+}
-+
-+struct preflist_iterator_args {
-+ int count;
-+ int requested;
-+ int ifindex;
-+ struct in6_addr *list;
-+};
-+
-+static int preflist_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct preflist_iterator_args *state =
-+ (struct preflist_iterator_args *)args;
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ struct in6_addr *newaddr =
-+ (struct in6_addr *)state->list + state->count;
-+
-+ if (state->count >= state->requested)
-+ return ITERATOR_STOP;
-+
-+ if (time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ DEBUG(DBG_INFO, "preflist_iterator: Deleting entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr));
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ if (state->ifindex != entry->ifindex)
-+ return ITERATOR_CONT;
-+
-+ ipv6_addr_copy(newaddr, &entry->global_addr);
-+ DEBUG(DBG_INFO, "preflist_iterator: adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x to list", NIPV6ADDR(&entry->global_addr));
-+ state->count++;
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int gc_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+
-+ int *type = (int *)args;
-+
-+ if (*type == 1 || time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int mipv6_halist_gc(int type)
-+{
-+ DEBUG_FUNC();
-+ hashlist_iterate(home_agents.entries, &type, gc_iterator);
-+ return 0;
-+}
-+
-+static void mipv6_halist_expire(unsigned long dummy)
-+{
-+ DEBUG_FUNC();
-+
-+ write_lock(&home_agents_lock);
-+ mipv6_halist_gc(0);
-+ write_unlock(&home_agents_lock);
-+}
-+
-+
-+static struct mipv6_halist_entry *mipv6_halist_new_entry(void)
-+{
-+ struct mipv6_halist_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ entry = hashlist_alloc(home_agents.entries, SLAB_ATOMIC);
-+
-+ return entry;
-+}
-+
-+
-+
-+/**
-+ * mipv6_halist_add - Add new home agent to the Home Agents List
-+ * @ifindex: interface identifier
-+ * @glob_addr: home agent's global address
-+ * @ll_addr: home agent's link-local address
-+ * @pref: relative preference for this home agent
-+ * @lifetime: lifetime for the entry
-+ *
-+ * Adds new home agent to the Home Agents List. The list is interface
-+ * specific and @ifindex tells through which interface the home agent
-+ * was heard. Returns zero on success and negative on failure.
-+ **/
-+
-+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen,
-+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime)
-+{
-+ int update = 0, ret = 0;
-+ unsigned int mpref;
-+ struct mipv6_halist_entry *entry = NULL;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&home_agents_lock);
-+
-+ if (glob_addr == NULL || lifetime <= 0) {
-+ DEBUG(DBG_WARNING, "invalid arguments");
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ mpref = PREF_BASE - pref;
-+ if ((entry = (struct mipv6_halist_entry *)
-+ hashlist_get(home_agents.entries, glob_addr)) != NULL) {
-+ if (entry->ifindex == ifindex) {
-+ DEBUG(DBG_DATADUMP, "updating old entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr));
-+ update = 1;
-+ } else {
-+ DEBUG(DBG_INFO, "halist_add : adding new entry with address %x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(glob_addr));
-+ update = 0;
-+ }
-+ }
-+ if (update) {
-+ entry->expire = jiffies + lifetime * HZ;
-+ if (entry->preference != mpref) {
-+ entry->preference = mpref;
-+ ret = hashlist_reposition(home_agents.entries,
-+ (void *)entry, mpref);
-+ }
-+ } else {
-+ entry = mipv6_halist_new_entry();
-+ if (entry == NULL) {
-+ DEBUG(DBG_INFO, "list full");
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ entry->ifindex = ifindex;
-+ if (ll_addr) {
-+ ipv6_addr_copy(&entry->link_local_addr, ll_addr);
-+ mipv6_ha_ac_add(ll_addr, ifindex, glob_addr, plen);
-+ } else
-+ ipv6_addr_set(&entry->link_local_addr, 0, 0, 0, 0);
-+
-+ ipv6_addr_copy(&entry->global_addr, glob_addr);
-+ entry->plen = plen;
-+ entry->preference = mpref;
-+ entry->expire = jiffies + lifetime * HZ;
-+ ret = hashlist_add(home_agents.entries, glob_addr, mpref,
-+ entry);
-+ }
-+out:
-+ write_unlock(&home_agents_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_halist_delete - delete home agent from Home Agents List
-+ * @glob_addr: home agent's global address
-+ *
-+ * Deletes entry for home agent @glob_addr from the Home Agent List.
-+ **/
-+int mipv6_halist_delete(struct in6_addr *glob_addr)
-+{
-+ struct hashlist_entry *e;
-+ struct mipv6_halist_entry *entry;
-+ DEBUG_FUNC();
-+
-+ if (glob_addr == NULL) {
-+ DEBUG(DBG_WARNING, "invalid glob addr");
-+ return -EINVAL;
-+ }
-+ write_lock(&home_agents_lock);
-+ if ((e = hashlist_get(home_agents.entries, glob_addr)) == NULL) {
-+ write_unlock(&home_agents_lock);
-+ return -ENOENT;
-+ }
-+ hashlist_delete(home_agents.entries, e);
-+ entry = (struct mipv6_halist_entry *)e;
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr, entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ hashlist_free(home_agents.entries, e);
-+ write_unlock(&home_agents_lock);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_ha_get_pref_list - Get list of preferred home agents
-+ * @ifindex: interface identifier
-+ * @addrs: pointer to a buffer to store the list
-+ * @max: maximum number of home agents to return
-+ *
-+ * Creates a list of @max preferred (or all known if less than @max)
-+ * home agents. Home Agents List is interface specific so you must
-+ * supply @ifindex. Stores list in addrs and returns number of home
-+ * agents stored. On failure, returns a negative value.
-+ **/
-+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max)
-+{
-+ struct preflist_iterator_args args;
-+
-+ DEBUG_FUNC();
-+ if (max <= 0) {
-+ *addrs = NULL;
-+ return 0;
-+ }
-+
-+ args.count = 0;
-+ args.requested = max;
-+ args.ifindex = ifindex;
-+ args.list = kmalloc(max * sizeof(struct in6_addr), GFP_ATOMIC);
-+
-+ if (args.list == NULL) return -ENOMEM;
-+
-+ read_lock(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, preflist_iterator);
-+ read_unlock(&home_agents_lock);
-+
-+ if (args.count >= 0) {
-+ *addrs = args.list;
-+ } else {
-+ kfree(args.list);
-+ *addrs = NULL;
-+ }
-+
-+ return args.count;
-+}
-+
-+struct getaddr_iterator_args {
-+ struct net_device *dev;
-+ struct in6_addr *addr;
-+};
-+
-+static int getaddr_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ struct getaddr_iterator_args *state =
-+ (struct getaddr_iterator_args *)args;
-+
-+ if (entry->ifindex != state->dev->ifindex)
-+ return ITERATOR_CONT;
-+
-+ if (ipv6_chk_addr(&entry->global_addr, state->dev)) {
-+ ipv6_addr_copy(state->addr, &entry->global_addr);
-+ return ITERATOR_STOP;
-+ }
-+ return ITERATOR_CONT;
-+}
-+
-+/*
-+ * Get Home Agent Address for given interface. If node is not serving
-+ * as a HA for this interface returns negative error value.
-+ */
-+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr)
-+{
-+ struct getaddr_iterator_args args;
-+ struct net_device *dev;
-+
-+ if (ifindex <= 0)
-+ return -EINVAL;
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL)
-+ return -ENODEV;
-+
-+ memset(addr, 0, sizeof(struct in6_addr));
-+ args.dev = dev;
-+ args.addr = addr;
-+ read_lock(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, getaddr_iterator);
-+ read_unlock(&home_agents_lock);
-+ dev_put(dev);
-+
-+ if (ipv6_addr_any(addr))
-+ return -ENOENT;
-+
-+ return 0;
-+}
-+
-+#define HALIST_INFO_LEN 81
-+
-+struct procinfo_iterator_args {
-+ char *buffer;
-+ int offset;
-+ int length;
-+ int skip;
-+ int len;
-+};
-+
-+static int procinfo_iterator(void *data, void *args,
-+ unsigned long *pref)
-+{
-+ struct procinfo_iterator_args *arg =
-+ (struct procinfo_iterator_args *)args;
-+ struct mipv6_halist_entry *entry =
-+ (struct mipv6_halist_entry *)data;
-+ unsigned long int expire;
-+
-+ DEBUG_FUNC();
-+
-+ if (entry == NULL) return ITERATOR_ERR;
-+
-+ if (time_after(jiffies, entry->expire)) {
-+ if (!ipv6_addr_any(&entry->link_local_addr)) {
-+ mipv6_ha_ac_del(&entry->link_local_addr,
-+ entry->ifindex,
-+ &entry->global_addr, entry->plen);
-+ }
-+ return ITERATOR_DELETE_ENTRY;
-+ }
-+ if (arg->skip < arg->offset / HALIST_INFO_LEN) {
-+ arg->skip++;
-+ return ITERATOR_CONT;
-+ }
-+
-+ if (arg->len >= arg->length)
-+ return ITERATOR_CONT;
-+
-+ expire = (entry->expire - jiffies) / HZ;
-+
-+ arg->len += sprintf(arg->buffer + arg->len,
-+ "%02d %08x%08x%08x%08x %08x%08x%08x%08x %05ld %05ld\n",
-+ entry->ifindex,
-+ ntohl(entry->global_addr.s6_addr32[0]),
-+ ntohl(entry->global_addr.s6_addr32[1]),
-+ ntohl(entry->global_addr.s6_addr32[2]),
-+ ntohl(entry->global_addr.s6_addr32[3]),
-+ ntohl(entry->link_local_addr.s6_addr32[0]),
-+ ntohl(entry->link_local_addr.s6_addr32[1]),
-+ ntohl(entry->link_local_addr.s6_addr32[2]),
-+ ntohl(entry->link_local_addr.s6_addr32[3]),
-+ -(entry->preference - PREF_BASE), expire);
-+
-+ return ITERATOR_CONT;
-+}
-+
-+static int halist_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct procinfo_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.buffer = buffer;
-+ args.offset = offset;
-+ args.length = length;
-+ args.skip = 0;
-+ args.len = 0;
-+
-+ read_lock_bh(&home_agents_lock);
-+ hashlist_iterate(home_agents.entries, &args, procinfo_iterator);
-+ read_unlock_bh(&home_agents_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % HALIST_INFO_LEN;
-+
-+ args.len -= offset % HALIST_INFO_LEN;
-+
-+ if (args.len > length)
-+ args.len = length;
-+ if (args.len < 0)
-+ args.len = 0;
-+
-+ return args.len;
-+}
-+
-+static int halist_compare(void *data, void *hashkey)
-+{
-+ struct mipv6_halist_entry *e = (struct mipv6_halist_entry *)data;
-+ struct in6_addr *key = (struct in6_addr *)hashkey;
-+
-+ return ipv6_addr_cmp(&e->global_addr, key);
-+}
-+
-+static __u32 halist_hash(void *hashkey)
-+{
-+ struct in6_addr *key = (struct in6_addr *)hashkey;
-+ __u32 hash;
-+
-+ hash = key->s6_addr32[0] ^
-+ key->s6_addr32[1] ^
-+ key->s6_addr32[2] ^
-+ key->s6_addr32[3];
-+
-+ return hash;
-+}
-+
-+int __init mipv6_halist_init(__u32 size)
-+{
-+ DEBUG_FUNC();
-+
-+ if (size <= 0) {
-+ DEBUG(DBG_ERROR, "size must be at least 1");
-+ return -EINVAL;
-+ }
-+ init_timer(&home_agents.expire_timer);
-+ home_agents.expire_timer.data = 0;
-+ home_agents.expire_timer.function = mipv6_halist_expire;
-+ home_agents_lock = RW_LOCK_UNLOCKED;
-+
-+ home_agents.entries = hashlist_create(16, size, sizeof(struct mipv6_halist_entry),
-+ "mip6_halist", NULL, NULL,
-+ halist_compare, halist_hash);
-+
-+ if (home_agents.entries == NULL) {
-+ DEBUG(DBG_ERROR, "Failed to initialize hashlist");
-+ return -ENOMEM;
-+ }
-+
-+ proc_net_create("mip6_home_agents", 0, halist_proc_info);
-+ DEBUG(DBG_INFO, "Home Agents List initialized");
-+ return 0;
-+}
-+
-+void __exit mipv6_halist_exit(void)
-+{
-+ DEBUG_FUNC();
-+ proc_net_remove("mip6_home_agents");
-+ write_lock_bh(&home_agents_lock);
-+ DEBUG(DBG_INFO, "Stopping the halist timer");
-+ del_timer(&home_agents.expire_timer);
-+ mipv6_halist_gc(1);
-+ write_unlock_bh(&home_agents_lock);
-+ hashlist_destroy(home_agents.entries);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/halist.h
-@@ -0,0 +1,28 @@
-+/*
-+ * MIPL Mobile IPv6 Home Agents List header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HALIST_H
-+#define _HALIST_H
-+
-+int mipv6_halist_init(__u32 size);
-+
-+void mipv6_halist_exit(void);
-+
-+int mipv6_halist_add(int ifindex, struct in6_addr *glob_addr, int plen,
-+ struct in6_addr *ll_addr, unsigned int pref, __u32 lifetime);
-+
-+int mipv6_halist_delete(struct in6_addr *glob_addr);
-+
-+int mipv6_ha_get_pref_list(int ifindex, struct in6_addr **addrs, int max);
-+
-+int mipv6_ha_get_addr(int ifindex, struct in6_addr *addr);
-+
-+#endif /* _HALIST_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/hashlist.c
-@@ -0,0 +1,351 @@
-+/*
-+ * Generic hashtable with chaining. Supports secodary sort order
-+ * with doubly linked-list.
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id: s.hashlist.c 1.21 02/10/07 19:31:52+03:00 antti@traci.mipl.mediapoli.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.
-+ */
-+
-+#include <linux/slab.h>
-+#include "hashlist.h"
-+#include "debug.h"
-+
-+struct hashlist {
-+ int count; /* entry count */
-+ int maxcount; /* max entries */
-+ __u32 bucketnum; /* hash buckets */
-+
-+ kmem_cache_t *kmem;
-+
-+ struct list_head *hashtable;
-+ struct list_head sortedlist;
-+
-+ int (*compare)(void *data, void *hashkey);
-+ __u32 (*hash_function)(void *hashkey);
-+};
-+
-+/**
-+ * hashlist_create - Create new hashlist
-+ * @bucketnum: number of hash buckets
-+ * @maxentries: maximum number of entries (0 = no limit)
-+ * @size: entry size in bytes
-+ * @name: name for kmem_cache_t
-+ * @ctor: kmem_cache_t constructor
-+ * @dtor: kmem_cache_t destructor
-+ * @compare: compare function for key
-+ * @hash_function: hash function
-+ *
-+ * Creates a hashlist structure with @max_entries entries of @size
-+ * bytes. User must supply @hash_function and @compare function for
-+ * the hashlist. User can also supply @ctor and @dtor for kmem_cache.
-+ **/
-+struct hashlist *hashlist_create(int bucketnum, int max_entries, size_t size,
-+ char *name,
-+ void (*ctor)(void *, kmem_cache_t *, unsigned long),
-+ void (*dtor)(void *, kmem_cache_t *, unsigned long),
-+ int (*compare)(void *data, void *hashkey),
-+ __u32 (*hash_function)(void *hashkey))
-+{
-+ int i;
-+ struct hashlist *hl;
-+
-+ if (!compare || !hash_function)
-+ goto hlfailed;
-+
-+ hl = kmalloc(sizeof(struct hashlist), GFP_ATOMIC);
-+ if (!hl) goto hlfailed;
-+
-+ hl->kmem = kmem_cache_create(name, size, 0, 0, ctor, dtor);
-+ if (!hl->kmem) goto poolfailed;
-+
-+ hl->hashtable = kmalloc(
-+ sizeof(struct list_head) * bucketnum, GFP_ATOMIC);
-+ if (!hl->hashtable) goto hashfailed;
-+
-+ for (i = 0; i < bucketnum; i++)
-+ INIT_LIST_HEAD(&hl->hashtable[i]);
-+
-+ INIT_LIST_HEAD(&hl->sortedlist);
-+
-+ hl->maxcount = max_entries;
-+ hl->count = 0;
-+ hl->bucketnum = bucketnum;
-+ hl->compare = compare;
-+ hl->hash_function = hash_function;
-+
-+ return hl;
-+
-+hashfailed:
-+ kmem_cache_destroy(hl->kmem);
-+ hl->kmem = NULL;
-+
-+poolfailed:
-+ kfree(hl);
-+
-+hlfailed:
-+ DEBUG(DBG_ERROR, "could not create hashlist");
-+
-+ return NULL;
-+}
-+
-+/**
-+ * hashlist_destroy - Destroy hashlist
-+ * @hashlist: hashlist to destroy
-+ *
-+ * Frees all memory allocated for a hashlist.
-+ **/
-+void hashlist_destroy(struct hashlist *hashlist)
-+{
-+ DEBUG_FUNC();
-+
-+ if (hashlist == NULL) return;
-+
-+ if (hashlist->hashtable) {
-+ kfree(hashlist->hashtable);
-+ hashlist->hashtable = NULL;
-+ }
-+
-+ if (hashlist->kmem) {
-+ kmem_cache_destroy(hashlist->kmem);
-+ hashlist->kmem = NULL;
-+ }
-+
-+ kfree(hashlist);
-+
-+ return;
-+}
-+
-+/*
-+ * Insert a chain of entries to hashlist into correct order. The
-+ * entries are assumed to have valid hashkeys. We use time_after_eq
-+ * for comparing, since it handles wrap-around correctly, and the
-+ * sortkey is usually jiffies.
-+ */
-+static void sorted_insert(struct list_head *lh, struct hashlist_entry *he)
-+{
-+ struct list_head *p;
-+ struct hashlist_entry *hlp = NULL;
-+ unsigned long sortkey = he->sortkey;
-+
-+ if (list_empty(lh)) {
-+ list_add(&he->sorted, lh);
-+ return;
-+ }
-+
-+ list_for_each(p, lh) {
-+ hlp = list_entry(p, typeof(*hlp), sorted);
-+ if (time_after_eq(hlp->sortkey, sortkey)) {
-+ list_add(&he->sorted, hlp->sorted.prev);
-+ return;
-+ }
-+ }
-+ list_add(&he->sorted, &hlp->sorted);
-+}
-+
-+/**
-+ * hashlist_iterate - Apply function for all elements in a hash list
-+ * @hashlist: pointer to hashlist
-+ * @args: data to pass to the function
-+ * @func: pointer to a function
-+ *
-+ * Apply arbitrary function @func to all elements in a hash list.
-+ * @func must be a pointer to a function with the following prototype:
-+ * int func(void *entry, void *arg, struct in6_addr *hashkey, unsigned
-+ * long *sortkey). Function must return %ITERATOR_STOP,
-+ * %ITERATOR_CONT or %ITERATOR_DELETE_ENTRY. %ITERATOR_STOP stops
-+ * iterator and returns last return value from the function.
-+ * %ITERATOR_CONT continues with iteration. %ITERATOR_DELETE_ENTRY
-+ * deletes current entry from the hashlist. If function changes
-+ * hashlist element's sortkey, iterator automatically schedules
-+ * element to be reinserted after all elements have been processed.
-+ */
-+int hashlist_iterate(
-+ struct hashlist *hashlist, void *args,
-+ hashlist_iterator_t func)
-+{
-+ int res = ITERATOR_CONT;
-+ unsigned long skey;
-+ struct list_head *p, *n, repos;
-+ struct hashlist_entry *he;
-+
-+ DEBUG_FUNC();
-+ INIT_LIST_HEAD(&repos);
-+
-+ list_for_each_safe(p, n, &hashlist->sortedlist) {
-+ he = list_entry(p, typeof(*he), sorted);
-+ if (res == ITERATOR_STOP)
-+ break;
-+ skey = he->sortkey;
-+ res = func(he, args, &he->sortkey);
-+ if (res == ITERATOR_DELETE_ENTRY) {
-+ hashlist_delete(hashlist, he);
-+ hashlist_free(hashlist, he);
-+ } else if (skey != he->sortkey) {
-+ /* iterator changed the sortkey, schedule for
-+ * repositioning */
-+ list_move(&he->sorted, &repos);
-+ }
-+ }
-+ list_for_each_safe(p, n, &repos) {
-+ he = list_entry(p, typeof(*he), sorted);
-+ sorted_insert(&hashlist->sortedlist, he);
-+ }
-+ return res;
-+}
-+
-+/**
-+ * hashlist_alloc - Allocate memory for a hashlist entry
-+ * @hashlist: hashlist for allocated entry
-+ * @size: size of entry in bytes
-+ *
-+ * Allocates @size bytes memory from @hashlist->kmem.
-+ **/
-+void *hashlist_alloc(struct hashlist *hashlist, int type)
-+{
-+ if (hashlist == NULL) return NULL;
-+ return kmem_cache_alloc(hashlist->kmem, type);
-+}
-+
-+/**
-+ * hashlist_free - Free hashlist entry
-+ * @hashlist: hashlist where @he is
-+ * @he: entry to free
-+ *
-+ * Frees an allocated hashlist entry.
-+ **/
-+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he)
-+{
-+ kmem_cache_free(hashlist->kmem, he);
-+}
-+
-+/**
-+ * hashlist_add - Add element to hashlist
-+ * @hashlist: pointer to hashlist
-+ * @hashkey: hashkey for the element
-+ * @sortkey: key for sorting
-+ * @data: element data
-+ *
-+ * Add element to hashlist. Hashlist is also sorted in a linked list
-+ * by @sortkey.
-+ */
-+int hashlist_add(struct hashlist *hashlist, void *hashkey,
-+ unsigned long sortkey, void *entry)
-+{
-+ struct hashlist_entry *he = (struct hashlist_entry *)entry;
-+ unsigned int hash;
-+
-+ if (hashlist->count >= hashlist->maxcount)
-+ return -1;
-+
-+ hashlist->count++;
-+
-+ /* link the entry to sorted order */
-+ he->sortkey = sortkey;
-+ sorted_insert(&hashlist->sortedlist, he);
-+
-+ /* hash the entry */
-+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum;
-+ list_add(&he->hashlist, &hashlist->hashtable[hash]);
-+
-+ return 0;
-+}
-+
-+/**
-+ * hashlist_get_ex - Get element from hashlist
-+ * @hashlist: hashlist
-+ * @hashkey: hashkey of the desired entry
-+ *
-+ * Lookup entry with @hashkey from the hash table using @compare
-+ * function for entry comparison. Returns entry on success, otherwise
-+ * %NULL.
-+ **/
-+struct hashlist_entry *hashlist_get_ex(
-+ struct hashlist *hashlist, void *hashkey,
-+ int (*compare)(void *data, void *hashkey))
-+{
-+ struct list_head *p, *bkt;
-+ __u32 hash;
-+
-+ hash = hashlist->hash_function(hashkey) % hashlist->bucketnum;
-+ bkt = &hashlist->hashtable[hash];
-+
-+ /* scan the entries within the same hashbucket */
-+ list_for_each(p, bkt) {
-+ struct hashlist_entry *he = list_entry(p, typeof(*he),
-+ hashlist);
-+ if (compare(he, hashkey) == 0)
-+ return he;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * hashlist_get - Get element from hashlist
-+ * @hashlist: hashlist
-+ * @hashkey: hashkey of the desired entry
-+ *
-+ * Lookup entry with @hashkey from the hash table. Returns entry on
-+ * success, otherwise %NULL.
-+ **/
-+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey)
-+{
-+ return hashlist_get_ex(hashlist, hashkey, hashlist->compare);
-+}
-+
-+/**
-+ * hashlist_reposition - set entry to new position in the list
-+ * @hashlist: hashlist
-+ * @he: entry to reposition
-+ * @sortkey: new sortkey of the entry
-+ *
-+ * If secondary order sortkey changes, entry must be repositioned in
-+ * the sorted list.
-+ **/
-+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he,
-+ unsigned long sortkey)
-+{
-+ list_del(&he->sorted);
-+ he->sortkey = sortkey;
-+ sorted_insert(&hashlist->sortedlist, he);
-+
-+ return 0;
-+}
-+
-+/**
-+ * hashlist_delete - Delete entry from hashlist
-+ * @hashlist: hashlist where entry is
-+ * @he: entry to delete
-+ *
-+ * Deletes an entry from the hashlist and sorted list.
-+ **/
-+void hashlist_delete(struct hashlist *hashlist,
-+ struct hashlist_entry *he)
-+{
-+ list_del_init(&he->hashlist);
-+ list_del_init(&he->sorted);
-+
-+ hashlist->count--;
-+}
-+
-+/**
-+ * hashlist_get_first - Get first item from sorted list
-+ * @hashlist: pointer to hashlist
-+ *
-+ * Returns first item in the secondary sort order.
-+ **/
-+void * hashlist_get_first(struct hashlist *hashlist)
-+{
-+ if (list_empty(&hashlist->sortedlist))
-+ return NULL;
-+
-+ return list_entry(hashlist->sortedlist.next, struct hashlist_entry, sorted);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/hashlist.h
-@@ -0,0 +1,63 @@
-+/*
-+ * MIPL Mobile IPv6 Hashlist header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HASHLIST_H
-+#define _HASHLIST_H
-+
-+#define ITERATOR_ERR -1
-+#define ITERATOR_CONT 0
-+#define ITERATOR_STOP 1
-+#define ITERATOR_DELETE_ENTRY 2
-+
-+struct kmem_cache_t;
-+
-+struct hashlist_entry {
-+ unsigned long sortkey;
-+ struct list_head sorted;
-+ struct list_head hashlist;
-+};
-+
-+struct hashlist * hashlist_create(
-+ int bucketnum, int max_entries, size_t size, char *name,
-+ void (*ctor)(void *, kmem_cache_t *, unsigned long),
-+ void (*dtor)(void *, kmem_cache_t *, unsigned long),
-+ int (*compare)(void *data, void *hashkey),
-+ __u32 (*hash_function)(void *hashkey));
-+
-+void hashlist_destroy(struct hashlist *hashlist);
-+
-+void *hashlist_alloc(struct hashlist *hashlist, int type);
-+
-+void hashlist_free(struct hashlist *hashlist, struct hashlist_entry *he);
-+
-+struct hashlist_entry *hashlist_get(struct hashlist *hashlist, void *hashkey);
-+
-+struct hashlist_entry *hashlist_get_ex(
-+ struct hashlist *hashlist, void *hashkey,
-+ int (*compare)(void *data, void *hashkey));
-+
-+int hashlist_add(struct hashlist *hashlist, void *hashkey,
-+ unsigned long sortkey, void *data);
-+
-+void hashlist_delete(struct hashlist *hashlist, struct hashlist_entry *he);
-+
-+/* iterator function */
-+typedef int (*hashlist_iterator_t)(void *, void *, unsigned long *);
-+
-+int hashlist_iterate(struct hashlist *hashlist, void *args,
-+ hashlist_iterator_t func);
-+
-+void * hashlist_get_first(struct hashlist *hashlist);
-+
-+int hashlist_reposition(struct hashlist *hashlist, struct hashlist_entry *he,
-+ unsigned long sortkey);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/hmac.c
-@@ -0,0 +1,658 @@
-+/* Authentication algorithms
-+ *
-+ * Authors:
-+ * Alexis Olivereau <Alexis.Olivereau@crm.mot.com>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes:
-+ * Henrik Petander : Cleaned up unused parts
-+ *
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/tty.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/in6.h>
-+
-+#include "hmac.h"
-+#define LROLL(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
-+
-+/* MD5 */
-+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
-+#define H(x, y, z) ((x) ^ (y) ^ (z))
-+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-+
-+#define FF(a, b, c, d, m, s, t) { \
-+ (a) += F ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define GG(a, b, c, d, m, s, t) { \
-+ (a) += G ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define HH(a, b, c, d, m, s, t) { \
-+ (a) += H ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+#define II(a, b, c, d, m, s, t) { \
-+ (a) += I ((b), (c), (d)) + (m) + (t); \
-+ (a) = LROLL((a), (s)); \
-+ (a) += (b); \
-+ }
-+
-+#define s11 7
-+#define s12 12
-+#define s13 17
-+#define s14 22
-+#define s21 5
-+#define s22 9
-+#define s23 14
-+#define s24 20
-+#define s31 4
-+#define s32 11
-+#define s33 16
-+#define s34 23
-+#define s41 6
-+#define s42 10
-+#define s43 15
-+#define s44 21
-+
-+/* SHA-1 */
-+#define f(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define g(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-+#define h(x, y, z) ((x) ^ (y) ^ (z))
-+
-+#define K1 0x5a827999
-+#define K2 0x6ed9eba1
-+#define K3 0x8f1bbcdc
-+#define K4 0xca62c1d6
-+
-+int ah_hmac_md5_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len)
-+{
-+ int i;
-+ int key_up4;
-+ uint32_t ipad = 0x36363636;
-+ uint8_t extkey[64];
-+
-+ ahp->key_auth = key;
-+ ahp->key_auth_len = key_len;
-+ ahp->context = (void *) kmalloc(sizeof(MD5_CTX), GFP_ATOMIC);
-+ if (ahp->context == NULL)
-+ return -1;
-+ md5_init((MD5_CTX *) ahp->context);
-+ if ((64 * sizeof(uint8_t)) < ahp->key_auth_len) {
-+ printk("buffer overflow!");
-+ return -1;
-+ }
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = ipad;
-+
-+ md5_compute((MD5_CTX *) ahp->context, extkey, 64);
-+ return 0;
-+}
-+
-+void ah_hmac_md5_loop(struct ah_processing *ahp, void *str, uint32_t len)
-+{
-+ md5_compute((MD5_CTX *) ahp->context, str, len);
-+}
-+
-+void ah_hmac_md5_result(struct ah_processing *ahp, char *digest)
-+{
-+ uint8_t inner[HMAC_MD5_HASH_LEN];
-+ int i;
-+ int key_up4;
-+ uint32_t opad = 0x5c5c5c5c;
-+ uint8_t extkey[64];
-+
-+ md5_final((MD5_CTX *) ahp->context, inner);
-+ md5_init((MD5_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = opad;
-+
-+ md5_compute((MD5_CTX *) ahp->context, extkey, 64);
-+ md5_compute((MD5_CTX *) ahp->context, inner, HMAC_MD5_HASH_LEN);
-+
-+ md5_final((MD5_CTX *) ahp->context, digest);
-+
-+ kfree(ahp->context);
-+}
-+
-+int ah_hmac_sha1_init(struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len)
-+{
-+ int i;
-+ int key_up4;
-+ uint32_t ipad = 0x36363636;
-+ uint8_t extkey[64];
-+
-+ ahp->key_auth = key;
-+ ahp->key_auth_len = key_len;
-+
-+ ahp->context = (void *) kmalloc(sizeof(SHA1_CTX), GFP_ATOMIC);
-+ //if (ahp->context == NULL)
-+ // return -1;
-+
-+ sha1_init((SHA1_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ ipad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = ipad;
-+
-+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64);
-+ return 0;
-+}
-+
-+void ah_hmac_sha1_loop(struct ah_processing *ahp, void *str, uint32_t len)
-+{
-+ if (!ahp)
-+ return;
-+ sha1_compute((SHA1_CTX *) ahp->context, str, len);
-+}
-+
-+void ah_hmac_sha1_result(struct ah_processing *ahp, char *digest)
-+{
-+ uint8_t inner[HMAC_SHA1_HASH_LEN];
-+ int i;
-+ int key_up4;
-+ uint32_t opad = 0x5c5c5c5c;
-+ uint8_t extkey[64];
-+
-+ if (!ahp)
-+ return;
-+ sha1_final((SHA1_CTX *) ahp->context, inner);
-+ sha1_init((SHA1_CTX *) ahp->context);
-+
-+ memcpy(extkey, ahp->key_auth, ahp->key_auth_len);
-+ if (ahp->key_auth_len % 4) {
-+ memset(extkey + ahp->key_auth_len, 0,
-+ 4 - (ahp->key_auth_len % 4));
-+ }
-+ key_up4 = ((ahp->key_auth_len + 0x3) & 0xFFFFFFFC) / 4;
-+
-+ for (i = 0; i < key_up4; i++)
-+ ((uint32_t *) extkey)[i] = ((uint32_t *) extkey)[i] ^ opad;
-+ for (i = key_up4; i < 16; i++)
-+ ((uint32_t *) extkey)[i] = opad;
-+
-+ sha1_compute((SHA1_CTX *) ahp->context, extkey, 64);
-+ sha1_compute((SHA1_CTX *) ahp->context, inner,
-+ HMAC_SHA1_HASH_LEN);
-+
-+ sha1_final((SHA1_CTX *) ahp->context, digest);
-+
-+ kfree(ahp->context);
-+}
-+
-+void md5_init(MD5_CTX * ctx)
-+{
-+ ctx->A = 0x67452301;
-+ ctx->B = 0xefcdab89;
-+ ctx->C = 0x98badcfe;
-+ ctx->D = 0x10325476;
-+ ctx->buf_cur = ctx->buf;
-+ ctx->bitlen[0] = ctx->bitlen[1] = 0;
-+ memset(ctx->buf, 0, 64);
-+}
-+
-+void md5_over_block(MD5_CTX * ctx, uint8_t * data)
-+{
-+ uint32_t M[16];
-+ uint32_t a = ctx->A;
-+ uint32_t b = ctx->B;
-+ uint32_t c = ctx->C;
-+ uint32_t d = ctx->D;
-+
-+ create_M_blocks(M, data);
-+
-+ /* Round 1 */
-+ FF(a, b, c, d, M[0], s11, 0xd76aa478); /* 1 */
-+ FF(d, a, b, c, M[1], s12, 0xe8c7b756); /* 2 */
-+ FF(c, d, a, b, M[2], s13, 0x242070db); /* 3 */
-+ FF(b, c, d, a, M[3], s14, 0xc1bdceee); /* 4 */
-+ FF(a, b, c, d, M[4], s11, 0xf57c0faf); /* 5 */
-+ FF(d, a, b, c, M[5], s12, 0x4787c62a); /* 6 */
-+ FF(c, d, a, b, M[6], s13, 0xa8304613); /* 7 */
-+ FF(b, c, d, a, M[7], s14, 0xfd469501); /* 8 */
-+ FF(a, b, c, d, M[8], s11, 0x698098d8); /* 9 */
-+ FF(d, a, b, c, M[9], s12, 0x8b44f7af); /* 10 */
-+ FF(c, d, a, b, M[10], s13, 0xffff5bb1); /* 11 */
-+ FF(b, c, d, a, M[11], s14, 0x895cd7be); /* 12 */
-+ FF(a, b, c, d, M[12], s11, 0x6b901122); /* 13 */
-+ FF(d, a, b, c, M[13], s12, 0xfd987193); /* 14 */
-+ FF(c, d, a, b, M[14], s13, 0xa679438e); /* 15 */
-+ FF(b, c, d, a, M[15], s14, 0x49b40821); /* 16 */
-+
-+ /* Round 2 */
-+ GG(a, b, c, d, M[1], s21, 0xf61e2562); /* 17 */
-+ GG(d, a, b, c, M[6], s22, 0xc040b340); /* 18 */
-+ GG(c, d, a, b, M[11], s23, 0x265e5a51); /* 19 */
-+ GG(b, c, d, a, M[0], s24, 0xe9b6c7aa); /* 20 */
-+ GG(a, b, c, d, M[5], s21, 0xd62f105d); /* 21 */
-+ GG(d, a, b, c, M[10], s22, 0x02441453); /* 22 */
-+ GG(c, d, a, b, M[15], s23, 0xd8a1e681); /* 23 */
-+ GG(b, c, d, a, M[4], s24, 0xe7d3fbc8); /* 24 */
-+ GG(a, b, c, d, M[9], s21, 0x21e1cde6); /* 25 */
-+ GG(d, a, b, c, M[14], s22, 0xc33707d6); /* 26 */
-+ GG(c, d, a, b, M[3], s23, 0xf4d50d87); /* 27 */
-+ GG(b, c, d, a, M[8], s24, 0x455a14ed); /* 28 */
-+ GG(a, b, c, d, M[13], s21, 0xa9e3e905); /* 29 */
-+ GG(d, a, b, c, M[2], s22, 0xfcefa3f8); /* 30 */
-+ GG(c, d, a, b, M[7], s23, 0x676f02d9); /* 31 */
-+ GG(b, c, d, a, M[12], s24, 0x8d2a4c8a); /* 32 */
-+
-+ /* Round 3 */
-+ HH(a, b, c, d, M[5], s31, 0xfffa3942); /* 33 */
-+ HH(d, a, b, c, M[8], s32, 0x8771f681); /* 34 */
-+ HH(c, d, a, b, M[11], s33, 0x6d9d6122); /* 35 */
-+ HH(b, c, d, a, M[14], s34, 0xfde5380c); /* 36 */
-+ HH(a, b, c, d, M[1], s31, 0xa4beea44); /* 37 */
-+ HH(d, a, b, c, M[4], s32, 0x4bdecfa9); /* 38 */
-+ HH(c, d, a, b, M[7], s33, 0xf6bb4b60); /* 39 */
-+ HH(b, c, d, a, M[10], s34, 0xbebfbc70); /* 40 */
-+ HH(a, b, c, d, M[13], s31, 0x289b7ec6); /* 41 */
-+ HH(d, a, b, c, M[0], s32, 0xeaa127fa); /* 42 */
-+ HH(c, d, a, b, M[3], s33, 0xd4ef3085); /* 43 */
-+ HH(b, c, d, a, M[6], s34, 0x4881d05); /* 44 */
-+ HH(a, b, c, d, M[9], s31, 0xd9d4d039); /* 45 */
-+ HH(d, a, b, c, M[12], s32, 0xe6db99e5); /* 46 */
-+ HH(c, d, a, b, M[15], s33, 0x1fa27cf8); /* 47 */
-+ HH(b, c, d, a, M[2], s34, 0xc4ac5665); /* 48 */
-+
-+ /* Round 4 */
-+ II(a, b, c, d, M[0], s41, 0xf4292244); /* 49 */
-+ II(d, a, b, c, M[7], s42, 0x432aff97); /* 50 */
-+ II(c, d, a, b, M[14], s43, 0xab9423a7); /* 51 */
-+ II(b, c, d, a, M[5], s44, 0xfc93a039); /* 52 */
-+ II(a, b, c, d, M[12], s41, 0x655b59c3); /* 53 */
-+ II(d, a, b, c, M[3], s42, 0x8f0ccc92); /* 54 */
-+ II(c, d, a, b, M[10], s43, 0xffeff47d); /* 55 */
-+ II(b, c, d, a, M[1], s44, 0x85845dd1); /* 56 */
-+ II(a, b, c, d, M[8], s41, 0x6fa87e4f); /* 57 */
-+ II(d, a, b, c, M[15], s42, 0xfe2ce6e0); /* 58 */
-+ II(c, d, a, b, M[6], s43, 0xa3014314); /* 59 */
-+ II(b, c, d, a, M[13], s44, 0x4e0811a1); /* 60 */
-+ II(a, b, c, d, M[4], s41, 0xf7537e82); /* 61 */
-+ II(d, a, b, c, M[11], s42, 0xbd3af235); /* 62 */
-+ II(c, d, a, b, M[2], s43, 0x2ad7d2bb); /* 63 */
-+ II(b, c, d, a, M[9], s44, 0xeb86d391); /* 64 */
-+
-+ ctx->A += a;
-+ ctx->B += b;
-+ ctx->C += c;
-+ ctx->D += d;
-+}
-+
-+void create_M_blocks(uint32_t * M, uint8_t * data)
-+{
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy((uint8_t *) M, data, 64);
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ int i;
-+ for (i = 0; i < 16; i++, data += 4) {
-+ ((uint8_t *) (&M[i]))[0] = data[3];
-+ ((uint8_t *) (&M[i]))[1] = data[2];
-+ ((uint8_t *) (&M[i]))[2] = data[1];
-+ ((uint8_t *) (&M[i]))[3] = data[0];
-+ }
-+#endif /* HAVE_BIG_ENDIAN */
-+}
-+
-+void md5_compute(MD5_CTX * ctx, uint8_t * data, uint32_t len)
-+{
-+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f);
-+
-+ /* First we update the bit length */
-+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3))
-+ ctx->bitlen[1]++;
-+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */
-+
-+ if (pos) {
-+ /* Buffer is not empty */
-+ if (64 - pos >= len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ pos += len;
-+ if (pos == 64) {
-+ /* The current block is over */
-+ md5_over_block(ctx, ctx->buf);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ return;
-+ } else {
-+ memcpy(ctx->buf_cur, data, 64 - pos);
-+ md5_over_block(ctx, ctx->buf);
-+ len -= (64 - pos);
-+ data += (64 - pos);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ }
-+ while (len >= 64) {
-+ md5_over_block(ctx, data);
-+ len -= 64;
-+ data += 64;
-+ }
-+ if (len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ }
-+}
-+
-+void md5_final(MD5_CTX * ctx, uint8_t * digest)
-+{
-+ uint32_t rem_size;
-+ uint8_t *buf_cur = ctx->buf_cur;
-+ int i;
-+
-+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f);
-+ *(buf_cur++) = 0x80;
-+
-+ if (rem_size > 8 + 1) {
-+ /* We have enough room in the current block */
-+ for (i = 0; i < rem_size - 8 - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ } else {
-+ /* We do not have enough room and need therefore to add a new
-+ 64-byte block */
-+ for (i = 0; i < rem_size - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ md5_over_block(ctx, ctx->buf);
-+
-+ buf_cur = ctx->buf;
-+ for (i = 0; i < 64 - 8; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ }
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8);
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff;
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+ md5_over_block(ctx, ctx->buf);
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t));
-+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t));
-+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t));
-+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t));
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ digest[0] = ((ctx->A) >> 24) & 0xff;
-+ digest[1] = ((ctx->A) >> 16) & 0xff;
-+ digest[2] = ((ctx->A) >> 8) & 0xff;
-+ digest[3] = ((ctx->A) >> 0) & 0xff;
-+ digest[4] = ((ctx->B) >> 24) & 0xff;
-+ digest[5] = ((ctx->B) >> 16) & 0xff;
-+ digest[6] = ((ctx->B) >> 8) & 0xff;
-+ digest[7] = ((ctx->B) >> 0) & 0xff;
-+ digest[8] = ((ctx->C) >> 24) & 0xff;
-+ digest[9] = ((ctx->C) >> 16) & 0xff;
-+ digest[10] = ((ctx->C) >> 8) & 0xff;
-+ digest[11] = ((ctx->C) >> 0) & 0xff;
-+ digest[12] = ((ctx->D) >> 24) & 0xff;
-+ digest[13] = ((ctx->D) >> 16) & 0xff;
-+ digest[14] = ((ctx->D) >> 8) & 0xff;
-+ digest[15] = ((ctx->D) >> 0) & 0xff;
-+#endif /* HAVE_BIG_ENDIAN */
-+}
-+
-+void sha1_init(SHA1_CTX * ctx)
-+{
-+ ctx->A = 0x67452301;
-+ ctx->B = 0xefcdab89;
-+ ctx->C = 0x98badcfe;
-+ ctx->D = 0x10325476;
-+ ctx->E = 0xc3d2e1f0;
-+ ctx->buf_cur = ctx->buf;
-+ ctx->bitlen[0] = ctx->bitlen[1] = 0;
-+ memset(ctx->buf, 0, 64);
-+}
-+
-+void sha1_over_block(SHA1_CTX * ctx, uint8_t * data)
-+{
-+ int i;
-+ uint32_t W[80];
-+ uint32_t a = ctx->A;
-+ uint32_t b = ctx->B;
-+ uint32_t c = ctx->C;
-+ uint32_t d = ctx->D;
-+ uint32_t e = ctx->E;
-+ uint32_t temp;
-+
-+ create_W_blocks(W, data);
-+
-+ /* Round 1 */
-+ for (i = 0; i < 20; i++) {
-+ temp = LROLL(a, 5) + f(b, c, d) + e + W[i] + K1;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 2 */
-+ for (i = 20; i < 40; i++) {
-+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K2;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 3 */
-+ for (i = 40; i < 60; i++) {
-+ temp = LROLL(a, 5) + g(b, c, d) + e + W[i] + K3;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ /* Round 4 */
-+ for (i = 60; i < 80; i++) {
-+ temp = LROLL(a, 5) + h(b, c, d) + e + W[i] + K4;
-+ e = d;
-+ d = c;
-+ c = LROLL(b, 30);
-+ b = a;
-+ a = temp;
-+ }
-+
-+ ctx->A += a;
-+ ctx->B += b;
-+ ctx->C += c;
-+ ctx->D += d;
-+ ctx->E += e;
-+}
-+
-+void create_W_blocks(uint32_t * W, uint8_t * data)
-+{
-+ int i;
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy((uint8_t *) W, data, 64);
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ for (i = 0; i < 16; i++, data += 4) {
-+ ((uint8_t *) (&W[i]))[0] = data[3];
-+ ((uint8_t *) (&W[i]))[1] = data[2];
-+ ((uint8_t *) (&W[i]))[2] = data[1];
-+ ((uint8_t *) (&W[i]))[3] = data[0];
-+ }
-+#endif /* HAVE_LITTLE_ENDIAN */
-+ for (i = 16; i < 80; i++) {
-+ W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
-+ W[i] = LROLL(W[i], 1);
-+ }
-+}
-+
-+void sha1_compute(SHA1_CTX * ctx, uint8_t * data, uint32_t len)
-+{
-+ uint8_t pos = ((ctx->bitlen[0] >> 3) & 0x3f);
-+
-+ /* First we update the bit length */
-+ if ((ctx->bitlen[0] += (len << 3)) < (len << 3))
-+ ctx->bitlen[1]++;
-+ ctx->bitlen[1] += (len >> 29); /* len is expressed in bytes */
-+
-+ if (pos) {
-+ /* Buffer is not empty */
-+ if (64 - pos >= len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ pos += len;
-+ if (pos == 64) {
-+ /* The current block is over */
-+ sha1_over_block(ctx, ctx->buf);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ return;
-+ } else {
-+ memcpy(ctx->buf_cur, data, 64 - pos);
-+ sha1_over_block(ctx, ctx->buf);
-+ len -= (64 - pos);
-+ data += (64 - pos);
-+ ctx->buf_cur = ctx->buf;
-+ }
-+ }
-+ while (len >= 64) {
-+ sha1_over_block(ctx, data);
-+ len -= 64;
-+ data += 64;
-+ }
-+ if (len) {
-+ memcpy(ctx->buf_cur, data, len);
-+ ctx->buf_cur += len;
-+ }
-+}
-+
-+void sha1_final(SHA1_CTX * ctx, uint8_t * digest)
-+{
-+ uint32_t rem_size;
-+ uint8_t *buf_cur = ctx->buf_cur;
-+ int i;
-+
-+ rem_size = 64 - ((ctx->bitlen[0] >> 3) & 0x3f);
-+ *(buf_cur++) = 0x80;
-+
-+ if (rem_size > 8 + 1) {
-+ /* We have enough room in the current block */
-+ for (i = 0; i < rem_size - 8 - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ } else {
-+ /* We do not have enough room and need therefore to add a new
-+ 64-byte block */
-+ for (i = 0; i < rem_size - 1; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ sha1_over_block(ctx, ctx->buf);
-+
-+ buf_cur = ctx->buf;
-+ for (i = 0; i < 64 - 8; i++) {
-+ *(buf_cur++) = 0;
-+ }
-+ }
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy(buf_cur, (uint8_t *) ctx->bitlen, 8);
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ *(buf_cur++) = (ctx->bitlen[1] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[1] >> 0) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 24) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 16) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 8) & 0xff;
-+ *(buf_cur++) = (ctx->bitlen[0] >> 0) & 0xff;
-+#endif /* HAVE_LITTLE_ENDIAN */
-+
-+ sha1_over_block(ctx, ctx->buf);
-+
-+#ifdef HAVE_BIG_ENDIAN
-+ memcpy(digest + 0, (uint8_t *) (&(ctx->A)), sizeof(uint32_t));
-+ memcpy(digest + 4, (uint8_t *) (&(ctx->B)), sizeof(uint32_t));
-+ memcpy(digest + 8, (uint8_t *) (&(ctx->C)), sizeof(uint32_t));
-+ memcpy(digest + 12, (uint8_t *) (&(ctx->D)), sizeof(uint32_t));
-+ memcpy(digest + 16, (uint8_t *) (&(ctx->E)), sizeof(uint32_t));
-+#endif /* HAVE_BIG_ENDIAN */
-+
-+#ifdef HAVE_LITTLE_ENDIAN
-+ digest[0] = ((ctx->A) >> 24) & 0xff;
-+ digest[1] = ((ctx->A) >> 16) & 0xff;
-+ digest[2] = ((ctx->A) >> 8) & 0xff;
-+ digest[3] = ((ctx->A) >> 0) & 0xff;
-+ digest[4] = ((ctx->B) >> 24) & 0xff;
-+ digest[5] = ((ctx->B) >> 16) & 0xff;
-+ digest[6] = ((ctx->B) >> 8) & 0xff;
-+ digest[7] = ((ctx->B) >> 0) & 0xff;
-+ digest[8] = ((ctx->C) >> 24) & 0xff;
-+ digest[9] = ((ctx->C) >> 16) & 0xff;
-+ digest[10] = ((ctx->C) >> 8) & 0xff;
-+ digest[11] = ((ctx->C) >> 0) & 0xff;
-+ digest[12] = ((ctx->D) >> 24) & 0xff;
-+ digest[13] = ((ctx->D) >> 16) & 0xff;
-+ digest[14] = ((ctx->D) >> 8) & 0xff;
-+ digest[15] = ((ctx->D) >> 0) & 0xff;
-+ digest[16] = ((ctx->E) >> 24) & 0xff;
-+ digest[17] = ((ctx->E) >> 16) & 0xff;
-+ digest[18] = ((ctx->E) >> 8) & 0xff;
-+ digest[19] = ((ctx->E) >> 0) & 0xff;
-+#endif /* HAVE_LITTLE_ENDIAN */
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/hmac.h
-@@ -0,0 +1,94 @@
-+/*
-+ * MIPL Mobile IPv6 Message authentication algorithms
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _HMAC_H
-+#define _HMAC_H
-+
-+#include <linux/types.h>
-+#include <linux/in6.h>
-+
-+#define HAVE_LITTLE_ENDIAN
-+
-+#define NO_EXPIRY 1 /* For sec_as */
-+
-+#define ALG_AUTH_NONE 0
-+#define ALG_AUTH_HMAC_MD5 1
-+#define ALG_AUTH_HMAC_SHA1 2
-+
-+struct sec_as;
-+struct ah_processing {
-+ void *context;
-+ struct sec_as *sas;
-+ u_int8_t *key_auth;
-+ u_int32_t key_auth_len;
-+};
-+
-+struct antireplay {
-+ u_int32_t count;
-+ u_int32_t bitmap;
-+};
-+
-+typedef struct {
-+ u_int32_t A, B, C, D;
-+ u_int32_t bitlen[2];
-+ u_int8_t* buf_cur;
-+ u_int8_t buf[64];
-+} MD5_CTX;
-+
-+typedef struct {
-+ u_int32_t A, B, C, D, E;
-+ u_int32_t bitlen[2];
-+ u_int8_t* buf_cur;
-+ u_int8_t buf[64];
-+} SHA1_CTX;
-+
-+
-+
-+int ah_hmac_md5_init (struct ah_processing *ahp, u_int8_t *key, u_int32_t key_len);
-+void ah_hmac_md5_loop(struct ah_processing*, void*, u_int32_t);
-+void ah_hmac_md5_result(struct ah_processing*, char*);
-+int ah_hmac_sha1_init(struct ah_processing*, u_int8_t *key, u_int32_t key_len);
-+void ah_hmac_sha1_loop(struct ah_processing*, void*, u_int32_t);
-+void ah_hmac_sha1_result(struct ah_processing*, char*);
-+
-+
-+#define AH_HDR_LEN 12 /* # of bytes for Next Header, Payload Length,
-+ RESERVED, Security Parameters Index and
-+
-+ Sequence Number Field */
-+
-+void md5_init(MD5_CTX *ctx);
-+void md5_over_block(MD5_CTX *ctx, u_int8_t* data);
-+void create_M_blocks(u_int32_t* M, u_int8_t* data);
-+void md5_compute(MD5_CTX *ctx, u_int8_t* data, u_int32_t len);
-+void md5_final(MD5_CTX *ctx, u_int8_t* digest);
-+
-+void sha1_init(SHA1_CTX *ctx);
-+void sha1_over_block(SHA1_CTX *ctx, u_int8_t* data);
-+void create_W_blocks(u_int32_t* W, u_int8_t* data);
-+void sha1_compute(SHA1_CTX *ctx, u_int8_t* data, u_int32_t len);
-+void sha1_final(SHA1_CTX *ctx, u_int8_t* digest);
-+
-+struct mipv6_acq {
-+ struct in6_addr coa;
-+ struct in6_addr haddr;
-+ struct in6_addr peer;
-+ u_int32_t spi;
-+};
-+#define MIPV6_MAX_AUTH_DATA 20
-+
-+#define HMAC_MD5_HASH_LEN 16
-+#define HMAC_SHA1_HASH_LEN 20
-+#define HMAC_SHA1_KEY_SIZE 20
-+#define HMAC_MD5_ICV_LEN 12 /* RFC 2403 */
-+#define HMAC_SHA1_ICV_LEN 12 /* RFC 2404 */
-+
-+#endif /* _HMAC_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/ioctl_mn.c
-@@ -0,0 +1,142 @@
-+/*
-+ * Mobile Node IOCTL Control device
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/fs.h>
-+#include <linux/poll.h>
-+#include <linux/ioctl.h>
-+#include <net/ipv6.h>
-+#include <asm/uaccess.h>
-+
-+#include "debug.h"
-+#include "mdetect.h"
-+#include "multiaccess_ctl.h"
-+
-+/* Reserved for local / experimental use */
-+#define MAJOR_NUM 0xf9
-+
-+/* Get Care-of address information for Mobile Node */
-+#define IOCTL_GET_CAREOFADDR _IOWR(MAJOR_NUM, 9, void *)
-+
-+#define MA_IOCTL_SET_IFACE_PREFERENCE _IOR (MAJOR_NUM, 13, void *)
-+
-+/* The name of the device file */
-+#define CTLFILE "mipv6_dev"
-+
-+static int inuse = 0;
-+
-+static int mipv6_open(struct inode *inode, struct file *file)
-+{
-+ DEBUG(DBG_INFO, "(%p)\n", file);
-+
-+ if (inuse)
-+ return -EBUSY;
-+
-+ inuse++;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+static int mipv6_close(struct inode *inode, struct file *file)
-+{
-+ DEBUG(DBG_INFO, "(%p,%p)\n", inode, file);
-+ inuse--;
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+int mipv6_ioctl(struct inode *inode, struct file *file,
-+ unsigned int ioctl_num, /* The number of the ioctl */
-+ unsigned long arg) /* The parameter to it */
-+{
-+ struct in6_addr careofaddr;
-+
-+ /* Switch according to the ioctl called */
-+ switch (ioctl_num) {
-+ case IOCTL_GET_CAREOFADDR:
-+ DEBUG(DBG_DATADUMP, "IOCTL_GET_CAREOFADDR");
-+ /* First get home address from user and then look up
-+ * the care-of address and return it
-+ */
-+ if (copy_from_user(&careofaddr, (struct in6_addr *)arg,
-+ sizeof(struct in6_addr)) < 0) {
-+ DEBUG(DBG_WARNING, "Copy from user failed");
-+ return -EFAULT;
-+ }
-+ mipv6_get_care_of_address(&careofaddr, &careofaddr);
-+ if (copy_to_user((struct in6_addr *)arg, &careofaddr,
-+ sizeof(struct in6_addr)) < 0) {
-+ DEBUG(DBG_WARNING, "copy_to_user failed");
-+ return -EFAULT;
-+ }
-+ break;
-+ case MA_IOCTL_SET_IFACE_PREFERENCE:
-+ DEBUG(DBG_INFO, "MA_IOCTL_SET_IFACE_PREFERENCE");
-+ ma_ctl_set_preference(arg);
-+ break;
-+
-+ default:
-+ DEBUG(DBG_WARNING, "Unknown ioctl cmd (%d)", ioctl_num);
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+
-+struct file_operations Fops = {
-+ owner: THIS_MODULE,
-+ read: NULL,
-+ write: NULL,
-+ poll: NULL,
-+ ioctl: mipv6_ioctl,
-+ open: mipv6_open,
-+ release: mipv6_close
-+};
-+
-+
-+/* Initialize the module - Register the character device */
-+int mipv6_ioctl_mn_init(void)
-+{
-+ int ret_val;
-+
-+ /* Register the character device (atleast try) */
-+ ret_val = register_chrdev(MAJOR_NUM, CTLFILE, &Fops);
-+
-+ /* Negative values signify an error */
-+ if (ret_val < 0) {
-+ DEBUG(DBG_ERROR, "failed registering char device (err=%d)",
-+ ret_val);
-+ return ret_val;
-+ }
-+
-+ DEBUG(DBG_INFO, "Device number %x, success", MAJOR_NUM);
-+ return 0;
-+}
-+
-+
-+/* Cleanup - unregister the appropriate file from /proc */
-+void mipv6_ioctl_mn_exit(void)
-+{
-+ int ret;
-+ /* Unregister the device */
-+ ret = unregister_chrdev(MAJOR_NUM, CTLFILE);
-+
-+ /* If there's an error, report it */
-+ if (ret < 0)
-+ DEBUG(DBG_ERROR, "errorcode: %d\n", ret);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mdetect.c
-@@ -0,0 +1,1153 @@
-+/*
-+ * Movement Detection Module
-+ *
-+ * Authors:
-+ * Henrik Petander <lpetande@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Handles the L3 movement detection of mobile node and also
-+ * changing of its routes.
-+ *
-+ */
-+
-+/*
-+ * Changes:
-+ *
-+ * Nanno Langstraat : Locking fixes
-+ * Venkata Jagana : Locking fix
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/if_arp.h>
-+#include <linux/route.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipglue.h>
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include "util.h"
-+#include "mdetect.h"
-+#include "mn.h"
-+#include "debug.h"
-+#include "multiaccess_ctl.h"
-+
-+#define START 0
-+#define CONTINUE 1
-+#define OK 2
-+#define DEBUG_MDETECT 7
-+
-+#define DEF_RTR_POLL_IVAL 5 /* In seconds */
-+
-+#define NO_RTR 0
-+#define RTR_SUSPECT 1
-+#define CURR_RTR_OK 2
-+
-+#define RA_RCVD 0
-+#define NA_RCVD 1
-+#define TIMEOUT 2
-+
-+#define MIPV6_MDF_NONE 0x0
-+#define MIPV6_MDF_HAS_RTR_PREV 0x1
-+
-+#define ROUTER_REACHABLE 1
-+#define RADV_MISSED 2
-+#define NOT_REACHABLE 3
-+
-+/* R_TIME_OUT paramater is used to make the decision when to change the
-+ * default router, if the current one is unreachable. 2s is pretty aggressive
-+ * and may result in hopping between two routers. OTOH a small value enhances
-+ * the performance
-+ */
-+#define R_TIME_OUT 30*HZ
-+
-+/* maximum RA interval for router unreachability detection */
-+#define MAX_RADV_INTERVAL 6*HZ /* 6000 ms... */
-+
-+/* Threshold for exponential resending of router solicitations */
-+#define RS_RESEND_LINEAR 10*HZ
-+
-+#define EAGER_CELL_SWITCHING 1
-+#define LAZY_CELL_SWITCHING 0
-+#define RESPECT_DAD 1
-+
-+#define ROUTER_ADDRESS 0x20
-+
-+/* RA flags */
-+#define ND_RA_FLAG_MANAGED 0x80
-+#define ND_RA_FLAG_OTHER 0x40
-+#define ND_RA_FLAG_HA 0x20
-+
-+/* DAD flags for global and link local addresses */
-+
-+#define COA_TENTATIVE 0x10
-+#define LLADDR_TENTATIVE 0x01
-+
-+struct router {
-+ struct list_head list;
-+ struct in6_addr ll_addr;
-+ struct in6_addr raddr; /* Also contains prefix */
-+ __u8 link_addr[MAX_ADDR_LEN]; /* link layer address */
-+ __u8 link_addr_len;
-+ __u8 state;
-+ __u8 is_current;
-+ __u8 reachable;
-+ int ifindex;
-+ int pfix_len; /* Length of the network prefix */
-+ unsigned long lifetime; /* from ra */
-+ __u32 last_ns_sent;
-+ __u32 last_ra_rcvd;
-+ __u32 interval; /* ra interval in milliseconds, 0 if not set */
-+ int glob_addr; /*Whether raddr contains also routers global address*/
-+ __u8 flags; /* RA flags, for example ha */
-+ struct in6_addr CoA; /* care-off address used with this router */
-+ int extra_addr_route;
-+};
-+
-+/* dad could also be RESPECT_DAD for duplicate address detection of
-+ new care-of addresses */
-+static int dad = 0;
-+
-+/* Only one choice, nothing else implemented */
-+int max_rtr_reach_time = DEF_RTR_POLL_IVAL;
-+
-+
-+int eager_cell_switching = EAGER_CELL_SWITCHING; /* Can be set to 0 via proc */
-+static spinlock_t router_lock;
-+static spinlock_t ho_lock;
-+
-+static void coa_timer_handler(unsigned long arg);
-+static void timer_handler(unsigned long foo);
-+static struct router *curr_router = NULL, *next_router = NULL;
-+static struct timer_list r_timer = { function: timer_handler };
-+static struct timer_list coa_timer = { function: coa_timer_handler };
-+#define MAX_ROUTERS 1000
-+static LIST_HEAD(rtr_list);
-+static int num_routers = 0;
-+static struct handoff *_ho = NULL;
-+/*
-+ * Functions for handling the default router list, which movement
-+ * detection uses for avoiding loops etc.
-+ */
-+
-+/* TODO: Send NS to router after MAX interval has passed from last RA */
-+static int mipv6_router_state(struct router *rtr) {
-+ if (rtr->interval) {
-+ if (time_before(jiffies, (rtr->last_ra_rcvd + (rtr->interval * HZ) / 1000)))
-+ return ROUTER_REACHABLE;
-+ else
-+ return NOT_REACHABLE;
-+ }
-+ else
-+ if (time_after(jiffies, rtr->last_ra_rcvd + (rtr->lifetime * HZ)))
-+ return NOT_REACHABLE;
-+ return ROUTER_REACHABLE;
-+}
-+
-+/* searches for a specific router or any router that is reachable,
-+ * if address is NULL. Also deletes obsolete routers.
-+ */
-+static void mipv6_router_gc(void)
-+{
-+ struct router *curr = NULL;
-+ struct list_head *lh, *lh_tmp;
-+
-+ DEBUG_FUNC();
-+
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ curr = list_entry(lh, struct router, list);
-+ if (mipv6_router_state(curr) == NOT_REACHABLE && !curr->is_current) {
-+ num_routers--;
-+ list_del_init(&curr->list);
-+ DEBUG(DBG_DATADUMP, "Deleting unreachable router %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr->raddr));
-+ kfree(curr);
-+ }
-+ else {
-+ DEBUG(DBG_DATADUMP, "NOT Deleting router %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr->raddr));
-+ }
-+ }
-+}
-+
-+static struct router *mipv6_rtr_get(struct in6_addr *search_addr)
-+{
-+ struct router *rtr = NULL;
-+ struct list_head *lh;
-+
-+ DEBUG_FUNC();
-+
-+ if (search_addr == NULL)
-+ return NULL;
-+ list_for_each(lh, &rtr_list) {
-+ rtr = list_entry(lh, struct router, list);
-+ if(!ipv6_addr_cmp(search_addr, &rtr->raddr)) {
-+ return rtr;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * Adds router to list
-+ */
-+static struct router *mipv6_rtr_add(struct router *nrt)
-+{
-+
-+ struct router *rptr;
-+
-+ DEBUG_FUNC();
-+
-+ /* check if someone is trying DoS attack, or we just have some
-+ memory leaks... */
-+ if (num_routers > MAX_ROUTERS) {
-+ DEBUG(DBG_CRITICAL,
-+ "failed to add new router, MAX_ROUTERS exceeded");
-+ return NULL;
-+ }
-+
-+ rptr = kmalloc(sizeof(struct router), GFP_ATOMIC);
-+ if (rptr) {
-+ memcpy(rptr, nrt, sizeof(struct router));
-+ list_add(&rptr->list, &rtr_list);
-+ num_routers++;
-+ }
-+ DEBUG(DBG_INFO, "Adding router: %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "lifetime : %d sec, adv.interval: %d millisec",
-+ NIPV6ADDR(&rptr->raddr), rptr->lifetime, rptr->interval);
-+
-+ DEBUG(DBG_INFO, "num_routers after addition: %d", num_routers);
-+ return rptr;
-+}
-+
-+/* Cleans up the list */
-+static void list_free(struct router **curr_router_p)
-+{
-+ struct router *tmp;
-+ struct list_head *lh, *lh_tmp;
-+
-+ DEBUG_FUNC();
-+
-+ DEBUG(DBG_INFO, "Freeing the router list");
-+ /* set curr_router->prev_router and curr_router NULL */
-+ *curr_router_p = NULL;
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ tmp = list_entry(lh, struct router, list);
-+ DEBUG(DBG_INFO, "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&tmp->ll_addr));
-+ list_del(&tmp->list);
-+ kfree(tmp);
-+ num_routers--;
-+ }
-+}
-+
-+int rs_state = START;
-+
-+/* Sends router solicitations to all valid devices
-+ * source = link local address (of sending interface)
-+ * dstaddr = all routers multicast address
-+ * Solicitations are sent at an exponentially decreasing rate
-+ *
-+ * TODO: send solicitation first at a normal rate (from ipv6) and
-+ * after that use the exponentially increasing intervals
-+ */
-+static int rs_send(void)
-+{
-+ struct net_device *dev;
-+ struct in6_addr raddr, lladdr;
-+ struct inet6_dev *in6_dev = NULL;
-+ static int num_rs;
-+
-+ if (rs_state == START) {
-+ num_rs = 0;
-+ rs_state = CONTINUE;
-+ } else if (num_rs++ > MAX_RTR_SOLICITATIONS)
-+ return HZ;
-+
-+ ipv6_addr_all_routers(&raddr);
-+ read_lock(&dev_base_lock);
-+
-+ /* Send router solicitations to all interfaces */
-+ for (dev = dev_base; dev; dev = dev->next) {
-+ if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ETHER) {
-+ DEBUG(DBG_DATADUMP, "Sending RS to device %s",
-+ dev->name);
-+ if (!ipv6_get_lladdr(dev, &lladdr)) {
-+ ndisc_send_rs(dev, &lladdr, &raddr);
-+ in6_dev = in6_dev_get(dev);
-+ in6_dev->if_flags |= IF_RS_SENT;
-+ in6_dev_put(in6_dev);
-+ } else {
-+ DEBUG(DBG_DATADUMP, "%s: device doesn't have link-local address!\n", dev->name);
-+ continue;
-+ }
-+ }
-+
-+ }
-+ read_unlock(&dev_base_lock);
-+ return RTR_SOLICITATION_INTERVAL;
-+}
-+
-+/* Create a new CoA for MN and also add a route to it if it is still tentative
-+ to allow MN to get packets to the address immediately
-+ */
-+static int form_coa(struct in6_addr *coa, struct in6_addr *pfix,
-+ int plen, int ifindex)
-+{
-+ struct net_device *dev;
-+ struct inet6_dev *in6_dev;
-+ int ret = 0;
-+
-+ if ((dev = dev_get_by_index(ifindex)) == NULL) {
-+ DEBUG(DBG_WARNING, "Device is not present");
-+ return -1;
-+ }
-+ if ((in6_dev = in6_dev_get(dev)) == NULL) {
-+ DEBUG(DBG_WARNING, "inet6_dev is not present");
-+ dev_put(dev);
-+ return -1;
-+ }
-+ coa->s6_addr32[0] = pfix->s6_addr32[0];
-+ coa->s6_addr32[1] = pfix->s6_addr32[1];
-+
-+ if (ipv6_generate_eui64(coa->s6_addr + 8, dev) &&
-+ ipv6_inherit_eui64(coa->s6_addr + 8, in6_dev)) {
-+ in6_dev_put(in6_dev);
-+ dev_put(dev);
-+ return -1;
-+ }
-+ if (ipv6_chk_addr(coa, dev) == 0) {
-+ DEBUG(DBG_WARNING, "care-of address still tentative");
-+ ret = 1;
-+ }
-+ DEBUG(DBG_INFO, "Formed new CoA: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(coa));
-+
-+ in6_dev_put(in6_dev);
-+ dev_put(dev);
-+ return ret;
-+}
-+
-+static inline int rtr_is_gw(struct router *rtr, struct rt6_info *rt)
-+{
-+ return ((rt->rt6i_flags & RTF_GATEWAY) &&
-+ !ipv6_addr_cmp(&rt->rt6i_gateway, &rtr->ll_addr));
-+}
-+
-+static inline int is_prefix_route(struct router *rtr, struct rt6_info *rt)
-+{
-+ return (!(rt->rt6i_flags & RTF_GATEWAY) &&
-+ mipv6_prefix_compare(&rt->rt6i_dst.addr, &rtr->raddr,
-+ rtr->pfix_len));
-+}
-+
-+/*
-+ * Function that determines whether given rt6_info should be destroyed
-+ * (negative => destroy rt6_info, zero or positive => do nothing)
-+ */
-+static int mn_route_cleaner(struct rt6_info *rt, void *arg)
-+{
-+ int type;
-+
-+ struct router *rtr = (struct router *)arg;
-+
-+ int ret = -1;
-+
-+ DEBUG_FUNC();
-+
-+ if (!rt || !rtr) {
-+ DEBUG(DBG_ERROR, "mn_route_cleaner: rt or rtr NULL");
-+ return 0;
-+ }
-+
-+ /* Do not delete routes to local addresses or to multicast
-+ * addresses, since we need them to get router advertisements
-+ * etc. Multicast addresses are more tricky, but we don't
-+ * delete them in any case. The routing mechanism is not optimal for
-+ * multihoming.
-+ *
-+ * Also keep all new prefix routes, gateway routes through rtr and
-+ * all remaining default routes (including those used for reverse
-+ * tunneling)
-+ */
-+ type = ipv6_addr_type(&rt->rt6i_dst.addr);
-+
-+ if ((type & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)) ||
-+ rt->rt6i_dev == &loopback_dev || rtr_is_gw(rtr, rt) ||
-+ is_prefix_route(rtr, rt) || (rt->rt6i_flags & RTF_DEFAULT))
-+ ret = 0;
-+
-+ /* delete all others */
-+
-+ if (rt->rt6i_dev != &loopback_dev) {
-+ DEBUG(DEBUG_MDETECT,
-+ "%s route:\n"
-+ "dev: %s,\n"
-+ "gw: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "flags: %x,\n"
-+ "metric: %d,\n"
-+ "src: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "dst: %x:%x:%x:%x:%x:%x:%x:%x,\n"
-+ "plen: %d\n",
-+ (ret ? "Deleting" : "Keeping"),
-+ rt->rt6i_dev->name,
-+ NIPV6ADDR(&rt->rt6i_gateway),
-+ rt->rt6i_flags,
-+ rt->rt6i_metric,
-+ NIPV6ADDR(&rt->rt6i_src.addr),
-+ NIPV6ADDR(&rt->rt6i_dst.addr),
-+ rt->rt6i_dst.plen);
-+ }
-+ return ret;
-+}
-+
-+/*
-+ * Deletes old routes
-+ */
-+static __inline__ void delete_routes(struct router *rtr)
-+{
-+ DEBUG_FUNC();
-+
-+ /* Routing table is locked to ensure that nobody uses its */
-+ write_lock_bh(&rt6_lock);
-+ DEBUG(DBG_INFO, "mipv6: Purging routes");
-+ /* TODO: Does not prune, should it? */
-+ fib6_clean_tree(&ip6_routing_table,
-+ mn_route_cleaner, 0, rtr);
-+ write_unlock_bh(&rt6_lock);
-+
-+}
-+
-+
-+static __inline__ void delete_coas(struct router *rtr)
-+{
-+ struct net_device *dev;
-+ struct inet6_dev *idev;
-+ struct inet6_ifaddr *ifa;
-+
-+ dev = dev_get_by_index(rtr->ifindex);
-+ if (!dev)
-+ return;
-+
-+ idev = in6_dev_get(dev);
-+
-+ if (idev) {
-+ read_lock_bh(&idev->lock);
-+ ifa = idev->addr_list;
-+ while (ifa) {
-+ int keep;
-+ spin_lock(&ifa->lock);
-+
-+ keep = (ifa->flags&(IFA_F_PERMANENT|IFA_F_HOMEADDR) ||
-+ !ipv6_addr_cmp(&ifa->addr, &rtr->CoA));
-+
-+ spin_unlock(&ifa->lock);
-+
-+ if (keep)
-+ ifa = ifa->if_next;
-+ else {
-+ in6_ifa_hold(ifa);
-+ read_unlock_bh(&idev->lock);
-+
-+ ipv6_del_addr(ifa);
-+
-+ read_lock_bh(&idev->lock);
-+ ifa = idev->addr_list;
-+ }
-+ }
-+ read_unlock_bh(&idev->lock);
-+ in6_dev_put(idev);
-+ }
-+ dev_put(dev);
-+}
-+
-+int next_mdet_state[3][3] = {{CURR_RTR_OK, NO_RTR, NO_RTR},
-+ {CURR_RTR_OK, CURR_RTR_OK, NO_RTR},
-+ {CURR_RTR_OK, CURR_RTR_OK, RTR_SUSPECT}};
-+
-+char *states[3] = {"NO_RTR", "RTR_SUSPECT", "CURR_RTR_OK"};
-+char *events[3] = {"RA_RCVD", "NA_RCVD", "TIMEOUT"};
-+
-+/* State transitions
-+ * NO_RTR, RA_RCVD -> CURR_RTR_OK
-+ * NO_RTR, NA_RCVD -> NO_RTR
-+ * NO_RTR, TIMEOUT -> NO_RTR
-+
-+ * RTR_SUSPECT, RA_RCVD -> CURR_RTR_OK
-+ * RTR_SUSPECT, NA_RCVD -> CURR_RTR_OK
-+ * RTR_SUSPECT, TIMEOUT -> NO_RTR
-+
-+ * CURR_RTR_OK, RA_RCVD -> CURR_RTR_OK
-+ * CURR_RTR_OK, NA_RCVD -> CURR_RTR_OK
-+ * CURR_RTR_OK, TIMEOUT -> RTR_SUSPECT
-+ */
-+static int _curr_state = NO_RTR;
-+
-+#if 0
-+static int get_mdet_state(void){
-+ int state;
-+ spin_lock_bh(&router_lock);
-+ state = _curr_state;
-+ spin_unlock_bh(&router_lock);
-+ return state;
-+}
-+#endif
-+
-+/* Needs to be called with router_lock locked */
-+static int mdet_statemachine(int event)
-+{
-+
-+ if (event > 2 || _curr_state > 2) {
-+ DEBUG(DBG_ERROR, "Got illegal event or curr_state");
-+ return -1;
-+ }
-+
-+ DEBUG(DBG_DATADUMP, "Got event %s and curr_state is %s",
-+ events[event], states[_curr_state]);
-+
-+ _curr_state = next_mdet_state[_curr_state][event];
-+ DEBUG(DBG_DATADUMP, "Next state is %s", states[_curr_state]);
-+ return _curr_state;
-+}
-+
-+static void mipv6_do_ll_dad(int ifindex)
-+{
-+ struct net_device *dev = dev_get_by_index(ifindex);
-+ if (dev) {
-+ struct in6_addr lladdr;
-+ struct inet6_ifaddr *ifa;
-+ if (!ipv6_get_lladdr(dev, &lladdr) &&
-+ (ifa = ipv6_get_ifaddr(&lladdr, dev)) != NULL) {
-+ spin_lock_bh(&ifa->lock);
-+ if (!(ifa->flags & IFA_F_TENTATIVE)) {
-+ ifa->flags |= IFA_F_TENTATIVE;
-+ spin_unlock_bh(&ifa->lock);
-+ addrconf_dad_start(ifa, 0);
-+ } else
-+ spin_unlock_bh(&ifa->lock);
-+
-+ }
-+ dev_put(dev);
-+ }
-+}
-+/*
-+ * Changes the router, called from ndisc.c if mipv6_router_event
-+ * returns true.
-+ */
-+
-+static void mipv6_change_router(void)
-+{
-+ struct in6_addr coa;
-+ int ret, ifindex;
-+
-+ DEBUG_FUNC();
-+
-+
-+ if (next_router == NULL)
-+ return;
-+
-+ spin_lock(&router_lock);
-+
-+
-+ if (curr_router != NULL &&
-+ !ipv6_addr_cmp(&curr_router->ll_addr, &next_router->ll_addr)) {
-+ DEBUG(DBG_INFO,"Trying to handoff from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&curr_router->ll_addr));
-+ DEBUG(DBG_INFO,"Trying to handoff to: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&next_router->ll_addr));
-+ next_router = NULL; /* Let's not leave dangling pointers */
-+ spin_unlock(&router_lock);
-+ return;
-+ }
-+ ret = form_coa(&next_router->CoA, &next_router->raddr,
-+ next_router->pfix_len, next_router->ifindex);
-+ if (ret < 0) {
-+ DEBUG(DBG_ERROR, "handoff: Creation of coa failed");
-+ spin_unlock(&router_lock);
-+ return;
-+ } else if (ret > 0)
-+ next_router->flags |= COA_TENTATIVE;
-+
-+ mdet_statemachine(RA_RCVD); /* TODO: What if DAD fails... */
-+ if (next_router->interval)
-+ mod_timer(&r_timer, jiffies +
-+ (next_router->interval * HZ)/1000);
-+ else
-+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ);
-+
-+
-+ if (ret == 0) {
-+ ipv6_addr_copy(&coa, &next_router->CoA);
-+ ifindex = next_router->ifindex;
-+ spin_unlock(&router_lock);
-+ mipv6_mdet_finalize_ho(&coa, ifindex);
-+ return;
-+ }
-+ spin_unlock(&router_lock);
-+
-+}
-+static unsigned long ns_send(void)
-+{
-+ struct neighbour *neigh;
-+ struct net_device *dev;
-+ struct in6_addr *raddr;
-+
-+ DEBUG(DBG_DATADUMP, "Sending Neighbour solicitation to default router to verify its reachability");
-+ if (!curr_router)
-+ return HZ;
-+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL)
-+ return HZ;
-+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) {
-+ dev_put(dev);
-+ return HZ;
-+ }
-+ if (curr_router->glob_addr)
-+ raddr = &curr_router->raddr;
-+ else
-+ raddr = &curr_router->ll_addr;
-+
-+ curr_router->last_ns_sent = jiffies;
-+ ndisc_send_ns(dev, neigh, raddr, raddr, NULL);
-+
-+ neigh_release(neigh);
-+ dev_put(dev);
-+ return HZ/5; /* Wait 200ms for a reply */
-+}
-+
-+static int na_rcvd(void)
-+{
-+ int neigh_ok = 0;
-+ struct neighbour *neigh;
-+ struct net_device *dev;
-+
-+ if (!curr_router)
-+ return 0;
-+ if ((dev = dev_get_by_index(curr_router->ifindex)) == NULL)
-+ return 0;
-+ if ((neigh = ndisc_get_neigh(dev, &curr_router->ll_addr)) == NULL) {
-+ dev_put(dev);
-+ return 0;
-+ }
-+ if (neigh->flags & NTF_ROUTER &&
-+ (time_after(neigh->confirmed, curr_router->last_ns_sent) ||
-+ neigh->confirmed == curr_router->last_ns_sent)) {
-+ neigh_ok = 1;
-+ DEBUG(DBG_DATADUMP, "Mdetect event: NA rcvd from curr rtr");
-+ } else
-+ DEBUG(DBG_DATADUMP, "Mdetect event: NA NOT rcvd from curr rtr within time limit");
-+ neigh_release(neigh);
-+ dev_put(dev);
-+ return neigh_ok;
-+}
-+
-+static void coa_timer_handler(unsigned long dummy)
-+{
-+
-+ spin_lock_bh(&ho_lock);
-+ if (_ho) {
-+ DEBUG(DBG_INFO, "Starting handoff after DAD");
-+ mipv6_mobile_node_moved(_ho);
-+ kfree(_ho);
-+ _ho = NULL;
-+ }
-+ spin_unlock_bh(&ho_lock);
-+}
-+static void timer_handler(unsigned long foo)
-+{
-+ unsigned long timeout;
-+ int state;
-+ spin_lock_bh(&router_lock);
-+
-+ if (_curr_state != NO_RTR)
-+ rs_state = START;
-+
-+ if (_curr_state == RTR_SUSPECT && na_rcvd()) {
-+ state = mdet_statemachine(NA_RCVD);
-+ timeout = curr_router->interval ? curr_router->interval : max_rtr_reach_time * HZ;
-+ } else {
-+ state = mdet_statemachine(TIMEOUT);
-+ if (state == NO_RTR)
-+ timeout = rs_send();
-+ else /* RTR_SUSPECT */
-+ timeout = ns_send();
-+ }
-+ if (!timeout)
-+ timeout = HZ;
-+
-+ mipv6_router_gc();
-+ mod_timer(&r_timer, jiffies + timeout);
-+ spin_unlock_bh(&router_lock);
-+}
-+
-+/**
-+ * mipv6_get_care_of_address - get node's care-of primary address
-+ * @homeaddr: one of node's home addresses
-+ * @coaddr: buffer to store care-of address
-+ *
-+ * Stores the current care-of address in the @coaddr, assumes
-+ * addresses in EUI-64 format. Since node might have several home
-+ * addresses caller MUST supply @homeaddr. If node is at home
-+ * @homeaddr is stored in @coaddr. Returns 0 on success, otherwise a
-+ * negative value.
-+ **/
-+int mipv6_get_care_of_address(
-+ struct in6_addr *homeaddr, struct in6_addr *coaddr)
-+{
-+
-+ DEBUG_FUNC();
-+
-+ if (homeaddr == NULL)
-+ return -1;
-+ spin_lock_bh(&router_lock);
-+ if (curr_router == NULL || mipv6_mn_is_at_home(homeaddr) ||
-+ mipv6_prefix_compare(homeaddr, &curr_router->raddr, 64) ||
-+ curr_router->flags&COA_TENTATIVE) {
-+ DEBUG(DBG_INFO,
-+ "mipv6_get_care_of_address: returning home address");
-+ ipv6_addr_copy(coaddr, homeaddr);
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+
-+ }
-+
-+ /* At home or address check failure probably due to dad wait */
-+ if (mipv6_prefix_compare(&curr_router->raddr, homeaddr,
-+ curr_router->pfix_len)
-+ || (dad == RESPECT_DAD &&
-+ (ipv6_chk_addr(coaddr, NULL) == 0))) {
-+ ipv6_addr_copy(coaddr, homeaddr);
-+ } else {
-+ ipv6_addr_copy(coaddr, &curr_router->CoA);
-+ }
-+
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+
-+int mipv6_mdet_del_if(int ifindex)
-+{
-+ struct router *curr = NULL;
-+ struct list_head *lh, *lh_tmp;
-+
-+ spin_lock_bh(&router_lock);
-+ list_for_each_safe(lh, lh_tmp, &rtr_list) {
-+ curr = list_entry(lh, struct router, list);
-+ if (curr->ifindex == ifindex) {
-+ num_routers--;
-+ list_del_init(&curr->list);
-+ DEBUG(DBG_DATADUMP, "Deleting router %x:%x:%x:%x:%x:%x:%x:%x on interface %d",
-+ NIPV6ADDR(&curr->raddr), ifindex);
-+ if (curr_router == curr)
-+ curr_router = NULL;
-+ kfree(curr);
-+ }
-+ }
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+
-+void mipv6_mdet_retrigger_ho(void)
-+{
-+ struct handoff ho;
-+
-+ spin_lock_bh(&router_lock);
-+ if (curr_router != NULL) {
-+ ho.coa = &curr_router->CoA;
-+ ho.plen = curr_router->pfix_len;
-+ ho.ifindex = curr_router->ifindex;
-+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr);
-+ ho.home_address = (curr_router->glob_addr &&
-+ curr_router->flags&ND_RA_FLAG_HA);
-+ }
-+ spin_unlock_bh(&router_lock);
-+ mipv6_mobile_node_moved(&ho);
-+}
-+
-+void mipv6_mdet_set_curr_rtr_reachable(int reachable)
-+{
-+ spin_lock_bh(&router_lock);
-+ if (curr_router != NULL) {
-+ curr_router->reachable = reachable;
-+ }
-+ spin_unlock_bh(&router_lock);
-+
-+}
-+
-+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex)
-+{
-+ int dummy;
-+ struct handoff ho;
-+ struct router *tmp;
-+ struct net_device *dev;
-+ struct in6_addr ll_addr;
-+
-+ spin_lock_bh(&router_lock);
-+
-+ if (!next_router) {
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+ }
-+
-+ dev = dev_get_by_index(next_router->ifindex);
-+
-+ if (ipv6_get_lladdr(dev, &ll_addr) == 0) {
-+ if (ipv6_addr_cmp(&ll_addr, coa) == 0)
-+ DEBUG(DBG_INFO, "DAD for link local address completed");
-+ next_router->flags &= ~LLADDR_TENTATIVE;
-+ }
-+
-+ dev_put(dev);
-+
-+ if (mipv6_prefix_compare(coa, &next_router->CoA,
-+ next_router->pfix_len)) {
-+ DEBUG(DBG_INFO, "DAD for Care-of address completed");
-+ next_router->flags &= ~COA_TENTATIVE;
-+ }
-+ if (!(next_router->flags&LLADDR_TENTATIVE) && !(next_router->flags&COA_TENTATIVE)) {
-+ DEBUG(DBG_INFO, "%s: Proceeding with handoff after DAD\n", __FUNCTION__);
-+ tmp = curr_router;
-+ curr_router = next_router;
-+ curr_router->is_current = 1;
-+ next_router = NULL;
-+ curr_router->flags &= ~COA_TENTATIVE;
-+ delete_routes(curr_router);
-+ delete_coas(curr_router);
-+ if (tmp) {
-+ struct net_device *dev_old = dev_get_by_index(tmp->ifindex);
-+ struct rt6_info *rt = NULL;
-+ if (dev_old) {
-+ rt = rt6_get_dflt_router(&tmp->ll_addr, dev_old);
-+ dev_put(dev_old);
-+ }
-+ if (rt)
-+ ip6_del_rt(rt, NULL);
-+ tmp->is_current = 0;
-+ }
-+
-+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy);
-+ ma_ctl_upd_iface(curr_router->ifindex, MA_IFACE_CURRENT, &dummy);
-+
-+
-+ ho.coa = &curr_router->CoA;
-+ ho.plen = curr_router->pfix_len;
-+ ho.ifindex = curr_router->ifindex;
-+ ipv6_addr_copy(&ho.rtr_addr, &curr_router->raddr);
-+ ho.home_address = (curr_router->glob_addr &&
-+ curr_router->flags&ND_RA_FLAG_HA);
-+
-+ spin_unlock_bh(&router_lock);
-+ mipv6_mobile_node_moved(&ho);
-+ } else
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
-+/* Decides whether router candidate is the same router as current rtr
-+ * based on prefix / global addresses of the routers and their link local
-+ * addresses
-+ */
-+static int is_current_rtr(struct router *nrt, struct router *crt)
-+{
-+ DEBUG_FUNC();
-+
-+ DEBUG(DEBUG_MDETECT, "Current router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x and", NIPV6ADDR(&crt->raddr));
-+ DEBUG(DEBUG_MDETECT, "Candidate router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&nrt->raddr));
-+
-+ return (!ipv6_addr_cmp(&nrt->raddr,&crt->raddr) &&
-+ !ipv6_addr_cmp(&nrt->ll_addr, &crt->ll_addr));
-+}
-+
-+/*
-+ * Change next router to nrtr
-+ * Returns 1, if router has been changed.
-+ */
-+
-+static int change_next_rtr(struct router *nrtr, struct router *ortr)
-+{
-+ int changed = 0;
-+ DEBUG_FUNC();
-+
-+ if (!next_router || ipv6_addr_cmp(&nrtr->raddr, &next_router->raddr)) {
-+ changed = 1;
-+ }
-+ next_router = nrtr;
-+ return changed;
-+}
-+static int clean_ncache(struct router *nrt, struct router *ort, int same_if)
-+{
-+ struct net_device *ortdev;
-+ DEBUG_FUNC();
-+
-+ /* Always call ifdown after a handoff to ensure proper routing */
-+
-+ if (!ort)
-+ return 0;
-+ if ((ortdev = dev_get_by_index(ort->ifindex)) == NULL) {
-+ DEBUG(DBG_WARNING, "Device is not present");
-+ return -1;
-+ }
-+ neigh_ifdown(&nd_tbl, ortdev);
-+ dev_put(ortdev);
-+ return 0;
-+}
-+
-+static int mdet_get_if_preference(int ifi)
-+{
-+ int pref = 0;
-+
-+ DEBUG_FUNC();
-+
-+ pref = ma_ctl_get_preference(ifi);
-+
-+ DEBUG(DEBUG_MDETECT, "ifi: %d preference %d", ifi, pref);
-+
-+ return pref;
-+}
-+
-+/*
-+ * Called from mipv6_mn_ra_rcv to determine whether to do a handoff.
-+ */
-+static int mipv6_router_event(struct router *rptr)
-+{
-+ struct router *nrt = NULL;
-+ int new_router = 0, same_if = 1;
-+ int oldstate = _curr_state;
-+ int addrtype = ipv6_addr_type(&rptr->raddr);
-+
-+ DEBUG_FUNC();
-+
-+ if (rptr->lifetime == 0)
-+ return MIPV6_IGN_RTR;
-+ DEBUG(DEBUG_MDETECT, "Received a RA from router: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x", NIPV6ADDR(&rptr->raddr));
-+ spin_lock(&router_lock);
-+
-+ /* Add or update router entry */
-+ if ((nrt = mipv6_rtr_get(&rptr->raddr)) == NULL) {
-+ if (addrtype == IPV6_ADDR_ANY || (nrt = mipv6_rtr_add(rptr)) == NULL) {
-+ spin_unlock(&router_lock);
-+ return MIPV6_IGN_RTR;
-+ }
-+ DEBUG(DBG_INFO, "Router not on list,adding it to the list");
-+ new_router = 1;
-+ }
-+ nrt->last_ra_rcvd = jiffies;
-+ nrt->state = ROUTER_REACHABLE;
-+ nrt->interval = rptr->interval;
-+ nrt->lifetime = rptr->lifetime;
-+ nrt->ifindex = rptr->ifindex;
-+ nrt->flags = rptr->flags;
-+ nrt->glob_addr = rptr->glob_addr;
-+
-+ /* Whether from current router */
-+ if (curr_router && curr_router->reachable &&
-+ is_current_rtr(nrt, curr_router)) {
-+ if (nrt->interval)
-+ mod_timer(&r_timer, jiffies + (nrt->interval * HZ)/1000);
-+ else
-+ mod_timer(&r_timer, jiffies + max_rtr_reach_time * HZ);
-+ mdet_statemachine(RA_RCVD);
-+ spin_unlock(&router_lock);
-+ return MIPV6_ADD_RTR;
-+ } else if (oldstate == NO_RTR) {
-+ rt6_purge_dflt_routers(0); /* For multiple interface case */
-+ DEBUG(DBG_INFO, "No router or router not reachable, switching to new one");
-+ goto handoff;
-+ }
-+ if (!curr_router) {
-+ /* Startup */
-+ goto handoff;
-+ }
-+ /* Router behind same interface as current one ?*/
-+ same_if = (nrt->ifindex == curr_router->ifindex);
-+ /* Switch to new router behind same interface if eager cell
-+ * switching is used or if the interface is preferred
-+ */
-+ if ((new_router && eager_cell_switching && same_if) ||
-+ (mdet_get_if_preference(nrt->ifindex) >
-+ mdet_get_if_preference(curr_router->ifindex))) {
-+ DEBUG(DBG_INFO, "Switching to new router.");
-+ goto handoff;
-+ }
-+
-+ /* No handoff, don't add default route */
-+ DEBUG(DEBUG_MDETECT, "Ignoring RA");
-+ spin_unlock(&router_lock);
-+ return MIPV6_IGN_RTR;
-+handoff:
-+ clean_ncache(nrt, curr_router, same_if);
-+ nrt->reachable = 1;
-+ if (same_if && change_next_rtr(nrt, curr_router)) {
-+ mipv6_do_ll_dad(nrt->ifindex);
-+ nrt->flags |= LLADDR_TENTATIVE;
-+ }
-+ spin_unlock(&router_lock);
-+
-+ return MIPV6_CHG_RTR;
-+}
-+
-+/*
-+ * Called from ndisc.c's router_discovery.
-+ */
-+
-+static inline int ret_to_ha(struct in6_addr *addr)
-+{
-+ int res = 0;
-+ struct mn_info *minfo;
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_ha(addr);
-+ if (minfo != NULL) {
-+ spin_lock(&minfo->lock);
-+ if (minfo->has_home_reg) {
-+ res = 1;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock(&mn_info_lock);
-+ return res;
-+}
-+
-+static int mipv6_mn_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts)
-+{
-+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif;
-+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct router nrt;
-+ struct in6_addr *ha = NULL;
-+ u8 *lladdr = NULL;
-+ int res;
-+ DEBUG_FUNC();
-+
-+ memset(&nrt, 0, sizeof(struct router));
-+
-+ if (ra->icmph.icmp6_home_agent) {
-+ nrt.flags |= ND_RA_FLAG_HA;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_HA up");
-+ }
-+
-+ if (ra->icmph.icmp6_addrconf_managed) {
-+ nrt.flags |= ND_RA_FLAG_MANAGED;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_MANAGED up");
-+ }
-+
-+ if (ra->icmph.icmp6_addrconf_other) {
-+ nrt.flags |= ND_RA_FLAG_OTHER;
-+ DEBUG(DBG_DATADUMP, "RA has ND_RA_FLAG_OTHER up");
-+ }
-+
-+ ipv6_addr_copy(&nrt.ll_addr, saddr);
-+ nrt.ifindex = ifi;
-+ nrt.lifetime = ntohs(ra->icmph.icmp6_rt_lifetime);
-+
-+ if (ndopts->nd_opts_src_lladdr) {
-+ lladdr = (u8 *) ndopts->nd_opts_src_lladdr+2;
-+ nrt.link_addr_len = skb->dev->addr_len;
-+ memcpy(nrt.link_addr, lladdr, nrt.link_addr_len);
-+ }
-+ if (ndopts->nd_opts_pi) {
-+ struct nd_opt_hdr *p;
-+ for (p = ndopts->nd_opts_pi;
-+ p;
-+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) {
-+ struct prefix_info *pinfo;
-+ int update = 0;
-+
-+ pinfo = (struct prefix_info *) p;
-+
-+ if (!pinfo->autoconf)
-+ continue;
-+
-+ if ((pinfo->router_address &&
-+ (update = ret_to_ha(&pinfo->prefix))) ||
-+ ipv6_addr_type(&nrt.raddr) != IPV6_ADDR_UNICAST) {
-+ ipv6_addr_copy(&nrt.raddr, &pinfo->prefix);
-+ nrt.pfix_len = pinfo->prefix_len;
-+ if (pinfo->router_address)
-+ nrt.glob_addr = 1;
-+ else
-+ nrt.glob_addr = 0;
-+ if (update)
-+ ha = &pinfo->prefix;
-+ DEBUG(DBG_DATADUMP, "Address of the received "
-+ "prefix info option: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&nrt.raddr));
-+ DEBUG(DBG_DATADUMP, "the length of the prefix is %d",
-+ nrt.pfix_len);
-+ }
-+ }
-+ }
-+ if (ndopts->nd_opts_rai) {
-+ nrt.interval = ntohl(*(__u32 *)(ndopts->nd_opts_rai+4));
-+ DEBUG(DBG_DATADUMP,
-+ "received router interval option with interval : %d ",
-+ nrt.interval / HZ);
-+
-+ if (nrt.interval > MAX_RADV_INTERVAL) {
-+ nrt.interval = 0;
-+ DEBUG(DBG_DATADUMP, "but we are using: %d, "
-+ "because interval>MAX_RADV_INTERVAL",
-+ nrt.interval / HZ);
-+ }
-+ }
-+
-+ res = mipv6_router_event(&nrt);
-+
-+ if (ha && lladdr) {
-+ mipv6_mn_ha_nd_update(__dev_get_by_index(ifi), ha, lladdr);
-+ }
-+ return res;
-+}
-+
-+int __init mipv6_initialize_mdetect(void)
-+{
-+
-+ DEBUG_FUNC();
-+
-+ spin_lock_init(&router_lock);
-+ spin_lock_init(&ho_lock);
-+ init_timer(&coa_timer);
-+ init_timer(&r_timer);
-+ r_timer.expires = jiffies + HZ;
-+ add_timer(&r_timer);
-+
-+ /* Actual HO, also deletes old routes after the addition of new ones
-+ in ndisc */
-+ MIPV6_SETCALL(mipv6_change_router, mipv6_change_router);
-+
-+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_mn_ra_rcv);
-+
-+ return 0;
-+}
-+
-+int __exit mipv6_shutdown_mdetect()
-+{
-+
-+ DEBUG_FUNC();
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_change_router);
-+ spin_lock_bh(&router_lock);
-+ spin_lock(&ho_lock);
-+ del_timer(&coa_timer);
-+ del_timer(&r_timer);
-+ /* Free the memory allocated by router list */
-+ list_free(&curr_router);
-+ if (_ho)
-+ kfree(_ho);
-+ spin_unlock(&ho_lock);
-+ spin_unlock_bh(&router_lock);
-+ return 0;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mdetect.h
-@@ -0,0 +1,37 @@
-+/*
-+ * MIPL Mobile IPv6 Movement detection module header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MDETECT_H
-+#define _MDETECT_H
-+
-+struct handoff {
-+ int home_address; /* Is the coa a home address */
-+ int ifindex;
-+ int plen;
-+ struct in6_addr *coa;
-+ struct in6_addr rtr_addr; /* Prefix or rtr address if coa is home address */
-+};
-+
-+int mipv6_initialize_mdetect(void);
-+
-+int mipv6_shutdown_mdetect(void);
-+
-+int mipv6_get_care_of_address(struct in6_addr *homeaddr, struct in6_addr *coa);
-+
-+int mipv6_mdet_del_if(int ifindex);
-+
-+int mipv6_mdet_finalize_ho(const struct in6_addr *coa, const int ifindex);
-+
-+void mipv6_mdet_retrigger_ho(void);
-+
-+void mipv6_mdet_set_curr_rtr_reachable(int reachable);
-+
-+#endif /* _MDETECT_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mipv6_icmp.c
-@@ -0,0 +1,342 @@
-+/**
-+ * Generic icmp routines
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>,
-+ * Ville Nuorvala <vnuorval@tcs.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <net/checksum.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+#include <net/mipglue.h>
-+
-+#include "debug.h"
-+#include "bcache.h"
-+#include "mipv6_icmp.h"
-+#include "config.h"
-+
-+struct mipv6_icmpv6_msg {
-+ struct icmp6hdr icmph;
-+ __u8 *data;
-+ struct in6_addr *daddr;
-+ int len;
-+ __u32 csum;
-+};
-+
-+#define MIPV6_ICMP_HOP_LIMIT 64
-+
-+static struct socket *mipv6_icmpv6_socket = NULL;
-+static __u16 identifier = 0;
-+
-+int mipv6_icmpv6_no_rcv(struct sk_buff *skb)
-+{
-+ return 0;
-+}
-+
-+static int mipv6_icmpv6_xmit_holder = -1;
-+
-+static int mipv6_icmpv6_xmit_lock_bh(void)
-+{
-+ if (!spin_trylock(&mipv6_icmpv6_socket->sk->lock.slock)) {
-+ if (mipv6_icmpv6_xmit_holder == smp_processor_id())
-+ return -EAGAIN;
-+ spin_lock(&mipv6_icmpv6_socket->sk->lock.slock);
-+ }
-+ mipv6_icmpv6_xmit_holder = smp_processor_id();
-+ return 0;
-+}
-+
-+static __inline__ int mipv6_icmpv6_xmit_lock(void)
-+{
-+ int ret;
-+ local_bh_disable();
-+ ret = mipv6_icmpv6_xmit_lock_bh();
-+ if (ret)
-+ local_bh_enable();
-+ return ret;
-+}
-+
-+static void mipv6_icmpv6_xmit_unlock_bh(void)
-+{
-+ mipv6_icmpv6_xmit_holder = -1;
-+ spin_unlock(&mipv6_icmpv6_socket->sk->lock.slock);
-+}
-+
-+static __inline__ void mipv6_icmpv6_xmit_unlock(void)
-+{
-+ mipv6_icmpv6_xmit_unlock_bh();
-+ local_bh_enable();
-+}
-+
-+
-+/**
-+ * mipv6_icmpv6_dest_unreach - Destination Unreachable ICMP error message handler
-+ * @skb: buffer containing ICMP error message
-+ *
-+ * Special Mobile IPv6 ICMP handling. If Correspondent Node receives
-+ * persistent ICMP Destination Unreachable messages for a destination
-+ * in its Binding Cache, the binding should be deleted. See draft
-+ * section 8.8.
-+ **/
-+static int mipv6_icmpv6_rcv_dest_unreach(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
-+ struct ipv6hdr *ipv6h = (struct ipv6hdr *) (icmph + 1);
-+ int left = (skb->tail - skb->h.raw) - sizeof(*icmph)- sizeof(ipv6h);
-+ struct ipv6_opt_hdr *eh;
-+ struct rt2_hdr *rt2h = NULL;
-+ struct in6_addr *daddr = &ipv6h->daddr;
-+ struct in6_addr *saddr = &ipv6h->saddr;
-+ int hdrlen, nexthdr = ipv6h->nexthdr;
-+ struct mipv6_bce bce;
-+ DEBUG_FUNC();
-+
-+ eh = (struct ipv6_opt_hdr *) (ipv6h + 1);
-+
-+ while (left > 0) {
-+ if (nexthdr != NEXTHDR_HOP && nexthdr != NEXTHDR_DEST &&
-+ nexthdr != NEXTHDR_ROUTING)
-+ return 0;
-+
-+ hdrlen = ipv6_optlen(eh);
-+ if (hdrlen > left)
-+ return 0;
-+
-+ if (nexthdr == NEXTHDR_ROUTING) {
-+ struct ipv6_rt_hdr *rth = (struct ipv6_rt_hdr *) eh;
-+
-+ if (rth->type == IPV6_SRCRT_TYPE_2) {
-+ if (hdrlen != sizeof(struct rt2_hdr))
-+ return 0;
-+
-+ rt2h = (struct rt2_hdr *) rth;
-+
-+ if (rt2h->rt_hdr.segments_left > 0)
-+ daddr = &rt2h->addr;
-+ break;
-+ }
-+ }
-+ /* check for home address option in case this node is a MN */
-+ if (nexthdr == NEXTHDR_DEST) {
-+ __u8 *raw = (__u8 *) eh;
-+ __u16 i = 2;
-+ while (1) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+
-+ if (i + sizeof (*hao) > hdrlen)
-+ break;
-+
-+ hao = (struct mipv6_dstopt_homeaddr *) &raw[i];
-+
-+ if (hao->type == MIPV6_TLV_HOMEADDR &&
-+ hao->length == sizeof(struct in6_addr)) {
-+ saddr = &hao->addr;
-+ break;
-+ }
-+ if (hao->type)
-+ i += hao->length + 2;
-+ else
-+ i++;
-+ }
-+
-+ }
-+ nexthdr = eh->nexthdr;
-+ eh = (struct ipv6_opt_hdr *) ((u8 *) eh + hdrlen);
-+ left -= hdrlen;
-+ }
-+ if (rt2h == NULL) return 0;
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bce) == 0 && !(bce.flags&HOME_REGISTRATION)) {
-+ /* A primitive algorithm for detecting persistent ICMP destination unreachable messages */
-+ if (bce.destunr_count &&
-+ time_after(jiffies,
-+ bce.last_destunr + MIPV6_DEST_UNR_IVAL*HZ))
-+ bce.destunr_count = 0;
-+
-+ bce.destunr_count++;
-+
-+ mipv6_bcache_icmp_err(daddr, saddr, bce.destunr_count);
-+
-+ if (bce.destunr_count > MIPV6_MAX_DESTUNREACH && mipv6_bcache_delete(daddr, saddr, CACHE_ENTRY) == 0) {
-+ DEBUG(DBG_INFO, "Deleted bcache entry "
-+ "%x:%x:%x:%x:%x:%x:%x:%x "
-+ "%x:%x:%x:%x:%x:%x:%x:%x (reason: "
-+ "%d dest unreachables) ",
-+ NIPV6ADDR(daddr), NIPV6ADDR(saddr), bce.destunr_count);
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int mipv6_icmpv6_getfrag(const void *data, struct in6_addr *saddr,
-+ char *buff, unsigned int offset,
-+ unsigned int len)
-+{
-+ struct mipv6_icmpv6_msg *msg = (struct mipv6_icmpv6_msg *) data;
-+ struct icmp6hdr *icmph;
-+ __u32 csum;
-+
-+ if (offset) {
-+ msg->csum = csum_partial_copy_nocheck(msg->data + offset -
-+ sizeof(*icmph), buff,
-+ len, msg->csum);
-+ return 0;
-+ }
-+
-+ csum = csum_partial_copy_nocheck((__u8 *) &msg->icmph, buff,
-+ sizeof(*icmph), msg->csum);
-+
-+ csum = csum_partial_copy_nocheck(msg->data, buff + sizeof(*icmph),
-+ len - sizeof(*icmph), csum);
-+
-+ icmph = (struct icmp6hdr *) buff;
-+
-+ icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
-+ IPPROTO_ICMPV6, csum);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_icmpv6_send - generic icmpv6 message send
-+ * @daddr: destination address
-+ * @saddr: source address
-+ * @type: icmp type
-+ * @code: icmp code
-+ * @id: packet identifier. If null, uses internal counter to get new id
-+ * @data: packet data
-+ * @datalen: length of data in bytes
-+ */
-+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr, int type,
-+ int code, __u16 *id, __u16 flags, void *data, int datalen)
-+{
-+ struct sock *sk = mipv6_icmpv6_socket->sk;
-+ struct flowi fl;
-+ struct mipv6_icmpv6_msg msg;
-+
-+ DEBUG_FUNC();
-+
-+ fl.proto = IPPROTO_ICMPV6;
-+ fl.fl6_dst = daddr;
-+ fl.fl6_src = saddr;
-+ fl.fl6_flowlabel = 0;
-+ fl.uli_u.icmpt.type = type;
-+ fl.uli_u.icmpt.code = code;
-+
-+ msg.icmph.icmp6_type = type;
-+ msg.icmph.icmp6_code = code;
-+ msg.icmph.icmp6_cksum = 0;
-+
-+ if (id)
-+ msg.icmph.icmp6_identifier = htons(*id);
-+ else
-+ msg.icmph.icmp6_identifier = htons(identifier++);
-+
-+ msg.icmph.icmp6_sequence = htons(flags);
-+ msg.data = data;
-+ msg.csum = 0;
-+ msg.len = datalen + sizeof(struct icmp6hdr);
-+ msg.daddr = daddr;
-+
-+ if (mipv6_icmpv6_xmit_lock())
-+ return;
-+
-+ ip6_build_xmit(sk, mipv6_icmpv6_getfrag, &msg, &fl, msg.len, NULL, -1,
-+ MSG_DONTWAIT);
-+
-+ ICMP6_INC_STATS_BH(Icmp6OutMsgs);
-+ mipv6_icmpv6_xmit_unlock();
-+}
-+
-+/**
-+ * icmp6_rcv - ICMPv6 receive and multiplex
-+ * @skb: buffer containing ICMP message
-+ *
-+ * Generic ICMPv6 receive function to multiplex messages to approriate
-+ * handlers. Only used for ICMP messages with special handling in
-+ * Mobile IPv6.
-+ **/
-+static void icmp6_rcv(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *hdr;
-+
-+ if (skb_is_nonlinear(skb) &&
-+ skb_linearize(skb, GFP_ATOMIC) != 0) {
-+ kfree_skb(skb);
-+ return;
-+ }
-+ __skb_push(skb, skb->data-skb->h.raw);
-+
-+ hdr = (struct icmp6hdr *) skb->h.raw;
-+
-+ switch (hdr->icmp6_type) {
-+ case ICMPV6_DEST_UNREACH:
-+ mipv6_icmpv6_rcv_dest_unreach(skb);
-+ break;
-+
-+ case ICMPV6_PARAMPROB:
-+ mip6_fn.icmpv6_paramprob_rcv(skb);
-+ break;
-+
-+ case MIPV6_DHAAD_REPLY:
-+ mip6_fn.icmpv6_dhaad_rep_rcv(skb);
-+ break;
-+
-+ case MIPV6_PREFIX_ADV:
-+ mip6_fn.icmpv6_pfxadv_rcv(skb);
-+ break;
-+
-+ case MIPV6_DHAAD_REQUEST:
-+ mip6_fn.icmpv6_dhaad_req_rcv(skb);
-+ break;
-+
-+ case MIPV6_PREFIX_SOLICIT:
-+ mip6_fn.icmpv6_pfxsol_rcv(skb);
-+ break;
-+ }
-+}
-+
-+int mipv6_icmpv6_init(void)
-+{
-+ struct sock *sk;
-+ int err;
-+
-+ if ((mipv6_icmpv6_socket = sock_alloc()) == NULL) {
-+ DEBUG(DBG_ERROR, "Cannot allocate mipv6_icmpv6_socket");
-+ return -1;
-+ }
-+ mipv6_icmpv6_socket->type = SOCK_RAW;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMP,
-+ &mipv6_icmpv6_socket)) < 0) {
-+ DEBUG(DBG_ERROR, "Cannot initialize mipv6_icmpv6_socket");
-+ sock_release(mipv6_icmpv6_socket);
-+ mipv6_icmpv6_socket = NULL; /* For safety */
-+ return err;
-+ }
-+ sk = mipv6_icmpv6_socket->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->prot->unhash(sk);
-+
-+ /* Register our ICMP handler */
-+ MIPV6_SETCALL(mipv6_icmp_rcv, icmp6_rcv);
-+ return 0;
-+}
-+
-+void mipv6_icmpv6_exit(void)
-+{
-+ MIPV6_RESETCALL(mipv6_icmp_rcv);
-+ if (mipv6_icmpv6_socket)
-+ sock_release(mipv6_icmpv6_socket);
-+ mipv6_icmpv6_socket = NULL; /* For safety */
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mipv6_icmp.h
-@@ -0,0 +1,43 @@
-+/*
-+ * MIPL Mobile IPv6 ICMP send and receive prototypes
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MIPV6_ICMP
-+#define _MIPV6_ICMP
-+
-+#include <linux/config.h>
-+#include <linux/in6.h>
-+
-+void mipv6_icmpv6_send(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int type, int code, __u16 *id, __u16 flags,
-+ void *data, int datalen);
-+
-+void mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id);
-+
-+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr);
-+/* No handling */
-+int mipv6_icmpv6_no_rcv(struct sk_buff *skb);
-+
-+/* Receive DHAAD Reply message */
-+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb);
-+/* Receive Parameter Problem message */
-+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb);
-+/* Receive prefix advertisements */
-+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb);
-+
-+/* Receive DHAAD Request message */
-+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb);
-+/* Receive prefix solicitations */
-+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb);
-+
-+int mipv6_icmpv6_init(void);
-+void mipv6_icmpv6_exit(void);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mipv6_icmp_ha.c
-@@ -0,0 +1,158 @@
-+/*
-+ * Home Agent specific ICMP routines
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/sched.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "halist.h"
-+#include "debug.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+
-+/* Is this the easiest way of checking on
-+ * which interface an anycast address is ?
-+ */
-+static int find_ac_dev(struct in6_addr *addr)
-+{
-+ int ifindex = 0;
-+ struct net_device *dev;
-+ read_lock(&dev_base_lock);
-+ for (dev=dev_base; dev; dev=dev->next) {
-+ if (ipv6_chk_acast_addr(dev, addr)) {
-+ ifindex = dev->ifindex;
-+ break;
-+ }
-+ }
-+ read_unlock(&dev_base_lock);
-+ return ifindex;
-+}
-+
-+/**
-+ * mipv6_icmpv6_send_dhaad_rep - Reply to DHAAD Request
-+ * @ifindex: index of interface request was received from
-+ * @id: request's identification number
-+ * @daddr: requester's IPv6 address
-+ *
-+ * When Home Agent receives Dynamic Home Agent Address Discovery
-+ * request, it replies with a list of home agents available on the
-+ * home link.
-+ */
-+void mipv6_icmpv6_send_dhaad_rep(int ifindex, __u16 id, struct in6_addr *daddr)
-+{
-+ __u8 *data = NULL;
-+ struct in6_addr home, *ha_addrs = NULL;
-+ int addr_count, max_addrs, size = 0;
-+
-+ if (daddr == NULL)
-+ return;
-+
-+ if (mipv6_ha_get_addr(ifindex, &home) < 0) {
-+ DEBUG(DBG_INFO, "Not Home Agent in this interface");
-+ return;
-+ }
-+
-+ /* We send all available HA addresses, not exceeding a maximum
-+ * number we can fit in a packet with minimum IPv6 MTU (to
-+ * avoid fragmentation).
-+ */
-+ max_addrs = 76;
-+ addr_count = mipv6_ha_get_pref_list(ifindex, &ha_addrs, max_addrs);
-+
-+ if (addr_count < 0) return;
-+
-+ if (addr_count != 0 && ha_addrs == NULL) {
-+ DEBUG(DBG_ERROR, "addr_count = %d but return no addresses",
-+ addr_count);
-+ return;
-+ }
-+ data = (u8 *)ha_addrs;
-+
-+ size = addr_count * sizeof(struct in6_addr);
-+
-+ mipv6_icmpv6_send(daddr, &home, MIPV6_DHAAD_REPLY,
-+ 0, &id, 0, data, size);
-+ if (ha_addrs) {
-+ data = NULL;
-+ kfree(ha_addrs);
-+ }
-+}
-+
-+/**
-+ * mipv6_icmpv6_dhaad_req - Home Agent Address Discovery Request ICMP handler
-+ * @skb: buffer containing ICMP information message
-+ *
-+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent
-+ * Address Discovery Request messages.
-+ **/
-+int mipv6_icmpv6_rcv_dhaad_req(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ __u16 identifier;
-+ int ifindex = 0;
-+
-+ DEBUG_FUNC();
-+
-+ /* Invalid packet checks. */
-+ if (phdr->icmp6_code != 0)
-+ return 0;
-+
-+ identifier = ntohs(phdr->icmp6_identifier);
-+
-+ /*
-+ * Make sure we have the right ifindex (if the
-+ * req came through another interface.
-+ */
-+ ifindex = find_ac_dev(daddr);
-+ if (ifindex == 0) {
-+ DEBUG(DBG_WARNING, "received dhaad request to anycast address %x:%x:%x:%x:%x:%x:%x:%x"
-+ " on which prefix we are not HA",
-+ NIPV6ADDR(daddr));
-+ return 0;
-+ }
-+
-+ /*
-+ * send reply with list
-+ */
-+ mipv6_icmpv6_send_dhaad_rep(ifindex, identifier, saddr);
-+ return 1;
-+}
-+#if 0
-+/**
-+ * mipv6_icmpv6_handle_pfx_sol - handle prefix solicitations
-+ * @skb: sk_buff including the icmp6 message
-+ */
-+int mipv6_icmpv6_rcv_pfx_sol(struct sk_buff *skb)
-+{
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ struct inet6_ifaddr *ifp;
-+
-+ DEBUG_FUNC();
-+
-+ if (!(ifp = ipv6_get_ifaddr(daddr, NULL)))
-+ return -1;
-+
-+ in6_ifa_put(ifp);
-+ mipv6_pfx_cancel_send(saddr, -1);
-+
-+ return 0;
-+}
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mipv6_icmp_mn.c
-@@ -0,0 +1,273 @@
-+/*
-+ * Mobile Node specific ICMP routines
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/sched.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "mn.h"
-+#include "bul.h"
-+#include "mdetect.h"
-+#include "debug.h"
-+#include "mipv6_icmp.h"
-+#include "util.h"
-+//#include "prefix.h"
-+
-+#define INFINITY 0xffffffff
-+
-+/**
-+ * mipv6_icmpv6_paramprob - Parameter Problem ICMP error message handler
-+ * @skb: buffer containing ICMP error message
-+ *
-+ * Special Mobile IPv6 ICMP handling. If Mobile Node receives ICMP
-+ * Parameter Problem message when using a Home Address Option,
-+ * offending node should be logged and error message dropped. If
-+ * error is received because of a Binding Update, offending node
-+ * should be recorded in Binding Update List and no more Binding
-+ * Updates should be sent to this destination. See RFC 3775 section
-+ * 10.15.
-+ **/
-+int mipv6_icmpv6_rcv_paramprob(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = skb ? &skb->nh.ipv6h->saddr : NULL;
-+ struct in6_addr *daddr = skb ? &skb->nh.ipv6h->daddr : NULL;
-+ struct ipv6hdr *hdr = (struct ipv6hdr *) (phdr + 1);
-+ int ulen = (skb->tail - (unsigned char *) (phdr + 1));
-+
-+ int errptr;
-+ __u8 *off_octet;
-+
-+ DEBUG_FUNC();
-+
-+ /* We only handle code 1 & 2 messages. */
-+ if (phdr->icmp6_code != ICMPV6_UNK_NEXTHDR &&
-+ phdr->icmp6_code != ICMPV6_UNK_OPTION)
-+ return 0;
-+
-+ /* Find offending octet in the original packet. */
-+ errptr = ntohl(phdr->icmp6_pointer);
-+
-+ /* There is not enough of the original packet left to figure
-+ * out what went wrong. Bail out. */
-+ if (ulen <= errptr)
-+ return 0;
-+
-+ off_octet = ((__u8 *) hdr + errptr);
-+ DEBUG(DBG_INFO, "Parameter problem: offending octet %d [0x%2x]",
-+ errptr, *off_octet);
-+
-+ /* If CN did not understand Mobility Header, set BUL entry to
-+ * ACK_ERROR so no further BUs are sumbitted to this CN. */
-+ if (phdr->icmp6_code == ICMPV6_UNK_NEXTHDR &&
-+ *off_octet == IPPROTO_MOBILITY) {
-+ struct bul_inval_args args;
-+ args.all_rr_states = 1;
-+ args.cn = saddr;
-+ args.mn = daddr;
-+ write_lock(&bul_lock);
-+ mipv6_bul_iterate(mn_bul_invalidate, &args);
-+ write_unlock(&bul_lock);
-+ }
-+
-+ /* If CN did not understand Home Address Option, we log an
-+ * error and discard the error message. */
-+ if (phdr->icmp6_code == ICMPV6_UNK_OPTION &&
-+ *off_octet == MIPV6_TLV_HOMEADDR) {
-+ DEBUG(DBG_WARNING, "Correspondent node does not "
-+ "implement Home Address Option receipt.");
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_mn_dhaad_send_req - Send DHAAD Request to home network
-+ * @home_addr: address to do DHAAD for
-+ * @plen: prefix length for @home_addr
-+ *
-+ * Send Dynamic Home Agent Address Discovery Request to the Home
-+ * Agents anycast address in the nodes home network.
-+ **/
-+void
-+mipv6_icmpv6_send_dhaad_req(struct in6_addr *home_addr, int plen, __u16 dhaad_id)
-+{
-+ struct in6_addr ha_anycast;
-+ struct in6_addr careofaddr;
-+
-+ if (mipv6_get_care_of_address(home_addr, &careofaddr) < 0) {
-+ DEBUG(DBG_WARNING, "Could not get node's Care-of Address");
-+ return;
-+ }
-+
-+ if (mipv6_ha_anycast(&ha_anycast, home_addr, plen) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "Could not get Home Agent Anycast address for home address %x:%x.%x:%x:%x:%x:%x:%x/%d",
-+ NIPV6ADDR(home_addr), plen);
-+ return;
-+ }
-+
-+ mipv6_icmpv6_send(&ha_anycast, &careofaddr, MIPV6_DHAAD_REQUEST, 0,
-+ &dhaad_id, 0, NULL, 0);
-+
-+}
-+
-+/**
-+ * mipv6_icmpv6_dhaad_rep - Home Agent Address Discovery Reply ICMP handler
-+ * @skb: buffer containing ICMP information message
-+ *
-+ * Special Mobile IPv6 ICMP message. Handles Dynamic Home Agent
-+ * Address Discovery Reply messages.
-+ **/
-+int mipv6_icmpv6_rcv_dhaad_rep(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *phdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *address;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ __u16 identifier;
-+ int ulen = (skb->tail - (unsigned char *) ((__u32 *) phdr + 2));
-+ int i;
-+ struct in6_addr home_addr, coa;
-+ struct in6_addr *first_ha = NULL;
-+ struct mn_info *minfo;
-+ int n_addr = ulen / sizeof(struct in6_addr);
-+
-+ DEBUG_FUNC();
-+
-+ /* Invalid packet checks. */
-+ if (ulen % sizeof(struct in6_addr) != 0)
-+ return 0;
-+
-+ if (phdr->icmp6_code != 0)
-+ return 0;
-+
-+ identifier = ntohs(phdr->icmp6_identifier);
-+ if (ulen > 0) {
-+ address = (struct in6_addr *) ((__u32 *) phdr + 2);
-+ } else {
-+ address = saddr;
-+ n_addr = 1;
-+ }
-+
-+ /* receive list of home agent addresses
-+ * add to home agents list
-+ */
-+ DEBUG(DBG_INFO, "DHAAD: got %d home agents", n_addr);
-+
-+ first_ha = address;
-+
-+ /* lookup H@ with identifier */
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_id(identifier);
-+ if (!minfo) {
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_INFO, "no mninfo with id %d",
-+ identifier);
-+ return 0;
-+ }
-+ spin_lock(&minfo->lock);
-+
-+ /* Logic:
-+ * 1. if old HA on list, prefer it
-+ * 2. otherwise first HA on list prefered
-+ */
-+ for (i = 0; i < n_addr; i++) {
-+ DEBUG(DBG_INFO, "HA[%d] %x:%x:%x:%x:%x:%x:%x:%x",
-+ i, NIPV6ADDR(address));
-+ if (ipv6_addr_cmp(&minfo->ha, address) == 0) {
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+ return 0;
-+ }
-+ address++;
-+ }
-+ ipv6_addr_copy(&minfo->ha, first_ha);
-+ spin_unlock(&minfo->lock);
-+ ipv6_addr_copy(&home_addr, &minfo->home_addr);
-+ read_unlock(&mn_info_lock);
-+
-+ mipv6_get_care_of_address(&home_addr, &coa);
-+ init_home_registration(&home_addr, &coa);
-+
-+ return 1;
-+}
-+#if 0
-+/**
-+ * mipv6_icmpv6_handle_pfx_adv - handle prefix advertisements
-+ * @skb: sk_buff including the icmp6 message
-+ */
-+int mipv6_icmpv6_rcv_pfx_adv(struct sk_buff *skb)
-+{
-+ struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
-+ __u8 *opt = (__u8 *) (hdr + 1);
-+ int optlen = (skb->tail - opt);
-+ unsigned long min_expire = INFINITY;
-+ struct inet6_skb_parm *parm = (struct inet6_skb_parm *) skb->cb;
-+
-+ DEBUG_FUNC();
-+
-+ while (optlen > 0) {
-+ int len = opt[1] << 3;
-+ if (len == 0)
-+ goto set_timer;
-+
-+ if (opt[0] == ND_OPT_PREFIX_INFO) {
-+ int ifindex;
-+ unsigned long expire;
-+ struct prefix_info *pinfo =
-+ (struct prefix_info *) opt;
-+ struct net_device *dev;
-+ struct mn_info *mninfo;
-+
-+ read_lock(&mn_info_lock);
-+ mninfo = mipv6_mninfo_get_by_ha(saddr);
-+ if (mninfo == NULL) {
-+ ifindex = 0;
-+ } else {
-+ spin_lock(&mninfo->lock);
-+ ifindex = mninfo->ifindex;
-+ spin_unlock(&mninfo->lock);
-+ mninfo = NULL;
-+ }
-+ read_unlock(&mn_info_lock);
-+
-+ if (!(dev = dev_get_by_index(ifindex))) {
-+ DEBUG(DBG_WARNING, "Cannot find device by index %d", parm->iif);
-+ goto nextopt;
-+ }
-+
-+ expire = ntohl(pinfo->valid);
-+ expire = expire == 0 ? INFINITY : expire;
-+
-+ min_expire = expire < min_expire ? expire : min_expire;
-+
-+ dev_put(dev);
-+ }
-+
-+nextopt:
-+ optlen -= len;
-+ opt += len;
-+ }
-+
-+set_timer:
-+
-+ mipv6_pfx_add_home(parm->iif, saddr, daddr, min_expire);
-+ return 0;
-+}
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mn.c
-@@ -0,0 +1,1521 @@
-+/*
-+ * Mobile-node functionality
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/sched.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/ipsec.h>
-+#include <linux/notifier.h>
-+#include <linux/list.h>
-+#include <linux/route.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv6.h>
-+#include <linux/tqueue.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/uaccess.h>
-+
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/neighbour.h>
-+#include <net/ndisc.h>
-+#include <net/ip6_route.h>
-+#include <net/mipglue.h>
-+
-+#include "util.h"
-+#include "mdetect.h"
-+#include "bul.h"
-+#include "mobhdr.h"
-+#include "debug.h"
-+#include "mn.h"
-+#include "mipv6_icmp.h"
-+#include "multiaccess_ctl.h"
-+//#include "prefix.h"
-+#include "tunnel_mn.h"
-+#include "stats.h"
-+#include "config.h"
-+
-+#define MIPV6_BUL_SIZE 128
-+
-+static LIST_HEAD(mn_info_list);
-+
-+/* Lock for list of MN infos */
-+rwlock_t mn_info_lock = RW_LOCK_UNLOCKED;
-+
-+static spinlock_t ifrh_lock = SPIN_LOCK_UNLOCKED;
-+
-+struct ifr_holder {
-+ struct list_head list;
-+ struct in6_ifreq ifr;
-+ int old_ifi;
-+ struct handoff *ho;
-+};
-+
-+LIST_HEAD(ifrh_list);
-+
-+static struct tq_struct mv_home_addr_task;
-+
-+/* Determines whether manually configured home addresses are preferred as
-+ * source addresses over dynamically configured ones
-+ */
-+int mipv6_use_preconfigured_hoaddr = 1;
-+
-+/* Determines whether home addresses, which are at home are preferred as
-+ * source addresses over other home addresses
-+ */
-+int mipv6_use_topol_corr_hoaddr = 0;
-+
-+static spinlock_t icmpv6_id_lock = SPIN_LOCK_UNLOCKED;
-+static __u16 icmpv6_id = 0;
-+
-+static inline __u16 mipv6_get_dhaad_id(void)
-+{
-+ __u16 ret;
-+ spin_lock_bh(&icmpv6_id_lock);
-+ ret = ++icmpv6_id;
-+ spin_unlock_bh(&icmpv6_id_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_home - Returns mn_info for a home address
-+ * @haddr: home address of MN
-+ *
-+ * Returns mn_info on success %NULL otherwise. Caller MUST hold
-+ * @mn_info_lock (read or write).
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+
-+ DEBUG_FUNC();
-+
-+ if (!haddr)
-+ return NULL;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (!ipv6_addr_cmp(&minfo->home_addr, haddr)) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_ha - Lookup mn_info with Home Agent address
-+ * @home_agent: Home Agent address
-+ *
-+ * Searches for a mn_info entry with @ha set to @home_agent. You MUST
-+ * hold @mn_info_lock when calling this function. Returns pointer to
-+ * mn_info entry or %NULL on failure.
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+
-+ if (!home_agent)
-+ return NULL;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (!ipv6_addr_cmp(&minfo->ha, home_agent)) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_get_by_id - Lookup mn_info with id
-+ * @id: DHAAD identifier
-+ *
-+ * Searches for a mn_info entry with @dhaad_id set to @id. You MUST
-+ * hold @mn_info_lock when calling this function. Returns pointer to
-+ * mn_info entry or %NULL on failure.
-+ **/
-+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo = 0;
-+
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (minfo->dhaad_id == id) {
-+ spin_unlock(&minfo->lock);
-+ return minfo;
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mipv6_mninfo_add - Adds a new home info for MN
-+ * @ifindex: Interface for home address
-+ * @home_addr: Home address of MN, must be set
-+ * @plen: prefix length of the home address, must be set
-+ * @isathome : home address at home
-+ * @lifetime: lifetime of the home address, 0 is infinite
-+ * @ha: home agent for the home address
-+ * @ha_plen: prefix length of home agent's address, can be zero
-+ * @ha_lifetime: Lifetime of the home address, 0 is infinite
-+ *
-+ * The function adds a new home info entry for MN, allowing it to
-+ * register the home address with the home agent. Starts home
-+ * registration process. If @ha is %ADDRANY, DHAAD is performed to
-+ * find a home agent. Returns 0 on success, a negative value
-+ * otherwise. Caller MUST NOT hold @mn_info_lock or
-+ * @addrconf_hash_lock.
-+ **/
-+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen,
-+ int isathome, unsigned long lifetime, struct in6_addr *ha,
-+ int ha_plen, unsigned long ha_lifetime, int man_conf)
-+{
-+ struct mn_info *minfo;
-+ struct in6_addr coa;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL){
-+ DEBUG(1, "MN info already exists");
-+ write_unlock_bh(&mn_info_lock);
-+ return;
-+ }
-+ minfo = kmalloc(sizeof(struct mn_info), GFP_ATOMIC);
-+ if (!minfo) {
-+ write_unlock_bh(&mn_info_lock);
-+ return;
-+ }
-+ memset(minfo, 0, sizeof(struct mn_info));
-+ spin_lock_init(&minfo->lock);
-+
-+
-+ ipv6_addr_copy(&minfo->home_addr, home_addr);
-+
-+ if (ha)
-+ ipv6_addr_copy(&minfo->ha, ha);
-+ if (ha_plen < 128 && ha_plen > 0)
-+ minfo->home_plen = ha_plen;
-+ else minfo->home_plen = 64;
-+
-+ minfo->ifindex_user = ifindex; /* Ifindex for tunnel interface */
-+ minfo->ifindex = ifindex; /* Interface on which home address is currently conf'd */
-+ /* TODO: we should get home address lifetime from somewhere */
-+ /* minfo->home_addr_expires = jiffies + lifetime * HZ; */
-+
-+ /* manual configuration flag cannot be unset by dynamic updates
-+ * from prefix advertisements
-+ */
-+ if (!minfo->man_conf) minfo->man_conf = man_conf;
-+ minfo->is_at_home = isathome;
-+
-+ list_add(&minfo->list, &mn_info_list);
-+ write_unlock_bh(&mn_info_lock);
-+
-+ if (mipv6_get_care_of_address(home_addr, &coa) == 0)
-+ init_home_registration(home_addr, &coa);
-+}
-+
-+/**
-+ * mipv6_mninfo_del - Delete home info for MN
-+ * @home_addr : Home address or prefix
-+ * @del_dyn_only : Delete only dynamically created home entries
-+ *
-+ * Deletes every mn_info entry that matches the first plen bits of
-+ * @home_addr. Returns number of deleted entries on success and a
-+ * negative value otherwise. Caller MUST NOT hold @mn_info_lock.
-+ **/
-+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only)
-+{
-+ struct list_head *lh, *next;
-+ struct mn_info *minfo;
-+ int ret = -1;
-+ if (!home_addr)
-+ return -1;
-+
-+ write_lock(&mn_info_lock);
-+
-+ list_for_each_safe(lh, next, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if (ipv6_addr_cmp(&minfo->home_addr, home_addr) == 0
-+ && ((!minfo->man_conf && del_dyn_only) || !del_dyn_only)){
-+ list_del(&minfo->list);
-+ kfree(minfo);
-+ ret++;
-+ }
-+ }
-+ write_unlock(&mn_info_lock);
-+ return ret;
-+}
-+
-+void mipv6_mn_set_home(int ifindex, struct in6_addr *homeaddr, int plen,
-+ struct in6_addr *homeagent, int ha_plen)
-+{
-+ mipv6_mninfo_add(ifindex, homeaddr, plen, 0, 0,
-+ homeagent, ha_plen, 0, 1);
-+}
-+
-+static int skip_dad(struct in6_addr *addr)
-+{
-+ struct mn_info *minfo;
-+ int ret = 0;
-+
-+ if (addr == NULL) {
-+ DEBUG(DBG_CRITICAL, "Null argument");
-+ return 0;
-+ }
-+ read_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(addr)) != NULL) {
-+ if ((minfo->is_at_home != MN_NOT_AT_HOME) && (minfo->has_home_reg))
-+ ret = 1;
-+ DEBUG(DBG_INFO, "minfo->is_at_home = %d, minfo->has_home_reg = %d",
-+ minfo->is_at_home, minfo->has_home_reg);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ return ret;
-+}
-+/**
-+ * mipv6_mn_is_home_addr - Determines if addr is node's home address
-+ * @addr: IPv6 address
-+ *
-+ * Returns 1 if addr is node's home address. Otherwise returns zero.
-+ **/
-+int mipv6_mn_is_home_addr(struct in6_addr *addr)
-+{
-+ int ret = 0;
-+
-+ if (addr == NULL) {
-+ DEBUG(DBG_CRITICAL, "Null argument");
-+ return -1;
-+ }
-+ read_lock_bh(&mn_info_lock);
-+ if (mipv6_mninfo_get_by_home(addr))
-+ ret = 1;
-+ read_unlock_bh(&mn_info_lock);
-+
-+ return (ret);
-+}
-+
-+/**
-+ * mipv6_mn_is_at_home - determine if node is home for a home address
-+ * @home_addr : home address of MN
-+ *
-+ * Returns 1 if home address in question is in the home network, 0
-+ * otherwise. Caller MUST NOT not hold @mn_info_lock.
-+ **/
-+int mipv6_mn_is_at_home(struct in6_addr *home_addr)
-+{
-+ struct mn_info *minfo;
-+ int ret = 0;
-+ read_lock_bh(&mn_info_lock);
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) {
-+ spin_lock(&minfo->lock);
-+ ret = (minfo->is_at_home == MN_AT_HOME);
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return ret;
-+}
-+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg)
-+{
-+ struct mn_info *minfo;
-+ read_lock_bh(&mn_info_lock);
-+
-+ if ((minfo = mipv6_mninfo_get_by_home(home_addr)) != NULL) {
-+ spin_lock(&minfo->lock);
-+ minfo->has_home_reg = has_home_reg;
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+}
-+
-+static int mn_inet6addr_event(
-+ struct notifier_block *nb, unsigned long event, void *ptr)
-+{
-+ struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)ptr;
-+
-+ switch (event) {
-+ case NETDEV_UP:
-+ /* Is address a valid coa ?*/
-+ if (!(ifp->flags & IFA_F_TENTATIVE))
-+ mipv6_mdet_finalize_ho(&ifp->addr,
-+ ifp->idev->dev->ifindex);
-+ else if(skip_dad(&ifp->addr))
-+ ifp->flags &= ~IFA_F_TENTATIVE;
-+ break;
-+ case NETDEV_DOWN:
-+#if 0
-+ /* This is useless with manually configured home
-+ addresses, which will not expire
-+ */
-+ mipv6_mninfo_del(&ifp->addr, 0);
-+#endif
-+ break;
-+
-+ }
-+
-+ return NOTIFY_DONE;
-+}
-+
-+struct notifier_block mipv6_mn_inet6addr_notifier = {
-+ mn_inet6addr_event,
-+ NULL,
-+ 0 /* check if using zero is ok */
-+};
-+
-+static void mipv6_get_saddr_hook(struct in6_addr *homeaddr)
-+{
-+ int found = 0, reiter = 0;
-+ struct list_head *lh;
-+ struct mn_info *minfo = NULL;
-+ struct in6_addr coa;
-+
-+ read_lock_bh(&mn_info_lock);
-+restart:
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if ((ipv6_addr_scope(homeaddr) != ipv6_addr_scope(&minfo->home_addr))
-+ || ipv6_chk_addr(&minfo->home_addr, NULL) == 0)
-+ continue;
-+
-+ spin_lock(&minfo->lock);
-+ if (minfo->is_at_home == MN_AT_HOME || minfo->has_home_reg) {
-+ if ((mipv6_use_topol_corr_hoaddr &&
-+ minfo->is_at_home == MN_AT_HOME) ||
-+ (mipv6_use_preconfigured_hoaddr &&
-+ minfo->man_conf) ||
-+ (!(mipv6_use_preconfigured_hoaddr ||
-+ mipv6_use_topol_corr_hoaddr) || reiter)) {
-+ spin_unlock(&minfo->lock);
-+ ipv6_addr_copy(homeaddr, &minfo->home_addr);
-+ found = 1;
-+ break;
-+ }
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+ if (!found && !reiter) {
-+ reiter = 1;
-+ goto restart;
-+ }
-+
-+ if (!found && minfo &&
-+ !mipv6_get_care_of_address(&minfo->home_addr, &coa)) {
-+ ipv6_addr_copy(homeaddr, &coa);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ DEBUG(DBG_DATADUMP, "Source address selection: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(homeaddr));
-+ return;
-+}
-+
-+static void mv_home_addr(void *arg)
-+{
-+ mm_segment_t oldfs;
-+ int err = 0, new_if = 0;
-+ struct list_head *lh, *next;
-+ struct ifr_holder *ifrh;
-+ LIST_HEAD(list);
-+
-+ DEBUG(DBG_INFO, "mipv6 move home address task");
-+
-+ spin_lock_bh(&ifrh_lock);
-+ list_splice_init(&ifrh_list, &list);
-+ spin_unlock_bh(&ifrh_lock);
-+
-+ oldfs = get_fs(); set_fs(KERNEL_DS);
-+ list_for_each_safe(lh, next, &list) {
-+ ifrh = list_entry(lh, struct ifr_holder, list);
-+ if (ifrh->old_ifi) {
-+ new_if = ifrh->ifr.ifr6_ifindex;
-+ ifrh->ifr.ifr6_ifindex = ifrh->old_ifi;
-+ err = addrconf_del_ifaddr(&ifrh->ifr);
-+ ifrh->ifr.ifr6_ifindex = new_if;
-+ if (err < 0)
-+ DEBUG(DBG_WARNING, "removal of home address %x:%x:%x:%x:%x:%x:%x:%x from"
-+ " old interface %d failed with status %d",
-+ NIPV6ADDR(&ifrh->ifr.ifr6_addr), ifrh->old_ifi, err);
-+ }
-+ if(!err) {
-+ err = addrconf_add_ifaddr(&ifrh->ifr);
-+ }
-+ if (ifrh->ho) {
-+ DEBUG(DBG_INFO, "Calling mobile_node moved after moving home address to new if");
-+ mipv6_mobile_node_moved(ifrh->ho);
-+ }
-+ list_del(&ifrh->list);
-+ kfree(ifrh);
-+ }
-+ set_fs(oldfs);
-+
-+ if (err < 0)
-+ DEBUG(DBG_WARNING, "adding of home address to a new interface %d failed %d", new_if, err);
-+ else {
-+ DEBUG(DBG_WARNING, "adding of home address to a new interface OK");
-+ }
-+}
-+
-+struct dhaad_halist {
-+ struct list_head list;
-+ struct in6_addr addr;
-+ int retry;
-+};
-+
-+/* clear all has from candidate list. do this when a new dhaad reply
-+ * is received. */
-+int mipv6_mn_flush_ha_candidate(struct list_head *ha)
-+{
-+ struct list_head *p, *tmp;
-+ struct dhaad_halist *e;
-+
-+ list_for_each_safe(p, tmp, ha) {
-+ e = list_entry(p, struct dhaad_halist, list);
-+ list_del(p);
-+ kfree(e);
-+ e = NULL;
-+ }
-+ return 0;
-+}
-+
-+/* add new ha to candidates. only done when dhaad reply is received. */
-+int mipv6_mn_add_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct dhaad_halist *e;
-+
-+ e = kmalloc(sizeof(*e), GFP_ATOMIC);
-+ memset(e, 0, sizeof(*e));
-+ ipv6_addr_copy(&e->addr, addr);
-+
-+ list_add_tail(&e->list, ha);
-+ return 0;
-+}
-+
-+#define MAX_RETRIES_PER_HA 3
-+
-+/* get next ha candidate. this is done when dhaad reply has been
-+ * received and we want to register with the best available ha. */
-+int mipv6_mn_get_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct list_head *p;
-+
-+ list_for_each(p, ha) {
-+ struct dhaad_halist *e;
-+ e = list_entry(p, typeof(*e), list);
-+ if (e->retry >= 0 && e->retry < MAX_RETRIES_PER_HA) {
-+ ipv6_addr_copy(addr, &e->addr);
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/* change candidate status. if registration with ha fails, we
-+ * increase retry for ha candidate. if retry is >= 3 we set it to -1
-+ * (failed), do get_ha_candidate() again */
-+int mipv6_mn_try_ha_candidate(struct list_head *ha, struct in6_addr *addr)
-+{
-+ struct list_head *p;
-+
-+ list_for_each(p, ha) {
-+ struct dhaad_halist *e;
-+ e = list_entry(p, typeof(*e), list);
-+ if (ipv6_addr_cmp(addr, &e->addr) == 0) {
-+ if (e->retry >= MAX_RETRIES_PER_HA) e->retry = -1;
-+ else if (e->retry >= 0) e->retry++;
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_mn_get_bulifetime - Get lifetime for a binding update
-+ * @home_addr: home address for BU
-+ * @coa: care-of address for BU
-+ * @flags: flags used for BU
-+ *
-+ * Returns maximum lifetime for BUs determined by the lifetime of
-+ * care-of address and the lifetime of home address.
-+ **/
-+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr, struct in6_addr *coa,
-+ __u8 flags)
-+{
-+ struct inet6_ifaddr *ifp_hoa, *ifp_coa;
-+ __u32 lifetime = (flags & MIPV6_BU_F_HOME ?
-+ HA_BU_DEF_LIFETIME : CN_BU_DEF_LIFETIME);
-+
-+ ifp_hoa = ipv6_get_ifaddr(home_addr, NULL);
-+ if(!ifp_hoa) {
-+ DEBUG(DBG_INFO, "home address missing");
-+ return 0;
-+ }
-+ if (!(ifp_hoa->flags & IFA_F_PERMANENT)){
-+ if (ifp_hoa->valid_lft)
-+ lifetime = min_t(__u32, lifetime, ifp_hoa->valid_lft);
-+ else
-+ DEBUG(DBG_ERROR, "Zero lifetime for home address");
-+ }
-+ in6_ifa_put(ifp_hoa);
-+
-+ ifp_coa = ipv6_get_ifaddr(coa, NULL);
-+ if (!ifp_coa) {
-+ DEBUG(DBG_INFO, "care-of address missing");
-+ return 0;
-+ }
-+ if (!(ifp_coa->flags & IFA_F_PERMANENT)) {
-+ if(ifp_coa->valid_lft)
-+ lifetime = min_t(__u32, lifetime, ifp_coa->valid_lft);
-+ else
-+ DEBUG(DBG_ERROR,
-+ "Zero lifetime for care-of address");
-+ }
-+ in6_ifa_put(ifp_coa);
-+
-+ DEBUG(DBG_INFO, "Lifetime for binding is %ld", lifetime);
-+ return lifetime;
-+}
-+
-+static int
-+mipv6_mn_tnl_rcv_send_bu_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ struct ipv6hdr *inner;
-+ struct ipv6hdr *outer = skb->nh.ipv6h;
-+ struct mn_info *minfo = NULL;
-+ __u32 lifetime;
-+ __u8 user_flags = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if (!is_mip6_tnl(t))
-+ return IP6_TNL_ACCEPT;
-+
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled"
-+ " not doing route optimization");
-+ return IP6_TNL_ACCEPT;
-+ }
-+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*inner)))
-+ return IP6_TNL_DROP;
-+
-+ inner = (struct ipv6hdr *)skb->h.raw;
-+
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(&inner->daddr);
-+
-+ if (!minfo) {
-+ DEBUG(DBG_WARNING, "MN info missing");
-+ read_unlock(&mn_info_lock);
-+ return IP6_TNL_ACCEPT;
-+ }
-+ DEBUG(DBG_DATADUMP, "MIPV6 MN: Received a tunneled IPv6 packet"
-+ " to %x:%x:%x:%x:%x:%x:%x:%x,"
-+ " from %x:%x:%x:%x:%x:%x:%x:%x with\n tunnel header"
-+ "daddr: %x:%x:%x:%x:%x:%x:%x:%x,"
-+ "saddr: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&inner->daddr), NIPV6ADDR(&inner->saddr),
-+ NIPV6ADDR(&outer->daddr), NIPV6ADDR(&outer->saddr));
-+
-+ spin_lock(&minfo->lock);
-+
-+ /* We don't send bus in response to all tunneled packets */
-+
-+ if (!ipv6_addr_cmp(&minfo->ha, &inner->saddr)) {
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_ERROR, "HA BUG: Received a tunneled packet "
-+ "originally sent by home agent, not sending BU");
-+ return IP6_TNL_ACCEPT;
-+ }
-+ spin_unlock(&minfo->lock);
-+ read_unlock(&mn_info_lock);
-+
-+ DEBUG(DBG_DATADUMP, "Sending BU to correspondent node");
-+
-+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0;
-+
-+ if (inner->nexthdr != IPPROTO_DSTOPTS &&
-+ inner->nexthdr != IPPROTO_MOBILITY) {
-+ struct in6_addr coa;
-+ /* Don't start RR when receiving ICMP error messages */
-+ if (inner->nexthdr == IPPROTO_ICMPV6) {
-+ int ptr = (u8*)(inner+1) - skb->data;
-+ u8 type;
-+
-+ if (skb_copy_bits(skb,
-+ ptr+offsetof(struct icmp6hdr,
-+ icmp6_type),
-+ &type, 1)
-+ || !(type & ICMPV6_INFOMSG_MASK)) {
-+ return IP6_TNL_ACCEPT;
-+ }
-+ }
-+ lifetime = mipv6_mn_get_bulifetime(&inner->daddr,
-+ &outer->daddr, 0);
-+ if (lifetime &&
-+ !mipv6_get_care_of_address(&inner->daddr, &coa)) {
-+ write_lock(&bul_lock);
-+ mipv6_send_bu(&inner->daddr, &inner->saddr, &coa,
-+ INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1,
-+ user_flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ }
-+ }
-+ DEBUG(DBG_DATADUMP, "setting rcv_tunnel flag in skb");
-+ skb->security |= MIPV6_RCV_TUNNEL;
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_send_bu_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_FIRST,
-+ mipv6_mn_tnl_rcv_send_bu_hook
-+};
-+
-+static int
-+mipv6_mn_tnl_xmit_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_encapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_xmit_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_ENCAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_mn_tnl_xmit_stats_hook
-+};
-+
-+static int
-+mipv6_mn_tnl_rcv_stats_hook(struct ip6_tnl *t, struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ if (is_mip6_tnl(t))
-+ MIPV6_INC_STATS(n_decapsulations);
-+ return IP6_TNL_ACCEPT;
-+}
-+
-+static struct ip6_tnl_hook_ops mipv6_mn_tnl_rcv_stats_ops = {
-+ {NULL, NULL},
-+ IP6_TNL_PRE_DECAP,
-+ IP6_TNL_PRI_LAST,
-+ mipv6_mn_tnl_rcv_stats_hook
-+};
-+
-+static void mn_check_tunneled_packet(struct sk_buff *skb)
-+{
-+ DEBUG_FUNC();
-+ /* If tunnel flag was set */
-+ if (skb->security & MIPV6_RCV_TUNNEL) {
-+ struct in6_addr coa;
-+ __u32 lifetime;
-+ __u8 user_flags = 0;
-+ int ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
-+ int len = skb->len - ptr;
-+ __u8 nexthdr = skb->nh.ipv6h->nexthdr;
-+
-+ if (len < 0)
-+ return;
-+
-+ ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
-+ if (ptr < 0)
-+ return;
-+
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled");
-+ return;
-+ }
-+ if (nexthdr == IPPROTO_MOBILITY)
-+ return;
-+
-+ /* Don't start RR when receiving ICMP error messages */
-+ if (nexthdr == IPPROTO_ICMPV6) {
-+ u8 type;
-+
-+ if (skb_copy_bits(skb,
-+ ptr+offsetof(struct icmp6hdr,
-+ icmp6_type),
-+ &type, 1)
-+ || !(type & ICMPV6_INFOMSG_MASK)) {
-+ return;
-+ }
-+ }
-+ user_flags |= mip6node_cnf.bu_cn_ack ? MIPV6_BU_F_ACK : 0;
-+ mipv6_get_care_of_address(&skb->nh.ipv6h->daddr, &coa);
-+ lifetime = mipv6_mn_get_bulifetime(&skb->nh.ipv6h->daddr,
-+ &coa, 0);
-+
-+ DEBUG(DBG_WARNING, "packet to address %x:%x:%x:%x:%x:%x:%x:%x"
-+ "was tunneled. Sending BU to CN"
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&skb->nh.ipv6h->daddr),
-+ NIPV6ADDR(&skb->nh.ipv6h->saddr));
-+ /* This should work also with home address option */
-+
-+ write_lock(&bul_lock);
-+ mipv6_send_bu(&skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr,
-+ &coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, user_flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ }
-+}
-+
-+static int sched_mv_home_addr_task(struct in6_addr *haddr, int plen_new,
-+ int newif, int oldif, struct handoff *ho)
-+{
-+ int alloc_size;
-+ struct ifr_holder *ifrh;
-+
-+ alloc_size = sizeof(*ifrh) + (ho ? sizeof(*ho): 0);
-+ if ((ifrh = kmalloc(alloc_size, GFP_ATOMIC)) == NULL) {
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ return -1;
-+ }
-+ if (ho) {
-+ ifrh->ho = (struct handoff *)((struct ifr_holder *)(ifrh + 1));
-+ memcpy(ifrh->ho, ho, sizeof(*ho));
-+ } else
-+ ifrh->ho = NULL;
-+
-+ /* must queue task to avoid deadlock with rtnl */
-+ ifrh->ifr.ifr6_ifindex = newif;
-+ ifrh->ifr.ifr6_prefixlen = plen_new;
-+ ipv6_addr_copy(&ifrh->ifr.ifr6_addr, haddr);
-+ ifrh->old_ifi = oldif;
-+
-+ spin_lock_bh(&ifrh_lock);
-+ list_add_tail(&ifrh->list, &ifrh_list);
-+ spin_unlock_bh(&ifrh_lock);
-+
-+ schedule_task(&mv_home_addr_task);
-+
-+ return 0;
-+}
-+
-+static void send_ret_home_ns(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ int ifindex)
-+{
-+ struct in6_addr nil;
-+ struct in6_addr mcaddr;
-+ struct net_device *dev = dev_get_by_index(ifindex);
-+ if (!dev)
-+ return;
-+ memset(&nil, 0, sizeof(nil));
-+ addrconf_addr_solict_mult(home_addr, &mcaddr);
-+ ndisc_send_ns(dev, NULL, home_addr, &mcaddr, &nil);
-+ dev_put(dev);
-+}
-+
-+static inline int ha_is_reachable(int ifindex, struct in6_addr *ha)
-+{
-+ struct net_device *dev;
-+ int reachable = 0;
-+
-+ dev = dev_get_by_index(ifindex);
-+ if (dev) {
-+ struct neighbour *neigh;
-+ if ((neigh = ndisc_get_neigh(dev, ha)) != NULL) {
-+ read_lock_bh(&neigh->lock);
-+ if (neigh->nud_state&NUD_VALID)
-+ reachable = 1;
-+ read_unlock_bh(&neigh->lock);
-+ neigh_release(neigh);
-+ }
-+ dev_put(dev);
-+ }
-+ return reachable;
-+}
-+
-+static int mn_ha_handoff(struct handoff *ho)
-+{
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+ struct in6_addr *coa= ho->coa;
-+ int wait_mv_home = 0;
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(lh, &mn_info_list) {
-+ __u8 has_home_reg;
-+ int ifindex;
-+ struct in6_addr ha;
-+ __u8 athome;
-+ __u32 lifetime;
-+ struct mipv6_bul_entry *entry = NULL;
-+
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ has_home_reg = minfo->has_home_reg;
-+ ifindex = minfo->ifindex;
-+ ipv6_addr_copy(&ha, &minfo->ha);
-+
-+ if (mipv6_prefix_compare(&ho->rtr_addr, &minfo->home_addr,
-+ ho->plen)) {
-+ if (minfo->has_home_reg)
-+ athome = minfo->is_at_home = MN_RETURNING_HOME;
-+ else
-+ athome = minfo->is_at_home = MN_AT_HOME;
-+ coa = &minfo->home_addr;
-+
-+ spin_unlock(&minfo->lock);
-+#if 0
-+ /* Cancel prefix solicitation, rtr is our HA */
-+ mipv6_pfx_cancel_send(&ho->rtr_addr, ifindex);
-+#endif
-+ minfo->ifindex = ho->ifindex;
-+
-+ if (minfo->has_home_reg &&
-+ !ha_is_reachable(ho->ifindex, &minfo->ha)) {
-+ send_ret_home_ns(&minfo->ha,
-+ &minfo->home_addr,
-+ ho->ifindex);
-+ mipv6_mdet_set_curr_rtr_reachable(0);
-+ wait_mv_home++;
-+ }
-+ if (ifindex != ho->ifindex){
-+ wait_mv_home++;
-+ DEBUG(DBG_INFO,
-+ "Moving home address back to "
-+ "the home interface");
-+ sched_mv_home_addr_task(&minfo->home_addr,
-+ 128,
-+ ho->ifindex,
-+ ifindex, ho);
-+ }
-+ if (!has_home_reg || wait_mv_home)
-+ continue;
-+
-+ lifetime = 0;
-+
-+ } else {
-+ athome = minfo->is_at_home = MN_NOT_AT_HOME;
-+ if (minfo->ifindex_user != minfo->ifindex) {
-+ DEBUG(DBG_INFO, "Scheduling home address move to virtual interface");
-+ sched_mv_home_addr_task(&minfo->home_addr,
-+ 128,
-+ minfo->ifindex_user,
-+ minfo->ifindex, ho); /* Is minfo->ifindex correct */
-+
-+ wait_mv_home++;
-+ }
-+ minfo->ifindex = minfo->ifindex_user;
-+ spin_unlock(&minfo->lock);
-+ if (wait_mv_home)
-+ continue;
-+ if (!has_home_reg &&
-+ init_home_registration(&minfo->home_addr,
-+ ho->coa)) {
-+ continue;
-+ }
-+ lifetime = mipv6_mn_get_bulifetime(&minfo->home_addr,
-+ ho->coa,
-+ MIPV6_BU_F_HOME);
-+
-+ }
-+ write_lock(&bul_lock);
-+ if (!(entry = mipv6_bul_get(&ha, &minfo->home_addr)) ||
-+ !(entry->flags & MIPV6_BU_F_HOME)) {
-+ DEBUG(DBG_ERROR,
-+ "Unable to find home registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x!\n",
-+ NIPV6ADDR(&minfo->home_addr));
-+ write_unlock(&bul_lock);
-+ continue;
-+ }
-+ DEBUG(DBG_INFO, "Sending home de ? %d registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n"
-+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "with lifetime %ld",
-+ (athome != MN_NOT_AT_HOME),
-+ NIPV6ADDR(&entry->home_addr),
-+ NIPV6ADDR(&entry->cn_addr), lifetime);
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return wait_mv_home;
-+}
-+/**
-+ * mn_cn_handoff - called for every bul entry to send BU to CN
-+ * @rawentry: bul entry
-+ * @args: handoff event
-+ * @sortkey:
-+ *
-+ * Since MN can have many home addresses and home networks, every BUL
-+ * entry needs to be checked
-+ **/
-+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bul_entry *entry = (struct mipv6_bul_entry *)rawentry;
-+ struct in6_addr *coa = (struct in6_addr *)args;
-+
-+ DEBUG_FUNC();
-+
-+ /* Home registrations already handled by mn_ha_handoff */
-+ if (entry->flags & MIPV6_BU_F_HOME)
-+ return ITERATOR_CONT;
-+
-+ /* BUL is locked by mipv6_mobile_node_moved which calls us
-+ through mipv6_bul_iterate */
-+
-+ if (mipv6_prefix_compare(coa,
-+ &entry->home_addr,
-+ 64)) {
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ &entry->home_addr, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags, 0,
-+ NULL);
-+ } else {
-+ u32 lifetime = mipv6_mn_get_bulifetime(&entry->home_addr,
-+ coa,
-+ entry->flags);
-+ mipv6_send_bu(&entry->home_addr, &entry->cn_addr,
-+ coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, entry->flags,
-+ lifetime, NULL);
-+ }
-+ return ITERATOR_CONT;
-+}
-+
-+
-+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bul_entry *bul = (struct mipv6_bul_entry *)rawentry;
-+ struct bul_inval_args *arg = (struct bul_inval_args *)args;
-+
-+ DEBUG_FUNC();
-+
-+ if (!ipv6_addr_cmp(arg->cn, &bul->cn_addr) &&
-+ (!ipv6_addr_cmp(arg->mn, &bul->home_addr) ||
-+ !ipv6_addr_cmp(arg->mn, &bul->coa))) {
-+ if (arg->all_rr_states || !bul->rr ||
-+ (bul->rr->rr_state != RR_INIT &&
-+ bul->rr->rr_state != RR_DONE)) {
-+ bul->state = ACK_ERROR;
-+ bul->callback = bul_entry_expired;
-+ bul->callback_time = jiffies +
-+ DUMB_CN_BU_LIFETIME * HZ;
-+ bul->expire = bul->callback_time;
-+ DEBUG(DBG_INFO, "BUL entry set to ACK_ERROR");
-+ mipv6_bul_reschedule(bul);
-+ }
-+ }
-+ return ITERATOR_CONT;
-+}
-+/**
-+ * init_home_registration - start Home Registration process
-+ * @home_addr: home address
-+ * @coa: care-of address
-+ *
-+ * Checks whether we have a Home Agent address for this home address.
-+ * If not starts Dynamic Home Agent Address Discovery. Otherwise
-+ * tries to register with home agent if not already registered.
-+ * Returns 1, if home registration process is started and 0 otherwise
-+ **/
-+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa)
-+{
-+ struct mn_info *hinfo;
-+ struct in6_addr ha;
-+ __u8 man_conf;
-+ int ifindex;
-+ __u32 lifetime;
-+ __u8 user_flags = 0, flags;
-+
-+ DEBUG_FUNC();
-+
-+ read_lock_bh(&mn_info_lock);
-+ if ((hinfo = mipv6_mninfo_get_by_home(home_addr)) == NULL) {
-+ DEBUG(DBG_ERROR, "No mn_info found for address: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(home_addr));
-+ read_unlock_bh(&mn_info_lock);
-+ return -ENOENT;
-+ }
-+ spin_lock(&hinfo->lock);
-+ if (mipv6_prefix_compare(&hinfo->home_addr, coa, hinfo->home_plen)) {
-+ spin_unlock(&hinfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+ DEBUG(DBG_INFO, "Adding home address, MN at home");
-+ return 1;
-+ }
-+ if (ipv6_addr_any(&hinfo->ha)) {
-+ int dhaad_id = mipv6_get_dhaad_id();
-+ hinfo->dhaad_id = dhaad_id;
-+ spin_unlock(&hinfo->lock);
-+ mipv6_icmpv6_send_dhaad_req(home_addr, hinfo->home_plen, dhaad_id);
-+ read_unlock_bh(&mn_info_lock);
-+ DEBUG(DBG_INFO,
-+ "Home Agent address not set, initiating DHAAD");
-+ return 1;
-+ }
-+ ipv6_addr_copy(&ha, &hinfo->ha);
-+ man_conf = hinfo->man_conf;
-+ ifindex = hinfo->ifindex;
-+ spin_unlock(&hinfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+#if 0
-+ if (man_conf)
-+ mipv6_pfx_add_ha(&ha, coa, ifindex);
-+#endif
-+ if (mipv6_bul_exists(&ha, home_addr)) {
-+ DEBUG(DBG_INFO, "BU already sent to HA");
-+ return 0;
-+ }
-+ /* user flags received through sysctl */
-+ user_flags |= mip6node_cnf.bu_lladdr ? MIPV6_BU_F_LLADDR : 0;
-+ user_flags |= mip6node_cnf.bu_keymgm ? MIPV6_BU_F_KEYMGM : 0;
-+
-+ flags = MIPV6_BU_F_HOME | MIPV6_BU_F_ACK | user_flags;
-+
-+ lifetime = mipv6_mn_get_bulifetime(home_addr, coa, flags);
-+
-+ DEBUG(DBG_INFO, "Sending initial home registration for "
-+ "home address: %x:%x:%x:%x:%x:%x:%x:%x\n"
-+ "to home agent %x:%x:%x:%x:%x:%x:%x:%x, "
-+ "with lifetime %ld, prefixlength %d",
-+ NIPV6ADDR(home_addr), NIPV6ADDR(&ha), lifetime, 0);
-+
-+ write_lock_bh(&bul_lock);
-+ mipv6_send_bu(home_addr, &ha, coa, INITIAL_BINDACK_DAD_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, flags, lifetime, NULL);
-+ write_unlock_bh(&bul_lock);
-+
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_mobile_node_moved - Send BUs to all HAs and CNs
-+ * @ho: handoff structure contains the new and previous routers
-+ *
-+ * Event for handoff. Sends BUs everyone on Binding Update List.
-+ **/
-+int mipv6_mobile_node_moved(struct handoff *ho)
-+{
-+#if 0
-+ int bu_to_prev_router = 1;
-+#endif
-+ int dummy;
-+
-+ DEBUG_FUNC();
-+
-+ ma_ctl_upd_iface(ho->ifindex,
-+ MA_IFACE_CURRENT | MA_IFACE_HAS_ROUTER, &dummy);
-+
-+ /* First send BU to HA, then to all other nodes that are on BU list */
-+ if (mn_ha_handoff(ho) != 0)
-+ return 0; /* Wait for move home address task */
-+#if 0
-+ /* Add current care-of address to mn_info list, if current router acts
-+ as a HA.*/
-+
-+ if (ho->home_address && bu_to_prev_router)
-+ mipv6_mninfo_add(ho->coa, ho->plen,
-+ MN_AT_HOME, 0, &ho->rtr_addr,
-+ ho->plen, ROUTER_BU_DEF_LIFETIME,
-+ 0);
-+
-+#endif
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_mn_send_home_na - send NA when returning home
-+ * @haddr: home address to advertise
-+ *
-+ * After returning home, MN must advertise all its valid addresses in
-+ * home link to all nodes.
-+ **/
-+void mipv6_mn_send_home_na(struct in6_addr *haddr)
-+{
-+ struct net_device *dev = NULL;
-+ struct in6_addr mc_allnodes;
-+ struct mn_info *hinfo = NULL;
-+
-+ read_lock(&mn_info_lock);
-+ hinfo = mipv6_mninfo_get_by_home(haddr);
-+ if (!hinfo) {
-+ read_unlock(&mn_info_lock);
-+ return;
-+ }
-+ spin_lock(&hinfo->lock);
-+ hinfo->is_at_home = MN_AT_HOME;
-+ dev = dev_get_by_index(hinfo->ifindex);
-+ spin_unlock(&hinfo->lock);
-+ read_unlock(&mn_info_lock);
-+ if (dev == NULL) {
-+ DEBUG(DBG_ERROR, "Send home_na: device not found.");
-+ return;
-+ }
-+
-+ ipv6_addr_all_nodes(&mc_allnodes);
-+ ndisc_send_na(dev, NULL, &mc_allnodes, haddr, 0, 0, 1, 1);
-+ dev_put(dev);
-+}
-+
-+static int mn_use_hao(struct in6_addr *daddr, struct in6_addr *saddr)
-+{
-+ struct mipv6_bul_entry *entry;
-+ struct mn_info *minfo = NULL;
-+ int add_ha = 0;
-+
-+ read_lock_bh(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(saddr);
-+ if (minfo && minfo->is_at_home != MN_AT_HOME) {
-+ read_lock_bh(&bul_lock);
-+ if ((entry = mipv6_bul_get(daddr, saddr)) == NULL) {
-+ read_unlock_bh(&bul_lock);
-+ read_unlock_bh(&mn_info_lock);
-+ return add_ha;
-+ }
-+ add_ha = (entry->state != ACK_ERROR &&
-+ (!entry->rr || entry->rr->rr_state == RR_DONE ||
-+ entry->flags & MIPV6_BU_F_HOME));
-+ read_unlock_bh(&bul_lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+ return add_ha;
-+}
-+
-+static int
-+mn_dev_event(struct notifier_block *nb, unsigned long event, void *ptr)
-+{
-+ struct net_device *dev = ptr;
-+ struct list_head *lh;
-+ struct mn_info *minfo;
-+ int newif = 0;
-+
-+ /* here are probably the events we need to worry about */
-+ switch (event) {
-+ case NETDEV_UP:
-+ DEBUG(DBG_DATADUMP, "New netdevice %s registered.", dev->name);
-+ if (dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev))
-+ ma_ctl_add_iface(dev->ifindex);
-+
-+ break;
-+ case NETDEV_GOING_DOWN:
-+ DEBUG(DBG_DATADUMP, "Netdevice %s disappeared.", dev->name);
-+ /*
-+ * Go through mn_info list and move all home addresses on the
-+ * netdev going down to a new device. This will make it
-+ * practically impossible for the home address to return home,
-+ * but allow MN to retain its connections using the address.
-+ */
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(lh, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ if (minfo->ifindex == dev->ifindex) {
-+ if (sched_mv_home_addr_task(&minfo->home_addr, 128,
-+ minfo->ifindex_user,
-+ 0, NULL) < 0) {
-+ minfo->ifindex = 0;
-+ spin_unlock(&minfo->lock);
-+ read_unlock_bh(&mn_info_lock);
-+ return NOTIFY_DONE;
-+ } else {
-+ minfo->ifindex = minfo->ifindex_user;
-+ if (minfo->is_at_home) {
-+ minfo->is_at_home = 0;
-+
-+ }
-+ newif = minfo->ifindex_user;
-+ }
-+ }
-+ spin_unlock(&minfo->lock);
-+ }
-+
-+ read_unlock_bh(&mn_info_lock);
-+ }
-+ ma_ctl_upd_iface(dev->ifindex, MA_IFACE_NOT_PRESENT, &newif);
-+ mipv6_mdet_del_if(dev->ifindex);
-+
-+ return NOTIFY_DONE;
-+}
-+
-+struct notifier_block mipv6_mn_dev_notifier = {
-+ mn_dev_event,
-+ NULL,
-+ 0 /* check if using zero is ok */
-+};
-+
-+static void deprecate_addr(struct mn_info *minfo)
-+{
-+ /*
-+ * Lookup address from IPv6 address list and set deprecated flag
-+ */
-+
-+}
-+
-+/*
-+ * Required because we can only modify addresses after the packet is
-+ * constructed. We otherwise mess with higher level protocol
-+ * pseudoheaders. With strict protocol layering life would be SO much
-+ * easier!
-+ */
-+static unsigned int modify_xmit_addrs(unsigned int hooknum,
-+ struct sk_buff **pskb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn) (struct sk_buff *))
-+{
-+ struct sk_buff *skb = *pskb;
-+
-+ DEBUG_FUNC();
-+
-+ if (skb) {
-+ struct ipv6hdr *hdr = skb->nh.ipv6h;
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct mipv6_bul_entry *bule;
-+ struct in6_addr *daddr;
-+
-+ if (!ipv6_addr_any(&opt->hoa))
-+ daddr = &opt->hoa;
-+ else
-+ daddr = &hdr->daddr;
-+
-+ /* We don't consult bul when sending a BU to avoid deadlock, since
-+ * BUL is already locked.
-+ */
-+
-+
-+ if (opt->mipv6_flags & MIPV6_SND_HAO &&
-+ !(opt->mipv6_flags & MIPV6_SND_BU)) {
-+ write_lock(&bul_lock);
-+ bule = mipv6_bul_get(daddr, &hdr->saddr);
-+ if (!bule) {
-+ write_unlock(&bul_lock);
-+ return NF_ACCEPT;
-+ }
-+ if (!bule->rr || bule->rr->rr_state == RR_DONE ||
-+ bule->flags & MIPV6_BU_F_HOME) {
-+ DEBUG(DBG_DATADUMP,
-+ "Replace source address with CoA and reroute");
-+ ipv6_addr_copy(&hdr->saddr, &bule->coa);
-+ skb->nfcache |= NFC_ALTERED;
-+ }
-+ write_unlock(&bul_lock);
-+ } else if (opt->mipv6_flags & MIPV6_SND_HAO) {
-+ mipv6_get_care_of_address(&hdr->saddr, &hdr->saddr);
-+ skb->nfcache |= NFC_ALTERED;
-+ }
-+ }
-+ return NF_ACCEPT;
-+}
-+
-+/* We set a netfilter hook so that we can modify outgoing packet's
-+ * source addresses
-+ */
-+struct nf_hook_ops addr_modify_hook_ops = {
-+ {NULL, NULL}, /* List head, no predecessor, no successor */
-+ modify_xmit_addrs,
-+ PF_INET6,
-+ NF_IP6_LOCAL_OUT,
-+ NF_IP6_PRI_FIRST /* Should be of EXTREMELY high priority since we
-+ * do not want to mess with IPSec (possibly
-+ * implemented as packet filter)
-+ */
-+};
-+
-+#define MN_INFO_LEN 77
-+
-+static int mn_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct list_head *p;
-+ struct mn_info *minfo;
-+ int len = 0, skip = 0;
-+
-+ DEBUG_FUNC();
-+
-+ read_lock_bh(&mn_info_lock);
-+ list_for_each(p, &mn_info_list) {
-+ if (len < offset / MN_INFO_LEN) {
-+ skip++;
-+ continue;
-+ }
-+ if (len >= length)
-+ break;
-+ minfo = list_entry(p, struct mn_info, list);
-+ spin_lock(&minfo->lock);
-+ len += sprintf(buffer + len, "%02d %08x%08x%08x%08x %02x "
-+ "%08x%08x%08x%08x %d %d\n",
-+ minfo->ifindex,
-+ ntohl(minfo->home_addr.s6_addr32[0]),
-+ ntohl(minfo->home_addr.s6_addr32[1]),
-+ ntohl(minfo->home_addr.s6_addr32[2]),
-+ ntohl(minfo->home_addr.s6_addr32[3]),
-+ minfo->home_plen,
-+ ntohl(minfo->ha.s6_addr32[0]),
-+ ntohl(minfo->ha.s6_addr32[1]),
-+ ntohl(minfo->ha.s6_addr32[2]),
-+ ntohl(minfo->ha.s6_addr32[3]),
-+ minfo->is_at_home, minfo->has_home_reg);
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock_bh(&mn_info_lock);
-+
-+ *start = buffer;
-+ if (offset)
-+ *start += offset % MN_INFO_LEN;
-+
-+ len -= offset % MN_INFO_LEN;
-+
-+ if (len > length)
-+ len = length;
-+ if (len < 0)
-+ len = 0;
-+
-+ return len;
-+}
-+
-+int mipv6_mn_ha_nd_update(struct net_device *dev,
-+ struct in6_addr *ha, u8 *lladdr)
-+{
-+ int valid = 0;
-+ struct neighbour *neigh;
-+ if ((neigh = ndisc_get_neigh(dev, ha))) {
-+ read_lock(&neigh->lock);
-+ valid = neigh->nud_state & NUD_VALID;
-+ read_unlock(&neigh->lock);
-+ if (!valid && lladdr)
-+ neigh_update(neigh, lladdr, NUD_REACHABLE, 0, 1);
-+ neigh_release(neigh);
-+ }
-+ return valid;
-+}
-+
-+int mipv6_mn_ha_probe(struct inet6_ifaddr *ifp, u8 *lladdr)
-+{
-+ struct mn_info *minfo;
-+
-+ if (!(minfo = mipv6_mninfo_get_by_home(&ifp->addr)) ||
-+ ipv6_addr_any(&minfo->ha))
-+ return 0;
-+
-+ if (mipv6_mn_ha_nd_update(ifp->idev->dev, &minfo->ha, lladdr))
-+ mipv6_mdet_retrigger_ho();
-+ return 1;
-+}
-+
-+int __init mipv6_mn_init(void)
-+{
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ if (mipv6_add_tnl_to_ha())
-+ return -ENODEV;
-+
-+ mipv6_bul_init(MIPV6_BUL_SIZE);
-+ mip6_fn.mn_use_hao = mn_use_hao;
-+ mip6_fn.mn_check_tunneled_packet = mn_check_tunneled_packet;
-+ INIT_TQUEUE(&mv_home_addr_task, mv_home_addr, NULL);
-+
-+ ma_ctl_init();
-+ for (dev = dev_base; dev; dev = dev->next) {
-+ if (dev->flags & IFF_UP &&
-+ dev->type != ARPHRD_LOOPBACK && !dev_is_mip6_tnl(dev)) {
-+ ma_ctl_add_iface(dev->ifindex);
-+ }
-+ }
-+ DEBUG(DBG_INFO, "Multiaccess support initialized");
-+
-+ register_netdevice_notifier(&mipv6_mn_dev_notifier);
-+ register_inet6addr_notifier(&mipv6_mn_inet6addr_notifier);
-+
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_send_bu_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_register_hook(&mipv6_mn_tnl_rcv_stats_ops);
-+
-+ MIPV6_SETCALL(mipv6_set_home, mipv6_mn_set_home);
-+
-+ mipv6_initialize_mdetect();
-+
-+ /* COA to home transformation hook */
-+ MIPV6_SETCALL(mipv6_get_home_address, mipv6_get_saddr_hook);
-+ MIPV6_SETCALL(mipv6_mn_ha_probe, mipv6_mn_ha_probe);
-+ MIPV6_SETCALL(mipv6_is_home_addr, mipv6_mn_is_home_addr);
-+ proc_net_create("mip6_mninfo", 0, mn_proc_info);
-+ /* Set packet modification hook (source addresses) */
-+ nf_register_hook(&addr_modify_hook_ops);
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mn_exit(void)
-+{
-+ struct list_head *lh, *tmp;
-+ struct mn_info *minfo;
-+ DEBUG_FUNC();
-+
-+ mip6_fn.mn_use_hao = NULL;
-+ mip6_fn.mn_check_tunneled_packet = NULL;
-+
-+ MIPV6_RESETCALL(mipv6_set_home);
-+ MIPV6_RESETCALL(mipv6_get_home_address);
-+ MIPV6_RESETCALL(mipv6_mn_ha_probe);
-+ MIPV6_RESETCALL(mipv6_is_home_addr);
-+ nf_unregister_hook(&addr_modify_hook_ops);
-+ proc_net_remove("mip6_mninfo");
-+ mipv6_shutdown_mdetect();
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_xmit_stats_ops);
-+ ip6ip6_tnl_unregister_hook(&mipv6_mn_tnl_rcv_send_bu_ops);
-+ ma_ctl_clean();
-+
-+ unregister_inet6addr_notifier(&mipv6_mn_inet6addr_notifier);
-+ unregister_netdevice_notifier(&mipv6_mn_dev_notifier);
-+ write_lock_bh(&mn_info_lock);
-+
-+ list_for_each_safe(lh, tmp, &mn_info_list) {
-+ minfo = list_entry(lh, struct mn_info, list);
-+ if (minfo->is_at_home == MN_NOT_AT_HOME)
-+ deprecate_addr(minfo);
-+ list_del(&minfo->list);
-+ kfree(minfo);
-+ }
-+ write_unlock_bh(&mn_info_lock);
-+ mipv6_bul_exit();
-+ flush_scheduled_tasks();
-+ mipv6_del_tnl_to_ha();
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mn.h
-@@ -0,0 +1,96 @@
-+/*
-+ * MIPL Mobile IPv6 Mobile Node header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MN_H
-+#define _MN_H
-+
-+#include <linux/in6.h>
-+
-+/* constants for sending of BUs*/
-+#define HA_BU_DEF_LIFETIME 10000
-+#define CN_BU_DEF_LIFETIME 420 /* Max lifetime for RR bindings from RFC 3775 */
-+#define DUMB_CN_BU_LIFETIME 600 /* BUL entry lifetime in case of dumb CN */
-+#define ROUTER_BU_DEF_LIFETIME 30 /* For packet forwarding from previous coa */
-+#define ERROR_DEF_LIFETIME DUMB_CN_BU_LIFETIME
-+
-+extern rwlock_t mn_info_lock;
-+
-+#define MN_NOT_AT_HOME 0
-+#define MN_RETURNING_HOME 1
-+#define MN_AT_HOME 2
-+
-+/*
-+ * Mobile Node information record
-+ */
-+struct mn_info {
-+ struct in6_addr home_addr;
-+ struct in6_addr ha;
-+ __u8 home_plen;
-+ __u8 is_at_home;
-+ __u8 has_home_reg;
-+ __u8 man_conf;
-+ int ifindex;
-+ int ifindex_user;
-+ unsigned long home_addr_expires;
-+ unsigned short dhaad_id;
-+ struct list_head list;
-+ spinlock_t lock;
-+};
-+
-+/* prototypes for interface functions */
-+int mipv6_mn_init(void);
-+void mipv6_mn_exit(void);
-+
-+struct handoff;
-+
-+/* Interface to movement detection */
-+int mipv6_mobile_node_moved(struct handoff *ho);
-+
-+void mipv6_mn_send_home_na(struct in6_addr *haddr);
-+/* Init home reg. with coa */
-+int init_home_registration(struct in6_addr *home_addr, struct in6_addr *coa);
-+
-+/* mn_info functions that require locking by caller */
-+struct mn_info *mipv6_mninfo_get_by_home(struct in6_addr *haddr);
-+
-+struct mn_info *mipv6_mninfo_get_by_ha(struct in6_addr *home_agent);
-+
-+struct mn_info *mipv6_mninfo_get_by_id(unsigned short id);
-+
-+/* "safe" mn_info functions */
-+void mipv6_mninfo_add(int ifindex, struct in6_addr *home_addr, int plen,
-+ int isathome, unsigned long lifetime, struct in6_addr *ha,
-+ int ha_plen, unsigned long ha_lifetime, int man_conf);
-+
-+int mipv6_mninfo_del(struct in6_addr *home_addr, int del_dyn_only);
-+
-+void mipv6_mn_set_home_reg(struct in6_addr *home_addr, int has_home_reg);
-+
-+int mipv6_mn_is_at_home(struct in6_addr *addr);
-+
-+int mipv6_mn_is_home_addr(struct in6_addr *addr);
-+
-+__u32 mipv6_mn_get_bulifetime(struct in6_addr *home_addr,
-+ struct in6_addr *coa, __u8 flags);
-+int mn_cn_handoff(void *rawentry, void *args, unsigned long *sortkey);
-+
-+int mipv6_mn_ha_nd_update(struct net_device *dev,
-+ struct in6_addr *ha, u8 *lladdr);
-+
-+struct bul_inval_args {
-+ int all_rr_states;
-+ struct in6_addr *cn;
-+ struct in6_addr *mn;
-+};
-+
-+int mn_bul_invalidate(void *rawentry, void *args, unsigned long *sortkey);
-+
-+#endif /* _MN_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mobhdr.h
-@@ -0,0 +1,101 @@
-+/*
-+ * MIPL Mobile IPv6 Mobility Header send and receive
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _MOBHDR_H
-+#define _MOBHDR_H
-+
-+#include <net/mipv6.h>
-+
-+/* RR states for mipv6_send_bu() */
-+#define RR_INIT 0x00
-+#define RR_WAITH 0x01
-+#define RR_WAITC 0x02
-+#define RR_WAITHC 0x13
-+#define RR_DONE 0x10
-+
-+#define MH_UNKNOWN_CN 1
-+#define MH_AUTH_FAILED 2
-+#define MH_SEQUENCE_MISMATCH 3
-+
-+struct mipv6_bul_entry;
-+struct sk_buff;
-+
-+int mipv6_mh_common_init(void);
-+void mipv6_mh_common_exit(void);
-+int mipv6_mh_mn_init(void);
-+void mipv6_mh_mn_exit(void);
-+
-+struct mipv6_mh_opt {
-+ struct mipv6_mo_alt_coa *alt_coa;
-+ struct mipv6_mo_nonce_indices *nonce_indices;
-+ struct mipv6_mo_bauth_data *auth_data;
-+ struct mipv6_mo_br_advice *br_advice;
-+ int freelen;
-+ int totlen;
-+ u8 *next_free;
-+ u8 data[0];
-+};
-+
-+struct mobopt {
-+ struct mipv6_mo_alt_coa *alt_coa;
-+ struct mipv6_mo_nonce_indices *nonce_indices;
-+ struct mipv6_mo_bauth_data *auth_data;
-+ struct mipv6_mo_br_advice *br_advice;
-+};
-+
-+struct mipv6_mh_opt *alloc_mh_opts(int totlen);
-+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data);
-+int parse_mo_tlv(void *mos, int len, struct mobopt *opts);
-+int mipv6_add_pad(u8 *data, int n);
-+
-+struct mipv6_auth_parm {
-+ struct in6_addr *coa;
-+ struct in6_addr *cn_addr;
-+ __u8 *k_bu;
-+};
-+
-+int send_mh(struct in6_addr *daddr, struct in6_addr *saddr,
-+ u8 msg_type, u8 msg_len, u8 *msg,
-+ struct in6_addr *hao_addr, struct in6_addr *rth_addr,
-+ struct mipv6_mh_opt *ops, struct mipv6_auth_parm *parm);
-+
-+int mipv6_mh_register(int type, int (*func)(struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *));
-+
-+void mipv6_mh_unregister(int type);
-+
-+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct mipv6_mh_opt *ops);
-+
-+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *coa, __u32 initdelay,
-+ __u32 maxackdelay, __u8 exp, __u8 flags,
-+ __u32 lifetime, struct mipv6_mh_opt *ops);
-+
-+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *home, __u8 status);
-+
-+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *auth_coa, struct in6_addr *rep_coa,
-+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu);
-+
-+/* Binding Authentication Data Option routines */
-+#define MAX_HASH_LENGTH 20
-+#define MIPV6_RR_MAC_LENGTH 12
-+
-+int mipv6_auth_build(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 *aud_data, __u8 *k_bu);
-+
-+int mipv6_auth_check(struct in6_addr *cn_addr, struct in6_addr *coa,
-+ __u8 *opt, __u8 optlen, struct mipv6_mo_bauth_data *aud,
-+ __u8 *k_bu);
-+#endif /* _MOBHDR_H */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mobhdr_common.c
-@@ -0,0 +1,1210 @@
-+/*
-+ * Mobile IPv6 Mobility Header Common Functions
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id: s.mh_recv.c 1.159 02/10/16 15:01:29+03:00 antti@traci.mipl.mediapoli.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.
-+ *
-+ */
-+
-+#include <linux/autoconf.h>
-+#include <linux/types.h>
-+#include <linux/in6.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipsec.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+#include <net/checksum.h>
-+#include <net/protocol.h>
-+
-+#include "stats.h"
-+#include "debug.h"
-+#include "mobhdr.h"
-+#include "bcache.h"
-+
-+#include "rr_crypto.h"
-+#include "exthdrs.h"
-+#include "config.h"
-+
-+#define MIPV6_MH_MAX MIPV6_MH_BE
-+struct mh_proto {
-+ int (*func) (struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct mipv6_mh *);
-+};
-+
-+static struct mh_proto mh_rcv[MIPV6_MH_MAX];
-+
-+int mipv6_mh_register(int type, int (*func)(struct sk_buff *,
-+ struct in6_addr *, struct in6_addr *,
-+ struct in6_addr *, struct in6_addr *, struct mipv6_mh *))
-+{
-+ if (mh_rcv[type].func != NULL)
-+ return -1;
-+
-+ mh_rcv[type].func = func;
-+
-+ return 0;
-+}
-+
-+void mipv6_mh_unregister(int type)
-+{
-+ if (type < 0 || type > MIPV6_MH_MAX)
-+ return;
-+
-+ mh_rcv[type].func = NULL;
-+}
-+
-+struct socket *mipv6_mh_socket = NULL;
-+
-+/* TODO: Fix fragmentation */
-+static int dstopts_getfrag(
-+ const void *data, struct in6_addr *addr,
-+ char *buff, unsigned int offset, unsigned int len)
-+{
-+ memcpy(buff, data + offset, len);
-+ return 0;
-+}
-+
-+struct mipv6_mh_opt *alloc_mh_opts(int totlen)
-+{
-+ struct mipv6_mh_opt *ops;
-+
-+ ops = kmalloc(sizeof(*ops) + totlen, GFP_ATOMIC);
-+ if (ops == NULL)
-+ return NULL;
-+
-+ memset(ops, 0, sizeof(*ops));
-+ ops->next_free = ops->data;
-+ ops->freelen = totlen;
-+
-+ return ops;
-+}
-+
-+int append_mh_opt(struct mipv6_mh_opt *ops, u8 type, u8 len, void *data)
-+{
-+ struct mipv6_mo *mo;
-+
-+ if (ops->next_free == NULL) {
-+ DEBUG(DBG_ERROR, "No free room for option");
-+ return -ENOMEM;
-+ }
-+ if (ops->freelen < len + 2) {
-+ DEBUG(DBG_ERROR, "No free room for option");
-+ return -ENOMEM;
-+ }
-+ else {
-+ ops->freelen -= (len + 2);
-+ ops->totlen += (len + 2);
-+ }
-+
-+ mo = (struct mipv6_mo *)ops->next_free;
-+ mo->type = type;
-+ mo->length = len;
-+
-+ switch (type) {
-+ case MIPV6_OPT_ALTERNATE_COA:
-+ ops->alt_coa = (struct mipv6_mo_alt_coa *)mo;
-+ ipv6_addr_copy(&ops->alt_coa->addr, (struct in6_addr *)data);
-+ break;
-+ case MIPV6_OPT_NONCE_INDICES:
-+ DEBUG(DBG_INFO, "Added nonce indices pointer");
-+ ops->nonce_indices = (struct mipv6_mo_nonce_indices *)mo;
-+ ops->nonce_indices->home_nonce_i = *(__u16 *)data;
-+ ops->nonce_indices->careof_nonce_i = *((__u16 *)data + 1);
-+ break;
-+ case MIPV6_OPT_AUTH_DATA:
-+ DEBUG(DBG_INFO, "Added opt auth_data pointer");
-+ ops->auth_data = (struct mipv6_mo_bauth_data *)mo;
-+ break;
-+ case MIPV6_OPT_BIND_REFRESH_ADVICE:
-+ ops->br_advice = (struct mipv6_mo_br_advice *)mo;
-+ ops->br_advice->refresh_interval = htons(*(u16 *)data);
-+ break;
-+ default:
-+ DEBUG(DBG_ERROR, "Unknow option type");
-+ break;
-+ }
-+
-+ if (ops->freelen == 0)
-+ ops->next_free = NULL;
-+ else
-+ ops->next_free += (len + 2);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Calculates required padding with xn + y requirement with offset
-+ */
-+static inline int optpad(int xn, int y, int offset)
-+{
-+ return ((y - offset) & (xn - 1));
-+}
-+
-+static int option_pad(int type, int offset)
-+{
-+ if (type == MIPV6_OPT_ALTERNATE_COA)
-+ return optpad(8, 6, offset); /* 8n + 6 */
-+ if (type == MIPV6_OPT_BIND_REFRESH_ADVICE ||
-+ type == MIPV6_OPT_NONCE_INDICES)
-+ return optpad(2, 0, offset); /* 2n */
-+ return 0;
-+}
-+
-+/*
-+ * Add Pad1 or PadN option to data
-+ */
-+int mipv6_add_pad(u8 *data, int n)
-+{
-+ struct mipv6_mo_padn *padn;
-+
-+ if (n <= 0) return 0;
-+ if (n == 1) {
-+ *data = MIPV6_OPT_PAD1;
-+ return 1;
-+ }
-+ padn = (struct mipv6_mo_padn *)data;
-+ padn->type = MIPV6_OPT_PADN;
-+ padn->length = n - 2;
-+ memset(padn->data, 0, n - 2);
-+ return n;
-+}
-+
-+/*
-+ * Write options to mobility header buffer
-+ */
-+static int prepare_mh_opts(u8 *optdata, int off, struct mipv6_mh_opt *ops)
-+{
-+ u8 *nextopt = optdata;
-+ int offset = off, pad = 0;
-+
-+ if (ops == NULL) {
-+ nextopt = NULL;
-+ return -1;
-+ }
-+
-+ if (ops->alt_coa) {
-+ pad = option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->alt_coa, sizeof(struct mipv6_mo_alt_coa));
-+ nextopt += sizeof(struct mipv6_mo_alt_coa);
-+ offset += pad + sizeof(struct mipv6_mo_alt_coa);
-+ }
-+
-+ if (ops->br_advice) {
-+ pad = option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->br_advice, sizeof(struct mipv6_mo_br_advice));
-+ nextopt += sizeof(struct mipv6_mo_br_advice);
-+ offset += pad + sizeof(struct mipv6_mo_br_advice);
-+ }
-+
-+ if (ops->nonce_indices) {
-+ pad = option_pad(MIPV6_OPT_NONCE_INDICES, offset);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->nonce_indices, sizeof(struct mipv6_mo_nonce_indices));
-+ nextopt += sizeof(struct mipv6_mo_nonce_indices);
-+ offset += pad + sizeof(struct mipv6_mo_nonce_indices);
-+ }
-+
-+ if (ops->auth_data) {
-+ /* This option should always be the last. Header
-+ * length must be a multiple of 8 octects, so we pad
-+ * if necessary. */
-+ pad = optpad(8, 0, offset + ops->auth_data->length + 2);
-+ nextopt += mipv6_add_pad(nextopt, pad);
-+ memcpy(nextopt, ops->auth_data, ops->auth_data->length + 2);
-+ nextopt += ops->auth_data->length + 2;
-+ }
-+ nextopt = NULL;
-+
-+ return 0;
-+}
-+
-+static int calculate_mh_opts(struct mipv6_mh_opt *ops, int mh_len)
-+{
-+ int offset = mh_len;
-+
-+ if (ops == NULL)
-+ return 0;
-+
-+ if (ops->alt_coa)
-+ offset += sizeof(struct mipv6_mo_alt_coa)
-+ + option_pad(MIPV6_OPT_ALTERNATE_COA, offset);
-+
-+ if (ops->br_advice)
-+ offset += sizeof(struct mipv6_mo_br_advice)
-+ + option_pad(MIPV6_OPT_BIND_REFRESH_ADVICE, offset);
-+
-+ if (ops->nonce_indices)
-+ offset += sizeof(struct mipv6_mo_nonce_indices)
-+ + option_pad(MIPV6_OPT_NONCE_INDICES, offset);
-+
-+ if (ops->auth_data) /* no alignment */
-+ offset += ops->auth_data->length + 2;
-+
-+ return offset - mh_len;
-+}
-+
-+/*
-+ *
-+ * Mobility Header Message send functions
-+ *
-+ */
-+
-+/**
-+ * send_mh - builds and sends a MH msg
-+ *
-+ * @daddr: destination address for packet
-+ * @saddr: source address for packet
-+ * @msg_type: type of MH
-+ * @msg_len: message length
-+ * @msg: MH type specific data
-+ * @hao_addr: home address for home address option
-+ * @rth_addr: routing header address
-+ * @ops: mobility options
-+ * @parm: auth data
-+ *
-+ * Builds MH, appends the type specific msg data to the header and
-+ * sends the packet with a home address option, if a home address was
-+ * given. Returns 0, if everything succeeded and a negative error code
-+ * otherwise.
-+ **/
-+int send_mh(struct in6_addr *daddr,
-+ struct in6_addr *saddr,
-+ u8 msg_type, u8 msg_len, u8 *msg,
-+ struct in6_addr *hao_addr,
-+ struct in6_addr *rth_addr,
-+ struct mipv6_mh_opt *ops,
-+ struct mipv6_auth_parm *parm)
-+{
-+ struct flowi fl;
-+ struct mipv6_mh *mh;
-+ struct sock *sk = mipv6_mh_socket->sk;
-+ struct ipv6_txoptions *txopt = NULL;
-+ int tot_len = sizeof(struct mipv6_mh) + msg_len;
-+ int padded_len = 0, txopt_len = 0;
-+
-+ DEBUG_FUNC();
-+ /* Add length of options */
-+ tot_len += calculate_mh_opts(ops, tot_len);
-+ /* Needs to be a multiple of 8 octets */
-+ padded_len = tot_len + optpad(8, 0, tot_len);
-+
-+ mh = sock_kmalloc(sk, padded_len, GFP_ATOMIC);
-+ if (!mh) {
-+ DEBUG(DBG_ERROR, "memory allocation failed");
-+ return -ENOMEM;
-+ }
-+
-+ memset(&fl, 0, sizeof(fl));
-+ fl.proto = IPPROTO_MOBILITY;
-+ fl.fl6_dst = daddr;
-+ fl.fl6_src = saddr;
-+ fl.fl6_flowlabel = 0;
-+ fl.oif = sk->bound_dev_if;
-+
-+ if (hao_addr || rth_addr) {
-+ __u8 *opt_ptr;
-+
-+ if (hao_addr)
-+ txopt_len += sizeof(struct mipv6_dstopt_homeaddr) + 6;
-+ if (rth_addr)
-+ txopt_len += sizeof(struct rt2_hdr);
-+
-+ txopt_len += sizeof(*txopt);
-+ txopt = sock_kmalloc(sk, txopt_len, GFP_ATOMIC);
-+ if (txopt == NULL) {
-+ DEBUG(DBG_ERROR, "No socket space left");
-+ sock_kfree_s(sk, mh, padded_len);
-+ return -ENOMEM;
-+ }
-+ memset(txopt, 0, txopt_len);
-+ txopt->tot_len = txopt_len;
-+ opt_ptr = (__u8 *) (txopt + 1);
-+ if (hao_addr) {
-+ int holen = sizeof(struct mipv6_dstopt_homeaddr) + 6;
-+ txopt->dst1opt = (struct ipv6_opt_hdr *) opt_ptr;
-+ txopt->opt_flen += holen;
-+ opt_ptr += holen;
-+ mipv6_append_dst1opts(txopt->dst1opt, saddr,
-+ NULL, holen);
-+ txopt->mipv6_flags = MIPV6_SND_HAO | MIPV6_SND_BU;
-+ }
-+ if (rth_addr) {
-+ int rtlen = sizeof(struct rt2_hdr);
-+ txopt->srcrt2 = (struct ipv6_rt_hdr *) opt_ptr;
-+ txopt->opt_nflen += rtlen;
-+ opt_ptr += rtlen;
-+ mipv6_append_rt2hdr(txopt->srcrt2, rth_addr);
-+ }
-+ }
-+
-+ /* Fill in the fields of MH */
-+ mh->payload = NEXTHDR_NONE;
-+ mh->length = (padded_len >> 3) - 1; /* Units of 8 octets - 1 */
-+ mh->type = msg_type;
-+ mh->reserved = 0;
-+ mh->checksum = 0;
-+
-+ memcpy(mh->data, msg, msg_len);
-+ prepare_mh_opts(mh->data + msg_len, msg_len + sizeof(*mh), ops);
-+ /* If BAD is present, this is already done. */
-+ mipv6_add_pad((u8 *)mh + tot_len, padded_len - tot_len);
-+
-+ if (parm && parm->k_bu && ops && ops->auth_data) {
-+ /* Calculate the position of the authorization data before adding checksum*/
-+ mipv6_auth_build(parm->cn_addr, parm->coa, (__u8 *)mh,
-+ (__u8 *)mh + padded_len - MIPV6_RR_MAC_LENGTH, parm->k_bu);
-+ }
-+ /* Calculate the MH checksum */
-+ mh->checksum = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst,
-+ padded_len, IPPROTO_MOBILITY,
-+ csum_partial((char *)mh, padded_len, 0));
-+ ip6_build_xmit(sk, dstopts_getfrag, mh, &fl, padded_len, txopt, 255,
-+ MSG_DONTWAIT);
-+ /* dst cache must be cleared so RR messages can be routed through
-+ different interfaces */
-+ sk_dst_reset(sk);
-+
-+ if (txopt_len)
-+ sock_kfree_s(sk, txopt, txopt_len);
-+ sock_kfree_s(sk, mh, padded_len);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_brr - send a Binding Refresh Request
-+ * @saddr: source address for BRR
-+ * @daddr: destination address for BRR
-+ * @ops: mobility options
-+ *
-+ * Sends a binding request. On a mobile node, use the mobile node's
-+ * home address for @saddr. Returns 0 on success, negative on
-+ * failure.
-+ **/
-+int mipv6_send_brr(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct mipv6_mh_opt *ops)
-+{
-+ struct mipv6_mh_brr br;
-+
-+ memset(&br, 0, sizeof(br));
-+ /* We don't need to explicitly add a RH to brr, since it will be
-+ * included automatically, if a BCE exists
-+ */
-+ MIPV6_INC_STATS(n_brr_sent);
-+ return send_mh(daddr, saddr, MIPV6_MH_BRR, sizeof(br), (u8 *)&br,
-+ NULL, NULL, ops, NULL);
-+}
-+
-+/**
-+ * mipv6_send_ba - send a Binding Acknowledgement
-+ * @saddr: source address for BA
-+ * @daddr: destination address for BA
-+ * @reply_coa: destination care-of address of MN
-+ * @auth_coa: care-of address of MN used for authentication
-+ * @status: status field value
-+ * @sequence: sequence number from BU
-+ * @lifetime: granted lifetime for binding in seconds
-+ * @ops: mobility options
-+ *
-+ * Send a binding acknowledgement. On a mobile node, use the mobile
-+ * node's home address for saddr. Returns 0 on success, non-zero on
-+ * failure.
-+ **/
-+int mipv6_send_ba(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *auth_coa, struct in6_addr *rep_coa,
-+ u8 status, u16 sequence, u32 lifetime, u8 *k_bu)
-+{
-+ struct mipv6_mh_ba ba;
-+ struct mipv6_auth_parm parm;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ops_len = 0, ret = 0;
-+ struct mipv6_bce bc_entry;
-+ int coming_home = 0;
-+ int bypass_tnl = 0;
-+
-+ memset(&ba, 0, sizeof(ba));
-+
-+ ba.status = status;
-+ ba.sequence = htons(sequence);
-+ ba.lifetime = htons(lifetime >> 2);
-+
-+ DEBUG(DBG_INFO, "sending a status %d BA %s authenticator to MN \n"
-+ "%x:%x:%x:%x:%x:%x:%x:%x at care of address \n"
-+ "%x:%x:%x:%x:%x:%x:%x:%x : with lifetime %d and \n"
-+ " sequence number %d",
-+ status, k_bu ? "with" : "without",
-+ NIPV6ADDR(daddr), NIPV6ADDR(auth_coa), lifetime, sequence);
-+
-+ memset(&parm, 0, sizeof(parm));
-+ parm.coa = auth_coa;
-+ parm.cn_addr = saddr;
-+
-+ if (k_bu) {
-+ ops_len += sizeof(struct mipv6_mo_bauth_data) +
-+ MIPV6_RR_MAC_LENGTH;
-+ parm.k_bu = k_bu;
-+ }
-+
-+ if (mip6node_cnf.binding_refresh_advice) {
-+ ops_len += sizeof(struct mipv6_mo_br_advice);
-+ }
-+ if (ops_len) {
-+ ops = alloc_mh_opts(ops_len);
-+ if (ops == NULL) {
-+ DEBUG(DBG_WARNING, "Out of memory");
-+ return -ENOMEM;
-+ }
-+ if (mip6node_cnf.binding_refresh_advice > 0) {
-+ if (append_mh_opt(ops, MIPV6_OPT_BIND_REFRESH_ADVICE, 2,
-+ &mip6node_cnf.binding_refresh_advice) < 0) {
-+ DEBUG(DBG_WARNING, "Adding BRA failed");
-+ if (ops)
-+ kfree(ops);
-+ return -ENOMEM;
-+ }
-+ }
-+ if (k_bu) {
-+ if (append_mh_opt(ops, MIPV6_OPT_AUTH_DATA,
-+ MIPV6_RR_MAC_LENGTH, NULL) < 0) {
-+ DEBUG(DBG_WARNING, "Adding BAD failed");
-+ if (ops)
-+ kfree(ops);
-+ return -ENOMEM;
-+ }
-+ }
-+ }
-+ coming_home = !ipv6_addr_cmp(rep_coa, daddr);
-+
-+ bypass_tnl = (coming_home &&
-+ !mipv6_bcache_get(daddr, saddr, &bc_entry) &&
-+ bc_entry.flags&MIPV6_BU_F_HOME &&
-+ status >= 128);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del)
-+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (coming_home)
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
-+ NULL, NULL, ops, &parm);
-+ else
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BA, sizeof(ba), (u8 *)&ba,
-+ NULL, rep_coa, ops, &parm);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add)
-+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (ret == 0) {
-+ if (status < 128) {
-+ MIPV6_INC_STATS(n_ba_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_ban_sent);
-+ }
-+ }
-+
-+ if (ops)
-+ kfree(ops);
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_be - send a Binding Error message
-+ * @saddr: source address for BE
-+ * @daddr: destination address for BE
-+ * @home: Home Address in offending packet (if any)
-+ *
-+ * Sends a binding error. On a mobile node, use the mobile node's
-+ * home address for @saddr. Returns 0 on success, negative on
-+ * failure.
-+ **/
-+int mipv6_send_be(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *home, __u8 status)
-+{
-+ struct mipv6_mh_be be;
-+ int ret = 0;
-+ struct mipv6_bce bc_entry;
-+ int bypass_tnl = 0;
-+
-+ if (ipv6_addr_is_multicast(daddr))
-+ return -EINVAL;
-+
-+ memset(&be, 0, sizeof(be));
-+ be.status = status;
-+ if (home)
-+ ipv6_addr_copy(&be.home_addr, home);
-+
-+ if (mipv6_bcache_get(daddr, saddr, &bc_entry) == 0 &&
-+ bc_entry.flags&MIPV6_BU_F_HOME)
-+ bypass_tnl = 1;
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_del)
-+ mip6_fn.bce_tnl_rt_del(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ ret = send_mh(daddr, saddr, MIPV6_MH_BE, sizeof(be), (u8 *)&be,
-+ NULL, NULL, NULL, NULL);
-+
-+ if (bypass_tnl && mip6_fn.bce_tnl_rt_add)
-+ mip6_fn.bce_tnl_rt_add(&bc_entry.coa,
-+ &bc_entry.our_addr,
-+ &bc_entry.home_addr);
-+
-+ if (ret == 0)
-+ MIPV6_INC_STATS(n_be_sent);
-+
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_send_addr_test - send a HoT or CoT message
-+ * @saddr: source address
-+ * @daddr: destination address
-+ * @msg_type: HoT or CoT message
-+ * @init: HoTI or CoTI message
-+ *
-+ * Send a reply to HoTI or CoTI message.
-+ **/
-+static int mipv6_send_addr_test(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ int msg_type,
-+ struct mipv6_mh_addr_ti *init)
-+{
-+ u_int8_t *kgen_token = NULL;
-+ struct mipv6_mh_addr_test addr_test;
-+ struct mipv6_rr_nonce *nonce;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ret = 0;
-+
-+ DEBUG_FUNC();
-+
-+ if ((nonce = mipv6_rr_get_new_nonce())== NULL) {
-+ DEBUG(DBG_WARNING, "Nonce creation failed");
-+ return 0;
-+ }
-+ if (mipv6_rr_cookie_create(daddr, &kgen_token, nonce->index)) {
-+ DEBUG(DBG_WARNING, "No cookie");
-+ return 0;
-+ }
-+
-+ addr_test.nonce_index = nonce->index;
-+ memcpy(addr_test.init_cookie, init->init_cookie,
-+ MIPV6_RR_COOKIE_LENGTH);
-+ memcpy(addr_test.kgen_token, kgen_token,
-+ MIPV6_RR_COOKIE_LENGTH);
-+
-+ /* No options defined */
-+ ret = send_mh(daddr, saddr, msg_type, sizeof(addr_test),
-+ (u8 *)&addr_test, NULL, NULL, ops, NULL);
-+
-+ if (ret == 0) {
-+ if (msg_type == MIPV6_MH_HOT) {
-+ MIPV6_INC_STATS(n_hot_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_cot_sent);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void bc_cache_add(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ __u8 ba_status = SUCCESS;
-+
-+ if (lifetime > MAX_RR_BINDING_LIFE)
-+ lifetime = MAX_RR_BINDING_LIFE;
-+
-+ if (mipv6_bcache_add(ifindex, daddr, haddr, coa, lifetime,
-+ sequence, flags, CACHE_ENTRY) != 0) {
-+ DEBUG(DBG_ERROR, "binding failed.");
-+ ba_status = INSUFFICIENT_RESOURCES;
-+ }
-+
-+ if (flags & MIPV6_BU_F_ACK) {
-+ DEBUG(DBG_INFO, "sending ack (code=%d)", ba_status);
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, ba_status, sequence,
-+ lifetime, k_bu);
-+ }
-+}
-+
-+static void bc_cn_home_add(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *haddr, struct in6_addr *coa,
-+ struct in6_addr *rep_coa, __u32 lifetime,
-+ __u16 sequence, __u8 flags, __u8 *k_bu)
-+{
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa,
-+ HOME_REGISTRATION_NOT_SUPPORTED,
-+ sequence, lifetime, k_bu);
-+}
-+
-+static void bc_cache_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+ __u8 status = SUCCESS;
-+
-+ /* Cached Care-of Address Deregistration */
-+ if (mipv6_bcache_exists(haddr, daddr) == CACHE_ENTRY) {
-+ mipv6_bcache_delete(haddr, daddr, CACHE_ENTRY);
-+ } else {
-+ DEBUG(DBG_INFO, "entry is not in cache");
-+ status = REASON_UNSPECIFIED;
-+ }
-+ if (flags & MIPV6_BU_F_ACK) {
-+ mipv6_send_ba(daddr, haddr, coa, rep_coa, status, sequence,
-+ 0, k_bu);
-+ }
-+}
-+
-+static void bc_cn_home_delete(struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 sequence, __u8 flags,
-+ __u8 *k_bu)
-+{
-+}
-+
-+/**
-+ * parse_mo_tlv - Parse TLV-encoded Mobility Options
-+ * @mos: pointer to Mobility Options
-+ * @len: total length of options
-+ * @opts: structure to store option pointers
-+ *
-+ * Parses Mobility Options passed in @mos. Stores pointers in @opts
-+ * to all valid mobility options found in @mos. Unknown options and
-+ * padding (%MIPV6_OPT_PAD1 and %MIPV6_OPT_PADN) is ignored and
-+ * skipped.
-+ **/
-+int parse_mo_tlv(void *mos, int len, struct mobopt *opts)
-+{
-+ struct mipv6_mo *curr = (struct mipv6_mo *)mos;
-+ int left = len;
-+
-+ while (left > 0) {
-+ int optlen = 0;
-+ if (curr->type == MIPV6_OPT_PAD1)
-+ optlen = 1;
-+ else
-+ optlen = 2 + curr->length;
-+
-+ if (optlen > left)
-+ goto bad;
-+
-+ switch (curr->type) {
-+ case MIPV6_OPT_PAD1:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PAD1 at %x", curr);
-+ break;
-+ case MIPV6_OPT_PADN:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_PADN at %x", curr);
-+ break;
-+ case MIPV6_OPT_ALTERNATE_COA:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_ACOA at %x", curr);
-+ opts->alt_coa = (struct mipv6_mo_alt_coa *)curr;
-+ break;
-+ case MIPV6_OPT_NONCE_INDICES:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_NONCE_INDICES at %x", curr);
-+ opts->nonce_indices =
-+ (struct mipv6_mo_nonce_indices *)curr;
-+ break;
-+ case MIPV6_OPT_AUTH_DATA:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_AUTH_DATA at %x", curr);
-+ opts->auth_data = (struct mipv6_mo_bauth_data *)curr;
-+ break;
-+ case MIPV6_OPT_BIND_REFRESH_ADVICE:
-+ DEBUG(DBG_DATADUMP, "MIPV6_OPT_BIND_REFRESH_ADVICE at %x", curr);
-+ opts->br_advice = (struct mipv6_mo_br_advice *)curr;
-+ break;
-+ default:
-+ DEBUG(DBG_INFO, "MO Unknown option type %d at %x, ignoring.",
-+ curr->type, curr);
-+ /* unknown mobility option, ignore and skip */
-+ }
-+
-+ (u8 *)curr += optlen;
-+ left -= optlen;
-+ }
-+
-+ if (left == 0)
-+ return 0;
-+ bad:
-+ return -1;
-+}
-+
-+/*
-+ *
-+ * Mobility Header Message handlers
-+ *
-+ */
-+
-+static int mipv6_handle_mh_testinit(struct sk_buff *skb,
-+ struct in6_addr *cn,
-+ struct in6_addr *lcoa,
-+ struct in6_addr *saddr,
-+ struct in6_addr *fcoa,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_addr_ti *ti = (struct mipv6_mh_addr_ti *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*ti);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than H/C TestInit");
-+ return -1;
-+ }
-+ if (!mip6node_cnf.accept_ret_rout) {
-+ DEBUG(DBG_INFO, "Return routability administratively disabled");
-+ return -1;
-+ }
-+ if (lcoa || fcoa) {
-+ DEBUG(DBG_INFO, "H/C TestInit has HAO or RTH2, dropped.");
-+ return -1;
-+ }
-+
-+ if (mh->type == MIPV6_MH_HOTI) {
-+ MIPV6_INC_STATS(n_hoti_rcvd);
-+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_HOT, ti);
-+ } else if (mh->type == MIPV6_MH_COTI) {
-+ MIPV6_INC_STATS(n_coti_rcvd);
-+ return mipv6_send_addr_test(cn, saddr, MIPV6_MH_COT, ti);
-+ } else
-+ return -1; /* Impossible to get here */
-+}
-+
-+/**
-+ * mipv6_handle_mh_bu - Binding Update handler
-+ * @src: care-of address of sender
-+ * @dst: our address
-+ * @haddr: home address of sender
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ * Handles Binding Update. Packet and offset to option are passed.
-+ * Returns 0 on success, otherwise negative.
-+ **/
-+static int mipv6_handle_mh_bu(struct sk_buff *skb,
-+ struct in6_addr *dst,
-+ struct in6_addr *unused,
-+ struct in6_addr *haddr,
-+ struct in6_addr *coaddr,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_bu *bu = (struct mipv6_mh_bu *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ int auth = 0;
-+ int dereg; /* Is this deregistration? */
-+ int addr_type;
-+
-+ struct mipv6_bce bc_entry;
-+ struct in6_addr *coa, *reply_coa;
-+ __u8 *key_bu = NULL; /* RR BU authentication key */
-+ __u8 flags = bu->flags;
-+ __u16 sequence;
-+ __u32 lifetime;
-+ __u16 nonce_ind = (__u16) -1;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*bu);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than BU");
-+ MIPV6_INC_STATS(n_bu_drop.invalid);
-+ return -1;
-+ }
-+
-+ addr_type = ipv6_addr_type(haddr);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL || !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+
-+ /* If HAO not present, CoA == HAddr */
-+ if (coaddr == NULL)
-+ coa = haddr;
-+ else {
-+ coa = coaddr;
-+ addr_type = ipv6_addr_type(coa);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+ }
-+ reply_coa = coa;
-+
-+ sequence = ntohs(bu->sequence);
-+ if (bu->lifetime == 0xffff)
-+ lifetime = 0xffffffff;
-+ else
-+ lifetime = ntohs(bu->lifetime) << 2;
-+
-+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
-+
-+ if (opt_len > 0) {
-+ struct mobopt opts;
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(bu + 1, opt_len, &opts) < 0) {
-+ MIPV6_INC_STATS(n_bu_drop.invalid);
-+ return -1;
-+ }
-+ /*
-+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_NONCE_INDICES,
-+ * MIPV6_OPT_ALT_COA
-+ */
-+ if (opts.alt_coa) {
-+ coa = &opts.alt_coa->addr;
-+ dereg = (ipv6_addr_cmp(haddr, coa) == 0 || lifetime == 0);
-+ }
-+ addr_type = ipv6_addr_type(coa);
-+ if (addr_type&IPV6_ADDR_LINKLOCAL ||
-+ !(addr_type&IPV6_ADDR_UNICAST))
-+ return -EINVAL;
-+
-+ if (flags & MIPV6_BU_F_HOME) {
-+ if (opts.nonce_indices)
-+ return -1;
-+ } else {
-+ u8 ba_status = 0;
-+ u8 *h_ckie = NULL, *c_ckie = NULL; /* Home and care-of cookies */
-+
-+ /* BUs to CN MUST include authorization data and nonce indices options */
-+ if (!opts.auth_data || !opts.nonce_indices) {
-+ DEBUG(DBG_WARNING,
-+ "Route optimization BU without authorization material, aborting processing");
-+ return MH_AUTH_FAILED;
-+ }
-+ if (mipv6_rr_cookie_create(
-+ haddr, &h_ckie, opts.nonce_indices->home_nonce_i) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "mipv6_rr_cookie_create failed for home cookie");
-+ ba_status = EXPIRED_HOME_NONCE_INDEX;
-+ }
-+ nonce_ind = opts.nonce_indices->home_nonce_i;
-+ /* Don't create the care-of cookie, if MN deregisters */
-+ if (!dereg && mipv6_rr_cookie_create(
-+ coa, &c_ckie,
-+ opts.nonce_indices->careof_nonce_i) < 0) {
-+ DEBUG(DBG_WARNING,
-+ "mipv6_rr_cookie_create failed for coa cookie");
-+ if (ba_status == 0)
-+ ba_status = EXPIRED_CAREOF_NONCE_INDEX;
-+ else
-+ ba_status = EXPIRED_NONCES;
-+ }
-+ if (ba_status == 0) {
-+ if (dereg)
-+ key_bu = mipv6_rr_key_calc(h_ckie, NULL);
-+ else
-+ key_bu = mipv6_rr_key_calc(h_ckie, c_ckie);
-+ mh->checksum = 0;/* TODO: Don't mangle the packet */
-+ if (key_bu && mipv6_auth_check(
-+ dst, coa, (__u8 *)mh, msg_len + sizeof(*mh), opts.auth_data, key_bu) == 0) {
-+ DEBUG(DBG_INFO, "mipv6_auth_check OK for BU");
-+ auth = 1;
-+ } else {
-+ DEBUG(DBG_WARNING,
-+ "BU Authentication failed");
-+ }
-+ }
-+ if (h_ckie)
-+ kfree(h_ckie);
-+ if (c_ckie)
-+ kfree(c_ckie);
-+ if (ba_status != 0) {
-+ MIPV6_INC_STATS(n_bu_drop.auth);
-+ mipv6_send_ba(dst, haddr, coa,
-+ reply_coa, ba_status,
-+ sequence, 0, NULL);
-+ goto out;
-+ }
-+ }
-+
-+ }
-+ /* Require authorization option for RO, home reg is protected by IPsec */
-+ if (!(flags & MIPV6_BU_F_HOME) && !auth) {
-+ MIPV6_INC_STATS(n_bu_drop.auth);
-+ if (key_bu)
-+ kfree(key_bu);
-+ return MH_AUTH_FAILED;
-+ }
-+
-+ if (mipv6_bcache_get(haddr, dst, &bc_entry) == 0) {
-+ if ((bc_entry.flags&MIPV6_BU_F_HOME) !=
-+ (flags&MIPV6_BU_F_HOME)) {
-+ DEBUG(DBG_INFO,
-+ "Registration type change. Sending BA REG_TYPE_CHANGE_FORBIDDEN");
-+ mipv6_send_ba(dst, haddr, coa, reply_coa,
-+ REG_TYPE_CHANGE_FORBIDDEN,
-+ sequence, lifetime, key_bu);
-+ goto out;
-+ }
-+ if (!MIPV6_SEQ_GT(sequence, bc_entry.seq)) {
-+ DEBUG(DBG_INFO,
-+ "Sequence number mismatch. Sending BA SEQUENCE_NUMBER_OUT_OF_WINDOW");
-+ mipv6_send_ba(dst, haddr, coa, reply_coa,
-+ SEQUENCE_NUMBER_OUT_OF_WINDOW,
-+ bc_entry.seq, lifetime, key_bu);
-+ goto out;
-+ }
-+ }
-+
-+ if (!dereg) {
-+ int ifindex;
-+ struct rt6_info *rt;
-+
-+ /* Avoid looping binding cache entries */
-+ if (mipv6_bcache_get(coa, dst, &bc_entry) == 0) {
-+ DEBUG(DBG_WARNING, "Looped BU, dropping the packet");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "calling bu_add.");
-+ if ((rt = rt6_lookup(haddr, dst, 0, 0)) != NULL) {
-+ ifindex = rt->rt6i_dev->ifindex;
-+ dst_release(&rt->u.dst);
-+ } else {
-+ /*
-+ * Can't process the BU since the right interface is
-+ * not found.
-+ */
-+ DEBUG(DBG_WARNING, "No route entry found for handling "
-+ "a BU request, (using 0 as index)");
-+ ifindex = 0;
-+ }
-+ if (flags & MIPV6_BU_F_HOME)
-+ mip6_fn.bce_home_add(ifindex, dst, haddr, coa,
-+ reply_coa, lifetime, sequence,
-+ flags, key_bu);
-+ else
-+ mip6_fn.bce_cache_add(ifindex, dst, haddr, coa,
-+ reply_coa, lifetime, sequence,
-+ flags, key_bu);
-+ } else {
-+ DEBUG(DBG_INFO, "calling BCE delete.");
-+
-+ if (flags & MIPV6_BU_F_HOME)
-+ mip6_fn.bce_home_del(dst, haddr, coa, reply_coa,
-+ sequence, flags, key_bu);
-+ else {
-+ mipv6_rr_invalidate_nonce(nonce_ind);
-+ mip6_fn.bce_cache_del(dst, haddr, coa, reply_coa,
-+ sequence, flags, key_bu);
-+ }
-+ }
-+ out:
-+ MIPV6_INC_STATS(n_bu_rcvd);
-+ if (key_bu)
-+ kfree(key_bu);
-+ return 0;
-+}
-+
-+static int mipv6_mh_rcv(struct sk_buff *skb)
-+{
-+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-+ struct mipv6_mh *mh;
-+ struct in6_addr *lhome, *fhome, *lcoa = NULL, *fcoa = NULL;
-+ int ret = 0;
-+
-+ fhome = &skb->nh.ipv6h->saddr;
-+ lhome = &skb->nh.ipv6h->daddr;
-+
-+ if (opt->hao != 0) {
-+ struct mipv6_dstopt_homeaddr *hao;
-+ hao = (struct mipv6_dstopt_homeaddr *)(skb->nh.raw + opt->hao);
-+ fcoa = &hao->addr;
-+ }
-+
-+ if (opt->srcrt2 != 0) {
-+ struct rt2_hdr *rt2;
-+ rt2 = (struct rt2_hdr *)((u8 *)skb->nh.raw + opt->srcrt2);
-+ lcoa = &rt2->addr;
-+ }
-+
-+ /* Verify checksum is correct */
-+ if (skb->ip_summed == CHECKSUM_HW) {
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
-+ skb->csum)) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "MIPv6 MH hw checksum failed\n");
-+ skb->ip_summed = CHECKSUM_NONE;
-+ }
-+ }
-+ if (skb->ip_summed == CHECKSUM_NONE) {
-+ if (csum_ipv6_magic(fhome, lhome, skb->len, IPPROTO_MOBILITY,
-+ skb_checksum(skb, 0, skb->len, 0))) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "MIPv6 MH checksum failed\n");
-+ goto bad;
-+ }
-+ }
-+
-+ if (!pskb_may_pull(skb, skb->h.raw-skb->data+sizeof(*mh)) ||
-+ !pskb_may_pull(skb,
-+ skb->h.raw-skb->data+((skb->h.raw[1]+1)<<3))) {
-+ DEBUG(DBG_INFO, "MIPv6 MH invalid length");
-+ kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ mh = (struct mipv6_mh *) skb->h.raw;
-+
-+ /* Verify there are no more headers after the MH */
-+ if (mh->payload != NEXTHDR_NONE) {
-+ __u32 pos = (__u32)&mh->payload - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "MIPv6 MH error");
-+ goto bad;
-+ }
-+
-+ if (mh->type > MIPV6_MH_MAX) {
-+ /* send binding error */
-+ printk("Invalid mobility header type (%d)\n", mh->type);
-+ mipv6_send_be(lhome, fcoa ? fcoa : fhome,
-+ fcoa ? fhome : NULL,
-+ MIPV6_BE_UNKNOWN_MH_TYPE);
-+ goto bad;
-+ }
-+ if (mh_rcv[mh->type].func != NULL) {
-+ ret = mh_rcv[mh->type].func(skb, lhome, lcoa, fhome, fcoa, mh);
-+ } else {
-+ DEBUG(DBG_INFO, "No handler for MH Type %d", mh->type);
-+ goto bad;
-+ }
-+
-+ kfree_skb(skb);
-+ return 0;
-+
-+bad:
-+ MIPV6_INC_STATS(n_mh_in_error);
-+ kfree_skb(skb);
-+ return 0;
-+
-+}
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+struct inet6_protocol mipv6_mh_protocol =
-+{
-+ mipv6_mh_rcv, /* handler */
-+ NULL /* error control */
-+};
-+#else
-+struct inet6_protocol mipv6_mh_protocol =
-+{
-+ mipv6_mh_rcv, /* handler */
-+ NULL, /* error control */
-+ NULL, /* next */
-+ IPPROTO_MOBILITY, /* protocol ID */
-+ 0, /* copy */
-+ NULL, /* data */
-+ "MIPv6 MH" /* name */
-+};
-+#endif
-+
-+/*
-+ *
-+ * Code module init/exit functions
-+ *
-+ */
-+
-+int __init mipv6_mh_common_init(void)
-+{
-+ struct sock *sk;
-+ int err;
-+
-+ mip6_fn.bce_home_add = bc_cn_home_add;
-+ mip6_fn.bce_cache_add = bc_cache_add;
-+ mip6_fn.bce_home_del = bc_cn_home_delete;
-+ mip6_fn.bce_cache_del = bc_cache_delete;
-+
-+ mipv6_mh_socket = sock_alloc();
-+ if (mipv6_mh_socket == NULL) {
-+ printk(KERN_ERR
-+ "Failed to create the MIP6 MH control socket.\n");
-+ return -1;
-+ }
-+ mipv6_mh_socket->type = SOCK_RAW;
-+
-+ if ((err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_MOBILITY,
-+ &mipv6_mh_socket)) < 0) {
-+ printk(KERN_ERR
-+ "Failed to initialize the MIP6 MH control socket (err %d).\n",
-+ err);
-+ sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL; /* for safety */
-+ return err;
-+ }
-+
-+ sk = mipv6_mh_socket->sk;
-+ sk->allocation = GFP_ATOMIC;
-+ sk->sndbuf = 64 * 1024 + sizeof(struct sk_buff);
-+ sk->prot->unhash(sk);
-+
-+ memset(&mh_rcv, 0, sizeof(mh_rcv));
-+ mh_rcv[MIPV6_MH_HOTI].func = mipv6_handle_mh_testinit;
-+ mh_rcv[MIPV6_MH_COTI].func = mipv6_handle_mh_testinit;
-+ mh_rcv[MIPV6_MH_BU].func = mipv6_handle_mh_bu;
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+ if (inet6_add_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY) < 0) {
-+ printk(KERN_ERR "Failed to register MOBILITY protocol\n");
-+ sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL;
-+ return -EAGAIN;
-+ }
-+#else
-+ inet6_add_protocol(&mipv6_mh_protocol);
-+#endif
-+ /* To disable the use of dst_cache,
-+ * which slows down the sending of BUs ??
-+ */
-+ sk->dst_cache=NULL;
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mh_common_exit(void)
-+{
-+ if (mipv6_mh_socket) sock_release(mipv6_mh_socket);
-+ mipv6_mh_socket = NULL; /* For safety. */
-+
-+#if LINUX_VERSION_CODE >= 0x2052a
-+ inet6_del_protocol(&mipv6_mh_protocol, IPPROTO_MOBILITY);
-+#else
-+ inet6_del_protocol(&mipv6_mh_protocol);
-+#endif
-+ memset(&mh_rcv, 0, sizeof(mh_rcv));
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/mobhdr_mn.c
-@@ -0,0 +1,1155 @@
-+/*
-+ * Mobile IPv6 Mobility Header Functions for Mobile Node
-+ *
-+ * Authors:
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ * Niklas Kämpe <nhkampe@cc.hut.fi>
-+ * Henrik Petander <henrik.petander@hut.fi>
-+ *
-+ * $Id:$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/types.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "mobhdr.h"
-+#include "mn.h"
-+#include "bul.h"
-+#include "rr_crypto.h"
-+#include "debug.h"
-+#include "util.h"
-+#include "stats.h"
-+
-+int rr_configured = 1;
-+
-+/* Return value of mipv6_rr_state() */
-+#define NO_RR 0
-+#define DO_RR 1
-+#define RR_FOR_COA 2
-+#define INPROGRESS_RR 3
-+
-+/**
-+ * send_bu_msg - sends a Binding Update
-+ * @bulentry : BUL entry with the information for building a BU
-+ *
-+ * Function builds a BU msg based on the contents of a bul entry.
-+ * Does not change the bul entry.
-+ **/
-+static int send_bu_msg(struct mipv6_bul_entry *binding)
-+{
-+ int auth = 0; /* Use auth */
-+ int ret = 0;
-+ struct mipv6_auth_parm parm;
-+ struct mipv6_mh_bu bu;
-+
-+ if (!binding) {
-+ DEBUG(DBG_ERROR, "called with a null bul entry");
-+ return -1;
-+ }
-+
-+ memset(&parm, 0, sizeof(parm));
-+ if (mipv6_prefix_compare(&binding->coa, &binding->home_addr, 64))
-+ parm.coa = &binding->home_addr;
-+ else
-+ parm.coa = &binding->coa;
-+ parm.cn_addr = &binding->cn_addr;
-+
-+ if (binding->rr && binding->rr->kbu) {
-+ DEBUG(DBG_INFO, "Binding with key");
-+ auth = 1;
-+ parm.k_bu = binding->rr->kbu;
-+ }
-+ memset(&bu, 0, sizeof(bu));
-+ bu.flags = binding->flags;
-+ bu.sequence = htons(binding->seq);
-+ bu.lifetime = htons(binding->lifetime >> 2);
-+ bu.reserved = 0;
-+
-+ ret = send_mh(&binding->cn_addr, &binding->home_addr,
-+ MIPV6_MH_BU, sizeof(bu), (u8 *)&bu,
-+ &binding->home_addr, NULL,
-+ binding->ops, &parm);
-+
-+ if (ret == 0)
-+ MIPV6_INC_STATS(n_bu_sent);
-+
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_send_addr_test_init - send a HoTI or CoTI message
-+ * @saddr: source address for H/CoTI
-+ * @daddr: destination address for H/CoTI
-+ * @msg_type: Identifies whether HoTI or CoTI
-+ * @init_cookie: the HoTi or CoTi init cookie
-+ *
-+ * The message will be retransmitted till we get a HoT or CoT message, since
-+ * our caller (mipv6_RR_start) has entered this message in the BUL with
-+ * exponential backoff retramission set.
-+ */
-+static int mipv6_send_addr_test_init(struct in6_addr *saddr,
-+ struct in6_addr *daddr,
-+ u8 msg_type,
-+ u8 *init_cookie)
-+{
-+ struct mipv6_mh_addr_ti ti;
-+ struct mipv6_mh_opt *ops = NULL;
-+ int ret = 0;
-+
-+ /* Set reserved and copy the cookie from address test init msg */
-+ ti.reserved = 0;
-+ mipv6_rr_mn_cookie_create(init_cookie);
-+ memcpy(ti.init_cookie, init_cookie, MIPV6_RR_COOKIE_LENGTH);
-+
-+ ret = send_mh(daddr, saddr, msg_type, sizeof(ti), (u8 *)&ti,
-+ NULL, NULL, ops, NULL);
-+ if (ret == 0) {
-+ if (msg_type == MIPV6_MH_HOTI) {
-+ MIPV6_INC_STATS(n_hoti_sent);
-+ } else {
-+ MIPV6_INC_STATS(n_coti_sent);
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ *
-+ * Callback handlers for binding update list
-+ *
-+ */
-+
-+/* Return value 0 means keep entry, non-zero means discard entry. */
-+
-+/* Callback for BUs not requiring acknowledgement
-+ */
-+int bul_entry_expired(struct mipv6_bul_entry *bulentry)
-+{
-+ /* Lifetime expired, delete entry. */
-+ DEBUG(DBG_INFO, "bul entry 0x%p lifetime expired, deleting entry",
-+ bulentry);
-+ return 1;
-+}
-+
-+/* Callback for BUs requiring acknowledgement with exponential resending
-+ * scheme */
-+static int bul_resend_exp(struct mipv6_bul_entry *bulentry)
-+{
-+ unsigned long now = jiffies;
-+
-+ DEBUG(DBG_INFO, "(0x%x) resending bu", (int) bulentry);
-+
-+
-+ /* If sending a de-registration, do not care about the
-+ * lifetime value, as de-registrations are normally sent with
-+ * a zero lifetime value. If the entry is a home entry get the
-+ * current lifetime.
-+ */
-+
-+ if (bulentry->lifetime != 0) {
-+ bulentry->lifetime = mipv6_mn_get_bulifetime(
-+ &bulentry->home_addr, &bulentry->coa, bulentry->flags);
-+
-+ bulentry->expire = now + bulentry->lifetime * HZ;
-+ } else {
-+ bulentry->expire = now + HOME_RESEND_EXPIRE * HZ;
-+ }
-+ if (bulentry->rr) {
-+ /* Redo RR, if cookies have expired */
-+ if (time_after(jiffies, bulentry->rr->home_time + MAX_TOKEN_LIFE * HZ))
-+ bulentry->rr->rr_state |= RR_WAITH;
-+ if (time_after(jiffies, bulentry->rr->careof_time + MAX_NONCE_LIFE * HZ))
-+ bulentry->rr->rr_state |= RR_WAITC;
-+
-+ if (bulentry->rr->rr_state & RR_WAITH) {
-+ /* Resend HoTI directly */
-+ mipv6_send_addr_test_init(&bulentry->home_addr,
-+ &bulentry->cn_addr, MIPV6_MH_HOTI,
-+ bulentry->rr->hot_cookie);
-+ }
-+ if (bulentry->rr->rr_state & RR_WAITC) {
-+ /* Resend CoTI directly */
-+ mipv6_send_addr_test_init(&bulentry->coa,
-+ &bulentry->cn_addr, MIPV6_MH_COTI,
-+ bulentry->rr->cot_cookie);
-+ }
-+ goto out;
-+ }
-+
-+ bulentry->seq++;
-+
-+ if (send_bu_msg(bulentry) < 0)
-+ DEBUG(DBG_ERROR, "Resending of BU failed");
-+
-+out:
-+ /* Schedule next retransmission */
-+ if (bulentry->delay < bulentry->maxdelay) {
-+ bulentry->delay = 2 * bulentry->delay;
-+ if (bulentry->delay > bulentry->maxdelay) {
-+ /* can happen if maxdelay is not power(mindelay, 2) */
-+ bulentry->delay = bulentry->maxdelay;
-+ }
-+ } else if (bulentry->flags & MIPV6_BU_F_HOME) {
-+ /* Home registration - continue sending BU at maxdelay rate */
-+ DEBUG(DBG_INFO, "Sending BU to HA after max ack wait time "
-+ "reached(0x%x)", (int) bulentry);
-+ bulentry->delay = bulentry->maxdelay;
-+ } else if (!(bulentry->flags & MIPV6_BU_F_HOME)) {
-+ /* Failed to get BA from a CN */
-+ bulentry->callback_time = now;
-+ return -1;
-+ }
-+
-+ bulentry->callback_time = now + bulentry->delay * HZ;
-+ return 0;
-+}
-+
-+
-+
-+/* Callback for sending a registration refresh BU
-+ */
-+static int bul_refresh(struct mipv6_bul_entry *bulentry)
-+{
-+ unsigned long now = jiffies;
-+
-+ /* Refresh interval passed, send new BU */
-+ DEBUG(DBG_INFO, "bul entry 0x%x refresh interval passed, sending new BU", (int) bulentry);
-+ if (bulentry->lifetime == 0)
-+ return 0;
-+
-+ /* Set new maximum lifetime and expiration time */
-+ bulentry->lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr,
-+ &bulentry->coa,
-+ bulentry->flags);
-+ bulentry->expire = now + bulentry->lifetime * HZ;
-+ bulentry->seq++;
-+ /* Send update */
-+ if (send_bu_msg(bulentry) < 0)
-+ DEBUG(DBG_ERROR, "Resending of BU failed");
-+
-+ if (time_after_eq(now, bulentry->expire)) {
-+ /* Sanity check */
-+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs", ERROR_DEF_LIFETIME);
-+ bulentry->lifetime = ERROR_DEF_LIFETIME;
-+ bulentry->expire = now + ERROR_DEF_LIFETIME*HZ;
-+ }
-+
-+ /* Set up retransmission */
-+ bulentry->state = RESEND_EXP;
-+ bulentry->callback = bul_resend_exp;
-+ bulentry->callback_time = now + INITIAL_BINDACK_TIMEOUT*HZ;
-+ bulentry->delay = INITIAL_BINDACK_TIMEOUT;
-+ bulentry->maxdelay = MAX_BINDACK_TIMEOUT;
-+
-+ return 0;
-+}
-+
-+static int mipv6_send_RR_bu(struct mipv6_bul_entry *bulentry)
-+{
-+ int ret;
-+ int ops_len = 0;
-+ u16 nonces[2];
-+
-+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x "
-+ "for home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(&bulentry->cn_addr), NIPV6ADDR(&bulentry->home_addr));
-+ nonces[0] = bulentry->rr->home_nonce_index;
-+ nonces[1] = bulentry->rr->careof_nonce_index;
-+ ops_len = sizeof(struct mipv6_mo_bauth_data) + MIPV6_RR_MAC_LENGTH +
-+ sizeof(struct mipv6_mo_nonce_indices);
-+ if (bulentry->ops) {
-+ DEBUG(DBG_WARNING, "Bul entry had existing mobility options, freeing them");
-+ kfree(bulentry->ops);
-+ }
-+ bulentry->ops = alloc_mh_opts(ops_len);
-+
-+ if (!bulentry->ops)
-+ return -ENOMEM;
-+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_NONCE_INDICES,
-+ sizeof(struct mipv6_mo_nonce_indices) - 2, nonces) < 0)
-+ return -ENOMEM;
-+
-+ if (append_mh_opt(bulentry->ops, MIPV6_OPT_AUTH_DATA,
-+ MIPV6_RR_MAC_LENGTH, NULL) < 0)
-+ return -ENOMEM;
-+ /* RR procedure is over, send a BU */
-+ if (!(bulentry->flags & MIPV6_BU_F_ACK)) {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired");
-+ bulentry->state = ACK_OK;
-+ bulentry->callback = bul_entry_expired;
-+ bulentry->callback_time = jiffies + HZ * bulentry->lifetime;
-+ bulentry->expire = jiffies + HZ * bulentry->lifetime;
-+ }
-+ else {
-+ bulentry->callback_time = jiffies + HZ;
-+ bulentry->expire = jiffies + HZ * bulentry->lifetime;
-+ }
-+
-+ ret = send_bu_msg(bulentry);
-+ mipv6_bul_reschedule(bulentry);
-+ return ret;
-+}
-+
-+static int mipv6_rr_state(struct mipv6_bul_entry *bul, struct in6_addr *saddr,
-+ struct in6_addr *coa, __u8 flags)
-+{
-+ if (!rr_configured)
-+ return NO_RR;
-+ if (flags & MIPV6_BU_F_HOME) {
-+ /* We don't need RR, this is a Home Registration */
-+ return NO_RR;
-+ }
-+ if (!bul || !bul->rr) {
-+ /* First time BU to CN, need RR */
-+ return DO_RR;
-+ }
-+
-+ switch (bul->rr->rr_state) {
-+ case RR_INIT:
-+ /* Need RR if first BU to CN */
-+ return DO_RR;
-+ case RR_DONE:
-+ /* If MN moves to a new coa, do RR for it */
-+ if (!ipv6_addr_cmp(&bul->coa, coa))
-+ return NO_RR;
-+ else
-+ return DO_RR;
-+ default:
-+ /*
-+ * We are in the middle of RR, the HoTI and CoTI have been
-+ * sent. But we haven't got HoT and CoT from the CN, so
-+ * don't do anything more at this time.
-+ */
-+ return INPROGRESS_RR;
-+ }
-+}
-+
-+/**
-+ * mipv6_RR_start - Start Return Routability procedure
-+ * @home_addr: home address
-+ * @cn_addr: correspondent address
-+ * @coa: care-of address
-+ * @entry: binding update list entry (if any)
-+ * @initdelay: initial ack timeout
-+ * @maxackdelay: maximum ack timeout
-+ * @flags: flags
-+ * @lifetime: lifetime of binding
-+ * @ops: mobility options
-+ *
-+ * Caller must hold @bul_lock (write).
-+ **/
-+static int mipv6_RR_start(struct in6_addr *home_addr, struct in6_addr *cn_addr,
-+ struct in6_addr *coa, struct mipv6_bul_entry *entry,
-+ __u32 initdelay, __u32 maxackdelay, __u8 flags,
-+ __u32 lifetime, struct mipv6_mh_opt *ops)
-+{
-+ int ret = -1;
-+ struct mipv6_bul_entry *bulentry = entry;
-+ struct mipv6_rr_info *rr = NULL;
-+ int seq = 0;
-+ DEBUG_FUNC();
-+
-+ /* Do RR procedure only for care-of address after handoff,
-+ if home cookie is still valid */
-+ if (bulentry && bulentry->rr) {
-+ if (time_before(jiffies, bulentry->rr->home_time + MAX_NONCE_LIFE * HZ) &&
-+ lifetime && !(ipv6_addr_cmp(home_addr, coa) == 0)) {
-+ mipv6_rr_mn_cookie_create(bulentry->rr->cot_cookie);
-+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for CoA");
-+ ipv6_addr_copy(&bulentry->coa, coa);
-+ bulentry->rr->rr_state |= RR_WAITC;
-+ } else if (!lifetime) { /* Send only HoTi when returning home */
-+ mipv6_rr_mn_cookie_create(bulentry->rr->hot_cookie);
-+ DEBUG(DBG_INFO, "Bul entry and rr info exist, only doing RR for HoA");
-+ ipv6_addr_copy(&bulentry->coa, coa); /* Home address as CoA */
-+ bulentry->rr->rr_state |= RR_WAITH;
-+ }
-+ } else {
-+ DEBUG(DBG_INFO, "Doing RR for both HoA and CoA");
-+ rr = kmalloc(sizeof(*rr), GFP_ATOMIC);
-+ memset(rr, 0, sizeof(*rr));
-+ rr->rr_state = RR_WAITHC;
-+ }
-+ if (bulentry) {
-+ if (bulentry->state == ACK_ERROR)
-+ goto out;
-+ seq = bulentry->seq + 1;
-+ } else
-+ seq = 0;
-+ /* Save the info in the BUL to retransmit the BU after RR is done */
-+ /* Caller must hold bul_lock (write) since we don't */
-+
-+ if ((bulentry = mipv6_bul_add(cn_addr, home_addr, coa,
-+ min_t(__u32, lifetime, MAX_RR_BINDING_LIFE),
-+ seq, flags, bul_resend_exp, initdelay,
-+ RESEND_EXP, initdelay,
-+ maxackdelay, ops,
-+ rr)) == NULL) {
-+ DEBUG(DBG_INFO, "couldn't update BUL for HoTi");
-+ goto out;
-+ }
-+
-+ rr = bulentry->rr;
-+ if (rr->rr_state&RR_WAITH)
-+ mipv6_send_addr_test_init(home_addr, cn_addr, MIPV6_MH_HOTI,
-+ rr->hot_cookie);
-+ if (ipv6_addr_cmp(home_addr, coa) && lifetime)
-+ mipv6_send_addr_test_init(coa, cn_addr, MIPV6_MH_COTI, rr->cot_cookie);
-+ else {
-+ bulentry->rr->rr_state &= ~RR_WAITC;
-+ }
-+ ret = 0;
-+out:
-+ return ret;
-+}
-+
-+/*
-+ * Status codes for mipv6_ba_rcvd()
-+ */
-+#define STATUS_UPDATE 0
-+#define STATUS_REMOVE 1
-+
-+/**
-+ * mipv6_ba_rcvd - Update BUL for this Binding Acknowledgement
-+ * @ifindex: interface BA came from
-+ * @cnaddr: sender IPv6 address
-+ * @home_addr: home address
-+ * @sequence: sequence number
-+ * @lifetime: lifetime granted by Home Agent in seconds
-+ * @refresh: recommended resend interval
-+ * @status: %STATUS_UPDATE (ack) or %STATUS_REMOVE (nack)
-+ *
-+ * This function must be called to notify the module of the receipt of
-+ * a binding acknowledgement so that it can cease retransmitting the
-+ * option. The caller must have validated the acknowledgement before calling
-+ * this function. 'status' can be either STATUS_UPDATE in which case the
-+ * binding acknowledgement is assumed to be valid and the corresponding
-+ * binding update list entry is updated, or STATUS_REMOVE in which case
-+ * the corresponding binding update list entry is removed (this can be
-+ * used upon receiving a negative acknowledgement).
-+ * Returns 0 if a matching binding update has been sent or non-zero if
-+ * not.
-+ */
-+static int mipv6_ba_rcvd(int ifindex, struct in6_addr *cnaddr,
-+ struct in6_addr *home_addr,
-+ u16 sequence, u32 lifetime,
-+ u32 refresh, int status)
-+{
-+ struct mipv6_bul_entry *bulentry;
-+ unsigned long now = jiffies;
-+ struct in6_addr coa;
-+
-+ DEBUG(DBG_INFO, "BA received with sequence number 0x%x, status: %d",
-+ (int) sequence, status);
-+
-+ /* Find corresponding entry in binding update list. */
-+ write_lock(&bul_lock);
-+ if ((bulentry = mipv6_bul_get(cnaddr, home_addr)) == NULL) {
-+ DEBUG(DBG_INFO, "- discarded, no entry in bul matches BA source address");
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+
-+ ipv6_addr_copy(&coa, &bulentry->coa);
-+ if (status == SEQUENCE_NUMBER_OUT_OF_WINDOW) {
-+ __u32 lifetime = mipv6_mn_get_bulifetime(&bulentry->home_addr,
-+ &bulentry->coa,
-+ bulentry->flags);
-+ bulentry->seq = sequence;
-+
-+ mipv6_send_bu(&bulentry->home_addr, &bulentry->cn_addr,
-+ &bulentry->coa, INITIAL_BINDACK_TIMEOUT,
-+ MAX_BINDACK_TIMEOUT, 1, bulentry->flags,
-+ lifetime, NULL);
-+ write_unlock(&bul_lock);
-+ return 0;
-+ } else if (status >= REASON_UNSPECIFIED) {
-+ int err;
-+ int at_home = MN_NOT_AT_HOME;
-+ DEBUG(DBG_WARNING, "- NACK - BA status: %d, deleting bul entry", status);
-+ if (bulentry->flags & MIPV6_BU_F_HOME) {
-+ struct mn_info *minfo;
-+ read_lock(&mn_info_lock);
-+ minfo = mipv6_mninfo_get_by_home(home_addr);
-+ if (minfo) {
-+ spin_lock(&minfo->lock);
-+ if (minfo->is_at_home != MN_NOT_AT_HOME)
-+ minfo->is_at_home = MN_AT_HOME;
-+ at_home = minfo->is_at_home;
-+ minfo->has_home_reg = 0;
-+ spin_unlock(&minfo->lock);
-+ }
-+ read_unlock(&mn_info_lock);
-+ DEBUG(DBG_ERROR, "Home registration failed: BA status: %d, deleting bul entry", status);
-+ }
-+ write_unlock(&bul_lock);
-+ err = mipv6_bul_delete(cnaddr, home_addr);
-+ if (at_home == MN_AT_HOME) {
-+ mipv6_mn_send_home_na(home_addr);
-+ write_lock_bh(&bul_lock);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ write_unlock_bh(&bul_lock);
-+ }
-+ return err;
-+ }
-+ bulentry->state = ACK_OK;
-+
-+ if (bulentry->flags & MIPV6_BU_F_HOME && lifetime > 0) {
-+ /* For home registrations: schedule a refresh binding update.
-+ * Use the refresh interval given by home agent or 80%
-+ * of lifetime, whichever is less.
-+ *
-+ * Adjust binding lifetime if 'granted' lifetime
-+ * (lifetime value in received binding acknowledgement)
-+ * is shorter than 'requested' lifetime (lifetime
-+ * value sent in corresponding binding update).
-+ * max((L_remain - (L_update - L_ack)), 0)
-+ */
-+ if (lifetime * HZ < (bulentry->expire - bulentry->lastsend)) {
-+ bulentry->expire =
-+ max_t(__u32, bulentry->expire -
-+ ((bulentry->expire - bulentry->lastsend) -
-+ lifetime * HZ), jiffies +
-+ ERROR_DEF_LIFETIME * HZ);
-+ }
-+ if (refresh > lifetime || refresh == 0)
-+ refresh = 4 * lifetime / 5;
-+ DEBUG(DBG_INFO, "setting callback for expiration of"
-+ " a Home Registration: lifetime:%d, refresh:%d",
-+ lifetime, refresh);
-+ bulentry->callback = bul_refresh;
-+ bulentry->callback_time = now + refresh * HZ;
-+ bulentry->expire = now + lifetime * HZ;
-+ bulentry->lifetime = lifetime;
-+ if (time_after_eq(jiffies, bulentry->expire)) {
-+ /* Sanity check */
-+ DEBUG(DBG_ERROR, "bul entry expire time in history - setting expire to %u secs",
-+ ERROR_DEF_LIFETIME);
-+ bulentry->expire = jiffies + ERROR_DEF_LIFETIME * HZ;
-+ }
-+ mipv6_mn_set_home_reg(home_addr, 1);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ } else if ((bulentry->flags & MIPV6_BU_F_HOME) && bulentry->lifetime == 0) {
-+ write_unlock(&bul_lock);
-+ DEBUG(DBG_INFO, "Got BA for deregistration BU");
-+ mipv6_mn_set_home_reg(home_addr, 0);
-+ mipv6_bul_delete(cnaddr, home_addr);
-+ mipv6_mn_send_home_na(home_addr);
-+
-+ write_lock_bh(&bul_lock);
-+ mipv6_bul_iterate(mn_cn_handoff, &coa);
-+ write_unlock_bh(&bul_lock);
-+ return 0;
-+ }
-+
-+ mipv6_bul_reschedule(bulentry);
-+ write_unlock(&bul_lock);
-+
-+ return 0;
-+}
-+
-+static int mipv6_handle_mh_HC_test(struct sk_buff *skb,
-+ struct in6_addr *saddr,
-+ struct in6_addr *fcoa,
-+ struct in6_addr *cn,
-+ struct in6_addr *lcoa,
-+ struct mipv6_mh *mh)
-+{
-+ int ret = 0;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ struct mipv6_mh_addr_test *tm = (struct mipv6_mh_addr_test *)mh->data;
-+ struct mipv6_bul_entry *bulentry;
-+
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*tm);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_INFO, "Mobility Header length less than H/C Test");
-+ return -1;
-+ }
-+ if (fcoa || lcoa) {
-+ DEBUG(DBG_INFO, "H/C Test has HAO or RTH2, dropped.");
-+ return -1;
-+ }
-+ write_lock(&bul_lock);
-+
-+ /* We need to get the home address, since CoT only has the CoA*/
-+ if (mh->type == MIPV6_MH_COT) {
-+ if ((bulentry = mipv6_bul_get_by_ccookie(cn, tm->init_cookie)) == NULL) {
-+ DEBUG(DBG_ERROR, "has no BUL or RR state for "
-+ "source:%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(cn));
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ } else { /* HoT has the home address */
-+ if (((bulentry = mipv6_bul_get(cn, saddr)) == NULL) || !bulentry->rr) {
-+ DEBUG(DBG_ERROR, "has no BUL or RR state for "
-+ "source:%x:%x:%x:%x:%x:%x:%x:%x "
-+ "dest:%x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(cn), NIPV6ADDR(saddr));
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ }
-+
-+ switch (mh->type) {
-+ case MIPV6_MH_HOT:
-+ if ((bulentry->rr->rr_state & RR_WAITH) == 0) {
-+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message");
-+ goto out;
-+ }
-+ /*
-+ * Make sure no home cookies have been received yet.
-+ * TODO: Check not being put in at this time since subsequent
-+ * BU's after this time will have home cookie stored.
-+ */
-+
-+ /* Check if the cookie received is the right one */
-+ if (!mipv6_equal_cookies(tm->init_cookie,
-+ bulentry->rr->hot_cookie)) {
-+ /* Invalid cookie, might be an old cookie */
-+ DEBUG(DBG_WARNING, "Received HoT cookie does not match stored cookie");
-+ goto out;
-+ }
-+ DEBUG(DBG_INFO, "Got Care-of Test message");
-+ bulentry->rr->rr_state &= ~RR_WAITH;
-+ memcpy(bulentry->rr->home_cookie, tm->kgen_token, MIPV6_COOKIE_LEN);
-+ bulentry->rr->home_nonce_index = tm->nonce_index;
-+ bulentry->rr->home_time = jiffies;
-+ ret = 1;
-+ break;
-+
-+ case MIPV6_MH_COT:
-+ if ((bulentry->rr->rr_state & RR_WAITC) == 0) {
-+ DEBUG(DBG_ERROR, "Not waiting for a Home Test message");
-+ goto out;
-+ }
-+ /*
-+ * Make sure no home cookies have been received yet.
-+ * TODO: Check not being put in at this time since subsequent
-+ * BU's at this time will have careof cookie stored.
-+ */
-+
-+ /* Check if the cookie received is the right one */
-+ if (!mipv6_equal_cookies(tm->init_cookie,
-+ bulentry->rr->cot_cookie)) {
-+ DEBUG(DBG_INFO, "Received CoT cookie does not match stored cookie");
-+ goto out;
-+ }
-+ bulentry->rr->rr_state &= ~RR_WAITC;
-+ memcpy(bulentry->rr->careof_cookie, tm->kgen_token, MIPV6_COOKIE_LEN);
-+ bulentry->rr->careof_nonce_index = tm->nonce_index;
-+ bulentry->rr->careof_time = jiffies;
-+ ret = 1;
-+ break;
-+ default:
-+ /* Impossible to get here */
-+ break;
-+ }
-+out:
-+ if (bulentry->rr->rr_state == RR_DONE) {
-+ if (bulentry->rr->kbu) /* First free any old keys */
-+ kfree(bulentry->rr->kbu);
-+ /* Store the session key to be used in BU's */
-+ if (ipv6_addr_cmp(&bulentry->coa, &bulentry->home_addr) && bulentry->lifetime)
-+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie,
-+ bulentry->rr->careof_cookie);
-+ else
-+ bulentry->rr->kbu = mipv6_rr_key_calc(bulentry->rr->home_cookie,
-+ NULL);
-+ /* RR procedure is over, send a BU */
-+ mipv6_send_RR_bu(bulentry);
-+ }
-+ write_unlock(&bul_lock);
-+ return ret;
-+}
-+
-+/**
-+ * mipv6_handle_mh_brr - Binding Refresh Request handler
-+ * @home: home address
-+ * @coa: care-of address
-+ * @cn: source of this packet
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ * Handles Binding Refresh Request. Packet and offset to option are
-+ * passed. Returns 0 on success, otherwise negative.
-+ **/
-+static int mipv6_handle_mh_brr(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *unused1,
-+ struct in6_addr *cn,
-+ struct in6_addr *unused2,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_brr *brr = (struct mipv6_mh_brr *)mh->data;
-+ struct mipv6_bul_entry *binding;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*brr);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BRR");
-+ MIPV6_INC_STATS(n_brr_drop.invalid);
-+ return -1;
-+ }
-+
-+ /* check we know src, else drop */
-+ write_lock(&bul_lock);
-+ if ((binding = mipv6_bul_get(cn, home)) == NULL) {
-+ MIPV6_INC_STATS(n_brr_drop.misc);
-+ write_unlock(&bul_lock);
-+ return MH_UNKNOWN_CN;
-+ }
-+
-+ MIPV6_INC_STATS(n_brr_rcvd);
-+
-+ if (opt_len > 0) {
-+ struct mobopt opts;
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(brr + 1, opt_len, &opts) < 0) {
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+ /*
-+ * MIPV6_OPT_AUTH_DATA
-+ */
-+ }
-+
-+ /* must hold bul_lock (write) */
-+ mipv6_RR_start(home, cn, &binding->coa, binding, binding->delay,
-+ binding->maxdelay, binding->flags,
-+ binding->lifetime, binding->ops);
-+
-+ write_unlock(&bul_lock);
-+ /* MAY also decide to delete binding and send zero lifetime BU
-+ with alt-coa set to home address */
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_handle_mh_ba - Binding Acknowledgement handler
-+ * @src: source of this packet
-+ * @coa: care-of address
-+ * @home: home address
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ **/
-+static int mipv6_handle_mh_ba(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *coa,
-+ struct in6_addr *src,
-+ struct in6_addr *unused,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_ba *ba = (struct mipv6_mh_ba *)mh->data;
-+ struct mipv6_bul_entry *binding = NULL;
-+ struct mobopt opts;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+
-+ int auth = 1, req_auth = 1, refresh = -1, ifindex = 0;
-+ u32 lifetime, sequence;
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*ba);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BA");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ return -1;
-+ }
-+
-+ lifetime = ntohs(ba->lifetime) << 2;
-+ sequence = ntohs(ba->sequence);
-+
-+ if (opt_len > 0) {
-+ memset(&opts, 0, sizeof(opts));
-+ if (parse_mo_tlv(ba + 1, opt_len, &opts) < 0)
-+ return -1;
-+ /*
-+ * MIPV6_OPT_AUTH_DATA, MIPV6_OPT_BR_ADVICE
-+ */
-+ if (opts.br_advice)
-+ refresh = ntohs(opts.br_advice->refresh_interval);
-+ }
-+
-+ if (ba->status >= EXPIRED_HOME_NONCE_INDEX &&
-+ ba->status <= EXPIRED_NONCES)
-+ req_auth = 0;
-+
-+ write_lock(&bul_lock);
-+ binding = mipv6_bul_get(src, home);
-+ if (!binding) {
-+ DEBUG(DBG_INFO, "No binding, BA dropped.");
-+ write_unlock(&bul_lock);
-+ return -1;
-+ }
-+
-+ if (opts.auth_data && binding->rr &&
-+ (mipv6_auth_check(src, coa, (__u8 *)mh, msg_len,
-+ opts.auth_data, binding->rr->kbu) == 0))
-+ auth = 1;
-+
-+ if (req_auth && binding->rr && !auth) {
-+ DEBUG(DBG_INFO, "BA Authentication failed.");
-+ MIPV6_INC_STATS(n_ba_drop.auth);
-+ write_unlock(&bul_lock);
-+ return MH_AUTH_FAILED;
-+ }
-+
-+ if (ba->status == SEQUENCE_NUMBER_OUT_OF_WINDOW) {
-+ DEBUG(DBG_INFO,
-+ "Sequence number out of window, setting seq to %d",
-+ sequence);
-+ } else if (binding->seq != sequence) {
-+ DEBUG(DBG_INFO, "BU/BA Sequence Number mismatch %d != %d",
-+ binding->seq, sequence);
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ write_unlock(&bul_lock);
-+ return MH_SEQUENCE_MISMATCH;
-+ }
-+ if (ba->status == EXPIRED_HOME_NONCE_INDEX || ba->status == EXPIRED_NONCES) {
-+ if (binding->rr) {
-+ /* Need to resend home test init to CN */
-+ binding->rr->rr_state |= RR_WAITH;
-+ mipv6_send_addr_test_init(&binding->home_addr,
-+ &binding->cn_addr,
-+ MIPV6_MH_HOTI,
-+ binding->rr->hot_cookie);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ } else {
-+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_NONCE_INDEX"
-+ "for non-RR BU");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ }
-+ write_unlock(&bul_lock);
-+ return 0;
-+ }
-+ if (ba->status == EXPIRED_CAREOF_NONCE_INDEX || ba->status == EXPIRED_NONCES) {
-+ if (binding->rr) {
-+ /* Need to resend care-of test init to CN */
-+ binding->rr->rr_state |= RR_WAITC;
-+ mipv6_send_addr_test_init(&binding->coa,
-+ &binding->cn_addr,
-+ MIPV6_MH_COTI,
-+ binding->rr->cot_cookie);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ } else {
-+ DEBUG(DBG_WARNING, "Got BA with status EXPIRED_HOME_CAREOF_INDEX"
-+ "for non-RR BU");
-+ MIPV6_INC_STATS(n_ba_drop.invalid);
-+ }
-+ write_unlock(&bul_lock);
-+ return 0;
-+ }
-+ write_unlock(&bul_lock);
-+
-+ if (ba->status >= REASON_UNSPECIFIED) {
-+ DEBUG(DBG_INFO, "Binding Ack status : %d indicates error", ba->status);
-+ mipv6_ba_rcvd(ifindex, src, home, sequence, lifetime,
-+ refresh, ba->status);
-+ MIPV6_INC_STATS(n_ban_rcvd);
-+ return 0;
-+ }
-+ MIPV6_INC_STATS(n_ba_rcvd);
-+ if (mipv6_ba_rcvd(ifindex, src, home, ntohs(ba->sequence), lifetime,
-+ refresh, ba->status)) {
-+ DEBUG(DBG_WARNING, "mipv6_ba_rcvd failed");
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_handle_mh_be - Binding Error handler
-+ * @cn: source of this packet
-+ * @coa: care-of address
-+ * @home: home address
-+ * @mh: pointer to the beginning of the Mobility Header
-+ *
-+ **/
-+
-+static int mipv6_handle_mh_be(struct sk_buff *skb,
-+ struct in6_addr *home,
-+ struct in6_addr *coa,
-+ struct in6_addr *cn,
-+ struct in6_addr *unused,
-+ struct mipv6_mh *mh)
-+{
-+ struct mipv6_mh_be *be = (struct mipv6_mh_be *)mh->data;
-+ int msg_len = (mh->length+1) << 3;
-+ int opt_len;
-+ struct in6_addr *hoa;
-+ struct bul_inval_args args;
-+
-+ DEBUG_FUNC();
-+
-+ if (msg_len > skb->len)
-+ return -1;
-+
-+ opt_len = msg_len - sizeof(*mh) - sizeof(*be);
-+
-+ if (opt_len < 0) {
-+ __u32 pos = (__u32)&mh->length - (__u32)skb->nh.raw;
-+ icmpv6_send(skb, ICMPV6_PARAMPROB,
-+ ICMPV6_HDR_FIELD, pos, skb->dev);
-+
-+ DEBUG(DBG_WARNING, "Mobility Header length less than BE");
-+ MIPV6_INC_STATS(n_be_drop.invalid);
-+ return -1;
-+ }
-+
-+
-+ if (!ipv6_addr_any(&be->home_addr))
-+ hoa = &be->home_addr;
-+ else
-+ hoa = home;
-+
-+ MIPV6_INC_STATS(n_be_rcvd);
-+
-+ args.all_rr_states = 0;
-+ args.cn = cn;
-+ args.mn = hoa;
-+
-+ switch (be->status) {
-+ case 1: /* Home Address Option used without a binding */
-+ /* Get ULP information about CN-MN communication. If
-+ nothing in progress, MUST delete. Otherwise MAY
-+ ignore. */
-+ args.all_rr_states = 1;
-+ case 2: /* Received unknown MH type */
-+ /* If not expecting ack, SHOULD ignore. If MH
-+ extension in use, stop it. If not, stop RO for
-+ this CN. */
-+ write_lock(&bul_lock);
-+ mipv6_bul_iterate(mn_bul_invalidate, &args);
-+ write_unlock(&bul_lock);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * mipv6_bu_rate_limit() : Takes a bulentry, a COA and 'flags' to check
-+ * whether BU being sent is for Home Registration or not.
-+ *
-+ * If the number of BU's sent is fewer than MAX_FAST_UPDATES, this BU
-+ * is allowed to be sent at the MAX_UPDATE_RATE.
-+ * If the number of BU's sent is greater than or equal to MAX_FAST_UPDATES,
-+ * this BU is allowed to be sent at the SLOW_UPDATE_RATE.
-+ *
-+ * Assumption : This function is not re-entrant. and the caller holds the
-+ * bulentry lock (by calling mipv6_bul_get()) to stop races with other
-+ * CPU's executing this same function.
-+ *
-+ * Side-Effects. Either of the following could on success :
-+ * 1. Sets consecutive_sends to 1 if the entry is a Home agent
-+ * registration or the COA has changed.
-+ * 2. Increments consecutive_sends if the number of BU's sent so
-+ * far is less than MAX_FAST_UPDATES, and this BU is being sent
-+ * atleast MAX_UPDATE_RATE after previous one.
-+ *
-+ * Return Value : 0 on Success, -1 on Failure
-+ */
-+static int mipv6_bu_rate_limit(struct mipv6_bul_entry *bulentry,
-+ struct in6_addr *coa, __u8 flags)
-+{
-+ if ((flags & MIPV6_BU_F_HOME) || ipv6_addr_cmp(&bulentry->coa, coa)) {
-+ /* Home Agent Registration or different COA - restart from 1 */
-+ bulentry->consecutive_sends = 1;
-+ return 0;
-+ }
-+
-+ if (bulentry->consecutive_sends < MAX_FAST_UPDATES) {
-+ /* First MAX_FAST_UPDATES can be sent at MAX_UPDATE_RATE */
-+ if (jiffies - bulentry->lastsend < MAX_UPDATE_RATE * HZ) {
-+ return -1;
-+ }
-+ bulentry->consecutive_sends ++;
-+ } else {
-+ /* Remaining updates SHOULD be sent at SLOW_UPDATE_RATE */
-+ if (jiffies - bulentry->lastsend < SLOW_UPDATE_RATE * HZ) {
-+ return -1;
-+ }
-+ /* Don't inc 'consecutive_sends' to avoid overflow to zero */
-+ }
-+ /* OK to send a BU */
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_send_bu - send a Binding Update
-+ * @saddr: source address for BU
-+ * @daddr: destination address for BU
-+ * @coa: care-of address for MN
-+ * @initdelay: initial BA wait timeout
-+ * @maxackdelay: maximum BA wait timeout
-+ * @exp: exponention back off
-+ * @flags: flags for BU
-+ * @lifetime: granted lifetime for binding
-+ * @ops: mobility options
-+ *
-+ * Send a binding update. 'flags' may contain any of %MIPV6_BU_F_ACK,
-+ * %MIPV6_BU_F_HOME, %MIPV6_BU_F_ROUTER bitwise ORed. If
-+ * %MIPV6_BU_F_ACK is included retransmission will be attempted until
-+ * the update has been acknowledged. Retransmission is done if no
-+ * acknowledgement is received within @initdelay seconds. @exp
-+ * specifies whether to use exponential backoff (@exp != 0) or linear
-+ * backoff (@exp == 0). For exponential backoff the time to wait for
-+ * an acknowledgement is doubled on each retransmission until a delay
-+ * of @maxackdelay, after which retransmission is no longer attempted.
-+ * For linear backoff the delay is kept constant and @maxackdelay
-+ * specifies the maximum number of retransmissions instead. If
-+ * sub-options are present ops must contain all sub-options to be
-+ * added. On a mobile node, use the mobile node's home address for
-+ * @saddr. Returns 0 on success, non-zero on failure.
-+ *
-+ * Caller may not hold @bul_lock.
-+ **/
-+int mipv6_send_bu(struct in6_addr *saddr, struct in6_addr *daddr,
-+ struct in6_addr *coa, u32 initdelay,
-+ u32 maxackdelay, u8 exp, u8 flags, u32 lifetime,
-+ struct mipv6_mh_opt *ops)
-+{
-+ int ret;
-+ __u8 state;
-+ __u16 seq = 0;
-+ int (*callback)(struct mipv6_bul_entry *);
-+ __u32 callback_time;
-+ struct mipv6_bul_entry *bulentry;
-+
-+ /* First a sanity check: don't send BU to local addresses */
-+ if(ipv6_chk_addr(daddr, NULL)) {
-+ DEBUG(DBG_ERROR, "BUG: Trying to send BU to local address");
-+ return -1;
-+ }
-+ DEBUG(DBG_INFO, "Sending BU to CN %x:%x:%x:%x:%x:%x:%x:%x "
-+ "for home address %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(daddr), NIPV6ADDR(saddr));
-+
-+ if ((bulentry = mipv6_bul_get(daddr, saddr)) != NULL) {
-+ if (bulentry->state == ACK_ERROR) {
-+ /*
-+ * Don't send any more BU's to nodes which don't
-+ * understanding one.
-+ */
-+ DEBUG(DBG_INFO, "Not sending BU to node which doesn't"
-+ " understand one");
-+ return -1;
-+ }
-+ if (mipv6_bu_rate_limit(bulentry, coa, flags) < 0) {
-+ DEBUG(DBG_DATADUMP, "Limiting BU sent.");
-+ return 0;
-+ }
-+ }
-+
-+ switch (mipv6_rr_state(bulentry, saddr, coa, flags)) {
-+ case INPROGRESS_RR:
-+ /* We are already doing RR, don't do BU at this time, it is
-+ * done automatically later */
-+ DEBUG(DBG_INFO, "RR in progress not sending BU");
-+ return 0;
-+
-+ case DO_RR:
-+ /* Just do RR and return, BU is done automatically later */
-+ DEBUG(DBG_INFO, "starting RR" );
-+ mipv6_RR_start(saddr, daddr, coa, bulentry, initdelay,
-+ maxackdelay, flags, lifetime, ops);
-+ return 0;
-+
-+ case NO_RR:
-+ DEBUG(DBG_DATADUMP, "No RR necessary" );
-+ default:
-+ break;
-+ }
-+
-+ if (bulentry)
-+ seq = bulentry->seq + 1;
-+
-+ /* Add to binding update list */
-+
-+ if (flags & MIPV6_BU_F_ACK) {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_resend_exp");
-+ /* Send using exponential backoff */
-+ state = RESEND_EXP;
-+ callback = bul_resend_exp;
-+ callback_time = initdelay;
-+ } else {
-+ DEBUG(DBG_INFO, "Setting bul callback to bul_entry_expired");
-+ /* No acknowledgement/resending required */
-+ state = ACK_OK; /* pretend we got an ack */
-+ callback = bul_entry_expired;
-+ callback_time = lifetime;
-+ }
-+
-+ /* BU only for the home address */
-+ /* We must hold bul_lock (write) while calling add */
-+ if ((bulentry = mipv6_bul_add(daddr, saddr, coa, lifetime, seq,
-+ flags, callback, callback_time,
-+ state, initdelay, maxackdelay, ops,
-+ NULL)) == NULL) {
-+ DEBUG(DBG_INFO, "couldn't update BUL");
-+ return 0;
-+ }
-+ ret = send_bu_msg(bulentry);
-+
-+ return ret;
-+}
-+
-+int __init mipv6_mh_mn_init(void)
-+{
-+ mipv6_mh_register(MIPV6_MH_HOT, mipv6_handle_mh_HC_test);
-+ mipv6_mh_register(MIPV6_MH_COT, mipv6_handle_mh_HC_test);
-+ mipv6_mh_register(MIPV6_MH_BA, mipv6_handle_mh_ba);
-+ mipv6_mh_register(MIPV6_MH_BRR, mipv6_handle_mh_brr);
-+ mipv6_mh_register(MIPV6_MH_BE, mipv6_handle_mh_be);
-+
-+ return 0;
-+}
-+
-+void __exit mipv6_mh_mn_exit(void)
-+{
-+ mipv6_mh_unregister(MIPV6_MH_HOT);
-+ mipv6_mh_unregister(MIPV6_MH_COT);
-+ mipv6_mh_unregister(MIPV6_MH_BA);
-+ mipv6_mh_unregister(MIPV6_MH_BRR);
-+ mipv6_mh_unregister(MIPV6_MH_BE);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/module_cn.c
-@@ -0,0 +1,167 @@
-+/*
-+ * Mobile IPv6 Common Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+
-+#include "bcache.h"
-+#include "mipv6_icmp.h"
-+#include "stats.h"
-+#include "mobhdr.h"
-+#include "exthdrs.h"
-+
-+int mipv6_debug = 1;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(mipv6_debug, "i");
-+#endif
-+
-+#include "config.h"
-+
-+struct mip6_func mip6_fn;
-+struct mip6_conf mip6node_cnf = {
-+ capabilities: CAP_CN,
-+ accept_ret_rout: 1,
-+ max_rtr_reachable_time: 0,
-+ eager_cell_switching: 0,
-+ max_num_tunnels: 0,
-+ min_num_tunnels: 0,
-+ binding_refresh_advice: 0,
-+ bu_lladdr: 0,
-+ bu_keymgm: 0,
-+ bu_cn_ack: 0
-+};
-+
-+#define MIPV6_BCACHE_SIZE 128
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 CN Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_DEBUG, "debuglevel",
-+ &mipv6_debug, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {NET_IPV6_MOBILITY_RETROUT, "accept_return_routability",
-+ &mip6node_cnf.accept_ret_rout, sizeof(int), 0644, NULL,
-+ &proc_dointvec},
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+extern void mipv6_rr_init(void);
-+
-+/* Initialize the module */
-+static int __init mip6_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Correspondent Node %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+ if ((err = mipv6_bcache_init(MIPV6_BCACHE_SIZE)) < 0)
-+ goto bcache_fail;
-+
-+ if ((err = mipv6_icmpv6_init()) < 0)
-+ goto icmp_fail;
-+
-+ if ((err = mipv6_stats_init()) < 0)
-+ goto stats_fail;
-+ mipv6_rr_init();
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+
-+ if ((err = mipv6_mh_common_init()) < 0)
-+ goto mh_fail;
-+
-+ MIPV6_SETCALL(mipv6_modify_txoptions, mipv6_modify_txoptions);
-+
-+ MIPV6_SETCALL(mipv6_handle_homeaddr, mipv6_handle_homeaddr);
-+ MIPV6_SETCALL(mipv6_icmp_swap_addrs, mipv6_icmp_swap_addrs);
-+
-+ return 0;
-+
-+mh_fail:
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ mipv6_stats_exit();
-+stats_fail:
-+ mipv6_icmpv6_exit();
-+icmp_fail:
-+ mipv6_bcache_exit();
-+bcache_fail:
-+ return err;
-+}
-+module_init(mip6_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_exit(void)
-+{
-+ printk(KERN_INFO "mip6_base.o exiting.\n");
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+
-+ /* Invalidate all custom kernel hooks. No need to do this
-+ separately for all hooks. */
-+ mipv6_invalidate_calls();
-+
-+ mipv6_mh_common_exit();
-+ mipv6_stats_exit();
-+ mipv6_icmpv6_exit();
-+ mipv6_bcache_exit();
-+}
-+module_exit(mip6_exit);
-+#endif /* MODULE */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/module_ha.c
-@@ -0,0 +1,264 @@
-+/*
-+ * Mobile IPv6 Home Agent Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+#include <net/addrconf.h>
-+
-+#include "mobhdr.h"
-+#include "tunnel_ha.h"
-+#include "ha.h"
-+#include "halist.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+#include "bcache.h"
-+#include "debug.h"
-+
-+int mipv6_use_auth = 0;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6 Home Agent");
-+MODULE_LICENSE("GPL");
-+#endif
-+
-+#include "config.h"
-+
-+#define MIPV6_HALIST_SIZE 128
-+struct ha_info_opt {
-+ u8 type;
-+ u8 len;
-+ u16 res;
-+ u16 pref;
-+ u16 ltime;
-+};
-+/*
-+ * Called from ndisc.c's router_discovery.
-+ */
-+static int mipv6_ha_ra_rcv(struct sk_buff *skb, struct ndisc_options *ndopts)
-+{
-+ unsigned int ha_info_pref = 0, ha_info_lifetime;
-+ int ifi = ((struct inet6_skb_parm *)skb->cb)->iif;
-+ struct ra_msg *ra = (struct ra_msg *) skb->h.raw;
-+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
-+ struct in6_addr ll_addr;
-+ struct hal {
-+ struct in6_addr prefix;
-+ int plen;
-+ struct hal *next;
-+ };
-+
-+ DEBUG_FUNC();
-+
-+ ha_info_lifetime = ntohs(ra->icmph.icmp6_rt_lifetime);
-+ ipv6_addr_copy(&ll_addr, saddr);
-+
-+ if (ndopts->nd_opts_hai) {
-+ struct ha_info_opt *hai = (struct ha_info_opt *)ndopts->nd_opts_hai;
-+ ha_info_pref = ntohs(hai->pref);
-+ ha_info_lifetime = ntohs(hai->ltime);
-+ DEBUG(DBG_DATADUMP,
-+ "received home agent info with preference : %d and lifetime : %d",
-+ ha_info_pref, ha_info_lifetime);
-+ }
-+ if (ndopts->nd_opts_pi) {
-+ struct nd_opt_hdr *p;
-+ for (p = ndopts->nd_opts_pi;
-+ p;
-+ p = ndisc_next_option(p, ndopts->nd_opts_pi_end)) {
-+ struct prefix_info *pinfo;
-+
-+ pinfo = (struct prefix_info *) p;
-+
-+ if (pinfo->router_address) {
-+ DEBUG(DBG_DATADUMP, "Adding router address to "
-+ "ha queue \n");
-+ /* If RA has H bit set and Prefix Info
-+ * Option R bit set, queue this
-+ * address to be added to Home Agents
-+ * List.
-+ */
-+ if (ipv6_addr_type(&pinfo->prefix) &
-+ IPV6_ADDR_LINKLOCAL)
-+ continue;
-+ if (!ra->icmph.icmp6_home_agent || !ha_info_lifetime) {
-+ mipv6_halist_delete(&pinfo->prefix);
-+ continue;
-+ } else {
-+
-+ mipv6_halist_add(ifi, &pinfo->prefix,
-+ pinfo->prefix_len, &ll_addr,
-+ ha_info_pref, ha_info_lifetime);
-+ }
-+
-+ }
-+
-+ }
-+ }
-+ return MIPV6_ADD_RTR;
-+}
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+extern int
-+mipv6_max_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+extern int
-+mipv6_min_tnls_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+int max_adv = ~(u16)0;
-+int min_zero = 0;
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_BINDING_REFRESH, "binding_refresh_advice",
-+ &mip6node_cnf.binding_refresh_advice, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_adv},
-+
-+ {NET_IPV6_MOBILITY_MAX_TNLS, "max_tnls", &mipv6_max_tnls, sizeof(int),
-+ 0644, NULL, &mipv6_max_tnls_sysctl},
-+ {NET_IPV6_MOBILITY_MIN_TNLS, "min_tnls", &mipv6_min_tnls, sizeof(int),
-+ 0644, NULL, &mipv6_min_tnls_sysctl},
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+extern void mipv6_check_dad(struct in6_addr *haddr);
-+extern void mipv6_dad_init(void);
-+extern void mipv6_dad_exit(void);
-+extern int mipv6_forward(struct sk_buff *);
-+
-+/* Initialize the module */
-+static int __init mip6_ha_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Home Agent %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+ mip6node_cnf.capabilities = CAP_CN | CAP_HA;
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_rcv_dhaad_req;
-+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_no_rcv;
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+ mipv6_initialize_tunnel();
-+
-+ if ((err = mipv6_ha_init()) < 0)
-+ goto ha_fail;
-+
-+ MIPV6_SETCALL(mipv6_ra_rcv, mipv6_ha_ra_rcv);
-+ MIPV6_SETCALL(mipv6_forward, mipv6_forward);
-+ mipv6_dad_init();
-+ MIPV6_SETCALL(mipv6_check_dad, mipv6_check_dad);
-+
-+ if ((err = mipv6_halist_init(MIPV6_HALIST_SIZE)) < 0)
-+ goto halist_fail;
-+
-+// mipv6_initialize_pfx_icmpv6();
-+
-+ return 0;
-+
-+halist_fail:
-+ mipv6_dad_exit();
-+ mipv6_ha_exit();
-+ha_fail:
-+ mipv6_shutdown_tunnel();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_forward);
-+ MIPV6_RESETCALL(mipv6_check_dad);
-+
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ return err;
-+}
-+module_init(mip6_ha_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_ha_exit(void)
-+{
-+ printk(KERN_INFO "mip6_ha.o exiting.\n");
-+ mip6node_cnf.capabilities &= ~(int)CAP_HA;
-+
-+ mipv6_bcache_cleanup(HOME_REGISTRATION);
-+
-+ MIPV6_RESETCALL(mipv6_ra_rcv);
-+ MIPV6_RESETCALL(mipv6_forward);
-+ MIPV6_RESETCALL(mipv6_check_dad);
-+
-+ mipv6_halist_exit();
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_dad_exit();
-+ mipv6_ha_exit();
-+ mipv6_shutdown_tunnel();
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+}
-+module_exit(mip6_ha_exit);
-+#endif /* MODULE */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/module_mn.c
-@@ -0,0 +1,188 @@
-+/*
-+ * Mobile IPv6 Mobile Node Module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Antti Tuominen <ajtuomin@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/mipglue.h>
-+
-+extern int mipv6_debug;
-+int mipv6_use_auth = 0;
-+
-+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-+MODULE_AUTHOR("MIPL Team");
-+MODULE_DESCRIPTION("Mobile IPv6 Mobile Node");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(mipv6_debug, "i");
-+#endif
-+
-+#include "config.h"
-+
-+#include "mobhdr.h"
-+#include "mn.h"
-+#include "mipv6_icmp.h"
-+//#include "prefix.h"
-+
-+/* TODO: These will go as soon as we get rid of the last two ioctls */
-+extern int mipv6_ioctl_mn_init(void);
-+extern void mipv6_ioctl_mn_exit(void);
-+
-+/**********************************************************************
-+ *
-+ * MIPv6 Module Init / Cleanup
-+ *
-+ **********************************************************************/
-+
-+#ifdef CONFIG_SYSCTL
-+/* Sysctl table */
-+
-+extern int max_rtr_reach_time;
-+extern int eager_cell_switching;
-+
-+static int max_reach = 1000;
-+static int min_reach = 1;
-+static int max_one = 1;
-+static int min_zero = 0;
-+
-+extern int
-+mipv6_mdetect_mech_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+extern int
-+mipv6_router_reach_sysctl(ctl_table *, int, struct file *, void *, size_t *);
-+
-+ctl_table mipv6_mobility_table[] = {
-+ {NET_IPV6_MOBILITY_BU_F_LLADDR, "bu_flag_lladdr",
-+ &mip6node_cnf.bu_lladdr, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+ {NET_IPV6_MOBILITY_BU_F_KEYMGM, "bu_flag_keymgm",
-+ &mip6node_cnf.bu_keymgm, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+ {NET_IPV6_MOBILITY_BU_F_CN_ACK, "bu_flag_cn_ack",
-+ &mip6node_cnf.bu_cn_ack, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+
-+ {NET_IPV6_MOBILITY_ROUTER_REACH, "max_router_reachable_time",
-+ &max_rtr_reach_time, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_reach, &max_reach},
-+
-+ {NET_IPV6_MOBILITY_MDETECT_MECHANISM, "eager_cell_switching",
-+ &eager_cell_switching, sizeof(int), 0644, NULL,
-+ &proc_dointvec_minmax, &sysctl_intvec, 0, &min_zero, &max_one},
-+
-+ {0}
-+};
-+ctl_table mipv6_table[] = {
-+ {NET_IPV6_MOBILITY, "mobility", NULL, 0, 0555, mipv6_mobility_table},
-+ {0}
-+};
-+
-+static struct ctl_table_header *mipv6_sysctl_header;
-+static struct ctl_table mipv6_net_table[];
-+static struct ctl_table mipv6_root_table[];
-+
-+ctl_table mipv6_net_table[] = {
-+ {NET_IPV6, "ipv6", NULL, 0, 0555, mipv6_table},
-+ {0}
-+};
-+
-+ctl_table mipv6_root_table[] = {
-+ {CTL_NET, "net", NULL, 0, 0555, mipv6_net_table},
-+ {0}
-+};
-+#endif /* CONFIG_SYSCTL */
-+
-+/* Initialize the module */
-+static int __init mip6_mn_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "MIPL Mobile IPv6 for Linux Mobile Node %s (%s)\n",
-+ MIPLVERSION, MIPV6VERSION);
-+ mip6node_cnf.capabilities = CAP_CN | CAP_MN;
-+
-+#ifdef CONFIG_IPV6_MOBILITY_DEBUG
-+ printk(KERN_INFO "Debug-level: %d\n", mipv6_debug);
-+#endif
-+
-+#ifdef CONFIG_SYSCTL
-+ mipv6_sysctl_header = register_sysctl_table(mipv6_root_table, 0);
-+#endif
-+ if ((err = mipv6_mn_init()) < 0)
-+ goto mn_fail;
-+
-+ mipv6_mh_mn_init();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = mipv6_icmpv6_rcv_dhaad_rep;
-+ mip6_fn.icmpv6_dhaad_req_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxadv_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_pfxsol_rcv = mipv6_icmpv6_no_rcv;
-+ mip6_fn.icmpv6_paramprob_rcv = mipv6_icmpv6_rcv_paramprob;
-+
-+// mipv6_initialize_pfx_icmpv6();
-+
-+ if ((err = mipv6_ioctl_mn_init()) < 0)
-+ goto ioctl_fail;
-+
-+ return 0;
-+
-+ioctl_fail:
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_mh_mn_exit();
-+ mipv6_mn_exit();
-+mn_fail:
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+ return err;
-+}
-+module_init(mip6_mn_init);
-+
-+#ifdef MODULE
-+/* Cleanup module */
-+static void __exit mip6_mn_exit(void)
-+{
-+ printk(KERN_INFO "mip6_mn.o exiting.\n");
-+ mip6node_cnf.capabilities &= ~(int)CAP_MN;
-+
-+ mipv6_ioctl_mn_exit();
-+// mipv6_shutdown_pfx_icmpv6();
-+
-+ mip6_fn.icmpv6_dhaad_rep_rcv = NULL;
-+ mip6_fn.icmpv6_dhaad_req_rcv = NULL;
-+ mip6_fn.icmpv6_pfxadv_rcv = NULL;
-+ mip6_fn.icmpv6_pfxsol_rcv = NULL;
-+ mip6_fn.icmpv6_paramprob_rcv = NULL;
-+
-+ mipv6_mn_exit();
-+
-+/* common cleanup */
-+#ifdef CONFIG_SYSCTL
-+ unregister_sysctl_table(mipv6_sysctl_header);
-+#endif
-+}
-+module_exit(mip6_mn_exit);
-+#endif /* MODULE */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/multiaccess_ctl.c
-@@ -0,0 +1,287 @@
-+/*
-+ * 2001 (c) Oy L M Ericsson Ab
-+ *
-+ * Author: NomadicLab / Ericsson Research <ipv6@nomadiclab.com>
-+ *
-+ * $Id$
-+ *
-+ */
-+
-+/*
-+ * Vertical hand-off information manager
-+ */
-+
-+#include <linux/netdevice.h>
-+#include <linux/in6.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <linux/list.h>
-+#include "multiaccess_ctl.h"
-+#include "debug.h"
-+
-+/*
-+ * Local variables
-+ */
-+static LIST_HEAD(if_list);
-+
-+/* Internal interface information list */
-+struct ma_if_info {
-+ struct list_head list;
-+ int interface_id;
-+ int preference;
-+ __u8 status;
-+};
-+
-+/**
-+ * ma_ctl_get_preference - get preference value for interface
-+ * @ifi: interface index
-+ *
-+ * Returns integer value preference for given interface.
-+ **/
-+int ma_ctl_get_preference(int ifi)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ int pref = 0;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == ifi) {
-+ pref = info->preference;
-+ return pref;
-+ }
-+ }
-+ return -1;
-+}
-+/**
-+ * ma_ctl_get_preference - get preference value for interface
-+ * @ifi: interface index
-+ *
-+ * Returns integer value interface index for interface with highest preference.
-+ **/
-+int ma_ctl_get_preferred_if(void)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info, *pref_if = NULL;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (!pref_if || (info->preference > pref_if->preference)) {
-+ pref_if = info;
-+ }
-+ }
-+ if (pref_if) return pref_if->interface_id;
-+ return 0;
-+}
-+/**
-+ * ma_ctl_set_preference - set preference for interface
-+ * @arg: ioctl args
-+ *
-+ * Sets preference of an existing interface (called by ioctl).
-+ **/
-+void ma_ctl_set_preference(unsigned long arg)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ struct ma_if_uinfo uinfo;
-+
-+ memset(&uinfo, 0, sizeof(struct ma_if_uinfo));
-+ if (copy_from_user(&uinfo, (struct ma_if_uinfo *)arg,
-+ sizeof(struct ma_if_uinfo)) < 0) {
-+ DEBUG(DBG_WARNING, "copy_from_user failed");
-+ return;
-+ }
-+
-+ /* check if the interface exists */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == uinfo.interface_id) {
-+ info->preference = uinfo.preference;
-+ return;
-+ }
-+ }
-+}
-+
-+/**
-+ * ma_ctl_add_iface - add new interface to list
-+ * @if_index: interface index
-+ *
-+ * Adds new interface entry to preference list. Preference is set to
-+ * the same value as @if_index. Entry @status is set to
-+ * %MA_IFACE_NOT_USED.
-+ **/
-+void ma_ctl_add_iface(int if_index)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+
-+ DEBUG_FUNC();
-+
-+ /* check if the interface already exists */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == if_index) {
-+ info->status = MA_IFACE_NOT_USED;
-+ info->preference = if_index;
-+ return;
-+ }
-+ }
-+
-+ info = kmalloc(sizeof(struct ma_if_info), GFP_ATOMIC);
-+ if (info == NULL) {
-+ DEBUG(DBG_ERROR, "Out of memory");
-+ return;
-+ }
-+ memset(info, 0, sizeof(struct ma_if_info));
-+ info->interface_id = if_index;
-+ info->preference = if_index;
-+ info->status = MA_IFACE_NOT_USED;
-+ list_add(&info->list, &if_list);
-+}
-+
-+/**
-+ * ma_ctl_del_iface - remove entry from the list
-+ * @if_index: interface index
-+ *
-+ * Removes entry for interface @if_index from preference list.
-+ **/
-+int ma_ctl_del_iface(int if_index)
-+{
-+ struct list_head *lh, *next;
-+ struct ma_if_info *info;
-+
-+ DEBUG_FUNC();
-+
-+ /* if the iface exists, change availability to 0 */
-+ list_for_each_safe(lh, next, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (info->interface_id == if_index) {
-+ list_del(&info->list);
-+ kfree(info);
-+ return 0;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+/**
-+ * ma_ctl_upd_iface - update entry (and list)
-+ * @if_index: interface to update
-+ * @status: new status for interface
-+ * @change_if_index: new interface
-+ *
-+ * Updates @if_index entry on preference list. Entry status is set to
-+ * @status. If new @status is %MA_IFACE_CURRENT, updates list to have
-+ * only one current device. If @status is %MA_IFACE_NOT_PRESENT,
-+ * entry is deleted and further if entry had %MA_IFACE_CURRENT set,
-+ * new current device is looked up and returned in @change_if_index.
-+ * New preferred interface is also returned if current device changes
-+ * to %MA_IFACE_NOT_USED. Returns 0 on success, otherwise negative.
-+ **/
-+int ma_ctl_upd_iface(int if_index, int status, int *change_if_index)
-+{
-+ struct list_head *lh, *tmp;
-+ struct ma_if_info *info, *pref = NULL;
-+ int found = 0;
-+
-+ DEBUG_FUNC();
-+
-+ *change_if_index = 0;
-+
-+ /* check if the interface exists */
-+ list_for_each_safe(lh, tmp, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (status == MA_IFACE_NOT_PRESENT) {
-+ if (info->interface_id == if_index) {
-+ list_del_init(&info->list);
-+ kfree(info);
-+ found = 1;
-+ break;
-+ }
-+ } else if (status == MA_IFACE_CURRENT) {
-+ if (info->interface_id == if_index) {
-+ info->status |= MA_IFACE_CURRENT;
-+ found = 1;
-+ } else {
-+ info->status |= MA_IFACE_NOT_USED;
-+ }
-+ } else if (status == MA_IFACE_NOT_USED) {
-+ if (info->interface_id == if_index) {
-+ if (info->status | MA_IFACE_CURRENT) {
-+ found = 1;
-+ }
-+ info->status &= !MA_IFACE_CURRENT;
-+ info->status |= MA_IFACE_NOT_USED;
-+ info->status &= !MA_IFACE_HAS_ROUTER;
-+ }
-+ break;
-+ } else if (status == MA_IFACE_HAS_ROUTER) {
-+ if (info->interface_id == if_index) {
-+ info->status |= MA_IFACE_HAS_ROUTER;
-+ }
-+ return 0;
-+ }
-+ }
-+
-+ if (status & (MA_IFACE_NOT_USED|MA_IFACE_NOT_PRESENT) && found) {
-+ /* select new interface */
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ if (pref == NULL || ((info->preference > pref->preference) &&
-+ info->status & MA_IFACE_HAS_ROUTER))
-+ pref = info;
-+ }
-+ if (pref) {
-+ *change_if_index = pref->interface_id;
-+ pref->status |= MA_IFACE_CURRENT;
-+ } else {
-+ *change_if_index = -1;
-+ }
-+ return 0;
-+ }
-+
-+ if (found) return 0;
-+
-+ return -1;
-+}
-+
-+static int if_proc_info(char *buffer, char **start, off_t offset,
-+ int length)
-+{
-+ struct list_head *lh;
-+ struct ma_if_info *info;
-+ int len = 0;
-+
-+ list_for_each(lh, &if_list) {
-+ info = list_entry(lh, struct ma_if_info, list);
-+ len += sprintf(buffer + len, "%02d %010d %1d %1d\n",
-+ info->interface_id, info->preference,
-+ !!(info->status & MA_IFACE_HAS_ROUTER),
-+ !!(info->status & MA_IFACE_CURRENT));
-+ }
-+
-+ *start = buffer + offset;
-+
-+ len -= offset;
-+
-+ if (len > length) len = length;
-+
-+ return len;
-+
-+}
-+
-+void ma_ctl_init(void)
-+{
-+ proc_net_create("mip6_iface", 0, if_proc_info);
-+}
-+
-+void ma_ctl_clean(void)
-+{
-+ proc_net_remove("mip6_iface");
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/multiaccess_ctl.h
-@@ -0,0 +1,77 @@
-+/*
-+ * 2001 (c) Oy L M Ericsson Ab
-+ *
-+ * Author: NomadicLab / Ericsson Research <ipv6@nomadiclab.com>
-+ *
-+ * $Id$
-+ *
-+ */
-+
-+#ifndef _MULTIACCESS_CTL_H
-+#define _MULTIACCESS_CTL_H
-+
-+/* status */
-+#define MA_IFACE_NOT_PRESENT 0x01
-+#define MA_IFACE_NOT_USED 0x02
-+#define MA_IFACE_HAS_ROUTER 0x04
-+#define MA_IFACE_CURRENT 0x10
-+
-+struct ma_if_uinfo {
-+ int interface_id;
-+ int preference;
-+ __u8 status;
-+};
-+/*
-+ * @ma_ctl_get_preferred_id: returns most preferred interface id
-+ */
-+int ma_ctl_get_preferred_if(void);
-+
-+/* @ma_ctl_get_preference: returns preference for an interface
-+ * @name: name of the interface (dev->name)
-+ */
-+int ma_ctl_get_preference(int ifi);
-+
-+/*
-+ * Public function: ma_ctl_set_preference
-+ * Description: Set preference of an existing interface (called by ioctl)
-+ * Returns:
-+ */
-+void ma_ctl_set_preference(unsigned long);
-+
-+/*
-+ * Public function: ma_ctl_add_iface
-+ * Description: Inform control module to insert a new interface
-+ * Returns: 0 if success, any other number means an error
-+ */
-+void ma_ctl_add_iface(int);
-+
-+/*
-+ * Public function: ma_ctl_del_iface
-+ * Description: Inform control module to remove an obsolete interface
-+ * Returns: 0 if success, any other number means an error
-+ */
-+int ma_ctl_del_iface(int);
-+
-+/*
-+ * Public function: ma_ctl_upd_iface
-+ * Description: Inform control module of status change.
-+ * Returns: 0 if success, any other number means an error
-+ */
-+int ma_ctl_upd_iface(int, int, int *);
-+
-+/*
-+ * Public function: ma_ctl_init
-+ * Description: XXX
-+ * Returns: XXX
-+ */
-+void ma_ctl_init(void);
-+
-+/*
-+ * Public function: ma_ctl_clean
-+ * Description: XXX
-+ * Returns: -
-+ */
-+void ma_ctl_clean(void);
-+
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/ndisc_ha.c
-@@ -0,0 +1,596 @@
-+/*
-+ * Mobile IPv6 Duplicate Address Detection Functions
-+ *
-+ * Authors:
-+ * Krishna Kumar <krkumar@us.ibm.com>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/autoconf.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/in6.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/mipv6.h>
-+
-+#include "debug.h"
-+#include "bcache.h"
-+#include "ha.h" /* mipv6_generate_ll_addr */
-+
-+/*
-+ * Binding Updates from MN are cached in this structure till DAD is performed.
-+ * This structure is used to retrieve a pending Binding Update for the HA to
-+ * reply to after performing DAD. The first cell is different from the rest as
-+ * follows :
-+ * 1. The first cell is used to chain the remaining cells.
-+ * 2. The timeout of the first cell is used to delete expired entries
-+ * in the list of cells, while the timeout of the other cells are
-+ * used for timing out a NS request so as to reply to a BU.
-+ * 3. The only elements of the first cell that are used are :
-+ * next, prev, and callback_timer.
-+ *
-+ * TODO : Don't we need to do pneigh_lookup on the Link Local address ?
-+ */
-+struct mipv6_dad_cell {
-+ /* Information needed for DAD management */
-+ struct mipv6_dad_cell *next; /* Next element on the DAD list */
-+ struct mipv6_dad_cell *prev; /* Prev element on the DAD list */
-+ __u16 probes; /* Number of times to probe for addr */
-+ __u16 flags; /* Entry flags - see below */
-+ struct timer_list callback_timer; /* timeout for entry */
-+
-+ /* Information needed for performing DAD */
-+ struct inet6_ifaddr *ifp;
-+ int ifindex;
-+ struct in6_addr daddr;
-+ struct in6_addr haddr; /* home address */
-+ struct in6_addr ll_haddr; /* Link Local value of haddr */
-+ struct in6_addr coa;
-+ struct in6_addr rep_coa;
-+ __u32 ba_lifetime;
-+ __u16 sequence;
-+ __u8 bu_flags;
-+};
-+
-+/* Values for the 'flags' field in the mipv6_dad_cell */
-+#define DAD_INIT_ENTRY 0
-+#define DAD_DUPLICATE_ADDRESS 1
-+#define DAD_UNIQUE_ADDRESS 2
-+
-+/* Head of the pending DAD list */
-+static struct mipv6_dad_cell dad_cell_head;
-+
-+/* Lock to access the pending DAD list */
-+static rwlock_t dad_lock = RW_LOCK_UNLOCKED;
-+
-+/* Timer routine which deletes 'expired' entries in the DAD list */
-+static void mipv6_dad_delete_old_entries(unsigned long unused)
-+{
-+ struct mipv6_dad_cell *curr, *next;
-+ unsigned long next_time = 0;
-+
-+ write_lock(&dad_lock);
-+ curr = dad_cell_head.next;
-+ while (curr != &dad_cell_head) {
-+ next = curr->next;
-+ if (curr->flags != DAD_INIT_ENTRY) {
-+ if (curr->callback_timer.expires <= jiffies) {
-+ /* Entry has expired, free it up. */
-+ curr->next->prev = curr->prev;
-+ curr->prev->next = curr->next;
-+ in6_ifa_put(curr->ifp);
-+ kfree(curr);
-+ } else if (next_time <
-+ curr->callback_timer.expires) {
-+ next_time = curr->callback_timer.expires;
-+ }
-+ }
-+ curr = next;
-+ }
-+ write_unlock(&dad_lock);
-+ if (next_time) {
-+ /*
-+ * Start another timer if more cells need to be removed at
-+ * a later stage.
-+ */
-+ dad_cell_head.callback_timer.expires = next_time;
-+ add_timer(&dad_cell_head.callback_timer);
-+ }
-+}
-+
-+/*
-+ * Queue a timeout routine to clean up 'expired' DAD entries.
-+ */
-+static void mipv6_start_dad_head_timer(struct mipv6_dad_cell *cell)
-+{
-+ unsigned long expire = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time * 10;
-+
-+ if (!timer_pending(&dad_cell_head.callback_timer) ||
-+ expire < dad_cell_head.callback_timer.expires) {
-+ /*
-+ * Add timer if none pending, or mod the timer if new
-+ * cell needs to be expired before existing timer runs.
-+ *
-+ * We let the cell remain as long as possible, so that
-+ * new BU's as part of retransmissions don't have to go
-+ * through DAD before replying.
-+ */
-+ dad_cell_head.callback_timer.expires = expire;
-+
-+ /*
-+ * Keep the cell around for atleast some time to handle
-+ * retransmissions or BU's due to fast MN movement. This
-+ * is needed otherwise a previous timeout can delete all
-+ * expired entries including this new one.
-+ */
-+ cell->callback_timer.expires = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time * 5;
-+ if (!timer_pending(&dad_cell_head.callback_timer)) {
-+ add_timer(&dad_cell_head.callback_timer);
-+ } else {
-+ mod_timer(&dad_cell_head.callback_timer, expire);
-+ }
-+ }
-+}
-+
-+
-+/* Join solicited node MC address */
-+static inline void mipv6_join_sol_mc_addr(struct in6_addr *addr,
-+ struct net_device *dev)
-+{
-+ struct in6_addr maddr;
-+
-+ /* Join solicited node MC address */
-+ addrconf_addr_solict_mult(addr, &maddr);
-+ ipv6_dev_mc_inc(dev, &maddr);
-+}
-+
-+/* Leave solicited node MC address */
-+static inline void mipv6_leave_sol_mc_addr(struct in6_addr *addr,
-+ struct net_device *dev)
-+{
-+ struct in6_addr maddr;
-+
-+ addrconf_addr_solict_mult(addr, &maddr);
-+ ipv6_dev_mc_dec(dev, &maddr);
-+}
-+
-+/* Send a NS */
-+static inline void mipv6_dad_send_ns(struct inet6_ifaddr *ifp,
-+ struct in6_addr *haddr)
-+{
-+ struct in6_addr unspec;
-+ struct in6_addr mcaddr;
-+
-+ ipv6_addr_set(&unspec, 0, 0, 0, 0);
-+ addrconf_addr_solict_mult(haddr, &mcaddr);
-+
-+ /* addr is 'unspec' since we treat this address as transient */
-+ ndisc_send_ns(ifp->idev->dev, NULL, haddr, &mcaddr, &unspec);
-+}
-+
-+/*
-+ * Search for a home address in the list of pending DAD's. Called from
-+ * Neighbor Advertisement
-+ * Return values :
-+ * -1 : No DAD entry found for this advertisement, or entry already
-+ * finished processing.
-+ * 0 : Entry found waiting for DAD to finish.
-+ */
-+static int dad_search_haddr(struct in6_addr *ll_haddr,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u16 * seq, struct inet6_ifaddr **ifp)
-+{
-+ struct mipv6_dad_cell *cell;
-+
-+ read_lock(&dad_lock);
-+ cell = dad_cell_head.next;
-+ while (cell != &dad_cell_head &&
-+ ipv6_addr_cmp(&cell->ll_haddr, ll_haddr) &&
-+ ipv6_addr_cmp(&cell->haddr, ll_haddr)) {
-+ cell = cell->next;
-+ }
-+ if (cell == &dad_cell_head || cell->flags != DAD_INIT_ENTRY) {
-+ /* Not found element, or element already finished processing */
-+ if (cell != &dad_cell_head) {
-+ /*
-+ * Set the state to DUPLICATE, even if it was UNIQUE
-+ * earlier. It is not needed to setup timer via
-+ * mipv6_start_dad_head_timer since this must have
-+ * already been done.
-+ */
-+ cell->flags = DAD_DUPLICATE_ADDRESS;
-+ }
-+ read_unlock(&dad_lock);
-+ return -1;
-+ }
-+
-+ /*
-+ * The NA found an unprocessed entry in the DAD list. Expire this
-+ * entry since another node advertised this address. Caller should
-+ * reject BU (DAD failed).
-+ */
-+ ipv6_addr_copy(daddr, &cell->daddr);
-+ ipv6_addr_copy(haddr, &cell->haddr);
-+ ipv6_addr_copy(coa, &cell->coa);
-+ ipv6_addr_copy(rep_coa, &cell->rep_coa);
-+ *seq = cell->sequence;
-+ *ifp = cell->ifp;
-+
-+ if (del_timer(&cell->callback_timer) == 0) {
-+ /* Timer already deleted, race with Timeout Handler */
-+ /* No action needed */
-+ }
-+
-+ cell->flags = DAD_DUPLICATE_ADDRESS;
-+
-+ /* Now leave this address to avoid future processing of NA's */
-+ mipv6_leave_sol_mc_addr(&cell->ll_haddr, cell->ifp->idev->dev);
-+ /* Leave also global address, if link local address was in use */
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr, cell->ifp->idev->dev);
-+ /* Start dad_head timer to remove this entry */
-+ mipv6_start_dad_head_timer(cell);
-+
-+ read_unlock(&dad_lock);
-+
-+ return 0;
-+}
-+
-+/* ENTRY routine called via Neighbor Advertisement */
-+void mipv6_check_dad(struct in6_addr *ll_haddr)
-+{
-+ struct in6_addr daddr, haddr, coa, rep_coa;
-+ struct inet6_ifaddr *ifp;
-+ __u16 seq;
-+
-+ if (dad_search_haddr(ll_haddr, &daddr, &haddr, &coa, &rep_coa, &seq,
-+ &ifp) < 0) {
-+ /*
-+ * Didn't find entry, or no action needed (the action has
-+ * already been performed).
-+ */
-+ return;
-+ }
-+
-+ /*
-+ * A DAD cell was present, meaning that there is a pending BU
-+ * request for 'haddr' - reject the BU.
-+ */
-+ mipv6_bu_finish(ifp, 0, DUPLICATE_ADDR_DETECT_FAIL,
-+ &daddr, &haddr, &coa, &rep_coa, 0, seq, 0, NULL);
-+ return;
-+}
-+
-+/*
-+ * Check if the passed 'cell' is in the list of pending DAD's. Called from
-+ * the Timeout Handler.
-+ *
-+ * Assumes that the caller is holding the dad_lock in reader mode.
-+ */
-+static int dad_search_cell(struct mipv6_dad_cell *cell)
-+{
-+ struct mipv6_dad_cell *tmp;
-+
-+ tmp = dad_cell_head.next;
-+ while (tmp != &dad_cell_head && tmp != cell) {
-+ tmp = tmp->next;
-+ }
-+ if (tmp == cell) {
-+ if (cell->flags == DAD_INIT_ENTRY) {
-+ /* Found valid entry */
-+ if (--cell->probes == 0) {
-+ /*
-+ * Retransmission's are over - return success.
-+ */
-+ cell->flags = DAD_UNIQUE_ADDRESS;
-+
-+ /*
-+ * Leave this address to avoid future
-+ * processing of NA's.
-+ */
-+ mipv6_leave_sol_mc_addr(&cell->ll_haddr,
-+ cell->ifp->idev->
-+ dev);
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr,
-+ cell->ifp->idev->dev);
-+ /* start timeout to delete this cell. */
-+ mipv6_start_dad_head_timer(cell);
-+ return 0;
-+ }
-+ /*
-+ * Retransmission not finished, send another NS and
-+ * return failure.
-+ */
-+ mipv6_dad_send_ns(cell->ifp, &cell->ll_haddr);
-+ if (ipv6_addr_cmp(&cell->ll_haddr, &cell->haddr))
-+ mipv6_leave_sol_mc_addr(&cell->haddr,
-+ cell->ifp->idev->dev);
-+ cell->callback_timer.expires = jiffies +
-+ cell->ifp->idev->nd_parms->retrans_time;
-+ add_timer(&cell->callback_timer);
-+ } else {
-+ /*
-+ * This means that an NA was received before the
-+ * timeout and when the state changed from
-+ * DAD_INIT_ENTRY, the BU got failed as a result.
-+ * There is nothing to be done.
-+ */
-+ }
-+ }
-+ return -1;
-+}
-+
-+/* ENTRY routine called via Timeout */
-+static void mipv6_dad_timeout(unsigned long arg)
-+{
-+ __u8 ba_status = SUCCESS;
-+ struct in6_addr daddr;
-+ struct in6_addr haddr;
-+ struct in6_addr coa;
-+ struct in6_addr rep_coa;
-+ struct inet6_ifaddr *ifp;
-+ int ifindex;
-+ __u32 ba_lifetime;
-+ __u16 sequence;
-+ __u8 flags;
-+ struct mipv6_dad_cell *cell = (struct mipv6_dad_cell *) arg;
-+
-+ /*
-+ * If entry is not in the list, we have already sent BU Failure
-+ * after getting a NA.
-+ */
-+ read_lock(&dad_lock);
-+ if (dad_search_cell(cell) < 0) {
-+ /*
-+ * 'cell' is no longer valid (may not be in the list or
-+ * is already processed, due to NA processing), or NS
-+ * retransmissions are not yet over.
-+ */
-+ read_unlock(&dad_lock);
-+ return;
-+ }
-+
-+ /* This is the final Timeout. Send Bind Ack Success */
-+
-+ ifp = cell->ifp;
-+ ifindex = cell->ifindex;
-+ ba_lifetime = cell->ba_lifetime;
-+ sequence = cell->sequence;
-+ flags = cell->bu_flags;
-+
-+ ipv6_addr_copy(&daddr, &cell->daddr);
-+ ipv6_addr_copy(&haddr, &cell->haddr);
-+ ipv6_addr_copy(&coa, &cell->coa);
-+ ipv6_addr_copy(&rep_coa, &cell->rep_coa);
-+ read_unlock(&dad_lock);
-+
-+ /* Send BU Acknowledgement Success */
-+ mipv6_bu_finish(ifp, ifindex, ba_status,
-+ &daddr, &haddr, &coa, &rep_coa,
-+ ba_lifetime, sequence, flags, NULL);
-+ return;
-+}
-+
-+/*
-+ * Check if original home address exists in our DAD pending list, if so return
-+ * the cell.
-+ *
-+ * Assumes that the caller is holding the dad_lock in writer mode.
-+ */
-+static struct mipv6_dad_cell *mipv6_dad_get_cell(struct in6_addr *haddr)
-+{
-+ struct mipv6_dad_cell *cell;
-+
-+ cell = dad_cell_head.next;
-+ while (cell != &dad_cell_head
-+ && ipv6_addr_cmp(&cell->haddr, haddr)) {
-+ cell = cell->next;
-+ }
-+ if (cell == &dad_cell_head) {
-+ /* Not found element */
-+ return NULL;
-+ }
-+ return cell;
-+}
-+
-+/*
-+ * Save all parameters needed for doing a Bind Ack in the mipv6_dad_cell
-+ * structure.
-+ */
-+static void mipv6_dad_save_cell(struct mipv6_dad_cell *cell,
-+ struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr,
-+ struct in6_addr *haddr,
-+ struct in6_addr *coa,
-+ struct in6_addr *rep_coa,
-+ __u32 ba_lifetime,
-+ __u16 sequence, __u8 flags)
-+{
-+ in6_ifa_hold(ifp);
-+ cell->ifp = ifp;
-+ cell->ifindex = ifindex;
-+
-+ ipv6_addr_copy(&cell->daddr, daddr);
-+ ipv6_addr_copy(&cell->haddr, haddr);
-+ ipv6_addr_copy(&cell->coa, coa);
-+ ipv6_addr_copy(&cell->rep_coa, rep_coa);
-+
-+ /* Convert cell->ll_haddr to Link Local address */
-+ if (flags & MIPV6_BU_F_LLADDR)
-+ mipv6_generate_ll_addr(&cell->ll_haddr, haddr);
-+ else
-+ ipv6_addr_copy(&cell->ll_haddr, haddr);
-+
-+ cell->ba_lifetime = ba_lifetime;
-+ cell->sequence = sequence;
-+ cell->bu_flags = flags;
-+}
-+
-+/*
-+ * Top level DAD routine for performing DAD.
-+ *
-+ * Return values
-+ * 0 : Don't need to do DAD.
-+ * 1 : Need to do DAD.
-+ * -n : Error, where 'n' is the reason for the error.
-+ *
-+ * Assumption : DAD process has been optimized by using cached values upto
-+ * some time. However sometimes this can cause problems. Eg. when the first
-+ * BU was received, DAD might have failed. Before the second BU arrived,
-+ * the node using MN's home address might have stopped using it, but still
-+ * we will return DAD_DUPLICATE_ADDRESS based on the first DAD's result. Or
-+ * this can go the other way around. However, it is a very small possibility
-+ * and thus optimization is turned on by default. It is possible to change
-+ * this feature (needs a little code-rewriting in this routine), but
-+ * currently DAD result is being cached for performance reasons.
-+ */
-+int mipv6_dad_start(struct inet6_ifaddr *ifp, int ifindex,
-+ struct in6_addr *daddr, struct in6_addr *haddr,
-+ struct in6_addr *coa, struct in6_addr *rep_coa,
-+ __u32 ba_lifetime, __u16 sequence, __u8 flags)
-+{
-+ int found;
-+ struct mipv6_dad_cell *cell;
-+ struct mipv6_bce bc_entry;
-+
-+ if (ifp->idev->cnf.dad_transmits == 0) {
-+ /* DAD is not configured on the HA, return SUCCESS */
-+ return 0;
-+ }
-+
-+ if (mipv6_bcache_get(haddr, daddr, &bc_entry) == 0) {
-+ /*
-+ * We already have an entry in our cache - don't need to
-+ * do DAD as we are already defending this home address.
-+ */
-+ return 0;
-+ }
-+
-+ write_lock(&dad_lock);
-+ if ((cell = mipv6_dad_get_cell(haddr)) != NULL) {
-+ /*
-+ * An existing entry for BU was found in our cache due
-+ * to retransmission of the BU or a new COA registration.
-+ */
-+ switch (cell->flags) {
-+ case DAD_INIT_ENTRY:
-+ /* Old entry is waiting for DAD to complete */
-+ break;
-+ case DAD_UNIQUE_ADDRESS:
-+ /* DAD is finished successfully - return success. */
-+ write_unlock(&dad_lock);
-+ return 0;
-+ case DAD_DUPLICATE_ADDRESS:
-+ /*
-+ * DAD is finished and we got a NA while doing BU -
-+ * return failure.
-+ */
-+ write_unlock(&dad_lock);
-+ return -DUPLICATE_ADDR_DETECT_FAIL;
-+ default:
-+ /* Unknown state - should never happen */
-+ DEBUG(DBG_WARNING,
-+ "cell entry in unknown state : %d",
-+ cell->flags);
-+ write_unlock(&dad_lock);
-+ return -REASON_UNSPECIFIED;
-+ }
-+ found = 1;
-+ } else {
-+ if ((cell = (struct mipv6_dad_cell *)
-+ kmalloc(sizeof(struct mipv6_dad_cell), GFP_ATOMIC))
-+ == NULL) {
-+ return -INSUFFICIENT_RESOURCES;
-+ }
-+ found = 0;
-+ }
-+
-+ mipv6_dad_save_cell(cell, ifp, ifindex, daddr, haddr, coa, rep_coa,
-+ ba_lifetime, sequence, flags);
-+
-+ if (!found) {
-+ cell->flags = DAD_INIT_ENTRY;
-+ cell->probes = ifp->idev->cnf.dad_transmits;
-+
-+ /* Insert element on dad_cell_head list */
-+ dad_cell_head.prev->next = cell;
-+ cell->next = &dad_cell_head;
-+ cell->prev = dad_cell_head.prev;
-+ dad_cell_head.prev = cell;
-+ write_unlock(&dad_lock);
-+ if (flags & MIPV6_BU_F_LLADDR) {
-+ /* join the solicited node MC of the global homeaddr.*/
-+ mipv6_join_sol_mc_addr(&cell->haddr, ifp->idev->dev);
-+ /* Send a NS */
-+ mipv6_dad_send_ns(ifp, &cell->haddr);
-+ }
-+ /* join the solicited node MC of the homeaddr. */
-+ mipv6_join_sol_mc_addr(&cell->ll_haddr, ifp->idev->dev);
-+
-+ /* Send a NS */
-+ mipv6_dad_send_ns(ifp, &cell->ll_haddr);
-+
-+ /* Initialize timer for this cell to timeout the NS. */
-+ init_timer(&cell->callback_timer);
-+ cell->callback_timer.data = (unsigned long) cell;
-+ cell->callback_timer.function = mipv6_dad_timeout;
-+ cell->callback_timer.expires = jiffies +
-+ ifp->idev->nd_parms->retrans_time;
-+ add_timer(&cell->callback_timer);
-+ } else {
-+ write_unlock(&dad_lock);
-+ }
-+ return 1;
-+}
-+
-+void __init mipv6_dad_init(void)
-+{
-+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head;
-+ init_timer(&dad_cell_head.callback_timer);
-+ dad_cell_head.callback_timer.data = 0;
-+ dad_cell_head.callback_timer.function =
-+ mipv6_dad_delete_old_entries;
-+}
-+
-+void __exit mipv6_dad_exit(void)
-+{
-+ struct mipv6_dad_cell *curr, *next;
-+
-+ write_lock_bh(&dad_lock);
-+ del_timer(&dad_cell_head.callback_timer);
-+
-+ curr = dad_cell_head.next;
-+ while (curr != &dad_cell_head) {
-+ next = curr->next;
-+ del_timer(&curr->callback_timer);
-+ if (curr->flags == DAD_INIT_ENTRY) {
-+ /*
-+ * We were in DAD_INIT state and listening to the
-+ * solicited node MC address - need to stop that.
-+ */
-+ mipv6_leave_sol_mc_addr(&curr->ll_haddr,
-+ curr->ifp->idev->dev);
-+ if (ipv6_addr_cmp(&curr->ll_haddr, &curr->haddr))
-+ mipv6_leave_sol_mc_addr(&curr->haddr,
-+ curr->ifp->idev->dev);
-+ }
-+ in6_ifa_put(curr->ifp);
-+ kfree(curr);
-+ curr = next;
-+ }
-+ dad_cell_head.next = dad_cell_head.prev = &dad_cell_head;
-+ write_unlock_bh(&dad_lock);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/prefix.c
-@@ -0,0 +1,217 @@
-+/**
-+ * Prefix solicitation and advertisement
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <linux/net.h>
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <linux/netdevice.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "mipv6_icmp.h"
-+#include "debug.h"
-+#include "sortedlist.h"
-+#include "prefix.h"
-+#include "config.h"
-+
-+#define INFINITY 0xffffffff
-+
-+struct timer_list pfx_timer;
-+
-+struct list_head pfx_list;
-+rwlock_t pfx_list_lock = RW_LOCK_UNLOCKED;
-+
-+int compare_pfx_list_entry(const void *data1, const void *data2,
-+ int datalen)
-+{
-+ struct pfx_list_entry *e1 = (struct pfx_list_entry *) data1;
-+ struct pfx_list_entry *e2 = (struct pfx_list_entry *) data2;
-+
-+ return ((ipv6_addr_cmp(&e1->daddr, &e2->daddr) == 0)
-+ && (e2->ifindex == -1 || e1->ifindex == e2->ifindex));
-+}
-+
-+/**
-+ * mipv6_pfx_cancel_send - cancel pending items to daddr from saddr
-+ * @daddr: Destination address
-+ * @ifindex: pending items on this interface will be canceled
-+ *
-+ * if ifindex == -1, all items to daddr will be removed
-+ */
-+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry entry;
-+
-+ DEBUG_FUNC();
-+
-+ /* We'll just be comparing these parts... */
-+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr));
-+ entry.ifindex = ifindex;
-+
-+ write_lock_bh(&pfx_list_lock);
-+
-+ while (mipv6_slist_del_item(&pfx_list, &entry,
-+ compare_pfx_list_entry) == 0)
-+ ;
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ write_unlock_bh(&pfx_list_lock);
-+}
-+
-+/**
-+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to
-+ * @daddr: address of HA
-+ * @saddr: our address to use as source address
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int ifindex)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry entry;
-+
-+ DEBUG_FUNC();
-+
-+ memcpy(&entry.daddr, daddr, sizeof(struct in6_addr));
-+ memcpy(&entry.saddr, saddr, sizeof(struct in6_addr));
-+ entry.retries = 0;
-+ entry.ifindex = ifindex;
-+
-+ write_lock_bh(&pfx_list_lock);
-+ if (mipv6_slist_modify(&pfx_list, &entry, sizeof(struct pfx_list_entry),
-+ jiffies + INITIAL_SOLICIT_TIMER * HZ,
-+ compare_pfx_list_entry))
-+ DEBUG(DBG_WARNING, "Cannot add new HA to pfx list");
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
-+
-+int mipv6_pfx_add_home(int ifindex, struct in6_addr *saddr,
-+ struct in6_addr *daddr, unsigned long min_expire)
-+{
-+ unsigned long tmp;
-+
-+ write_lock(&pfx_list_lock);
-+
-+ if (min_expire != INFINITY) {
-+ unsigned long expire;
-+ struct pfx_list_entry entry;
-+
-+ memcpy(&entry.daddr, saddr, sizeof(struct in6_addr));
-+ memcpy(&entry.saddr, daddr, sizeof(struct in6_addr));
-+ entry.retries = 0;
-+ entry.ifindex = ifindex;
-+
-+ /* This is against the RFC 3775, but we need to set
-+ * a minimum interval for a prefix solicitation.
-+ * Otherwise a prefix solicitation storm will
-+ * result if valid lifetime of the prefix is
-+ * smaller than MAX_PFX_ADV_DELAY
-+ */
-+ min_expire -= MAX_PFX_ADV_DELAY;
-+ min_expire = min_expire < MIN_PFX_SOL_DELAY ? MIN_PFX_SOL_DELAY : min_expire;
-+
-+ expire = jiffies + min_expire * HZ;
-+
-+ if (mipv6_slist_modify(&pfx_list, &entry,
-+ sizeof(struct pfx_list_entry),
-+ expire,
-+ compare_pfx_list_entry) != 0)
-+ DEBUG(DBG_WARNING, "Cannot add new entry to pfx_list");
-+ }
-+
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ write_unlock(&pfx_list_lock);
-+
-+ return 0;
-+}
-+
-+/**
-+ * set_ha_pfx_list - manipulate pfx_list for HA when timer goes off
-+ * @entry: pfx_list_entry that is due
-+ */
-+static void set_ha_pfx_list(struct pfx_list_entry *entry)
-+{
-+}
-+
-+/**
-+ * set_mn_pfx_list - manipulate pfx_list for MN when timer goes off
-+ * @entry: pfx_list_entry that is due
-+ */
-+static void set_mn_pfx_list(struct pfx_list_entry *entry)
-+{
-+}
-+
-+/**
-+ * pfx_timer_handler - general timer handler
-+ * @dummy: dummy
-+ *
-+ * calls set_ha_pfx_list and set_mn_pfx_list to do the thing when
-+ * a timer goes off
-+ */
-+static void pfx_timer_handler(unsigned long dummy)
-+{
-+ unsigned long tmp;
-+ struct pfx_list_entry *entry;
-+
-+ DEBUG_FUNC();
-+
-+ write_lock(&pfx_list_lock);
-+ if (!(entry = mipv6_slist_get_first(&pfx_list)))
-+ goto out;
-+
-+ if (mip6node_cnf.capabilities & CAP_HA)
-+ set_ha_pfx_list(entry);
-+ if (mip6node_cnf.capabilities & CAP_MN)
-+ set_mn_pfx_list(entry);
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+
-+ out:
-+ write_unlock(&pfx_list_lock);
-+}
-+
-+int mipv6_initialize_pfx_icmpv6(void)
-+{
-+ INIT_LIST_HEAD(&pfx_list);
-+
-+ init_timer(&pfx_timer);
-+ pfx_timer.function = pfx_timer_handler;
-+
-+ return 0;
-+}
-+
-+void mipv6_shutdown_pfx_icmpv6(void)
-+{
-+ struct prefix_info *tmp;
-+
-+ if (timer_pending(&pfx_timer))
-+ del_timer(&pfx_timer);
-+
-+ write_lock_bh(&pfx_list_lock);
-+ while ((tmp = mipv6_slist_del_first(&pfx_list)))
-+ kfree(tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/prefix.h
-@@ -0,0 +1,57 @@
-+/*
-+ * MIPL Mobile IPv6 Prefix solicitation and advertisement
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _PREFIX_H
-+#define _PREFIX_H
-+
-+#include <net/addrconf.h>
-+
-+struct pfx_list_entry {
-+ struct in6_addr daddr;
-+ struct in6_addr saddr;
-+ int retries;
-+ int ifindex;
-+};
-+
-+extern struct list_head pfx_list;
-+extern rwlock_t pfx_list_lock;
-+extern struct timer_list pfx_timer;
-+
-+int compare_pfx_list_entry(const void *data1, const void *data2,
-+ int datalen);
-+
-+/**
-+ * mipv6_pfx_cancel_send - cancel pending pfx_advs/sols to daddr
-+ * @daddr: destination address
-+ * @ifindex: pending items on this interface will be canceled
-+ *
-+ * if ifindex == -1, all items to daddr will be removed
-+ */
-+void mipv6_pfx_cancel_send(struct in6_addr *daddr, int ifindex);
-+
-+/**
-+ * mipv6_pfx_add_ha - add a new HA to send prefix solicitations to
-+ * @daddr: address of HA
-+ * @saddr: our address to use as source address
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfx_add_ha(struct in6_addr *daddr, struct in6_addr *saddr,
-+ int ifindex);
-+
-+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex);
-+
-+int mipv6_pfx_add_home(int ifindex, struct in6_addr *daddr,
-+ struct in6_addr *saddr, unsigned long min_expire);
-+
-+int mipv6_initialize_pfx_icmpv6(void);
-+void mipv6_shutdown_pfx_icmpv6(void);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/prefix_ha.c
-@@ -0,0 +1,122 @@
-+/**
-+ * Prefix advertisement for Home Agent
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/icmpv6.h>
-+#include <linux/net.h>
-+#include <linux/spinlock.h>
-+#include <linux/timer.h>
-+#include <linux/netdevice.h>
-+#include <net/ipv6.h>
-+#include <net/addrconf.h>
-+#include <net/ip6_route.h>
-+#include <net/mipv6.h>
-+
-+#include "mipv6_icmp.h"
-+#include "debug.h"
-+#include "sortedlist.h"
-+#include "util.h"
-+#include "bcache.h"
-+#include "config.h"
-+#include "prefix.h"
-+
-+/**
-+ * pfx_adv_iterator - modify pfx_list entries according to new prefix info
-+ * @data: MN's home registration bcache_entry
-+ * @args: new prefix info
-+ * @sortkey: ignored
-+ */
-+static int pfx_adv_iterator(void *data, void *args, unsigned long sortkey)
-+{
-+ struct mipv6_bce *bc_entry = (struct mipv6_bce *) data;
-+ struct prefix_info *pinfo = (struct prefix_info *) args;
-+
-+ if (mipv6_prefix_compare(&bc_entry->coa, &pinfo->prefix,
-+ pinfo->prefix_len) == 0) {
-+ struct pfx_list_entry pfx_entry;
-+
-+ memcpy(&pfx_entry.daddr, &bc_entry->coa,
-+ sizeof(struct in6_addr));
-+ memcpy(&pfx_entry.daddr, &bc_entry->our_addr,
-+ sizeof(struct in6_addr));
-+ pfx_entry.retries = 0;
-+ pfx_entry.ifindex = bc_entry->ifindex;
-+
-+ mipv6_slist_modify(&pfx_list, &pfx_entry,
-+ sizeof(struct pfx_list_entry),
-+ jiffies +
-+ net_random() % (MAX_PFX_ADV_DELAY * HZ),
-+ compare_pfx_list_entry);
-+ }
-+
-+ return 0;
-+}
-+
-+struct homereg_iterator_args {
-+ struct list_head *head;
-+ int count;
-+};
-+
-+static int homereg_iterator(void *data, void *args, unsigned long *sortkey)
-+{
-+ struct mipv6_bce *entry = (struct mipv6_bce *) data;
-+ struct homereg_iterator_args *state =
-+ (struct homereg_iterator_args *) args;
-+
-+ if (entry->type == HOME_REGISTRATION) {
-+ mipv6_slist_add(state->head, entry,
-+ sizeof(struct mipv6_bce),
-+ state->count);
-+ state->count++;
-+ }
-+ return 0;
-+}
-+
-+static int mipv6_bcache_get_homeregs(struct list_head *head)
-+{
-+ struct homereg_iterator_args args;
-+
-+ DEBUG_FUNC();
-+
-+ args.count = 0;
-+ args.head = head;
-+
-+ mipv6_bcache_iterate(homereg_iterator, &args);
-+ return args.count;
-+}
-+
-+/**
-+ * mipv6_prefix_added - prefix was added to interface, act accordingly
-+ * @pinfo: prefix_info that was added
-+ * @ifindex: interface index
-+ */
-+void mipv6_pfxs_modified(struct prefix_info *pinfo, int ifindex)
-+{
-+ int count;
-+ unsigned long tmp;
-+ struct list_head home_regs;
-+
-+ DEBUG_FUNC();
-+
-+ INIT_LIST_HEAD(&home_regs);
-+
-+ if (!(count = mipv6_bcache_get_homeregs(&home_regs)))
-+ return;
-+
-+ write_lock_bh(&pfx_list_lock);
-+ mipv6_slist_for_each(&home_regs, pinfo, pfx_adv_iterator);
-+ if ((tmp = mipv6_slist_get_first_key(&pfx_list)))
-+ mod_timer(&pfx_timer, tmp);
-+ write_unlock_bh(&pfx_list_lock);
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/rr_crypto.c
-@@ -0,0 +1,255 @@
-+/*
-+ * rr_cookie.c - Mobile IPv6 return routability crypto
-+ * Author : Henrik Petander <henrik.petander@hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/kernel.h>
-+#include <linux/types.h>
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/random.h>
-+
-+#include <net/ipv6.h>
-+
-+#include "debug.h"
-+#include "hmac.h"
-+#include "rr_crypto.h"
-+
-+#define DBG_RR 5
-+
-+u8 k_CN[HMAC_SHA1_KEY_SIZE]; // secret key of CN
-+
-+u16 curr_index = 0;
-+
-+struct nonce_timestamp nonce_table[MAX_NONCES];
-+spinlock_t nonce_lock = SPIN_LOCK_UNLOCKED;
-+void update_nonces(void);
-+
-+/** nonce_is_fresh - whether the nonce was generated recently
-+ *
-+ * @non_ts : table entry containing the nonce and a timestamp
-+ * @interval : if nonce was generated within interval seconds it is fresh
-+ *
-+ * Returns 1 if the nonce is fresh, 0 otherwise.
-+ */
-+static int nonce_is_fresh(struct nonce_timestamp *non_ts, unsigned long interval)
-+{
-+ if (time_before(jiffies, non_ts->timestamp + interval * HZ) && !non_ts->invalid)
-+ return 1;
-+ return 0;
-+}
-+void mipv6_rr_invalidate_nonce(u16 nonce_ind)
-+{
-+ spin_lock_bh(&nonce_lock);
-+ if (nonce_ind > MAX_NONCES) {
-+ spin_unlock_bh(&nonce_lock);
-+ return;
-+ }
-+ nonce_table[nonce_ind].invalid = 1;
-+ spin_unlock_bh(&nonce_lock);
-+}
-+/* Returns a pointer to a new nonce */
-+struct mipv6_rr_nonce * mipv6_rr_get_new_nonce(void)
-+{
-+ struct mipv6_rr_nonce *nce = kmalloc(sizeof(*nce), GFP_ATOMIC);
-+
-+ if (!nce)
-+ return NULL;
-+ // Lock nonces here
-+ spin_lock_bh(&nonce_lock);
-+ // If nonce is not fresh create new one
-+ if (!nonce_is_fresh(&nonce_table[curr_index], MIPV6_RR_NONCE_LIFETIME)) {
-+ // increment the last nonce pointer and create new nonce
-+ curr_index++;
-+ // Wrap around
-+ if (curr_index == MAX_NONCES)
-+ curr_index = 0;
-+ // Get random data to fill the nonce data
-+ get_random_bytes(nonce_table[curr_index].nonce.data, MIPV6_RR_NONCE_DATA_LENGTH);
-+ // Fill the index field
-+ nonce_table[curr_index].nonce.index = curr_index;
-+ nonce_table[curr_index].invalid = 0;
-+ nonce_table[curr_index].timestamp = jiffies;
-+ }
-+ spin_unlock_bh(&nonce_lock);
-+ memcpy(nce, &nonce_table[curr_index].nonce, sizeof(*nce));
-+ // Unlock nonces
-+ return nce;
-+}
-+/** mipv6_rr_nonce_get_by_index - returns a nonce for index
-+ * @nonce_ind : index of the nonce
-+ *
-+ * Returns a nonce or NULL if the nonce index was invalid or the nonce
-+ * for the index was not fresh.
-+ */
-+struct mipv6_rr_nonce * mipv6_rr_nonce_get_by_index(u16 nonce_ind)
-+{
-+ struct mipv6_rr_nonce *nce = NULL;
-+
-+ spin_lock_bh(&nonce_lock);
-+ if (nonce_ind >= MAX_NONCES) {
-+ DEBUG(DBG_WARNING, "Nonce index field from BU invalid");
-+
-+ /* Here a double of the nonce_lifetime is used for freshness
-+ * verification, since the nonces
-+ * are not created in response to every initiator packet
-+ */
-+ } else if (nonce_is_fresh(&nonce_table[nonce_ind], 2 * MIPV6_RR_NONCE_LIFETIME)) {
-+ nce = kmalloc(sizeof(*nce), GFP_ATOMIC);
-+ memcpy(nce, &nonce_table[nonce_ind].nonce, sizeof(*nce));
-+ }
-+ spin_unlock_bh(&nonce_lock);
-+
-+ return nce;
-+}
-+
-+/* Fills rr test init cookies with random bytes */
-+void mipv6_rr_mn_cookie_create(u8 *cookie)
-+{
-+ get_random_bytes(cookie, MIPV6_RR_COOKIE_LENGTH);
-+}
-+
-+/** mipv6_rr_cookie_create - builds a home or care-of cookie
-+ *
-+ * @addr : the home or care-of address from HoTI or CoTI
-+ * @ckie : memory where the cookie is copied to
-+ * @nce : pointer to a nonce used for the calculation, nce is freed during the function
-+ *
-+ */
-+int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie,
-+ u16 nonce_index)
-+{
-+ struct ah_processing ah_proc;
-+ u8 digest[HMAC_SHA1_HASH_LEN];
-+ struct mipv6_rr_nonce *nce;
-+
-+ if ((nce = mipv6_rr_nonce_get_by_index(nonce_index))== NULL)
-+ return -1;
-+
-+ if (*ckie == NULL && (*ckie = kmalloc(MIPV6_RR_COOKIE_LENGTH,
-+ GFP_ATOMIC)) == NULL) {
-+ kfree(nce);
-+ return -1;
-+ }
-+ /* Calculate the full hmac-sha1 digest from address and nonce using the secret key of cn */
-+
-+ if (ah_hmac_sha1_init(&ah_proc, k_CN, HMAC_SHA1_KEY_SIZE) < 0) {
-+ DEBUG(DBG_ERROR, "Hmac sha1 initialization failed");
-+ kfree(nce);
-+ return -1;
-+ }
-+
-+ ah_hmac_sha1_loop(&ah_proc, addr, sizeof(*addr));
-+ ah_hmac_sha1_loop(&ah_proc, nce->data, MIPV6_RR_NONCE_DATA_LENGTH);
-+ ah_hmac_sha1_result(&ah_proc, digest);
-+
-+
-+ /* clean up nonce */
-+ kfree(nce);
-+
-+ /* Copy first 64 bits of hash target to the cookie */
-+ memcpy(*ckie, digest, MIPV6_RR_COOKIE_LENGTH);
-+ return 0;
-+}
-+
-+/** mipv6_rr_key_calc - creates BU authentication key
-+ *
-+ * @hoc : Home Cookie
-+ * @coc : Care-of Cookie
-+ *
-+ * Returns BU authentication key of length HMAC_SHA1_KEY_SIZE or NULL in error cases,
-+ * caller needs to free the key.
-+ */
-+u8 *mipv6_rr_key_calc(u8 *hoc, u8 *coc)
-+{
-+
-+ u8 *key_bu = kmalloc(HMAC_SHA1_KEY_SIZE, GFP_ATOMIC);
-+ SHA1_CTX c;
-+
-+ if (!key_bu) {
-+ DEBUG(DBG_CRITICAL, "Memory allocation failed, could nort create BU authentication key");
-+ return NULL;
-+ }
-+
-+ /* Calculate the key from home and care-of cookies
-+ * Kbu = sha1(home_cookie | care-of cookie)
-+ * or KBu = sha1(home_cookie), if MN deregisters
-+ */
-+ sha1_init(&c);
-+ sha1_compute(&c, hoc, MIPV6_RR_COOKIE_LENGTH);
-+ if (coc)
-+ sha1_compute(&c, coc, MIPV6_RR_COOKIE_LENGTH);
-+ sha1_final(&c, key_bu);
-+ DEBUG(DBG_RR, "Home and Care-of cookies used for calculating key ");
-+ debug_print_buffer(DBG_RR, hoc, MIPV6_RR_COOKIE_LENGTH);
-+ if (coc)
-+ debug_print_buffer(DBG_RR, coc, MIPV6_RR_COOKIE_LENGTH);
-+
-+ return key_bu;
-+}
-+
-+void mipv6_rr_init(void)
-+{
-+ get_random_bytes(k_CN, HMAC_SHA1_KEY_SIZE);
-+ memset(nonce_table, 0, MAX_NONCES * sizeof(struct nonce_timestamp));
-+}
-+
-+#ifdef TEST_MIPV6_RR_CRYPTO
-+void mipv6_test_rr(void)
-+{
-+ struct mipv6_rr_nonce *nonce;
-+ struct in6_addr a1, a2;
-+ int ind1, ind2;
-+ u8 *ckie1 = NULL, *ckie2 = NULL;
-+ u8 *key_mn = NULL, *key_cn = NULL;
-+ mipv6_init_rr();
-+
-+ nonce = mipv6_rr_get_new_nonce();
-+ if (!nonce) {
-+ printk("mipv6_rr_get_new_nonce() failed, at 1! \n");
-+ return;
-+ }
-+ mipv6_rr_cookie_create(&a1, &ckie1, nonce->index);
-+ ind1 = nonce->index;
-+ kfree(nonce);
-+
-+ nonce = mipv6_rr_get_new_nonce();
-+ if (!nonce) {
-+ printk("mipv6_rr_get_new_nonce() failed, at 2! \n");
-+ return;
-+ }
-+
-+ mipv6_rr_cookie_create(&a2, &ckie2, nonce->index);
-+ ind2 = nonce->index;
-+ key_mn = mipv6_rr_key_calc(ckie1, ckie2);
-+
-+ /* Create home and coa cookies based on indices */
-+ mipv6_rr_cookie_create(&a1, &ckie1, ind1);
-+ mipv6_rr_cookie_create(&a2, &ckie2, ind2);
-+ key_cn = mipv6_rr_key_calc(ckie1, ckie2);
-+ if (!key_cn || !key_mn) {
-+ printk("creation of secret key failed!\n");
-+ return;
-+ }
-+ if(memcmp(key_cn, key_mn, HMAC_SHA1_KEY_SIZE))
-+ printk("mipv6_rr_key_calc produced different keys for MN and CN \n");
-+ else
-+ printk("mipv6_rr_crypto test OK\n");
-+ kfree(nonce);
-+ kfree(key_cn);
-+ kfree(key_mn);
-+}
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/rr_crypto.h
-@@ -0,0 +1,72 @@
-+/*
-+ * MIPL Mobile IPv6 Return routability crypto prototypes
-+ *
-+ * $Id:$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _RR_CRYPTO
-+#define _RR_CRYPTO
-+
-+#include <linux/in6.h>
-+
-+/* Macros and data structures */
-+
-+#define MIPV6_RR_NONCE_LIFETIME 60
-+#define MIPV6_RR_NONCE_DATA_LENGTH 8
-+#define MIPV6_RR_COOKIE_LENGTH 8
-+#define COOKIE_SIZE 8
-+#define MAX_NONCES 4
-+#define HMAC_SHA1_KEY_SIZE 20
-+
-+struct mipv6_rr_nonce {
-+ u_int16_t index;
-+ u_int8_t data[MIPV6_RR_NONCE_DATA_LENGTH];
-+};
-+
-+struct nonce_timestamp {
-+ struct mipv6_rr_nonce nonce;
-+ unsigned long timestamp;
-+ u_int8_t invalid;
-+};
-+
-+/* Function definitions */
-+
-+/* Return 1 if equal, 0 if not */
-+static __inline__ int mipv6_equal_cookies(u8 *c1, u8 *c2)
-+{
-+ return (memcmp(c1, c2, MIPV6_RR_COOKIE_LENGTH) == 0);
-+}
-+
-+/* Function declarations */
-+
-+/* Create cookie for HoTi and CoTi */
-+extern void mipv6_rr_mn_cookie_create(u8 *cookie);
-+
-+/* Create cookie for HoT and CoT */
-+extern int mipv6_rr_cookie_create(struct in6_addr *addr, u8 **ckie, u16 nonce_index);
-+
-+/* Calculate return routability key from home and care-of cookies, key length is
-+ * HMAC_SHA1_KEY_SIZE
-+ */
-+extern u_int8_t *mipv6_rr_key_calc(u8 *hoc, u8 *coc);
-+
-+extern struct mipv6_rr_nonce *mipv6_rr_get_new_nonce(void);
-+
-+/* For avoiding replay attacks when MN deregisters */
-+extern void mipv6_rr_invalidate_nonce(u16 nonce_index);
-+/*
-+ * initializes the return routability crypto
-+ */
-+
-+void mipv6_rr_init(void);
-+
-+#ifdef TEST_MIPV6_RR_CRYPTO
-+void mipv6_test_rr(void);
-+#endif /* TEST_MIPV6_RR_CRYPTO */
-+
-+#endif /* RR_CRYPTO */
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/sortedlist.c
-@@ -0,0 +1,349 @@
-+/**
-+ * Sorted list - linked list with sortkey.
-+ *
-+ * Authors:
-+ * Jaakko Laine <medved@iki.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/kernel.h>
-+#include <linux/types.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+
-+struct mipv6_sorted_list_entry {
-+ struct list_head list;
-+ void *data;
-+ int datalen;
-+ unsigned long sortkey;
-+};
-+
-+/**
-+ * compare - compares two arbitrary data items
-+ * @data1: first data item
-+ * @data2: second data item
-+ * @datalen: length of data items in bits
-+ *
-+ * datalen is in bits!
-+ */
-+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen)
-+{
-+ int n = datalen;
-+ __u8 * ptr1 = (__u8 *)data1;
-+ __u8 * ptr2 = (__u8 *)data2;
-+
-+ for (; n>=0; n-=8, ptr1++, ptr2++) {
-+ if (n >= 8) {
-+ if (*ptr1 != *ptr2)
-+ return 0;
-+ } else {
-+ if ((*ptr1 ^ *ptr2) & ((~0) << (8 - n)))
-+ return 0;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/**
-+ * mipv6_slist_add - add an entry to sorted list
-+ * @head: list_head of the sorted list
-+ * @data: item to store
-+ * @datalen: length of data (in bytes)
-+ * @key: sortkey of item
-+ *
-+ * Allocates memory for entry and data
-+ */
-+int mipv6_slist_add(struct list_head *head, void *data, int datalen,
-+ unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry, *tmp, *next;
-+
-+ entry = kmalloc(sizeof(struct mipv6_sorted_list_entry), GFP_ATOMIC);
-+
-+ if (!entry)
-+ return -1;
-+
-+ entry->data = kmalloc(datalen, GFP_ATOMIC);
-+
-+ if (!entry->data) {
-+ kfree(entry);
-+ return -1;
-+ }
-+
-+ memcpy(entry->data, data, datalen);
-+ entry->datalen = datalen;
-+ entry->sortkey = sortkey;
-+
-+ if ((pos = head->next) == head) {
-+ list_add(&entry->list, head);
-+ return 0;
-+ }
-+
-+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey < tmp->sortkey) {
-+ list_add(&entry->list, head);
-+ return 0;
-+ }
-+
-+ for (; pos != head; pos = pos->next) {
-+ tmp = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (pos->next == head) {
-+ list_add(&entry->list, &tmp->list);
-+ return 0;
-+ }
-+ next = list_entry(pos->next, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey >= tmp->sortkey && entry->sortkey < next->sortkey) {
-+ list_add(&entry->list, &tmp->list);
-+ return 0;
-+ }
-+ }
-+
-+ /* never reached */
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_slist_get_first - get the first data item in the list
-+ * @head: list_head of the sorted list
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_first(struct list_head *head)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return NULL;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ return entry->data;
-+}
-+
-+/**
-+ * mipv6_slist_del_first - delete (and get) the first item in list
-+ * @head: list_head of the sorted list
-+ *
-+ * Remember to kfree the item
-+ */
-+void *mipv6_slist_del_first(struct list_head *head)
-+{
-+ void *tmp;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return NULL;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ tmp = entry->data;
-+
-+ list_del(head->next);
-+ kfree(entry);
-+
-+ return tmp;
-+}
-+
-+/**
-+ * mipv6_slist_del_item - delete entry
-+ * @head: list_head of the sorted list
-+ * @data: item to delete
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+int mipv6_slist_del_item(struct list_head *head, void *data,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for(pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, entry->datalen)) {
-+ list_del(pos);
-+ kfree(entry->data);
-+ kfree(entry);
-+ return 0;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+/**
-+ * mipv6_slist_get_first_key - get sortkey of the first item
-+ * @head: list_head of the sorted list
-+ */
-+unsigned long mipv6_slist_get_first_key(struct list_head *head)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return 0;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ return entry->sortkey;
-+}
-+
-+/**
-+ * mipv6_slist_get_key - get sortkey of the data item
-+ * @head: list_head of the sorted list
-+ * @data: the item to search for
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+unsigned long mipv6_slist_get_key(struct list_head *head, void *data,
-+ int (*compare)(const void *data1,
-+ const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for(pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, entry->datalen))
-+ return entry->sortkey;
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_slist_get_data - get the data item identified by sortkey
-+ * @head: list_head of the sorted list
-+ * @key: sortkey of the item
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_for_each(pos, head) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (entry->sortkey == sortkey)
-+ return entry->data;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * reorder_entry - move an entry to a new position according to sortkey
-+ * @head: list_head of the sorted list
-+ * @entry_pos: current place of the entry
-+ * @key: new sortkey
-+ */
-+static void reorder_entry(struct list_head *head, struct list_head *entry_pos,
-+ unsigned long sortkey)
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_del(entry_pos);
-+
-+ for (pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (sortkey >= entry->sortkey) {
-+ list_add(entry_pos, &entry->list);
-+ return;
-+ }
-+ }
-+
-+ list_add(entry_pos, head);
-+}
-+
-+/**
-+ * mipv6_slist_modify - modify data item
-+ * @head: list_head of the sorted list
-+ * @data: item, whose sortkey is to be modified
-+ * @datalen: datalen in bytes
-+ * @new_key: new sortkey
-+ * @compare: function used for comparing the data items
-+ *
-+ * Compies the new data on top of the old one, if compare function returns
-+ * true. If there's no matching entry, new one will be created.
-+ * Compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen)
-+ */
-+int mipv6_slist_modify(struct list_head *head, void *data, int datalen,
-+ unsigned long new_key,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ for (pos = head->next; pos != head; pos = pos->next) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (compare(data, entry->data, datalen)) {
-+ memcpy(entry->data, data, datalen);
-+ entry->sortkey = new_key;
-+ reorder_entry(head, &entry->list, new_key);
-+ return 0;
-+ }
-+ }
-+
-+ return mipv6_slist_add(head, data, datalen, new_key);
-+}
-+
-+/**
-+ * mipv6_slist_push_first - move the first entry to place indicated by new_key
-+ * @head: list_head of the sorted list
-+ * @new_key: new sortkey
-+ */
-+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key)
-+{
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ if (list_empty(head))
-+ return -1;
-+
-+ entry = list_entry(head->next, struct mipv6_sorted_list_entry, list);
-+ entry->sortkey = new_key;
-+
-+ reorder_entry(head, head->next, new_key);
-+ return 0;
-+}
-+
-+/**
-+ * mipv6_slist_for_each - apply func to every item in list
-+ * @head: list_head of the sorted list
-+ * @args: args to pass to func
-+ * @func: function to use
-+ *
-+ * function must be of type
-+ * int (*func)(void *data, void *args, unsigned long sortkey)
-+ * List iteration will stop once func has been applied to every item
-+ * or when func returns true
-+ */
-+int mipv6_slist_for_each(struct list_head *head, void *args,
-+ int (*func)(void *data, void *args,
-+ unsigned long sortkey))
-+{
-+ struct list_head *pos;
-+ struct mipv6_sorted_list_entry *entry;
-+
-+ list_for_each(pos, head) {
-+ entry = list_entry(pos, struct mipv6_sorted_list_entry, list);
-+ if (func(entry->data, args, entry->sortkey))
-+ break;
-+ }
-+
-+ return 0;
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/sortedlist.h
-@@ -0,0 +1,133 @@
-+/*
-+ * Sorted list - linked list with sortkey
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+/**
-+ * compare - compares two arbitrary data items
-+ * @data1: first data item
-+ * @data2: second data item
-+ * @datalen: length of data items in bits
-+ *
-+ * datalen is in bits!
-+ */
-+int mipv6_bitwise_compare(const void *data1, const void *data2, int datalen);
-+
-+/**
-+ * mipv6_slist_add - add an entry to sorted list
-+ * @head: list_head of the sorted list
-+ * @data: item to store
-+ * @datalen: length of data (in bytes)
-+ * @key: sortkey of item
-+ *
-+ * Allocates memory for entry and data
-+ */
-+int mipv6_slist_add(struct list_head *head, void *data, int datalen,
-+ unsigned long sortkey);
-+
-+/**
-+ * mipv6_slist_get_first - get the first data item in the list
-+ * @head: list_head of the sorted list
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_first(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_del_first - delete (and get) the first item in list
-+ * @head: list_head of the sorted list
-+ *
-+ * Remember to kfree the item
-+ */
-+void *mipv6_slist_del_first(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_del_item - delete entry
-+ * @head: list_head of the sorted list
-+ * @data: item to delete
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits
-+ */
-+int mipv6_slist_del_item(struct list_head *head, void *data,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_get_first_key - get sortkey of the first item
-+ * @head: list_head of the sorted list
-+ */
-+unsigned long mipv6_slist_get_first_key(struct list_head *head);
-+
-+/**
-+ * mipv6_slist_get_key - get sortkey of the data item
-+ * @head: list_head of the sorted list
-+ * @data: the item to search for
-+ * @compare: function used for comparing the data items
-+ *
-+ * compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits
-+ */
-+unsigned long mipv6_slist_get_key(struct list_head *head, void *data,
-+ int (*compare)(const void *data1,
-+ const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_get_data - get the data item identified by sortkey
-+ * @head: list_head of the sorted list
-+ * @key: sortkey of the item
-+ *
-+ * Returns the actual data item, not copy, so don't kfree it
-+ */
-+void *mipv6_slist_get_data(struct list_head *head, unsigned long sortkey);
-+
-+/**
-+ * mipv6_slist_modify - modify data item
-+ * @head: list_head of the sorted list
-+ * @data: item, whose sortkey is to be modified
-+ * @datalen: datalen in bytes
-+ * @new_key: new sortkey
-+ * @compare: function used for comparing the data items
-+ *
-+ * Compies the new data on top of the old one, if compare function returns
-+ * non-negative. If there's no matching entry, new one will be created.
-+ * Compare function needs to have prototype
-+ * int (*compare)(const void *data1, const void *data2, int datalen) where
-+ * datalen is in bits.
-+ */
-+int mipv6_slist_modify(struct list_head *head, void *data, int datalen,
-+ unsigned long new_key,
-+ int (*compare)(const void *data1, const void *data2,
-+ int datalen));
-+
-+/**
-+ * mipv6_slist_push_first - move the first entry to place indicated by new_key
-+ * @head: list_head of the sorted list
-+ * @new_key: new sortkey
-+ */
-+int mipv6_slist_push_first(struct list_head *head, unsigned long new_key);
-+
-+/**
-+ * mipv6_slist_for_each - apply func to every item in list
-+ * @head: list_head of the sorted list
-+ * @args: args to pass to func
-+ * @func: function to use
-+ *
-+ * function must be of type
-+ * int (*func)(void *data, void *args, unsigned long sortkey)
-+ * List iteration will stop once func has been applied to every item
-+ * or when func returns true
-+ */
-+int mipv6_slist_for_each(struct list_head *head, void *args,
-+ int (*func)(void *data, void *args,
-+ unsigned long sortkey));
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/stats.c
-@@ -0,0 +1,90 @@
-+/*
-+ * Statistics module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Changes:
-+ * Krishna Kumar,
-+ * Venkata Jagana : SMP locking fix
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/proc_fs.h>
-+#include "stats.h"
-+
-+struct mipv6_statistics mipv6_stats;
-+
-+static int proc_info_dump(
-+ char *buffer, char **start,
-+ off_t offset, int length)
-+{
-+ struct inf {
-+ char *name;
-+ int *value;
-+ } int_stats[] = {
-+ {"NEncapsulations", &mipv6_stats.n_encapsulations},
-+ {"NDecapsulations", &mipv6_stats.n_decapsulations},
-+ {"NBindRefreshRqsRcvd", &mipv6_stats.n_brr_rcvd},
-+ {"NHomeTestInitsRcvd", &mipv6_stats.n_hoti_rcvd},
-+ {"NCareofTestInitsRcvd", &mipv6_stats.n_coti_rcvd},
-+ {"NHomeTestRcvd", &mipv6_stats.n_hot_rcvd},
-+ {"NCareofTestRcvd", &mipv6_stats.n_cot_rcvd},
-+ {"NBindUpdatesRcvd", &mipv6_stats.n_bu_rcvd},
-+ {"NBindAcksRcvd", &mipv6_stats.n_ba_rcvd},
-+ {"NBindNAcksRcvd", &mipv6_stats.n_ban_rcvd},
-+ {"NBindErrorsRcvd", &mipv6_stats.n_be_rcvd},
-+ {"NBindRefreshRqsSent", &mipv6_stats.n_brr_sent},
-+ {"NHomeTestInitsSent", &mipv6_stats.n_hoti_sent},
-+ {"NCareofTestInitsSent", &mipv6_stats.n_coti_sent},
-+ {"NHomeTestSent", &mipv6_stats.n_hot_sent},
-+ {"NCareofTestSent", &mipv6_stats.n_cot_sent},
-+ {"NBindUpdatesSent", &mipv6_stats.n_bu_sent},
-+ {"NBindAcksSent", &mipv6_stats.n_ba_sent},
-+ {"NBindNAcksSent", &mipv6_stats.n_ban_sent},
-+ {"NBindErrorsSent", &mipv6_stats.n_be_sent},
-+ {"NBindUpdatesDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindUpdatesDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindUpdatesDropMisc", &mipv6_stats.n_bu_drop.misc},
-+ {"NBindAcksDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindAcksDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindAcksDropMisc", &mipv6_stats.n_bu_drop.misc},
-+ {"NBindRqsDropAuth", &mipv6_stats.n_bu_drop.auth},
-+ {"NBindRqsDropInvalid", &mipv6_stats.n_bu_drop.invalid},
-+ {"NBindRqsDropMisc", &mipv6_stats.n_bu_drop.misc}
-+ };
-+
-+ int i;
-+ int len = 0;
-+ for(i=0; i<sizeof(int_stats) / sizeof(struct inf); i++) {
-+ len += sprintf(buffer + len, "%s = %d\n",
-+ int_stats[i].name, *int_stats[i].value);
-+ }
-+
-+ *start = buffer + offset;
-+
-+ len -= offset;
-+
-+ if(len > length) len = length;
-+
-+ return len;
-+}
-+
-+int mipv6_stats_init(void)
-+{
-+ memset(&mipv6_stats, 0, sizeof(struct mipv6_statistics));
-+ proc_net_create("mip6_stat", 0, proc_info_dump);
-+ return 0;
-+}
-+
-+void mipv6_stats_exit(void)
-+{
-+ proc_net_remove("mip6_stat");
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/stats.h
-@@ -0,0 +1,71 @@
-+/*
-+ * MIPL Mobile IPv6 Statistics header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _STATS_H
-+#define _STATS_H
-+
-+struct mipv6_drop {
-+ __u32 auth;
-+ __u32 invalid;
-+ __u32 misc;
-+};
-+
-+struct mipv6_statistics {
-+ int n_encapsulations;
-+ int n_decapsulations;
-+ int n_mh_in_msg;
-+ int n_mh_in_error;
-+ int n_mh_out_msg;
-+ int n_mh_out_error;
-+
-+ int n_brr_rcvd;
-+ int n_hoti_rcvd;
-+ int n_coti_rcvd;
-+ int n_hot_rcvd;
-+ int n_cot_rcvd;
-+ int n_bu_rcvd;
-+ int n_ba_rcvd;
-+ int n_ban_rcvd;
-+ int n_be_rcvd;
-+
-+ int n_brr_sent;
-+ int n_hoti_sent;
-+ int n_coti_sent;
-+ int n_hot_sent;
-+ int n_cot_sent;
-+ int n_bu_sent;
-+ int n_ba_sent;
-+ int n_ban_sent;
-+ int n_be_sent;
-+
-+ int n_ha_rcvd;
-+ int n_ha_sent;
-+
-+ struct mipv6_drop n_bu_drop;
-+ struct mipv6_drop n_ba_drop;
-+ struct mipv6_drop n_brr_drop;
-+ struct mipv6_drop n_be_drop;
-+ struct mipv6_drop n_ha_drop;
-+};
-+
-+extern struct mipv6_statistics mipv6_stats;
-+
-+#ifdef CONFIG_SMP
-+/* atomic_t is max 24 bits long */
-+#define MIPV6_INC_STATS(X) atomic_inc((atomic_t *)&mipv6_stats.X);
-+#else
-+#define MIPV6_INC_STATS(X) mipv6_stats.X++;
-+#endif
-+
-+int mipv6_stats_init(void);
-+void mipv6_stats_exit(void);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/tunnel.h
-@@ -0,0 +1,35 @@
-+/*
-+ * MIPL Mobile IPv6 IP6-IP6 tunneling header file
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _TUNNEL_H
-+#define _TUNNEL_H
-+
-+#include <linux/in6.h>
-+#include <linux/if_arp.h>
-+#include <net/ipv6_tunnel.h>
-+
-+static __inline__ int is_mip6_tnl(struct ip6_tnl *t)
-+{
-+ return (t != NULL &&
-+ t->parms.flags & IP6_TNL_F_KERNEL_DEV &&
-+ t->parms.flags & IP6_TNL_F_MIP6_DEV);
-+
-+}
-+
-+static __inline__ int dev_is_mip6_tnl(struct net_device *dev)
-+{
-+ struct ip6_tnl *t = (struct ip6_tnl *)dev->priv;
-+ return (dev->type == ARPHRD_TUNNEL6 && is_mip6_tnl(t));
-+}
-+
-+
-+#endif
-+
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/tunnel_ha.c
-@@ -0,0 +1,264 @@
-+/*
-+ * IPv6-IPv6 tunneling module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Ville Nuorvala <vnuorval@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/netdevice.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/ipv6_route.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/protocol.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/dst.h>
-+#include <net/addrconf.h>
-+
-+#include "tunnel.h"
-+#include "debug.h"
-+#include "stats.h"
-+#include "config.h"
-+
-+#define MIPV6_TNL_MAX IP6_TNL_MAX
-+#define MIPV6_TNL_MIN 1
-+
-+int mipv6_max_tnls = 3;
-+int mipv6_min_tnls = 1;
-+
-+DECLARE_MUTEX(tnl_sem);
-+
-+int mipv6_max_tnls_sysctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ down(&tnl_sem);
-+ if (write) {
-+ int diff;
-+ int old_max_tnls = mipv6_max_tnls;
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ if (err < 0)
-+ goto out;
-+ if (mipv6_max_tnls < mipv6_min_tnls ||
-+ mipv6_max_tnls > MIPV6_TNL_MAX) {
-+ mipv6_max_tnls = old_max_tnls;
-+ goto out;
-+ }
-+ if (mipv6_max_tnls < old_max_tnls) {
-+ diff = old_max_tnls - mipv6_max_tnls;
-+ ip6ip6_tnl_dec_max_kdev_count(diff);
-+ } else if (mipv6_max_tnls > old_max_tnls) {
-+ diff = mipv6_max_tnls - old_max_tnls;
-+ ip6ip6_tnl_inc_max_kdev_count(diff);
-+ }
-+ } else {
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ }
-+out:
-+ up(&tnl_sem);
-+ return err;
-+}
-+
-+int mipv6_min_tnls_sysctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ down(&tnl_sem);
-+ if (write) {
-+ int diff;
-+ int old_min_tnls = mipv6_min_tnls;
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ if (err < 0)
-+ goto out;
-+ if (mipv6_min_tnls > mipv6_max_tnls ||
-+ mipv6_min_tnls < MIPV6_TNL_MIN) {
-+ mipv6_min_tnls = old_min_tnls;
-+ goto out;
-+ }
-+ if (mipv6_min_tnls < old_min_tnls) {
-+ diff = old_min_tnls - mipv6_min_tnls;
-+ ip6ip6_tnl_dec_min_kdev_count(diff);
-+ } else if (mipv6_min_tnls > old_min_tnls) {
-+ diff = mipv6_min_tnls - old_min_tnls;
-+ ip6ip6_tnl_inc_min_kdev_count(diff);
-+ }
-+ } else {
-+ err = proc_dointvec(ctl, write, filp, buffer, lenp);
-+ }
-+out:
-+ up(&tnl_sem);
-+ return err;
-+}
-+
-+static __inline__ int mipv6_tnl_add(struct in6_addr *remote,
-+ struct in6_addr *local)
-+{
-+ struct ip6_tnl_parm p;
-+ int ret;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ ipv6_addr_copy(&p.laddr, local);
-+ ipv6_addr_copy(&p.raddr, remote);
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+
-+ ret = ip6ip6_kernel_tnl_add(&p);
-+ if (ret > 0) {
-+ DEBUG(DBG_INFO, "added tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+ } else {
-+ DEBUG(DBG_WARNING, "unable to add tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+ }
-+ return ret;
-+}
-+
-+static __inline__ int mipv6_tnl_del(struct in6_addr *remote,
-+ struct in6_addr *local)
-+{
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(remote, local);
-+
-+ DEBUG_FUNC();
-+
-+ if (t != NULL && (t->parms.flags & IP6_TNL_F_MIP6_DEV)) {
-+ DEBUG(DBG_INFO, "deleting tunnel from: "
-+ "%x:%x:%x:%x:%x:%x:%x:%x to: %x:%x:%x:%x:%x:%x:%x:%x",
-+ NIPV6ADDR(local), NIPV6ADDR(remote));
-+
-+ return ip6ip6_kernel_tnl_del(t);
-+ }
-+ return 0;
-+}
-+
-+static int add_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct in6_rtmsg rtmsg;
-+ int err;
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr);
-+
-+ if (!is_mip6_tnl(t)) {
-+ DEBUG(DBG_CRITICAL,"Tunnel missing");
-+ return -ENODEV;
-+ }
-+
-+ DEBUG(DBG_INFO, "adding route to: %x:%x:%x:%x:%x:%x:%x:%x via "
-+ "tunnel device", NIPV6ADDR(home_addr));
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr);
-+ rtmsg.rtmsg_dst_len = 128;
-+ rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-+ rtmsg.rtmsg_flags = RTF_UP | RTF_NONEXTHOP | RTF_HOST | RTF_MOBILENODE;
-+ rtmsg.rtmsg_ifindex = t->dev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) {
-+ err = 0;
-+ }
-+ return err;
-+}
-+
-+static void del_route_to_mn(struct in6_addr *coa, struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ struct ip6_tnl *t = ip6ip6_tnl_lookup(coa, ha_addr);
-+
-+ DEBUG_FUNC();
-+
-+ if (is_mip6_tnl(t)) {
-+ struct in6_rtmsg rtmsg;
-+
-+ DEBUG(DBG_INFO, "deleting route to: %x:%x:%x:%x:%x:%x:%x:%x "
-+ " via tunnel device", NIPV6ADDR(home_addr));
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_dst, home_addr);
-+ rtmsg.rtmsg_dst_len = 128;
-+ rtmsg.rtmsg_ifindex = t->dev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ ip6_route_del(&rtmsg, NULL);
-+ }
-+}
-+
-+
-+int mipv6_add_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ int ret;
-+
-+ DEBUG_FUNC();
-+
-+ ret = mipv6_tnl_add(coa, ha_addr);
-+
-+ if (ret > 0) {
-+ int err = add_route_to_mn(coa, ha_addr, home_addr);
-+ if (err) {
-+ if (err != -ENODEV) {
-+ mipv6_tnl_del(coa, ha_addr);
-+ }
-+ return err;
-+ }
-+ }
-+ return ret;
-+}
-+
-+int mipv6_del_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr)
-+{
-+ DEBUG_FUNC();
-+ del_route_to_mn(coa, ha_addr, home_addr);
-+ return mipv6_tnl_del(coa, ha_addr);
-+}
-+
-+__init void mipv6_initialize_tunnel(void)
-+{
-+ down(&tnl_sem);
-+ ip6ip6_tnl_inc_max_kdev_count(mipv6_max_tnls);
-+ ip6ip6_tnl_inc_min_kdev_count(mipv6_min_tnls);
-+ up(&tnl_sem);
-+ mip6_fn.bce_tnl_rt_add = add_route_to_mn;
-+ mip6_fn.bce_tnl_rt_del = del_route_to_mn;
-+}
-+
-+__exit void mipv6_shutdown_tunnel(void)
-+{
-+ mip6_fn.bce_tnl_rt_del = NULL;
-+ mip6_fn.bce_tnl_rt_add = NULL;
-+ down(&tnl_sem);
-+ ip6ip6_tnl_dec_min_kdev_count(mipv6_min_tnls);
-+ ip6ip6_tnl_dec_max_kdev_count(mipv6_max_tnls);
-+ up(&tnl_sem);
-+}
-+
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/tunnel_ha.h
-@@ -0,0 +1,20 @@
-+#ifndef _TUNNEL_HA_H
-+#define _TUNNEL_HA_H
-+
-+#include "tunnel.h"
-+
-+extern int mipv6_max_tnls;
-+extern int mipv6_min_tnls;
-+
-+extern void mipv6_initialize_tunnel(void);
-+extern void mipv6_shutdown_tunnel(void);
-+
-+extern int mipv6_add_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+extern int mipv6_del_tnl_to_mn(struct in6_addr *coa,
-+ struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/tunnel_mn.c
-@@ -0,0 +1,160 @@
-+/*
-+ * IPv6-IPv6 tunneling module
-+ *
-+ * Authors:
-+ * Sami Kivisaari <skivisaa@cc.hut.fi>
-+ * Ville Nuorvala <vnuorval@tml.hut.fi>
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/ipv6.h>
-+#include <linux/net.h>
-+#include <linux/netdevice.h>
-+#include <linux/init.h>
-+#include <linux/route.h>
-+#include <linux/ipv6_route.h>
-+
-+#ifdef CONFIG_SYSCTL
-+#include <linux/sysctl.h>
-+#endif /* CONFIG_SYSCTL */
-+
-+#include <net/protocol.h>
-+#include <net/ipv6.h>
-+#include <net/ip6_route.h>
-+#include <net/dst.h>
-+#include <net/addrconf.h>
-+
-+#include "tunnel.h"
-+#include "debug.h"
-+#include "stats.h"
-+
-+static struct net_device *mn_ha_tdev;
-+
-+static spinlock_t mn_ha_lock = SPIN_LOCK_UNLOCKED;
-+
-+static __inline__ int add_reverse_route(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ struct net_device *tdev)
-+{
-+ struct in6_rtmsg rtmsg;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr);
-+ rtmsg.rtmsg_src_len = 128;
-+ rtmsg.rtmsg_flags = RTF_UP | RTF_DEFAULT;
-+ rtmsg.rtmsg_ifindex = tdev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ if ((err = ip6_route_add(&rtmsg, NULL)) == -EEXIST) {
-+ return 0;
-+ }
-+ return err;
-+}
-+
-+static __inline__ void del_reverse_route(struct in6_addr *ha_addr,
-+ struct in6_addr *home_addr,
-+ struct net_device *tdev)
-+{
-+ struct in6_rtmsg rtmsg;
-+
-+ DEBUG(DBG_INFO, "removing reverse route via tunnel device");
-+
-+ memset(&rtmsg, 0, sizeof(rtmsg));
-+ ipv6_addr_copy(&rtmsg.rtmsg_src, home_addr);
-+ rtmsg.rtmsg_src_len = 128;
-+ rtmsg.rtmsg_ifindex = tdev->ifindex;
-+ rtmsg.rtmsg_metric = IP6_RT_PRIO_MIPV6;
-+ ip6_route_del(&rtmsg, NULL);
-+}
-+
-+int mipv6_add_tnl_to_ha(void)
-+{
-+ struct ip6_tnl_parm p;
-+ struct ip6_tnl *t;
-+ int err;
-+
-+ DEBUG_FUNC();
-+
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+ strcpy(p.name, "mip6mnha1");
-+
-+ rtnl_lock();
-+ if ((err = ip6ip6_tnl_create(&p, &t))) {
-+ rtnl_unlock();
-+ return err;
-+ }
-+ spin_lock_bh(&mn_ha_lock);
-+
-+ if (!mn_ha_tdev) {
-+ mn_ha_tdev = t->dev;
-+ dev_hold(mn_ha_tdev);
-+ }
-+ spin_unlock_bh(&mn_ha_lock);
-+ dev_open(t->dev);
-+ rtnl_unlock();
-+ return 0;
-+}
-+
-+int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr,
-+ struct in6_addr *coa,
-+ struct in6_addr *home_addr)
-+{
-+ int err = -ENODEV;
-+
-+ DEBUG_FUNC();
-+
-+ spin_lock_bh(&mn_ha_lock);
-+ if (mn_ha_tdev) {
-+ struct ip6_tnl_parm p;
-+ memset(&p, 0, sizeof(p));
-+ p.proto = IPPROTO_IPV6;
-+ ipv6_addr_copy(&p.laddr, coa);
-+ ipv6_addr_copy(&p.raddr, ha_addr);
-+ p.hop_limit = 255;
-+ p.flags = (IP6_TNL_F_KERNEL_DEV | IP6_TNL_F_MIP6_DEV |
-+ IP6_TNL_F_IGN_ENCAP_LIMIT);
-+
-+ ip6ip6_tnl_change((struct ip6_tnl *) mn_ha_tdev->priv, &p);
-+ if (ipv6_addr_cmp(coa, home_addr)) {
-+ err = add_reverse_route(ha_addr, home_addr,
-+ mn_ha_tdev);
-+ } else {
-+ del_reverse_route(ha_addr, home_addr, mn_ha_tdev);
-+ err = 0;
-+ }
-+ }
-+ spin_unlock_bh(&mn_ha_lock);
-+ return err;
-+}
-+
-+void mipv6_del_tnl_to_ha(void)
-+{
-+ struct net_device *dev;
-+
-+ DEBUG_FUNC();
-+
-+ rtnl_lock();
-+ spin_lock_bh(&mn_ha_lock);
-+ dev = mn_ha_tdev;
-+ mn_ha_tdev = NULL;
-+ spin_unlock_bh(&mn_ha_lock);
-+ dev_put(dev);
-+ unregister_netdevice(dev);
-+ rtnl_unlock();
-+}
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/tunnel_mn.h
-@@ -0,0 +1,14 @@
-+#ifndef _TUNNEL_MN_H
-+#define _TUNNEL_MN_H
-+
-+#include "tunnel.h"
-+
-+extern int mipv6_add_tnl_to_ha(void);
-+
-+extern int mipv6_mv_tnl_to_ha(struct in6_addr *ha_addr,
-+ struct in6_addr *coa,
-+ struct in6_addr *home_addr);
-+
-+extern int mipv6_del_tnl_to_ha(void);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/net/ipv6/mobile_ip6/util.h
-@@ -0,0 +1,91 @@
-+/*
-+ * MIPL Mobile IPv6 Utility functions
-+ *
-+ * $Id$
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _UTIL_H
-+#define _UTIL_H
-+
-+#include <linux/in6.h>
-+#include <asm/byteorder.h>
-+
-+/**
-+ * mipv6_prefix_compare - Compare two IPv6 prefixes
-+ * @addr: IPv6 address
-+ * @prefix: IPv6 address
-+ * @nprefix: number of bits to compare
-+ *
-+ * Perform prefix comparison bitwise for the @nprefix first bits
-+ * Returns 1, if the prefixes are the same, 0 otherwise
-+ **/
-+static inline int mipv6_prefix_compare(const struct in6_addr *addr,
-+ const struct in6_addr *prefix,
-+ const unsigned int pfix_len)
-+{
-+ int i;
-+ unsigned int nprefix = pfix_len;
-+
-+ if (nprefix > 128)
-+ return 0;
-+
-+ for (i = 0; nprefix > 0; nprefix -= 32, i++) {
-+ if (nprefix >= 32) {
-+ if (addr->s6_addr32[i] != prefix->s6_addr32[i])
-+ return 0;
-+ } else {
-+ if (((addr->s6_addr32[i] ^ prefix->s6_addr32[i]) &
-+ ((~0) << (32 - nprefix))) != 0)
-+ return 0;
-+ return 1;
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/**
-+ * homeagent_anycast - Compute Home Agent anycast address
-+ * @ac_addr: append home agent anycast suffix to passed prefix
-+ * @prefix: prefix ha anycast address is generated from
-+ * @plen: length of prefix in bits
-+ *
-+ * Calculate corresponding Home Agent Anycast Address (RFC2526) in a
-+ * given subnet.
-+ */
-+static inline int
-+mipv6_ha_anycast(struct in6_addr *ac_addr, struct in6_addr *prefix, int plen)
-+{
-+ if (plen <= 0 || plen > 120) {
-+ /* error, interface id should be minimum 8 bits */
-+ return -1;
-+ }
-+ ipv6_addr_copy(ac_addr, prefix);
-+
-+ if (plen < 32)
-+ ac_addr->s6_addr32[0] |= htonl((u32)(~0) >> plen);
-+ if (plen < 64)
-+ ac_addr->s6_addr32[1] |= htonl((u32)(~0) >> (plen > 32 ? plen % 32 : 0));
-+ if (plen < 92)
-+ ac_addr->s6_addr32[2] |= htonl((u32)(~0) >> (plen > 64 ? plen % 32 : 0));
-+ if (plen <= 120)
-+ ac_addr->s6_addr32[3] |= htonl((u32)(~0) >> (plen > 92 ? plen % 32 : 0));
-+
-+ /* RFC2526: for interface identifiers in EUI-64
-+ * format, the universal/local bit in the interface
-+ * identifier MUST be set to 0. */
-+ if (plen == 64) {
-+ ac_addr->s6_addr32[2] &= (int)htonl(0xfdffffff);
-+ }
-+ /* Mobile IPv6 Home-Agents anycast id (0x7e) */
-+ ac_addr->s6_addr32[3] &= (int)htonl(0xfffffffe);
-+
-+ return 0;
-+}
-+
-+#endif /* _UTIL_H */
---- linux-2.4.27/net/ipv6/ndisc.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/ndisc.c
-@@ -23,6 +23,7 @@
- * and moved to net/core.
- * Pekka Savola : RFC2461 validation
- * YOSHIFUJI Hideaki @USAGI : Verify ND options properly
-+ * Ville Nuorvala : RFC2461 fixes to proxy ND
- */
-
- /* Set to 3 to get tracing... */
-@@ -70,6 +71,7 @@
- #include <net/ip6_route.h>
- #include <net/addrconf.h>
- #include <net/icmp.h>
-+#include <net/mipglue.h>
-
- #include <net/checksum.h>
- #include <linux/proc_fs.h>
-@@ -187,6 +189,8 @@
- case ND_OPT_TARGET_LL_ADDR:
- case ND_OPT_MTU:
- case ND_OPT_REDIRECT_HDR:
-+ case ND_OPT_RTR_ADV_INTERVAL:
-+ case ND_OPT_HOME_AGENT_INFO:
- if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
- ND_PRINTK2((KERN_WARNING
- "ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
-@@ -372,8 +376,8 @@
- */
-
- void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
-- struct in6_addr *daddr, struct in6_addr *solicited_addr,
-- int router, int solicited, int override, int inc_opt)
-+ struct in6_addr *daddr, struct in6_addr *solicited_addr,
-+ int router, int solicited, int override, int inc_opt)
- {
- static struct in6_addr tmpaddr;
- struct inet6_ifaddr *ifp;
-@@ -766,7 +770,8 @@
- int addr_type = ipv6_addr_type(saddr);
-
- if (in6_dev && in6_dev->cnf.forwarding &&
-- (addr_type & IPV6_ADDR_UNICAST) &&
-+ (addr_type & IPV6_ADDR_UNICAST ||
-+ addr_type == IPV6_ADDR_ANY) &&
- pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
- int inc = ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST;
-
-@@ -778,13 +783,21 @@
- nd_tbl.stats.rcv_probes_mcast++;
- else
- nd_tbl.stats.rcv_probes_ucast++;
--
-- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-
-- if (neigh) {
-- ndisc_send_na(dev, neigh, saddr, &msg->target,
-- 0, 1, 0, 1);
-- neigh_release(neigh);
-+ if (addr_type & IPV6_ADDR_UNICAST) {
-+ neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-+
-+ if (neigh) {
-+ ndisc_send_na(dev, neigh, saddr, &msg->target,
-+ 0, 1, 0, 1);
-+ neigh_release(neigh);
-+ }
-+ } else {
-+ /* the proxy should also protect against DAD */
-+ struct in6_addr maddr;
-+ ipv6_addr_all_nodes(&maddr);
-+ ndisc_send_na(dev, NULL, &maddr, &msg->target,
-+ 0, 0, 0, 1);
- }
- } else {
- struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
-@@ -849,6 +862,9 @@
- if (ifp->flags & IFA_F_TENTATIVE) {
- addrconf_dad_failure(ifp);
- return;
-+ } else if (ndisc_mip_mn_ha_probe(ifp, lladdr)) {
-+ in6_ifa_put(ifp);
-+ return;
- }
- /* What should we make now? The advertisement
- is invalid, but ndisc specs say nothing
-@@ -887,6 +903,7 @@
- msg->icmph.icmp6_override, 1);
- neigh_release(neigh);
- }
-+ ndisc_check_mipv6_dad(&msg->target);
- }
-
- static void ndisc_router_discovery(struct sk_buff *skb)
-@@ -894,6 +911,7 @@
- struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
- struct neighbour *neigh;
- struct inet6_dev *in6_dev;
-+ int change_rtr;
- struct rt6_info *rt;
- int lifetime;
- struct ndisc_options ndopts;
-@@ -923,10 +941,6 @@
- ND_PRINTK1("RA: can't find in6 device\n");
- return;
- }
-- if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
-- in6_dev_put(in6_dev);
-- return;
-- }
-
- if (!ndisc_parse_options(opt, optlen, &ndopts)) {
- in6_dev_put(in6_dev);
-@@ -935,7 +949,12 @@
- "ICMP6 RA: invalid ND option, ignored.\n");
- return;
- }
-+ change_rtr = ndisc_mipv6_ra_rcv(skb, &ndopts);
-
-+ if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) {
-+ in6_dev_put(in6_dev);
-+ return;
-+ }
- if (in6_dev->if_flags & IF_RS_SENT) {
- /*
- * flag that an RA was received after an RS was sent
-@@ -963,8 +982,7 @@
- ip6_del_rt(rt, NULL);
- rt = NULL;
- }
--
-- if (rt == NULL && lifetime) {
-+ if (rt == NULL && lifetime && change_rtr) {
- ND_PRINTK2("ndisc_rdisc: adding default router\n");
-
- rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
-@@ -1087,6 +1105,8 @@
- if (rt)
- dst_release(&rt->u.dst);
- in6_dev_put(in6_dev);
-+
-+ ndisc_mipv6_change_router(change_rtr);
- }
-
- static void ndisc_redirect_rcv(struct sk_buff *skb)
---- linux-2.4.27/net/ipv6/raw.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/raw.c
-@@ -43,6 +43,7 @@
- #include <net/transp_v6.h>
- #include <net/udp.h>
- #include <net/inet_common.h>
-+#include <net/mipglue.h>
-
- #include <net/rawv6.h>
-
-@@ -641,6 +642,7 @@
- hdr.daddr = daddr;
- else
- hdr.daddr = NULL;
-+ hdr.daddr = mipv6_get_fake_hdr_daddr(hdr.daddr, daddr);
-
- err = ip6_build_xmit(sk, rawv6_frag_cksum, &hdr, &fl, len,
- opt, hlimit, msg->msg_flags);
---- linux-2.4.27/net/ipv6/route.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/route.c
-@@ -49,6 +49,7 @@
- #include <net/addrconf.h>
- #include <net/tcp.h>
- #include <linux/rtnetlink.h>
-+#include <net/mipglue.h>
-
- #include <asm/uaccess.h>
-
-@@ -363,12 +364,8 @@
- rt->u.dst.flags |= DST_HOST;
-
- #ifdef CONFIG_IPV6_SUBTREES
-- if (rt->rt6i_src.plen && saddr) {
-- ipv6_addr_copy(&rt->rt6i_src.addr, saddr);
-- rt->rt6i_src.plen = 128;
-- }
-+ rt->rt6i_src.plen = ort->rt6i_src.plen;
- #endif
--
- rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
-
- dst_hold(&rt->u.dst);
-@@ -511,14 +508,19 @@
- struct rt6_info *rt;
- int strict;
- int attempts = 3;
-+ struct in6_addr *saddr;
-
-+ if (ipv6_chk_addr(fl->nl_u.ip6_u.daddr, NULL))
-+ saddr = NULL;
-+ else
-+ saddr = fl->nl_u.ip6_u.saddr;
-+
- strict = ipv6_addr_type(fl->nl_u.ip6_u.daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL);
-
- relookup:
- read_lock_bh(&rt6_lock);
-
-- fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr,
-- fl->nl_u.ip6_u.saddr);
-+ fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, saddr);
-
- restart:
- rt = fn->leaf;
-@@ -663,25 +665,6 @@
- return (atomic_read(&ip6_dst_ops.entries) > ip6_rt_max_size);
- }
-
--/* Clean host part of a prefix. Not necessary in radix tree,
-- but results in cleaner routing tables.
--
-- Remove it only when all the things will work!
-- */
--
--static void ipv6_addr_prefix(struct in6_addr *pfx,
-- const struct in6_addr *addr, int plen)
--{
-- int b = plen&0x7;
-- int o = plen>>3;
--
-- memcpy(pfx->s6_addr, addr, o);
-- if (o < 16)
-- memset(pfx->s6_addr + o, 0, 16 - o);
-- if (b != 0)
-- pfx->s6_addr[o] = addr->s6_addr[o]&(0xff00 >> b);
--}
--
- static int ipv6_get_mtu(struct net_device *dev)
- {
- int mtu = IPV6_MIN_MTU;
-@@ -810,7 +793,7 @@
- if (!(gwa_type&IPV6_ADDR_UNICAST))
- goto out;
-
-- grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1);
-+ grt = rt6_lookup(gw_addr, &rtmsg->rtmsg_src, rtmsg->rtmsg_ifindex, 1);
-
- err = -EHOSTUNREACH;
- if (grt == NULL)
-@@ -848,7 +831,15 @@
- goto out;
- }
- }
--
-+#ifdef USE_IPV6_MOBILITY
-+ /* If destination is mobile node, add special skb->dst->input
-+ * function for proxy ND.
-+ */
-+ if (rtmsg->rtmsg_flags & RTF_MOBILENODE) {
-+ rt->u.dst.input = ip6_mipv6_forward;
-+ }
-+#endif /* CONFIG_IPV6_MOBILITY */
-+
- if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
- rt->rt6i_hoplimit = IPV6_DEFAULT_MCASTHOPS;
- else
-@@ -936,7 +927,7 @@
- struct rt6_info *rt, *nrt;
-
- /* Locate old route to this destination. */
-- rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1);
-+ rt = rt6_lookup(dest, saddr, neigh->dev->ifindex, 1);
-
- if (rt == NULL)
- return;
-@@ -1003,6 +994,9 @@
- nrt = ip6_rt_copy(rt);
- if (nrt == NULL)
- goto out;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ nrt->rt6i_src.plen = rt->rt6i_src.plen;
-+#endif
-
- nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
- if (on_link)
-@@ -1104,6 +1098,9 @@
- nrt = ip6_rt_copy(rt);
- if (nrt == NULL)
- goto out;
-+#ifdef CONFIG_IPV6_SUBTREES
-+ nrt->rt6i_src.plen = rt->rt6i_src.plen;
-+#endif
- ipv6_addr_copy(&nrt->rt6i_dst.addr, daddr);
- nrt->rt6i_dst.plen = 128;
- nrt->u.dst.flags |= DST_HOST;
---- linux-2.4.27/net/ipv6/tcp_ipv6.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/tcp_ipv6.c
-@@ -50,6 +50,7 @@
- #include <net/addrconf.h>
- #include <net/ip6_route.h>
- #include <net/inet_ecn.h>
-+#include <net/mipglue.h>
-
- #include <asm/uaccess.h>
-
-@@ -557,6 +558,7 @@
- struct flowi fl;
- struct dst_entry *dst;
- int addr_type;
-+ int reroute = 0;
- int err;
-
- if (addr_len < SIN6_LEN_RFC2133)
-@@ -660,7 +662,7 @@
-
- fl.proto = IPPROTO_TCP;
- fl.fl6_dst = &np->daddr;
-- fl.fl6_src = saddr;
-+ fl.fl6_src = saddr;
- fl.oif = sk->bound_dev_if;
- fl.uli_u.ports.dport = usin->sin6_port;
- fl.uli_u.ports.sport = sk->sport;
-@@ -669,31 +671,46 @@
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- fl.nl_u.ip6_u.daddr = rt0->addr;
- }
--
- dst = ip6_route_output(sk, &fl);
--
-+#ifdef CONFIG_IPV6_SUBTREES
-+ reroute = (saddr == NULL);
-+#endif
- if ((err = dst->error) != 0) {
- dst_release(dst);
- goto failure;
- }
--
-- ip6_dst_store(sk, dst, NULL);
-- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
--
-+ if (!reroute) {
-+ ip6_dst_store(sk, dst, NULL, NULL);
-+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-+ }
- if (saddr == NULL) {
- err = ipv6_get_saddr(dst, &np->daddr, &saddr_buf);
-+
-+ if (reroute)
-+ dst_release(dst);
- if (err)
- goto failure;
-
- saddr = &saddr_buf;
-+ ipv6_addr_copy(&np->rcv_saddr, saddr);
-+#ifdef CONFIG_IPV6_SUBTREES
-+ fl.fl6_src = saddr;
-+ dst = ip6_route_output(sk, &fl);
-+
-+ if ((err = dst->error) != 0) {
-+ dst_release(dst);
-+ goto failure;
-+ }
-+ ip6_dst_store(sk, dst, NULL, NULL);
-+ sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-+#endif
- }
-
- /* set the source address */
-- ipv6_addr_copy(&np->rcv_saddr, saddr);
- ipv6_addr_copy(&np->saddr, saddr);
- sk->rcv_saddr= LOOPBACK4_IPV6;
-
-- tp->ext_header_len = 0;
-+ tp->ext_header_len = tcp_v6_get_mipv6_header_len();
- if (np->opt)
- tp->ext_header_len = np->opt->opt_flen+np->opt->opt_nflen;
- tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
-@@ -1338,7 +1355,7 @@
- #endif
- MOD_INC_USE_COUNT;
-
-- ip6_dst_store(newsk, dst, NULL);
-+ ip6_dst_store(newsk, dst, NULL, NULL);
- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
-
- newtp = &(newsk->tp_pinfo.af_tcp);
-@@ -1383,7 +1400,7 @@
- sock_kfree_s(sk, opt, opt->tot_len);
- }
-
-- newtp->ext_header_len = 0;
-+ newtp->ext_header_len = tcp_v6_get_mipv6_header_len();
- if (np->opt)
- newtp->ext_header_len = np->opt->opt_nflen + np->opt->opt_flen;
-
-@@ -1710,7 +1727,7 @@
- return err;
- }
-
-- ip6_dst_store(sk, dst, NULL);
-+ ip6_dst_store(sk, dst, NULL, NULL);
- sk->route_caps = dst->dev->features&~NETIF_F_IP_CSUM;
- }
-
-@@ -1749,7 +1766,7 @@
- return -sk->err_soft;
- }
-
-- ip6_dst_store(sk, dst, NULL);
-+ ip6_dst_store(sk, dst, NULL, NULL);
- }
-
- skb->dst = dst_clone(dst);
---- linux-2.4.27/net/ipv6/udp.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/ipv6/udp.c
-@@ -48,6 +48,7 @@
- #include <net/ip.h>
- #include <net/udp.h>
- #include <net/inet_common.h>
-+#include <net/mipglue.h>
-
- #include <net/checksum.h>
-
-@@ -232,6 +233,7 @@
- struct ip6_flowlabel *flowlabel = NULL;
- int addr_type;
- int err;
-+ int reroute = 0;
-
- if (usin->sin6_family == AF_INET) {
- if (__ipv6_only_sock(sk))
-@@ -331,7 +333,7 @@
-
- fl.proto = IPPROTO_UDP;
- fl.fl6_dst = &np->daddr;
-- fl.fl6_src = &saddr;
-+ fl.fl6_src = NULL;
- fl.oif = sk->bound_dev_if;
- fl.uli_u.ports.dport = sk->dport;
- fl.uli_u.ports.sport = sk->sport;
-@@ -348,29 +350,44 @@
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- fl.fl6_dst = rt0->addr;
- }
--
- dst = ip6_route_output(sk, &fl);
--
- if ((err = dst->error) != 0) {
- dst_release(dst);
- fl6_sock_release(flowlabel);
-- return err;
-- }
--
-- ip6_dst_store(sk, dst, fl.fl6_dst);
--
-+ return err;
-+ }
-+#ifdef CONFIG_IPV6_SUBTREES
-+ reroute = (fl.fl6_src == NULL);
-+#endif
- /* get the source adddress used in the apropriate device */
-
- err = ipv6_get_saddr(dst, daddr, &saddr);
-
-+ if (reroute)
-+ dst_release(dst);
-+
- if (err == 0) {
-- if(ipv6_addr_any(&np->saddr))
-+#ifdef CONFIG_IPV6_SUBTREES
-+ if (reroute) {
-+ fl.fl6_src = &saddr;
-+ dst = ip6_route_output(sk, &fl);
-+ if ((err = dst->error) != 0) {
-+ dst_release(dst);
-+ fl6_sock_release(flowlabel);
-+ return err;
-+ }
-+ }
-+#endif
-+ if(ipv6_addr_any(&np->saddr)) {
- ipv6_addr_copy(&np->saddr, &saddr);
--
-+ fl.fl6_src = &np->saddr;
-+ }
- if(ipv6_addr_any(&np->rcv_saddr)) {
- ipv6_addr_copy(&np->rcv_saddr, &saddr);
- sk->rcv_saddr = LOOPBACK4_IPV6;
- }
-+ ip6_dst_store(sk, dst, fl.fl6_dst,
-+ fl.fl6_src == &np->saddr ? fl.fl6_src : NULL);
- sk->state = TCP_ESTABLISHED;
- }
- fl6_sock_release(flowlabel);
-@@ -889,6 +906,7 @@
- opt = fl6_merge_options(&opt_space, flowlabel, opt);
- if (opt && opt->srcrt)
- udh.daddr = daddr;
-+ udh.daddr = mipv6_get_fake_hdr_daddr(udh.daddr, daddr);
-
- udh.uh.source = sk->sport;
- udh.uh.len = len < 0x10000 ? htons(len) : 0;
---- linux-2.4.27/net/netsyms.c~mipv6-1.1-v2.4.26
-+++ linux-2.4.27/net/netsyms.c
-@@ -190,6 +190,7 @@
- #endif
- EXPORT_SYMBOL(pneigh_lookup);
- EXPORT_SYMBOL(pneigh_enqueue);
-+EXPORT_SYMBOL(pneigh_delete);
- EXPORT_SYMBOL(neigh_destroy);
- EXPORT_SYMBOL(neigh_parms_alloc);
- EXPORT_SYMBOL(neigh_parms_release);
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1-jpm1.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1-jpm1.patch
deleted file mode 100644
index 7ae04c21a6..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1-jpm1.patch
+++ /dev/null
@@ -1,8760 +0,0 @@
-
-#
-# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
-#
-
---- linux-2.4.25/Makefile~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/Makefile 2004-05-02 22:47:57.000000000 +0200
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 25
--EXTRAVERSION =-vrs2-pxa1
-+EXTRAVERSION =-vrs2-pxa1-jpm1
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
---- linux-2.4.25/arch/arm/mach-sa1100/Makefile~2.4.25-vrs2-pxa1-jpm1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/Makefile 2004-05-02 22:45:42.000000000 +0200
-@@ -18,7 +18,8 @@
- export-objs := assabet.o consus.o badge4.o dma-sa1100.o dma-sa1111.o \
- flexanet.o freebird.o frodo.o generic.o h3600.o \
- huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \
-- system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o
-+ system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \
-+ simpad.o
-
- # These aren't present yet, and prevents a plain -ac kernel building.
- # hwtimer.o
-@@ -30,7 +31,6 @@
- ifeq ($(CONFIG_CPU_FREQ),y)
- obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_CEP) += cpu-sa1110.o
--obj-$(CONFIG_SA1100_CONSUS) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
-@@ -52,7 +52,6 @@
- obj-$(CONFIG_SA1100_BRUTUS) += brutus.o
- obj-$(CONFIG_SA1100_CEP) += cep.o
- obj-$(CONFIG_SA1100_CERF) += cerf.o
--obj-$(CONFIG_SA1100_CONSUS) += consus.o
- obj-$(CONFIG_SA1100_EMPEG) += empeg.o
- obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o
- obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o
-@@ -87,7 +86,6 @@
- leds-$(CONFIG_SA1100_ASSABET) += leds-assabet.o
- leds-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o
- leds-$(CONFIG_SA1100_CERF) += leds-cerf.o
--leds-$(CONFIG_SA1100_CONSUS) += leds-consus.o
- leds-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o
- leds-$(CONFIG_SA1100_FRODO) += leds-frodo.o
- leds-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o
-@@ -108,7 +106,12 @@
-
- # Miscelaneous functions
- obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_APM) += apm.o
-
-+# SIMpad specific
-+export-objs += simpad_pm.o
-+obj-$(CONFIG_SIMPAD_PM) += simpad_pm.o
-+
- obj-$(CONFIG_SA1100_SSP) += ssp.o
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/video/fbmem.c 2004-05-02 22:45:42.000000000 +0200
-@@ -109,6 +109,7 @@
- extern int chips_init(void);
- extern int g364fb_init(void);
- extern int sa1100fb_init(void);
-+extern int mq200fb_init(void);
- extern int pxafb_init(void);
- extern int fm2fb_init(void);
- extern int fm2fb_setup(char*);
-@@ -306,6 +307,9 @@
- #ifdef CONFIG_FB_SA1100
- { "sa1100", sa1100fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_MQ200
-+ { "mq200fb", mq200fb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_PXA
- { "pxa", pxafb_init, NULL },
- #endif
---- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/arch/arm/config.in 2004-05-02 22:45:42.000000000 +0200
-@@ -128,6 +128,9 @@
- dep_bool ' Shannon' CONFIG_SA1100_SHANNON $CONFIG_ARCH_SA1100
- dep_bool ' Sherman' CONFIG_SA1100_SHERMAN $CONFIG_ARCH_SA1100
- dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100
-+if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then
-+ bool ' T-Sinus PAD' CONFIG_SA1100_SIMPAD_SINUSPAD
-+fi
- dep_bool ' Simputer' CONFIG_SA1100_SIMPUTER $CONFIG_ARCH_SA1100
- dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100
- dep_bool ' Victor' CONFIG_SA1100_VICTOR $CONFIG_ARCH_SA1100
-@@ -587,6 +590,10 @@
- tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
- tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
- dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
-+dep_tristate 'Advanced power management emulation support' CONFIG_APM $CONFIG_PM
-+if [ "$CONFIG_APM" != "n" ]; then
-+ bool ' SIMpad power management' CONFIG_SIMPAD_PM
-+fi
- dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
- string 'Default kernel command string' CONFIG_CMDLINE ""
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/simpad 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,967 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+CONFIG_ARCH_SA1100=y
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+CONFIG_SA1100_SIMPAD=y
-+# CONFIG_SA1100_SIMPAD_SINUSPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+CONFIG_SA1100_USB=m
-+CONFIG_SA1100_USB_NETLINK=m
-+CONFIG_SA1100_USB_CHAR=m
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+CONFIG_CPU_SA1100=y
-+# CONFIG_CPU_32v3 is not set
-+CONFIG_CPU_32v4=y
-+CONFIG_DISCONTIGMEM=y
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+CONFIG_ISA=y
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+CONFIG_PCMCIA_PROBE=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+CONFIG_PCMCIA_SA1100=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=m
-+CONFIG_PM=y
-+CONFIG_APM=y
-+CONFIG_SIMPAD_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="mtdparts=sa1100:512k(boot),1m(kernel),-(root) console=ttySA root=1f02 noinitrd mem=64M"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+CONFIG_MTD_JEDECPROBE=y
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+CONFIG_MTD_CFI_B2=y
-+# CONFIG_MTD_CFI_B4 is not set
-+# CONFIG_MTD_CFI_B8 is not set
-+CONFIG_MTD_CFI_I1=y
-+# CONFIG_MTD_CFI_I2 is not set
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+CONFIG_MTD_ROM=y
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+CONFIG_MTD_SA1100=y
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+CONFIG_MTD_MTDRAM=y
-+CONFIG_MTDRAM_TOTAL_SIZE=32768
-+CONFIG_MTDRAM_ERASE_SIZE=1
-+CONFIG_MTDRAM_ABS_POS=C2000000
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+CONFIG_PACKET_MMAP=y
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+CONFIG_DUMMY=y
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_AT1700 is not set
-+# CONFIG_DEPCA is not set
-+# CONFIG_HP100 is not set
-+# CONFIG_NET_ISA is not set
-+CONFIG_NET_PCI=y
-+# CONFIG_PCNET32 is not set
-+# CONFIG_ADAPTEC_STARFIRE is not set
-+# CONFIG_AC3200 is not set
-+# CONFIG_APRICOT is not set
-+# CONFIG_CS89x0 is not set
-+# CONFIG_TULIP is not set
-+# CONFIG_TC35815 is not set
-+# CONFIG_DM9102 is not set
-+# CONFIG_EEPRO100 is not set
-+# CONFIG_LNE390 is not set
-+# CONFIG_FEALNX is not set
-+# CONFIG_NATSEMI is not set
-+# CONFIG_NE2K_PCI is not set
-+# CONFIG_NE3210 is not set
-+# CONFIG_ES3210 is not set
-+# CONFIG_8139CP is not set
-+# CONFIG_8139TOO is not set
-+# CONFIG_8139TOO_PIO is not set
-+# CONFIG_8139TOO_TUNE_TWISTER is not set
-+# CONFIG_8139TOO_8129 is not set
-+# CONFIG_8139_NEW_RX_RESET is not set
-+# CONFIG_SIS900 is not set
-+# CONFIG_EPIC100 is not set
-+# CONFIG_SUNDANCE is not set
-+# CONFIG_VIA_RHINE is not set
-+# CONFIG_VIA_RHINE_MMIO is not set
-+# CONFIG_WINBOND_840 is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+# CONFIG_WAVELAN is not set
-+# CONFIG_ARLAN is not set
-+# CONFIG_AIRONET4500 is not set
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+CONFIG_AIRO=m
-+# CONFIG_HERMES is not set
-+# CONFIG_PCMCIA_HERMES is not set
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=m
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+# CONFIG_PCMCIA_RAYCS is not set
-+# CONFIG_PCMCIA_NETWAVE is not set
-+CONFIG_PCMCIA_WAVELAN=m
-+# CONFIG_AIRONET4500_CS is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=m
-+CONFIG_IRLAN=m
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=m
-+# CONFIG_IRDA_ULTRA is not set
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+# CONFIG_IRDA_DEBUG is not set
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=m
-+CONFIG_IRPORT_SIR=m
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+CONFIG_SA1100_FIR=m
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=m
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=m
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=m
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=m
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+CONFIG_SERIAL_SA1100=y
-+CONFIG_SERIAL_SA1100_CONSOLE=y
-+CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_AT91US3 is not set
-+# CONFIG_SERIAL_AT91US3_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=32
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_SA1100_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=m
-+CONFIG_TDA8007=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+CONFIG_REISERFS_FS=m
-+# CONFIG_REISERFS_CHECK is not set
-+CONFIG_REISERFS_PROC_INFO=y
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=m
-+CONFIG_JBD=m
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+CONFIG_JFFS_FS=m
-+CONFIG_JFFS_FS_VERBOSE=0
-+CONFIG_JFFS_PROC_FS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+CONFIG_CRAMFS=m
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+CONFIG_DEVFS_DEBUG=y
-+# CONFIG_DEVPTS_FS is not set
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=m
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+CONFIG_SMB_FS=m
-+# CONFIG_SMB_NLS_DEFAULT is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+CONFIG_ZLIB_FS_INFLATE=m
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+CONFIG_SMB_NLS=y
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=y
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=y
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+CONFIG_NLS_ISO8859_15=y
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+# CONFIG_FB_CYBER2000 is not set
-+CONFIG_FB_MQ200=y
-+# CONFIG_FB_VIRTUAL is not set
-+CONFIG_FBCON_ADVANCED=y
-+# CONFIG_FBCON_MFB is not set
-+# CONFIG_FBCON_CFB2 is not set
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_CFB24 is not set
-+# CONFIG_FBCON_CFB32 is not set
-+# CONFIG_FBCON_AFB is not set
-+# CONFIG_FBCON_ILBM is not set
-+# CONFIG_FBCON_IPLAN2P2 is not set
-+# CONFIG_FBCON_IPLAN2P4 is not set
-+# CONFIG_FBCON_IPLAN2P8 is not set
-+# CONFIG_FBCON_MAC is not set
-+# CONFIG_FBCON_VGA_PLANES is not set
-+# CONFIG_FBCON_VGA is not set
-+# CONFIG_FBCON_HGA is not set
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+CONFIG_FBCON_FONTS=y
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_SUN12x22 is not set
-+# CONFIG_FONT_6x11 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+# CONFIG_FONT_ACORN_8x8 is not set
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+CONFIG_SOUND_SA1100=y
-+# CONFIG_SOUND_UDA1341 is not set
-+# CONFIG_SOUND_ASSABET_UDA1341 is not set
-+# CONFIG_SOUND_H3600_UDA1341 is not set
-+# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-+# CONFIG_SOUND_SA1111_UDA1341 is not set
-+# CONFIG_SOUND_SA1111_AC97 is not set
-+# CONFIG_SOUND_SA1100SSP is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_VIDC is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+CONFIG_MCP=y
-+CONFIG_MCP_SA1100=y
-+CONFIG_MCP_UCB1200=y
-+CONFIG_MCP_UCB1200_AUDIO=y
-+CONFIG_MCP_UCB1200_TS=y
-+
-+#
-+# Console Switches
-+#
-+CONFIG_SWITCHES=y
-+CONFIG_SWITCHES_SA1100=y
-+CONFIG_SWITCHES_UCB1X00=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+# CONFIG_DEBUG_KERNEL is not set
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
-+# CONFIG_DEBUG_ERRORS is not set
-+# CONFIG_DEBUG_LL is not set
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/head-armv.S 2004-05-02 22:45:42.000000000 +0200
-@@ -93,6 +93,8 @@
- .section ".text.init",#alloc,#execinstr
- .type stext, #function
- ENTRY(stext)
-+ mov r1, #87
-+ mov r0, #0
- mov r12, r0
- /*
- * NOTE! Any code which is placed here should be done for one of
---- linux-2.4.25/arch/arm/kernel/irq.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:37.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/irq.c 2004-05-02 22:45:42.000000000 +0200
-@@ -82,9 +82,9 @@
-
- spin_lock_irqsave(&irq_controller_lock, flags);
- if (!desc->disable_depth++) {
--#ifndef CONFIG_CPU_SA1100
-+// #ifndef CONFIG_CPU_SA1100
- desc->mask(irq);
--#endif
-+// #endif
- }
- spin_unlock_irqrestore(&irq_controller_lock, flags);
- }
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/apm.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,520 @@
-+/*
-+ * bios-less APM driver for ARM Linux
-+ * Jamey Hicks <jamey@crl.dec.com>
-+ * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
-+ *
-+ * APM 1.2 Reference:
-+ * Intel Corporation, Microsoft Corporation. Advanced Power Management
-+ * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
-+ *
-+ * [This document is available from Microsoft at:
-+ * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/poll.h>
-+#include <linux/types.h>
-+#include <linux/stddef.h>
-+#include <linux/timer.h>
-+#include <linux/fcntl.h>
-+#include <linux/slab.h>
-+#include <linux/stat.h>
-+#include <linux/proc_fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/apm_bios.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/pm.h>
-+#include <linux/kernel.h>
-+#include <linux/smp_lock.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#if FIXME
-+#include <asm/arch-sa1100/pm.h>
-+#endif
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch-sa1100/h3600_hal.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch-sa1100/simpad_pm.h>
-+#endif
-+
-+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-+extern int (*console_blank_hook)(int);
-+#endif
-+
-+struct apm_bios_info apm_bios_info = {
-+ /* this driver simulates APM version 1.2 */
-+ version: 0x102,
-+ flags: APM_32_BIT_SUPPORT
-+};
-+
-+/*
-+ * The apm_bios device is one of the misc char devices.
-+ * This is its minor number.
-+ */
-+#define APM_MINOR_DEV 134
-+
-+/*
-+ * See Documentation/Config.help for the configuration options.
-+ *
-+ * Various options can be changed at boot time as follows:
-+ * (We allow underscores for compatibility with the modules code)
-+ * apm=on/off enable/disable APM
-+ * [no-]debug log some debugging messages
-+ * [no-]power[-_]off power off on shutdown
-+ */
-+
-+/*
-+ * Need to poll the APM BIOS every second
-+ */
-+#define APM_CHECK_TIMEOUT (HZ)
-+
-+/*
-+ * Ignore suspend events for this amount of time after a resume
-+ */
-+#define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
-+
-+/*
-+ * Maximum number of events stored
-+ */
-+#define APM_MAX_EVENTS 20
-+
-+/*
-+ * The per-file APM data
-+ */
-+struct apm_user {
-+ int magic;
-+ struct apm_user * next;
-+ int suser: 1;
-+ int suspend_wait: 1;
-+ int suspend_result;
-+ int suspends_pending;
-+ int standbys_pending;
-+ int suspends_read;
-+ int standbys_read;
-+ int event_head;
-+ int event_tail;
-+ apm_event_t events[APM_MAX_EVENTS];
-+};
-+
-+/*
-+ * The magic number in apm_user
-+ */
-+#define APM_BIOS_MAGIC 0x4101
-+
-+/*
-+ * Local variables
-+ */
-+//static int suspends_pending;
-+//static int standbys_pending;
-+//static int ignore_normal_resume;
-+
-+#ifdef CONFIG_APM_RTC_IS_GMT
-+# define clock_cmos_diff 0
-+# define got_clock_diff 1
-+#else
-+//static long clock_cmos_diff;
-+//static int got_clock_diff;
-+#endif
-+static int debug;
-+static int apm_disabled;
-+#ifdef CONFIG_SMP
-+static int power_off;
-+#else
-+static int power_off = 1;
-+#endif
-+static int exit_kapmd;
-+static int kapmd_running;
-+
-+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-+static struct apm_user * user_list = NULL;
-+
-+static char driver_version[] = "1.13"; /* no spaces */
-+
-+typedef struct lookup_t {
-+ int key;
-+ char * msg;
-+} lookup_t;
-+
-+static const lookup_t error_table[] = {
-+/* N/A { APM_SUCCESS, "Operation succeeded" }, */
-+ { APM_DISABLED, "Power management disabled" },
-+ { APM_CONNECTED, "Real mode interface already connected" },
-+ { APM_NOT_CONNECTED, "Interface not connected" },
-+ { APM_16_CONNECTED, "16 bit interface already connected" },
-+/* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */
-+ { APM_32_CONNECTED, "32 bit interface already connected" },
-+ { APM_32_UNSUPPORTED, "32 bit interface not supported" },
-+ { APM_BAD_DEVICE, "Unrecognized device ID" },
-+ { APM_BAD_PARAM, "Parameter out of range" },
-+ { APM_NOT_ENGAGED, "Interface not engaged" },
-+ { APM_BAD_FUNCTION, "Function not supported" },
-+ { APM_RESUME_DISABLED, "Resume timer disabled" },
-+ { APM_BAD_STATE, "Unable to enter requested state" },
-+/* N/A { APM_NO_EVENTS, "No events pending" }, */
-+ { APM_NO_ERROR, "BIOS did not set a return code" },
-+ { APM_NOT_PRESENT, "No APM present" }
-+};
-+#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
-+
-+static int apm_get_power_status(u_char *ac_line_status,
-+ u_char *battery_status,
-+ u_char *battery_flag,
-+ u_char *battery_percentage,
-+ u_short *battery_life)
-+{
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ h3600_apm_get_power_status(ac_line_status, battery_status, battery_flag, battery_percentage, battery_life);
-+#endif
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_apm_get_power_status(ac_line_status, battery_status, battery_flag, battery_percentage, battery_life);
-+#endif
-+ return APM_SUCCESS;
-+}
-+
-+static int queue_empty(struct apm_user *as)
-+{
-+ return as->event_head == as->event_tail;
-+}
-+
-+static apm_event_t get_queued_event(struct apm_user *as)
-+{
-+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-+ return as->events[as->event_tail];
-+}
-+
-+static int check_apm_user(struct apm_user *as, const char *func)
-+{
-+ if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-+ printk(KERN_ERR "apm: %s passed bad filp\n", func);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
-+{
-+ struct apm_user * as;
-+ int i;
-+ apm_event_t event;
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ as = fp->private_data;
-+ if (check_apm_user(as, "read"))
-+ return -EIO;
-+ if (count < sizeof(apm_event_t))
-+ return -EINVAL;
-+ if (queue_empty(as)) {
-+ if (fp->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ add_wait_queue(&apm_waitqueue, &wait);
-+ printk("do_read: waiting\n");
-+repeat:
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (queue_empty(as) && !signal_pending(current)) {
-+ schedule();
-+ goto repeat;
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&apm_waitqueue, &wait);
-+ }
-+ i = count;
-+ while ((i >= sizeof(event)) && !queue_empty(as)) {
-+ event = get_queued_event(as);
-+ printk(" do_read: event=%d\n", event);
-+ if (copy_to_user(buf, &event, sizeof(event))) {
-+ if (i < count)
-+ break;
-+ return -EFAULT;
-+ }
-+ switch (event) {
-+ case APM_SYS_SUSPEND:
-+ case APM_USER_SUSPEND:
-+ as->suspends_read++;
-+ break;
-+
-+ case APM_SYS_STANDBY:
-+ case APM_USER_STANDBY:
-+ as->standbys_read++;
-+ break;
-+ }
-+ buf += sizeof(event);
-+ i -= sizeof(event);
-+ }
-+ if (i < count)
-+ return count - i;
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+ return 0;
-+}
-+
-+static unsigned int do_poll(struct file *fp, poll_table * wait)
-+{
-+ struct apm_user * as;
-+
-+ as = fp->private_data;
-+ if (check_apm_user(as, "poll"))
-+ return 0;
-+ poll_wait(fp, &apm_waitqueue, wait);
-+ if (!queue_empty(as))
-+ return POLLIN | POLLRDNORM;
-+ return 0;
-+}
-+
-+static int do_ioctl(struct inode * inode, struct file *filp,
-+ u_int cmd, u_long arg)
-+{
-+ struct apm_user * as;
-+
-+ as = filp->private_data;
-+ if (check_apm_user(as, "ioctl"))
-+ return -EIO;
-+ if (!as->suser)
-+ return -EPERM;
-+ switch (cmd) {
-+ case APM_IOC_SUSPEND:
-+#if FIXME
-+ pm_suggest_suspend();
-+#endif
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+static int do_release(struct inode * inode, struct file * filp)
-+{
-+ struct apm_user * as;
-+
-+ as = filp->private_data;
-+ if (check_apm_user(as, "release"))
-+ return 0;
-+ filp->private_data = NULL;
-+ lock_kernel();
-+ unlock_kernel();
-+ kfree(as);
-+ return 0;
-+}
-+
-+static int do_open(struct inode * inode, struct file * filp)
-+{
-+ struct apm_user * as;
-+
-+ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
-+ if (as == NULL) {
-+ printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-+ sizeof(*as));
-+ return -ENOMEM;
-+ }
-+ as->magic = APM_BIOS_MAGIC;
-+ as->event_tail = as->event_head = 0;
-+ as->suspends_pending = as->standbys_pending = 0;
-+ as->suspends_read = as->standbys_read = 0;
-+ /*
-+ * XXX - this is a tiny bit broken, when we consider BSD
-+ * process accounting. If the device is opened by root, we
-+ * instantly flag that we used superuser privs. Who knows,
-+ * we might close the device immediately without doing a
-+ * privileged operation -- cevans
-+ */
-+ as->suser = capable(CAP_SYS_ADMIN);
-+ as->next = user_list;
-+ user_list = as;
-+ filp->private_data = as;
-+ return 0;
-+}
-+
-+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
-+{
-+ char * p;
-+ unsigned short dx;
-+ unsigned short error;
-+ unsigned char ac_line_status = 0xff;
-+ unsigned char battery_status = 0xff;
-+ unsigned char battery_flag = 0xff;
-+ unsigned char percentage = 0xff;
-+ int time_units = -1;
-+ char *units = "?";
-+
-+ p = buf;
-+
-+ if ((smp_num_cpus == 1) &&
-+ !(error = apm_get_power_status(&ac_line_status,
-+ &battery_status, &battery_flag, &percentage, &dx))) {
-+ if (apm_bios_info.version > 0x100) {
-+ if (dx != 0xffff) {
-+ units = (dx & 0x8000) ? "min" : "sec";
-+ time_units = dx & 0x7fff;
-+ }
-+ }
-+ }
-+ /* Arguments, with symbols from linux/apm_bios.h. Information is
-+ from the Get Power Status (0x0a) call unless otherwise noted.
-+
-+ 0) Linux driver version (this will change if format changes)
-+ 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
-+ 2) APM flags from APM Installation Check (0x00):
-+ bit 0: APM_16_BIT_SUPPORT
-+ bit 1: APM_32_BIT_SUPPORT
-+ bit 2: APM_IDLE_SLOWS_CLOCK
-+ bit 3: APM_BIOS_DISABLED
-+ bit 4: APM_BIOS_DISENGAGED
-+ 3) AC line status
-+ 0x00: Off-line
-+ 0x01: On-line
-+ 0x02: On backup power (BIOS >= 1.1 only)
-+ 0xff: Unknown
-+ 4) Battery status
-+ 0x00: High
-+ 0x01: Low
-+ 0x02: Critical
-+ 0x03: Charging
-+ 0x04: Selected battery not present (BIOS >= 1.2 only)
-+ 0xff: Unknown
-+ 5) Battery flag
-+ bit 0: High
-+ bit 1: Low
-+ bit 2: Critical
-+ bit 3: Charging
-+ bit 7: No system battery
-+ 0xff: Unknown
-+ 6) Remaining battery life (percentage of charge):
-+ 0-100: valid
-+ -1: Unknown
-+ 7) Remaining battery life (time units):
-+ Number of remaining minutes or seconds
-+ -1: Unknown
-+ 8) min = minutes; sec = seconds */
-+
-+ p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-+ driver_version,
-+ (apm_bios_info.version >> 8) & 0xff,
-+ apm_bios_info.version & 0xff,
-+ apm_bios_info.flags,
-+ ac_line_status,
-+ battery_status,
-+ battery_flag,
-+ percentage,
-+ time_units,
-+ units);
-+
-+ return p - buf;
-+}
-+
-+#ifndef MODULE
-+static int __init apm_setup(char *str)
-+{
-+ int invert;
-+
-+ while ((str != NULL) && (*str != '\0')) {
-+ if (strncmp(str, "off", 3) == 0)
-+ apm_disabled = 1;
-+ if (strncmp(str, "on", 2) == 0)
-+ apm_disabled = 0;
-+ invert = (strncmp(str, "no-", 3) == 0);
-+ if (invert)
-+ str += 3;
-+ if (strncmp(str, "debug", 5) == 0)
-+ debug = !invert;
-+ if ((strncmp(str, "power-off", 9) == 0) ||
-+ (strncmp(str, "power_off", 9) == 0))
-+ power_off = !invert;
-+ str = strchr(str, ',');
-+ if (str != NULL)
-+ str += strspn(str, ", \t");
-+ }
-+ return 1;
-+}
-+
-+__setup("apm=", apm_setup);
-+#endif
-+
-+static struct file_operations apm_bios_fops = {
-+ owner: THIS_MODULE,
-+ read: do_read,
-+ poll: do_poll,
-+ ioctl: do_ioctl,
-+ open: do_open,
-+ release: do_release,
-+};
-+
-+static struct miscdevice apm_device = {
-+ APM_MINOR_DEV,
-+ "apm_bios",
-+ &apm_bios_fops
-+};
-+
-+#define APM_INIT_ERROR_RETURN return -1
-+
-+/*
-+ * Just start the APM thread. We do NOT want to do APM BIOS
-+ * calls from anything but the APM thread, if for no other reason
-+ * than the fact that we don't trust the APM BIOS. This way,
-+ * most common APM BIOS problems that lead to protection errors
-+ * etc will have at least some level of being contained...
-+ *
-+ * In short, if something bad happens, at least we have a choice
-+ * of just killing the apm thread..
-+ */
-+static int __init apm_init(void)
-+{
-+ if (apm_bios_info.version == 0) {
-+ printk(KERN_INFO "apm: BIOS not found.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+ printk(KERN_INFO
-+ "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
-+ ((apm_bios_info.version >> 8) & 0xff),
-+ (apm_bios_info.version & 0xff),
-+ apm_bios_info.flags,
-+ driver_version);
-+
-+ if (apm_disabled) {
-+ printk(KERN_NOTICE "apm: disabled on user request.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+
-+ if (PM_IS_ACTIVE()) {
-+ printk(KERN_NOTICE "apm: overridden by ACPI.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+ pm_active = 1;
-+
-+ create_proc_info_entry("apm", 0, NULL, apm_get_info);
-+
-+ misc_register(&apm_device);
-+
-+ return 0;
-+}
-+
-+static void __exit apm_exit(void)
-+{
-+ misc_deregister(&apm_device);
-+ remove_proc_entry("apm", NULL);
-+ if (power_off)
-+ pm_power_off = NULL;
-+ exit_kapmd = 1;
-+ while (kapmd_running)
-+ schedule();
-+ pm_active = 0;
-+}
-+
-+module_init(apm_init);
-+module_exit(apm_exit);
-+
-+MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
-+MODULE_DESCRIPTION("A minimal emulation of APM");
-+MODULE_PARM(debug, "i");
-+MODULE_PARM_DESC(debug, "Enable debug mode");
-+MODULE_PARM(power_off, "i");
-+MODULE_PARM_DESC(power_off, "Enable power off");
-+
-+EXPORT_NO_SYMBOLS;
---- linux-2.4.25/arch/arm/mach-sa1100/leds.c~2.4.25-vrs2-pxa1-jpm1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/leds.c 2004-05-02 22:45:42.000000000 +0200
-@@ -45,6 +45,8 @@
- leds_event = pfs168_leds_event;
- if (machine_is_pt_system3())
- leds_event = system3_leds_event;
-+ if (machine_is_simpad())
-+ leds_event = simpad_leds_event;
-
- leds_event(led_start);
- return 0;
---- linux-2.4.25/arch/arm/mach-sa1100/leds.h~2.4.25-vrs2-pxa1-jpm1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/leds.h 2004-05-02 22:45:42.000000000 +0200
-@@ -12,4 +12,6 @@
- extern void hackkit_leds_event(led_event_t evt);
- extern void lart_leds_event(led_event_t evt);
- extern void pfs168_leds_event(led_event_t evt);
-+extern void simpad_leds_event(led_event_t evt);
- extern void system3_leds_event(led_event_t evt);
-+
---- linux-2.4.25/arch/arm/mach-sa1100/pm.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:37.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/pm.c 2004-05-02 22:45:42.000000000 +0200
-@@ -63,6 +63,7 @@
- SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
-
- SLEEP_SAVE_ICMR,
-+ SLEEP_SAVE_MECR,
- SLEEP_SAVE_Ser1SDCR0,
-
- SLEEP_SAVE_SIZE
-@@ -109,6 +110,8 @@
-
- SAVE(ICMR);
-
-+ SAVE(MECR);
-+
- /* ... maybe a global variable initialized by arch code to set this? */
- GRER = PWER;
- GFER = 0;
-@@ -163,6 +166,8 @@
- ICCR = 1;
- RESTORE(ICMR);
-
-+ RESTORE(MECR);
-+
- /* restore current time */
- xtime.tv_sec = RCNR + delta;
-
---- linux-2.4.25/arch/arm/mach-sa1100/simpad.c~2.4.25-vrs2-pxa1-jpm1.patch 2003-06-13 16:51:29.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/simpad.c 2004-05-02 22:48:26.000000000 +0200
-@@ -10,6 +10,7 @@
- #include <linux/tty.h>
- #include <linux/proc_fs.h>
- #include <linux/string.h>
-+#include <linux/pm.h>
-
- #include <asm/hardware.h>
- #include <asm/setup.h>
-@@ -28,6 +29,11 @@
- return cs3_shadow;
- }
-
-+void set_cs3(long value)
-+{
-+ *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
-+}
-+
- void set_cs3_bit(int value)
- {
- cs3_shadow |= value;
-@@ -40,31 +46,62 @@
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
- }
-
-+EXPORT_SYMBOL(set_cs3_bit);
-+EXPORT_SYMBOL(clear_cs3_bit);
-+
-+static void simpad_power_off(void)
-+{
-+ cli();
-+ set_cs3(0x800); /* only SD_MEDIAQ */
-+
-+ /* disable internal oscillator, float CS lines */
-+ PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
-+ /* enable wake-up on GPIO0 (Assabet...) */
-+ PWER = GFER = GRER = 1;
-+ /*
-+ * set scratchpad to zero, just in case it is used as a
-+ * restart address by the bootloader.
-+ */
-+ PSPR = 0;
-+ PGSR = 0;
-+ /* enter sleep mode */
-+ PMCR = PMCR_SF;
-+ while(1);
-+}
-+
-+static int __init simpad_init(void)
-+{
-+ pm_power_off = simpad_power_off;
-+ return 0;
-+}
-+
-+__initcall(simpad_init);
-+
- static void __init
- fixup_simpad(struct machine_desc *desc, struct param_struct *params,
- char **cmdline, struct meminfo *mi)
- {
--#ifdef CONFIG_SA1100_SIMPAD_DRAM_64MB /* DRAM */
-- SET_BANK( 0, 0xc0000000, 64*1024*1024 );
--#else
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
- SET_BANK( 0, 0xc0000000, 32*1024*1024 );
-+#else
-+ SET_BANK( 0, 0xc0000000, 64*1024*1024 );
- #endif
- mi->nr_banks = 1;
-- ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+
- setup_ramdisk( 1, 0, 0, 8192 );
- setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
- }
-
--
- static struct map_desc simpad_io_desc[] __initdata = {
-- /* virtual physical length domain r w c b */
-- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 },
-- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
-- { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
-+ /* virtual physical length domain r w c b */
-+ { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },
-+ { 0xe9000000, 0x08000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },
-+ { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CS3, write only */
-+ { 0xf2000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CS4, tda8007 */
-+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
- LAST_DESC
- };
-
--
- static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
- {
- if (port->mapbase == (u_int)&Ser1UTCR0) {
-@@ -81,20 +118,32 @@
-
- static void __init simpad_map_io(void)
- {
-- sa1100_map_io();
-- iotable_init(simpad_io_desc);
-+ sa1100_map_io();
-+ iotable_init(simpad_io_desc);
-
-- PSPR = 0xc0008000;
-- GPDR &= ~GPIO_GPIO0;
-- cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-- ENABLE_5V | RESET_SIMCARD);
-- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
-+ set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-+ ENABLE_5V | nRESET_SIMCARD);
-
-- //It is only possible to register 3 UART in serial_sa1100.c
-- sa1100_register_uart(0, 3);
-- sa1100_register_uart(1, 1);
-+ //It is only possible to register 3 UART in serial_sa1100.c
-+ sa1100_register_uart(0, 3);
-+ sa1100_register_uart(1, 1);
-
-- set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
-+ GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
-+ GPDR |= GPIO_UART_TXD;
-+ GPDR &= ~GPIO_UART_RXD;
-+ PPAR |= PPAR_UPR;
-+
-+ set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
-+ set_GPIO_IRQ_edge(GPIO_POWER_BUTTON, GPIO_FALLING_EDGE);
-+
-+ /*
-+ * Set up registers for sleep mode.
-+ */
-+
-+ PWER = PWER_GPIO0;
-+ PGSR = 0x818;
-+ PCFR = 0;
-+ PSDR = 0;
- }
-
- #ifdef CONFIG_PROC_FS
-@@ -140,7 +189,17 @@
-
- return len;
- }
--
-+
-+static int proc_cs3_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ unsigned long newRegValue;
-+ char *endp;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ set_cs3( newRegValue );
-+ return (count+endp-buffer);
-+}
-
- static struct proc_dir_entry *proc_cs3;
-
-@@ -148,7 +207,10 @@
- {
- proc_cs3 = create_proc_entry("cs3", 0, 0);
- if (proc_cs3)
-+ {
- proc_cs3->read_proc = proc_cs3_read;
-+ proc_cs3->write_proc = (void*)proc_cs3_write;
-+ }
- return 0;
- }
-
-@@ -165,6 +227,7 @@
- MACHINE_START(SIMPAD, "Simpad")
- MAINTAINER("Juergen Messerer")
- BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-+ BOOT_PARAMS(0xc0000100)
- FIXUP(fixup_simpad)
- MAPIO(simpad_map_io)
- INITIRQ(sa1100_init_irq)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/simpad_pm.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,147 @@
-+/*
-+* Powermanagement layer for SIMPad.
-+*
-+* Copyright 2003 Peter Pregler
-+* Copyright 2000,2001 Compaq Computer Corporation.
-+*
-+* Use consistent with the GNU GPL is permitted,
-+* provided that this copyright notice is
-+* preserved in its entirety in all copies and derived works.
-+*
-+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-+* FITNESS FOR ANY PARTICULAR PURPOSE.
-+*
-+* Author: Peter Pregler (based on work for ipaq by Andrew Christian)
-+* May, 2003
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/poll.h>
-+#include <asm/uaccess.h> /* get_user,copy_to_user */
-+#include <linux/string.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/console.h>
-+#include <linux/devfs_fs_kernel.h>
-+
-+#include <linux/tqueue.h>
-+#include <linux/sched.h>
-+#include <linux/pm.h>
-+#include <linux/proc_fs.h>
-+#include <linux/apm_bios.h>
-+#include <linux/kmod.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch-sa1100/simpad_pm.h>
-+
-+MODULE_AUTHOR("Peter Pregler");
-+MODULE_DESCRIPTION("Power manamgement abstraction layer for the SIMpad");
-+
-+/****************************************************************************/
-+/* Functions exported for use by the kernel and kernel modules */
-+/****************************************************************************/
-+
-+int simpad_apm_get_power_status(u_char *ac_line_status,
-+ u_char *battery_status,
-+ u_char *battery_flag,
-+ u_char *battery_percentage,
-+ u_short *battery_life)
-+{
-+ struct simpad_battery bstat;
-+ unsigned char ac = APM_AC_UNKNOWN;
-+ unsigned char level = APM_BATTERY_STATUS_UNKNOWN;
-+ int status, result;
-+
-+ result = simpad_get_battery(&bstat);
-+ if (result) {
-+ printk("%s: unable to access battery information: result=%d\n", __FUNCTION__, result);
-+ return 0;
-+ }
-+
-+ switch (bstat.ac_status) {
-+ case SIMPAD_AC_STATUS_AC_OFFLINE:
-+ ac = APM_AC_OFFLINE;
-+ break;
-+ case SIMPAD_AC_STATUS_AC_ONLINE:
-+ ac = APM_AC_ONLINE;
-+ break;
-+ case SIMPAD_AC_STATUS_AC_BACKUP:
-+ ac = APM_AC_BACKUP;
-+ break;
-+ }
-+
-+ if (ac_line_status != NULL)
-+ *ac_line_status = ac;
-+
-+ status = bstat.status;
-+ if (status & (SIMPAD_BATT_STATUS_CHARGING | SIMPAD_BATT_STATUS_CHARGE_MAIN))
-+ level = APM_BATTERY_STATUS_CHARGING;
-+ else if (status & (SIMPAD_BATT_STATUS_HIGH | SIMPAD_BATT_STATUS_FULL))
-+ level = APM_BATTERY_STATUS_HIGH;
-+ else if (status & SIMPAD_BATT_STATUS_LOW)
-+ level = APM_BATTERY_STATUS_LOW;
-+ else if (status & SIMPAD_BATT_STATUS_CRITICAL)
-+ level = APM_BATTERY_STATUS_CRITICAL;
-+
-+ if (battery_status != NULL)
-+ *battery_status = level;
-+
-+ if (battery_percentage != NULL)
-+ *battery_percentage = bstat.percentage;
-+
-+ /* we have a dumb battery - so we know nothing */
-+ if (battery_life != NULL) {
-+ *battery_life = APM_BATTERY_LIFE_UNKNOWN;
-+ }
-+
-+#if 0
-+ printk("apm_get_power: ac: %02x / bs: %02x / bf: %02x / perc: %02x / life: %d\n",
-+ *ac_line_status, *battery_status, *battery_flag,
-+ *battery_percentage, *battery_life );
-+#endif
-+ return 1;
-+}
-+
-+EXPORT_SYMBOL(simpad_apm_get_power_status);
-+
-+
-+/***********************************************************************************/
-+/* Initialization */
-+/***********************************************************************************/
-+
-+#ifdef CONFIG_FB_MQ200
-+extern void (*mq200_blank_helper)(int blank);
-+#endif
-+
-+int __init simpad_hal_init_module(void)
-+{
-+ int i;
-+ printk(KERN_INFO "SIMpad Registering HAL abstraction layer\n");
-+
-+ /* Request the appropriate underlying module to provide services */
-+
-+#ifdef CONFIG_FB_SA1100
-+ sa1100fb_blank_helper = simpad_hal_backlight_helper;
-+#endif
-+
-+ return 0;
-+}
-+
-+void simpad_hal_cleanup_module(void)
-+{
-+ int i;
-+ printk(KERN_INFO "SIMpad shutting down HAL abstraction layer\n");
-+
-+#ifdef CONFIG_FB_SA1100
-+ sa1100fb_blank_helper = NULL;
-+#endif
-+}
-+
-+module_init(simpad_hal_init_module);
-+module_exit(simpad_hal_cleanup_module);
---- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/char/Config.in 2004-05-02 22:45:42.000000000 +0200
-@@ -425,4 +425,7 @@
- tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO
- fi
-
-+if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then
-+ tristate 'Smartcardreader(TDA8007) support' CONFIG_TDA8007
-+fi
- endmenu
---- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/char/Makefile 2004-05-02 22:45:42.000000000 +0200
-@@ -376,6 +376,8 @@
- obj-y += ipmi/ipmi.o
- endif
-
-+obj-$(CONFIG_TDA8007) += tda8007.o
-+
- include $(TOPDIR)/Rules.make
-
- fastdep:
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/tda8007.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,514 @@
-+/*
-+ * linux/drivers/char/tda8007.c
-+ *
-+ * Copyright (C) 2001 juergen.messerer@freesurf.ch, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * The TDA8007B driver provides basic services for handling IO,
-+ * interrupts, and accessing registers.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/simpad.h>
-+#include <asm/uaccess.h>
-+
-+#include "tda8007b.h"
-+
-+#define TDA8007_DIRNAME "driver/tda8007"
-+#define REG_DIRNAME "registers"
-+
-+extern void clear_cs3_bit(int value);
-+
-+static struct proc_dir_entry *regdir;
-+static struct proc_dir_entry *tda8007dir;
-+
-+static ssize_t proc_tda8007_read(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos);
-+static ssize_t proc_tda8007_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos);
-+
-+static struct file_operations proc_reg_operations = {
-+ read: proc_tda8007_read,
-+ write: proc_tda8007_write
-+};
-+
-+static int __init tda8007_init();
-+
-+/* ------------------------------------------------------------------------- */
-+void tda8007_reg_write(int reg, int val)
-+{
-+ printk("Address:%x \n", CS4_BASE+reg);
-+ printk("Value:%x \n", val);
-+ TDA_REG_WRITE(reg,val);
-+}
-+/* ------------------------------------------------------------------------- */
-+int tda8007_reg_read(int reg)
-+{
-+ printk("Address:%x \n", CS4_BASE+reg);
-+ return(TDA_REG_READ(reg)&0xff);
-+}
-+/* ------------------------------------------------------------------------- */
-+int tdaregs[16];
-+/* ------------------------------------------------------------------------- */
-+static void tda8007_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ printk("\n****tda8007_irq****\n");
-+}
-+/* ------------------------------------------------------------------------- */
-+static int tda_card_present( uint cardport )
-+{
-+ int val=0;
-+
-+ switch( cardport )
-+ {
-+ case CARD_PORT1:
-+ if( tda8007_reg_read(TDA_MSR) & TDA_MSR_PR1 )
-+ val = 1;
-+ break;
-+ case CARD_PORT2:
-+ if( tda8007_reg_read(TDA_MSR) & TDA_MSR_PR2 )
-+ val = 1;
-+ break;
-+ default:
-+ val =0;
-+ break;
-+ }
-+
-+ return val;
-+}
-+/* ------------------------------------------------------------------------- */
-+void tda_inituart(void)
-+{
-+ int hsr_reg, fcr_reg;
-+
-+ printk("Init TDA8007 Uart\n");
-+ hsr_reg = tda8007_reg_read(TDA_HSR);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ tda8007_reg_write(TDA_CSR, 0x00);
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_SC1); /* select Card 1 */
-+
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC1);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ tda8007_reg_write(TDA_PDR, TDA_PDR_VAL); /* Rat v. jandu 8.9.2000 */
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR2_DIV);
-+
-+ tda8007_reg_write(TDA_CCR, 0x40|TDA_CCR_AC1); /*1=XTAL/2 2=XTAL/4 3=XTAL/8 */
-+ tda8007_reg_write(TDA_GTR, TDA_GTR_GT1);
-+
-+ fcr_reg = tda8007_reg_read(TDA_FCR);
-+ tda8007_reg_write(TDA_FCR, (fcr_reg & 0xf0) | TDA_FCR_FL1);
-+
-+ tda8007_reg_write(TDA_FCR, TDA_FCR_FL2|TDA_FCR_FL1|TDA_FCR_FL0);
-+ tda8007_reg_write(TDA_UCR1, TDA_UCR_SS|TDA_UCR_CONV);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ while( tda8007_reg_read(TDA_USR) & TDA_USR_TBE_RBF )
-+ {
-+ hsr_reg = tda8007_reg_read(TDA_URR);
-+ udelay(5);
-+ }
-+}
-+/* ------------------------------------------------------------------------- */
-+void start_tda8007_sync(int volt)
-+{
-+ int i=0,j=0;
-+ if( tda_card_present( CARD_PORT1 ) )
-+ {
-+ printk("Card Present ");
-+ tda8007_reg_write(TDA_TOR1, TDA_TOR1_TOL2|TDA_TOR1_TOL3);
-+ tda8007_reg_write(TDA_TOR2, TDA_TOR2_TOL16|TDA_TOR2_TOL15|
-+ TDA_TOR2_TOL13|TDA_TOR2_TOL12|
-+ TDA_TOR2_TOL11);
-+ tda8007_reg_write(TDA_TOR3, 0x00);
-+ tda8007_reg_write(TDA_TOC, TDA_TOC_MODE2);
-+ tda_inituart();
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX ASYNC MODE
-+
-+ if( volt == 3 )
-+ volt = TDA_PCR_3V_5V;
-+ else
-+ volt = 0x00;
-+
-+ tda8007_reg_write(TDA_PCR, 0x00|volt); // Set /Reset,3V
-+ udelay(1000);
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_START|volt); // /Reset,3V,Start
-+ udelay(2000);
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_RSTIN|TDA_PCR_START|volt); // Set Reset High
-+ i=0;
-+ while( 1 )// !serstat()
-+ {
-+ if( ((msr[i]=tda8007_reg_read(TDA_MSR)) & TDA_MSR_FE) == 0 )
-+ {
-+ hsr[i]=tda8007_reg_read(TDA_HSR);
-+ usr[i]=tda8007_reg_read(TDA_USR);
-+ csr[i]=tda8007_reg_read(TDA_CSR);
-+ urr[i]=tda8007_reg_read(TDA_URR);
-+ i++;
-+ }
-+ if( i == 1 )
-+ {
-+ /* Reset SS */
-+ tda8007_reg_write(TDA_UCR1,
-+ tda8007_reg_read(TDA_UCR1) & ~TDA_UCR_SS);
-+ /* Set Autoconv high */
-+ tda8007_reg_write(TDA_UCR2,
-+ tda8007_reg_read(TDA_UCR2) | TDA_UCR_nAUTOCONV);
-+ }
-+
-+ if( i >= BUFFSIZE )
-+ {
-+ printk("Buffer Overflow");
-+ break;
-+ }
-+ // tda8007_reg_write(TDA_FCR, TDA_FCR_PEC0|TDA_FCR_FL0);
-+ }
-+ hsr[i]=tda8007_reg_read(TDA_HSR);
-+ msr[i]=tda8007_reg_read(TDA_MSR);
-+ csr[i]=tda8007_reg_read(TDA_CSR);
-+ urr[i]=tda8007_reg_read(TDA_URR);
-+ i++;
-+ //serin();
-+ if( i==1 )
-+ printk("No Characters received\n");
-+ else
-+ for(j=0;j<i-1; j++)
-+ printk("Buffer[%3d]=USR(0x%02x) HSR(0x%02x) MSR(0x%02x) CSR(0x%02x) URR(0x%02x=%c)\n",
-+ j,usr[j],hsr[j],msr[j],csr[j],urr[j],pascii(urr[j]));
-+
-+ printk("Now USR(0x%02x) HSR(0x%02x) MSR(0x%02x) CSR(0x%02x) URR(0x%02x=%c)\n",
-+ usr[j],hsr[j],msr[j],csr[j],urr[j],pascii(urr[j]));
-+
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_RSTIN|volt); // remove start
-+ udelay(2000);
-+ tda8007_reg_write(TDA_PCR, 0x00|volt); // remove Reset
-+
-+ }
-+ else
-+ {
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_3V_5V);
-+ }
-+
-+}
-+/* -------------------------------------------------------------------------*/
-+int test_tda8007(void)
-+{
-+ int c, i,j, reg,end=0;
-+
-+ printk("\nTDA8007 TEST:");
-+
-+ for( i=0; i < 0x10; i++ )
-+ printk("\nTDA8007 Reg %2d = 0x%02x ", i, tda8007_reg_read(i)&0xff);
-+
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tdaregs[i]=tda8007_reg_read(i) & 0xff;
-+ }
-+ do
-+ {
-+ printk("\nTDA8007 IRQ=%s Command:",
-+ (GPLR&(1<<10) ? "HIGH":"LOW"));
-+
-+ //c=serin();
-+ //serout(c);
-+ printk("\n");
-+
-+ switch (c )
-+ {
-+
-+ case 'c':
-+ printk("\nReg?:");
-+ //reg=gethex(serin,serout);
-+ printk("\nVal?:");
-+ //i=gethex(serin,serout);
-+ tda8007_reg_write(reg,i);
-+ j=tda8007_reg_read(reg);
-+ printk("Reg 0x%02x (0x%02x) now 0x%02x\n", reg, i, j);
-+ break;
-+
-+ case 'i':
-+ printk("\nInit\n");
-+ tda8007_init();
-+
-+ case 'p':
-+ for( i=0; i < 0x10; i++ )
-+ printk("\nTDA8007 Reg %2d = 0x%02x ", i,
-+ tda8007_reg_read(i)&0xff);
-+ break;
-+ case 'e':
-+ end=1;
-+ break;
-+
-+ case 'r':
-+ while( 1 ) // serstat() == 0
-+ {
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tdaregs[i]=tda8007_reg_read(i) & 0xff;
-+ }
-+ }
-+ //serin();
-+ break;
-+
-+ case 'S':
-+ start_tda8007_sync(5);
-+ break;
-+ case 's':
-+ start_tda8007_sync(3);
-+ break;
-+ case 'w':
-+ while( 1 )//serstat() == 0
-+ {
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tda8007_reg_write(i,0x10-i);
-+ }
-+ }
-+ //serin();
-+ break;
-+
-+ default :
-+ //serout(0x07);
-+ break;
-+ }
-+
-+ }while( end == 0 );
-+ return(0);
-+}
-+/*-------------------------------------------------------------------------*/
-+static int tda8007_ioctl(struct inode *ino, struct file *filp,
-+ uint cmd, ulong arg)
-+{
-+ unsigned int val, gain;
-+ int ret = 0;
-+
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ switch (_IOC_NR(cmd))
-+ {
-+ case TDA_INFO:
-+ break;
-+
-+ case TDA_INIT:
-+ break;
-+
-+ case TDA_SET:
-+ break;
-+
-+ case TDA_CARD_PRESENT:
-+ break;
-+
-+ case TDA_CARD_VOLT:
-+ break;
-+
-+ default:
-+ val = 0;
-+ ret = -EINVAL;
-+ break;
-+ }
-+ return ret;
-+}
-+/* ------------------------------------------------------------------------- */
-+static ssize_t proc_tda8007_read( struct file *file, char *buf, size_t nbytes,
-+ loff_t *ppos)
-+{
-+ char outputbuf[80];
-+ int count = 0;
-+ int i = 0;
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ tda8007_reg_entry_t* current_reg = NULL;
-+
-+ if ((*ppos) > 0) /* Assume reading completed in previous read*/
-+ return 0;
-+
-+ for (i=0; i<NUM_OF_TDA8007_REG_ENTRY; i++)
-+ {
-+ if (tda8007_regs[i].low_ino==i_ino)
-+ {
-+ if( tda8007_regs[i].mode == 2 ) /* write only */
-+ {
-+ printk("%s\n", tda8007_regs[i].description);
-+ printk("Read operation is on this register not possible!\n");
-+ return -EINVAL;
-+ }
-+ current_reg = &tda8007_regs[i];
-+
-+ break;
-+ }
-+ }
-+
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ printk("%s\n", current_reg->description);
-+ count += sprintf(outputbuf, "%s: 0x%x\n", current_reg->name,
-+ tda8007_reg_read( current_reg->addr ));
-+ /* count = sprintf(outputbuf, "value: 0x%x\n",
-+ tda8007_reg_read( current_reg->addr ));*/
-+
-+ *ppos+=count;
-+
-+ if (count>nbytes) /* Assume output can be read at one time */
-+ return -EINVAL;
-+
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+
-+ return count;
-+}
-+/* ------------------------------------------------------------------------- */
-+static ssize_t proc_tda8007_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ int i;
-+ unsigned long newRegValue;
-+ char *endp;
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ tda8007_reg_entry_t* current_reg=NULL;
-+
-+ for (i=0; i<NUM_OF_TDA8007_REG_ENTRY; i++)
-+ {
-+ if (tda8007_regs[i].low_ino==i_ino)
-+ {
-+ if( tda8007_regs[i].mode == 1 ) /* read only */
-+ {
-+ printk("%s\n", tda8007_regs[i].description);
-+ printk("Write operation is on this register not possible!\n");
-+ return -EINVAL;
-+ }
-+ current_reg = &tda8007_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ tda8007_reg_write( current_reg->addr, newRegValue);
-+ return (count+endp-buffer);
-+}
-+/* ------------------------------------------------------------------------- */
-+static int __init tda8007_init()
-+{
-+ int i, hsr_reg, res;
-+ int ret = -ENODEV;
-+ struct proc_dir_entry *entry;
-+ int tda8007_major = 60;
-+
-+ res = register_chrdev( tda8007_major, "tda8007", NULL );
-+
-+ if(res < 0){
-+ printk(KERN_WARNING "tda8007: can't get major%d\n", tda8007_major);
-+ return res;
-+ }
-+
-+ if( tda8007_major == 0 )
-+ tda8007_major = res;
-+
-+ set_GPIO_IRQ_edge(GPIO_SMART_CARD, GPIO_RISING_EDGE);
-+
-+ ret = request_irq( IRQ_GPIO_SMART_CARD, tda8007_irq,
-+ SA_INTERRUPT, "SMARTCARD_CD", NULL );
-+ if (ret) {
-+ printk(KERN_ERR "tda8007: unable to grab irq%d: %d\n",
-+ IRQ_GPIO_SMART_CARD, ret);
-+ return ret;
-+ }
-+
-+ printk("\nInit TDA8007 IRQ=%s\n",
-+ (GPLR&(1<<10) ? "HIGH":"LOW"));
-+
-+// clear_cs3_bit(RESET_SIMCARD);
-+
-+
-+#ifdef CONFIG_PROC_FS
-+ /* Create two dir entries for the TDA8007 */
-+ tda8007dir = proc_mkdir("tda8007"/*TDA8007_DIRNAME*/, NULL);
-+ if (tda8007dir == NULL) {
-+ printk(KERN_ERR "tda80007: can't create /proc/" TDA8007_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ regdir = proc_mkdir(REG_DIRNAME, tda8007dir);
-+ if (regdir == NULL) {
-+ printk(KERN_ERR "tda8007: can't create /proc/" TDA8007_DIRNAME "/" REG_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ for(i=0;i<NUM_OF_TDA8007_REG_ENTRY;i++) {
-+ entry = create_proc_entry(tda8007_regs[i].name,
-+ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH,
-+ regdir);
-+ if(entry) {
-+ tda8007_regs[i].low_ino = entry->low_ino;
-+ entry->proc_fops = &proc_reg_operations;
-+ }
-+ else {
-+ printk( KERN_ERR
-+ "tda8007: can't create /proc/" REG_DIRNAME
-+ "/%s\n", tda8007_regs[i].name);
-+ return(-ENOMEM);
-+ }
-+ }
-+
-+#endif // CONFIG_PROC_FS
-+
-+
-+ tda8007_reg_write(TDA_CSR, 0);
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU);
-+ for( i=0; i < 16; i++ )
-+ tda8007_reg_write(i,0);
-+
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC2);
-+ tda8007_reg_write(TDA_PCR, 0); /* START=0 */
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC1);
-+ tda8007_reg_write(TDA_PCR, 0); /* START=0 */
-+ tda8007_reg_write(TDA_TOC, 0);
-+ tda8007_reg_write(TDA_FCR, TDA_FCR_FL2|TDA_FCR_FL1|TDA_FCR_FL0);
-+
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX DIS_CLK
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX CLK SYNC-MODE
-+ hsr_reg = tda8007_reg_read(TDA_HSR);
-+
-+ tda8007_reg_write(TDA_CCR, TDA_CCR_AC1|TDA_CCR_AC0); /* XTAL/8 */
-+
-+ return 0;
-+}
-+/* ------------------------------------------------------------------------- */
-+static void __exit tda8007_exit(void)
-+{
-+ int i;
-+
-+ free_irq(IRQ_GPIO_SMART_CARD, NULL);
-+ /* kfree(my_ucb);*/
-+
-+ if (regdir)
-+ {
-+ for(i=0;i<NUM_OF_TDA8007_REG_ENTRY;i++) {
-+ remove_proc_entry( tda8007_regs[i].name, regdir);
-+ }
-+ }
-+}
-+/* ------------------------------------------------------------------------- */
-+module_init(tda8007_init);
-+module_exit(tda8007_exit);
-+
-+MODULE_AUTHOR("Juergen Messerer <juergen.messerer@freesurf.ch>");
-+MODULE_DESCRIPTION("TDA8007 driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/tda8007b.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,312 @@
-+/*
-+ * Double multiprotocol IC car interface (Philips SmartCard reader)
-+ *
-+ * linux/drivers/char/tda8007b.h
-+ *
-+ * Copyright (C) 2002 juergen.messerer@freesurf.ch, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef TDA8007B_H
-+#define TDA8007B_H
-+
-+#define CS4BUSTYPE unsigned volatile long
-+#define CS4_BASE 0xf2000000
-+
-+#define CARD_PORT1 1
-+#define CARD_PORT2 2
-+#define CARD_PORT3 3
-+
-+#define TDA_REG_READ(reg) *(CS4BUSTYPE *)(CS4_BASE+reg)
-+#define TDA_REG_WRITE(reg,val) *(CS4BUSTYPE *)(CS4_BASE+reg)=val
-+
-+#define TDA_MULTIPLEXED_MODE 0
-+
-+#define TDA_UCR2_DIV 0
-+#define TDA_PDR_VAL 12
-+
-+#define pascii(i) ((i>=' ' && i < 0x7f) ? (i):'.')
-+
-+#define BUFFSIZE 128
-+
-+#define TDA_READ 1
-+#define TDA_WRITE 2
-+
-+#define TDA_INFO 1
-+#define TDA_INIT 2
-+#define TDA_SET 3
-+#define TDA_CARD_PRESENT 4
-+#define TDA_CARD_VOLT 5
-+
-+int hsr[BUFFSIZE];
-+int msr[BUFFSIZE];
-+int csr[BUFFSIZE];
-+int urr[BUFFSIZE];
-+int usr[BUFFSIZE];
-+
-+/*************************** Control Register ********************************/
-+
-+/*
-+ * Card select register (read/write)
-+ * all significant bits are cleared execept SC1 which is set (xxxx'0001)
-+ */
-+#define TDA_CSR 0x00
-+#define TDA_CSR_SC1 (1 << 0)
-+#define TDA_CSR_SC2 (1 << 1)
-+#define TDA_CSR_SC3 (1 << 2)
-+#define TDA_CSR_nRIU (1 << 3)
-+
-+/*
-+ * Clock configuration register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_CCR 0x01
-+#define TDA_CCR_AC0 (1 << 0)
-+#define TDA_CCR_AC1 (1 << 1)
-+#define TDA_CCR_AC2 (1 << 2)
-+#define TDA_CCR_SC (1 << 3)
-+#define TDA_CCR_CST (1 << 4)
-+#define TDA_CCR_SHL (1 << 5)
-+
-+/*
-+ * Programmable divider register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_PDR 0x02
-+#define TDA_PDR_PD0 (1 << 0)
-+#define TDA_PDR_PD1 (1 << 1)
-+#define TDA_PDR_PD2 (1 << 2)
-+#define TDA_PDR_PD3 (1 << 3)
-+#define TDA_PDR_PD4 (1 << 4)
-+#define TDA_PDR_PD5 (1 << 5)
-+#define TDA_PDR_PD6 (1 << 6)
-+#define TDA_PDR_PD7 (1 << 7)
-+
-+/*
-+ * UART configuration register 2(read/write)
-+ * all relevant bits are cleared after reset (x000'0000)
-+ */
-+#define TDA_UCR2 0x03
-+#define TDA_UCR_PSC (1 << 0)
-+#define TDA_UCR_CKU (1 << 1)
-+#define TDA_UCR_nAUTOCONV (1 << 2)
-+#define TDA_UCR_SAN (1 << 3)
-+#define TDA_UCR_PDWN (1 << 4)
-+#define TDA_UCR_DISAUX (1 << 5)
-+#define TDA_UCR_DISTBE_RBF (1 << 6)
-+
-+/*
-+ * Guard time register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_GTR 0x05
-+#define TDA_GTR_GT0 (1 << 0)
-+#define TDA_GTR_GT1 (1 << 1)
-+#define TDA_GTR_GT2 (1 << 2)
-+#define TDA_GTR_GT3 (1 << 3)
-+#define TDA_GTR_GT4 (1 << 4)
-+#define TDA_GTR_GT5 (1 << 5)
-+#define TDA_GTR_GT6 (1 << 6)
-+#define TDA_GTR_GT7 (1 << 7)
-+
-+/*
-+ * UART configuration register 1(read/write)
-+ * all relevant bits are cleared after reset (x000'0000)
-+ */
-+#define TDA_UCR1 0x06
-+#define TDA_UCR_CONV (1 << 0)
-+#define TDA_UCR_SS (1 << 1)
-+#define TDA_UCR_LCT (1 << 2)
-+#define TDA_UCR_T_R (1 << 3)
-+#define TDA_UCR_PROT (1 << 4)
-+#define TDA_UCR_FC (1 << 5)
-+#define TDA_UCR_FIP (1 << 6)
-+
-+/*
-+ * Power control register (read/write)
-+ * all relevant bits are cleared after reset (xx11'0000)
-+ */
-+#define TDA_PCR 0x07
-+#define TDA_PCR_START (1 << 0)
-+#define TDA_PCR_3V_5V (1 << 1)
-+#define TDA_PCR_RSTIN (1 << 2)
-+#define TDA_PCR_1V8 (1 << 3)
-+#define TDA_PCR_C4 (1 << 4)
-+#define TDA_PCR_C8 (1 << 5)
-+
-+/*
-+ * Time-out configuration register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOC 0x08
-+#define TDA_TOC_STOP_ALL 0x00
-+#define TDA_TOC_MODE1 0x61
-+#define TDA_TOC_MODE2 0x65
-+#define TDA_TOC_MODE3 0x68
-+#define TDA_TOC_MODE4 0x7c
-+#define TDA_TOC_MODE5 0xe5
-+
-+/*
-+ * Time-out register 1(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR1 0x09
-+#define TDA_TOR1_TOL0 (1 << 0)
-+#define TDA_TOR1_TOL1 (1 << 1)
-+#define TDA_TOR1_TOL2 (1 << 2)
-+#define TDA_TOR1_TOL3 (1 << 3)
-+#define TDA_TOR1_TOL4 (1 << 4)
-+#define TDA_TOR1_TOL5 (1 << 5)
-+#define TDA_TOR1_TOL6 (1 << 6)
-+#define TDA_TOR1_TOL7 (1 << 7)
-+
-+/*
-+ * Time-out register 2(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR2 0x0a
-+#define TDA_TOR2_TOL10 (1 << 0)
-+#define TDA_TOR2_TOL11 (1 << 1)
-+#define TDA_TOR2_TOL12 (1 << 2)
-+#define TDA_TOR2_TOL13 (1 << 3)
-+#define TDA_TOR2_TOL14 (1 << 4)
-+#define TDA_TOR2_TOL15 (1 << 5)
-+#define TDA_TOR2_TOL16 (1 << 6)
-+#define TDA_TOR2_TOL17 (1 << 7)
-+
-+/*
-+ * Time-out register 3(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR3 0x0b
-+#define TDA_TOR3_TOL16 (1 << 0)
-+#define TDA_TOR3_TOL17 (1 << 1)
-+#define TDA_TOR3_TOL18 (1 << 2)
-+#define TDA_TOR3_TOL19 (1 << 3)
-+#define TDA_TOR3_TOL20 (1 << 4)
-+#define TDA_TOR3_TOL21 (1 << 5)
-+#define TDA_TOR3_TOL22 (1 << 6)
-+#define TDA_TOR3_TOL23 (1 << 7)
-+
-+/*
-+ * Mixed status register (read only)
-+ * bits TBE, RBF and BGT are cleared, bit FE is set after reset (x10x'xxx0)
-+ */
-+#define TDA_MSR 0x0c
-+#define TDA_MSR_TBE_RBF (1 << 0)
-+#define TDA_MSR_INTAUX (1 << 1)
-+#define TDA_MSR_PR1 (1 << 2)
-+#define TDA_MSR_PR2 (1 << 3)
-+#define TDA_MSR_BGT (1 << 5)
-+#define TDA_MSR_FE (1 << 6)
-+
-+/*
-+ * FIFO control register (write only)
-+ * all relevant bits are cleared after reset (x000'x000)
-+ */
-+#define TDA_FCR 0x0c
-+#define TDA_FCR_FL0 (1 << 0)
-+#define TDA_FCR_FL1 (1 << 1)
-+#define TDA_FCR_FL2 (1 << 2)
-+#define TDA_FCR_PEC0 (1 << 4)
-+#define TDA_FCR_PEC1 (1 << 5)
-+#define TDA_FCR_PEC2 (1 << 6)
-+
-+/*
-+ * UART transmit register (write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_UTR 0x0d
-+#define TDA_UTR_UT0 (1 << 0)
-+#define TDA_UTR_UT1 (1 << 1)
-+#define TDA_UTR_UT2 (1 << 2)
-+#define TDA_UTR_UT3 (1 << 3)
-+#define TDA_UTR_UT4 (1 << 4)
-+#define TDA_UTR_UT5 (1 << 5)
-+#define TDA_UTR_UT6 (1 << 6)
-+#define TDA_UTR_UT7 (1 << 7)
-+
-+/*
-+ * UART receive register (read only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_URR 0x0d
-+#define TDA_URR_UR0 (1 << 0)
-+#define TDA_URR_UR1 (1 << 1)
-+#define TDA_URR_UR2 (1 << 2)
-+#define TDA_URR_UR3 (1 << 3)
-+#define TDA_URR_UR4 (1 << 4)
-+#define TDA_URR_UR5 (1 << 5)
-+#define TDA_URR_UR6 (1 << 6)
-+#define TDA_URR_UR7 (1 << 7)
-+
-+/*
-+ * UART status register (read only)
-+ * all bits are cleared (0x00'0000)
-+ */
-+#define TDA_USR 0x0e
-+#define TDA_USR_TBE_RBF (1 << 0)
-+#define TDA_USR_FER (1 << 1)
-+#define TDA_USR_OVR (1 << 2)
-+#define TDA_USR_PE (1 << 3)
-+#define TDA_USR_EA (1 << 4)
-+#define TDA_USR_TO1 (1 << 5)
-+#define TDA_USR_TO3 (1 << 7)
-+
-+/*
-+ * Hardware status register (read only)
-+ * all significant bits are cleared, except SUPL (x001'0000)
-+ */
-+#define TDA_HSR 0x0f
-+#define TDA_HSR_PTL (1 << 0)
-+#define TDA_HSR_INTAUXL (1 << 1)
-+#define TDA_HSR_PRL1 (1 << 2)
-+#define TDA_HSR_PRL2 (1 << 3)
-+#define TDA_HSR_SUPL (1 << 4)
-+#define TDA_HSR_PRTL1 (1 << 5)
-+#define TDA_HSR_PRTL2 (1 << 6)
-+
-+typedef struct tda8007_reg_entry {
-+ u32 addr;
-+ char* name;
-+ char* description;
-+ u8 mode;
-+ unsigned short low_ino;
-+} tda8007_reg_entry_t;
-+
-+
-+/*
-+ * Read : 1
-+ * Write : 2
-+ * Read/Write : 3
-+ */
-+
-+static tda8007_reg_entry_t tda8007_regs[] =
-+{
-+ {TDA_CSR, "TDA_CSR", "Card select register (read/write)", 3},
-+ {TDA_CCR, "TDA_CCR", "Clock configuration register (read/write)", 3},
-+ {TDA_PDR, "TDA_PDR", "Programmable divider register (read/write)", 3},
-+ {TDA_UCR2, "TDA_UCR2", "UART configuration register 2(read/write)", 3},
-+ {TDA_GTR, "TDA_GTR", "Guard time register (read/write)", 3},
-+ {TDA_UCR1, "TDA_UCR1", "UART configuration register 1(read/write)", 3},
-+ {TDA_PCR, "TDA_PCR", "Power control register (read/write)", 3},
-+ {TDA_TOC, "TDA_TOC", "Time-out configuration register (read/write)", 3},
-+ {TDA_MSR, "TDA_MSR", "Mixed status register (read only)", 1},
-+ {TDA_URR, "TDA_URR", "UART receive register (read only)", 1},
-+ {TDA_USR, "TDA_USR", "UART status register (read only)", 1},
-+ {TDA_HSR, "TDA_HSR", "Hardware status register (read only)", 1},
-+ {TDA_TOR1, "TDA_TOR1", "Time-out register 1(write only)", 2},
-+ {TDA_TOR2, "TDA_TOR2", "Time-out register 2(write only)", 2},
-+ {TDA_TOR3, "TDA_TOR3", "Time-out register 3(write only)", 2},
-+ {TDA_FCR, "TDA_FCR", "FIFO control register (write only)", 2},
-+ {TDA_UTR, "TDA_UTR", "UART transmit register (write only)", 2}
-+};
-+#define NUM_OF_TDA8007_REG_ENTRY (sizeof(tda8007_regs)/sizeof(tda8007_reg_entry_t))
-+/*
-+struct tda8007 {
-+
-+};
-+*/
-+#endif /* TDA8007B_H */
---- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/misc/Config.in 2004-05-02 22:45:42.000000000 +0200
-@@ -16,3 +16,15 @@
- dep_tristate ' UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND
-
- endmenu
-+mainmenu_option next_comment
-+comment 'Console Switches'
-+
-+tristate 'Console Switch Support' CONFIG_SWITCHES
-+if [ "$CONFIG_SWITCHES" != "n" ]; then
-+ dep_bool ' SA-1100 switches' CONFIG_SWITCHES_SA1100 $CONFIG_ARCH_SA1100
-+ if [ "$CONFIG_MCP_UCB1200" != "n" ]; then
-+ bool ' UCB1x00 switches' CONFIG_SWITCHES_UCB1X00
-+ fi
-+fi
-+
-+endmenu
---- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/misc/Makefile 2004-05-02 22:45:42.000000000 +0200
-@@ -21,6 +21,24 @@
- obj-$(CONFIG_MCP_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o
- obj-$(CONFIG_PXA_CERF_PDA) += cerf_ucb1400gpio.o
-
-+ifeq ($(CONFIG_SA1100_ASSABET),y)
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
-+endif
-+
-+ifeq ($(CONFIG_SA1100_SIMPAD),y)
-+export-objs += ucb1x00-simpad.o
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-simpad.o
-+endif
-+
-+obj-$(CONFIG_SWITCHES) += switches.o
-+
-+switches-objs-y += switches-core.o
-+switches-objs-$(CONFIG_SWITCHES_SA1100) += switches-sa1100.o
-+switches-objs-$(CONFIG_SWITCHES_UCB1X00) += switches-ucb1x00.o
-+
- include $(TOPDIR)/Rules.make
-
-+switches.o: $(switches-objs-y)
-+ $(LD) $(LD_RFLAG) -r -o $@ $(switches-objs-y)
-+
- fastdep:
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/switches-core.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,226 @@
-+/*
-+ * linux/drivers/misc/switches-core.c
-+ *
-+ * Copyright (C) 2000-2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 5 October 2000 - created.
-+ *
-+ * 25 October 2000 - userland file interface added.
-+ *
-+ * 13 January 2001 - added support for Spot.
-+ *
-+ * 11 September 2001 - UCB1200 driver framework support added.
-+ *
-+ * 19 December 2001 - separated out SA-1100 and UCB1x00 code.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/poll.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/wait.h>
-+
-+#include <asm/uaccess.h>
-+
-+#include "switches.h"
-+
-+
-+MODULE_AUTHOR("John Dorsey");
-+MODULE_DESCRIPTION("Console switch support");
-+MODULE_LICENSE("GPL");
-+
-+
-+struct switches_action {
-+ struct list_head list;
-+ switches_mask_t mask;
-+};
-+
-+
-+static int switches_users = 0;
-+
-+static spinlock_t switches_lock = SPIN_LOCK_UNLOCKED;
-+
-+DECLARE_WAIT_QUEUE_HEAD(switches_wait);
-+LIST_HEAD(switches_event_queue);
-+
-+
-+static ssize_t switches_read(struct file *file, char *buffer,
-+ size_t count, loff_t *pos)
-+{
-+ unsigned long flags;
-+ struct list_head *event;
-+ struct switches_action *action;
-+
-+ if (count < sizeof(struct switches_mask_t))
-+ return -EINVAL;
-+
-+ while (list_empty(&switches_event_queue)) {
-+
-+ if (file->f_flags & O_NDELAY)
-+ return -EAGAIN;
-+
-+ interruptible_sleep_on(&switches_wait);
-+
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+
-+ }
-+
-+ if (verify_area(VERIFY_WRITE, buffer, sizeof(struct switches_mask_t)))
-+ return -EFAULT;
-+
-+ spin_lock_irqsave(&switches_lock, flags);
-+
-+ event = switches_event_queue.next;
-+ action = list_entry(event, struct switches_action, list);
-+ copy_to_user(buffer, &(action->mask), sizeof(struct switches_mask_t));
-+ list_del(event);
-+ kfree(action);
-+
-+ spin_unlock_irqrestore(&switches_lock, flags);
-+
-+ return sizeof(struct switches_mask_t);
-+
-+}
-+
-+static ssize_t switches_write(struct file *file, const char *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ return -EINVAL;
-+}
-+
-+static unsigned int switches_poll(struct file *file, poll_table *wait)
-+{
-+
-+ poll_wait(file, &switches_wait, wait);
-+
-+ if (!list_empty(&switches_event_queue))
-+ return POLLIN | POLLRDNORM;
-+
-+ return 0;
-+
-+}
-+
-+static int switches_open(struct inode *inode, struct file *file)
-+{
-+
-+ if (switches_users > 0)
-+ return -EBUSY;
-+
-+ MOD_INC_USE_COUNT;
-+ ++switches_users;
-+ return 0;
-+
-+}
-+
-+static int switches_release(struct inode *inode, struct file *file)
-+{
-+
-+ --switches_users;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+
-+}
-+
-+static struct file_operations switches_ops = {
-+ read: switches_read,
-+ write: switches_write,
-+ poll: switches_poll,
-+ open: switches_open,
-+ release: switches_release
-+};
-+
-+static struct miscdevice switches_misc = {
-+ MISC_DYNAMIC_MINOR, SWITCHES_NAME, &switches_ops
-+};
-+
-+int switches_event(switches_mask_t *mask)
-+{
-+ struct switches_action *action;
-+
-+ if ((switches_users > 0) && (SWITCHES_COUNT(mask) > 0)) {
-+
-+ if ((action = (struct switches_action *)
-+ kmalloc(sizeof(struct switches_action),
-+ GFP_ATOMIC)) == NULL) {
-+ printk(KERN_ERR "%s: unable to allocate action "
-+ "descriptor\n", SWITCHES_NAME);
-+ return -1;
-+ }
-+
-+ action->mask = *mask;
-+
-+ spin_lock(&switches_lock);
-+ list_add_tail(&action->list, &switches_event_queue);
-+ spin_unlock(&switches_lock);
-+
-+ wake_up_interruptible(&switches_wait);
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static int __init switches_init(void)
-+{
-+
-+#ifdef CONFIG_SWITCHES_SA1100
-+ if (switches_sa1100_init() < 0) {
-+ printk(KERN_ERR "%s: unable to initialize SA-1100 switches\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+#endif
-+
-+#ifdef CONFIG_SWITCHES_UCB1X00
-+ if (switches_ucb1x00_init() < 0) {
-+ printk(KERN_ERR "%s: unable to initialize UCB1x00 switches\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+#endif
-+
-+ if (misc_register(&switches_misc) < 0) {
-+ printk(KERN_ERR "%s: unable to register misc device\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ printk("Console switches initialized\n");
-+
-+ return 0;
-+
-+}
-+
-+static void __exit switches_exit(void)
-+{
-+
-+#ifdef CONFIG_SWITCHES_SA1100
-+ switches_sa1100_exit();
-+#endif
-+
-+#ifdef CONFIG_SWITCHES_UCB1X00
-+ switches_ucb1x00_exit();
-+#endif
-+
-+ if (misc_deregister(&switches_misc) < 0)
-+ printk(KERN_ERR "%s: unable to deregister misc device\n",
-+ SWITCHES_NAME);
-+
-+}
-+
-+module_init(switches_init);
-+module_exit(switches_exit);
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/switches-sa1100.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,311 @@
-+/*
-+ * linux/drivers/misc/switches-sa1100.c
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created from sa1100_switches.c.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+#include <asm/arch/assabet.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch/simpad.h>
-+#endif
-+
-+#include "switches.h"
-+
-+
-+static void switches_sa1100_handler(int irq, void *dev_id,
-+ struct pt_regs *regs);
-+
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+
-+/* Assabet
-+ * ^^^^^^^
-+ * We have two general-purpose switches, S1 and S2, available via GPIO
-+ * on Assabet. This code sets bits in the range [1, 2] in the mask that
-+ * we return to userland.
-+ */
-+
-+static int assabet_switches_sa1100_init(void)
-+{
-+
-+ if (machine_has_neponset())
-+ NCR_0 |= NCR_GP01_OFF;
-+
-+ set_irq_type(IRQ_GPIO0, IRQT_BOTHEDGE);
-+ set_irq_type(IRQ_GPIO1, IRQT_BOTHEDGE);
-+
-+ if (request_irq(IRQ_GPIO0, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 0\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ if (request_irq(IRQ_GPIO1, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 1\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void assabet_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO1, NULL);
-+ free_irq(IRQ_GPIO0, NULL);
-+
-+}
-+
-+static void assabet_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO0: s = 0; break;
-+
-+ case IRQ_GPIO1: s = 1; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_ASSABET */
-+
-+
-+#ifdef CONFIG_SA1100_SPOT
-+
-+/* Spot
-+ * ^^^^
-+ * Spot (R2, R3) has a single general-purpose switch (S1), which is
-+ * also the power-on switch. We set bit [1] in the mask we return to
-+ * userland.
-+ */
-+
-+static int spot_switches_sa1100_init(void)
-+{
-+
-+ set_GPIO_IRQ_edge(GPIO_SW1, GPIO_BOTH_EDGES);
-+
-+ if (request_irq(IRQ_GPIO_SW1, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for SW1\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void spot_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO_SW1, NULL);
-+
-+}
-+
-+static void spot_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO_SW1: s = 0; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_SPOT */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+/* SIMpad
-+ * ^^^^
-+ * SIMpad has a single general-purpose switch (S0), which is
-+ * also the power-on switch. We set bit [1] in the mask we return to
-+ * userland.
-+ */
-+
-+static int simpad_switches_sa1100_init(void)
-+{
-+
-+ set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_BOTH_EDGES);
-+
-+ if (request_irq(IRQ_GPIO0, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for SW0\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void simpad_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO0, NULL);
-+
-+}
-+
-+static void simpad_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO0: s = 0; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+
-+
-+/* switches_sa1100_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * This routine is a generalized handler for SA-1100 switches
-+ * which manages action descriptors and calls a board-specific
-+ * service routine. This routine is appropriate for GPIO switches
-+ * or other primary interrupt sources, and can be registered as a
-+ * first-class IRQ handler using request_irq().
-+ */
-+static void switches_sa1100_handler(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ switches_mask_t mask;
-+
-+ SWITCHES_ZERO(&mask);
-+
-+ /* Porting note: call a board-specific switch interrupt handler
-+ * here. The handler can assume that sufficient storage for
-+ * `mask' has been allocated, and that the corresponding
-+ * switches_mask_t structure has been zeroed.
-+ */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_sa1100_handler(irq, &mask);
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ spot_switches_sa1100_handler(irq, &mask);
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_sa1100_handler(irq, &mask);
-+#endif
-+ }
-+
-+ switches_event(&mask);
-+
-+}
-+
-+int __init switches_sa1100_init(void)
-+{
-+
-+ /* Porting note: call a board-specific init routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ if (assabet_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ if (spot_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (simpad_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+
-+ return 0;
-+
-+}
-+
-+void __exit switches_sa1100_exit(void)
-+{
-+
-+ /* Porting note: call a board-specific shutdown routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_sa1100_shutdown();
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ spot_switches_sa1100_shutdown();
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_sa1100_shutdown();
-+#endif
-+ }
-+
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/switches-ucb1x00.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,331 @@
-+/*
-+ * linux/drivers/misc/switches-ucb1x00.c
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created from sa1100_switches.c.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+#include <asm/arch/assabet.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch/simpad.h>
-+#endif
-+
-+#include "switches.h"
-+#include "ucb1x00.h"
-+
-+
-+static struct ucb1x00 *ucb1x00;
-+
-+static void switches_ucb1x00_handler(int irq, void *devid);
-+
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+
-+/* Assabet
-+ * ^^^^^^^
-+ * Six switches are routed to GPIO pins on the UCB1300: S3 -- S8.
-+ * This code sets bits in the range [3, 8] in the mask that we
-+ * return to userland. Note that we transpose signals SW7 and SW8;
-+ * see assabet_switches_ucb1x00_handler().
-+ */
-+
-+static int assabet_switches_ucb1x00_init(void)
-+{
-+ int i;
-+
-+ /* Note that ucb1x00_init() must complete before this point: */
-+
-+ if ((ucb1x00 = ucb1x00_get()) == NULL) {
-+ printk(KERN_ERR "%s: UCB1300 driver not ready; switches "
-+ "3 -- 8 will not be available\n",
-+ SWITCHES_NAME);
-+ return 0;
-+ }
-+
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5, 0);
-+
-+ for (i = 0; i < 6; ++i) {
-+
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ if (ucb1x00_hook_irq(ucb1x00, i,
-+ switches_ucb1x00_handler, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to hook IRQ for "
-+ "UCB1300 IO_%d\n", SWITCHES_NAME, i);
-+ return -EBUSY;
-+ }
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void assabet_switches_ucb1x00_shutdown(void)
-+{
-+ int i;
-+
-+ for (i = 5; i >= 0; --i) {
-+
-+ ucb1x00_disable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ /* Only error conditions are ENOENT and EINVAL; silently
-+ * ignore:
-+ */
-+ ucb1x00_free_irq(ucb1x00, i, NULL);
-+
-+ }
-+
-+}
-+
-+static void assabet_switches_ucb1x00_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int last, this;
-+ static unsigned int states = 0;
-+
-+ last = ((states & (1 << irq)) != 0);
-+ this = ((ucb1x00_io_read(ucb1x00) & (1 << irq)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ /* Intel StrongARM SA-1110 Development Board
-+ * Schematics Figure 5, Sheet 5 of 12
-+ *
-+ * See switches S8 and S7. Notice their
-+ * relationship to signals SW7 and SW8. Hmmm.
-+ */
-+
-+ switch (irq) {
-+
-+ case 4:
-+
-+ SWITCHES_SET(mask, 8, this);
-+ break;
-+
-+ case 5:
-+
-+ SWITCHES_SET(mask, 7, this);
-+ break;
-+
-+ default:
-+
-+ SWITCHES_SET(mask, irq + 3, this);
-+
-+ }
-+
-+ states = this ? (states | (1 << irq)) : (states & ~(1 << irq));
-+
-+}
-+#endif /* CONFIG_SA1100_ASSABET */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+/* SIMpad
-+ * ^^^^^^
-+ * Six switches are routed to GPIO pins on the UCB1300: S3 -- S8.
-+ * This code sets bits in the range [3, 8] in the mask that we
-+ * return to userland.
-+ */
-+
-+static int simpad_switches_ucb1x00_init(void)
-+{
-+ int i;
-+
-+ /* Note that ucb1x00_init() must complete before this point: */
-+
-+ if ((ucb1x00 = ucb1x00_get()) == NULL) {
-+ printk(KERN_ERR "%s: UCB1300 driver not ready; switches "
-+ "3 -- 8 will not be available\n",
-+ SWITCHES_NAME);
-+ return 0;
-+ }
-+
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5,
-+ UCB_IO_8 | UCB_IO_9);
-+
-+ ucb1x00_disable(ucb1x00);
-+
-+ for (i = 0; i < 6; ++i) {
-+
-+ if (ucb1x00_hook_irq(ucb1x00, i,
-+ switches_ucb1x00_handler, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to hook IRQ for "
-+ "UCB1300 IO_%d\n", SWITCHES_NAME, i);
-+ return -EBUSY;
-+ }
-+
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+ }
-+
-+ return 0;
-+
-+}
-+
-+int simpad_switches_ucb1x00_reinit(void)
-+{
-+ int i;
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5,
-+ UCB_IO_8 | UCB_IO_9);
-+
-+ ucb1x00_disable(ucb1x00);
-+
-+ for (i = 0; i < 6; ++i)
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ return 0;
-+}
-+
-+static void simpad_switches_ucb1x00_shutdown(void)
-+{
-+ int i;
-+
-+ for (i = 5; i >= 0; --i) {
-+
-+ ucb1x00_disable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ /* Only error conditions are ENOENT and EINVAL; silently
-+ * ignore:
-+ */
-+ ucb1x00_free_irq(ucb1x00, i, NULL);
-+
-+ }
-+
-+}
-+
-+static void simpad_switches_ucb1x00_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int last, this;
-+ static unsigned int states = 0;
-+
-+ last = ((states & (1 << irq)) != 0);
-+ this = ((~ucb1x00_io_read(ucb1x00) & (1 << irq)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ switch (irq) {
-+
-+ case 4:
-+
-+
-+
-+ case 5:
-+
-+
-+
-+ default:
-+
-+ SWITCHES_SET(mask, irq + 3, this);
-+
-+ }
-+
-+ states = this ? (states | (1 << irq)) : (states & ~(1 << irq));
-+
-+}
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+
-+/* switches_ucb1x00_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * This routine is a generalized handler for UCB1x00 GPIO switches
-+ * which calls a board-specific service routine and passes an event
-+ * mask to the core event handler. This routine is appropriate for
-+ * systems which use the ucb1x00 framework, and can be registered
-+ * using ucb1x00_hook_irq().
-+ */
-+static void switches_ucb1x00_handler(int irq, void *devid)
-+{
-+ switches_mask_t mask;
-+
-+ SWITCHES_ZERO(&mask);
-+
-+ /* Porting note: call a board-specific UCB1x00 switch handler here.
-+ * The handler can assume that sufficient storage for `mask' has
-+ * been allocated, and that the corresponding switches_mask_t
-+ * structure has been zeroed.
-+ */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_ucb1x00_handler(irq, &mask);
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_handler(irq, &mask);
-+#endif
-+ }
-+
-+ switches_event(&mask);
-+
-+}
-+
-+int __init switches_ucb1x00_init(void)
-+{
-+
-+ /* Porting note: call a board-specific init routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ if (assabet_switches_ucb1x00_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (simpad_switches_ucb1x00_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+
-+ return 0;
-+
-+}
-+
-+void __exit switches_ucb1x00_exit(void)
-+{
-+
-+ /* Porting note: call a board-specific shutdown routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_ucb1x00_shutdown();
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_shutdown();
-+#endif
-+ }
-+
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/switches.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,28 @@
-+/*
-+ * linux/drivers/misc/switches.h
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created.
-+ */
-+
-+#if !defined(_SWITCHES_H)
-+# define _SWITCHES_H
-+
-+#include <linux/switches.h>
-+
-+#define SWITCHES_NAME "switches"
-+
-+extern int switches_event(switches_mask_t *mask);
-+
-+extern int switches_sa1100_init(void);
-+extern void switches_sa1100_exit(void);
-+
-+extern int switches_ucb1x00_init(void);
-+extern void switches_ucb1x00_exit(void);
-+
-+#endif /* !defined(_SWITCHES_H) */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-assabet.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,114 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-assabet.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * We handle the machine-specific bits of the UCB1x00 driver here.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+
-+#include "ucb1x00.h"
-+
-+static struct proc_dir_entry *dir;
-+static struct ucb1x00 *ucb;
-+
-+static int ucb1x00_assabet_read_vbatt(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb1x00_assabet_read_vcharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb1x00_assabet_read_batt_temp(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD2, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int (*fn)(struct ucb1x00 *) = data;
-+ int v, len;
-+
-+ v = fn(ucb);
-+
-+ p += sprintf(p, "%d\n", v);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init ucb1x00_assabet_init(void)
-+{
-+ struct proc_dir_entry *res;
-+
-+ ucb = ucb1x00_get();
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ dir = proc_mkdir("ucb1x00", NULL);
-+ if (!dir)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vbatt", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_vbatt);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vcharger", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_vcharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("batt_temp", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_batt_temp);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_assabet_exit(void)
-+{
-+ remove_proc_entry("vbatt", dir);
-+ remove_proc_entry("vcharger", dir);
-+ remove_proc_entry("batt_temp", dir);
-+}
-+
-+module_init(ucb1x00_assabet_init);
-+module_exit(ucb1x00_assabet_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/misc/ucb1x00-audio.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:37.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-audio.c 2004-05-02 22:48:00.000000000 +0200
-@@ -283,7 +283,7 @@
- {
- struct ucb1x00_audio *ucba;
-
-- ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
-+ ucba = kmalloc(sizeof(*ucba), GFP_ATOMIC);
- if (ucba) {
- memset(ucba, 0, sizeof(*ucba));
-
---- linux-2.4.25/drivers/misc/ucb1x00-core.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-core.c 2004-05-02 22:45:42.000000000 +0200
-@@ -215,6 +215,9 @@
- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
- ucb1x00_disable(ucb);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_reinit();
-+#endif
- }
-
- return 0;
-@@ -561,8 +564,10 @@
- default_irq = IRQ_GPIO_UCB1300_IRQ;
- #endif
- #ifdef CONFIG_SA1100_SIMPAD
-- if (machine_is_simpad())
-+ if (machine_is_simpad()) {
- default_irq = IRQ_GPIO_UCB1300_IRQ;
-+ irq_gpio_pin = GPIO_UCB1300_IRQ;
-+ }
- #endif
- #ifdef CONFIG_SA1100_SIMPUTER
- if (machine_is_simputer()) {
-@@ -660,7 +665,7 @@
- if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)
- id = UCB_ID_1400_BUGGY;
-
-- my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
-+ my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_ATOMIC);
- ret = -ENOMEM;
- if (!my_ucb)
- goto out;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-simpad.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,241 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-simpad.c
-+ *
-+ * Modified by Juergen Messerer for SIMpad
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * We handle the machine-specific bits of the UCB1x00 driver here.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+
-+#include <asm/arch-sa1100/simpad_pm.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Conversion from AD -> mV
-+ * 7.5V = 1023 7.3313mV/Digit
-+ *
-+ * 400 Units == 9.7V
-+ * a = ADC value
-+ * 21 = ADC error
-+ * 12600 = Divident to get 2*7.3242
-+ * 860 = Divider to get 2*7.3242
-+ * 170 = Voltagedrop over
-+ */
-+#define CALIBRATE_BATTERY(a) ((((a + 21)*12600)/860) + 170)
-+
-+/*
-+ * We have two types of batteries a small and a large one
-+ * To get the right value we to distinguish between those two
-+ * 450 Units == 15 V
-+ */
-+#ifdef SMALL_BATTERY
-+#define CALIBRATE_SUPPLY(a) (((a) * 1500) / 51)
-+#define MIN_SUPPLY 8500 /* Less then 8.5V means no powersupply */
-+#else
-+#define CALIBRATE_SUPPLY(a) (((a) * 1500) / 45)
-+//#define MIN_SUPPLY 14000 /* Less then 14V means no powersupply */
-+#define MIN_SUPPLY 12000 /* Less then 12V means no powersupply */
-+#endif
-+
-+/*
-+ * Charging Current
-+ * if value is >= 50 then charging is on
-+ */
-+#define CALIBRATE_CHARGING(a) (((a)* 1000)/(152/4)))
-+//#define CHARGING_LED_LEVEL 50
-+
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+#define CHARGING_LED_LEVEL 12
-+#define CHARGING_MAX_LEVEL 120
-+#define BATT_FULL 8100
-+#define BATT_LOW 7300
-+#define BATT_CRITICAL 6700
-+#define BATT_EMPTY 6400
-+
-+
-+#else // CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+#define CHARGING_LED_LEVEL 28
-+#define CHARGING_MAX_LEVEL 265
-+#define BATT_FULL 8300
-+#define BATT_LOW 7400
-+#define BATT_CRITICAL 6800
-+#define BATT_EMPTY 6500
-+
-+#endif // CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+
-+static struct proc_dir_entry *dir;
-+static struct ucb1x00 *ucb;
-+
-+static int ucb1x00_simpad_read_vbatt(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return CALIBRATE_BATTERY(val);
-+}
-+
-+static int ucb1x00_simpad_read_vcharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD2, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return CALIBRATE_SUPPLY(val);
-+}
-+
-+static int ucb1x00_simpad_read_icharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD3, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int (*fn)(struct ucb1x00 *) = data;
-+ int v, len;
-+
-+ v = fn(ucb);
-+
-+ p += sprintf(p, "%d\n", v);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+/****************************************************************************/
-+/* Functions exported for use by the kernel and kernel modules */
-+/****************************************************************************/
-+
-+int simpad_get_battery(struct simpad_battery *bstat)
-+{
-+ int icharger, vcharger, vbatt;
-+
-+ if ( ucb ) {
-+ icharger = ucb1x00_simpad_read_icharger( ucb );
-+ vcharger = ucb1x00_simpad_read_vcharger( ucb );
-+ vbatt = ucb1x00_simpad_read_vbatt( ucb );
-+ } else {
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_UNKNOWN;
-+ bstat->status = SIMPAD_BATT_STATUS_UNKNOWN;
-+ bstat->percentage = 0x64; /* lets say 100% */
-+ bstat->life = 360; /* lets say a long time */
-+ return 0;
-+ }
-+
-+ /* AC status */
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_OFFLINE;
-+ if ( vcharger>MIN_SUPPLY ) {
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_ONLINE;
-+ }
-+
-+ /* charging */
-+ bstat->status = 0x0;
-+ if ( icharger > CHARGING_LED_LEVEL ) {
-+ bstat->status = SIMPAD_BATT_STATUS_CHARGING;
-+ }
-+
-+ if ( vbatt > BATT_LOW )
-+ bstat->status |= SIMPAD_BATT_STATUS_HIGH;
-+ else if ( vbatt < BATT_CRITICAL )
-+ bstat->status |= SIMPAD_BATT_STATUS_CRITICAL;
-+ else
-+ bstat->status |= SIMPAD_BATT_STATUS_LOW;
-+
-+ if (bstat->status & SIMPAD_BATT_STATUS_CHARGING) {
-+ if (icharger > CHARGING_MAX_LEVEL) icharger = CHARGING_MAX_LEVEL;
-+ if (icharger < CHARGING_LED_LEVEL) icharger = CHARGING_LED_LEVEL;
-+ bstat->percentage = 100 - 100 * (icharger - CHARGING_LED_LEVEL) /
-+ (CHARGING_MAX_LEVEL - CHARGING_LED_LEVEL);
-+ } else {
-+ if (vbatt > BATT_FULL) vbatt = BATT_FULL;
-+ if (vbatt < BATT_EMPTY) vbatt = BATT_EMPTY;
-+ bstat->percentage = 100 * (vbatt - BATT_EMPTY) / (BATT_FULL - BATT_EMPTY);
-+ }
-+
-+ /* let's assume: full load is 7h */
-+ /* bstat->life = 420*bstat->percentage/100; */
-+ bstat->life = 0;
-+
-+#if 0
-+ printk("get_battery: ac: %02x / ch: %02x / perc: %02x / life: %d\n",
-+ bstat->ac_status, bstat->status,
-+ bstat->percentage, bstat->life );
-+#endif
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(simpad_get_battery);
-+
-+/****************************************************************************/
-+/* sample proc interface */
-+/****************************************************************************/
-+static int __init ucb1x00_simpad_init(void)
-+{
-+ struct proc_dir_entry *res;
-+
-+ ucb = ucb1x00_get();
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ dir = proc_mkdir("ucb1x00", NULL);
-+ if (!dir)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vbatt", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_vbatt);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vcharger", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_vcharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("icharger", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_icharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_simpad_exit(void)
-+{
-+ remove_proc_entry("vbatt", dir);
-+ remove_proc_entry("vcharger", dir);
-+ remove_proc_entry("icharger", dir);
-+}
-+
-+module_init(ucb1x00_simpad_init);
-+module_exit(ucb1x00_simpad_exit);
-+
-+MODULE_AUTHOR("Juergen Messerer <juergen.messerer@freesurf.ch>");
-+MODULE_DESCRIPTION("SIMpad noddy testing only example ADC driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/misc/ucb1x00-ts.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-ts.c 2004-05-02 22:45:42.000000000 +0200
-@@ -356,7 +356,7 @@
- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-
-- udelay(55);
-+ udelay(250); /*former 55*/
-
- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
- }
-@@ -379,7 +379,7 @@
- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-
-- udelay(55);
-+ udelay(250); /*former 55*/
-
- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
- }
---- linux-2.4.25/drivers/mtd/Config.in~2.4.25-vrs2-pxa1-jpm1.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/Config.in 2004-05-02 22:45:42.000000000 +0200
-@@ -11,6 +11,9 @@
- if [ "$CONFIG_MTD_DEBUG" = "y" ]; then
- int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0
- fi
-+ if [ "$CONFIG_CRAMFS" = "y" ]; then
-+ bool ' Cramfs root partition' CONFIG_ROOT_CRAMFS
-+ fi
- dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
- dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
- dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
---- linux-2.4.25/drivers/mtd/maps/sa1100-flash.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:37.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/sa1100-flash.c 2004-05-02 22:45:42.000000000 +0200
-@@ -767,40 +767,38 @@
- #endif
-
- #ifdef CONFIG_SA1100_SIMPAD
--#define SIMPAD_FLASH_SIZE 0x02000000
--static struct mtd_partition simpad_partitions[] = {
-- {
-- name: "SIMpad boot firmware",
-- size: 0x00080000,
-- offset: 0,
-- mask_flags: MTD_WRITEABLE, /* force read-only */
-- }, {
-- name: "SIMpad kernel",
-- size: 0x00100000,
-- offset: 0x00080000,
-- }, {
--#ifdef CONFIG_JFFS2_FS
-- name: "SIMpad root jffs2",
-- size: MTDPART_SIZ_FULL,
-- offset: 0x00180000,
-+
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
-+#define SIMPAD_FLASH_SIZE 0x01000000
- #else
-- name: "SIMpad initrd",
-- size: 0x00300000,
-- offset: 0x00180000,
-- }, {
-- name: "SIMpad root cramfs",
-- size: 0x00300000,
-- offset: 0x00480000,
-- }, {
-- name: "SIMpad usr cramfs",
-- size: 0x005c0000,
-- offset: 0x00780000,
-- }, {
-- name: "SIMpad usr local",
-- size: MTDPART_SIZ_FULL,
-- offset: 0x00d40000,
-+#define SIMPAD_FLASH_SIZE 0x02000000
- #endif
-- }
-+
-+static struct mtd_partition simpad_partitions[] = {
-+ {
-+ name: "SIMpad boot firmware",
-+ offset: 0,
-+ size: 0x00080000,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "SIMpad kernel",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00100000
-+ },{
-+#ifdef CONFIG_ROOT_CRAMFS
-+ name: "SIMpad root cramfs",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00D80000
-+ },{
-+ name: "SIMpad local jffs",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL
-+#else
-+ name: "SIMpad root jffs2",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL
-+#endif /* CONFIG_CRAM_FS */
-+ }
- };
- #endif /* CONFIG_SA1100_SIMPAD */
-
---- linux-2.4.25/drivers/pcmcia/sa1100_simpad.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:37.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_simpad.c 2004-05-02 22:45:42.000000000 +0200
-@@ -9,20 +9,18 @@
-
- #include <asm/hardware.h>
- #include <asm/irq.h>
-+#include <asm/arch/simpad.h>
-+
- #include "sa1100_generic.h"
--
-+
- extern long get_cs3_shadow(void);
--extern void set_cs3_bit(int value);
-+extern void set_cs3_bit(int value);
- extern void clear_cs3_bit(int value);
-
-
- static int simpad_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
-
-- set_cs3_bit(PCMCIA_RESET);
-- clear_cs3_bit(PCMCIA_BUFF_DIS);
-- clear_cs3_bit(PCMCIA_RESET);
--
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
-
- /* Set transition detect */
-@@ -63,6 +61,9 @@
-
- if(state_array->size<2) return -1;
-
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-+
- levels=GPLR;
-
- state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
-@@ -100,13 +101,15 @@
- static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
- *configure)
- {
-- unsigned long value, flags;
-+ static int irq_disabled = 0;
-
-- if(configure->sock>1) return -1;
-+ if(configure->sock>1)
-+ return -1;
-
-- if(configure->sock==0) return 0;
-+ if(configure->sock==0)
-+ return 0;
-
-- save_flags_cli(flags);
-+ //local_irq_save(flags);
-
- /* Murphy: see table of MIC2562a-1 */
-
-@@ -116,8 +119,8 @@
- break;
-
- case 33:
-- clear_cs3_bit(VCC_3V_EN|EN0);
-- set_cs3_bit(VCC_5V_EN|EN1);
-+ clear_cs3_bit(VCC_3V_EN|EN1);
-+ set_cs3_bit(VCC_5V_EN|EN0);
- break;
-
- case 50:
-@@ -129,26 +132,50 @@
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
-- restore_flags(flags);
-+ //restore_flags(flags);
- return -1;
- }
-
-- /* Silently ignore Vpp, output enable, speaker enable. */
-+ if(configure->reset)
-+ set_cs3_bit(PCMCIA_RESET);
-+ else
-+ clear_cs3_bit(PCMCIA_RESET);
-+
-+ if(configure->output)
-+ clear_cs3_bit(PCMCIA_BUFF_DIS);
-+ else
-+ set_cs3_bit(PCMCIA_BUFF_DIS);
-
-- restore_flags(flags);
-+ if(configure->irq) {
-+ enable_irq(IRQ_GPIO_CF_IRQ);
-+ irq_disabled = 0;
-+ }
-+ else {
-+ if (!irq_disabled) {
-+ disable_irq(IRQ_GPIO_CF_IRQ);
-+ irq_disabled = 1;
-+ }
-+ }
-+
-+ //local_irq_restore(flags);
-
- return 0;
- }
-
- static int simpad_pcmcia_socket_init(int sock)
- {
-- set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_BOTH_EDGES);
-+ if(sock == 1)
-+ set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_BOTH_EDGES);
- return 0;
- }
-
- static int simpad_pcmcia_socket_suspend(int sock)
- {
-- set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_NO_EDGES);
-+ if(sock == 1)
-+ {
-+ set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_NO_EDGES);
-+ set_cs3_bit(PCMCIA_RESET);
-+ }
- return 0;
- }
-
---- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/video/Config.in 2004-05-02 22:45:42.000000000 +0200
-@@ -61,6 +61,10 @@
- fi
- fi
- dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
-+ if [ "$CONFIG_SA1100_SIMPAD" = "y" -o \
-+ "$CONFIGG_SA1100_GDS2200" = "y" ]; then
-+ bool ' MQ200 VGA support' CONFIG_FB_MQ200
-+ fi
- if [ "$CONFIG_APOLLO" = "y" ]; then
- define_bool CONFIG_FB_APOLLO y
- fi
---- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/drivers/video/Makefile 2004-05-02 22:45:42.000000000 +0200
-@@ -141,6 +141,7 @@
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
- obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
-+obj-$(CONFIG_FB_MQ200) += mq200fb.o
-
- # Generic Low Level Drivers
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/mq200fb.c 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,1963 @@
-+/* MQ200 console frame buffer driver---mq200fb.c
-+ *
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ */
-+
-+#include <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/vmalloc.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/interrupt.h>
-+#include <linux/proc_fs.h> /* all the /proc functions */
-+#include <linux/ioport.h>
-+#include <asm/uaccess.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <asm/io.h>
-+
-+#include <linux/console.h>
-+
-+#include <video/fbcon.h>
-+#ifdef CONFIG_FBCON_MFB
-+#include <video/fbcon-mfb.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB2
-+#include <video/fbcon-cfb2.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB4
-+#include <video/fbcon-cfb4.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB8
-+#include <video/fbcon-cfb8.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+#include <video/fbcon-cfb16.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+#include <video/fbcon-cfb24.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+#include <video/fbcon-cfb32.h>
-+#endif
-+
-+#include <video/MQ200/mq2hw.h>
-+#include <video/MQ200/mqdata.h>
-+#include <video/MQ200/mqplat.h>
-+
-+/* GPIO handling */
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+
-+#ifdef TEST
-+#undef PDEBUG /* Safety */
-+
-+#define PDEBUG(fmt, args...) printk(KERN_EMERG fmt, ##args)
-+#else
-+#define PDEBUG(fmt, args...)
-+#endif
-+
-+#define MQ200_DIRNAME "driver/mq200"
-+#define REG_DIRNAME "registers"
-+
-+void enable_cursor(void *pMQMMIO);
-+
-+static ssize_t proc_read_reg(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos);
-+static ssize_t proc_write_reg(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos);
-+
-+static struct file_operations proc_reg_operations = {
-+ read: proc_read_reg,
-+ write: proc_write_reg
-+};
-+
-+typedef struct sa1110_reg_entry {
-+ u32 phyaddr;
-+ char* name;
-+ char* description;
-+ unsigned short low_ino;
-+} sa1110_reg_entry_t;
-+
-+#define CMAPSIZE 32
-+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-+
-+#define mq200_p2v( x ) \
-+ (((x) - 0x4b800000) + 0xf2800000)
-+
-+/* The following is copied from mq2hw.c for initialization of MQ200 */
-+/* PLL1 data */
-+#define PLL1_83MHZ 0x0EF2082A
-+#define DEF_MIU2_83MHZ 0x4143E086
-+#define PLL1_50MHZ 0x0B200A2A
-+#define DEF_MIU2_50MHZ 0x40C30086
-+
-+/* Miscellaneous default data */
-+#define DEF_D1 0x05000271
-+#define DEF_D2 0x00000271
-+#define DEF_MIU3 0x6D6AABFF
-+#define DEF_MIU4 0x00000001
-+#define DEF_MIU5 0x0000010D
-+
-+#ifdef CONFIG_SA1100_GDS2200
-+#define DEF_GPO_CONTROL 0x00020054
-+#else
-+#define DEF_GPO_CONTROL 0x00000000
-+#endif
-+
-+#define DEF_GPIO_CONTROL 0x00000000
-+#define DEF_PWM_CONTROL 0x00A16c44
-+#define PWMOFFMASK 0xFF0FFF0F
-+
-+struct fb_info_mq200 {
-+ struct fb_info fb_info;
-+ struct fb_fix_screeninfo fix;
-+ struct fb_var_screeninfo var;
-+ struct display disp;
-+ struct {
-+ __u8 red, green, blue;
-+ } palette[256];
-+ struct fb_info_mq200 *next;
-+ unsigned int mqMmioAddrVirt;
-+ unsigned int mqFbAddrVirt;
-+ unsigned int mqMmioAddrPhys;
-+ unsigned int mqFbAddrPhys;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+};
-+
-+u32 mqflag;
-+u32 mqMmioAddr, mqFbAddr;
-+
-+/* Interface need to console.c. The following variable are defined in
-+ drivers/char/console.c */
-+
-+extern unsigned char color_table[];
-+extern int default_red[];
-+extern int default_grn[];
-+extern int default_blu[];
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+ extern void set_cs3_bit(int value);
-+ extern void clear_cs3_bit(int value);
-+ DISPLAY_CONFIG dc = {800, 600, 16, 60, 1600, 0x00130004};
-+#else
-+ DISPLAY_CONFIG dc = {800, 600, 32, 60, 3200, 0x0023000f};
-+#endif
-+
-+static int currcon = 0;
-+static char mq200fb_name[16] = "MQ200FB";
-+
-+static struct fb_var_screeninfo mq200fb_default = {
-+ /* 800x600, 32 bpp */
-+ 800, 600, 800, 600, 0, 0, 32, 0,
-+ {0, 8, 0}, {8, 8, 0}, {16, 8, 0}, {24, 8, 0},
-+ 0, 0, -1, -1, 0, MQ200_FB_SIZE, 64, 64, 32, 32, 64, 2,
-+ 0, FB_VMODE_NONINTERLACED
-+};
-+static union {
-+ u16 cfb16[CMAPSIZE];
-+ u32 cfb24[CMAPSIZE];
-+ u32 cfb32[CMAPSIZE];
-+} fbcon_cmap;
-+
-+static struct proc_dir_entry *regdir;
-+static struct proc_dir_entry *mq200dir;
-+static struct proc_dir_entry *driverdir;
-+
-+/* Functions used to initialize MQ200 chip */
-+void setmqmode(PDISPLAY_CONFIG, void *);
-+void setup_cursor(void *);
-+void onoffdisplay(int, void *);
-+unsigned long getbppbits(int);
-+PDISPLAY_TIMING getgcparam(int, int, int);
-+void setpal(int, unsigned long, void *);
-+void setupfp(int, void *);
-+void setuphfbuffer(int, unsigned long, void *);
-+void setupgc(int, int, int, int, int, void *);
-+void setupgcmem(PDISPLAY_CONFIG, unsigned long, void *);
-+long idmqchip(void *pMQMMIO);
-+void turnoffMQ200(void * pMQMMIO);
-+
-+/* Interface used by the world */
-+int mq200fb_setup(char*);
-+static int mq200fb_open(struct fb_info *info, int user);
-+static int mq200fb_release (struct fb_info *info, int user);
-+static int mq200fb_get_fix(struct fb_fix_screeninfo *fix, int con, \
-+ struct fb_info *info);
-+static int mq200fb_get_var(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_set_var(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_pan_display(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, \
-+ struct fb_info *info);
-+static int mq200fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, \
-+ struct fb_info *info);
-+static int mq200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-+ u_long arg, int con, struct fb_info *info);
-+
-+/* Interface to the low level console driver */
-+int mq200fb_init(void);
-+static int mq200fbcon_switch(int con, struct fb_info *info);
-+static int mq200fbcon_updatevar(int con, struct fb_info *info);
-+static void mq200fbcon_blank(int blank, struct fb_info *info);
-+
-+/* int sa1100fb_map_video_memory(void * pmem int memsize); */
-+
-+/*
-+ *Internal routines
-+ */
-+
-+static u_long get_line_length(int xres_virtual, int bpp);
-+static void mq200fb_encode_fix(struct fb_fix_screeninfo *fix,
-+ struct fb_var_screeninfo *var);
-+static void set_color_bitfields(struct fb_var_screeninfo *var);
-+static int mq200fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-+ u_int *transp, struct fb_info *info);
-+static int mq200fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info);
-+static void do_install_cmap(int con, struct fb_info *info);
-+
-+#ifdef CONFIG_PM
-+static int mq200fb_pm_callback(struct pm_dev *, pm_request_t, void *);
-+#endif
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+static void mq200_backlight(void *, int);
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+static void writeBrightness(void *, int);
-+#endif
-+
-+static struct fb_ops mq200fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: mq200fb_get_fix,
-+ fb_get_var: mq200fb_get_var,
-+ fb_set_var: mq200fb_set_var,
-+ fb_get_cmap: mq200fb_get_cmap,
-+ fb_set_cmap: mq200fb_set_cmap,
-+ fb_pan_display: mq200fb_pan_display,
-+ fb_ioctl: mq200fb_ioctl,
-+};
-+
-+typedef struct mq200_reg_entry {
-+ u32 phyaddr;
-+ char* name;
-+ char* description;
-+ unsigned short low_ino;
-+} mq200_reg_entry_t;
-+
-+static mq200_reg_entry_t mq200_regs[] =
-+{
-+ { 0x4be00000, "PM_MISC", "MQ200 PM_MISC" },
-+ { 0x4be00004, "D1_STATE", "MQ200 D1_STATE" },
-+ { 0x4be00008, "D2_STATE", "MQ200 D2_STATE" },
-+ { 0x4be00018, "PLL2_CONTROL", "MQ200 PLL2_CONTROL" },
-+ { 0x4be0001c, "PLL3_CONTROL", "MQ200 PLL3_CONTROL" },
-+ { 0x4be02000, "CPU_CONTROL", "MQ200 CPU_CONTROL" },
-+ { 0x4be02004, "DRAW_STATUS", "MQ200 DRAW_STATUS" },
-+ { 0x4be04000, "MIU_CONTROL1", "MQ200 MIU_CONTROL1" },
-+ { 0x4be04004, "MIU_CONTROL2", "MQ200 MIU_CONTROL2" },
-+ { 0x4be04008, "MIU_CONTROL3", "MQ200 MIU_CONTROL3" },
-+ { 0x4be0400c, "MIU_CONTROL4", "MQ200 MIU_CONTROL4" },
-+ { 0x4be04010, "MIU_CONTROL5", "MQ200 MIU_CONTROL5" },
-+ { 0x4be0a000, "GC1_CONTROL", "MQ200 GC1_CONTROL" },
-+ { 0x4be0a004, "GC1_CRT_CONTROL", "MQ200 GC1_CRT_CONTROL" },
-+ { 0x4be0a008, "HD1_CONTROL", "MQ200 HD1_CONTROL" },
-+ { 0x4be0a00c, "VD1_CONTROL", "MQ200 VD1_CONTROL" },
-+ { 0x4be0a010, "HS1_CONTROL", "MQ200 HS1_CONTROL" },
-+ { 0x4be0a014, "VS1_CONTROL", "MQ200 VS1_CONTROL" },
-+ { 0x4be0a020, "HW1_CONTROL", "MQ200 HW1_CONTROL" },
-+ { 0x4be0a024, "VW1_CONTROL", "MQ200 VW1_CONTROL" },
-+ { 0x4be0a040, "HW_CURSOR1_POS", "MQ200 HW_CURSOR1_POS" },
-+ { 0x4be0a044, "HW_CURSOR1_ADDR", "MQ200 HW_CURSOR1_ADDR" },
-+ { 0x4be0e000, "FP_CONTROL", "MQ200 FP_CONTROL" },
-+ { 0x4be0e004, "FP_PIN_CONTROL", "MQ200 FP_PIN_CONTROL" },
-+ { 0x4be0e008, "FP_GPO_CONTROL", "MQ200 FP_GPO_CONTROL" },
-+ { 0x4be0e00c, "FP_GPIO_CONTROL", "MQ200 FP_GPIO_CONTROL" },
-+ { 0x4be0e010, "STN_CONTROL", "MQ200 STN_CONTROL" },
-+ { 0x4be0e014, "DSTN_FB_CONTROL", "MQ200 DSTN_FB_CONTROL" },
-+ { 0x4be0e03c, "PWM_CONTROL", "MQ200 PWM_CONTROL" },
-+ { 0x4be14000, "DC_0", "MQ200 DC_1" },
-+ { 0x4be14004, "DC_1", "MQ200 DC_2" },
-+ { 0x4be14008, "DC_SW_0", "MQ200 DC_SW_0" },
-+ { 0x4be1400c, "DC_SW_1", "MQ200 DC_SW_1" },
-+ { 0x4be16040, "PMR", "MQ200 PMR" },
-+ { 0x4be16044, "PMCSR", "MQ200 PMCSR" }
-+};
-+
-+#define NUM_OF_MQ200_REG_ENTRY (sizeof(mq200_regs)/sizeof(mq200_reg_entry_t))
-+
-+static int mq200fb_open(struct fb_info *info, int user)
-+{
-+ /*
-+ * Nothing, only a usage count for the moment
-+ */
-+ MOD_INC_USE_COUNT;
-+ return(0);
-+
-+}
-+
-+/* Release console */
-+static int mq200fb_release (struct fb_info *info, int user)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+ turnoffMQ200((void *) p->mqMmioAddrVirt);
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+/* Get the Fixed Part of the Display */
-+static int mq200fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_get_fix.\n", __LINE__);
-+
-+ *fix = p->fix;
-+ return 0;
-+
-+}
-+
-+
-+ /*
-+ * Get the User Defined Part of the Display
-+ */
-+
-+static int mq200fb_get_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_get_var.\n", __LINE__);
-+
-+ *var = p->var;
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Set the User Defined Part of the Display
-+ */
-+
-+static int mq200fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 * p = (struct fb_info_mq200 *) info;
-+ int err, activate = var->activate;
-+ int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
-+ u_long line_length;
-+
-+ struct display *display;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_set_var.\n", __LINE__);
-+
-+ if (con >= 0)
-+ display = &fb_display[con];
-+ else
-+ display = &(p->disp); /* used during initialization */
-+
-+ /*
-+ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-+ * as FB_VMODE_SMOOTH_XPAN is only used internally
-+ */
-+
-+ if (var->vmode & FB_VMODE_CONUPDATE) {
-+ var->vmode |= FB_VMODE_YWRAP;
-+ var->xoffset = display->var.xoffset;
-+ var->yoffset = display->var.yoffset;
-+ }
-+
-+ /*
-+ * Memory limit
-+ */
-+ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-+ if (line_length*var->yres_virtual > MQ200_FB_SIZE)
-+ return -ENOMEM;
-+
-+ set_color_bitfields(var);
-+
-+ if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-+ oldxres = display->var.xres;
-+ oldyres = display->var.yres;
-+ oldvxres = display->var.xres_virtual;
-+ oldvyres = display->var.yres_virtual;
-+ oldbpp = display->var.bits_per_pixel;
-+ display->var = *var;
-+ if (oldxres != var->xres || oldyres != var->yres ||
-+ oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
-+ oldbpp != var->bits_per_pixel) {
-+
-+ display->screen_base = (char *) p->mqFbAddrVirt;
-+ display->visual = p->fix.visual;
-+ display->type = p->fix.type;
-+ display->type_aux = p->fix.type_aux;
-+ display->ypanstep = p->fix.ypanstep;
-+ display->ywrapstep = p->fix.ywrapstep;
-+ display->line_length = p->fix.line_length;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef CONFIG_FBCON_MFB
-+ case 1:
-+ display->dispsw = &fbcon_mfb;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB2
-+ case 2:
-+ display->dispsw = &fbcon_cfb2;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB4
-+ case 4:
-+ display->dispsw = &fbcon_cfb4;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB8
-+ case 8:
-+ display->dispsw = &fbcon_cfb8;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ display->dispsw = &fbcon_cfb16;
-+ display->dispsw_data = fbcon_cmap.cfb16;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ display->dispsw = &fbcon_cfb24;
-+ display->dispsw_data = fbcon_cmap.cfb24;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ display->dispsw = &fbcon_cfb32;
-+ display->dispsw_data = fbcon_cmap.cfb32;
-+ break;
-+#endif
-+ default:
-+ display->dispsw = &fbcon_dummy;
-+ break;
-+ }
-+
-+
-+ if (p->fb_info.changevar)
-+ (*p->fb_info.changevar)(con);
-+ }
-+
-+ if (oldbpp != var->bits_per_pixel) {
-+ if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-+ return err;
-+ do_install_cmap(con, info);
-+ }
-+
-+ }
-+
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Pan or Wrap the Display
-+ *
-+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-+ */
-+
-+static int mq200fb_pan_display(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ PDEBUG("mq200fb: %i---mq200fb_pan_display.\n", __LINE__);
-+
-+ if (var->vmode & FB_VMODE_YWRAP) {
-+ if (var->yoffset < 0 ||
-+ var->yoffset >= fb_display[con].var.yres_virtual ||
-+ var->xoffset)
-+ return -EINVAL;
-+ } else {
-+ if (var->xoffset+fb_display[con].var.xres >
-+ fb_display[con].var.xres_virtual ||
-+ var->yoffset+fb_display[con].var.yres >
-+ fb_display[con].var.yres_virtual)
-+ return -EINVAL;
-+ }
-+ fb_display[con].var.xoffset = var->xoffset;
-+ fb_display[con].var.yoffset = var->yoffset;
-+ if (var->vmode & FB_VMODE_YWRAP)
-+ fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-+ else
-+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
-+ return 0;
-+}
-+
-+ /*
-+ * Get the Colormap
-+ */
-+
-+static int mq200fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ PDEBUG("mq200fb: %i---mq200fb_get_cmap.\n", __LINE__);
-+
-+ if (con == currcon) /* current console? */
-+ return fb_get_cmap(cmap, kspc, mq200fb_getcolreg, info);
-+ else if (fb_display[con].cmap.len) /* non default colormap? */
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ {
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-+ }
-+ return 0;
-+}
-+
-+ /*
-+ * Set the Colormap
-+ */
-+
-+static int mq200fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err;
-+
-+ PDEBUG("mq200fb: %i---mq200fb_set_cmap.\n", __LINE__);
-+
-+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
-+ return err;
-+ }
-+ if (con == currcon) /* current console? */
-+ return fb_set_cmap(cmap, kspc, mq200fb_setcolreg, info);
-+ else
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ return 0;
-+}
-+
-+
-+static int mq200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-+ u_long arg, int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+
-+int __init mq200fb_setup(char *options)
-+{
-+ PDEBUG("mq200fb.c: %i---mq200fb_setup\n", __LINE__);
-+
-+/*
-+ char *this_opt;
-+
-+ fb_info.fontname[0] = '\0';
-+
-+ if (!options || !*options)
-+ return 0;
-+
-+ for (this_opt = strtok(options, ","); this_opt;
-+ this_opt = strtok(NULL, ",")) {
-+ if (!strncmp(this_opt, "font:", 5))
-+ strcpy(fb_info.fontname, this_opt+5);
-+ }
-+*/
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Initialisation
-+ */
-+
-+int __init mq200fb_init(void)
-+{
-+ struct fb_info_mq200 *p = NULL;
-+ int i; /* used as loop counter */
-+ struct proc_dir_entry *entry;
-+
-+ p = (struct fb_info_mq200 *) kmalloc(sizeof(*p), GFP_ATOMIC);
-+ if(p==NULL)
-+ return 0;
-+ memset(p, 0, sizeof(*p));
-+
-+ mq200dir = proc_mkdir(MQ200_DIRNAME, NULL);
-+ if (mq200dir == NULL) {
-+ printk(KERN_ERR "mq200fb: can't create /proc/" MQ200_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ regdir = proc_mkdir(REG_DIRNAME, mq200dir);
-+ if (regdir == NULL) {
-+ printk(KERN_ERR "mq200fb: can't create /proc/" MQ200_DIRNAME "/" REG_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ for(i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ entry = create_proc_entry(mq200_regs[i].name,
-+ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH,
-+ regdir);
-+ if(entry) {
-+ mq200_regs[i].low_ino = entry->low_ino;
-+ entry->proc_fops = &proc_reg_operations;
-+ }
-+ else {
-+ printk( KERN_ERR
-+ "mq200fb: can't create /proc/" REG_DIRNAME
-+ "/%s\n", mq200_regs[i].name);
-+ return(-ENOMEM);
-+ }
-+ }
-+
-+
-+#ifdef MQ_SA1110
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+ pCPUReg=(u32 *)ioremap( MSC2, 4);
-+ *pCPUReg = 0x42194449;
-+ iounmap((void *) pCPUReg);
-+
-+ GPDR |= 0x08000000;
-+ GAFR |= 0x08000000;
-+ TUCR |= 0x20000000;
-+
-+ ASSABET_BCR_set(ASSABET_BCR_GFX_RST); /* ASSABET_BCR */
-+
-+ MQ_DELAY(8);
-+ ASSABET_BCR_clear(ASSABET_BCR_GFX_RST);
-+ MQ_DELAY(30);
-+ ASSABET_BCR_set(ASSABET_BCR_GFX_RST); /* ASSABET_BCR */
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+ GPDR |= (1<<3);
-+ GAFR |= ~(1<<3);
-+ GPSR |= (1<<3);
-+#endif
-+
-+ p->mqMmioAddrPhys=REGISTER_BASE;
-+ p->mqFbAddrPhys=FB_BASE;
-+
-+ p->mqMmioAddrVirt = mqMmioAddr = 0xf2e00000;
-+ p->mqFbAddrVirt = mqFbAddr = 0xf2800000;
-+
-+#endif /* MQ_SA1110 */
-+
-+ mqflag = dc.flag;
-+
-+ PDEBUG("mq200fb.c: line %i, mqMmioAddr = 0X%08X, mqFbAddr = 0X%08X\n",\
-+ __LINE__, mqMmioAddr, mqFbAddr);
-+
-+ /* Setmode for MQ200 chip */
-+ setmqmode(&dc, (void *) mqMmioAddr);
-+
-+ /* Set fb_info_mq200.fix info */
-+ strcpy(p->fix.id, mq200fb_name);
-+ p->fix.smem_start = p->mqFbAddrPhys;
-+ p->fix.smem_len = MQ200_FB_SIZE;
-+ p->fix.mmio_start = p->mqMmioAddrPhys;
-+ p->fix.mmio_len = MQ200_MMIO_SIZE;
-+ p->fix.type = FB_TYPE_PACKED_PIXELS;
-+
-+ if(dc.bpp <= 8)
-+ p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else if (dc.bpp >= 16)
-+ p->fix.visual = FB_VISUAL_DIRECTCOLOR;
-+
-+ p->fix.line_length = dc.stride;
-+
-+ /* Set fb_info_mq200.var info */
-+ p->var.xres = dc.x;
-+ p->var.yres = dc.y;
-+ p->var.xres_virtual = dc.x;
-+ p->var.yres_virtual = dc.y;
-+ p->var.bits_per_pixel = dc.bpp;
-+
-+ if(dc.bpp == 8) {
-+ p->var.red.offset = 0;
-+ p->var.green.offset = 0;
-+ p->var.blue.offset = 0;
-+ p->var.red.length = p->var.green.length = \
-+ p->var.blue.length = dc.bpp;
-+ p->var.transp.length = 0;
-+ p->var.transp.offset = 0;
-+ }
-+ else if(dc.bpp == 16) {
-+#ifdef CONF
-+ IG_PREP
-+ p->var.red.offset = 2;
-+ p->var.green.offset = -3;
-+ p->var.blue.offset = 8;
-+#else
-+ p->var.red.offset = 11;
-+ p->var.green.offset = 5;
-+ p->var.blue.offset = 0;
-+#endif
-+
-+ p->var.red.length = 5;
-+ p->var.green.length = 6;
-+ p->var.blue.length = 5;
-+ }
-+ else if (dc.bpp == 24) {
-+#ifdef CONFIG_PREP
-+ p->var.red.offset = 8;
-+ p->var.green.offset = 16;
-+ p->var.blue.offset = 24;
-+#else
-+ p->var.red.offset = 16;
-+ p->var.green.offset = 8;
-+ p->var.blue.offset = 0;
-+#endif
-+ p->var.red.length = 8;
-+ p->var.green.length = 8;
-+ p->var.blue.length = 8;
-+ }
-+ else if(dc.bpp == 32) {
-+#ifdef CONFIG_PREP
-+ p->var.red.offset = 8;
-+ p->var.green.offset = 16;
-+ p->var.blue.offset = 24;
-+#else
-+ p->var.red.offset = 0;
-+ p->var.green.offset = 8;
-+ p->var.blue.offset = 16;
-+#endif /* CONFIG_PREP */
-+ p->var.red.length = 8;
-+ p->var.green.length = 8;
-+ p->var.blue.length = 8;
-+ }
-+
-+ p->var.transp.length = 0;
-+ p->var.transp.offset = 0;
-+ p->var.height = p->var.width = -1;
-+ p->var.vmode = FB_VMODE_NONINTERLACED;
-+ p->var.pixclock = 10000;
-+ p->var.left_margin = p->var.right_margin = 16;
-+ p->var.upper_margin = p->var.lower_margin = 16;
-+ p->var.hsync_len = p->var.vsync_len = 8;
-+
-+ /* Set fb_info_mq200.disp info */
-+ p->disp.var = p->var;
-+ p->disp.cmap.red = NULL;
-+ p->disp.cmap.green = NULL;
-+ p->disp.cmap.blue = NULL;
-+ p->disp.cmap.transp = NULL;
-+ p->disp.screen_base = (char *) p->mqFbAddrVirt;
-+ p->disp.visual = p->fix.visual;
-+ p->disp.type = p->fix.type;
-+ p->disp.type_aux = p->fix.type_aux;
-+ p->disp.line_length = p->fix.line_length;
-+ p->disp.can_soft_blank = 1;
-+
-+ switch(dc.bpp) {
-+#ifdef CONFIG_FBCON_CFB8
-+ case 8:
-+ p->disp.dispsw = &fbcon_cfb8;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ p->disp.dispsw = &fbcon_cfb16;
-+ p->disp.dispsw_data = fbcon_cmap.cfb16;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ p->disp.dispsw = &fbcon_cfb24;
-+ p->disp.dispsw_data = fbcon_cmap.cfb24;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ p->disp.dispsw = &fbcon_cfb32;
-+ p->disp.dispsw_data = fbcon_cmap.cfb32;
-+ break;
-+#endif
-+ default:
-+ PDEBUG("mq200fb.c: %i---Wrong configuration options", __LINE__);
-+ }
-+
-+ p->disp.scrollmode = SCROLL_YREDRAW;
-+
-+ strcpy(p->fb_info.modename, p->fix.id);
-+ p->fb_info.changevar = NULL;
-+ p->fb_info.node = NODEV;
-+
-+ p->fb_info.fbops = &mq200fb_ops;
-+ p->fb_info.disp = &(p->disp);
-+ p->fb_info.switch_con = &mq200fbcon_switch;
-+ p->fb_info.updatevar = &mq200fbcon_updatevar;
-+ p->fb_info.blank = &mq200fbcon_blank;
-+ p->fb_info.flags = FBINFO_FLAG_DEFAULT;
-+
-+ for (i = 0; i < 16; i++) {
-+ int j = color_table[i];
-+ p->palette[i].red = default_red[j];
-+ p->palette[i].green = default_grn[j];
-+ p->palette[i].blue = default_blu[j];
-+ }
-+
-+ if (register_framebuffer(&p->fb_info) < 0) {
-+ PDEBUG("Oops...register_framebuffer failed!\n");
-+ iounmap(p);
-+ iounmap((void *)mqMmioAddr);
-+ iounmap((void *)mqFbAddr);
-+ return -EINVAL;
-+ }
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Note that the console registers this as well, but we want to
-+ * power down the display prior to sleeping.
-+ */
-+ p->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, mq200fb_pm_callback);
-+ if (p->pm)
-+ p->pm->data = p;
-+#endif
-+ PDEBUG("fb%d: Virtual frame buffer device, using %ldK of video memory\n", \
-+ GET_FB_IDX(p->fb_info.node), MQ200_FB_SIZE >> 10);
-+ return 0;
-+}
-+
-+static int mq200fbcon_switch(int con, struct fb_info *info)
-+{
-+ /* Do we have to save the colormap? */
-+
-+ PDEBUG("mq200fb: mq200fbcon_switch.\n");
-+
-+ if (fb_display[currcon].cmap.len)
-+ fb_get_cmap(&fb_display[currcon].cmap, 1, mq200fb_getcolreg, info);
-+
-+ currcon = con;
-+ /* Install new colormap */
-+ do_install_cmap(con, info);
-+ return 0;
-+}
-+
-+/*
-+ * Update the `var' structure (called by fbcon.c)
-+ */
-+
-+static int mq200fbcon_updatevar(int con, struct fb_info *info)
-+{
-+ /* Nothing */
-+
-+ PDEBUG("mq200fb: mq200fbcon_updatevar.\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Blank the display.
-+ */
-+
-+static void mq200fbcon_blank(int blank, struct fb_info *info)
-+{
-+ /*struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;*/
-+
-+ /* Nothing */
-+ /*
-+ if(blank)
-+ onoffdisplay(DISABLE_LCD_GC1, (void *) p->mqMmioAddrVirt);
-+ else
-+ onoffdisplay(ENABLE_LCD_GC1, (void *) p->mqMmioAddrVirt);*/
-+}
-+
-+static u_long get_line_length(int xres_virtual, int bpp)
-+{
-+ u_long length;
-+
-+ PDEBUG("mq200fb: get_line_length.\n");
-+
-+ length = (xres_virtual+bpp-1)/bpp;
-+ length = (length+31)&-32;
-+ length >>= 3;
-+ return(length);
-+}
-+
-+static void mq200fb_encode_fix(struct fb_fix_screeninfo *fix,
-+ struct fb_var_screeninfo *var)
-+{
-+
-+ PDEBUG("mq200fb: mq200fb_encode_fix.\n");
-+
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, mq200fb_name);
-+ fix->smem_start = mqFbAddr;
-+ fix->smem_len = MQ200_FB_SIZE;
-+ fix->type = FB_TYPE_PACKED_PIXELS;
-+ fix->type_aux = 0;
-+ switch (var->bits_per_pixel) {
-+ case 1:
-+ fix->visual = FB_VISUAL_MONO01;
-+ break;
-+ case 2:
-+ case 4:
-+ case 8:
-+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
-+ break;
-+ case 16:
-+ case 24:
-+ case 32:
-+ fix->visual = FB_VISUAL_DIRECTCOLOR;
-+ break;
-+ }
-+ fix->ywrapstep = 1;
-+ fix->xpanstep = 1;
-+ fix->ypanstep = 1;
-+ fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-+}
-+
-+static void set_color_bitfields(struct fb_var_screeninfo *var)
-+{
-+
-+ PDEBUG("mq200fb: set_color_bitfields.\n");
-+
-+ switch (var->bits_per_pixel) {
-+ case 1:
-+ 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 */
-+#ifdef CONFIG_PREP
-+ var->red.offset = 2;
-+ var->green.offset = -3;
-+ var->blue.offset = 8;
-+#else
-+ var->red.offset = 11;
-+ var->green.offset = 5;
-+ var->blue.offset = 0;
-+#endif
-+ var->red.length = 5;
-+ var->green.length = 6;
-+ var->blue.length = 5;
-+ var->transp.length = 0;
-+ var->transp.offset = 0;
-+ break;
-+ case 24: /* RGB 888 */
-+#ifdef CONFIG_PREP
-+ var->red.offset = 8;
-+ var->green.offset = 16;
-+ var->blue.offset = 24;
-+#else
-+ var->red.offset = 16;
-+ var->green.offset = 8;
-+ var->blue.offset = 0;
-+#endif
-+ var->red.length = 8;
-+ var->green.length = 8;
-+ var->blue.length = 8;
-+ break;
-+ case 32: /* RGBA 8888 */
-+ var->red.offset = 0;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 16;
-+ var->blue.length = 8;
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ break;
-+ }
-+ var->red.msb_right = 0;
-+ var->green.msb_right = 0;
-+ var->blue.msb_right = 0;
-+ var->transp.msb_right = 0;
-+}
-+
-+
-+ /*
-+ * Read a single color register and split it into
-+ * colors/transparent. Return != 0 for invalid regno.
-+ */
-+
-+static int mq200fb_getcolreg(u_int regno, u_int *red, u_int *green,
-+ u_int *blue, u_int *transp, struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ /*PDEBUG("mq200fb: mq200fb_getcolreg.\n");*/
-+
-+ if (regno > 255)
-+ return 1;
-+ *red = (p->palette[regno].red<<8) | p->palette[regno].red;
-+ *green = (p->palette[regno].green<<8) | p->palette[regno].green;
-+ *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
-+ *transp = 0;
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Set a single color register. The values supplied are already
-+ * rounded down to the hardware's capabilities (according to the
-+ * entries in the var structure). Return != 0 for invalid regno.
-+ */
-+
-+static int mq200fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+ unsigned long color;
-+
-+ if (regno > 255)
-+ return 1;
-+
-+ /*PDEBUG("In mq200fb_setcolreg, regno = %d, 0x%0x\n", regno, red);*/
-+
-+ /*PDEBUG("mq200fb: mq200fb_setcolreg.\n");*/
-+
-+ switch (p->var.bits_per_pixel) {
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ if(regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb16[regno] =
-+ ((red & 0xf800) >> 9) |
-+ ((green & 0xf800) >> 14) |
-+ ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
-+#else
-+ fbcon_cmap.cfb16[regno] =
-+ ((red & 0xf800) >> 0) |
-+ ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
-+
-+#endif /* CONFIG_PREP */
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ if (regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb24[regno] =
-+ ((red & 0xff00)) |
-+ ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-+#else
-+ fbcon_cmap.cfb24[regno] =
-+ ((red & 0xff00) << 8) |
-+ ((green & 0xff00)) | ((blue & 0xff00) >> 8);
-+#endif
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ if(regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb32[regno] =
-+ ((red & 0xff00)) |
-+ ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-+#else
-+ fbcon_cmap.cfb32[regno] =
-+ ((red & 0xff00) >> 8) |
-+ ((green & 0xff00)) | ((blue & 0xff00) << 8);
-+#endif
-+
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ red &= 0xFF;
-+ green &= 0xFF;
-+ blue &= 0xFF;
-+
-+ p->palette[regno].red = red;
-+ p->palette[regno].green = green;
-+ p->palette[regno].blue = blue;
-+
-+ color = red | (green << 8) | (blue << 16);
-+ setpal(regno, color, (void *)p->mqMmioAddrVirt);
-+
-+ return 0;
-+}
-+
-+
-+static void do_install_cmap(int con, struct fb_info *info)
-+{
-+ if (con != currcon)
-+ return;
-+
-+ PDEBUG("mq200fb: do_install_cmap.\n");
-+
-+ if (fb_display[con].cmap.len)
-+ fb_set_cmap(&fb_display[con].cmap, 1, mq200fb_setcolreg, info);
-+ else {
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ fb_set_cmap(fb_default_cmap(size), 1, mq200fb_setcolreg, info);
-+ }
-+}
-+
-+
-+#ifdef MODULE
-+int init_module(void)
-+{
-+ return mq200fb_init();
-+}
-+
-+void cleanup_module(void)
-+{
-+ unregister_framebuffer(&(fb_info_mq200.fb_info));
-+ iounmap((void *)(fb_info_mq200.mqMmioAddrVirt));
-+ iounmap((void *)(fb_info_mq200.mqFbAddrVirt));
-+}
-+
-+#endif /* MODULE */
-+
-+/* The following is copied from mq2hw.c for initialization of MQ200 */
-+
-+long idmqchip(void *pMQMMIO)
-+{
-+ unsigned long id;
-+
-+ id = READ32(PCI_VENDOR_DEVICE);
-+ return (id);
-+}
-+
-+/* Setmode for MediaQ chip
-+ *
-+ */
-+void setmqmode(PDISPLAY_CONFIG pDC, void *pMQMMIO)
-+{
-+ volatile unsigned long regdata, pmmisc;
-+ int x=0, y=0, freq=0, paneltype; /* i is used as loop counter */
-+ unsigned long screensize, gc_startaddr;
-+
-+ printk("mq200fb: setmqmode - before reset\n");
-+ regdata = SW_CHIP_RESET;
-+ REG32(DC_0, regdata);
-+ MQ_DELAY(10);
-+ /* use 50MHz for LCD only and 83MHz if CRT is on */
-+ if (pDC->flag & CRT_ON)
-+ regdata = PLL1_83MHZ;
-+ else
-+ regdata = PLL1_50MHZ;
-+ REG32(DC_0, regdata);
-+ MQ_DELAY(30);
-+
-+ /* Enter D0 state from reset D3 state */
-+
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D0);
-+ MQ_DELAY(30);
-+
-+ while(1)
-+ {
-+ if((READ32(PCI_PM_CNTL_STATUS) & POWER_STATE_MASK) == 0x0)
-+ break;
-+ }
-+
-+ /* In stable D3 state here ... */
-+ /*
-+ * Set up PMU misc registers
-+ * - also PMCLK_2048CYCLE and FP_PMCLK_128K if SA1110
-+ */
-+ if ((READ32(DC_1) & BUS_MODE_MASK) == BUS_MODE_SA1110)
-+ regdata = GE_ENABLE|GE_BY_PLL1|PMCLK_2048CYCLE|FP_PMCLK_512;
-+ else
-+ /* the rest of CPUs */
-+ regdata = GE_ENABLE|GE_BY_PLL1;
-+ REG32(PM_MISC, regdata);
-+
-+ REG32(D1_STATE, DEF_D1);
-+ REG32(D2_STATE, DEF_D2);
-+
-+ /* To initialize MIU block ... */
-+ REG32(MIU_CONTROL1, DRAM_RESET_DISABLE);
-+ MQ_DELAY(5);
-+
-+ REG32(MIU_CONTROL1, 0x00);
-+ MQ_DELAY(5);
-+
-+ if (pDC->flag & CRT_ON)
-+ regdata = DEF_MIU2_83MHZ;
-+ else
-+ regdata = DEF_MIU2_50MHZ;
-+ REG32(MIU_CONTROL2, regdata);
-+ REG32(MIU_CONTROL3, DEF_MIU3);
-+ /* MIU REG 5 MUST BE PROGRAMMED BEFORE MIU REG 4 */
-+ REG32(MIU_CONTROL5, DEF_MIU5);
-+ REG32(MIU_CONTROL4, DEF_MIU4);
-+ MQ_DELAY(5);
-+
-+ REG32(MIU_CONTROL1, MIU_ENABLE | MIU_RESET_DISABLE);
-+ MQ_DELAY(5);
-+
-+ /* Here, MIU is supposed to ready to serve ... */
-+
-+ gc_startaddr = 0;
-+ /* Last 1KB is reserved for hardware cursor */
-+ if (mqflag & ENA_HW_CURSOR)
-+ {
-+ printk("mq200fb: enabling hardware cursor\n");
-+ setup_cursor(pMQMMIO);
-+ enable_cursor(pMQMMIO);
-+
-+ }
-+ /* Set up GE Base Address */
-+ REG32(BASE_ADDRESS, gc_startaddr);
-+ /* Set up flat panel parameters
-+ *
-+ */
-+ paneltype = pDC->flag & PANEL_TYPE_MASK;
-+ if (paneltype)
-+ {
-+ /* Panel is used as a display in the system */
-+ setupfp(paneltype, pMQMMIO);
-+
-+ /* Set up DSTN half frame buffer */
-+ screensize = pDC->x * pDC->y * pDC->bpp / 8 + gc_startaddr;
-+ setuphfbuffer(paneltype, screensize, pMQMMIO);
-+
-+ /* Get flat panel frequency */
-+ freq = fpControlData[paneltype].freq;
-+ }
-+
-+ /* Based on display configuration, proper GC is set up .. */
-+ if (pDC->flag & LARGE_DESKTOP)
-+ {
-+ switch (pDC->flag & LCDCRT_POS_MASK)
-+ {
-+ case HORI_CRT_LCD:
-+ case HORI_LCD_CRT:
-+ x = pDC->x / 2;
-+ y = pDC->y;
-+ break;
-+
-+ case VERT_CRT_LCD:
-+ case VERT_LCD_CRT:
-+ x = pDC->x;
-+ y = pDC->y / 2;
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ /* SAME_IMAGE and simultaneous LCD and/or CRT */
-+ x = pDC->x;
-+ y = pDC->y;
-+ }
-+
-+ /* Set up GC memory configuration */
-+ setupgcmem(pDC, gc_startaddr, pMQMMIO);
-+
-+ pmmisc = READ32(PM_MISC);
-+
-+ /* Set up 2 GCs */
-+ if (pDC->flag & USE_2GCs)
-+ {
-+ /* Set up GC1 for CRT */
-+ setupgc(IS_GC1, x, y, pDC->bpp, pDC->refresh, pMQMMIO);
-+
-+ /* Set up GC2 for flat panel */
-+ setupgc(IS_GC2, x, y, pDC->bpp, freq, pMQMMIO);
-+
-+ /* PLL2 and PLL3 are both used ... */
-+ /* to save a little bit power, can shut down PLL3 if both LCD
-+ and CRT are the same frequency...
-+ */
-+ pmmisc |= (PLL2_ENABLE | PLL3_ENABLE);
-+ REG32(PM_MISC, pmmisc);
-+
-+ /* Enable panel and CRT accordingly */
-+ if (pDC->flag & LCD_ON)
-+ onoffdisplay(ENABLE_LCD_GC2, pMQMMIO);
-+
-+ if (pDC->flag & CRT_ON)
-+ onoffdisplay(ENABLE_CRT_GC1, pMQMMIO);
-+ }
-+ else
-+ {
-+ /* Simultaneous mode - set up GC1 only */
-+ if (paneltype)
-+ setupgc(IS_GC1, x, y, pDC->bpp, freq, pMQMMIO);
-+ else
-+ setupgc(IS_GC1, x, y, pDC->bpp, pDC->refresh, pMQMMIO);
-+
-+ /* Use PLL2 */
-+ pmmisc |= PLL2_ENABLE;
-+ REG32(PM_MISC, pmmisc);
-+
-+ /* Enable panel and CRT accordingly */
-+ if (pDC->flag & LCD_ON)
-+ onoffdisplay(ENABLE_LCD_GC1, pMQMMIO);
-+
-+ if (pDC->flag & CRT_ON)
-+ onoffdisplay(ENABLE_CRT_GC1, pMQMMIO);
-+ }
-+}
-+
-+/* Set up flat panel register depending on panel type
-+ *
-+ */
-+void setupfp(int panel, void *pMQMMIO)
-+{
-+ PFPDATA_CONTROL pFP;
-+ int frcaddr, frcidx, i;
-+
-+ /* Locate panel data pointer */
-+ pFP = &fpControlData[panel];
-+ printk("FP_PIN_CONTROL set to %x\n", (u_int)pFP->fpPinControl);
-+ REG32(FP_CONTROL, pFP->fpControl);
-+ REG32(FP_PIN_CONTROL, pFP->fpPinControl);
-+ REG32(STN_CONTROL, pFP->stnControl);
-+ REG32(FP_GPO_CONTROL, DEF_GPO_CONTROL);
-+ REG32(FP_GPIO_CONTROL, DEF_GPIO_CONTROL);
-+ REG32(PWM_CONTROL, DEF_PWM_CONTROL);
-+
-+ /* Program FRC registers for STN panel (DSTN and SSTN) */
-+ frcidx = 0; /* DSTN */
-+ if ( (pFP->fpControl & FP_TYPE_MASK) != FP_TYPE_TFT )
-+ {
-+ if ((pFP->fpControl & FP_TYPE_MASK) == FP_TYPE_SSTN)
-+ frcidx++; /* SSTN index */
-+
-+ for ( i = frcaddr = 0; i < FRC_PATTERN_CNT; i++,frcaddr+=4 )
-+ REG32((FRC_PATTERN + frcaddr),
-+ FRCControlData[frcidx].frcPattern[i]);
-+
-+ for ( i = frcaddr = 0; i < FRC_WEIGHT_CNT; i++,frcaddr+=4 )
-+ REG32((FRC_WEIGHT + frcaddr), FRCControlData[frcidx].frcWeight[i]);
-+ }
-+
-+ /* Set up flat panel GPO and GPIO register from default */
-+ REG32(FP_GPO_CONTROL, DEF_GPO_CONTROL);
-+ REG32(FP_GPIO_CONTROL, DEF_GPIO_CONTROL);
-+
-+ return;
-+}
-+
-+/* Set up DSTN half frame buffer register depending on panel type
-+ *
-+ * panel : panel type
-+ * sizeused : used (occupied) area of frame buffer
-+ *
-+ */
-+void setuphfbuffer(int panel, unsigned long sizeused, void *pMQMMIO)
-+{
-+ PFPDATA_CONTROL pFP;
-+ unsigned long dstnfbsize, dstnstart, dstnend;
-+
-+ /* Locate panel data pointer */
-+ pFP = &fpControlData[panel];
-+
-+ /* Figure out half frame buffer for DSTN panel */
-+ if ( (pFP->fpControl & FP_TYPE_MASK) == FP_TYPE_DSTN )
-+ {
-+ /* Color D-STN memory requirement - no need to *3 for mono dstn panel */
-+ if (pFP->fpControl & FP_MONO)
-+ dstnfbsize = pFP->x;
-+ else
-+ dstnfbsize = pFP->x * 3;
-+ dstnfbsize = (((dstnfbsize + 127) >> 7) * pFP->y) << 3;
-+
-+ /* make it suitable for register bits definition */
-+ dstnstart = (sizeused + 127) >> 7;
-+ dstnend = (sizeused + dstnfbsize + 15) >> 4;
-+ REG32(DSTN_FB_CONTROL, (dstnstart | ((dstnend - 1) << 16)));
-+ }
-+ return;
-+}
-+
-+/* Set up graphics controller (GC1 or GC2) timing registers and PLLx
-+ *
-+ * gc: GC1 or GC2
-+ * x : horizontal viewport size
-+ * y : vertical viewport size
-+ * refresh : refresh rate (mainly VESA-supported mode)
-+ *
-+ */
-+void setupgc(int gc, int x, int y, int bpp, int refresh, void *pMQMMIO)
-+{
-+ PDISPLAY_TIMING pDT;
-+ unsigned long gccontrol;
-+
-+ /* Locate GC timing parameters first */
-+ pDT = getgcparam(x, y, refresh);
-+
-+ /* error checking for pDT here */
-+
-+ gccontrol = getbppbits(bpp) |
-+ FDx_1 | (1L << 24) |
-+ IM_ENABLE;
-+
-+ if (gc == IS_GC1)
-+ {
-+ /* Set up GC window as display */
-+ REG32(HW1_CONTROL, ((x - 1) << 16) | (1 << 28));
-+ REG32(VW1_CONTROL, ((y - 1) << 16));
-+
-+ REG32(HD1_CONTROL, pDT->hd);
-+ REG32(VD1_CONTROL, pDT->vd);
-+ REG32(HS1_CONTROL, pDT->hs);
-+ REG32(VS1_CONTROL, pDT->vs);
-+ REG32(VS1_CONTROL, pDT->vs);
-+ REG32(GC1_CRT_CONTROL, pDT->crtc);
-+
-+ /* Program PLL2 for GC1 */
-+ REG32(PLL2_CONTROL, pDT->pll);
-+
-+ /* GC1 control register */
-+ gccontrol |= GxRCLK_PLL2;
-+ REG32(GC1_CONTROL, gccontrol);
-+ }
-+ else
-+ if (gc == IS_GC2)
-+ {
-+ /* Set up GC window as display */
-+ REG32(HW2_CONTROL, ((x - 1) << 16));
-+ REG32(VW2_CONTROL, ((y - 1) << 16));
-+
-+ REG32(HD2_CONTROL, pDT->hd);
-+ REG32(VD2_CONTROL, pDT->vd);
-+ REG32(HS2_CONTROL, pDT->hs);
-+ REG32(VS2_CONTROL, pDT->vs);
-+ REG32(VS2_CONTROL, pDT->vs);
-+ REG32(GC1_CRT_CONTROL, pDT->crtc);
-+
-+ /* Program PLL3 for GC2 */
-+ REG32(PLL3_CONTROL, pDT->pll);
-+
-+ /* GC2 control register */
-+ gccontrol |= GxRCLK_PLL3;
-+ REG32(GC2_CONTROL, gccontrol);
-+ }
-+ return;
-+}
-+
-+/* Set up graphics controller (GC1 or GC2) memory configuration (stride and
-+ * starting address etc.)
-+ *
-+ * pDC : pointer to active DIPSLAY_CONFIG structure
-+ * startaddr : starting address - 0 if starting from very beginning
-+ *
-+ * - use GC1 for Simultaneous mode (1 GC)
-+ * - use GC1 for CRT and GC2 for LCD at QView mode
-+ *
-+ */
-+void setupgcmem(PDISPLAY_CONFIG pDC, unsigned long startaddr, void *pMQMMIO)
-+{
-+ unsigned long stride=0, start1=0, start2=0;
-+
-+ if (pDC->flag & LARGE_DESKTOP)
-+ {
-+ /* 4 possible layouts */
-+ switch (pDC->flag & LCDCRT_POS_MASK)
-+ {
-+ case HORI_CRT_LCD:
-+ stride = (pDC->x / 2) * pDC->bpp / 8;
-+ start1 = startaddr;
-+ start2 = startaddr + stride;
-+ break;
-+
-+ case HORI_LCD_CRT:
-+ stride = (pDC->x / 2) * pDC->bpp / 8;
-+ start1 = startaddr + stride;
-+ start2 = startaddr;
-+ break;
-+
-+ case VERT_CRT_LCD:
-+ stride = pDC->x * pDC->bpp / 8;
-+ start1 = startaddr;
-+ start2 = startaddr + stride * pDC->y / 2;
-+ break;
-+
-+ case VERT_LCD_CRT:
-+ stride = pDC->x * pDC->bpp / 8;
-+ start1 = startaddr + stride * pDC->y / 2;
-+ start2 = startaddr;
-+ break;
-+ }
-+
-+ /* Program to the chip */
-+ REG32(IW1_STRIDE, stride);
-+ REG32(IW2_STRIDE, stride);
-+
-+ REG32(IW1_START_ADDR, start1);
-+ REG32(IW2_START_ADDR, start2);
-+ }
-+ else
-+ {
-+ /* QView Same Image and Simultaneous LCD and/or CRT
-+ *
-+ * - set up 2 GCs in any cases ...
-+ * - 2 addidtional registers write vs. code size
-+ *
-+ */
-+
-+ /* Calculate stride */
-+ stride = pDC->x * pDC->bpp / 8;
-+
-+ REG32(IW1_STRIDE, stride);
-+ REG32(IW2_STRIDE, stride);
-+
-+ REG32(IW1_START_ADDR, startaddr);
-+ REG32(IW2_START_ADDR, startaddr);
-+ }
-+ return;
-+}
-+
-+/* Program palette entry
-+ *
-+ */
-+void setpal(int index, unsigned long color, void *pMQMMIO)
-+{
-+ /*PDEBUG("mq200fb: setpal. %d %d\n", index, color);*/
-+
-+ REG32_PAL(index, color);
-+}
-+
-+/* Vertical blank time is in progress ..
-+ *
-+ */
-+void invblank(void *pMQMMIO)
-+{
-+ unsigned long *intstat = (unsigned long *)(pMQMMIO+INT_STATUS_REG);
-+
-+ /* Make sure int occurs first */
-+ while ( !(*intstat & ST_GC1_VDE_F) );
-+
-+ /* Reset GC1 VDE F status bit - write 1 to clear the status */
-+ REG32(INT_STATUS_REG,ST_GC1_VDE_F);
-+
-+ /* Wait for next VDE falling edge for DAC access */
-+ while ( !(*intstat & ST_GC1_VDE_F) );
-+
-+ /* Here MQ200 should be in V blank period ... */
-+ return;
-+}
-+
-+/* Retrive graphics controller parameters from supported table
-+ *
-+ */
-+PDISPLAY_TIMING getgcparam(int x, int y, int refresh)
-+{
-+ int i;
-+
-+ for (i=0; i < MAX_MQMODE; i++)
-+ {
-+ if ( TimingParam[i].x == x
-+ && TimingParam[i].y == y
-+ && TimingParam[i].refresh == refresh )
-+ return ( (PDISPLAY_TIMING)&TimingParam[i] );
-+ }
-+ return (NULL); /* not existed */
-+}
-+
-+/* Return color depth setting for GC
-+ *
-+ */
-+unsigned long getbppbits(int bpp)
-+{
-+ unsigned long bppbits = 0;
-+
-+ switch(bpp)
-+ {
-+ case 8UL: bppbits = GC_8BPP; break;
-+ case 16UL: bppbits = GC_16BPP_BP; break;
-+ case 24UL: bppbits = GC_24BPP_BP; break;
-+ case 32UL: bppbits = GC_32BPP_ARGB_BP; break;
-+ case 4UL: bppbits = GC_4BPP; break;
-+ case 2UL: bppbits = GC_2BPP; break;
-+ case 1UL: bppbits = GC_1BPP; break;
-+ }
-+ return (bppbits);
-+}
-+
-+/* Turn on/off LCD or CRT driven by either GC1 or GC2
-+ *
-+ */
-+void onoffdisplay(int display_flag, void *pMQMMIO)
-+{
-+ unsigned long fpcontrol, gccontrol, crtcontrol;
-+
-+ switch (display_flag)
-+ {
-+ case ENABLE_LCD_GC1:
-+ /* Obtain current setting */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ gccontrol = READ32(GC1_CONTROL);
-+
-+ /* Turn on GC1 first if remain disabled */
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC1_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Flat panel controlled by GC1 */
-+ REG32(FP_CONTROL, fpcontrol | FPI_BY_GC1);
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+ mq200_backlight(pMQMMIO, 1);
-+#endif
-+
-+ break;
-+
-+ case ENABLE_LCD_GC2:
-+ /* Obtain current setting */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ gccontrol = READ32(GC2_CONTROL);
-+
-+ /* Turn on GC1 first if remain disabled */
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC2_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Flat panel controlled by GC1 */
-+ REG32(FP_CONTROL, fpcontrol | FPI_BY_GC2);
-+ break;
-+
-+ case DISABLE_LCD_GC1:
-+ /* Disable flat panel first */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ REG32(FP_CONTROL, fpcontrol);
-+
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & (~CRT_BY_GCxMASK);
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+ mq200_backlight(pMQMMIO, 0);
-+#endif
-+
-+ /* Disable GC1 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC1))
-+ {
-+ gccontrol = READ32(GC1_CONTROL);
-+ REG32(GC1_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case DISABLE_LCD_GC2:
-+ /* Disable flat panel first */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ REG32(FP_CONTROL, fpcontrol);
-+
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & (~CRT_BY_GCxMASK);
-+
-+ /* Disable GC2 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC2))
-+ {
-+ gccontrol = READ32(GC2_CONTROL);
-+ REG32(GC2_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case ENABLE_CRT_GC1:
-+ /* Enable GC1 if not yet enabled */
-+ gccontrol = READ32(GC1_CONTROL);
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC1_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Enable CRT by GC1 */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol | CRT_BY_GC1);
-+ break;
-+
-+ case ENABLE_CRT_GC2:
-+ /* Enable GC2 if not yet enabled */
-+ gccontrol = READ32(GC2_CONTROL);
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC2_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Enable CRT by GC2 */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol | CRT_BY_GC2);
-+ break;
-+
-+ case DISABLE_CRT_GC1:
-+ /* Disable CRT first */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol);
-+
-+ fpcontrol = READ32(FP_CONTROL) & (~FPI_BY_GCxMASK);
-+
-+ /* Disable GC1 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC1))
-+ {
-+ gccontrol = READ32(GC1_CONTROL);
-+ REG32(GC1_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case DISABLE_CRT_GC2:
-+ /* Disable CRT first */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol);
-+
-+ fpcontrol = READ32(FP_CONTROL) & (~FPI_BY_GCxMASK);
-+
-+ /* Disable GC2 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC2))
-+ {
-+ gccontrol = READ32(GC2_CONTROL);
-+ REG32(GC2_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+ }
-+ return;
-+}
-+
-+/* Setup hardware cursor data area start address in the frame buffer
-+ *
-+ */
-+void setup_cursor(void *pMQMMIO)
-+{
-+ REG32(HW_CURSOR1_FGCLR, CURSOR_FGCLR);
-+ REG32(HW_CURSOR2_FGCLR, CURSOR_FGCLR);
-+ REG32(HW_CURSOR1_BGCLR, CURSOR_BGCLR);
-+ REG32(HW_CURSOR2_BGCLR, CURSOR_BGCLR);
-+ REG32(HW_CURSOR1_ADDR, 0x000007ff);
-+ REG32(HW_CURSOR2_ADDR, 0x000007ff);
-+}
-+
-+/* Move cursor position and adjust hot spot offset
-+ *
-+ */
-+void move_cursor(unsigned long pos, unsigned long addr, void *pMQMMIO)
-+{
-+ REG32(HW_CURSOR1_POS, pos);
-+ REG32(HW_CURSOR2_POS, pos);
-+}
-+
-+/* Enable hardware cursor
-+ *
-+ */
-+void enable_cursor(void *pMQMMIO)
-+{
-+ u32 temp;
-+
-+ temp = READ32(GC1_CONTROL) | HC_ENABLE;
-+ REG32(GC1_CONTROL, temp);
-+ if (mqflag & USE_2GCs)
-+ {
-+ temp = READ32(GC2_CONTROL) | HC_ENABLE;
-+ REG32(GC2_CONTROL, temp);
-+ }
-+}
-+
-+/* Disable hardware cursor
-+ *
-+ */
-+void disable_cursor(void *pMQMMIO)
-+{
-+ u32 temp;
-+
-+ temp = READ32(GC1_CONTROL) & HC_DISABLE;
-+ REG32(GC1_CONTROL, temp);
-+ if (mqflag & USE_2GCs)
-+ {
-+ temp = READ32(GC2_CONTROL) & HC_DISABLE;
-+ REG32(GC2_CONTROL, temp);
-+ }
-+}
-+/* The above is copied from mq2hw.c for initialization of MQ200 */
-+
-+void turnoffMQ200(void * pMQMMIO)
-+{
-+ volatile u32 temp;
-+
-+ temp = READ32(FP_CONTROL);
-+ temp &=0xfffffffc;
-+ REG32(FP_CONTROL, temp);
-+ udelay(5000);
-+ temp =READ32(FP_CONTROL) & 0x3;
-+ if(temp != 0)
-+ PDEBUG("FP_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("FP_CONTROL is cleared properly");
-+
-+ temp = READ32(FP_PIN_CONTROL);
-+ temp |= 0x1;
-+ REG32(FP_PIN_CONTROL, temp);
-+ udelay(5000);
-+
-+ temp = READ32(GC1_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC1_CONTROL, temp);
-+ udelay(5000);
-+ temp = READ32(GC1_CONTROL) & 0x1;
-+ if(temp != 0)
-+ PDEBUG("GC1_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("GC1_CONTROL is cleared properly");
-+
-+ temp = READ32(GC1_CRT_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC1_CRT_CONTROL, temp);
-+ udelay(5000);
-+
-+ temp = READ32(GC2_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC2_CONTROL, temp);
-+ udelay(5000);
-+ temp = READ32(GC2_CONTROL) & 0x1;
-+ if(temp != 0)
-+ PDEBUG("GC2_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("GC2_CONTROL is cleared properly");
-+
-+ return;
-+}
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Power management hook. Note that we won't be called from IRQ context,
-+ * unlike the blank functions above, so we may sleep.
-+ */
-+static int
-+mq200fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) pm_dev->data;
-+ void * pMQMMIO = (void *) p->mqMmioAddrVirt;
-+
-+ if (req == PM_SUSPEND){
-+
-+ onoffdisplay(DISABLE_LCD_GC1, pMQMMIO);
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D3);
-+ MQ_DELAY(30);
-+ }
-+ if( req == PM_RESUME){
-+ setmqmode(&dc, pMQMMIO);
-+ onoffdisplay(ENABLE_LCD_GC1, pMQMMIO);
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D0);
-+ MQ_DELAY(30);
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+
-+static void mq200_backlight(void *pMQMMIO, int flag)
-+{
-+
-+#ifdef CONFIG_SA1100_GDS2200
-+ unsigned long gpiocontrol, data;
-+ int i;
-+
-+ gpiocontrol = READ32(FP_GPIO_CONTROL) & 0x3f;
-+ data = (flag ? GPIO2_OUT_HIGH : 0);
-+ for(i = 0 ; i < 128 ; i++) {
-+ REG32(FP_GPIO_CONTROL, gpiocontrol | data);
-+ MQ_DELAY(1);
-+ REG32(FP_GPIO_CONTROL, gpiocontrol | GPIO1_OUT_HIGH | data);
-+ MQ_DELAY(1);
-+ REG32(FP_GPIO_CONTROL, gpiocontrol);
-+ MQ_DELAY(1);
-+ }
-+
-+#endif /* CONFIG_SA1100_GDS2200 */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+ if(flag)
-+ set_cs3_bit(DISPLAY_ON);
-+ else
-+ clear_cs3_bit(DISPLAY_ON);
-+
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+}
-+#endif /* CONFIG_SA1100_GDS2200 || CONFIG_SA1100_SIMPAD */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+static void writeBrightness(void *pMQMMIO, int brightness)
-+{
-+ unsigned long dutyCycle, pwmcontrol;
-+ int MAX_BRIGHT_REG = 0x000000fc; /* int 254 */
-+
-+ if(brightness > MAX_BRIGHT_REG)
-+ return;
-+ else
-+ {
-+ /*
-+ *Determine dutyCycle.
-+ *Note: the lower the value, the brighter the display!
-+ */
-+
-+ dutyCycle = MAX_BRIGHT_REG - brightness;
-+
-+ /*
-+ *Configure PWM0 (source clock = oscillator clock, pwm always enabled,
-+ *zero, clock pre-divider = 4) pwm frequency = 12.0kHz
-+ */
-+ pwmcontrol = READ32(PWM_CONTROL);
-+ REG32(PWM_CONTROL, 0x00000044 | (pwmcontrol & 0xffffff00));
-+
-+
-+ /* Write to pwm duty cycle register. */
-+
-+ REG32(PWM_CONTROL, ((dutyCycle << 8) & 0x0000ff00) |
-+ (pwmcontrol & 0xffff00ff));
-+ }
-+}
-+
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+static int proc_read_reg(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ char outputbuf[15];
-+ int count;
-+ int i;
-+ mq200_reg_entry_t* current_reg=NULL;
-+ if (*ppos>0) /* Assume reading completed in previous read*/
-+ return 0;
-+ for (i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ if (mq200_regs[i].low_ino==i_ino) {
-+ current_reg = &mq200_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ count = sprintf(outputbuf, "0x%08X\n",
-+ *((volatile *) mq200_p2v(current_reg->phyaddr)));
-+ *ppos+=count;
-+ if (count>nbytes) /* Assume output can be read at one time */
-+ return -EINVAL;
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+ return count;
-+}
-+
-+static ssize_t proc_write_reg(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ mq200_reg_entry_t* current_reg=NULL;
-+ int i;
-+ unsigned long newRegValue;
-+ char *endp;
-+
-+ for (i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ if (mq200_regs[i].low_ino==i_ino) {
-+ current_reg = &mq200_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ *((volatile *) mq200_p2v(current_reg->phyaddr))=newRegValue;
-+ return (count+endp-buffer);
-+}
-+
---- linux-2.4.25/include/asm-arm/arch-sa1100/simpad.h~2.4.25-vrs2-pxa1-jpm1.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-sa1100/simpad.h 2004-05-02 22:45:42.000000000 +0200
-@@ -28,6 +28,7 @@
- #define GPIO_UART3_DCD GPIO_GPIO18
- #define GPIO_UART3_DSR GPIO_GPIO17
-
-+#define GPIO_POWER_BUTTON GPIO_GPIO0
- #define GPIO_UCB1300_IRQ GPIO_GPIO (22) /* UCB GPIO and touchscreen */
-
- #define IRQ_UART1_CTS IRQ_GPIO15
-@@ -37,7 +38,12 @@
- #define IRQ_UART3_DCD GPIO_GPIO18
- #define IRQ_UART3_DSR GPIO_GPIO17
-
--#define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
-+#define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
-+#define IRQ_GPIO_POWER_BUTTON IRQ_GPIO0
-+
-+/*--- SmartCard ---*/
-+#define GPIO_SMART_CARD GPIO_GPIO10
-+#define IRQ_GPIO_SMART_CARD IRQ_GPIO10
-
- /*--- PCMCIA ---*/
- #define GPIO_CF_CD GPIO_GPIO24
-@@ -65,7 +71,7 @@
- #define LED2_ON 0x1000
- #define IRDA_MODE 0x2000 // Fast/Slow IrDA mode
- #define ENABLE_5V 0x4000 // Enable 5V circuit
--#define RESET_SIMCARD 0x8000
-+#define nRESET_SIMCARD 0x8000
-
- #define RS232_ENABLE 0x0440
- #define PCMCIAMASK 0x402f
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-sa1100/simpad_pm.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,236 @@
-+/*
-+* Abstraction interface for microcontroller connection to rest of system
-+*
-+* Copyright 2003 Peter Pregler
-+* Copyright 2000,1 Compaq Computer Corporation.
-+*
-+* Use consistent with the GNU GPL is permitted,
-+* provided that this copyright notice is
-+* preserved in its entirety in all copies and derived works.
-+*
-+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-+* FITNESS FOR ANY PARTICULAR PURPOSE.
-+*
-+* Author: Peter Pregler (based on work for ipaq by Andrew Christian)
-+*
-+*/
-+
-+#ifndef __SIMPAD_HAL_H
-+#define __SIMPAD_HAL_H
-+
-+extern int simpad_apm_get_power_status(unsigned char *ac_line_status, unsigned char *battery_status,
-+ unsigned char *battery_flag, unsigned char *battery_percentage,
-+ unsigned short *battery_life);
-+
-+
-+struct simpad_battery {
-+ unsigned char ac_status; /* line connected yes/no */
-+ unsigned char status; /* battery loading yes/no */
-+ unsigned char percentage; /* percentage loaded */
-+ unsigned short life; /* life till empty */
-+};
-+
-+extern int simpad_get_battery(struct simpad_battery *bstat);
-+
-+/* These should match the apm_bios.h definitions */
-+#define SIMPAD_AC_STATUS_AC_OFFLINE 0x00
-+#define SIMPAD_AC_STATUS_AC_ONLINE 0x01
-+#define SIMPAD_AC_STATUS_AC_BACKUP 0x02 /* What does this mean? */
-+#define SIMPAD_AC_STATUS_AC_UNKNOWN 0xff
-+
-+/* These bitfields are rarely "or'd" together */
-+#define SIMPAD_BATT_STATUS_HIGH 0x01
-+#define SIMPAD_BATT_STATUS_LOW 0x02
-+#define SIMPAD_BATT_STATUS_CRITICAL 0x04
-+#define SIMPAD_BATT_STATUS_CHARGING 0x08
-+#define SIMPAD_BATT_STATUS_CHARGE_MAIN 0x10
-+#define SIMPAD_BATT_STATUS_DEAD 0x20 /* Battery will not charge */
-+#define SIMPAD_BATT_NOT_INSTALLED 0x20 /* For expansion pack batteries */
-+#define SIMPAD_BATT_STATUS_FULL 0x40 /* Battery fully charged (and connected to AC) */
-+#define SIMPAD_BATT_STATUS_NOBATT 0x80
-+#define SIMPAD_BATT_STATUS_UNKNOWN 0xff
-+
-+#if FIXME
-+#include <linux/simpad_ts.h>
-+
-+enum simpad_asset_type {
-+ ASSET_TCHAR = 0,
-+ ASSET_SHORT,
-+ ASSET_LONG
-+};
-+
-+#define TTYPE(_type) (((unsigned int)_type) << 8)
-+#define TCHAR(_len) (TTYPE(ASSET_TCHAR) | (_len))
-+#define TSHORT TTYPE(ASSET_SHORT)
-+#define TLONG TTYPE(ASSET_LONG)
-+#define ASSET(_type,_num) ((((unsigned int)_type)<<16) | (_num))
-+
-+#define ASSET_HM_VERSION ASSET( TCHAR(10), 0 ) /* 1.1, 1.2 */
-+#define ASSET_SERIAL_NUMBER ASSET( TCHAR(40), 1 ) /* Unique iPAQ serial number */
-+#define ASSET_MODULE_ID ASSET( TCHAR(20), 2 ) /* E.g., "iPAQ 3700" */
-+#define ASSET_PRODUCT_REVISION ASSET( TCHAR(10), 3 ) /* 1.0, 2.0 */
-+#define ASSET_PRODUCT_ID ASSET( TSHORT, 4 ) /* 2 = Palm-sized computer */
-+#define ASSET_FRAME_RATE ASSET( TSHORT, 5 )
-+#define ASSET_PAGE_MODE ASSET( TSHORT, 6 ) /* 0 = Flash memory */
-+#define ASSET_COUNTRY_ID ASSET( TSHORT, 7 ) /* 0 = USA */
-+#define ASSET_IS_COLOR_DISPLAY ASSET( TSHORT, 8 ) /* Boolean, 1 = yes */
-+#define ASSET_ROM_SIZE ASSET( TSHORT, 9 ) /* 16, 32 */
-+#define ASSET_RAM_SIZE ASSET( TSHORT, 10 ) /* 32768 */
-+#define ASSET_HORIZONTAL_PIXELS ASSET( TSHORT, 11 ) /* 240 */
-+#define ASSET_VERTICAL_PIXELS ASSET( TSHORT, 12 ) /* 320 */
-+
-+#define ASSET_TYPE(_asset) (((_asset)&0xff000000)>>24)
-+#define ASSET_TCHAR_LEN(_asset) (((_asset)&0x00ff0000)>>16)
-+#define ASSET_NUMBER(_asset) ((_asset)&0x0000ffff)
-+
-+#define MAX_TCHAR_LEN 40
-+
-+struct simpad_asset {
-+ unsigned int type;
-+ union {
-+ unsigned char tchar[ MAX_TCHAR_LEN ];
-+ unsigned short vshort;
-+ unsigned long vlong;
-+ } a;
-+};
-+
-+/********************************************************************
-+ * Interface to the hardware-type specific functions
-+ *
-+ * get_version Read the version number of the microcontroller on the option pack SPI bus
-+ * spi_read Reads from the serial EEPROM memory on the option pack SPI bus
-+ * spi_write Write to the serial EEPROM memory on the option pack SPI bus
-+ * get_option_detect Returns whether or not an option pack is present
-+ *
-+ * get_thermal_sensor Return measured temperature of the unit, in units of 0.125 deg C
-+ * set_notify_led Turns on, off, or blinks the Green LED
-+ * read_light_sensor Returns the value of the front light sensor
-+ * get_battery Returns the current voltage and charging state of all batteries
-+ * audio_clock Sets the audio CODEC to run at a particular rate
-+ * audio_power Turns on/off audio CODEC (internally calls audio_clock)
-+ * audio_mute Mutes the audio CODEC
-+ * asset_read Extracts PocketPC-style asset information from persistent memory
-+ * backlight_control Adjusts the backlight level (only on/off for 3100)
-+ *
-+ *
-+ * iPAQ 3100 only
-+ * ==============
-+ * codec_control Reset/mute/control level of 3100 audio codec
-+ * contrast_control Adjusts the contrast level (only for 3100)
-+ *
-+ * iPAQ 3600, 3700 only
-+ * ====================
-+ * eeprom_read Reads from the asset information on the eeprom of a 3600 (deprecated)
-+ * eeprom_write Writes to the asset information on the eeprom (deprecated)
-+ *
-+ * The interfaces to the EEPROM functions are maintained only because the simpad_ts driver has
-+ * a deprecated ioctl call for them. They are used internally by the "asset_read" function.
-+ *
-+ * iPAQ 3800, 3900 only
-+ * ====================
-+ * set_ebat Tells enhanced PCMCIA sleeves that this iPAQ can handle
-+ * a wider voltage range (applies to 3800, 3900)
-+ *
-+ *********************************************************************/
-+
-+struct simpad_hal_ops {
-+ /* Functions provided by the underlying hardware */
-+ int (*get_version)( struct simpad_ts_version * );
-+ int (*eeprom_read)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*eeprom_write)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*get_thermal_sensor)( unsigned short * );
-+ int (*set_notify_led)( unsigned char mode, unsigned char duration,
-+ unsigned char ontime, unsigned char offtime );
-+ int (*read_light_sensor)( unsigned char *result );
-+ int (*get_battery)( struct simpad_battery * );
-+ int (*spi_read)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*spi_write)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*codec_control)( unsigned char, unsigned char );
-+ int (*get_option_detect)( int *result );
-+ int (*audio_clock)( long samplerate );
-+ int (*audio_power)( long samplerate );
-+ int (*audio_mute)( int mute );
-+ int (*asset_read)( struct simpad_asset *asset );
-+ int (*set_ebat)( void );
-+
-+ /* Functions indirectly provided by the underlying hardware */
-+ int (*backlight_control)( enum flite_pwr power, unsigned char level );
-+ int (*contrast_control)( unsigned char level );
-+
-+ /* for module use counting */
-+ struct module *owner;
-+};
-+
-+/* Used by the device-specific hardware module to register itself */
-+extern int simpad_hal_register_interface( struct simpad_hal_ops *ops );
-+extern void simpad_hal_unregister_interface( struct simpad_hal_ops *ops );
-+
-+/*
-+ * Calls into HAL from the device-specific hardware module
-+ * These run at interrupt time
-+ */
-+extern void simpad_hal_keypress( unsigned char key );
-+extern void simpad_hal_touchpanel( unsigned short x, unsigned short y, int down );
-+extern void simpad_hal_option_detect( int present );
-+
-+/* Callbacks registered by device drivers */
-+struct simpad_driver_ops {
-+ void (*keypress)( unsigned char key );
-+ void (*touchpanel)( unsigned short x, unsigned short y, int down );
-+ void (*option_detect)( int present );
-+};
-+
-+extern int simpad_hal_register_driver( struct simpad_driver_ops * );
-+extern void simpad_hal_unregister_driver( struct simpad_driver_ops * );
-+
-+
-+/* Calls into HAL from device drivers and other kernel modules */
-+extern void simpad_get_flite( struct simpad_ts_backlight *bl );
-+extern void simpad_get_contrast( unsigned char *contrast );
-+extern int simpad_set_flite( enum flite_pwr pwr, unsigned char brightness );
-+extern int simpad_set_contrast( unsigned char contrast );
-+extern int simpad_toggle_frontlight( void );
-+
-+extern int simpad_apm_get_power_status(unsigned char *ac_line_status, unsigned char *battery_status,
-+ unsigned char *battery_flag, unsigned char *battery_percentage,
-+ unsigned short *battery_life);
-+
-+extern struct simpad_hal_ops *simpad_hal_ops;
-+
-+/* Do not use this macro in driver files - instead, use the inline functions defined below */
-+#define CALL_HAL( f, args... ) \
-+ { int __result = -EIO; \
-+ if ( simpad_hal_ops && simpad_hal_ops->f ) { \
-+ __MOD_INC_USE_COUNT(simpad_hal_ops->owner); \
-+ __result = simpad_hal_ops->f(args); \
-+ __MOD_DEC_USE_COUNT(simpad_hal_ops->owner); \
-+ } \
-+ return __result; }
-+
-+#define HFUNC static __inline__ int
-+
-+/* The eeprom_read/write address + len has a maximum value of 512. Both must be even numbers */
-+HFUNC simpad_eeprom_read( u16 addr, u8 *data, u16 len ) CALL_HAL(eeprom_read,addr,data,len)
-+HFUNC simpad_eeprom_write( u16 addr, u8 *data, u16 len) CALL_HAL(eeprom_write,addr,data,len)
-+HFUNC simpad_spi_read( u8 addr, u8 *data, u16 len) CALL_HAL(spi_read,addr,data,len)
-+HFUNC simpad_spi_write( u8 addr, u8 *data, u16 len) CALL_HAL(spi_write,addr,data,len)
-+HFUNC simpad_get_version( struct simpad_ts_version *v ) CALL_HAL(get_version,v)
-+HFUNC simpad_get_thermal_sensor( u16 *thermal ) CALL_HAL(get_thermal_sensor,thermal)
-+HFUNC simpad_set_led( u8 mode, u8 dur, u8 ont, u8 offt ) CALL_HAL(set_notify_led, mode, dur, ont, offt)
-+HFUNC simpad_get_light_sensor( u8 *result ) CALL_HAL(read_light_sensor,result)
-+HFUNC simpad_get_battery( struct simpad_battery *bat ) CALL_HAL(get_battery,bat)
-+HFUNC simpad_get_option_detect( int *result) CALL_HAL(get_option_detect,result)
-+HFUNC simpad_audio_clock( long samplerate ) CALL_HAL(audio_clock,samplerate)
-+HFUNC simpad_audio_power( long samplerate ) CALL_HAL(audio_power,samplerate)
-+HFUNC simpad_audio_mute( int mute ) CALL_HAL(audio_mute,mute)
-+HFUNC simpad_asset_read( struct simpad_asset *asset ) CALL_HAL(asset_read,asset)
-+HFUNC simpad_set_ebat( void ) CALL_HAL(set_ebat)
-+
-+/* Don't use these functions directly - rather, call {get,set}_{flite,contrast} */
-+ /* Functions indirectly provided by the underlying hardware */
-+HFUNC simpad_backlight_control( enum flite_pwr p, u8 v ) CALL_HAL(backlight_control,p,v)
-+HFUNC simpad_contrast_control( u8 level ) CALL_HAL(contrast_control,level)
-+
-+#endif
-+#endif
---- linux-2.4.25/include/linux/apm_bios.h~2.4.25-vrs2-pxa1-jpm1.patch 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.25/include/linux/apm_bios.h 2004-05-02 22:45:42.000000000 +0200
-@@ -216,4 +216,19 @@
- #define APM_IOC_STANDBY _IO('A', 1)
- #define APM_IOC_SUSPEND _IO('A', 2)
-
-+#define APM_AC_OFFLINE 0
-+#define APM_AC_ONLINE 1
-+#define APM_AC_BACKUP 2
-+#define APM_AC_UNKNOWN 0xFF
-+
-+#define APM_BATTERY_STATUS_HIGH 0
-+#define APM_BATTERY_STATUS_LOW 1
-+#define APM_BATTERY_STATUS_CRITICAL 2
-+#define APM_BATTERY_STATUS_CHARGING 3
-+#define APM_BATTERY_STATUS_UNKNOWN 0xFF
-+
-+#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
-+#define APM_BATTERY_LIFE_MINUTES 0x8000
-+#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
-+
- #endif /* LINUX_APM_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/switches.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,74 @@
-+/*
-+ * linux/include/linux/switches.h
-+ *
-+ * Copyright (C) 2000 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 23 October 2000 - created.
-+ */
-+
-+#if !defined(_LINUX_SWITCHES_H)
-+#define _LINUX_SWITCHES_H
-+
-+#define SWITCHES_MASK_SIZE (128)
-+
-+typedef unsigned long switches_bitfield;
-+
-+#define SWITCHES_BITS (sizeof(switches_bitfield) * 8)
-+#define SWITCHES_NUM_FIELDS (SWITCHES_MASK_SIZE / SWITCHES_BITS)
-+#define SWITCHES_FIELD_SELECT(i) ((i) / SWITCHES_BITS)
-+#define SWITCHES_FIELD_MASK(i) ((switches_bitfield)(1 << (i) % \
-+ SWITCHES_BITS))
-+
-+typedef struct switches_mask_t {
-+ unsigned int count;
-+ switches_bitfield events[SWITCHES_NUM_FIELDS];
-+ switches_bitfield states[SWITCHES_NUM_FIELDS];
-+} switches_mask_t;
-+
-+#define SWITCHES_ZERO(m) \
-+do { \
-+ unsigned int sz_i; \
-+ (m)->count = 0; \
-+ for(sz_i = 0; sz_i < SWITCHES_NUM_FIELDS; ++sz_i) \
-+ (m)->events[sz_i] = (m)->states[sz_i] = 0; \
-+} while (0)
-+
-+/* `s' is the state of the switch, either 0 or non-zero: */
-+#define SWITCHES_SET(m, i, s) \
-+do { \
-+ ((m)->events[SWITCHES_FIELD_SELECT((i))] |= \
-+ SWITCHES_FIELD_MASK((i))); \
-+ if(s) \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] |= \
-+ SWITCHES_FIELD_MASK((i))); \
-+ else \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ ++((m)->count); \
-+} while (0)
-+
-+/* Should only use to clear an event set by SWITCHES_SET(): */
-+#define SWITCHES_CLEAR(m, i) \
-+do { \
-+ ((m)->events[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ --((m)->count); \
-+}
-+
-+#define SWITCHES_COUNT(m) ((m)->count)
-+
-+/* Returns 0 or non-zero: */
-+#define SWITCHES_EVENT(m, i) \
-+((m)->events[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i)))
-+
-+/* Returns 0 or non-zero: */
-+#define SWITCHES_STATE(m, i) \
-+((m)->states[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i)))
-+
-+#endif /* !defined(_LINUX_SWITCHES_H) */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mq2ge.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,81 @@
-+#ifndef _VIDEO_MQ200_MQ2GE_H
-+#define _VIDEO_MQ200_MQ2GE_H
-+
-+
-+/* Misc. GE Function Macro */
-+#undef CHECK_SRCFIFO
-+#define RGB_RASTER_CHECK
-+#define INCLUDE_GENERIC_CODE
-+
-+#ifdef CHECK_SRCFIFO
-+#define geWAITSRCFIFO(cnt) geWaitSrcFIFO(cnt)
-+#define geWAITCMDFIFO(cnt) geWaitCmdFIFO(cnt)
-+#define geWAITNOTBUSY() geWaitNotBusy()
-+#else
-+#define geWAITSRCFIFO(cnt)
-+#define geWAITCMDFIFO(cnt)
-+#define geWAITNOTBUSY()
-+#endif
-+
-+/* Additional UGL Raster Ops */
-+#define UGL_RASTER_OP_NOP 0x00000000L
-+
-+#define UGL_RASTER_OP_BLACKNESS 0x00000001L
-+#define UGL_RASTER_OP_BSRC_BLACK 0x00000002L
-+#define UGL_RASTER_OP_BSRC_OCOPY 0x00000003L
-+#define UGL_RASTER_OP_BSRC_XCOPY 0x00000004L
-+
-+#define UGL_RASTER_OP_WHITENESS 0x00010001L
-+#define UGL_RASTER_OP_WSRC_COPY 0x00010002L
-+#define UGL_RASTER_OP_WSRC_WHITE 0x00010003L
-+#define UGL_RASTER_OP_WSRC_INVERT 0x00010004L
-+
-+#define UGL_RASTER_OP_SRC_COPY 0x00020001L
-+#define UGL_RASTER_OP_SRCDEST_AND 0x00020002L
-+#define UGL_RASTER_OP_SRCDEST_OR 0x00020003L
-+#define UGL_RASTER_OP_SRCDEST_XOR 0x00020004L
-+
-+#define UGL_RASTER_OP_DEST_COPY 0x00030001L
-+#define UGL_RASTER_OP_DESTSRC_AND 0x00030002L
-+#define UGL_RASTER_OP_DESTSRC_OR 0x00030003L
-+#define UGL_RASTER_OP_DESTSRC_XOR 0x00030004L
-+
-+/* MediaQ Raster Ops */
-+#define MQ200_SOURCE_ROP 0x01
-+#define MQ200_PATTERN_ROP 0x02
-+#define MQ200_GE_NOP 0x000000AAL
-+#define MQ200_GE_BLACKNESS 0x00000000L
-+#define MQ200_GE_WHITENESS 0x000000FFL
-+#define MQ200_GE_SRC_INVERT 0x00000033L
-+#define MQ200_GE_SRC_COPY 0x000000CCL
-+#define MQ200_GE_SRCDEST_XOR 0x00000066L
-+#define MQ200_GE_SRCDEST_AND 0x00000088L
-+#define MQ200_GE_SRCDEST_OR 0x000000EEL
-+#define MQ200_GE_PATTERN_INVERT 0x0000000FL
-+#define MQ200_GE_PATTERN_COPY 0x000000F0L
-+#define MQ200_GE_PATDEST_XOR 0x0000005AL
-+#define MQ200_GE_PATDEST_AND 0x000000A0L
-+#define MQ200_GE_PATDEST_OR 0x000000FAL
-+/* MediaQ Raster Ops mapping table */
-+#define UGL_NR_OPERAND 4
-+#define UGL_NR_OPERATION 5
-+
-+#define geREG_2( idx1, val1, idx2, val2 ) \
-+ geREG( idx2, val2 ); \
-+ geREG( idx1, val1 )
-+#define geREG_3( idx1, val1, idx2, val2, idx3, val3 ) \
-+ geREG_2( idx2, val2, idx3, val3 ); \
-+ geREG( idx1, val1 )
-+#define geREG_4( idx1, val1, idx2, val2, idx3, val3, idx4, val4 ) \
-+ geREG_3( idx2, val2, idx3, val3, idx4, val4 ); \
-+ geREG( idx1, val1 )
-+#define geREG_5( idx1, val1, idx2, val2, idx3, val3, idx4, val4, idx5, val5 ) \
-+ geREG_4( idx2, val2, idx3, val3, idx4, val4, idx5, val5 ); \
-+ geREG( idx1, val1 )
-+
-+/* Declare MQ200 GE Utility Functions */
-+void geWaitNotBusy(void);
-+void geWaitCmdFIFO(u32 cnt);
-+void geWaitSrcFIFO(u32 cnt);
-+
-+#endif /* _VIDEO_MQ200_MQ2GE_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mq2hw.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,879 @@
-+/***************************************************************************
-+ MQ200HW.H
-+
-+ MQ200 chip definition file
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQ2HW_H
-+#define _VIDEO_MQ200_MQ2HW_H
-+
-+#define MQ200_VENDOR_ID 0x4D51
-+#define MQ200_DEVICE_ID 0x0200
-+#define MQ200_ID 0x02004D51
-+#define PM_ID_CAP 0x06210001 /* Power management ID/capability */
-+
-+/* Revision ID */
-+#define MQ200_REV_0X 0x00
-+#define MQ200_REV_1A 0x01
-+#define MQ200_REV_1B1C 0x11
-+#define MQ200_REV_1D 0x10
-+
-+/* Some useful defines */
-+#ifndef ULONG
-+#define ULONG unsigned long
-+#endif
-+#ifndef USHORT
-+#define USHORT unsigned short
-+#endif
-+#ifndef BYTE
-+#define BYTE unsigned char
-+#endif
-+
-+/* To access MediaQ memory-mapped IO register (32bit in size) */
-+#define REG32(addr,val) (*(volatile ULONG *)((ULONG)pMQMMIO+addr)=(val))
-+#define READ32(addr) (*((volatile ULONG *)((ULONG)pMQMMIO+addr)))
-+#define geREG(addr,val) (*(volatile ULONG *)(mqMmioAddr+addr)=(val))
-+#define geREAD(addr) (*((volatile ULONG *)(mqMmioAddr+addr)))
-+#define gcREG(addr,val) geREG(addr,val)
-+#define gcREAD(addr) geREAD(addr)
-+#define cpuREG(addr,val) geREG(addr,val)
-+#define cpuREAD(addr) geREAD(addr)
-+#define pmuREG(addr,val) geREG(addr,val)
-+#define pmuREAD(addr) geREAD(addr)
-+#define pciREG(addr,val) geREG(addr,val)
-+#define pciREAD(addr) geREAD(addr)
-+
-+/* To access MediaQ DAC - index-based */
-+#define REG32_PAL(idx,val) (*(ULONG *)((ULONG)pMQMMIO+C1_BASE+idx*4)=(val))
-+#define READ32_PAL(idx) (*(ULONG *)((ULONG)pMQMMIO+C1_BASE+idx*4))
-+
-+/* MQ200 module offset */
-+#define PM_BASE (0) /* Power Management + Clk Gen */
-+#define CC_BASE (0x2000) /* CPU interface */
-+#define MM_BASE (0x4000) /* Memory Controller (m1/m2) */
-+#define VI_BASE (0x6000) /* Video-in controller */
-+#define IN_BASE (0x8000) /* Interrupt controller */
-+#define GC_BASE (0xA000) /* Graphics Controller 1/2 */
-+#define GE_BASE (0xC000) /* Graphics engine */
-+#define GE2_BASE (0xC200) /* Graphics engine (GE2) */
-+#define FP_BASE (0xE000) /* Flat panel interface */
-+#define C1_BASE (0x10000) /* Color palette 1 */
-+#define C2_BASE (0x12000) /* Color palette 2 */
-+#define DC_BASE (0x14000) /* Device Configuration Space */
-+#define PC_BASE (0x16000) /* PCI Configuration Header */
-+#define PSF_BASE (0x18000) /* Primary Source FIFO Space */
-+#define SSF_BASE (0x1A000) /* Secondary Source FIFO Space */
-+
-+#define MQ200_MMIO_SIZE (0x1C0000L)
-+#define MQ200_FB_SIZE (0x200000L) /* 2MB memory */
-+#define GC_OFFSET (0x80)
-+
-+/* Interrupt Controller */
-+#define INT_CONTROL_REG (IN_BASE + 0x00) /* Global interrupt ctrl reg */
-+#define INT_MASK_REG (IN_BASE + 0x04) /* Interrupt mask reg */
-+#define INT_STATUS_REG (IN_BASE + 0x08) /* Interrupt status reg */
-+#define INT_RAW_STATUS_REG (IN_BASE + 0x0C) /* Interrupt pin raw */
-+ /* status reg*/
-+
-+/* INT_CONTROL_REG - Global Interrupt Control Register */
-+#define INT_ENABLE 0x00000001 /* Interrupt to CPU enabled */
-+#define INT_PORLARITY_HIGH 0x00000002 /* Interrupt is active high */
-+#define INT_GPIO1_0To1 0x00000004 /* Interrupt as xition 0 to 1 */
-+#define INT_GPIO2_0To1 0x00000008 /* Interrupt as xition 0 to 1 */
-+#define INT_GPIO3_0To1 0x00000010 /* Interrupt as xtion 0 to 1 */
-+
-+/* INT_MASK_REG -- Interrupt Mask Register */
-+#define UM_GC1_VSE_R 0x00000001 /* GC1 VSE - Rising edge */
-+#define UM_GC1_VSE_F 0x00000002 /* GC1 VSE - Falling edge */
-+#define UM_GC1_VDE_R 0x00000004 /* GC1 VDE - Rising edge */
-+#define UM_GC1_VDE_F 0x00000008 /* GC1 VDE - Falling edge */
-+#define UM_GC2_VSE_R 0x00000010 /* GC2 VSE - Rising edge */
-+#define UM_GC2_VSE_F 0x00000020 /* GC2 VSE - Falling edge */
-+#define UM_GC2_VDE_R 0x00000040 /* GC2 VDE - Rising edge */
-+#define UM_GC2_VDE_F 0x00000080 /* GC2 VDE - Falling edge */
-+#define UM_CFIFO_HALF_EMPTY 0x00000100 /* Command fifo half empty */
-+#define UM_CFIFO_EMPTY 0x00000200 /* Command fifo empty */
-+#define UM_SFIFO_HALF_EMPTY 0x00000400 /* Source fifo half empty */
-+#define UM_SFIFO_EMPTY 0x00000800 /* Source fifo empty */
-+#define UM_GE_IDLE 0x00001000 /* GE is idle */
-+#define UM_GPIO_1 0x00002000 /* GPIO pin 1 */
-+#define UM_GPIO_2 0x00004000 /* GPIO pin 2 */
-+#define UM_GPIO_3 0x00008000 /* GPIO pin 3 */
-+
-+/* INT_STATUS_REG -- Interrupt Status Register */
-+#define ST_GC1_VSE_R 0x00000001 /* GC1 VSE - Rising edge */
-+#define ST_GC1_VSE_F 0x00000002 /* GC1 VSE - Falling edge */
-+#define ST_GC1_VDE_R 0x00000004 /* GC1 VDE - Rising edge */
-+#define ST_GC1_VDE_F 0x00000008 /* GC1 VDE - Falling edge */
-+#define ST_GC2_VSE_R 0x00000010 /* GC2 VSE - Rising edge */
-+#define ST_GC2_VSE_F 0x00000020 /* GC2 VSE - Falling edge */
-+#define ST_GC2_VDE_R 0x00000040 /* GC2 VDE - Rising edge */
-+#define ST_GC2_VDE_F 0x00000080 /* GC2 VDE - Falling edge */
-+#define ST_CFIFO_HALF_EMPTY 0x00000100 /* Command fifo half empty */
-+#define ST_CFIFO_EMPTY 0x00000200 /* Command fifo empty */
-+#define ST_SFIFO_HALF_EMPTY 0x00000400 /* Source fifo half empty */
-+#define ST_SFIFO_EMPTY 0x00000800 /* Source fifo empty */
-+#define ST_GE_IDLE 0x00001000 /* GE is idle */
-+#define ST_GPIO_1 0x00002000 /* GPIO pin 1 */
-+#define ST_GPIO_2 0x00004000 /* GPIO pin 2 */
-+#define ST_GPIO_3 0x00008000 /* GPIO pin 3 */
-+
-+/* INT_RAW_STATUA_REG -- Interrupt Pin Raw Status Register */
-+#define GC1_VSE 0x00000001 /* GC1 - VSE */
-+#define GC1_VDE 0x00000004 /* GC1 - VDE */
-+#define GC2_VSE 0x00000010 /* GC2 - VSE */
-+#define GC2_VDE 0x00000040 /* GC2 - VDE */
-+#define INT_GE_BUSY 0x00000100 /* GE busy */
-+#define SFIFO_EMPTY 0x00000200 /* Source fifo empty */
-+#define SFIFO_HEMPTY 0x00000400 /* Source fifo half empty */
-+#define CFIFO_EMPTY 0x00000800 /* Command fifo empty */
-+#define CFIFO_HEMPTY 0x00001000 /* Command fifo half empty */
-+#define GPIO_PIN_1 0x00002000 /* GPIO pin 1 */
-+#define GPIO_PIN_2 0x00004000 /* GPIO pin 2 */
-+#define GPIO_PIN_3 0x00008000 /* GPIO pin 3 */
-+
-+/* 2D Engine registers - GE1 (0x00 - 0x7F) */
-+#define DRAW_CMD (GE_BASE + 0x00) /* Drawing command register */
-+#define WIDTH_HEIGHT (GE_BASE + 0x04) /* Width/height register */
-+#define LINE_DRAW WIDTH_HEIGHT /* Bresenham Line Draw reg */
-+#define DEST_XY (GE_BASE + 0x08) /* Destination X/Y register */
-+#define LINE_MAJOR_X DEST_XY /* Bresenham Line Start X/Y reg */
-+#define PAT_OFFSET DEST_XY /* Pattern Offset register */
-+#define SRC_XY (GE_BASE + 0x0C) /* Source X/Y register */
-+#define LINE_MINOR_Y SRC_XY /* Bresenham Line Delta register */
-+#define COLOR_COMPARE (GE_BASE + 0x10) /* Color compare register */
-+#define CLIP_LeftT (GE_BASE + 0x14) /* Clip Left/Top register */
-+#define CLIP_RightB (GE_BASE + 0x18) /* Clip Right/Bottom register */
-+#define FG_COLOR (GE_BASE + 0x1C) /* Fg color for Mono src reg */
-+#define BG_COLOR (GE_BASE + 0x20) /* Bg color for Mono src reg */
-+#define SRC_STRIDE_OFFSET (GE_BASE + 0x24) /* Source Stride & Offset Reg */
-+#define DEST_STRIDE (GE_BASE + 0x28) /* Base address register */
-+#define BASE_ADDRESS (GE_BASE + 0x2C) /* Base address register */
-+#define TEST_RESULT_REG (GE_BASE + 0x7C) /* Test result register */
-+#define COLOR_PATTERN (GE_BASE + 0x100) /* Color pattern registers */
-+#define MONO_PATTERN0 COLOR_PATTERN /* Mono Pattern register 0 */
-+#define MONO_PATTERN1 (GE_BASE + 0x104) /* Mono Pattern register 1 */
-+#define PAT_FG_COLOR (GE_BASE + 0x108) /* Mono Pattern Fg color reg */
-+#define PAT_BG_COLOR (GE_BASE + 0x10C) /* Mono Pattern Bg color reg */
-+#define _FIRST_GE DRAW_CMD
-+#define _LAST_GE (COLOR_PATTERN + 0x80)
-+#define SRC_IMAGE_DATA (GE_BASE + 0xC000) /* Source Data register */
-+
-+/* 2D Engine registers - GE2 (0x80 to 0xFF) */
-+#define DRAW_CMD2 (GE2_BASE + 0x00) /* Drawing command register */
-+#define WIDTH_HEIGHT2 (GE2_BASE + 0x04) /* Width/height register */
-+#define LINE_DRAW2 WIDTH_HEIGHT2 /* Bresenham Line Draw register */
-+#define DEST_XY2 (GE2_BASE + 0x08) /* Destination X/Y register */
-+#define LINE_MAJOR_X2 DEST_XY2 /* Bresenham Line Start X/Y reg */
-+#define PAT_OFFSET2 DEST_XY2 /* Pattern Offset register */
-+#define SRC_XY2 (GE2_BASE + 0x0C) /* Source X/Y register */
-+#define LINE_MINOR_Y2 SRC_XY2 /* Bresenham Line Delta register */
-+#define COLOR_COMPARE2 (GE2_BASE + 0x10) /* Color compare register */
-+#define CLIP_LeftT2 (GE2_BASE + 0x14) /* Clip Left/Top register */
-+#define CLIP_RightB2 (GE2_BASE + 0x18) /* Clip Right/Bottom register */
-+#define FG_COLOR2 (GE2_BASE + 0x1C) /* Fg color for Mono src reg */
-+#define BG_COLOR2 (GE2_BASE + 0x20) /* Bg color for Mono src reg */
-+#define SRC_STRIDE_OFFSET2 (GE2_BASE + 0x24) /* Source Stride & Offset Reg */
-+#define DEST_STRIDE2 (GE2_BASE + 0x28) /* Base address register */
-+#define BASE_ADDRESS2 (GE2_BASE + 0x2C) /* Base address register */
-+#define TEST_RESULT_REG2 (GE2_BASE + 0x7C) /* Test result register */
-+#define COLOR_PATTERN2 (GE2_BASE + 0x100) /* Color pattern registers */
-+#define MONO_PATTERN02 COLOR_PATTERN2 /* Mono Pattern register 0 */
-+#define MONO_PATTERN12 (GE2_BASE + 0x104) /* Mono Pattern register 1 */
-+#define PAT_FG_COLOR2 (GE2_BASE + 0x108) /* Mono Pattern Fg color reg */
-+#define PAT_BG_COLOR2 (GE2_BASE + 0x10C) /* Mono Pattern Bg color reg */
-+#define _FIRST_GE2 DRAW_CMD2
-+#define _LAST_GE2 (COLOR_PATTERN2 + 0x80)
-+#define SRC_IMAGE_DATA2 (GE2_BASE + 0xC000) /* Source Data register */
-+
-+
-+/* DEST_STRIDE color depth */
-+#define GE_8BPP 0x00000000 /* 8BPP mode */
-+#define GE_16BPP 0x40000000 /* 16BPP mode */
-+#define GE_24BPP 0x80000000 /* 24BPP mode */
-+#define GE_32BPP 0xC0000000 /* 24BPP mode */
-+
-+/* BASE_ADDRESS */
-+#define GE_TEST_MODE_ENABLE 0x20000000 /* Test mode enabled */
-+#define GE_TEST_MASK 0xc0000000 /* Test mode read path select */
-+#define SEL_CLIP_LR 0x40000000 /* Select clipping left/right */
-+#define SEL_CLIP_TB 0x80000000 /* Select clipping top/bottom */
-+
-+/* Draw command register bits */
-+#define DO_BITBLT 0x00000200
-+#define DO_AAFONT 0x00000300
-+#define DO_LINEDRAW 0x00000400
-+#define X_DIR 0x00000800 /* Negative X direction */
-+#define Y_DIR 0x00001000 /* Negative Y direction */
-+#define SRC_IS_MEMORY 0x00002000 /* Source is in system memory */
-+#define MONO_SRC 0x00004000 /* Source is mono bitmap */
-+#define MONO_PATTERN 0x00008000 /* Pattern is monochrome */
-+#define TRANS_COLOR 0x00010000 /* Transparency is enabled */
-+#define TRANS_NOT_EQUAL 0x00020000 /* Polarity for color */
-+#define TRANS_MONO 0x00040000 /* Mono xparency is enabled */
-+#define TRANS_MONO_FG 0x00080000 /* Polarity for mono */
-+#define PACKED_MODE 0x00100000 /* Memory xfer mode select */
-+#define ALPHA_BYTE_MASK 0x00600000 /* Alpha Byte mask for 32bpp */
-+#define MONO_SOLID 0x00800000 /* Solid Mono Pattern */
-+#define SRC_NE_DEST_STRIDE 0x01000000 /* Src Not Equal Dest Stride */
-+#define ROP2_ENABLE 0x02000000 /* Use Rop2 code */
-+#define CLIP_ENABLE 0x04000000 /* Clipping is enabled */
-+#define AUTO_EXEC 0x08000000 /* Auto execute at dest X/Y */
-+#define VDE_GC2_ENABLE 0x10000000 /* Enable falling edge check */
-+#define VDE_GC1_ENABLE 0x20000000 /* Enable falling edge check */
-+#define COLOR_DEPTH_MASK 0xC0000000 /* Color Depth mask */
-+#define GE_8BPP 0x00000000 /* 8BPP mode */
-+#define GE_16BPP 0x40000000 /* 16BPP mode */
-+#define GE_24BPP 0x80000000 /* 24BPP mode */
-+
-+/* Graphics Controller 1 Registers */
-+#define GC1_CONTROL (GC_BASE + 0x00) /* Graphics Controll 1 Control Reg */
-+#define GC1_CRT_CONTROL (GC_BASE + 0x04) /* CRT controll register */
-+#define HD1_CONTROL (GC_BASE + 0x08) /* Horizontal Display 1 Control */
-+#define VD1_CONTROL (GC_BASE + 0x0C) /* Vertical Display 1 Control */
-+#define HS1_CONTROL (GC_BASE + 0x10) /* Horizontal Sync 1 Control */
-+#define VS1_CONTROL (GC_BASE + 0x14) /* Vertical Sync 1 Control */
-+#define HW1_CONTROL (GC_BASE + 0x20) /* Horizontal Window 1 Control */
-+#define VW1_CONTROL (GC_BASE + 0x24) /* Vertical Window 1 Control */
-+#define AHW1_CONTROL (GC_BASE + 0x28) /* Alt Horizontal Window 1 Control */
-+#define AVW1_CONTROL (GC_BASE + 0x2C) /* Alt Vertical Window 1 Control */
-+#define IW1_START_ADDR (GC_BASE + 0x30) /* Image Window 1 Start Address */
-+#define AIW1_START_ADDR (GC_BASE + 0x34) /* Alt Image Window 1 Start Address */
-+#define IW1_STRIDE (GC_BASE + 0x38) /* (Alt) Image Window 1 Stride */
-+#define IW1_LINE_SIZE (GC_BASE + 0x3C) /* (Alt) Image Window 1 Line Size */
-+#define HW_CURSOR1_POS (GC_BASE + 0x40) /* Hardware cursor 1 position */
-+#define HW_CURSOR1_ADDR (GC_BASE + 0x44) /* Start address and offset */
-+#define HW_CURSOR1_FGCLR (GC_BASE + 0x48) /* Foreground color */
-+#define HW_CURSOR1_BGCLR (GC_BASE + 0x4C) /* Background color */
-+
-+/* Graphics Controller 2 Registers */
-+#define GC2_CONTROL (GC_BASE + 0x80) /* Graphics Controll 2 Control Reg */
-+#define GC2_CRC_CONTROL (GC_BASE + 0x84) /* CRC Control */
-+#define HD2_CONTROL (GC_BASE + 0x88) /* Horizontal Display 2 Control */
-+#define VD2_CONTROL (GC_BASE + 0x8C) /* Vertical Display 2 Control */
-+#define HS2_CONTROL (GC_BASE + 0x90) /* Horizontal Sync 2 Control */
-+#define VS2_CONTROL (GC_BASE + 0x94) /* Vertical Sync 2 Control */
-+#define HW2_CONTROL (GC_BASE + 0xA0) /* Horizontal Window 2 Control */
-+#define VW2_CONTROL (GC_BASE + 0xA4) /* Vertical Window 2 Control */
-+#define AHW2_CONTROL (GC_BASE + 0xA8) /* Alt Horizontal Window 2 Control */
-+#define AVW2_CONTROL (GC_BASE + 0xAC) /* Alt Vertical Window 2 Control */
-+#define IW2_START_ADDR (GC_BASE + 0xB0) /* Image Window 2 Start Address */
-+#define AIW2_START_ADDR (GC_BASE + 0xB4) /* Alt Image Window 2 Start Address */
-+#define IW2_STRIDE (GC_BASE + 0xB8) /* (Alt) Image Window 2 Stride */
-+#define IW2_LINE_SIZE (GC_BASE + 0xBC) /* (Alt) Image Window 2 Line Size */
-+#define HW_CURSOR2_POS (GC_BASE + 0xC0) /* Hardware cursor 2 position */
-+#define HW_CURSOR2_ADDR (GC_BASE + 0xC4) /* Start address and offset */
-+#define HW_CURSOR2_FGCLR (GC_BASE + 0xC8) /* Foreground color */
-+#define HW_CURSOR2_BGCLR (GC_BASE + 0xCC) /* Background color */
-+
-+/* GC1_CONTROL/GC2_CONTROL register */
-+#define GC_ENABLE 0x00000001UL /* Controll 1/2 enabled */
-+#define GC_DISABLE 0xfffffffeUL /* Controll 1/2 disabled */
-+#define HORZ_COUNT_RESET 0x00000002UL /* Horiz counter 1/2 reset */
-+#define VERT_COUNT_RESET 0x00000004UL /* Vertical counter 1/2 reset */
-+#define IM_ENABLE 0x00000008UL /* Image Window 1/2 Enable */
-+#define IM_DISABLE 0xfffffff7UL /* Image Window 1/2 Disable */
-+
-+#define GC_1BPP 0x00000000UL /* GC1/2 color depth */
-+#define GC_2BPP 0x00000010UL
-+#define GC_4BPP 0x00000020UL
-+#define GC_8BPP 0x00000030UL
-+#define GC_16BPP 0x00000040UL /* with color palette enabled */
-+#define GC_24BPP_NBP 0x00000050UL /* with color palette enabled */
-+#define GC_32BPP_ABGR 0x00000060UL /* with color palette enabled */
-+#define GC_32BPP_ARGB 0x00000070UL /* with color palette enabled */
-+#define GC_16BPP_BP 0x000000C0UL /* with color pal bypassed */
-+#define GC_24BPP_BP 0x000000D0UL /* with color pal bypassed */
-+#define GC_32BPP_ABGR_BP 0x000000E0UL /* with color pal bypassed */
-+#define GC_32BPP_ARGB_BP 0x000000F0UL /* with color pal bypassed */
-+#define GC_32BPP GC_32BPP_ARGB /* Default 32bpp with ARGB */
-+#define GC_24BPP GC_24BPP_NBP
-+
-+#define HC_ENABLE 0x00000100UL /* Hardware cursor enable */
-+#define HC_DISABLE 0xfffffeffUL /* And mask to disable HC */
-+#define AIM_ENABLE 0x00000800UL /* Alt Image Win 1/2 Enable */
-+
-+#define AGC_1BPP 0x00000000UL /* Alt GC1/2 color depth */
-+#define AGC_2BPP 0x00001000UL
-+#define AGC_4BPP 0x00002000UL
-+#define AGC_8BPP 0x00003000UL
-+#define AGC_16BPP 0x00004000UL
-+#define AGC_24BPP 0x00005000UL
-+#define AGC_32BPP_ABGR 0x00006000UL
-+#define AGC_32BPP_ARGB 0x00007000UL
-+#define AGC_16BPP_BP 0x0000C000UL
-+#define AGC_24BPP_BP 0x0000D000UL
-+#define AGC_32BPP_ABGR_BP 0x0000E000UL
-+#define AGC_32BPP_ARGB_BP 0x0000F000UL
-+#define AGC_32BPP AGC_32BPP_ARGB_BP /* Default 32bpp w/ ARGB_BP */
-+
-+#define GxRCLK_BUSCLK 0x00000000UL /* G1RCLK source is bus clock */
-+#define GxRCLK_PLL1 0x00010000UL /* G1RCLK source is PLL1 */
-+#define GxRCLK_PLL2 0x00020000UL /* G1RCLK source is PLL2 */
-+#define GxRCLK_PLL3 0x00030000UL /* G1RCLK source is PLL3 */
-+#define GxRCLK_PLL_MASK 0x00030000UL /* G1RCLK source mask */
-+#define GC_TEST_MODE0 0x00040000UL /* Test mode 0 enabled */
-+#define GC_TEST_MODE1 0x00080000UL /* Test mode 1 enabled */
-+
-+#define FDx_1 0x00000000UL /* FD1 = 1 */
-+#define FDx_15 0x00100000UL /* FD1 = 1.5 */
-+#define FDx_25 0x00200000UL /* FD1 = 2.5 */
-+#define FDx_35 0x00300000UL /* FD1 = 3.5 */
-+#define FDx_45 0x00400000UL /* FD1 = 4.5 */
-+#define FDx_55 0x00500000UL /* FD1 = 5.5 */
-+#define FDx_65 0x00600000UL /* FD1 = 6.5 */
-+
-+/* GC1_CRT_CONTROL register */
-+#define CRT_ENABLE 0x00000001UL /* CRT DAC enabled */
-+#define CRT_DISABLE 0xfffffffeUL /* CRT DAC disabled -and mask */
-+#define CRT_BY_GC1 0x00000001UL /* CRT DAC driven by GC1 */
-+#define CRT_BY_GC2 0x00000003UL /* CRT DAC driven by GC2 */
-+#define CRT_BY_GCxMASK 0xfffffffcUL /* Mask for CRT DAC */
-+#define VSYNC_OUT_PMCLK 0x00000004UL /* CRT VSYNC output PMCLK
-+ at PwrDn */
-+#define HSYNC_OUT_PMCLK 0x00000008UL /* CRT HSYNC output PMCLK
-+ at PwrDn */
-+#define HSYNC_OUT_LOW 0x00000010UL /* CRT HSYNC output pin low */
-+#define HSYNC_OUT_HIGH 0x00000020UL /* CRT HSYNC output pin high */
-+#define VSYNC_OUT_LOW 0x00000040UL /* CRT VSYNC output pin low */
-+#define VSYNC_OUT_HIGH 0x00000080UL /* CRT VSYNC output pin high */
-+#define HSYNC_POLARITY_LOW 0x00000100UL /* active low */
-+#define VSYNC_POLARITY_LOW 0x00000200UL /* active low */
-+#define SYNC_PED_ENABLE 0x00000400UL /* Sync pedestal enable */
-+#define BLANK_PED_ENABLE 0x00000800UL /* Blank pedestal enable */
-+#define CSYNC_ENABLE 0x00001000UL /* Composite Sync Enable */
-+#define VREF_EXTERNAL 0x00002000UL /* Select external VREF */
-+#define MON_SENSE_ENABLE 0x00004000UL /* CRT DAC monitor sense
-+ enable */
-+#define CONST_OUT_ENABLE 0x00008000UL /* Constant output enable */
-+#define BLUE_NOT_LOADED 0x01000000UL /* Blue DAC is not loaded */
-+#define GREEN_NOT_LOADED 0x02000000UL /* Green DAC is not loaded */
-+#define RED_NOT_LOADED 0x04000000UL /* Red DAC is not loaded */
-+
-+/* GC2_CRC_CONTROL */
-+#define CRC_ENABLE 0x00000001UL /* Enable CRC logic */
-+#define CRC_2_VSYNC 0x00000002UL /* Wait for 2 vsync */
-+#define CRC_READ_BLUE 0x00000000UL /* Read CRC result for blue */
-+#define CRC_READ_GREEN 0x00000004UL /* Read CRC result for green */
-+#define CRC_READ_RED 0x00000008UL /* Read CRC result for red */
-+#define CRC_RESULT_MASK 0x3fffff00UL /* CRC result mask */
-+
-+/* Flat Panel Interface Registers */
-+#define FP_CONTROL (FP_BASE + 0x00) /* Flat panel control */
-+#define FP_PIN_CONTROL (FP_BASE + 0x04) /* Flat panel pin control */
-+#define FP_GPO_CONTROL (FP_BASE + 0x08) /* FP Gen. purpose output ctrl */
-+#define FP_GPIO_CONTROL (FP_BASE + 0x0C) /* FP Gen. purpose I/O control */
-+#define STN_CONTROL (FP_BASE + 0x10) /* STN panel control */
-+#define DSTN_FB_CONTROL (FP_BASE + 0x14) /* D-STN frame buffer control */
-+#define PWM_CONTROL (FP_BASE + 0x3C) /* PWM control */
-+#define FRC_PATTERN (FP_BASE + 0x40) /* FRC pattern starting index */
-+#define FRC_WEIGHT (FP_BASE + 0xC0) /* FRC weight starting index */
-+
-+/* FP_CONTROL */
-+#define FPI_ENABLE 0x00000001UL /* Trigger fp power up sequence */
-+#define FPI_DISABLE 0xfffffffeUL /* Trigger fp power down sequence */
-+#define FPI_BY_GC1 0x00000001UL /* FPI enabled & driven by GC1 */
-+#define FPI_BY_GC2 0x00000003UL /* FPI enabled & driven by GC2 */
-+#define FPI_BY_GCxMASK 0xfffffffcUL /* mask */
-+#define FP_TYPE_TFT 0x00000000UL /* Flat panel type TFT */
-+#define FP_TYPE_SSTN 0x00000004UL /* Flat panel type S-STN */
-+#define FP_TYPE_DSTN 0x00000008UL /* Flat panel type D-STN */
-+#define FP_TYPE_MASK 0x0000000cUL /* Flat panel type mask */
-+#define FP_COLOR 0x00000000UL /* Color flat panel */
-+#define FP_MONO 0x00000010UL /* Mono flat panel */
-+#define TFT_4BITS_MONO 0x00000000UL /* Specify num of bits/pixel */
-+#define TFT_12BITS_COLOR 0x00000000UL /* Specify num of bits/pixel */
-+#define SSTN_4BITS_MONOCLR 0x00000000UL /* Specify num of bits/pixel */
-+#define DSTN_8BITS_MONOCLR 0x00000000UL /* Specify num of bits/pixel */
-+#define TFT_6BITS_MONO 0x00000020UL /* Specify num of bits/pixel */
-+#define TFT_18BITS_COLOR 0x00000020UL /* Specify num of bits/pixel */
-+#define SSTN_8BITS_MONOCLR 0x00000020UL /* Specify num of bits/pixel */
-+#define DSTN_16BITS_MONOCLR 0x00000020UL /* Specify num of bits/pixel */
-+#define TFT_8BITS_MONO 0x00000040UL /* Specify num of bits/pixel */
-+#define TFT_24BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define SSTN_12BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define DSTN_24BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define SSTN_16BITS_MONOCLR 0x00000060UL /* Specify num of bits/pixel */
-+#define SSTN_24BITS_COLOR 0x00000080UL /* Specify num of bits/pixel */
-+#define DITHER_PATTERN_0 0x00000000UL /* Dither pattern */
-+#define DITHER_PATTERN_1 0x00000100UL /* Dither pattern */
-+#define DITHER_PATTERN_2 0x00000200UL /* Dither pattern */
-+#define DITHER_PATTERN_3 0x00000300UL /* Dither pattern */
-+#define DITHER_BASE_8BITS 0x00000000UL /* No dithering */
-+#define DITHER_BASE_2BITS 0x00002000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_3BITS 0x00003000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_4BITS 0x00004000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_6BITS 0x00006000UL /* Num of bits to be dithered */
-+#define FRC_ALTWIN_DISABLE 0x00008000UL /* Disable Dither/FRC if Alt enabled */
-+#define FRC_2LEVEL 0x00000000UL /* Disable FRC */
-+#define FRC_4LEVEL 0x00010000UL /* 4-level FRC */
-+#define FRC_8LEVEL 0x00020000UL /* 8-level FRC */
-+#define FRC_16LEVEL 0x00030000UL /* 16-level FRC */
-+#define DITHER_PATTERN_ADJ1 0x00fc0000UL /* Dither pattern adjust 1 */
-+#define DITHER_PATTERN_ADJ2 0x07000000UL /* Dither pattern adjust 2 */
-+#define DITHER_PATTERN_ADJ3 0x08000000UL /* Dither pattern adjust 3 */
-+#define TEST_MODE0_ENABLE 0x10000000UL /* Enable test mode 0 */
-+#define TEST_MODE1_ENABLE 0x20000000UL /* Enable test mode 1 */
-+#define TEST_MODE2_ENABLE 0x40000000UL /* Enable test mode 2 */
-+#define TEST_MODE3_ENABLE 0x80000000UL /* Enable test mode 3 */
-+
-+/* FP_PIN_CONTROL */
-+#define FP_PIN_DISABLE 0x00000001UL /* Disable flat panel pins */
-+#define DATA_INV_ENABLE 0x00000002UL /* TFT fp data inversion enabled */
-+#define FP_DISP_ENABLE 0x00000004UL /* FP Display enable control */
-+#define FMOD_ENABLE 0x00000008UL /* Flat panel AC mod enable */
-+#define FD2_SCLK 0x00000010UL /* STN output shift clk on FD2 pin*/
-+#define FSCLK_OUTPUT_ENABLE 0x00000020UL /* FSCLK output enable */
-+#define TFT_SCLK_SELECT 0x00000040UL /* TFT shift clock select */
-+#define SCLK_MASK 0x00000080UL /* Shift clock mask */
-+#define STN_LP_DISABLE 0x00000100UL /* STN LP control */
-+#define SCLK_DISABLE 0x00000200UL /* STN shift clock control */
-+#define STN_ExtraLP_ENABLE 0x00000400UL /* STN extra LP control */
-+#define FP_FD2_MAX 0x00000000UL /* FD2 drive strength - max (16mA)*/
-+#define FP_FD2_MEDIUM 0x00001000UL /* FD2 drive strength - medium */
-+#define FP_FD2_MEDIUM2 0x00002000UL /* FD2 drive strength - medium 2 */
-+#define FP_FD2_MIN 0x00003000UL /* FD2 drive strength - min */
-+#define FP_DATA_MAX 0x00000000UL /* Data drv strength - max (16mA) */
-+#define FP_DATA_MEDIUM 0x00004000UL /* Data drive strength - medium */
-+#define FP_DATA_MEDIUM2 0x00008000UL /* Data drive strength - medium 2 */
-+#define FP_DATA_MIN 0x0000c000UL /* Data drive strength - min */
-+#define FD2_ACTIVE_L 0x00010000UL /* Flat panel data bit 2 polarity */
-+#define FD_ACTIVE_L 0x00020000UL /* Flat panel data polarity */
-+#define FDE_ACTIVE_L 0x00040000UL /* Data enable polarity */
-+#define FHSYNC_ACTIVE_L 0x00080000UL /* Horz sync polarity */
-+#define FVSYNC_ACTIVE_L 0x00100000UL /* Vert sync polarity */
-+#define FSCLK_ACTIVE_L 0x00200000UL /* Shift clock polarity */
-+#define FP_FSCLK_MAX 0x00000000UL /* Sh clk drv strength -max (16mA)*/
-+#define FP_FSCLK_MEDIUM 0x00400000UL /* Sh clk drv strength -medium */
-+#define FP_FSCLK_MEDIUM2 0x00800000UL /* Sh clk drv strength -medium 2 */
-+#define FP_FSCLK_MIN 0x00c00000UL /* Sh clk drv strength -min */
-+#define FSCLK_DELAY 0x07000000UL /* Shift clock delay */
-+
-+/* FP_GPO_CONTROL */
-+#define ENCTL_AS_GPO0 0x00000001UL /* ENCTL used as GPO 0 */
-+#define ENCTL_AS_OSC 0x00000002UL /* ENCTL used as Oscillator clock */
-+#define ENCTL_AS_PLL3 0x00000003UL /* ENCTL used as PLL3 clock */
-+#define ENVEE_AS_GPO1 0x00000004UL /* ENVEE used as GPO 1 */
-+#define PWM0_AS_GPO2 0x00000010UL /* PWM0 pin used as GPO 2 */
-+#define PWM1_AS_GPO3 0x00000040UL /* PWM1 pin used as GPO 3 */
-+#define ENVDD_AS_GPO4 0x00000100UL /* ENVDD pin used as GPO 4 */
-+#define FP_PWM_MAX 0x00000000UL /* PWM0/1 drv strength -max (16mA)*/
-+#define FP_PWM_MEDIUM 0x00000400UL /* PWM0/1 drv strength -medium */
-+#define FP_PWM_MEDIUM2 0x00000800UL /* PWM0/1 drv strength -medium 2 */
-+#define FP_PWM_MIN 0x00000c00UL /* PWM0/1 drv strength -min */
-+#define FP_GPIO_MAX 0x00000000UL /* GPIO0/1/2 drv strgth. -max 16mA*/
-+#define FP_GPIO_MEDIUM 0x00001000UL /* GPIO0/1/2 drv strgth. -medium */
-+#define FP_GPIO_MEDIUM2 0x00002000UL /* GPIO0/1/2 drv strgth. -medium 2*/
-+#define FP_GPIO_MIN 0x00003000UL /* GPIO0/1/2 drv strgth. -min */
-+#define FP_EN_MAX 0x00000000UL /* ENVDD/ENCTL/ENVEE -max (16mA) */
-+#define FP_EN_MEDIUM 0x00004000UL /* ENVDD/ENCTL/ENVEE -medium */
-+#define FP_EN_MEDIUM2 0x00008000UL /* ENVDD/ENCTL/ENVEE -medium 2 */
-+#define FP_EN_MIN 0x0000c000UL /* ENVDD/ENCTL/ENVEE -min */
-+#define GPO0_DATA_HIGH 0x00010000UL /* ENCTL is driven high */
-+#define GPO1_DATA_HIGH 0x00020000UL /* ENVEE is driven high */
-+#define GPO2_DATA_HIGH 0x00040000UL /* PWM0 is driven high */
-+#define GPO3_DATA_HIGH 0x00080000UL /* PWM1 is driven high */
-+#define GPO4_DATA_HIGH 0x00100000UL /* ENVDD is driven high */
-+
-+/* FP_GPIO_CONTROL */
-+#define GPIO0_IN 0x00000000UL /* General-purpose input */
-+#define GPIO0_OUT 0x00000001UL /* General-purpose output */
-+#define GPIO0_PLL1 0x00000002UL /* GPIO0 used to output PLL 1 clk */
-+#define GPIO0_CRC_B 0x00000003UL /* GPIO0 used to output CRC Blue */
-+#define GPIO1_IN 0x00000000UL /* General-purpose input */
-+#define GPIO1_OUT 0x00000004UL /* General-purpose output */
-+#define GPIO1_PLL2 0x00000008UL /* GPIO1 used to output PLL 2 clk */
-+#define GPIO1_CRC_G 0x0000000cUL /* GPIO1 used to output CRC Green */
-+#define GPIO2_IN 0x00000000UL /* General-purpose input */
-+#define GPIO2_OUT 0x00000010UL /* General-purpose output */
-+#define GPIO2_PLL3 0x00000020UL /* GPIO2 used to output PLL 3 clk */
-+#define GPIO2_CRC_R 0x00000030UL /* GPIO2 used to output CRC Red */
-+#define GPIO0_OUT_HIGH 0x00010000UL /* GOIO0 output data */
-+#define GPIO1_OUT_HIGH 0x00020000UL /* GOIO1 output data */
-+#define GPIO2_OUT_HIGH 0x00040000UL /* GOIO2 output data */
-+#define GPIO0_IN_HIGH 0x01000000UL /* GOIO0 input data */
-+#define GPIO1_IN_HIGH 0x02000000UL /* GOIO1 input data */
-+#define GPIO2_IN_HIGH 0x04000000UL /* GOIO2 input data */
-+
-+/* STN_CONTROL */
-+#define FMOD_FRAMECLK 0x00000000UL /* FMOD generated using frame clock */
-+#define FMOD_LINECLK 0x80000000UL /* FMOD generated using line clock */
-+
-+/* PWM_CONTROL */
-+#define PWM0_BY_PLL 0x00000000UL /* PWM 0 signal by PLL */
-+#define PWM0_BY_BUS 0x00000001UL /* PWM 0 signal using bus clk */
-+#define PWM0_BY_PMC 0x00000002UL /* PWM 0 signal by power mgt clock */
-+#define PWM0_ALWAYS_ON 0x00000004UL /* PWM 0 signal always generated */
-+#define PWM0_DC_MASK 0xffff00ffUL /* PWM 0 duty cycle mask */
-+#define PWM0_MASK 0xffff0000UL /* PWM 0 mask */
-+#define PWM1_BY_PLL 0x00000000UL /* PWM 1 signal by PLL */
-+#define PWM1_BY_BUS 0x00010000UL /* PWM 1 signal using bus clk */
-+#define PWM1_BY_PMC 0x00020000UL /* PWM 1 signal by power mgt clock */
-+#define PWM1_ALWAYS_ON 0x00040000UL /* PWM 1 signal always generated */
-+#define PWM1_DC_MASK 0x00ffffffUL /* PWM 0 duty cycle mask */
-+#define PWM1_MASK 0x0000ffffUL /* PWM 1 mask */
-+
-+/* PCI Power Management Interface Registers */
-+#ifndef PCI_VENDOR_DEVICE
-+#define PCI_VENDOR_DEVICE (PC_BASE + 0x00)
-+#endif
-+
-+#ifndef PCI_CMD_STATUS
-+#define PCI_CMD_STATUS (PC_BASE + 0x04)
-+#endif
-+
-+#ifndef PCI_REV_CLASS
-+#define PCI_REV_CLASS (PC_BASE + 0x08)
-+#endif
-+
-+#ifndef PCI_HEADER_TYPE
-+#define PCI_HEADER_TYPE (PC_BASE + 0x0c)
-+#endif
-+
-+#ifndef PCI_SUB_ID
-+#define PCI_SUB_ID (PC_BASE + 0x2c)
-+#endif
-+
-+#ifndef PCI_ROM_BASE
-+#define PCI_ROM_BASE (PC_BASE + 0x30)
-+#endif
-+
-+#ifndef PCI_CAP_PTR
-+#define PCI_CAP_PTR (PC_BASE + 0x34)
-+#endif
-+
-+#ifndef PCI_INTERRUPT
-+#define PCI_INTERRUPT (PC_BASE + 0x3c)
-+#endif
-+
-+#ifndef PCI_PM_REGISTER
-+#define PCI_PM_REGISTER (PC_BASE + 0x40)
-+#endif
-+
-+#ifndef PCI_PM_CNTL_STATUS
-+#define PCI_PM_CNTL_STATUS (PC_BASE + 0x44)
-+#endif
-+
-+/* POWER_STATE */
-+#define POWER_STATE_MASK 0x00000003UL /* Device power state mask */
-+#define ENTER_D0 0x00000000UL /* Enter D0 state */
-+#define ENTER_D1 0x00000001UL /* Enter D1 state */
-+#define ENTER_D2 0x00000002UL /* Enter D2 state */
-+#define ENTER_D3 0x00000003UL /* Enter D3 state */
-+
-+/* DC (Device Configuration Unit) Registers */
-+#define DC_0 (DC_BASE + 0x00) /* Device Configruation Register 0 */
-+#define DC_1 (DC_BASE + 0x04) /* Device Configruation Register 1 */
-+#define DC_SW_0 (DC_BASE + 0x08) /* Software Register 0 */
-+#define DC_SW_1 (DC_BASE + 0x0C) /* Software Register 1 */
-+
-+/* DC_0 */
-+#define OSC_BYPASSED 0x00000001UL /* Oscillator bypassed, powered down */
-+#define OSC_ENABLE 0x00000002UL /* Oscillator control can be enabled */
-+#define PLL1_BYPASSED 0x00000004UL /* PLL1 bypassed */
-+#define PLL1_ENABLE 0x00000008UL /* PLL1 can be enabled */
-+#define PLL1_DIVBY1 0x00000000UL /* PLL1 P output divisor by 1 */
-+#define PLL1_DIVBY2 0x00000010UL /* PLL1 P output divisor by 2 */
-+#define PLL1_DIVBY4 0x00000020UL /* PLL1 P output divisor by 4 */
-+#define PLL1_DIVBY8 0x00000030UL /* PLL1 P output divisor by 8 */
-+#define PLL1_DIVBY16 0x00000040UL /* PLL1 P output divisor by 16 */
-+#define PLL1_DIV_MASK 0x00000070UL /* PLL1 P output divisor mask */
-+#define CIF_DIVBY1 0x00000000UL /* CPU Interface clk divisor by 1 */
-+#define CIF_DIVBY2 0x00000080UL /* CPU Interface clk divisor by 2 */
-+#define STRONGARM_SYNC_F 0x00002000UL /* StrongARM bus intrf at fall edge */
-+#define SW_CHIP_RESET 0x00004000UL /* Software chip reset */
-+#define MEM_STANDBY_DISABLE 0x00008000UL /* Memory Power unit Standby disab. */
-+#define OSC_SHAPER_DISABLE 0x01000000UL /* Oscillator waveform shaper disab. */
-+#define FAST_POWER_DISABLE 0x02000000UL /* Fast Power Sequencing disable */
-+#define OSC_FREQ_SEL_0 0x00000000UL /* Osc frequency select range 0 */
-+#define OSC_FREQ_SEL_1 0x04000000UL /* Osc frequency select range 1 */
-+#define OSC_FREQ_SEL_2 0x08000000UL /* Osc frequency select range 2 */
-+#define OSC_FREQ_SEL_3 0x0c000000UL /* Osc frequency select range 3 */
-+
-+/* DC_1 */
-+#define BUS_MODE_MASK 0x0000003FUL /* Bus interface mode mask */
-+#define BUS_MODE_SH7709 0x00000001UL /* Bus interface mode - SH7709 */
-+#define BUS_MODE_SH7750 0x00000002UL /* Bus interface mode - SH7750 */
-+#define BUS_MODE_VR41xx 0x00000004UL /* Bus interface mode - VR4111/21 */
-+#define BUS_MODE_SA1110 0x00000008UL /* Bus interface mode - SA1110 */
-+#define BUS_MODE_TX3922 0x00000010UL /* Bus interface mode - TX3922 */
-+#define BUS_MODE_PCI 0x00000020UL /* Bus interface mode - PCI */
-+
-+/* PMU (Power Management Unit) Registers */
-+#define PM_MISC (PM_BASE + 0x00) /* Power management misc ctrl */
-+#define D1_STATE (PM_BASE + 0x04) /* D1 state control */
-+#define D2_STATE (PM_BASE + 0x08) /* D2 state control */
-+#define PLL2_CONTROL (PM_BASE + 0x18) /* PLL2 programming */
-+#define PLL3_CONTROL (PM_BASE + 0x1C) /* PLL3 programming */
-+
-+/* PM_MISC */
-+#define PLL1_N_BIT5 0x00000001UL /* Bit 5 of PLL1 N parameter */
-+#define PLL2_ENABLE 0x00000004UL /* PLL2 can be enabled */
-+#define PLL3_ENABLE 0x00000008UL /* PLL3 can be enabled */
-+#define FORCE_POWER_STATE 0x00000020UL /* For testing */
-+#define GE_ENABLE 0x00000100UL /* GE can be enabled */
-+#define GE_CLOCK_ON 0x00000200UL /* GE clock is always running */
-+#define GE_PIPELINE_ON 0x00000400UL /* GE pipeline always running */
-+#define GE_BY_BUS 0x00000000UL /* GE driven by bus intf clk */
-+#define GE_BY_PLL1 0x00000800UL /* GE driven by PLL1 */
-+#define GE_BY_PLL2 0x00001000UL /* GE driven by PLL2 */
-+#define GE_BY_PLL3 0x00001800UL /* GE driven by PLL3 */
-+#define GE_BY_MASK 0x00001800UL /* GE clock select mask */
-+#define GE_CMDFIFO_RESET 0x00002000UL /* GE command FIFO is reset */
-+#define GE_SRCFIFO_RESET 0x00004000UL /* GE CPU src FIFO is reset */
-+#define POWER_ON_IF_MIU_ON 0x00008000UL /* Pwr seq on when MIU enab.*/
-+#define D3_MEM_REFRESF 0x00010000UL /* FrameBuf refreshed in D3 */
-+#define D4_MEM_REFRESF 0x00020000UL /* FrameBuf refreshed in D4 */
-+#define PMCLK_4CYCLE 0x00000000UL /* Power sequencing interval */
-+#define PMCLK_8CYCLE 0x00040000UL /* Power sequencing interval */
-+#define PMCLK_16CYCLE 0x00080000UL /* Power sequencing interval */
-+#define PMCLK_2048CYCLE 0x000c0000UL /* Power sequencing interval */
-+#define FP_PMCLK_512 0x00000000UL /* FP power seq interval */
-+#define FP_PMCLK_1024 0x00100000UL /* FP power seq interval */
-+#define FP_PMCLK_2048 0x00200000UL /* FP power seq interval */
-+#define FP_PMCLK_128K 0x00300000UL /* FP power seq interval */
-+#define POWER_SEQ_ALL 0x00400000UL /* General power seq interval */
-+#define PMU_TEST_MODE 0x008000UL /* PMU test mode */
-+#define PM_POWER_MASK 0x03000000UL /* Power state mask */
-+#define PM_D0_STATE 0x00000000UL /* Power state D0 */
-+#define PM_D1_STATE 0x01000000UL /* Power state D1 */
-+#define PM_D2_STATE 0x02000000UL /* Power state D2 */
-+#define PM_D3_STATE 0x03000000UL /* Power state D3 */
-+#define POWER_IN_PROGRESS 0x04000000UL /* Power seq. active status */
-+
-+/* D1_STATE and D2_STATE */
-+#define DxOSC_ENABLE 0x00000001UL /* Oscillator can be enabled in D1/2 */
-+#define DxPLL1_ENABLE 0x00000002UL /* PLL1 can be enabled in D1/2 */
-+#define DxPLL2_ENABLE 0x00000004UL /* PLL2 can be enabled in D1/2 */
-+#define DxPLL3_ENABLE 0x00000008UL /* PLL3 can be enabled in D1/2 */
-+#define DxMIU_ENABLE 0x00000010UL /* MIU can be enabled in D1/2 */
-+#define DxMEM_REFRESH 0x00000020UL /* Memory is refreshed in D1/2 */
-+#define DxGE_ENABLE 0x00000040UL /* GE can be enabled in D1/2 */
-+#define DxCRT_ENABLE 0x00000100UL /* CRT can be enabled in D1/2 */
-+#define DxFP_ENABLE 0x00000200UL /* Flat panel can be enabled in D1/2 */
-+#define DxGC1_ENABLE 0x00010000UL /* GC1 can be enabled in D1/2 */
-+#define DxW1_ENABLE 0x00020000UL /* Window 1 can be enabled in D1/2 */
-+#define DxAW1_ENABLE 0x00040000UL /* Alt window 1 enabled in D1/2 */
-+#define DxHC1_ENABLE 0x00080000UL /* Cursor 1 enabled in D1/2 */
-+#define DxGC2_ENABLE 0x01000000UL /* GC2 can be enabled in D1/2 */
-+#define DxW2_ENABLE 0x02000000UL /* Window 2 can be enabled in D1/2 */
-+#define DxAW2_ENABLE 0x04000000UL /* Alt window 2 enabled in D1/2 */
-+#define DxHC2_ENABLE 0x08000000UL /* Cursor 2 enabled in D1/2 */
-+
-+/* PLL2_CONTROL/PLL3_CONTROL */
-+#define PLL_FROM_OSC 0x00000000UL /* PLL2/3 ref clock from OSCCLK */
-+#define PLL_FROM_PxCLK 0x00000001UL /* PLL2/3 ref clock from P2CLK */
-+#define PLL_BYPASSED 0x00000002UL /* PLL2/3 is bypassed */
-+#define PLL_DIVBY1 0x00000000UL /* PLL2/3 P output divisor by 1 */
-+#define PLL_DIVBY2 0x00000010UL /* PLL2/3 P output divisor by 2 */
-+#define PLL_DIVBY4 0x00000020UL /* PLL2/3 P output divisor by 4 */
-+#define PLL_DIVBY8 0x00000030UL /* PLL2/3 P output divisor by 8 */
-+#define PLL_DIVBY16 0x00000040UL /* PLL2/3 P output divisor by 16 */
-+#define PLL_DIV_MASK 0x00000070UL /* PLL2/3 P output divisor mask */
-+
-+/* CPU Interface Registers */
-+#define CPU_CONTROL (CC_BASE + 0x00) /* CPU control register */
-+#define DRAW_STATUS (CC_BASE + 0x04) /* Drawing status register */
-+
-+/* CPU_CONTROL */
-+#define SW_RESET 0x00000002UL /* Reset all modules except CIF */
-+#define MIU_READ_REQ 0x00000004UL /* MIU read request */
-+#define CLKRUN_ENABLE 0x00000008UL /* CLKRUN enabled. On Pwr-on, disab. */
-+
-+/* DRAW_STATUS */
-+#define CMD_FIFO_MASK 0x0000001fUL /* Command FIFO entries mask */
-+#define SRC_FIFO_MASK 0x00000f00UL /* Source FIFO entry mask */
-+#define GE_BUSY 0x00010000UL /* Any command in Comm FIFO */
-+#define CMD_FIFO_FULL 0x00000000UL /* Cmd fifo full bit */
-+#define CMD_FIFO_EMPTY 0x00000010UL /* Cmd fifo empty, 16x32 bits free */
-+#define SRC_FIFO_FULL 0x00000000UL /* Src fifo full bit */
-+#define SRC_FIFO_EMPTY 0x00000800UL /* Src fifo empty, 8x128 bits free */
-+
-+#define CMD_FIFO_CNT 16 /* Command FIFO full entry */
-+#define CMD_FIFO_MAX_INDEX 64
-+#define SRC_FIFO_MAX_BYTES 128 /* max pixels in src fifo - 8bits */
-+#define SRC_FIFO_MAX_WORDS 64 /* max pixels in src fifo - 16bits */
-+#define SRC_FIFO_MAX_DWORDS 32 /* max dwords in src fifo - 32bits */
-+
-+/* MIU (Memory Interface Unit) Registers */
-+#define MIU_CONTROL1 (MM_BASE + 0x00) /* Memory interface control 1 */
-+#define MIU_CONTROL2 (MM_BASE + 0x04) /* Memory interface control 2 */
-+#define MIU_CONTROL3 (MM_BASE + 0x08) /* Memory interface control 3 */
-+#define MIU_CONTROL4 (MM_BASE + 0x0C) /* Memory interface control 4 */
-+#define MIU_CONTROL5 (MM_BASE + 0x10) /* Memory interface control 5 */
-+
-+/* MIU_CONTROL1 */
-+#define MIU_ENABLE 0x00000001UL /* Enable MIU */
-+#define MIU_RESET_DISABLE 0x00000002UL /* MIU reset is disabled */
-+#define DRAM_RESET_DISABLE 0x00000004UL /* DRAM reset is disabled */
-+
-+/* MIU_CONTROL2 */
-+#define CLK_FROM_BUS 0x00000001UL /* Bus clk for mem clk src */
-+#define CLK_FROM_PLL2 0x00000001UL /* PLL2 for mem clock source */
-+#define MEM_REFRESH_ENABLE 0x00000002UL /* Mem ref disab at pwr dw mod*/
-+#define CPU_PB_ENABLE 0x00000004UL /* Page Break enab after CPU mem cyc */
-+#define GC1_PB_ENABLE 0x00000008UL /* Page Break after GC1 mem cycles */
-+#define GC2_PB_ENABLE 0x00000010UL /* Page Break after GC2 mem cycles */
-+#define STN_R_PB_ENABLE 0x00000020UL /* Page Break after STN read mem cyc */
-+#define STN_W_PB_ENABLE 0x00000040UL /* Page Break after STN wr. mem cyc */
-+#define GE_PB_ENABLE 0x00000080UL /* Page Break after GE memory cycles */
-+#define AUTO_REF_ENABLE 0x40000000UL /* Standby sig enab. when MIU active */
-+#define STANDBY_ENABLE 0x80000000UL /* Standby sig enab. when MIU active */
-+
-+/* MIU_CONTROL3 */
-+#define DISPLAY_BURST2 0x00000000UL /* Burst size for disp mem refresh */
-+#define DISPLAY_BURST4 0x00000001UL
-+#define DISPLAY_BURST6 0x00000002UL
-+#define DISPLAY_BURST8 0x00000003UL
-+#define STN_R_BURST2 0x00000000UL /* Burst size for STN read mem cycle */
-+#define STN_R_BURST4 0x00000004UL
-+#define STN_R_BURST6 0x00000008UL
-+#define STN_R_BURST8 0x0000000cUL
-+#define STN_W_BURST2 0x00000000UL /* Burst size for STN write mem cyc */
-+#define STN_W_BURST4 0x00000010UL
-+#define STN_W_BURST6 0x00000020UL
-+#define STN_W_BURST8 0x00000030UL
-+#define GE_RW_BURST2 0x00000000UL /* Burst size for GE r/w mem cycle */
-+#define GE_RW_BURST4 0x00000040UL
-+#define GE_RW_BURST6 0x00000080UL
-+#define GE_RW_BURST8 0x000000c0UL
-+#define CPU_RW_BURST2 0x00000000UL /* Burst size for CPU r/w mem cycle */
-+#define CPU_RW_BURST4 0x00000100UL
-+#define CPU_RW_BURST6 0x00000200UL
-+#define CPU_RW_BURST8 0x00000300UL
-+
-+/* MIU_CONTROL4 */
-+#define R_LATENCY_REQUEST 0x00000001UL /* Read Latency Request */
-+
-+/* MIU_CONTROL5 */
-+#define LATENCY_1 0x00000001UL /* EDRAM Latency 1 */
-+#define LATENCY_2 0x00000005UL /* EDRAM Latency 2 */
-+#define LATENCY_3 0x00000007UL /* EDRAM Latency 3 */
-+#define DUMMY_IN_COMMANDS 0x00000008UL /* Dummy cycle insertion betw cmds */
-+#define DUMMY_IN_PRECHARGE 0x00000010UL /* Dummy cyc between precharge cyc */
-+#define DELAY_1ns 0x00000000UL /* Internal memory clock delay */
-+#define ACT_TO_CLOSE_3 0x00000100UL /* Bank activate to close - 3 mclk */
-+#define ACT_TO_CLOSE_4 0x00000200UL /* Bank activate to close - 4 mclk */
-+#define ACT_TO_CLOSE_5 0x00000300UL /* Bank activate to close - 5 mclk */
-+#define ACT_TO_COMMAND_2 0x00000000UL /* Bank activate to cmd r/w - 2 mclk */
-+#define ACT_TO_COMMAND_3 0x00000400UL /* Bank activate to cmd r/w - 3 mclk */
-+#define CLOSE_TO_ACT_2 0x00000000UL /* Bank close to activate - 2 mclk */
-+#define CLOSE_TO_ACT_3 0x00000800UL /* Bank close to activate - 3 mclk */
-+#define ROW_CYCLE_6 0x00000000UL /* Row Cycle time - 6 memory clock */
-+#define ROW_CYCLE_8 0x00001000UL /* Row Cycle time - 8 memory clock */
-+#define DELAY_R_CLOCK_0_0 0x00000000UL /* Delay for read clock - no delay */
-+#define DELAY_R_CLOCK_0_5 0x00010000UL /* Delay for read clock - 0.5ns */
-+#define DELAY_R_CLOCK_1_0 0x00020000UL /* Delay for read clock - 1.0ns */
-+#define DELAY_R_CLOCK_1_5 0x00030000UL /* Delay for read clock - 1.5ns */
-+#define DELAY_M_CLOCK_0_0 0x00000000UL /* Delay for memory clock - no delay */
-+#define DELAY_M_CLOCK_0_5 0x00020000UL /* Delay for memory clock - 0.5ns */
-+#define DELAY_M_CLOCK_1_0 0x00080000UL /* Delay for memory clock - 1.0ns */
-+#define DELAY_M_CLOCK_1_5 0x000c0000UL /* Delay for memory clock - 1.5ns */
-+
-+
-+/*
-+ * Data structure and defines for MQ chip and driver interface
-+ */
-+
-+/* Display configuration structure - for interface */
-+typedef struct DisplayConfig
-+{
-+ int x; /* x resolution */
-+ int y; /* y resolution */
-+ int bpp; /* color depth */
-+ int refresh; /* CRT refresh rate */
-+ int stride; /* memory stride */
-+ unsigned long flag; /* display flag */
-+} DISPLAY_CONFIG, *PDISPLAY_CONFIG;
-+
-+/* Flag definition */
-+#define PANEL_TYPE_MASK 0x000000ff /* Panel type mask */
-+#define PROCESSOR_MASK 0x00003f00 /* Mask of processor type */
-+#define IS_SH3 0x00000000
-+#define IS_SH4 0x00000100
-+#define IS_NEC 0x00000200
-+#define IS_SARM 0x00000300
-+#define IS_TOSHIBA 0x00000400
-+#define IS_PCI 0x00000500
-+#define LCD_ON 0x00010000 /* LCD mode */
-+#define CRT_ON 0x00020000 /* CRT mode */
-+#define LARGE_DESKTOP 0x00040000 /* Large desktop mode is on */
-+#define INDEP_DISPLAY 0x00080000 /* Independent display */
-+#define SAME_IMAGE 0x00100000 /* Use 2 GC but same image */
-+#define USE_2GCs 0x001C0000 /* 2 GCs are used */
-+#define USE_2GCs_MASK 0x001C0000 /* mask for 2 GCs */
-+#define ENA_HW_CURSOR 0x00200000 /* Enable hw cursor */
-+#define HORI_LCD_CRT 0x00000000 /* QView hori arrangement */
-+#define HORI_CRT_LCD 0x10000000 /* QView hori arrangement */
-+#define VERT_CRT_LCD 0x20000000 /* QView vert arrangement */
-+#define VERT_LCD_CRT 0x30000000 /* QView vert arrangement */
-+#define LCDCRT_POS_MASK 0x30000000 /* mask for QV orientation */
-+
-+/* Display timing structure */
-+typedef struct DisplayTiming
-+{
-+ int x; /* x resolution */
-+ int y; /* y resolution */
-+ int refresh; /* refresh rate */
-+ unsigned long hd; /* hori display control */
-+ unsigned long vd; /* vert display control */
-+ unsigned long hs; /* hori sync control */
-+ unsigned long vs; /* vert sync control */
-+ unsigned long crtc; /* crt control */
-+ unsigned long pll; /* PLL2 or PLL3 setting */
-+} DISPLAY_TIMING, *PDISPLAY_TIMING;
-+
-+/* Flat panel register */
-+typedef struct FPControl
-+{
-+ int x; /* panel size x */
-+ int y; /* panel size y */
-+ int freq; /* panel freq */
-+ unsigned long fpControl; /* flat panel control */
-+ unsigned long fpPinControl; /* flat panel pin control */
-+ unsigned long stnControl; /* stn panel control */
-+} FPDATA_CONTROL, *PFPDATA_CONTROL;
-+
-+/* Frame rate control */
-+#define FRC_PATTERN_CNT 32
-+#define FRC_WEIGHT_CNT 8
-+typedef struct FRCControl
-+{
-+ ULONG frcPattern[FRC_PATTERN_CNT]; /* FRC pattern control */
-+ ULONG frcWeight[FRC_WEIGHT_CNT]; /* FRC weight control */
-+} FRC_CONTROL, *PFRC_CONTROL;
-+
-+/* Miscellaneous defines */
-+#define IS_GC1 1
-+#define IS_GC2 2
-+
-+/* Turn on/off display */
-+#define ENABLE_LCD_GC1 0
-+#define ENABLE_LCD_GC2 1
-+#define DISABLE_LCD_GC1 2
-+#define DISABLE_LCD_GC2 3
-+#define ENABLE_CRT_GC1 4
-+#define ENABLE_CRT_GC2 5
-+#define DISABLE_CRT_GC1 6
-+#define DISABLE_CRT_GC2 7
-+
-+/*
-+ * Handy macro
-+ *
-+ */
-+/*
-+#define CHECK_IF_STATE_D(s) {\
-+ unsigned long ulState = (s);\
-+ unsigned long ulPMReg;\
-+ while(1)\
-+ {\
-+ ulPMReg = READ32(PCI_PM_CNTL_STATUS);\
-+ if((ulPMReg &0x03) == ulState)\
-+ break;\
-+ } }
-+*/
-+#endif /* _VIDEO_MQ200_MQ2HW_H */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mqdata.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,754 @@
-+/***************************************************************************
-+ MQDATA.C
-+
-+ This file contains timing and flat panel parameters for MediaQ graphics
-+ chip.
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQDATA_H
-+#define _VIDEO_MQ200_MQDATA_H
-+/* LCD/CRT timing parameters for each resolution - VESA modes
-+ *
-+ * . the first entry is reserved to provide customized panel timing support
-+ * . OEM can fill in proper timing for non-VESA LCD (or CRT)
-+ *
-+ */
-+DISPLAY_TIMING TimingParam[] =
-+{
-+ { /* customized refresh rate - reserved for non-VESA panel timing */
-+ 0,0,0, /* X/Y/Freq */
-+ 0, /* HD Total + HD End */
-+ 0, /* VD Total + VD End */
-+ 0, /* HS Start + HS End */
-+ 0, /* VS Start + VS End */
-+ 0x00000000, /* CRT control */
-+ 0x00000000, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 240 90Hz (25.175 MHz) */
-+ 640,240,90, /* X/Y/Freq */
-+ (793-2) | (640L << 16), /* HD Total + HD End */
-+ (262-1) | ((240L-1) << 16), /* VD Total + VD End */
-+ 647 | (704L << 16), /* HS Start + HS End */
-+ 245 | (246L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00a30930, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 60Hz (25.175 MHz) */
-+ 640,480,60, /* X/Y/Freq */
-+ (800-2) | (640L << 16), /* HD Total + HD End */
-+ (525-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 656 | (752L << 16), /* HS Start + HS End */
-+ 490 | (492L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00a30930, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 72Hz (31.5 MHz) */
-+ 640,480,72, /* X/Y/Freq */
-+ (832-2) | (640L << 16), /* HD Total + HD End */
-+ (520-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 688 | (728L << 16), /* HS Start + HS End */
-+ 489 | (492L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f50b30, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 75Hz (31.5 MHz) */
-+ 640,480,75, /* X/Y/Freq */
-+ (840-2) | (640L << 16), /* HD Total + HD End */
-+ (500-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 680 | (744L << 16), /* HS Start + HS End */
-+ 481 | (484L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f50b30, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 85Hz (36 MHz) */
-+ 640,480,85, /* X/Y/Freq */
-+ (832-2) | (640L << 16), /* HD Total + HD End */
-+ (509-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 696 | (752L << 16), /* HS Start + HS End */
-+ 481 | (484L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00d20830, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 60Hz (40 MHz) */
-+ 800,600,60, /* X/Y/Freq */
-+ (1056-2) | (800L << 16), /* HD Total + HD End */
-+ (628-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 839 | (967L << 16), /* HS Start + HS End */
-+ 601 | (605L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00e90830, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 72Hz 50 MHz) */
-+ 800,600,72, /* X/Y/Freq */
-+ (1040-2) | (800L << 16), /* HD Total + HD End */
-+ (666-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 856 | (976L << 16), /* HS Start + HS End */
-+ 637 | (643L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00b20a20, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 75Hz (49.5 MHz) */
-+ 800,600,75, /* X/Y/Freq */
-+ (1056-2) | (800L << 16), /* HD Total + HD End */
-+ (625-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 816 | (896L << 16), /* HS Start + HS End */
-+ 601 | (604L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00900820, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 85Hz (56.25 MHz) */
-+ 800,600,85, /* X/Y/Freq */
-+ (1047-2) | (800L << 16), /* HD Total + HD End */
-+ (631-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 832 | (896L << 16), /* HS Start + HS End */
-+ 601 | (604L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00b60920, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 60Hz (65 MHz) */
-+ 1024,768,60, /* X/Y/Freq */
-+ (1344-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1048 | (1184L << 16), /* HS Start + HS End */
-+ 771 | (777L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00fd0b20, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 70Hz (75 MHz) */
-+ 1024,768,70, /* X/Y/Freq */
-+ (1327-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1047 | (1183L << 16), /* HS Start + HS End */
-+ 771 | (777L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f30920, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 75Hz (78.750 MHz) */
-+ 1024,768,75, /* X/Y/Freq */
-+ (1312-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1040 | (1136L << 16), /* HS Start + HS End */
-+ 769 | (772L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00cc0720, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 85Hz (94.5 MHz) */
-+ 1024,768,85, /* X/Y/Freq */
-+ (1375-2) | (1024L << 16), /* HD Total + HD End */
-+ (808-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1072 | (1168L << 16), /* HS Start + HS End */
-+ 769 | (772L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x007a0710, /* PLLx multiplier and control */
-+ }
-+};
-+#define MAX_MQMODE (sizeof(TimingParam) / sizeof(TimingParam[0]))
-+
-+/* Flat panel control registers
-+ */
-+FPDATA_CONTROL fpControlData[] =
-+{
-+ /* Type 0 : OEM Specific panel
-+ */
-+ { /* Flat panel info */
-+ 0, 0, 0,
-+
-+ /* Flat panel Control */
-+ 0
-+ ,
-+
-+ /* Flat panel pin control */
-+ 0
-+ ,
-+
-+ /* STN panel control */
-+ 0x0
-+ },
-+ /* Type 1 : SSTN VGA 8Bit Color - 72Hz
-+ * - Sanyo SSTN 640x480 8-bit color interface
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 2 : DSTN 16 Bit VGA Color - 72Hz
-+ * - Hitachi 8.2" SX21V001
-+ * - Sanyo 10.4" LM-CJ53-22NTK
-+ * - Sharp 10.4" LM64C35P
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 3 : TFT 18 Bit VGA - 60Hz
-+ * - NEC 10.4" NL6448AC33-24
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 4 : TFT 18 Bit SVGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 5 : DSTN 16Bit SVGA Color Panel - 72Hz
-+ * - Hitachi 10.0" SX25S001
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 6 : DSTN 8 Bit VGA Color - 72Hz
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 7 : SSTN VGA 16Bit Color - 72Hz
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 8 : SSTN VGA 8Bit Color - 60Hz
-+ * - Sanyo SSTN 640x480 8-bit color interface
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 9 : DSTN 16 Bit VGA Color - 60Hz
-+ * - Hitachi 8.2" SX21V001
-+ * - Sanyo 10.4" LM-CJ53-22NTK
-+ * - Sharp 10.4" LM64C35P
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_1
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 10 : DSTN 16Bit SVGA Color Panel - 60Hz
-+ * - Hitachi 10.0" SX25S001
-+ * - Hitachi 12.1" SX25S003
-+ * - Sanyo LM-FC53-22NTK
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+#if 1
-+ 0x0C1B4128
-+#else
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0C840000
-+#endif
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 11 : DSTN 24Bit XGA Color Panel - 60Hz
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_24BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 12 : DSTN 16Bit XGA Color Panel - 60Hz
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 13 : TFT 18Bit XGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 14 : TFT 24Bit XGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_24BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 15 : TFT 18 Bit SVGA - 60Hz (Similar to type 4)
-+ * - NEC 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel control */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ | FSCLK_ACTIVE_L
-+ | FSCLK_DELAY
-+ ,
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 16 : SSTN VGA 8Bit Color - 90Hz
-+ * - Sharp LM8M64 SSTN 640x240 8-bit color interface
-+ */
-+ { /* Flat panel control */
-+ 640, 240, 90,
-+
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_1
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ }
-+};
-+
-+/* Flat panel FRC weight/pattern registers - for SSTN and DSTN panel only
-+ *
-+ */
-+FRC_CONTROL FRCControlData[] =
-+{
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0x0E3D5C61,
-+ 0xF87A429B,
-+ 0x4A791825,
-+ 0xBC3E06DF,
-+ 0xC2F190AD,
-+ 0x34B68E57,
-+ 0x86B5D4E9,
-+ 0x70F2CA13,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0x685B3A07,
-+ 0x9E1C24FD,
-+ 0x2C1F7E43,
-+ 0xDA5860B9,
-+ 0xA497F6CB,
-+ 0x52D0E831,
-+ 0xE0D3B28F,
-+ 0x1694AC75,
-+ },
-+
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ },
-+
-+ /* FRC Pattern Data - 2FCA (for SSTN) */
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x4A791825,
-+ 0xBC3E06DF,
-+ 0x0E3D5C61,
-+ 0xF87A429B,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0x2C1F7E43,
-+ 0xDA5860B9,
-+ 0x685B3A07,
-+ 0x9E1C24FD,
-+ 0xE0D3B28F,
-+ 0x1694AC75,
-+ 0xA497F6CB,
-+ 0x52D0E831,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0x86B5D4E9,
-+ 0x70F2CA13,
-+ 0xC2F190AD,
-+ 0x34B68E57,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ },
-+
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ },
-+
-+ /* FRC Pattern Data - (for Panletype 4-> Simpad) */
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ },
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ }
-+};
-+#endif /* _VIDEO_MQ200_MQDATA_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mqmacros.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,86 @@
-+#ifndef _VIDEO_MQ200_MQMACROS_H
-+#define _VIDEO_MQ200_MQMACROS_H
-+
-+#ifdef CHECK_SRCFIFO
-+
-+#define PUMP_PACKED_SRCFIFO(pSrcData,srcStride,nDwords,height,extras) \
-+ { \
-+ u32 *pData; \
-+ u32 i,j; \
-+ while( height-- ) \
-+ { \
-+ pData = (u32 *)((u32)(pSrcData + 3UL) & ~0x03UL); \
-+ j = nDwords; \
-+ while ( j >= SRC_FIFO_MAX_DWORDS ) \
-+ { \
-+ geWAITSRCFIFO( SRC_FIFO_MAX_DWORDS ); \
-+ for ( i = 0; i < SRC_FIFO_MAX_DWORDS; i++ ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ j -= SRC_FIFO_MAX_DWORDS; \
-+ } \
-+ geWAITSRCFIFO( j ); \
-+ while( j-- ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ pSrcData += srcStride; \
-+ } \
-+ geWAITSRCFIFO( extras ); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+
-+#define PUMP_REAL_PACKED_SRCFIFO(pSrcData,nDwords,extras) \
-+ { \
-+ u32 *pData =(u32 *)pSrcData; \
-+ u32 i; \
-+ while(nDwords) \
-+ { \
-+ if (nDwords >= SRC_FIFO_MAX_DWORDS) \
-+ { \
-+ geWAITSRCFIFO( SRC_FIFO_MAX_DWORDS ); \
-+ for (i = SRC_FIFO_MAX_DWORDS; i > 0; i--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ nDwords -= SRC_FIFO_MAX_DWORDS; \
-+ } \
-+ else \
-+ { \
-+ geWAITSRCFIFO( nDwords ); \
-+ for (i = nDwords; i > 0; i--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ nDwords -= nDwords; \
-+ } \
-+ } \
-+ geWAITSRCFIFO(extras); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#else /* CHECK_SRCFIFO */
-+
-+#define PUMP_PACKED_SRCFIFO(pSrcData,srcStride,nDwords,height,extras) \
-+ { \
-+ u32 *pData; \
-+ u32 i; \
-+ while( height-- ) \
-+ { \
-+ pData = (u32 *)((u32)(pSrcData + 3UL) & ~0x03UL); \
-+ for ( i = 0; i < nDwords; i++ ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ pSrcData += srcStride; \
-+ } \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#define PUMP_REAL_PACKED_SRCFIFO(pSrcData,nDwords,extras) \
-+ { \
-+ u32 *pData =(u32 *)pSrcData; \
-+ while(nDwords--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#endif
-+
-+#endif /* _VIDEO_MQ200_MQMACROS_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mqplat.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,106 @@
-+/***************************************************************************
-+ MQPLAT.H
-+
-+ MQ200 platform, system or OS specific header file
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQPLAT_H
-+#define _VIDEO_MQ200_MQPLAT_H
-+
-+/* OS variation - ONLY define one */
-+#undef MQ_VXWORKS
-+#undef MQ_EPOC32
-+#undef MQ_WINCE
-+#undef MQ_OS9
-+#define MQ_LINUX
-+
-+/* CPU variation - ONLY define one */
-+#undef MQ_X86
-+#define MQ_SA1110
-+#undef MQ_MIPS_NEC
-+#undef MQ_MIPS_TOSHIBA
-+#undef MQ_SH4
-+
-+/* PCI support - undef accordingly */
-+#undef MQ_PCI
-+#ifdef MQ_PCI
-+ #warning "MQ200 driver compiled for PCI !"
-+#endif
-+
-+/* Derived equates from CPU type */
-+#ifdef MQ_SHx
-+ #warning "MQ200 driver compiled for SHx !"
-+ #define FB_BASE 0x93800000L /* MQ200 frame buffer adddr */
-+#endif
-+
-+#ifdef MQ_MIPS_NEC
-+ #warning "MQ200 driver compiled for NEC MIPS !"
-+ #define CHECK_FIFO_REQUIRED /* GE fifo checking required */
-+ #define FB_BASE 0xAA000000L
-+
-+ #ifdef MQ_PCI
-+ #define IOREGS_BASE 0xAF000000L /* for VR4122 */
-+ #define IOREGS_SIZE 0x00002000L
-+ #else
-+ #define IOREGS_BASE 0xAB000000L /* for VR 4111/21 */
-+ #define IOREGS_SIZE 0x00001000L
-+ #define CHECK_NOTBUSY /* Needed for NEC MIPS */
-+ #define CHECK_CMDFIFO /* Needed for NEC MIPS */
-+ #endif /* MQ_PCI */
-+#endif
-+
-+#ifdef MQ_MIPS_TOSHIBA
-+ #warning "MQ200 driver compiled for TOSHIBA MIPS !"
-+ #define FB_BASE 0x6D800000L
-+#endif
-+
-+#ifdef MQ_SA1110
-+ #warning "MQ200 driver compiled for Intel SA1110 !"
-+ #define FB_BASE_CS3 0x1b800000L /* configured as CS3 */
-+ #define FB_BASE_CS4 0x43800000L /* configured as CS4 */
-+#define FB_BASE_CS5 0x4b800000L /* configured as CS5 */
-+#define FB_BASE FB_BASE_CS5 /* change accordingly! */
-+#define REGISTER_BASE 0x4be00000L
-+#endif
-+
-+/* OS-derived misc defines */
-+#ifdef MQ_VXWORKS
-+ #warning "MQ200 driver compiled for VxWorks !"
-+ #define MQ_DELAY(cnt) taskDelay(cnt*30);
-+ #define MQ_COLOR_RGB /* Color (32bit):ARGB */
-+#endif
-+
-+#ifdef MQ_WINCE
-+ #warning "MQ200 driver compiled for Window CE !"
-+ #define MQ_DELAY(cnt) Sleep(cnt)
-+#endif
-+
-+#ifdef MQ_LINUX
-+ #warning "MQ200 driver compiled for Linux !"
-+/* #define MQ_DELAY(cnt) {volatile int delay; for (delay=0; delay<10000*cnt; delay++); } */
-+
-+#define MQ_DELAY(cnt) mdelay(cnt * 10)
-+#endif
-+
-+/* Further derivation
-+#ifdef MQ_COLOR_RGB
-+ #define GETR(color) (unsigned char)(color >> 16)
-+ #define GETG(color) (unsigned char)((unsigned short)(color) >> 8)
-+ #define GETB(color) (unsigned char)(color)
-+ #define MAKERGB(r,g,b) ((unsigned long)(((unsigned char)(r)|\
-+ ((unsigned short)((unsigned char)(g))<<8))|\
-+ (((unsigned long)(unsigned char)(b))<<16)))
-+#endif
-+*/
-+
-+/* Cursor color */
-+#ifndef CURSOR_FGCLR
-+ #define CURSOR_FGCLR 0x0000FFFF /* Yellow */
-+#endif
-+#ifndef CURSOR_BGCLR
-+ #define CURSOR_BGCLR 0x00000000 /* Black */
-+#endif
-+#endif /* _VIDEO_MQ200_MQPLAT_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/MQ200/mqproto.h 2004-05-02 22:45:42.000000000 +0200
-@@ -0,0 +1,19 @@
-+/***************************************************************************
-+ MQPROTO.H
-+
-+ MQ200 common function prototypes
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef MQPROTO_H
-+#define MQPROTO_H
-+
-+/*
-+ * mqdata.h
-+ */
-+extern FPDATA_CONTROL fpControlData[];
-+extern DISPLAY_TIMING TimingParam[];
-+
-+#endif /* MQPROTO_H */
---- linux-2.4.25/init/do_mounts.c~2.4.25-vrs2-pxa1-jpm1.patch 2004-05-02 22:45:40.000000000 +0200
-+++ linux-2.4.25/init/do_mounts.c 2004-05-02 22:45:42.000000000 +0200
-@@ -789,7 +789,13 @@
- return;
- }
- printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
-+#ifdef CONFIG_SA1100_SIMPAD
-+ /* no floppy -> cramfs */
-+ printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying cramfs.\n");
-+ ROOT_DEV = MKDEV(31, 2);
-+#else
- ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-+#endif
- }
- #endif
- devfs_make_root(root_device_name);
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1.patch
deleted file mode 100644
index 512fb6d3fc..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2-pxa1.patch
+++ /dev/null
@@ -1,39937 +0,0 @@
-
-#
-# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
-#
-
---- linux-2.4.25/Documentation/Configure.help~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/Documentation/Configure.help 2004-03-31 17:15:11.000000000 +0200
-@@ -4526,6 +4526,24 @@
- building a kernel for install/rescue disks or your system is very
- limited in memory.
-
-+Kernel Execute-In-Place from ROM
-+CONFIG_XIP_KERNEL
-+ Execute-In-Place allows the kernel to run directly from
-+ non-volatile storage, such as flash. This saves RAM space since
-+ the text section of the kernel is not loaded from flash to
-+ RAM. Read-write sections, such as the data section and stack,
-+ are still copied to RAM. The XIP kernel is not compressed since it
-+ has to run directly from flash, so it will take more space to store
-+ it. The flash address where the kernel is linked to run from and
-+ is stored is board dependent. Therefore, if you say Y, you must
-+ know the proper physical address where to store the kernel image.
-+
-+ Also note that the make target becomes "make xipImage" rather than
-+ "make zImage" or "make Image". The final kernel binary to put in
-+ ROM memory will be arch/arm/boot/xipImage.
-+
-+ If unsure, say N.
-+
- # Choice: kcore
- Kernel core (/proc/kcore) format
- CONFIG_KCORE_ELF
-@@ -13386,6 +13404,30 @@
-
- If you don't know what this all is, saying Y is a safe choice.
-
-+Workaround for XScale cache errata
-+CONFIG_XSCALE_CACHE_ERRATA
-+ There are couple errata that say that the cache may get confused
-+ whether some cache lines are dirty or not, resulting in some memory
-+ corruptions. The workaround (using the cache only in write through
-+ mode) is performance impairing, and the bug _might_ just not be
-+ that visible or critical to you depending on many esoteric
-+ hardware factors.
-+
-+ Not using the workaround makes Linux unreliable. If you're used
-+ to some other OSes which requires to be rebooted once in a while
-+ then this won't look so bad to you. On the other hand you may
-+ stress test the system for hours without seeing any effect of this
-+ bug.
-+
-+ So this is configurable. Let's hope a future core revision will tell
-+ this was just a bad dream. But in the mean time the risk and
-+ trade-off is yours to decide.
-+
-+ This should apply to all PXA250 up to rev B2 (erratum #120) and
-+ possibly other current XScale cores as well.
-+
-+ If you don't know what to answer, say Y.
-+
- Support CD-ROM drives that are not SCSI or IDE/ATAPI
- CONFIG_CD_NO_IDESCSI
- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
-@@ -16568,6 +16610,40 @@
-
- If unsure, say N.
-
-+Use linear addressing for cramfs
-+CONFIG_CRAMFS_LINEAR
-+ This option tells the cramfs driver to load data directly from a linear
-+ adressed memory range (usually non volatile memory like flash) instead
-+ of going through the block device layer. This saves some memory since
-+ no intermediate buffering is necessary.
-+
-+ This is also a prerequisite for XIP of binaries stored on the filesystem.
-+
-+ The location of the cramfs image in memory is board dependent. Therefore,
-+ if you say Y, you must know the proper physical address where to store
-+ the cramfs image and specify it using the physaddr=0x******** mount
-+ option (for example: "mount -t cramfs -o physaddr=0x100000 none /mnt").
-+
-+ If unsure, say N.
-+
-+Support XIP on linear cramfs
-+CONFIG_CRAMFS_LINEAR_XIP
-+ You must say Y to this option if you want to be able to run applications
-+ directly from non-volatile memory. XIP applications are marked by
-+ setting the sticky bit (ie, "chmod +t <app name>"). A cramfs file system
-+ then needs to be created using mkcramfs (with XIP cramfs support
-+ in it). Applications marked for XIP execution will not be compressed
-+ since they have to run directly from flash.
-+
-+Root file system on linear cramfs
-+CONFIG_ROOT_CRAMFS_LINEAR
-+ Say Y if you have enabled linear cramfs, and you want to be able to use
-+ the linear cramfs image as a root file system. To actually have the
-+ kernel mount this cramfs image as a root file system, you must also pass
-+ the command line parameter "root=/dev/null rootflags=physaddr=0x********"
-+ to the kernel (replace 0x******** with the physical address location
-+ of the linear cramfs image to boot with).
-+
- CMS file system support
- CONFIG_CMS_FS
- Read only support for CMS minidisk file systems found on IBM
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/arm/XScale/PXA/USB-client 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,38 @@
-+Date: Wed, 05 Jun 2002 13:38:53 -0700
-+From: Frank Becker <fbecker@intrinsyc.com>
-+To: Nicolas Pitre <nico@cam.org>
-+Subject: [PATCH] PXA-USB
-+
-+Hi Nicolas,
-+
-+one more patch...
-+
-+This patch adds minimal USB client (UDC) support.
-+
-+Some notes:
-+It adds just enough to get usb-eth working. I.e.
-+endpoints 0-2, no dma. Performance isn't stellar
-+partially due to UDC bug workarounds...
-+(~350K @ 100Mhz, ~550K @ 200Mhz).
-+
-+Endpoint 1&2 have changed direction compared to
-+the SA, so the host side requires a change to
-+usbnet.c to flip endpoints (in:2/out:1 -> in:1/out:2).
-+
-+usb-eth and usb-char for PXA are almost identical
-+to the SA versions, so they could probably be merged at
-+one point. I made some minor changes to the eth driver
-+to grab the usb resources at open, rather than at init
-+and allow eth&char to be loaded at the same time.
-+
-+Stuart Lynne was working on his own USB client driver
-+(and he was getting higher throughput than my driver).
-+Assuming you guys have something in the oven for USB
-+as well, there should be good selection for best of
-+breed :)
-+
-+Cheers,
-+Frank.
-+--
-+Frank Becker - Intrinsyc Software, Inc. - http://www.intrinsyc.com/
-+Need a break? http://criticalmass.sf.net/
---- linux-2.4.25/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -1,11 +1,13 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 25
--EXTRAVERSION =-vrs2
-+EXTRAVERSION =-vrs2-pxa1
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
--ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-+#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-+ARCH := arm
-+
- KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
-
- CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
-@@ -19,7 +21,7 @@
- HOSTCC = gcc
- HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
-
--CROSS_COMPILE =
-+CROSS_COMPILE = arm-linux-
-
- #
- # Include the make variables (CC, etc...)
-@@ -168,6 +170,7 @@
- DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
- DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
- DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
-+DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmcdrivers.o
- DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o
- DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o
- DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o
---- linux-2.4.25/arch/arm/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/arch/arm/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -13,10 +13,11 @@
- CFLAGS +=-Uarm -fno-common -pipe
-
- ifeq ($(CONFIG_FRAME_POINTER),y)
--CFLAGS :=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog)
-+CFLAGS :=$(CFLAGS:-fomit-frame-pointer=)
-+CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
- endif
-
--CFLAGS :=$(CFLAGS:-O2=-Os)
-+#CFLAGS :=$(CFLAGS:-O2=-Os)
-
- ifeq ($(CONFIG_DEBUG_INFO),y)
- CFLAGS +=-g
-@@ -38,6 +39,8 @@
- arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
- arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
- arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5
-+#arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -mcpu=xscale
-+arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mcpu=xscale
-
- # This selects how we optimise for the processor.
- tune-y :=
-@@ -49,6 +52,8 @@
- tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
- tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
-+tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale
-+#tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm
-
- CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
- CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
-@@ -127,6 +132,10 @@
- MACHINE = sa1100
- endif
-
-+ifeq ($(CONFIG_ARCH_PXA),y)
-+MACHINE = pxa
-+endif
-+
- ifeq ($(CONFIG_ARCH_L7200),y)
- MACHINE = l7200
- endif
-@@ -164,6 +173,17 @@
- MACHINE = omaha
- endif
-
-+ifeq ($(CONFIG_XIP_KERNEL),y)
-+ DATAADDR := $(TEXTADDR)
-+ # Replace phys addr with virt addr while keeping offset from base.
-+ # Virt base addr also defined in include/asm-arm/arch-*/hardware.h
-+ TEXTADDR = $(shell echo 0x`echo $(CONFIG_XIP_PHYS_ADDR)|sed -e's/^0x//'` |\
-+ awk --non-decimal-data '/[:xdigit:]/ \
-+ {printf("0x%x\n",and($$0,0x001fffff)+0xe8000000)}' )
-+ LDSCRIPT = arch/arm/vmlinux-armv-xip.lds.in
-+ export DATAADDR
-+endif
-+
- export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS
-
- # Only set INCDIR if its not already defined above
-@@ -269,7 +289,7 @@
- arch/arm/kernel arch/arm/mm arch/arm/lib: dummy
- $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
-
--bzImage zImage zinstall Image bootpImage install: vmlinux
-+bzImage zImage zinstall Image xipImage bootpImage install: vmlinux
- @$(MAKEBOOT) $@
-
- CLEAN_FILES += \
---- linux-2.4.25/arch/arm/boot/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/boot/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -113,6 +113,10 @@
- endif
- endif
-
-+ifeq ($(CONFIG_ARCH_PXA),y)
-+ZRELADDR = 0xa0008000
-+endif
-+
- ifeq ($(CONFIG_ARCH_ANAKIN),y)
- ZRELADDR = 0x20008000
- endif
-@@ -140,6 +144,14 @@
- zImage: compressed/vmlinux
- $(OBJCOPY) $(OBJCOPYFLAGS) $< $@
-
-+ifeq ($(CONFIG_XIP_KERNEL),y)
-+xipImage: $(CONFIGURE) $(SYSTEM)
-+ $(OBJCOPY) -S -O binary -R .data $(SYSTEM) vmlinux-text.bin
-+ $(OBJCOPY) -S -O binary -R .init -R .text -R __ex_table -R __ksymtab $(SYSTEM) vmlinux-data.bin
-+ cat vmlinux-text.bin vmlinux-data.bin > $@
-+ $(RM) -f vmlinux-text.bin vmlinux-data.bin
-+endif
-+
- bootpImage: bootp/bootp
- $(OBJCOPY) $(OBJCOPYFLAGS) $< $@
-
-@@ -160,7 +172,7 @@
- sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
-
- clean:
-- $(RM) Image zImage bootpImage
-+ $(RM) Image xipImage zImage bootpImage
- @$(MAKE) -C compressed clean
- @$(MAKE) -C bootp clean
-
---- linux-2.4.25/arch/arm/boot/compressed/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/boot/compressed/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -71,6 +71,10 @@
- OBJS += head-sa1100.o
- endif
-
-+ifeq ($(CONFIG_CPU_XSCALE),y)
-+OBJS += head-xscale.o
-+endif
-+
- SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
-
- LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/boot/compressed/head-xscale.S 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,50 @@
-+/*
-+ * linux/arch/arm/boot/compressed/head-xscale.S
-+ *
-+ * XScale specific tweaks. This is merged into head.S by the linker.
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/mach-types.h>
-+
-+ .section ".start", #alloc, #execinstr
-+
-+__XScale_start:
-+
-+ @ Preserve r8/r7 i.e. kernel entry values
-+
-+ @ Data cache might be active.
-+ @ Be sure to flush kernel binary out of the cache,
-+ @ whatever state it is, before it is turned off.
-+ @ This is done by fetching through currently executed
-+ @ memory to be sure we hit the same cache.
-+ bic r2, pc, #0x1f
-+ add r3, r2, #0x10000 @ 64 kb is quite enough...
-+1: ldr r0, [r2], #32
-+ teq r2, r3
-+ bne 1b
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
-+
-+ @ disabling MMU and caches
-+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
-+ bic r0, r0, #0x05 @ clear DC, MMU
-+ bic r0, r0, #0x1000 @ clear Icache
-+ mcr p15, 0, r0, c1, c0, 0
-+
-+#ifdef CONFIG_ARCH_LUBBOCK
-+ mov r7, #MACH_TYPE_LUBBOCK
-+#endif
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ mov r7, #MACH_TYPE_PXA_IDP
-+#endif
-+
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ mov r7, #(MACH_TYPE_TRIZEPS2 & 0xFF00)
-+ add r7, r7, #(MACH_TYPE_TRIZEPS2 & 0xFF)
-+#endif
-+
-+
---- linux-2.4.25/arch/arm/boot/compressed/head.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/arch/arm/boot/compressed/head.S 2004-03-31 17:15:11.000000000 +0200
-@@ -351,7 +351,11 @@
- orr r1, r1, #3 << 10
- add r2, r3, #16384
- 1: cmp r1, r8 @ if virt > start of RAM
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ orrhs r1, r1, #0x08 @ set cacheable, not bufferable
-+#else
- orrhs r1, r1, #0x0c @ set cacheable, bufferable
-+#endif
- cmp r1, r9 @ if virt > end of RAM
- bichs r1, r1, #0x0c @ clear cacheable, bufferable
- str r1, [r0], #4 @ 1:1 mapping
-@@ -364,7 +368,11 @@
- * so there is no map overlap problem for up to 1 MB compressed kernel.
- * If the execution is in RAM then we would only be duplicating the above.
- */
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ mov r1, #0x1a
-+#else
- mov r1, #0x1e
-+#endif
- orr r1, r1, #3 << 10
- mov r2, pc, lsr #20
- orr r1, r1, r2, lsl #20
---- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/arch/arm/config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -38,6 +38,7 @@
- Cirrus-CL-PS7500FE CONFIG_ARCH_CLPS7500 \
- CLPS711x/EP721x-based CONFIG_ARCH_CLPS711X \
- Co-EBSA285 CONFIG_ARCH_CO285 \
-+ PXA250/210-based CONFIG_ARCH_PXA \
- EBSA-110 CONFIG_ARCH_EBSA110 \
- Excalibur-ARM CONFIG_ARCH_CAMELOT \
- FootBridge CONFIG_ARCH_FOOTBRIDGE \
-@@ -148,6 +149,47 @@
- endmenu
-
- mainmenu_option next_comment
-+comment 'Intel PXA250/210 Implementations'
-+dep_bool ' Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA
-+dep_bool ' Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA
-+dep_bool ' Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA
-+dep_bool ' Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA
-+
-+if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then
-+ define_bool CONFIG_PXA_CERF y
-+
-+ choice 'CerfBoard Style' \
-+ "PDA CONFIG_PXA_CERF_PDA \
-+ BOARD CONFIG_PXA_CERF_BOARD" PDA
-+
-+ choice 'CerfBoard RAM Available' \
-+ "128MB CONFIG_PXA_CERF_RAM_128MB \
-+ 64MB CONFIG_PXA_CERF_RAM_64MB \
-+ 32MB CONFIG_PXA_CERF_RAM_32MB \
-+ 16MB CONFIG_PXA_CERF_RAM_16MB" 64MB
-+
-+ choice 'CerfBoard Flash Available' \
-+ "64MB CONFIG_PXA_CERF_FLASH_64MB \
-+ 32MB CONFIG_PXA_CERF_FLASH_32MB \
-+ 16MB CONFIG_PXA_CERF_FLASH_16MB \
-+ 8MB CONFIG_PXA_CERF_FLASH_8MB" 32MB
-+fi
-+
-+if [ "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
-+ define_bool CONFIG_SA1111 y
-+fi
-+
-+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
-+ define_bool CONFIG_TRIZEPS2 y
-+fi
-+
-+dep_tristate 'PXA USB function support' CONFIG_PXA_USB $CONFIG_ARCH_PXA
-+dep_tristate ' Support for PXA USB network link function' CONFIG_PXA_USB_NETLINK $CONFIG_PXA_USB
-+dep_tristate ' Support for PXA USB character device emulation' CONFIG_PXA_USB_CHAR $CONFIG_PXA_USB
-+
-+endmenu
-+
-+mainmenu_option next_comment
- comment 'CLPS711X/EP721X Implementations'
- dep_bool ' AUTCPU12' CONFIG_ARCH_AUTCPU12 $CONFIG_ARCH_CLPS711X
- dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X
-@@ -385,6 +427,12 @@
- define_bool CONFIG_CPU_SA1100 n
- fi
-
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ define_bool CONFIG_CPU_32v5 y
-+ define_bool CONFIG_CPU_XSCALE y
-+ bool 'Workaround for XScale cache errata (see help)' CONFIG_XSCALE_CACHE_ERRATA
-+fi
-+
- # Figure out what processor architecture version we should be using.
- # This defines the compiler instruction set which depends on the machine type.
-
-@@ -493,6 +541,7 @@
- hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
-
- if [ "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
- dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL
- fi
-@@ -501,8 +550,10 @@
- bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
- if [ "$CONFIG_HOTPLUG" = "y" ]; then
- source drivers/pcmcia/Config.in
-+ source drivers/mmc/Config.in
- else
- define_bool CONFIG_PCMCIA n
-+ define_bool CONFIG_MMC n
- fi
- if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; then
- if [ "$CONFIG_PCMCIA" != "n" ]; then
-@@ -513,6 +564,14 @@
- bool 'System V IPC' CONFIG_SYSVIPC
- bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
- bool 'Sysctl support' CONFIG_SYSCTL
-+
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_bool 'Kernel Execute-In-Place from ROM (EXPERIMENTAL)' CONFIG_XIP_KERNEL $CONFIG_EXPERIMENTAL
-+ if [ "$CONFIG_XIP_KERNEL" = "y" ]; then
-+ hex ' Kernel .text physical address' CONFIG_XIP_PHYS_ADDR 0
-+ fi
-+fi
-+
- comment 'At least one math emulation must be selected'
- tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
- if [ "$CONFIG_FPE_NWFPE" != "n" ]; then
-@@ -538,6 +597,9 @@
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_CO285" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_LUBBOCK" = "y" -o \
-+ "$CONFIG_ARCH_PXA_IDP" = "y" -o \
-+ "$CONFIG_ARCH_PXA_CERF" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_CDB89712" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
-@@ -549,8 +611,12 @@
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_CO285" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_LUBBOCK" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
-+ "$CONFIG_ARCH_LUBBOCK" = "y" -o \
-+ "$CONFIG_ARCH_PXA_CERF" = "y" -o \
-+ "$CONFIG_ARCH_PXA_IDP" = "y" -o \
- "$CONFIG_ARCH_OMAHA" = "y" ]; then
- bool ' Timer LED' CONFIG_LEDS_TIMER
- bool ' CPU usage LED' CONFIG_LEDS_CPU
-@@ -684,6 +750,7 @@
- if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_TBOX" = "y" -o \
- "$CONFIG_ARCH_CLPS7500" = "y" -o \
-@@ -705,6 +772,7 @@
- "$CONFIG_ARCH_TBOX" = "y" -o \
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_PCI" = "y" ]; then
- mainmenu_option next_comment
- comment 'Sound'
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/cerfboard_pxa 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,857 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_PXA_CERF=y
-+CONFIG_PXA_CERF=y
-+# CONFIG_PXA_CERF_PDA is not set
-+CONFIG_PXA_CERF_BOARD=y
-+# CONFIG_PXA_CERF_RAM_128MB is not set
-+CONFIG_PXA_CERF_RAM_64MB=y
-+# CONFIG_PXA_CERF_RAM_32MB is not set
-+# CONFIG_PXA_CERF_RAM_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_64MB is not set
-+CONFIG_PXA_CERF_FLASH_32MB=y
-+# CONFIG_PXA_CERF_FLASH_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_8MB is not set
-+CONFIG_PXA_USB=y
-+CONFIG_PXA_USB_NETLINK=y
-+CONFIG_PXA_USB_CHAR=m
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
-+CONFIG_LEDS=y
-+# CONFIG_LEDS_TIMER is not set
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_PXA_CERF=y
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=m
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+CONFIG_FILTER=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+# CONFIG_PPP_SYNC_TTY is not set
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+CONFIG_PCMCIA_FMVJ18X=m
-+CONFIG_PCMCIA_PCNET=m
-+CONFIG_PCMCIA_AXNET=m
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+CONFIG_PCMCIA_RAYCS=m
-+CONFIG_PCMCIA_NETWAVE=m
-+CONFIG_PCMCIA_WAVELAN=m
-+CONFIG_AIRONET4500_CS=m
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+# CONFIG_I2C_CHARDEV is not set
-+# CONFIG_I2C_PROC is not set
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+CONFIG_WATCHDOG=y
-+# CONFIG_WATCHDOG_NOWAYOUT is not set
-+# CONFIG_ACQUIRE_WDT is not set
-+# CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM7101_WDT is not set
-+# CONFIG_SC520_WDT is not set
-+# CONFIG_PCWATCHDOG is not set
-+# CONFIG_21285_WATCHDOG is not set
-+# CONFIG_977_WATCHDOG is not set
-+# CONFIG_SA1100_WATCHDOG is not set
-+CONFIG_PXA_WATCHDOG=m
-+# CONFIG_OMAHA_WATCHDOG is not set
-+# CONFIG_EUROTECH_WDT is not set
-+# CONFIG_IB700_WDT is not set
-+# CONFIG_WAFER_WDT is not set
-+# CONFIG_I810_TCO is not set
-+# CONFIG_MIXCOMWD is not set
-+# CONFIG_60XX_WDT is not set
-+# CONFIG_SC1200_WDT is not set
-+# CONFIG_SOFT_WATCHDOG is not set
-+# CONFIG_W83877F_WDT is not set
-+# CONFIG_WDT is not set
-+# CONFIG_WDTPCI is not set
-+# CONFIG_MACHZ_WDT is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=y
-+CONFIG_PCMCIA_CHRDEV=y
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+CONFIG_ROMFS_FS=y
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+CONFIG_NLS_CODEPAGE_863=m
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+# CONFIG_FB is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/cerfpda_pxa 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,962 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_PXA_CERF=y
-+CONFIG_PXA_CERF=y
-+CONFIG_PXA_CERF_PDA=y
-+# CONFIG_PXA_CERF_BOARD is not set
-+# CONFIG_PXA_CERF_RAM_128MB is not set
-+CONFIG_PXA_CERF_RAM_64MB=y
-+# CONFIG_PXA_CERF_RAM_32MB is not set
-+# CONFIG_PXA_CERF_RAM_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_64MB is not set
-+CONFIG_PXA_CERF_FLASH_32MB=y
-+# CONFIG_PXA_CERF_FLASH_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_8MB is not set
-+CONFIG_PXA_USB=y
-+CONFIG_PXA_USB_NETLINK=y
-+CONFIG_PXA_USB_CHAR=y
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_ARM_THUMB is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
-+CONFIG_LEDS=y
-+# CONFIG_LEDS_TIMER is not set
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_PXA_CERF=y
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+CONFIG_BLK_DEV_LOOP=m
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+CONFIG_FILTER=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+# CONFIG_PPP_SYNC_TTY is not set
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+CONFIG_PCMCIA_FMVJ18X=m
-+CONFIG_PCMCIA_PCNET=m
-+CONFIG_PCMCIA_AXNET=m
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+# CONFIG_NET_PCMCIA_RADIO is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=y
-+CONFIG_IRLAN=y
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=y
-+CONFIG_IRDA_ULTRA=y
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+CONFIG_IRDA_DEBUG=y
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=y
-+# CONFIG_IRPORT_SIR is not set
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+
-+#
-+# ATA/IDE/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_INTEL_RNG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=y
-+CONFIG_PCMCIA_CHRDEV=y
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=m
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+CONFIG_ROMFS_FS=y
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+CONFIG_NLS_CODEPAGE_863=m
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_PXA_8BPP is not set
-+CONFIG_FB_PXA_16BPP=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+CONFIG_FBCON_FONTS=y
-+# CONFIG_FONT_8x8 is not set
-+# CONFIG_FONT_8x16 is not set
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_SUN12x22 is not set
-+# CONFIG_FONT_6x11 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+CONFIG_FONT_ACORN_8x8=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+# CONFIG_USB_UHCI is not set
-+# CONFIG_USB_UHCI_ALT is not set
-+# CONFIG_USB_OHCI is not set
-+# CONFIG_USB_OHCI_SA1111 is not set
-+# CONFIG_USB_AUDIO is not set
-+# CONFIG_USB_BLUETOOTH is not set
-+# CONFIG_USB_STORAGE is not set
-+# CONFIG_USB_STORAGE_DEBUG is not set
-+# CONFIG_USB_STORAGE_DATAFAB is not set
-+# CONFIG_USB_STORAGE_FREECOM is not set
-+# CONFIG_USB_STORAGE_ISD200 is not set
-+# CONFIG_USB_STORAGE_DPCM is not set
-+# CONFIG_USB_STORAGE_HP8200e is not set
-+# CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_JUMPSHOT is not set
-+# CONFIG_USB_ACM is not set
-+# CONFIG_USB_PRINTER is not set
-+# CONFIG_USB_HID is not set
-+# CONFIG_USB_HIDDEV is not set
-+# CONFIG_USB_KBD is not set
-+# CONFIG_USB_MOUSE is not set
-+# CONFIG_USB_WACOM is not set
-+# CONFIG_USB_DC2XX is not set
-+# CONFIG_USB_MDC800 is not set
-+# CONFIG_USB_SCANNER is not set
-+# CONFIG_USB_MICROTEK is not set
-+# CONFIG_USB_HPUSBSCSI is not set
-+# CONFIG_USB_PEGASUS is not set
-+# CONFIG_USB_KAWETH is not set
-+# CONFIG_USB_CATC is not set
-+# CONFIG_USB_CDCETHER is not set
-+# CONFIG_USB_USBNET is not set
-+# CONFIG_USB_USS720 is not set
-+
-+#
-+# USB Serial Converter support
-+#
-+# CONFIG_USB_SERIAL is not set
-+# CONFIG_USB_SERIAL_GENERIC is not set
-+# CONFIG_USB_SERIAL_BELKIN is not set
-+# CONFIG_USB_SERIAL_WHITEHEAT is not set
-+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-+# CONFIG_USB_SERIAL_EMPEG is not set
-+# CONFIG_USB_SERIAL_FTDI_SIO is not set
-+# CONFIG_USB_SERIAL_VISOR is not set
-+# CONFIG_USB_SERIAL_IPAQ is not set
-+# CONFIG_USB_SERIAL_IR is not set
-+# CONFIG_USB_SERIAL_EDGEPORT is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-+# CONFIG_USB_SERIAL_KEYSPAN is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-+# CONFIG_USB_SERIAL_MCT_U232 is not set
-+# CONFIG_USB_SERIAL_KLSI is not set
-+# CONFIG_USB_SERIAL_PL2303 is not set
-+# CONFIG_USB_SERIAL_CYBERJACK is not set
-+# CONFIG_USB_SERIAL_XIRCOM is not set
-+# CONFIG_USB_SERIAL_OMNINET is not set
-+# CONFIG_USB_RIO500 is not set
-+
-+#
-+# Bluetooth support
-+#
-+CONFIG_BLUEZ=y
-+CONFIG_BLUEZ_L2CAP=y
-+
-+#
-+# Bluetooth device drivers
-+#
-+# CONFIG_BLUEZ_HCIUSB is not set
-+CONFIG_BLUEZ_HCIUART=y
-+CONFIG_BLUEZ_HCIVHCI=y
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/csb226 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,615 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Board
-+#
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_INNOKOM is not set
-+CONFIG_ARCH_CSB226=y
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_CPU_FREQ is not set
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+# CONFIG_MMC is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="console=ttyS0,19200"
-+CONFIG_ALIGNMENT_TRAP=y
-+CONFIG_ARM_HWTIMER=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+# CONFIG_MTD is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+CONFIG_ARM_CIRRUS=y
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+# CONFIG_JFFS2_FS is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+# CONFIG_NFS_V3 is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+# CONFIG_MSDOS_PARTITION is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_WAITQ=y
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/innokom 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,699 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Board
-+#
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_INNOKOM=y
-+# CONFIG_ARCH_CSB226 is not set
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_CPU_FREQ is not set
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+# CONFIG_MMC is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/nfs mem=32M ip=dhcp console=ttyS0,19200"
-+CONFIG_ALIGNMENT_TRAP=y
-+CONFIG_ARM_HWTIMER=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+CONFIG_MTD_CFI_AMDSTD=y
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_INNOKOM=y
-+CONFIG_MTD_INNOKOM_16MB=y
-+# CONFIG_MTD_INNOKOM_64MB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+# CONFIG_IP_PNP_BOOTP is not set
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91X=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_JFFS2_FS_NAND is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+# CONFIG_MSDOS_PARTITION is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_WAITQ=y
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/lubbock 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,971 @@
-+#
-+# Automatically generated make config: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+# CONFIG_KMOD is not set
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200 is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+
-+#
-+# Archimedes/A5000 Implementations (select only ONE)
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# AT91RM9200 Implementations
-+#
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+CONFIG_ARCH_LUBBOCK=y
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_ARCH_TRIZEPS2 is not set
-+CONFIG_SA1111=y
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+
-+#
-+# Processor Type
-+#
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+
-+#
-+# Processor Features
-+#
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+
-+#
-+# MMC device drivers
-+#
-+CONFIG_MMC=m
-+CONFIG_MMC_PXA=m
-+CONFIG_MMC_BLOCK=m
-+CONFIG_MMC_PARTITIONS=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+
-+#
-+# At least one math emulation must be selected
-+#
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+CONFIG_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=32M"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+
-+#
-+# User Modules And Translation Layers
-+#
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+CONFIG_MTD_CFI_B2=y
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+CONFIG_MTD_CFI_I1=y
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+CONFIG_MTD_LUBBOCK=y
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+
-+#
-+# Disk-On-Chip Device Drivers
-+#
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+# CONFIG_BLK_STATS is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+
-+#
-+#
-+#
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91X=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+# CONFIG_PCMCIA_3C574 is not set
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=y
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+# CONFIG_PCMCIA_SMC91C92 is not set
-+# CONFIG_PCMCIA_XIRC2PS is not set
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+# CONFIG_NET_PCMCIA_RADIO is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+
-+#
-+# Please see Documentation/ide.txt for help/info on IDE drives
-+#
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+CONFIG_BLK_DEV_IDECS=y
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+
-+#
-+# IDE chipset support/bugfixes
-+#
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+CONFIG_BLK_DEV_IDE_MODES=y
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+# CONFIG_BLK_DEV_ATARAID_SII is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_INPUT_MX1TS is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_AT91 is not set
-+# CONFIG_SERIAL_AT91_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+
-+#
-+# Other L3 adapters
-+#
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+CONFIG_BUSMOUSE=y
-+# CONFIG_ATIXL_BUSMOUSE is not set
-+# CONFIG_LOGIBUSMOUSE is not set
-+# CONFIG_MS_BUSMOUSE is not set
-+CONFIG_MOUSE=y
-+CONFIG_PSMOUSE=y
-+# CONFIG_82C710_MOUSE is not set
-+# CONFIG_PC110_PAD is not set
-+# CONFIG_MK712_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_PXA_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+# CONFIG_PCMCIA_SERIAL_CS is not set
-+# CONFIG_SYNCLINK_CS is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+# CONFIG_CRAMFS_LINEAR is not set
-+# CONFIG_CRAMFS_LINEAR_XIP is not set
-+# CONFIG_ROOT_CRAMFS_LINEAR is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+# CONFIG_NFS_V3 is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+# CONFIG_FB_DBMX1 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_PXA_8BPP is not set
-+CONFIG_FB_PXA_16BPP=y
-+# CONFIG_FB_PXA_QVGA is not set
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+CONFIG_FBCON_FONTWIDTH8_ONLY=y
-+# CONFIG_FBCON_FONTS is not set
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_ALI5455 is not set
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_FORTE is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_VIDC is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_ZLIB_INFLATE=y
-+CONFIG_ZLIB_DEFLATE=y
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/pxa_idp 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,933 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+CONFIG_ARCH_PXA_IDP=y
-+# CONFIG_ARCH_PXA_CERF is not set
-+CONFIG_PXA_USB=m
-+CONFIG_PXA_USB_NETLINK=m
-+CONFIG_PXA_USB_CHAR=m
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+CONFIG_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/mtdblock2 init=/linuxrc console=ttyS0,115200"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+CONFIG_MTD_LUBBOCK=y
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_PXA_CERF is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+CONFIG_ASI_MTD0_SIZE=40000
-+CONFIG_ASI_MTD1_SIZE=100000
-+CONFIG_ASI_MTD2_SIZE=1e00000
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+# CONFIG_IP_PNP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91111=m
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+CONFIG_NET_POCKET=y
-+# CONFIG_DE600 is not set
-+# CONFIG_DE620 is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+CONFIG_WAVELAN=m
-+# CONFIG_ARLAN is not set
-+CONFIG_AIRONET4500=y
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+CONFIG_HERMES=m
-+CONFIG_PCMCIA_HERMES=m
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+# CONFIG_PCMCIA_3C574 is not set
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=m
-+# CONFIG_PCMCIA_AXNET is not set
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+CONFIG_PCMCIA_RAYCS=m
-+CONFIG_PCMCIA_NETWAVE=m
-+CONFIG_PCMCIA_WAVELAN=m
-+CONFIG_AIRONET4500_CS=m
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=m
-+CONFIG_IRLAN=m
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=m
-+CONFIG_IRDA_ULTRA=y
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+CONFIG_IRDA_DEBUG=y
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=m
-+# CONFIG_IRPORT_SIR is not set
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+CONFIG_PXA_FIR=m
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+CONFIG_INPUT_KEYBDEV=m
-+CONFIG_INPUT_MOUSEDEV=m
-+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
-+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+# CONFIG_IDP_KEYB is not set
-+CONFIG_MATRIX_KEYBOARD=y
-+# CONFIG_SA1111_PS2_KEYB is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+CONFIG_BUSMOUSE=y
-+# CONFIG_ATIXL_BUSMOUSE is not set
-+# CONFIG_LOGIBUSMOUSE is not set
-+# CONFIG_MS_BUSMOUSE is not set
-+CONFIG_MOUSE=y
-+CONFIG_PSMOUSE=y
-+# CONFIG_82C710_MOUSE is not set
-+# CONFIG_PC110_PAD is not set
-+# CONFIG_MK712_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=m
-+CONFIG_JBD=m
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+# CONFIG_UMSDOS_FS is not set
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+CONFIG_CRAMFS=y
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+CONFIG_ZLIB_FS_INFLATE=y
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_BSD_DISKLABEL is not set
-+# CONFIG_MINIX_SUBPARTITION is not set
-+# CONFIG_SOLARIS_X86_PARTITION is not set
-+# CONFIG_UNIXWARE_DISKLABEL is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+# CONFIG_FBCON_FONTS is not set
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=m
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+# CONFIG_DEBUG_LL is not set
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/trizeps2 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,873 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+CONFIG_ARCH_TRIZEPS2=y
-+CONFIG_TRIZEPS2=y
-+CONFIG_PXA_USB=y
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/mtdblock3 rw console=ttyS0,38400 mem=32M noinitrd init=/linuxrc"
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_PXA_CERF is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+CONFIG_MTD_TRIZEPS2=y
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+CONFIG_SMC9194=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+# CONFIG_WAVELAN is not set
-+# CONFIG_ARLAN is not set
-+# CONFIG_AIRONET4500 is not set
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+# CONFIG_HERMES is not set
-+# CONFIG_PCMCIA_HERMES is not set
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+CONFIG_PCMCIA_3C574=m
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+# CONFIG_PCMCIA_PCNET is not set
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+# CONFIG_PCMCIA_SMC91C92 is not set
-+# CONFIG_PCMCIA_XIRC2PS is not set
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+# CONFIG_PCMCIA_RAYCS is not set
-+# CONFIG_PCMCIA_NETWAVE is not set
-+# CONFIG_PCMCIA_WAVELAN is not set
-+# CONFIG_AIRONET4500_CS is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=m
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=m
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=m
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_PXA_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+# CONFIG_PCMCIA_SERIAL_CS is not set
-+CONFIG_TRIZEPS2_TTLIO=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=y
-+CONFIG_JBD=y
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+# CONFIG_UMSDOS_FS is not set
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=m
-+# CONFIG_NFS_V3 is not set
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=m
-+CONFIG_LOCKD=m
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+CONFIG_FBCON_ADVANCED=y
-+# CONFIG_FBCON_MFB is not set
-+# CONFIG_FBCON_CFB2 is not set
-+# CONFIG_FBCON_CFB4 is not set
-+# CONFIG_FBCON_CFB8 is not set
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_CFB24 is not set
-+# CONFIG_FBCON_CFB32 is not set
-+# CONFIG_FBCON_AFB is not set
-+# CONFIG_FBCON_ILBM is not set
-+# CONFIG_FBCON_IPLAN2P2 is not set
-+# CONFIG_FBCON_IPLAN2P4 is not set
-+# CONFIG_FBCON_IPLAN2P8 is not set
-+# CONFIG_FBCON_MAC is not set
-+# CONFIG_FBCON_VGA_PLANES is not set
-+# CONFIG_FBCON_VGA is not set
-+# CONFIG_FBCON_HGA is not set
-+CONFIG_FBCON_FONTWIDTH8_ONLY=y
-+CONFIG_FBCON_FONTS=y
-+# CONFIG_FONT_8x8 is not set
-+# CONFIG_FONT_8x16 is not set
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+CONFIG_FONT_ACORN_8x8=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+CONFIG_MCP=y
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+CONFIG_MCP_UCB1X00_TS_COMPAT=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- linux-2.4.25/arch/arm/kernel/Makefile~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -10,7 +10,7 @@
- HEAD_OBJ = head-$(PROCESSOR).o
- ENTRY_OBJ = entry-$(PROCESSOR).o
-
--AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
-+AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
- AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
-
- # This is depreciated.
-@@ -45,7 +45,7 @@
- $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
- $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \
- $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \
-- $(CONFIG_ARCH_AT91RM9200)
-+ $(CONFIG_ARCH_AT91RM9200) $(CONFIG_ARCH_PXA)
-
- ifneq ($(findstring y,$(no-irq-arch)),y)
- obj-y += irq-arch.o
---- linux-2.4.25/arch/arm/kernel/debug-armv.S~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/debug-armv.S 2004-03-31 17:15:11.000000000 +0200
-@@ -221,6 +221,31 @@
- bne 1001b
- .endm
-
-+#elif defined(CONFIG_ARCH_PXA)
-+
-+ .macro addruart,rx
-+ mrc p15, 0, \rx, c1, c0
-+ tst \rx, #1 @ MMU enabled?
-+ moveq \rx, #0x40000000 @ physical
-+ movne \rx, #io_p2v(0x40000000) @ virtual
-+ orr \rx, \rx, #0x00100000 @ FFUART
-+ .endm
-+
-+ .macro senduart,rd,rx
-+ str \rd, [\rx, #0]
-+ .endm
-+
-+ .macro busyuart,rd,rx
-+1002: ldr \rd, [\rx, #0x14]
-+ tst \rd, #(1 << 6)
-+ beq 1002b
-+ .endm
-+
-+ .macro waituart,rd,rx
-+1001: ldr \rd, [\rx, #0x14]
-+ tst \rd, #(1 << 5)
-+ beq 1001b
-+ .endm
- #elif defined(CONFIG_ARCH_CLPS7500)
- .macro addruart,rx
- mov \rx, #0xe0000000
---- linux-2.4.25/arch/arm/kernel/entry-armv.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/entry-armv.S 2004-03-31 17:15:11.000000000 +0200
-@@ -615,6 +615,27 @@
- .text
- .endm
-
-+#elif CONFIG_ARCH_PXA
-+
-+ .macro disable_fiq
-+ .endm
-+
-+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-+ mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000
-+ add \base, \base, #0x00d00000
-+ ldr \irqstat, [\base, #0] @ ICIP
-+ ldr \irqnr, [\base, #4] @ ICMR
-+ ands \irqstat, \irqstat, \irqnr
-+ beq 1001f
-+ rsb \irqnr, \irqstat, #0
-+ and \irqstat, \irqstat, \irqnr
-+ clz \irqnr, \irqstat
-+ rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
-+1001:
-+ .endm
-+
-+ .macro irq_prio_table
-+ .endm
- #else
- #error Unknown architecture
- #endif
-@@ -891,9 +912,17 @@
- stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack
- mrs ip, cpsr
- str ip, [sp, #-4]! @ Save cpsr_SVC
-+#ifdef CONFIG_CPU_XSCALE
-+ mra r4, r5, acc0
-+ stmfd sp!, {r4, r5}
-+#endif
- str sp, [r0, #TSS_SAVE] @ Save sp_SVC
- ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r2, [r1, #TSS_DOMAIN]
-+#ifdef CONFIG_CPU_XSCALE
-+ ldmfd sp!, {r4, r5}
-+ mar acc0, r4, r5
-+#endif
- ldr ip, [sp], #4
- mcr p15, 0, r2, c3, c0 @ Set domain register
- msr spsr, ip @ Save tasks CPSR into SPSR for this return
---- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:08.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/head-armv.S 2004-03-31 17:15:11.000000000 +0200
-@@ -30,6 +30,7 @@
- *
- * swapper_pg_dir, pgtbl and krnladr are all closely related.
- */
-+#ifndef CONFIG_XIP_KERNEL
- #if (TEXTADDR & 0xffff) != 0x8000
- #error TEXTADDR must start at 0xXXXX8000
- #endif
-@@ -41,6 +42,26 @@
- adr \reg, stext
- sub \reg, \reg, #0x4000
- .endm
-+#else
-+#if (DATAADDR & 0xffff) != 0x8000
-+#error DATAADDR must start at 0xXXXX8000
-+#endif
-+
-+#define PAGE_OFFSET 0xc0000000
-+#ifdef CONFIG_ARCH_LUBBOCK
-+#define PHYS_OFFSET 0xa0000000
-+#elif CONFIG_ARCH_OMAP
-+#define PHYS_OFFSET 0x10000000
-+#endif
-+
-+ .globl SYMBOL_NAME(swapper_pg_dir)
-+ .equ SYMBOL_NAME(swapper_pg_dir), DATAADDR - 0x4000
-+
-+ .macro pgtbl, reg, rambase
-+ ldr \reg, PGTBL
-+ add \reg, \reg, #PHYS_OFFSET - PAGE_OFFSET
-+ .endm
-+#endif
-
- /*
- * Since the page table is closely related to the kernel start address, we
-@@ -131,6 +152,32 @@
- mov r1, #MACH_TYPE_L7200
- #endif
-
-+#ifdef CONFIG_XIP_KERNEL
-+
-+#if defined(CONFIG_ARCH_LUBBOCK)
-+ mov r1, #MACH_TYPE_LUBBOCK
-+#endif
-+
-+ @ Data cache might be active.
-+ @ Be sure to flush kernel binary out of the cache,
-+ @ whatever state it is, before it is turned off.
-+ @ This is done by fetching through currently executed
-+ @ memory to be sure we hit the same cache.
-+ bic r2, pc, #0x1f
-+ add r3, r2, #0x10000 @ 64 kb is quite enough...
-+1: ldr r0, [r2], #32
-+ teq r2, r3
-+ bne 1b
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
-+
-+ @ disabling MMU and caches
-+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
-+ bic r0, r0, #0x05 @ clear DC, MMU
-+ bic r0, r0, #0x1000 @ clear Icache
-+ mcr p15, 0, r0, c1, c0, 0
-+#endif
-+
- mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
- msr cpsr_c, r0 @ and all irqs disabled
- bl __lookup_processor_type
-@@ -179,6 +226,17 @@
- */
- .align 5
- __mmap_switched:
-+#ifdef CONFIG_XIP_KERNEL
-+ ldr r3, ETEXT @ data section copy
-+ ldr r4, SDATA
-+ ldr r5, EDATA
-+1:
-+ ldr r6, [r3], #4
-+ str r6, [r4], #4
-+ cmp r4, r5
-+ blo 1b
-+#endif
-+
- adr r3, __switch_data + 4
- ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
- @ sp = stack pointer
-@@ -233,6 +291,8 @@
- teq r0, r2
- bne 1b
-
-+#ifndef CONFIG_XIP_KERNEL
-+
- /*
- * Create identity mapping for first MB of kernel to
- * cater for the MMU enable. This identity mapping
-@@ -271,6 +331,43 @@
- add r3, r8, r2 @ flags + rambase
- str r3, [r0]
-
-+#else /* CONFIG_XIP_KERNEL */
-+
-+ mov r3, pc, lsr #20
-+ mov r3, r3, lsl #20 @ phys kernel start
-+
-+ add r0, r4, r3, lsr #18
-+ orr r3, r3, r8
-+ str r3, [r0]
-+
-+ mov r0, #TEXTADDR & 0xff000000
-+ add r0, r0, #TEXTADDR & 0x00f00000 @ virt kernel start
-+ add r0, r4, r0, lsr #18
-+ add r2, r3, #4 << 20 @ kernel + 4MB
-+
-+1:
-+ str r3, [r0], #4
-+ add r3, r3, #1 << 20
-+ cmp r3, r2
-+ bne 1b
-+
-+ bic r3, r4, #0x000ff000 @ ram start
-+ add r0, r4, r3, lsr #18
-+ orr r3, r3, r8
-+ str r3, [r0], #4
-+
-+ add r0, r3, #PAGE_OFFSET - PHYS_OFFSET
-+ add r0, r4, r0, lsr #18
-+ add r2, r3, #4 << 20 @ ram + 4MB
-+
-+1:
-+ str r3, [r0], #4
-+ add r3, r3, #1 << 20
-+ cmp r3, r2
-+ bne 1b
-+
-+#endif /* CONFIG_XIP_KERNEL */
-+
- bic r8, r8, #0x0c @ turn off cacheable
- @ and bufferable bits
- #ifdef CONFIG_DEBUG_LL
-@@ -433,3 +530,13 @@
- mov pc, lr
- 2: ldmib r4, {r5, r6, r7} @ found, get results
- mov pc, lr
-+
-+#ifdef CONFIG_XIP_KERNEL
-+
-+PGTBL: .long SYMBOL_NAME(swapper_pg_dir)
-+
-+ETEXT: .long SYMBOL_NAME(_endtext)
-+SDATA: .long SYMBOL_NAME(_sdata)
-+EDATA: .long SYMBOL_NAME(__bss_start)
-+
-+#endif
---- linux-2.4.25/arch/arm/kernel/setup.c~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/setup.c 2004-03-31 17:15:11.000000000 +0200
-@@ -55,6 +55,10 @@
- extern void reboot_setup(char *str);
- extern int root_mountflags;
- extern int _stext, _text, _etext, _edata, _end;
-+#ifdef CONFIG_XIP_KERNEL
-+extern int _endtext, _sdata;
-+#endif
-+
-
- unsigned int processor_id;
- unsigned int __machine_arch_type;
-@@ -105,6 +109,109 @@
- #define lp1 io_res[1]
- #define lp2 io_res[2]
-
-+#ifdef CONFIG_CPU_32
-+static const char *cache_types[16] = {
-+ "write-through",
-+ "write-back",
-+ "write-back",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "write-back",
-+ "write-back",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+static const char *cache_clean[16] = {
-+ "not required",
-+ "read-block",
-+ "cp15 c7 ops",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "cp15 c7 ops",
-+ "cp15 c7 ops",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+static const char *cache_lockdown[16] = {
-+ "not supported",
-+ "not supported",
-+ "not supported",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "format A",
-+ "format B",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+#define CACHE_TYPE(x) (((x) >> 25) & 15)
-+#define CACHE_S(x) ((x) & (1 << 24))
-+#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
-+#define CACHE_ISIZE(x) ((x) & 4095)
-+
-+#define CACHE_SIZE(y) (((y) >> 6) & 7)
-+#define CACHE_ASSOC(y) (((y) >> 3) & 7)
-+#define CACHE_M(y) ((y) & (1 << 2))
-+#define CACHE_LINE(y) ((y) & 3)
-+
-+static inline void dump_cache(const char *prefix, unsigned int cache)
-+{
-+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-+
-+ printk("%s size %dK associativity %d line length %d sets %d\n",
-+ prefix,
-+ mult << (8 + CACHE_SIZE(cache)),
-+ (mult << CACHE_ASSOC(cache)) >> 1,
-+ 8 << CACHE_LINE(cache),
-+ 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-+ CACHE_LINE(cache)));
-+}
-+
-+static inline void dump_cpu_cache_id(void)
-+{
-+ unsigned int cache_info;
-+
-+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
-+
-+ if (cache_info == processor_id)
-+ return;
-+
-+ printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
-+ if (CACHE_S(cache_info)) {
-+ dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
-+ dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
-+ } else {
-+ dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
-+ }
-+}
-+
-+#else
-+#define dump_cpu_cache_id() do { } while (0)
-+#endif
-+
- static void __init setup_processor(void)
- {
- extern struct proc_info_list __proc_info_begin, __proc_info_end;
-@@ -272,7 +379,11 @@
-
- kernel_code.start = __virt_to_phys(init_mm.start_code);
- kernel_code.end = __virt_to_phys(init_mm.end_code - 1);
-+#ifndef CONFIG_XIP_KERNEL
- kernel_data.start = __virt_to_phys(init_mm.end_code);
-+#else
-+ kernel_data.start = __virt_to_phys(init_mm.start_data);
-+#endif
- kernel_data.end = __virt_to_phys(init_mm.brk - 1);
-
- for (i = 0; i < mi->nr_banks; i++) {
-@@ -531,7 +642,12 @@
- }
-
- init_mm.start_code = (unsigned long) &_text;
-+#ifndef CONFIG_XIP_KERNEL
- init_mm.end_code = (unsigned long) &_etext;
-+#else
-+ init_mm.end_code = (unsigned long) &_endtext;
-+ init_mm.start_data = (unsigned long) &_sdata;
-+#endif
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_end;
-
-@@ -568,6 +684,41 @@
- NULL
- };
-
-+static const char *proc_arch[16] = {
-+ "undefined 0",
-+ "4",
-+ "4T",
-+ "5",
-+ "5T",
-+ "5TE",
-+ "undefined 6",
-+ "undefined 7",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15"
-+};
-+
-+static void
-+c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
-+{
-+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-+
-+ seq_printf(m, "%s size\t\t: %d\n"
-+ "%s assoc\t\t: %d\n"
-+ "%s line length\t: %d\n"
-+ "%s sets\t\t: %d\n",
-+ type, mult << (8 + CACHE_SIZE(cache)),
-+ type, (mult << CACHE_ASSOC(cache)) >> 1,
-+ type, 8 << CACHE_LINE(cache),
-+ type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-+ CACHE_LINE(cache)));
-+}
-+
- static int c_show(struct seq_file *m, void *v)
- {
- int i;
-@@ -586,7 +737,60 @@
- if (elf_hwcap & (1 << i))
- seq_printf(m, "%s ", hwcap_str[i]);
-
-- seq_puts(m, "\n\n");
-+ seq_puts(m, "\n");
-+
-+ if ((processor_id & 0x0000f000) == 0x00000000) {
-+ /* pre-ARM7 */
-+ seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
-+ } else if ((processor_id & 0x0000f000) == 0x00007000) {
-+ /* ARM7 */
-+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
-+ "CPU architecture: %s\n"
-+ "CPU variant\t: 0x%02x\n"
-+ "CPU part\t: 0x%03x\n",
-+ processor_id >> 24,
-+ processor_id & (1 << 23) ? "4T" : "3",
-+ (processor_id >> 16) & 127,
-+ (processor_id >> 4) & 0xfff);
-+ } else {
-+ /* post-ARM7 */
-+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
-+ "CPU architecture: %s\n"
-+ "CPU variant\t: 0x%x\n"
-+ "CPU part\t: 0x%03x\n",
-+ processor_id >> 24,
-+ proc_arch[(processor_id >> 16) & 15],
-+ (processor_id >> 20) & 15,
-+ (processor_id >> 4) & 0xfff);
-+ }
-+ seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
-+
-+#ifdef CONFIG_CPU_32
-+ {
-+ unsigned int cache_info;
-+
-+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
-+ if (cache_info != processor_id) {
-+ seq_printf(m, "Cache type\t: %s\n"
-+ "Cache clean\t: %s\n"
-+ "Cache lockdown\t: %s\n"
-+ "Cache unified\t: %s\n",
-+ cache_types[CACHE_TYPE(cache_info)],
-+ cache_clean[CACHE_TYPE(cache_info)],
-+ cache_lockdown[CACHE_TYPE(cache_info)],
-+ CACHE_S(cache_info) ? "harvard" : "unified");
-+
-+ if (CACHE_S(cache_info)) {
-+ c_show_cache(m, "I", CACHE_ISIZE(cache_info));
-+ c_show_cache(m, "D", CACHE_DSIZE(cache_info));
-+ } else {
-+ c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
-+ }
-+ }
-+ }
-+#endif
-+
-+ seq_puts(m, "\n");
-
- seq_printf(m, "Hardware\t: %s\n", machine_name);
- seq_printf(m, "Revision\t: %04x\n", system_rev);
---- linux-2.4.25/arch/arm/lib/copy_page.S~2.4.25-vrs2-pxa1.patch 2001-03-07 04:44:35.000000000 +0100
-+++ linux-2.4.25/arch/arm/lib/copy_page.S 2004-03-31 17:15:11.000000000 +0200
-@@ -13,6 +13,8 @@
- #include <asm/assembler.h>
- #include <asm/constants.h>
-
-+#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
-+
- .text
- .align 5
- /*
-@@ -23,9 +25,13 @@
- */
- ENTRY(copy_page)
- stmfd sp!, {r4, lr} @ 2
-- mov r2, #PAGE_SZ/64 @ 1
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r1, #32] )
-+ mov r2, #COPY_COUNT @ 1
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
--1: stmia r0!, {r3, r4, ip, lr} @ 4
-+1: PLD( pld [r1, #64] )
-+ PLD( pld [r1, #96] )
-+2: stmia r0!, {r3, r4, ip, lr} @ 4
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
- stmia r0!, {r3, r4, ip, lr} @ 4
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
-@@ -33,6 +39,8 @@
- ldmia r1!, {r3, r4, ip, lr} @ 4
- subs r2, r2, #1 @ 1
- stmia r0!, {r3, r4, ip, lr} @ 4
-- ldmneia r1!, {r3, r4, ip, lr} @ 4
-- bne 1b @ 1
-+ ldmgtia r1!, {r3, r4, ip, lr} @ 4
-+ bgt 1b @ 1
-+ PLD( ldmeqia r1!, {r3, r4, ip, lr} )
-+ PLD( beq 2b )
- LOADREGS(fd, sp!, {r4, pc}) @ 3
---- linux-2.4.25/arch/arm/lib/findbit.S~2.4.25-vrs2-pxa1.patch 2000-09-19 00:15:25.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/findbit.S 2004-03-31 17:15:11.000000000 +0200
-@@ -43,7 +43,15 @@
- /*
- * One or more bits in the LSB of r3 are assumed to be set.
- */
--.found: tst r3, #0x0f
-+.found:
-+#if __LINUX_ARM_ARCH__ >= 5
-+ rsb r1, r3, #0
-+ and r3, r3, r1
-+ clz r3, r3
-+ rsb r3, r3, #31
-+ add r0, r2, r3
-+#else
-+ tst r3, #0x0f
- addeq r2, r2, #4
- movne r3, r3, lsl #4
- tst r3, #0x30
-@@ -52,5 +60,6 @@
- tst r3, #0x40
- addeq r2, r2, #1
- mov r0, r2
-+#endif
- RETINSTR(mov,pc,lr)
-
---- linux-2.4.25/arch/arm/lib/getuser.S~2.4.25-vrs2-pxa1.patch 2002-08-03 02:39:42.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/getuser.S 2004-03-31 17:15:11.000000000 +0200
-@@ -18,7 +18,7 @@
- * Inputs: r0 contains the address
- * Outputs: r0 is the error code
- * r1, r2 contains the zero-extended value
-- * lr corrupted
-+ * ip, lr corrupted
- *
- * No other registers must be altered. (see include/asm-arm/uaccess.h
- * for specific ASM register usage).
-@@ -42,14 +42,14 @@
-
- .global __get_user_2
- __get_user_2:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #2
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #2
-+ cmp r0, ip
- 2: ldrlsbt r1, [r0], #1
--3: ldrlsbt r2, [r0]
-- orrls r1, r1, r2, lsl #8
-+3: ldrlsbt ip, [r0]
-+ orrls r1, r1, ip, lsl #8
- movls r0, #0
- movls pc, lr
- b __get_user_bad
---- linux-2.4.25/arch/arm/lib/memcpy.S~2.4.25-vrs2-pxa1.patch 2001-03-07 04:44:35.000000000 +0100
-+++ linux-2.4.25/arch/arm/lib/memcpy.S 2004-03-31 17:15:11.000000000 +0200
-@@ -8,6 +8,9 @@
- * published by the Free Software Foundation.
- *
- * ASM optimised string functions
-+ *
-+ * Big Endian, prefetching and code factorization provided by Nicolas Pitre:
-+ * Copyright (C) 2002-2003 MontaVista Software, Inc.
- */
- #include <linux/linkage.h>
- #include <asm/assembler.h>
-@@ -27,15 +30,16 @@
-
- /*
- * Prototype: void memcpy(void *to,const void *from,unsigned long n);
-- * ARM3: cant use memcopy here!!!
- */
- ENTRY(memcpy)
- ENTRY(memmove)
- ENTER
-- cmp r1, r0
-- bcc 19f
-+ subs ip, r0, r1
-+ cmphi r2, ip
-+ bhi 18f
- subs r2, r2, #4
- blt 6f
-+ PLD( pld [r1, #0] )
- ands ip, r0, #3
- bne 7f
- ands ip, r1, #3
-@@ -43,29 +47,59 @@
-
- 1: subs r2, r2, #8
- blt 5f
-- subs r2, r2, #0x14
-- blt 3f
--2: ldmia r1!,{r3 - r9, ip}
-- stmia r0!,{r3 - r9, ip}
-+ subs r2, r2, #20
-+ blt 4f
-+
-+ PLD( subs r2, r2, #65 )
-+ PLD( blt 3f )
-+ PLD( pld [r1, #32] )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #64] )
-+ PLD( beq 2f )
-+ PLD( rsb ip, ip, #32 )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #96] )
-+ PLD( blt 2f )
-+ PLD( cmp ip, #16 )
-+ PLD( sub r2, r2, ip )
-+ PLD( ldmgeia r1!, {r3 - r6} )
-+ PLD( stmgeia r0!, {r3 - r6} )
-+ PLD( beq 2f )
-+ PLD( and ip, ip, #15 )
-+ PLD( cmp ip, #8 )
-+ PLD( ldr r3, [r1], #4 )
-+ PLD( ldrge r4, [r1], #4 )
-+ PLD( ldrgt r5, [r1], #4 )
-+ PLD( str r3, [r0], #4 )
-+ PLD( strge r4, [r0], #4 )
-+ PLD( strgt r5, [r0], #4 )
-+
-+2: PLD( pld [r1, #96] )
-+3: ldmia r1!, {r3 - r9, ip}
- subs r2, r2, #32
-+ stmia r0!, {r3 - r9, ip}
- bge 2b
-- cmn r2, #16
-+ PLD( cmn r2, #65 )
-+ PLD( bge 3b )
-+ PLD( add r2, r2, #65 )
-+4: cmn r2, #16
- ldmgeia r1!, {r3 - r6}
-+ subge r2, r2, #16
- stmgeia r0!, {r3 - r6}
-- subge r2, r2, #0x10
--3: adds r2, r2, #0x14
--4: ldmgeia r1!, {r3 - r5}
-+ adds r2, r2, #20
-+ ldmgeia r1!, {r3 - r5}
-+ subge r2, r2, #12
- stmgeia r0!, {r3 - r5}
-- subges r2, r2, #12
-- bge 4b
- 5: adds r2, r2, #8
- blt 6f
- subs r2, r2, #4
- ldrlt r3, [r1], #4
- ldmgeia r1!, {r4, r5}
-+ subge r2, r2, #4
- strlt r3, [r0], #4
- stmgeia r0!, {r4, r5}
-- subge r2, r2, #4
-
- 6: adds r2, r2, #4
- EXITEQ
-@@ -92,122 +126,175 @@
- beq 1b
-
- 8: bic r1, r1, #3
-- ldr r7, [r1], #4
- cmp ip, #2
-- bgt 15f
-- beq 11f
-+ ldr lr, [r1], #4
-+ bgt 17f
-+ beq 16f
-+
-+
-+ .macro forward_copy_shift pull push
-+
- cmp r2, #12
-- blt 10f
-- sub r2, r2, #12
--9: mov r3, r7, lsr #8
-- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-+ PLD( pld [r1, #0] )
-+ blt 14f
-+ subs r2, r2, #28
-+ blt 12f
-+
-+ PLD( subs r2, r2, #97 )
-+ PLD( blt 11f )
-+ PLD( pld [r1, #32] )
-+
-+ PLD( @ cache alignment )
-+ PLD( rsb ip, r1, #36 )
-+ PLD( pld [r1, #64] )
-+ PLD( ands ip, ip, #31 )
-+ PLD( pld [r1, #96] )
-+ PLD( beq 10f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #128] )
-+ PLD( blt 10f )
-+ PLD( sub r2, r2, ip )
-+9: PLD( mov r3, lr, pull #\pull )
-+ PLD( ldr lr, [r1], #4 )
-+ PLD( subs ip, ip, #4 )
-+ PLD( orr r3, r3, lr, push #\push )
-+ PLD( str r3, [r0], #4 )
-+ PLD( bgt 9b )
-+
-+10: PLD( pld [r1, #128] )
-+11: mov r3, lr, pull #\pull
-+ ldmia r1!, {r4 - r9, ip, lr}
-+ subs r2, r2, #32
-+ orr r3, r3, r4, push #\push
-+ mov r4, r4, pull #\pull
-+ orr r4, r4, r5, push #\push
-+ mov r5, r5, pull #\pull
-+ orr r5, r5, r6, push #\push
-+ mov r6, r6, pull #\pull
-+ orr r6, r6, r7, push #\push
-+ mov r7, r7, pull #\pull
-+ orr r7, r7, r8, push #\push
-+ mov r8, r8, pull #\pull
-+ orr r8, r8, r9, push #\push
-+ mov r9, r9, pull #\pull
-+ orr r9, r9, ip, push #\push
-+ mov ip, ip, pull #\pull
-+ orr ip, ip, lr, push #\push
-+ stmia r0!, {r3 - r9, ip}
-+ bge 10b
-+ PLD( cmn r2, #97 )
-+ PLD( bge 11b )
-+ PLD( add r2, r2, #97 )
-+ cmn r2, #16
-+ blt 13f
-+12: mov r3, lr, pull #\pull
-+ ldmia r1!, {r4 - r6, lr}
-+ sub r2, r2, #16
-+ orr r3, r3, r4, push #\push
-+ mov r4, r4, pull #\pull
-+ orr r4, r4, r5, push #\push
-+ mov r5, r5, pull #\pull
-+ orr r5, r5, r6, push #\push
-+ mov r6, r6, pull #\pull
-+ orr r6, r6, lr, push #\push
- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 9b
-- adds r2, r2, #12
-- blt 100f
--10: mov r3, r7, lsr #8
-- ldr r7, [r1], #4
-+13: adds r2, r2, #28
-+ blt 15f
-+14: mov r3, lr, pull #\pull
-+ ldr lr, [r1], #4
- subs r2, r2, #4
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, lr, push #\push
- str r3, [r0], #4
-- bge 10b
--100: sub r1, r1, #3
-+ bge 14b
-+15:
-+ .endm
-+
-+
-+ forward_copy_shift pull=8 push=24
-+ sub r1, r1, #3
- b 6b
-
--11: cmp r2, #12
-- blt 13f /* */
-- sub r2, r2, #12
--12: mov r3, r7, lsr #16
-- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7,LSL#16
-- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 12b
-- adds r2, r2, #12
-- blt 14f
--13: mov r3, r7, lsr #16
-- ldr r7, [r1], #4
-- subs r2, r2, #4
-- orr r3, r3, r7, lsl #16
-- str r3, [r0], #4
-- bge 13b
--14: sub r1, r1, #2
-+16: forward_copy_shift pull=16 push=16
-+ sub r1, r1, #2
- b 6b
-
--15: cmp r2, #12
-- blt 17f
-- sub r2, r2, #12
--16: mov r3, r7, lsr #24
-- ldmia r1!,{r4 - r7}
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 16b
-- adds r2, r2, #12
-- blt 18f
--17: mov r3, r7, lsr #24
-- ldr r7, [r1], #4
-- subs r2, r2, #4
-- orr r3, r3, r7, lsl#8
-- str r3, [r0], #4
-- bge 17b
--18: sub r1, r1, #1
-+17: forward_copy_shift pull=24 push=8
-+ sub r1, r1, #1
- b 6b
-
-
--19: add r1, r1, r2
-+18: add r1, r1, r2
- add r0, r0, r2
- subs r2, r2, #4
- blt 24f
-+ PLD( pld [r1, #-4] )
- ands ip, r0, #3
- bne 25f
- ands ip, r1, #3
- bne 26f
-
--20: subs r2, r2, #8
-+19: subs r2, r2, #8
- blt 23f
-- subs r2, r2, #0x14
-+ subs r2, r2, #20
- blt 22f
--21: ldmdb r1!, {r3 - r9, ip}
-- stmdb r0!, {r3 - r9, ip}
-+
-+ PLD( subs r2, r2, #96 )
-+ PLD( pld [r1, #-32] )
-+ PLD( blt 21f )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #-64] )
-+ PLD( beq 20f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #-96] )
-+ PLD( blt 20f )
-+ PLD( cmp ip, #16 )
-+ PLD( sub r2, r2, ip )
-+ PLD( ldmgedb r1!, {r3 - r6} )
-+ PLD( stmgedb r0!, {r3 - r6} )
-+ PLD( beq 20f )
-+ PLD( and ip, ip, #15 )
-+ PLD( cmp ip, #8 )
-+ PLD( ldr r3, [r1, #-4]! )
-+ PLD( ldrge r4, [r1, #-4]! )
-+ PLD( ldrgt r5, [r1, #-4]! )
-+ PLD( str r3, [r0, #-4]! )
-+ PLD( strge r4, [r0, #-4]! )
-+ PLD( strgt r5, [r0, #-4]! )
-+
-+20: PLD( pld [r1, #-96] )
-+ PLD( pld [r1, #-128] )
-+21: ldmdb r1!, {r3 - r6}
- subs r2, r2, #32
-- bge 21b
--22: cmn r2, #16
-+ stmdb r0!, {r3 - r6}
-+ ldmdb r1!, {r3 - r6}
-+ stmgedb r0!, {r3 - r6}
- ldmgedb r1!, {r3 - r6}
- stmgedb r0!, {r3 - r6}
-+ ldmgedb r1!, {r3 - r6}
-+ subges r2, r2, #32
-+ stmdb r0!, {r3 - r6}
-+ bge 20b
-+ PLD( cmn r2, #96 )
-+ PLD( bge 21b )
-+ PLD( add r2, r2, #96 )
-+22: cmn r2, #16
-+ ldmgedb r1!, {r3 - r6}
- subge r2, r2, #16
-+ stmgedb r0!, {r3 - r6}
- adds r2, r2, #20
- ldmgedb r1!, {r3 - r5}
-- stmgedb r0!, {r3 - r5}
- subge r2, r2, #12
-+ stmgedb r0!, {r3 - r5}
- 23: adds r2, r2, #8
- blt 24f
- subs r2, r2, #4
- ldrlt r3, [r1, #-4]!
- ldmgedb r1!, {r4, r5}
-+ subge r2, r2, #4
- strlt r3, [r0, #-4]!
- stmgedb r0!, {r4, r5}
-- subge r2, r2, #4
-
- 24: adds r2, r2, #4
- EXITEQ
-@@ -230,89 +317,101 @@
- subs r2, r2, ip
- blt 24b
- ands ip, r1, #3
-- beq 20b
-+ beq 19b
-
- 26: bic r1, r1, #3
-- ldr r3, [r1], #0
- cmp ip, #2
-- blt 34f
-- beq 30f
-- cmp r2, #12
-- blt 28f
-- sub r2, r2, #12
--27: mov r7, r3, lsl #8
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #24
-- mov r6, r6, lsl #8
-- orr r6, r6, r5, lsr #24
-- mov r5, r5, lsl #8
-- orr r5, r5, r4, lsr #24
-- mov r4, r4, lsl #8
-- orr r4, r4, r3, lsr #24
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 27b
-- adds r2, r2, #12
-- blt 29f
--28: mov ip, r3, lsl #8
-- ldr r3, [r1, #-4]!
-- subs r2, r2, #4
-- orr ip, ip, r3, lsr #24
-- str ip, [r0, #-4]!
-- bge 28b
--29: add r1, r1, #3
-- b 24b
-+ ldr r3, [r1], #0
-+ blt 35f
-+ beq 34f
-
--30: cmp r2, #12
-+
-+ .macro backward_copy_shift push pull
-+
-+ cmp r2, #12
-+ PLD( pld [r1, #-4] )
- blt 32f
-- sub r2, r2, #12
--31: mov r7, r3, lsl #16
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #16
-- mov r6, r6, lsl #16
-- orr r6, r6, r5, lsr #16
-- mov r5, r5, lsl #16
-- orr r5, r5, r4, lsr #16
-- mov r4, r4, lsl #16
-- orr r4, r4, r3, lsr #16
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 31b
-- adds r2, r2, #12
-+ subs r2, r2, #28
-+ blt 30f
-+
-+ PLD( subs r2, r2, #96 )
-+ PLD( pld [r1, #-32] )
-+ PLD( blt 29f )
-+ PLD( pld [r1, #-64] )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #-96] )
-+ PLD( beq 28f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #-128] )
-+ PLD( blt 28f )
-+ PLD( sub r2, r2, ip )
-+27: PLD( mov r4, r3, push #\push )
-+ PLD( ldr r3, [r1, #-4]! )
-+ PLD( subs ip, ip, #4 )
-+ PLD( orr r4, r4, r3, pull #\pull )
-+ PLD( str r4, [r0, #-4]! )
-+ PLD( bgt 27b )
-+
-+28: PLD( pld [r1, #-128] )
-+29: mov lr, r3, push #\push
-+ ldmdb r1!, {r3 - r9, ip}
-+ subs r2, r2, #32
-+ orr lr, lr, ip, pull #\pull
-+ mov ip, ip, push #\push
-+ orr ip, ip, r9, pull #\pull
-+ mov r9, r9, push #\push
-+ orr r9, r9, r8, pull #\pull
-+ mov r8, r8, push #\push
-+ orr r8, r8, r7, pull #\pull
-+ mov r7, r7, push #\push
-+ orr r7, r7, r6, pull #\pull
-+ mov r6, r6, push #\push
-+ orr r6, r6, r5, pull #\pull
-+ mov r5, r5, push #\push
-+ orr r5, r5, r4, pull #\pull
-+ mov r4, r4, push #\push
-+ orr r4, r4, r3, pull #\pull
-+ stmdb r0!, {r4 - r9, ip, lr}
-+ bge 28b
-+ PLD( cmn r2, #96 )
-+ PLD( bge 29b )
-+ PLD( add r2, r2, #96 )
-+ cmn r2, #16
-+ blt 31f
-+30: mov r7, r3, push #\push
-+ ldmdb r1!, {r3 - r6}
-+ sub r2, r2, #16
-+ orr r7, r7, r6, pull #\pull
-+ mov r6, r6, push #\push
-+ orr r6, r6, r5, pull #\pull
-+ mov r5, r5, push #\push
-+ orr r5, r5, r4, pull #\pull
-+ mov r4, r4, push #\push
-+ orr r4, r4, r3, pull #\pull
-+ stmdb r0!, {r4 - r7}
-+31: adds r2, r2, #28
- blt 33f
--32: mov ip, r3, lsl #16
-+32: mov r4, r3, push #\push
- ldr r3, [r1, #-4]!
- subs r2, r2, #4
-- orr ip, ip, r3, lsr #16
-- str ip, [r0, #-4]!
-+ orr r4, r4, r3, pull #\pull
-+ str r4, [r0, #-4]!
- bge 32b
--33: add r1, r1, #2
-+33:
-+ .endm
-+
-+
-+ backward_copy_shift push=8 pull=24
-+ add r1, r1, #3
- b 24b
-
--34: cmp r2, #12
-- blt 36f
-- sub r2, r2, #12
--35: mov r7, r3, lsl #24
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #8
-- mov r6, r6, lsl #24
-- orr r6, r6, r5, lsr #8
-- mov r5, r5, lsl #24
-- orr r5, r5, r4, lsr #8
-- mov r4, r4, lsl #24
-- orr r4, r4, r3, lsr #8
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 35b
-- adds r2, r2, #12
-- blt 37f
--36: mov ip, r3, lsl #24
-- ldr r3, [r1, #-4]!
-- subs r2, r2, #4
-- orr ip, ip, r3, lsr #8
-- str ip, [r0, #-4]!
-- bge 36b
--37: add r1, r1, #1
-+34: backward_copy_shift push=16 pull=16
-+ add r1, r1, #2
-+ b 24b
-+
-+35: backward_copy_shift push=24 pull=8
-+ add r1, r1, #1
- b 24b
-
-- .align
---- linux-2.4.25/arch/arm/lib/uaccess.S~2.4.25-vrs2-pxa1.patch 2000-09-19 00:15:25.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/uaccess.S 2004-03-31 17:15:11.000000000 +0200
-@@ -43,6 +43,8 @@
- stmfd sp!, {r2, r4 - r7, lr}
- cmp r2, #4
- blt .c2u_not_enough
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r0, #0] )
- ands ip, r0, #3
- bne .c2u_dest_not_aligned
- .c2u_dest_aligned:
-@@ -71,13 +73,26 @@
- sub r2, r2, ip
- subs ip, ip, #32
- blt .c2u_0rem8lp
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-+ PLD( subs ip, ip, #64 )
-+ PLD( blt .c2u_0cpynopld )
-+ PLD( pld [r1, #60] )
-+ PLD( pld [r0, #60] )
-
--.c2u_0cpy8lp: ldmia r1!, {r3 - r6}
-+.c2u_0cpy8lp:
-+ PLD( pld [r1, #92] )
-+ PLD( pld [r0, #92] )
-+.c2u_0cpynopld: ldmia r1!, {r3 - r6}
- stmia r0!, {r3 - r6} @ Shouldnt fault
- ldmia r1!, {r3 - r6}
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #32
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_0cpy8lp
-+ PLD( cmn ip, #64 )
-+ PLD( bge .c2u_0cpynopld )
-+ PLD( add ip, ip, #64 )
-+
- .c2u_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6}
- stmgeia r0!, {r3 - r6} @ Shouldnt fault
-@@ -115,9 +130,9 @@
- .c2u_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_1nowords
-- mov r3, r7, lsr #8
-+ mov r3, r7, pull #8
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, r7, push #24
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -128,50 +143,63 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_1rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_1cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_1cpy8lp: mov r3, r7, lsr #8
-+.c2u_1cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_1cpynopld: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #24
-+ mov r4, r4, pull #8
-+ orr r4, r4, r5, push #24
-+ mov r5, r5, pull #8
-+ orr r5, r5, r6, push #24
-+ mov r6, r6, pull #8
-+ orr r6, r6, r7, push #24
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_1cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_1cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_1rem8lp: tst ip, #8
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #24
-- movne r4, r4, lsr #8
-- orrne r4, r4, r7, lsl #24
-+ orrne r3, r3, r4, push #24
-+ movne r4, r4, pull #8
-+ orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #24
-+ orrne r3, r3, r7, push #24
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_1fupi
--.c2u_1nowords: mov r3, r7, lsr #8
-+.c2u_1nowords: mov r3, r7, lsr #byte(1)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(2)
- USER( strgebt r3, [r0], #1) @ May fault
-- movgt r3, r3, lsr #8
-+ movgt r3, r7, lsr #byte(3)
- USER( strgtbt r3, [r0], #1) @ May fault
- b .c2u_finished
-
- .c2u_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_2nowords
-- mov r3, r7, lsr #16
-+ mov r3, r7, pull #16
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #16
-+ orr r3, r3, r7, push #16
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -182,39 +210,52 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_2rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_2cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_2cpy8lp: mov r3, r7, lsr #16
-+.c2u_2cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_2cpynopld: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7, lsl #16
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #16
-+ mov r4, r4, pull #16
-+ orr r4, r4, r5, push #16
-+ mov r5, r5, pull #16
-+ orr r5, r5, r6, push #16
-+ mov r6, r6, pull #16
-+ orr r6, r6, r7, push #16
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_2cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_2cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_2rem8lp: tst ip, #8
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #16
-- movne r4, r4, lsr #16
-- orrne r4, r4, r7, lsl #16
-+ orrne r3, r3, r4, push #16
-+ movne r4, r4, pull #16
-+ orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #16
-+ orrne r3, r3, r7, push #16
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_2fupi
--.c2u_2nowords: mov r3, r7, lsr #16
-+.c2u_2nowords: mov r3, r7, lsr #byte(2)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(3)
- USER( strgebt r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #0
- USER( strgtbt r3, [r0], #1) @ May fault
-@@ -223,9 +264,9 @@
- .c2u_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_3nowords
-- mov r3, r7, lsr #24
-+ mov r3, r7, pull #24
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #8
-+ orr r3, r3, r7, push #8
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -236,41 +277,54 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_3rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_3cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_3cpy8lp: mov r3, r7, lsr #24
-+.c2u_3cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_3cpynopld: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #8
-+ mov r4, r4, pull #24
-+ orr r4, r4, r5, push #8
-+ mov r5, r5, pull #24
-+ orr r5, r5, r6, push #8
-+ mov r6, r6, pull #24
-+ orr r6, r6, r7, push #8
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_3cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_3cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_3rem8lp: tst ip, #8
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #8
-- movne r4, r4, lsr #24
-- orrne r4, r4, r7, lsl #8
-+ orrne r3, r3, r4, push #8
-+ movne r4, r4, pull #24
-+ orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #8
-+ orrne r3, r3, r7, push #8
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_3fupi
--.c2u_3nowords: mov r3, r7, lsr #24
-+.c2u_3nowords: mov r3, r7, lsr #byte(3)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- ldrge r3, [r1], #0
-+ ldrgeb r3, [r1], #1
- USER( strgebt r3, [r0], #1) @ May fault
-- movgt r3, r3, lsr #8
-+ ldrgtb r3, [r1], #0
- USER( strgtbt r3, [r0], #1) @ May fault
- b .c2u_finished
-
-@@ -302,6 +356,8 @@
- stmfd sp!, {r0, r2, r4 - r7, lr}
- cmp r2, #4
- blt .cfu_not_enough
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r0, #0] )
- ands ip, r0, #3
- bne .cfu_dest_not_aligned
- .cfu_dest_aligned:
-@@ -329,13 +385,26 @@
- sub r2, r2, ip
- subs ip, ip, #32
- blt .cfu_0rem8lp
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-+ PLD( subs ip, ip, #64 )
-+ PLD( blt .cfu_0cpynopld )
-+ PLD( pld [r1, #60] )
-+ PLD( pld [r0, #60] )
-
--.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
-+.cfu_0cpy8lp:
-+ PLD( pld [r1, #92] )
-+ PLD( pld [r0, #92] )
-+.cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault
- stmia r0!, {r3 - r6}
- ldmia r1!, {r3 - r6} @ Shouldnt fault
-- stmia r0!, {r3 - r6}
- subs ip, ip, #32
-+ stmia r0!, {r3 - r6}
- bpl .cfu_0cpy8lp
-+ PLD( cmn ip, #64 )
-+ PLD( bge .cfu_0cpynopld )
-+ PLD( add ip, ip, #64 )
-+
- .cfu_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6} @ Shouldnt fault
- stmgeia r0!, {r3 - r6}
-@@ -374,9 +443,9 @@
- .cfu_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_1nowords
-- mov r3, r7, lsr #8
-+ mov r3, r7, pull #8
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, r7, push #24
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -387,50 +456,63 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_1rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_1cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_1cpy8lp: mov r3, r7, lsr #8
-+.cfu_1cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_1cpynopld: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-- stmia r0!, {r3 - r6}
- subs ip, ip, #16
-+ orr r3, r3, r4, push #24
-+ mov r4, r4, pull #8
-+ orr r4, r4, r5, push #24
-+ mov r5, r5, pull #8
-+ orr r5, r5, r6, push #24
-+ mov r6, r6, pull #8
-+ orr r6, r6, r7, push #24
-+ stmia r0!, {r3 - r6}
- bpl .cfu_1cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_1cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_1rem8lp: tst ip, #8
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #24
-- movne r4, r4, lsr #8
-- orrne r4, r4, r7, lsl #24
-+ orrne r3, r3, r4, push #24
-+ movne r4, r4, pull #8
-+ orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #24
-+ orrne r3, r3, r7, push #24
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_1fupi
--.cfu_1nowords: mov r3, r7, lsr #8
-+.cfu_1nowords: mov r3, r7, lsr #byte(1)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(2)
- strgeb r3, [r0], #1
-- movgt r3, r3, lsr #8
-+ movgt r3, r7, lsr #byte(3)
- strgtb r3, [r0], #1
- b .cfu_finished
-
- .cfu_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_2nowords
-- mov r3, r7, lsr #16
-+ mov r3, r7, pull #16
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #16
-+ orr r3, r3, r7, push #16
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -441,39 +523,52 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_2rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_2cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_2cpy8lp: mov r3, r7, lsr #16
-+.cfu_2cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_2cpynopld: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7, lsl #16
-- stmia r0!, {r3 - r6}
- subs ip, ip, #16
-+ orr r3, r3, r4, push #16
-+ mov r4, r4, pull #16
-+ orr r4, r4, r5, push #16
-+ mov r5, r5, pull #16
-+ orr r5, r5, r6, push #16
-+ mov r6, r6, pull #16
-+ orr r6, r6, r7, push #16
-+ stmia r0!, {r3 - r6}
- bpl .cfu_2cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_2cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_2rem8lp: tst ip, #8
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #16
-- movne r4, r4, lsr #16
-- orrne r4, r4, r7, lsl #16
-+ orrne r3, r3, r4, push #16
-+ movne r4, r4, pull #16
-+ orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #16
-+ orrne r3, r3, r7, push #16
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_2fupi
--.cfu_2nowords: mov r3, r7, lsr #16
-+.cfu_2nowords: mov r3, r7, lsr #byte(2)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(3)
- strgeb r3, [r0], #1
- USER( ldrgtbt r3, [r1], #0) @ May fault
- strgtb r3, [r0], #1
-@@ -482,9 +577,9 @@
- .cfu_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_3nowords
-- mov r3, r7, lsr #24
-+ mov r3, r7, pull #24
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #8
-+ orr r3, r3, r7, push #8
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -495,41 +590,54 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_3rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_3cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_3cpy8lp: mov r3, r7, lsr #24
-+.cfu_3cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_3cpynopld: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-+ orr r3, r3, r4, push #8
-+ mov r4, r4, pull #24
-+ orr r4, r4, r5, push #8
-+ mov r5, r5, pull #24
-+ orr r5, r5, r6, push #8
-+ mov r6, r6, pull #24
-+ orr r6, r6, r7, push #8
- stmia r0!, {r3 - r6}
- subs ip, ip, #16
- bpl .cfu_3cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_3cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_3rem8lp: tst ip, #8
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #8
-- movne r4, r4, lsr #24
-- orrne r4, r4, r7, lsl #8
-+ orrne r3, r3, r4, push #8
-+ movne r4, r4, pull #24
-+ orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #8
-+ orrne r3, r3, r7, push #8
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_3fupi
--.cfu_3nowords: mov r3, r7, lsr #24
-+.cfu_3nowords: mov r3, r7, lsr #byte(3)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
--USER( ldrget r3, [r1], #0) @ May fault
-+USER( ldrgebt r3, [r1], #1) @ May fault
- strgeb r3, [r0], #1
-- movgt r3, r3, lsr #8
-+USER( ldrgtbt r3, [r1], #1) @ May fault
- strgtb r3, [r0], #1
- b .cfu_finished
-
-@@ -544,7 +652,7 @@
- ldr r1, [sp], #4 @ unsigned long count
- subs r4, r1, r2 @ bytes left to copy
- movne r1, r4
-- blne SYMBOL_NAME(__memzero)
-+ blne __memzero
- mov r0, r4
- LOADREGS(fd,sp!, {r4 - r7, pc})
- .previous
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,56 @@
-+#
-+# Makefile for the linux kernel.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+
-+USE_STANDARD_AS_RULE := true
-+
-+O_TARGET := pxa.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+export-objs := generic.o irq.o dma.o sa1111.o \
-+ usb_ctl.o usb_recv.o usb_send.o
-+
-+# Common support (must be linked before board specific support)
-+obj-y += generic.o irq.o dma.o
-+obj-$(CONFIG_SA1111) += sa1111.o
-+
-+# Specific board support
-+obj-$(CONFIG_ARCH_CSB226) += csb226.o
-+obj-$(CONFIG_ARCH_INNOKOM) += innokom.o
-+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
-+obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o
-+obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-+obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
-+
-+# Support for blinky lights
-+leds-y := leds.o
-+leds-$(CONFIG_ARCH_CSB226) += leds-csb226.o
-+leds-$(CONFIG_ARCH_INNOKOM) += leds-innokom.o
-+leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
-+leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
-+leds-$(CONFIG_ARCH_PXA_CERF) += leds-cerf.o
-+
-+obj-$(CONFIG_LEDS) += $(leds-y)
-+
-+# PXA USB client support
-+list-multi += pxausb_core.o
-+pxausb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
-+obj-$(CONFIG_PXA_USB) += pxausb_core.o
-+obj-$(CONFIG_PXA_USB_NETLINK) += usb-eth.o
-+obj-$(CONFIG_PXA_USB_CHAR) += usb-char.o
-+
-+# Misc features
-+obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+pxausb_core.o: $(pxausb_core-objs)
-+ $(LD) -r -o $@ $(pxausb_core-objs)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/cerf.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,266 @@
-+/*
-+ * linux/arch/arm/mach-pxa/cerf.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/io.h>
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int cerf_debug = DEBUGGING;
-+#else
-+#define cerf_debug 0
-+#endif
-+
-+static void __init cerf_init_irq(void)
-+{
-+ pxa_init_irq();
-+
-+ if( cerf_debug > 1)
-+ {
-+#if 0
-+ GPDR0 = 0xc05b9130;
-+ GPDR1 = 0xfcffab82;
-+ GPDR2 = 0x0001ffff;
-+#endif
-+
-+ printk(KERN_INFO "Pin directions:\n");
-+ printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0);
-+ printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1);
-+ printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2);
-+
-+ printk(KERN_INFO "Pin State:\n");
-+ printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0);
-+ printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1);
-+ printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2);
-+
-+ printk(KERN_INFO "Rising Edge:\n");
-+ printk(KERN_INFO "GRER0 0x%08x\n", GRER0);
-+ printk(KERN_INFO "GRER1 0x%08x\n", GRER1);
-+ printk(KERN_INFO "GRER2 0x%08x\n", GRER2);
-+
-+ printk(KERN_INFO "Falling Edge:\n");
-+ printk(KERN_INFO "GFER0 0x%08x\n", GFER0);
-+ printk(KERN_INFO "GFER1 0x%08x\n", GFER1);
-+ printk(KERN_INFO "GFER2 0x%08x\n", GFER2);
-+ }
-+
-+ /* set_GPIO_IRQ_edge has to be called before an irq can be requested */
-+ set_GPIO_IRQ_edge( 0, GPIO_FALLING_EDGE); /* CPLD */
-+#ifdef CONFIG_PXA_CERF_PDA
-+ set_GPIO_IRQ_edge( 2, GPIO_RISING_EDGE); /* UART B Interrupt */
-+ set_GPIO_IRQ_edge( 3, GPIO_RISING_EDGE); /* UART A Interrupt */
-+ set_GPIO_IRQ_edge( 32, GPIO_RISING_EDGE); /* UCB1400 Interrupt */
-+#endif
-+ set_GPIO_IRQ_edge( 14, GPIO_FALLING_EDGE); /* PCMCIA Card Detect */
-+ set_GPIO_IRQ_edge( 21, GPIO_RISING_EDGE); /* Ethernet Interrupt */
-+}
-+
-+static int __init cerf_init(void)
-+{
-+ /*
-+ * All of the code that was here was SA1111 init code
-+ * which we do not have.
-+ */
-+ return 0;
-+}
-+
-+__initcall(cerf_init);
-+
-+static void __init
-+fixup_cerf(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ SET_BANK (0, CERF_RAM_BASE, CERF_RAM_SIZE);
-+ mi->nr_banks = 1;
-+
-+#if 0 // Enable this stuff if you plan on not using jffs2
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+/*
-+ * IO map for the devices.
-+ */
-+static struct map_desc cerf_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { CERF_FLASH_BASE , CERF_FLASH_PHYS , CERF_FLASH_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_ETH_BASE , CERF_ETH_PHYS , CERF_ETH_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+#ifdef CONFIG_PXA_CERF_PDA
-+ { CERF_BT_BASE , CERF_BT_PHYS , CERF_BT_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_SERIAL_BASE, CERF_SERIAL_PHYS, CERF_SERIAL_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_CPLD_BASE , CERF_CPLD_PHYS , CERF_CPLD_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+#endif
-+
-+ LAST_DESC
-+};
-+
-+static void __init cerf_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(cerf_io_desc);
-+
-+ if( cerf_debug > 1)
-+ {
-+ printk(KERN_INFO "origMCS0 = 0x%08x\n", MSC0);
-+ printk(KERN_INFO "origMCS1 = 0x%08x\n", MSC1);
-+ printk(KERN_INFO "origMCS2 = 0x%08x\n", MSC2);
-+ }
-+
-+ /* setup memory timing for CS0/1 */
-+ MSC0 = MSC_CS(0, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(3) |
-+ MSC_RDN(15) |
-+ MSC_RDF(13) |
-+ MSC_RBW(0) |
-+ MSC_RT(0)) |
-+#ifdef CONFIG_PXA_CERF_PDA
-+ MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(7) |
-+ MSC_RDN(15) |
-+ MSC_RDF(15) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+#elif defined(CONFIG_PXA_CERF_BOARD)
-+ MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(1) |
-+ MSC_RDN(2) |
-+ MSC_RDF(4) |
-+ MSC_RBW(0) |
-+ MSC_RT(4));
-+#endif
-+ printk(KERN_INFO "MCS0 = 0x%08x\n", MSC0);
-+
-+ /* setup memory timing for CS2/3 */
-+ MSC1 = MSC_CS(2, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(5) |
-+ MSC_RDN(10) |
-+ MSC_RDF(10) |
-+ MSC_RBW(1) |
-+ MSC_RT(0)) |
-+ MSC_CS(3, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(5) |
-+ MSC_RDN(10) |
-+ MSC_RDF(10) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+ printk(KERN_INFO "MCS1 = 0x%08x\n", MSC1);
-+
-+ /* setup memory timing for CS4/5 */
-+ MSC2 = MSC_CS(4, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(2) |
-+ MSC_RDN(4) |
-+ MSC_RDF(4) |
-+ MSC_RBW(1) |
-+ MSC_RT(0)) |
-+ MSC_CS(5, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(2) |
-+ MSC_RDN(4) |
-+ MSC_RDF(4) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+ printk(KERN_INFO "MCS2 = 0x%08x\n", MSC2);
-+
-+#ifdef CONFIG_SOUND_PXA_AC97
-+ printk(KERN_INFO "Enabling sound amp for pxa cerf pda.\n");
-+ outw( CERF_PDA_SOUND_ENABLE, CERF_CPLD_BASE+CERF_PDA_CPLD_SOUND_ENA);
-+#endif
-+
-+#ifdef CONFIG_FB_PXA
-+ printk(KERN_INFO "Setting LCD to brightness to %d/15\n", CERF_PDA_DEFAULT_BRIGHTNESS);
-+ outw( CERF_PDA_DEFAULT_BRIGHTNESS, CERF_CPLD_BASE+CERF_PDA_CPLD_BRIGHTNESS);
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ /* Enable IrDA UART (SIR)*/
-+ CKEN |= CKEN5_STUART;
-+
-+ /* We want to get our goods from the STUART */
-+ set_GPIO_mode(GPIO46_STRXD_MD);
-+ set_GPIO_mode(GPIO47_STTXD_MD);
-+
-+ /* make sure FIR ICP is off */
-+ ICCR0 = 0;
-+
-+ /* configure STUART to for SIR
-+ * NOTE: RCVEIR and XMITIR must not be set at the same time!
-+ * Start with receive in IR mode, and switch transmit to IR only
-+ * when we need to send something in serial driver.
-+ */
-+ STISR = IrSR_IR_RECEIVE_ON;
-+#endif
-+
-+#if 0
-+ /* Connect FIR ICP to GPIO pins */
-+ CKEN |= CKEN13_FICP;
-+ set_GPIO_mode(GPIO46_ICPRXD_MD);
-+ set_GPIO_mode(GPIO47_ICPTXD_MD);
-+ ICCR0 = 0x1 | 0x18; //ICP unit enable
-+#endif
-+
-+#if 0
-+ /* Enable BT UART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+#endif
-+
-+ if( cerf_debug > 1)
-+ {
-+ printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0);
-+ printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1);
-+ printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2);
-+ printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0);
-+ printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1);
-+ printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2);
-+ printk(KERN_INFO "GAFR0_L 0x%08x\n", GAFR0_L);
-+ printk(KERN_INFO "GAFR0_U 0x%08x\n", GAFR0_U);
-+ printk(KERN_INFO "GAFR1_L 0x%08x\n", GAFR1_L);
-+ printk(KERN_INFO "GAFR1_U 0x%08x\n", GAFR1_U);
-+ printk(KERN_INFO "GAFR2_L 0x%08x\n", GAFR2_L);
-+ printk(KERN_INFO "GAFR2_U 0x%08x\n", GAFR2_U);
-+ printk(KERN_INFO "CKEN = 0x%08x\n", CKEN);
-+ printk(KERN_INFO "ICCR0 = 0x%08x\n", ICCR0);
-+ printk(KERN_INFO "STISR = 0x%08x\n", STISR);
-+ }
-+}
-+
-+MACHINE_START(PXA_CERF, "CerfBoard PXA Reference Board")
-+ MAINTAINER("Intrinsyc Software Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_cerf)
-+ MAPIO(cerf_map_io)
-+ INITIRQ(cerf_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/cpu-pxa.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,240 @@
-+/*
-+ * linux/arch/arm/mach-pxa/cpu-pxa.c
-+ *
-+ * Copyright (C) 2002,2003 Intrinsyc Software
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * 31-Jul-2002 : Initial version [FB]
-+ * 29-Jan-2003 : added PXA255 support [FB]
-+ *
-+ * Note:
-+ *
-+ * Quote from erratum 134:
-+ * ""If the operation of these peripherals would be adversely affected,
-+ * then these peripherals would have to be disabled during a frequency
-+ * change. (MMC,FFUART,STUART,BTUART,IRDA,SSP,UDC,AC97)""
-+ *
-+ * This sounds like they are not sure what the bug is...
-+ * If you run into problems with any of these peripherals, the effected
-+ * driver should register with cpu freq notification and disable/enable
-+ * the peripheral on CPUFREQ_PRECHANGE and CPUFREQ_POSTCHANGE.
-+ *
-+ * So far I've tested this code only under light load. It works for me.
-+ *
-+ * TODO:
-+ * - determine min/max freq at runtime
-+ * - determine pxbus value at runtime
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+
-+#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int freq_debug = DEBUGGING;
-+#else
-+#define freq_debug 0
-+#endif
-+
-+typedef struct
-+{
-+ unsigned int khz;
-+ unsigned int cccr;
-+ unsigned int pxbus;
-+} pxa_freqs_t;
-+
-+#define CCLKCFG_TURBO 0x1
-+#define CCLKCFG_FCS 0x2
-+
-+#define PXA250_REV_A1 0x1
-+#define PXA250_REV_B2 0x4
-+#define PXA25x_MIN_FREQ 99000
-+
-+//#define PXA25x_ALLOW_OVERCLOCK
-+
-+#ifdef PXA25x_ALLOW_OVERCLOCK
-+#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
-+#define OC(x...) x
-+#define PXA25x_MAX_FREQ 471000
-+#else
-+#define OC(x...)
-+#define PXA25x_MAX_FREQ 400000
-+#endif
-+
-+/* If CONFIG_CPU_FREQ is turned on but we find (at runtime)
-+ * we can't support scaling, try to handle requests gracefully.
-+ */
-+static int supported;
-+
-+static pxa_freqs_t pxa250_valid_freqs[] =
-+{
-+ {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
-+ {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
-+ {398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
-+ {0,0}
-+};
-+
-+static pxa_freqs_t pxa255_valid_freqs[] =
-+{
-+ { 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */
-+OC( {118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */
-+ {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
-+OC( {236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */
-+ {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
-+OC( {354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */
-+ {398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
-+ {398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */
-+OC( {471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */
-+ {0,0}
-+};
-+
-+static pxa_freqs_t *pxa_valid_freqs;
-+
-+/* This should be called with a valid freq point that was
-+ * obtained via pxa_validate_speed
-+ */
-+static pxa_freqs_t * pxa_get_freq_info( unsigned int khz)
-+{
-+ int i=0;
-+ while( pxa_valid_freqs[i].khz)
-+ {
-+ if( pxa_valid_freqs[i].khz == khz)
-+ return &pxa_valid_freqs[i];
-+ i++;
-+ }
-+
-+ /* shouldn't get here */
-+ return 0;
-+}
-+
-+/* find a valid frequency point */
-+static unsigned int pxa_validate_speed(unsigned int khz)
-+{
-+ int i=0;
-+ unsigned int vfreq = 0;
-+ while( pxa_valid_freqs[i].khz && (khz >= pxa_valid_freqs[i].khz))
-+ {
-+ vfreq = pxa_valid_freqs[i].khz;
-+ i++;
-+ }
-+ return vfreq;
-+}
-+
-+/* This should be called with a valid freq point that was
-+ * obtained via pxa_validate_speed
-+ */
-+static void pxa_setspeed(unsigned int khz)
-+{
-+ unsigned long flags;
-+ unsigned int unused;
-+ void *ramstart = phys_to_virt(0xa0000000);
-+ pxa_freqs_t *freq_info;
-+
-+ if( ! supported) return;
-+
-+ freq_info = pxa_get_freq_info( khz);
-+
-+ if( ! freq_info) return;
-+
-+ CCCR = freq_info->cccr;
-+ if( freq_debug)
-+ printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n",
-+ khz/1000, freq_info->pxbus);
-+
-+ local_irq_save(flags);
-+ __asm__ __volatile__("\
-+ ldr r4, [%1] @load MDREFR \n\
-+ b 2f \n\
-+ .align 5 \n\
-+1: \n\
-+ mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\
-+ \n\
-+ @ restart sdcke 0 / 1 \n\
-+ bic r5, r4, #(0x00001000 | 0x00008000) @ MDREFR_E0PIN | MDREFR_E1PIN \n\
-+ str r5, [%1] @clear \n\
-+ str r4, [%1] @restore \n\
-+ \n\
-+ @ Generate refresh cycles for all banks \n\
-+ ldr r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ \n\
-+ b 3f \n\
-+2: b 1b \n\
-+3: nop \n\
-+ "
-+ : "=&r" (unused)
-+ : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart)
-+ : "r4", "r5");
-+ local_irq_restore(flags);
-+}
-+
-+static int pxa_init_freqs( void)
-+{
-+ int cpu_ver;
-+ asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver));
-+
-+ if( (cpu_ver & 0xf) <= PXA250_REV_A1)
-+ {
-+ return 0;
-+ }
-+
-+ if( (cpu_ver & 0xf) <= PXA250_REV_B2)
-+ {
-+ if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n");
-+ pxa_valid_freqs = pxa250_valid_freqs;
-+ }
-+ else /* C0 and above */
-+ {
-+ if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n");
-+ pxa_valid_freqs = pxa255_valid_freqs;
-+ }
-+
-+ return 1;
-+}
-+
-+static int __init pxa_clk_init(void)
-+{
-+ if( pxa_init_freqs())
-+ {
-+ if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n");
-+ supported = 1;
-+
-+ cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ);
-+ cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
-+ }
-+ else
-+ {
-+ if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n");
-+ /* Note that we have to initialize the generic code in order to
-+ * release a lock (cpufreq_sem). Any registration for freq changes
-+ * (e.g. lcd driver) will get blocked otherwise.
-+ */
-+ cpufreq_init( 0, 0, 0);
-+ cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
-+ }
-+
-+ return 0;
-+}
-+
-+module_init(pxa_clk_init);
-+
-+MODULE_AUTHOR ("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/csb226.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,180 @@
-+/*
-+ * linux/arch/arm/mach-pxa/csb226.c
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+static unsigned long csb226_irq_en_mask;
-+
-+static void csb226_mask_and_ack_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask &= ~(1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
-+ CSB226_IRQ_SET_CLR &= ~(1 << csb226_irq);
-+}
-+
-+static void csb226_mask_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask &= ~(1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
-+}
-+
-+static void csb226_unmask_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask |= (1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN |= (1 << csb226_irq);
-+}
-+
-+void csb226_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long irq_status;
-+ int i;
-+
-+ while ((irq_status = CSB226_IRQ_SET_CLR & csb226_irq_en_mask)) {
-+ for (i = 0; i < 6; i++) {
-+ if(irq_status & (1<<i))
-+ do_IRQ(CSB226_IRQ(i), regs);
-+ }
-+ }
-+}
-+
-+/* FIXME: this should not be necessary on csb226 */
-+static struct irqaction csb226_irq = {
-+ name: "CSB226 FPGA",
-+ handler: csb226_irq_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+static void __init csb226_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ /* setup extra csb226 irqs */
-+/* RS: ???
-+ for(irq = CSB226_IRQ(0); irq <= CSB226_IRQ(5); irq++)
-+ {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = csb226_mask_and_ack_irq;
-+ irq_desc[irq].mask = csb226_mask_irq;
-+ irq_desc[irq].unmask = csb226_unmask_irq;
-+ }
-+
-+ set_GPIO_IRQ_edge(GPIO_CSB226_IRQ, GPIO_FALLING_EDGE);
-+ setup_arm_irq(IRQ_GPIO_CSB226_IRQ, &csb226_irq);
-+*/
-+}
-+
-+/* FIXME: not necessary on CSB226? */
-+static int __init csb226_init(void)
-+{
-+ int ret;
-+
-+ return 0;
-+}
-+
-+__initcall(csb226_init);
-+
-+static void __init
-+fixup_csb226(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+ mi->nr_banks = 1;
-+#if 0
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+/* FIXME: shouldn't this be moved to arch/arm/mach-pxa/mm.c? [RS] */
-+static struct map_desc csb226_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+// { 0xf4000000, 0x04000000, 0x00ffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* HT4562B PS/2 controller */
-+ { 0xf8000000, 0x08000000, 1024*1024, DOMAIN_IO, 0, 1, 0, 0 }, /* CS8900 LAN controller */
-+// { 0xe0000000, 0x20000000, 0x0fffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* CompactFlash */
-+#if 0
-+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
-+ { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
-+#endif
-+ LAST_DESC
-+};
-+
-+static void __init csb226_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(csb226_io_desc);
-+
-+ /* This enables the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ /* This is for the CS8900 chip select */
-+ set_GPIO_mode(GPIO78_nCS_2_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(CSB226, "Cogent CSB226 Development Platform")
-+ MAINTAINER("Robert Schwebel, Pengutronix")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_csb226)
-+ MAPIO(csb226_map_io)
-+ INITIRQ(csb226_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/dma.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,131 @@
-+/*
-+ * linux/arch/arm/mach-pxa/dma.c
-+ *
-+ * PXA DMA registration and IRQ dispatching
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Nov 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+
-+#include <asm/system.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+
-+static struct dma_channel {
-+ char *name;
-+ void (*irq_handler)(int, void *, struct pt_regs *);
-+ void *data;
-+} dma_channels[16];
-+
-+
-+int pxa_request_dma (char *name, pxa_dma_prio prio,
-+ void (*irq_handler)(int, void *, struct pt_regs *),
-+ void *data)
-+{
-+ unsigned long flags;
-+ int i, found = 0;
-+
-+ /* basic sanity checks */
-+ if (!name || !irq_handler)
-+ return -EINVAL;
-+
-+ local_irq_save(flags);
-+
-+ /* try grabbing a DMA channel with the requested priority */
-+ for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
-+ if (!dma_channels[i].name) {
-+ found = 1;
-+ break;
-+ }
-+ }
-+
-+ if (!found) {
-+ /* requested prio group is full, try hier priorities */
-+ for (i = prio-1; i >= 0; i--) {
-+ if (!dma_channels[i].name) {
-+ found = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (found) {
-+ DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ dma_channels[i].name = name;
-+ dma_channels[i].irq_handler = irq_handler;
-+ dma_channels[i].data = data;
-+ } else {
-+ printk (KERN_WARNING "No more available DMA channels for %s\n", name);
-+ i = -ENODEV;
-+ }
-+
-+ local_irq_restore(flags);
-+ return i;
-+}
-+
-+void pxa_free_dma (int dma_ch)
-+{
-+ unsigned long flags;
-+
-+ if (!dma_channels[dma_ch].name) {
-+ printk (KERN_CRIT __FUNCTION__
-+ ": trying to free channel %d which is already freed\n",
-+ dma_ch);
-+ return;
-+ }
-+
-+ local_irq_save(flags);
-+ DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ dma_channels[dma_ch].name = NULL;
-+ local_irq_restore(flags);
-+}
-+
-+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int i, dint = DINT;
-+
-+ for (i = 0; i < 16; i++) {
-+ if (dint & (1 << i)) {
-+ struct dma_channel *channel = &dma_channels[i];
-+ if (channel->name && channel->irq_handler) {
-+ channel->irq_handler(i, channel->data, regs);
-+ } else {
-+ /*
-+ * IRQ for an unregistered DMA channel:
-+ * let's clear the interrupts and disable it.
-+ */
-+ printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
-+ DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ }
-+ }
-+ }
-+}
-+
-+static int __init pxa_dma_init (void)
-+{
-+ int ret;
-+
-+ ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-+ if (ret)
-+ printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
-+ return ret;
-+}
-+
-+__initcall(pxa_dma_init);
-+
-+EXPORT_SYMBOL(pxa_request_dma);
-+EXPORT_SYMBOL(pxa_free_dma);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/generic.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/arch/arm/mach-pxa/generic.c
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * Code common to all PXA machines.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Since this file should be linked before any other machine specific file,
-+ * the __initcall() here will be executed first. This serves as default
-+ * initialization stuff for PXA machines which can be overriden later if
-+ * need be.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+#include <asm/pgtable.h>
-+#include <asm/mach/map.h>
-+
-+#include "generic.h"
-+
-+/*
-+ * Various clock factors driven by the CCCR register.
-+ */
-+
-+/* Crystal Frequency to Memory Frequency Multiplier (L) */
-+static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
-+
-+/* Memory Frequency to Run Mode Frequency Multiplier (M) */
-+static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
-+
-+/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
-+/* Note: we store the value N * 2 here. */
-+static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
-+
-+/* Crystal clock */
-+#define BASE_CLK 3686400
-+
-+/*
-+ * Get the clock frequency as reflected by CCCR and the turbo flag.
-+ * We assume these values have been applied via a fcs.
-+ * If info is not 0 we also display the current settings.
-+ */
-+unsigned int get_clk_frequency_khz( int info)
-+{
-+ unsigned long cccr, turbo;
-+ unsigned int l, L, m, M, n2, N;
-+
-+ cccr = CCCR;
-+ asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) );
-+
-+ l = L_clk_mult[(cccr >> 0) & 0x1f];
-+ m = M_clk_mult[(cccr >> 5) & 0x03];
-+ n2 = N2_clk_mult[(cccr >> 7) & 0x07];
-+
-+ L = l * BASE_CLK;
-+ M = m * L;
-+ N = n2 * M / 2;
-+
-+ if( info)
-+ {
-+ L += 5000;
-+ printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n",
-+ L / 1000000, (L % 1000000) / 10000, l );
-+ M += 5000;
-+ printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n",
-+ M / 1000000, (M % 1000000) / 10000, m );
-+ N += 5000;
-+ printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n",
-+ N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5,
-+ (turbo & 1) ? "" : "in" );
-+ }
-+
-+ return (turbo & 1) ? (N/1000) : (M/1000);
-+}
-+
-+EXPORT_SYMBOL(get_clk_frequency_khz);
-+
-+/*
-+ * Return the current lclk requency in units of 10kHz
-+ */
-+unsigned int get_lclk_frequency_10khz(void)
-+{
-+ return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
-+}
-+
-+EXPORT_SYMBOL(get_lclk_frequency_10khz);
-+
-+/*
-+ * Handy function to set GPIO alternate functions
-+ */
-+
-+void set_GPIO_mode(int gpio_mode)
-+{
-+ long flags;
-+ int gpio = gpio_mode & GPIO_MD_MASK_NR;
-+ int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
-+ int gafr;
-+
-+ local_irq_save(flags);
-+ if (gpio_mode & GPIO_MD_MASK_DIR)
-+ GPDR(gpio) |= GPIO_bit(gpio);
-+ else
-+ GPDR(gpio) &= ~GPIO_bit(gpio);
-+ gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
-+ GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
-+ local_irq_restore(flags);
-+}
-+
-+EXPORT_SYMBOL(set_GPIO_mode);
-+
-+/*
-+ * Note that 0xfffe0000-0xffffffff is reserved for the vector table and
-+ * cache flush area.
-+ */
-+static struct map_desc standard_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
-+ { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
-+ { 0xf8000000, 0x40000000, 0x01800000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */
-+ { 0xfa000000, 0x44000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
-+ { 0xfc000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */
-+ { 0xff000000, 0x00000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* UNCACHED_PHYS_0 */
-+ LAST_DESC
-+};
-+
-+void __init pxa_map_io(void)
-+{
-+ iotable_init(standard_io_desc);
-+ get_clk_frequency_khz( 1);
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/generic.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,19 @@
-+/*
-+ * linux/arch/arm/mach-pxa/generic.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+extern void __init pxa_map_io(void);
-+extern void __init pxa_init_irq(void);
-+
-+#define SET_BANK(__nr,__start,__size) \
-+ mi->bank[__nr].start = (__start), \
-+ mi->bank[__nr].size = (__size), \
-+ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/idp.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/arch/arm/mach-pxa/idp.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
-+ *
-+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
-+ * Initial code
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+#define PXA_IDP_REV02
-+
-+#ifndef PXA_IDP_REV02
-+/* shadow registers for write only registers */
-+unsigned int idp_cpld_led_control_shadow = 0x1;
-+unsigned int idp_cpld_periph_pwr_shadow = 0xd;
-+unsigned int ipd_cpld_cir_shadow = 0;
-+unsigned int idp_cpld_kb_col_high_shadow = 0;
-+unsigned int idp_cpld_kb_col_low_shadow = 0;
-+unsigned int idp_cpld_pccard_en_shadow = 0xC3;
-+unsigned int idp_cpld_gpioh_dir_shadow = 0;
-+unsigned int idp_cpld_gpioh_value_shadow = 0;
-+unsigned int idp_cpld_gpiol_dir_shadow = 0;
-+unsigned int idp_cpld_gpiol_value_shadow = 0;
-+
-+/*
-+ * enable all LCD signals -- they should still be on
-+ * write protect flash
-+ * enable all serial port transceivers
-+ */
-+
-+unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */
-+ (0x1 << 19) | /* disable flash write enable */
-+ (0x7 << 9)); /* enable serial port transeivers */
-+
-+#endif
-+
-+static int __init idp_init(void)
-+{
-+ printk("idp_init()\n");
-+ return 0;
-+}
-+
-+__initcall(idp_init);
-+
-+static void __init idp_init_irq(void)
-+{
-+ pxa_init_irq();
-+}
-+
-+static void __init
-+fixup_idp(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+#ifdef PXA_IDP_REV02
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+#else
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+#endif
-+ mi->nr_banks = 1;
-+#if 0
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+static struct map_desc idp_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+
-+
-+#ifndef PXA_IDP_REV02
-+ { IDP_CTRL_PORT_BASE,
-+ IDP_CTRL_PORT_PHYS,
-+ IDP_CTRL_PORT_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+#endif
-+
-+ { IDP_IDE_BASE,
-+ IDP_IDE_PHYS,
-+ IDP_IDE_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_ETH_BASE,
-+ IDP_ETH_PHYS,
-+ IDP_ETH_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_COREVOLT_BASE,
-+ IDP_COREVOLT_PHYS,
-+ IDP_COREVOLT_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_CPLD_BASE,
-+ IDP_CPLD_PHYS,
-+ IDP_CPLD_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+
-+ LAST_DESC
-+};
-+
-+static void __init idp_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(idp_io_desc);
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(SMC_IRQ), GPIO_RISING_EDGE);
-+}
-+
-+MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
-+ MAINTAINER("Accelent Systems Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
-+ FIXUP(fixup_idp)
-+ MAPIO(idp_map_io)
-+ INITIRQ(idp_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/innokom.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,129 @@
-+/*
-+ * linux/arch/arm/mach-pxa/innokom.c
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+
-+static void __init innokom_init_irq(void)
-+{
-+ pxa_init_irq();
-+}
-+
-+
-+void sw_update_handler( int irq, void* dev_id,struct pt_regs* regs)
-+{
-+}
-+
-+
-+void reset_handler( int irq, void* dev_id,struct pt_regs* regs)
-+{
-+}
-+
-+
-+static int __init innokom_init(void)
-+{
-+ int sw_irq = GPIO_2_80_TO_IRQ(11); /* software update button */
-+ int reset_irq = GPIO_2_80_TO_IRQ(3); /* reset button */
-+
-+ set_GPIO_IRQ_edge(11,GPIO_FALLING_EDGE);
-+ if (request_irq(sw_irq,sw_update_handler,SA_INTERRUPT,"software update button",NULL))
-+ printk(KERN_INFO "innokom: can't get assigned irq %i\n",sw_irq);
-+
-+ set_GPIO_IRQ_edge(3,GPIO_FALLING_EDGE);
-+ if (request_irq(reset_irq,reset_handler,SA_INTERRUPT,"reset button",NULL))
-+ printk(KERN_INFO "innokom: can't get assigned irq %i\n",reset_irq);
-+
-+ return 0;
-+}
-+
-+
-+__initcall(innokom_init);
-+
-+
-+static void __init
-+fixup_innokom(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ /* we probably want to get this information from the bootloader later */
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+ mi->nr_banks = 1;
-+}
-+
-+
-+/* memory mapping */
-+static struct map_desc innokom_io_desc[] __initdata = {
-+/* virtual physical length domain r w c b */
-+ { INNOKOM_ETH_BASE, INNOKOM_ETH_PHYS, INNOKOM_ETH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* ETH SMSC 91111 */
-+ LAST_DESC
-+};
-+
-+static void __init innokom_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(innokom_io_desc);
-+
-+ /* Enable the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ set_GPIO_mode(GPIO33_nCS_5_MD); /* SMSC network chip */
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(INNOKOM, "Auerswald Innokom")
-+ MAINTAINER("Robert Schwebel, Pengutronix")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_innokom)
-+ MAPIO(innokom_map_io)
-+ INITIRQ(innokom_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/irq.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,282 @@
-+/*
-+ * linux/arch/arm/mach-pxa/irq.c
-+ *
-+ * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/ptrace.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/mach/irq.h>
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+
-+/*
-+ * PXA GPIO edge detection for IRQs:
-+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
-+ * This must be called *before* the appropriate IRQ is registered.
-+ * Use this instead of directly setting GRER/GFER.
-+ */
-+
-+static int GPIO_IRQ_rising_edge[3];
-+static int GPIO_IRQ_falling_edge[3];
-+
-+void set_GPIO_IRQ_edge (int gpio_nr, int edge)
-+{
-+ long flags;
-+ local_irq_save(flags);
-+ set_GPIO_mode(gpio_nr | GPIO_IN);
-+ if (edge & GPIO_FALLING_EDGE)
-+ set_bit (gpio_nr, GPIO_IRQ_falling_edge);
-+ else
-+ clear_bit (gpio_nr, GPIO_IRQ_falling_edge);
-+ if (edge & GPIO_RISING_EDGE)
-+ set_bit (gpio_nr, GPIO_IRQ_rising_edge);
-+ else
-+ clear_bit (gpio_nr, GPIO_IRQ_rising_edge);
-+ irq_desc[IRQ_GPIO(gpio_nr)].valid = 1;
-+ local_irq_restore(flags);
-+}
-+
-+EXPORT_SYMBOL(set_GPIO_IRQ_edge);
-+
-+
-+/*
-+ * We don't need to ACK IRQs on the PXA unless they're GPIOs
-+ * this is for IRQs known as PXA_IRQ([10...31]).
-+ */
-+
-+static void pxa_mask_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+static void pxa_unmask_irq(unsigned int irq)
-+{
-+ ICMR |= (1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+/*
-+ * GPIO IRQs must be acknoledged. This is for GPIO 0 and 1.
-+ */
-+
-+static void pxa_mask_and_ack_GPIO_0_1_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+ GEDR0 = (1 << (irq - IRQ_GPIO0));
-+}
-+
-+static void pxa_mask_GPIO_0_1_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+static void pxa_unmask_GPIO_0_1_irq(unsigned int irq)
-+{
-+ int gpio = irq - IRQ_GPIO0;
-+ GRER0 = (GRER0 & ~(1 << gpio))|(GPIO_IRQ_rising_edge[0] & (1 << gpio));
-+ GFER0 = (GFER0 & ~(1 << gpio))|(GPIO_IRQ_falling_edge[0] & (1 << gpio));
-+ ICMR |= (1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+/*
-+ * Demux handler for GPIO 2-80 edge detect interrupts
-+ */
-+
-+static int GPIO_2_80_enabled[3]; /* enabled i.e. unmasked GPIO IRQs */
-+static int GPIO_2_80_spurious[3]; /* GPIOs that triggered when masked */
-+
-+static void pxa_GPIO_2_80_demux(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ int i, gedr, spurious;
-+
-+ while ((gedr = (GEDR0 & ~3))) {
-+ /*
-+ * We don't want to clear GRER/GFER when the corresponding
-+ * IRQ is masked because we could miss a level transition
-+ * i.e. an IRQ which need servicing as soon as it is
-+ * unmasked. However, such situation should happen only
-+ * during the loop below. Thus all IRQs which aren't
-+ * enabled at this point are considered spurious. Those
-+ * are cleared but only de-activated if they happen twice.
-+ */
-+ spurious = gedr & ~GPIO_2_80_enabled[0];
-+ if (spurious) {
-+ GEDR0 = spurious;
-+ GRER0 &= ~(spurious & GPIO_2_80_spurious[0]);
-+ GFER0 &= ~(spurious & GPIO_2_80_spurious[0]);
-+ GPIO_2_80_spurious[0] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 2; i < 32; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(2) + i - 2, regs);
-+ }
-+ }
-+ }
-+ while ((gedr = GEDR1)) {
-+ spurious = gedr & ~GPIO_2_80_enabled[1];
-+ if (spurious) {
-+ GEDR1 = spurious;
-+ GRER1 &= ~(spurious & GPIO_2_80_spurious[1]);
-+ GFER1 &= ~(spurious & GPIO_2_80_spurious[1]);
-+ GPIO_2_80_spurious[1] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 0; i < 32; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(32) + i, regs);
-+ }
-+ }
-+ }
-+ while ((gedr = (GEDR2 & 0x0001ffff))) {
-+ spurious = gedr & ~GPIO_2_80_enabled[2];
-+ if (spurious) {
-+ GEDR2 = spurious;
-+ GRER2 &= ~(spurious & GPIO_2_80_spurious[2]);
-+ GFER2 &= ~(spurious & GPIO_2_80_spurious[2]);
-+ GPIO_2_80_spurious[2] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 0; i < 17; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(64) + i, regs);
-+ }
-+ }
-+ }
-+}
-+
-+static struct irqaction GPIO_2_80_irqaction = {
-+ name: "GPIO 2-80",
-+ handler: pxa_GPIO_2_80_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+#define GRER_x(i) (*(&GRER0 + (i)))
-+#define GFER_x(i) (*(&GFER0 + (i)))
-+#define GEDR_x(i) (*(&GEDR0 + (i)))
-+#define GPLR_x(i) (*(&GPLR0 + (i)))
-+
-+static void pxa_mask_and_ack_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ GPIO_2_80_spurious[index] &= ~mask;
-+ GPIO_2_80_enabled[index] &= ~mask;
-+ GEDR_x(index) = mask;
-+}
-+
-+static void pxa_mask_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ GPIO_2_80_spurious[index] &= ~mask;
-+ GPIO_2_80_enabled[index] &= ~mask;
-+}
-+
-+static void pxa_unmask_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ if (GPIO_2_80_spurious[index] & mask) {
-+ /*
-+ * We don't want to miss an interrupt that would have occurred
-+ * while it was masked. Simulate it if it is the case.
-+ */
-+ int state = GPLR_x(index);
-+ if (((state & GPIO_IRQ_rising_edge[index]) |
-+ (~state & GPIO_IRQ_falling_edge[index])) & mask)
-+ {
-+ /* just in case it gets referenced: */
-+ struct pt_regs dummy;
-+
-+ memzero(&dummy, sizeof(dummy));
-+ do_IRQ(irq, &dummy);
-+
-+ /* we are being called recursively from do_IRQ() */
-+ return;
-+ }
-+ }
-+ GPIO_2_80_enabled[index] |= mask;
-+ GRER_x(index) =
-+ (GRER_x(index) & ~mask) | (GPIO_IRQ_rising_edge[index] & mask);
-+ GFER_x(index) =
-+ (GFER_x(index) & ~mask) | (GPIO_IRQ_falling_edge[index] & mask);
-+}
-+
-+
-+void __init pxa_init_irq(void)
-+{
-+ int irq;
-+
-+ /* disable all IRQs */
-+ ICMR = 0;
-+
-+ /* all IRQs are IRQ, not FIQ */
-+ ICLR = 0;
-+
-+ /* clear all GPIO edge detects */
-+ GFER0 = GFER1 = GFER2 = 0;
-+ GRER0 = GRER1 = GRER2 = 0;
-+ GEDR0 = GEDR0;
-+ GEDR1 = GEDR1;
-+ GEDR2 = GEDR2;
-+
-+ /* only unmasked interrupts kick us out of idle */
-+ ICCR = 1;
-+
-+ for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 0;
-+ irq_desc[irq].mask_ack = pxa_mask_irq;
-+ irq_desc[irq].mask = pxa_mask_irq;
-+ irq_desc[irq].unmask = pxa_unmask_irq;
-+ }
-+
-+ /*
-+ * Note: GPIO IRQs are initially invalid until set_GPIO_IRQ_edge()
-+ * is called at least once.
-+ */
-+
-+ for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-+ irq_desc[irq].valid = 0;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_0_1_irq;
-+ irq_desc[irq].mask = pxa_mask_GPIO_0_1_irq;
-+ irq_desc[irq].unmask = pxa_unmask_GPIO_0_1_irq;
-+ }
-+
-+ for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
-+ irq_desc[irq].valid = 0;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_2_80_irq;
-+ irq_desc[irq].mask = pxa_mask_GPIO_2_80_irq;
-+ irq_desc[irq].unmask = pxa_unmask_GPIO_2_80_irq;
-+ }
-+ setup_arm_irq( IRQ_GPIO_2_80, &GPIO_2_80_irqaction );
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/leds-cerf.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,135 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-cerf.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void pxa_cerf_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= CERF_HEARTBEAT_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= CERF_SYS_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~CERF_SYS_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+#ifndef CONFIG_PXA_CERF_PDA
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~CERF_SYS_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= CERF_SYS_BUSY_LED;
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ {
-+ switch (hw_led_state) {
-+ case 0: // all on
-+ CERF_HEARTBEAT_LED_ON;
-+ CERF_SYS_BUSY_LED_ON;
-+ break;
-+ case 1: // turn off heartbeat, status on:
-+ CERF_HEARTBEAT_LED_OFF;
-+ CERF_SYS_BUSY_LED_ON;
-+ break;
-+ case 2: // status off, heartbeat on:
-+ CERF_HEARTBEAT_LED_ON;
-+ CERF_SYS_BUSY_LED_OFF;
-+ break;
-+ case 3: // turn them both off...
-+ CERF_HEARTBEAT_LED_OFF;
-+ CERF_SYS_BUSY_LED_OFF;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ local_irq_restore(flags);
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/leds-idp.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,112 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-idp.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * Macros for actual LED manipulation should be in machine specific
-+ * files in this 'mach' directory.
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void idp_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= IDP_HB_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= IDP_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~IDP_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~IDP_HB_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= IDP_HB_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~IDP_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= IDP_BUSY_LED;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ IDP_WRITE_LEDS(hw_led_state);
-+
-+ local_irq_restore(flags);
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/leds-lubbock.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,134 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-lubbock.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * See leds.h for bit definitions. The first version defines D28 on the
-+ * Lubbock dev board as the heartbeat, and D27 as the Sys_busy led.
-+ * There's plenty more if you're interested in adding them :)
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void lubbock_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= HEARTBEAT_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= SYS_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~SYS_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~HEARTBEAT_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= HEARTBEAT_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~SYS_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= SYS_BUSY_LED;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ {
-+ switch (hw_led_state) {
-+ case 0: // all on
-+ HEARTBEAT_LED_ON;
-+ SYS_BUSY_LED_ON;
-+ break;
-+ case 1: // turn off heartbeat, status on:
-+ HEARTBEAT_LED_OFF;
-+ SYS_BUSY_LED_ON;
-+ break;
-+ case 2: // status off, heartbeat on:
-+ HEARTBEAT_LED_ON;
-+ SYS_BUSY_LED_OFF;
-+ break;
-+ case 3: // turn them both off...
-+ HEARTBEAT_LED_OFF;
-+ SYS_BUSY_LED_OFF;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ local_irq_restore(flags);
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/leds.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,32 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds.c
-+ *
-+ * xscale LEDs dispatcher
-+ *
-+ * Copyright (C) 2001 Nicolas Pitre
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
-+ */
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/leds.h>
-+#include <asm/mach-types.h>
-+
-+#include "leds.h"
-+
-+static int __init
-+pxa_leds_init(void)
-+{
-+ if (machine_is_lubbock())
-+ leds_event = lubbock_leds_event;
-+ if (machine_is_pxa_idp())
-+ leds_event = idp_leds_event;
-+ if (machine_is_pxa_cerf())
-+ leds_event = pxa_cerf_leds_event;
-+
-+ leds_event(led_start);
-+ return 0;
-+}
-+
-+__initcall(pxa_leds_init);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/leds.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,12 @@
-+/*
-+ * include/asm-arm/arch-pxa/leds.h
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
-+ *
-+ * blinky lights for various PXA-based systems:
-+ *
-+ */
-+
-+extern void lubbock_leds_event(led_event_t evt);
-+extern void idp_leds_event(led_event_t evt);
-+extern void pxa_cerf_leds_event(led_event_t evt);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/lubbock.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,157 @@
-+/*
-+ * linux/arch/arm/mach-pxa/lubbock.c
-+ *
-+ * Support for the Intel DBPXA250 Development Platform.
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/bitops.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+#ifdef CONFIG_SA1111
-+ #include "sa1111.h"
-+#endif
-+
-+
-+static unsigned long lubbock_irq_enabled;
-+
-+static void lubbock_mask_irq(unsigned int irq)
-+{
-+ int lubbock_irq = (irq - LUBBOCK_IRQ(0));
-+ LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
-+}
-+
-+static void lubbock_unmask_irq(unsigned int irq)
-+{
-+ int lubbock_irq = (irq - LUBBOCK_IRQ(0));
-+ /* the irq can be acknowledged only if deasserted, so it's done here */
-+ LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
-+ LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
-+}
-+
-+void lubbock_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
-+ do {
-+ GEDR(0) = GPIO_bit(0); /* clear useless edge notification */
-+ if (likely(pending))
-+ do_IRQ( LUBBOCK_IRQ(0) + __ffs(pending), regs );
-+ pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
-+ } while (pending);
-+}
-+
-+static struct irqaction lubbock_irq = {
-+ name: "Lubbock FPGA",
-+ handler: lubbock_irq_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+static void __init lubbock_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ /* setup extra lubbock irqs */
-+ for(irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = lubbock_mask_irq;
-+ irq_desc[irq].mask = lubbock_mask_irq;
-+ irq_desc[irq].unmask = lubbock_unmask_irq;
-+ }
-+
-+ set_GPIO_IRQ_edge(GPIO_LUBBOCK_IRQ, GPIO_FALLING_EDGE);
-+ setup_arm_irq(IRQ_GPIO_LUBBOCK_IRQ, &lubbock_irq);
-+}
-+
-+static int __init lubbock_init(void)
-+{
-+ int ret;
-+
-+ ret = sa1111_probe(LUBBOCK_SA1111_BASE);
-+ if (ret)
-+ return ret;
-+ sa1111_wake();
-+ sa1111_init_irq(LUBBOCK_SA1111_IRQ);
-+ return 0;
-+}
-+
-+__initcall(lubbock_init);
-+
-+static void __init
-+fixup_lubbock(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ /* Some boards have 32MB some 64MB. Let's use a safe default */
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+ mi->nr_banks = 1;
-+}
-+
-+static struct map_desc lubbock_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
-+ { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
-+ LAST_DESC
-+};
-+
-+static void __init lubbock_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(lubbock_io_desc);
-+
-+ /* This enables the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ /* This is for the SMC chip select */
-+ set_GPIO_mode(GPIO79_nCS_3_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform")
-+ MAINTAINER("MontaVista Software Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ FIXUP(fixup_lubbock)
-+ MAPIO(lubbock_map_io)
-+ INITIRQ(lubbock_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/pm.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,265 @@
-+/*
-+ * PXA250/210 Power Management Routines
-+ *
-+ * Original code for the SA11x0:
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * Modified for the PXA250 by Nicolas Pitre:
-+ * Copyright (c) 2002 Monta Vista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+
-+
-+/*
-+ * Debug macros
-+ */
-+#undef DEBUG
-+
-+extern void pxa_cpu_suspend(void);
-+extern void pxa_cpu_resume(void);
-+
-+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
-+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-+
-+/*
-+ * List of global PXA peripheral registers to preserve.
-+ * More ones like CP and general purpose register values are preserved
-+ * with the stack pointer in sleep.S.
-+ */
-+enum { SLEEP_SAVE_START = 0,
-+
-+ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
-+ SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
-+
-+ SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
-+ SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
-+ SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
-+ SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L,
-+ SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U,
-+
-+ SLEEP_SAVE_FFIER, SLEEP_SAVE_FFLCR, SLEEP_SAVE_FFMCR,
-+ SLEEP_SAVE_FFSPR, SLEEP_SAVE_FFISR,
-+ SLEEP_SAVE_FFDLL, SLEEP_SAVE_FFDLH,
-+
-+ SLEEP_SAVE_ICMR,
-+ SLEEP_SAVE_CKEN,
-+
-+ SLEEP_SAVE_CKSUM,
-+
-+ SLEEP_SAVE_SIZE
-+};
-+
-+
-+int pm_do_suspend(void)
-+{
-+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+ unsigned long checksum = 0;
-+ int i;
-+
-+ cli();
-+ clf();
-+
-+ leds_event(led_stop);
-+
-+ /* preserve current time */
-+ RCNR = xtime.tv_sec;
-+
-+ /*
-+ * Temporary solution. This won't be necessary once
-+ * we move pxa support into the serial/* driver
-+ * Save the FF UART
-+ */
-+ SAVE(FFIER);
-+ SAVE(FFLCR);
-+ SAVE(FFMCR);
-+ SAVE(FFSPR);
-+ SAVE(FFISR);
-+ FFLCR |= 0x80;
-+ SAVE(FFDLL);
-+ SAVE(FFDLH);
-+ FFLCR &= 0xef;
-+
-+ /* save vital registers */
-+ SAVE(OSCR);
-+ SAVE(OSMR0);
-+ SAVE(OSMR1);
-+ SAVE(OSMR2);
-+ SAVE(OSMR3);
-+ SAVE(OIER);
-+
-+ SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
-+ SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
-+ SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
-+ SAVE(GAFR0_L); SAVE(GAFR0_U);
-+ SAVE(GAFR1_L); SAVE(GAFR1_U);
-+ SAVE(GAFR2_L); SAVE(GAFR2_U);
-+
-+ SAVE(ICMR);
-+ ICMR = 0;
-+
-+ SAVE(CKEN);
-+ CKEN = 0;
-+
-+ /* Note: wake up source are set up in each machine specific files */
-+
-+ /* clear GPIO transition detect bits */
-+ GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
-+
-+ /* Clear sleep reset status */
-+ RCSR = RCSR_SMR;
-+
-+ /* set resume return address */
-+ PSPR = virt_to_phys(pxa_cpu_resume);
-+
-+ /* before sleeping, calculate and save a checksum */
-+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
-+ checksum += sleep_save[i];
-+ sleep_save[SLEEP_SAVE_CKSUM] = checksum;
-+
-+ /* *** go zzz *** */
-+ pxa_cpu_suspend();
-+
-+ /* after sleeping, validate the checksum */
-+ checksum = 0;
-+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
-+ checksum += sleep_save[i];
-+
-+ /* if invalid, display message and wait for a hardware reset */
-+ if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
-+#ifdef CONFIG_ARCH_LUBBOCK
-+ LUB_HEXLED = 0xbadbadc5;
-+#endif
-+ while (1);
-+ }
-+
-+ /* ensure not to come back here if it wasn't intended */
-+ PSPR = 0;
-+
-+ /* restore registers */
-+ RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
-+ RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
-+ RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
-+ RESTORE(GAFR0_L); RESTORE(GAFR0_U);
-+ RESTORE(GAFR1_L); RESTORE(GAFR1_U);
-+ RESTORE(GAFR2_L); RESTORE(GAFR2_U);
-+
-+ PSSR = PSSR_PH;
-+
-+ RESTORE(OSMR0);
-+ RESTORE(OSMR1);
-+ RESTORE(OSMR2);
-+ RESTORE(OSMR3);
-+ RESTORE(OSCR);
-+ RESTORE(OIER);
-+
-+ RESTORE(CKEN);
-+
-+ ICLR = 0;
-+ ICCR = 1;
-+ RESTORE(ICMR);
-+
-+ /*
-+ * Temporary solution. This won't be necessary once
-+ * we move pxa support into the serial/* driver.
-+ * Restore the FF UART.
-+ */
-+ RESTORE(FFMCR);
-+ RESTORE(FFSPR);
-+ RESTORE(FFLCR);
-+ FFLCR |= 0x80;
-+ RESTORE(FFDLH);
-+ RESTORE(FFDLL);
-+ RESTORE(FFLCR);
-+ RESTORE(FFISR);
-+ FFFCR = 0x07;
-+ RESTORE(FFIER);
-+
-+ /* restore current time */
-+ xtime.tv_sec = RCNR;
-+
-+#ifdef DEBUG
-+ printk(KERN_DEBUG "*** made it back from resume\n");
-+#endif
-+
-+ leds_event(led_start);
-+
-+ sti();
-+
-+ return 0;
-+}
-+
-+unsigned long sleep_phys_sp(void *sp)
-+{
-+ return virt_to_phys(sp);
-+}
-+
-+#ifdef CONFIG_SYSCTL
-+/*
-+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
-+ * linux/sysctl.h.
-+ *
-+ * This means our interface here won't survive long - it needs a new
-+ * interface. Quick hack to get this working - use sysctl id 9999.
-+ */
-+#warning ACPI broke the kernel, this interface needs to be fixed up.
-+#define CTL_ACPI 9999
-+#define ACPI_S1_SLP_TYP 19
-+
-+/*
-+ * Send us to sleep.
-+ */
-+static int sysctl_pm_do_suspend(void)
-+{
-+ int retval;
-+
-+ retval = pm_send_all(PM_SUSPEND, (void *)3);
-+
-+ if (retval == 0) {
-+ retval = pm_do_suspend();
-+
-+ pm_send_all(PM_RESUME, (void *)0);
-+ }
-+
-+ return retval;
-+}
-+
-+static struct ctl_table pm_table[] =
-+{
-+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
-+ {0}
-+};
-+
-+static struct ctl_table pm_dir_table[] =
-+{
-+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-+ {0}
-+};
-+
-+/*
-+ * Initialize power interface
-+ */
-+static int __init pm_init(void)
-+{
-+ register_sysctl_table(pm_dir_table, 1);
-+ return 0;
-+}
-+
-+__initcall(pm_init);
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/pxa_usb.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,230 @@
-+/*
-+ * pxa_usb.h
-+ *
-+ * Public interface to the pxa USB core. For use by client modules
-+ * like usb-eth and usb-char.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100_usb.h
-+ *
-+ */
-+
-+#ifndef _PXA_USB_H
-+#define _PXA_USB_H
-+#include <asm/byteorder.h>
-+
-+typedef void (*usb_callback_t)(int flag, int size);
-+
-+/* in usb_ctl.c (see also descriptor methods at bottom of file) */
-+
-+// Open the USB client for client and initialize data structures
-+// to default values, but _do not_ start UDC.
-+int pxa_usb_open( const char * client_name );
-+
-+// Start UDC running
-+int pxa_usb_start( void );
-+
-+// Immediately stop udc, fire off completion routines w/-EINTR
-+int pxa_usb_stop( void ) ;
-+
-+// Disconnect client from usb core
-+int pxa_usb_close( void ) ;
-+
-+// set notify callback for when core reaches configured state
-+// return previous pointer (if any)
-+typedef void (*usb_notify_t)(void);
-+usb_notify_t pxa_set_configured_callback( usb_notify_t callback );
-+
-+/* in usb_send.c */
-+int pxa_usb_xmitter_avail( void );
-+int pxa_usb_send(char *buf, int len, usb_callback_t callback);
-+void sa110a_usb_send_reset(void);
-+
-+/* in usb_recev.c */
-+int pxa_usb_recv(char *buf, int len, usb_callback_t callback);
-+void pxa_usb_recv_reset(void);
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Descriptor Management
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define DescriptorHeader \
-+ __u8 bLength; \
-+ __u8 bDescriptorType
-+
-+
-+// --- Device Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bcdUSB; /* USB specification revision number in BCD */
-+ __u8 bDeviceClass; /* USB class for entire device */
-+ __u8 bDeviceSubClass; /* USB subclass information for entire device */
-+ __u8 bDeviceProtocol; /* USB protocol information for entire device */
-+ __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
-+ __u16 idVendor; /* USB vendor ID */
-+ __u16 idProduct; /* USB product ID */
-+ __u16 bcdDevice; /* vendor assigned device release number */
-+ __u8 iManufacturer; /* index of manufacturer string */
-+ __u8 iProduct; /* index of string that describes product */
-+ __u8 iSerialNumber; /* index of string containing device serial number */
-+ __u8 bNumConfigurations; /* number fo configurations */
-+} __attribute__ ((packed)) device_desc_t;
-+
-+// --- Configuration Descriptor ------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
-+ __u8 bNumInterfaces; /* number of interfaces in this cfg */
-+ __u8 bConfigurationValue; /* used to uniquely ID this cfg */
-+ __u8 iConfiguration; /* index of string describing configuration */
-+ __u8 bmAttributes; /* bitmap of attributes for ths cfg */
-+ __u8 MaxPower; /* power draw in 2ma units */
-+} __attribute__ ((packed)) config_desc_t;
-+
-+// bmAttributes:
-+enum {
-+ USB_CONFIG_REMOTEWAKE=0x20,
-+ USB_CONFIG_SELFPOWERED=0x40,
-+ USB_CONFIG_BUSPOWERED=0x80
-+};
-+
-+// MaxPower:
-+#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
-+
-+// --- Interface Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
-+ __u8 bAlternateSetting; /* ids an alternate setting for this interface */
-+ __u8 bNumEndpoints; /* number of endpoints in this interface */
-+ __u8 bInterfaceClass; /* USB class info applying to this interface */
-+ __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
-+ __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
-+ __u8 iInterface; /* index of string describing interface */
-+} __attribute__ ((packed)) intf_desc_t;
-+
-+// --- Endpoint Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
-+ __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
-+ __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
-+ __u8 bInterval; /* polling interval for this ep in this cfg */
-+} __attribute__ ((packed)) ep_desc_t;
-+
-+// bEndpointAddress:
-+enum {
-+ USB_OUT =0,
-+ USB_IN =1
-+};
-+
-+#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
-+// bmAttributes:
-+enum {
-+ USB_EP_CNTRL =0,
-+ USB_EP_BULK =2,
-+ USB_EP_INT =3,
-+ USB_EP_ISO =4
-+};
-+
-+// --- String Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
-+} __attribute__ ((packed)) string_desc_t;
-+
-+/*=======================================================
-+ * Handy helpers when working with above
-+ *
-+ */
-+// these are x86-style 16 bit "words" ...
-+#define make_word_c( w ) __constant_cpu_to_le16(w)
-+#define make_word( w ) __cpu_to_le16(w)
-+
-+// descriptor types
-+enum {
-+ USB_DESC_DEVICE = 1,
-+ USB_DESC_CONFIG = 2,
-+ USB_DESC_STRING = 3,
-+ USB_DESC_INTERFACE = 4,
-+ USB_DESC_ENDPOINT = 5
-+};
-+
-+
-+/*=======================================================
-+ * Default descriptor layout for SA-1100 and SA-1110 UDC
-+ */
-+
-+enum {
-+ UNUSED = 0,
-+
-+ BULK_IN1 = 1,
-+ BULK_OUT1 = 2,
-+ ISO_IN1 = 3,
-+ ISO_OUT1 = 4,
-+ INT_IN1 = 5,
-+
-+ BULK_IN2 = 6,
-+ BULK_OUT2 = 7,
-+ ISO_IN2 = 8,
-+ ISO_OUT2 = 9,
-+ INT_IN2 = 10,
-+
-+ BULK_IN3 = 11,
-+ BULK_OUT3 = 12,
-+ ISO_IN3 = 13,
-+ ISO_OUT3 = 14,
-+ INT_IN3 = 15
-+} /*endpoint_type*/;
-+
-+/* "config descriptor buffer" - that is, one config,
-+ ..one interface and 2 endpoints */
-+struct cdb {
-+ config_desc_t cfg;
-+ intf_desc_t intf;
-+ ep_desc_t ep1;
-+ ep_desc_t ep2;
-+} __attribute__ ((packed));
-+
-+/* all SA device descriptors */
-+typedef struct {
-+ device_desc_t dev; /* device descriptor */
-+ struct cdb b; /* bundle of descriptors for this cfg */
-+} __attribute__ ((packed)) desc_t;
-+
-+
-+/*=======================================================
-+ * Descriptor API
-+ */
-+
-+/* Get the address of the statically allocated desc_t structure
-+ in the usb core driver. Clients can modify this between
-+ the time they call pxa_usb_open() and pxa_usb_start()
-+*/
-+desc_t *
-+pxa_usb_get_descriptor_ptr( void );
-+
-+
-+/* Set a pointer to the string descriptor at "index". The driver
-+ ..has room for 8 string indicies internally. Index zero holds
-+ ..a LANGID code and is set to US English by default. Inidices
-+ ..1-7 are available for use in the config descriptors as client's
-+ ..see fit. This pointer is assumed to be good as long as the
-+ ..SA usb core is open (so statically allocate them). Returnes -EINVAL
-+ ..if index out of range */
-+int pxa_usb_set_string_descriptor( int index, string_desc_t * p );
-+
-+/* reverse of above */
-+string_desc_t *
-+pxa_usb_get_string_descriptor( int index );
-+
-+/* kmalloc() a string descriptor and convert "p" to unicode in it */
-+string_desc_t *
-+pxa_usb_kmalloc_string_descriptor( const char * p );
-+
-+#endif /* _PXA_USB_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/sa1111.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,3 @@
-+#include "../mach-sa1100/sa1111.c"
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/sa1111.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,2 @@
-+#include "../mach-sa1100/sa1111.h"
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/sleep.S 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,150 @@
-+/*
-+ * Low-level PXA250/210 sleep/wakeUp support
-+ *
-+ * Initial SA1110 code:
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * Adapted for PXA by Nicolas Pitre:
-+ * Copyright (c) 2002 Monta Vista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/assembler.h>
-+#include <asm/hardware.h>
-+
-+ .text
-+
-+/*
-+ * pxa_cpu_suspend()
-+ *
-+ * Forces CPU into sleep state
-+ */
-+
-+ENTRY(pxa_cpu_suspend)
-+
-+ mra r2, r3, acc0
-+ stmfd sp!, {r2 - r12, lr} @ save registers on stack
-+
-+ @ get coprocessor registers
-+ mrc p15, 0, r4, c15, c1, 0 @ CP access reg
-+ mrc p15, 0, r5, c13, c0, 0 @ PID
-+ mrc p15, 0, r6, c3, c0, 0 @ domain ID
-+ mrc p15, 0, r7, c2, c0, 0 @ translation table base addr
-+ mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
-+ mrc p15, 0, r9, c1, c0, 0 @ control reg
-+
-+ @ store them plus current virtual stack ptr on stack
-+ mov r10, sp
-+ stmfd sp!, {r4 - r10}
-+
-+ @ preserve phys address of stack
-+ mov r0, sp
-+ bl sleep_phys_sp
-+ ldr r1, =sleep_save_sp
-+ str r0, [r1]
-+
-+ @ clean data cache
-+ bl cpu_xscale_cache_clean_invalidate_all
-+
-+ @ Put the processor to sleep
-+ @ (also workaround for sighting 28071)
-+
-+ @ prepare value for sleep mode
-+ mov r1, #3 @ sleep mode
-+
-+ @ prepare to put SDRAM into self-refresh manually
-+ ldr r4, =MDREFR
-+ ldr r5, [r4]
-+ orr r5, r5, #MDREFR_SLFRSH
-+
-+ @ prepare pointer to physical address 0 (virtual mapping in generic.c)
-+ mov r2, #UNCACHED_PHYS_0
-+
-+ @ align execution to a cache line
-+ b 1f
-+
-+ .ltorg
-+ .align 5
-+1:
-+
-+ @ All needed values are now in registers.
-+ @ These last instructions should be in cache
-+
-+ @ put SDRAM into self-refresh
-+ str r5, [r4]
-+
-+ @ force address lines low by reading at physical address 0
-+ ldr r3, [r2]
-+
-+ @ enter sleep mode
-+ mcr p14, 0, r1, c7, c0, 0
-+
-+20: nop
-+ b 20b @ loop waiting for sleep
-+
-+/*
-+ * cpu_pxa_resume()
-+ *
-+ * entry point from bootloader into kernel during resume
-+ *
-+ * Note: Yes, part of the following code is located into the .data section.
-+ * This is to allow sleep_save_sp to be accessed with a relative load
-+ * while we can't rely on any MMU translation. We could have put
-+ * sleep_save_sp in the .text section as well, but some setups might
-+ * insist on it to be truely read-only.
-+ */
-+
-+ .data
-+ .align 5
-+ENTRY(pxa_cpu_resume)
-+ mov r0, #I_BIT | F_BIT | MODE_SVC @ set SVC, irqs off
-+ msr cpsr_c, r0
-+
-+ ldr r0, sleep_save_sp @ stack phys addr
-+ ldr r2, =resume_after_mmu @ its absolute virtual address
-+ ldmfd r0, {r4 - r9, sp} @ CP regs + virt stack ptr
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB
-+
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bic r9, r9, #0x0004 @ see cpu_xscale_proc_init
-+#endif
-+
-+ mcr p15, 0, r4, c15, c1, 0 @ CP access reg
-+ mcr p15, 0, r5, c13, c0, 0 @ PID
-+ mcr p15, 0, r6, c3, c0, 0 @ domain ID
-+ mcr p15, 0, r7, c2, c0, 0 @ translation table base addr
-+ mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
-+ b resume_turn_on_mmu @ cache align execution
-+
-+ .align 5
-+resume_turn_on_mmu:
-+ mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, caches, etc.
-+
-+ @ Let us ensure we jump to resume_after_mmu only when the mcr above
-+ @ actually took effect. They call it the "cpwait" operation.
-+ mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15
-+ sub pc, r2, r1, lsr #32 @ jump to virtual addr
-+ nop
-+ nop
-+ nop
-+
-+sleep_save_sp:
-+ .word 0 @ preserve stack phys ptr here
-+
-+ .text
-+resume_after_mmu:
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bl cpu_xscale_proc_init
-+#endif
-+ ldmfd sp!, {r2, r3}
-+ mar acc0, r2, r3
-+ ldmfd sp!, {r4 - r12, pc} @ return to caller
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/trizeps2.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,105 @@
-+/*
-+ * linux/arch/arm/mach-pxa/trizeps2.c
-+ *
-+ * Support for the Keith&Koep MT6N Development Platform.
-+ *
-+ * Author: Luc De Cock
-+ * Created: Jan 13, 2003
-+ * Copyright: Teradyne DS, Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+static unsigned long trizeps2_irq_en_mask;
-+unsigned short trizeps2_bcr_shadow = 0x50; // 0x70
-+
-+
-+static void __init trizeps2_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ set_GPIO_IRQ_edge(GPIO_ETHERNET_IRQ, GPIO_RISING_EDGE);
-+}
-+
-+static int __init trizeps2_init(void)
-+{
-+ /* Configure the BCR register */
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+
-+ *bcr = trizeps2_bcr_shadow;
-+ return 0;
-+}
-+
-+__initcall(trizeps2_init);
-+
-+static void __init
-+fixup_trizeps2(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+#ifdef TRIZEPS2_MEM_64MB
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+#else
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+#endif
-+ mi->nr_banks = 1;
-+}
-+
-+static struct map_desc trizeps2_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf0000000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* BCR */
-+ { 0xf0100000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA STATUS */
-+ { 0xf1000000, 0x0c800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf2000000, 0x0d800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* TTL-IO */
-+ LAST_DESC
-+};
-+
-+static void __init trizeps2_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(trizeps2_io_desc);
-+
-+ /* This is for the SMC chip select */
-+ set_GPIO_mode(GPIO79_nCS_3_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(TRIZEPS2, "Keith-n-Koep MT6N Development Platform")
-+ MAINTAINER("Luc De Cock")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ FIXUP(fixup_trizeps2)
-+ MAPIO(trizeps2_map_io)
-+ INITIRQ(trizeps2_init_irq)
-+MACHINE_END
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb-char.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,719 @@
-+/*
-+ * (C) Copyright 2000-2001 Extenex Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * usb-char.c
-+ *
-+ * Miscellaneous character device interface for SA1100 USB function
-+ * driver.
-+ *
-+ * Background:
-+ * The SA1100 function driver ported from the Compaq Itsy project
-+ * has an interface, usb-eth.c, to feed network packets over the
-+ * usb wire and into the Linux TCP/IP stack.
-+ *
-+ * This file replaces that one with a simple character device
-+ * interface that allows unstructured "byte pipe" style reads and
-+ * writes over the USB bulk endpoints by userspace programs.
-+ *
-+ * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
-+ * when set, (the default) causes the ethernet interface to be used.
-+ * When not set, this more pedestrian character interface is linked
-+ * in instead.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ * ward.willats@extenex.com
-+ *
-+ * To do:
-+ * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
-+ * uses and get bytes out at the same time DMA is going on. Investigate:
-+ * a) changing usb_recv to use alloc_consistent() at client request; or
-+ * b) non-ring-buffer based data structures. In the meantime, I am using
-+ * a bounce buffer. Simple, but wasteful.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/cache.h>
-+#include <linux/poll.h>
-+#include <linux/circ_buf.h>
-+#include <linux/timer.h>
-+
-+#include <asm/io.h>
-+#include <asm/semaphore.h>
-+#include <asm/proc/page.h>
-+#include <asm/mach-types.h>
-+
-+#include "usb-char.h"
-+#include "pxa_usb.h"
-+
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Driver Options
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define VERSION "0.4"
-+
-+
-+#define VERBOSITY 1
-+
-+#if VERBOSITY
-+# define PRINTK(x, a...) printk (x, ## a)
-+#else
-+# define PRINTK(x, a...) /**/
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals - Macros - Enums - Structures
-+//////////////////////////////////////////////////////////////////////////////
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+typedef int bool; enum { false = 0, true = 1 };
-+
-+static const char pszMe[] = "usbchr: ";
-+
-+static wait_queue_head_t wq_read;
-+static wait_queue_head_t wq_write;
-+static wait_queue_head_t wq_poll;
-+
-+/* Serialze multiple writers onto the transmit hardware
-+.. since we sleep the writer during transmit to stay in
-+.. sync. (Multiple writers don't make much sense, but..) */
-+static DECLARE_MUTEX( xmit_sem );
-+
-+// size of usb DATA0/1 packets. 64 is standard maximum
-+// for bulk transport, though most hosts seem to be able
-+// to handle larger.
-+#define TX_PACKET_SIZE 64
-+#define RX_PACKET_SIZE 64
-+#define RBUF_SIZE (4*PAGE_SIZE)
-+
-+static struct wcirc_buf {
-+ char *buf;
-+ int in;
-+ int out;
-+} rx_ring = { NULL, 0, 0 };
-+
-+static struct {
-+ unsigned long cnt_rx_complete;
-+ unsigned long cnt_rx_errors;
-+ unsigned long bytes_rx;
-+ unsigned long cnt_tx_timeouts;
-+ unsigned long cnt_tx_errors;
-+ unsigned long bytes_tx;
-+} charstats;
-+
-+
-+static char * tx_buf = NULL;
-+static char * packet_buffer = NULL;
-+static int sending = 0;
-+static int usb_ref_count = 0;
-+static int last_tx_result = 0;
-+static int last_rx_result = 0;
-+static int last_tx_size = 0;
-+static struct timer_list tx_timer;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+static char * what_the_f( int e );
-+static void free_txrx_buffers( void );
-+static void twiddle_descriptors( void );
-+static void free_string_descriptors( void ) ;
-+static int usbc_open( struct inode *pInode, struct file *pFile );
-+static void rx_done_callback_packet_buffer( int flag, int size );
-+
-+static void tx_timeout( unsigned long );
-+static void tx_done_callback( int flag, int size );
-+
-+static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
-+static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument );
-+static int usbc_close( struct inode *pInode, struct file *pFile );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+static void extenex_configured_notify_proc( void );
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static char * what_the_f( int e )
-+{
-+ char * p;
-+ switch( e ) {
-+ case 0:
-+ p = "noErr";
-+ break;
-+ case -ENODEV:
-+ p = "ENODEV - usb not in config state";
-+ break;
-+ case -EBUSY:
-+ p = "EBUSY - another request on the hardware";
-+ break;
-+ case -EAGAIN:
-+ p = "EAGAIN";
-+ break;
-+ case -EINTR:
-+ p = "EINTR - interrupted\n";
-+ break;
-+ case -EPIPE:
-+ p = "EPIPE - zero length xfer\n";
-+ break;
-+ default:
-+ p = "????";
-+ break;
-+ }
-+ return p;
-+}
-+
-+static void free_txrx_buffers( void )
-+{
-+ if ( rx_ring.buf != NULL ) {
-+ kfree( rx_ring.buf );
-+ rx_ring.buf = NULL;
-+ }
-+ if ( packet_buffer != NULL ) {
-+ kfree( packet_buffer );
-+ packet_buffer = NULL;
-+ }
-+ if ( tx_buf != NULL ) {
-+ kfree( tx_buf );
-+ tx_buf = NULL;
-+ }
-+}
-+
-+/* twiddle_descriptors()
-+ * It is between open() and start(). Setup descriptors.
-+ */
-+static void twiddle_descriptors( void )
-+{
-+ desc_t * pDesc = pxa_usb_get_descriptor_ptr();
-+ string_desc_t * pString;
-+
-+ pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
-+ pDesc->b.ep1.bmAttributes = USB_EP_BULK;
-+ pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
-+ pDesc->b.ep2.bmAttributes = USB_EP_BULK;
-+
-+ if ( machine_is_extenex1() ) {
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ pDesc->dev.idVendor = make_word_c( 0xC9F );
-+ pDesc->dev.idProduct = 1;
-+ pDesc->dev.bcdDevice = make_word_c( 0x0001 );
-+ pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
-+ pDesc->b.cfg.MaxPower = 0;
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "Extenex" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 1, pString );
-+ pDesc->dev.iManufacturer = 1;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "Handheld Theater" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 2, pString );
-+ pDesc->dev.iProduct = 2;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "00000000" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 3, pString );
-+ pDesc->dev.iSerialNumber = 3;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 4, pString );
-+ pDesc->b.intf.iInterface = 4;
-+ }
-+ pxa_set_configured_callback( extenex_configured_notify_proc );
-+#endif
-+ }
-+}
-+
-+static void free_string_descriptors( void )
-+{
-+ if ( machine_is_extenex1() ) {
-+ string_desc_t * pString;
-+ int i;
-+ for( i = 1 ; i <= 4 ; i++ ) {
-+ pString = pxa_usb_get_string_descriptor( i );
-+ if ( pString )
-+ kfree( pString );
-+ }
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// ASYNCHRONOUS
-+//////////////////////////////////////////////////////////////////////////////
-+static void kick_start_rx( void )
-+{
-+ if ( usb_ref_count ) {
-+ int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ if ( total_space >= RX_PACKET_SIZE ) {
-+ pxa_usb_recv( packet_buffer,
-+ RX_PACKET_SIZE,
-+ rx_done_callback_packet_buffer
-+ );
-+ }
-+ }
-+}
-+/*
-+ * rx_done_callback_packet_buffer()
-+ * We have completed a DMA xfer into the temp packet buffer.
-+ * Move to ring.
-+ *
-+ * flag values:
-+ * on init, -EAGAIN
-+ * on reset, -EINTR
-+ * on RPE, -EIO
-+ * on short packet -EPIPE
-+ */
-+static void
-+rx_done_callback_packet_buffer( int flag, int size )
-+{
-+ charstats.cnt_rx_complete++;
-+
-+ if ( flag == 0 || flag == -EPIPE ) {
-+ size_t n;
-+
-+ charstats.bytes_rx += size;
-+
-+ n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ n = MIN( n, size );
-+ size -= n;
-+
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
-+ rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
-+ rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
-+
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+
-+ last_rx_result = 0;
-+
-+ kick_start_rx();
-+
-+ } else if ( flag != -EAGAIN ) {
-+ charstats.cnt_rx_errors++;
-+ last_rx_result = flag;
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+ }
-+ else /* init, start a read */
-+ kick_start_rx();
-+}
-+
-+
-+static void tx_timeout( unsigned long unused )
-+{
-+ printk( "%stx timeout\n", pszMe );
-+ pxa_usb_send_reset();
-+ charstats.cnt_tx_timeouts++;
-+}
-+
-+
-+// on init, -EAGAIN
-+// on reset, -EINTR
-+// on TPE, -EIO
-+static void tx_done_callback( int flags, int size )
-+{
-+ if ( flags == 0 )
-+ charstats.bytes_tx += size;
-+ else
-+ charstats.cnt_tx_errors++;
-+ last_tx_size = size;
-+ last_tx_result = flags;
-+ sending = 0;
-+ wake_up_interruptible( &wq_write );
-+ wake_up_interruptible( &wq_poll );
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Workers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static int usbc_open( struct inode *pInode, struct file *pFile )
-+{
-+ int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
-+
-+ /* start usb core */
-+ retval = pxa_usb_open( "usb-char" );
-+ if ( retval ) return retval;
-+
-+ /* allocate memory */
-+ if ( usb_ref_count == 0 ) {
-+ tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+ if ( tx_buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.buf =
-+ (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
-+
-+ if ( rx_ring.buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+
-+ packet_buffer =
-+ (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+
-+ if ( packet_buffer == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.in = rx_ring.out = 0;
-+ memset( &charstats, 0, sizeof( charstats ) );
-+ sending = 0;
-+ last_tx_result = 0;
-+ last_tx_size = 0;
-+ }
-+
-+ /* modify default descriptors */
-+ twiddle_descriptors();
-+
-+ retval = pxa_usb_start();
-+ if ( retval ) {
-+ printk( "%sAGHH! Could not USB core\n", pszMe );
-+ free_txrx_buffers();
-+ return retval;
-+ }
-+ usb_ref_count++; /* must do _before_ kick_start() */
-+ MOD_INC_USE_COUNT;
-+ kick_start_rx();
-+ return 0;
-+
-+ malloc_fail:
-+ free_txrx_buffers();
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Read endpoint. Note that you can issue a read to an
-+ * unconfigured endpoint. Eventually, the host may come along
-+ * and configure underneath this module and data will appear.
-+ */
-+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval;
-+ int flags;
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%sread()\n", pszMe );
-+
-+ local_irq_save( flags );
-+ if ( last_rx_result == 0 ) {
-+ local_irq_restore( flags );
-+ } else { /* an error happended and receiver is paused */
-+ local_irq_restore( flags );
-+ last_rx_result = 0;
-+ kick_start_rx();
-+ }
-+
-+ add_wait_queue( &wq_read, &wait );
-+ while( 1 ) {
-+ ssize_t bytes_avail;
-+ ssize_t bytes_to_end;
-+
-+ set_current_state( TASK_INTERRUPTIBLE );
-+
-+ /* snap ring buf state */
-+ local_irq_save( flags );
-+ bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ local_irq_restore( flags );
-+
-+ if ( bytes_avail != 0 ) {
-+ ssize_t bytes_to_move = MIN( stCount, bytes_avail );
-+ retval = 0; // will be bytes transfered
-+ if ( bytes_to_move != 0 ) {
-+ size_t n = MIN( bytes_to_end, bytes_to_move );
-+ if ( copy_to_user( pUserBuffer,
-+ &rx_ring.buf[ rx_ring.out ],
-+ n ) ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ bytes_to_move -= n;
-+ retval += n;
-+ // might go 1 char off end, so wrap
-+ rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
-+ if ( copy_to_user( pUserBuffer + n,
-+ &rx_ring.buf[ rx_ring.out ],
-+ bytes_to_move )
-+ ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_ring.out += bytes_to_move; // cannot wrap
-+ retval += bytes_to_move;
-+ kick_start_rx();
-+ }
-+ break;
-+ }
-+ else if ( last_rx_result ) {
-+ retval = last_rx_result;
-+ break;
-+ }
-+ else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
-+ retval = -EAGAIN;
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) { // no data, can sleep, but signal
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule(); // no data, can sleep
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_read, &wait );
-+
-+ if ( retval < 0 )
-+ printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
-+ return retval;
-+}
-+
-+/*
-+ * Write endpoint. This routine attempts to break the passed in buffer
-+ * into usb DATA0/1 packet size chunks and send them to the host.
-+ * (The lower-level driver tries to do this too, but easier for us
-+ * to manage things here.)
-+ *
-+ * We are at the mercy of the host here, in that it must send an IN
-+ * token to us to pull this data back, so hopefully some higher level
-+ * protocol is expecting traffic to flow in that direction so the host
-+ * is actually polling us. To guard against hangs, a 5 second timeout
-+ * is used.
-+ *
-+ * This routine takes some care to only report bytes sent that have
-+ * actually made it across the wire. Thus we try to stay in lockstep
-+ * with the completion routine and only have one packet on the xmit
-+ * hardware at a time. Multiple simultaneous writers will get
-+ * "undefined" results.
-+ *
-+ */
-+static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval = 0;
-+ ssize_t stSent = 0;
-+
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
-+
-+ down( &xmit_sem ); // only one thread onto the hardware at a time
-+
-+ while( stCount != 0 && retval == 0 ) {
-+ int nThisTime = MIN( TX_PACKET_SIZE, stCount );
-+ copy_from_user( tx_buf, pUserBuffer, nThisTime );
-+ sending = nThisTime;
-+ retval = pxa_usb_send( tx_buf, nThisTime, tx_done_callback );
-+ if ( retval < 0 ) {
-+ char * p = what_the_f( retval );
-+ printk( "%sCould not queue xmission. rc=%d - %s\n",
-+ pszMe, retval, p );
-+ sending = 0;
-+ break;
-+ }
-+ /* now have something on the diving board */
-+ add_wait_queue( &wq_write, &wait );
-+ tx_timer.expires = jiffies + ( HZ * 5 );
-+ add_timer( &tx_timer );
-+ while( 1 ) {
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ if ( sending == 0 ) { /* it jumped into the pool */
-+ del_timer( &tx_timer );
-+ retval = last_tx_result;
-+ if ( retval == 0 ) {
-+ stSent += last_tx_size;
-+ pUserBuffer += last_tx_size;
-+ stCount -= last_tx_size;
-+ }
-+ else
-+ printk( "%sxmission error rc=%d - %s\n",
-+ pszMe, retval, what_the_f(retval) );
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) {
-+ del_timer( &tx_timer );
-+ printk( "%ssignal\n", pszMe );
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_write, &wait );
-+ }
-+
-+ up( &xmit_sem );
-+
-+ if ( 0 == retval )
-+ retval = stSent;
-+ return retval;
-+}
-+
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
-+{
-+ unsigned int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%poll()\n", pszMe );
-+
-+ poll_wait( pFile, &wq_poll, pWait );
-+
-+ if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
-+ retval |= POLLIN | POLLRDNORM;
-+ if ( pxa_usb_xmitter_avail() )
-+ retval |= POLLOUT | POLLWRNORM;
-+ return retval;
-+}
-+
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument )
-+{
-+ int retval = 0;
-+
-+ switch( nCmd ) {
-+
-+ case USBC_IOC_FLUSH_RECEIVER:
-+ pxa_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ break;
-+
-+ case USBC_IOC_FLUSH_TRANSMITTER:
-+ pxa_usb_send_reset();
-+ break;
-+
-+ case USBC_IOC_FLUSH_ALL:
-+ pxa_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ pxa_usb_send_reset();
-+ break;
-+
-+ default:
-+ retval = -ENOIOCTLCMD;
-+ break;
-+
-+ }
-+ return retval;
-+}
-+
-+
-+static int usbc_close( struct inode *pInode, struct file * pFile )
-+{
-+ PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
-+ if ( --usb_ref_count == 0 ) {
-+ down( &xmit_sem );
-+ pxa_usb_stop();
-+ free_txrx_buffers();
-+ free_string_descriptors();
-+ del_timer( &tx_timer );
-+ pxa_usb_close();
-+ up( &xmit_sem );
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+#include "../../../drivers/char/ex_gpio.h"
-+void extenex_configured_notify_proc( void )
-+{
-+ if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
-+ printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
-+}
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Initialization
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static struct file_operations usbc_fops = {
-+ owner: THIS_MODULE,
-+ open: usbc_open,
-+ read: usbc_read,
-+ write: usbc_write,
-+ poll: usbc_poll,
-+ ioctl: usbc_ioctl,
-+ release: usbc_close,
-+};
-+
-+static struct miscdevice usbc_misc_device = {
-+ USBC_MINOR, "usb_char", &usbc_fops
-+};
-+
-+/*
-+ * usbc_init()
-+ */
-+
-+int __init usbc_init( void )
-+{
-+ int rc;
-+
-+ if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
-+ printk( KERN_WARNING "%sCould not register device 10, "
-+ "%d. (%d)\n", pszMe, USBC_MINOR, rc );
-+ return -EBUSY;
-+ }
-+
-+ // initialize wait queues
-+ init_waitqueue_head( &wq_read );
-+ init_waitqueue_head( &wq_write );
-+ init_waitqueue_head( &wq_poll );
-+
-+ // initialize tx timeout timer
-+ init_timer( &tx_timer );
-+ tx_timer.function = tx_timeout;
-+
-+ printk( KERN_INFO "USB Function Character Driver Interface"
-+ " - %s, (C) 2001, Extenex Corp.\n", VERSION
-+ );
-+
-+ return rc;
-+}
-+
-+void __exit usbc_exit( void )
-+{
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(usbc_init);
-+module_exit(usbc_exit);
-+
-+
-+
-+// end: usb-char.c
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb-char.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2001 Extenex Corporation
-+ *
-+ * usb-char.h
-+ *
-+ * Character device emulation client for SA-1100 client usb core.
-+ *
-+ *
-+ *
-+ */
-+#ifndef _USB_CHAR_H
-+#define _USB_CHAR_H
-+
-+#define USBC_MAJOR 10 /* miscellaneous character device */
-+#define USBC_MINOR 240 /* in the "reserved for local use" range */
-+
-+#define USBC_MAGIC 0x8E
-+
-+/* zap everything in receive ring buffer */
-+#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
-+
-+/* reset transmitter */
-+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
-+
-+/* do both of above */
-+#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
-+
-+
-+
-+
-+
-+
-+#endif /* _USB_CHAR_H */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb-eth.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,479 @@
-+/*
-+ * Ethernet driver for the PXA USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original initial ethernet test driver
-+ * Copyright (c) Compaq Computer Corporation, 1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
-+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
-+ * Now, since we do not know what size of packet we are receiving
-+ * last usb packet in sequence will always be less than max packet
-+ * receive endpoint can accept.
-+ * Now the only way to check correct start of frame is to compare
-+ * MAC address. Also now we are stalling on each receive error.
-+ *
-+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
-+ * aligned buffer, but this breaks IP code (unaligned access).
-+ *
-+ * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
-+ * they are disabled now.
-+ *
-+ * 03/06/2001 - Readded "zerocopy" receive path (tunable).
-+ *
-+ */
-+
-+// Define DMA_NO_COPY if you want data to arrive directly into the
-+// receive network buffers, instead of arriving into bounce buffer
-+// and then get copied to network buffer.
-+// This does not work correctly right now.
-+#undef DMA_NO_COPY
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/timer.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/random.h>
-+
-+#include "pxa_usb.h"
-+
-+
-+#define ETHERNET_VENDOR_ID 0x49f
-+#define ETHERNET_PRODUCT_ID 0x505A
-+#define MAX_PACKET 32768
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+
-+// Should be global, so that insmod can change these
-+int usb_rsize=64;
-+int usb_wsize=64;
-+
-+static struct usbe_info_t {
-+ struct net_device *dev;
-+ u16 packet_id;
-+ struct net_device_stats stats;
-+} usbe_info;
-+
-+static char usb_eth_name[16] = "usbf";
-+static struct net_device usb_eth_device;
-+static struct sk_buff *cur_tx_skb, *next_tx_skb;
-+static struct sk_buff *cur_rx_skb, *next_rx_skb;
-+static volatile int terminating;
-+#ifndef DMA_NO_COPY
-+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
-+#endif
-+
-+static int usb_change_mtu (struct net_device *net, int new_mtu)
-+{
-+ if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
-+ return -EINVAL;
-+ // no second zero-length packet read wanted after mtu-sized packets
-+ if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
-+ return -EDOM;
-+
-+ net->mtu = new_mtu;
-+ return 0;
-+}
-+
-+static struct sk_buff *
-+usb_new_recv_skb(void)
-+{
-+ struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
-+
-+ if (skb) {
-+ skb_reserve(skb, 2);
-+ }
-+ return skb;
-+}
-+
-+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
-+static void
-+usb_recv_callback(int flag, int size)
-+{
-+ struct sk_buff *skb;
-+
-+ if (terminating)
-+ return;
-+
-+ skb = cur_rx_skb;
-+
-+ /* flag validation */
-+ if (flag == 0) {
-+ if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
-+ usbe_info.stats.rx_over_errors++;
-+ goto error;
-+ }
-+#ifndef DMA_NO_COPY
-+ memcpy(skb->tail,dmabuf,size);
-+#endif
-+ skb_put(skb, size);
-+ } else {
-+ if (flag == -EIO) {
-+ usbe_info.stats.rx_errors++;
-+ }
-+ goto error;
-+ }
-+
-+
-+ /*
-+ * If the real size of the packet is divisible by usb_rsize
-+ * an extra byte will be added. Thus size == usb_rsize
-+ * should only happen if more data is to come.
-+ */
-+ /* validate packet length */
-+ if (size == usb_rsize ) {
-+ /* packet not complete yet */
-+ skb = NULL;
-+ }
-+
-+ /*
-+ * At this point skb is non null if we have a complete packet.
-+ * If so take a fresh skb right away and restart USB receive without
-+ * further delays, then process the packet. Otherwise resume USB
-+ * receive on the current skb and exit.
-+ */
-+
-+ if (skb)
-+ cur_rx_skb = next_rx_skb;
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize,
-+ usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ if (!skb)
-+ return;
-+
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!next_rx_skb) {
-+ /*
-+ * We can't aford loosing buffer space...
-+ * So we drop the current packet and recycle its skb.
-+ */
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ usbe_info.stats.rx_dropped++;
-+ skb_trim(skb, 0);
-+ next_rx_skb = skb;
-+ return;
-+ }
-+ if ( skb->len >= sizeof(struct ethhdr)) {
-+ if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
-+ // This frame is not for us. nor it is broadcast
-+ usbe_info.stats.rx_frame_errors++;
-+ kfree_skb(skb);
-+ goto error;
-+ }
-+
-+#if 0
-+{
-+ int i;
-+
-+ for (i = 0; i < skb->len; i++)
-+ {
-+ printk("%02X ", skb->data[i]);
-+ if( (i%8)==7) printk("\n");
-+ }
-+ printk("...\n");
-+}
-+#endif
-+
-+ }
-+
-+ if (skb->len) {
-+ int status;
-+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
-+
-+ skb->dev = &usb_eth_device;
-+ skb->protocol = eth_type_trans (skb, &usb_eth_device);
-+ usbe_info.stats.rx_packets++;
-+ usbe_info.stats.rx_bytes += skb->len;
-+ skb->ip_summed = CHECKSUM_NONE;
-+ status = netif_rx (skb);
-+ if (status != NET_RX_SUCCESS)
-+ printk("netif_rx failed with code %d\n",status);
-+ } else {
-+error:
-+//printk("ERROR... tailroom=%d size=%d len=%d flag=%d\n", skb_tailroom(skb), size, skb->len, flag);
-+ /*
-+ * Error due to HW addr mismatch, or IO error.
-+ * Recycle the current skb and reset USB reception.
-+ */
-+ skb_trim(cur_rx_skb, 0);
-+// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
-+#endif
-+ }
-+}
-+
-+
-+static void
-+usb_send_callback(int flag, int size)
-+{
-+ struct net_device *dev = usbe_info.dev;
-+ struct net_device_stats *stats;
-+ struct sk_buff *skb=cur_tx_skb;
-+ int ret;
-+
-+ if (terminating)
-+ return;
-+
-+ stats = &usbe_info.stats;
-+ switch (flag) {
-+ case 0:
-+ stats->tx_packets++;
-+ stats->tx_bytes += size;
-+ break;
-+ case -EIO:
-+ stats->tx_errors++;
-+ break;
-+ default:
-+ stats->tx_dropped++;
-+ break;
-+ }
-+
-+ cur_tx_skb = next_tx_skb;
-+ next_tx_skb = NULL;
-+ dev_kfree_skb_irq(skb);
-+ if (!cur_tx_skb)
-+ return;
-+
-+ dev->trans_start = jiffies;
-+ ret = pxa_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb_irq(cur_tx_skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ netif_wake_queue(dev);
-+}
-+
-+static int
-+usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ int ret;
-+ long flags;
-+
-+ if (next_tx_skb) {
-+ printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
-+ return 1;
-+ }
-+
-+ if (skb_shared (skb)) {
-+ struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
-+ if (!skb2) {
-+ usbe_info.stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 1;
-+ }
-+ skb = skb2;
-+ }
-+
-+ if ((skb->len % usb_wsize) == 0) {
-+ skb->len++; // other side will ignore this one, anyway.
-+ }
-+
-+ save_flags_cli(flags);
-+ if (cur_tx_skb) {
-+ next_tx_skb = skb;
-+ netif_stop_queue(dev);
-+ } else {
-+ cur_tx_skb = skb;
-+ dev->trans_start = jiffies;
-+ ret = pxa_usb_send(skb->data, skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb(skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ }
-+ restore_flags(flags);
-+ return 0;
-+}
-+
-+static void
-+usb_xmit_timeout(struct net_device *dev )
-+{
-+ pxa_usb_send_reset();
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+
-+static int
-+usb_eth_open(struct net_device *dev)
-+{
-+ int rc;
-+ rc = pxa_usb_open( "usb-eth" );
-+ if ( rc == 0 ) {
-+ string_desc_t * pstr;
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+
-+ pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
-+ pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
-+ pd->dev.idVendor = ETHERNET_VENDOR_ID;
-+ pd->dev.idProduct = ETHERNET_PRODUCT_ID;
-+ pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" );
-+ if ( pstr ) {
-+ pxa_usb_set_string_descriptor( 1, pstr );
-+ pd->dev.iProduct = 1;
-+ }
-+ rc = pxa_usb_start();
-+ }
-+
-+ if( rc == 0)
-+ {
-+ terminating = 0;
-+ cur_tx_skb = next_tx_skb = NULL;
-+ cur_rx_skb = usb_new_recv_skb();
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!cur_rx_skb || !next_rx_skb) {
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+
-+ pxa_usb_stop();
-+ pxa_usb_close();
-+ return -ENOMEM;;
-+ }
-+
-+ MOD_INC_USE_COUNT;
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ }
-+
-+ return rc;
-+}
-+
-+static int
-+usb_eth_release(struct net_device *dev)
-+{
-+ string_desc_t * pstr;
-+
-+ terminating = 1;
-+ pxa_usb_send_reset();
-+ pxa_usb_recv_reset();
-+ if (cur_tx_skb)
-+ kfree_skb(cur_tx_skb);
-+ if (next_tx_skb)
-+ kfree_skb(next_tx_skb);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+
-+ pxa_usb_stop();
-+ pxa_usb_close();
-+ if ( (pstr = pxa_usb_get_string_descriptor(1)) != NULL )
-+ kfree( pstr );
-+
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static struct net_device_stats *
-+usb_eth_stats(struct net_device *dev)
-+{
-+ struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
-+ struct net_device_stats *stats=NULL;
-+
-+ if (priv)
-+ stats = &priv->stats;
-+ return stats;
-+}
-+
-+static int
-+usb_eth_probe(struct net_device *dev)
-+{
-+ u8 node_id [ETH_ALEN];
-+
-+ get_random_bytes (node_id, sizeof node_id);
-+ node_id [0] &= 0xfe; // clear multicast bit
-+
-+ /*
-+ * Assign the hardware address of the board:
-+ * generate it randomly, as there can be many such
-+ * devices on the bus.
-+ */
-+ memcpy (dev->dev_addr, node_id, sizeof node_id);
-+
-+ dev->open = usb_eth_open;
-+ dev->change_mtu = usb_change_mtu;
-+ dev->stop = usb_eth_release;
-+ dev->hard_start_xmit = usb_eth_xmit;
-+ dev->get_stats = usb_eth_stats;
-+ dev->watchdog_timeo = 1*HZ;
-+ dev->tx_timeout = usb_xmit_timeout;
-+ dev->priv = &usbe_info;
-+
-+ usbe_info.dev = dev;
-+
-+ /* clear the statistics */
-+ memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
-+
-+ ether_setup(dev);
-+ dev->flags &= ~IFF_MULTICAST;
-+ dev->flags &= ~IFF_BROADCAST;
-+ //dev->flags |= IFF_NOARP;
-+
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+MODULE_PARM(usb_rsize, "1i");
-+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to pxa");
-+MODULE_PARM(usb_wsize, "1i");
-+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from pxa to host");
-+#endif
-+
-+static int __init
-+usb_eth_init(void)
-+{
-+#ifndef DMA_NO_COPY
-+ dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
-+ if (!dmabuf)
-+ return -ENOMEM;
-+#endif
-+ strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
-+ usb_eth_device.init = usb_eth_probe;
-+ if (register_netdev(&usb_eth_device) != 0)
-+ return -EIO;
-+
-+ printk( KERN_INFO "USB Function Ethernet Driver Interface\n");
-+
-+ return 0;
-+}
-+
-+static void __exit
-+usb_eth_cleanup(void)
-+{
-+#ifndef DMA_NO_COPY
-+ kfree(dmabuf);
-+#endif
-+ unregister_netdev(&usb_eth_device);
-+}
-+
-+module_init(usb_eth_init);
-+module_exit(usb_eth_cleanup);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,769 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation, 2001
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * PXA USB controller core driver.
-+ *
-+ * This file provides interrupt routing and overall coordination
-+ * of the endpoints.
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for more info.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+
-+int usbctl_next_state_on_event( int event );
-+static void udc_int_hndlr(int, void *, struct pt_regs *);
-+static void initialize_descriptors( void );
-+static void soft_connect_hook( int enable );
-+static void udc_disable(void);
-+static void udc_enable(void);
-+
-+#if CONFIG_PROC_FS
-+#define PROC_NODE_NAME "driver/pxausb"
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals
-+//////////////////////////////////////////////////////////////////////////////
-+static const char pszMe[] = "usbctl: ";
-+struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
-+
-+/* device descriptors */
-+static desc_t desc;
-+
-+#define MAX_STRING_DESC 8
-+static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
-+static string_desc_t sd_zero; /* special sd_zero holds language codes */
-+
-+// called when configured
-+static usb_notify_t configured_callback = NULL;
-+
-+enum {
-+ kStateZombie = 0,
-+ kStateZombieSuspend = 1,
-+ kStateDefault = 2,
-+ kStateDefaultSuspend = 3,
-+ kStateAddr = 4,
-+ kStateAddrSuspend = 5,
-+ kStateConfig = 6,
-+ kStateConfigSuspend = 7
-+};
-+
-+/*
-+ * FIXME: The PXA UDC handles several host device requests without user
-+ * notification/intervention. The table could be collapsed quite a bit...
-+ */
-+static int device_state_machine[8][6] = {
-+// suspend reset resume adddr config deconfig
-+/* zombie */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError },
-+/* zom sus */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError },
-+/* default */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kStateAddr, kStateConfig, kError },
-+/* def sus */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kError , kError , kError },
-+/* addr */ { kStateAddrSuspend , kStateDefault, kStateAddr , kError , kStateConfig, kError },
-+/* addr sus */{ kStateAddrSuspend , kStateDefault, kStateAddr , kError , kError , kError },
-+/* config */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kStateDefault },
-+/* cfg sus */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kError }
-+};
-+
-+/* "device state" is the usb device framework state, as opposed to the
-+ "state machine state" which is whatever the driver needs and is much
-+ more fine grained
-+*/
-+static int sm_state_to_device_state[8] = {
-+// zombie zom suspend
-+USB_STATE_POWERED, USB_STATE_SUSPENDED,
-+// default default sus
-+USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
-+// addr addr sus
-+USB_STATE_ADDRESS, USB_STATE_SUSPENDED,
-+// config config sus
-+USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
-+};
-+
-+static char * state_names[8] =
-+{ "zombie", "zombie suspended",
-+ "default", "default suspended",
-+ "address", "address suspended",
-+ "configured", "config suspended"
-+};
-+
-+static char * event_names[6] =
-+{ "suspend", "reset", "resume",
-+ "address assigned", "configure", "de-configure"
-+};
-+
-+static char * device_state_names[] =
-+{ "not attached", "attached", "powered", "default",
-+ "address", "configured", "suspended" };
-+
-+static int sm_state = kStateZombie;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Async
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* The UDCCR reg contains mask and interrupt status bits,
-+ * so using '|=' isn't safe as it may ack an interrupt.
-+ */
-+
-+void udc_set_mask_UDCCR( int mask )
-+{
-+ UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
-+}
-+
-+void udc_clear_mask_UDCCR( int mask)
-+{
-+ UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
-+}
-+
-+void udc_ack_int_UDCCR( int mask)
-+{
-+ /* udccr contains the bits we dont want to change */
-+ __u32 udccr = UDCCR & UDCCR_MASK_BITS;
-+
-+ UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
-+}
-+
-+static void
-+udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ __u32 status = UDCCR;
-+ __u32 ir0_status = USIR0;
-+ __u32 ir1_status = USIR1;
-+ __u32 uicr0 = UICR0;
-+ __u32 uicr1 = UICR1;
-+
-+ //mask ints
-+ udc_set_mask_UDCCR( UDCCR_REM | UDCCR_SRM);
-+ UICR0 = 0xff;
-+ UICR1 = 0xff;
-+
-+ if( usb_debug > 2)
-+ {
-+ printk("%s--- udc_int_hndlr\n"
-+ "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
-+ "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n",
-+ pszMe, status, UDCCS0, UDCCS1, UDCCS2, ir0_status, ir1_status, uicr0, uicr1);
-+ }
-+
-+ /* SUSpend Interrupt Request */
-+ if ( status & UDCCR_SUSIR )
-+ {
-+ udc_ack_int_UDCCR( UDCCR_SUSIR);
-+ if( usb_debug) printk("%sSuspend...\n", pszMe);
-+ usbctl_next_state_on_event( kEvSuspend );
-+ }
-+
-+ /* RESume Interrupt Request */
-+ if ( status & UDCCR_RESIR )
-+ {
-+ udc_ack_int_UDCCR( UDCCR_RESIR);
-+ if( usb_debug) printk("%sResume...\n", pszMe);
-+ usbctl_next_state_on_event( kEvResume );
-+ }
-+
-+ /* ReSeT Interrupt Request - UDC has been reset */
-+ if ( status & UDCCR_RSTIR )
-+ {
-+ /* clear the reset interrupt */
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+
-+ /* check type of reset */
-+ if( (UDCCR & UDCCR_UDA) == 0)
-+ {
-+ /* reset assertion took place, nothing to do */
-+ if( usb_debug) printk("%sReset assertion...\n", pszMe);
-+ }
-+
-+ /* ok, it's a reset negation, go on with reset */
-+ else if ( usbctl_next_state_on_event( kEvReset ) != kError )
-+ {
-+ /* starting reset sequence now... */
-+ if( usb_debug) printk("%sResetting\n", pszMe);
-+
-+ ep0_reset();
-+ ep_bulk_in1_reset();
-+ ep_bulk_out1_reset();
-+
-+ usbctl_next_state_on_event( kEvConfig );
-+ }
-+ else
-+ {
-+ printk("%sUnexpected reset\n", pszMe);
-+ }
-+ }
-+ else
-+ {
-+ /* ep0 int */
-+ if (ir0_status & USIR0_IR0)
-+ ep0_int_hndlr();
-+
-+ /* transmit bulk */
-+ if (ir0_status & USIR0_IR1)
-+ ep_bulk_in1_int_hndlr(ir0_status);
-+
-+ /* receive bulk */
-+ if ( ir0_status & USIR0_IR2)
-+ ep_bulk_out1_int_hndlr(ir0_status);
-+
-+ while (UDCCS2 & UDCCS_BO_RNE)
-+ {
-+ if( usb_debug) printk("More Bulk-out data...\n");
-+ ep_bulk_out1_int_hndlr(ir0_status);
-+ }
-+ }
-+
-+ UICR0 = uicr0;
-+ UICR1 = uicr1;
-+ udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); /* enable suspend/resume, reset */
-+
-+ /* clear all endpoint ints */
-+ USIR0 |= 0xff;
-+ USIR1 |= 0xff;
-+
-+ if( usb_debug > 2)
-+ {
-+ printk("%sudc_int_hndlr\n"
-+ "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
-+ "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n",
-+ pszMe, UDCCR, UDCCS0, UDCCS1, UDCCS2, USIR0, USIR1, UICR0, UICR1);
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Public Interface
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* Open PXA usb core on behalf of a client, but don't start running */
-+
-+int
-+pxa_usb_open( const char * client )
-+{
-+ if ( usbd_info.client_name != NULL )
-+ {
-+ printk( "%sUnable to register %s (%s already registered).\n",
-+ pszMe, client, usbd_info.client_name );
-+ return -EBUSY;
-+ }
-+
-+ usbd_info.client_name = (char*) client;
-+ memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
-+ memset(string_desc_array, 0, sizeof(string_desc_array));
-+
-+ /* hack to start in zombie suspended state */
-+ sm_state = kStateZombieSuspend;
-+ usbd_info.state = USB_STATE_SUSPENDED;
-+
-+ /* create descriptors for enumeration */
-+ initialize_descriptors();
-+
-+ printk( "%s%s registered.\n", pszMe, client );
-+ return 0;
-+}
-+
-+/* Start running. Must have called usb_open (above) first */
-+int
-+pxa_usb_start( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+
-+ /* start UDC internal machinery running */
-+ udc_enable();
-+ udelay( 100 );
-+
-+ /* flush DMA and fire through some -EAGAINs */
-+ ep_bulk_out1_init( usbd_info.dmach_rx );
-+ ep_bulk_in1_init( usbd_info.dmach_tx );
-+
-+ /* give endpoint notification we are starting */
-+ ep_bulk_out1_state_change_notify( USB_STATE_SUSPENDED );
-+ ep_bulk_in1_state_change_notify( USB_STATE_SUSPENDED );
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* enable suspend/resume, reset */
-+ udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM);
-+ /* enable ep0, ep1, ep2 */
-+ UICR0 &= ~(UICR0_IM0 | UICR0_IM1 | UICR0_IM2);
-+
-+ if( usb_debug) printk( "%sStarted %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Stop USB core from running */
-+int
-+pxa_usb_stop( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ /* mask everything */
-+ /* disable suspend/resume, reset */
-+ udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM);
-+ /* disable ep0, ep1, ep2 */
-+ UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2);
-+
-+ ep_bulk_out1_reset();
-+ ep_bulk_in1_reset();
-+
-+ udc_disable();
-+ if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Tell PXA core client is through using it */
-+int
-+pxa_usb_close( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name );
-+ usbd_info.client_name = NULL;
-+ return 0;
-+}
-+
-+/* set a proc to be called when device is configured */
-+usb_notify_t pxa_set_configured_callback( usb_notify_t func )
-+{
-+ usb_notify_t retval = configured_callback;
-+ configured_callback = func;
-+ return retval;
-+}
-+
-+/*====================================================
-+ * Descriptor Manipulation.
-+ * Use these between open() and start() above to setup
-+ * the descriptors for your device.
-+ *
-+ */
-+
-+/* get pointer to static default descriptor */
-+desc_t *
-+pxa_usb_get_descriptor_ptr( void ) { return &desc; }
-+
-+/* optional: set a string descriptor */
-+int
-+pxa_usb_set_string_descriptor( int i, string_desc_t * p )
-+{
-+ int retval;
-+ if ( i < MAX_STRING_DESC ) {
-+ string_desc_array[i] = p;
-+ retval = 0;
-+ } else {
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+/* optional: get a previously set string descriptor */
-+string_desc_t *
-+pxa_usb_get_string_descriptor( int i )
-+{
-+ return ( i < MAX_STRING_DESC )
-+ ? string_desc_array[i]
-+ : NULL;
-+}
-+
-+
-+/* optional: kmalloc and unicode up a string descriptor */
-+string_desc_t *
-+pxa_usb_kmalloc_string_descriptor( const char * p )
-+{
-+ string_desc_t * pResult = NULL;
-+
-+ if ( p ) {
-+ int len = strlen( p );
-+ int uni_len = len * sizeof( __u16 );
-+ pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
-+ if ( pResult != NULL ) {
-+ int i;
-+ pResult->bLength = uni_len + 2;
-+ pResult->bDescriptorType = USB_DESC_STRING;
-+ for( i = 0; i < len ; i++ ) {
-+ pResult->bString[i] = make_word( (__u16) p[i] );
-+ }
-+ }
-+ }
-+ return pResult;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Exports to rest of driver
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* called by the int handler here and the two endpoint files when interesting
-+ .."events" happen */
-+
-+int
-+usbctl_next_state_on_event( int event )
-+{
-+ int next_state = device_state_machine[ sm_state ][ event ];
-+ if ( next_state != kError )
-+ {
-+ int next_device_state = sm_state_to_device_state[ next_state ];
-+ if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ],
-+ state_names[ next_state ], device_state_names[ next_device_state ] );
-+
-+ sm_state = next_state;
-+ if ( usbd_info.state != next_device_state )
-+ {
-+ if ( configured_callback != NULL
-+ &&
-+ next_device_state == USB_STATE_CONFIGURED
-+ &&
-+ usbd_info.state != USB_STATE_SUSPENDED
-+ ) {
-+ configured_callback();
-+ }
-+ usbd_info.state = next_device_state;
-+
-+ ep_bulk_out1_state_change_notify( next_device_state );
-+ ep_bulk_in1_state_change_notify( next_device_state );
-+ }
-+ }
-+#if 1
-+ else
-+ printk( "%s%s --> [%s] --> ??? is an error.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ] );
-+#endif
-+ return next_state;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* setup default descriptors */
-+
-+static void
-+initialize_descriptors(void)
-+{
-+ desc.dev.bLength = sizeof( device_desc_t );
-+ desc.dev.bDescriptorType = USB_DESC_DEVICE;
-+ desc.dev.bcdUSB = 0x100; /* 1.0 */
-+ desc.dev.bDeviceClass = 0xFF; /* vendor specific */
-+ desc.dev.bDeviceSubClass = 0;
-+ desc.dev.bDeviceProtocol = 0;
-+ desc.dev.bMaxPacketSize0 = 16; /* ep0 max fifo size */
-+ desc.dev.idVendor = 0; /* vendor ID undefined */
-+ desc.dev.idProduct = 0; /* product */
-+ desc.dev.bcdDevice = 0; /* vendor assigned device release num */
-+ desc.dev.iManufacturer = 0; /* index of manufacturer string */
-+ desc.dev.iProduct = 0; /* index of product description string */
-+ desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
-+ desc.dev.bNumConfigurations = 1;
-+
-+ desc.b.cfg.bLength = sizeof( config_desc_t );
-+ desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
-+ desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
-+ desc.b.cfg.bNumInterfaces = 1;
-+ desc.b.cfg.bConfigurationValue = 1;
-+ desc.b.cfg.iConfiguration = 0;
-+ desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
-+ desc.b.cfg.MaxPower = USB_POWER( 500 );
-+
-+ desc.b.intf.bLength = sizeof( intf_desc_t );
-+ desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
-+ desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
-+ desc.b.intf.bAlternateSetting = 0;
-+ desc.b.intf.bNumEndpoints = 2;
-+ desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
-+ desc.b.intf.bInterfaceSubClass = 0;
-+ desc.b.intf.bInterfaceProtocol = 0;
-+ desc.b.intf.iInterface = 0;
-+
-+/*
-+ * FIXME...
-+ * The host usbnet driver expects EP1=out EP2=in. On the PXA UDC EP1=in, EP2=out
-+ */
-+ desc.b.ep1.bLength = sizeof( ep_desc_t );
-+ desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_IN );
-+ desc.b.ep1.bmAttributes = USB_EP_BULK;
-+ desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep1.bInterval = 0;
-+
-+ desc.b.ep2.bLength = sizeof( ep_desc_t );
-+ desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_OUT );
-+ desc.b.ep2.bmAttributes = USB_EP_BULK;
-+ desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep2.bInterval = 0;
-+
-+// FIXME: Add support for all endpoint...
-+
-+ /* set language */
-+ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
-+ sd_zero.bDescriptorType = USB_DESC_STRING;
-+ sd_zero.bLength = sizeof( string_desc_t );
-+ sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
-+ pxa_usb_set_string_descriptor( 0, &sd_zero );
-+}
-+
-+/* soft_connect_hook()
-+ * Some devices have platform-specific circuitry to make USB
-+ * not seem to be plugged in, even when it is. This allows
-+ * software to control when a device 'appears' on the USB bus
-+ * (after Linux has booted and this driver has loaded, for
-+ * example). If you have such a circuit, control it here.
-+ */
-+static void
-+soft_connect_hook( int enable )
-+{
-+}
-+
-+/* disable the UDC at the source */
-+static void
-+udc_disable(void)
-+{
-+ soft_connect_hook( 0 );
-+ /* clear UDC-enable */
-+ udc_clear_mask_UDCCR( UDCCR_UDE);
-+
-+ /* Disable clock for USB device */
-+ CKEN &= ~CKEN11_USB;
-+}
-+
-+
-+/* enable the udc at the source */
-+static void
-+udc_enable(void)
-+{
-+ /* Enable clock for USB device */
-+ CKEN |= CKEN11_USB;
-+
-+ /* try to clear these bits before we enable the udc */
-+ udc_ack_int_UDCCR( UDCCR_SUSIR);
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+ udc_ack_int_UDCCR( UDCCR_RESIR);
-+
-+ /* set UDC-enable */
-+ udc_set_mask_UDCCR( UDCCR_UDE);
-+ if( (UDCCR & UDCCR_UDA) == 0)
-+ {
-+ /* There's a reset on the bus,
-+ * clear the interrupt bit and keep going
-+ */
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+ }
-+
-+ /* "USB test mode" to work around errata 40-42 (stepping a0, a1)
-+ * which could result in missing packets and interrupts.
-+ * Supposedly this turns off double buffering for all endpoints.
-+ */
-+ if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
-+ UDC_RES1 = 0x00;
-+ UDC_RES2 = 0x00;
-+ if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Proc Filesystem Support
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#if CONFIG_PROC_FS
-+
-+#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
-+#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
-+#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
-+#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
-+
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ const char * num_fmt = "%25.25s: %8.8lX\n";
-+ const char * cnt_fmt = "%25.25s: %lu\n";
-+ const char * yn_fmt = "%25.25s: %s\n";
-+ const char * yes = "YES";
-+ const char * no = "NO";
-+ unsigned long v;
-+ char * p = page;
-+ int len;
-+
-+ SAY( "PXA USB Controller Core\n" );
-+ SAY( "Active Client: %s\n", usbd_info.client_name ? usbd_info.client_name : "none");
-+ SAY( "USB state: %s (%s) %d\n",
-+ device_state_names[ sm_state_to_device_state[ sm_state ] ],
-+ state_names[ sm_state ],
-+ sm_state );
-+
-+ SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
-+ SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
-+ SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
-+ SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
-+
-+ SAY( "\n" );
-+
-+ v = UDCCR;
-+ SAY( "\nUDC Control Register\n" );
-+ SAYV( v );
-+ SAYC( "UDC Enabled", ( v & UDCCR_UDE ) ? yes : no );
-+ SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
-+ SAYC( "Suspend/Resume interrupts masked", ( v & UDCCR_SRM ) ? yes : no );
-+ SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
-+ SAYC( "Reset pending", ( v & UDCCR_RSTIR ) ? yes : no );
-+ SAYC( "Suspend pending", ( v & UDCCR_SUSIR ) ? yes : no );
-+ SAYC( "Resume pending", ( v & UDCCR_RESIR ) ? yes : no );
-+
-+ len = ( p - page ) - off;
-+ if ( len < 0 )
-+ len = 0;
-+ *eof = ( len <=count ) ? 1 : 0;
-+ *start = page + off;
-+ return len;
-+}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+#if 0
-+static void irq_handler(int channel, void *data, struct pt_regs *regs)
-+{
-+ if( channel == usbd_info.dmach_rx)
-+ {
-+ printk( "USB receive DMA\n");
-+ }
-+ else if( channel == usbd_info.dmach_tx)
-+ {
-+ printk( "USB transmit DMA\n");
-+ }
-+ else
-+ {
-+ printk( "USB unknown DMA channel\n");
-+ }
-+}
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Module Initialization and Shutdown
-+//////////////////////////////////////////////////////////////////////////////
-+/*
-+ * usbctl_init()
-+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs
-+ * entry. Leave UDC disabled.
-+ */
-+int __init usbctl_init( void )
-+{
-+ int retval = 0;
-+
-+ udc_disable();
-+
-+ memset( &usbd_info, 0, sizeof( usbd_info ) );
-+
-+#if CONFIG_PROC_FS
-+ create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
-+#endif
-+
-+#if 0
-+ /* setup rx dma */
-+ usbd_info.dmach_rx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
-+ if (usbd_info.dmach_rx < 0) {
-+ printk("%sunable to register for rx dma rc=%d\n", pszMe, usbd_info.dmach_rx );
-+ goto err_rx_dma;
-+ }
-+
-+ /* setup tx dma */
-+ usbd_info.dmach_tx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
-+ if (usbd_info.dmach_tx < 0) {
-+ printk("%sunable to register for tx dma rc=%d\n",pszMe,usbd_info.dmach_tx);
-+ goto err_tx_dma;
-+ }
-+#endif
-+
-+ /* now allocate the IRQ. */
-+ retval = request_irq(IRQ_USB, udc_int_hndlr, SA_INTERRUPT, "PXA USB core", NULL);
-+ if (retval) {
-+ printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
-+ goto err_irq;
-+ }
-+
-+ printk( "PXA USB Controller Core Initialized\n");
-+ return 0;
-+
-+err_irq:
-+#if 0
-+ pxa_free_dma(usbd_info.dmach_tx);
-+ usbd_info.dmach_tx = 0;
-+err_tx_dma:
-+ pxa_free_dma(usbd_info.dmach_rx);
-+ usbd_info.dmach_rx = 0;
-+err_rx_dma:
-+#endif
-+ return retval;
-+}
-+/*
-+ * usbctl_exit()
-+ * Release DMA and interrupt resources
-+ */
-+void __exit usbctl_exit( void )
-+{
-+ printk("Unloading PXA USB Controller\n");
-+
-+ udc_disable();
-+
-+#if CONFIG_PROC_FS
-+ remove_proc_entry ( PROC_NODE_NAME, NULL);
-+#endif
-+
-+ pxa_free_dma(usbd_info.dmach_rx);
-+ pxa_free_dma(usbd_info.dmach_tx);
-+ free_irq(IRQ_USB, NULL);
-+}
-+
-+module_init( usbctl_init );
-+module_exit( usbctl_exit );
-+
-+EXPORT_SYMBOL( pxa_usb_open );
-+EXPORT_SYMBOL( pxa_usb_start );
-+EXPORT_SYMBOL( pxa_usb_stop );
-+EXPORT_SYMBOL( pxa_usb_close );
-+EXPORT_SYMBOL( pxa_usb_get_descriptor_ptr );
-+EXPORT_SYMBOL( pxa_usb_set_string_descriptor );
-+EXPORT_SYMBOL( pxa_usb_get_string_descriptor );
-+EXPORT_SYMBOL( pxa_usb_kmalloc_string_descriptor );
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_ctl.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation 2001
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * usb_ctl.h
-+ *
-+ * PRIVATE interface used to share info among components of the PXA USB
-+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
-+ * should use pxa_usb.h.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.h
-+ *
-+ */
-+
-+#ifndef _USB_CTL_H
-+#define _USB_CTL_H
-+
-+/* Interrupt mask bits and UDC enable bit */
-+#define UDCCR_MASK_BITS (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
-+
-+/*
-+ * These states correspond to those in the USB specification v1.0
-+ * in chapter 8, Device Framework.
-+ */
-+enum {
-+ USB_STATE_NOTATTACHED =0,
-+ USB_STATE_ATTACHED =1,
-+ USB_STATE_POWERED =2,
-+ USB_STATE_DEFAULT =3,
-+ USB_STATE_ADDRESS =4,
-+ USB_STATE_CONFIGURED =5,
-+ USB_STATE_SUSPENDED =6
-+};
-+
-+struct usb_stats_t {
-+ unsigned long ep0_fifo_write_failures;
-+ unsigned long ep0_bytes_written;
-+ unsigned long ep0_fifo_read_failures;
-+ unsigned long ep0_bytes_read;
-+};
-+
-+struct usb_info_t
-+{
-+ char * client_name;
-+ dmach_t dmach_tx, dmach_rx;
-+ int state;
-+ unsigned char address;
-+ struct usb_stats_t stats;
-+};
-+
-+/* in usb_ctl.c */
-+extern struct usb_info_t usbd_info;
-+
-+/*
-+ * Function Prototypes
-+ */
-+enum {
-+ kError =-1,
-+ kEvSuspend =0,
-+ kEvReset =1,
-+ kEvResume =2,
-+ kEvAddress =3,
-+ kEvConfig =4,
-+ kEvDeConfig =5
-+};
-+int usbctl_next_state_on_event( int event );
-+
-+/* endpoint zero */
-+void ep0_reset(void);
-+void ep0_int_hndlr(void);
-+
-+/* receiver */
-+void ep_bulk_out1_state_change_notify( int new_state );
-+int ep_bulk_out1_recv(void);
-+int ep_bulk_out1_init(int chn);
-+void ep_bulk_out1_int_hndlr(int status);
-+void ep_bulk_out1_reset(void);
-+void ep_bulk_out1_stall(void);
-+
-+/* xmitter */
-+void ep_bulk_in1_state_change_notify( int new_state );
-+void ep_bulk_in1_reset(void);
-+int ep_bulk_in1_init(int chn);
-+void ep_bulk_in1_int_hndlr(int status);
-+void ep_bulk_in1_stall(void);
-+
-+#endif /* _USB_CTL_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,556 @@
-+/*
-+ * Copyright (C) Extenex Corporation 2001
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * PXA USB controller driver - Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for more info.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+
-+#include "pxa_usb.h" /* public interface */
-+#include "usb_ctl.h" /* private stuff */
-+#include "usb_ep0.h"
-+
-+
-+// 1 == lots of trace noise, 0 = only "important' stuff
-+#define VERBOSITY 0
-+
-+enum { true = 1, false = 0 };
-+typedef int bool;
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+#if 1 && !defined( ASSERT )
-+# define ASSERT(expr) \
-+if(!(expr)) { \
-+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-+#expr,__FILE__,__FUNCTION__,__LINE__); \
-+}
-+#else
-+# define ASSERT(expr)
-+#endif
-+
-+#if VERBOSITY
-+#define PRINTKD(fmt, args...) printk( fmt , ## args)
-+#else
-+#define PRINTKD(fmt, args...)
-+#endif
-+
-+static EP0_state ep0_state = EP0_IDLE;
-+
-+/***************************************************************************
-+ Prototypes
-+ ***************************************************************************/
-+/* "setup handlers" -- the main functions dispatched to by the
-+ .. isr. These represent the major "modes" of endpoint 0 operation */
-+static void sh_setup_begin(void); /* setup begin (idle) */
-+static void sh_write( void ); /* writing data */
-+static int read_fifo( usb_dev_request_t * p );
-+static void write_fifo( void );
-+static void get_descriptor( usb_dev_request_t * pReq );
-+static void queue_and_start_write( void * p, int req, int act );
-+
-+/***************************************************************************
-+ Inline Helpers
-+ ***************************************************************************/
-+
-+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
-+
-+/* print string descriptor */
-+static inline void psdesc( string_desc_t * p )
-+{
-+ int i;
-+ int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
-+ printk( "'" );
-+ for( i = 0 ; i < nchars ; i++ ) {
-+ printk( "%c", (char) p->bString[i] );
-+ }
-+ printk( "'\n" );
-+}
-+
-+#if VERBOSITY
-+/* "pcs" == "print control status" */
-+static inline void pcs( void )
-+{
-+ __u32 foo = UDCCS0;
-+ printk( "%08x: %s %s %s %s %s %s\n",
-+ foo,
-+ foo & UDCCS0_SA ? "SA" : "",
-+ foo & UDCCS0_OPR ? "OPR" : "",
-+ foo & UDCCS0_RNE ? "RNE" : "",
-+ foo & UDCCS0_SST ? "SST" : "",
-+ foo & UDCCS0_FST ? "FST" : "",
-+ foo & UDCCS0_DRWF ? "DRWF" : ""
-+ );
-+}
-+static inline void preq( usb_dev_request_t * pReq )
-+{
-+ static char * tnames[] = { "dev", "intf", "ep", "oth" };
-+ static char * rnames[] = { "std", "class", "vendor", "???" };
-+ char * psz;
-+ switch( pReq->bRequest ) {
-+ case GET_STATUS: psz = "get stat"; break;
-+ case CLEAR_FEATURE: psz = "clr feat"; break;
-+ case SET_FEATURE: psz = "set feat"; break;
-+ case SET_ADDRESS: psz = "set addr"; break;
-+ case GET_DESCRIPTOR: psz = "get desc"; break;
-+ case SET_DESCRIPTOR: psz = "set desc"; break;
-+ case GET_CONFIGURATION: psz = "get cfg"; break;
-+ case SET_CONFIGURATION: psz = "set cfg"; break;
-+ case GET_INTERFACE: psz = "get intf"; break;
-+ case SET_INTERFACE: psz = "set intf"; break;
-+ case SYNCH_FRAME: psz = "synch frame"; break;
-+ default: psz = "unknown"; break;
-+ }
-+ printk( "- [%s: %s req to %s. dir=%s]\n", psz,
-+ rnames[ (pReq->bmRequestType >> 5) & 3 ],
-+ tnames[ pReq->bmRequestType & 3 ],
-+ ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
-+}
-+
-+#else
-+static inline void pcs( void ){}
-+static inline void preq( usb_dev_request_t *x){}
-+#endif
-+
-+/***************************************************************************
-+ Globals
-+ ***************************************************************************/
-+static const char pszMe[] = "usbep0: ";
-+
-+/* pointer to current setup handler */
-+static void (*current_handler)(void) = sh_setup_begin;
-+
-+/* global write struct to keep write
-+ ..state around across interrupts */
-+static struct {
-+ unsigned char *p;
-+ int bytes_left;
-+} wr;
-+
-+/***************************************************************************
-+ Public Interface
-+ ***************************************************************************/
-+
-+/* reset received from HUB (or controller just went nuts and reset by itself!)
-+ so udc core has been reset, track this state here */
-+void ep0_reset(void)
-+{
-+ PRINTKD( "%sep0_reset\n", pszMe);
-+ /* reset state machine */
-+ current_handler = sh_setup_begin;
-+ wr.p = NULL;
-+ wr.bytes_left = 0;
-+ usbd_info.address=0;
-+}
-+
-+/* handle interrupt for endpoint zero */
-+void ep0_int_hndlr( void )
-+{
-+ PRINTKD( "%sep0_int_hndlr\n", pszMe);
-+ pcs();
-+ (*current_handler)();
-+}
-+
-+/***************************************************************************
-+ Setup Handlers
-+ ***************************************************************************/
-+/*
-+ * sh_setup_begin()
-+ * This setup handler is the "idle" state of endpoint zero. It looks for OPR
-+ * (OUT packet ready) to see if a setup request has been been received from the
-+ * host.
-+ *
-+ */
-+static void sh_setup_begin( void )
-+{
-+ usb_dev_request_t req;
-+ int request_type;
-+ int n;
-+ __u32 cs_reg_in = UDCCS0;
-+
-+ PRINTKD( "%ssh_setup_begin\n", pszMe);
-+
-+ /* Be sure out packet ready, otherwise something is wrong */
-+ if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
-+ /* we can get here early...if so, we'll int again in a moment */
-+ PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ if( ((cs_reg_in & UDCCS0_SA) == 0) && (ep0_state == EP0_IN_DATA_PHASE))
-+ {
-+ PRINTKD( "%ssetup begin: premature status\n", pszMe );
-+
-+ /* premature status, reset tx fifo and go back to idle state*/
-+ UDCCS0 = UDCCS0_OPR | UDCCS0_FTF;
-+
-+ ep0_state = EP0_IDLE;
-+ return;
-+ }
-+
-+ if( (UDCCS0 & UDCCS0_RNE) == 0)
-+ {
-+ /* zero-length OUT? */
-+ printk( "%ssetup begin: zero-length OUT?\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ /* read the setup request */
-+ n = read_fifo( &req );
-+ if ( n != sizeof( req ) ) {
-+ printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
-+ " Stalling out...\n",
-+ pszMe, sizeof( req ), n );
-+ /* force stall, serviced out */
-+ UDCCS0 = UDCCS0_FST;
-+ goto sh_sb_end;
-+ }
-+
-+ /* Is it a standard request? (not vendor or class request) */
-+ request_type = type_code_from_request( req.bmRequestType );
-+ if ( request_type != 0 ) {
-+ printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
-+ pszMe, request_type );
-+ goto sh_sb_end;
-+ }
-+
-+#if VERBOSITY
-+ {
-+ unsigned char * pdb = (unsigned char *) &req;
-+ PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
-+ pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
-+ );
-+ preq( &req );
-+ }
-+#endif
-+
-+ /* Handle it */
-+ switch( req.bRequest ) {
-+
-+ case SET_ADDRESS:
-+ PRINTKD( "%sSET_ADDRESS handled by UDC\n", pszMe);
-+ break;
-+#if 0 /* NOT_NEEDED */
-+
-+ case SET_FEATURE:
-+ PRINTKD( "%sSET_FEATURE handled by UDC\n", pszMe);
-+ break;
-+
-+ case CLEAR_FEATURE:
-+ PRINTKD( "%sCLEAR_FEATURE handled by UDC\n", pszMe);
-+ break;
-+
-+ case GET_CONFIGURATION:
-+ PRINTKD( "%sGET_CONFIGURATION handled by UDC\n", pszMe );
-+ break;
-+
-+ case GET_STATUS:
-+ PRINTKD( "%s%sGET_STATUS handled by UDC\n", pszMe );
-+ break;
-+
-+ case GET_INTERFACE:
-+ PRINTKD( "%sGET_INTERFACE handled by UDC\n", pszMe);
-+ break;
-+
-+ case SYNCH_FRAME:
-+ PRINTKD( "%sSYNCH_FRAME handled by UDC\n", pszMe );
-+ break;
-+#endif
-+
-+ case GET_DESCRIPTOR:
-+ PRINTKD( "%sGET_DESCRIPTOR\n", pszMe );
-+ get_descriptor( &req );
-+ break;
-+
-+ case SET_INTERFACE:
-+ PRINTKD( "%sSET_INTERFACE TODO...\n", pszMe);
-+ break;
-+
-+ case SET_DESCRIPTOR:
-+ PRINTKD( "%sSET_DESCRIPTOR TODO...\n", pszMe );
-+ break;
-+
-+ case SET_CONFIGURATION:
-+ PRINTKD( "%sSET_CONFIGURATION %d\n", pszMe, req.wValue);
-+
-+/*
-+ * FIXME: Something is not quite right here... I only ever get a
-+ * de-configure from the host. Ignoring it for now, since usb
-+ * ethernet won't do anything unless usb is 'configured'.
-+ *
-+ */
-+#if 0
-+ switch( req.wValue)
-+ {
-+ case 0:
-+ /* configured */
-+ usbctl_next_state_on_event( kEvConfig );
-+ break;
-+ case 1:
-+ /* de-configured */
-+ usbctl_next_state_on_event( kEvDeConfig );
-+ break;
-+ default:
-+ PRINTKD( "%sSET_CONFIGURATION: unknown configuration value (%d)\n", pszMe, req.wValue);
-+ break;
-+ }
-+#endif
-+ break;
-+ default :
-+ printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
-+ break;
-+ } /* switch( bRequest ) */
-+
-+sh_sb_end:
-+ return;
-+}
-+
-+/*
-+ * sh_write()
-+ *
-+ * Due to UDC bugs we push everything into the fifo in one go.
-+ * Using interrupts just didn't work right...
-+ * This should be ok, since control request are small.
-+ */
-+static void sh_write()
-+{
-+ PRINTKD( "sh_write\n" );
-+ do
-+ {
-+ write_fifo();
-+ } while( ep0_state != EP0_END_XFER);
-+}
-+
-+/***************************************************************************
-+ Other Private Subroutines
-+ ***************************************************************************/
-+/*
-+ * queue_and_start_write()
-+ * data == data to send
-+ * req == bytes host requested
-+ * act == bytes we actually have
-+ *
-+ * Sets up the global "wr"-ite structure and load the outbound FIFO
-+ * with data.
-+ *
-+ */
-+static void queue_and_start_write( void * data, int req, int act )
-+{
-+ PRINTKD( "write start: bytes requested=%d actual=%d\n", req, act);
-+
-+ wr.p = (unsigned char*) data;
-+ wr.bytes_left = MIN( act, req );
-+
-+ ep0_state = EP0_IN_DATA_PHASE;
-+ sh_write();
-+
-+ return;
-+}
-+/*
-+ * write_fifo()
-+ * Stick bytes in the endpoint zero FIFO.
-+ *
-+ */
-+static void write_fifo( void )
-+{
-+ int bytes_this_time = MIN( wr.bytes_left, EP0_FIFO_SIZE );
-+ int bytes_written = 0;
-+
-+ while( bytes_this_time-- ) {
-+// PRINTKD( "%2.2X ", *wr.p );
-+ UDDR0 = *wr.p++;
-+ bytes_written++;
-+ }
-+ wr.bytes_left -= bytes_written;
-+
-+ usbd_info.stats.ep0_bytes_written += bytes_written;
-+
-+ if( (wr.bytes_left==0))
-+ {
-+ wr.p = NULL; /* be anal */
-+
-+ if(bytes_written < EP0_FIFO_SIZE)
-+ {
-+ int count;
-+ int udccs0;
-+
-+ /* We always end the transfer with a short or zero length packet */
-+ ep0_state = EP0_END_XFER;
-+ current_handler = sh_setup_begin;
-+
-+ /* Let the packet go... */
-+ UDCCS0 = UDCCS0_IPR;
-+
-+ /* Wait until we get to status-stage, then ack.
-+ *
-+ * When the UDC sets the UDCCS0[OPR] bit, an interrupt
-+ * is supposed to be generated (see 12.5.1 step 14ff, PXA Dev Manual).
-+ * That approach didn't work out. Usually a new SETUP command was
-+ * already in the fifo. I tried many approaches but was always losing
-+ * at least some OPR interrupts. Thus the polling below...
-+ */
-+ count = 1000;
-+ udccs0 = UDCCS0;
-+ do
-+ {
-+ if( (UDCCS0 & UDCCS0_OPR))
-+ {
-+ /* clear OPR, generate ack */
-+ UDCCS0 = UDCCS0_OPR;
-+ break;
-+ }
-+ count--;
-+ udelay(1);
-+ } while( count);
-+
-+ PRINTKD( "write fifo: count=%d UDCCS0=%x UDCCS0=%x\n", count, udccs0, UDCCS0);
-+ }
-+ }
-+ /* something goes poopy if I dont wait here ... */
-+ udelay(500);
-+
-+ PRINTKD( "write fifo: bytes sent=%d, bytes left=%d\n", bytes_written, wr.bytes_left);
-+}
-+
-+/*
-+ * read_fifo()
-+ * Read bytes out of FIFO and put in request.
-+ * Called to do the initial read of setup requests
-+ * from the host. Return number of bytes read.
-+ *
-+ */
-+static int read_fifo( usb_dev_request_t * request )
-+{
-+ int bytes_read = 0;
-+ unsigned char * pOut = (unsigned char*) request;
-+
-+ int udccs0 = UDCCS0;
-+
-+ if( (udccs0 & SETUP_READY) == SETUP_READY)
-+ {
-+ /* ok it's a setup command */
-+ while( UDCCS0 & UDCCS0_RNE)
-+ {
-+ if( bytes_read >= sizeof( usb_dev_request_t))
-+ {
-+ /* We've already read enought o fill usb_dev_request_t.
-+ * Our tummy is full. Go barf...
-+ */
-+ printk( "%sread_fifo(): read failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_read_failures++;
-+ break;
-+ }
-+
-+ *pOut++ = UDDR0;
-+ bytes_read++;
-+ }
-+ }
-+ PRINTKD( "read_fifo %d bytes\n", bytes_read );
-+
-+ /* clear SA & OPR */
-+ UDCCS0 = SETUP_READY;
-+
-+ usbd_info.stats.ep0_bytes_read += bytes_read;
-+ return bytes_read;
-+}
-+
-+/*
-+ * get_descriptor()
-+ * Called from sh_setup_begin to handle data return
-+ * for a GET_DESCRIPTOR setup request.
-+ */
-+static void get_descriptor( usb_dev_request_t * pReq )
-+{
-+ string_desc_t * pString;
-+ ep_desc_t * pEndpoint = 0;
-+
-+ desc_t * pDesc = pxa_usb_get_descriptor_ptr();
-+ int type = pReq->wValue >> 8;
-+ int idx = pReq->wValue & 0xFF;
-+
-+// PRINTKD( "%sget_descriptor for %d\n", pszMe, type );
-+ switch( type ) {
-+ case USB_DESC_DEVICE:
-+ queue_and_start_write( &pDesc->dev,
-+ pReq->wLength,
-+ pDesc->dev.bLength );
-+ break;
-+
-+ // return config descriptor buffer, cfg, intf, 2 ep
-+ case USB_DESC_CONFIG:
-+ queue_and_start_write( &pDesc->b,
-+ pReq->wLength,
-+ sizeof( struct cdb ) );
-+ break;
-+
-+ // not quite right, since doesn't do language code checking
-+ case USB_DESC_STRING:
-+ pString = pxa_usb_get_string_descriptor( idx );
-+ if ( pString ) {
-+ if ( idx != 0 ) { // if not language index
-+ printk( "%sReturn string %d: ", pszMe, idx );
-+ psdesc( pString );
-+ }
-+ queue_and_start_write( pString,
-+ pReq->wLength,
-+ pString->bLength );
-+ }
-+ else {
-+ printk("%sunkown string index %d Stall.\n", pszMe, idx );
-+ }
-+ break;
-+
-+ case USB_DESC_INTERFACE:
-+ if ( idx == pDesc->b.intf.bInterfaceNumber ) {
-+ queue_and_start_write( &pDesc->b.intf,
-+ pReq->wLength,
-+ pDesc->b.intf.bLength );
-+ }
-+ break;
-+
-+ case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
-+ if ( idx == 1 )
-+ pEndpoint = &pDesc->b.ep1; //[BULK_IN1];
-+ else if ( idx == 2 )
-+ pEndpoint = &pDesc->b.ep2; //[BULK_OUT1];
-+ else
-+ pEndpoint = NULL;
-+ if ( pEndpoint ) {
-+ queue_and_start_write( pEndpoint,
-+ pReq->wLength,
-+ pEndpoint->bLength );
-+ } else {
-+ printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
-+ }
-+ break;
-+
-+
-+ default :
-+ printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
-+ break;
-+
-+ }
-+}
-+
-+/* end usb_ep0.c - who needs this comment? */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_ep0.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,66 @@
-+/*
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * usb_ep0.h - PXA USB controller driver.
-+ * Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for details.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) -
-+ *
-+ */
-+
-+#ifndef __USB_EP0_H
-+#define __USB_EP0_H
-+
-+#define EP0_FIFO_SIZE 16
-+#define SETUP_READY (UDCCS0_SA | UDCCS0_OPR)
-+
-+/*================================================
-+ * USB Protocol Stuff
-+ */
-+
-+/* Request Codes */
-+enum {
-+ GET_STATUS =0,
-+ CLEAR_FEATURE =1,
-+ /* reserved =2 */
-+ SET_FEATURE =3,
-+ /* reserved =4 */
-+ SET_ADDRESS =5,
-+ GET_DESCRIPTOR =6,
-+ SET_DESCRIPTOR =7,
-+ GET_CONFIGURATION =8,
-+ SET_CONFIGURATION =9,
-+ GET_INTERFACE =10,
-+ SET_INTERFACE =11,
-+ SYNCH_FRAME =12
-+};
-+
-+typedef enum {
-+ EP0_IDLE,
-+ EP0_IN_DATA_PHASE,
-+ EP0_END_XFER,
-+ EP0_OUT_DATA_PHASE
-+} EP0_state;
-+
-+/* USB Device Requests */
-+typedef struct
-+{
-+ __u8 bmRequestType;
-+ __u8 bRequest;
-+ __u16 wValue;
-+ __u16 wIndex;
-+ __u16 wLength;
-+} usb_dev_request_t __attribute__ ((packed));
-+
-+/* Data extraction from usb_request_t fields */
-+enum {
-+ kTargetDevice =0,
-+ kTargetInterface=1,
-+ kTargetEndpoint =2
-+};
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_recv.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,173 @@
-+/*
-+ * Generic receive layer for the PXA USB client function
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_recv.c
-+ *
-+ * TODO: Add support for DMA.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static char *ep_bulk_out1_buf;
-+static int ep_bulk_out1_len;
-+static int ep_bulk_out1_remain;
-+static usb_callback_t ep_bulk_out1_callback;
-+static int rx_pktsize;
-+
-+static void
-+ep_bulk_out1_start(void)
-+{
-+ /* disable DMA */
-+ UDCCS2 &= ~UDCCS_BO_DME;
-+
-+ /* enable interrupts for endpoint 2 (bulk out) */
-+ UICR0 &= ~UICR0_IM2;
-+}
-+
-+static void
-+ep_bulk_out1_done(int flag)
-+{
-+ int size = ep_bulk_out1_len - ep_bulk_out1_remain;
-+
-+ if (!ep_bulk_out1_len)
-+ return;
-+
-+ ep_bulk_out1_len = 0;
-+ if (ep_bulk_out1_callback) {
-+ ep_bulk_out1_callback(flag, size);
-+ }
-+}
-+
-+void
-+ep_bulk_out1_state_change_notify( int new_state )
-+{
-+}
-+
-+void
-+ep_bulk_out1_stall( void )
-+{
-+ /* SET_FEATURE force stall at UDC */
-+ UDCCS2 |= UDCCS_BO_FST;
-+}
-+
-+int
-+ep_bulk_out1_init(int chn)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ ep_bulk_out1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep_bulk_out1_reset(void)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ UDCCS2 &= ~UDCCS_BO_FST;
-+ ep_bulk_out1_done(-EINTR);
-+}
-+
-+void
-+ep_bulk_out1_int_hndlr(int udcsr)
-+{
-+ int status = UDCCS2;
-+ if( usb_debug) printk("ep_bulk_out1_int_hndlr: UDCCS2=%x\n", status);
-+
-+ if( (status & (UDCCS_BO_RNE | UDCCS_BO_RSP)) == UDCCS_BO_RSP)
-+ {
-+ /* zero-length packet */
-+ }
-+
-+ if( status & UDCCS_BO_RNE)
-+ {
-+ int len;
-+ int i;
-+ char *buf = ep_bulk_out1_buf + ep_bulk_out1_len - ep_bulk_out1_remain;
-+
-+ /* bytes in FIFO */
-+ len = (UBCR2 & 0xff) +1;
-+
-+ if( usb_debug) printk("usb_recv: "
-+ "len=%d out1_len=%d out1_remain=%d\n",
-+ len,ep_bulk_out1_len,ep_bulk_out1_remain);
-+
-+ if( len > ep_bulk_out1_remain)
-+ {
-+ /* FIXME: if this happens, we need a temporary overflow buffer */
-+ printk("usb_recv: Buffer overwrite warning...\n");
-+ len = ep_bulk_out1_remain;
-+ }
-+
-+ /* read data out of fifo */
-+ for( i=0; i<len; i++)
-+ {
-+ *buf++ = UDDR2 & 0xff;
-+ }
-+
-+ ep_bulk_out1_remain -= len;
-+ ep_bulk_out1_done((len) ? 0 : -EPIPE);
-+ }
-+
-+ /* ack RPC - FIXME: '|=' we may ack SST here, too */
-+ UDCCS2 |= UDCCS_BO_RPC;
-+ return;
-+}
-+
-+int
-+pxa_usb_recv(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (ep_bulk_out1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep_bulk_out1_buf = buf;
-+ ep_bulk_out1_len = len;
-+ ep_bulk_out1_callback = callback;
-+ ep_bulk_out1_remain = len;
-+ ep_bulk_out1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+void
-+pxa_usb_recv_reset(void)
-+{
-+ ep_bulk_out1_reset();
-+}
-+
-+void
-+pxa_usb_recv_stall(void)
-+{
-+ ep_bulk_out1_stall();
-+}
-+
-+EXPORT_SYMBOL(pxa_usb_recv_stall);
-+EXPORT_SYMBOL(pxa_usb_recv);
-+EXPORT_SYMBOL(pxa_usb_recv_reset);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-pxa/usb_send.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,190 @@
-+/*
-+ * Generic xmit layer for the PXA USB client function
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_send.c
-+ *
-+ * TODO: Add support for DMA.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+#include <asm/byteorder.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static char *ep_bulk_in1_buf;
-+static int ep_bulk_in1_len;
-+static int ep_bulk_in1_remain;
-+static usb_callback_t ep_bulk_in1_callback;
-+static int tx_pktsize;
-+
-+/* device state is changing, async */
-+void
-+ep_bulk_in1_state_change_notify( int new_state )
-+{
-+}
-+
-+/* set feature stall executing, async */
-+void
-+ep_bulk_in1_stall( void )
-+{
-+ UDCCS1 |= UDCCS_BI_FST;
-+}
-+
-+static void
-+ep_bulk_in1_send_packet(void)
-+{
-+ int i;
-+ char *buf = ep_bulk_in1_buf + ep_bulk_in1_len - ep_bulk_in1_remain;
-+ int out_size = tx_pktsize;
-+
-+ if( usb_debug) printk( "ep_bulk_in1_send_packet: UICR0=%x UDCCS1=%x\n", UICR0, UDCCS1);
-+
-+ if( out_size > ep_bulk_in1_remain)
-+ {
-+ out_size = ep_bulk_in1_remain;
-+ }
-+
-+ for( i=0; i<out_size; i++)
-+ {
-+ UDDR1 = *buf++;
-+ }
-+
-+ UDCCS1 = UDCCS_BI_TPC;
-+ if( out_size < tx_pktsize)
-+ {
-+ /* short packet */
-+ UDCCS1 = UDCCS_BI_TSP;
-+ }
-+ ep_bulk_in1_remain -= out_size;
-+
-+ if( usb_debug) printk( "ep_bulk_in1_send_packet: "
-+ "UICR0=%x UDCCS1=%x send bytes=%d left=%d\n",
-+ UICR0, UDCCS1, out_size, ep_bulk_in1_remain);
-+}
-+
-+static void
-+ep_bulk_in1_start(void)
-+{
-+ if (!ep_bulk_in1_len)
-+ return;
-+
-+ UICR0 &= ~UICR0_IM1;
-+
-+ ep_bulk_in1_send_packet();
-+}
-+
-+static void
-+ep_bulk_in1_done(int flag)
-+{
-+ int size = ep_bulk_in1_len - ep_bulk_in1_remain;
-+ if (ep_bulk_in1_len) {
-+ ep_bulk_in1_len = 0;
-+ if (ep_bulk_in1_callback)
-+ ep_bulk_in1_callback(flag, size);
-+ }
-+}
-+
-+int
-+ep_bulk_in1_init(int chn)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ ep_bulk_in1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep_bulk_in1_reset(void)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ UDCCS1 &= ~UDCCS_BI_FST;
-+ ep_bulk_in1_done(-EINTR);
-+}
-+
-+void
-+ep_bulk_in1_int_hndlr(int usir0)
-+{
-+ int status = UDCCS1;
-+
-+ if (ep_bulk_in1_remain != 0) {
-+ /* more data to go */
-+ ep_bulk_in1_start();
-+ } else {
-+ if( status & UDCCS_BI_TPC)
-+ {
-+ UDCCS1 = UDCCS_BI_TPC;
-+ }
-+ ep_bulk_in1_done(0);
-+ }
-+}
-+
-+int
-+pxa_usb_send(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if( usb_debug) printk( "pxa_usb_send: "
-+ "data len=%d state=%d blen=%d\n",
-+ len, usbd_info.state, ep_bulk_in1_len);
-+
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+
-+ if (ep_bulk_in1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep_bulk_in1_buf = buf;
-+ ep_bulk_in1_len = len;
-+ ep_bulk_in1_callback = callback;
-+ ep_bulk_in1_remain = len;
-+ ep_bulk_in1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+
-+void
-+pxa_usb_send_reset(void)
-+{
-+ ep_bulk_in1_reset();
-+}
-+
-+int
-+pxa_usb_xmitter_avail( void )
-+{
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+ if (ep_bulk_in1_len)
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+
-+EXPORT_SYMBOL(pxa_usb_xmitter_avail);
-+EXPORT_SYMBOL(pxa_usb_send);
-+EXPORT_SYMBOL(pxa_usb_send_reset);
---- linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c 2004-03-31 17:15:11.000000000 +0200
-@@ -54,7 +54,7 @@
- * address as its return value, and the DMA address via
- * the dma_addr_t pointer.
- */
-- vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
-+ vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf, 0);
-
- SADTSA = (unsigned long)dma_buf;
- SADTCA = 4;
---- linux-2.4.25/arch/arm/mach-sa1100/sa1111.c~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/sa1111.c 2004-03-31 17:15:11.000000000 +0200
-@@ -243,9 +243,15 @@
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
-+#if CONFIG_ARCH_SA1100
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-+#elif CONFIG_ARCH_PXA
-+ set_GPIO_mode(GPIO11_3_6MHz_MD);
-+#else
-+#error missing clock setup
-+#endif
-
- /*
- * Turn VCO on, and disable PLL Bypass.
-@@ -300,6 +306,8 @@
- SBI_SMCR = smcr;
- }
-
-+#ifdef CONFIG_ARCH_SA1100
-+
- /*
- * Disable the memory bus request/grant signals on the SA1110 to
- * ensure that we don't receive spurious memory requests. We set
-@@ -341,5 +349,7 @@
- local_irq_restore(flags);
- }
-
-+#endif
-+
- EXPORT_SYMBOL(sa1111_wake);
- EXPORT_SYMBOL(sa1111_doze);
---- linux-2.4.25/arch/arm/mm/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -44,6 +44,7 @@
- p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
- p-$(CONFIG_CPU_SA110) += proc-sa110.o
- p-$(CONFIG_CPU_SA1100) += proc-sa110.o
-+p-$(CONFIG_CPU_XSCALE) += proc-xscale.o
-
- # Integrator follows "new style"
- # Soon, others will do too, and we can get rid of this
---- linux-2.4.25/arch/arm/mm/consistent.c~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/consistent.c 2004-03-31 17:15:11.000000000 +0200
-@@ -37,7 +37,8 @@
- *
- * Note that this does *not* zero the allocated area!
- */
--void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
-+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle,
-+ unsigned long cache_flags)
- {
- struct page *page, *end, *free;
- unsigned long order;
-@@ -55,7 +56,7 @@
- goto no_page;
-
- *dma_handle = page_to_bus(page);
-- ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0);
-+ ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, cache_flags);
- if (!ret)
- goto no_remap;
-
-@@ -106,7 +107,7 @@
- #endif
- gfp |= GFP_DMA;
-
-- return consistent_alloc(gfp, size, handle);
-+ return consistent_alloc(gfp, size, handle, 0);
- }
-
- /*
---- linux-2.4.25/arch/arm/mm/init.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/init.c 2004-03-31 17:15:11.000000000 +0200
-@@ -49,6 +49,9 @@
- static unsigned long totalram_pages;
- extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
- extern char _stext, _text, _etext, _end, __init_begin, __init_end;
-+#ifdef CONFIG_XIP_KERNEL
-+extern char _endtext, _sdata;
-+#endif
- extern unsigned long phys_initrd_start;
- extern unsigned long phys_initrd_size;
-
-@@ -347,7 +350,11 @@
- * Register the kernel text and data with bootmem.
- * Note that this can only be in node 0.
- */
-+#ifdef CONFIG_XIP_KERNEL
-+ reserve_bootmem_node(pgdat, __pa(&_sdata), &_end - &_sdata);
-+#else
- reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
-+#endif
-
- #ifdef CONFIG_CPU_32
- /*
-@@ -601,8 +608,13 @@
- unsigned int codepages, datapages, initpages;
- int i, node;
-
-+#ifndef CONFIG_XIP_KERNEL
- codepages = &_etext - &_text;
- datapages = &_end - &_etext;
-+#else
-+ codepages = &_endtext - &_text;
-+ datapages = &_end - &_sdata;
-+#endif
- initpages = &__init_end - &__init_begin;
-
- high_memory = (void *)__va(meminfo.end);
-@@ -658,11 +670,13 @@
-
- void free_initmem(void)
- {
-+#ifndef CONFIG_XIP_KERNEL
- if (!machine_is_integrator()) {
- free_area((unsigned long)(&__init_begin),
- (unsigned long)(&__init_end),
- "init");
- }
-+#endif
- }
-
- #ifdef CONFIG_BLK_DEV_INITRD
---- linux-2.4.25/arch/arm/mm/mm-armv.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/mm-armv.c 2004-03-31 17:15:11.000000000 +0200
-@@ -356,6 +356,19 @@
- p ++;
- #endif
-
-+#ifdef CONFIG_XIP_KERNEL
-+ p->physical = KERNEL_XIP_BASE_PHYS;
-+ p->virtual = KERNEL_XIP_BASE_VIRT;
-+ p->length = PGDIR_SIZE * 8;
-+ p->domain = DOMAIN_KERNEL;
-+ p->prot_read = 0; /* r=0, b=0 --> read-only for kernel mode */
-+ p->prot_write = 0;
-+ p->cacheable = 1;
-+ p->bufferable = 1;
-+
-+ p ++;
-+#endif
-+
- /*
- * Go through the initial mappings, but clear out any
- * pgdir entries that are not in the description.
-@@ -386,7 +399,7 @@
- init_maps->prot_read = 0;
- init_maps->prot_write = 0;
- init_maps->cacheable = 1;
-- init_maps->bufferable = 0;
-+ init_maps->bufferable = 1;
-
- create_mapping(init_maps);
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-xscale.S 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,1086 @@
-+/*
-+ * linux/arch/arm/mm/proc-xscale.S
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: November 2000
-+ * Copyright: (C) 2000, 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * MMU functions for the Intel XScale CPUs
-+ *
-+ * 2001 Aug 21:
-+ * some contributions by Brett Gaines <brett.w.gaines@intel.com>
-+ * Copyright 2001 by Intel Corp.
-+ *
-+ * 2001 Sep 08:
-+ * Completely revisited, many important fixes
-+ * Nicolas Pitre <nico@cam.org>
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+#include <asm/proc/pgtable.h>
-+
-+/*
-+ * Some knobs for cache allocation policy.
-+ * Allocate on write may or may not be beneficial depending on the memory
-+ * usage pattern of your main application. Write through cache is definitely
-+ * a performance loss in most cases, but might be used for special purposes.
-+ */
-+#define PMD_CACHE_WRITE_ALLOCATE 1
-+#define PTE_CACHE_WRITE_ALLOCATE 1
-+#define CACHE_WRITE_THROUGH 0
-+
-+/*
-+ * There are errata that say that dirty status bits in the cache may get
-+ * corrupted. The workaround significantly affects performance, and the bug
-+ * _might_ just not be that visible or critical to you, so it is configurable.
-+ * Let's hope a future core revision will tell us this was only a bad dream.
-+ * But in the mean time the risk and tradeoff is yours to decide....
-+ */
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+#undef CACHE_WRITE_THROUGH
-+#define CACHE_WRITE_THROUGH 1
-+#endif
-+
-+/*
-+ * This is the maximum size of an area which will be flushed. If the area
-+ * is larger than this, then we flush the whole cache
-+ */
-+#define MAX_AREA_SIZE 32768
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define CACHELINESIZE 32
-+
-+/*
-+ * the size of the data cache
-+ */
-+#define CACHESIZE 32768
-+
-+/*
-+ * and the page size
-+ */
-+#define PAGESIZE 4096
-+
-+/*
-+ * Virtual address used to allocate the cache when flushed
-+ *
-+ * This must be an address range which is _never_ used. It should
-+ * apparently have a mapping in the corresponding page table for
-+ * compatibility with future CPUs that _could_ require it. For instance we
-+ * don't care.
-+ *
-+ * This must be aligned on a 2*CACHESIZE boundary. The code selects one of
-+ * the 2 areas in alternance each time the clean_d_cache macro is used.
-+ * Without this the XScale core exhibits cache eviction problems and no one
-+ * knows why.
-+ *
-+ * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
-+ */
-+#define CLEAN_ADDR 0xfffe0000
-+
-+/*
-+ * This macro is used to wait for a CP15 write and is needed
-+ * when we have to ensure that the last operation to the co-pro
-+ * was completed before continuing with operation.
-+ */
-+ .macro cpwait, rd
-+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
-+ mov \rd, \rd @ wait for completion
-+ sub pc, pc, #4 @ flush instruction pipeline
-+ .endm
-+
-+ .macro cpwait_ret, lr, rd
-+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
-+ sub pc, \lr, \rd, LSR #32 @ wait for completion and
-+ @ flush instruction pipeline
-+ .endm
-+
-+#if !CACHE_WRITE_THROUGH
-+
-+/*
-+ * This macro cleans the entire dcache using line allocate.
-+ * The main loop has been unrolled to reduce loop overhead.
-+ * rd and rs are two scratch registers.
-+ */
-+ .macro clean_d_cache, rd, rs
-+ ldr \rs, =clean_addr
-+ ldr \rd, [\rs]
-+ eor \rd, \rd, #CACHESIZE
-+ str \rd, [\rs]
-+ add \rs, \rd, #CACHESIZE
-+1: mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ teq \rd, \rs
-+ bne 1b
-+ .endm
-+
-+ .macro clean_d_line, rd
-+ mcr p15, 0, \rd, c7, c10, 1
-+ .endm
-+
-+ .data
-+clean_addr: .word CLEAN_ADDR
-+
-+#else
-+
-+/*
-+ * If cache is write-through, there is no need to clean it.
-+ * Simply invalidating will do.
-+ */
-+
-+ .macro clean_d_cache, rd, rs
-+ mcr p15, 0, \rd, c7, c6, 0
-+ .endm
-+
-+ /* let's try to skip this needless operations at least within loops */
-+ .macro clean_d_line, rd
-+ .endm
-+
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_xscale_data_abort()
-+ *
-+ * obtain information about current aborted instruction.
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = saved SPSR
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR, bit 11 = write
-+ * r3 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ ldr r3, [r2] @ read aborted instruction
-+ bic r1, r1, #1 << 11 @ clear bits 11 of FSR
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_check_bugs()
-+ */
-+ENTRY(cpu_xscale_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+#ifndef CONFIG_XSCALE_CACHE_ERRATA
-+/*
-+ * cpu_xscale_proc_init()
-+ *
-+ * Nothing too exciting at the moment
-+ */
-+ENTRY(cpu_xscale_proc_init)
-+ mov pc, lr
-+#else
-+/*
-+ * We enable the cache here, but we make sure all the status bits for dirty
-+ * lines are cleared as well (see PXA250 erratum #120).
-+ */
-+ENTRY(cpu_xscale_proc_init)
-+ @ enable data cache
-+ ldr r0, cr_p
-+ ldmia r0, {r1, r2}
-+ orr r1, r1, #0x4
-+ orr r2, r2, #0x4
-+ stmia r0, {r1, r2}
-+ mcr p15, 0, r1, c1, c0, 0
-+ cpwait r0
-+
-+ @ invalidate data cache
-+ mcr p15, 0, r0, c7, c6, 0
-+
-+ @ fill main cache with write-through lines
-+ bic r0, pc, #0x1f
-+ add r1, r0, #CACHESIZE
-+1: ldr r2, [r0], #32
-+ cmp r0, r1
-+ bne 1b
-+
-+ @ enable test feature to force all fills to the mini-cache
-+ mov r1, #0x8
-+ mcr p15, 0, r1, c15, c15, 3
-+
-+ @ fill mini-cache with write-through lines (2kbytes, 64 lines)
-+ add r1, r0, #2048
-+2: ldr r2, [r0], #32
-+ cmp r0, r1
-+ bne 2b
-+
-+ @ disable test feature to force all fills to the mini-cache
-+ mov r1, #0x0
-+ mcr p15, 0, r1, c15, c15, 3
-+
-+ @ invalidate data cache again
-+ mcr p15, 0, r1, c7, c6, 0
-+ mov pc, lr
-+
-+cr_p: .long SYMBOL_NAME(cr_alignment)
-+#endif
-+
-+/*
-+ * cpu_xscale_proc_fin()
-+ */
-+ENTRY(cpu_xscale_proc_fin)
-+ str lr, [sp, #-4]!
-+ mov r0, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r0
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1800 @ ...IZ...........
-+ bic r0, r0, #0x0006 @ .............CA.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ bl cpu_xscale_cache_clean_invalidate_all @ clean caches
-+ ldr pc, [sp], #4
-+
-+/*
-+ * cpu_xscale_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_reset)
-+ mov r1, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r1 @ reset CPSR
-+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
-+ bic r1, r1, #0x0086 @ ........B....CA.
-+ bic r1, r1, #0x1900 @ ...IZ..S........
-+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
-+ bic r1, r1, #0x0001 @ ...............M
-+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
-+ @ CAUTION: MMU turned off from this point. We count on the pipeline
-+ @ already containing those two last instructions to survive.
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mov pc, r0
-+
-+/*
-+ * cpu_xscale_do_idle(type)
-+ *
-+ * Cause the processor to idle
-+ *
-+ * type:
-+ * 0 = slow idle
-+ * 1 = fast idle
-+ * 2 = switch to slow processor clock
-+ * 3 = switch to fast processor clock
-+ *
-+ * For now we do nothing but go to idle mode for every case
-+ *
-+ * XScale supports clock switching, but using idle mode support
-+ * allows external hardware to react to system state changes.
-+ */
-+ .align 5
-+
-+ENTRY(cpu_xscale_do_idle)
-+ mov r0, #1
-+ mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+/*
-+ * cpu_xscale_cache_clean_invalidate_all (void)
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. We should preserve r0 at all times.
-+ * 2. Even if this function implies cache "invalidation" by its name,
-+ * we don't need to actually use explicit invalidation operations
-+ * since the goal is to discard all valid references from the cache
-+ * and the cleaning of it already has that effect.
-+ * 3. Because of 2 above and the fact that kernel space memory is always
-+ * coherent across task switches there is no need to worry about
-+ * inconsistencies due to interrupts, ence no irq disabling.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_xscale_cache_clean_invalidate_all_r2:
-+ clean_d_cache r0, r1
-+ teq r2, #0
-+ mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_cache_clean_invalidate_range)
-+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhi cpu_xscale_cache_clean_invalidate_all_r2
-+1: clean_d_line r0 @ Clean D cache line
-+ mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ teq r2, #0
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ moveq pc, lr
-+ sub r0, r0, r3
-+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_flush_ram_page(page)
-+ *
-+ * clean all cache lines associated with this memory page
-+ *
-+ * page: page to clean
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_flush_ram_page)
-+#if !CACHE_WRITE_THROUGH
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #2 * CACHELINESIZE
-+ bne 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_xscale_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that on XScale we must clean all
-+ * entries also due to hardware errata (80200 A0 & A1 only).
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_invalidate_range)
-+ mrc p15, 0, r2, c0, c0, 0 @ Read part no.
-+ eor r2, r2, #0x69000000
-+ eor r2, r2, #0x00052000 @ 80200 XX part no.
-+ bics r2, r2, #0x1 @ Clear LSB in revision field
-+ moveq r2, #0
-+ beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1
-+
-+ tst r0, #CACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ tst r1, #CACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line
-+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
-+1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_range)
-+#if !CACHE_WRITE_THROUGH
-+ bic r0, r0, #CACHELINESIZE - 1
-+ sub r2, r1, r0
-+ cmp r2, #MAX_AREA_SIZE
-+ movhi r2, #0
-+ bhi cpu_xscale_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_clean_dcache_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * Note:
-+ * 1. we don't need to flush the write buffer in this case. [really? -Nico]
-+ * 2. we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_page)
-+#if !CACHE_WRITE_THROUGH
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #4 * CACHELINESIZE
-+ bne 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_entry)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_xscale_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * Note: This is vaguely defined as supposed to bring the dcache and the
-+ * icache in sync by the way this function is used.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_icache_invalidate_range)
-+ bic r0, r0, #CACHELINESIZE - 1
-+1: clean_d_line r0 @ Clean D cache line
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_icache_invalidate_page(page)
-+ *
-+ * invalidate all Icache lines associated with this area of memory
-+ *
-+ * page: page to invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_icache_invalidate_page)
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #4 * CACHELINESIZE
-+ bne 1b
-+ mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
-+ mov pc, lr
-+
-+/* ================================ CACHE LOCKING============================
-+ *
-+ * The XScale MicroArchitecture implements support for locking entries into
-+ * the data and instruction cache. The following functions implement the core
-+ * low level instructions needed to accomplish the locking. The developer's
-+ * manual states that the code that performs the locking must be in non-cached
-+ * memory. To accomplish this, the code in xscale-cache-lock.c copies the
-+ * following functions from the cache into a non-cached memory region that
-+ * is allocated through consistent_alloc().
-+ *
-+ */
-+ .align 5
-+/*
-+ * xscale_icache_lock
-+ *
-+ * r0: starting address to lock
-+ * r1: end address to lock
-+ */
-+ENTRY(xscale_icache_lock)
-+
-+iLockLoop:
-+ bic r0, r0, #CACHELINESIZE - 1
-+ mcr p15, 0, r0, c9, c1, 0 @ lock into cache
-+ cmp r0, r1 @ are we done?
-+ add r0, r0, #CACHELINESIZE @ advance to next cache line
-+ bls iLockLoop
-+ mov pc, lr
-+
-+/*
-+ * xscale_icache_unlock
-+ */
-+ENTRY(xscale_icache_unlock)
-+ mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
-+ mov pc, lr
-+
-+/*
-+ * xscale_dcache_lock
-+ *
-+ * r0: starting address to lock
-+ * r1: end address to lock
-+ */
-+ENTRY(xscale_dcache_lock)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov r2, #1
-+ mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
-+ cpwait ip @ Wait for completion
-+
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+dLockLoop:
-+ msr cpsr_c, r3
-+ mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
-+ mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
-+ msr cpsr_c, r2
-+ ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
-+ @ location [r0]. Post-increment
-+ @ r3 to next cache line
-+ cmp r0, r1 @ Are we done?
-+ bls dLockLoop
-+
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov r2, #0
-+ mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
-+ cpwait_ret lr, ip
-+
-+/*
-+ * xscale_dcache_unlock
-+ */
-+ENTRY(xscale_dcache_unlock)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
-+ mov pc, lr
-+
-+/*
-+ * Needed to determine the length of the code that needs to be copied.
-+ */
-+ .align 5
-+ENTRY(xscale_cache_dummy)
-+ mov pc, lr
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_all)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_range)
-+ bic r0, r0, #(PAGESIZE - 1) & 0x00ff
-+ bic r0, r0, #(PAGESIZE - 1) & 0xff00
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE @ arbitrary, should be tuned
-+ bhi cpu_xscale_tlb_invalidate_all
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ blo 1b
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_page)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r3, c8, c5, 1 @ invalidate I TLB entry
-+ cpwait_ret lr, ip
-+
-+/* ================================ TLB LOCKING==============================
-+ *
-+ * The XScale MicroArchitecture implements support for locking entries into
-+ * the Instruction and Data TLBs. The following functions provide the
-+ * low level support for supporting these under Linux. xscale-lock.c
-+ * implements some higher level management code. Most of the following
-+ * is taken straight out of the Developer's Manual.
-+ */
-+
-+/*
-+ * Lock I-TLB entry
-+ *
-+ * r0: Virtual address to translate and lock
-+ */
-+ .align 5
-+ENTRY(xscale_itlb_lock)
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+ msr cpsr_c, r3 @ Disable interrupts
-+ mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
-+ mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
-+ msr cpsr_c, r2 @ Restore interrupts
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Lock D-TLB entry
-+ *
-+ * r0: Virtual address to translate and lock
-+ */
-+ .align 5
-+ENTRY(xscale_dtlb_lock)
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+ msr cpsr_c, r3 @ Disable interrupts
-+ mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
-+ mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
-+ msr cpsr_c, r2 @ Restore interrupts
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Unlock all I-TLB entries
-+ */
-+ .align 5
-+ENTRY(xscale_itlb_unlock)
-+ mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
-+ mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Unlock all D-TLB entries
-+ */
-+ENTRY(xscale_dtlb_unlock)
-+ mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
-+ mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
-+ cpwait_ret lr, ip
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_xscale_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pgd)
-+ clean_d_cache r1, r2
-+ mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pmd)
-+#if PMD_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
-+ and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ orreq r1, r1, #PMD_SECT_TEX(1)
-+#elif CACHE_WRITE_THROUGH
-+ and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ biceq r1, r1, #PMD_SECT_BUFFERABLE
-+#endif
-+ str r1, [r0]
-+ mov ip, #0
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ *
-+ * Errata 40: must set memory to write-through for user read-only pages.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ bic r2, r1, #0xff0
-+ orr r2, r2, #PTE_TYPE_EXT @ extended page
-+
-+ eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
-+
-+ tst r3, #L_PTE_USER | L_PTE_EXEC @ User or Exec?
-+ orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
-+
-+ tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
-+ @ combined with user -> user r/w
-+
-+ @
-+ @ Handle the X bit. We want to set this bit for the minicache
-+ @ (U = E = B = W = 0, C = 1) or when write allocate is enabled,
-+ @ and we have a writeable, cacheable region. If we ignore the
-+ @ U and E bits, we can allow user space to use the minicache as
-+ @ well.
-+ @
-+ @ X = C & ~W & ~B
-+ @ | C & W & B & write_allocate
-+ @
-+ eor ip, r1, #L_PTE_CACHEABLE
-+ tst ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+#if PTE_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
-+ eorne ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+ tstne ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+#endif
-+ orreq r2, r2, #PTE_EXT_TEX(1)
-+
-+#if CACHE_WRITE_THROUGH
-+ tst r1, #L_PTE_CACHEABLE
-+ bicne r2, r2, #L_PTE_BUFFERABLE @ clear B only if C is set
-+#else
-+ @
-+ @ Errata 40: The B bit must be cleared for a user read-only
-+ @ cacheable page.
-+ @
-+ @ B = B & ~((U|E) & C & ~W)
-+ @
-+ and ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
-+ teq ip, #L_PTE_USER | L_PTE_CACHEABLE
-+ teqne ip, #L_PTE_EXEC | L_PTE_CACHEABLE
-+ teqne ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
-+ biceq r2, r2, #PTE_BUFFERABLE
-+#endif
-+
-+ tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
-+ movne r2, #0 @ no -> fault
-+
-+ str r2, [r0] @ hardware version
-+
-+ @ We try to map 64K page entries when possible.
-+ @ We do that for kernel space only since the usage pattern from
-+ @ the setting of VM area is quite simple. User space is not worth
-+ @ the implied complexity because of ever randomly changing PTEs
-+ @ (page aging, swapout, etc) requiring constant coherency checks.
-+ @ Since PTEs are usually set in increasing order, we test the
-+ @ possibility for a large page only when given the last PTE of a
-+ @ 64K boundary.
-+ tsteq r1, #L_PTE_USER
-+ andeq r1, r0, #(15 << 2)
-+ teqeq r1, #(15 << 2)
-+ beq 1f
-+
-+ mov ip, #0
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+ @ See if we have 16 identical PTEs but with consecutive base addresses
-+1: bic r3, r2, #0x0000f000
-+ mov r1, #0x0000f000
-+2: eor r2, r2, r3
-+ teq r2, r1
-+ bne 4f
-+ subs r1, r1, #0x00001000
-+ ldr r2, [r0, #-4]!
-+ bne 2b
-+ eors r2, r2, r3
-+ bne 4f
-+
-+ @ Now create our LARGE PTE from the current EXT one.
-+ bic r3, r3, #PTE_TYPE_MASK
-+ orr r3, r3, #PTE_TYPE_LARGE
-+ and r2, r3, #0x30 @ EXT_AP --> LARGE_AP0
-+ orr r2, r2, r2, lsl #2 @ add LARGE_AP1
-+ orr r2, r2, r2, lsl #4 @ add LARGE_AP3 + LARGE_AP2
-+ and r1, r3, #0x3c0 @ EXT_TEX
-+ bic r3, r3, #0x3c0
-+ orr r2, r2, r1, lsl #(12 - 6) @ --> LARGE_TEX
-+ orr r2, r2, r3 @ add remaining bits
-+
-+ @ then put it in the pagetable
-+ mov r3, r2
-+3: strd r2, [r0], #8
-+ tst r0, #(15 << 2)
-+ bne 3b
-+
-+ @ Then sync the 2 corresponding cache lines
-+ sub r0, r0, #(16 << 2)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+4: orr r0, r0, #(15 << 2)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+ .ltorg
-+
-+cpu_manu_name:
-+ .asciz "Intel"
-+
-+cpu_80200_name:
-+ .asciz "XScale-80200"
-+
-+cpu_pxa210_name:
-+ .asciz "XScale-PXA210"
-+
-+cpu_pxa250_name:
-+ .asciz "XScale-PXA250"
-+
-+cpu_pxa255_name:
-+ .asciz "XScale-PXA255"
-+
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__xscale_setup:
-+ mov r0, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+ mov r0, #1 @ Allow user space to access
-+ mcr p15, 0, r0, c15, c1, 0 @ ... CP 0 only.
-+#if CACHE_WRITE_THROUGH
-+ mov r0, #0x20
-+#else
-+ mov r0, #0x00
-+#endif
-+ mcr p15, 0, r0, c1, c1, 0 @ set auxiliary control reg
-+ mrc p15, 0, r0, c1, c0, 0 @ get control register
-+ bic r0, r0, #0x0200 @ ......R.........
-+ bic r0, r0, #0x0082 @ ........B.....A.
-+ orr r0, r0, #0x0005 @ .............C.M
-+ orr r0, r0, #0x3900 @ ..VIZ..S........
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bic r0, r0, #0x0004 @ see cpu_xscale_proc_init
-+#endif
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+
-+ .type xscale_processor_functions, #object
-+ENTRY(xscale_processor_functions)
-+ .word cpu_xscale_data_abort
-+ .word cpu_xscale_check_bugs
-+ .word cpu_xscale_proc_init
-+ .word cpu_xscale_proc_fin
-+ .word cpu_xscale_reset
-+ .word cpu_xscale_do_idle
-+
-+ /* cache */
-+ .word cpu_xscale_cache_clean_invalidate_all
-+ .word cpu_xscale_cache_clean_invalidate_range
-+ .word cpu_xscale_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_xscale_dcache_invalidate_range
-+ .word cpu_xscale_dcache_clean_range
-+ .word cpu_xscale_dcache_clean_page
-+ .word cpu_xscale_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_xscale_icache_invalidate_range
-+ .word cpu_xscale_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_xscale_tlb_invalidate_all
-+ .word cpu_xscale_tlb_invalidate_range
-+ .word cpu_xscale_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_xscale_set_pgd
-+ .word cpu_xscale_set_pmd
-+ .word cpu_xscale_set_pte
-+ .size xscale_processor_functions, . - xscale_processor_functions
-+
-+ .type cpu_80200_info, #object
-+cpu_80200_info:
-+ .long cpu_manu_name
-+ .long cpu_80200_name
-+ .size cpu_80200_info, . - cpu_80200_info
-+
-+ .type cpu_pxa210_info, #object
-+cpu_pxa210_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa210_name
-+ .size cpu_pxa210_info, . - cpu_pxa210_info
-+
-+ .type cpu_pxa250_info, #object
-+cpu_pxa250_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa250_name
-+ .size cpu_pxa250_info, . - cpu_pxa250_info
-+
-+ .type cpu_pxa255_info, #object
-+cpu_pxa255_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa255_name
-+ .size cpu_pxa255_info, . - cpu_pxa255_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5te"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __80200_proc_info,#object
-+__80200_proc_info:
-+ .long 0x69052000
-+ .long 0xfffffff0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_80200_info
-+ .long xscale_processor_functions
-+ .size __80200_proc_info, . - __80200_proc_info
-+
-+ .type __pxa210_proc_info,#object
-+__pxa210_proc_info:
-+ .long 0x69052120
-+ .long 0xfffff3f0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa210_info
-+ .long xscale_processor_functions
-+ .size __pxa210_proc_info, . - __pxa210_proc_info
-+
-+ .type __pxa250_proc_info,#object
-+__pxa250_proc_info:
-+ .long 0x69052100
-+ .long 0xfffff7f0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa250_info
-+ .long xscale_processor_functions
-+ .size __pxa250_proc_info, . - __pxa250_proc_info
-+
-+ .type __pxa255_proc_info,#object
-+__pxa255_proc_info:
-+ .long 0x69052d00
-+ .long 0xfffffff0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa255_info
-+ .long xscale_processor_functions
-+ .size __pxa255_proc_info, . - __pxa255_proc_info
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/vmlinux-armv-xip.lds.in 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,125 @@
-+/*
-+ * ld script to make ARM Linux kernel
-+ *
-+ * (C) Copyright 2001 Lineo Japan, Inc.
-+ *
-+ * May be copied or modified under the terms of the GNU General Public
-+ * License. See linux/COPYING for more information.
-+ *
-+ * Based on arch/arm/vmlinux-armv.lds.in
-+ *
-+ * taken from the i386 version by Russell King
-+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
-+ */
-+OUTPUT_ARCH(arm)
-+ENTRY(stext)
-+SECTIONS
-+{
-+ . = TEXTADDR;
-+ .init : { /* Init code and data */
-+ _stext = .;
-+ __init_begin = .;
-+ *(.text.init)
-+ __proc_info_begin = .;
-+ *(.proc.info)
-+ __proc_info_end = .;
-+ __arch_info_begin = .;
-+ *(.arch.info)
-+ __arch_info_end = .;
-+ __tagtable_begin = .;
-+ *(.taglist)
-+ __tagtable_end = .;
-+ . = ALIGN(16);
-+ __setup_start = .;
-+ *(.setup.init)
-+ __setup_end = .;
-+ __initcall_start = .;
-+ *(.initcall.init)
-+ __initcall_end = .;
-+ . = ALIGN(4096);
-+ __init_end = .;
-+ }
-+
-+ /DISCARD/ : { /* Exit code and data */
-+ *(.text.exit)
-+ *(.data.exit)
-+ *(.exitcall.exit)
-+ }
-+
-+ .text : { /* Real text segment */
-+ _text = .; /* Text and read-only data */
-+ *(.text)
-+ *(.fixup)
-+ *(.gnu.warning)
-+ *(.text.lock) /* out-of-line lock text */
-+ *(.rodata)
-+ *(.rodata.*)
-+ *(.glue_7)
-+ *(.glue_7t)
-+ *(.kstrtab)
-+ *(.got) /* Global offset table */
-+ *(.got.plt)
-+
-+ _etext = .; /* End of text section */
-+ }
-+
-+ . = ALIGN(16);
-+ __ex_table : { /* Exception table */
-+ __start___ex_table = .;
-+ *(__ex_table)
-+ __stop___ex_table = .;
-+ }
-+
-+ __ksymtab : { /* Kernel symbol table */
-+ __start___ksymtab = .;
-+ *(__ksymtab)
-+ __stop___ksymtab = .;
-+ }
-+
-+ _endtext = .;
-+
-+ . = DATAADDR;
-+
-+ _sdata = .;
-+
-+ . = ALIGN(8192);
-+
-+ .data : {
-+ /*
-+ * first, the init task union, aligned
-+ * to an 8192 byte boundary.
-+ */
-+ *(.init.task)
-+
-+ /*
-+ * then the cacheline aligned data
-+ */
-+ . = ALIGN(32);
-+ *(.data.cacheline_aligned)
-+
-+ /*
-+ * and the usual data section
-+ */
-+ *(.data)
-+ CONSTRUCTORS
-+
-+ *(.data.init)
-+
-+ _edata = .;
-+ }
-+
-+ .bss : {
-+ __bss_start = .; /* BSS */
-+ *(.bss)
-+ *(COMMON)
-+ _end = . ;
-+ }
-+ /* Stabs debugging sections. */
-+ .stab 0 : { *(.stab) }
-+ .stabstr 0 : { *(.stabstr) }
-+ .stab.excl 0 : { *(.stab.excl) }
-+ .stab.exclstr 0 : { *(.stab.exclstr) }
-+ .stab.index 0 : { *(.stab.index) }
-+ .stab.indexstr 0 : { *(.stab.indexstr) }
-+ .comment 0 : { *(.comment) }
-+}
---- linux-2.4.25/drivers/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -25,6 +25,7 @@
- subdir-$(CONFIG_NUBUS) += nubus
- subdir-$(CONFIG_TC) += tc
- subdir-$(CONFIG_VT) += video
-+subdir-$(CONFIG_MMC) += mmc
- subdir-$(CONFIG_MAC) += macintosh
- subdir-$(CONFIG_PPC32) += macintosh
- subdir-$(CONFIG_USB) += usb
---- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/char/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -253,6 +253,7 @@
- dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
- dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
- dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
-+ dep_tristate ' PXA250/210 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_PXA
- dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
- dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
- dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
-@@ -335,6 +336,9 @@
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
- tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
- fi
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ tristate 'PXA250/210 Real Time Clock' CONFIG_PXA_RTC
-+fi
- if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
- tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
- fi
-@@ -417,4 +421,8 @@
- dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV
- fi
-
-+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
-+ tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO
-+fi
-+
- endmenu
---- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/char/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -280,6 +280,7 @@
- obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
- obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
- obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
-+obj-$(CONFIG_PXA_RTC) += sa1100-rtc.o
- obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
- ifeq ($(CONFIG_PPC),)
- obj-$(CONFIG_NVRAM) += nvram.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/mt6n_ttl.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,316 @@
-+/*
-+ * Trizeps-2 MT6N development board TTL-IO interface for Linux
-+ *
-+ * Copyright (C) 2003 Luc De Cock
-+ *
-+ * This driver allows use of the TTL-IO interface on the MT6N
-+ * from user space. It exports the /dev/ttlio interface supporting
-+ * some ioctl() and also the /proc/driver/ttlio pseudo-file
-+ * for status information.
-+ *
-+ * The ioctls can be used to set individual TTL output lines.
-+ * Only ioctls are supported.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Based on other minimal char device drivers, like Alan's
-+ * watchdog, Ted's random, Paul's rtc, etc. etc.
-+ *
-+ * 1.00 Luc De Cock: initial version.
-+ */
-+
-+#define TTLIO_VERSION "1.00"
-+
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/miscdevice.h>
-+#include <linux/fcntl.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+/* Writing to the register sets the output lines
-+* Reading from the register returns the status of the input lines
-+*/
-+static unsigned short *ttlio_base = (unsigned short *) TRIZEPS2_TTLIO_BASE;
-+static unsigned short ttlio_shadow = 0;
-+
-+/* interrupt stuff */
-+static struct fasync_struct *ttlio_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(ttlio_wait);
-+static int ttlio_irq_arrived = 0;
-+static spinlock_t ttlio_lock;
-+static unsigned short ttlio_in = 0;
-+static volatile unsigned long teller = 0;
-+
-+
-+static int ttlio_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg);
-+
-+static int ttlio_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+
-+
-+static void ttlio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ ttlio_in = *ttlio_base;
-+
-+ ttlio_irq_arrived = 1;
-+ teller++;
-+
-+ /* wake up the waiting process */
-+ wake_up_interruptible(&ttlio_wait);
-+ kill_fasync(&ttlio_async_queue, SIGIO, POLL_IN);
-+}
-+
-+/*
-+ * Now all the various file operations that we export.
-+ */
-+
-+static int ttlio_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ unsigned long ttlio_val;
-+
-+ switch (cmd) {
-+ case TTLIO_RESET: /* clear all lines */
-+ {
-+ *ttlio_base = 0;
-+ return 0;
-+ }
-+ case TTLIO_GET: /* get state of TTL input lines */
-+ {
-+ ttlio_val = *ttlio_base;
-+ return put_user(ttlio_val, (unsigned long *)arg);
-+ }
-+ case TTLIO_SET: /* set state of TTL output lines */
-+ {
-+ unsigned long user_val;
-+ if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
-+ return -EFAULT;
-+ ttlio_shadow |= (unsigned short) user_val;
-+ *ttlio_base = ttlio_shadow;
-+ return 0;
-+ }
-+ case TTLIO_UNSET: /* unset (clear) state of TTL output lines */
-+ {
-+ unsigned long user_val;
-+ if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
-+ return -EFAULT;
-+ ttlio_shadow &= ~((unsigned short) user_val);
-+ *ttlio_base = ttlio_shadow;
-+ return 0;
-+ }
-+ case 100: /* get counter */
-+ {
-+ return put_user(teller, (unsigned long *)arg);
-+ }
-+ case 101: /* reset counter */
-+ {
-+ teller = 0;
-+ return 0;
-+ }
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+}
-+
-+static ssize_t ttlio_read(struct file *file, char *buf,
-+ size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned short data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned short))
-+ return -EINVAL;
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ spin_lock_irq(&ttlio_lock);
-+ data = *ttlio_base;
-+ spin_unlock_irq(&ttlio_lock);
-+ retval = put_user(data, (unsigned short *) buf);
-+ if (!retval)
-+ retval = sizeof(unsigned short);
-+ return retval;
-+ }
-+ /* blocking read: wait for interrupt */
-+ add_wait_queue(&ttlio_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq(&ttlio_lock);
-+ data = *ttlio_base;
-+ if (ttlio_irq_arrived) {
-+ ttlio_irq_arrived = 0;
-+ break;
-+ }
-+ spin_unlock_irq(&ttlio_lock);
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+ schedule();
-+ }
-+
-+ spin_unlock_irq(&ttlio_lock);
-+ retval = put_user(data, (unsigned short *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned short);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&ttlio_wait, &wait);
-+ return retval;
-+}
-+
-+static ssize_t ttlio_write(struct file *file,
-+ const char *buf, size_t count, loff_t *ppos)
-+{
-+ unsigned short content;
-+
-+ if (count < sizeof(unsigned short))
-+ return -EINVAL;
-+
-+ if (copy_from_user (&content, buf, sizeof(unsigned short)))
-+ return -EFAULT;
-+
-+ ttlio_shadow = content;
-+ *ttlio_base = ttlio_shadow;
-+
-+ *ppos += sizeof(unsigned short);
-+
-+ return sizeof(unsigned short);
-+}
-+
-+static int ttlio_open(struct inode *inode, struct file *file)
-+{
-+ ttlio_irq_arrived = 0;
-+ return 0;
-+}
-+
-+static int ttlio_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &ttlio_async_queue);
-+}
-+
-+static unsigned int ttlio_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait(file, &ttlio_wait, wait);
-+ return ttlio_irq_arrived ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t ttlio_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+/*
-+ * The various file operations we support.
-+ */
-+
-+static struct file_operations ttlio_fops = {
-+ owner: THIS_MODULE,
-+ llseek: ttlio_llseek,
-+ read: ttlio_read,
-+ poll: ttlio_poll,
-+ write: ttlio_write,
-+ ioctl: ttlio_ioctl,
-+ open: ttlio_open,
-+ fasync: ttlio_fasync,
-+};
-+
-+static struct miscdevice ttlio_dev = {
-+ TTLIO_MINOR,
-+ "ttlio",
-+ &ttlio_fops
-+};
-+
-+static int __init ttlio_init(void)
-+{
-+ printk(KERN_INFO "MT6N TTL-I/O driver (release %s)\n",
-+ TTLIO_VERSION);
-+
-+ misc_register(&ttlio_dev);
-+ create_proc_read_entry ("driver/ttlio", 0, 0, ttlio_read_proc, NULL);
-+
-+ set_GPIO_IRQ_edge(GPIO_TTLIO_IRQ, GPIO_FALLING_EDGE);
-+ if (request_irq(TTLIO_IRQ, ttlio_interrupt, SA_INTERRUPT, "ttlio irq", NULL)) {
-+ printk(KERN_ERR "ttlio: irq %d already in use\n", TTLIO_IRQ);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static void __exit ttlio_exit(void)
-+{
-+ free_irq(TTLIO_IRQ, NULL);
-+ remove_proc_entry ("driver/ttlio", NULL);
-+ misc_deregister(&ttlio_dev);
-+}
-+
-+module_init(ttlio_init);
-+module_exit(ttlio_exit);
-+EXPORT_NO_SYMBOLS;
-+
-+/*
-+ * Info exported via "/proc/driver/ttlio".
-+ */
-+
-+static int ttlio_proc_output(char *buf)
-+{
-+ char *p;
-+ unsigned short val;
-+ int i;
-+
-+ p = buf;
-+
-+ p += sprintf(p, "input : ");
-+ /* write the state of the input lines */
-+ val = *ttlio_base;
-+ for (i = 0; i < 8*sizeof(unsigned short); i++) {
-+ *p++ = (val & 1) ? '1' : '0';
-+ val >>= 1;
-+ }
-+ *p = 0;
-+ p += sprintf(p, "\noutput: ");
-+ /* write the state of the output lines */
-+ val = ttlio_shadow;
-+ for (i = 0; i < 8*sizeof(unsigned short); i++) {
-+ *p++ = (val & 1) ? '1' : '0';
-+ val >>= 1;
-+ }
-+ *p = 0;
-+ p += sprintf(p, "\n");
-+
-+ return p - buf;
-+}
-+
-+static int ttlio_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ int len = ttlio_proc_output (page);
-+ if (len <= off+count) *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count) len = count;
-+ if (len < 0) len = 0;
-+ return len;
-+}
-+
-+MODULE_AUTHOR("Luc De Cock");
-+MODULE_DESCRIPTION("MT6N TTL-I/O driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/char/sa1100-rtc.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/char/sa1100-rtc.c 2004-03-31 17:15:11.000000000 +0200
-@@ -1,5 +1,6 @@
- /*
- * Real Time Clock interface for Linux on StrongARM SA1100
-+ * and XScale PXA250/210.
- *
- * Copyright (c) 2000 Nils Faerber
- *
-@@ -470,5 +471,5 @@
- module_exit(rtc_exit);
-
- MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
--MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
-+MODULE_DESCRIPTION("SA1100/PXA Realtime Clock Driver (RTC)");
- EXPORT_NO_SYMBOLS;
---- linux-2.4.25/drivers/char/sa1100_wdt.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/char/sa1100_wdt.c 2004-03-31 17:15:11.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- * Watchdog driver for the SA11x0
-+ * Watchdog driver for the SA11x0/PXA
- *
- * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
- * Based on SoftDog driver by Alan Cox <alan@redhat.com>
-@@ -35,13 +35,20 @@
-
- #define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
-
--static int sa1100_margin = TIMER_MARGIN; /* in seconds */
-+static int timer_margin = TIMER_MARGIN; /* in seconds */
- static int sa1100wdt_users;
- static int pre_margin;
- #ifdef MODULE
--MODULE_PARM(sa1100_margin,"i");
-+MODULE_PARM(timer_margin,"i");
- #endif
-
-+static void sa1100dog_ping( void)
-+{
-+ /* reload counter with (new) margin */
-+ pre_margin=3686400 * timer_margin;
-+ OSMR3 = OSCR + pre_margin;
-+}
-+
- /*
- * Allow only one person to hold it open
- */
-@@ -51,9 +58,7 @@
- if(test_and_set_bit(1,&sa1100wdt_users))
- return -EBUSY;
- MOD_INC_USE_COUNT;
-- /* Activate SA1100 Watchdog timer */
-- pre_margin=3686400 * sa1100_margin;
-- OSMR3 = OSCR + pre_margin;
-+ sa1100dog_ping();
- OSSR = OSSR_M3;
- OWER = OWER_WME;
- OIER |= OIER_E3;
-@@ -93,8 +98,11 @@
- unsigned int cmd, unsigned long arg)
- {
- static struct watchdog_info ident = {
-- identity: "SA1100 Watchdog",
-+ identity: "PXA/SA1100 Watchdog",
-+ options: WDIOF_SETTIMEOUT,
-+ firmware_version: 0,
- };
-+ int new_margin;
-
- switch(cmd){
- default:
-@@ -108,6 +116,16 @@
- case WDIOC_KEEPALIVE:
- OSMR3 = OSCR + pre_margin;
- return 0;
-+ case WDIOC_SETTIMEOUT:
-+ if (get_user(new_margin, (int *)arg))
-+ return -EFAULT;
-+ if (new_margin < 1)
-+ return -EINVAL;
-+ timer_margin = new_margin;
-+ sa1100dog_ping();
-+ /* Fall */
-+ case WDIOC_GETTIMEOUT:
-+ return put_user(timer_margin, (int *)arg);
- }
- }
-
-@@ -123,7 +141,11 @@
- static struct miscdevice sa1100dog_miscdev=
- {
- WATCHDOG_MINOR,
-- "SA1100 watchdog",
-+#if defined(CONFIG_SA1100_WATCHDOG)
-+ "SA1100_watchdog",
-+#elif defined(CONFIG_PXA_WATCHDOG)
-+ "PXA_watchdog",
-+#endif
- &sa1100dog_fops
- };
-
-@@ -136,7 +158,7 @@
- if (ret)
- return ret;
-
-- printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
-+ printk("SA1100/PXA Watchdog Timer: timer margin %d sec\n", timer_margin);
-
- return 0;
- }
---- linux-2.4.25/drivers/char/serial.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/char/serial.c 2004-03-31 17:15:11.000000000 +0200
-@@ -133,6 +133,16 @@
- #endif
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+#define pxa_port(x) ((x) == PORT_PXA)
-+#define pxa_buggy_port(x) ({ \
-+ int cpu_ver; asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); \
-+ ((x) == PORT_PXA && (cpu_ver & ~1) == 0x69052100); })
-+#else
-+#define pxa_port(x) (0)
-+#define pxa_buggy_port(x) (0)
-+#endif
-+
- /* Set of debugging defines */
-
- #undef SERIAL_DEBUG_INTR
-@@ -311,6 +321,7 @@
- { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |
- UART_STARTECH },
- { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "PXA UART", 32, UART_CLEAR_FIFO | UART_USE_FIFO },
- { 0, 0}
- };
-
-@@ -424,6 +435,9 @@
- case SERIAL_IO_MEM:
- return readb((unsigned long) info->iomem_base +
- (offset<<info->iomem_reg_shift));
-+ case SERIAL_IO_MEM32:
-+ return readl((unsigned long) info->iomem_base +
-+ (offset<<info->iomem_reg_shift));
- default:
- return inb(info->port + offset);
- }
-@@ -443,6 +457,10 @@
- writeb(value, (unsigned long) info->iomem_base +
- (offset<<info->iomem_reg_shift));
- break;
-+ case SERIAL_IO_MEM32:
-+ writel(value, (unsigned long) info->iomem_base +
-+ (offset<<info->iomem_reg_shift));
-+ break;
- default:
- outb(value, info->port+offset);
- }
-@@ -1306,6 +1324,16 @@
- }
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+ if (state->type == PORT_PXA) {
-+ switch ((long)state->iomem_base) {
-+ case (long)&FFUART: CKEN |= CKEN6_FFUART; break;
-+ case (long)&BTUART: CKEN |= CKEN7_BTUART; break;
-+ case (long)&STUART: CKEN |= CKEN5_STUART; break;
-+ }
-+ }
-+#endif
-+
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in change_speed())
-@@ -1403,6 +1431,8 @@
- {
- if (state->irq != 0)
- info->MCR |= UART_MCR_OUT2;
-+ if (pxa_buggy_port(state->type) && state->irq != 0)
-+ info->MCR ^= UART_MCR_OUT2;
- }
- info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
- serial_outp(info, UART_MCR, info->MCR);
-@@ -1411,6 +1441,8 @@
- * Finally, enable interrupts
- */
- info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-+ if (pxa_port(state->type))
-+ info->IER |= UART_IER_UUE | UART_IER_RTOIE;
- serial_outp(info, UART_IER, info->IER); /* enable interrupts */
-
- #ifdef CONFIG_SERIAL_MANY_PORTS
-@@ -1542,6 +1574,8 @@
- } else
- #endif
- info->MCR &= ~UART_MCR_OUT2;
-+ if (pxa_buggy_port(state->type))
-+ info->MCR ^= UART_MCR_OUT2;
- info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
-
- /* disable break condition */
-@@ -1567,6 +1601,20 @@
- state->baud_base = SERIAL_RSA_BAUD_BASE_LO;
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+ if (state->type == PORT_PXA
-+#ifdef CONFIG_SERIAL_CONSOLE
-+ && sercons.index != info->line
-+#endif
-+ ) {
-+ switch ((long)state->iomem_base) {
-+ case (long)&FFUART: CKEN &= ~CKEN6_FFUART; break;
-+ case (long)&BTUART: CKEN &= ~CKEN7_BTUART; break;
-+ case (long)&STUART: CKEN &= ~CKEN5_STUART; break;
-+ }
-+ }
-+#endif
-+
-
- (void)serial_in(info, UART_RX); /* read data port to reset things */
-
-@@ -1857,6 +1905,8 @@
- save_flags(flags); cli();
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type))
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
- restore_flags(flags);
- }
-
-@@ -1933,6 +1983,11 @@
- && !(info->IER & UART_IER_THRI)) {
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type)) {
-+ save_flags(flags); cli();
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
-+ restore_flags(flags);
-+ }
- }
- return ret;
- }
-@@ -1990,6 +2045,8 @@
- /* Make sure transmit interrupts are on */
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type))
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
- }
- }
-
-@@ -5517,7 +5574,6 @@
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- state->magic = SSTATE_MAGIC;
- state->line = i;
-- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
-@@ -5531,14 +5587,18 @@
- state->irq = irq_cannonicalize(state->irq);
- if (state->hub6)
- state->io_type = SERIAL_IO_HUB6;
-- if (state->port && check_region(state->port,8))
-+ if (state->port && check_region(state->port,8)) {
-+ state->type = PORT_UNKNOWN;
- continue;
-+ }
- #ifdef CONFIG_MCA
- if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
- continue;
- #endif
-- if (state->flags & ASYNC_BOOT_AUTOCONF)
-+ if (state->flags & ASYNC_BOOT_AUTOCONF) {
-+ state->type = PORT_UNKNOWN;
- autoconfig(state);
-+ }
- }
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- if (state->type == PORT_UNKNOWN)
-@@ -5858,6 +5918,8 @@
- */
- ier = serial_in(info, UART_IER);
- serial_out(info, UART_IER, 0x00);
-+ if (pxa_port(info->state->type))
-+ serial_out(info, UART_IER, UART_IER_UUE);
-
- /*
- * Now, do each character
-@@ -6009,6 +6071,8 @@
- serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */
- serial_out(info, UART_LCR, cval); /* reset DLAB */
- serial_out(info, UART_IER, 0);
-+ if (pxa_port(info->state->type))
-+ serial_out(info, UART_IER, UART_IER_UUE);
- serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
- /*
---- linux-2.4.25/drivers/i2c/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -54,6 +54,11 @@
- fi
- fi
-
-+ if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_tristate 'PXA I2C Algorithm' CONFIG_I2C_PXA_ALGO $CONFIG_I2C
-+ dep_tristate 'PXA I2C Adapter' CONFIG_I2C_PXA_ADAP $CONFIG_I2C_PXA_ALGO
-+ fi
-+
- if [ "$CONFIG_ALL_PPC" = "y" ] ; then
- dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
- fi
---- linux-2.4.25/drivers/i2c/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -6,7 +6,7 @@
-
- export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
- i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
-- i2c-proc.o
-+ i2c-algo-pxa.o i2c-proc.o
-
- # Init order: core, chardev, bit adapters, pcf adapters
-
-@@ -35,6 +35,10 @@
- obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o
- obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
-
-+# PXA adapters
-+obj-$(CONFIG_I2C_PXA_ALGO) += i2c-algo-pxa.o
-+obj-$(CONFIG_I2C_PXA_ADAP) += i2c-adap-pxa.o
-+
- # This is needed for automatic patch generation: sensors code starts here
- # This is needed for automatic patch generation: sensors code ends here
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-adap-pxa.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,396 @@
-+/*
-+ * i2c_adap_pxa.c
-+ *
-+ * I2C adapter for the PXA I2C bus access.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Apr 2002: Initial version [CS]
-+ * Jun 2002: Properly seperated algo/adap [FB]
-+ * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
-+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-id.h>
-+#include <linux/init.h>
-+#include <linux/time.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/irqs.h> /* for IRQ_I2C */
-+
-+#include "i2c-pxa.h"
-+
-+/*
-+ * Set this to zero to remove all debug statements via dead code elimination.
-+ */
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int i2c_debug = DEBUG;
-+#else
-+#define i2c_debug 0
-+#endif
-+
-+static int irq = 0;
-+static volatile int i2c_pending = 0; /* interrupt pending when 1 */
-+static volatile int bus_error = 0;
-+static volatile int tx_finished = 0;
-+static volatile int rx_finished = 0;
-+
-+static wait_queue_head_t i2c_wait;
-+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte);
-+
-+/* place a byte in the transmit register */
-+static void i2c_pxa_write_byte(u8 value)
-+{
-+ IDBR = value;
-+}
-+
-+/* read byte in the receive register */
-+static u8 i2c_pxa_read_byte(void)
-+{
-+ return (u8) (0xff & IDBR);
-+}
-+
-+static void i2c_pxa_start(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_START;
-+ icr &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK);
-+ ICR = icr;
-+
-+ bus_error=0; /* clear any bus_error from previous txfers */
-+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */
-+ rx_finished=0;
-+ i2c_pending = 0;
-+}
-+
-+static void i2c_pxa_repeat_start(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_START;
-+ icr &= ~(ICR_STOP | ICR_ALDIE);
-+ ICR = icr;
-+
-+ bus_error=0; /* clear any bus_error from previous txfers */
-+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */
-+ rx_finished=0;
-+ i2c_pending = 0;
-+}
-+
-+static void i2c_pxa_stop(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_STOP;
-+ icr &= ~(ICR_START);
-+ ICR = icr;
-+}
-+
-+static void i2c_pxa_midbyte(void)
-+{
-+ unsigned long icr = ICR;
-+ icr &= ~(ICR_START | ICR_STOP);
-+ ICR = icr;
-+}
-+
-+static void i2c_pxa_abort(void)
-+{
-+ unsigned long timeout = jiffies + HZ/4;
-+
-+#ifdef PXA_ABORT_MA
-+ while ((long)(timeout - jiffies) > 0 && (ICR & ICR_TB)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+
-+ ICR |= ICR_MA;
-+ udelay(100);
-+#else
-+ while ((long)(timeout - jiffies) > 0 && (IBMR & 0x1) == 0) {
-+ i2c_pxa_transfer( 1, I2C_RECEIVE, 1);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+#endif
-+ ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
-+}
-+
-+static int i2c_pxa_wait_bus_not_busy( void)
-+{
-+ int timeout = DEF_TIMEOUT;
-+
-+ while (timeout-- && (ISR & ISR_IBB)) {
-+ udelay(100); /* wait for 100 us */
-+ }
-+
-+ return (timeout<=0);
-+}
-+
-+static void i2c_pxa_wait_for_ite(void){
-+ unsigned long flags;
-+ if (irq > 0) {
-+ save_flags_cli(flags);
-+ if (i2c_pending == 0) {
-+ interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT );
-+ }
-+ i2c_pending = 0;
-+ restore_flags(flags);
-+ } else {
-+ udelay(100);
-+ }
-+}
-+
-+static int i2c_pxa_wait_for_int( int wait_type)
-+{
-+ int timeout = DEF_TIMEOUT;
-+#ifdef DEBUG
-+ if (bus_error)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on enter\n");
-+ if (rx_finished)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on enter\n");
-+ if (tx_finished)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on enter\n");
-+#endif
-+
-+ if (wait_type == I2C_RECEIVE){ /* wait on receive */
-+
-+ do {
-+ i2c_pxa_wait_for_ite();
-+ } while (!(rx_finished) && timeout-- && !signal_pending(current));
-+
-+#ifdef DEBUG
-+ if (timeout<0){
-+ if (tx_finished)
-+ printk("Error: i2c-algo-pxa.o: received a tx"
-+ " interrupt while waiting on a rx in wait_for_int");
-+ }
-+#endif
-+ } else { /* wait on transmit */
-+
-+ do {
-+ i2c_pxa_wait_for_ite();
-+ } while (!(tx_finished) && timeout-- && !signal_pending(current));
-+
-+#ifdef DEBUG
-+ if (timeout<0){
-+ if (rx_finished)
-+ printk("Error: i2c-algo-pxa.o: received a rx"
-+ " interrupt while waiting on a tx in wait_for_int");
-+ }
-+#endif
-+ }
-+
-+ udelay(ACK_DELAY); /* this is needed for the bus error */
-+
-+ tx_finished=0;
-+ rx_finished=0;
-+
-+ if (bus_error){
-+ bus_error=0;
-+ if( i2c_debug > 2)printk("wait_for_int: error - no ack.\n");
-+ return BUS_ERROR;
-+ }
-+
-+ if (signal_pending(current)) {
-+ return (-ERESTARTSYS);
-+ } else if (timeout < 0) {
-+ if( i2c_debug > 2)printk("wait_for_int: timeout.\n");
-+ return(-EIO);
-+ } else
-+ return(0);
-+}
-+
-+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte)
-+{
-+ if( lastbyte)
-+ {
-+ if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK;
-+ i2c_pxa_stop();
-+ }
-+ else if( midbyte)
-+ {
-+ i2c_pxa_midbyte();
-+ }
-+ ICR |= ICR_TB;
-+}
-+
-+static void i2c_pxa_reset( void)
-+{
-+#ifdef DEBUG
-+ printk("Resetting I2C Controller Unit\n");
-+#endif
-+
-+ /* abort any transfer currently under way */
-+ i2c_pxa_abort();
-+
-+ /* reset according to 9.8 */
-+ ICR = ICR_UR;
-+ ISR = I2C_ISR_INIT;
-+ ICR &= ~ICR_UR;
-+
-+ /* set the global I2C clock on */
-+ CKEN |= CKEN14_I2C;
-+
-+ /* set our slave address */
-+ ISAR = I2C_PXA_SLAVE_ADDR;
-+
-+ /* set control register values */
-+ ICR = I2C_ICR_INIT;
-+
-+ /* clear any leftover states from prior transmissions */
-+ i2c_pending = rx_finished = tx_finished = bus_error = 0;
-+
-+ /* enable unit */
-+ ICR |= ICR_IUE;
-+ udelay(100);
-+}
-+
-+static void i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int status, wakeup = 0;
-+ status = (ISR);
-+
-+ if (status & ISR_BED){
-+ (ISR) |= ISR_BED;
-+ bus_error=ISR_BED;
-+ wakeup = 1;
-+ }
-+ if (status & ISR_ITE){
-+ (ISR) |= ISR_ITE;
-+ tx_finished=ISR_ITE;
-+ wakeup = 1;
-+ }
-+ if (status & ISR_IRF){
-+ (ISR) |= ISR_IRF;
-+ rx_finished=ISR_IRF;
-+ wakeup = 1;
-+ }
-+ if (wakeup) {
-+ i2c_pending = 1;
-+ wake_up_interruptible(&i2c_wait);
-+ }
-+}
-+
-+static int i2c_pxa_resource_init( void)
-+{
-+ init_waitqueue_head(&i2c_wait);
-+
-+ if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C_PXA", 0) < 0) {
-+ irq = 0;
-+ if( i2c_debug)
-+ printk(KERN_INFO "I2C: Failed to register I2C irq %i\n", IRQ_I2C);
-+ return -ENODEV;
-+ }else{
-+ irq = IRQ_I2C;
-+ enable_irq(irq);
-+ }
-+ return 0;
-+}
-+
-+static void i2c_pxa_resource_release( void)
-+{
-+ if( irq > 0)
-+ {
-+ disable_irq(irq);
-+ free_irq(irq,0);
-+ irq=0;
-+ }
-+}
-+
-+static void i2c_pxa_inc_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_INC_USE_COUNT;
-+#endif
-+}
-+
-+static void i2c_pxa_dec_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_DEC_USE_COUNT;
-+#endif
-+}
-+
-+static int i2c_pxa_client_register(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static int i2c_pxa_client_unregister(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static struct i2c_algo_pxa_data i2c_pxa_data = {
-+ write_byte: i2c_pxa_write_byte,
-+ read_byte: i2c_pxa_read_byte,
-+
-+ start: i2c_pxa_start,
-+ repeat_start: i2c_pxa_repeat_start,
-+ stop: i2c_pxa_stop,
-+ abort: i2c_pxa_abort,
-+
-+ wait_bus_not_busy: i2c_pxa_wait_bus_not_busy,
-+ wait_for_interrupt: i2c_pxa_wait_for_int,
-+ transfer: i2c_pxa_transfer,
-+ reset: i2c_pxa_reset,
-+
-+ udelay: 10,
-+ timeout: DEF_TIMEOUT,
-+};
-+
-+static struct i2c_adapter i2c_pxa_ops = {
-+ name: "PXA-I2C-Adapter",
-+ id: I2C_ALGO_PXA,
-+ algo_data: &i2c_pxa_data,
-+ inc_use: i2c_pxa_inc_use,
-+ dec_use: i2c_pxa_dec_use,
-+ client_register: i2c_pxa_client_register,
-+ client_unregister: i2c_pxa_client_unregister,
-+ retries: 2,
-+};
-+
-+extern int i2c_pxa_add_bus(struct i2c_adapter *);
-+extern int i2c_pxa_del_bus(struct i2c_adapter *);
-+
-+static int __init i2c_adap_pxa_init(void)
-+{
-+ if( i2c_pxa_resource_init() == 0) {
-+
-+ if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) {
-+ i2c_pxa_resource_release();
-+ printk(KERN_INFO "I2C: Failed to add bus\n");
-+ return -ENODEV;
-+ }
-+ } else {
-+ return -ENODEV;
-+ }
-+
-+ printk(KERN_INFO "I2C: Successfully added bus\n");
-+
-+ return 0;
-+}
-+
-+static void i2c_adap_pxa_exit(void)
-+{
-+ i2c_pxa_del_bus( &i2c_pxa_ops);
-+ i2c_pxa_resource_release();
-+
-+ printk(KERN_INFO "I2C: Successfully removed bus\n");
-+}
-+
-+module_init(i2c_adap_pxa_init);
-+module_exit(i2c_adap_pxa_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-algo-pxa.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,376 @@
-+/*
-+ * i2c-algo-pxa.c
-+ *
-+ * I2C algorithm for the PXA I2C bus access.
-+ * Byte driven algorithm similar to pcf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Apr 2002: Initial version [CS]
-+ * Jun 2002: Properly seperated algo/adap [FB]
-+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
-+ * Jan 2003: allow SMBUS_QUICK as valid msg [FB]
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/i2c.h> /* struct i2c_msg and others */
-+#include <linux/i2c-id.h>
-+
-+#include "i2c-pxa.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via dead code elimination.
-+ */
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int i2c_debug = DEBUG;
-+#else
-+#define i2c_debug 0
-+#endif
-+
-+static int pxa_scan = 1;
-+
-+static int i2c_pxa_valid_messages( struct i2c_msg msgs[], int num)
-+{
-+ int i;
-+ if (num < 1 || num > MAX_MESSAGES){
-+ if( i2c_debug)
-+ printk(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n",
-+ MAX_MESSAGES, num);
-+ return -EINVAL;
-+ }
-+
-+ /* check consistency of our messages */
-+ for (i=0;i<num;i++){
-+ if (&msgs[i]==NULL){
-+ if( i2c_debug) printk(KERN_INFO "Msgs is NULL\n");
-+ return -EINVAL;
-+ } else {
-+ if (msgs[i].len < 0 || msgs[i].buf == NULL){
-+ if( i2c_debug)printk(KERN_INFO "Length is less than zero");
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+static int i2c_pxa_readbytes(struct i2c_adapter *i2c_adap, char *buf,
-+ int count, int last)
-+{
-+
-+ int i, timeout=0;
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+
-+ /* increment number of bytes to read by one -- read dummy byte */
-+ for (i = 0; i <= count; i++) {
-+ if (i!=0){
-+ /* set ACK to NAK for last received byte ICR[ACKNAK] = 1
-+ only if not a repeated start */
-+
-+ if ((i == count) && last) {
-+ adap->transfer( last, I2C_RECEIVE, 0);
-+ }else{
-+ adap->transfer( 0, I2C_RECEIVE, 1);
-+ }
-+
-+ timeout = adap->wait_for_interrupt(I2C_RECEIVE);
-+
-+#ifdef DEBUG
-+ if (timeout==BUS_ERROR){
-+ printk(KERN_INFO "i2c_pxa_readbytes: bus error -> forcing reset\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout){
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_readbytes: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+
-+ }
-+
-+ if (i) {
-+ buf[i - 1] = adap->read_byte();
-+ } else {
-+ adap->read_byte(); /* dummy read */
-+ }
-+ }
-+ return (i - 1);
-+}
-+
-+static int i2c_pxa_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
-+ int count, int last)
-+{
-+
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+ int wrcount, timeout;
-+
-+ for (wrcount=0; wrcount<count; ++wrcount) {
-+
-+ adap->write_byte(buf[wrcount]);
-+ if ((wrcount==(count-1)) && last) {
-+ adap->transfer( last, I2C_TRANSMIT, 0);
-+ }else{
-+ adap->transfer( 0, I2C_TRANSMIT, 1);
-+ }
-+
-+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
-+
-+#ifdef DEBUG
-+ if (timeout==BUS_ERROR) {
-+ printk(KERN_INFO "i2c_pxa_sendbytes: bus error -> forcing reset.\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout) {
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_sendbytes: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+ }
-+ return (wrcount);
-+}
-+
-+
-+static inline int i2c_pxa_set_ctrl_byte(struct i2c_algo_pxa_data * adap, struct i2c_msg *msg)
-+{
-+ u16 flags = msg->flags;
-+ u8 addr;
-+ addr = (u8) ( (0x7f & msg->addr) << 1 );
-+ if (flags & I2C_M_RD )
-+ addr |= 1;
-+ if (flags & I2C_M_REV_DIR_ADDR )
-+ addr ^= 1;
-+ adap->write_byte(addr);
-+ return 0;
-+}
-+
-+static int i2c_pxa_do_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
-+{
-+ struct i2c_algo_pxa_data * adap;
-+ struct i2c_msg *pmsg=NULL;
-+ int i;
-+ int ret=0, timeout;
-+
-+ adap = i2c_adap->algo_data;
-+
-+ timeout = adap->wait_bus_not_busy();
-+
-+ if (timeout) {
-+ return I2C_RETRY;
-+ }
-+
-+ for (i = 0;ret >= 0 && i < num; i++) {
-+ int last = i + 1 == num;
-+ pmsg = &msgs[i];
-+
-+ ret = i2c_pxa_set_ctrl_byte(adap,pmsg);
-+
-+ /* Send START */
-+ if (i == 0) {
-+ adap->start();
-+ }else{
-+ adap->repeat_start();
-+ }
-+
-+ adap->transfer(0, I2C_TRANSMIT, 0);
-+
-+ /* Wait for ITE (transmit empty) */
-+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
-+
-+#ifdef DEBUG
-+ /* Check for ACK (bus error) */
-+ if (timeout==BUS_ERROR){
-+ printk(KERN_INFO "i2c_pxa_do_xfer: bus error -> forcing reset\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout) {
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_do_xfer: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+/* FIXME: handle arbitration... */
-+#if 0
-+ /* Check for bus arbitration loss */
-+ if (adap->arbitration_loss()){
-+ printk("Arbitration loss detected \n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+#endif
-+
-+ /* Read */
-+ if (pmsg->flags & I2C_M_RD) {
-+ /* read bytes into buffer*/
-+ ret = i2c_pxa_readbytes(i2c_adap, pmsg->buf, pmsg->len, last);
-+#if DEBUG > 2
-+ if (ret != pmsg->len) {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d/%d bytes.\n",
-+ ret, pmsg->len);
-+ } else {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d bytes.\n",ret);
-+ }
-+#endif
-+ } else { /* Write */
-+ ret = i2c_pxa_sendbytes(i2c_adap, pmsg->buf, pmsg->len, last);
-+#if DEBUG > 2
-+ if (ret != pmsg->len) {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d/%d bytes.\n",
-+ ret, pmsg->len);
-+ } else {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d bytes.\n",ret);
-+ }
-+#endif
-+ }
-+ }
-+
-+ if (ret<0){
-+ return ret;
-+ }else{
-+ return i;
-+ }
-+}
-+
-+static int i2c_pxa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
-+{
-+ int retval = i2c_pxa_valid_messages( msgs, num);
-+ if( retval > 0)
-+ {
-+ int i;
-+ for (i=i2c_adap->retries; i>=0; i--){
-+ int retval = i2c_pxa_do_xfer(i2c_adap,msgs,num);
-+ if (retval!=I2C_RETRY){
-+ return retval;
-+ }
-+ if( i2c_debug)printk(KERN_INFO"Retrying transmission \n");
-+ udelay(100);
-+ }
-+ if( i2c_debug)printk(KERN_INFO"Retried %i times\n",i2c_adap->retries);
-+ return -EREMOTEIO;
-+
-+ }
-+ return retval;
-+}
-+
-+struct i2c_algorithm i2c_pxa_algorithm = {
-+ name: "PXA-I2C-Algorithm",
-+ id: I2C_ALGO_PXA,
-+ master_xfer: i2c_pxa_xfer,
-+ smbus_xfer: NULL,
-+ slave_send: NULL,
-+ slave_recv: NULL,
-+ algo_control: NULL,
-+};
-+
-+/*
-+ * registering functions to load algorithms at runtime
-+ */
-+int i2c_pxa_add_bus(struct i2c_adapter *i2c_adap)
-+{
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+
-+ printk(KERN_INFO"I2C: Adding %s.\n", i2c_adap->name);
-+
-+ i2c_adap->algo = &i2c_pxa_algorithm;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ /* register new adapter to i2c module... */
-+ i2c_add_adapter(i2c_adap);
-+
-+ adap->reset();
-+
-+ /* scan bus */
-+ if (pxa_scan) {
-+ int i;
-+ printk(KERN_INFO "I2C: Scanning bus ");
-+ for (i = 0x02; i < 0xff; i+=2) {
-+ if( i==(I2C_PXA_SLAVE_ADDR<<1)) continue;
-+
-+ if (adap->wait_bus_not_busy()) {
-+ printk(KERN_INFO "I2C: scanning bus %s - TIMEOUTed.\n",
-+ i2c_adap->name);
-+ return -EIO;
-+ }
-+ adap->write_byte(i);
-+ adap->start();
-+ adap->transfer(0, I2C_TRANSMIT, 0);
-+
-+ if ((adap->wait_for_interrupt(I2C_TRANSMIT) != BUS_ERROR)) {
-+ printk("(%02x)",i>>1);
-+ adap->abort();
-+ } else {
-+// printk(".");
-+ adap->stop();
-+ }
-+ udelay(adap->udelay);
-+ }
-+ printk("\n");
-+ }
-+ return 0;
-+}
-+
-+int i2c_pxa_del_bus(struct i2c_adapter *i2c_adap)
-+{
-+ int res;
-+ if ((res = i2c_del_adapter(i2c_adap)) < 0)
-+ return res;
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ printk(KERN_INFO "I2C: Removing %s.\n", i2c_adap->name);
-+
-+ return 0;
-+}
-+
-+static int __init i2c_algo_pxa_init (void)
-+{
-+ printk(KERN_INFO "I2C: PXA algorithm module loaded.\n");
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(i2c_pxa_add_bus);
-+EXPORT_SYMBOL(i2c_pxa_del_bus);
-+
-+MODULE_PARM(pxa_scan, "i");
-+MODULE_PARM_DESC(pxa_scan, "Scan for active chips on the bus");
-+
-+MODULE_AUTHOR("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
-+
-+module_init(i2c_algo_pxa_init);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-pxa.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,76 @@
-+/*
-+ * i2c_pxa.h
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#ifndef _I2C_PXA_H_
-+#define _I2C_PXA_H_
-+
-+struct i2c_algo_pxa_data
-+{
-+ void (*write_byte) (u8 value);
-+ u8 (*read_byte) (void);
-+ void (*start) (void);
-+ void (*repeat_start) (void);
-+ void (*stop) (void);
-+ void (*abort) (void);
-+ int (*wait_bus_not_busy) (void);
-+ int (*wait_for_interrupt) (int wait_type);
-+ void (*transfer) (int lastbyte, int receive, int midbyte);
-+ void (*reset) (void);
-+
-+ int udelay;
-+ int timeout;
-+};
-+
-+#define DEF_TIMEOUT 3
-+#define BUS_ERROR (-EREMOTEIO)
-+#define ACK_DELAY 0 /* time to delay before checking bus error */
-+#define MAX_MESSAGES 65536 /* maximum number of messages to send */
-+
-+#define I2C_SLEEP_TIMEOUT 2 /* time to sleep for on i2c transactions */
-+#define I2C_RETRY (-2000) /* an error has occurred retry transmit */
-+#define I2C_TRANSMIT 1
-+#define I2C_RECEIVE 0
-+#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */
-+#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */
-+/* ICR initialize bit values
-+*
-+* 15. FM 0 (100 Khz operation)
-+* 14. UR 0 (No unit reset)
-+* 13. SADIE 0 (Disables the unit from interrupting on slave addresses
-+* matching its slave address)
-+* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration
-+* in master mode)
-+* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode)
-+* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent)
-+* 9. IRFIE 1 (Enable interrupts from full buffer received)
-+* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty)
-+* 7. GCD 1 (Disables i2c unit response to general call messages as a slave)
-+* 6. IUE 0 (Disable unit until we change settings)
-+* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL)
-+* 4. MA 0 (Only send stop with the ICR stop bit)
-+* 3. TB 0 (We are not transmitting a byte initially)
-+* 2. ACKNAK 0 (Send an ACK after the unit receives a byte)
-+* 1. STOP 0 (Do not send a STOP)
-+* 0. START 0 (Do not send a START)
-+*
-+*/
-+
-+#define I2C_ISR_INIT 0x7FF /* status register init */
-+/* I2C status register init values
-+ *
-+ * 10. BED 1 (Clear bus error detected)
-+ * 9. SAD 1 (Clear slave address detected)
-+ * 7. IRF 1 (Clear IDBR Receive Full)
-+ * 6. ITE 1 (Clear IDBR Transmit Empty)
-+ * 5. ALD 1 (Clear Arbitration Loss Detected)
-+ * 4. SSD 1 (Clear Slave Stop Detected)
-+ */
-+
-+#endif
---- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -13,5 +13,6 @@
- dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
- dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
- dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
-+dep_tristate ' UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND
-
- endmenu
---- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -11,13 +11,15 @@
-
- O_TARGET := misc.o
-
--export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
-+export-objs := mcp-core.o mcp-sa1100.o mcp-pxa.o \
-+ ucb1x00-core.o
-
--obj-$(CONFIG_MCP) += mcp-core.o
--obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
-+obj-$(CONFIG_MCP_SA1100) += mcp-core.o mcp-sa1100.o
- obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
- obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
- obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-+obj-$(CONFIG_MCP_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o
-+obj-$(CONFIG_PXA_CERF_PDA) += cerf_ucb1400gpio.o
-
- include $(TOPDIR)/Rules.make
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/cerf_ucb1400gpio.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,189 @@
-+/*
-+ * cerf_ucb1400gpio.c
-+ *
-+ * UCB1400 GPIO control stuff for the cerf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ * Jun 2002: Removed ac97 dependency [FB]
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int ucb_debug = DEBUGGING;
-+#else
-+#define ucb_debug 0
-+#endif
-+
-+#define UP 1
-+#define DOWN 0
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_lcd_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ if( ucb_debug > 2) printk( KERN_INFO "Enabling LCD.\n");
-+ /* Enable [not] LCD_RESET to enable the LCD display */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_LCD_RESET, 0);
-+
-+ /* Enable the Contrast circuit */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_ENA, 0);
-+}
-+
-+void cerf_ucb1400gpio_lcd_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ if( ucb_debug > 2) printk( KERN_INFO "Disabling LCD.\n");
-+ /* Disable the Contrast circuit */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+
-+ /* Disable [not] LCD_RESET to enable the LCD display */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+}
-+
-+void cerf_ucb1400gpio_lcd_contrast_step( int direction)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ // Assert the chip select and the up modifier
-+ ucb1x00_io_set_dir( ucb, 0,
-+ (UCB1400_GPIO_CONT_CS |
-+ UCB1400_GPIO_CONT_DOWN |
-+ UCB1400_GPIO_CONT_INC));
-+
-+ if( direction == DOWN)
-+ {
-+ if( ucb_debug > 3)
-+ printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
-+ "stepping up\n");
-+ //goin' up
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_DOWN, 0);
-+ }
-+ else
-+ {
-+ if( ucb_debug > 3)
-+ printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
-+ "stepping down\n");
-+ //goin' down
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
-+ }
-+
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_CS);
-+
-+ // Assert the line up, down then up again
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
-+ udelay(1);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_INC, 0);
-+ udelay(1);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
-+
-+ // Deassert the chip select and the up modifier
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_CS, 0);
-+}
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_irda_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Enabling IRDA.\n");
-+ /* Enable IRDA (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+}
-+
-+void cerf_ucb1400gpio_irda_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Disabling IRDA.\n");
-+ /* Disable IRDA (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_IRDA_ENABLE, 0);
-+}
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_bt_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Enabling Bluetooth.\n");
-+ /* Enable BT (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+}
-+
-+void cerf_ucb1400gpio_bt_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Disabling Bluetooth.\n");
-+ /* Disable BT (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_BT_ENABLE, 0);
-+}
-+
-+/* -- -- */
-+
-+/* -- Enable Bluetooth and IRDA automatically via pseudo module -- */
-+#if defined(CONFIG_BLUEZ) || defined(CONFIG_IRDA)
-+static int __init cerf_ucb1400gpio_module_init (void)
-+{
-+#ifdef CONFIG_BLUEZ
-+ cerf_ucb1400gpio_bt_enable();
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ cerf_ucb1400gpio_irda_enable();
-+#endif
-+ return 0;
-+}
-+
-+static void __exit cerf_ucb1400gpio_module_exit (void)
-+{
-+#ifdef CONFIG_BLUEZ
-+ cerf_ucb1400gpio_bt_disable();
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ cerf_ucb1400gpio_irda_disable();
-+#endif
-+}
-+
-+module_init(cerf_ucb1400gpio_module_init);
-+module_exit(cerf_ucb1400gpio_module_exit);
-+#endif
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/mcp-pxa.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,57 @@
-+/*
-+ * linux/drivers/misc/mcp-pxa.c
-+ *
-+ * 2002-01-10 Jeff Sutherland <jeffs@accelent.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.
-+ *
-+ * NOTE: This is a quick hack to gain access to the aclink codec's
-+ * touch screen facility. Its audio is handled by a separate
-+ * (non-mcp) driver at the present time.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/ac97_codec.h>
-+
-+#include "mcp.h"
-+
-+
-+extern int pxa_ac97_get(struct ac97_codec **codec);
-+extern void pxa_ac97_put(void);
-+
-+
-+struct mcp *mcp_get(void)
-+{
-+ struct ac97_codec *codec;
-+ if (pxa_ac97_get(&codec) < 0)
-+ return NULL;
-+ return (struct mcp *)codec;
-+}
-+
-+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ struct ac97_codec *codec = (struct ac97_codec *)mcp;
-+ codec->codec_write(codec, reg, val);
-+}
-+
-+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
-+{
-+ struct ac97_codec *codec = (struct ac97_codec *)mcp;
-+ return codec->codec_read(codec, reg);
-+}
-+
-+void mcp_enable(struct mcp *mcp)
-+{
-+ /*
-+ * Should we do something here to make sure the aclink
-+ * codec is alive???
-+ * A: not for now --NP
-+ */
-+}
-+
-+void mcp_disable(struct mcp *mcp)
-+{
-+}
---- linux-2.4.25/drivers/misc/mcp.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/mcp.h 2004-03-31 17:15:11.000000000 +0200
-@@ -10,16 +10,22 @@
- #ifndef MCP_H
- #define MCP_H
-
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/dma.h>
-+#endif
-+
- struct mcp {
- struct module *owner;
- spinlock_t lock;
- int use_count;
- unsigned int sclk_rate;
- unsigned int rw_timeout;
-+#ifdef CONFIG_ARCH_SA1100
- dma_device_t dma_audio_rd;
- dma_device_t dma_audio_wr;
- dma_device_t dma_telco_rd;
- dma_device_t dma_telco_wr;
-+#endif
- void (*set_telecom_divisor)(struct mcp *, unsigned int);
- void (*set_audio_divisor)(struct mcp *, unsigned int);
- void (*reg_write)(struct mcp *, unsigned int, unsigned int);
---- linux-2.4.25/drivers/misc/ucb1x00-core.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-core.c 2004-03-31 17:15:11.000000000 +0200
-@@ -23,12 +23,18 @@
- #include <linux/errno.h>
- #include <linux/interrupt.h>
- #include <linux/pm.h>
-+#include <linux/tqueue.h>
-+#include <linux/config.h>
-
--#include <asm/dma.h>
--#include <asm/hardware.h>
- #include <asm/irq.h>
- #include <asm/mach-types.h>
-+
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/arch/assabet.h>
- #include <asm/arch/shannon.h>
-+#endif
-+
-+#include <asm/hardware.h>
-
- #include "ucb1x00.h"
-
-@@ -155,6 +161,10 @@
- *
- * If called for a synchronised ADC conversion, it may sleep
- * with the ADC semaphore held.
-+ *
-+ * See ucb1x00.h for definition of the UCB_ADC_DAT macro. It
-+ * addresses a bug in the ucb1200/1300 which, of course, Philips
-+ * decided to finally fix in the ucb1400 ;-) -jws
- */
- unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
- {
-@@ -218,22 +228,75 @@
- * Since we need to read an internal register, we must re-enable
- * SIBCLK to talk to the chip. We leave the clock running until
- * we have finished processing all interrupts from the chip.
-+ *
-+ * A restriction with interrupts exists when using the ucb1400, as
-+ * the codec read/write routines may sleep while waiting for codec
-+ * access completion and uses semaphores for access control to the
-+ * AC97 bus. A complete codec read cycle could take anywhere from
-+ * 60 to 100uSec so we *definitely* don't want to spin inside the
-+ * interrupt handler waiting for codec access. So, we handle the
-+ * interrupt by scheduling a RT kernel thread to run in process
-+ * context instead of interrupt context.
- */
--static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+
-+static int ucb1x00_thread(void *_ucb)
- {
-- struct ucb1x00 *ucb = devid;
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ struct ucb1x00 *ucb = _ucb;
- struct ucb1x00_irq *irq;
- unsigned int isr, i;
-
-- ucb1x00_enable(ucb);
-- isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+ ucb->rtask = tsk;
-
-- for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-- if (isr & 1 && irq->fn)
-- irq->fn(i, irq->devid);
-- ucb1x00_disable(ucb);
-+ daemonize();
-+ reparent_to_init();
-+ tsk->tty = NULL;
-+ tsk->policy = SCHED_FIFO;
-+ tsk->rt_priority = 1;
-+ strcpy(tsk->comm, "kUCB1x00d");
-+
-+ /* only want to receive SIGKILL */
-+ spin_lock_irq(&tsk->sigmask_lock);
-+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-+ recalc_sigpending(tsk);
-+ spin_unlock_irq(&tsk->sigmask_lock);
-+
-+ add_wait_queue(&ucb->irq_wait, &wait);
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ complete(&ucb->complete);
-+
-+ for (;;) {
-+ if (signal_pending(tsk))
-+ break;
-+ enable_irq(ucb->irq);
-+ schedule();
-+
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ for (i = 0, irq = ucb->irq_handler;
-+ i < 16 && isr;
-+ i++, isr >>= 1, irq++)
-+ if (isr & 1 && irq->fn)
-+ irq->fn(i, irq->devid);
-+ ucb1x00_disable(ucb);
-+
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ }
-+
-+ remove_wait_queue(&ucb->irq_wait, &wait);
-+ ucb->rtask = NULL;
-+ complete_and_exit(&ucb->complete, 0);
-+}
-+
-+static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ struct ucb1x00 *ucb = devid;
-+ disable_irq(irqnr);
-+ wake_up(&ucb->irq_wait);
- }
-
- /**
-@@ -291,6 +354,11 @@
- spin_lock_irqsave(&ucb->lock, flags);
-
- ucb1x00_enable(ucb);
-+
-+ /* This prevents spurious interrupts on the UCB1400 */
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
- if (edges & UCB_RISING) {
- ucb->irq_ris_enbl |= 1 << idx;
- ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-@@ -456,6 +524,7 @@
- unsigned int irq_gpio_pin = 0;
- int irq, default_irq = NO_IRQ;
-
-+#ifdef CONFIG_ARCH_SA1100
- if (machine_is_adsbitsy())
- default_irq = IRQ_GPCIN4;
-
-@@ -514,12 +583,40 @@
- }
- #endif
-
-+#endif /* CONFIG_ARCH_SA1100 */
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if (machine_is_pxa_idp()) {
-+ default_irq = TOUCH_PANEL_IRQ;
-+ irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
-+ GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
-+ }
-+#endif
-+
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ if (machine_is_trizeps2()) {
-+ default_irq = TOUCH_PANEL_IRQ;
-+ irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
-+ GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
-+ }
-+#endif
-+
-+
-+#ifdef CONFIG_PXA_CERF_PDA
-+ if (machine_is_pxa_cerf()) {
-+ irq_gpio_pin = CERF_GPIO_UCB1400_IRQ;
-+ }
-+#endif
-+
- /*
- * Eventually, this will disappear.
- */
- if (irq_gpio_pin)
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE);
-+#else
- set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
--
-+#endif
- irq = ucb1x00_detect_irq(ucb);
- if (irq != NO_IRQ) {
- if (default_irq != NO_IRQ && irq != default_irq)
-@@ -541,21 +638,7 @@
-
- struct ucb1x00 *my_ucb;
-
--/**
-- * ucb1x00_get - get the UCB1x00 structure describing a chip
-- * @ucb: UCB1x00 structure describing chip
-- *
-- * Return the UCB1x00 structure describing a chip.
-- *
-- * FIXME: Currently very noddy indeed, which currently doesn't
-- * matter since we only support one chip.
-- */
--struct ucb1x00 *ucb1x00_get(void)
--{
-- return my_ucb;
--}
--
--static int __init ucb1x00_init(void)
-+static int ucb1x00_init_helper(void)
- {
- struct mcp *mcp;
- unsigned int id;
-@@ -568,23 +651,28 @@
- mcp_enable(mcp);
- id = mcp_reg_read(mcp, UCB_ID);
-
-- if (id != UCB_ID_1200 && id != UCB_ID_1300) {
-+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_1400) {
- printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
- goto out;
- }
-
-+ /* distinguish between UCB1400 revs 1B and 2A */
-+ if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)
-+ id = UCB_ID_1400_BUGGY;
-+
- my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
- ret = -ENOMEM;
- if (!my_ucb)
- goto out;
-
-+#ifdef CONFIG_ARCH_SA1100
- if (machine_is_shannon()) {
- /* reset the codec */
- GPDR |= SHANNON_GPIO_CODEC_RESET;
- GPCR = SHANNON_GPIO_CODEC_RESET;
- GPSR = SHANNON_GPIO_CODEC_RESET;
--
- }
-+#endif
-
- memset(my_ucb, 0, sizeof(struct ucb1x00));
-
-@@ -599,13 +687,12 @@
- if (ret)
- goto out;
-
-+ init_waitqueue_head(&my_ucb->irq_wait);
- ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
- if (ret) {
- printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
- my_ucb->irq, ret);
-- kfree(my_ucb);
-- my_ucb = NULL;
-- goto out;
-+ goto irq_err;
- }
-
- #ifdef CONFIG_PM
-@@ -616,16 +703,55 @@
- my_ucb->pmdev->data = my_ucb;
- #endif
-
-+ init_completion(&my_ucb->complete);
-+ ret = kernel_thread(ucb1x00_thread, my_ucb, CLONE_FS | CLONE_FILES);
-+ if (ret >= 0) {
-+ wait_for_completion(&my_ucb->complete);
-+ ret = 0;
-+ goto out;
-+ }
-+
-+ free_irq(my_ucb->irq, my_ucb);
-+irq_err:
-+ kfree(my_ucb);
-+ my_ucb = NULL;
- out:
- mcp_disable(mcp);
- no_mcp:
- return ret;
- }
-
-+/**
-+ * ucb1x00_get - get the UCB1x00 structure describing a chip
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the UCB1x00 structure describing a chip.
-+ *
-+ * FIXME: Currently very noddy indeed, which currently doesn't
-+ * matter since we only support one chip.
-+ */
-+struct ucb1x00 *ucb1x00_get(void)
-+{
-+ if( !my_ucb) ucb1x00_init_helper();
-+
-+ return my_ucb;
-+}
-+
-+static int __init ucb1x00_init(void)
-+{
-+ /* check if driver is already initialized */
-+ if( my_ucb) return 0;
-+
-+ return ucb1x00_init_helper();
-+}
-+
- static void __exit ucb1x00_exit(void)
- {
-+ send_sig(SIGKILL, my_ucb->rtask, 1);
-+ wait_for_completion(&my_ucb->complete);
- free_irq(my_ucb->irq, my_ucb);
- kfree(my_ucb);
-+ my_ucb = 0;
- }
-
- module_init(ucb1x00_init);
---- linux-2.4.25/drivers/misc/ucb1x00-ts.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-ts.c 2004-03-31 17:15:11.000000000 +0200
-@@ -35,7 +35,11 @@
- /*
- * Define this if you want the UCB1x00 stuff to talk to the input layer
- */
-+#ifdef CONFIG_INPUT
-+#define USE_INPUT
-+#else
- #undef USE_INPUT
-+#endif
-
- #ifndef USE_INPUT
-
-@@ -73,7 +77,7 @@
- struct pm_dev *pmdev;
- #endif
-
-- wait_queue_head_t irq_wait;
-+ struct semaphore irq_wait;
- struct semaphore sem;
- struct completion init_exit;
- struct task_struct *rtask;
-@@ -259,6 +263,11 @@
- input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
- }
-
-+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
-+{
-+ input_report_abs(&ts->idev, ABS_PRESSURE, 0);
-+}
-+
- static int ucb1x00_ts_open(struct input_dev *idev)
- {
- struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-@@ -304,10 +313,15 @@
- */
- static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
- {
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-- UCB_TS_CR_MODE_INT);
-+ if (ts->ucb->id == UCB_ID_1400_BUGGY)
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
-+ else
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
- }
-
- /*
-@@ -397,13 +411,13 @@
- /*
- * This is a RT kernel thread that handles the ADC accesses
- * (mainly so we can use semaphores in the UCB1200 core code
-- * to serialise accesses to the ADC).
-+ * to serialise accesses to the ADC). The UCB1400 access
-+ * functions are expected to be able to sleep as well.
- */
- static int ucb1x00_thread(void *_ts)
- {
- struct ucb1x00_ts *ts = _ts;
- struct task_struct *tsk = current;
-- DECLARE_WAITQUEUE(wait, tsk);
- int valid;
-
- ts->rtask = tsk;
-@@ -429,10 +443,8 @@
-
- valid = 0;
-
-- add_wait_queue(&ts->irq_wait, &wait);
- for (;;) {
- unsigned int x, y, p, val;
-- signed long timeout;
-
- ts->restart = 0;
-
-@@ -457,8 +469,6 @@
- val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
-
- if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
-- set_task_state(tsk, TASK_INTERRUPTIBLE);
--
- ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
- ucb1x00_disable(ts->ucb);
-
-@@ -471,7 +481,15 @@
- valid = 0;
- }
-
-- timeout = MAX_SCHEDULE_TIMEOUT;
-+ /*
-+ * Since ucb1x00_enable_irq() might sleep due
-+ * to the way the UCB1400 regs are accessed, we
-+ * can't use set_task_state() before that call,
-+ * and not changing state before enabling the
-+ * interrupt is racy. A semaphore solves all
-+ * those issues quite nicely.
-+ */
-+ down_interruptible(&ts->irq_wait);
- } else {
- ucb1x00_disable(ts->ucb);
-
-@@ -486,16 +504,13 @@
- }
-
- set_task_state(tsk, TASK_INTERRUPTIBLE);
-- timeout = HZ / 100;
-+ schedule_timeout(HZ / 100);
- }
-
-- schedule_timeout(timeout);
- if (signal_pending(tsk))
- break;
- }
-
-- remove_wait_queue(&ts->irq_wait, &wait);
--
- ts->rtask = NULL;
- ucb1x00_ts_evt_clear(ts);
- complete_and_exit(&ts->init_exit, 0);
-@@ -509,7 +524,7 @@
- {
- struct ucb1x00_ts *ts = id;
- ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-- wake_up(&ts->irq_wait);
-+ up(&ts->irq_wait);
- }
-
- static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
-@@ -525,7 +540,7 @@
- if (ts->rtask)
- panic("ucb1x00: rtask running?");
-
-- init_waitqueue_head(&ts->irq_wait);
-+ sema_init(&ts->irq_wait, 0);
- ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
- if (ret < 0)
- goto out;
-@@ -585,7 +600,7 @@
- * after sleep.
- */
- ts->restart = 1;
-- wake_up(&ts->irq_wait);
-+ up(&ts->irq_wait);
- }
- return 0;
- }
---- linux-2.4.25/drivers/misc/ucb1x00.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00.h 2004-03-31 17:15:11.000000000 +0200
-@@ -10,8 +10,47 @@
- #ifndef UCB1200_H
- #define UCB1200_H
-
-+#ifdef CONFIG_ARCH_PXA
-+
-+/* ucb1400 aclink register mappings: */
-+
-+#define UCB_IO_DATA 0x5a
-+#define UCB_IO_DIR 0x5c
-+#define UCB_IE_RIS 0x5e
-+#define UCB_IE_FAL 0x60
-+#define UCB_IE_STATUS 0x62
-+#define UCB_IE_CLEAR 0x62
-+#define UCB_TS_CR 0x64
-+#define UCB_ADC_CR 0x66
-+#define UCB_ADC_DATA 0x68
-+#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */
-+
-+#define UCB_ADC_DAT(x) ((x) & 0x3ff)
-+
-+#else
-+
-+/* ucb1x00 SIB register mappings: */
-+
- #define UCB_IO_DATA 0x00
- #define UCB_IO_DIR 0x01
-+#define UCB_IE_RIS 0x02
-+#define UCB_IE_FAL 0x03
-+#define UCB_IE_STATUS 0x04
-+#define UCB_IE_CLEAR 0x04
-+#define UCB_TC_A 0x05
-+#define UCB_TC_B 0x06
-+#define UCB_AC_A 0x07
-+#define UCB_AC_B 0x08
-+#define UCB_TS_CR 0x09
-+#define UCB_ADC_CR 0x0a
-+#define UCB_ADC_DATA 0x0b
-+#define UCB_ID 0x0c
-+#define UCB_MODE 0x0d
-+
-+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-+
-+#endif
-+
-
- #define UCB_IO_0 (1 << 0)
- #define UCB_IO_1 (1 << 1)
-@@ -24,10 +63,6 @@
- #define UCB_IO_8 (1 << 8)
- #define UCB_IO_9 (1 << 9)
-
--#define UCB_IE_RIS 0x02
--#define UCB_IE_FAL 0x03
--#define UCB_IE_STATUS 0x04
--#define UCB_IE_CLEAR 0x04
- #define UCB_IE_ADC (1 << 11)
- #define UCB_IE_TSPX (1 << 12)
- #define UCB_IE_TSMX (1 << 13)
-@@ -36,11 +71,9 @@
-
- #define UCB_IRQ_TSPX 12
-
--#define UCB_TC_A 0x05
- #define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
- #define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
-
--#define UCB_TC_B 0x06
- #define UCB_TC_B_VOICE_ENA (1 << 3)
- #define UCB_TC_B_CLIP (1 << 4)
- #define UCB_TC_B_ATT (1 << 6)
-@@ -49,14 +82,11 @@
- #define UCB_TC_B_IN_ENA (1 << 14)
- #define UCB_TC_B_OUT_ENA (1 << 15)
-
--#define UCB_AC_A 0x07
--#define UCB_AC_B 0x08
- #define UCB_AC_B_LOOP (1 << 8)
- #define UCB_AC_B_MUTE (1 << 13)
- #define UCB_AC_B_IN_ENA (1 << 14)
- #define UCB_AC_B_OUT_ENA (1 << 15)
-
--#define UCB_TS_CR 0x09
- #define UCB_TS_CR_TSMX_POW (1 << 0)
- #define UCB_TS_CR_TSPX_POW (1 << 1)
- #define UCB_TS_CR_TSMY_POW (1 << 2)
-@@ -72,7 +102,6 @@
- #define UCB_TS_CR_TSPX_LOW (1 << 12)
- #define UCB_TS_CR_TSMX_LOW (1 << 13)
-
--#define UCB_ADC_CR 0x0a
- #define UCB_ADC_SYNC_ENA (1 << 0)
- #define UCB_ADC_VREFBYP_CON (1 << 1)
- #define UCB_ADC_INP_TSPX (0 << 2)
-@@ -87,15 +116,13 @@
- #define UCB_ADC_START (1 << 7)
- #define UCB_ADC_ENA (1 << 15)
-
--#define UCB_ADC_DATA 0x0b
- #define UCB_ADC_DAT_VAL (1 << 15)
--#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-
--#define UCB_ID 0x0c
- #define UCB_ID_1200 0x1004
- #define UCB_ID_1300 0x1005
-+#define UCB_ID_1400 0x4304
-+#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */
-
--#define UCB_MODE 0x0d
- #define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
- #define UCB_MODE_AUD_OFF_CAN (1 << 13)
-
-@@ -115,6 +142,9 @@
- unsigned int irq;
- struct semaphore adc_sem;
- spinlock_t io_lock;
-+ wait_queue_head_t irq_wait;
-+ struct completion complete;
-+ struct task_struct *rtask;
- u16 id;
- u16 io_dir;
- u16 io_out;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,12 @@
-+mainmenu_option next_comment
-+comment 'MMC device drivers'
-+tristate 'Multi Media Card support' CONFIG_MMC
-+if [ "$CONFIG_MMC" = "y" -o "$CONFIG_MMC" = "m" ]; then
-+ dep_tristate 'PXA250 MMC driver' CONFIG_MMC_PXA $CONFIG_MMC
-+ dep_tristate 'MMC block driver' CONFIG_MMC_BLOCK $CONFIG_MMC
-+ if [ "$CONFIG_MMC_BLOCK" = "y" -o "$CONFIG_MMC_BLOCK" = "m" ]; then
-+ bool ' MMC partitioning support' CONFIG_MMC_PARTITIONS
-+ fi
-+fi
-+endmenu
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,14 @@
-+#
-+# Makefile for MMC drivers
-+#
-+
-+export-objs := mmc_core.o
-+
-+obj-$(CONFIG_MMC) += mmc_core.o # mmc_test.o
-+obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
-+obj-$(CONFIG_MMC_PXA) += mmc_pxa.o
-+# EXTRA_CFLAGS += -DCONFIG_MMC_DEBUG -DCONFIG_MMC_DEBUG_VERBOSE=2
-+
-+O_TARGET := mmcdrivers.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/error.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,70 @@
-+/*
-+ * linux/include/linux/mmc/error.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: error.h,v 0.2 2002/07/11 16:27:01 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_ERROR_H__
-+#define __MMC_ERROR_H__
-+
-+/* MMC protocol card error codes */
-+#define MMC_CARD_STATUS_OUT_OF_RANGE (1<<31)
-+#define MMC_CARD_STATUS_ADDRESS_ERROR (1<<30)
-+#define MMC_CARD_STATUS_BLOCK_LEN_ERROR (1<<29)
-+#define MMC_CARD_STATUS_ERASE_SEQ_ERROR (1<<28)
-+#define MMC_CARD_STATUS_ERASE_PARAM (1<<27)
-+#define MMC_CARD_STATUS_WP_VIOLATION (1<<26)
-+#define MMC_CARD_STATUS_CARD_IS_LOCKED (1<<25)
-+#define MMC_CARD_STATUS_LOCK_UNLOCK_FAILED (1<<24)
-+#define MMC_CARD_STATUS_COM_CRC_ERROR (1<<23)
-+#define MMC_CARD_STATUS_ILLEGAL_COMMAND (1<<22)
-+#define MMC_CARD_STATUS_CARD_ECC_FAILED (1<<21)
-+#define MMC_CARD_STATUS_CC_ERROR (1<<20)
-+#define MMC_CARD_STATUS_ERROR (1<<19)
-+#define MMC_CARD_STATUS_UNDERRUN (1<<18)
-+#define MMC_CARD_STATUS_OVERRUN (1<<17)
-+#define MMC_CARD_STATUS_CID_CSD_OVERWRITE (1<<16)
-+#define MMC_CARD_STATUS_ERASE_RESET (1<<13)
-+
-+#define MMC_ERROR( fmt, args... ) printk( KERN_ERR "%s(): " fmt, __FUNCTION__, ##args )
-+
-+/*
-+ * Error codes returned by MMC subsystem functions and
-+ * error reporting function prototypes
-+ */
-+enum _mmc_error {
-+/* controller errors */
-+ MMC_ERROR_GENERIC = -10000,
-+ MMC_ERROR_CRC_WRITE_ERROR = -10001,
-+ MMC_ERROR_CRC_READ_ERROR = -10002,
-+ MMC_ERROR_RES_CRC_ERROR = -10003,
-+ MMC_ERROR_READ_TIME_OUT = -10004,
-+ MMC_ERROR_TIME_OUT_RESPONSE = -10005,
-+ MMC_ERROR_INVAL = -10006,
-+/* protocol errors reported in card status (R1 response) */
-+ MMC_ERROR_OUT_OF_RANGE = -10007,
-+ MMC_ERROR_ADDRESS_ERROR = -10008,
-+ MMC_ERROR_BLOCK_LEN_ERROR = -10009,
-+ MMC_ERROR_ERASE_SEQ_ERROR = -10010,
-+ MMC_ERROR_ERASE_PARAM = -10011,
-+ MMC_ERROR_WP_VIOLATION = -10012,
-+ MMC_ERROR_CARD_IS_LOCKED = -10013,
-+ MMC_ERROR_LOCK_UNLOCK_FAILED = -10014,
-+ MMC_ERROR_COM_CRC_ERROR = -10015,
-+ MMC_ERROR_ILLEGAL_COMMAND = -10016,
-+ MMC_ERROR_CARD_ECC_FAILED = -10017,
-+ MMC_ERROR_CC_ERROR = -10018,
-+ MMC_ERROR_ERROR = -10019,
-+ MMC_ERROR_UNDERRUN = -10020,
-+ MMC_ERROR_OVERRUN = -10021,
-+ MMC_ERROR_CID_CSD_OVERWRITE = -10022,
-+ /* FIXME: incomplete */
-+ MMC_ERROR_ERASE_RESET = -10025
-+};
-+#endif /* __MMC_ERROR_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,463 @@
-+/*
-+ * linux/drivers/mmc/mmc.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc.h,v 0.3.1.8 2002/09/18 12:58:00 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_P_H__
-+#define __MMC_P_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+
-+#include <linux/spinlock.h>
-+
-+#ifdef CONFIG_PROC_FS
-+#include <linux/proc_fs.h>
-+#endif
-+
-+#include <asm/semaphore.h>
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+
-+#include "types.h"
-+
-+#include "error.h"
-+
-+#define MMC_CONTROLLERS_MAX (4)
-+#define MMC_CARDS_MAX (16)
-+
-+/* test device */
-+#define MMC_TEST_MAJOR (240)
-+#define MMC_TEST_TRANSFER_MODE_DEFAULT MMC_TRANSFER_MODE_BLOCK_SINGLE
-+
-+/* block device */
-+#define MMC_BLOCK_MAJOR (241) /* FIXME: MMC_MAJOR */
-+#define MMC_BLOCK_DEVICES_MAX (1<<MINORBITS) /* FIXME */
-+#define MMC_BLOCK_SECT_SIZE (512) /* FIXME */
-+#define MMC_BLOCK_PARTNBITS (3)
-+
-+/* Device minor number encoding:
-+ * [7:6] - host
-+ * [5:3] - card slot number
-+ * [2:0] - partition number
-+ */
-+#define MMC_MINOR_HOST_SHIFT (6)
-+#define MMC_MINOR_CARD_MASK (0x07)
-+
-+/*
-+ * MMC controller abstraction
-+ */
-+enum _mmc_controller_state {
-+ MMC_CONTROLLER_ABSENT = 0,
-+ MMC_CONTROLLER_FOUND,
-+ MMC_CONTROLLER_INITIALIZED,
-+ MMC_CONTROLLER_UNPLUGGED
-+};
-+
-+enum _mmc_dir {
-+ MMC_READ = 1,
-+ MMC_WRITE
-+};
-+
-+enum _mmc_buftype {
-+ MMC_USER = 1,
-+ MMC_KERNEL
-+};
-+
-+struct _mmc_data_transfer_req_rec {
-+ mmc_dir_t cmd; /* read or write operation requested */
-+ mmc_transfer_mode_t mode; /* requested data transfer mode */
-+ mmc_buftype_t type; /* whether supplied buffer resides in user or kernel space */
-+ char *buf; /* poiner to the caller's buffer */
-+ ssize_t cnt; /* number of bytes to transfer */
-+ loff_t addr; /* card address */
-+ ssize_t blksz; /* block size as for CSD[READ_BL_LEN] or CSD[WRITE_BL_LEN] */
-+ ssize_t nob; /* number of blocks to transfer */
-+};
-+
-+struct _mmc_controller_tmpl_rec {
-+ struct module *owner; /* driver module */
-+ char name[16];
-+
-+ const ssize_t block_size_max; /* max acceptable block size */
-+ const ssize_t nob_max; /* max blocks per one data transfer */
-+
-+ int (*probe)( mmc_controller_t ); /* hardware probe */
-+ int (*init)( mmc_controller_t ); /* initialize, e.g. request irq, DMA and allocate buffers */
-+ void (*remove)( mmc_controller_t ); /* free resources */
-+#if 0 /* CONFIG_HOTPLUG */
-+ void (*attach)( void ); /|* controller hotplug callbacks *|/
-+ void (*detach)( void );
-+#endif
-+#ifdef CONFIG_PM
-+ int (*suspend)( mmc_controller_t ); /* power management callbacks */
-+ void (*resume)( mmc_controller_t );
-+#endif
-+
-+/* MMC protocol macros, v3.4, p.120 */
-+ int (*init_card_stack)( mmc_controller_t );
-+ int (*update_acq)( mmc_controller_t ); /* update card stack management data */
-+ int (*single_card_acq)( mmc_controller_t );
-+ int (*check_card_stack)( mmc_controller_t );
-+ int (*setup_card)( mmc_controller_t, mmc_card_t );
-+ int (*stream_read)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*read_block)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*read_mblock)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*stream_write)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*write_block)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*write_mblock)( mmc_controller_t, mmc_data_transfer_req_t );
-+/* TODO:
-+ int (*sg_io)( mmc_controller_t, sg_list_t );
-+*/
-+/* TODO:
-+ * 1) erase group macros
-+ * int (*erase_group)( mmc_controller_t, mmc_erase_group_info_t );
-+ * 2) write protection macros;
-+ * int (*set_write_prot)( mmc_controller_t, mmc_write_protection_info_t )
-+ * 3) lock/password management macros;
-+ */
-+};
-+
-+#ifndef MMC_CTRLR_BLKSZ_DEFAULT
-+#define MMC_CTRLR_BLKSZ_DEFAULT (512)
-+#endif
-+
-+#ifndef MMC_CTRLR_NOB_DEFAULT
-+#define MMC_CTRLR_NOB_DEFAULT (1)
-+#endif
-+
-+struct _mmc_card_rec {
-+/* public card interface */
-+ struct _mmc_card_info_rec info; /* see <linux/mmc/mmc.h> */
-+
-+/* private kernel specific data */
-+ mmc_state_t state; /* card's state as per last operation */
-+ mmc_card_t next; /* link to the stack */
-+ mmc_controller_t ctrlr; /* back reference to the controller */
-+ int usage; /* reference count */
-+ int slot; /* card's number for device reference */
-+/* TODO: async I/O queue */
-+#ifdef CONFIG_PROC_FS
-+ proc_dir_entry_t proc;
-+ char proc_name[16];
-+#endif
-+ unsigned long card_data[0] /* card specific data */
-+ __attribute__((aligned (sizeof(unsigned long))));
-+};
-+
-+struct _mmc_card_stack_rec {
-+ mmc_card_t first; /* first card on the stack */
-+ mmc_card_t last; /* last card on the stack */
-+ mmc_card_t selected; /* currently selected card */
-+ int ncards;
-+};
-+
-+struct _mmc_controller_rec {
-+ mmc_controller_state_t state; /* found, initialized, unplugged... */
-+ int usage; /* reference count */
-+ int slot; /* host's number for device reference */
-+ semaphore_t io_sem; /* I/O serialization */
-+ rwsemaphore_t update_sem; /* card stack check/update serialization */
-+
-+ mmc_controller_tmpl_t tmpl; /* methods provided by the driver */
-+ mmc_card_stack_rec_t stack; /* card stack management data */
-+
-+ u32 rca_next; /* next RCA to assign */
-+ int slot_next; /* next slot number to assign */
-+#ifdef CONFIG_PROC_FS
-+ char proc_name[16];
-+ proc_dir_entry_t proc;
-+#endif
-+ unsigned long host_data[0] /* driver can request some extra space */
-+ __attribute__((aligned (sizeof(unsigned long))));
-+};
-+
-+/*
-+ * MMC core interface
-+ */
-+enum _mmc_reg_type {
-+ MMC_REG_TYPE_USER = 1,
-+ MMC_REG_TYPE_HOST,
-+ MMC_REG_TYPE_CARD
-+};
-+
-+struct _mmc_notifier_rec {
-+ struct _mmc_notifier_rec *next;
-+ mmc_notifier_fn_t add;
-+ mmc_notifier_fn_t remove;
-+};
-+
-+enum _mmc_response {
-+ MMC_NORESPONSE = 1,
-+ MMC_R1,
-+ MMC_R2,
-+ MMC_R3,
-+ MMC_R4,
-+ MMC_R5
-+};
-+
-+#undef EXTERN
-+#ifndef __MMC_CORE_IMPLEMENTATION__
-+#define EXTERN extern
-+#else
-+#define EXTERN /* empty */
-+#endif
-+
-+EXTERN void *mmc_register( mmc_reg_type_t, void *, size_t );
-+EXTERN void mmc_unregister( mmc_reg_type_t, void * );
-+EXTERN int mmc_update_card_stack( int );
-+
-+EXTERN mmc_card_t mmc_get_card( int, int );/* get reference to the card */
-+EXTERN void mmc_put_card( mmc_card_t ); /* release card reference */
-+
-+EXTERN int mmc_notify_add( mmc_card_t ); /* user notification */
-+EXTERN int mmc_notify_remove( mmc_card_t );
-+
-+EXTERN ssize_t mmc_read( mmc_card_t, mmc_transfer_mode_t, char *, size_t, loff_t * ); /* generic read */
-+EXTERN ssize_t mmc_write( mmc_card_t, mmc_transfer_mode_t, const char *, size_t, loff_t * ); /* generic write */
-+EXTERN int mmc_ioctl( mmc_card_t, unsigned int, unsigned long ); /* generic ioctl */
-+/*
-+ * TODO: [?m.b. ioctl()] to erase, lock and write protect
-+ * 1) mmc_erase
-+ * 2) mmc_write_prot
-+ * 3) mmc_lock
-+ */
-+#undef EXTERN
-+
-+static inline mmc_card_t __mmc_card_alloc( size_t extra )
-+{
-+ mmc_card_t ret = kmalloc( sizeof( mmc_card_rec_t ) + extra, GFP_KERNEL );
-+
-+ if ( ret ) {
-+ memset( ret, 0, sizeof( mmc_card_rec_t ) + extra );
-+ }
-+
-+ return ret;
-+}
-+
-+static inline void __mmc_card_free( mmc_card_t card )
-+{
-+ if ( card ) {
-+ kfree( card );
-+ }
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_init( mmc_card_stack_t stack )
-+{
-+ mmc_card_stack_t ret = NULL;
-+ if ( stack ) {
-+ memset( stack, 0, sizeof( mmc_card_stack_rec_t ) );
-+ ret = stack;
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_add( mmc_card_stack_t stack, mmc_card_t card )
-+{
-+ mmc_card_stack_t ret = NULL;
-+
-+ if ( stack && card ) {
-+ card->next = NULL;
-+
-+ if ( stack->first ) {
-+ stack->last->next = card;
-+ stack->last = card;
-+ } else
-+ stack->first = stack->last = card;
-+
-+ ++stack->ncards;
-+ ret = stack;
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_remove( mmc_card_stack_t stack, mmc_card_t card )
-+{
-+ mmc_card_stack_t ret = NULL;
-+ register mmc_card_t prev;
-+ int found = FALSE;
-+
-+ if ( !stack || !card )
-+ goto error;
-+
-+ if ( stack->ncards > 0 ) {
-+ if ( stack->first == card ) {
-+ stack->first = stack->first->next;
-+ if ( stack->last == card )
-+ stack->last = stack->last->next;
-+ found = TRUE;
-+ } else {
-+ for ( prev = stack->first; prev; prev = prev->next )
-+ if ( prev->next == card ) {
-+ found = TRUE;
-+ break;
-+ }
-+ if ( found ) {
-+ if ( prev->next == stack->last )
-+ stack->last = prev->next;
-+ prev->next = prev->next->next;
-+ }
-+ }
-+ if ( found ) {
-+ --stack->ncards;
-+ ret = stack;
-+ }
-+ }
-+error:
-+ return ret;
-+}
-+
-+static inline void __mmc_card_stack_free( mmc_card_stack_t stack )
-+{
-+ mmc_card_t card, next;
-+
-+ if ( stack && (stack->ncards > 0) ) {
-+ card = stack->first;
-+ while ( card ) {
-+ next = card->next;
-+ kfree( card );
-+ card = next;
-+ }
-+ __mmc_card_stack_init( stack );
-+ }
-+}
-+
-+static inline int __mmc_card_stack_foreach( mmc_card_stack_t stack, mmc_notifier_fn_t fn, int unplugged_also )
-+{
-+ int ret = 0;
-+ register mmc_card_t card = NULL;
-+
-+ if ( stack && fn ) {
-+ for ( card = stack->first; card; card = card->next )
-+ if ( (card->state != MMC_CARD_STATE_UNPLUGGED)
-+ || unplugged_also )
-+ if ( fn( card ) ) {
-+ ret = -card->slot;
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * Debugging macros
-+ */
-+#ifdef CONFIG_MMC_DEBUG
-+
-+#define MMC_DEBUG_LEVEL0 (0) /* major */
-+#define MMC_DEBUG_LEVEL1 (1)
-+#define MMC_DEBUG_LEVEL2 (2) /* device */
-+#define MMC_DEBUG_LEVEL3 (3) /* protocol */
-+#define MMC_DEBUG_LEVEL4 (4) /* everything */
-+
-+#define MMC_DEBUG(n, args...) \
-+if (n <= CONFIG_MMC_DEBUG_VERBOSE) { \
-+ printk(KERN_INFO __FUNCTION__ "(): " args); \
-+}
-+#define __ENTER0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry\n" );
-+#define __LEAVE0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit\n" );
-+#define __ENTER( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry: " format "\n", args );
-+#define __LEAVE( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit: " format "\n", args );
-+
-+#define MMC_DUMP_CSD( card ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"CSD register:\n" \
-+" csd_structure=%u\n" \
-+" spec_vers=%u\n" \
-+" taac=%x\n" \
-+" nsac=%x\n" \
-+" tran_speed=%x\n" \
-+" ccc=%x\n" \
-+" read_bl_len=%u\n" \
-+" read_bl_partial=%u\n" \
-+" write_blk_misalign=%u\n" \
-+" read_blk_misalign=%u\n" \
-+" dsr_imp=%u\n" \
-+" c_size=%u\n" \
-+" vdd_r_curr_min=%u\n" \
-+" vdd_r_curr_max=%u\n" \
-+" vdd_w_curr_min=%u\n" \
-+" vdd_w_curr_max=%u\n" \
-+" c_size_mult=%u\n" \
-+" erase_grp_size=%u\n" \
-+" erase_grp_mult=%u\n" \
-+" wp_grp_size=%u\n" \
-+" wp_grp_enable=%u\n" \
-+" default_ecc=%u\n" \
-+" r2w_factor=%u\n" \
-+" write_bl_len=%u\n" \
-+" write_bl_partial=%u\n" \
-+" content_prot_app=%u\n" \
-+" file_format_grp=%u\n" \
-+" copy=%u\n" \
-+" perm_write_protect=%d\n" \
-+" tmp_write_protect=%d\n" \
-+" file_format=%d\n" \
-+" ecc=%d\n", \
-+card->info.csd.csd_structure, \
-+card->info.csd.spec_vers, \
-+card->info.csd.taac, \
-+card->info.csd.nsac, \
-+card->info.csd.tran_speed, \
-+card->info.csd.ccc, \
-+card->info.csd.read_bl_len, \
-+card->info.csd.read_bl_partial, \
-+card->info.csd.write_blk_misalign, \
-+card->info.csd.read_blk_misalign, \
-+card->info.csd.dsr_imp, \
-+card->info.csd.c_size, \
-+card->info.csd.vdd_r_curr_min, \
-+card->info.csd.vdd_r_curr_max, \
-+card->info.csd.vdd_w_curr_min, \
-+card->info.csd.vdd_w_curr_max, \
-+card->info.csd.c_size_mult, \
-+card->info.csd.erase_grp_size, \
-+card->info.csd.erase_grp_mult, \
-+card->info.csd.wp_grp_size, \
-+card->info.csd.wp_grp_enable, \
-+card->info.csd.default_ecc, \
-+card->info.csd.r2w_factor, \
-+card->info.csd.write_bl_len, \
-+card->info.csd.write_bl_partial, \
-+card->info.csd.content_prot_app, \
-+card->info.csd.file_format_grp, \
-+card->info.csd.copy, \
-+card->info.csd.perm_write_protect, \
-+card->info.csd.tmp_write_protect, \
-+card->info.csd.file_format, \
-+card->info.csd.ecc );
-+
-+#else /* CONFIG_MMC_DEBUG */
-+#define MMC_DEBUG(n, args...) /* empty */
-+#define __ENTER0( ) /* empty */
-+#define __LEAVE0( ) /* empty */
-+#define __ENTER( args... ) /* empty */
-+#define __LEAVE( args... ) /* empty */
-+#define MMC_DUMP_CSD( card ) /* empty */
-+#endif /* CONFIG_MMC_DEBUG */
-+
-+/*
-+ * Miscellaneous defines
-+ */
-+#ifndef MMC_DUMP_R1
-+#define MMC_DUMP_R1( ctrlr ) /* empty */
-+#endif
-+#ifndef MMC_DUMP_R2
-+#define MMC_DUMP_R2( ctrlr ) /* empty */
-+#endif
-+#ifndef MMC_DUMP_R3
-+#define MMC_DUMP_R3( ctrlr ) /* empty */
-+#endif
-+
-+#endif /* __KERNEL__ */
-+
-+#endif /* __MMC_P_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc_block.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,989 @@
-+/*
-+ * linux/drivers/mmc/mmc_block.c
-+ * driver for the block device on the MMC card
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_block.c,v 0.3.1.16 2002/09/27 17:36:09 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/devfs_fs_kernel.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/hdreg.h>
-+#include <linux/blkpg.h>
-+#include <asm/uaccess.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+#include "error.h"
-+
-+#define MAJOR_NR MMC_BLOCK_MAJOR
-+#define MAJOR_NAME "mmc"
-+#define DEVICE_NAME "mmc_block"
-+#define DEVICE_REQUEST mmc_block_request
-+#define DEVICE_NR(device) (device)
-+#define DEVICE_ON(device)
-+#define DEVICE_OFF(device)
-+#define DEVICE_NO_RANDOM
-+#include <linux/blk.h>
-+/* for old kernels... */
-+#ifndef QUEUE_EMPTY
-+#define QUEUE_EMPTY (!CURRENT)
-+#endif
-+#if LINUX_VERSION_CODE < 0x20300
-+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
-+#else
-+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
-+#endif
-+
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
-+#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
-+#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
-+#else
-+#define BLK_INC_USE_COUNT do {} while(0)
-+#define BLK_DEC_USE_COUNT do {} while(0)
-+#endif
-+
-+#define MMC_BLOCK_RAW_DEVICE( device ) ((device>>MMC_BLOCK_PARTNBITS)<<MMC_BLOCK_PARTNBITS)
-+#define MMC_BLOCK_MKDEV( host, slot ) \
-+ MKDEV( MMC_BLOCK_MAJOR, \
-+ (host<<MMC_MINOR_HOST_SHIFT) \
-+ | (slot<<MMC_BLOCK_PARTNBITS) )
-+
-+typedef struct _mmc_block_device mmc_block_device_rec_t;
-+typedef struct _mmc_block_device *mmc_block_device_t;
-+
-+struct _mmc_block_device {
-+ mmc_card_t card;
-+ int host;
-+ int slot;
-+ kdev_t rdev;
-+ int usage;
-+ semaphore_t sem;
-+};
-+
-+static int mmc_block_blk_sizes[1<<MINORBITS];
-+static int mmc_block_blk_blksizes[1<<MINORBITS];
-+static int mmc_block_hardsect_sizes[1<<MINORBITS];
-+static struct hd_struct mmc_block_partitions[1<<MINORBITS];
-+
-+/* Accessed under device table lock */
-+static gendisk_rec_t mmc_block_gendisk = {
-+ major: MMC_BLOCK_MAJOR,
-+ major_name: MAJOR_NAME,
-+ minor_shift: MMC_BLOCK_PARTNBITS,
-+ max_p: (1<<MMC_BLOCK_PARTNBITS),
-+ sizes: mmc_block_blk_sizes,
-+ part: mmc_block_partitions
-+};
-+
-+static mmc_block_device_rec_t mmc_block_device[1<<MINORBITS];
-+static rwsemaphore_t mmc_block_device_sem;
-+
-+static inline void __mmc_block_rdlock_devices( void )
-+{
-+ down_read( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_rdunlock_devices( void )
-+{
-+ up_read( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_wrlock_devices( void )
-+{
-+ down_write( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_wrunlock_devices( void )
-+{
-+ up_write( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_lock_device( kdev_t rdev )
-+{
-+ __mmc_block_rdlock_devices();
-+ down( &mmc_block_device[MINOR( rdev )].sem );
-+}
-+
-+static inline void __mmc_block_unlock_device( kdev_t rdev )
-+{
-+ up( &mmc_block_device[MINOR( rdev )].sem );
-+ __mmc_block_rdunlock_devices();
-+}
-+
-+static inline void __mmc_block_device_init( int minor )
-+{
-+ mmc_block_device_t dev = &mmc_block_device[minor];
-+
-+ dev->usage = 0;
-+ dev->card = NULL;
-+ dev->host = minor >> MMC_MINOR_HOST_SHIFT;
-+ dev->slot = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
-+ dev->rdev = MKDEV( MMC_BLOCK_MAJOR, minor );
-+}
-+
-+static inline int __mmc_block_validate_device( kdev_t rdev )
-+{
-+ int ret = -1;
-+ int minor = MINOR( rdev );
-+
-+ if ( mmc_block_device[minor].card
-+ && (mmc_block_gendisk.part[minor].nr_sects > 0) )
-+ ret = 0;
-+
-+ return ret;
-+}
-+
-+static inline int __mmc_block_invalidate_card( mmc_card_t card, int invalidate )
-+{
-+ int ret = 0;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER( "card = 0x%p", card );
-+
-+ if ( card && card->ctrlr ) {
-+ register int i;
-+
-+ start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
-+ minor = MINOR( start );
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ if ( invalidate )
-+ invalidate_device( start + i, 0 );
-+
-+ __mmc_block_device_init( minor + i );
-+
-+ mmc_block_gendisk.part[minor + i].nr_sects = 0;
-+ mmc_block_gendisk.part[minor + i].start_sect = 0;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ }
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline int mmc_block_invalidate_card( int host, int slot, int invalidate )
-+{
-+ int ret = 0;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER( "host=%d slot=%d", host, slot );
-+
-+ if ( (host >= 0) && (slot >= 0) ) {
-+ register int i;
-+ mmc_card_t card = NULL;
-+
-+ start = MMC_BLOCK_MKDEV( host, slot );
-+ minor = MINOR( start );
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ if ( !card )
-+ card = mmc_block_device[minor + i].card;
-+
-+ if ( invalidate )
-+ invalidate_device( start + i, 0 );
-+
-+ __mmc_block_device_init( minor + i );
-+
-+ mmc_block_gendisk.part[minor + i].nr_sects = 0;
-+ mmc_block_gendisk.part[minor + i].start_sect = 0;
-+ }
-+ if ( card )
-+ mmc_put_card( card );
-+ __mmc_block_wrunlock_devices();
-+ }
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+/* Get device reference locked for writing */
-+static inline mmc_block_device_t __mmc_block_get_device( kdev_t rdev )
-+{
-+ mmc_block_device_t ret = NULL;
-+ u8 minor = MINOR( rdev );
-+ int host_no, card_no;
-+
-+ __ENTER( "rdev=%x:%x", MAJOR( rdev ), MINOR( rdev ) );
-+
-+ host_no = minor >> MMC_MINOR_HOST_SHIFT;
-+ if ( host_no >= MMC_CONTROLLERS_MAX )
-+ goto error;
-+
-+ card_no = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
-+ if ( card_no >= MMC_CARDS_MAX )
-+ goto error;
-+
-+ __mmc_block_lock_device( rdev );
-+ if ( __mmc_block_validate_device( rdev ) ) {
-+ __mmc_block_unlock_device( rdev );
-+ goto error;
-+ }
-+
-+ ret = &mmc_block_device[minor];
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
-+ MAJOR( ret->rdev ), MINOR( ret->rdev ),
-+ ret->card, ret->usage );
-+error:
-+ __LEAVE( "ret=0x%p", ret );
-+ return ret;
-+}
-+
-+/* Unlocks the device */
-+static inline void __mmc_block_put_device( mmc_block_device_t dev )
-+{
-+ __ENTER0();
-+
-+ if ( dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
-+ MAJOR( dev->rdev ), MINOR( dev->rdev ),
-+ dev->card, dev->usage );
-+ __mmc_block_unlock_device( dev->rdev );
-+ }
-+
-+ __LEAVE0();
-+}
-+
-+/* Atomically increases use count of the valid device */
-+static inline mmc_block_device_t mmc_block_get_device( kdev_t rdev )
-+{
-+ mmc_block_device_t ret = NULL;
-+
-+ __ENTER0();
-+
-+ ret = __mmc_block_get_device( rdev );
-+ if ( !ret )
-+ goto error;
-+
-+ ret->usage++;
-+ __mmc_block_put_device( ret );
-+error:
-+ __LEAVE( "ret=0x%p dusage=%d card=0x%p cusage=%d",
-+ ret, ret ? ret->usage : -1,
-+ ret ? ret->card : NULL,
-+ ret ? (ret->card ? ret->card->usage : -1) : -1 );
-+ return ret;
-+}
-+
-+/* Check is there references to the card */
-+static inline int __mmc_block_check_card( kdev_t rdev )
-+{
-+ int ret = TRUE;
-+ int start = MINOR( MMC_BLOCK_RAW_DEVICE( rdev ) );
-+ register int i;
-+
-+ for ( i = 0; i < mmc_block_gendisk.max_p; i++ )
-+ if ( mmc_block_device[start + i].usage > 0 ) {
-+ ret = FALSE;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+/* Atomically decreases device use count */
-+static inline void mmc_block_put_device( mmc_block_device_t dev )
-+{
-+ __ENTER0();
-+
-+ if ( dev ) {
-+ int invalidate = FALSE;
-+
-+ __mmc_block_get_device( dev->rdev );
-+ if ( dev->usage > 0 )
-+ --dev->usage;
-+
-+ if ( dev->usage ) {
-+ __mmc_block_put_device( dev );
-+ goto out;
-+
-+ } else {
-+ int host, slot;
-+ mmc_card_t card = NULL;
-+
-+ invalidate = __mmc_block_check_card( dev->rdev );
-+ if ( invalidate ) {
-+ host = dev->card->ctrlr->slot;
-+ slot = dev->card->slot;
-+
-+ if ( dev->card ) {
-+ card = dev->card;
-+ mmc_put_card( dev->card );
-+ dev->card = NULL;
-+ }
-+ }
-+ __mmc_block_put_device( dev );
-+
-+ if ( invalidate )
-+ __mmc_block_invalidate_card( card, TRUE );
-+ }
-+
-+ }
-+out:
-+ __LEAVE0();
-+}
-+
-+static int mmc_block_open( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_block_device_t dev = NULL;
-+
-+ __ENTER0();
-+
-+ if ( !inode || !file )
-+ goto error;
-+
-+ BLK_INC_USE_COUNT;
-+
-+ check_disk_change( inode->i_rdev );
-+
-+ dev = mmc_block_get_device( inode->i_rdev );
-+ if ( !dev )
-+ goto error;
-+
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+ if ( !dev )
-+ goto error;
-+
-+ if ( file->f_mode & FMODE_WRITE ) { /* FIXME */
-+ if ( dev->usage > 1 ) {
-+ ret = -EBUSY;
-+ __mmc_block_put_device( dev );
-+ mmc_block_put_device( dev );
-+ goto error;
-+ }
-+ }
-+
-+ __mmc_block_put_device( dev );
-+
-+ if ( file )
-+ file->private_data = dev;
-+
-+ ret = 0;
-+ goto out;
-+error:
-+ BLK_DEC_USE_COUNT;
-+out:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static int mmc_block_release( struct inode *inode, struct file *file )
-+{
-+ int ret = -EINVAL;
-+ mmc_block_device_t dev = NULL;
-+
-+ __ENTER( "inode=0x%p file=0x%p rdev=(%x:%x)", inode, file,
-+ inode ? MAJOR( inode->i_rdev ) : 0xff,
-+ inode ? MINOR( inode->i_rdev ) : 0xff );
-+
-+ if ( !file && !inode )
-+ goto error;
-+
-+ if ( file )
-+ dev = file->private_data;
-+ else
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
-+ goto error;
-+ }
-+
-+ if ( file ) {
-+ mmc_block_put_device( dev );
-+ file->private_data = NULL;
-+
-+ } else {
-+ int invalidate = FALSE;
-+
-+ if ( dev->usage > 0 )
-+ --dev->usage;
-+
-+ if ( dev->usage ) {
-+ __mmc_block_put_device( dev );
-+ goto out;
-+
-+ } else {
-+ int host, slot;
-+ mmc_card_t card = NULL;
-+
-+ invalidate = __mmc_block_check_card( dev->rdev );
-+ if ( invalidate ) {
-+ host = dev->card->ctrlr->slot;
-+ slot = dev->card->slot;
-+
-+ if ( dev->card ) {
-+ card = dev->card;
-+ mmc_put_card( dev->card );
-+ dev->card = NULL;
-+ }
-+ }
-+ __mmc_block_put_device( dev );
-+
-+ if ( invalidate )
-+ __mmc_block_invalidate_card( card, TRUE );
-+
-+ }
-+ }
-+
-+out:
-+ BLK_DEC_USE_COUNT;
-+ ret = 0;
-+error:
-+ __LEAVE0();
-+ return ret;
-+}
-+
-+static int mmc_block_check_disk_change( kdev_t rdev )
-+{
-+ int ret = 0;
-+#if 0
-+ mmc_block_device_t dev = &mmc_block_device[MINOR( rdev )];
-+
-+ __mmc_block_lock_device( rdev );
-+ if ( !dev->card )
-+ ret = 1;
-+ __mmc_block_unlock_device( rdev );
-+#else
-+ ret = 1;
-+#endif
-+ return ret;
-+}
-+
-+static int mmc_block_revalidate( kdev_t rdev )
-+{
-+ int ret = 1;
-+ mmc_card_t card;
-+ mmc_block_device_t dev;
-+ kdev_t start = MMC_BLOCK_RAW_DEVICE( rdev );
-+ int minor = MINOR( start );
-+ int host, slot;
-+ int i;
-+
-+ __ENTER0();
-+
-+ (void)mmc_update_card_stack( MINOR( start )>>MMC_MINOR_HOST_SHIFT );
-+
-+ __mmc_block_wrlock_devices();
-+
-+ dev = &mmc_block_device[minor];
-+ host = dev->host;
-+ slot = dev->slot;
-+
-+ if ( dev->card ) { /* card has not been changed actually */
-+ __mmc_block_wrunlock_devices();
-+ goto out;
-+
-+ } else {
-+ card = mmc_get_card( host, slot );
-+ if ( !card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "failed to get card: "
-+ "host=%d, slot=%d\n", host, slot );
-+ __mmc_block_wrunlock_devices();
-+ goto error;
-+ }
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ /* FIXME */
-+ __mmc_block_rdlock_devices(); /* handle the request for sector 0 */
-+ grok_partitions( &mmc_block_gendisk, MINOR( start ),
-+ mmc_block_gendisk.max_p,
-+ card->info.capacity>>9 /* sectors */
-+ );
-+ __mmc_block_rdunlock_devices();
-+ /* FIXME */
-+ __mmc_block_wrlock_devices();
-+ for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ int minor = MINOR( i );
-+
-+ dev = &mmc_block_device[minor];
-+ if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+out:
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static void mmc_block_handle_request( void )
-+{
-+ struct request *request;
-+ mmc_block_device_t dev;
-+ mmc_card_t card;
-+ char *buf;
-+ loff_t pos;
-+ unsigned int result = 0;
-+
-+ for (;;) {
-+ int minor;
-+
-+ INIT_REQUEST;
-+ request = CURRENT;
-+ spin_unlock_irq( &io_request_lock );
-+
-+ minor = MINOR( request->rq_dev );
-+ dev = __mmc_block_get_device( request->rq_dev );
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "invalid device (%x:%x)\n",
-+ MAJOR( request->rq_dev ), minor );
-+
-+ goto end_req;
-+ }
-+
-+ card = dev->card;
-+ (void)__mmc_block_put_device( dev );
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+// printk( KERN_INFO __FUNCTION__"(): "
-+ "request %p: cmd %i sec %li (nr. %li)\n",
-+ CURRENT, CURRENT->cmd, CURRENT->sector,
-+ CURRENT->current_nr_sectors );
-+
-+ if ( request->current_nr_sectors >
-+ mmc_block_gendisk.part[minor].nr_sects )
-+ goto end_req;
-+
-+ // Handle the request
-+ // TODO: handle clusterred requests in multiple block transfer mode
-+ buf = request->buffer;
-+ pos = (mmc_block_gendisk.part[minor].start_sect +
-+ request->sector) * MMC_BLOCK_SECT_SIZE;
-+
-+ switch ( request->cmd )
-+ {
-+ int i, ret;
-+
-+ case READ:
-+#if 0
-+ ret = mmc_read( card,
-+ (request->current_nr_sectors > 1) ?
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ request->current_nr_sectors
-+ * MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+
-+#else
-+ for ( i = 0;
-+ i < request->current_nr_sectors;
-+ i++ ) {
-+ ret = mmc_read( card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+ else
-+ buf += ret;
-+ }
-+#endif
-+ result = 1;
-+ break;
-+
-+ case WRITE:
-+ // TODO: Read only device
-+#if 0
-+ ret = mmc_write( card,
-+ (request->current_nr_sectors > 1) ?
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ request->current_nr_sectors
-+ * MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+
-+#else
-+ for ( i = 0;
-+ i < request->current_nr_sectors;
-+ i++ ) {
-+ ret = mmc_write( card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+ else
-+ buf += ret;
-+ }
-+#endif
-+ result = 1;
-+ break;
-+ }
-+
-+end_req:
-+ __LEAVE( "result=%d", result );
-+ spin_lock_irq( &io_request_lock );
-+ end_request( result );
-+ }
-+}
-+
-+static volatile int leaving = 0;
-+static DECLARE_MUTEX_LOCKED( thread_sem );
-+static DECLARE_WAIT_QUEUE_HEAD( thr_wq );
-+static pid_t thr_id = -1;
-+
-+int mmc_block_thread( void *arg )
-+{
-+ struct task_struct *task = current;
-+ DECLARE_WAITQUEUE(wait, task);
-+
-+ __ENTER0();
-+
-+ task->session = 1;
-+ task->pgrp = 1;
-+ task->flags |= PF_MEMALLOC;
-+ strcpy( task->comm, "mmcblockd" );
-+ task->tty = NULL;
-+ spin_lock_irq( &task->sigmask_lock );
-+ sigfillset( &task->blocked );
-+ recalc_sigpending( task );
-+ spin_unlock_irq( &task->sigmask_lock );
-+ exit_mm( task );
-+ exit_files( task );
-+ exit_sighand( task );
-+ exit_fs( task );
-+
-+ while ( !leaving ) {
-+ add_wait_queue( &thr_wq, &wait);
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ spin_lock_irq( &io_request_lock );
-+ if ( QUEUE_EMPTY || QUEUE_PLUGGED ) {
-+ spin_unlock_irq( &io_request_lock );
-+ schedule();
-+ remove_wait_queue( &thr_wq, &wait );
-+ } else {
-+ remove_wait_queue( &thr_wq, &wait );
-+ set_current_state( TASK_RUNNING );
-+ mmc_block_handle_request(); /* handle the request */
-+ spin_unlock_irq( &io_request_lock );
-+ }
-+ }
-+
-+ up( &thread_sem );
-+
-+ __LEAVE0();
-+ return 0;
-+}
-+
-+#if LINUX_VERSION_CODE < 0x20300
-+#define RQFUNC_ARG void
-+#else
-+#define RQFUNC_ARG request_queue_t *q
-+#endif
-+
-+static void mmc_block_request( RQFUNC_ARG )
-+{
-+ wake_up( &thr_wq );
-+}
-+
-+static int mmc_block_ioctl( struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -ENODEV;
-+ mmc_block_device_t dev;
-+ mmc_card_t card;
-+ int minor;
-+ __ENTER0();
-+
-+ if ( !inode || !file ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+ minor = MINOR( inode->i_rdev );
-+
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
-+ goto error;
-+ }
-+
-+ card = dev->card;
-+ __mmc_block_put_device( dev );
-+
-+ switch ( cmd ) {
-+ case BLKGETSIZE: /* Return device size */
-+ {
-+ unsigned long value;
-+
-+ __mmc_block_rdlock_devices();
-+ value = mmc_block_gendisk.part[minor].nr_sects;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( put_user( value, (unsigned long *) arg) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+
-+#ifdef BLKGETSIZE64
-+ case BLKGETSIZE64:
-+ {
-+ unsigned long value;
-+
-+ __mmc_block_rdlock_devices();
-+ value = mmc_block_gendisk.part[minor].nr_sects;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( put_user( (u64)value, (u64 *) arg) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+#endif
-+
-+ case HDIO_GETGEO:
-+ {
-+ struct hd_geometry geo;
-+
-+ ret = !access_ok( VERIFY_WRITE, arg, sizeof( geo ) );
-+ if ( ret ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+
-+ geo.heads = 1;
-+ geo.sectors = 1;
-+
-+ __mmc_block_rdlock_devices();
-+ geo.cylinders = mmc_block_gendisk.part[minor].nr_sects;
-+ geo.start = mmc_block_gendisk.part[minor].start_sect;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( copy_to_user( (int *)arg, &geo, sizeof( geo ) ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+
-+ case BLKRRPART:
-+ if ( !capable( CAP_SYS_ADMIN ) ) {
-+ ret = -EACCES;
-+ goto error;
-+ }
-+ (void)mmc_block_revalidate( inode->i_rdev );
-+ break;
-+
-+ default:
-+ ret = blk_ioctl( inode->i_rdev, cmd, arg );
-+ goto out;
-+ }
-+
-+ ret = 0;
-+error:
-+out:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+#if LINUX_VERSION_CODE < 0x20326
-+static struct file_operations mmc_block_fops =
-+{
-+ open: mmc_block_open,
-+ ioctl: mmc_block_ioctl,
-+ release: mmc_block_release,
-+ check_media_change: mmc_block_check_disk_change,
-+ revalidate: mmc_block_revalidate,
-+ read: block_read,
-+ write: block_write
-+};
-+#else
-+static struct block_device_operations mmc_block_fops =
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
-+ owner: THIS_MODULE,
-+#endif
-+ open: mmc_block_open,
-+ release: mmc_block_release,
-+ ioctl: mmc_block_ioctl,
-+ check_media_change: mmc_block_check_disk_change,
-+ revalidate: mmc_block_revalidate
-+};
-+#endif
-+
-+
-+static int mmc_block_notify_add( mmc_card_t card )
-+{
-+ int ret = -1;
-+ mmc_block_device_t dev;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER0();
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
-+ dev = &mmc_block_device[MINOR( start )];
-+
-+ __mmc_block_wrlock_devices();
-+ if ( !dev->card ) {
-+ dev->card = card;
-+ ret = 0;
-+ }
-+ __mmc_block_wrunlock_devices();
-+
-+ if ( !ret ) {
-+ int i;
-+
-+ /* allow to read partition table */
-+ __mmc_block_rdlock_devices();
-+ grok_partitions( &mmc_block_gendisk, MINOR( start ),
-+ mmc_block_gendisk.max_p,
-+ card->info.capacity>>9 /* sectors */
-+ );
-+ __mmc_block_rdunlock_devices();
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ minor = MINOR( i );
-+ dev = &mmc_block_device[minor];
-+ if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+
-+static int mmc_block_notify_remove( mmc_card_t card )
-+{
-+ int ret = -1;
-+
-+ __ENTER( "card=0x%p", card );
-+
-+ if ( card && card->ctrlr )
-+ ret = __mmc_block_invalidate_card( card, FALSE );
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static mmc_notifier_rec_t mmc_block_notifier = {
-+ add: mmc_block_notify_add,
-+ remove: mmc_block_notify_remove
-+};
-+
-+static int __init mmc_block_module_init( void )
-+{
-+ int ret = -ENODEV;
-+ int i;
-+
-+ __ENTER0();
-+
-+ init_rwsem( &mmc_block_device_sem );
-+
-+ if ( devfs_register_blkdev( MAJOR_NR, MAJOR_NAME, &mmc_block_fops ) ) {
-+ MMC_ERROR( "Can't allocate major number %d for MMC block devices.\n", MMC_BLOCK_MAJOR );
-+ ret = -EAGAIN;
-+ goto error;
-+ }
-+
-+ for ( i = 0; i < (1<<MINORBITS); i++ ) {
-+ __mmc_block_device_init( i );
-+ init_MUTEX( &mmc_block_device[i].sem );
-+
-+ /* We fill it in at open() time. */
-+ mmc_block_blk_sizes[i] = 0;
-+ mmc_block_blk_blksizes[i] = BLOCK_SIZE;
-+ mmc_block_hardsect_sizes[i] = 0;
-+ }
-+
-+ init_waitqueue_head( &thr_wq );
-+ /* Allow the block size to default to BLOCK_SIZE. */
-+ blksize_size[MAJOR_NR] = mmc_block_blk_blksizes;
-+ hardsect_size[MAJOR_NR] = mmc_block_hardsect_sizes;
-+ /* Gendisk stuff */
-+ memset( mmc_block_partitions, 0, sizeof( mmc_block_partitions ) );
-+ add_gendisk( &mmc_block_gendisk );
-+
-+/* FIXME: per controller request queue, I/O and card stack update threads */
-+ blk_init_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ), &mmc_block_request );
-+ thr_id = kernel_thread( mmc_block_thread, NULL,
-+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND );
-+
-+ if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_block_notifier, 0 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+
-+ ret = 0;
-+ goto out;
-+error:
-+ if ( thr_id != -1 ) {
-+/* quit the thread */
-+ leaving = 1;
-+ wake_up(&thr_wq);
-+
-+ down(&thread_sem);
-+ }
-+ blksize_size[MAJOR_NR] = NULL;
-+ blk_size[MAJOR_NR] = NULL;
-+ hardsect_size[MAJOR_NR] = NULL;
-+out:
-+ __LEAVE0();
-+ return ret;
-+}
-+
-+static void __exit mmc_block_module_cleanup( void )
-+{
-+/* quit the thread */
-+ leaving = 1;
-+ wake_up(&thr_wq);
-+
-+ down(&thread_sem);
-+
-+ mmc_unregister( MMC_REG_TYPE_USER, &mmc_block_notifier );
-+ del_gendisk( &mmc_block_gendisk );
-+ devfs_unregister_blkdev( MAJOR_NR, MAJOR_NAME );
-+
-+ blk_cleanup_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ) );
-+ blksize_size[MAJOR_NR] = NULL;
-+ blk_size[MAJOR_NR] = NULL;
-+ hardsect_size[MAJOR_NR] = NULL;
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init( mmc_block_module_init );
-+module_exit( mmc_block_module_cleanup );
-+
-+
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc_core.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,1124 @@
-+/*
-+ * linux/drivers/mmc/mmc_core.c
-+ * MultiMediaCard subsystem core implementation
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_core.c,v 0.3.1.14 2002/09/27 17:36:09 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/slab.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+
-+#ifdef CONFIG_PM
-+#include <linux/pm.h>
-+#endif
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+
-+#define __MMC_CORE_IMPLEMENTATION__
-+#include "mmc.h"
-+
-+/* MMC controllers registered in the system */
-+static mmc_controller_t mmc_controller[MMC_CONTROLLERS_MAX];
-+static int mmc_ncontrollers = 0;
-+static rwsemaphore_t mmc_controller_sem; /* controller table lock */
-+#ifdef CONFIG_PM
-+static struct pm_dev *mmc_pm_dev = NULL;
-+#endif
-+
-+/* users' notification list */
-+static mmc_notifier_t mmc_notifier = NULL;
-+static rwsemaphore_t mmc_notifier_sem; /* notifiers' list lock */
-+#ifdef CONFIG_PROC_FS
-+static proc_dir_entry_t mmc_proc_dir = NULL;
-+#endif
-+
-+/************************************************
-+ * service function prototypes and declarations *
-+ ************************************************/
-+static inline int mmc_acquire_io( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ int ret = -EIO;
-+
-+ __ENTER0();
-+
-+ if ( !card || !ctrlr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+#ifdef CONFIG_HOTPLUG
-+/* TODO: account for controller removal */
-+#endif
-+ down( &ctrlr->io_sem );
-+#if 0
-+ down_read( &ctrlr->update_sem ); /* FIXME */
-+ if ( card->state != MMC_CARD_STATE_UNPLUGGED )
-+ ret = 0;
-+ up_read( &ctrlr->update_sem );
-+
-+ if ( ret )
-+ up( &ctrlr->io_sem );
-+#else
-+ ret = 0;
-+#endif
-+
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline void mmc_release_io( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ __ENTER0();
-+#ifdef CONFIG_HOTPLUG
-+/* TODO: account for controller removal */
-+#endif
-+ if ( !card && !ctrlr ) { /* FIXME */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "bad card reference\n" );
-+ goto error;
-+ }
-+ up( &ctrlr->io_sem );
-+error:
-+ __LEAVE0();
-+}
-+
-+/* TODO: there should be a separate context to be awaken
-+ * by the card intertion interrupt; called under ctrlr->update_sem
-+ * held down by now */
-+static int __mmc_update_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ mmc_card_t card, prev;
-+
-+ __ENTER0();
-+
-+ if ( !ctrlr || !ctrlr->tmpl )
-+ goto error;
-+
-+ /* check unplugged cards first... */
-+ if ( (ret = ctrlr->tmpl->check_card_stack( ctrlr )) )
-+ goto error;
-+
-+ /* unregister unplugged cards and free 'em immediately */
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ prev = ctrlr->stack.first;
-+ /* process the stack tail first */
-+ if ( prev->next ) {
-+ card = prev->next;
-+ while ( card ) {
-+ if ( card->state == MMC_CARD_STATE_UNPLUGGED ) {
-+ if ( ctrlr->stack.selected == card )
-+ ctrlr->stack.selected = NULL;
-+#ifdef CONFIG_PROC_FS
-+ if ( card->proc ) {
-+ remove_proc_entry( card->proc_name, ctrlr->proc );
-+ card->proc = NULL;
-+ }
-+#endif
-+ ctrlr->slot_next = card->slot; /* FIXME */
-+ prev->next = card->next;
-+ if ( ctrlr->stack.last == card )
-+ ctrlr->stack.last = prev;
-+ /* FIXME: controller use count */
-+ mmc_notify_remove( card );
-+ --ctrlr->stack.ncards;
-+ if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count "
-+ "decreased (%d)\n",
-+ ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT(
-+ ctrlr->tmpl->owner );
-+ }
-+ __mmc_card_free( card );
-+
-+ card = prev->next;
-+ }
-+ }
-+ }
-+ /* then the head */
-+ card = ctrlr->stack.first;
-+ if ( card && (card->state == MMC_CARD_STATE_UNPLUGGED) ) {
-+ if ( ctrlr->stack.selected == card )
-+ ctrlr->stack.selected = NULL;
-+#ifdef CONFIG_PROC_FS
-+ if ( card->proc ) {
-+ remove_proc_entry( card->proc_name, ctrlr->proc );
-+ card->proc = NULL;
-+ }
-+#endif
-+ ctrlr->slot_next = card->slot; /* FIXME */
-+ mmc_notify_remove( card ); /* FIXME: should unregister here */
-+ ctrlr->stack.first = card->next;
-+ if ( ctrlr->stack.last == card )
-+ ctrlr->stack.last = NULL;
-+ /* FIXME: controller use count */
-+ --ctrlr->stack.ncards;
-+ if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "'%s' use count "
-+ "decreased (%d)\n", ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT( ctrlr->tmpl->owner );
-+ }
-+ __mmc_card_free( card );
-+ }
-+ }
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "after stack check: ncards=%d"
-+ " first=0x%x last=0x%x\n", ctrlr->stack.ncards,
-+ ctrlr->stack.first, ctrlr->stack.last );
-+ /* ...then add newly inserted ones */
-+ if ( (ret = ctrlr->tmpl->update_acq( ctrlr )) )
-+ goto error;
-+ /* ret = 0; */
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+/*
-+ * 1) check error code returned by controller; it's up to
-+ * controller to detect error conditions reported by the card
-+ * and to abort data transfer requests properly (e.g. send
-+ * CMD12(STOP_TRANSMISSION) to abort ADDRESS_ERROR multiple
-+ * block transfers)
-+ * 2) arrange for card stack update when necessary
-+ * (all pending i/o requests must be held pending,
-+ * update procedure must start immediately after
-+ * error has been detected)
-+ */
-+static inline int __mmc_check_error( mmc_card_t card, int err )
-+{
-+ int ret = -EIO;
-+ mmc_controller_t ctrlr;
-+
-+ __ENTER0();
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+
-+ if ( err < 0 ) {
-+ switch ( err ) {
-+ /* bus error occurred */
-+ case MMC_ERROR_CRC_WRITE_ERROR:
-+ case MMC_ERROR_CRC_READ_ERROR:
-+ case MMC_ERROR_RES_CRC_ERROR:
-+ case MMC_ERROR_READ_TIME_OUT:
-+ case MMC_ERROR_TIME_OUT_RESPONSE:
-+ down_write( &ctrlr->update_sem ); /* FIXME */
-+ if ( !__mmc_update_card_stack( ctrlr ) )
-+ ret = -ENXIO;
-+ up_write( &ctrlr->update_sem );
-+ break;
-+ }
-+ } else
-+ ret = err;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline void __mmc_free_controller( mmc_controller_t ctrlr )
-+{
-+ if ( ctrlr ) {
-+ if ( ctrlr->stack.ncards > 0 )
-+ __mmc_card_stack_free( &ctrlr->stack );
-+ kfree( ctrlr );
-+ }
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+static int mmc_proc_read_card_info( char *page, char **start, off_t off, int count, int *eof, void *data )
-+{
-+ int ret = -EINVAL;
-+ mmc_card_t card = (mmc_card_t)data;
-+ char *cp = page;
-+
-+ if ( !card )
-+ goto error;
-+
-+ down_read( &card->ctrlr->update_sem );
-+/* TODO: proc report
-+ * Type: RO, RW or IO (by CCC)
-+ * MID: 0x%02x card->info.cid.mid
-+ * OID: 0x%04x card->info.cid.oid
-+ * PNM: %s card->info.pnm
-+ * PRV: %s card->info.prv
-+ * PSN: 0x%08x card->info.cid.psn
-+ * MDT: %s card->info.mdt
-+ * Capacity: card->info.capacity (Bytes)
-+ */
-+#if 1
-+ cp += sprintf( cp, "Capacity: %dKb.\n\n", (card->info.capacity>>10) );
-+#else /* TODO */
-+ cp += sprintf( cp, "Type : %s\n", card->info.type );
-+ cp += sprintf( cp, "MID : 0x%02x\n", card->info.cid.mid );
-+ cp += sprintf( cp, "OID : 0x%04x\n", card->info.cid.oid );
-+ cp += sprintf( cp, "PNM : %s\n", card->info.pnm );
-+ cp += sprintf( cp, "PRV : %s\n", card->info.prv );
-+ cp += sprintf( cp, "PSN : 0x%08x\n", card->info.cid.psn );
-+ cp += sprintf( cp, "MDT : %s\n", card->info.mdt );
-+ cp += sprintf( cp, "Capacity: %dKB\n",
-+ (card->info.capacity>>10) );
-+#endif
-+ up_read( &card->ctrlr->update_sem );
-+
-+ ret = cp - page;
-+error:
-+ return ret;
-+}
-+#endif
-+
-+/*************************************
-+ * MMC core interface implementation *
-+ *************************************/
-+int mmc_notify_add( mmc_card_t card )
-+{
-+ int ret = 0;
-+ mmc_notifier_t notifier;
-+
-+ __ENTER0();
-+ if ( card ) {
-+ for ( notifier = mmc_notifier; notifier;
-+ notifier = notifier->next )
-+ if ( notifier->add )
-+ if ( (ret = notifier->add( card )) )
-+ break;
-+ }
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_notify_add );
-+
-+int mmc_notify_remove( mmc_card_t card )
-+{
-+ int ret = 0;
-+ mmc_notifier_t notifier;
-+
-+ __ENTER0();
-+ if ( card ) {
-+ for ( notifier = mmc_notifier; notifier;
-+ notifier = notifier->next )
-+ if ( notifier->remove )
-+ if ( (ret = notifier->remove( card )) )
-+ break;
-+ }
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_notify_remove );
-+
-+int mmc_update_card_stack( int host )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+
-+ __ENTER0();
-+
-+ if ( (host < 0) || (host >= MMC_CONTROLLERS_MAX) )
-+ goto error;
-+
-+ down_read( &mmc_controller_sem );
-+ if ( (ctrlr = mmc_controller[host]) ) {
-+ down_write( &ctrlr->update_sem );
-+ (void)__mmc_update_card_stack( ctrlr );
-+ up_write( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+ ret = 0;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_update_card_stack );
-+
-+ssize_t mmc_read( mmc_card_t card, mmc_transfer_mode_t mode, char *buf, size_t size, loff_t *paddr )
-+{
-+ ssize_t ret = -EIO;
-+ mmc_controller_t ctrlr;
-+ mmc_data_transfer_req_rec_t transfer;
-+
-+ if ( !paddr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( !card ) {
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%x",
-+ card, card->usage, mode, buf, size, *paddr );
-+
-+ ctrlr = card->ctrlr;
-+ if ( (ret = mmc_acquire_io( ctrlr, card )) )
-+ goto error;
-+
-+ memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
-+ transfer.cmd = MMC_READ;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER; /* FIXME: buffer cache */
-+ transfer.buf = buf;
-+ transfer.addr = *paddr;
-+ transfer.cnt = size;
-+
-+/* max block size defined by CSD[read_bl_len] */
-+ transfer.blksz = card->info.read_bl_len;
-+ transfer.nob = size / transfer.blksz;
-+ if ( (size - (transfer.nob * transfer.blksz)) > 0 )
-+ transfer.nob++;
-+
-+/* TODO: controller may restrict maximum block size; set block size
-+ * and number of blocks that their accumulated length fit to
-+ * CSD[READ_BL_LEN] not to bother with block misalignment in multiple
-+ * block transfers */
-+ ctrlr = card->ctrlr;
-+ if ( transfer.blksz > ctrlr->tmpl->block_size_max ) {
-+ ret = -EINVAL; /* FIXME */
-+ goto error;
-+ }
-+
-+ if ( ctrlr->stack.selected != card ) {
-+ if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
-+ goto err_mmc;
-+ ctrlr->stack.selected = card;
-+ }
-+
-+ switch( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM:
-+ if ( !ctrlr->tmpl->stream_read ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+/* TODO: The max clock frequency for stream read operation is given by
-+ the following formula:
-+ max speed = min ( TRAN_SPEED, 8*2^(READ_BL_LEN) - NSAC/TAAC )
-+
-+ If the card is not able to sustain data transfer it will set the
-+ UNDERRUN error bit in the status register, abort the transmission
-+ and wait in the Data state for a stop command
-+ */
-+ ret = ctrlr->tmpl->stream_read( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ if ( !ctrlr->tmpl->read_block ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+/* TODO: buffer size and data alignment (v3.4, p.29):
-+ if CSD[READ_BL_PARTIAL] is set, smaller blocks whose starting
-+ and ending address are entirely contained within one physical
-+ block (as defined by CSD[READ_BL_LEN]) may also be transmitted
-+ */
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->read_block( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ if ( !ctrlr->tmpl->read_mblock ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+
-+ if ( transfer.nob > ctrlr->tmpl->nob_max ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+/* TODO: buffer size and data alignment (v3.4, p.29):
-+ if the host uses patrial blocks whose accumulated length is
-+ not block aligned and block misalignment is not allowed, the
-+ card should detect a block misalignment error condition at the
-+ beginning of the first misaligned block
-+ */
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->read_mblock( card->ctrlr, &transfer );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
-+ ret = -EINVAL;
-+ }
-+err_mmc:
-+ ret = __mmc_check_error( card, ret );
-+ if ( ret >= 0 ) {
-+ ret = size - transfer.cnt;
-+ *paddr += ret;
-+ }
-+err_down:
-+ mmc_release_io( ctrlr, card );
-+error:
-+ __LEAVE("ret=%d", ret);
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_read );
-+
-+ssize_t mmc_write( mmc_card_t card, mmc_transfer_mode_t mode, const char *buf, size_t size, loff_t *paddr )
-+{
-+ ssize_t ret = -ESPIPE;
-+ mmc_controller_t ctrlr;
-+ mmc_data_transfer_req_rec_t transfer;
-+
-+ if ( !paddr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( !card ) {
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%llx",
-+ card, card->usage, mode, buf, size, *paddr );
-+
-+ ctrlr = card->ctrlr;
-+ if ( (ret = mmc_acquire_io( ctrlr, card )) )
-+ goto error;
-+
-+ memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
-+ transfer.cmd = MMC_WRITE;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER; /* FIXME: buffer cache */
-+ transfer.buf = (char *)buf;
-+ transfer.addr = *paddr;
-+ transfer.cnt = size;
-+
-+/* max block size defined by CSD[write_bl_len] */
-+ transfer.blksz = card->info.write_bl_len;
-+ transfer.nob = size / transfer.blksz;
-+ if ( (size - (transfer.nob * transfer.blksz)) > 0 )
-+ transfer.nob++;
-+
-+/* TODO: controller may restrict maximum block size; set block size
-+ * and number of blocks that their accumulated length fit to
-+ * CSD[WRITE_BL_LEN] not to bother with block misalignment in multiple
-+ * block transfers */
-+ ctrlr = card->ctrlr;
-+ if ( transfer.blksz > ctrlr->tmpl->block_size_max ) {
-+ ret = -EINVAL; /* FIXME */
-+ goto error;
-+ }
-+
-+ if ( ctrlr->stack.selected != card ) {
-+ if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
-+ goto err_mmc;
-+ ctrlr->stack.selected = card;
-+ }
-+
-+ transfer.cmd = MMC_WRITE;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER;
-+ switch( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM:
-+ if ( !ctrlr->tmpl->stream_write ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ ret = ctrlr->tmpl->stream_write( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ if ( !ctrlr->tmpl->write_block ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->write_block( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ if ( !ctrlr->tmpl->write_mblock ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->write_mblock( card->ctrlr, &transfer );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
-+ }
-+
-+err_mmc:
-+ ret = __mmc_check_error( card, ret ); /* FIXME */
-+ if ( ret >= 0 ) {
-+ ret = size - transfer.cnt;
-+ *paddr += ret;
-+ }
-+err_down:
-+ mmc_release_io( ctrlr, card );
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_write );
-+
-+int mmc_ioctl( mmc_card_t card, unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+
-+ if ( !card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" )
-+ goto error;
-+ }
-+
-+ ctrlr = card->ctrlr;
-+ if ( mmc_acquire_io( ctrlr, card ) ) {
-+ ret = -ENXIO;
-+ goto error;
-+ }
-+
-+ switch ( cmd ) {
-+ case IOCMMCGCARDESC:
-+ if ( copy_to_user( (void *)arg, &card->info, sizeof( mmc_card_info_rec_t ) ) )
-+ ret = -EFAULT;
-+ break;
-+/*
-+ * 1. TODO: erase region
-+ * 2. TODO: set/unset write protection, lock/password
-+ */
-+ default:
-+ ret = -ENOIOCTLCMD;
-+ }
-+
-+ mmc_release_io( ctrlr, card );
-+error:
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_ioctl );
-+
-+/*
-+ * registry stuff
-+ */
-+mmc_card_t mmc_get_card( int host, int slot )
-+{
-+ mmc_card_t ret = NULL;
-+ mmc_controller_t ctrlr = NULL;
-+ int found;
-+
-+ __ENTER( "host=%d, card=%d", host, slot );
-+
-+ if ( ((host < 0) || (host >= MMC_CONTROLLERS_MAX))
-+ && ((slot < 0) || (slot >= MMC_CARDS_MAX)) )
-+ goto error;
-+
-+ down_read( &mmc_controller_sem );
-+
-+ if ( (ctrlr = mmc_controller[host]) ) {
-+ down_write( &ctrlr->update_sem );
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ ret = ctrlr->stack.first;
-+ found = FALSE;
-+ while ( ret ) {
-+ if ( (ret->slot == slot) && (ret->state !=
-+ MMC_CARD_STATE_UNPLUGGED) ) {
-+ found = TRUE;
-+ break;
-+ }
-+ ret = ret->next;
-+ }
-+
-+ if ( found ) {
-+ if ( ctrlr->tmpl->owner ) {
-+ ++ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count increased (%d)\n",
-+ ctrlr->tmpl->name, ctrlr->usage );
-+ __MOD_INC_USE_COUNT( ctrlr->tmpl->owner );
-+ }
-+ ++ret->usage;
-+ } else
-+ ret = NULL;
-+ }
-+ up_write( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+error:
-+ __LEAVE("ret=0x%p usage=%d", ret, ret ? ret->usage : -1 );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_get_card );
-+
-+void mmc_put_card( mmc_card_t card )
-+{
-+ mmc_card_t tmp = NULL;
-+ mmc_controller_t ctrlr;
-+ int found;
-+
-+ __ENTER( "card=0x%p", card );
-+
-+ if ( !card )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+
-+ down_read( &mmc_controller_sem );
-+ if ( !ctrlr || (ctrlr != mmc_controller[ctrlr->slot]) ) {
-+ MMC_ERROR( "bad controller reference: ctrlr=0x%p\n", ctrlr );
-+ goto err_down;
-+ }
-+
-+ down_write( &ctrlr->update_sem );
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ tmp = ctrlr->stack.first;
-+ found = FALSE;
-+ while ( tmp ) {
-+ if ( tmp == card ) {
-+ found = TRUE;
-+ break;
-+ }
-+ tmp = tmp->next;
-+ }
-+
-+ if ( found ) {
-+ if ( tmp->usage > 0 ) {
-+ --tmp->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "usage=%d"
-+ "owner=0x%p\n", tmp->usage,
-+ ctrlr->tmpl->owner );
-+ if ( !tmp->usage && (ctrlr->usage > 0)
-+ && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count "
-+ "decreased (%d)\n",
-+ ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT(
-+ ctrlr->tmpl->owner );
-+ }
-+ }
-+ } else
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" );
-+
-+ }
-+ up_write( &ctrlr->update_sem );
-+err_down:
-+ up_read( &mmc_controller_sem );
-+error:
-+ __LEAVE( "found=%d", found );
-+ return;
-+}
-+EXPORT_SYMBOL( mmc_put_card );
-+
-+static inline void *mmc_register_user( mmc_notifier_t notifier )
-+{
-+ mmc_notifier_t ret = NULL, last = mmc_notifier;
-+
-+ MOD_INC_USE_COUNT;
-+ if ( notifier ) {
-+ down_write( &mmc_notifier_sem );
-+
-+ notifier->next = NULL;
-+ if ( !last ) {
-+ mmc_notifier = notifier;
-+ ret = notifier;
-+ } else {
-+ while ( last->next ) {
-+ if ( last == notifier ) {
-+ MOD_DEC_USE_COUNT;
-+ break;
-+ }
-+ last = last->next;
-+ }
-+ if ( last != notifier ) {
-+ last->next = notifier;
-+ ret = notifier;
-+ }
-+ }
-+ up_write( &mmc_notifier_sem );
-+ }
-+/* notify new user about the cards present in the system */
-+ if ( ret && ret->add ) {
-+ int i;
-+
-+ down_read( &mmc_controller_sem );
-+ for ( i = 0; i < mmc_ncontrollers; i++ ) {
-+ mmc_controller_t ctrlr = mmc_controller[i];
-+
-+ down_read( &ctrlr->update_sem ); /* FIXME */
-+ __mmc_card_stack_foreach( &ctrlr->stack,
-+ ret->add, FALSE );
-+ up_read( &ctrlr->update_sem ); /* FIXME */
-+ }
-+ up_read( &mmc_controller_sem );
-+ }
-+/* error: */
-+ __LEAVE( "mmc_notifier=0x%p, mmc_notifier->next=0x%p",
-+ mmc_notifier, mmc_notifier ? mmc_notifier->next : NULL );
-+ return ret;
-+}
-+
-+static inline mmc_controller_t mmc_register_controller( mmc_controller_tmpl_t tmpl, size_t extra )
-+{
-+ mmc_controller_t ret = NULL;
-+ int found;
-+ int i;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ down_write( &mmc_controller_sem );
-+
-+ if ( mmc_ncontrollers >= MMC_CONTROLLERS_MAX ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're too many controllers\n" );
-+ goto error;
-+ }
-+
-+ found = FALSE;
-+ for ( i = 0; i < MMC_CONTROLLERS_MAX; i++ )
-+ if ( !mmc_controller[i] ) {
-+ found = TRUE;
-+ break;
-+ }
-+
-+ if ( !found ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're no empty slots\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->init ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->probe ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'probe()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->init_card_stack ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init_card_stack()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->update_acq ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'update_acq()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->check_card_stack ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'check_card_stack()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->setup_card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'setup_card()'\n" );
-+ goto error;
-+ }
-+
-+ ret = kmalloc( sizeof( mmc_controller_rec_t ) + extra, GFP_ATOMIC ); /* FIXME: ISA + GFP_DMA */
-+ if ( !ret ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "out of memory\n" );
-+ goto error;
-+ }
-+
-+ memset( ret, 0, sizeof( mmc_controller_rec_t ) + extra );
-+
-+ if ( (tmpl->probe( ret ) != 1) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller probe failed\n" );
-+ goto err_free;
-+ }
-+
-+ if ( tmpl->init( ret ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller initialization failure\n" );
-+ goto err_free;
-+ }
-+
-+ ret->state = MMC_CONTROLLER_FOUND;
-+ ret->slot = i;
-+ ret->tmpl = tmpl;
-+ init_MUTEX( &ret->io_sem );
-+ init_rwsem( &ret->update_sem );
-+#ifdef CONFIG_PROC_FS
-+ if ( mmc_proc_dir ) {
-+ snprintf( ret->proc_name, sizeof( ret->proc_name ),
-+ "host%d", ret->slot );
-+ ret->proc = proc_mkdir( ret->proc_name, mmc_proc_dir );
-+ }
-+#endif
-+
-+/* initialize card stack */
-+ if ( ret->tmpl->init_card_stack( ret ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "card stack initialization failure\n" );
-+ if ( ret->tmpl->remove )
-+ ret->tmpl->remove( ret ); /* FIXME */
-+ goto err_free;
-+ }
-+
-+ mmc_controller[ret->slot] = ret;
-+ ++mmc_ncontrollers;
-+
-+/* notify users */
-+ if ( ret->stack.ncards > 0 ) {
-+ down_read( &mmc_notifier_sem );
-+ if ( (i = __mmc_card_stack_foreach( &ret->stack, mmc_notify_add, FALSE ) ) < 0 )
-+ MMC_ERROR( "device add notification failed at slot %d\n", -i );
-+ up_read( &mmc_notifier_sem );
-+ }
-+ goto out;
-+
-+err_free:
-+#ifdef CONFIG_PROC_FS
-+ if ( ret->proc )
-+ remove_proc_entry( ret->proc_name, mmc_proc_dir );
-+#endif
-+ kfree( ret );
-+error:
-+ ret = NULL;
-+ MOD_DEC_USE_COUNT;
-+out:
-+ up_write( &mmc_controller_sem );
-+ return ret;
-+}
-+
-+static inline mmc_card_t mmc_register_card( mmc_card_t card )
-+{
-+ mmc_card_t ret = NULL;
-+ mmc_controller_t ctrlr;
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+#ifdef CONFIG_PROC_FS
-+ if ( ctrlr->proc ) {
-+ snprintf( card->proc_name, sizeof( card->proc_name ),
-+ "card%d", card->slot );
-+ card->proc = create_proc_read_entry( card->proc_name,
-+ 0444, ctrlr->proc,
-+ mmc_proc_read_card_info, card );
-+ }
-+#endif
-+ mmc_notify_add( card );
-+error:
-+ return ret;
-+}
-+
-+void *mmc_register( mmc_reg_type_t reg_type, void *tmpl, size_t extra )
-+{
-+ void *ret = NULL;
-+
-+ switch ( reg_type ) {
-+ case MMC_REG_TYPE_CARD:
-+ ret = mmc_register_card( (mmc_card_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_USER:
-+ ret = mmc_register_user( (mmc_notifier_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_HOST:
-+ ret = mmc_register_controller( (mmc_controller_tmpl_t)tmpl, extra );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "register request for unknown type\n" );
-+ }
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_register );
-+
-+static inline void mmc_unregister_user( mmc_notifier_t notifier )
-+{
-+ mmc_notifier_t prev = mmc_notifier;
-+ int found = FALSE;
-+
-+ if ( notifier ) {
-+ down_write( &mmc_notifier_sem );
-+
-+ if ( mmc_notifier == notifier) {
-+ mmc_notifier = prev->next;
-+ found = TRUE;
-+
-+ } else if ( mmc_notifier ) {
-+ while( prev ) {
-+ if ( prev->next == notifier ) {
-+ found = TRUE;
-+ prev->next = prev->next->next;
-+ break;
-+ }
-+ prev = prev->next;
-+ }
-+ }
-+
-+ if ( found ) {
-+ if ( notifier->remove ) {
-+ int i;
-+
-+ down_read( &mmc_controller_sem );
-+ for ( i = 0; i < mmc_ncontrollers; i++ ) {
-+ mmc_controller_t ctrlr =
-+ mmc_controller[i];
-+
-+ down_read( &ctrlr->update_sem );
-+ __mmc_card_stack_foreach( &ctrlr->stack, notifier->remove, FALSE );
-+ up_read( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+ }
-+ }
-+
-+ up_write( &mmc_notifier_sem );
-+ }
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static inline void mmc_unregister_controller( mmc_controller_t ctrlr )
-+{
-+ if ( !ctrlr || (mmc_controller[ctrlr->slot] != ctrlr ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad unregister request\n" );
-+ goto error;
-+ }
-+
-+ down_write( &mmc_controller_sem );
-+
-+/* notify users */
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ int slot;
-+
-+ down_read( &mmc_notifier_sem );
-+ if ( (slot = __mmc_card_stack_foreach( &ctrlr->stack, mmc_notify_remove, FALSE ) ) )
-+ MMC_ERROR( "device remove notification failed at slot %d\n", -slot );
-+ up_read( &mmc_notifier_sem );
-+ }
-+
-+#ifdef CONFIG_PROC_FS
-+ if ( ctrlr->proc )
-+ remove_proc_entry( ctrlr->proc_name, mmc_proc_dir );
-+#endif
-+
-+ if ( ctrlr->tmpl && ctrlr->tmpl->remove )
-+ ctrlr->tmpl->remove( ctrlr );
-+
-+ mmc_controller[ctrlr->slot] = NULL;
-+ --mmc_ncontrollers;
-+
-+ __mmc_free_controller( ctrlr );
-+
-+ up_write( &mmc_controller_sem );
-+ MOD_DEC_USE_COUNT;
-+error:
-+ return;
-+}
-+
-+void mmc_unregister( mmc_reg_type_t reg_type, void *tmpl )
-+{
-+ switch ( reg_type ) {
-+ case MMC_REG_TYPE_USER:
-+ mmc_unregister_user( (mmc_notifier_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_HOST:
-+ mmc_unregister_controller( (mmc_controller_t)tmpl );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "unregister request for unknown type\n" );
-+ }
-+}
-+EXPORT_SYMBOL( mmc_unregister );
-+
-+#ifdef CONFIG_PM
-+/* power management support */
-+static int mmc_pm_callback( struct pm_dev *pmdev, pm_request_t pmreq, void *pmdata )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+ int i;
-+
-+ __ENTER( "pmreq=%d", pmreq );
-+
-+ down_read( &mmc_controller_sem );
-+
-+ switch ( pmreq ) {
-+ case PM_SUSPEND:
-+ for ( ret = 0, i = 0; !ret && (i < mmc_ncontrollers); i++ ) {
-+ ctrlr = mmc_controller[i];
-+ if ( ctrlr->tmpl->suspend )
-+ ret = ctrlr->tmpl->suspend( ctrlr );
-+ }
-+ if ( !ret )
-+ break;
-+
-+ case PM_RESUME:
-+ for ( i = mmc_ncontrollers - 1; i >= 0; i-- ) {
-+ ctrlr = mmc_controller[i];
-+ if ( ctrlr->tmpl->resume )
-+ ctrlr->tmpl->resume( ctrlr );
-+ }
-+ ret = 0;
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "unsupported PM request %d\n",
-+ pmreq );
-+ }
-+
-+ up_read( &mmc_controller_sem );
-+/* error: */
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+#endif
-+
-+/* kernel module stuff */
-+static int __init mmc_core_module_init( void )
-+{
-+ int ret = -ENODEV;
-+
-+ memset( &mmc_controller, 0, sizeof( mmc_controller ) );
-+
-+ init_rwsem( &mmc_controller_sem );
-+ init_rwsem( &mmc_notifier_sem );
-+#ifdef CONFIG_PM
-+ if ( !(mmc_pm_dev = pm_register( PM_UNKNOWN_DEV, 0, mmc_pm_callback )) ) MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register PM callback\n" );
-+#endif
-+#ifdef CONFIG_PROC_FS
-+ mmc_proc_dir = proc_mkdir( "mmc", NULL );
-+#endif
-+ ret = 0;
-+/* error: */
-+ return ret;
-+}
-+
-+static void __exit mmc_core_module_cleanup( void )
-+{
-+#ifdef CONFIG_PROC_FS
-+ if ( mmc_proc_dir )
-+ remove_proc_entry( "mmc", NULL );
-+#endif
-+#ifdef CONFIG_PM
-+ pm_unregister( mmc_pm_dev );
-+#endif
-+}
-+
-+module_init( mmc_core_module_init );
-+module_exit( mmc_core_module_cleanup );
-+
-+MODULE_LICENSE( "GPL" );
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc_pxa.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,1902 @@
-+/*
-+ * linux/drivers/mmc/mmc_pxa.c
-+ * driver for Cotulla MMC controller
-+ *
-+ * Authors: Vladimir Shebordaev, Igor Oblakov
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_pxa.c,v 0.3.1.12 2002/09/25 19:25:48 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/dma.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+#include "mmc_pxa.h"
-+
-+static mmc_controller_t host = NULL;
-+
-+/* service routines */
-+static inline int pxa_mmc_check_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( hostdata->state != state ) {
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "state (%s vs %s)\n", PXA_MMC_STATE_LABEL( hostdata->state ), PXA_MMC_STATE_LABEL( state ) );
-+ goto error;
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline void pxa_mmc_set_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ hostdata->state = state;
-+}
-+
-+static inline int pxa_mmc_init_completion( mmc_controller_t ctrlr, u32 mask )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( xchg( &hostdata->busy, 1 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "another interrupt "
-+ "is already been expected\n" );
-+ goto error;
-+ }
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ hostdata->irqcnt = 1000;
-+#endif
-+ init_completion( &hostdata->completion );
-+
-+ MMC_I_MASK = MMC_I_MASK_ALL & ~mask;
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+static struct timer_list timer;
-+static void wait_timeo( unsigned long arg ) {
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)arg;
-+ hostdata->timeo = 1;
-+ complete( &hostdata->completion );
-+ return;
-+}
-+#endif
-+
-+static inline int pxa_mmc_wait_for_completion( mmc_controller_t ctrlr, u32 mask )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( !xchg( &hostdata->busy, 1 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "there were no "
-+ "interrupt awaited for\n" );
-+ goto error;
-+ }
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ hostdata->timeo = 0;
-+ del_timer( &timer );
-+ timer.function = wait_timeo;
-+ timer.expires = jiffies + 1UL*HZ;
-+ timer.data = (unsigned long)hostdata;
-+ add_timer( &timer );
-+#endif
-+ wait_for_completion( &hostdata->completion );
-+#if CONFIG_MMC_DEBUG_IRQ
-+ del_timer( &timer );
-+ if ( hostdata->timeo ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "irq timed out: " "mask=%x stat=%x\n", mask, MMC_STAT );
-+ goto error;
-+ }
-+#endif
-+ /* verify interrupt */
-+ if ( (mask == ~0UL) || !( hostdata->mmc_i_reg & ~mask ) )
-+ ret = 0;
-+
-+error:
-+ xchg( &hostdata->busy, 0 );
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_stop_bus_clock( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+
-+ if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_CLK_OFF ) )
-+ goto out;
-+
-+ if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "BUFFER_IN_TRANSIT\n" );
-+ goto error;
-+ }
-+
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_CLK_IS_OFF ) )
-+ goto error;
-+
-+ MMC_STRPCL = MMC_STRPCL_STOP_CLK;
-+
-+ if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_CLK_IS_OFF ) )
-+ goto error;
-+
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is off\n" );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_CLK_OFF );
-+out:
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_start_bus_clock( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
-+ && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ MMC_STRPCL = MMC_STRPCL_START_CLK;
-+ wmb();
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is on\n" );
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/*
-+int pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t response )
-+
-+Effects: initializes completion to wait for END_CMD_RES intr,
-+ waits for intr to occur, checks controller and card status
-+Requiers: controller is in CLK_OFF state
-+Modifies: moves controller to the END_CMD state
-+Returns:
-+*/
-+static mmc_error_t pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t format, int send_abort )
-+{
-+ mmc_error_t ret = MMC_ERROR_GENERIC;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ int mask, nwords;
-+ u32 status;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD%d(0x%04x%04x)\n", MMC_CMD & 0x3f, MMC_ARGH, MMC_ARGL);
-+
-+/* FIXME: check arguments */
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
-+ && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ mask = MMC_I_MASK_END_CMD_RES;
-+ if ( pxa_mmc_init_completion( ctrlr, mask ) )
-+ goto error;
-+
-+ MMC_PRTBUF = MMC_PRTBUF_BUF_FULL;
-+/* start the clock */
-+ if ( pxa_mmc_start_bus_clock( ctrlr ) )
-+ goto error;
-+
-+/* wait for END_CMD_RES intr */
-+ if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_END_CMD_RES ) )
-+ goto error;
-+
-+/* check status */
-+ if ( hostdata->mmc_stat & MMC_STAT_TIME_OUT_RESPONSE ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response timeout\n");
-+ ret = MMC_ERROR_TIME_OUT_RESPONSE;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_READ_TIME_OUT ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read timeout\n");
-+ ret = MMC_ERROR_READ_TIME_OUT;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_RES_CRC_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response crc err\n");
-+ ret = MMC_ERROR_RES_CRC_ERROR;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_CRC_READ_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read crc err\n");
-+ ret = MMC_ERROR_CRC_READ_ERROR;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_CRC_WRITE_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "write crc err\n");
-+ ret = MMC_ERROR_CRC_WRITE_ERROR;
-+ goto error;
-+ }
-+
-+ nwords = (format == MMC_NORESPONSE) ? 0 :
-+ (format == MMC_R1) ? 3 :
-+ (format == MMC_R2) ? 8 :
-+ (format == MMC_R3) ? 3 :
-+ -1;
-+ ret = nwords;
-+ if ( nwords > 0 ) {
-+ register int i;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "nwords=%d\n", nwords );
-+ for ( i = nwords - 1; i >= 0 ; i-- ) {
-+ u32 res = MMC_RES;
-+ int ibase = i<<1;
-+
-+ hostdata->mmc_res[ibase] = ((u8 *)&res)[0];
-+ hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1];
-+ --ret;
-+ }
-+#ifdef CONFIG_MMC_DEBUG
-+ switch ( format ) {
-+ case MMC_R1:
-+ MMC_DUMP_R1( ctrlr );
-+ break;
-+ case MMC_R2:
-+ MMC_DUMP_R2( ctrlr );
-+ break;
-+ case MMC_R3:
-+ MMC_DUMP_R3( ctrlr );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "unknown response format\n" );
-+ ret = MMC_ERROR_GENERIC;
-+ goto error;
-+ }
-+#endif
-+
-+/* check card status for R1(b) commands */
-+ if ( format == MMC_R1 ) {
-+ u8 cmd;
-+
-+ ((u8 *)&status)[0] = hostdata->mmc_res[1];
-+ ((u8 *)&status)[1] = hostdata->mmc_res[2];
-+ ((u8 *)&status)[2] = hostdata->mmc_res[3];
-+ ((u8 *)&status)[3] = hostdata->mmc_res[4];
-+ cmd = PXA_MMC_RESPONSE( ctrlr, 5 )&0x3f;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ //printk( KERN_INFO __FUNCTION__"(): "
-+ "cmd=%u status: 0x%08x\n",
-+ cmd, status );
-+ switch ( cmd ) {
-+ case 11:
-+ case 18:
-+ case 20:
-+ case 25:
-+ if ( !(status & 0x00000100) ) /* FIXME */
-+ goto mmc_error;
-+ default:
-+ break;
-+ }
-+ if ( status & MMC_CARD_STATUS_OUT_OF_RANGE ) {
-+ ret = MMC_ERROR_OUT_OF_RANGE;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ADDRESS_ERROR ) {
-+ ret = MMC_ERROR_ADDRESS_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_BLOCK_LEN_ERROR ) {
-+ ret = MMC_ERROR_ADDRESS_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_SEQ_ERROR ) {
-+ ret = MMC_ERROR_ERASE_SEQ_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_PARAM ) {
-+ ret = MMC_ERROR_ERASE_PARAM;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_WP_VIOLATION ) {
-+ ret = MMC_ERROR_WP_VIOLATION;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CARD_IS_LOCKED ) {
-+ ret = MMC_ERROR_CARD_IS_LOCKED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_LOCK_UNLOCK_FAILED ) {
-+ ret = MMC_ERROR_LOCK_UNLOCK_FAILED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_COM_CRC_ERROR ) {
-+ ret = MMC_ERROR_COM_CRC_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ILLEGAL_COMMAND ) {
-+ ret = MMC_ERROR_ILLEGAL_COMMAND;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CARD_ECC_FAILED ) {
-+ ret = MMC_ERROR_CARD_ECC_FAILED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CC_ERROR ) {
-+ ret = MMC_ERROR_CC_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERROR ) {
-+ ret = MMC_ERROR_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_UNDERRUN ) {
-+ ret = MMC_ERROR_UNDERRUN;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_OVERRUN ) {
-+ ret = MMC_ERROR_OVERRUN;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CID_CSD_OVERWRITE ) {
-+ ret = MMC_ERROR_CID_CSD_OVERWRITE;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_RESET ) {
-+ ret = MMC_ERROR_ERASE_RESET;
-+ goto mmc_error;
-+ }
-+ }
-+ }
-+
-+ if ( ret >= 0 )
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_CMD );
-+ goto out;
-+mmc_error:
-+#if 1
-+ if ( send_abort ) {
-+ /* send CMD12 to abort failed transfer */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ ret = -EIO;
-+ goto error;
-+ }
-+#endif
-+error:
-+ /* move controller to the IDLE state */
-+ pxa_mmc_stop_bus_clock( ctrlr );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+out:
-+ return ret;
-+}
-+
-+/*
-+int pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t cmd, mmc_dir_t dir, mmc_transfer_mode_t mode )
-+
-+Effects: finilizes data transfer request
-+Reqires: controller is in the END_BUFFER state
-+Modifies: moves controller to the IDLE state
-+Returns: zero upon success or error condition code otherwise
-+ */
-+static mmc_error_t pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t dir, mmc_transfer_mode_t mode )
-+{
-+ int ret = MMC_ERROR_GENERIC;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_IO ) )
-+ goto error;
-+
-+ switch ( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM: /* FIXME */
-+ if ( dir == MMC_WRITE ) {
-+ /* 1. wait for STOP_CMD intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_STOP_CMD )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_STOP_CMD )) )
-+ goto error;
-+ }
-+ /* 2. send CMD12 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+ if ( dir == MMC_WRITE )
-+ MMC_CMDAT |= MMC_CMDAT_BUSY;
-+
-+ /* 3. wait for CMD12 to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "ready for CMD12\n" );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ /* 4. wait for DATA_TRAN_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 5. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ /* 1. wait for DATA_TRAN done intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ /* 2. send CMD12 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+ if ( dir == MMC_WRITE )
-+ MMC_CMDAT |= MMC_CMDAT_BUSY;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD12\n" );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 3. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ /* 1. wait for DATA_TRAN_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 2. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown transfer mode\n" );
-+ goto error;
-+ }
-+/* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_update_acq( mmc_controller_t ctrlr )
-+{
-+ int ret = -EINVAL;
-+ pxa_mmc_hostdata_t hostdata = NULL;
-+ mmc_card_t card = NULL;
-+ mmc_card_stack_rec_t fake;
-+ mmc_card_stack_t stack = &fake;
-+ u16 argl = 0U, argh = 0U;
-+ int ncards = 0;
-+
-+ if ( !ctrlr )
-+ goto error;
-+
-+ hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ __mmc_card_stack_init( stack );
-+
-+ /* max open-drain mode frequency is 400kHZ */
-+ MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
-+ MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
-+
-+ /* discover and add cards to the stack */
-+ /* I. bus operation condition setup */
-+ /* 1) send CMD1 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ argl = 0x0000;
-+ argh = 0x0004;
-+
-+ MMC_CMD = CMD(1);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+
-+ MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
-+ if ( !ret ) {
-+ argh = (PXA_MMC_RESPONSE( ctrlr, 4 ) << 8)
-+ | PXA_MMC_RESPONSE( ctrlr, 3 );
-+ argl = (PXA_MMC_RESPONSE( ctrlr, 2 ) << 8)
-+ | PXA_MMC_RESPONSE( ctrlr, 1 );
-+
-+ } else if ( ret != MMC_ERROR_TIME_OUT_RESPONSE )
-+ goto err_free;
-+
-+ if ( !argh && !argl ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "assuming full voltage range support\n" );
-+ argh = 0x00ff;
-+ argl = 0xff00;
-+ }
-+
-+ /* 2) continuously send CMD1 'till there're busy cards */
-+ for(;;) {
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(1);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+
-+ MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
-+ if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
-+ break;
-+
-+ else if ( !ret ) {
-+ /* busy state reported by LOW signal level
-+ * (MMC v3.2, p.58)
-+ *
-+ * Thanks to Alexander Samoutin :)
-+ */
-+ if ( !(PXA_MMC_RESPONSE( ctrlr, 4 ) & 0x80) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "busy state reported\n");
-+ udelay( 20 );
-+ continue;
-+ } else
-+ break;
-+ } else
-+ goto err_free;
-+ }
-+
-+/* II. card identification: the cards in Ready state
-+ * are the only expected to respond
-+ */
-+ for (;;) {
-+ argh = 0U;
-+ argl = 0U;
-+
-+ /* 1) send CMD2 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(2);
-+ MMC_ARGH = 0x0003;
-+ MMC_ARGL = 0xf300;
-+ MMC_CMDAT = MMC_CMDAT_R2;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD2(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE );
-+ if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
-+ break;
-+
-+ else if ( ret ) /* bus error */
-+ goto err_free;
-+
-+ /* TODO: store CID for the card */
-+
-+ /* 2) assign RCA */
-+ if ( !++ctrlr->rca_next ) /* overflow */
-+ ++ctrlr->rca_next;
-+ argh = ctrlr->rca_next;
-+
-+ /* 3) send it to the card last responded (CMD3) */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(3);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD3(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
-+ if ( ret ) /* CMD3 failed */
-+ goto err_free;
-+
-+ card = __mmc_card_alloc( sizeof( pxa_mmc_card_data_rec_t ) );
-+ if ( !card ) {
-+ MMC_ERROR( "out of memory\n" );
-+ goto err_free;
-+ }
-+
-+ card->info.rca = argh;
-+ card->slot = ctrlr->slot_next++; /* FIXME: minor encoding */
-+ card->ctrlr = ctrlr;
-+
-+ if ( !__mmc_card_stack_add( stack, card ) )
-+ goto err_free;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "added card: "
-+ "slot %d, RCA=0x%04x\n", card->slot, argh );
-+ ++ncards;
-+ }
-+
-+ if ( ncards ) {
-+/* III. read CSD registers of all cards; DSR support also reported there */
-+ for ( card = stack->first; card; card = card->next ) {
-+ pxa_mmc_card_data_t card_data =
-+ (pxa_mmc_card_data_t)card->card_data;
-+
-+ /* 1) send CMD9 */
-+ argh = card->info.rca;
-+ argl = 0U;
-+
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(9);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R2;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "CMD9(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE )) )
-+ goto err_free;
-+
-+ memcpy( &card->info.csd, hostdata->mmc_res, 15 );
-+ MMC_DUMP_CSD( card );
-+
-+ card->info.read_bl_len = (1<<card->info.csd.read_bl_len);
-+ card->info.write_bl_len = (1<<card->info.csd.write_bl_len);
-+ card->info.capacity = (card->info.csd.c_size + 1)
-+ * (1<<(card->info.csd.c_size_mult + 2))
-+ * card->info.read_bl_len;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "card capacity=%dMb\n",
-+ card->info.capacity>>20 );
-+ card->info.tran_speed = 20*1024; /* FIXME */
-+ card->info.transfer_mode = MMC_TRANSFER_MODE_BLOCK_SINGLE;
-+ /* 2) set bus operation freq */
-+ card_data->clkrt = pxa_mmc_clkrt( card->info.tran_speed );
-+ /* 3) register card with MMC core */
-+ mmc_register( MMC_REG_TYPE_CARD, card, 0 );
-+ }
-+/* IV. set DSR registers of the cards */
-+#if 0 /* TODO */
-+ if ( card->info.csd.dsr_imp ) {
-+ set_dsr = TRUE;
-+ /* calculate DSR */
-+ }
-+#endif
-+ }
-+#if 0 /* TODO */
-+ if ( set_dsr ) {
-+ /* send CMD4 */
-+ }
-+#endif
-+/* merge list of the newly inserted cards into controller card stack */
-+ if ( !ctrlr->stack.ncards ) {
-+ ctrlr->stack.first = stack->first;
-+ ctrlr->stack.last = stack->last;
-+ } else
-+ ctrlr->stack.last->next = stack->first;
-+
-+ ctrlr->stack.ncards += stack->ncards;
-+
-+ ret = 0;
-+ goto out;
-+err_free:
-+ __mmc_card_stack_free( stack );
-+error:
-+out:
-+ return ret;
-+}
-+
-+/* MMC protocol macros: v3.4, p.120 */
-+static int pxa_mmc_init_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -EIO;
-+ u16 argl = 0U, argh = 0U;
-+
-+ if ( !ctrlr || ctrlr->stack.ncards ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ /* initialize stack */
-+ /* 1) send CMD0 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ /* max open-drain mode frequency is 400kHZ */
-+ MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
-+ MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
-+ MMC_SPI = MMC_SPI_DISABLE;
-+
-+ MMC_CMD = CMD(0); /* CMD0 with zero argument */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_INIT;
-+
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, FALSE )) )
-+ goto error;
-+
-+ /* update card stack */
-+ if ( (ret = pxa_mmc_update_acq( ctrlr )) )
-+ goto err_free;
-+
-+ /* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "ncards=%d\n", ctrlr->stack.ncards );
-+ goto out;
-+
-+err_free:
-+ __mmc_card_stack_free( &ctrlr->stack );
-+error:
-+out:
-+ return ret;
-+}
-+
-+static int pxa_mmc_check_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ mmc_card_t card;
-+
-+ if ( !ctrlr )
-+ goto error;
-+
-+ if ( ctrlr->stack.ncards > 0 ) {
-+/* for each card in the stack: */
-+ for( card = ctrlr->stack.first; card; card = card->next ) {
-+ u16 argh = card->info.rca;
-+ u16 argl = 0UL;
-+
-+/* 1) send CMD9( card->rca ) */
-+ if ( pxa_mmc_stop_bus_clock( ctrlr ) )
-+ goto error;
-+
-+ /* SanDisk's cards do not respond to CMD9 */
-+ MMC_CMD = CMD(13);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD13(0x%04x%04x)\n",
-+ argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
-+/* 2) if card responded, it is still there */
-+ if ( ret )
-+ card->state = MMC_CARD_STATE_UNPLUGGED;
-+ }
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure links the bus master with a single card
-+ * 1) cross checks with the internal stack management data if a card still
-+ * exists in the slot
-+ * 2) send CMD7( card->public.rca )
-+ * 3) setup data path and controller options
-+ */
-+static int pxa_mmc_setup_card( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ int ret = -ENODEV;
-+ pxa_mmc_hostdata_t hostdata;
-+ pxa_mmc_card_data_t card_data;
-+ u16 argh = 0U;
-+#ifdef CONFIG_MMC_DEBUG
-+ u16 argl = 0U;
-+#endif
-+
-+ if ( !ctrlr || !card ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( card->ctrlr != ctrlr ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "card is on another bus\n" );
-+ goto error;
-+ }
-+
-+ hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ card_data = (pxa_mmc_card_data_t)card->card_data;
-+
-+ argh = card->info.rca;
-+
-+/* select requested card */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(7);
-+ MMC_ARGH = argh;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD7(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* set controller options */
-+#ifndef CONFIG_MMC_DEBUG
-+ MMC_CLKRT = card_data->clkrt;
-+#endif
-+/* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_iobuf_init( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+#ifdef PIO
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#endif
-+#ifndef PIO
-+/* TODO */
-+#else
-+ hostdata->iobuf.buf.pos = hostdata->iobuf.iodata;
-+ hostdata->iobuf.buf.cnt = cnt;
-+#endif
-+ return 0;
-+}
-+/* TODO: ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+effects: reads at most cnt bytes from the card to the controller I/O buffer;
-+ takes care of partial data transfers
-+requieres:
-+modifies: ctrlr->iobuf
-+returns: number of bytes actually transferred or negative error code if there were any errors
-+ */
-+ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int ndesc;
-+ int chan = hostdata->iobuf.buf.chan;
-+ pxa_dma_desc *desc;
-+#endif
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_END_CMD) && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
-+ goto error;
-+ }
-+
-+ if ( cnt > hostdata->iobuf.bufsz )
-+ cnt = hostdata->iobuf.bufsz;
-+
-+ if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
-+#ifndef PIO
-+ if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
-+ goto error;
-+
-+ if ( (desc = hostdata->iobuf.buf.last_read_desc) ) {
-+ desc->ddadr &= ~DDADR_STOP;
-+ desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
-+ desc->dcmd |= (1<<5);
-+ }
-+/* 1) setup descriptors for DMA transfer from the device */
-+ ndesc = (cnt>>5) - 1; /* FIXME: partial read */
-+ desc = &hostdata->iobuf.buf.read_desc[ndesc];
-+ hostdata->iobuf.buf.last_read_desc = desc;
-+ /* TODO: partial read */
-+ desc->ddadr |= DDADR_STOP;
-+ desc->dcmd |= DCMD_ENDIRQEN;
-+/* 2) start DMA channel */
-+ DDADR( chan ) = hostdata->iobuf.buf.read_desc_phys_addr;
-+ DCSR( chan ) |= DCSR_RUN;
-+#else
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_RXFIFO_RD_REQ ) )
-+ goto error;
-+#endif
-+
-+ if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
-+ goto error;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
-+ goto error;
-+
-+ if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+ssize_t pxa_mmc_write_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int ndesc;
-+ int chan = hostdata->iobuf.buf.chan;
-+ pxa_dma_desc *desc;
-+#endif
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_END_CMD)
-+ && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state (%s)\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ if ( cnt > hostdata->iobuf.bufsz )
-+ cnt = hostdata->iobuf.bufsz;
-+
-+ if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
-+#ifndef PIO
-+ if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
-+ goto error;
-+ if ( (desc = hostdata->iobuf.buf.last_write_desc) ) {
-+ desc->ddadr &= ~DDADR_STOP;
-+ desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
-+ desc->dcmd |= (1<<5);
-+ }
-+/* 1) setup descriptors for DMA transfer to the device */
-+ ndesc = (cnt>>5) - 1; /* FIXME: partial write */
-+ desc = &hostdata->iobuf.buf.write_desc[ndesc];
-+ /* TODO: partial write */
-+ hostdata->iobuf.buf.last_write_desc = desc;
-+ desc->ddadr |= DDADR_STOP;
-+ desc->dcmd |= DCMD_ENDIRQEN;
-+/* 2) start DMA channel */
-+ DDADR( chan ) = hostdata->iobuf.buf.write_desc_phys_addr;
-+ DCSR( chan ) |= DCSR_RUN;
-+#else
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_TXFIFO_WR_REQ ) )
-+ goto error;
-+#endif
-+ if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
-+ goto error;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
-+ goto error;
-+
-+ if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+/* TODO: ssize_t pxa_mmc_copy_from_buffer( ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+effects: copies at most cnt bytes from the controller I/O buffer to the user or kernel buffer
-+ pointed by buf
-+requiers:
-+modifies:
-+returns: number of bytes actually transferred or negative error code if there were any errors
-+ */
-+ssize_t pxa_mmc_copy_from_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+#ifndef PIO
-+/* TODO: check that DMA channel is not running */
-+#endif
-+ switch ( to ) {
-+ case MMC_USER:
-+ if ( copy_to_user( buf, hostdata->iobuf.iodata, cnt ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ break;
-+ case MMC_KERNEL:
-+ memcpy( buf, hostdata->iobuf.iodata, cnt );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
-+ goto error;
-+ }
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+ssize_t pxa_mmc_copy_to_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+/* check that DMA channel is not running */
-+#endif
-+ switch ( to ) {
-+ case MMC_USER:
-+ if ( copy_from_user( hostdata->iobuf.iodata, buf, cnt ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ break;
-+ case MMC_KERNEL:
-+ memcpy( hostdata->iobuf.iodata, buf, cnt );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
-+ goto error;
-+ }
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally passes the data from the user buffer to the card */
-+static int pxa_mmc_stream_read( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u16 argh = 0UL, argl = 0UL;
-+ ssize_t size = 0;
-+
-+ while ( transfer->cnt > 0 ) {
-+ size = (transfer->cnt < hostdata->iobuf.blksz) ?
-+ transfer->cnt : hostdata->iobuf.blksz;
-+ /* 1. send CMD11 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ /* 2. setup controller registers to start stream data transfer */
-+ MMC_CMD = CMD(11); /* READ_DAT_UNTIL_STOP */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = 0xffff;
-+ MMC_BLKLEN = size;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+ /* 3. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD11(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+ /* 4. transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, size )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->addr += ret;
-+ transfer->cnt -= ret;
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure reads a data block from a card at a given kernel address */
-+static int pxa_mmc_read_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -ENODEV;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+/* CMD17 (READ_SINGLE_BLOCK) */
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(17); /* READ_SINGLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+ MMC_NOB = 1;
-+ MMC_BLKLEN = transfer->blksz;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD17(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->blksz )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ transfer->nob -= 1;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally reads data blocks from
-+ * a card to the user buffer. Controller options and block size
-+ * are already set by setup_card(). Data alignment and partial
-+ * data accessibility assumed to be checked by mmc_core */
-+static int pxa_mmc_read_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start multiple block transfer */
-+ MMC_CMD = CMD(18); /* READ_MULTIPLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = transfer->nob;
-+ MMC_BLKLEN = transfer->blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. start clock */
-+ if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 4. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD18(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 6. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* Sequentally writes the data from a user buffer to the card */
-+static int pxa_mmc_stream_write( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u16 argh = 0UL, argl = 0UL;
-+ ssize_t size = 0;
-+
-+ __ENTER( "transfer: cmd=%d mode=%d type=%d blksz=%d "
-+ "nob=%d buf=%p cnt=%d addr=%Lx", transfer->cmd,
-+ transfer->mode, transfer->type, transfer->blksz,
-+ transfer->nob, transfer->buf, transfer->cnt, transfer->addr );
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start stream data transfer */
-+ MMC_CMD = CMD(20); /* WRITE_DAT_UNTIL_STOP */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = 0xffff;
-+ MMC_BLKLEN = hostdata->iobuf.blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD20(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 4. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ size = (transfer->cnt < hostdata->iobuf.blksz) ?
-+ transfer->cnt : hostdata->iobuf.blksz;
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr,
-+ transfer->type, transfer->buf, size )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure writes a data block to a card at a given address */
-+static int pxa_mmc_write_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -ENODEV;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+/* CMD17 (READ_SINGLE_BLOCK) */
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(24); /* WRITE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+ MMC_NOB = 1;
-+ MMC_BLKLEN = transfer->blksz;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD24(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type, transfer->buf, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ transfer->nob -= 1;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally writes data blocks to a card at a given address */
-+static ssize_t pxa_mmc_write_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.write_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start multiple block transfer */
-+ MMC_CMD = CMD(25); /* WRITE_MULTIPLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = transfer->nob;
-+ MMC_BLKLEN = transfer->blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. start clock */
-+ if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 4. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD25(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 6. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type,
-+ transfer->buf, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void pxa_mmc_irq( int irq, void *dev_id, struct pt_regs *regs )
-+{
-+ mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifdef PIO
-+ register int i, cnt;
-+ register char *buf;
-+#endif
-+
-+ hostdata->mmc_i_reg = MMC_I_REG;
-+ hostdata->mmc_stat = MMC_STAT;
-+ hostdata->mmc_cmdat = MMC_CMDAT;
-+#if 0
-+ if (hostdata->mmc_i_reg != 0x0010) {
-+ printk("IREG %08x", hostdata->mmc_i_reg);
-+ if (hostdata->mmc_i_reg & 0x0001) printk(" DATA_TRAN_DONE");
-+ if (hostdata->mmc_i_reg & 0x0002) printk(" PRG_DONE");
-+ if (hostdata->mmc_i_reg & 0x0004) printk(" END_CMD");
-+ if (hostdata->mmc_i_reg & 0x0008) printk(" STOP_CMD");
-+ if (hostdata->mmc_i_reg & 0x0010) printk(" CLK_OFF");
-+ if (hostdata->mmc_i_reg & 0x0020) printk(" RX_FIFO");
-+ if (hostdata->mmc_i_reg & 0x0040) printk(" TX_FIFO");
-+ printk("\nSTAT %08x", hostdata->mmc_stat);
-+ if (hostdata->mmc_stat & 0x0001) printk(" READ_TO");
-+ if (hostdata->mmc_stat & 0x0002) printk(" RESP_TO");
-+ if (hostdata->mmc_stat & 0x0004) printk(" WR_CRC");
-+ if (hostdata->mmc_stat & 0x0008) printk(" READ_CRC");
-+ if (hostdata->mmc_stat & 0x0010) printk(" SPI_RD_TKN");
-+ if (hostdata->mmc_stat & 0x0020) printk(" RESP_CRC");
-+ if (hostdata->mmc_stat & 0x0040) printk(" TX_FIFO");
-+ if (hostdata->mmc_stat & 0x0080) printk(" RX_FIFO");
-+ if (hostdata->mmc_stat & 0x0100) printk(" CLK");
-+ if (hostdata->mmc_stat & 0x0800) printk(" DATA_TRAN_DONE");
-+ if (hostdata->mmc_stat & 0x1000) printk(" PRG_DONE");
-+ if (hostdata->mmc_stat & 0x2000) printk(" END_CMD");
-+ printk("\n");
-+ }
-+#endif
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ if ( --hostdata->irqcnt <= 0 ) {
-+ printk( KERN_INFO __FUNCTION__"(): irqcnt exceeded\n" );
-+ goto complete;
-+ }
-+#endif
-+ switch ( hostdata->state ) {
-+ case PXA_MMC_FSM_IDLE:
-+ case PXA_MMC_FSM_CLK_OFF:
-+ case PXA_MMC_FSM_END_IO:
-+ case PXA_MMC_FSM_END_BUFFER:
-+ case PXA_MMC_FSM_END_CMD:
-+ goto complete;
-+#ifdef PIO
-+ case PXA_MMC_FSM_BUFFER_IN_TRANSIT:
-+ if ( hostdata->mmc_stat & MMC_STAT_ERRORS )
-+ goto complete;
-+
-+ buf = hostdata->iobuf.buf.pos;
-+ cnt = (hostdata->iobuf.buf.cnt < 32) ?
-+ hostdata->iobuf.buf.cnt : 32;
-+ if ( hostdata->mmc_cmdat & MMC_CMDAT_WRITE ) {
-+ if ( !(hostdata->mmc_stat & MMC_STAT_XMIT_FIFO_EMPTY) )
-+ break;
-+ for ( i = 0; i < cnt; i++ )
-+ MMC_TXFIFO = *buf++;
-+ if ( cnt < 32 )
-+ MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL;
-+ } else { /* i.e. MMC_CMDAT_READ */
-+ if( !(hostdata->mmc_stat & MMC_STAT_RECV_FIFO_FULL) )
-+ break;
-+ for( i = 0; i < cnt; i++ )
-+ *buf++ = MMC_RXFIFO;
-+ }
-+
-+ hostdata->iobuf.buf.pos = buf;
-+ hostdata->iobuf.buf.cnt -= i;
-+ if ( hostdata->iobuf.buf.cnt <= 0 ) {
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
-+ goto complete;
-+ }
-+ break;
-+#endif /* PIO */
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state %d\n",
-+ hostdata->state );
-+ goto complete;
-+ }
-+ return;
-+complete:
-+ MMC_I_MASK = MMC_I_MASK_ALL;
-+ complete( &hostdata->completion );
-+ return;
-+}
-+
-+#ifndef PIO
-+static void pxa_mmc_dma_irq( int irq, void *dev_id, struct pt_regs *regs )
-+{
-+ mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u32 dcsr;
-+ u32 ddadr;
-+ int chan = hostdata->iobuf.buf.chan;
-+
-+ ddadr = DDADR( chan );
-+ dcsr = DCSR( chan );
-+ DCSR( chan ) = dcsr & ~DCSR_STOPIRQEN;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "MMC DMA interrupt: chan=%d ddadr=0x%08x "
-+ "dcmd=0x%08x dcsr=0x%08x\n",
-+ chan, ddadr, DCMD( chan ), dcsr );
-+/* bus error */
-+ if ( dcsr & DCSR_BUSERR ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "bus error on DMA channel %d\n",
-+ chan );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_ERROR );
-+ goto complete;
-+ }
-+/* data transfer completed */
-+ if ( dcsr & DCSR_ENDINTR ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
-+ goto complete;
-+ }
-+ return;
-+complete:
-+ complete( &hostdata->completion );
-+ return;
-+}
-+#endif
-+
-+
-+static int pxa_mmc_init( mmc_controller_t ctrlr )
-+{
-+ int ret = -ENODEV;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int i;
-+ register pxa_dma_desc *desc;
-+#endif
-+
-+/* hardware initialization */
-+/* I. prepare to transfer data */
-+/* 1. allocate buffer */
-+#ifndef PIO
-+ hostdata->iobuf.buf.read_desc = consistent_alloc( GFP_KERNEL,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ &hostdata->iobuf.buf.read_desc_phys_addr, 0 );
-+ if ( !hostdata->iobuf.buf.read_desc ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ hostdata->iobuf.buf.write_desc = consistent_alloc( GFP_KERNEL,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ &hostdata->iobuf.buf.write_desc_phys_addr, 0 );
-+ if ( !hostdata->iobuf.buf.write_desc ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ hostdata->iobuf.iodata = consistent_alloc( GFP_ATOMIC,
-+ PXA_MMC_IODATA_SIZE,
-+ &hostdata->iobuf.buf.phys_addr, 0 );
-+#else
-+ hostdata->iobuf.iodata = kmalloc( PXA_MMC_IODATA_SIZE, GFP_ATOMIC );
-+#endif
-+ if ( !hostdata->iobuf.iodata ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+/* 2. initialize iobuf */
-+ hostdata->iobuf.blksz = PXA_MMC_BLKSZ_MAX;
-+ hostdata->iobuf.bufsz = PXA_MMC_IODATA_SIZE;
-+ hostdata->iobuf.nob = PXA_MMC_BLOCKS_PER_BUFFER;
-+#ifndef PIO
-+ /* request DMA channel */
-+ if ( (hostdata->iobuf.buf.chan = pxa_request_dma( "MMC", DMA_PRIO_LOW,
-+ pxa_mmc_dma_irq, ctrlr )) < 0 ) {
-+ MMC_ERROR( "failed to request DMA channel\n" );
-+ goto error;
-+ }
-+
-+ DRCMRRXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
-+ DRCMRTXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
-+
-+ for ( i = 0; i < ((PXA_MMC_IODATA_SIZE>>5) - 1); i++ ) {
-+ desc = &hostdata->iobuf.buf.read_desc[i];
-+ desc->ddadr = hostdata->iobuf.buf.read_desc_phys_addr
-+ + ((i + 1) * sizeof( pxa_dma_desc ));
-+ desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
-+ desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+
-+ desc = &hostdata->iobuf.buf.write_desc[i];
-+ desc->ddadr = hostdata->iobuf.buf.write_desc_phys_addr
-+ + ((i + 1) * sizeof( pxa_dma_desc ));
-+ desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
-+ desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+ }
-+ desc = &hostdata->iobuf.buf.read_desc[i];
-+ desc->ddadr = (hostdata->iobuf.buf.read_desc_phys_addr +
-+ (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
-+ desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
-+ desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+
-+ desc = &hostdata->iobuf.buf.write_desc[i];
-+ desc->ddadr = (hostdata->iobuf.buf.write_desc_phys_addr +
-+ (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
-+ desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
-+ desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+#endif
-+/* II. MMC */
-+/* 1) request irq */
-+ if ( request_irq( IRQ_MMC, pxa_mmc_irq, 0, "MMC", ctrlr ) ) {
-+ MMC_ERROR( "failed to request IRQ_MMC\n" );
-+ goto error;
-+ }
-+
-+/* 2) initialize h/w and ctrlr */
-+ set_GPIO_mode( GPIO6_MMCCLK_MD );
-+ CKEN |= CKEN12_MMC; /* enable MMC unit clock */
-+
-+ ret = 0;
-+ goto out;
-+error:
-+#ifndef PIO
-+/* free DMA resources */
-+ if ( hostdata->iobuf.buf.chan >= 0 ) {
-+ DRCMRRXMMC = 0;
-+ DRCMRTXMMC = 0;
-+ pxa_free_dma( hostdata->iobuf.buf.chan );
-+ }
-+ if ( hostdata->iobuf.iodata )
-+ consistent_free( hostdata->iobuf.iodata,
-+ PXA_MMC_IODATA_SIZE,
-+ hostdata->iobuf.buf.phys_addr );
-+ if ( hostdata->iobuf.buf.read_desc )
-+ consistent_free( hostdata->iobuf.buf.read_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.read_desc_phys_addr );
-+ if ( hostdata->iobuf.buf.write_desc )
-+ consistent_free( hostdata->iobuf.buf.write_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.write_desc_phys_addr );
-+#else
-+ kfree( hostdata->iobuf.iodata );
-+#endif
-+out:
-+ return ret;
-+}
-+
-+static void pxa_mmc_remove( mmc_controller_t ctrlr )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+/* 1) free buffer(s) */
-+#ifndef PIO
-+ consistent_free( hostdata->iobuf.iodata, PXA_MMC_IODATA_SIZE,
-+ hostdata->iobuf.buf.phys_addr );
-+ consistent_free( hostdata->iobuf.buf.read_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.read_desc_phys_addr );
-+ consistent_free( hostdata->iobuf.buf.write_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.write_desc_phys_addr );
-+/* 2) release DMA channel */
-+ if ( hostdata->iobuf.buf.chan >= 0 ) {
-+ DRCMRRXMMC = 0;
-+ DRCMRTXMMC = 0;
-+ pxa_free_dma( hostdata->iobuf.buf.chan );
-+ }
-+#else
-+ kfree( hostdata->iobuf.iodata );
-+#endif
-+/* II. MMC */
-+/* 1) release irq */
-+ free_irq( IRQ_MMC, ctrlr );
-+ CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
-+}
-+
-+static int pxa_mmc_probe( mmc_controller_t ctrlr )
-+{
-+ return 1;
-+}
-+
-+#ifdef CONFIG_PM
-+static int pxa_mmc_suspend( mmc_controller_t ctrlr )
-+{
-+ int ret = -EBUSY;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "state=%s\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+
-+ if ( hostdata->state == PXA_MMC_FSM_IDLE ) {
-+ /* save registers */
-+ SAVED_MMC_CLKRT = MMC_CLKRT;
-+ SAVED_MMC_RESTO = MMC_RESTO;
-+ SAVED_MMC_SPI = MMC_SPI;
-+ SAVED_DRCMRRXMMC = DRCMRRXMMC;
-+ SAVED_DRCMRTXMMC = DRCMRTXMMC;
-+
-+#if 0 /* FIXME */
-+ /* send CMD0 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(0); /* CMD0 with zero argument */
-+ MMC_ARGH = 0UL;
-+ MMC_ARGL = 0UL;
-+ MMC_CMDAT = 0UL;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", 0UL, 0UL );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE,
-+ FALSE )) )
-+ {
-+ ret = -EIO;
-+ goto error;
-+ }
-+#endif
-+
-+ set_GPIO_mode( GPIO6_MMCCLK );
-+ CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
-+
-+ hostdata->suspended = TRUE;
-+ ret = 0;
-+ }
-+error:
-+ return ret;
-+}
-+
-+static void pxa_mmc_resume( mmc_controller_t ctrlr )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( hostdata->suspended == TRUE ) {
-+ set_GPIO_mode( GPIO6_MMCCLK_MD );
-+ CKEN |= CKEN12_MMC; /* enable MMC unit clock */
-+
-+ /* restore registers */
-+ MMC_CLKRT = SAVED_MMC_CLKRT;
-+ MMC_RESTO = SAVED_MMC_RESTO;
-+ MMC_SPI = SAVED_MMC_SPI;
-+ DRCMRRXMMC = SAVED_DRCMRRXMMC;
-+ DRCMRTXMMC = SAVED_DRCMRTXMMC;
-+
-+ hostdata->suspended = FALSE;
-+
-+ mmc_update_card_stack( ctrlr->slot ); /* FIXME */
-+ }
-+
-+ return;
-+}
-+#endif
-+
-+static mmc_controller_tmpl_rec_t pxa_mmc_controller_tmpl_rec = {
-+ owner: THIS_MODULE,
-+ name: "PXA250",
-+ block_size_max: PXA_MMC_BLKSZ_MAX,
-+ nob_max: PXA_MMC_NOB_MAX,
-+ probe: pxa_mmc_probe,
-+ init: pxa_mmc_init,
-+ remove: __devexit_p( pxa_mmc_remove ),
-+#ifdef CONFIG_PM
-+ suspend: pxa_mmc_suspend,
-+ resume: pxa_mmc_resume,
-+#endif /* CONFIG_PM */
-+ update_acq: pxa_mmc_update_acq,
-+// single_card_acq: pxa_mmc_single_card_acq,
-+ init_card_stack: pxa_mmc_init_card_stack,
-+ check_card_stack: pxa_mmc_check_card_stack,
-+ setup_card: pxa_mmc_setup_card,
-+ stream_read: pxa_mmc_stream_read,
-+ read_block: pxa_mmc_read_block,
-+ read_mblock: pxa_mmc_read_mblock,
-+ stream_write: pxa_mmc_stream_write,
-+ write_block: pxa_mmc_write_block,
-+ write_mblock: pxa_mmc_write_mblock
-+ /* TODO
-+ sg_io: pxa_mmc_sg_io
-+ */
-+ /* TODO:
-+ * erase,
-+ * write protection,
-+ * lock/password management methods
-+ */
-+};
-+
-+static int __devinit mmc_pxa_module_init( void )
-+{
-+ int ret = -ENODEV;
-+#ifdef CONFIG_ARCH_RAMSES
-+ RAMSES_MMC_ON();
-+ udelay(1000);
-+#endif
-+
-+ host = mmc_register( MMC_REG_TYPE_HOST, &pxa_mmc_controller_tmpl_rec,
-+ sizeof( pxa_mmc_hostdata_rec_t ) );
-+ if ( !host ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void __devexit mmc_pxa_module_cleanup( void )
-+{
-+ mmc_unregister( MMC_REG_TYPE_HOST, host );
-+#ifdef CONFIG_ARCH_RAMSES
-+ RAMSES_MMC_OFF();
-+#endif
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE( "GPL" );
-+
-+module_init( mmc_pxa_module_init );
-+module_exit( mmc_pxa_module_cleanup );
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc_pxa.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,278 @@
-+/*
-+ * linux/drivers/mmc/mmc_pxa.h
-+ *
-+ * Author: Vladimir Shebordaev, Igor Oblakov
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_PXA_P_H__
-+#define __MMC_PXA_P_H__
-+
-+#include <linux/completion.h>
-+
-+#define PIO
-+
-+/* PXA-250 MMC controller registers */
-+
-+/* MMC_STRPCL */
-+#define MMC_STRPCL_STOP_CLK (0x0001UL)
-+#define MMC_STRPCL_START_CLK (0x0002UL)
-+
-+/* MMC_STAT */
-+#define MMC_STAT_END_CMD_RES (0x0001UL << 13)
-+#define MMC_STAT_PRG_DONE (0x0001UL << 12)
-+#define MMC_STAT_DATA_TRAN_DONE (0x0001UL << 11)
-+#define MMC_STAT_CLK_EN (0x0001UL << 8)
-+#define MMC_STAT_RECV_FIFO_FULL (0x0001UL << 7)
-+#define MMC_STAT_XMIT_FIFO_EMPTY (0x0001UL << 6)
-+#define MMC_STAT_RES_CRC_ERROR (0x0001UL << 5)
-+#define MMC_STAT_SPI_READ_ERROR_TOKEN (0x0001UL << 4)
-+#define MMC_STAT_CRC_READ_ERROR (0x0001UL << 3)
-+#define MMC_STAT_CRC_WRITE_ERROR (0x0001UL << 2)
-+#define MMC_STAT_TIME_OUT_RESPONSE (0x0001UL << 1)
-+#define MMC_STAT_READ_TIME_OUT (0x0001UL)
-+
-+#define MMC_STAT_ERRORS (MMC_STAT_RES_CRC_ERROR|MMC_STAT_SPI_READ_ERROR_TOKEN\
-+ |MMC_STAT_CRC_READ_ERROR|MMC_STAT_TIME_OUT_RESPONSE\
-+ |MMC_STAT_READ_TIME_OUT)
-+
-+/* MMC_CLKRT */
-+#define MMC_CLKRT_20MHZ (0x0000UL)
-+#define MMC_CLKRT_10MHZ (0x0001UL)
-+#define MMC_CLKRT_5MHZ (0x0002UL)
-+#define MMC_CLKRT_2_5MHZ (0x0003UL)
-+#define MMC_CLKRT_1_25MHZ (0x0004UL)
-+#define MMC_CLKRT_0_625MHZ (0x0005UL)
-+#define MMC_CLKRT_0_3125MHZ (0x0006UL)
-+
-+/* MMC_SPI */
-+#define MMC_SPI_DISABLE (0x00UL)
-+#define MMC_SPI_EN (0x01UL)
-+#define MMC_SPI_CS_EN (0x01UL << 2)
-+#define MMC_SPI_CS_ADDRESS (0x01UL << 3)
-+#define MMC_SPI_CRC_ON (0x01UL << 1)
-+
-+/* MMC_CMDAT */
-+#define MMC_CMDAT_MMC_DMA_EN (0x0001UL << 7)
-+#define MMC_CMDAT_INIT (0x0001UL << 6)
-+#define MMC_CMDAT_BUSY (0x0001UL << 5)
-+#define MMC_CMDAT_STREAM (0x0001UL << 4)
-+#define MMC_CMDAT_BLOCK (0x0000UL << 4)
-+#define MMC_CMDAT_WRITE (0x0001UL << 3)
-+#define MMC_CMDAT_READ (0x0000UL << 3)
-+#define MMC_CMDAT_DATA_EN (0x0001UL << 2)
-+#define MMC_CMDAT_R1 (0x0001UL)
-+#define MMC_CMDAT_R2 (0x0002UL)
-+#define MMC_CMDAT_R3 (0x0003UL)
-+
-+/* MMC_RESTO */
-+#define MMC_RES_TO_MAX (0x007fUL) /* [6:0] */
-+
-+/* MMC_RDTO */
-+#define MMC_READ_TO_MAX (0x0ffffUL) /* [15:0] */
-+
-+/* MMC_BLKLEN */
-+#define MMC_BLK_LEN_MAX (0x03ffUL) /* [9:0] */
-+
-+/* MMC_PRTBUF */
-+#define MMC_PRTBUF_BUF_PART_FULL (0x01UL)
-+#define MMC_PRTBUF_BUF_FULL (0x00UL )
-+
-+/* MMC_I_MASK */
-+#define MMC_I_MASK_TXFIFO_WR_REQ (0x01UL << 6)
-+#define MMC_I_MASK_RXFIFO_RD_REQ (0x01UL << 5)
-+#define MMC_I_MASK_CLK_IS_OFF (0x01UL << 4)
-+#define MMC_I_MASK_STOP_CMD (0x01UL << 3)
-+#define MMC_I_MASK_END_CMD_RES (0x01UL << 2)
-+#define MMC_I_MASK_PRG_DONE (0x01UL << 1)
-+#define MMC_I_MASK_DATA_TRAN_DONE (0x01UL)
-+#define MMC_I_MASK_ALL (0x07fUL)
-+
-+
-+/* MMC_I_REG */
-+#define MMC_I_REG_TXFIFO_WR_REQ (0x01UL << 6)
-+#define MMC_I_REG_RXFIFO_RD_REQ (0x01UL << 5)
-+#define MMC_I_REG_CLK_IS_OFF (0x01UL << 4)
-+#define MMC_I_REG_STOP_CMD (0x01UL << 3)
-+#define MMC_I_REG_END_CMD_RES (0x01UL << 2)
-+#define MMC_I_REG_PRG_DONE (0x01UL << 1)
-+#define MMC_I_REG_DATA_TRAN_DONE (0x01UL)
-+#define MMC_I_REG_ALL (0x007fUL)
-+
-+/* MMC_CMD */
-+#define MMC_CMD_INDEX_MAX (0x006fUL) /* [5:0] */
-+#define CMD(x) (x)
-+
-+/* MMC_ARGH */
-+/* MMC_ARGL */
-+/* MMC_RES */
-+/* MMC_RXFIFO */
-+#define MMC_RXFIFO_PHYS_ADDR 0x41100040 //MMC_RXFIFO physical address
-+/* MMC_TXFIFO */
-+#define MMC_TXFIFO_PHYS_ADDR 0x41100044 //MMC_TXFIFO physical address
-+
-+/* implementation specific declarations */
-+#define PXA_MMC_BLKSZ_MAX (1<<9) /* actually 1023 */
-+#define PXA_MMC_NOB_MAX ((1<<16)-2)
-+#define PXA_MMC_BLOCKS_PER_BUFFER (2)
-+
-+#define PXA_MMC_IODATA_SIZE (PXA_MMC_BLOCKS_PER_BUFFER*PXA_MMC_BLKSZ_MAX) /* 1K */
-+
-+typedef enum _pxa_mmc_fsm { /* command processing FSM */
-+ PXA_MMC_FSM_IDLE = 1,
-+ PXA_MMC_FSM_CLK_OFF,
-+ PXA_MMC_FSM_END_CMD,
-+ PXA_MMC_FSM_BUFFER_IN_TRANSIT,
-+ PXA_MMC_FSM_END_BUFFER,
-+ PXA_MMC_FSM_END_IO,
-+ PXA_MMC_FSM_END_PRG,
-+ PXA_MMC_FSM_ERROR
-+} pxa_mmc_state_t;
-+
-+#define PXA_MMC_STATE_LABEL( state ) (\
-+ (state == PXA_MMC_FSM_IDLE) ? "IDLE" :\
-+ (state == PXA_MMC_FSM_CLK_OFF) ? "CLK_OFF" :\
-+ (state == PXA_MMC_FSM_END_CMD) ? "END_CMD" :\
-+ (state == PXA_MMC_FSM_BUFFER_IN_TRANSIT) ? "IN_TRANSIT" :\
-+ (state == PXA_MMC_FSM_END_BUFFER) ? "END_BUFFER" :\
-+ (state == PXA_MMC_FSM_END_IO) ? "END_IO" :\
-+ (state == PXA_MMC_FSM_END_PRG) ? "END_PRG" : "UNKNOWN" )
-+
-+typedef enum _pxa_mmc_result {
-+ PXA_MMC_NORMAL = 0,
-+ PXA_MMC_INVALID_STATE = -1,
-+ PXA_MMC_TIMEOUT = -2,
-+ PXA_MMC_ERROR = -3
-+} pxa_mmc_result_t;
-+
-+typedef u32 pxa_mmc_clkrt_t;
-+
-+typedef char *pxa_mmc_iodata_t;
-+#ifdef PIO
-+typedef struct _pxa_mmc_piobuf_rec {
-+ char *pos; /* current buffer position */
-+ int cnt; /* byte counter */
-+} pxa_mmc_piobuf_rec_t, *pxa_mmc_piobuf_t;
-+#else /* i.e. DMA */
-+typedef struct _pxa_mmc_dmabuf_rec { /* TODO: buffer ring, DMA irq completion */
-+ int chan; /* dma channel no */
-+ dma_addr_t phys_addr; /* iodata physical address */
-+ pxa_dma_desc *read_desc; /* input descriptor array virtual address */
-+ pxa_dma_desc *write_desc; /* output descriptor array virtual address */
-+ dma_addr_t read_desc_phys_addr; /* descriptor array physical address */
-+ dma_addr_t write_desc_phys_addr; /* descriptor array physical address */
-+ pxa_dma_desc *last_read_desc; /* last input descriptor
-+ * used by the previous transfer
-+ */
-+ pxa_dma_desc *last_write_desc; /* last output descriptor
-+ * used by the previous transfer
-+ */
-+} pxa_mmc_dmabuf_rec_t, *pxa_mmc_dmabuf_t;
-+#endif
-+
-+typedef struct _pxa_mmc_iobuf_rec {
-+ ssize_t blksz; /* current block size in bytes */
-+ ssize_t bufsz; /* buffer size for each transfer */
-+ ssize_t nob; /* number of blocks pers buffer */
-+#ifndef PIO
-+ pxa_mmc_dmabuf_rec_t buf; /* i.e. DMA buffer ring on the iodata */
-+#else /* i.e. DMA */
-+ pxa_mmc_piobuf_rec_t buf; /* PIO buffer accounting */
-+#endif
-+ pxa_mmc_iodata_t iodata; /* I/O data buffer */
-+} pxa_mmc_iobuf_rec_t, *pxa_mmc_iobuf_t;
-+
-+typedef struct _pxa_mmc_hostdata_rec {
-+ pxa_mmc_state_t state; /* FSM */
-+#ifdef CONFIG_PM
-+ int suspended;
-+#endif
-+ pxa_mmc_iobuf_rec_t iobuf; /* data transfer state */
-+
-+ int busy; /* atomic busy flag */
-+ struct completion completion; /* completion */
-+#if CONFIG_MMC_DEBUG_IRQ
-+ int irqcnt;
-+ int timeo;
-+#endif
-+
-+/* cached controller state */
-+ u32 mmc_i_reg; /* interrupt last requested */
-+ u32 mmc_i_mask; /* mask to be set by intr handler */
-+ u32 mmc_stat; /* status register at the last intr */
-+ u32 mmc_cmdat; /* MMC_CMDAT at the last inr */
-+ u8 mmc_res[16]; /* response to the last command in host order */
-+ u32 saved_mmc_clkrt;
-+ u32 saved_mmc_resto;
-+ u32 saved_mmc_spi;
-+ u32 saved_drcmrrxmmc;
-+ u32 saved_drcmrtxmmc;
-+
-+/* controller options */
-+ pxa_mmc_clkrt_t clkrt; /* current bus clock rate */
-+} pxa_mmc_hostdata_rec_t, *pxa_mmc_hostdata_t;
-+
-+#define PXA_MMC_STATUS( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_stat)
-+#define PXA_MMC_RESPONSE( ctrlr, idx ) ((((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_res)[idx])
-+#define PXA_MMC_CLKRT( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->clkrt)
-+
-+#define SAVED_MMC_CLKRT (hostdata->saved_mmc_clkrt)
-+#define SAVED_MMC_RESTO (hostdata->saved_mmc_resto)
-+#define SAVED_MMC_SPI (hostdata->saved_mmc_spi)
-+#define SAVED_DRCMRRXMMC (hostdata->saved_drcmrrxmmc )
-+#define SAVED_DRCMRTXMMC (hostdata->saved_drcmrtxmmc )
-+
-+static inline int pxa_mmc_clkrt( int speed )
-+{
-+ return MMC_CLKRT_20MHZ; /* TODO */
-+}
-+
-+/* PXA MMC controller specific card data */
-+typedef struct _pxa_mmc_card_data_rec {
-+ pxa_mmc_clkrt_t clkrt; /* clock rate to be set for the card */
-+} pxa_mmc_card_data_rec_t, *pxa_mmc_card_data_t;
-+
-+#ifdef CONFIG_MMC_DEBUG
-+#undef MMC_DUMP_R1
-+#undef MMC_DUMP_R2
-+#undef MMC_DUMP_R3
-+#define MMC_DUMP_R2( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R2 response: %02x %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 15 ), \
-+PXA_MMC_RESPONSE( ctrlr, 14 ), \
-+PXA_MMC_RESPONSE( ctrlr, 13 ), \
-+PXA_MMC_RESPONSE( ctrlr, 12 ), \
-+PXA_MMC_RESPONSE( ctrlr, 11 ), \
-+PXA_MMC_RESPONSE( ctrlr, 10 ), \
-+PXA_MMC_RESPONSE( ctrlr, 9 ), \
-+PXA_MMC_RESPONSE( ctrlr, 8 ), \
-+PXA_MMC_RESPONSE( ctrlr, 7 ), \
-+PXA_MMC_RESPONSE( ctrlr, 6 ), \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ), \
-+PXA_MMC_RESPONSE( ctrlr, 0 ) );
-+#define MMC_DUMP_R1( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R1(b) response: %02x %02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ) );
-+#define MMC_DUMP_R3( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R3 response: %02x %02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ) );
-+
-+#endif
-+#endif /* __MMC_PXA_P_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/mmc_test.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,538 @@
-+/*
-+ * linux/drivers/mmc/mmc_test.c
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_test.c,v 0.4 2002/08/01 12:26:40 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/fs.h>
-+#ifdef CONFIG_DEVFS_FS
-+#include <linux/devfs_fs_kernel.h>
-+#endif
-+
-+#include <asm/uaccess.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+
-+typedef struct _mmc_test_device_rec mmc_test_device_rec_t;
-+typedef struct _mmc_test_device_rec *mmc_test_device_t;
-+
-+struct _mmc_test_device_rec {
-+ mmc_card_t card;
-+ mmc_transfer_mode_t transfer_mode;
-+ int usage;
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_handle_t devfs_handle;
-+#endif
-+};
-+
-+/* MMC device table */
-+static mmc_test_device_rec_t mmc_test_device[MMC_CONTROLLERS_MAX][MMC_CARDS_MAX];
-+static DECLARE_MUTEX(mmc_test_device_mutex);
-+
-+static inline mmc_test_device_t __mmc_test_get_device( kdev_t rdev )
-+{
-+ mmc_test_device_t ret = NULL;
-+ u8 minor = MINOR( rdev );
-+ int host_no, card_no;
-+
-+ host_no = minor >> MMC_MINOR_HOST_SHIFT;
-+ if ( host_no >= MMC_CONTROLLERS_MAX )
-+ goto error;
-+
-+ card_no = minor & MMC_MINOR_CARD_MASK;
-+ if ( card_no >= MMC_CARDS_MAX )
-+ goto error;
-+
-+ ret = &mmc_test_device[host_no][card_no];
-+ if ( !ret->card ) {
-+ ret->card = mmc_get_card( host_no, card_no );
-+ if ( !ret->card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to get card: host=%d, card=%d\n", host_no, card_no );
-+ ret = NULL;
-+ goto error;
-+ }
-+
-+ }
-+ ++ret->usage;
-+
-+error:
-+ return ret;
-+}
-+
-+static inline void __mmc_test_put_device( mmc_test_device_t dev )
-+{
-+ mmc_put_card( dev->card );
-+ --dev->usage;
-+}
-+
-+static inline mmc_test_device_t mmc_test_get_device( kdev_t kdev )
-+{
-+ mmc_test_device_t ret = NULL;
-+
-+ down( &mmc_test_device_mutex );
-+ ret = __mmc_test_get_device( kdev );
-+ up( &mmc_test_device_mutex );
-+
-+ return ret;
-+}
-+
-+static inline void mmc_test_put_device( mmc_test_device_t dev )
-+{
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ __mmc_test_put_device( dev );
-+ if ( !dev->usage ) {
-+ if ( dev->card ) {
-+ if ( dev->card->usage ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "broken card reference\n" );
-+ }
-+ memset( dev, 0, sizeof( mmc_test_device_rec_t ) );
-+ }
-+ }
-+ up( &mmc_test_device_mutex );
-+ }
-+}
-+
-+static inline int mmc_test_set_transfer_mode( mmc_test_device_t dev, mmc_transfer_mode_t mode )
-+{
-+ int ret = -1;
-+
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ dev->transfer_mode = mode;
-+ ret = 0;
-+ up( &mmc_test_device_mutex );
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_transfer_mode_t mmc_test_get_transfer_mode( mmc_test_device_t dev )
-+{
-+ mmc_transfer_mode_t ret = MMC_TRANSFER_MODE_UNDEFINED;
-+
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ ret = dev->transfer_mode;
-+ up( &mmc_test_device_mutex );
-+ }
-+ return ret;
-+}
-+
-+static int mmc_test_open( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = NULL;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ __ENTER0( );
-+ dev = mmc_test_get_device( inode->i_rdev );
-+ if ( !dev || !dev->card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to acquire device\n" );
-+ goto error;
-+ }
-+
-+ if ( dev->card->usage > 1 ) {
-+ ret = -EBUSY;
-+ goto error;
-+ }
-+
-+ dev->transfer_mode = MMC_TEST_TRANSFER_MODE_DEFAULT; /* FIXME: should check card CCC */
-+ file->private_data = dev;
-+
-+ __LEAVE0( );
-+ return 0;
-+error:
-+ MOD_DEC_USE_COUNT;
-+ mmc_test_put_device( dev );
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static int mmc_test_release( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ __ENTER( "host=%d, card=%d", dev->card->ctrlr->slot, dev->card->slot );
-+
-+ file->private_data = NULL;
-+
-+ mmc_test_put_device( dev );
-+ MOD_DEC_USE_COUNT;
-+
-+ ret = 0;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static ssize_t mmc_test_read( struct file *file, char *buf, size_t size, loff_t *ppos )
-+{
-+ ssize_t ret = -ENODEV;
-+ ssize_t retsize = 0;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( dev->transfer_mode ) {
-+ char *mbuf;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual read_bl_len or ctrlr->block_size_max whichever is less ), GFP_KERNEL */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 512) ? 512 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_read( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 1024) ? 1024 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_read( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+
-+ case MMC_TRANSFER_MODE_STREAM:
-+ ret = mmc_read( dev->card, dev->transfer_mode,
-+ buf, size, ppos );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static ssize_t mmc_test_write( struct file *file, const char *buf, size_t size, loff_t *ppos )
-+{
-+ ssize_t ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+ int retsize=0;
-+
-+ __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( dev->transfer_mode ) {
-+ char *mbuf;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual write_bl_len or ctrlr->block_size_max whichever is less, GFP_KERNEL */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while ( size > 0 ) {
-+ int lsize = ( size > 512 ) ? 512 : size;
-+
-+ /* Copy from user */
-+ if ( copy_from_user( mbuf, buf, lsize ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ ret = mmc_write( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ mbuf, lsize, ppos );
-+ if( ret <= 0 )
-+ break;
-+
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+
-+ kfree( mbuf );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 1024) ? 1024 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_write( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( (char *)buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+ case MMC_TRANSFER_MODE_STREAM:
-+ ret = mmc_write( dev->card, dev->transfer_mode,
-+ buf, size, ppos );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static loff_t mmc_test_llseek( struct file *file, loff_t offset, int origin )
-+{
-+ loff_t ret = -ESPIPE;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+ mmc_card_t card;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "host=%d, card=%d, off=%ld, orig=%d", dev->card->ctrlr->slot, dev->card->slot, (long)offset, origin );
-+
-+ card = dev->card;
-+
-+ switch ( origin ) {
-+ case SEEK_CUR:
-+ file->f_pos += offset;
-+ break;
-+
-+ case SEEK_END:
-+ file->f_pos = card->info.capacity + offset;
-+ break;
-+
-+ case SEEK_SET:
-+ file->f_pos = offset;
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ ret = file->f_pos;
-+error:
-+ __LEAVE( "ret=%ld", (long)ret );
-+ return ret;
-+}
-+
-+static int mmc_test_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( cmd ) {
-+ case IOCMMCSTRNSMODE:
-+ if ( get_user( ret, (int *)arg ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ ret = mmc_test_set_transfer_mode( dev, ret );
-+ break;
-+
-+ case IOCMMCGTRNSMODE:
-+ ret = mmc_test_get_transfer_mode( dev );
-+ if ( put_user( ret, (int *)arg ) )
-+ ret = -EFAULT;
-+ break;
-+
-+ default:
-+ ret = mmc_ioctl( dev->card, cmd, arg );
-+ }
-+
-+error:
-+ return ret;
-+}
-+
-+struct file_operations mmc_test_fops = {
-+ owner: THIS_MODULE,
-+ open: mmc_test_open,
-+ release: mmc_test_release,
-+ read: mmc_test_read,
-+ write: mmc_test_write,
-+ ioctl: mmc_test_ioctl,
-+ llseek: mmc_test_llseek
-+};
-+
-+#ifdef CONFIG_DEVFS_FS
-+static int mmc_test_add_card( mmc_card_t card ) /* TODO */
-+{
-+ int ret = -1;
-+ __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
-+/* TODO: make kdev; register with devfs */
-+ __LEAVE0( );
-+ return ret;
-+}
-+
-+static int mmc_test_remove_card( mmc_card_t card ) /* TODO */
-+{
-+ int ret = -1;
-+ __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
-+/* TODO: make kdev; unregister with devfs */
-+ __LEAVE0( );
-+ return ret;
-+}
-+
-+static mmc_notifier_rec_t mmc_test_notifier = {
-+ add: mmc_test_add_card,
-+ remove: mmc_test_remove_card
-+};
-+#endif /* CONFIG_DEVFS_FS */
-+
-+static int __init mmc_test_module_init( void )
-+{
-+ int ret = -ENODEV;
-+
-+#ifdef CONFIG_DEVFS_FS
-+ if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_test_notifier, 0 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+#else
-+ mmc_register( MMC_REG_TYPE_USER, NULL, 0 );
-+ if ( register_chrdev( MMC_TEST_MAJOR, "mmc_test", &mmc_test_fops ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "failed to request device major number\n" );
-+ mmc_unregister( MMC_REG_TYPE_USER, NULL );
-+ goto error;
-+ }
-+#endif
-+
-+ memset( mmc_test_device, 0, sizeof( mmc_test_device ) );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void __exit mmc_test_module_cleanup( void )
-+{
-+#ifdef CONFIG_DEVFS_FS
-+ mmc_unregister( MMC_REG_TYPE_USER, &mmc_test_notifier );
-+#else
-+ mmc_unregister( MMC_REG_TYPE_USER, NULL );
-+ unregister_chrdev( MMC_TEST_MAJOR, "mmc_test" );
-+#endif
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init( mmc_test_module_init );
-+module_exit( mmc_test_module_cleanup );
-+
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/pm_test.c 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,29 @@
-+/* Power Managment Test Module. RTSoft Co. 2002 */
-+
-+/* The necessary header files */
-+
-+/* Standard in kernel modules */
-+#include <linux/kernel.h> /* We're doing kernel work */
-+#include <linux/module.h> /* Specifically, a module */
-+#define CONFIG_PM
-+#include <linux/pm.h>
-+
-+
-+static int pmdata = -1;
-+
-+/* Initialize the module - register the proc file */
-+
-+int init_module()
-+{
-+ pm_send_all(PM_SUSPEND,&pmdata);
-+ return(0);
-+}
-+
-+
-+/* Cleanup - unregister our file from /proc */
-+void cleanup_module()
-+{
-+ pm_send_all(PM_RESUME,NULL);
-+}
-+
-+MODULE_LICENSE( "GPL" );
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mmc/types.h 2004-03-31 17:15:11.000000000 +0200
-@@ -0,0 +1,59 @@
-+/*
-+ * linux/drivers/mmc/types.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: types.h,v 0.5 2002/08/13 17:34:02 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_TYPES_P_H__
-+#define __MMC_TYPES_P_H__
-+
-+#ifdef __KERNEL__
-+#include <linux/kdev_t.h>
-+
-+typedef enum _mmc_reg_type mmc_reg_type_t;
-+typedef enum _mmc_response mmc_response_fmt_t;
-+
-+/* MMC card private description */
-+typedef struct _mmc_card_rec mmc_card_rec_t;
-+typedef struct _mmc_card_rec *mmc_card_t;
-+typedef enum _mmc_dir mmc_dir_t;
-+typedef enum _mmc_buftype mmc_buftype_t;
-+
-+/* notifier declarations */
-+typedef struct _mmc_notifier_rec mmc_notifier_rec_t;
-+typedef struct _mmc_notifier_rec *mmc_notifier_t;
-+
-+typedef int (*mmc_notifier_fn_t) ( mmc_card_t );
-+
-+/* MMC card stack */
-+typedef struct _mmc_card_stack_rec mmc_card_stack_rec_t;
-+typedef struct _mmc_card_stack_rec *mmc_card_stack_t;
-+
-+typedef struct _mmc_data_transfer_req_rec mmc_data_transfer_req_rec_t;
-+typedef struct _mmc_data_transfer_req_rec *mmc_data_transfer_req_t;
-+
-+/* MMC controller */
-+typedef struct _mmc_controller_tmpl_rec mmc_controller_tmpl_rec_t;
-+typedef struct _mmc_controller_tmpl_rec *mmc_controller_tmpl_t;
-+
-+typedef enum _mmc_controller_state mmc_controller_state_t;
-+typedef struct _mmc_controller_rec mmc_controller_rec_t;
-+typedef struct _mmc_controller_rec *mmc_controller_t;
-+
-+/* various kernel types */
-+typedef struct semaphore semaphore_t;
-+typedef struct rw_semaphore rwsemaphore_t;
-+typedef struct proc_dir_entry proc_dir_entry_rec_t;
-+typedef struct proc_dir_entry *proc_dir_entry_t;
-+typedef struct gendisk gendisk_rec_t;
-+typedef struct gendisk *gendisk_t;
-+#endif /* __KERNEL__ */
-+
-+#endif /* __MMC_TYPES_P_H__ */
-+
---- linux-2.4.25/drivers/net/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/net/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -125,6 +125,7 @@
- dep_tristate ' SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA
- dep_tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA
- dep_tristate ' SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA
-+ tristate ' SMC 91C9x/91C1xx support' CONFIG_SMC91X
- fi
- bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
- if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
---- linux-2.4.25/drivers/net/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/net/Makefile 2004-03-31 17:15:11.000000000 +0200
-@@ -137,6 +137,7 @@
- obj-$(CONFIG_SK_G16) += sk_g16.o
- obj-$(CONFIG_HP100) += hp100.o
- obj-$(CONFIG_SMC9194) += smc9194.o
-+obj-$(CONFIG_SMC91X) += smc91x.o
- obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
- obj-$(CONFIG_ARM_ETHERH) += 8390.o
- obj-$(CONFIG_WD80x3) += wd.o 8390.o
---- linux-2.4.25/drivers/net/cirrus.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/net/cirrus.c 2004-03-31 17:15:11.000000000 +0200
-@@ -67,6 +67,9 @@
- #elif CONFIG_ARCH_CDB89712
- # define CIRRUS_DEFAULT_IO ETHER_BASE + 0x300
- # define CIRRUS_DEFAULT_IRQ IRQ_EINT3
-+#elif CONFIG_ARCH_CSB226
-+# define CIRRUS_DEFAULT_IO 0xF8000000
-+# define CIRRUS_DEFAULT_IRQ IRQ_GPIO(14)
- #else
- # define CIRRUS_DEFAULT_IO 0
- # define CIRRUS_DEFAULT_IRQ 0
---- linux-2.4.25/drivers/net/irda/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/net/irda/Config.in 2004-03-31 17:15:11.000000000 +0200
-@@ -42,5 +42,7 @@
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
- dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
- fi
--
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_tristate 'Intel PXA2xx Internal IR' CONFIG_PXA_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
-+fi
- endmenu
---- linux-2.4.25/drivers/net/irda/Makefile~2.4.25-vrs2-pxa1.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/net/irda/Makefile 2004-03-31 17:15:12.000000000 +0200
-@@ -16,6 +16,7 @@
- obj-$(CONFIG_USB_IRDA) += irda-usb.o
- obj-$(CONFIG_NSC_FIR) += nsc-ircc.o
- obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
-+obj-$(CONFIG_PXA_FIR) += pxa_ir.o
- obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o
- obj-$(CONFIG_TOSHIBA_OLD) += toshoboe.o
- obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/net/irda/pxa_ir.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,1545 @@
-+/*
-+ * linux/drivers/net/irda/pxa_ir.c
-+ *
-+ * Author:
-+ * Alexey Lugovskoy RTSoft.
-+ * lugovskoy@rtsoft.msk.ru
-+ *
-+ * Dmitrij Frasenyak RTSoft.
-+ * sed@mipt.sw.ru
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Infra-red SIR and FIR driver for the PXA 210/250 embedded microprocessors
-+ * Based on linux/drivers/net/irda/sa1100_ir.c
-+ *
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/netdevice.h>
-+#include <linux/slab.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/interrupt.h>
-+#include <linux/delay.h>
-+#include <linux/ioport.h>
-+#include <linux/delay.h>
-+
-+#include <linux/pm.h>
-+
-+#include <net/irda/irda.h>
-+#include <net/irda/irmod.h>
-+#include <net/irda/wrapper.h>
-+#include <net/irda/irda_device.h>
-+
-+#include <asm/irq.h>
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/lubbock.h>
-+
-+
-+static int rx_count = 0;
-+static int tx_count = 0;
-+
-+/*
-+ * Our netdevice. There is only ever one of these.
-+ */
-+
-+static struct net_device *netdev;
-+
-+struct pxa250_irda {
-+
-+ unsigned char open;
-+
-+ int speed;
-+ int newspeed;
-+
-+ struct sk_buff *txskb;
-+ struct sk_buff *rxskb;
-+
-+
-+ /* => FIR */
-+ unsigned int fir_irq;
-+ int txdma_ch;
-+ int rxdma_ch;
-+ dma_addr_t txbuf_dma;
-+ dma_addr_t rxbuf_dma;
-+ void* txbuf_dma_virt;
-+ void* rxbuf_dma_virt;
-+ /* <= FIR*/
-+ struct net_device_stats stats;
-+ struct irlap_cb *irlap;
-+ struct pm_dev *pmdev;
-+ struct qos_info qos;
-+
-+ /* => SIR */
-+ iobuff_t tx_buff;
-+ iobuff_t rx_buff;
-+ /* <= SIR */
-+};
-+
-+#define IS_FIR(si) ((si)->speed >= 4000000)
-+
-+#define HPSIR_MAX_RXLEN 2050
-+#define HPSIR_MAX_TXLEN 2050
-+#define TXBUFF_MAX_SIZE HPSIR_MAX_TXLEN
-+#define SET_SIR_MODE STISR = STISR_RCVEIR | STISR_XMITIR | STISR_XMODE
-+
-+/*
-+ * If you want to disable debug information
-+ * please uncomment line bellow
-+ */
-+
-+#define PXA_FIR_DUMP_ENABLE
-+#undef PXA_FIR_DUMP_ENABLE
-+
-+
-+#define PXA_FIR_DEBUG_ENABLE
-+#undef PXA_FIR_DEBUG_ENABLE
-+
-+#define PXA_FIR_IRQ_DEBUG_ENABLE
-+#undef PXA_FIR_IRQ_DEBUG_ENABLE
-+
-+#ifdef PXA_FIR_DEBUG_ENABLE
-+#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);
-+#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);
-+#define DBG(args...) printk(KERN_ERR __FUNCTION__"():"args);
-+#else
-+#define __ECHO_IN
-+#define __ECHO_OUT
-+#define DBG(args...)
-+#endif
-+
-+#ifdef PXA_FIR_IRQ_DEBUG_ENABLE
-+#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args);
-+#else
-+#define DBG_IRQ(args...)
-+#endif
-+
-+
-+static int pxa250_irda_set_speed(struct net_device *dev,int speed);
-+static void pxa250_start_rx_dma(struct net_device *dev);
-+
-+
-+
-+/**************************************************************************
-+ * Misc FIR/SIR functions *
-+ **************************************************************************/
-+/*
-+ * Allocate the receive buffer, unless it is already allocated.
-+ */
-+
-+static int pxa250_irda_rx_alloc(struct pxa250_irda *si)
-+{
-+ __ECHO_IN;
-+
-+ if (si->rxskb)
-+ return 0;
-+
-+ si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-+
-+ if (!si->rxskb) {
-+ printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
-+ return -ENOMEM;
-+ }
-+
-+ /*
-+ * Align any IP headers that may be contained
-+ * within the frame.
-+ */
-+ skb_reserve(si->rxskb, 1);
-+
-+ __ECHO_OUT;
-+
-+ return 0;
-+}
-+
-+
-+
-+/**************************************************************************
-+ * FIR *
-+ **************************************************************************/
-+
-+
-+
-+
-+static inline void pxa250_dma_stop(int ch)
-+{
-+ __ECHO_IN;
-+
-+ DCSR(ch) &= ~DCSR_RUN;
-+
-+ __ECHO_OUT;
-+
-+}
-+
-+
-+static void pxa250_ficp_rx_start(void)
-+{
-+ ICCR0 = 0;
-+ ICCR2 = 1 << 2 | 0 << 3 ;
-+ ICCR0 = ICCR0_ITR ;
-+ ICCR0 |= ICCR0_RIE | ICCR0_RXE ;
-+}
-+
-+/*
-+ * Change Alternative Function encoding
-+ * Enable ICP unit
-+ * Disabe STUART unit
-+ * Enable IRQ unit clock;
-+ * Configure direction of GPIO used by ICP
-+ */
-+
-+
-+static void pxa250_do_fir_GPIO_config(void)
-+{
-+ /*
-+ * Modify GPIO 46 and 47 Alternate Function
-+ */
-+
-+ __ECHO_IN;
-+
-+ /*Switch AF*/
-+ set_GPIO_mode (GPIO46_ICPRXD_MD);
-+ set_GPIO_mode (GPIO47_ICPTXD_MD);
-+
-+ if (machine_is_lubbock())
-+ LUB_MISC_WR |= 1 << 4;
-+
-+ /*init clock*/
-+ CKEN |= CKEN13_FICP;
-+
-+ __ECHO_OUT;
-+}
-+
-+/*
-+ * Low level hardware configuration and startup.
-+ */
-+
-+static int pxa250_fir_irda_startup(struct pxa250_irda *si)
-+{
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Disable STUART
-+ */
-+
-+ STIER &= ~IER_UUE;
-+
-+ /*Disable STUART FIFO */
-+ STFCR = 0;
-+
-+ /*
-+ * Do low level configuration for HW AF and clock
-+ */
-+ pxa250_do_fir_GPIO_config();
-+
-+ __ECHO_OUT;
-+ return 0;
-+}
-+
-+
-+/*
-+ * Aieeeeee .. we should never get here :(
-+ */
-+static void pxa250_irda_rxdma_irq(int ch,void *id, struct pt_regs *regs)
-+{
-+ struct net_device *dev=id;
-+ struct pxa250_irda *si=dev->priv;
-+ u_int dcsr;
-+
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Make sure that irq is our.
-+ */
-+
-+ if ( ch != si->rxdma_ch )
-+ /*just*/ return;
-+
-+ /*
-+ * Check status
-+ */
-+ dcsr = DCSR(ch);
-+
-+ DBG("DCSR=%x\n",dcsr);
-+
-+ if (dcsr & DCSR_STOPSTATE )
-+ {
-+ DBG_IRQ("Chanel %d in stop state\n",ch);
-+ }
-+
-+ if (dcsr & DCSR_BUSERR )
-+ {
-+ /*
-+ * BUS Error we must restart reception
-+ */
-+
-+ DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
-+ DCSR(ch) |= DCSR_BUSERR;
-+ }
-+
-+ if (dcsr & DCSR_ENDINTR )
-+ {
-+ DBG("PXA IrDA: Normal end of dma channel %d - packet to big\n", ch);
-+ DCSR(ch) |= DCSR_ENDINTR;
-+ }
-+
-+ /* no mater what restart rx*/
-+ pxa250_start_rx_dma(dev);
-+
-+ return ;
-+
-+}
-+
-+
-+static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs)
-+{
-+ struct net_device *dev=id;
-+ struct pxa250_irda *si=dev->priv;
-+ struct sk_buff *skb = si->txskb;
-+ u_int dcsr;
-+
-+
-+ __ECHO_IN;
-+ DBG_IRQ("transmit\n");
-+
-+
-+ /*
-+ * Make sure that irq is our.
-+ */
-+
-+ if ( ch != si->txdma_ch )
-+ /*just*/ return;
-+
-+
-+ /*
-+ * Check status
-+ */
-+ dcsr = DCSR(ch);
-+
-+ DBG("DCSR=%x",dcsr);
-+
-+ if (dcsr & DCSR_STOPSTATE )
-+ {
-+ DBG("Chanel %d in stop state\n",ch);
-+ }
-+
-+ if (dcsr & DCSR_BUSERR )
-+ {
-+ DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
-+ DCSR(ch) |= DCSR_BUSERR;
-+ si->txskb = NULL;
-+ }
-+
-+ if (dcsr & DCSR_ENDINTR )
-+ {
-+ DBG("PXA IrDA: Normal end of dma channel %d\n", ch);
-+ DCSR(ch) |= DCSR_ENDINTR;
-+ si->txskb = NULL;
-+ }
-+
-+ /*
-+ * Account and free the packet.
-+ */
-+ if (skb)
-+ {
-+ si->stats.tx_packets ++;
-+ si->stats.tx_bytes += skb->len;
-+ dev_kfree_skb_irq(skb);
-+ }
-+
-+ /*Disable transceiver and enable receiver*/
-+
-+ if (si->newspeed) {
-+ pxa250_irda_set_speed(dev, si->newspeed);
-+ si->newspeed = 0;
-+ }
-+
-+ while (ICSR1 & ICSR1_TBY)
-+ udelay(1);
-+
-+ ICCR0 &= ~ICCR0_TXE;
-+
-+
-+ enable_irq(si->fir_irq);
-+
-+ ICCR0 |= ICCR0_RXE;
-+
-+ /*
-+ * Make sure that the TX queue is available for sending
-+ * (for retries). TX has priority over RX at all times.
-+ */
-+ netif_wake_queue(dev);
-+
-+ __ECHO_OUT;
-+}
-+
-+
-+static void pxa250_start_rx_dma(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int ch=si->rxdma_ch;
-+
-+ if (!si->rxskb) {
-+ DBG("rx buffer went missing\n");
-+/* return; */
-+ }
-+
-+ DCSR(ch)=0;
-+ DCSR(ch)=DCSR_NODESC;
-+ DSADR(ch) = __PREG(ICDR);
-+ DTADR(ch) = si->rxbuf_dma; /* phisical address */;
-+
-+ /* We should never do END_IRQ. !!!*/
-+ DCMD(ch) = DCMD_ENDIRQEN| DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | HPSIR_MAX_RXLEN;
-+
-+ /*
-+ * All right information will be available as soon as we set RXE flag
-+ */
-+
-+ DCSR(ch) = DCSR_ENDINTR | DCSR_BUSERR;
-+ DCSR(ch) = DCSR_RUN | DCSR_NODESC ;
-+
-+}
-+
-+
-+
-+
-+static int pxa250_get_rx_len(struct pxa250_irda *si)
-+{
-+ /*
-+ * DMA have to be stoped here
-+ */
-+
-+ if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) )
-+ printk("warning dma have to be stoped befor counting len\n");
-+
-+ return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) );
-+
-+}
-+
-+static void pxa250_irda_fir_error(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ struct sk_buff *skb = si->rxskb;
-+ int len;
-+ int stat,data;
-+
-+ __ECHO_IN;
-+
-+ if (!skb)
-+ {
-+ printk("pxa250 fir_error: SKB is NULL!\n");
-+ return;
-+ }
-+
-+ /*
-+ * Get the current data position.
-+ */
-+
-+ len=pxa250_get_rx_len(si);
-+ DBG("RXLEN=%d\n",len);
-+ memcpy(skb->data, si->rxbuf_dma_virt, len);
-+
-+ do {
-+ /*
-+ * Read Status, and then Data.
-+ */
-+ stat = ICSR1;
-+ rmb();
-+ data = ICDR;
-+ if (stat & (ICSR1_CRE | ICSR1_ROR)) {
-+ si->stats.rx_errors++;
-+ if (stat & ICSR1_CRE)
-+ si->stats.rx_crc_errors++;
-+ if (stat & ICSR1_ROR)
-+ si->stats.rx_frame_errors++;
-+ } else
-+ skb->data[len++] = data;
-+
-+ /*
-+ * If we hit the end of frame, there's
-+ * no point in continuing.
-+ */
-+ if (stat & ICSR1_EOF)
-+ break;
-+ } while (ICSR0 & ICSR0_EIF);
-+
-+ if (stat & ICSR1_EOF) {
-+ si->rxskb = NULL;
-+
-+ skb_put(skb, len);
-+ skb->dev = dev;
-+ skb->mac.raw = skb->data;
-+ skb->protocol = htons(ETH_P_IRDA);
-+ si->stats.rx_packets++;
-+ si->stats.rx_bytes += len;
-+
-+ /*
-+ * Before we pass the buffer up, allocate a new one.
-+ */
-+
-+ si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-+
-+ if (!si->rxskb) {
-+ printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
-+ return;
-+ }
-+
-+ /*
-+ * Align any IP headers that may be contained
-+ * within the frame.
-+ */
-+ skb_reserve(si->rxskb, 1);
-+
-+ netif_rx(skb);
-+ }
-+}
-+
-+/*
-+ * FIR format interrupt service routine. We only have to
-+ * handle RX events; transmit events go via the TX DMA irq handler.
-+ *
-+ * No matter what, we disable RX, process, and then restart RX.
-+ */
-+
-+static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+ struct pxa250_irda *si = dev->priv;
-+ int status;
-+
-+ /*
-+ * Stop RX
-+ */
-+
-+ __ECHO_IN;
-+
-+ pxa250_dma_stop(si->rxdma_ch);
-+
-+
-+ /*
-+ * Framing error - we throw away the packet completely.
-+ * Clearing RXE flushes the error conditions and data
-+ * from the fifo.
-+ */
-+ status=ICSR0;
-+
-+ if (status & (ICSR0_FRE | ICSR0_RAB)) {
-+ DBG_IRQ("Framing error or RAB\n");
-+
-+ si->stats.rx_errors++;
-+
-+ if (ICSR0 & ICSR0_FRE)
-+ si->stats.rx_frame_errors++;
-+
-+ /* Clear RX fifo
-+ * DMA will be cleared when we restart RX
-+ * Should we check RNE after that?
-+ */
-+
-+ ICCR0 &= ~ICCR0_RXE;
-+
-+ /*
-+ * Clear selected status bits now, so we
-+ * don't miss them next time around.
-+ */
-+ ICSR0 = status & (ICSR0_FRE | ICSR0_RAB);
-+ }
-+
-+
-+ /*
-+ * Deal with any receive errors. The any of the lowest
-+ * 8 bytes in the FIFO may contain an error. We must read
-+ * them one by one. The "error" could even be the end of
-+ * packet!
-+ */
-+ if (ICSR0 & ICSR0_EIF)
-+ pxa250_irda_fir_error(dev);
-+
-+ /*
-+ * No matter what happens, we must restart reception.
-+ */
-+
-+ ICCR0 = 0;
-+ pxa250_start_rx_dma(dev);
-+ pxa250_ficp_rx_start();
-+ __ECHO_OUT;
-+}
-+
-+
-+
-+
-+
-+/**************************************************************************
-+ * SIR *
-+ **************************************************************************/
-+/*
-+ * HP-SIR format interrupt service routines.
-+ */
-+static void pxa250_sir_transmit(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ if (si->tx_buff.len)
-+ {
-+ /* Disable receiver and enable transmiter*/
-+
-+
-+
-+ STISR &= ~STISR_RCVEIR;
-+// STISR |= STISR_XMITIR;
-+
-+
-+
-+ disable_irq(dev->irq);
-+
-+ do
-+ {
-+
-+ if (STLSR & LSR_TDRQ)
-+ {
-+ STTHR = *si->tx_buff.data++;
-+ si->tx_buff.len -= 1;
-+
-+ tx_count++;
-+ }
-+
-+
-+ } while (si->tx_buff.len);
-+
-+
-+ if (si->tx_buff.len == 0)
-+ {
-+
-+
-+ si->stats.tx_packets++;
-+ si->stats.tx_bytes += si->tx_buff.data -
-+ si->tx_buff.head;
-+
-+ /*
-+ * We need to ensure that the transmitter has
-+ * finished.
-+ */
-+
-+ do
-+ {
-+ udelay(1);
-+
-+ }
-+ while ( ! (STLSR & LSR_TEMT) );
-+
-+
-+ /*
-+
-+ * Ok, we've finished transmitting. Now enable
-+ * the receiver. Sometimes we get a receive IRQ
-+ * immediately after a transmit...
-+ */
-+
-+ if (si->newspeed)
-+ {
-+ pxa250_irda_set_speed(dev, si->newspeed);
-+ si->newspeed = 0;
-+ }
-+
-+ /* I'm hungry! */
-+ netif_wake_queue(dev);
-+ }
-+
-+ enable_irq (dev->irq);
-+ STIER = (IER_RAVIE | IER_UUE | IER_RTIOE);
-+
-+ STISR |= STISR_RCVEIR;
-+// STISR &= ~STISR_XMITIR;
-+ }
-+}
-+
-+static void pxa250_irda_hpsir_irq(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ /*
-+ * Deal with any receive errors first. The bytes in error may be
-+ * the only bytes in the receive FIFO, so we do this first.
-+ */
-+ __ECHO_IN;
-+
-+ while (STLSR & LSR_FIFOE)
-+ {
-+ int stat, data;
-+
-+ stat = STLSR;
-+ data = STRBR;
-+
-+
-+ if (stat & (LSR_FE | LSR_OE | LSR_PE))
-+
-+ {
-+ si->stats.rx_errors++;
-+ if (stat & LSR_FE)
-+ si->stats.rx_frame_errors++;
-+ if (stat & LSR_OE)
-+ si->stats.rx_fifo_errors++;
-+
-+ } else
-+ {
-+ rx_count++;
-+ async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
-+ }
-+
-+ }
-+
-+ /*
-+ * We must clear certain bits.
-+ */
-+
-+ if (STLSR & (LSR_DR))
-+ {
-+ /*
-+ * Fifo contains at least 1 character.
-+ */
-+ do
-+ {
-+ int data;
-+
-+ data = STRBR;
-+
-+ async_unwrap_char(dev, &si->stats, &si->rx_buff,
-+ data); /* was Ser2UTDR); Clo */
-+ rx_count++;
-+
-+ } while (STLSR & LSR_DR);
-+
-+ dev->last_rx = jiffies;
-+ }
-+
-+ __ECHO_OUT;
-+}
-+
-+static void pxa250_sir_irda_shutdown(struct pxa250_irda *si)
-+{
-+
-+ STIER = 0;
-+ STFCR = 0;
-+ STISR = 0;
-+ CKEN &= ~CKEN5_STUART;
-+}
-+
-+
-+/************************************************************************************/
-+
-+/*Low level init/uninstall function PM control and IrDA protocol stack registration */
-+
-+/*
-+ * Set the IrDA communications speed.
-+ * Interrupt have to be disabled here.
-+ */
-+
-+static int pxa250_irda_startup(struct net_device *dev)
-+{
-+
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Ensure that the ports for this device are setup correctly.
-+ */
-+
-+
-+ set_GPIO_mode (GPIO46_STRXD_MD);
-+ set_GPIO_mode (GPIO47_STTXD_MD);
-+
-+ STMCR = MCR_OUT2;
-+ STLCR = LCR_WLS1 | LCR_WLS0;
-+
-+ SET_SIR_MODE;
-+ CKEN |= CKEN5_STUART;
-+ /* enable irq from stuart */
-+ ICMR |= ( 1 << 20 );
-+
-+ /*reset FIFO*/
-+
-+/* STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF;// | FCR_ITL_16;
-+
-+ STIER = IER_UUE | IER_RAVIE | IER_RTOIE;
-+*/
-+ __ECHO_OUT;
-+
-+ return 0;
-+
-+}
-+
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Suspend the IrDA interface.
-+ */
-+
-+static int pxa250_irda_shutdown(struct pxa250_irda *si)
-+{
-+
-+ pxa250_sir_irda_shutdown(si);
-+ return 0;
-+
-+}
-+
-+
-+static int pxa250_irda_suspend(struct net_device *dev, int state)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ if (si && si->open) {
-+ /*
-+ * Stop the transmit queue
-+ */
-+ if (IS_FIR(si))
-+ return -1;
-+
-+ netif_stop_queue(dev);
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+ pxa250_sir_irda_shutdown(si);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Resume the IrDA interface.
-+ */
-+
-+static int pxa250_irda_resume(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ __ECHO_IN;
-+
-+ if (si && si->open) {
-+ /*
-+ * If we missed a speed change, initialise at the new speed
-+ * directly. It is debatable whether this is actually
-+ * required, but in the interests of continuing from where
-+ * we left off it is desireable. The converse argument is
-+ * that we should re-negotiate at 9600 baud again.
-+ */
-+ if (si->newspeed) {
-+ si->speed = si->newspeed;
-+ si->newspeed = 0;
-+ }
-+
-+ pxa250_irda_startup(dev);
-+ enable_irq(dev->irq);
-+
-+ /*
-+ * This automatically wakes up the queue
-+ */
-+ netif_wake_queue(dev);
-+ pxa250_irda_set_speed(dev,si->speed = 9600);
-+
-+ }
-+
-+ __ECHO_OUT;
-+ return 0;
-+}
-+
-+static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ int ret;
-+
-+
-+ if (!dev->data)
-+ return -EINVAL;
-+
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ ret = pxa250_irda_suspend((struct net_device *)dev->data,
-+ (int)data);
-+ break;
-+
-+ case PM_RESUME:
-+ ret = pxa250_irda_resume((struct net_device *)dev->data);
-+ break;
-+
-+ default:
-+
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+#endif
-+
-+
-+
-+
-+static void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+
-+ pxa250_irda_hpsir_irq(dev);
-+
-+}
-+
-+
-+static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int speed = irda_get_next_speed(skb);
-+ int mtt;
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Does this packet contain a request to change the interface
-+ * speed? If so, remember it until we complete the transmission
-+ * of this frame.
-+ */
-+ if (speed != si->speed && speed != -1)
-+ si->newspeed = speed;
-+
-+ /*
-+ * If this is an empty frame, we can bypass a lot.
-+ */
-+ if (skb->len == 0) {
-+ if (si->newspeed) {
-+ si->newspeed = 0;
-+ pxa250_irda_set_speed(dev, speed);
-+ }
-+ dev_kfree_skb(skb);
-+ return 0;
-+ }
-+
-+
-+ DBG("stop queue\n");
-+ netif_stop_queue(dev);
-+
-+ if(!IS_FIR(si))
-+ {
-+
-+ si->tx_buff.data = si->tx_buff.head;
-+ si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
-+ si->tx_buff.truesize);
-+
-+
-+ pxa250_sir_transmit(dev);
-+
-+
-+
-+ dev_kfree_skb(skb);
-+
-+ dev->trans_start = jiffies;
-+
-+ return 0;
-+ }
-+ else /* FIR */
-+ {
-+ DBG("Enter FIR transmit\n");
-+ /*
-+ * We must not be transmitting...
-+ */
-+ if (si->txskb)
-+ BUG();
-+
-+ disable_irq(si->fir_irq);
-+
-+ netif_stop_queue(dev);
-+ DBG("queue stoped\n");
-+ si->txskb = skb;
-+
-+ /* we could not just map so we'll need some triks */
-+ /* skb->data may be not DMA capable -Sed- */
-+
-+
-+ if (skb->len > TXBUFF_MAX_SIZE)
-+ {
-+ printk (KERN_ERR "skb data too large\n");
-+ printk (KERN_ERR "len=%d",skb->len);
-+ BUG();
-+ }
-+
-+
-+ DBG("gonna copy %d bytes to txbuf\n",skb->len);
-+
-+ memcpy (si->txbuf_dma_virt, skb->data , skb->len);
-+
-+ /* Actual sending ;must not be receiving !!! */
-+ /* Write data and source address */
-+
-+ DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 );
-+
-+ /*Disable receiver and enable transifer */
-+ ICCR0 &= ~ICCR0_RXE;
-+
-+ if (ICSR1 & ICSR1_TBY)
-+ BUG();
-+
-+ ICCR0 |= ICCR0_TXE;
-+
-+ DBG("FICP status %x\n",ICSR0);
-+
-+ if (0){
-+ int i;
-+
-+ DBG("sending packet\n");
-+ for (i=0;i<skb->len;i++)
-+ (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ;
-+ DBG(" done\n");
-+
-+ }
-+ /*
-+ * If we have a mean turn-around time, impose the specified
-+ * specified delay. We could shorten this by timing from
-+ * the point we received the packet.
-+ */
-+
-+ mtt = irda_get_mtt(skb);
-+ if(mtt)
-+ udelay(mtt);
-+
-+ DCSR(si->txdma_ch)=0;
-+ DCSR(si->txdma_ch)=DCSR_NODESC;
-+ DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */
-+ DTADR(si->txdma_ch) = __PREG(ICDR);
-+
-+ DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len;
-+
-+ DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;
-+ DCSR(si->txdma_ch) = DCSR_RUN | DCSR_NODESC ;
-+
-+ DBG("FICP status %x\n",ICSR0);
-+
-+ return 0;
-+ }
-+
-+}
-+
-+static int
-+pxa250_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
-+{
-+ struct if_irda_req *rq = (struct if_irda_req *)ifreq;
-+ struct pxa250_irda *si = dev->priv;
-+ int ret = -EOPNOTSUPP;
-+
-+ __ECHO_IN;
-+
-+ switch (cmd) {
-+ case SIOCSBANDWIDTH:
-+ if (capable(CAP_NET_ADMIN)) {
-+ /*
-+ * We are unable to set the speed if the
-+ * device is not running.
-+ */
-+ if (si->open) {
-+ ret = pxa250_irda_set_speed(dev,
-+ rq->ifr_baudrate);
-+ } else {
-+ printk("pxa250_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
-+ ret = 0;
-+ }
-+ }
-+ break;
-+
-+ case SIOCSMEDIABUSY:
-+ ret = -EPERM;
-+ if (capable(CAP_NET_ADMIN)) {
-+ irda_device_set_media_busy(dev, TRUE);
-+ ret = 0;
-+ }
-+ break;
-+
-+ case SIOCGRECEIVING:
-+ rq->ifr_receiving = IS_FIR(si) ? 0
-+ : si->rx_buff.state != OUTSIDE_FRAME;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ __ECHO_OUT;
-+
-+ return ret;
-+}
-+
-+static struct net_device_stats *pxa250_irda_stats(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ return &si->stats;
-+}
-+
-+static int pxa250_irda_start(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int err;
-+ unsigned int flags;
-+
-+
-+ MOD_INC_USE_COUNT;
-+
-+ __ECHO_IN;
-+ si->speed = 9600;
-+
-+ local_irq_save(flags);
-+
-+ err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0, dev->name, dev);
-+ if (err)
-+ goto err_fir_irq;
-+
-+ err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev);
-+ if (err)
-+ goto err_irq;
-+
-+ /*
-+ * The interrupt must remain disabled for now.
-+ */
-+
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+
-+ local_irq_restore(flags);
-+
-+
-+ /* Allocate DMA channel for receiver (not used) */
-+ err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev);
-+ if (err < 0 )
-+ goto err_rx_dma;
-+ si->rxdma_ch=err;
-+
-+ DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch;
-+
-+
-+ /* Allocate DMA channel for transmit */
-+ err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev);
-+ if (err < 0 )
-+ goto err_tx_dma;
-+
-+ si->txdma_ch=err;
-+
-+ /*
-+ * Make sure that ICP will be able
-+ * to assert the transmit dma request bit
-+ * through the peripherals request bus (PREQ)
-+ */
-+
-+ DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch;
-+
-+ DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch);
-+
-+ /* allocate consistent buffers for dma access
-+ * buffers have to be aligned and situated in dma capable memory region;
-+ */
-+ si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma);
-+ if (! si->rxbuf_dma_virt )
-+ goto err_rxbuf_dma;
-+
-+ si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN, &si->txbuf_dma);
-+ if (! si->txbuf_dma_virt )
-+ goto err_txbuf_dma;
-+
-+ /* Alocate skb for receiver */
-+ err=pxa250_irda_rx_alloc(si);
-+ if (err)
-+ goto err_rx_alloc;
-+
-+ /*
-+ * Setup the serial port for the specified config.
-+ */
-+ err = pxa250_irda_startup(dev);
-+ if (err)
-+ goto err_startup;
-+
-+ pxa250_irda_set_speed(dev,si->speed = 9600);
-+
-+
-+ /*
-+ * Open a new IrLAP layer instance.
-+ */
-+ si->irlap = irlap_open(dev, &si->qos, "pxa250");
-+ err = -ENOMEM;
-+ if (!si->irlap)
-+ goto err_irlap;
-+
-+ /*
-+ * Now enable the interrupt and start the queue
-+ */
-+ si->open = 1;
-+ enable_irq(dev->irq);
-+ netif_start_queue(dev);
-+ return 0;
-+
-+err_irlap:
-+ si->open = 0;
-+ pxa250_sir_irda_shutdown(si);
-+err_startup:
-+ dev_kfree_skb(si->rxskb);
-+err_rx_alloc:
-+ consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
-+err_txbuf_dma:
-+ consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
-+err_rxbuf_dma:
-+ pxa_free_dma(si->txdma_ch);
-+err_tx_dma:
-+ pxa_free_dma(si->rxdma_ch);
-+err_rx_dma:
-+ free_irq(dev->irq, dev);
-+err_irq:
-+ free_irq(si->fir_irq, dev);
-+err_fir_irq:
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+static int pxa250_irda_stop(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ printk(KERN_ERR "Irda stop... RX = %d TX = %d\n",rx_count,tx_count);
-+
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+/* pxa250_irda_shutdown(si); */
-+
-+ /*
-+ * If we have been doing DMA receive, make sure we
-+ * tidy that up cleanly.
-+ */
-+ if (si->rxskb) {
-+ dev_kfree_skb(si->rxskb);
-+ si->rxskb = NULL;
-+ }
-+
-+ /* Stop IrLAP */
-+ if (si->irlap) {
-+ irlap_close(si->irlap);
-+ si->irlap = NULL;
-+ }
-+
-+ consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
-+ consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
-+ pxa_free_dma(si->txdma_ch);
-+ pxa_free_dma(si->rxdma_ch);
-+
-+ netif_stop_queue(dev);
-+ si->open = 0;
-+
-+ /*
-+ * Free resources
-+ */
-+ free_irq(dev->irq, dev);
-+ free_irq(si->fir_irq, dev);
-+
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+static int pxa250_irda_init_iobuf(iobuff_t *io, int size)
-+{
-+ io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
-+ if (io->head != NULL) {
-+ io->truesize = size;
-+ io->in_frame = FALSE;
-+ io->state = OUTSIDE_FRAME;
-+ io->data = io->head;
-+ }
-+ return io->head ? 0 : -ENOMEM;
-+}
-+
-+
-+
-+
-+static int pxa250_stop_fir(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ unsigned int flag;
-+
-+ save_flags(flag);
-+ cli();
-+
-+ pxa250_dma_stop(si->txdma_ch);
-+ pxa250_dma_stop(si->rxdma_ch);
-+
-+ if (si->txskb)
-+ dev_kfree_skb_irq(si->txskb);
-+
-+ ICCR0 &= ~(ICCR0_RXE | ICCR0_TXE );
-+ disable_irq(si->fir_irq);
-+ CKEN &= ~CKEN13_FICP;
-+
-+ restore_flags(flag);
-+
-+ return 0;
-+}
-+
-+
-+
-+static int pxa250_irda_set_speed(struct net_device *dev, int speed)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int brd, ret = -EINVAL;
-+ static int last_fir_speed=0;
-+
-+ __ECHO_IN;
-+
-+
-+
-+ switch (speed) {
-+ case 9600: case 19200: case 38400:
-+ case 57600: case 115200:
-+
-+ /* Baud rate fixed - Clo */
-+
-+ /*
-+ * FIXME
-+ */
-+ if (last_fir_speed)
-+ {
-+
-+ pxa250_stop_fir(dev);
-+ set_GPIO_mode (GPIO46_STRXD_MD);
-+ set_GPIO_mode (GPIO47_STTXD_MD);
-+
-+ enable_irq(dev->irq);
-+ netif_wake_queue(dev);
-+ last_fir_speed=0;
-+ }
-+
-+
-+ LUB_MISC_WR &= ~(1 << 4);
-+
-+ brd = 14745600 / (16 * speed);
-+
-+ STLCR |= LCR_DLAB;
-+
-+ STDLH = brd >> 8; /* Clo: set Divisor Latch High */
-+ STDLL = brd & 0xFF; /* Clo: set Devisor Latch Low */
-+
-+ STLCR &= ~LCR_DLAB; /* Clo: clear DLAB bit */
-+
-+ STMCR = MCR_OUT2;
-+
-+ CKEN |= CKEN5_STUART;
-+
-+ ICMR |= ( 1 << 20 );
-+
-+ STLCR = LCR_WLS1 | LCR_WLS0;
-+
-+ SET_SIR_MODE;
-+
-+ STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF | FCR_ITL_1 ;// | FCR_ITL_16;
-+
-+ STIER = IER_UUE | IER_RAVIE | IER_RTIOE;
-+
-+ si->speed = speed;
-+
-+ ret = 0;
-+ break;
-+
-+ case 4000000:
-+
-+ if (last_fir_speed)
-+ goto speed_out;
-+
-+ disable_irq(dev->irq);
-+
-+ pxa250_sir_irda_shutdown(si);
-+ pxa250_fir_irda_startup(si);
-+ pxa250_irda_rx_alloc(si);
-+ ICCR0=0;
-+ pxa250_start_rx_dma(dev);
-+ pxa250_ficp_rx_start();
-+
-+ enable_irq(si->fir_irq);
-+ DBG("enable FIR \n");
-+ si->speed = speed;
-+
-+ netif_wake_queue(dev);
-+ last_fir_speed=1;
-+speed_out:
-+
-+ ret=0;
-+
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ __ECHO_OUT;
-+
-+ return ret;
-+}
-+
-+
-+static int pxa250_irda_net_init(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ unsigned int baudrate_mask;
-+ int err = -ENOMEM;
-+
-+ si = kmalloc(sizeof(struct pxa250_irda), GFP_KERNEL);
-+ if (!si)
-+ goto out;
-+
-+ memset(si, 0, sizeof(*si));
-+
-+ /*
-+ * Initialise the HP-SIR buffers
-+ */
-+
-+ err = pxa250_irda_init_iobuf(&si->rx_buff, 14384);
-+ if (err)
-+ goto out;
-+ err = pxa250_irda_init_iobuf(&si->tx_buff, 4000);
-+ if (err)
-+ goto out_free_rx;
-+
-+ si->fir_irq = IRQ_ICP;
-+ dev->priv = si;
-+ dev->hard_start_xmit = pxa250_irda_hard_xmit;
-+ dev->open = pxa250_irda_start;
-+ dev->stop = pxa250_irda_stop;
-+ dev->do_ioctl = pxa250_irda_ioctl;
-+ dev->get_stats = pxa250_irda_stats;
-+
-+ irda_device_setup(dev);
-+ irda_init_max_qos_capabilies(&si->qos);
-+
-+ /*
-+ * We support original IRDA up to 115k2. (we don't currently
-+ * support 4Mbps). Min Turn Time set to 1ms or greater.
-+ */
-+ baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-+ baudrate_mask |= IR_4000000 << 8;
-+ si->qos.baud_rate.bits &= baudrate_mask;
-+ si->qos.min_turn_time.bits = 7;
-+
-+ irda_qos_bits_to_value(&si->qos);
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Power-Management is optional.
-+ */
-+ si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, pxa250_irda_pmproc);
-+ if (si->pmdev)
-+ si->pmdev->data = dev;
-+#endif
-+
-+ return 0;
-+
-+ kfree(si->tx_buff.head);
-+out_free_rx:
-+ kfree(si->rx_buff.head);
-+out:
-+ kfree(si);
-+
-+ return err;
-+}
-+
-+/*
-+ * Remove all traces of this driver module from the kernel, so we can't be
-+ * called. Note that the device has already been stopped, so we don't have
-+ * to worry about interrupts or dma.
-+ */
-+static void pxa250_irda_net_uninit(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ dev->hard_start_xmit = NULL;
-+ dev->open = NULL;
-+ dev->stop = NULL;
-+ dev->do_ioctl = NULL;
-+ dev->get_stats = NULL;
-+ dev->priv = NULL;
-+
-+ pm_unregister(si->pmdev);
-+
-+ kfree(si->tx_buff.head);
-+ kfree(si->rx_buff.head);
-+ kfree(si);
-+}
-+
-+static int __init pxa250_irda_init(void)
-+{
-+ struct net_device *dev;
-+ int err;
-+
-+ /* STUART */
-+ err = request_mem_region(__PREG(STRBR), 0x24, "IrDA") ? 0 : -EBUSY;
-+ if (err)
-+ goto err_mem_1;
-+
-+ /* FIR */
-+ err = request_mem_region(__PREG(ICCR0), 0x1c, "IrDA") ? 0 : -EBUSY;
-+ if (err)
-+ goto err_mem_2;
-+
-+
-+ rtnl_lock();
-+ dev = dev_alloc("irda%d", &err);
-+ if (dev) {
-+ dev->irq = IRQ_STUART;
-+ dev->init = pxa250_irda_net_init;
-+ dev->uninit = pxa250_irda_net_uninit;
-+
-+ err = register_netdevice(dev);
-+
-+ if (err)
-+ kfree(dev);
-+ else
-+ netdev = dev;
-+ }
-+ rtnl_unlock();
-+
-+ if (err) {
-+ release_mem_region(__PREG(ICCR0), 0x1c);
-+err_mem_2:
-+ release_mem_region(__PREG(STRBR), 0x24);
-+ }
-+err_mem_1:
-+ return err;
-+}
-+
-+static void __exit pxa250_irda_exit(void)
-+{
-+ struct net_device *dev = netdev;
-+
-+ netdev = NULL;
-+ if (dev) {
-+ rtnl_lock();
-+ unregister_netdevice(dev);
-+ rtnl_unlock();
-+ }
-+
-+ release_mem_region(__PREG(ICCR0), 0x1c);
-+
-+ release_mem_region(__PREG(STRBR), 0x24);
-+
-+ /*
-+ * We now know that the netdevice is no longer in use, and all
-+ * references to our driver have been removed. The only structure
-+ * which may still be present is the netdevice, which will get
-+ * cleaned up by net/core/dev.c
-+ */
-+}
-+
-+module_init(pxa250_irda_init);
-+module_exit(pxa250_irda_exit);
-+
-+MODULE_AUTHOR("Alexey Lugovskoy Frasenyak Dmitrij");
-+MODULE_DESCRIPTION("PXA250 SIR/FIR");
-+MODULE_LICENSE("GPL");
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/net/smc91x.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,2123 @@
-+/*------------------------------------------------------------------------
-+ . smc91x.c
-+ . This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices.
-+ .
-+ . Copyright (C) 1996 by Erik Stahlman
-+ . Copyright (C) 2001 Standard Microsystems Corporation
-+ . Developed by Simple Network Magic Corporation
-+ . Copyright (C) 2003 Monta Vista Software, Inc.
-+ . Unified SMC91x driver by Nicolas Pitre
-+ .
-+ . This program is free software; you can redistribute it and/or modify
-+ . it under the terms of the GNU General Public License as published by
-+ . the Free Software Foundation; either version 2 of the License, or
-+ . (at your option) any later version.
-+ .
-+ . This program is distributed in the hope that it will be useful,
-+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ . GNU General Public License for more details.
-+ .
-+ . You should have received a copy of the GNU General Public License
-+ . along with this program; if not, write to the Free Software
-+ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ .
-+ . Arguments:
-+ . io = for the base address
-+ . irq = for the IRQ
-+ . nowait = 0 for normal wait states, 1 eliminates additional wait states
-+ .
-+ . original author:
-+ . Erik Stahlman <erik@vt.edu>
-+ .
-+ . hardware multicast code:
-+ . Peter Cammaert <pc@denkart.be>
-+ .
-+ . contributors:
-+ . Daris A Nevil <dnevil@snmc.com>
-+ . Nicolas Pitre <nico@cam.org>
-+ .
-+ . History:
-+ . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
-+ . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
-+ . 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111
-+ . 08/22/01 Scott Anderson merge changes from smc9194 to smc91111
-+ . 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111
-+ . 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support
-+ . 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races,
-+ . more bus abstraction, big cleanup, etc.
-+ ----------------------------------------------------------------------------*/
-+
-+static const char version[] =
-+ "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
-+
-+/* Debugging level */
-+#ifndef SMC_DEBUG
-+#define SMC_DEBUG 0
-+#endif
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/timer.h>
-+#include <linux/errno.h>
-+#include <linux/ioport.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#ifdef CONFIG_PM
-+#include <linux/pm.h>
-+#endif
-+
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include "smc91x.h"
-+
-+
-+#ifdef CONFIG_ISA
-+/*
-+ . the LAN91C111 can be at any of the following port addresses. To change,
-+ . for a slightly different card, you can add it to the array. Keep in
-+ . mind that the array must end in zero.
-+*/
-+static unsigned int smc_portlist[] __initdata = {
-+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
-+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
-+};
-+#endif /* CONFIG_ISA */
-+
-+#ifndef SMC_IOADDR
-+# define SMC_IOADDR -1
-+#endif
-+static int io = SMC_IOADDR;
-+
-+#ifndef SMC_IRQ
-+# define SMC_IRQ -1
-+#endif
-+static int irq = SMC_IRQ;
-+
-+#ifndef SMC_NOWAIT
-+# define SMC_NOWAIT 0
-+#endif
-+static int nowait = SMC_NOWAIT;
-+
-+MODULE_PARM(io, "i");
-+MODULE_PARM(irq, "i");
-+MODULE_PARM(nowait, "i");
-+MODULE_PARM_DESC(io, "I/O base address");
-+MODULE_PARM_DESC(irq, "IRQ number");
-+MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
-+
-+
-+/*------------------------------------------------------------------------
-+ .
-+ . The internal workings of the driver. If you are changing anything
-+ . here with the SMC stuff, you should have the datasheet and know
-+ . what you are doing.
-+ .
-+ -------------------------------------------------------------------------*/
-+#define CARDNAME "LAN91x"
-+
-+// Use power-down feature of the chip
-+#define POWER_DOWN 1
-+
-+/*
-+ . Wait time for memory to be free. This probably shouldn't be
-+ . tuned that much, as waiting for this means nothing else happens
-+ . in the system
-+*/
-+#define MEMORY_WAIT_TIME 16
-+
-+/*
-+ . This selects whether TX packets are sent one by one to the SMC91x internal
-+ . memory ans throttled until transmission completes. This may prevent
-+ . RX overruns a litle by keeping much of the memory free for RX packets
-+ . but to the expense of reduced TX throughput and increased IRQ overhead.
-+ . Note this is not a cure for a too slow data bus or too high IRQ latency.
-+ */
-+#define THROTTLE_TX_PKTS 0
-+
-+
-+/* store this information for the driver.. */
-+struct smc_local {
-+
-+ // If I have to wait until memory is available to send
-+ // a packet, I will store the skbuff here, until I get the
-+ // desired memory. Then, I'll send it out and free it.
-+ struct sk_buff *saved_skb;
-+
-+ // these are things that the kernel wants me to keep, so users
-+ // can find out semi-useless statistics of how well the card is
-+ // performing
-+ struct net_device_stats stats;
-+
-+ // version/revision of the SMC91x chip
-+ int version;
-+
-+ // Set to true during the auto-negotiation sequence
-+ int autoneg_active;
-+
-+ // Address of our PHY port
-+ int phyaddr;
-+
-+ // Type of PHY
-+ int phytype;
-+
-+ // Last contents of PHY Register 18
-+ int lastPhy18;
-+
-+ // Contains the current active transmission mode
-+ int tcr_cur_mode;
-+
-+ // Contains the current active receive mode
-+ int rcr_cur_mode;
-+
-+ // Contains the current active receive/phy mode
-+ int rpc_cur_mode;
-+ int ctl_autoneg;
-+ int ctl_rfduplx;
-+ int ctl_rspeed;
-+
-+#ifdef CONFIG_PM
-+ struct pm_dev* pm;
-+#endif
-+
-+};
-+
-+
-+#if SMC_DEBUG > 2
-+#define PRINTK3(args...) printk(args)
-+#else
-+#define PRINTK3(args...) do { } while(0)
-+#endif
-+
-+#if SMC_DEBUG > 1
-+#define PRINTK2(args...) printk(args)
-+#else
-+#define PRINTK2(args...) do { } while(0)
-+#endif
-+
-+#if SMC_DEBUG > 0
-+#define PRINTK1(args...) printk(args)
-+#define PRINTK(args...) printk(args)
-+#else
-+#define PRINTK1(args...) do { } while(0)
-+#define PRINTK(args...) printk(KERN_DEBUG args)
-+#endif
-+
-+#if SMC_DEBUG > 3
-+static void PRINT_PKT(u_char *buf, int length)
-+{
-+ int i;
-+ int remainder;
-+ int lines;
-+
-+ lines = length / 16;
-+ remainder = length % 16;
-+
-+ for (i = 0; i < lines ; i ++) {
-+ int cur;
-+ for (cur = 0; cur < 8; cur++) {
-+ u_char a, b;
-+ a = *buf++;
-+ b = *buf++;
-+ printk("%02x%02x ", a, b);
-+ }
-+ printk("\n");
-+ }
-+ for (i = 0; i < remainder/2 ; i++) {
-+ u_char a, b;
-+ a = *buf++;
-+ b = *buf++;
-+ printk("%02x%02x ", a, b );
-+ }
-+ printk("\n");
-+}
-+#else
-+#define PRINT_PKT(x...) do { } while(0)
-+#endif
-+
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) do { \
-+ unsigned long flags; \
-+ unsigned char mask; \
-+ local_irq_save(flags); \
-+ mask = SMC_GET_INT_MASK(); \
-+ mask |= (x); \
-+ SMC_SET_INT_MASK(mask); \
-+ local_irq_restore(flags); \
-+} while (0)
-+
-+/* this disables an interrupt from the interrupt mask register */
-+#define SMC_DISABLE_INT(x) do { \
-+ unsigned long flags; \
-+ unsigned char mask; \
-+ local_irq_save(flags); \
-+ mask = SMC_GET_INT_MASK(); \
-+ mask &= ~(x); \
-+ SMC_SET_INT_MASK(mask); \
-+ local_irq_restore(flags); \
-+} while (0)
-+
-+/* wait while MMU is busy */
-+#define SMC_WAIT_MMU_BUSY() do { \
-+ if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \
-+ unsigned long timeout = jiffies + 2; \
-+ while (SMC_GET_MMU_CMD() & MC_BUSY) { \
-+ if (time_after(jiffies, timeout)) { \
-+ printk("%s: timeout %s line %d\n", \
-+ dev->name, __FILE__, __LINE__); \
-+ break; \
-+ } \
-+ } \
-+ } \
-+} while (0)
-+
-+
-+/* this does a soft reset on the device */
-+static void
-+smc_reset(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int status;
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* This resets the registers mostly to defaults, but doesn't
-+ affect EEPROM. That seems unnecessary */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_SOFTRST );
-+
-+ /* Setup the Configuration Register */
-+ /* This is necessary because the CONFIG_REG is not affected */
-+ /* by a soft reset */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( CONFIG_DEFAULT );
-+
-+ /* Setup for fast accesses if requested */
-+ /* If the card/system can't handle it then there will */
-+ /* be no recovery except for a hard reset or power cycle */
-+ if (nowait)
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT );
-+
-+#ifdef POWER_DOWN
-+ /* Release from possible power-down state */
-+ /* Configuration register is not affected by Soft Reset */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN );
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+ status &= ~PHY_CNTL_PDN;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+#endif
-+
-+ /* this should pause enough for the chip to be happy */
-+ udelay(1);
-+
-+ /* Disable transmit and receive functionality */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_CLEAR );
-+ SMC_SET_TCR( TCR_CLEAR );
-+
-+ /* set the control register to automatically
-+ release successfully transmitted packets, to make the best
-+ use out of our limited memory */
-+ SMC_SELECT_BANK( 1 );
-+#if ! THROTTLE_TX_PKTS
-+ SMC_SET_CTL( SMC_GET_CTL() | CTL_AUTO_RELEASE );
-+#else
-+ SMC_SET_CTL( SMC_GET_CTL() & ~CTL_AUTO_RELEASE );
-+#endif
-+
-+ /* Disable all interrupts */
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* Reset the MMU */
-+ SMC_SET_MMU_CMD( MC_RESET );
-+ SMC_WAIT_MMU_BUSY();
-+}
-+
-+/* Enable Interrupts, Receive, and Transmit */
-+static void
-+smc_enable(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int mask;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* see the header file for options in TCR/RCR DEFAULT*/
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+
-+ /* now, enable interrupts */
-+ mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
-+ if (lp->version >= 0x70)
-+ mask |= IM_MDINT;
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( mask );
-+}
-+
-+/* this puts the device in an inactive state */
-+static void
-+smc_shutdown(struct net_device *dev)
-+{
-+ int ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int status;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ /* no more interrupts for me */
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* and tell the card to stay away from that nasty outside world */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_CLEAR );
-+ SMC_SET_TCR( TCR_CLEAR );
-+
-+#ifdef POWER_DOWN
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+ status |= PHY_CNTL_PDN;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+
-+ /* finally, shut the chip down */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN );
-+#endif
-+}
-+
-+/* This is the procedure to handle the receipt of a packet. */
-+static inline void
-+smc_rcv(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ unsigned int packet_number, status, packet_len;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ packet_number = SMC_GET_RXFIFO();
-+ if (unlikely(packet_number & RXFIFO_REMPTY)) {
-+ PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
-+ return;
-+ }
-+
-+ /* read from start of packet */
-+ SMC_SET_PTR( PTR_READ | PTR_RCV | PTR_AUTOINC );
-+
-+ /* First two words are status and packet length */
-+ SMC_GET_PKT_HDR(status, packet_len);
-+ packet_len &= 0x07ff; /* mask off top bits */
-+ PRINTK2("%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
-+ dev->name, packet_number, status,
-+ packet_len, packet_len);
-+
-+ if (unlikely(status & RS_ERRORS)) {
-+ lp->stats.rx_errors++;
-+ if (status & RS_ALGNERR)
-+ lp->stats.rx_frame_errors++;
-+ if (status & (RS_TOOSHORT | RS_TOOLONG))
-+ lp->stats.rx_length_errors++;
-+ if (status & RS_BADCRC)
-+ lp->stats.rx_crc_errors++;
-+ } else {
-+ struct sk_buff *skb;
-+ unsigned char *data;
-+ unsigned int data_len;
-+
-+ /* set multicast stats */
-+ if (status & RS_MULTICAST)
-+ lp->stats.multicast++;
-+
-+ /*
-+ * Actual payload is packet_len - 4 (or 3 if odd byte).
-+ * We want skb_reserve(2) and the final ctrl word
-+ * (2 bytes, possibly containing the payload odd byte).
-+ * Ence packet_len - 4 + 2 + 2.
-+ */
-+ skb = dev_alloc_skb(packet_len);
-+ if (unlikely(skb == NULL)) {
-+ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-+ dev->name);
-+ lp->stats.rx_dropped++;
-+ goto done;
-+ }
-+
-+ /* Align IP header to 32 bits */
-+ skb_reserve(skb, 2);
-+
-+ /* BUG: the LAN91C111 rev A never sets this bit. Force it. */
-+ if (lp->version == 0x90)
-+ status |= RS_ODDFRAME;
-+
-+ /*
-+ * If odd length: packet_len - 3,
-+ * otherwise packet_len - 4.
-+ */
-+ data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4);
-+ data = skb_put(skb, data_len);
-+ SMC_PULL_DATA(data, packet_len - 2);
-+
-+ PRINT_PKT(data, packet_len - 2);
-+
-+ dev->last_rx = jiffies;
-+ skb->dev = dev;
-+ skb->protocol = eth_type_trans(skb, dev);
-+ netif_rx(skb);
-+ lp->stats.rx_packets++;
-+ lp->stats.rx_bytes += data_len;
-+ }
-+
-+done:
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_MMU_CMD( MC_RELEASE );
-+}
-+
-+/*
-+ * This is called to actually send a packet to the chip.
-+ * Returns non-zero when successful.
-+ */
-+static void
-+smc_hardware_send_packet(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ struct sk_buff *skb = lp->saved_skb;
-+ unsigned int packet_no, len;
-+ unsigned char *buf;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ if (unlikely(!skb)) {
-+ printk ("%s: In XMIT with no packet to send\n", dev->name);
-+ return;
-+ }
-+
-+ packet_no = SMC_GET_AR();
-+ if (unlikely(packet_no & AR_FAILED)) {
-+ printk("%s: Memory allocation failed.\n", dev->name);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_fifo_errors++;
-+ dev_kfree_skb_any(skb);
-+ return;
-+ }
-+
-+ /* point to the beginning of the packet */
-+ SMC_SET_PN( packet_no );
-+ SMC_SET_PTR( PTR_AUTOINC );
-+
-+ buf = skb->data;
-+ len = skb->len;
-+ PRINTK2("%s: TX PNR 0x%x lENGTH 0x%04x (%d) BUF 9x%p\n",
-+ dev->name, packet_no, len, len, buf);
-+ PRINT_PKT(buf, len);
-+
-+ /*
-+ * Send the packet length ( +6 for status words, length, and ctl.
-+ * The card will pad to 64 bytes with zeroes if packet is too small.
-+ */
-+ SMC_PUT_PKT_HDR(0, len + 6);
-+
-+ /* send the actual data */
-+ SMC_PUSH_DATA(buf, len & ~1);
-+
-+ /* Send final ctl word with the last byte if there is one */
-+ SMC_outw( ((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG );
-+
-+ /* and let the chipset deal with it */
-+ SMC_SET_MMU_CMD( MC_ENQUEUE );
-+ SMC_ACK_INT( IM_TX_EMPTY_INT );
-+
-+ dev->trans_start = jiffies;
-+ dev_kfree_skb_any(skb);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_packets++;
-+ lp->stats.tx_bytes += len;
-+}
-+
-+/*
-+ . Since I am not sure if I will have enough room in the chip's ram
-+ . to store the packet, I call this routine which either sends it
-+ . now, or set the card to generates an interrupt when ready
-+ . for the packet.
-+ */
-+static int
-+smc_hard_start_xmit( struct sk_buff * skb, struct net_device * dev )
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ unsigned int numPages, poll_count, status, saved_bank;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ if (unlikely(lp->saved_skb != NULL)) {
-+ /* THIS SHOULD NEVER HAPPEN. */
-+ printk( KERN_CRIT
-+ "%s: Bad Craziness - sent packet while busy.\n",
-+ dev->name );
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_aborted_errors++;
-+ return 1;
-+ }
-+ lp->saved_skb = skb;
-+
-+ /*
-+ ** The MMU wants the number of pages to be the number of 256 bytes
-+ ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
-+ **
-+ ** The 91C111 ignores the size bits, but the code is left intact
-+ ** for backwards and future compatibility.
-+ **
-+ ** Pkt size for allocating is data length +6 (for additional status
-+ ** words, length and ctl!)
-+ **
-+ ** If odd size then last byte is included in ctl word.
-+ */
-+ numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
-+ if (unlikely(numPages > 7)) {
-+ printk("%s: Far too big packet error.\n", dev->name);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ /* now, try to allocate the memory */
-+ saved_bank = SMC_CURRENT_BANK();
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_MMU_CMD( MC_ALLOC | numPages );
-+
-+ /*
-+ * Poll the chip for a short amount of time in case the
-+ * allocation succeeds quickly.
-+ */
-+ poll_count = MEMORY_WAIT_TIME;
-+ do {
-+ status = SMC_GET_INT();
-+ if (status & IM_ALLOC_INT) {
-+ SMC_ACK_INT( IM_ALLOC_INT );
-+ break;
-+ }
-+ } while (--poll_count);
-+
-+ if (!poll_count) {
-+ /* oh well, wait until the chip finds memory later */
-+ netif_stop_queue(dev);
-+ PRINTK2("%s: TX memory allocation deferred.\n", dev->name);
-+ SMC_ENABLE_INT( IM_ALLOC_INT );
-+ } else {
-+ /* Send current packet immediately.. */
-+#if THROTTLE_TX_PKTS
-+ netif_stop_queue(dev);
-+#endif
-+ smc_hardware_send_packet(dev);
-+ SMC_ENABLE_INT( IM_TX_INT | IM_TX_EMPTY_INT );
-+ }
-+
-+ SMC_SELECT_BANK( saved_bank );
-+ return 0;
-+}
-+
-+/*
-+ . This handles a TX interrupt, which is only called when an error
-+ . relating to a packet is sent or CTL_AUTO_RELEASE is not set.
-+*/
-+static void
-+smc_tx(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned int saved_packet, packet_no, tx_status, pkt_len;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* If the TX FIFO is empty then nothing to do */
-+ packet_no = SMC_GET_TXFIFO();
-+ if (unlikely(packet_no & TXFIFO_TEMPTY)) {
-+ PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
-+ return;
-+ }
-+
-+ /* select packet to read from */
-+ saved_packet = SMC_GET_PN();
-+ SMC_SET_PN( packet_no );
-+
-+ /* read the first word (status word) from this packet */
-+ SMC_SET_PTR( PTR_AUTOINC | PTR_READ );
-+ SMC_GET_PKT_HDR(tx_status, pkt_len);
-+ PRINTK2("%s: TX STATUS 0x%04x PNR 0x%02x\n",
-+ dev->name, tx_status, packet_no);
-+
-+ if (!(tx_status & TS_SUCCESS))
-+ lp->stats.tx_errors++;
-+ if (tx_status & TS_LOSTCAR)
-+ lp->stats.tx_carrier_errors++;
-+ if (tx_status & TS_LATCOL) {
-+ printk( KERN_DEBUG
-+ "%s: Late collision occurred on last xmit.\n",
-+ dev->name);
-+ lp->stats.tx_window_errors++;
-+ }
-+
-+ /* kill the packet */
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_MMU_CMD( MC_FREEPKT );
-+
-+ /* Don't restore Packet Number Reg until busy bit is cleared */
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_PN( saved_packet );
-+
-+ /* re-enable transmit */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+ SMC_SELECT_BANK( 2 );
-+}
-+
-+
-+//---PHY CONTROL AND CONFIGURATION-----------------------------------------
-+
-+/*------------------------------------------------------------
-+ . Debugging function for viewing MII Management serial bitstream
-+ .-------------------------------------------------------------*/
-+#if SMC_DEBUG > 3
-+static void
-+PRINT_MII_STREAM(u_char *bits, int size)
-+{
-+ int i;
-+
-+ printk("BIT#:");
-+ for (i = 0; i < size; ++i)
-+ printk("%d", i%10);
-+
-+ printk("\nMDOE:");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDOE)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\nMDO :");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDO)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\nMDI :");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDI)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\n");
-+}
-+#else
-+#define PRINT_MII_STREAM(x...)
-+#endif
-+
-+/*------------------------------------------------------------
-+ . Reads a register from the MII Management serial interface
-+ .-------------------------------------------------------------*/
-+static int
-+smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg)
-+{
-+ int oldBank;
-+ int i, mask, mii_reg;
-+ u_char bits[64];
-+ int input_idx, phydata;
-+ int clk_idx = 0;
-+
-+ // 32 consecutive ones on MDO to establish sync
-+ for (i = 0; i < 32; ++i)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Start code <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Read command <10>
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Output the PHY address, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyaddr & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Output the phy register number, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyreg & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Tristate and turnaround (2 bit times)
-+ bits[clk_idx++] = 0;
-+ //bits[clk_idx++] = 0;
-+
-+ // Input starts at this bit time
-+ input_idx = clk_idx;
-+
-+ // Will input 16 bits
-+ for (i = 0; i < 16; ++i)
-+ bits[clk_idx++] = 0;
-+
-+ // Final clock bit
-+ bits[clk_idx++] = 0;
-+
-+ // Save the current bank
-+ oldBank = SMC_CURRENT_BANK();
-+
-+ // Select bank 3
-+ SMC_SELECT_BANK( 3 );
-+
-+ // Get the current MII register value
-+ mii_reg = SMC_GET_MII();
-+
-+ // Turn off all MII Interface bits
-+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-+
-+ // Clock all 64 cycles
-+ for (i = 0; i < sizeof bits; ++i) {
-+ // Clock Low - output data
-+ SMC_SET_MII( mii_reg | bits[i] );
-+ udelay(50);
-+
-+ // Clock Hi - input data
-+ SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
-+ udelay(50);
-+ bits[i] |= SMC_GET_MII() & MII_MDI;
-+ }
-+
-+ // Return to idle state
-+ // Set clock to low, data to low, and output tristated
-+ SMC_SET_MII( mii_reg );
-+ udelay(50);
-+
-+ // Restore original bank select
-+ SMC_SELECT_BANK( oldBank );
-+
-+ // Recover input data
-+ phydata = 0;
-+ for (i = 0; i < 16; ++i) {
-+ phydata <<= 1;
-+
-+ if (bits[input_idx++] & MII_MDI)
-+ phydata |= 0x0001;
-+ }
-+
-+ PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
-+ __FUNCTION__, phyaddr, phyreg, phydata);
-+ PRINT_MII_STREAM(bits, sizeof(bits));
-+
-+ return phydata;
-+}
-+
-+/*------------------------------------------------------------
-+ . Writes a register to the MII Management serial interface
-+ .-------------------------------------------------------------*/
-+static void
-+smc_write_phy_register( unsigned long ioaddr, int phyaddr,
-+ int phyreg, int phydata )
-+{
-+ int oldBank;
-+ int i, mask, mii_reg;
-+ u_char bits[65];
-+ int clk_idx = 0;
-+
-+ // 32 consecutive ones on MDO to establish sync
-+ for (i = 0; i < 32; ++i)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Start code <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Write command <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Output the PHY address, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyaddr & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Output the phy register number, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyreg & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Tristate and turnaround (2 bit times)
-+ bits[clk_idx++] = 0;
-+ bits[clk_idx++] = 0;
-+
-+ // Write out 16 bits of data, msb first
-+ mask = 0x8000;
-+ for (i = 0; i < 16; ++i) {
-+ if (phydata & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Final clock bit (tristate)
-+ bits[clk_idx++] = 0;
-+
-+ // Save the current bank
-+ oldBank = SMC_CURRENT_BANK();
-+
-+ // Select bank 3
-+ SMC_SELECT_BANK( 3 );
-+
-+ // Get the current MII register value
-+ mii_reg = SMC_GET_MII();
-+
-+ // Turn off all MII Interface bits
-+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-+
-+ // Clock all cycles
-+ for (i = 0; i < sizeof bits; ++i) {
-+ // Clock Low - output data
-+ SMC_SET_MII( mii_reg | bits[i] );
-+ udelay(50);
-+
-+ // Clock Hi - input data
-+ SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
-+ udelay(50);
-+ bits[i] |= SMC_GET_MII() & MII_MDI;
-+ }
-+
-+ // Return to idle state
-+ // Set clock to low, data to low, and output tristated
-+ SMC_SET_MII( mii_reg );
-+ udelay(50);
-+
-+ // Restore original bank select
-+ SMC_SELECT_BANK( oldBank );
-+
-+ PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
-+ __FUNCTION__, phyaddr, phyreg, phydata);
-+ PRINT_MII_STREAM(bits, sizeof(bits));
-+}
-+
-+
-+/*------------------------------------------------------------
-+ . Finds and reports the PHY address
-+ .-------------------------------------------------------------*/
-+static int smc_detect_phy(struct net_device* dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ int phy_id1, phy_id2;
-+ int phyaddr;
-+ int found = 0;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ // Scan all 32 PHY addresses if necessary
-+ for (phyaddr = 0; phyaddr < 32; ++phyaddr) {
-+ // Read the PHY identifiers
-+ phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
-+ phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
-+
-+ PRINTK3("%s: phy_id1=0x%x, phy_id2=0x%x\n",
-+ dev->name, phy_id1, phy_id2);
-+
-+ // Make sure it is a valid identifier
-+ if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
-+ (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) {
-+ if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) {
-+ // Save the PHY's address
-+ lp->phyaddr = phyaddr;
-+ found = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!found) {
-+ PRINTK("%s: No PHY found\n", dev->name);
-+ return(0);
-+ }
-+
-+ // Set the PHY type
-+ if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) {
-+ lp->phytype = PHY_LAN83C183;
-+ PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name);
-+ }
-+
-+ if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) {
-+ lp->phytype = PHY_LAN83C180;
-+ PRINTK("%s: PHY=LAN83C180\n", dev->name);
-+ }
-+
-+ return 1;
-+}
-+
-+/*------------------------------------------------------------
-+ . Waits the specified number of milliseconds - kernel friendly
-+ .-------------------------------------------------------------*/
-+static void
-+smc_wait_ms(unsigned int ms)
-+{
-+ if (!in_interrupt()) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(1 + ms * HZ / 1000);
-+ } else {
-+ /* if this happens it must be fixed */
-+ printk( KERN_WARNING "%s: busy wait while in interrupt!\n",
-+ __FUNCTION__);
-+ mdelay(ms);
-+ }
-+}
-+
-+/*------------------------------------------------------------
-+ . Sets the PHY to a configuration as determined by the user
-+ .-------------------------------------------------------------*/
-+static int
-+smc_phy_fixed(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int my_fixed_caps, cfg1;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ // Enter Link Disable state
-+ cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG);
-+ cfg1 |= PHY_CFG1_LNKDIS;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1);
-+
-+ // Set our fixed capabilities
-+ // Disable auto-negotiation
-+ my_fixed_caps = 0;
-+
-+ if (lp->ctl_rfduplx)
-+ my_fixed_caps |= PHY_CNTL_DPLX;
-+
-+ if (lp->ctl_rspeed == 100)
-+ my_fixed_caps |= PHY_CNTL_SPEED;
-+
-+ // Write our capabilities to the phy control register
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps);
-+
-+ // Re-Configure the Receive/Phy Control register
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+
-+ // Success
-+ return(1);
-+}
-+
-+/*------------------------------------------------------------
-+ . Configures the specified PHY through the MII management interface
-+ . using Autonegotiation.
-+ . Calls smc_phy_fixed() if the user has requested a certain config.
-+ .-------------------------------------------------------------*/
-+static void
-+smc_phy_configure(struct net_device* dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int timeout;
-+ int phyaddr;
-+ int my_phy_caps; // My PHY capabilities
-+ int my_ad_caps; // My Advertised capabilities
-+ int status;
-+
-+ PRINTK3("%s:smc_program_phy()\n", dev->name);
-+
-+ // Set the blocking flag
-+ lp->autoneg_active = 1;
-+
-+ // Find the address and type of our phy
-+ if (!smc_detect_phy(dev))
-+ goto smc_phy_configure_exit;
-+
-+ // Get the detected phy address
-+ phyaddr = lp->phyaddr;
-+
-+ // Reset the PHY, setting all other bits to zero
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
-+
-+ // Wait for the reset to complete, or time out
-+ timeout = 6; // Wait up to 3 seconds
-+ while (timeout--) {
-+ if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
-+ & PHY_CNTL_RST))
-+ // reset complete
-+ break;
-+ smc_wait_ms(500); // wait 500 millisecs
-+ if (signal_pending(current)) { // Exit anyway if signaled
-+ PRINTK("%s: PHY reset interrupted by signal\n",
-+ dev->name);
-+ timeout = 0;
-+ break;
-+ }
-+ }
-+
-+ if (timeout < 1) {
-+ printk("%s: PHY reset timed out\n", dev->name);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ // Read PHY Register 18, Status Output
-+ lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
-+
-+ // Enable PHY Interrupts (for register 18)
-+ // Interrupts listed here are disabled
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
-+ PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
-+ PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
-+ PHY_INT_SPDDET | PHY_INT_DPLXDET);
-+
-+ /* Configure the Receive/Phy Control register */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+
-+ // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
-+ my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+
-+ // If the user requested no auto neg, then go set his request
-+ if (!(lp->ctl_autoneg)) {
-+ smc_phy_fixed(dev);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ if( !( my_phy_caps & PHY_STAT_CAP_ANEG))
-+ {
-+ printk(KERN_INFO "Auto negotiation NOT supported\n");
-+ smc_phy_fixed(dev);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ my_ad_caps = PHY_AD_CSMA; // I am CSMA capable
-+
-+ if (my_phy_caps & PHY_STAT_CAP_T4)
-+ my_ad_caps |= PHY_AD_T4;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TXF)
-+ my_ad_caps |= PHY_AD_TX_FDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TXH)
-+ my_ad_caps |= PHY_AD_TX_HDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TF)
-+ my_ad_caps |= PHY_AD_10_FDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TH)
-+ my_ad_caps |= PHY_AD_10_HDX;
-+
-+ // Disable capabilities not selected by our user
-+ if (lp->ctl_rspeed != 100)
-+ my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);
-+
-+ if (!lp->ctl_rfduplx)
-+ my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);
-+
-+ // Update our Auto-Neg Advertisement Register
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
-+
-+ // Read the register back. Without this, it appears that when
-+ // auto-negotiation is restarted, sometimes it isn't ready and
-+ // the link does not come up.
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG);
-+
-+ PRINTK2("%s: phy caps=%x\n", dev->name, my_phy_caps);
-+ PRINTK2("%s: phy advertised caps=%x\n", dev->name, my_ad_caps);
-+
-+ // Restart auto-negotiation process in order to advertise my caps
-+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
-+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
-+
-+ // Wait for the auto-negotiation to complete. This may take from
-+ // 2 to 3 seconds.
-+ // Wait for the reset to complete, or time out
-+ timeout = 20; // Wait up to 10 seconds
-+ while (timeout--) {
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_RMT_REG);
-+ if (status & PHY_AD_ACK)
-+ // auto-negotiate complete
-+ break;
-+
-+ smc_wait_ms(500); // wait 500 millisecs
-+ if (signal_pending(current)) { // Exit anyway if signaled
-+ printk(KERN_DEBUG
-+ "%s: PHY auto-negotiate interrupted by signal\n",
-+ dev->name);
-+ timeout = 0;
-+ break;
-+ }
-+ }
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+
-+ if (timeout < 1) {
-+ PRINTK("%s: PHY auto-negotiate timed out\n", dev->name);
-+ }
-+
-+ // Fail if we detected an auto-negotiate remote fault
-+ if (status & PHY_STAT_REM_FLT) {
-+ PRINTK("%s: PHY remote fault detected\n", dev->name);
-+ }
-+
-+ // Wait for link. Once the link is up, phy18 should be up to date
-+ timeout = 200;
-+ do
-+ {
-+ udelay(100);
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+ } while ( ((status & PHY_STAT_LINK)==0) && --timeout);
-+
-+ if (status & PHY_STAT_LINK)
-+ {
-+ PRINTK("%s: Ethernet Link Detected\n", dev->name);
-+ }
-+
-+ // The smc_phy_interrupt() routine will be called to update lastPhy18
-+
-+ // Set our sysctl parameters to match auto-negotiation results
-+ if ( lp->lastPhy18 & PHY_INT_SPDDET ) {
-+ PRINTK("%s: PHY 100BaseT\n", dev->name);
-+ lp->rpc_cur_mode |= RPC_SPEED;
-+ } else {
-+ PRINTK("%s: PHY 10BaseT\n", dev->name);
-+ lp->rpc_cur_mode &= ~RPC_SPEED;
-+ }
-+
-+ if ( lp->lastPhy18 & PHY_INT_DPLXDET ) {
-+ PRINTK("%s: PHY Full Duplex\n", dev->name);
-+ lp->rpc_cur_mode |= RPC_DPLX;
-+ lp->tcr_cur_mode |= TCR_SWFDUP;
-+ } else {
-+ PRINTK("%s: PHY Half Duplex\n", dev->name);
-+ lp->rpc_cur_mode &= ~RPC_DPLX;
-+ lp->tcr_cur_mode &= ~TCR_SWFDUP;
-+ }
-+
-+ // Re-Configure the Receive/Phy Control register and TCR
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+
-+smc_phy_configure_exit:
-+ // Exit auto-negotiation
-+ lp->autoneg_active = 0;
-+}
-+
-+/*************************************************************************
-+ . smc_phy_interrupt
-+ .
-+ . Purpose: Handle interrupts relating to PHY register 18. This is
-+ . called from the "hard" interrupt handler.
-+ .
-+ ************************************************************************/
-+static void
-+smc_phy_interrupt(struct net_device* dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int phy18;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ for(;;) {
-+ // Read PHY Register 18, Status Output
-+ phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
-+
-+ // Exit if not more changes
-+ if (phy18 == lp->lastPhy18)
-+ break;
-+
-+#if SMC_DEBUG > 1
-+ PRINTK2("%s: phy18=0x%04x\n", dev->name, phy18);
-+ PRINTK2("%s: lastPhy18=0x%04x\n", dev->name, lp->lastPhy18);
-+
-+ // Handle events
-+ if ((phy18 & PHY_INT_LNKFAIL) !=
-+ (lp->lastPhy18 & PHY_INT_LNKFAIL))
-+ PRINTK2("%s: PHY Link Fail=%x\n", dev->name,
-+ phy18 & PHY_INT_LNKFAIL);
-+
-+ if ((phy18 & PHY_INT_LOSSSYNC) !=
-+ (lp->lastPhy18 & PHY_INT_LOSSSYNC))
-+ PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name,
-+ phy18 & PHY_INT_LOSSSYNC);
-+
-+ if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD))
-+ PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name,
-+ phy18 & PHY_INT_CWRD);
-+
-+ if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD))
-+ PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name,
-+ phy18 & PHY_INT_SSD);
-+
-+ if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD))
-+
-+ PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name,
-+ phy18 & PHY_INT_ESD);
-+
-+ if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL))
-+ PRINTK2("%s: PHY Reverse Polarity Detected=%x\n",
-+ dev->name, phy18 & PHY_INT_RPOL);
-+
-+ if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB))
-+ PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name,
-+ phy18 & PHY_INT_JAB);
-+
-+ if ((phy18 & PHY_INT_SPDDET) !=
-+ (lp->lastPhy18 & PHY_INT_SPDDET))
-+ PRINTK2("%s: PHY Speed Detect=%x\n", dev->name,
-+ phy18 & PHY_INT_SPDDET);
-+
-+ if ((phy18 & PHY_INT_DPLXDET) !=
-+ (lp->lastPhy18 & PHY_INT_DPLXDET))
-+ PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name,
-+ phy18 & PHY_INT_DPLXDET);
-+#endif
-+ // Update the last phy 18 variable
-+ lp->lastPhy18 = phy18;
-+ }
-+}
-+
-+//--- END PHY CONTROL AND CONFIGURATION-------------------------------------
-+
-+
-+/*
-+ * This is the main routine of the driver, to handle the device when
-+ * it needs some attention.
-+ */
-+static void
-+smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int status, mask, timeout, card_stats;
-+ int saved_bank, saved_pointer;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ saved_bank = SMC_CURRENT_BANK();
-+ SMC_SELECT_BANK(2);
-+ saved_pointer = SMC_GET_PTR();
-+ mask = SMC_GET_INT_MASK();
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* set a timeout value, so I don't stay here forever */
-+ timeout = 8;
-+
-+ do {
-+ status = SMC_GET_INT();
-+
-+ PRINTK2("%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
-+ dev->name, status, mask,
-+ ({ int meminfo; SMC_SELECT_BANK(0);
-+ meminfo = SMC_GET_MIR();
-+ SMC_SELECT_BANK(2); meminfo; }),
-+ SMC_GET_FIFO());
-+
-+ status &= mask;
-+ if (!status)
-+ break;
-+
-+ if (status & IM_RCV_INT) {
-+ PRINTK3("%s: RX irq\n", dev->name);
-+ smc_rcv(dev);
-+ } else if (status & IM_TX_INT) {
-+ PRINTK3("%s: TX int\n", dev->name);
-+ smc_tx(dev);
-+ SMC_ACK_INT( IM_TX_INT );
-+#if THROTTLE_TX_PKTS
-+ netif_wake_queue(dev);
-+#endif
-+ } else if (status & IM_ALLOC_INT) {
-+ PRINTK3("%s: Allocation irq\n", dev->name);
-+ smc_hardware_send_packet(dev);
-+ mask |= (IM_TX_INT | IM_TX_EMPTY_INT);
-+ mask &= ~IM_ALLOC_INT;
-+#if ! THROTTLE_TX_PKTS
-+ netif_wake_queue(dev);
-+#endif
-+ } else if (status & IM_TX_EMPTY_INT) {
-+ PRINTK3("%s: TX empty\n", dev->name);
-+ mask &= ~IM_TX_EMPTY_INT;
-+
-+ /* update stats */
-+ SMC_SELECT_BANK( 0 );
-+ card_stats = SMC_GET_COUNTER();
-+ SMC_SELECT_BANK( 2 );
-+
-+ /* single collisions */
-+ lp->stats.collisions += card_stats & 0xF;
-+ card_stats >>= 4;
-+
-+ /* multiple collisions */
-+ lp->stats.collisions += card_stats & 0xF;
-+ } else if (status & IM_RX_OVRN_INT) {
-+ PRINTK1( "%s: RX overrun\n", dev->name);
-+ SMC_ACK_INT( IM_RX_OVRN_INT );
-+ lp->stats.rx_errors++;
-+ lp->stats.rx_fifo_errors++;
-+ } else if (status & IM_EPH_INT) {
-+ PRINTK("%s: UNSUPPORTED: EPH INTERRUPT\n", dev->name);
-+ } else if (status & IM_MDINT) {
-+ SMC_ACK_INT( IM_MDINT );
-+ smc_phy_interrupt(dev);
-+ } else if (status & IM_ERCV_INT ) {
-+ SMC_ACK_INT( IM_ERCV_INT );
-+ PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
-+ }
-+ } while (--timeout);
-+
-+ /* restore register states */
-+ SMC_SET_INT_MASK( mask );
-+ SMC_SET_PTR( saved_pointer );
-+ SMC_SELECT_BANK( saved_bank );
-+
-+ PRINTK3("%s: Interrupt done\n", dev->name);
-+}
-+
-+/* Our watchdog timed out. Called by the networking layer */
-+static void
-+smc_timeout(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ smc_reset(dev);
-+ smc_enable(dev);
-+
-+#if 0
-+ /* Reconfiguring the PHY doesn't seem like a bad idea here, but
-+ * it introduced a problem. Now that this is a timeout routine,
-+ * we are getting called from within an interrupt context.
-+ * smc_phy_configure() calls smc_wait_ms() which calls
-+ * schedule_timeout() which calls schedule(). When schedule()
-+ * is called from an interrupt context, it prints out
-+ * "Scheduling in interrupt" and then calls BUG(). This is
-+ * obviously not desirable. This was worked around by removing
-+ * the call to smc_phy_configure() here because it didn't seem
-+ * absolutely necessary. Ultimately, if smc_wait_ms() is
-+ * supposed to be usable from an interrupt context (which it
-+ * looks like it thinks it should handle), it should be fixed.
-+ */
-+ /* Reconfigure the PHY */
-+ smc_phy_configure(dev);
-+#endif
-+
-+ /* clear anything saved */
-+ if (lp->saved_skb != NULL) {
-+ dev_kfree_skb (lp->saved_skb);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_aborted_errors++;
-+ }
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+/*
-+ * Finds the CRC32 of a set of bytes.
-+ * (from Peter Cammaert's code)
-+ */
-+static int
-+crc32(char *s, int length)
-+{
-+ /* indices */
-+ int perByte;
-+ int perBit;
-+ /* crc polynomial for Ethernet */
-+ const unsigned long poly = 0xedb88320;
-+ /* crc value - preinitialized to all 1's */
-+ unsigned long crc_value = 0xffffffff;
-+
-+ for ( perByte = 0; perByte < length; perByte ++ ) {
-+ unsigned char c;
-+
-+ c = *(s++);
-+ for ( perBit = 0; perBit < 8; perBit++ ) {
-+ crc_value = (crc_value>>1)^
-+ (((crc_value^c)&0x01)?poly:0);
-+ c >>= 1;
-+ }
-+ }
-+ return crc_value;
-+}
-+
-+/*
-+ . This sets the internal hardware table to filter out unwanted multicast
-+ . packets before they take up memory.
-+ .
-+ . The SMC chip uses a hash table where the high 6 bits of the CRC of
-+ . address are the offset into the table. If that bit is 1, then the
-+ . multicast packet is accepted. Otherwise, it's dropped silently.
-+ .
-+ . To use the 6 bits as an offset into the table, the high 3 bits are the
-+ . number of the 8 bit register, while the low 3 bits are the bit within
-+ . that register.
-+ .
-+ . This routine is based very heavily on the one provided by Peter Cammaert.
-+*/
-+static void
-+smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs)
-+{
-+ int i;
-+ unsigned char multicast_table[ 8 ];
-+ struct dev_mc_list *cur_addr;
-+
-+ /* table for flipping the order of 3 bits */
-+ static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
-+
-+ /* start with a table of all zeros: reject all */
-+ memset( multicast_table, 0, sizeof( multicast_table ) );
-+
-+ cur_addr = addrs;
-+ for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
-+ int position;
-+
-+ /* do we have a pointer here? */
-+ if ( !cur_addr )
-+ break;
-+ /* make sure this is a multicast address - shouldn't this
-+ be a given if we have it here ? */
-+ if ( !( *cur_addr->dmi_addr & 1 ) )
-+ continue;
-+
-+ /* only use the low order bits */
-+ position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f;
-+
-+ /* do some messy swapping to put the bit in the right spot */
-+ multicast_table[invert3[position&7]] |=
-+ (1<<invert3[(position>>3)&7]);
-+
-+ }
-+ /* now, the table can be loaded into the chipset */
-+ SMC_SELECT_BANK( 3 );
-+ SMC_SET_MCAST( multicast_table );
-+}
-+
-+/*
-+ . This routine will, depending on the values passed to it,
-+ . either make it accept multicast packets, go into
-+ . promiscuous mode ( for TCPDUMP and cousins ) or accept
-+ . a select set of multicast packets
-+*/
-+static void smc_set_multicast_list(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ SMC_SELECT_BANK(0);
-+ if ( dev->flags & IFF_PROMISC ) {
-+ PRINTK2("%s: RCR_PRMS\n", dev->name);
-+ lp->rcr_cur_mode |= RCR_PRMS;
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ }
-+
-+/* BUG? I never disable promiscuous mode if multicasting was turned on.
-+ Now, I turn off promiscuous mode, but I don't do anything to multicasting
-+ when promiscuous mode is turned on.
-+*/
-+
-+ /* Here, I am setting this to accept all multicast packets.
-+ I don't need to zero the multicast table, because the flag is
-+ checked before the table is
-+ */
-+ else if (dev->flags & IFF_ALLMULTI) {
-+ lp->rcr_cur_mode |= RCR_ALMUL;
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ PRINTK2("%s: RCR_ALMUL\n", dev->name);
-+ }
-+
-+ /* We just get all multicast packets even if we only want them
-+ . from one source. This will be changed at some future
-+ . point. */
-+ else if (dev->mc_count ) {
-+ /* support hardware multicasting */
-+
-+ /* be sure I get rid of flags I might have set */
-+ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ /* NOTE: this has to set the bank, so make sure it is the
-+ last thing called. The bank is set to zero at the top */
-+ smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
-+ } else {
-+ PRINTK2("%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name);
-+ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+
-+ /*
-+ since I'm disabling all multicast entirely, I need to
-+ clear the multicast list
-+ */
-+ SMC_SELECT_BANK( 3 );
-+ SMC_CLEAR_MCAST();
-+ }
-+}
-+
-+
-+/*
-+ * Open and Initialize the board
-+ *
-+ * Set up everything, reset the card, etc ..
-+ */
-+static int
-+smc_open(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* clear out all the junk that was put here before... */
-+ memset(dev->priv, 0, sizeof(struct smc_local));
-+
-+ // Setup the default Register Modes
-+ lp->tcr_cur_mode = TCR_DEFAULT;
-+ lp->rcr_cur_mode = RCR_DEFAULT;
-+ lp->rpc_cur_mode = RPC_DEFAULT;
-+
-+ /* Set default parameters */
-+#ifdef CONFIG_ARCH_RAMSES
-+ lp->ctl_autoneg = 0;
-+ lp->ctl_rfduplx = 0;
-+ lp->ctl_rspeed = 10;
-+#else
-+ lp->ctl_autoneg = 1;
-+ lp->ctl_rfduplx = 1;
-+ lp->ctl_rspeed = 100;
-+#endif
-+
-+ SMC_SELECT_BANK(3);
-+ lp->version = SMC_GET_REV() & 0xff;
-+
-+ /* reset the hardware */
-+ smc_reset(dev);
-+ smc_enable(dev);
-+
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_MAC_ADDR(dev->dev_addr);
-+
-+ /* Configure the PHY */
-+ if (lp->version >= 0x70)
-+ smc_phy_configure(dev);
-+
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+/*----------------------------------------------------
-+ . smc_close
-+ .
-+ . this makes the board clean up everything that it can
-+ . and not talk to the outside world. Caused by
-+ . an 'ifconfig ethX down'
-+ .
-+ -----------------------------------------------------*/
-+static int
-+smc_close(struct net_device *dev)
-+{
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ netif_stop_queue(dev);
-+
-+ /* clear everything */
-+ smc_shutdown(dev);
-+
-+ return 0;
-+}
-+
-+/*------------------------------------------------------------
-+ . Get the current statistics.
-+ . This may be called with the card open or closed.
-+ .-------------------------------------------------------------*/
-+static struct net_device_stats *
-+smc_query_statistics(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ return &lp->stats;
-+}
-+
-+/*----------------------------------------------------------------------
-+ . smc_findirq
-+ .
-+ . This routine has a simple purpose -- make the SMC chip generate an
-+ . interrupt, so an auto-detect routine can detect it, and find the IRQ,
-+ ------------------------------------------------------------------------
-+*/
-+int __init
-+smc_findirq( unsigned long ioaddr )
-+{
-+ int timeout = 20;
-+ unsigned long cookie;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ cookie = probe_irq_on();
-+
-+ /*
-+ * What I try to do here is trigger an ALLOC_INT. This is done
-+ * by allocating a small chunk of memory, which will give an interrupt
-+ * when done.
-+ */
-+
-+ /* enable ALLOCation interrupts ONLY */
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT_MASK( IM_ALLOC_INT );
-+
-+ /*
-+ . Allocate 512 bytes of memory. Note that the chip was just
-+ . reset so all the memory is available
-+ */
-+ SMC_SET_MMU_CMD( MC_ALLOC | 1 );
-+
-+ /*
-+ . Wait until positive that the interrupt has been generated
-+ */
-+ do {
-+ int int_status;
-+ udelay(10);
-+ int_status = SMC_GET_INT();
-+ if (int_status & IM_ALLOC_INT)
-+ break; /* got the interrupt */
-+ } while (--timeout);
-+
-+ /* there is really nothing that I can do here if timeout fails,
-+ as autoirq_report will return a 0 anyway, which is what I
-+ want in this case. Plus, the clean up is needed in both
-+ cases. */
-+
-+ /* and disable all interrupts again */
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* and return what I found */
-+ return probe_irq_off(cookie);
-+}
-+
-+/*----------------------------------------------------------------------
-+ . Function: smc_probe( unsigned long ioaddr )
-+ .
-+ . Purpose:
-+ . Tests to see if a given ioaddr points to an SMC91x chip.
-+ . Returns a 0 on success
-+ .
-+ . Algorithm:
-+ . (1) see if the high byte of BANK_SELECT is 0x33
-+ . (2) compare the ioaddr with the base register's address
-+ . (3) see if I recognize the chip ID in the appropriate register
-+ .
-+ .---------------------------------------------------------------------
-+ */
-+/*---------------------------------------------------------------
-+ . Here I do typical initialization tasks.
-+ .
-+ . o Initialize the structure if needed
-+ . o print out my vanity message if not done so already
-+ . o print out what type of hardware is detected
-+ . o print out the ethernet address
-+ . o find the IRQ
-+ . o set up my private data
-+ . o configure the dev structure with my subroutines
-+ . o actually GRAB the irq.
-+ . o GRAB the region
-+ .-----------------------------------------------------------------
-+*/
-+static int __init
-+smc_probe(struct net_device *dev, unsigned long ioaddr)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ static int version_printed = 0;
-+ int i, retval;
-+ unsigned int val, revision_register;
-+ const char *version_string;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ /* Grab the region so that no one else tries to probe our ioports. */
-+ if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
-+ return -EBUSY;
-+
-+ /* First, see if the high byte is 0x33 */
-+ val = SMC_CURRENT_BANK();
-+ PRINTK2("%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
-+ if ( (val & 0xFF00) != 0x3300 ) {
-+ if ( (val & 0xFF) == 0x33 ) {
-+ printk( KERN_WARNING
-+ "%s: Detected possible byte-swapped interface"
-+ " at IOADDR 0x%lx\n", CARDNAME, ioaddr);
-+ }
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* The above MIGHT indicate a device, but I need to write to further
-+ test this. */
-+ SMC_SELECT_BANK(0);
-+ val = SMC_CURRENT_BANK();
-+ if ( (val & 0xFF00 ) != 0x3300 ) {
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* well, we've already written once, so hopefully another time won't
-+ hurt. This time, I need to switch the bank register to bank 1,
-+ so I can access the base address register */
-+ SMC_SELECT_BANK(1);
-+ val = SMC_GET_BASE();
-+ val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
-+ if ( (ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val ) {
-+ printk( "%s: IOADDR %lx doesn't match configuration (%x).\n",
-+ CARDNAME, ioaddr, val );
-+ }
-+
-+ /* check if the revision register is something that I recognize.
-+ These might need to be added to later, as future revisions
-+ could be added. */
-+ SMC_SELECT_BANK(3);
-+ revision_register = SMC_GET_REV();
-+ PRINTK2("%s: revision = 0x%04x\n", CARDNAME, revision_register);
-+ version_string = chip_ids[ (revision_register >> 4) & 0xF];
-+ if (!version_string || (revision_register & 0xff00) != 0x3300) {
-+ /* I don't recognize this chip, so... */
-+ printk( "%s: IO 0x%lx: Unrecognized revision register 0x%04x"
-+ ", Contact author.\n", CARDNAME,
-+ ioaddr, revision_register);
-+
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* At this point I'll assume that the chip is an SMC91x. */
-+ if (version_printed++ == 0)
-+ printk("%s", version);
-+
-+ /* set the private data to zero by default */
-+ memset(lp, 0, sizeof(struct smc_local));
-+
-+ /* fill in some of the fields */
-+ dev->base_addr = ioaddr;
-+ lp->version = revision_register & 0xff;
-+
-+ /* Get the MAC address */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_GET_MAC_ADDR(dev->dev_addr);
-+
-+ /* now, reset the chip, and put it into a known state */
-+ smc_reset( dev );
-+
-+ /*
-+ . If dev->irq is 0, then the device has to be banged on to see
-+ . what the IRQ is.
-+ .
-+ . This banging doesn't always detect the IRQ, for unknown reasons.
-+ . a workaround is to reset the chip and try again.
-+ .
-+ . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-+ . be what is requested on the command line. I don't do that, mostly
-+ . because the card that I have uses a non-standard method of accessing
-+ . the IRQs, and because this _should_ work in most configurations.
-+ .
-+ . Specifying an IRQ is done with the assumption that the user knows
-+ . what (s)he is doing. No checking is done!!!!
-+ .
-+ */
-+ if ( dev->irq < 1 ) {
-+ int trials;
-+
-+ trials = 3;
-+ while ( trials-- ) {
-+ dev->irq = smc_findirq( ioaddr );
-+ if ( dev->irq )
-+ break;
-+ /* kick the card and try again */
-+ smc_reset( dev );
-+ }
-+ }
-+ if (dev->irq == 0 ) {
-+ printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
-+ dev->name);
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+ dev->irq = irq_cannonicalize(dev->irq);
-+
-+ /* now, print out the card info, in a short format.. */
-+ printk( "%s: %s (rev %d) at %#lx IRQ %d%s%s\n",
-+ dev->name, version_string, revision_register & 0x0f,
-+ ioaddr, dev->irq, nowait ? " [nowait]" : "",
-+ THROTTLE_TX_PKTS ? " [throttle_tx]" : "" );
-+
-+ /* Print the Ethernet address */
-+ printk("%s: Ethernet addr: ", dev->name);
-+ for (i = 0; i < 5; i++)
-+ printk("%2.2x:", dev->dev_addr[i] );
-+ printk("%2.2x\n", dev->dev_addr[5] );
-+
-+ /* Fill in the fields of the device structure with ethernet values. */
-+ ether_setup(dev);
-+
-+ /* Grab the IRQ */
-+ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-+ if (retval) {
-+ goto err_out;
-+ }
-+
-+ dev->open = smc_open;
-+ dev->stop = smc_close;
-+ dev->hard_start_xmit = smc_hard_start_xmit;
-+ dev->tx_timeout = smc_timeout;
-+ dev->watchdog_timeo = HZ/10;
-+ dev->get_stats = smc_query_statistics;
-+ dev->set_multicast_list = smc_set_multicast_list;
-+
-+ return 0;
-+
-+err_out:
-+ release_region(ioaddr, SMC_IO_EXTENT);
-+ return retval;
-+}
-+
-+/*-------------------------------------------------------------------------
-+ |
-+ | smc_init( void )
-+ | Input parameters:
-+ | dev->base_addr == 0, try to find all possible locations
-+ | dev->base_addr > 0x1ff, this is the address to check
-+ | dev->base_addr == <anything else>, return failure code
-+ |
-+ | Output:
-+ | 0 --> there is a device
-+ | anything else, error
-+ |
-+ ---------------------------------------------------------------------------
-+*/
-+static struct net_device *global_dev = NULL; /* needs to be fixed */
-+
-+#ifdef CONFIG_PM
-+
-+static int smc_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ unsigned long ioaddr = global_dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ smc_shutdown(global_dev);
-+ break;
-+ case PM_RESUME:
-+ smc_reset(global_dev);
-+ smc_enable(global_dev);
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_MAC_ADDR(global_dev->dev_addr);
-+ if (lp->version >= 0x70)
-+ smc_phy_configure(global_dev);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+#endif
-+
-+static int __init
-+smc_init(void)
-+{
-+ int ret;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+#ifdef MODULE
-+ if (io == -1)
-+ printk( KERN_WARNING
-+ "%s: You shouldn't use auto-probing with insmod!\n",
-+ CARDNAME );
-+#endif
-+
-+ if (global_dev) {
-+ printk("%s: already initialized.\n", CARDNAME);
-+ return -EBUSY;
-+ }
-+
-+ global_dev = init_etherdev(0, sizeof(struct smc_local));
-+ if (!global_dev) {
-+ printk("%s: could not allocate device.\n", CARDNAME);
-+ return -ENOMEM;
-+ }
-+ SET_MODULE_OWNER(global_dev);
-+
-+ /* copy the parameters from insmod into the device structure */
-+ if (io != -1)
-+ global_dev->base_addr = io;
-+ if (irq != -1)
-+ global_dev->irq = irq;
-+
-+#ifdef CONFIG_ISA
-+ /* try a specific location */
-+ if (global_dev->base_addr > 0x1ff)
-+ ret = smc_probe(global_dev, global_dev->base_addr);
-+ else if (global_dev->base_addr != 0)
-+ ret = -ENXIO;
-+ else {
-+ int i;
-+
-+ /* check every ethernet address */
-+ for (i = 0; smc_portlist[i]; i++) {
-+ ret = smc_probe(global_dev, smc_portlist[i]);
-+ if (ret == 0)
-+ break;
-+ }
-+ }
-+#elif defined(CONFIG_ARCH_LUBBOCK)
-+ {
-+ int ioaddr = LUBBOCK_ETH_VIRT + (0x300 << 2);
-+ volatile int *attaddr = (int *)(LUBBOCK_ETH_VIRT + 0x100000);
-+ unsigned long flags;
-+
-+ /* first reset, then enable the device. Sequence is critical */
-+ local_irq_save(flags);
-+ attaddr[ECOR] |= ECOR_RESET;
-+ udelay(100);
-+ attaddr[ECOR] &= ~ECOR_RESET;
-+ attaddr[ECOR] |= ECOR_ENABLE;
-+
-+ /* force 16-bit mode */
-+ attaddr[ECSR] &= ~ECSR_IOIS8;
-+ mdelay(1);
-+ local_irq_restore(flags);
-+
-+ global_dev->irq = LUBBOCK_ETH_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#elif defined(CONFIG_ARCH_PXA_IDP)
-+ {
-+ int ioaddr = IDP_ETH_BASE + 0x300;
-+ global_dev->irq = SMC_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#elif defined(CONFIG_ARCH_RAMSES)
-+ {
-+ int ioaddr = RAMSES_ETH_BASE + 0x300;
-+ global_dev->irq = SMC_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#else
-+ if (global_dev->base_addr == -1) {
-+ printk(KERN_WARNING"%s: SMC91X_BASE_ADDR not set!\n", CARDNAME);
-+ ret = -ENXIO;
-+ } else {
-+ void *ioaddr = ioremap(global_dev->base_addr, SMC_IO_EXTENT);
-+ ret = smc_probe(global_dev, (unsigned long)ioaddr);
-+ if (ret != 0)
-+ iounmap(ioaddr);
-+ }
-+#endif
-+
-+#ifdef SMC_USE_PXA_DMA
-+ if (ret == 0) {
-+ int dma = pxa_request_dma(global_dev->name, DMA_PRIO_LOW,
-+ smc_pxa_dma_irq, NULL);
-+ if (dma >= 0) {
-+ global_dev->dma = dma;
-+ PRINTK("%s: using DMA channel %d\n", global_dev->name, dma);
-+ } else {
-+ global_dev->dma = -1;
-+ }
-+ }
-+#endif
-+
-+#ifdef CONFIG_PM
-+ if (ret == 0) {
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+ lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback);
-+ }
-+#endif
-+
-+ if (ret != 0) {
-+ printk("%s: not found.\n", CARDNAME);
-+ kfree(global_dev->priv);
-+ unregister_netdev(global_dev);
-+ kfree(global_dev);
-+ }
-+
-+ return ret;
-+}
-+
-+static void __exit
-+smc_cleanup(void)
-+{
-+ unregister_netdev(global_dev);
-+#ifdef CONFIG_PM
-+ {
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+ pm_unregister(lp->pm);
-+ }
-+#endif
-+ free_irq(global_dev->irq, global_dev);
-+ release_region(global_dev->base_addr, SMC_IO_EXTENT);
-+
-+#ifndef CONFIG_ISA
-+ iounmap((void *)global_dev->base_addr);
-+#endif
-+
-+ kfree(global_dev);
-+ global_dev = NULL;
-+}
-+
-+module_init(smc_init);
-+module_exit(smc_cleanup);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/net/smc91x.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,835 @@
-+/*------------------------------------------------------------------------
-+ . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device.
-+ .
-+ . Copyright (C) 1996 by Erik Stahlman
-+ . Copyright (C) 2001 Standard Microsystems Corporation
-+ . Developed by Simple Network Magic Corporation
-+ . Copyright (C) 2003 Monta Vista Software, Inc.
-+ . Unified SMC91x driver by Nicolas Pitre
-+ .
-+ . This program is free software; you can redistribute it and/or modify
-+ . it under the terms of the GNU General Public License as published by
-+ . the Free Software Foundation; either version 2 of the License, or
-+ . (at your option) any later version.
-+ .
-+ . This program is distributed in the hope that it will be useful,
-+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ . GNU General Public License for more details.
-+ .
-+ . You should have received a copy of the GNU General Public License
-+ . along with this program; if not, write to the Free Software
-+ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ .
-+ . Information contained in this file was obtained from the LAN91C111
-+ . manual from SMC. To get a copy, if you really want one, you can find
-+ . information under www.smsc.com.
-+ .
-+ . Authors
-+ . Erik Stahlman <erik@vt.edu>
-+ . Daris A Nevil <dnevil@snmc.com>
-+ . Nicolas Pitre <nico@cam.org>
-+ .
-+ ---------------------------------------------------------------------------*/
-+#ifndef _SMC91X_H_
-+#define _SMC91X_H_
-+
-+
-+/*
-+ * Define your architecture specific configuration parameters here.
-+ */
-+
-+#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
-+ defined(CONFIG_SA1100_PFS168) || \
-+ defined(CONFIG_SA1100_FLEXANET) || \
-+ defined(CONFIG_SA1100_GRAPHICSMASTER) || \
-+ defined(CONFIG_ARCH_LUBBOCK)
-+
-+/* We can only do 16-bit reads and writes in the static memory space. */
-+#define SMC_CAN_USE_8BIT 0
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 0
-+#define SMC_NOWAIT 1
-+
-+/* The first two address lines aren't connected... */
-+#define SMC_IO_SHIFT 2
-+
-+#define SMC_inw(a, r) readw((a) + (r))
-+#define SMC_outw(v, a, r) writew(v, (a) + (r))
-+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-+
-+#ifdef CONFIG_ARCH_LUBBOCK
-+#define SMC_IOADDR LUBBOCK_ETH_PHYS
-+#endif
-+
-+#elif defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_ARCH_PXA_IDP) || defined(CONFIG_ARCH_RAMSES)
-+
-+#ifdef CONFIG_ARCH_MAINSTONE
-+#include <asm/arch/mainstone.h>
-+#define SMC_IOADDR (MST_ETH_PHYS + 0x300)
-+#define SMC_IRQ MAINSTONE_IRQ(3)
-+
-+#elif CONFIG_ARCH_PXA_IDP
-+#include <asm/arch/idp.h>
-+#define SMC_IOADDR (IDP_ETH_PHYS + 0x300)
-+#define SMC_IRQ ETHERNET_IRQ
-+
-+#elif CONFIG_ARCH_RAMSES
-+#include <asm/arch/ramses.h>
-+#define SMC_IOADDR (RAMSES_ETH_PHYS + 0x300)
-+#define SMC_IRQ ETHERNET_IRQ
-+#endif
-+
-+#define SMC_CAN_USE_8BIT 1
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 1
-+#define SMC_IO_SHIFT 0
-+#define SMC_NOWAIT 1
-+#define SMC_USE_PXA_DMA 1
-+
-+#define SMC_inb(a, r) readb((a) + (r))
-+#define SMC_inw(a, r) readw((a) + (r))
-+#define SMC_inl(a, r) readl((a) + (r))
-+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-+#define SMC_outl(v, a, r) writel(v, (a) + (r))
-+#define SMC_insl(a, r, p, l) insl((a) + (r), p, l)
-+#define SMC_outsl(a, r, p, l) outsl((a) + (r), p, l)
-+
-+/* We actually can't write halfwords properly if not word aligned */
-+static inline void
-+SMC_outw(u16 val, unsigned long ioaddr, int reg)
-+{
-+ if (reg & 2) {
-+ unsigned int v = val << 16;
-+ v |= readl(ioaddr + (reg & ~2)) & 0xffff;
-+ writel(v, ioaddr + (reg & ~2));
-+ } else {
-+ writew(val, ioaddr + reg);
-+ }
-+}
-+
-+#elif defined(CONFIG_ISA)
-+
-+#define SMC_CAN_USE_8BIT 1
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 0
-+
-+#define SMC_inb(a, r) inb((a) + (r))
-+#define SMC_inw(a, r) inw((a) + (r))
-+#define SMC_outb(v, a, r) outb(v, (a) + (r))
-+#define SMC_outw(v, a, r) outw(v, (a) + (r))
-+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-+
-+#endif
-+
-+
-+#ifdef SMC_USE_PXA_DMA
-+/*
-+ * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
-+ * always happening in irq context so no need to worry about races. TX is
-+ * different and probably not worth it for that reason, and not as critical
-+ * as RX which can overrun memory and lose packets.
-+ */
-+#include <linux/pci.h>
-+#include <asm/dma.h>
-+
-+#ifdef SMC_insl
-+#undef SMC_insl
-+#define SMC_insl(a, r, p, l) smc_pxa_dma_insl(a, r, dev->dma, p, l)
-+static inline void
-+smc_pxa_dma_insl(u_long ioaddr, int reg, int dma, u_char *buf, int len)
-+{
-+ dma_addr_t dmabuf;
-+
-+ /* fallback if no DMA available */
-+ if (dma == -1) {
-+ insl(ioaddr + reg, buf, len);
-+ return;
-+ }
-+
-+ /* 64 bit alignment is required for memory to memory DMA */
-+ if ((long)buf & 4) {
-+ *((u32 *)buf)++ = SMC_inl(ioaddr, reg);
-+ len--;
-+ }
-+
-+ len *= 4;
-+ dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
-+ DCSR(dma) = DCSR_NODESC;
-+ DTADR(dma) = dmabuf;
-+ DSADR(dma) = SMC_IOADDR + reg;
-+ DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-+ DCMD_WIDTH4 | (DCMD_LENGTH & len));
-+ DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-+ while (!(DCSR(dma) & DCSR_STOPSTATE));
-+ DCSR(dma) = 0;
-+ pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
-+}
-+#endif
-+
-+#ifdef SMC_insw
-+#undef SMC_insw
-+#define SMC_insw(a, r, p, l) smc_pxa_dma_insw(a, r, dev->dma, p, l)
-+static inline void
-+smc_pxa_dma_insw(u_long ioaddr, int reg, int dma, u_char *buf, int len)
-+{
-+ dma_addr_t dmabuf;
-+
-+ /* fallback if no DMA available */
-+ if (dma == -1) {
-+ insw(ioaddr + reg, buf, len);
-+ return;
-+ }
-+
-+ /* 64 bit alignment is required for memory to memory DMA */
-+ while ((long)buf & 6) {
-+ *((u16 *)buf)++ = SMC_inw(ioaddr, reg);
-+ len--;
-+ }
-+
-+ len *= 2;
-+ dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
-+ DCSR(dma) = DCSR_NODESC;
-+ DTADR(dma) = dmabuf;
-+ DSADR(dma) = SMC_IOADDR + reg;
-+ DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-+ DCMD_WIDTH2 | (DCMD_LENGTH & len));
-+ DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-+ while (!(DCSR(dma) & DCSR_STOPSTATE));
-+ DCSR(dma) = 0;
-+ pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
-+}
-+#endif
-+
-+static void
-+smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
-+{
-+ DCSR(dma) = 0;
-+}
-+#endif /* SMC_USE_PXA_DMA */
-+
-+
-+/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */
-+#ifndef SMC_IO_SHIFT
-+#define SMC_IO_SHIFT 0
-+#endif
-+#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-+
-+
-+/*
-+ . Bank Select Register:
-+ .
-+ . yyyy yyyy 0000 00xx
-+ . xx = bank number
-+ . yyyy yyyy = 0x33, for identification purposes.
-+*/
-+#define BANK_SELECT (14 << SMC_IO_SHIFT)
-+
-+
-+// Transmit Control Register
-+/* BANK 0 */
-+#define TCR_REG SMC_REG(0x0000, 0)
-+#define TCR_ENABLE 0x0001 // When 1 we can transmit
-+#define TCR_LOOP 0x0002 // Controls output pin LBK
-+#define TCR_FORCOL 0x0004 // When 1 will force a collision
-+#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0
-+#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames
-+#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier
-+#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation
-+#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error
-+#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback
-+#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode
-+
-+#define TCR_CLEAR 0 /* do NOTHING */
-+/* the default settings for the TCR register : */
-+#define TCR_DEFAULT (TCR_ENABLE | TCR_PAD_EN)
-+
-+
-+// EPH Status Register
-+/* BANK 0 */
-+#define EPH_STATUS_REG SMC_REG(0x0002, 0)
-+#define ES_TX_SUC 0x0001 // Last TX was successful
-+#define ES_SNGL_COL 0x0002 // Single collision detected for last tx
-+#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx
-+#define ES_LTX_MULT 0x0008 // Last tx was a multicast
-+#define ES_16COL 0x0010 // 16 Collisions Reached
-+#define ES_SQET 0x0020 // Signal Quality Error Test
-+#define ES_LTXBRD 0x0040 // Last tx was a broadcast
-+#define ES_TXDEFR 0x0080 // Transmit Deferred
-+#define ES_LATCOL 0x0200 // Late collision detected on last tx
-+#define ES_LOSTCARR 0x0400 // Lost Carrier Sense
-+#define ES_EXC_DEF 0x0800 // Excessive Deferral
-+#define ES_CTR_ROL 0x1000 // Counter Roll Over indication
-+#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin
-+#define ES_TXUNRN 0x8000 // Tx Underrun
-+
-+
-+// Receive Control Register
-+/* BANK 0 */
-+#define RCR_REG SMC_REG(0x0004, 0)
-+#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted
-+#define RCR_PRMS 0x0002 // Enable promiscuous mode
-+#define RCR_ALMUL 0x0004 // When set accepts all multicast frames
-+#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets
-+#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets
-+#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision
-+#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier
-+#define RCR_SOFTRST 0x8000 // resets the chip
-+
-+/* the normal settings for the RCR register : */
-+#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN)
-+#define RCR_CLEAR 0x0 // set it to a base state
-+
-+
-+// Counter Register
-+/* BANK 0 */
-+#define COUNTER_REG SMC_REG(0x0006, 0)
-+
-+
-+// Memory Information Register
-+/* BANK 0 */
-+#define MIR_REG SMC_REG(0x0008, 0)
-+
-+
-+// Receive/Phy Control Register
-+/* BANK 0 */
-+#define RPC_REG SMC_REG(0x000A, 0)
-+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
-+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
-+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
-+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
-+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
-+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
-+#define RPC_LED_RES (0x01) // LED = Reserved
-+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
-+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
-+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
-+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
-+#define RPC_LED_TX (0x06) // LED = TX packet occurred
-+#define RPC_LED_RX (0x07) // LED = RX packet occurred
-+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
-+
-+
-+/* Bank 0 0x0C is reserved */
-+
-+// Bank Select Register
-+/* All Banks */
-+#define BSR_REG 0x000E
-+
-+
-+// Configuration Reg
-+/* BANK 1 */
-+#define CONFIG_REG SMC_REG(0x0000, 1)
-+#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy
-+#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL
-+#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus
-+#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
-+
-+// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
-+#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN)
-+
-+
-+// Base Address Register
-+/* BANK 1 */
-+#define BASE_REG SMC_REG(0x0002, 1)
-+
-+
-+// Individual Address Registers
-+/* BANK 1 */
-+#define ADDR0_REG SMC_REG(0x0004, 1)
-+#define ADDR1_REG SMC_REG(0x0006, 1)
-+#define ADDR2_REG SMC_REG(0x0008, 1)
-+
-+
-+// General Purpose Register
-+/* BANK 1 */
-+#define GP_REG SMC_REG(0x000A, 1)
-+
-+
-+// Control Register
-+/* BANK 1 */
-+#define CTL_REG SMC_REG(0x000C, 1)
-+#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received
-+#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
-+#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt
-+#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt
-+#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt
-+#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
-+#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers
-+#define CTL_STORE 0x0001 // When set stores registers into EEPROM
-+
-+
-+// MMU Command Register
-+/* BANK 2 */
-+#define MMU_CMD_REG SMC_REG(0x0000, 2)
-+#define MC_BUSY 1 // When 1 the last release has not completed
-+#define MC_NOP (0<<5) // No Op
-+#define MC_ALLOC (1<<5) // OR with number of 256 byte packets
-+#define MC_RESET (2<<5) // Reset MMU to initial state
-+#define MC_REMOVE (3<<5) // Remove the current rx packet
-+#define MC_RELEASE (4<<5) // Remove and release the current rx packet
-+#define MC_FREEPKT (5<<5) // Release packet in PNR register
-+#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit
-+#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs
-+
-+
-+// Packet Number Register
-+/* BANK 2 */
-+#define PN_REG SMC_REG(0x0002, 2)
-+
-+
-+// Allocation Result Register
-+/* BANK 2 */
-+#define AR_REG SMC_REG(0x0003, 2)
-+#define AR_FAILED 0x80 // Alocation Failed
-+
-+
-+// TX FIFO Ports Register
-+/* BANK 2 */
-+#define TXFIFO_REG SMC_REG(0x0004, 2)
-+#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty
-+
-+// RX FIFO Ports Register
-+/* BANK 2 */
-+#define RXFIFO_REG SMC_REG(0x0005, 2)
-+#define RXFIFO_REMPTY 0x80 // RX FIFO Empty
-+
-+#define FIFO_REG SMC_REG(0x0004, 2)
-+
-+// Pointer Register
-+/* BANK 2 */
-+#define PTR_REG SMC_REG(0x0006, 2)
-+#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area
-+#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access
-+#define PTR_READ 0x2000 // When 1 the operation is a read
-+
-+
-+// Data Register
-+/* BANK 2 */
-+#define DATA_REG SMC_REG(0x0008, 2)
-+
-+
-+// Interrupt Status/Acknowledge Register
-+/* BANK 2 */
-+#define INT_REG SMC_REG(0x000C, 2)
-+
-+
-+// Interrupt Mask Register
-+/* BANK 2 */
-+#define IM_REG SMC_REG(0x000D, 2)
-+#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt
-+#define IM_ERCV_INT 0x40 // Early Receive Interrupt
-+#define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section
-+#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns
-+#define IM_ALLOC_INT 0x08 // Set when allocation request is completed
-+#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty
-+#define IM_TX_INT 0x02 // Transmit Interrupt
-+#define IM_RCV_INT 0x01 // Receive Interrupt
-+
-+
-+// Multicast Table Registers
-+/* BANK 3 */
-+#define MCAST_REG1 SMC_REG(0x0000, 3)
-+#define MCAST_REG2 SMC_REG(0x0002, 3)
-+#define MCAST_REG3 SMC_REG(0x0004, 3)
-+#define MCAST_REG4 SMC_REG(0x0006, 3)
-+
-+
-+// Management Interface Register (MII)
-+/* BANK 3 */
-+#define MII_REG SMC_REG(0x0008, 3)
-+#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
-+#define MII_MDOE 0x0008 // MII Output Enable
-+#define MII_MCLK 0x0004 // MII Clock, pin MDCLK
-+#define MII_MDI 0x0002 // MII Input, pin MDI
-+#define MII_MDO 0x0001 // MII Output, pin MDO
-+
-+
-+// Revision Register
-+/* BANK 3 */
-+/* ( hi: chip id low: rev # ) */
-+#define REV_REG SMC_REG(0x000A, 3)
-+
-+
-+// Early RCV Register
-+/* BANK 3 */
-+/* this is NOT on SMC9192 */
-+#define ERCV_REG SMC_REG(0x000C, 3)
-+#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received
-+#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask
-+
-+
-+// External Register
-+/* BANK 7 */
-+#define EXT_REG SMC_REG(0x0000, 7)
-+
-+
-+#define CHIP_9192 3
-+#define CHIP_9194 4
-+#define CHIP_9195 5
-+#define CHIP_9196 6
-+#define CHIP_91100 7
-+#define CHIP_91100FD 8
-+#define CHIP_91111FD 9
-+
-+static const char * chip_ids[ 16 ] = {
-+ NULL, NULL, NULL,
-+ /* 3 */ "SMC91C90/91C92",
-+ /* 4 */ "SMC91C94",
-+ /* 5 */ "SMC91C95",
-+ /* 6 */ "SMC91C96",
-+ /* 7 */ "SMC91C100",
-+ /* 8 */ "SMC91C100FD",
-+ /* 9 */ "SMC91C11xFD",
-+ NULL, NULL, NULL,
-+ NULL, NULL, NULL};
-+
-+
-+/*
-+ . Transmit status bits
-+*/
-+#define TS_SUCCESS 0x0001
-+#define TS_LOSTCAR 0x0400
-+#define TS_LATCOL 0x0200
-+#define TS_16COL 0x0010
-+
-+/*
-+ . Receive status bits
-+*/
-+#define RS_ALGNERR 0x8000
-+#define RS_BRODCAST 0x4000
-+#define RS_BADCRC 0x2000
-+#define RS_ODDFRAME 0x1000
-+#define RS_TOOLONG 0x0800
-+#define RS_TOOSHORT 0x0400
-+#define RS_MULTICAST 0x0001
-+#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
-+
-+
-+// PHY Types
-+enum {
-+ PHY_LAN83C183 = 1, // LAN91C111 Internal PHY
-+ PHY_LAN83C180
-+};
-+
-+
-+// PHY Register Addresses (LAN91C111 Internal PHY)
-+
-+// PHY Control Register
-+#define PHY_CNTL_REG 0x00
-+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
-+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
-+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
-+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
-+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
-+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
-+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
-+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
-+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
-+
-+// PHY Status Register
-+#define PHY_STAT_REG 0x01
-+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
-+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
-+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
-+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
-+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
-+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
-+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
-+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
-+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
-+#define PHY_STAT_LINK 0x0004 // 1=valid link
-+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
-+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
-+
-+// PHY Identifier Registers
-+#define PHY_ID1_REG 0x02 // PHY Identifier 1
-+#define PHY_ID2_REG 0x03 // PHY Identifier 2
-+
-+// PHY Auto-Negotiation Advertisement Register
-+#define PHY_AD_REG 0x04
-+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
-+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
-+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
-+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
-+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
-+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
-+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
-+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
-+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
-+
-+// PHY Auto-negotiation Remote End Capability Register
-+#define PHY_RMT_REG 0x05
-+// Uses same bit definitions as PHY_AD_REG
-+
-+// PHY Configuration Register 1
-+#define PHY_CFG1_REG 0x10
-+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
-+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
-+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
-+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
-+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
-+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
-+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
-+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
-+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
-+#define PHY_CFG1_TLVL_MASK 0x003C
-+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
-+
-+
-+// PHY Configuration Register 2
-+#define PHY_CFG2_REG 0x11
-+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
-+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
-+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
-+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
-+
-+// PHY Status Output (and Interrupt status) Register
-+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
-+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
-+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
-+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
-+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
-+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
-+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
-+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
-+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
-+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
-+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
-+
-+// PHY Interrupt/Status Mask Register
-+#define PHY_MASK_REG 0x13 // Interrupt Mask
-+// Uses the same bit definitions as PHY_INT_REG
-+
-+
-+/*
-+ * SMC91C96 ethernet config and status registers.
-+ * These are in the "attribute" space.
-+ */
-+#define ECOR 0x8000
-+#define ECOR_RESET 0x80
-+#define ECOR_LEVEL_IRQ 0x40
-+#define ECOR_WR_ATTRIB 0x04
-+#define ECOR_ENABLE 0x01
-+
-+#define ECSR 0x8002
-+#define ECSR_IOIS8 0x20
-+#define ECSR_PWRDWN 0x04
-+#define ECSR_INT 0x02
-+
-+
-+/*
-+ * Macros to abstract register access according to the data bus
-+ * capabilities. Please try to use those and not the in/out primitives.
-+ * Note: the following macros do *not* select the bank -- this must
-+ * be done separately as needed in the main code. The SMC_REG() macro
-+ * only uses the bank argument for debugging purposes.
-+ */
-+
-+#if SMC_DEBUG > 0
-+#define SMC_REG(reg, bank) \
-+ ({ \
-+ int __b = SMC_CURRENT_BANK(); \
-+ if ((__b & ~0xf0) != (0x3300 | bank)) { \
-+ printk( "%s: bank reg screwed (0x%04x)\n", \
-+ CARDNAME, __b ); \
-+ BUG(); \
-+ } \
-+ reg<<SMC_IO_SHIFT; \
-+ })
-+#else
-+#define SMC_REG(reg, bank) (reg<<SMC_IO_SHIFT)
-+#endif
-+
-+#if SMC_CAN_USE_8BIT
-+#define SMC_GET_PN() SMC_inb( ioaddr, PN_REG )
-+#define SMC_SET_PN(x) SMC_outb( x, ioaddr, PN_REG )
-+#define SMC_GET_AR() SMC_inb( ioaddr, AR_REG )
-+#define SMC_GET_TXFIFO() SMC_inb( ioaddr, TXFIFO_REG )
-+#define SMC_GET_RXFIFO() SMC_inb( ioaddr, RXFIFO_REG )
-+#define SMC_GET_INT() SMC_inb( ioaddr, INT_REG )
-+#define SMC_ACK_INT(x) SMC_outb( x, ioaddr, INT_REG )
-+#define SMC_GET_INT_MASK() SMC_inb( ioaddr, IM_REG )
-+#define SMC_SET_INT_MASK(x) SMC_outb( x, ioaddr, IM_REG )
-+#else
-+#define SMC_GET_PN() (SMC_inw( ioaddr, PN_REG ) & 0xFF)
-+#define SMC_SET_PN(x) SMC_outw( x, ioaddr, PN_REG )
-+#define SMC_GET_AR() (SMC_inw( ioaddr, PN_REG ) >> 8)
-+#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF)
-+#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8)
-+#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF)
-+#define SMC_ACK_INT(x) \
-+ do { \
-+ unsigned long __flags; \
-+ int __mask; \
-+ local_irq_save(__flags); \
-+ __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \
-+ SMC_outw( __mask | (x), ioaddr, INT_REG ); \
-+ local_irq_restore(__flags); \
-+ } while (0)
-+#define SMC_GET_INT_MASK() (SMC_inw( ioaddr, INT_REG ) >> 8)
-+#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG )
-+#endif
-+
-+#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT )
-+#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT )
-+#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG )
-+#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG )
-+#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG )
-+#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG )
-+#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG )
-+#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG )
-+#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG )
-+#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG )
-+#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG )
-+#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG )
-+#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG )
-+#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG )
-+#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG )
-+#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG )
-+#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG )
-+#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG )
-+#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG )
-+#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG )
-+#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG )
-+#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG )
-+#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG )
-+#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG )
-+#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG )
-+
-+#ifndef SMC_GET_MAC_ADDR
-+#define SMC_GET_MAC_ADDR(addr) \
-+ do { \
-+ unsigned int __v; \
-+ __v = SMC_inw( ioaddr, ADDR0_REG ); \
-+ addr[0] = __v; addr[1] = __v >> 8; \
-+ __v = SMC_inw( ioaddr, ADDR1_REG ); \
-+ addr[2] = __v; addr[3] = __v >> 8; \
-+ __v = SMC_inw( ioaddr, ADDR2_REG ); \
-+ addr[4] = __v; addr[5] = __v >> 8; \
-+ } while (0)
-+#endif
-+
-+#define SMC_SET_MAC_ADDR(addr) \
-+ do { \
-+ SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \
-+ SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \
-+ SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \
-+ } while (0)
-+
-+#define SMC_CLEAR_MCAST() \
-+ do { \
-+ SMC_outw( 0, ioaddr, MCAST_REG1 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG2 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG3 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG4 ); \
-+ } while (0)
-+#define SMC_SET_MCAST(x) \
-+ do { \
-+ unsigned char *mt = (x); \
-+ SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \
-+ SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \
-+ SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \
-+ SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \
-+ } while (0)
-+
-+#if SMC_CAN_USE_32BIT
-+/*
-+ * Some setups just can't write 8 or 16 bits reliably when not aligned
-+ * to a 32 bit boundary. I tell you that exists!
-+ * We do the ones that can have their low parts written to 0 here.
-+ */
-+#undef SMC_SELECT_BANK
-+#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<<SMC_IO_SHIFT )
-+#undef SMC_SET_RPC
-+#define SMC_SET_RPC(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(8, 0) )
-+#undef SMC_SET_PN
-+#define SMC_SET_PN(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(0, 2) )
-+#undef SMC_SET_PTR
-+#define SMC_SET_PTR(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(4, 2) )
-+#endif
-+
-+#if SMC_CAN_USE_32BIT
-+#define SMC_PUT_PKT_HDR(status, length) \
-+ SMC_outl( (status) | (length) << 16, ioaddr, DATA_REG )
-+#define SMC_GET_PKT_HDR(status, length) \
-+ do { \
-+ unsigned int __val = SMC_inl( ioaddr, DATA_REG ); \
-+ (status) = __val & 0xffff; \
-+ (length) = __val >> 16; \
-+ } while (0)
-+#else
-+#define SMC_PUT_PKT_HDR(status, length) \
-+ do { \
-+ SMC_outw( status, ioaddr, DATA_REG ); \
-+ SMC_outw( length, ioaddr, DATA_REG ); \
-+ } while (0)
-+#define SMC_GET_PKT_HDR(status, length) \
-+ do { \
-+ (status) = SMC_inw( ioaddr, DATA_REG ); \
-+ (length) = SMC_inw( ioaddr, DATA_REG ); \
-+ } while (0)
-+#endif
-+
-+#if SMC_CAN_USE_32BIT
-+#define SMC_PUSH_DATA(p, l) \
-+ do { \
-+ char *__ptr = (p); \
-+ int __len = (l); \
-+ if (__len >= 2 && (long)__ptr & 2) { \
-+ __len -= 2; \
-+ SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
-+ } \
-+ SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \
-+ if (__len & 2) { \
-+ __ptr += (__len & ~3); \
-+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
-+ } \
-+ } while (0)
-+#define SMC_PULL_DATA(p, l) \
-+ do { \
-+ char *__ptr = (p); \
-+ int __len = (l); \
-+ if ((long)__ptr & 2) { \
-+ /* \
-+ * We want 32bit alignment here. \
-+ * Since some buses perform a full 32bit \
-+ * fetch even for 16bit data we can't use \
-+ * SMC_inw() here. Back both source (on chip \
-+ * and destination) pointers of 2 bytes. \
-+ */ \
-+ (long)__ptr &= ~2; \
-+ __len += 2; \
-+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
-+ } \
-+ __len += 2; \
-+ SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
-+ } while (0)
-+#elif SMC_CAN_USE_16BIT
-+#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-+#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
-+#elif SMC_CAN_USE_8BIT
-+#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-+#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
-+#endif
-+
-+#if ! SMC_CAN_USE_16BIT
-+#define SMC_outw(x, ioaddr, reg) \
-+ do { \
-+ unsigned int __val16 = (x); \
-+ SMC_outb( __val16, ioaddr, reg ); \
-+ SMC_outb( __val16 >> 8, ioaddr, reg + 1 ); \
-+ } while (0)
-+#define SMC_inw(ioaddr, reg) \
-+ ({ \
-+ unsigned int __val16; \
-+ __val16 = SMC_inb( ioaddr, reg ); \
-+ __val16 |= SMC_inb( ioaddr, reg + 1 ) << 8; \
-+ __val16; \
-+ })
-+#endif
-+
-+
-+#endif /* _SMC91X_H_ */
---- linux-2.4.25/drivers/pcmcia/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/Config.in 2004-03-31 17:15:12.000000000 +0200
-@@ -45,6 +45,7 @@
- if [ "$CONFIG_ARM" = "y" ]; then
- dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
- dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
-+ dep_tristate ' PXA250/210 support' CONFIG_PCMCIA_PXA $CONFIG_ARCH_PXA $CONFIG_PCMCIA
- fi
-
- endmenu
---- linux-2.4.25/drivers/pcmcia/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/Makefile 2004-03-31 17:15:12.000000000 +0200
-@@ -94,6 +94,11 @@
-
- obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
-
-+subdir-$(CONFIG_PCMCIA_PXA) += pxa
-+ifeq ($(CONFIG_PCMCIA_PXA),y)
-+ obj-y += pxa/pxa_cs.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-
- pcmcia_core.o: $(pcmcia_core-objs)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/Makefile 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,18 @@
-+#
-+# Makefile for the Intel PXA250/210 PCMCIA driver
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+
-+O_TARGET := pxa_cs.o
-+
-+obj-y := pxa.o
-+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
-+obj-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o
-+obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
-+obj-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o
-+
-+obj-m := $(O_TARGET)
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/lubbock.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,329 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/lubbock.c
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
-+ *
-+ * Lubbock PCMCIA specific routines.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+#include <asm/hardware/sa1111.h>
-+
-+/*
-+ * I'd really like to move the INTPOL stuff to arch/arm/mach-sa1100/sa1111.c
-+ * ... and maybe even arch/arm/mach-pxa/sa1111.c now too! : )
-+ */
-+#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
-+#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
-+
-+static int lubbock_pcmcia_init(struct pcmcia_init *init){
-+ int return_val=0;
-+
-+ /* Set PCMCIA Socket 0 power to standby mode.
-+ */
-+ PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+
-+ /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller.
-+ * Note that this is done only after first initializing GPIO_A<3:0>
-+ * output state above to be certain that we drive signals to the same
-+ * state as the pull-downs connected to these lines. The pull-downs are
-+ * req'd to make sure PCMCIA power is OFF until we can get around to
-+ * setting up the GPIO_A<3:0> state and direction.
-+ */
-+ PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+
-+ /* Set CF Socket 1 power to standby mode. */
-+ LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+#warning what if a request_irq fails?
-+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
-+ "Lubbock PCMCIA (0) CD", NULL);
-+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
-+ "Lubbock CF (1) CD", NULL);
-+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
-+ "Lubbock PCMCIA (0) BVD1", NULL);
-+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
-+ "Lubbock CF (1) BVD1", NULL);
-+
-+ return (return_val<0) ? -1 : 2;
-+}
-+
-+static int lubbock_pcmcia_shutdown(void){
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+
-+ return 0;
-+}
-+
-+static int lubbock_pcmcia_socket_state(struct pcmcia_state_array
-+ *state_array){
-+ unsigned long status;
-+ int return_val=1;
-+
-+ if(state_array->size<2) return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-+
-+ status=PCSR;
-+
-+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-+
-+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-+
-+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-+
-+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-+
-+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-+
-+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-+
-+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-+
-+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-+
-+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-+
-+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-+
-+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-+
-+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-+
-+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-+
-+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-+
-+ return return_val;
-+}
-+
-+static int lubbock_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-+
-+ switch(info->sock){
-+ case 0:
-+ info->irq=S0_READY_NINT;
-+ break;
-+
-+ case 1:
-+ info->irq=S1_READY_NINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+lubbock_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ unsigned long flags, pccr, gpio, misc_wr, status;
-+ int ret=1;
-+
-+ local_irq_save(flags);
-+
-+ pccr=PCCR;
-+ gpio=PA_DWR;
-+ misc_wr = LUB_MISC_WR;
-+
-+ /* Lubbock uses the Maxim MAX1602, with the following connections:
-+ *
-+ * Socket 0 (PCMCIA):
-+ * MAX1602 Lubbock Register
-+ * Pin Signal
-+ * ----- ------- ----------------------
-+ * A0VPP S0_PWR0 SA-1111 GPIO A<0>
-+ * A1VPP S0_PWR1 SA-1111 GPIO A<1>
-+ * A0VCC S0_PWR2 SA-1111 GPIO A<2>
-+ * A1VCC S0_PWR3 SA-1111 GPIO A<3>
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ * Socket 1 (CF):
-+ * MAX1602 Lubbock Register
-+ * Pin Signal
-+ * ----- ------- ----------------------
-+ * A0VPP GND VPP is not connected
-+ * A1VPP GND VPP is not connected
-+ * A0VCC S1_PWR0 MISC_WR<14>
-+ * A1VCC S1_PWR0 MISC_WR<15>
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN GND VPP is not connected
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ */
-+
-+again:
-+ switch(sock){
-+ case 0:
-+
-+ switch(state->Vcc){
-+ case 0:
-+ pccr = (pccr & ~PCCR_S0_FLT);
-+ gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
-+ break;
-+
-+ case 33:
-+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
-+ break;
-+
-+ case 50:
-+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
-+ ret = -1;
-+ break;
-+ }
-+
-+ switch(state->Vpp){
-+ case 0:
-+ gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
-+ break;
-+
-+ case 120:
-+ gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
-+ break;
-+
-+ default:
-+ /* REVISIT: I'm not sure about this? Is this correct?
-+ Is it always safe or do we have potential problems
-+ with bogus combinations of Vcc and Vpp settings? */
-+ if(state->Vpp == state->Vcc)
-+ gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp);
-+ ret = -1;
-+ break;
-+ }
-+ }
-+
-+ pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S0_RST) : (pccr&~PCCR_S0_RST);
-+
-+ break;
-+
-+ case 1:
-+ switch(state->Vcc){
-+ case 0:
-+ pccr = (pccr & ~PCCR_S1_FLT);
-+ misc_wr &= ~((1 << 15) | (1 << 14));
-+ break;
-+
-+ case 33:
-+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
-+ misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
-+ break;
-+
-+ case 50:
-+ pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
-+ misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
-+ ret = -1;
-+ break;
-+ }
-+
-+ if(state->Vpp!=state->Vcc && state->Vpp!=0){
-+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp);
-+ ret = -1;
-+ break;
-+ }
-+
-+ pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S1_RST) : (pccr&~PCCR_S1_RST);
-+
-+ break;
-+
-+ default:
-+ ret = -1;
-+ }
-+
-+ if (ret >= 0) {
-+ PCCR = pccr;
-+ LUB_MISC_WR = misc_wr;
-+ PA_DWR = gpio;
-+ }
-+
-+ if (ret > 0) {
-+ ret = 0;
-+ /*
-+ * HACK ALERT:
-+ * We can't sense the voltage properly on Lubbock before actually
-+ * applying some power to the socket (catch 22).
-+ * Resense the socket Voltage Sense pins after applying socket power.
-+ */
-+ if (sock == 0)
-+ status = PCSR & (PCSR_S0_VS1 | PCSR_S0_VS2);
-+ else
-+ status = PCSR & (PCSR_S1_VS1 | PCSR_S1_VS2);
-+
-+ if ((status == (PCSR_S0_VS1 | PCSR_S0_VS2)) && (state->Vcc == 33)) {
-+ /* Switch to 5V, Configure socket 0 with 5V voltage */
-+ PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+ PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+ state->Vcc = 50;
-+ state->Vpp = 50;
-+ goto again;
-+ }
-+ if ((status == (PCSR_S1_VS1 | PCSR_S1_VS2)) && (state->Vcc == 33)) {
-+ /* Switch to 5V, Configure socket 1 with 5V voltage */
-+ LUB_MISC_WR &= ~((1 << 15) | (1 << 14));
-+ state->Vcc = 50;
-+ state->Vpp = 50;
-+ goto again;
-+ }
-+ }
-+
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+
-+struct pcmcia_low_level lubbock_pcmcia_ops = {
-+ lubbock_pcmcia_init,
-+ lubbock_pcmcia_shutdown,
-+ lubbock_pcmcia_socket_state,
-+ lubbock_pcmcia_get_irq_info,
-+ lubbock_pcmcia_configure_socket
-+};
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/pxa.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,1247 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa.c
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.c
-+ *
-+ */
-+
-+/*======================================================================
-+
-+ Device driver for the PCMCIA control functionality of Intel
-+ PXA250/210 microprocessors.
-+
-+ The contents of this file are subject to the Mozilla Public
-+ License Version 1.1 (the "License"); you may not use this file
-+ except in compliance with the License. You may obtain a copy of
-+ the License at http://www.mozilla.org/MPL/
-+
-+ Software distributed under the License is distributed on an "AS
-+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-+ implied. See the License for the specific language governing
-+ rights and limitations under the License.
-+
-+ The initial developer of the original code is John G. Dorsey
-+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
-+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
-+
-+ Alternatively, the contents of this file may be used under the
-+ terms of the GNU Public License version 2 (the "GPL"), in which
-+ case the provisions of the GPL are applicable instead of the
-+ above. If you wish to allow the use of your version of this file
-+ only under the terms of the GPL and not to allow others to use
-+ your version of this file under the MPL, indicate your decision
-+ by deleting the provisions above and replace them with the notice
-+ and other provisions required by the GPL. If you do not delete
-+ the provisions above, a recipient may use your version of this
-+ file under either the MPL or the GPL.
-+
-+======================================================================*/
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/config.h>
-+#include <linux/cpufreq.h>
-+#include <linux/delay.h>
-+#include <linux/ioport.h>
-+#include <linux/kernel.h>
-+#include <linux/tqueue.h>
-+#include <linux/timer.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+#include <linux/proc_fs.h>
-+#include <linux/version.h>
-+#include <linux/cpufreq.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/cs.h>
-+#include <pcmcia/ss.h>
-+#include <pcmcia/bus_ops.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/arch/lubbock.h>
-+
-+#include "pxa.h"
-+
-+#ifdef PCMCIA_DEBUG
-+static int pc_debug;
-+#endif
-+
-+MODULE_AUTHOR("George Davis <davis_g@mvista.com>");
-+MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA250/210 Socket Controller");
-+
-+/* This structure maintains housekeeping state for each socket, such
-+ * as the last known values of the card detect pins, or the Card Services
-+ * callback value associated with the socket:
-+ */
-+static struct pxa_pcmcia_socket
-+pxa_pcmcia_socket[PXA_PCMCIA_MAX_SOCK];
-+
-+static int pxa_pcmcia_socket_count;
-+
-+
-+/* Returned by the low-level PCMCIA interface: */
-+static struct pcmcia_low_level *pcmcia_low_level;
-+
-+/* Event poll timer structure */
-+static struct timer_list poll_timer;
-+
-+
-+/* Prototypes for routines which are used internally: */
-+
-+static int pxa_pcmcia_driver_init(void);
-+static void pxa_pcmcia_driver_shutdown(void);
-+static void pxa_pcmcia_task_handler(void *data);
-+static void pxa_pcmcia_poll_event(unsigned long data);
-+static void pxa_pcmcia_interrupt(int irq, void *dev,
-+ struct pt_regs *regs);
-+static struct tq_struct pxa_pcmcia_task;
-+
-+#ifdef CONFIG_PROC_FS
-+static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
-+ int count, int *eof, void *data);
-+#endif
-+
-+
-+/* Prototypes for operations which are exported to the
-+ * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
-+ */
-+
-+static int pxa_pcmcia_init(unsigned int sock);
-+static int pxa_pcmcia_suspend(unsigned int sock);
-+static int pxa_pcmcia_register_callback(unsigned int sock,
-+ void (*handler)(void *,
-+ unsigned int),
-+ void *info);
-+static int pxa_pcmcia_inquire_socket(unsigned int sock,
-+ socket_cap_t *cap);
-+static int pxa_pcmcia_get_status(unsigned int sock, u_int *value);
-+static int pxa_pcmcia_get_socket(unsigned int sock,
-+ socket_state_t *state);
-+static int pxa_pcmcia_set_socket(unsigned int sock,
-+ socket_state_t *state);
-+static int pxa_pcmcia_get_io_map(unsigned int sock,
-+ struct pccard_io_map *io);
-+static int pxa_pcmcia_set_io_map(unsigned int sock,
-+ struct pccard_io_map *io);
-+static int pxa_pcmcia_get_mem_map(unsigned int sock,
-+ struct pccard_mem_map *mem);
-+static int pxa_pcmcia_set_mem_map(unsigned int sock,
-+ struct pccard_mem_map *mem);
-+#ifdef CONFIG_PROC_FS
-+static void pxa_pcmcia_proc_setup(unsigned int sock,
-+ struct proc_dir_entry *base);
-+#endif
-+
-+static struct pccard_operations pxa_pcmcia_operations = {
-+ pxa_pcmcia_init,
-+ pxa_pcmcia_suspend,
-+ pxa_pcmcia_register_callback,
-+ pxa_pcmcia_inquire_socket,
-+ pxa_pcmcia_get_status,
-+ pxa_pcmcia_get_socket,
-+ pxa_pcmcia_set_socket,
-+ pxa_pcmcia_get_io_map,
-+ pxa_pcmcia_set_io_map,
-+ pxa_pcmcia_get_mem_map,
-+ pxa_pcmcia_set_mem_map,
-+#ifdef CONFIG_PROC_FS
-+ pxa_pcmcia_proc_setup
-+#endif
-+};
-+
-+#ifdef CONFIG_CPU_FREQ
-+/* forward declaration */
-+static struct notifier_block pxa_pcmcia_notifier_block;
-+#endif
-+
-+
-+/* pxa_pcmcia_driver_init()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ *
-+ * This routine performs a basic sanity check to ensure that this
-+ * kernel has been built with the appropriate board-specific low-level
-+ * PCMCIA support, performs low-level PCMCIA initialization, registers
-+ * this socket driver with Card Services, and then spawns the daemon
-+ * thread which is the real workhorse of the socket driver.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
-+ * on the low-level kernel interface.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int __init pxa_pcmcia_driver_init(void){
-+ servinfo_t info;
-+ struct pcmcia_init pcmcia_init;
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+ unsigned int i, clock;
-+ unsigned long mecr;
-+
-+ printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE);
-+
-+ CardServices(GetCardServicesInfo, &info);
-+
-+ if(info.Revision!=CS_RELEASE_CODE){
-+ printk(KERN_ERR "Card Services release codes do not match\n");
-+ return -1;
-+ }
-+
-+ /* Setup GPIOs for PCMCIA/CF alternate function mode.
-+ *
-+ * It would be nice if set_GPIO_mode included support
-+ * for driving GPIO outputs to default high/low state
-+ * before programming GPIOs as outputs. Setting GPIO
-+ * outputs to default high/low state via GPSR/GPCR
-+ * before defining them as outputs should reduce
-+ * the possibility of glitching outputs during GPIO
-+ * setup. This of course assumes external terminators
-+ * are present to hold GPIOs in a defined state.
-+ *
-+ * In the meantime, setup default state of GPIO
-+ * outputs before we enable them as outputs.
-+ */
-+
-+ GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-+ GPIO_bit(GPIO49_nPWE) |
-+ GPIO_bit(GPIO50_nPIOR) |
-+ GPIO_bit(GPIO51_nPIOW) |
-+ GPIO_bit(GPIO52_nPCE_1) |
-+ GPIO_bit(GPIO53_nPCE_2);
-+
-+ set_GPIO_mode(GPIO48_nPOE_MD);
-+ set_GPIO_mode(GPIO49_nPWE_MD);
-+ set_GPIO_mode(GPIO50_nPIOR_MD);
-+ set_GPIO_mode(GPIO51_nPIOW_MD);
-+ set_GPIO_mode(GPIO52_nPCE_1_MD);
-+ set_GPIO_mode(GPIO53_nPCE_2_MD);
-+ set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
-+ set_GPIO_mode(GPIO55_nPREG_MD);
-+ set_GPIO_mode(GPIO56_nPWAIT_MD);
-+ set_GPIO_mode(GPIO57_nIOIS16_MD);
-+
-+
-+ if(machine_is_lubbock()){
-+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_CSB226)
-+ pcmcia_low_level=&lubbock_pcmcia_ops;
-+#endif
-+ } else if (machine_is_pxa_idp()) {
-+ pcmcia_low_level=&pxa_idp_pcmcia_ops;
-+ } else if( machine_is_pxa_cerf()){
-+ pcmcia_low_level=&cerf_pcmcia_ops;
-+ } else if (machine_is_trizeps2()){
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ pcmcia_low_level=&trizeps2_pcmcia_ops;
-+#endif
-+ }
-+
-+ if (!pcmcia_low_level) {
-+ printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n");
-+ return -ENODEV;
-+ }
-+
-+ pcmcia_init.handler=pxa_pcmcia_interrupt;
-+
-+ if((pxa_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){
-+ printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n");
-+ return -EIO;
-+ }
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ /* Configure MECR based on the number of sockets present. */
-+ if (pxa_pcmcia_socket_count == 2) {
-+ MECR |= GPIO_bit(0);
-+ } else {
-+ MECR &= ~GPIO_bit(0);
-+ }
-+
-+ if(pcmcia_low_level->socket_state(&state_array)<0){
-+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
-+ return -EIO;
-+ }
-+
-+ /* Well, it looks good to go. So we can now enable the PCMCIA
-+ * controller.
-+ */
-+ MECR |= GPIO_bit(1);
-+
-+ /* We need to initialize the MCXX registers to default values
-+ * here because we're not guaranteed to see a SetIOMap operation
-+ * at runtime.
-+ */
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ for(i=0; i<pxa_pcmcia_socket_count; ++i){
-+ pxa_pcmcia_socket[i].k_state=state[i];
-+
-+ /* This is an interim fix. Apparently, SetSocket is no longer
-+ * called to initialize each socket (prior to the first detect
-+ * event). For now, we'll just manually set up the mask.
-+ */
-+ pxa_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
-+
-+ pxa_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE;
-+ pxa_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i);
-+ pxa_pcmcia_socket[i].phys_mem=_PCMCIAMem(i);
-+
-+ /* REVISIT: cleanup these macros */
-+ //MCIO_SET(i, PXA_PCMCIA_IO_ACCESS, clock);
-+ //MCATTR_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
-+ //MCMEM_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
-+
-+ pxa_pcmcia_socket[i].speed_io=PXA_PCMCIA_IO_ACCESS;
-+ pxa_pcmcia_socket[i].speed_attr=PXA_PCMCIA_ATTR_MEM_ACCESS;
-+ pxa_pcmcia_socket[i].speed_mem=PXA_PCMCIA_5V_MEM_ACCESS;
-+ }
-+
-+/* REVISIT: cleanup these macros */
-+MCMEM0 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCMEM1 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCIO0 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCIO1 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+
-+#ifdef CONFIG_CPU_FREQ
-+ if(cpufreq_register_notifier(&pxa_pcmcia_notifier_block) < 0){
-+ printk(KERN_ERR "Unable to register CPU frequency change notifier\n");
-+ return -ENXIO;
-+ }
-+#endif
-+
-+ /* Only advertise as many sockets as we can detect: */
-+ if(register_ss_entry(pxa_pcmcia_socket_count,
-+ &pxa_pcmcia_operations)<0){
-+ printk(KERN_ERR "Unable to register socket service routine\n");
-+ return -ENXIO;
-+ }
-+
-+ /* Start the event poll timer. It will reschedule by itself afterwards. */
-+ pxa_pcmcia_poll_event(0);
-+
-+ DEBUG(1, "pxa_cs: initialization complete\n");
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_driver_init() */
-+
-+module_init(pxa_pcmcia_driver_init);
-+
-+
-+/* pxa_pcmcia_driver_shutdown()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Invokes the low-level kernel service to free IRQs associated with this
-+ * socket controller and reset GPIO edge detection.
-+ */
-+static void __exit pxa_pcmcia_driver_shutdown(void){
-+
-+ del_timer_sync(&poll_timer);
-+ unregister_ss_entry(&pxa_pcmcia_operations);
-+#ifdef CONFIG_CPU_FREQ
-+ cpufreq_unregister_notifier(&pxa_pcmcia_notifier_block);
-+#endif
-+ pcmcia_low_level->shutdown();
-+ flush_scheduled_tasks();
-+
-+ DEBUG(1, "pxa_cs: shutdown complete\n");
-+}
-+
-+module_exit(pxa_pcmcia_driver_shutdown);
-+
-+
-+/* pxa_pcmcia_init()
-+ * ^^^^^^^^^^^^^^^^^^^^
-+ * We perform all of the interesting initialization tasks in
-+ * pxa_pcmcia_driver_init().
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_init(unsigned int sock){
-+
-+ DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_suspend()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^
-+ * We don't currently perform any actions on a suspend.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_suspend(unsigned int sock)
-+{
-+ socket_state_t st;
-+ int ret;
-+
-+ DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
-+
-+ st.Vcc = 0;
-+ st.Vpp = 0;
-+ st.flags = SS_RESET;
-+
-+ ret = pcmcia_low_level->configure_socket(sock, &st);
-+
-+ if (ret == 0)
-+ pxa_pcmcia_socket[sock].cs_state = dead_socket;
-+
-+ return ret;
-+}
-+
-+
-+/* pxa_pcmcia_events()
-+ * ^^^^^^^^^^^^^^^^^^^^^^
-+ * Helper routine to generate a Card Services event mask based on
-+ * state information obtained from the kernel low-level PCMCIA layer
-+ * in a recent (and previous) sampling. Updates `prev_state'.
-+ *
-+ * Returns: an event mask for the given socket state.
-+ */
-+static inline unsigned pxa_pcmcia_events(struct pcmcia_state *state,
-+ struct pcmcia_state *prev_state,
-+ unsigned int mask,
-+ unsigned int flags){
-+ unsigned int events=0;
-+
-+ if(state->detect!=prev_state->detect){
-+
-+ DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
-+
-+ events|=mask&SS_DETECT;
-+ }
-+
-+ if(state->ready!=prev_state->ready){
-+
-+ DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
-+
-+ events|=mask&((flags&SS_IOCARD)?0:SS_READY);
-+ }
-+
-+ if(state->bvd1!=prev_state->bvd1){
-+
-+ DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
-+
-+ events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD;
-+ }
-+
-+ if(state->bvd2!=prev_state->bvd2){
-+
-+ DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
-+
-+ events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN;
-+ }
-+
-+ DEBUG(2, "events: %s%s%s%s%s%s\n",
-+ (events==0)?"<NONE>":"",
-+ (events&SS_DETECT)?"DETECT ":"",
-+ (events&SS_READY)?"READY ":"",
-+ (events&SS_BATDEAD)?"BATDEAD ":"",
-+ (events&SS_BATWARN)?"BATWARN ":"",
-+ (events&SS_STSCHG)?"STSCHG ":"");
-+
-+ *prev_state=*state;
-+
-+ return events;
-+
-+} /* pxa_pcmcia_events() */
-+
-+
-+/* pxa_pcmcia_task_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Processes serviceable socket events using the "eventd" thread context.
-+ *
-+ * Event processing (specifically, the invocation of the Card Services event
-+ * callback) occurs in this thread rather than in the actual interrupt
-+ * handler due to the use of scheduling operations in the PCMCIA core.
-+ */
-+static void pxa_pcmcia_task_handler(void *data) {
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+ int i, events, all_events, irq_status;
-+
-+ DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ do {
-+
-+ DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
-+
-+ if((irq_status=pcmcia_low_level->socket_state(&state_array))<0)
-+ printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
-+
-+ all_events=0;
-+
-+ if(irq_status>0){
-+
-+ for(i=0; i<state_array.size; ++i, all_events|=events)
-+ if((events=
-+ pxa_pcmcia_events(&state[i],
-+ &pxa_pcmcia_socket[i].k_state,
-+ pxa_pcmcia_socket[i].cs_state.csc_mask,
-+ pxa_pcmcia_socket[i].cs_state.flags)))
-+ if(pxa_pcmcia_socket[i].handler!=NULL)
-+ pxa_pcmcia_socket[i].handler(pxa_pcmcia_socket[i].handler_info,
-+ events);
-+ }
-+
-+ } while(all_events);
-+} /* pxa_pcmcia_task_handler() */
-+
-+static struct tq_struct pxa_pcmcia_task = {
-+ routine: pxa_pcmcia_task_handler
-+};
-+
-+
-+/* pxa_pcmcia_poll_event()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Let's poll for events in addition to IRQs since IRQ only is unreliable...
-+ */
-+static void pxa_pcmcia_poll_event(unsigned long dummy)
-+{
-+ DEBUG(3, "%s(): polling for events\n", __FUNCTION__);
-+ poll_timer.function = pxa_pcmcia_poll_event;
-+ poll_timer.expires = jiffies + PXA_PCMCIA_POLL_PERIOD;
-+ add_timer(&poll_timer);
-+ schedule_task(&pxa_pcmcia_task);
-+}
-+
-+
-+/* pxa_pcmcia_interrupt()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Service routine for socket driver interrupts (requested by the
-+ * low-level PCMCIA init() operation via pxa_pcmcia_thread()).
-+ * The actual interrupt-servicing work is performed by
-+ * pxa_pcmcia_thread(), largely because the Card Services event-
-+ * handling code performs scheduling operations which cannot be
-+ * executed from within an interrupt context.
-+ */
-+static void pxa_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
-+ DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
-+ schedule_task(&pxa_pcmcia_task);
-+}
-+
-+
-+/* pxa_pcmcia_register_callback()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the register_callback() operation for the in-kernel
-+ * PCMCIA service (formerly SS_RegisterCallback in Card Services). If
-+ * the function pointer `handler' is not NULL, remember the callback
-+ * location in the state for `sock', and increment the usage counter
-+ * for the driver module. (The callback is invoked from the interrupt
-+ * service routine, pxa_pcmcia_interrupt(), to notify Card Services
-+ * of interesting events.) Otherwise, clear the callback pointer in the
-+ * socket state and decrement the module usage count.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_register_callback(unsigned int sock,
-+ void (*handler)(void *,
-+ unsigned int),
-+ void *info){
-+ if(handler==NULL){
-+ pxa_pcmcia_socket[sock].handler=NULL;
-+ MOD_DEC_USE_COUNT;
-+ } else {
-+ MOD_INC_USE_COUNT;
-+ pxa_pcmcia_socket[sock].handler=handler;
-+ pxa_pcmcia_socket[sock].handler_info=info;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_inquire_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the inquire_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_InquireSocket in Card Services). Of note is
-+ * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
-+ * `cap' to "trick" Card Services into tolerating large "I/O memory"
-+ * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
-+ * resource database check. (Mapped memory is set up within the socket
-+ * driver itself.)
-+ *
-+ * In conjunction with the STATIC_MAP capability is a new field,
-+ * `io_offset', recommended by David Hinds. Rather than go through
-+ * the SetIOMap interface (which is not quite suited for communicating
-+ * window locations up from the socket driver), we just pass up
-+ * an offset which is applied to client-requested base I/O addresses
-+ * in alloc_io_space().
-+ *
-+ * Returns: 0 on success, -1 if no pin has been configured for `sock'
-+ */
-+static int pxa_pcmcia_inquire_socket(unsigned int sock,
-+ socket_cap_t *cap){
-+ struct pcmcia_irq_info irq_info;
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(sock>=pxa_pcmcia_socket_count){
-+ printk(KERN_ERR "pxa_cs: socket %u not configured\n", sock);
-+ return -1;
-+ }
-+
-+ /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
-+ * force_low argument to validate_mem() in rsrc_mgr.c -- since in
-+ * general, the mapped * addresses of the PCMCIA memory regions
-+ * will not be within 0xffff, setting force_low would be
-+ * undesirable.
-+ *
-+ * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
-+ * resource database; we instead pass up physical address ranges
-+ * and allow other parts of Card Services to deal with remapping.
-+ *
-+ * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
-+ * not 32-bit CardBus devices.
-+ */
-+ cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
-+
-+ irq_info.sock=sock;
-+ irq_info.irq=-1;
-+
-+ if(pcmcia_low_level->get_irq_info(&irq_info)<0){
-+ printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n",
-+ sock);
-+ return -1;
-+ }
-+
-+ cap->irq_mask=0;
-+ cap->map_size=PAGE_SIZE;
-+ cap->pci_irq=irq_info.irq;
-+ cap->io_offset=pxa_pcmcia_socket[sock].virt_io;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_inquire_socket() */
-+
-+
-+/* pxa_pcmcia_get_status()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_status() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetStatus in Card Services). Essentially just
-+ * fills in bits in `status' according to internal driver state or
-+ * the value of the voltage detect chipselect register.
-+ *
-+ * As a debugging note, during card startup, the PCMCIA core issues
-+ * three set_socket() commands in a row the first with RESET deasserted,
-+ * the second with RESET asserted, and the last with RESET deasserted
-+ * again. Following the third set_socket(), a get_status() command will
-+ * be issued. The kernel is looking for the SS_READY flag (see
-+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_get_status(unsigned int sock,
-+ unsigned int *status){
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ if((pcmcia_low_level->socket_state(&state_array))<0){
-+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
-+ return -1;
-+ }
-+
-+ pxa_pcmcia_socket[sock].k_state=state[sock];
-+
-+ *status=state[sock].detect?SS_DETECT:0;
-+
-+ *status|=state[sock].ready?SS_READY:0;
-+
-+ /* The power status of individual sockets is not available
-+ * explicitly from the hardware, so we just remember the state
-+ * and regurgitate it upon request:
-+ */
-+ *status|=pxa_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
-+
-+ if(pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
-+ *status|=state[sock].bvd1?SS_STSCHG:0;
-+ else {
-+ if(state[sock].bvd1==0)
-+ *status|=SS_BATDEAD;
-+ else if(state[sock].bvd2==0)
-+ *status|=SS_BATWARN;
-+ }
-+
-+ *status|=state[sock].vs_3v?SS_3VCARD:0;
-+
-+ *status|=state[sock].vs_Xv?SS_XVCARD:0;
-+
-+ DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n",
-+ (*status&SS_DETECT)?"DETECT ":"",
-+ (*status&SS_READY)?"READY ":"",
-+ (*status&SS_BATDEAD)?"BATDEAD ":"",
-+ (*status&SS_BATWARN)?"BATWARN ":"",
-+ (*status&SS_POWERON)?"POWERON ":"",
-+ (*status&SS_STSCHG)?"STSCHG ":"",
-+ (*status&SS_3VCARD)?"3VCARD ":"",
-+ (*status&SS_XVCARD)?"XVCARD ":"");
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_get_status() */
-+
-+
-+/* pxa_pcmcia_get_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetSocket in Card Services). Not a very
-+ * exciting routine.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_get_socket(unsigned int sock,
-+ socket_state_t *state){
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ /* This information was given to us in an earlier call to set_socket(),
-+ * so we're just regurgitating it here:
-+ */
-+ *state=pxa_pcmcia_socket[sock].cs_state;
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetSocket in Card Services). We more or
-+ * less punt all of this work and let the kernel handle the details
-+ * of power configuration, reset, &c. We also record the value of
-+ * `state' in order to regurgitate it to the PCMCIA core later.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_set_socket(unsigned int sock,
-+ socket_state_t *state){
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
-+ "\tVcc %d Vpp %d irq %d\n",
-+ (state->csc_mask==0)?"<NONE>":"",
-+ (state->csc_mask&SS_DETECT)?"DETECT ":"",
-+ (state->csc_mask&SS_READY)?"READY ":"",
-+ (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-+ (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-+ (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-+ (state->flags==0)?"<NONE>":"",
-+ (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-+ (state->flags&SS_IOCARD)?"IOCARD ":"",
-+ (state->flags&SS_RESET)?"RESET ":"",
-+ (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-+ (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
-+ state->Vcc, state->Vpp, state->io_irq);
-+
-+ if(pcmcia_low_level->configure_socket(sock, state)<0){
-+ printk(KERN_ERR "Unable to configure socket %u\n", sock);
-+ return -1;
-+ }
-+
-+ pxa_pcmcia_socket[sock].cs_state=*state;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_socket() */
-+
-+
-+/* pxa_pcmcia_get_io_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_io_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetIOMap in Card Services). Just returns an
-+ * I/O map descriptor which was assigned earlier by a set_io_map().
-+ *
-+ * Returns: 0 on success, -1 if the map index was out of range
-+ */
-+static int pxa_pcmcia_get_io_map(unsigned int sock,
-+ struct pccard_io_map *map){
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(map->map>=MAX_IO_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ *map=pxa_pcmcia_socket[sock].io_map[map->map];
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_io_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_io_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetIOMap in Card Services). We configure
-+ * the map speed as requested, but override the address ranges
-+ * supplied by Card Services.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_set_io_map(unsigned int sock,
-+ struct pccard_io_map *map){
-+ unsigned int clock, speed;
-+ unsigned long mecr, start;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n"
-+ "\tflags: %s%s%s%s%s%s%s%s\n",
-+ map->map, map->speed, map->start, map->stop,
-+ (map->flags==0)?"<NONE>":"",
-+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-+ (map->flags&MAP_16BIT)?"16BIT ":"",
-+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-+ (map->flags&MAP_0WS)?"0WS ":"",
-+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
-+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-+ (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
-+
-+ if(map->map>=MAX_IO_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ if(map->flags&MAP_ACTIVE){
-+
-+ speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS;
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ pxa_pcmcia_socket[sock].speed_io=speed;
-+
-+ if (sock == 0) {
-+ MCIO0 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCIO1 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+
-+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
-+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
-+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
-+ sock, MECR_BSIO_GET(mecr, sock));
-+
-+ }
-+
-+ start=map->start;
-+
-+ if(map->stop==1)
-+ map->stop=PAGE_SIZE-1;
-+
-+ map->start=pxa_pcmcia_socket[sock].virt_io;
-+ map->stop=map->start+(map->stop-start);
-+
-+ pxa_pcmcia_socket[sock].io_map[map->map]=*map;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_io_map() */
-+
-+
-+/* pxa_pcmcia_get_mem_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_mem_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetMemMap in Card Services). Just returns a
-+ * memory map descriptor which was assigned earlier by a
-+ * set_mem_map() request.
-+ *
-+ * Returns: 0 on success, -1 if the map index was out of range
-+ */
-+static int pxa_pcmcia_get_mem_map(unsigned int sock,
-+ struct pccard_mem_map *map){
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(map->map>=MAX_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ *map=pxa_pcmcia_socket[sock].mem_map[map->map];
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_mem_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_mem_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetMemMap in Card Services). We configure
-+ * the map speed as requested, but override the address ranges
-+ * supplied by Card Services.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_set_mem_map(unsigned int sock,
-+ struct pccard_mem_map *map){
-+ unsigned int clock, speed;
-+ unsigned long mecr, start;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n"
-+ "\tsys_stop %#lx\n\tcard_start %#x\n"
-+ "\tflags: %s%s%s%s%s%s%s%s\n",
-+ map->map, map->speed, map->sys_start, map->sys_stop,
-+ map->card_start, (map->flags==0)?"<NONE>":"",
-+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-+ (map->flags&MAP_16BIT)?"16BIT ":"",
-+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-+ (map->flags&MAP_0WS)?"0WS ":"",
-+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
-+ (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
-+
-+ if(map->map>=MAX_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ if(map->flags&MAP_ACTIVE){
-+ /* When clients issue RequestMap, the access speed is not always
-+ * properly configured:
-+ */
-+ if(map->speed > 0)
-+ speed = map->speed;
-+ else
-+ switch(pxa_pcmcia_socket[sock].cs_state.Vcc){
-+ case 33:
-+ speed = PXA_PCMCIA_3V_MEM_ACCESS;
-+ break;
-+ default:
-+ speed = PXA_PCMCIA_5V_MEM_ACCESS;
-+ }
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ if(map->flags&MAP_ATTRIB){
-+ if (sock == 0) {
-+ MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+ pxa_pcmcia_socket[sock].speed_attr=speed;
-+ } else {
-+ if (sock == 0) {
-+ MCMEM0 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCMEM1 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+ pxa_pcmcia_socket[sock].speed_mem=speed;
-+ }
-+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
-+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
-+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
-+ sock, MECR_BSIO_GET(mecr, sock));
-+ }
-+
-+ start=map->sys_start;
-+
-+ if(map->sys_stop==0)
-+ map->sys_stop=PAGE_SIZE-1;
-+
-+ map->sys_start=(map->flags & MAP_ATTRIB)?\
-+ pxa_pcmcia_socket[sock].phys_attr:\
-+ pxa_pcmcia_socket[sock].phys_mem;
-+
-+ map->sys_stop=map->sys_start+(map->sys_stop-start);
-+
-+ pxa_pcmcia_socket[sock].mem_map[map->map]=*map;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_mem_map() */
-+
-+
-+#if defined(CONFIG_PROC_FS)
-+
-+/* pxa_pcmcia_proc_setup()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the proc_setup() operation for the in-kernel PCMCIA
-+ * service (formerly SS_ProcSetup in Card Services).
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static void pxa_pcmcia_proc_setup(unsigned int sock,
-+ struct proc_dir_entry *base){
-+ struct proc_dir_entry *entry;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if((entry=create_proc_entry("status", 0, base))==NULL){
-+ printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
-+ return;
-+ }
-+
-+ entry->read_proc=pxa_pcmcia_proc_status;
-+ entry->data=(void *)sock;
-+}
-+
-+
-+/* pxa_pcmcia_proc_status()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the /proc/bus/pccard/??/status file.
-+ *
-+ * Returns: the number of characters added to the buffer
-+ */
-+static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
-+ int count, int *eof, void *data){
-+ char *p=buf;
-+ unsigned int sock=(unsigned int)data;
-+ unsigned int clock = get_lclk_frequency_10khz();
-+ unsigned long mecr = MECR;
-+
-+ p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].k_state.detect?"detect ":"",
-+ pxa_pcmcia_socket[sock].k_state.ready?"ready ":"",
-+ pxa_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
-+ pxa_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
-+ pxa_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
-+
-+ p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
-+ pxa_pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
-+ pxa_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
-+ "SS_IOCARD ":"",
-+ (pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
-+ pxa_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
-+ ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
-+ (pxa_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
-+ ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
-+ (pxa_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
-+
-+ p+=sprintf(p, "mask : %s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
-+ "SS_DETECT ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
-+ "SS_READY ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
-+ "SS_BATDEAD ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
-+ "SS_BATWARN ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
-+ "SS_STSCHG ":"");
-+
-+ p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
-+ "SS_PWR_AUTO ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
-+ "SS_IOCARD ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_RESET?\
-+ "SS_RESET ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
-+ "SS_SPKR_ENA ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
-+ "SS_OUTPUT_ENA ":"");
-+
-+ p+=sprintf(p, "Vcc : %d\n", pxa_pcmcia_socket[sock].cs_state.Vcc);
-+
-+ p+=sprintf(p, "Vpp : %d\n", pxa_pcmcia_socket[sock].cs_state.Vpp);
-+
-+ p+=sprintf(p, "irq : %d\n", pxa_pcmcia_socket[sock].cs_state.io_irq);
-+
-+ p+=sprintf(p, "I/O : %u (%u)\n", pxa_pcmcia_socket[sock].speed_io,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCIO1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCIO0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ p+=sprintf(p, "attribute: %u (%u)\n", pxa_pcmcia_socket[sock].speed_attr,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCATT1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCATT0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ p+=sprintf(p, "common : %u (%u)\n", pxa_pcmcia_socket[sock].speed_mem,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCMEM1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCMEM0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ return p-buf;
-+}
-+
-+#endif /* defined(CONFIG_PROC_FS) */
-+
-+
-+#ifdef CONFIG_CPU_FREQ
-+
-+/* pxa_pcmcia_update_mecr()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * When pxa_pcmcia_notifier() decides that a MECR adjustment (due
-+ * to a core clock frequency change) is needed, this routine establishes
-+ * new BS_xx values consistent with the clock speed `clock'.
-+ */
-+static void pxa_pcmcia_update_mecr(unsigned int clock){
-+ unsigned int sock;
-+
-+ for(sock = 0; sock < PXA_PCMCIA_MAX_SOCK; ++sock){
-+
-+ // REVISIT: MCXX macros needed here
-+ // MECR_BSIO_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_io,
-+// clock));
-+ // MECR_BSA_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_attr,
-+// clock));
-+ // MECR_BSM_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_mem,
-+// clock));
-+ }
-+}
-+
-+/* pxa_pcmcia_notifier()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^
-+ * When changing the processor core clock frequency, it is necessary
-+ * to adjust the MECR timings accordingly. We've recorded the timings
-+ * requested by Card Services, so this is just a matter of finding
-+ * out what our current speed is, and then recomputing the new MECR
-+ * values.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_notifier(struct notifier_block *nb,
-+ unsigned long val, void *data){
-+ struct cpufreq_info *ci = data;
-+
-+ switch(val){
-+ case CPUFREQ_MINMAX:
-+
-+ break;
-+
-+ case CPUFREQ_PRECHANGE:
-+
-+ if(ci->new_freq > ci->old_freq){
-+ DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
-+ __FUNCTION__,
-+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
-+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
-+ pxa_pcmcia_update_mecr(ci->new_freq);
-+ }
-+
-+ break;
-+
-+ case CPUFREQ_POSTCHANGE:
-+
-+ if(ci->new_freq < ci->old_freq){
-+ DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
-+ __FUNCTION__,
-+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
-+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
-+ pxa_pcmcia_update_mecr(ci->new_freq);
-+ }
-+
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__,
-+ val);
-+ return -1;
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static struct notifier_block pxa_pcmcia_notifier_block = {
-+ notifier_call: pxa_pcmcia_notifier
-+};
-+
-+#endif
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/pxa.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,233 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.h
-+ *
-+ */
-+
-+/*======================================================================
-+
-+ Device driver for the PCMCIA control functionality of Intel
-+ PXA250/210 microprocessors.
-+
-+ The contents of this file are subject to the Mozilla Public
-+ License Version 1.1 (the "License"); you may not use this file
-+ except in compliance with the License. You may obtain a copy of
-+ the License at http://www.mozilla.org/MPL/
-+
-+ Software distributed under the License is distributed on an "AS
-+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-+ implied. See the License for the specific language governing
-+ rights and limitations under the License.
-+
-+ The initial developer of the original code is John G. Dorsey
-+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
-+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
-+
-+ Alternatively, the contents of this file may be used under the
-+ terms of the GNU Public License version 2 (the "GPL"), in which
-+ case the provisions of the GPL are applicable instead of the
-+ above. If you wish to allow the use of your version of this file
-+ only under the terms of the GPL and not to allow others to use
-+ your version of this file under the MPL, indicate your decision
-+ by deleting the provisions above and replace them with the notice
-+ and other provisions required by the GPL. If you do not delete
-+ the provisions above, a recipient may use your version of this
-+ file under either the MPL or the GPL.
-+
-+======================================================================*/
-+
-+#if !defined(_PCMCIA_PXA_H)
-+# define _PCMCIA_PXA_H
-+
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/ss.h>
-+#include <pcmcia/bulkmem.h>
-+#include <pcmcia/cistpl.h>
-+#include "../cs_internal.h"
-+
-+#include <asm/arch/pcmcia.h>
-+
-+
-+/* MECR: Expansion Memory Configuration Register
-+ * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
-+ *
-+ * MECR layout is:
-+ *
-+ * FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
-+ *
-+ * (This layout is actually true only for the SA-1110; the FASTn bits are
-+ * reserved on the SA-1100.)
-+ */
-+
-+#define MCXX_SETUP_MASK (0x7f)
-+#define MCXX_ASST_MASK (0x1f)
-+#define MCXX_HOLD_MASK (0x3f)
-+#define MCXX_SETUP_SHIFT (0)
-+#define MCXX_ASST_SHIFT (7)
-+#define MCXX_HOLD_SHIFT (14)
-+
-+
-+#define MECR_SET(mecr, sock, shift, mask, bs) \
-+((mecr)=((mecr)&~(((mask)<<(shift))<<\
-+ ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
-+ (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
-+
-+#define MECR_GET(mecr, sock, shift, mask) \
-+((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
-+ (shift))&(mask))
-+
-+#define MECR_BSIO_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSIO_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_BSA_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSA_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_BSM_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSM_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_FAST_SET(mecr, sock, fast) \
-+MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
-+
-+#define MECR_FAST_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
-+
-+
-+/* This function implements the BS value calculation for setting the MECR
-+ * using integer arithmetic:
-+ */
-+static inline unsigned int pxa_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
-+ unsigned int cpu_clock_khz){
-+ unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
-+ return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
-+}
-+
-+static inline u_int pxa_mcxx_hold(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 300000) + ((code % 300000) ? 1 : 0);
-+}
-+
-+static inline u_int pxa_mcxx_asst(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 300000) + ((code % 300000) ? 1 : 0);
-+}
-+
-+static inline u_int pxa_mcxx_setup(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 100000) + ((code % 100000) ? 1 : 0) + 1;
-+}
-+
-+/* This function returns the (approxmiate) command assertion period, in
-+ * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
-+ */
-+
-+static inline u_int pxa_pcmcia_cmd_time(u_int mem_clk_10khz,
-+ u_int pcmcia_mcxx_asst){
-+ return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
-+}
-+
-+
-+/* SA-1100 PCMCIA Memory and I/O timing
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * The SA-1110 Developer's Manual, section 10.2.5, says the following:
-+ *
-+ * "To calculate the recommended BS_xx value for each address space:
-+ * divide the command width time (the greater of twIOWR and twIORD,
-+ * or the greater of twWE and twOE) by processor cycle time; divide
-+ * by 2; divide again by 3 (number of BCLK's per command assertion);
-+ * round up to the next whole number; and subtract 1."
-+ *
-+ * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
-+ * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
-+ * a minimum value of 165ns, as well. Section 4.7.2 (describing
-+ * common and attribute memory write timing) says that twWE has a
-+ * minimum value of 150ns for a 250ns cycle time (for 5V operation;
-+ * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
-+ * operation, also section 4.7.4). Section 4.7.3 says that taOE
-+ * has a maximum value of 150ns for a 300ns cycle time (for 5V
-+ * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
-+ *
-+ * When configuring memory maps, Card Services appears to adopt the policy
-+ * that a memory access time of "0" means "use the default." The default
-+ * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
-+ * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
-+ * memory command width time is 300ns.
-+ */
-+
-+/* The PXA 250 and PXA 210 Application Processors Developer's Manual
-+ * was used to determine correct PXA_PCMCIA_IO_ACCES time
-+ */
-+
-+#define PXA_PCMCIA_IO_ACCESS (165)
-+
-+/* Default PC Card Common Memory timings*/
-+
-+#define PXA_PCMCIA_5V_MEM_ACCESS (250)
-+#define PXA_PCMCIA_3V_MEM_ACCESS (250)
-+
-+/* Atrribute Memory timing - must be constant via PC Card standart*/
-+
-+#define PXA_PCMCIA_ATTR_MEM_ACCESS (300)
-+
-+
-+/* The socket driver actually works nicely in interrupt-driven form,
-+ * so the (relatively infrequent) polling is "just to be sure."
-+ */
-+#define PXA_PCMCIA_POLL_PERIOD (2*HZ)
-+
-+
-+/* This structure encapsulates per-socket state which we might need to
-+ * use when responding to a Card Services query of some kind.
-+ */
-+struct pxa_pcmcia_socket {
-+ socket_state_t cs_state;
-+ struct pcmcia_state k_state;
-+ unsigned int irq;
-+ void (*handler)(void *, unsigned int);
-+ void *handler_info;
-+ pccard_io_map io_map[MAX_IO_WIN];
-+ pccard_mem_map mem_map[MAX_WIN];
-+ ioaddr_t virt_io, phys_attr, phys_mem;
-+ unsigned short speed_io, speed_attr, speed_mem;
-+};
-+
-+
-+/* I/O pins replacing memory pins
-+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
-+ *
-+ * These signals change meaning when going from memory-only to
-+ * memory-or-I/O interface:
-+ */
-+#define iostschg bvd1
-+#define iospkr bvd2
-+
-+
-+/*
-+ * Declaration for all implementation specific low_level operations.
-+ */
-+extern struct pcmcia_low_level lubbock_pcmcia_ops;
-+extern struct pcmcia_low_level pxa_idp_pcmcia_ops;
-+extern struct pcmcia_low_level cerf_pcmcia_ops;
-+extern struct pcmcia_low_level trizeps2_pcmcia_ops;
-+
-+#endif /* !defined(_PCMCIA_PXA_H) */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/pxa_idp.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,297 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa_idp.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
-+ *
-+ * Platform specific routines for the Accelent PXA250 IDP, based on those
-+ * first done for the Lubbock.
-+ *
-+ * Version 1.0 2002-05-02 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+static int
-+pxa_idp_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int return_val = 0;
-+
-+ /* Set PCMCIA Socket 0 power to standby mode.
-+ * PXA IDP has dedicated CPLD pins for all this stuff :-)
-+ */
-+
-+ /* both slots disabled, reset NOT active */
-+ IDP_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE;
-+
-+ IDP_CPLD_PCCARD_PWR = 0; //all power to both slots off
-+
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID));
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID));
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID),
-+ GPIO_BOTH_EDGES);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID),
-+ GPIO_BOTH_EDGES);
-+
-+ /* irq's for slots: */
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT));
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT));
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT),
-+ GPIO_FALLING_EDGE);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT),
-+ GPIO_FALLING_EDGE);
-+
-+ return_val =
-+ request_irq(PCMCIA_S0_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD0", NULL);
-+
-+ if (return_val < 0)
-+ return -1;
-+
-+ return_val +=
-+ request_irq(PCMCIA_S1_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD1", NULL);
-+
-+ if (return_val < 0) {
-+ free_irq(PCMCIA_S0_CD_VALID, NULL);
-+ return -1;
-+ }
-+
-+ return 2;
-+}
-+
-+static int
-+pxa_idp_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(PCMCIA_S0_CD_VALID, NULL);
-+ free_irq(PCMCIA_S1_CD_VALID, NULL);
-+
-+ IDP_CPLD_PCCARD_EN = 0x03; //disable slots
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR = 0; //shut off all power
-+
-+ return 0;
-+}
-+
-+static int
-+pxa_idp_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ unsigned long status;
-+ int return_val = 1;
-+ int i;
-+ volatile unsigned long *stat_regs[2] = { &IDP_CPLD_PCCARD0_STATUS,
-+ &IDP_CPLD_PCCARD1_STATUS
-+ };
-+
-+ if (state_array->size < 2)
-+ return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size) * sizeof (struct pcmcia_state));
-+
-+ for (i = 0; i < 2; i++) {
-+
-+ status = *stat_regs[i];
-+
-+ /* this one is a gpio */
-+ state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1;
-+
-+ state_array->state[i].ready =
-+ ((status & _PCC_IRQ) == 0) ? 0 : 1;
-+ state_array->state[i].bvd1 = (status & PCC_BVD1) ? 0 : 1;
-+ state_array->state[i].bvd2 = (status & PCC_BVD2) ? 0 : 1;
-+ state_array->state[i].wrprot =
-+ (status & _PCC_WRPROT) ? 1 : 0;
-+ state_array->state[i].vs_3v = (status & PCC_VS1) ? 0 : 1;
-+ state_array->state[i].vs_Xv = (status & PCC_VS2) ? 0 : 1;
-+ }
-+
-+ return return_val;
-+}
-+
-+static int
-+pxa_idp_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-+{
-+ switch (info->sock) {
-+ case 0:
-+ info->irq = PCMCIA_S0_RDYINT;
-+ break;
-+
-+ case 1:
-+ info->irq = PCMCIA_S1_RDYINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+pxa_idp_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ /* The PXA Idp uses the Maxim MAX1602, with the following connections:
-+ *
-+ * Socket 0 (PCMCIA):
-+ * MAX1602 PXA_IDP Register
-+ * Pin Signal IDP_CPLD_PCCARD_PWR:
-+ * ----- ------- ----------------------
-+ * A0VPP PCC0_PWR0 bit0
-+ * A1VPP PCC0_PWR1 bit1
-+ * A0VCC PCC0_PWR2 bit2
-+ * A1VCC PCC0_PWR3 bit3
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ * Socket 1 (PCMCIA):
-+ * MAX1602 PXA_IDP Register
-+ * Pin Signal IDP_CPLD_PCCARD_PWR:
-+ * ----- ------- ----------------------
-+ * A0VPP PCC1_PWR0 bit4
-+ * A1VPP PCC1_PWR1 bit5
-+ * A0VCC PCC1_PWR2 bit6
-+ * A1VCC PCC1_PWR3 bit7
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ */
-+
-+ switch (sock) {
-+ case 0:
-+ switch (state->Vcc) {
-+ case 0:
-+ IDP_CPLD_PCCARD_EN |= PCC0_ENABLE; // disable socket
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ break;
-+
-+ case 33:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR3;
-+ IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE; //turn it on
-+ break;
-+
-+ case 50:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR2;
-+ IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
-+ break;
-+
-+ case 120:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc)
-+ IDP_CPLD_PCCARD_PWR =
-+ (IDP_CPLD_PCCARD_PWR &
-+ ~(PCC0_PWR0 | PCC0_PWR1)) | PCC0_PWR0;
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+
-+ IDP_CPLD_PCCARD_EN =
-+ (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC0_RESET)
-+ : (IDP_CPLD_PCCARD_EN & ~PCC0_RESET);
-+ break;
-+
-+ case 1:
-+ switch (state->Vcc) {
-+ case 0:
-+ IDP_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ break;
-+
-+ case 33:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR3;
-+ IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on
-+ break;
-+
-+ case 50:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR2;
-+ IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
-+ break;
-+
-+ case 120:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc)
-+ IDP_CPLD_PCCARD_PWR =
-+ (IDP_CPLD_PCCARD_PWR &
-+ ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0;
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+ IDP_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC1_RESET)
-+ : (IDP_CPLD_PCCARD_EN & ~PCC1_RESET);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+struct pcmcia_low_level pxa_idp_pcmcia_ops = {
-+ pxa_idp_pcmcia_init,
-+ pxa_idp_pcmcia_shutdown,
-+ pxa_idp_pcmcia_socket_state,
-+ pxa_idp_pcmcia_get_irq_info,
-+ pxa_idp_pcmcia_configure_socket
-+};
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/pxa/trizeps2.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,187 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/trizeps2.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
-+ *
-+ * Platform specific routines for the Keith-n-Koep Trizeps-II, based on IDP
-+ *
-+ * Copyright (c) 2003 Teradyne DS, Ltd.
-+ * Port to Trizeps-2 MT6N board by Luc De Cock
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+static int trizeps2_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int return_val = 0;
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+ unsigned short val;
-+
-+ /* reset the PCMCIA controller */
-+ val = trizeps2_bcr_shadow | BCR_PCMCIA_RESET;
-+ *bcr = val;
-+ udelay(500);
-+ /* un-reset it again */
-+ trizeps2_bcr_shadow &= ~BCR_PCMCIA_RESET;
-+ /* enable the PCMCIA buffer */
-+ trizeps2_bcr_shadow &= ~(1 << 5);
-+ *bcr = trizeps2_bcr_shadow;
-+
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID));
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID),
-+ PCMCIA_S_CD_VALID_EDGE);
-+ GPDR(IRQ_TO_GPIO(PCMCIA_S_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S_RDYINT));
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(PCMCIA_S_RDYINT),
-+ PCMCIA_S_RDYINT_EDGE);
-+
-+ return_val = request_irq(PCMCIA_S_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD", NULL);
-+ if (return_val < 0) {
-+ return -1;
-+ }
-+ /* only 1 slot */
-+ return 1;
-+}
-+
-+static int trizeps2_pcmcia_shutdown(void)
-+{
-+ free_irq(PCMCIA_S_CD_VALID, NULL);
-+
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+ trizeps2_bcr_shadow |= (1 << 5); /* pcmcia buffer off */
-+ *bcr = trizeps2_bcr_shadow;
-+ trizeps2_bcr_shadow &= 0xFFF0; /* pcmcia control logic grounded */
-+ *bcr = trizeps2_bcr_shadow;
-+
-+ return 0;
-+}
-+
-+static int trizeps2_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ unsigned long status;
-+ int return_val = 1;
-+ volatile unsigned short *stat_regs[1] = {
-+ &TRIZEPS2_PCCARD_STATUS
-+ };
-+
-+ if (state_array->size < 1)
-+ return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size) * sizeof (struct pcmcia_state));
-+
-+ status = *stat_regs[0];
-+
-+ /* this one is a gpio */
-+ state_array->state[0].detect = (PCC_DETECT) ? 0 : 1;
-+ state_array->state[0].ready = (PCC_READY) ? 1 : 0;
-+ state_array->state[0].bvd1 = (status & PCC_BVD1) ? 1 : 0;
-+ state_array->state[0].bvd2 = (status & PCC_BVD2) ? 1 : 0;
-+ state_array->state[0].wrprot = 0; /* r/w all the time */
-+ state_array->state[0].vs_3v = (status & PCC_VS1) ? 0 : 1;
-+ state_array->state[0].vs_Xv = (status & PCC_VS2) ? 0 : 1;
-+
-+ return return_val;
-+}
-+
-+static int trizeps2_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-+{
-+ switch (info->sock) {
-+ case 0:
-+ info->irq = PCMCIA_S_RDYINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int trizeps2_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ unsigned short cntr_logic = trizeps2_bcr_shadow & 0xF;
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+
-+ /* configure Vcc and Vpp */
-+ switch (sock) {
-+ case 0:
-+ switch (state->Vcc) {
-+ case 0:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ break;
-+
-+ case 33:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ cntr_logic |= PCC_3V;
-+ break;
-+
-+ case 50:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ cntr_logic |= PCC_5V;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ break;
-+
-+ case 120:
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ cntr_logic |= PCC_EN1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc) {
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ cntr_logic |= PCC_EN0;
-+ }
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+ trizeps2_bcr_shadow &= ~(PCC_EN0 | PCC_EN1 | PCC_3V | PCC_5V |
-+ BCR_PCMCIA_RESET);
-+ trizeps2_bcr_shadow |= cntr_logic;
-+ *bcr = trizeps2_bcr_shadow;
-+ /* reset PCMCIA controller if requested */
-+ trizeps2_bcr_shadow |=
-+ (state->flags & SS_RESET) ? BCR_PCMCIA_RESET : 0;
-+ *bcr = trizeps2_bcr_shadow;
-+ udelay(500);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+struct pcmcia_low_level trizeps2_pcmcia_ops = {
-+ trizeps2_pcmcia_init,
-+ trizeps2_pcmcia_shutdown,
-+ trizeps2_pcmcia_socket_state,
-+ trizeps2_pcmcia_get_irq_info,
-+ trizeps2_pcmcia_configure_socket
-+};
-+
---- linux-2.4.25/drivers/pcmcia/sa1100_cerf.c~2.4.25-vrs2-pxa1.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.c 2004-03-31 17:15:12.000000000 +0200
-@@ -7,15 +7,25 @@
- */
- #include <linux/kernel.h>
- #include <linux/sched.h>
-+#include <linux/delay.h>
-
- #include <asm/hardware.h>
- #include <asm/irq.h>
--#include "sa1100_generic.h"
-
--#ifdef CONFIG_SA1100_CERF_CPLD
--#define CERF_SOCKET 0
-+#include <pcmcia/ss.h>
-+#include <asm/arch/pcmcia.h>
-+#include "sa1100_cerf.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination
-+ */
-+//#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int pcmcia_debug = DEBUGGING;
- #else
--#define CERF_SOCKET 1
-+#define pcmcia_debug 0 /* gcc will remove all the debug code for us */
- #endif
-
- static struct irqs {
-@@ -23,122 +33,178 @@
- unsigned int gpio;
- const char *str;
- } irqs[] = {
-- { IRQ_GPIO_CF_CD, GPIO_CF_CD, "CF_CD" },
-- { IRQ_GPIO_CF_BVD2, GPIO_CF_BVD2, "CF_BVD2" },
-- { IRQ_GPIO_CF_BVD1, GPIO_CF_BVD1, "CF_BVD1" }
-+ { PCMCIA_IRQ_CF_CD, PCMCIA_GPIO_CF_CD_EDGE, "CF_CD" },
-+ { PCMCIA_IRQ_CF_BVD2, PCMCIA_GPIO_CF_BVD2_EDGE, "CF_BVD2" },
-+ { PCMCIA_IRQ_CF_BVD1, PCMCIA_GPIO_CF_BVD1_EDGE, "CF_BVD1" }
- };
-
-+static void cerf_pcmcia_reset( void)
-+{
-+ int i;
-+
-+ // Make sure SKTSEL is 0 (single slot)
-+ set_GPIO_mode(54 | GPIO_OUT);
-+ GPCR1 = GPIO_bit(54);
-+ set_GPIO_mode(GPIO54_pSKTSEL_MD);
-+
-+ PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
-+ mdelay(300);
-+
-+ PCMCIA_GPSR = PCMCIA_GPIO_CF_RESET_MASK;
-+ udelay(20);
-+
-+ PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
-+ mdelay(50);
-+
-+ for( i=0; i<10; i++)
-+ {
-+ if( cerf_pcmcia_level_ready()) break;
-+ mdelay(100);
-+ }
-+}
-+
- static int cerf_pcmcia_init(struct pcmcia_init *init)
- {
-- int i, res;
-+ int i, res;
-
-- set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_init: enter\n");
-
-- for (i = 0; i < ARRAY_SIZE(irqs); i++) {
-- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
-- res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-- irqs[i].str, NULL);
-- if (res)
-- goto irq_err;
-- }
-+ cerf_pcmcia_set_gpio_direction();
-
-- return 2;
-+ set_GPIO_IRQ_edge( PCMCIA_GPIO_CF_IRQ_EDGE, GPIO_FALLING_EDGE );
-
-- irq_err:
-- printk(KERN_ERR "%s: Request for IRQ%d failed\n", __FUNCTION__, irqs[i].irq);
-+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
-
-- while (i--)
-- free_irq(irqs[i].irq, NULL);
-+ set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
-
-- return -1;
-+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (res)
-+ goto irq_err;
-+ }
-+
-+ printk( KERN_INFO "PCMCIA for Cerf: OK\n");
-+
-+ return CERF_SOCKET+1; /* last socket used +1 */
-+
-+irq_err:
-+ printk(KERN_ERR "%s: Request for IRQ%d failed\n",
-+ __FUNCTION__, irqs[i].irq);
-+
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ return -1;
- }
-
- static int cerf_pcmcia_shutdown(void)
- {
-- int i;
-+ int i;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_shutdown: enter\n");
-
-- for (i = 0; i < ARRAY_SIZE(irqs); i++)
-- free_irq(irqs[i].irq, NULL);
-+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
-+ free_irq(irqs[i].irq, NULL);
-
-- return 0;
-+ return 0;
- }
-
--static int cerf_pcmcia_socket_state(struct pcmcia_state_array
-- *state_array){
-- unsigned long levels;
-- int i = CERF_SOCKET;
-+static int cerf_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ int i = CERF_SOCKET;
-
-- if(state_array->size<2) return -1;
-+ if( pcmcia_debug > 3)
-+ printk( KERN_INFO "cerf_pcmcia_socket_state: i=%d, size=%d\n",
-+ i, state_array->size);
-
-- levels=GPLR;
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-
-- state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
-- state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
-- state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
-- state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
-- state_array->state[i].wrprot=0;
-- state_array->state[i].vs_3v=1;
-- state_array->state[i].vs_Xv=0;
-+ state_array->state[i].detect = cerf_pcmcia_level_detect();
-+ state_array->state[i].ready = cerf_pcmcia_level_ready();
-+ state_array->state[i].bvd1 = cerf_pcmcia_level_bvd1();
-+ state_array->state[i].bvd2 = cerf_pcmcia_level_bvd2();
-+ state_array->state[i].wrprot=0;
-+ state_array->state[i].vs_3v=1;
-+ state_array->state[i].vs_Xv=0;
-
-- return 1;
-+ if( pcmcia_debug > 3)
-+ printk( KERN_INFO "cerf_pcmcia_socket_state: "
-+ "detect=%d ready=%d bvd1=%d bvd2=%d\n",
-+ state_array->state[i].detect,
-+ state_array->state[i].ready,
-+ state_array->state[i].bvd1,
-+ state_array->state[i].bvd2);
-+
-+ return 1;
- }
-
- static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-
-- if(info->sock>1) return -1;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_get_irq_info: "
-+ "sock=%d\n", info->sock);
-
-- if (info->sock == CERF_SOCKET)
-- info->irq=IRQ_GPIO_CF_IRQ;
-+ if(info->sock>1) return -1;
-
-- return 0;
-+ if (info->sock == CERF_SOCKET)
-+ info->irq=PCMCIA_IRQ_CF_IRQ;
-+
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_get_irq_info: irq=%d\n",info->irq);
-+
-+ return 0;
- }
-
--static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
-- *configure)
-+static int cerf_pcmcia_configure_socket( unsigned int sock, socket_state_t *state)
- {
-- if(configure->sock>1)
-- return -1;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_configure_socket:"
-+ "sock=%d vcc=%d flags=%x\n",
-+ sock, state->Vcc, state->flags);
-
-- if (configure->sock != CERF_SOCKET)
-- return 0;
-+ if(sock>1)
-+ return -1;
-
-- switch(configure->vcc){
-- case 0:
-- break;
-+ if (sock != CERF_SOCKET)
-+ return 0;
-
-- case 50:
-- case 33:
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPCR = GPIO_PWR_SHUTDOWN;
-+ switch(state->Vcc){
-+ case 0:
-+ break;
-+
-+ case 50:
-+ case 33:
-+#if defined(CONFIG_SA1100_CERF_CPLD)
-+ PCMCIA_GPDR |= PCMCIA_PWR_SHUTDOWN;
-+ PCMCIA_GPCR |= PCMCIA_PWR_SHUTDOWN;
- #endif
-- break;
-+ /* voltage selected automatically */
-+ break;
-
-- default:
-- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
-- configure->vcc);
-- return -1;
-- }
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-
-- if(configure->reset)
-- {
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPSR = GPIO_CF_RESET;
--#endif
-- }
-- else
-- {
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPCR = GPIO_CF_RESET;
--#endif
-- }
-+ if(state->flags&SS_RESET)
-+ {
-+ cerf_pcmcia_reset();
-+ }
-
-- return 0;
-+ return 0;
- }
-
-+#ifdef CONFIG_SA1100_CERF
- static int cerf_pcmcia_socket_init(int sock)
- {
- int i;
-
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_socket_init: sock=%d\n",sock);
-+
- if (sock == CERF_SOCKET)
- for (i = 0; i < ARRAY_SIZE(irqs); i++)
- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
-@@ -150,21 +216,26 @@
- {
- int i;
-
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_socket_suspend: sock=%d\n",sock);
-+
- if (sock == CERF_SOCKET)
- for (i = 0; i < ARRAY_SIZE(irqs); i++)
- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
-
- return 0;
- }
-+#endif
-
- struct pcmcia_low_level cerf_pcmcia_ops = {
-- init: cerf_pcmcia_init,
-- shutdown: cerf_pcmcia_shutdown,
-- socket_state: cerf_pcmcia_socket_state,
-- get_irq_info: cerf_pcmcia_get_irq_info,
-- configure_socket: cerf_pcmcia_configure_socket,
-+init: cerf_pcmcia_init,
-+shutdown: cerf_pcmcia_shutdown,
-+socket_state: cerf_pcmcia_socket_state,
-+get_irq_info: cerf_pcmcia_get_irq_info,
-+configure_socket: cerf_pcmcia_configure_socket,
-
-- socket_init: cerf_pcmcia_socket_init,
-- socket_suspend: cerf_pcmcia_socket_suspend,
-+#ifdef CONFIG_SA1100_CERF
-+socket_init: cerf_pcmcia_socket_init,
-+socket_suspend: cerf_pcmcia_socket_suspend,
-+#endif
- };
--
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_cerf.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,138 @@
-+/*
-+ * drivers/pcmcia/cerf.h
-+ *
-+ * PCMCIA implementation routines for CerfBoard
-+ * Based off the Assabet.
-+ *
-+ */
-+#ifndef _LINUX_PCMCIA_CERF_H
-+#define _LINUX_PCMCIA_CERF_H
-+
-+#include <linux/config.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+#ifdef CONFIG_PXA_CERF /* PXA */
-+
-+#define PCMCIA_GPCR GPCR0
-+#define PCMCIA_GPSR GPSR0
-+
-+#define PCMCIA_GPIO_CF_CD 14
-+#define PCMCIA_GPIO_CF_IRQ 13
-+#define PCMCIA_GPIO_CF_RESET 12
-+#ifdef CONFIG_PXA_CERF_PDA
-+# define PCMCIA_GPIO_CF_BVD1 11
-+# define PCMCIA_GPIO_CF_BVD2 10
-+#elif defined( CONFIG_PXA_CERF_BOARD)
-+# define PCMCIA_GPIO_CF_BVD1 32
-+# define PCMCIA_GPIO_CF_BVD2 10
-+#endif
-+
-+#define PCMCIA_GPIO_CF_CD_MASK (GPIO_bit(PCMCIA_GPIO_CF_CD))
-+#define PCMCIA_GPIO_CF_IRQ_MASK (GPIO_bit(PCMCIA_GPIO_CF_IRQ))
-+#define PCMCIA_GPIO_CF_RESET_MASK (GPIO_bit(PCMCIA_GPIO_CF_RESET))
-+#define PCMCIA_GPIO_CF_BVD1_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD1))
-+#define PCMCIA_GPIO_CF_BVD2_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD2))
-+
-+#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD
-+#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ
-+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET
-+#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1
-+#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2
-+
-+#define PCMCIA_IRQ_CF_CD IRQ_GPIO(PCMCIA_GPIO_CF_CD)
-+#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO(PCMCIA_GPIO_CF_IRQ)
-+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO(PCMCIA_GPIO_CF_BVD1)
-+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO(PCMCIA_GPIO_CF_BVD2)
-+
-+#define PCMCIA_PWR_SHUTDOWN 0 /* not needed */
-+#define CERF_SOCKET 0
-+
-+inline void cerf_pcmcia_set_gpio_direction(void)
-+{
-+ GPDR(PCMCIA_GPIO_CF_CD) &= ~(PCMCIA_GPIO_CF_CD_MASK);
-+ GPDR(PCMCIA_GPIO_CF_BVD1) &= ~(PCMCIA_GPIO_CF_BVD1_MASK);
-+ GPDR(PCMCIA_GPIO_CF_BVD2) &= ~(PCMCIA_GPIO_CF_BVD2_MASK);
-+ GPDR(PCMCIA_GPIO_CF_IRQ) &= ~(PCMCIA_GPIO_CF_IRQ_MASK);
-+ GPDR(PCMCIA_GPIO_CF_RESET)|= (PCMCIA_GPIO_CF_RESET_MASK);
-+}
-+
-+inline int cerf_pcmcia_level_detect( void)
-+{
-+ return ((GPLR(PCMCIA_GPIO_CF_CD)&PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
-+}
-+inline int cerf_pcmcia_level_ready( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_IRQ)&PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd1( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_BVD1)&PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd2( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_BVD2)&PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
-+}
-+
-+#elif defined(CONFIG_SA1100_CERF) /* SA1100 */
-+
-+#define PCMCIA_GPDR GPDR
-+#define PCMCIA_GPCR GPCR
-+#define PCMCIA_GPSR GPSR
-+#define PCMCIA_GPLR GPLR
-+
-+#define PCMCIA_GPIO_CF_CD_MASK GPIO_CF_CD
-+#define PCMCIA_GPIO_CF_IRQ_MASK GPIO_CF_IRQ
-+#define PCMCIA_GPIO_CF_RESET_MASK GPIO_CF_RESET
-+#define PCMCIA_GPIO_CF_BVD1_MASK GPIO_CF_BVD1
-+#define PCMCIA_GPIO_CF_BVD2_MASK GPIO_CF_BVD2
-+
-+#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD_MASK
-+#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ_MASK
-+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET_MASK
-+#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1_MASK
-+#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2_MASK
-+
-+#define PCMCIA_IRQ_CF_CD IRQ_GPIO_CF_CD
-+#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO_CF_IRQ
-+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO_CF_BVD1
-+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO_CF_BVD2
-+
-+#define PCMCIA_PWR_SHUTDOWN GPIO_PWR_SHUTDOWN
-+
-+#ifdef CONFIG_SA1100_CERF_CPLD
-+#define CERF_SOCKET 0
-+#else
-+#define CERF_SOCKET 1
-+#endif
-+
-+inline void cerf_pcmcia_set_gpio_direction(void)
-+{
-+ PCMCIA_GPDR &= ~(PCMCIA_GPIO_CF_CD_MASK |
-+ PCMCIA_GPIO_CF_BVD1_MASK |
-+ PCMCIA_GPIO_CF_BVD2_MASK |
-+ PCMCIA_GPIO_CF_IRQ_MASK);
-+ PCMCIA_GPDR |= PCMCIA_GPIO_CF_RESET_MASK;
-+}
-+
-+inline int cerf_pcmcia_level_detect( void)
-+{
-+ return ((PCMCIA_GPLR & PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
-+}
-+inline int cerf_pcmcia_level_ready( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd1( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd2( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
-+}
-+
-+#endif
-+
-+#endif
---- linux-2.4.25/drivers/sound/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/sound/Config.in 2004-03-31 17:15:12.000000000 +0200
-@@ -239,6 +239,7 @@
- dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
- fi
- dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
-+ dep_tristate ' Intel PXA250/210 AC97 audio' CONFIG_SOUND_PXA_AC97 $CONFIG_ARCH_PXA $CONFIG_SOUND
- fi
-
- dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
---- linux-2.4.25/drivers/sound/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/sound/Makefile 2004-03-31 17:15:12.000000000 +0200
-@@ -11,7 +11,7 @@
- msnd.o opl3.o sb_common.o sequencer_syms.o \
- sound_core.o sound_syms.o uart401.o \
- nm256_audio.o ac97.o ac97_codec.o aci.o \
-- sa1100-audio.o
-+ sa1100-audio.o pxa-audio.o pxa-ac97.o
-
- # Each configuration option enables a list of files.
-
-@@ -85,6 +85,7 @@
- obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
- obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
- obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
-+obj-$(CONFIG_SOUND_PXA_AC97)+= pxa-ac97.o pxa-audio.o ac97_codec.o
- obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
- obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
- obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
---- linux-2.4.25/drivers/sound/ac97_codec.c~2.4.25-vrs2-pxa1.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/sound/ac97_codec.c 2004-03-31 17:15:12.000000000 +0200
-@@ -155,6 +155,7 @@
- {0x45838308, "ESS Allegro ES1988", &null_ops},
- {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */
- {0x4e534331, "National Semiconductor LM4549", &null_ops},
-+ {0x50534304, "Philips UCB1400", &default_ops},
- {0x53494c22, "Silicon Laboratory Si3036", &null_ops},
- {0x53494c23, "Silicon Laboratory Si3038", &null_ops},
- {0x545200FF, "TriTech TR?????", &tritech_m_ops},
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/pxa-ac97.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,370 @@
-+/*
-+ * linux/drivers/sound/pxa-ac97.c -- AC97 interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * AC97 GPIO Changes:-
-+ * In order to read/write codec GPIO bits using AC97 link slot 12,
-+ * all IO to AC97_GPIO_STATUS must be via the Xscale modem codec
-+ * address space.
-+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/poll.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ac97_codec.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "pxa-audio.h"
-+
-+static struct completion CAR_completion;
-+static int waitingForMask;
-+static DECLARE_MUTEX(CAR_mutex);
-+
-+static u16 pxa_ac97_read(struct ac97_codec *codec, u8 reg)
-+{
-+ u16 val = -1;
-+
-+ down(&CAR_mutex);
-+ if (!(CAR & CAR_CAIP)) {
-+ volatile u32 *reg_addr;
-+
-+ // if we are reading the GPIO status then this is cached
-+ // in hardware so we don't need to read over the link.
-+ if (reg == AC97_GPIO_STATUS) {
-+ reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
-+ val = *reg_addr;
-+ return val;
-+ }
-+
-+ reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
-+
-+ waitingForMask=GSR_SDONE;
-+
-+ init_completion(&CAR_completion);
-+ (void)*reg_addr; //start read access across the ac97 link
-+ wait_for_completion(&CAR_completion);
-+
-+ if (GSR & GSR_RDCS) {
-+ GSR |= GSR_RDCS; //write a 1 to clear
-+ printk(KERN_CRIT __FUNCTION__": read codec register timeout.\n");
-+ }
-+
-+ init_completion(&CAR_completion);
-+ val = *reg_addr; //valid data now but we've just started another cycle...
-+ wait_for_completion(&CAR_completion);
-+
-+ } else {
-+ printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
-+ }
-+ up(&CAR_mutex);
-+ //printk("%s(0x%02x) = 0x%04x\n", __FUNCTION__, reg, val);
-+ return val;
-+}
-+
-+static void pxa_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
-+{
-+ down(&CAR_mutex);
-+ if (!(CAR & CAR_CAIP)) {
-+ volatile u32 *reg_addr;
-+
-+ // if we are writing to the codec GPIO using slot 12
-+ // then we have to write to the modem register space
-+ if (reg == AC97_GPIO_STATUS) {
-+ reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
-+ *reg_addr = val;
-+ return;
-+ }
-+
-+ reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
-+
-+ waitingForMask=GSR_CDONE;
-+ init_completion(&CAR_completion);
-+ *reg_addr = val;
-+ wait_for_completion(&CAR_completion);
-+ } else {
-+ printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
-+ }
-+ up(&CAR_mutex);
-+ //printk("%s(0x%02x, 0x%04x)\n", __FUNCTION__, reg, val);
-+}
-+
-+static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int gsr = GSR;
-+ GSR = gsr & (GSR_SDONE|GSR_CDONE); //write a 1 to clear
-+ if (gsr & waitingForMask)
-+ {
-+ complete(&CAR_completion);
-+ }
-+}
-+
-+static struct ac97_codec pxa_ac97_codec = {
-+ codec_read: pxa_ac97_read,
-+ codec_write: pxa_ac97_write,
-+};
-+
-+static DECLARE_MUTEX(pxa_ac97_mutex);
-+static int pxa_ac97_refcount;
-+
-+int pxa_ac97_get(struct ac97_codec **codec)
-+{
-+ int ret;
-+
-+ *codec = NULL;
-+ down(&pxa_ac97_mutex);
-+
-+ if (!pxa_ac97_refcount) {
-+ ret = request_irq(IRQ_AC97, pxa_ac97_irq, 0, "AC97", NULL);
-+ if (ret)
-+ return ret;
-+
-+ CKEN |= CKEN2_AC97;
-+ set_GPIO_mode(GPIO31_SYNC_AC97_MD);
-+ set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD);
-+ set_GPIO_mode(GPIO28_BITCLK_AC97_MD);
-+ set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD);
-+
-+ GCR = 0;
-+ udelay(10);
-+ GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE;
-+ while (!(GSR & GSR_PCR)) {
-+ schedule();
-+ }
-+
-+ ret = ac97_probe_codec(&pxa_ac97_codec);
-+ if (ret != 1) {
-+ free_irq(IRQ_AC97, NULL);
-+ GCR = GCR_ACLINK_OFF;
-+ CKEN &= ~CKEN2_AC97;
-+ return ret;
-+ }
-+
-+ // need little hack for UCB1400 (should be moved elsewhere)
-+ pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1);
-+ //pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7);
-+ pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);
-+ pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);
-+ }
-+
-+ pxa_ac97_refcount++;
-+ up(&pxa_ac97_mutex);
-+ *codec = &pxa_ac97_codec;
-+ return 0;
-+}
-+
-+void pxa_ac97_put(void)
-+{
-+ down(&pxa_ac97_mutex);
-+ pxa_ac97_refcount--;
-+ if (!pxa_ac97_refcount) {
-+ GCR = GCR_ACLINK_OFF;
-+ CKEN &= ~CKEN2_AC97;
-+ free_irq(IRQ_AC97, NULL);
-+ }
-+ up(&pxa_ac97_mutex);
-+}
-+
-+EXPORT_SYMBOL(pxa_ac97_get);
-+EXPORT_SYMBOL(pxa_ac97_put);
-+
-+
-+/*
-+ * Audio Mixer stuff
-+ */
-+
-+static audio_state_t ac97_audio_state;
-+static audio_stream_t ac97_audio_in;
-+
-+static int mixer_ioctl( struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret, val;
-+
-+ ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg);
-+ if (ret)
-+ return ret;
-+
-+ /* We must snoop for some commands to provide our own extra processing */
-+ switch (cmd) {
-+ case SOUND_MIXER_WRITE_RECSRC:
-+ /*
-+ * According to the PXA250 spec, mic-in should use different
-+ * DRCMR and different AC97 FIFO.
-+ * Unfortunately current UCB1400 versions (up to ver 2A) don't
-+ * produce slot 6 for the audio input frame, therefore the PXA
-+ * AC97 mic-in FIFO is always starved.
-+ */
-+#if 0
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ pxa_audio_clear_buf(&ac97_audio_in);
-+ *ac97_audio_in.drcmr = 0;
-+ if (val & (1 << SOUND_MIXER_MIC)) {
-+ ac97_audio_in.dcmd = DCMD_RXMCDR;
-+ ac97_audio_in.drcmr = &DRCMRRXMCDR;
-+ ac97_audio_in.dev_addr = __PREG(MCDR);
-+ } else {
-+ ac97_audio_in.dcmd = DCMD_RXPCDR;
-+ ac97_audio_in.drcmr = &DRCMRRXPCDR;
-+ ac97_audio_in.dev_addr = __PREG(PCDR);
-+ }
-+ if (ac97_audio_state.rd_ref)
-+ *ac97_audio_in.drcmr =
-+ ac97_audio_in.dma_ch | DRCMR_MAPVLD;
-+#endif
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static struct file_operations mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ llseek: no_llseek,
-+ owner: THIS_MODULE
-+};
-+
-+/*
-+ * AC97 codec ioctls
-+ */
-+
-+static int codec_adc_rate = 48000;
-+static int codec_dac_rate = 48000;
-+
-+static int ac97_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret;
-+ long val;
-+
-+ switch(cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* FIXME: do we support mono? */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* FIXME: do we support mono? */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret)
-+ return ret;
-+ if (file->f_mode & FMODE_READ)
-+ codec_adc_rate = ac97_set_adc_rate(&pxa_ac97_codec, val);
-+ if (file->f_mode & FMODE_WRITE)
-+ codec_dac_rate = ac97_set_dac_rate(&pxa_ac97_codec, val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ if (file->f_mode & FMODE_READ)
-+ val = codec_adc_rate;
-+ if (file->f_mode & FMODE_WRITE)
-+ val = codec_dac_rate;
-+ return put_user(val, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* FIXME: can we do other fmts? */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+ return 0;
-+}
-+
-+
-+/*
-+ * Audio stuff
-+ */
-+
-+static audio_stream_t ac97_audio_out = {
-+ name: "AC97 audio out",
-+ dcmd: DCMD_TXPCDR,
-+ drcmr: &DRCMRTXPCDR,
-+ dev_addr: __PREG(PCDR),
-+};
-+
-+static audio_stream_t ac97_audio_in = {
-+ name: "AC97 audio in",
-+ dcmd: DCMD_RXPCDR,
-+ drcmr: &DRCMRRXPCDR,
-+ dev_addr: __PREG(PCDR),
-+};
-+
-+static audio_state_t ac97_audio_state = {
-+ output_stream: &ac97_audio_out,
-+ input_stream: &ac97_audio_in,
-+ client_ioctl: ac97_ioctl,
-+ sem: __MUTEX_INITIALIZER(ac97_audio_state.sem),
-+};
-+
-+static int ac97_audio_open(struct inode *inode, struct file *file)
-+{
-+ return pxa_audio_attach(inode, file, &ac97_audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to pxa_audio_attach().
-+ */
-+
-+static struct file_operations ac97_audio_fops = {
-+ open: ac97_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int __init pxa_ac97_init(void)
-+{
-+ int ret;
-+ struct ac97_codec *dummy;
-+
-+ ret = pxa_ac97_get(&dummy);
-+ if (ret)
-+ return ret;
-+
-+ ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1);
-+ pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1);
-+
-+ return 0;
-+}
-+
-+static void __exit pxa_ac97_exit(void)
-+{
-+ unregister_sound_dsp(ac97_audio_state.dev_dsp);
-+ unregister_sound_mixer(pxa_ac97_codec.dev_mixer);
-+ pxa_ac97_put();
-+}
-+
-+
-+module_init(pxa_ac97_init);
-+module_exit(pxa_ac97_exit);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/pxa-audio.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,853 @@
-+/*
-+ * linux/drivers/sound/pxa-audio.c -- audio interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/poll.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "pxa-audio.h"
-+
-+
-+#define AUDIO_NBFRAGS_DEFAULT 8
-+#define AUDIO_FRAGSIZE_DEFAULT 8192
-+
-+#define MAX_DMA_SIZE 4096
-+#define DMA_DESC_SIZE sizeof(pxa_dma_desc)
-+
-+
-+/*
-+ * This function frees all buffers
-+ */
-+#define audio_clear_buf pxa_audio_clear_buf
-+
-+void pxa_audio_clear_buf(audio_stream_t * s)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ int frag;
-+
-+ if (!s->buffers)
-+ return;
-+
-+ /* Ensure DMA isn't running */
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ add_wait_queue(&s->stop_wq, &wait);
-+ DCSR(s->dma_ch) = DCSR_STOPIRQEN;
-+ schedule();
-+ remove_wait_queue(&s->stop_wq, &wait);
-+
-+ /* free DMA buffers */
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+ if (!b->master)
-+ continue;
-+ consistent_free(b->data, b->master, b->dma_desc->dsadr);
-+ }
-+
-+ /* free descriptor ring */
-+ if (s->buffers->dma_desc)
-+ consistent_free(s->buffers->dma_desc,
-+ s->nbfrags * s->descs_per_frag * DMA_DESC_SIZE,
-+ s->dma_desc_phys);
-+
-+ /* free buffer structure array */
-+ kfree(s->buffers);
-+ s->buffers = NULL;
-+}
-+
-+/*
-+ * This function allocates the DMA descriptor array and buffer data space
-+ * according to the current number of fragments and fragment size.
-+ */
-+static int audio_setup_buf(audio_stream_t * s)
-+{
-+ pxa_dma_desc *dma_desc;
-+ dma_addr_t dma_desc_phys;
-+ int nb_desc, frag, i, buf_size = 0;
-+ char *dma_buf = NULL;
-+ dma_addr_t dma_buf_phys = 0;
-+
-+ if (s->buffers)
-+ return -EBUSY;
-+
-+ /* Our buffer structure array */
-+ s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
-+ if (!s->buffers)
-+ goto err;
-+ memzero(s->buffers, sizeof(audio_buf_t) * s->nbfrags);
-+
-+ /*
-+ * Our DMA descriptor array:
-+ * for Each fragment we have one checkpoint descriptor plus one
-+ * descriptor per MAX_DMA_SIZE byte data blocks.
-+ */
-+ nb_desc = (1 + (s->fragsize + MAX_DMA_SIZE - 1)/MAX_DMA_SIZE) * s->nbfrags;
-+ dma_desc = consistent_alloc(GFP_KERNEL,
-+ nb_desc * DMA_DESC_SIZE,
-+ &dma_desc_phys,
-+ 0);
-+ if (!dma_desc)
-+ goto err;
-+ s->descs_per_frag = nb_desc / s->nbfrags;
-+ s->buffers->dma_desc = dma_desc;
-+ s->dma_desc_phys = dma_desc_phys;
-+ for (i = 0; i < nb_desc - 1; i++)
-+ dma_desc[i].ddadr = dma_desc_phys + (i + 1) * DMA_DESC_SIZE;
-+ dma_desc[i].ddadr = dma_desc_phys;
-+
-+ /* Our actual DMA buffers */
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+
-+ /*
-+ * Let's allocate non-cached memory for DMA buffers.
-+ * We try to allocate all memory at once.
-+ * If this fails (a common reason is memory fragmentation),
-+ * then we'll try allocating smaller buffers.
-+ */
-+ if (!buf_size) {
-+ buf_size = (s->nbfrags - frag) * s->fragsize;
-+ do {
-+ dma_buf = consistent_alloc(GFP_KERNEL,
-+ buf_size,
-+ &dma_buf_phys,
-+ 0);
-+ if (!dma_buf)
-+ buf_size -= s->fragsize;
-+ } while (!dma_buf && buf_size);
-+ if (!dma_buf)
-+ goto err;
-+ b->master = buf_size;
-+ memzero(dma_buf, buf_size);
-+ }
-+
-+ /*
-+ * Set up our checkpoint descriptor. Since the count
-+ * is always zero, we'll abuse the dsadr and dtadr fields
-+ * just in case this one is picked up by the hardware
-+ * while processing SOUND_DSP_GETPTR.
-+ */
-+ dma_desc->dsadr = dma_buf_phys;
-+ dma_desc->dtadr = dma_buf_phys;
-+ dma_desc->dcmd = DCMD_ENDIRQEN;
-+ if (s->output && !s->mapped)
-+ dma_desc->ddadr |= DDADR_STOP;
-+ b->dma_desc = dma_desc++;
-+
-+ /* set up the actual data descriptors */
-+ for (i = 0; (i * MAX_DMA_SIZE) < s->fragsize; i++) {
-+ dma_desc[i].dsadr = (s->output) ?
-+ (dma_buf_phys + i*MAX_DMA_SIZE) : s->dev_addr;
-+ dma_desc[i].dtadr = (s->output) ?
-+ s->dev_addr : (dma_buf_phys + i*MAX_DMA_SIZE);
-+ dma_desc[i].dcmd = s->dcmd |
-+ ((s->fragsize < MAX_DMA_SIZE) ?
-+ s->fragsize : MAX_DMA_SIZE);
-+ }
-+ dma_desc += i;
-+
-+ /* handle buffer pointers */
-+ b->data = dma_buf;
-+ dma_buf += s->fragsize;
-+ dma_buf_phys += s->fragsize;
-+ buf_size -= s->fragsize;
-+ }
-+
-+ s->usr_frag = s->dma_frag = 0;
-+ s->bytecount = 0;
-+ s->fragcount = 0;
-+ sema_init(&s->sem, (s->output) ? s->nbfrags : 0);
-+ return 0;
-+
-+err:
-+ printk("pxa-audio: unable to allocate audio memory\n ");
-+ audio_clear_buf(s);
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Our DMA interrupt handler
-+ */
-+static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs)
-+{
-+ audio_stream_t *s = dev_id;
-+ u_int dcsr;
-+
-+ dcsr = DCSR(ch);
-+ DCSR(ch) = dcsr & ~DCSR_STOPIRQEN;
-+
-+ if (!s->buffers) {
-+ printk("AC97 DMA: wow... received IRQ for channel %d but no buffer exists\n", ch);
-+ return;
-+ }
-+
-+ if (dcsr & DCSR_BUSERR)
-+ printk("AC97 DMA: bus error interrupt on channel %d\n", ch);
-+
-+ if (dcsr & DCSR_ENDINTR) {
-+ u_long cur_dma_desc;
-+ u_int cur_dma_frag;
-+
-+ /*
-+ * Find out which DMA desc is current. Note that DDADR
-+ * points to the next desc, not the current one.
-+ */
-+ cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE;
-+
-+ /*
-+ * Let the compiler nicely optimize constant divisors into
-+ * multiplications for the common cases which is much faster.
-+ * Common cases: x = 1 + (1 << y) for y = [0..3]
-+ */
-+ switch (s->descs_per_frag) {
-+ case 2: cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break;
-+ case 3: cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break;
-+ case 5: cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break;
-+ case 9: cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break;
-+ default: cur_dma_frag =
-+ cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE);
-+ }
-+
-+ /* Account for possible wrap back of cur_dma_desc above */
-+ if (cur_dma_frag >= s->nbfrags)
-+ cur_dma_frag = s->nbfrags - 1;
-+
-+ while (s->dma_frag != cur_dma_frag) {
-+ if (!s->mapped) {
-+ /*
-+ * This fragment is done - set the checkpoint
-+ * descriptor to STOP until it is gets
-+ * processed by the read or write function.
-+ */
-+ s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP;
-+ up(&s->sem);
-+ }
-+ if (++s->dma_frag >= s->nbfrags)
-+ s->dma_frag = 0;
-+
-+ /* Accounting */
-+ s->bytecount += s->fragsize;
-+ s->fragcount++;
-+ }
-+
-+ /* ... and for polling processes */
-+ wake_up(&s->frag_wq);
-+ }
-+
-+ if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE))
-+ wake_up(&s->stop_wq);
-+}
-+
-+/*
-+ * Validate and sets up buffer fragments, etc.
-+ */
-+static int audio_set_fragments(audio_stream_t *s, int val)
-+{
-+ if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN)
-+ return -EBUSY;
-+ if (s->buffers)
-+ audio_clear_buf(s);
-+ s->nbfrags = (val >> 16) & 0x7FFF;
-+ val &= 0xffff;
-+ if (val < 5)
-+ val = 5;
-+ if (val > 15)
-+ val = 15;
-+ s->fragsize = 1 << val;
-+ if (s->nbfrags < 2)
-+ s->nbfrags = 2;
-+ if (s->nbfrags * s->fragsize > 256 * 1024)
-+ s->nbfrags = 256 * 1024 / s->fragsize;
-+ if (audio_setup_buf(s))
-+ return -ENOMEM;
-+ return val|(s->nbfrags << 16);
-+}
-+
-+
-+/*
-+ * The fops functions
-+ */
-+
-+static int audio_write(struct file *file, const char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ const char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ int chunksize, ret = 0;
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = &s->buffers[s->usr_frag];
-+
-+ /* Grab a fragment */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&s->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&s->sem))
-+ break;
-+ }
-+
-+ /* Feed the current buffer */
-+ chunksize = s->fragsize - b->offset;
-+ if (chunksize > count)
-+ chunksize = count;
-+ if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
-+ up(&s->sem);
-+ return -EFAULT;
-+ }
-+ b->offset += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->offset < s->fragsize) {
-+ up(&s->sem);
-+ break;
-+ }
-+
-+ /*
-+ * Activate DMA on current buffer.
-+ * We unlock this fragment's checkpoint descriptor and
-+ * kick DMA if it is idle. Using checkpoint descriptors
-+ * allows for control operations without the need for
-+ * stopping the DMA channel if it is already running.
-+ */
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+
-+ /* move the index to the next fragment */
-+ if (++s->usr_frag >= s->nbfrags)
-+ s->usr_frag = 0;
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ return ret;
-+}
-+
-+
-+static int audio_read(struct file *file, char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ char *buffer0 = buffer;
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s = state->input_stream;
-+ int chunksize, ret = 0;
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = &s->buffers[s->usr_frag];
-+
-+ /* prime DMA */
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) =
-+ s->buffers[s->dma_frag].dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+
-+ /* Wait for a buffer to become full */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&s->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&s->sem))
-+ break;
-+ }
-+
-+ /* Grab data from current buffer */
-+ chunksize = s->fragsize - b->offset;
-+ if (chunksize > count)
-+ chunksize = count;
-+ if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
-+ up(&s->sem);
-+ return -EFAULT;
-+ }
-+ b->offset += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->offset < s->fragsize) {
-+ up(&s->sem);
-+ break;
-+ }
-+
-+ /*
-+ * Make this buffer available for DMA again.
-+ * We unlock this fragment's checkpoint descriptor and
-+ * kick DMA if it is idle. Using checkpoint descriptors
-+ * allows for control operations without the need for
-+ * stopping the DMA channel if it is already running.
-+ */
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+
-+ /* move the index to the next fragment */
-+ if (++s->usr_frag >= s->nbfrags)
-+ s->usr_frag = 0;
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ return ret;
-+}
-+
-+
-+static int audio_sync(struct file *file)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ audio_buf_t *b;
-+ pxa_dma_desc *final_desc;
-+ u_long dcmd_save = 0;
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
-+ return 0;
-+
-+ /*
-+ * Send current buffer if it contains data. Be sure to send
-+ * a full sample count.
-+ */
-+ final_desc = NULL;
-+ b = &s->buffers[s->usr_frag];
-+ if (b->offset &= ~3) {
-+ final_desc = &b->dma_desc[1 + b->offset/MAX_DMA_SIZE];
-+ b->offset &= (MAX_DMA_SIZE-1);
-+ dcmd_save = final_desc->dcmd;
-+ final_desc->dcmd = b->offset | s->dcmd | DCMD_ENDIRQEN;
-+ final_desc->ddadr |= DDADR_STOP;
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+ }
-+
-+ /* Wait for DMA to complete. */
-+ set_current_state(TASK_INTERRUPTIBLE);
-+#if 0
-+ /*
-+ * The STOPSTATE IRQ never seem to occur if DCSR_STOPIRQEN is set
-+ * along wotj DCSR_RUN. Silicon bug?
-+ */
-+ add_wait_queue(&s->stop_wq, &wait);
-+ DCSR(s->dma_ch) |= DCSR_STOPIRQEN;
-+ schedule();
-+#else
-+ add_wait_queue(&s->frag_wq, &wait);
-+ while ((DCSR(s->dma_ch) & DCSR_RUN) && !signal_pending(current)) {
-+ schedule();
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ }
-+#endif
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&s->frag_wq, &wait);
-+
-+ /* Restore the descriptor chain. */
-+ if (final_desc) {
-+ final_desc->dcmd = dcmd_save;
-+ final_desc->ddadr &= ~DDADR_STOP;
-+ b->dma_desc->ddadr |= DDADR_STOP;
-+ }
-+ return 0;
-+}
-+
-+
-+static unsigned int audio_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ unsigned int mask = 0;
-+
-+ if (file->f_mode & FMODE_READ) {
-+ /* Start audio input if not already active */
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ if (DCSR(is->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(is->dma_ch) =
-+ is->buffers[is->dma_frag].dma_desc->ddadr;
-+ DCSR(is->dma_ch) = DCSR_RUN;
-+ }
-+ poll_wait(file, &is->frag_wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ poll_wait(file, &os->frag_wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_READ)
-+ if (( is->mapped && is->bytecount > 0) ||
-+ (!is->mapped && atomic_read(&is->sem.count) > 0))
-+ mask |= POLLIN | POLLRDNORM;
-+
-+ if (file->f_mode & FMODE_WRITE)
-+ if (( os->mapped && os->bytecount > 0) ||
-+ (!os->mapped && atomic_read(&os->sem.count) > 0))
-+ mask |= POLLOUT | POLLWRNORM;
-+
-+ return mask;
-+}
-+
-+
-+static int audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *os = state->output_stream;
-+ audio_stream_t *is = state->input_stream;
-+ long val;
-+
-+ switch (cmd) {
-+ case OSS_GETVERSION:
-+ return put_user(SOUND_VERSION, (int *)arg);
-+
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ if (file->f_mode & FMODE_WRITE)
-+ return put_user(os->fragsize, (int *)arg);
-+ else
-+ return put_user(is->fragsize, (int *)arg);
-+
-+ case SNDCTL_DSP_GETCAPS:
-+ val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
-+ if (is && os)
-+ val |= DSP_CAP_DUPLEX;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if (get_user(val, (long *) arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ int ret = audio_set_fragments(is, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ int ret = audio_set_fragments(os, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_SYNC:
-+ return audio_sync(file);
-+
-+ case SNDCTL_DSP_SETDUPLEX:
-+ return 0;
-+
-+ case SNDCTL_DSP_POST:
-+ return 0;
-+
-+ case SNDCTL_DSP_GETTRIGGER:
-+ val = 0;
-+ if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN)
-+ val |= PCM_ENABLE_INPUT;
-+ if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN)
-+ val |= PCM_ENABLE_OUTPUT;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETTRIGGER:
-+ if (get_user(val, (int *)arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ if (val & PCM_ENABLE_INPUT) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ if (!(DCSR(is->dma_ch) & DCSR_RUN)) {
-+ audio_buf_t *b = &is->buffers[is->dma_frag];
-+ DDADR(is->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(is->dma_ch) = DCSR_RUN;
-+ }
-+ } else {
-+ DCSR(is->dma_ch) = 0;
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (val & PCM_ENABLE_OUTPUT) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ if (!(DCSR(os->dma_ch) & DCSR_RUN)) {
-+ audio_buf_t *b = &os->buffers[os->dma_frag];
-+ DDADR(os->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(os->dma_ch) = DCSR_RUN;
-+ }
-+ } else {
-+ DCSR(os->dma_ch) = 0;
-+ }
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_GETOSPACE:
-+ case SNDCTL_DSP_GETISPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ inf.bytes = atomic_read(&s->sem.count) * s->fragsize;
-+ inf.bytes -= s->buffers[s->usr_frag].offset;
-+ inf.fragments = inf.bytes / s->fragsize;
-+ inf.fragsize = s->fragsize;
-+ inf.fragstotal = s->nbfrags;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETOPTR:
-+ case SNDCTL_DSP_GETIPTR:
-+ {
-+ count_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
-+ dma_addr_t ptr;
-+ int bytecount, offset, flags;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (DCSR(s->dma_ch) & DCSR_RUN) {
-+ audio_buf_t *b;
-+ save_flags_cli(flags);
-+ ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch);
-+ b = &s->buffers[s->dma_frag];
-+ offset = ptr - b->dma_desc->dsadr;
-+ if (offset >= s->fragsize)
-+ offset = s->fragsize - 4;
-+ } else {
-+ save_flags(flags);
-+ offset = 0;
-+ }
-+ inf.ptr = s->dma_frag * s->fragsize + offset;
-+ bytecount = s->bytecount + offset;
-+ s->bytecount = -offset;
-+ inf.blocks = s->fragcount;
-+ s->fragcount = 0;
-+ restore_flags(flags);
-+ if (bytecount < 0)
-+ bytecount = 0;
-+ inf.bytes = bytecount;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_NONBLOCK:
-+ file->f_flags |= O_NONBLOCK;
-+ return 0;
-+
-+ case SNDCTL_DSP_RESET:
-+ if (file->f_mode & FMODE_WRITE)
-+ audio_clear_buf(os);
-+ if (file->f_mode & FMODE_READ)
-+ audio_clear_buf(is);
-+ return 0;
-+
-+ default:
-+ return state->client_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s;
-+ unsigned long size, vma_addr;
-+ int i, ret;
-+
-+ if (vma->vm_pgoff != 0)
-+ return -EINVAL;
-+
-+ if (vma->vm_flags & VM_WRITE) {
-+ if (!state->wr_ref)
-+ return -EINVAL;;
-+ s = state->output_stream;
-+ } else if (vma->vm_flags & VM_READ) {
-+ if (!state->rd_ref)
-+ return -EINVAL;
-+ s = state->input_stream;
-+ } else return -EINVAL;
-+
-+ if (s->mapped)
-+ return -EINVAL;
-+ size = vma->vm_end - vma->vm_start;
-+ if (size != s->fragsize * s->nbfrags)
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ vma_addr = vma->vm_start;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *buf = &s->buffers[i];
-+ if (!buf->master)
-+ continue;
-+ ret = remap_page_range(vma_addr, buf->dma_desc->dsadr,
-+ buf->master, vma->vm_page_prot);
-+ if (ret)
-+ return ret;
-+ vma_addr += buf->master;
-+ }
-+ for (i = 0; i < s->nbfrags; i++)
-+ s->buffers[i].dma_desc->ddadr &= ~DDADR_STOP;
-+ s->mapped = 1;
-+ return 0;
-+}
-+
-+
-+static int audio_release(struct inode *inode, struct file *file)
-+{
-+ audio_state_t *state = file->private_data;
-+
-+ down(&state->sem);
-+
-+ if (file->f_mode & FMODE_READ) {
-+ audio_clear_buf(state->input_stream);
-+ *state->input_stream->drcmr = 0;
-+ pxa_free_dma(state->input_stream->dma_ch);
-+ state->rd_ref = 0;
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_sync(file);
-+ audio_clear_buf(state->output_stream);
-+ *state->output_stream->drcmr = 0;
-+ pxa_free_dma(state->output_stream->dma_ch);
-+ state->wr_ref = 0;
-+ }
-+
-+ up(&state->sem);
-+ return 0;
-+}
-+
-+
-+int pxa_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state)
-+{
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ int err;
-+
-+ down(&state->sem);
-+
-+ /* access control */
-+ err = -ENODEV;
-+ if ((file->f_mode & FMODE_WRITE) && !os)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && !is)
-+ goto out;
-+ err = -EBUSY;
-+ if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && state->rd_ref)
-+ goto out;
-+
-+ /* request DMA channels */
-+ if (file->f_mode & FMODE_WRITE) {
-+ err = pxa_request_dma(os->name, DMA_PRIO_LOW,
-+ audio_dma_irq, os);
-+ if (err < 0)
-+ goto out;
-+ os->dma_ch = err;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ err = pxa_request_dma(is->name, DMA_PRIO_LOW,
-+ audio_dma_irq, is);
-+ if (err < 0) {
-+ if (file->f_mode & FMODE_WRITE) {
-+ *os->drcmr = 0;
-+ pxa_free_dma(os->dma_ch);
-+ }
-+ goto out;
-+ }
-+ is->dma_ch = err;
-+ }
-+
-+ file->private_data = state;
-+ file->f_op->release = audio_release;
-+ file->f_op->write = audio_write;
-+ file->f_op->read = audio_read;
-+ file->f_op->mmap = audio_mmap;
-+ file->f_op->poll = audio_poll;
-+ file->f_op->ioctl = audio_ioctl;
-+ file->f_op->llseek = no_llseek;
-+
-+ if ((file->f_mode & FMODE_WRITE)) {
-+ state->wr_ref = 1;
-+ os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ os->output = 1;
-+ os->mapped = 0;
-+ init_waitqueue_head(&os->frag_wq);
-+ init_waitqueue_head(&os->stop_wq);
-+ *os->drcmr = os->dma_ch | DRCMR_MAPVLD;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ state->rd_ref = 1;
-+ is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ is->output = 0;
-+ is->mapped = 0;
-+ init_waitqueue_head(&is->frag_wq);
-+ init_waitqueue_head(&is->stop_wq);
-+ *is->drcmr = is->dma_ch | DRCMR_MAPVLD;
-+ }
-+
-+ err = 0;
-+
-+out:
-+ up(&state->sem);
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(pxa_audio_attach);
-+EXPORT_SYMBOL(pxa_audio_clear_buf);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/pxa-audio.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,55 @@
-+/*
-+ * linux/drivers/sound/pxa-audio.h -- audio interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+typedef struct {
-+ int offset; /* current buffer position */
-+ char *data; /* actual buffer */
-+ pxa_dma_desc *dma_desc; /* pointer to the starting desc */
-+ int master; /* owner for buffer allocation, contain size whn true */
-+} audio_buf_t;
-+
-+typedef struct {
-+ char *name; /* stream identifier */
-+ audio_buf_t *buffers; /* pointer to audio buffer array */
-+ u_int usr_frag; /* user fragment index */
-+ u_int dma_frag; /* DMA fragment index */
-+ u_int fragsize; /* fragment size */
-+ u_int nbfrags; /* number of fragments */
-+ u_int dma_ch; /* DMA channel number */
-+ dma_addr_t dma_desc_phys; /* phys addr of descriptor ring */
-+ u_int descs_per_frag; /* nbr descriptors per fragment */
-+ int bytecount; /* nbr of processed bytes */
-+ int fragcount; /* nbr of fragment transitions */
-+ struct semaphore sem; /* account for fragment usage */
-+ wait_queue_head_t frag_wq; /* for poll(), etc. */
-+ wait_queue_head_t stop_wq; /* for users of DCSR_STOPIRQEN */
-+ u_long dcmd; /* DMA descriptor dcmd field */
-+ volatile u32 *drcmr; /* the DMA request channel to use */
-+ u_long dev_addr; /* device physical address for DMA */
-+ int mapped:1; /* mmap()'ed buffers */
-+ int output:1; /* 0 for input, 1 for output */
-+} audio_stream_t;
-+
-+typedef struct {
-+ audio_stream_t *output_stream;
-+ audio_stream_t *input_stream;
-+ int dev_dsp; /* audio device handle */
-+ int rd_ref:1; /* open reference for recording */
-+ int wr_ref:1; /* open reference for playback */
-+ int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
-+ struct semaphore sem; /* prevent races in attach/release */
-+} audio_state_t;
-+
-+extern int pxa_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state);
-+extern void pxa_audio_clear_buf(audio_stream_t *s);
-+
---- linux-2.4.25/drivers/sound/sa1100-audio.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1100-audio.c 2004-03-31 17:15:12.000000000 +0200
-@@ -148,7 +148,8 @@
- do {
- dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
- dmasize,
-- &dmaphys);
-+ &dmaphys,
-+ 0);
- if (!dmabuf)
- dmasize -= s->fragsize;
- } while (!dmabuf && dmasize);
---- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/video/Config.in 2004-03-31 17:15:12.000000000 +0200
-@@ -50,6 +50,15 @@
- if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
- bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
- fi
-+ tristate ' PXA LCD support' CONFIG_FB_PXA $CONFIG_ARCH_PXA
-+ if [ "$CONFIG_FB_PXA" != "n" ]; then
-+ choice 'LCD Bit Depth' \
-+ "8-Bpp CONFIG_FB_PXA_8BPP \
-+ 16-Bpp CONFIG_FB_PXA_16BPP" Bit-Depth
-+ fi
-+ if [ "$CONFIG_FB_PXA" != "n" -a "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
-+ bool ' Lubbock QVGA LCD support instead of DSTN' CONFIG_FB_PXA_QVGA
-+ fi
- fi
- dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
- if [ "$CONFIG_APOLLO" = "y" ]; then
-@@ -295,7 +304,7 @@
- if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
- "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
- "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
-- "$CONFIG_FB_DBMX1" = "y" ]; then
-+ "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB2 y
- define_tristate CONFIG_FBCON_CFB4 y
- else
-@@ -329,7 +338,7 @@
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
- "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
- "$CONFIG_FB_INTEL" = "y" -o \
-- "$CONFIG_FB_DBMX1" = "y" ]; then
-+ "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB8 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
-@@ -372,7 +381,7 @@
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
- "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
- "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
-- "$CONFIG_FB_ANAKIN" = "y" -o \
-+ "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_PXA" = "y" -o \
- "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB16 y
- else
---- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/video/Makefile 2004-03-31 17:15:12.000000000 +0200
-@@ -14,7 +14,7 @@
- fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
- fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
- fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
-- fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
-+ fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o pxafb.o \
- cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
-
- # Each configuration option enables a list of files.
-@@ -129,6 +129,10 @@
- obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
- obj-$(CONFIG_FB_HGA) += hgafb.o
- obj-$(CONFIG_FB_SA1100) += sa1100fb.o
-+obj-$(CONFIG_FB_PXA) += pxafb.o
-+ifeq ($(CONFIG_PXA_CERF_PDA),y)
-+ obj-$(CONFIG_FB_PXA) += lcdctrl.o lcdctrl_cerf.o
-+endif
- obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
- obj-$(CONFIG_FB_VIRTUAL) += vfb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
---- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/video/fbmem.c 2004-03-31 17:15:12.000000000 +0200
-@@ -109,6 +109,7 @@
- extern int chips_init(void);
- extern int g364fb_init(void);
- extern int sa1100fb_init(void);
-+extern int pxafb_init(void);
- extern int fm2fb_init(void);
- extern int fm2fb_setup(char*);
- extern int q40fb_init(void);
-@@ -305,6 +306,9 @@
- #ifdef CONFIG_FB_SA1100
- { "sa1100", sa1100fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_PXA
-+ { "pxa", pxafb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_SUN3
- { "sun3", sun3fb_init, sun3fb_setup },
- #endif
-@@ -675,13 +679,13 @@
- #elif defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
--#elif defined(__arm__) || defined(__mips__)
-+#elif defined(__mips__)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- #elif defined(__sh__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
- #elif defined(__hppa__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
--#elif defined(__ia64__)
-+#elif defined(__ia64__) || defined(__arm__)
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- #elif defined(__hppa__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/lcdctrl.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,223 @@
-+/*
-+ * lcdctrl.c
-+ *
-+ * Generic LCD control for brightness, contrast, etc.
-+ * Device specific drivers implement a lcdctrl_device and
-+ * provides access to it via lcdctrl_device_get_ops().
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#include <video/lcdctrl.h>
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int lcd_debug = DEBUGGING;
-+#else
-+#define lcd_debug 0
-+#endif
-+
-+/* -- prototypes -- */
-+
-+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
-+ unsigned int cmd , unsigned long arg);
-+static int lcdctrl_open(struct inode *inode, struct file *filp);
-+static int lcdctrl_close(struct inode *inode, struct file *filp);
-+
-+/* -- variables -- */
-+
-+struct lcdctrl_device *lcd_device;
-+
-+static int intensity;
-+static int brightness;
-+static int contrast;
-+
-+static int enabled;
-+static int sync_needed;
-+static int chrdev_major;
-+
-+static struct file_operations lcdctrl_fops = {
-+ ioctl: lcdctrl_ioctl,
-+ open: lcdctrl_open,
-+ release: lcdctrl_close
-+};
-+
-+/* -- ioctl -- */
-+
-+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
-+ unsigned int cmd , unsigned long arg)
-+{
-+ int ret;
-+ ret = -EINVAL;
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "lcdctrl_ioctl: cmd=%d, arg=%ld\n", cmd, arg);
-+
-+ switch(cmd)
-+ {
-+ case _LCDCTRL_IOCTL_ON:
-+ ret = lcdctrl_enable();
-+ break;
-+ case _LCDCTRL_IOCTL_OFF:
-+ ret = lcdctrl_disable();
-+ break;
-+ case _LCDCTRL_IOCTL_INTENSITY:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_intensity(arg);
-+ break;
-+ case _LCDCTRL_IOCTL_BRIGHTNESS:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_brightness(arg);
-+ break;
-+ case _LCDCTRL_IOCTL_CONTRAST:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_contrast(arg, LCD_NO_SYNC);
-+ break;
-+ case _LCDCTRL_IOCTL_GET_BRIGHTNESS:
-+ ret = brightness;
-+ break;
-+ case _LCDCTRL_IOCTL_GET_CONTRAST:
-+ ret = contrast;
-+ break;
-+ case _LCDCTRL_IOCTL_GET_INTENSITY:
-+ ret = intensity;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "lcdctrl_ioctl: invalid ioctl\n");
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int lcdctrl_open(struct inode *inode, struct file *filp)
-+{
-+// MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int lcdctrl_close(struct inode *inode, struct file *filp)
-+{
-+// MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/* -- -- */
-+
-+int lcdctrl_enable( void)
-+{
-+ int result;
-+
-+ if( enabled) return 0;
-+
-+ result = lcd_device->enable();
-+
-+ lcdctrl_set_intensity( intensity);
-+ lcdctrl_set_brightness( brightness);
-+ lcdctrl_set_contrast( contrast, sync_needed);
-+ sync_needed = LCD_NO_SYNC;
-+
-+ enabled = 1;
-+ return result;
-+}
-+
-+int lcdctrl_disable( void)
-+{
-+ enabled = 0;
-+ return lcd_device->disable();
-+}
-+
-+int lcdctrl_set_intensity( int i)
-+{
-+ intensity = i;
-+ return lcd_device->set_intensity( i);
-+}
-+
-+int lcdctrl_set_brightness( int b)
-+{
-+ brightness = b;
-+ return lcd_device->set_brightness( b);
-+}
-+
-+int lcdctrl_set_contrast( int c, int sync)
-+{
-+ contrast = c;
-+ return lcd_device->set_contrast( c, sync);
-+}
-+
-+int lcdctrl_get_intensity( void)
-+{
-+ return intensity;
-+}
-+
-+int lcdctrl_get_brightness( void)
-+{
-+ return brightness;
-+}
-+
-+int lcdctrl_get_contrast( void)
-+{
-+ return contrast;
-+}
-+
-+/* -- -- */
-+
-+/* the device specific driver should implement this */
-+struct lcdctrl_device *lcdctrl_device_get_ops(void);
-+
-+int lcdctrl_init( void)
-+{
-+ int ret;
-+
-+ lcd_device = lcdctrl_device_get_ops();
-+
-+ if( !lcd_device)
-+ {
-+ printk(KERN_ERR "lcdctrl_init: No lcd_device registered.\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = lcd_device->init( &intensity, &brightness, &contrast);
-+
-+ sync_needed = LCD_SYNC_NEEDED;
-+
-+ if( ret == 0)
-+ {
-+ chrdev_major =
-+ register_chrdev( 0,_LCD_CONTROL_NAME,&lcdctrl_fops);
-+ if( lcd_debug)
-+ printk(KERN_INFO "lcdctrl_init: OK\n");
-+ }
-+ return ret;
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/lcdctrl_cerf.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,175 @@
-+/*
-+ * lcdctrl_cerf.c
-+ *
-+ * Cerf LCD control for brightness and contrast.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/arch/cerf_ucb1400gpio.h>
-+
-+#include <video/lcdctrl.h>
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int lcd_debug = DEBUGGING;
-+#else
-+#define lcd_debug 0
-+#endif
-+
-+#define LCD_MAX_INTENSITY 0
-+#define LCD_MAX_BRIGHTNESS 15
-+#define LCD_MAX_CONTRAST 100
-+
-+#define LCD_DEFAULT_INTENSITY 0
-+#define LCD_DEFAULT_BRIGHTNESS 14*100/(LCD_MAX_BRIGHTNESS)
-+#define LCD_DEFAULT_CONTRAST 90*100/(LCD_MAX_CONTRAST)
-+
-+#define UP 1
-+#define DOWN 0
-+
-+/* -- prototypes -- */
-+
-+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast);
-+static int cerf_lcdctrl_enable(void);
-+static int cerf_lcdctrl_disable(void);
-+static int cerf_lcdctrl_set_intensity( int i);
-+static int cerf_lcdctrl_set_brightness( int b);
-+static int cerf_lcdctrl_set_contrast( int c, int sync);
-+
-+static void cerf_lcdctrl_contrast_step( int direction);
-+
-+/* -- variables -- */
-+
-+static int dev_contrast;
-+
-+/* -- -- */
-+
-+static struct lcdctrl_device cerf_dev = {
-+ init: cerf_lcdctrl_init,
-+ enable: cerf_lcdctrl_enable,
-+ disable: cerf_lcdctrl_disable,
-+ set_intensity: cerf_lcdctrl_set_intensity,
-+ set_brightness: cerf_lcdctrl_set_brightness,
-+ set_contrast: cerf_lcdctrl_set_contrast
-+};
-+
-+static int cerf_lcdctrl_enable( void)
-+{
-+ cerf_ucb1400gpio_lcd_enable();
-+
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_disable( void)
-+{
-+ cerf_ucb1400gpio_lcd_disable();
-+
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_intensity( int i)
-+{
-+ int dev_intensity = LCD_MAX_INTENSITY*i/100;
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_intensity: "
-+ "dev_intensity = %d\n", dev_intensity);
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_brightness( int b)
-+{
-+ int dev_brightness = LCD_MAX_BRIGHTNESS*b/100;
-+ outw( dev_brightness, CERF_PDA_CPLD+CERF_PDA_CPLD_BRIGHTNESS);
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_brightness: "
-+ "dev_brightness = %d\n", dev_brightness);
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_contrast( int c, int sync)
-+{
-+ int new_dev_contrast = LCD_MAX_CONTRAST*c/100;
-+ int i;
-+ int count;
-+ int direction = UP;
-+ if( sync == LCD_SYNC_NEEDED)
-+ {
-+ /* In order to sync we step down to the lowest contrast level */
-+ for( i=0; i<LCD_MAX_CONTRAST; i++)
-+ cerf_lcdctrl_contrast_step(DOWN);
-+ dev_contrast = 0;
-+ }
-+
-+ count = new_dev_contrast - dev_contrast;
-+ if( count < 0)
-+ {
-+ /* new contrast is lower then current setting */
-+ direction = DOWN;
-+ count = -count;
-+ }
-+
-+ for( i=0; i<count; i++)
-+ cerf_lcdctrl_contrast_step(direction);
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_contrast: "
-+ "dev_contrast = %d\n", new_dev_contrast);
-+ dev_contrast = new_dev_contrast;
-+
-+ return 0;
-+}
-+
-+/* -- -- */
-+
-+static void cerf_lcdctrl_contrast_step( int direction)
-+{
-+ cerf_ucb1400gpio_lcd_contrast_step( direction);
-+}
-+
-+/* -- -- */
-+
-+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast)
-+{
-+ *intensity = LCD_DEFAULT_INTENSITY;
-+ *brightness = LCD_DEFAULT_BRIGHTNESS;
-+ *contrast = LCD_DEFAULT_CONTRAST;
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_init: OK\n");
-+ return 0;
-+}
-+
-+/* this is the hook for lcdctrl to access to the device specifics */
-+struct lcdctrl_device *lcdctrl_device_get_ops(void)
-+{
-+ return &cerf_dev;
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/pxafb.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,1410 @@
-+/*
-+ * linux/drivers/video/pxafb.c
-+ *
-+ * Copyright (C) 1999 Eric A. Thomas
-+ * Based on acornfb.c Copyright (C) Russell King.
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ *
-+ * Intel PXA250/210 LCD Controller Frame Buffer Driver
-+ *
-+ * Please direct your questions and comments on this driver to the following
-+ * email address:
-+ *
-+ * linux-arm-kernel@lists.arm.linux.org.uk
-+ *
-+ *
-+ * Code Status:
-+ *
-+ * 2001/08/03: <cbrake@accelent.com>
-+ * - Ported from SA1100 to PXA250
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/fb.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/init.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-mfb.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb8.h>
-+#include <video/fbcon-cfb16.h>
-+#include <video/lcdctrl.h> /* brightness, contrast, etc. control */
-+
-+/*
-+ * debugging?
-+ */
-+#define DEBUG 0
-+/*
-+ * Complain if VAR is out of range.
-+ */
-+#define DEBUG_VAR 1
-+
-+#undef ASSABET_PAL_VIDEO
-+
-+#include "pxafb.h"
-+
-+void (*pxafb_blank_helper)(int blank);
-+EXPORT_SYMBOL(pxafb_blank_helper);
-+
-+/*
-+ * IMHO this looks wrong. In 8BPP, length should be 8.
-+ */
-+static struct pxafb_rgb rgb_8 = {
-+ red: { offset: 0, length: 4, },
-+ green: { offset: 0, length: 4, },
-+ blue: { offset: 0, length: 4, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct pxafb_rgb def_rgb_16 = {
-+ red: { offset: 11, length: 5, },
-+ green: { offset: 5, length: 6, },
-+ blue: { offset: 0, length: 5, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct pxafb_mach_info pxa_fb_info __initdata = {
-+ pixclock: LCD_PIXCLOCK, /* clock period in ps */
-+ bpp: LCD_BPP,
-+ xres: LCD_XRES,
-+ yres: LCD_YRES,
-+ hsync_len: LCD_HORIZONTAL_SYNC_PULSE_WIDTH,
-+ vsync_len: LCD_VERTICAL_SYNC_PULSE_WIDTH,
-+ left_margin: LCD_BEGIN_OF_LINE_WAIT_COUNT,
-+ upper_margin: LCD_BEGIN_FRAME_WAIT_COUNT,
-+ right_margin: LCD_END_OF_LINE_WAIT_COUNT,
-+ lower_margin: LCD_END_OF_FRAME_WAIT_COUNT,
-+ sync: LCD_SYNC,
-+ lccr0: LCD_LCCR0,
-+ lccr3: LCD_LCCR3
-+};
-+
-+static struct pxafb_mach_info * __init
-+pxafb_get_machine_info(struct pxafb_info *fbi)
-+{
-+ return &pxa_fb_info;
-+}
-+
-+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
-+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
-+
-+static inline void pxafb_schedule_task(struct pxafb_info *fbi, u_int state)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ /*
-+ * We need to handle two requests being made at the same time.
-+ * There are two important cases:
-+ * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
-+ * We must perform the unblanking, which will do our REENABLE for us.
-+ * 2. When we are blanking, but immediately unblank before we have
-+ * blanked. We do the "REENABLE" thing here as well, just to be sure.
-+ */
-+ if (fbi->task_state == C_ENABLE && state == C_REENABLE)
-+ state = (u_int) -1;
-+ if (fbi->task_state == C_DISABLE && state == C_ENABLE)
-+ state = C_REENABLE;
-+
-+ if (state != (u_int)-1) {
-+ fbi->task_state = state;
-+ schedule_task(&fbi->task);
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+/*
-+ * Get the VAR structure pointer for the specified console
-+ */
-+static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;
-+}
-+
-+/*
-+ * Get the DISPLAY structure pointer for the specified console
-+ */
-+static inline struct display *get_con_display(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con < 0) ? fbi->fb.disp : &fb_display[con];
-+}
-+
-+/*
-+ * Get the CMAP pointer for the specified console
-+ */
-+static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;
-+}
-+
-+static inline u_int
-+chan_to_field(u_int chan, struct fb_bitfield *bf)
-+{
-+ chan &= 0xffff;
-+ chan >>= 16 - bf->length;
-+ return chan << bf->offset;
-+}
-+
-+static int
-+pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ u_int val, ret = 1;
-+
-+ if (regno < fbi->palette_size) {
-+ val = ((red >> 0) & 0xf800);
-+ val |= ((green >> 5) & 0x07e0);
-+ val |= ((blue >> 11) & 0x001f);
-+
-+ fbi->palette_cpu[regno] = val;
-+ ret = 0;
-+ }
-+ return ret;
-+}
-+
-+static int
-+pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ u_int val;
-+ int ret = 1;
-+
-+ /*
-+ * If greyscale is true, then we convert the RGB value
-+ * to greyscale no mater what visual we are using.
-+ */
-+ if (fbi->fb.var.grayscale)
-+ red = green = blue = (19595 * red + 38470 * green +
-+ 7471 * blue) >> 16;
-+
-+ switch (fbi->fb.disp->visual) {
-+ case FB_VISUAL_TRUECOLOR:
-+ case FB_VISUAL_DIRECTCOLOR:
-+ /*
-+ * 12 or 16-bit True Colour. We encode the RGB value
-+ * according to the RGB bitfield information.
-+ */
-+ if (regno <= 16) {
-+ u16 *pal = fbi->fb.pseudo_palette;
-+
-+ val = chan_to_field(red, &fbi->fb.var.red);
-+ val |= chan_to_field(green, &fbi->fb.var.green);
-+ val |= chan_to_field(blue, &fbi->fb.var.blue);
-+
-+ pal[regno] = val;
-+ ret = 0;
-+ }
-+ break;
-+
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * pxafb_decode_var():
-+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
-+ * if it's too big, return -EINVAL.
-+ *
-+ * Suggestion: Round up in the following order: bits_per_pixel, xres,
-+ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
-+ * bitfields, horizontal timing, vertical timing.
-+ */
-+static int pxafb_validate_var(struct fb_var_screeninfo *var,
-+ struct pxafb_info *fbi)
-+{
-+ int ret = -EINVAL;
-+
-+ if (var->xres < MIN_XRES)
-+ var->xres = MIN_XRES;
-+ if (var->yres < MIN_YRES)
-+ var->yres = MIN_YRES;
-+ if (var->xres > fbi->max_xres)
-+ var->xres = fbi->max_xres;
-+ if (var->yres > fbi->max_yres)
-+ var->yres = fbi->max_yres;
-+ var->xres_virtual =
-+ var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
-+ var->yres_virtual =
-+ var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
-+
-+ DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4: ret = 0; break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8: ret = 0; break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ /* make sure we are in passive mode */
-+ if (!(fbi->lccr0 & LCCR0_PAS))
-+ ret = 0;
-+ break;
-+
-+ case 16:
-+ /*
-+ * 16 bits works apparemtly fine in passive mode for those,
-+ * so don't complain
-+ */
-+ if (machine_is_lubbock() ||
-+ machine_is_pxa_cerf()) {
-+ ret = 0;
-+ } else
-+ /* make sure we are in active mode */
-+ if ((fbi->lccr0 & LCCR0_PAS))
-+ ret = 0;
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static inline void pxafb_set_truecolor(u_int is_true_color)
-+{
-+ DPRINTK("true_color = %d\n", is_true_color);
-+}
-+
-+static void
-+pxafb_hw_set_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
-+{
-+
-+ fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, &fbi->fb);
-+
-+ /* Set board control register to handle new color depth */
-+ pxafb_set_truecolor(var->bits_per_pixel >= 16);
-+
-+ pxafb_activate_var(var, fbi);
-+
-+}
-+
-+/*
-+ * pxafb_set_var():
-+ * Set the user defined part of the display for the specified console
-+ */
-+static int
-+pxafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
-+ struct display *display = get_con_display(&fbi->fb, con);
-+ int err, chgvar = 0, rgbidx;
-+
-+ DPRINTK("set_var\n");
-+
-+ /*
-+ * Decode var contents into a par structure, adjusting any
-+ * out of range values.
-+ */
-+ err = pxafb_validate_var(var, fbi);
-+ if (err)
-+ return err;
-+
-+ if (var->activate & FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
-+ return -EINVAL;
-+
-+ if (dvar->xres != var->xres)
-+ chgvar = 1;
-+ if (dvar->yres != var->yres)
-+ chgvar = 1;
-+ if (dvar->xres_virtual != var->xres_virtual)
-+ chgvar = 1;
-+ if (dvar->yres_virtual != var->yres_virtual)
-+ chgvar = 1;
-+ if (dvar->bits_per_pixel != var->bits_per_pixel)
-+ chgvar = 1;
-+ if (con < 0)
-+ chgvar = 0;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ if (fbi->cmap_static)
-+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-+ else
-+ display->visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->line_length = var->xres / 2;
-+ display->dispsw = &fbcon_cfb4;
-+ rgbidx = RGB_8;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ if (fbi->cmap_static)
-+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-+ else
-+ display->visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->line_length = var->xres;
-+ display->dispsw = &fbcon_cfb8;
-+ rgbidx = RGB_8;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ display->visual = FB_VISUAL_TRUECOLOR;
-+ display->line_length = var->xres * 2;
-+ display->dispsw = &fbcon_cfb16;
-+ display->dispsw_data = fbi->fb.pseudo_palette;
-+ rgbidx = RGB_16;
-+ break;
-+#endif
-+ default:
-+ rgbidx = 0;
-+ display->dispsw = &fbcon_dummy;
-+ break;
-+ }
-+
-+ display->screen_base = fbi->screen_cpu;
-+ display->next_line = display->line_length;
-+ display->type = fbi->fb.fix.type;
-+ display->type_aux = fbi->fb.fix.type_aux;
-+ display->ypanstep = fbi->fb.fix.ypanstep;
-+ display->ywrapstep = fbi->fb.fix.ywrapstep;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ *dvar = *var;
-+ dvar->activate &= ~FB_ACTIVATE_ALL;
-+
-+ /*
-+ * Copy the RGB parameters for this display
-+ * from the machine specific parameters.
-+ */
-+ dvar->red = fbi->rgb[rgbidx]->red;
-+ dvar->green = fbi->rgb[rgbidx]->green;
-+ dvar->blue = fbi->rgb[rgbidx]->blue;
-+ dvar->transp = fbi->rgb[rgbidx]->transp;
-+
-+ DPRINTK("RGBT length = %d:%d:%d:%d\n",
-+ dvar->red.length, dvar->green.length, dvar->blue.length,
-+ dvar->transp.length);
-+
-+ DPRINTK("RGBT offset = %d:%d:%d:%d\n",
-+ dvar->red.offset, dvar->green.offset, dvar->blue.offset,
-+ dvar->transp.offset);
-+
-+ /*
-+ * Update the old var. The fbcon drivers still use this.
-+ * Once they are using fbi->fb.var, this can be dropped.
-+ */
-+ display->var = *dvar;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ if (var->activate & FB_ACTIVATE_ALL)
-+ fbi->fb.disp->var = *dvar;
-+
-+ /*
-+ * If the console has changed and the console has defined
-+ * a changevar function, call that function.
-+ */
-+ if (chgvar && info && fbi->fb.changevar)
-+ fbi->fb.changevar(con);
-+
-+ /* If the current console is selected, activate the new var. */
-+ if (con != fbi->currcon)
-+ return 0;
-+
-+ pxafb_hw_set_var(dvar, fbi);
-+
-+ return 0;
-+}
-+
-+static int
-+__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct fb_cmap *dcmap = get_con_cmap(info, con);
-+ int err = 0;
-+
-+ if (con == -1)
-+ con = fbi->currcon;
-+
-+ /* no colormap allocated? (we always have "this" colour map allocated) */
-+ if (con >= 0)
-+ err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
-+
-+ if (!err && con == fbi->currcon)
-+ err = fb_set_cmap(cmap, kspc, pxafb_setcolreg, info);
-+
-+ if (!err)
-+ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
-+
-+ return err;
-+}
-+
-+static int
-+pxafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct display *disp = get_con_display(info, con);
-+
-+ if (disp->visual == FB_VISUAL_TRUECOLOR)
-+ return -EINVAL;
-+
-+ return __do_set_cmap(cmap, kspc, con, info);
-+}
-+
-+static int
-+pxafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ struct display *display = get_con_display(info, con);
-+
-+ *fix = info->fix;
-+
-+ fix->line_length = display->line_length;
-+ fix->visual = display->visual;
-+ return 0;
-+}
-+
-+static int
-+pxafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ *var = *get_con_var(info, con);
-+ return 0;
-+}
-+
-+static int
-+pxafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ struct fb_cmap *dcmap = get_con_cmap(info, con);
-+ fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+static struct fb_ops pxafb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: pxafb_get_fix,
-+ fb_get_var: pxafb_get_var,
-+ fb_set_var: pxafb_set_var,
-+ fb_get_cmap: pxafb_get_cmap,
-+ fb_set_cmap: pxafb_set_cmap,
-+};
-+
-+/*
-+ * pxafb_switch():
-+ * Change to the specified console. Palette and video mode
-+ * are changed to the console's stored parameters.
-+ *
-+ * Uh oh, this can be called from a tasklet (IRQ)
-+ */
-+static int pxafb_switch(int con, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct display *disp;
-+ struct fb_cmap *cmap;
-+
-+ DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
-+
-+ if (con == fbi->currcon)
-+ return 0;
-+
-+ if (fbi->currcon >= 0) {
-+ disp = fb_display + fbi->currcon;
-+
-+ /*
-+ * Save the old colormap and video mode.
-+ */
-+ disp->var = fbi->fb.var;
-+
-+ if (disp->cmap.len)
-+ fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
-+ }
-+
-+ fbi->currcon = con;
-+ disp = fb_display + con;
-+
-+ /*
-+ * Make sure that our colourmap contains 256 entries.
-+ */
-+ fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
-+
-+ if (disp->cmap.len)
-+ cmap = &disp->cmap;
-+ else
-+ cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
-+
-+ fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
-+
-+ fbi->fb.var = disp->var;
-+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ pxafb_set_var(&fbi->fb.var, con, info);
-+ return 0;
-+}
-+
-+/*
-+ * Formal definition of the VESA spec:
-+ * On
-+ * This refers to the state of the display when it is in full operation
-+ * Stand-By
-+ * This defines an optional operating state of minimal power reduction with
-+ * the shortest recovery time
-+ * Suspend
-+ * This refers to a level of power management in which substantial power
-+ * reduction is achieved by the display. The display can have a longer
-+ * recovery time from this state than from the Stand-by state
-+ * Off
-+ * This indicates that the display is consuming the lowest level of power
-+ * and is non-operational. Recovery from this state may optionally require
-+ * the user to manually power on the monitor
-+ *
-+ * Now, the fbdev driver adds an additional state, (blank), where they
-+ * turn off the video (maybe by colormap tricks), but don't mess with the
-+ * video itself: think of it semantically between on and Stand-By.
-+ *
-+ * So here's what we should do in our fbdev blank routine:
-+ *
-+ * VESA_NO_BLANKING (mode 0) Video on, front/back light on
-+ * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off
-+ * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off
-+ * VESA_POWERDOWN (mode 3) Video off, front/back light off
-+ *
-+ * This will match the matrox implementation.
-+ */
-+/*
-+ * pxafb_blank():
-+ * Blank the display by setting all palette values to zero. Note, the
-+ * 12 and 16 bpp modes don't really use the palette, so this will not
-+ * blank the display in all modes.
-+ */
-+static void pxafb_blank(int blank, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ int i;
-+
-+ DPRINTK("pxafb_blank: blank=%d info->modename=%s\n", blank,
-+ fbi->fb.modename);
-+
-+ switch (blank) {
-+ case VESA_POWERDOWN:
-+ case VESA_VSYNC_SUSPEND:
-+ case VESA_HSYNC_SUSPEND:
-+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
-+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-+ for (i = 0; i < fbi->palette_size; i++)
-+ pxafb_setpalettereg(i, 0, 0, 0, 0, info);
-+ pxafb_schedule_task(fbi, C_DISABLE);
-+ if (pxafb_blank_helper)
-+ pxafb_blank_helper(blank);
-+ break;
-+
-+ case VESA_NO_BLANKING:
-+ if (pxafb_blank_helper)
-+ pxafb_blank_helper(blank);
-+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
-+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-+ fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, info);
-+ pxafb_schedule_task(fbi, C_ENABLE);
-+ }
-+}
-+
-+static int pxafb_updatevar(int con, struct fb_info *info)
-+{
-+ DPRINTK("entered\n");
-+ return 0;
-+}
-+
-+/*
-+ * Calculate the PCD value from the clock rate (in picoseconds).
-+ * We take account of the PPCR clock setting.
-+ */
-+static inline int get_pcd(unsigned int pixclock)
-+{
-+ unsigned int pcd;
-+
-+ if (pixclock) {
-+ pcd = get_lclk_frequency_10khz() * pixclock;
-+ pcd /= 100000000;
-+ pcd += 1; /* make up for integer math truncations */
-+ } else {
-+ printk(KERN_WARNING "Please convert me to use the PCD calculations\n");
-+ pcd = 0;
-+ }
-+ return pcd;
-+}
-+
-+/*
-+ * pxafb_activate_var():
-+ * Configures LCD Controller based on entries in var parameter. Settings are
-+ * only written to the controller if changes were made.
-+ */
-+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
-+{
-+ struct pxafb_lcd_reg new_regs;
-+// u_int pcd = get_pcd(var->pixclock);
-+ u_long flags;
-+
-+ DPRINTK("Configuring PXA LCD\n");
-+
-+ DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
-+ var->xres, var->hsync_len,
-+ var->left_margin, var->right_margin);
-+ DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
-+ var->yres, var->vsync_len,
-+ var->upper_margin, var->lower_margin);
-+
-+#if DEBUG_VAR
-+ if (var->xres < 16 || var->xres > 1024)
-+ printk(KERN_ERR "%s: invalid xres %d\n",
-+ fbi->fb.fix.id, var->xres);
-+ if (var->hsync_len < 1 || var->hsync_len > 64)
-+ printk(KERN_ERR "%s: invalid hsync_len %d\n",
-+ fbi->fb.fix.id, var->hsync_len);
-+ if (var->left_margin < 1 || var->left_margin > 255)
-+ printk(KERN_ERR "%s: invalid left_margin %d\n",
-+ fbi->fb.fix.id, var->left_margin);
-+ if (var->right_margin < 1 || var->right_margin > 255)
-+ printk(KERN_ERR "%s: invalid right_margin %d\n",
-+ fbi->fb.fix.id, var->right_margin);
-+ if (var->yres < 1 || var->yres > 1024)
-+ printk(KERN_ERR "%s: invalid yres %d\n",
-+ fbi->fb.fix.id, var->yres);
-+ if (var->vsync_len < 1 || var->vsync_len > 64)
-+ printk(KERN_ERR "%s: invalid vsync_len %d\n",
-+ fbi->fb.fix.id, var->vsync_len);
-+ if (var->upper_margin < 0 || var->upper_margin > 255)
-+ printk(KERN_ERR "%s: invalid upper_margin %d\n",
-+ fbi->fb.fix.id, var->upper_margin);
-+ if (var->lower_margin < 0 || var->lower_margin > 255)
-+ printk(KERN_ERR "%s: invalid lower_margin %d\n",
-+ fbi->fb.fix.id, var->lower_margin);
-+#endif
-+
-+#if defined (CONFIG_PXA_CERF_PDA)
-+ new_regs.lccr0 = fbi->lccr0;
-+ new_regs.lccr1 =
-+ LCCR1_DisWdth(var->xres) +
-+ LCCR1_HorSnchWdth(var->hsync_len) +
-+ LCCR1_BegLnDel(var->left_margin) +
-+ LCCR1_EndLnDel(var->right_margin);
-+
-+ new_regs.lccr2 =
-+ LCCR2_DisHght(var->yres) +
-+ LCCR2_VrtSnchWdth(var->vsync_len) +
-+ LCCR2_BegFrmDel(var->upper_margin) +
-+ LCCR2_EndFrmDel(var->lower_margin);
-+
-+ new_regs.lccr3 = fbi->lccr3
-+ |
-+ (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-+ (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
-+#elif defined (CONFIG_FB_PXA_QVGA)
-+ new_regs.lccr0 = fbi->lccr0;
-+ new_regs.lccr1 =
-+ LCCR1_DisWdth(var->xres) +
-+ LCCR1_HorSnchWdth(var->hsync_len) +
-+ LCCR1_BegLnDel(var->left_margin) +
-+ LCCR1_EndLnDel(var->right_margin);
-+ new_regs.lccr2 =
-+ LCCR2_DisHght(var->yres) +
-+ LCCR2_VrtSnchWdth(var->vsync_len) +
-+ LCCR2_BegFrmDel(var->upper_margin) +
-+ LCCR2_EndFrmDel(var->lower_margin);
-+ new_regs.lccr3 = fbi->lccr3;
-+#else
-+ // FIXME using hardcoded values for now
-+ new_regs.lccr0 = fbi->lccr0;
-+// |
-+// LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
-+// LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
-+
-+ new_regs.lccr1 = 0x3030A7F;
-+// LCCR1_DisWdth(var->xres) +
-+// LCCR1_HorSnchWdth(var->hsync_len) +
-+// LCCR1_BegLnDel(var->left_margin) +
-+// LCCR1_EndLnDel(var->right_margin);
-+
-+ new_regs.lccr2 = 0x4EF;
-+// LCCR2_DisHght(var->yres) +
-+// LCCR2_VrtSnchWdth(var->vsync_len) +
-+// LCCR2_BegFrmDel(var->upper_margin) +
-+// LCCR2_EndFrmDel(var->lower_margin);
-+
-+ new_regs.lccr3 = fbi->lccr3;
-+// |
-+// (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-+// (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
-+// LCCR3_ACBsCntOff;
-+#endif
-+
-+// if (pcd)
-+// new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
-+
-+ DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
-+ DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
-+ DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-+ DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
-+
-+ /* Update shadow copy atomically */
-+ local_irq_save(flags);
-+
-+ /* setup dma descriptors */
-+ fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
-+ fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
-+ fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
-+
-+ fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
-+ fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
-+ fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
-+
-+ #define BYTES_PER_PANEL ((fbi->lccr0 & LCCR0_SDS) ? (var->xres * var->yres * var->bits_per_pixel / 8 / 2) : \
-+ (var->xres * var->yres * var->bits_per_pixel / 8))
-+
-+ /* populate descriptors */
-+ fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
-+ fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
-+ fbi->dmadesc_fblow_cpu->fidr = 0;
-+ fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
-+
-+ fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */
-+
-+ fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
-+ fbi->dmadesc_fbhigh_cpu->fidr = 0;
-+ fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
-+
-+ fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
-+ fbi->dmadesc_palette_cpu->fidr = 0;
-+ fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
-+
-+ if( var->bits_per_pixel < 12)
-+ {
-+ /* assume any mode with <12 bpp is palette driven */
-+ fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-+ fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
-+ fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
-+ }
-+ else
-+ {
-+ /* palette shouldn't be loaded in true-color mode */
-+ fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-+ fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
-+ }
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu = 0x%x\n", fbi->dmadesc_fblow_cpu);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%x\n", fbi->dmadesc_fbhigh_cpu);
-+ DPRINTK("fbi->dmadesc_palette_cpu = 0x%x\n", fbi->dmadesc_palette_cpu);
-+ DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
-+ DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
-+ DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
-+ DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
-+ DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
-+ DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
-+
-+ fbi->reg_lccr0 = new_regs.lccr0;
-+ fbi->reg_lccr1 = new_regs.lccr1;
-+ fbi->reg_lccr2 = new_regs.lccr2;
-+ fbi->reg_lccr3 = new_regs.lccr3;
-+ local_irq_restore(flags);
-+
-+ /*
-+ * Only update the registers if the controller is enabled
-+ * and something has changed.
-+ */
-+ if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
-+ (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
-+ (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1))
-+ pxafb_schedule_task(fbi, C_REENABLE);
-+
-+ return 0;
-+}
-+
-+/*
-+ * NOTE! The following functions are purely helpers for set_ctrlr_state.
-+ * Do not call them directly; set_ctrlr_state does the correct serialisation
-+ * to ensure that things happen in the right way 100% of time time.
-+ * -- rmk
-+ */
-+
-+/*
-+ * FIXME: move LCD power stuff into pxafb_power_up_lcd()
-+ * Also, I'm expecting that the backlight stuff should
-+ * be handled differently.
-+ */
-+static void pxafb_backlight_on(struct pxafb_info *fbi)
-+{
-+ DPRINTK("backlight on\n");
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ FB_BACKLIGHT_ON();
-+ }
-+#endif
-+}
-+
-+/*
-+ * FIXME: move LCD power stuf into pxafb_power_down_lcd()
-+ * Also, I'm expecting that the backlight stuff should
-+ * be handled differently.
-+ */
-+static void pxafb_backlight_off(struct pxafb_info *fbi)
-+{
-+ DPRINTK("backlight off\n");
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ FB_BACKLIGHT_OFF();
-+ }
-+#endif
-+
-+}
-+
-+static void pxafb_power_up_lcd(struct pxafb_info *fbi)
-+{
-+ DPRINTK("LCD power on\n");
-+ CKEN |= CKEN16_LCD;
-+
-+ if(machine_is_pxa_cerf()) {
-+ lcdctrl_enable();
-+ }
-+
-+#if CONFIG_ARCH_PXA_IDP
-+ /* set GPIOs, etc */
-+ if(machine_is_pxa_idp()) {
-+ // FIXME need to add proper delays
-+ FB_PWR_ON();
-+ FB_VLCD_ON(); // FIXME this should be after scanning starts
-+ }
-+#endif
-+}
-+
-+static void pxafb_power_down_lcd(struct pxafb_info *fbi)
-+{
-+ DPRINTK("LCD power off\n");
-+ CKEN &= ~CKEN16_LCD;
-+
-+ if(machine_is_pxa_cerf()) {
-+ lcdctrl_disable();
-+ }
-+
-+ /* set GPIOs, etc */
-+#if CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ // FIXME need to add proper delays
-+ FB_PWR_OFF();
-+ FB_VLCD_OFF(); // FIXME this should be before scanning stops
-+ }
-+#endif
-+
-+}
-+
-+static void pxafb_setup_gpio(struct pxafb_info *fbi)
-+{
-+ unsigned int lccr0;
-+
-+ /*
-+ * setup is based on type of panel supported
-+ */
-+
-+ lccr0 = fbi->lccr0;
-+
-+ /* 4 bit interface */
-+ if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
-+ {
-+ // bits 58-61
-+ GPDR1 |= (0xf << 26);
-+ GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20);
-+
-+ // bits 74-77
-+ GPDR2 |= (0xf << 10);
-+ GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
-+ }
-+
-+ /* 8 bit interface */
-+ else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
-+ (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
-+ {
-+ // bits 58-65
-+ GPDR1 |= (0x3f << 26);
-+ GPDR2 |= (0x3);
-+
-+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
-+ GAFR2_L = (GAFR2_L & ~0xf) | (0xa);
-+
-+ // bits 74-77
-+ GPDR2 |= (0xf << 10);
-+ GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
-+ }
-+
-+ /* 16 bit interface */
-+ else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
-+ {
-+ // bits 58-77
-+ GPDR1 |= (0x3f << 26);
-+ GPDR2 |= 0x00003fff;
-+
-+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
-+ GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
-+ }
-+ else
-+ {
-+ printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
-+ }
-+}
-+
-+static void pxafb_enable_controller(struct pxafb_info *fbi)
-+{
-+ DPRINTK("Enabling LCD controller\n");
-+
-+ /* Sequence from 11.7.10 */
-+ LCCR3 = fbi->reg_lccr3;
-+ LCCR2 = fbi->reg_lccr2;
-+ LCCR1 = fbi->reg_lccr1;
-+ LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
-+
-+ /* FIXME we used to have LCD power control here */
-+
-+ FDADR0 = fbi->fdadr0;
-+ FDADR1 = fbi->fdadr1;
-+ LCCR0 |= LCCR0_ENB;
-+
-+ DPRINTK("FDADR0 = 0x%08x\n", (unsigned int)FDADR0);
-+ DPRINTK("FDADR1 = 0x%08x\n", (unsigned int)FDADR1);
-+ DPRINTK("LCCR0 = 0x%08x\n", (unsigned int)LCCR0);
-+ DPRINTK("LCCR1 = 0x%08x\n", (unsigned int)LCCR1);
-+ DPRINTK("LCCR2 = 0x%08x\n", (unsigned int)LCCR2);
-+ DPRINTK("LCCR3 = 0x%08x\n", (unsigned int)LCCR3);
-+}
-+
-+static void pxafb_disable_controller(struct pxafb_info *fbi)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ DPRINTK("Disabling LCD controller\n");
-+
-+ /* FIXME add power down GPIO stuff here */
-+
-+ add_wait_queue(&fbi->ctrlr_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ LCSR = 0xffffffff; /* Clear LCD Status Register */
-+ LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
-+ LCCR0 &= ~LCCR0_ENB; /* Disable LCD Controller */
-+
-+ schedule_timeout(20 * HZ / 1000);
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&fbi->ctrlr_wait, &wait);
-+}
-+
-+/*
-+ * pxafb_handle_irq: Handle 'LCD DONE' interrupts.
-+ */
-+static void pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct pxafb_info *fbi = dev_id;
-+ unsigned int lcsr = LCSR;
-+
-+ if (lcsr & LCSR_LDD) {
-+ LCCR0 |= LCCR0_LDM;
-+ wake_up(&fbi->ctrlr_wait);
-+ }
-+
-+ LCSR = lcsr;
-+}
-+
-+/*
-+ * This function must be called from task context only, since it will
-+ * sleep when disabling the LCD controller, or if we get two contending
-+ * processes trying to alter state.
-+ */
-+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
-+{
-+ u_int old_state;
-+
-+ down(&fbi->ctrlr_sem);
-+
-+ old_state = fbi->state;
-+
-+ switch (state) {
-+ case C_DISABLE_CLKCHANGE:
-+ /*
-+ * Disable controller for clock change. If the
-+ * controller is already disabled, then do nothing.
-+ */
-+ if (old_state != C_DISABLE) {
-+ fbi->state = state;
-+ pxafb_disable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_DISABLE:
-+ /*
-+ * Disable controller
-+ */
-+ if (old_state != C_DISABLE) {
-+ fbi->state = state;
-+
-+ pxafb_backlight_off(fbi);
-+ if (old_state != C_DISABLE_CLKCHANGE)
-+ pxafb_disable_controller(fbi);
-+ pxafb_power_down_lcd(fbi);
-+ }
-+ break;
-+
-+ case C_ENABLE_CLKCHANGE:
-+ /*
-+ * Enable the controller after clock change. Only
-+ * do this if we were disabled for the clock change.
-+ */
-+ if (old_state == C_DISABLE_CLKCHANGE) {
-+ fbi->state = C_ENABLE;
-+ pxafb_enable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_REENABLE:
-+ /*
-+ * Re-enable the controller only if it was already
-+ * enabled. This is so we reprogram the control
-+ * registers.
-+ */
-+ if (old_state == C_ENABLE) {
-+ pxafb_disable_controller(fbi);
-+ pxafb_setup_gpio(fbi);
-+ pxafb_enable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_ENABLE:
-+ /*
-+ * Power up the LCD screen, enable controller, and
-+ * turn on the backlight.
-+ */
-+ if (old_state != C_ENABLE) {
-+ fbi->state = C_ENABLE;
-+ pxafb_setup_gpio(fbi);
-+ pxafb_power_up_lcd(fbi);
-+ pxafb_enable_controller(fbi);
-+ pxafb_backlight_on(fbi);
-+ }
-+ break;
-+ }
-+ up(&fbi->ctrlr_sem);
-+}
-+
-+/*
-+ * Our LCD controller task (which is called when we blank or unblank)
-+ * via keventd.
-+ */
-+static void pxafb_task(void *dummy)
-+{
-+ struct pxafb_info *fbi = dummy;
-+ u_int state = xchg(&fbi->task_state, -1);
-+
-+ set_ctrlr_state(fbi, state);
-+}
-+
-+#ifdef CONFIG_CPU_FREQ
-+/*
-+ * CPU clock speed change handler. We need to adjust the LCD timing
-+ * parameters when the CPU clock is adjusted by the power management
-+ * subsystem.
-+ */
-+static int
-+pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
-+ void *data)
-+{
-+ struct pxafb_info *fbi = TO_INF(nb, clockchg);
-+ u_int pcd;
-+
-+ switch (val) {
-+ case CPUFREQ_MINMAX:
-+ /* todo: fill in min/max values */
-+ break;
-+
-+ case CPUFREQ_PRECHANGE:
-+ set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
-+ break;
-+
-+ case CPUFREQ_POSTCHANGE:
-+ pcd = get_pcd(fbi->fb.var.pixclock);
-+ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
-+ set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
-+ break;
-+ }
-+ return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Power management hook. Note that we won't be called from IRQ context,
-+ * unlike the blank functions above, so we may sleep.
-+ */
-+static int
-+pxafb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ struct pxafb_info *fbi = pm_dev->data;
-+
-+ DPRINTK("pm_callback: %d\n", req);
-+
-+ if (req == PM_SUSPEND || req == PM_RESUME) {
-+ int state = (int)data;
-+
-+ if (state == 0) {
-+ /* Enter D0. */
-+ set_ctrlr_state(fbi, C_ENABLE);
-+ } else {
-+ /* Enter D1-D3. Disable the LCD controller. */
-+ set_ctrlr_state(fbi, C_DISABLE);
-+ }
-+ }
-+ DPRINTK("done\n");
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * pxafb_map_video_memory():
-+ * Allocates the DRAM memory for the frame buffer. This buffer is
-+ * remapped into a non-cached, non-buffered, memory region to
-+ * allow palette and pixel writes to occur without flushing the
-+ * cache. Once this area is remapped, all virtual memory
-+ * access to the video memory should occur at the new region.
-+ */
-+static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
-+{
-+ u_long palette_mem_size;
-+
-+ /*
-+ * We reserve one page for the palette, plus the size
-+ * of the framebuffer.
-+ *
-+ * layout of stuff in memory
-+ *
-+ * fblow descriptor
-+ * fbhigh descriptor
-+ * palette descriptor
-+ * palette
-+ * page boundary->
-+ * frame buffer
-+ */
-+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
-+ fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-+ &fbi->map_dma, PTE_BUFFERABLE);
-+
-+ if (fbi->map_cpu) {
-+ fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
-+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
-+ fbi->fb.fix.smem_start = fbi->screen_dma;
-+
-+ fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
-+
-+ palette_mem_size = fbi->palette_size * sizeof(u16);
-+
-+ DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
-+
-+ fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
-+ fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
-+
-+ }
-+
-+ return fbi->map_cpu ? 0 : -ENOMEM;
-+}
-+
-+/* Fake monspecs to fill in fbinfo structure */
-+static struct fb_monspecs monspecs __initdata = {
-+ 30000, 70000, 50, 65, 0 /* Generic */
-+};
-+
-+
-+static struct pxafb_info * __init pxafb_init_fbinfo(void)
-+{
-+ struct pxafb_mach_info *inf;
-+ struct pxafb_info *fbi;
-+
-+ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(struct display) +
-+ sizeof(u16) * 16, GFP_KERNEL);
-+ if (!fbi)
-+ return NULL;
-+
-+ memset(fbi, 0, sizeof(struct pxafb_info) + sizeof(struct display));
-+
-+ fbi->currcon = -1;
-+
-+ strcpy(fbi->fb.fix.id, PXA_NAME);
-+
-+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
-+ fbi->fb.fix.type_aux = 0;
-+ fbi->fb.fix.xpanstep = 0;
-+ fbi->fb.fix.ypanstep = 0;
-+ fbi->fb.fix.ywrapstep = 0;
-+ fbi->fb.fix.accel = FB_ACCEL_NONE;
-+
-+ fbi->fb.var.nonstd = 0;
-+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
-+ fbi->fb.var.height = -1;
-+ fbi->fb.var.width = -1;
-+ fbi->fb.var.accel_flags = 0;
-+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
-+
-+ strcpy(fbi->fb.modename, PXA_NAME);
-+ strcpy(fbi->fb.fontname, "Acorn8x8");
-+
-+ fbi->fb.fbops = &pxafb_ops;
-+ fbi->fb.changevar = NULL;
-+ fbi->fb.switch_con = pxafb_switch;
-+ fbi->fb.updatevar = pxafb_updatevar;
-+ fbi->fb.blank = pxafb_blank;
-+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
-+ fbi->fb.node = -1;
-+ fbi->fb.monspecs = monspecs;
-+ fbi->fb.disp = (struct display *)(fbi + 1);
-+ fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
-+
-+ fbi->rgb[RGB_8] = &rgb_8;
-+ fbi->rgb[RGB_16] = &def_rgb_16;
-+
-+ inf = pxafb_get_machine_info(fbi);
-+
-+ fbi->max_xres = inf->xres;
-+ fbi->fb.var.xres = inf->xres;
-+ fbi->fb.var.xres_virtual = inf->xres;
-+ fbi->max_yres = inf->yres;
-+ fbi->fb.var.yres = inf->yres;
-+ fbi->fb.var.yres_virtual = inf->yres;
-+ fbi->max_bpp = inf->bpp;
-+ fbi->fb.var.bits_per_pixel = inf->bpp;
-+ fbi->fb.var.pixclock = inf->pixclock;
-+ fbi->fb.var.hsync_len = inf->hsync_len;
-+ fbi->fb.var.left_margin = inf->left_margin;
-+ fbi->fb.var.right_margin = inf->right_margin;
-+ fbi->fb.var.vsync_len = inf->vsync_len;
-+ fbi->fb.var.upper_margin = inf->upper_margin;
-+ fbi->fb.var.lower_margin = inf->lower_margin;
-+ fbi->fb.var.sync = inf->sync;
-+ fbi->fb.var.grayscale = inf->cmap_greyscale;
-+ fbi->cmap_inverse = inf->cmap_inverse;
-+ fbi->cmap_static = inf->cmap_static;
-+ fbi->lccr0 = inf->lccr0;
-+ fbi->lccr3 = inf->lccr3;
-+ fbi->state = C_DISABLE;
-+ fbi->task_state = (u_char)-1;
-+ fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
-+ fbi->max_bpp / 8;
-+
-+ init_waitqueue_head(&fbi->ctrlr_wait);
-+ INIT_TQUEUE(&fbi->task, pxafb_task, fbi);
-+ init_MUTEX(&fbi->ctrlr_sem);
-+
-+ return fbi;
-+}
-+
-+int __init pxafb_init(void)
-+{
-+ struct pxafb_info *fbi;
-+ int ret;
-+
-+ fbi = pxafb_init_fbinfo();
-+ ret = -ENOMEM;
-+ if (!fbi)
-+ goto failed;
-+
-+ if(machine_is_pxa_cerf()) {
-+ // brightness&contrast is handled via lcdctrl.
-+ lcdctrl_init();
-+ }
-+
-+ /* Initialize video memory */
-+ ret = pxafb_map_video_memory(fbi);
-+ if (ret)
-+ goto failed;
-+
-+ ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT,
-+ "LCD", fbi);
-+ if (ret) {
-+ printk(KERN_ERR "pxafb: failed in request_irq: %d\n", ret);
-+ goto failed;
-+ }
-+
-+ pxafb_set_var(&fbi->fb.var, -1, &fbi->fb);
-+
-+ ret = register_framebuffer(&fbi->fb);
-+ if (ret < 0)
-+ goto failed;
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Note that the console registers this as well, but we want to
-+ * power down the display prior to sleeping.
-+ */
-+ fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, pxafb_pm_callback);
-+ if (fbi->pm)
-+ fbi->pm->data = fbi;
-+#endif
-+#ifdef CONFIG_CPU_FREQ
-+ fbi->clockchg.notifier_call = pxafb_clkchg_notifier;
-+ cpufreq_register_notifier(&fbi->clockchg);
-+#endif
-+
-+ /*
-+ * Ok, now enable the LCD controller
-+ */
-+ set_ctrlr_state(fbi, C_ENABLE);
-+
-+ /* This driver cannot be unloaded at the moment */
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+
-+failed:
-+ if (fbi)
-+ kfree(fbi);
-+ return ret;
-+}
-+
-+
-+#ifdef MODULE
-+module_init(pxafb_init);
-+#endif
-+
-+MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/pxafb.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,238 @@
-+/*
-+ * linux/drivers/video/pxafb.h
-+ * -- Intel PXA250/210 LCD Controller Frame Buffer Device
-+ *
-+ * Copyright (C) 1999 Eric A. Thomas
-+ * Based on acornfb.c Copyright (C) Russell King.
-+ *
-+ * 2001-08-03: Cliff Brake <cbrake@acclent.com>
-+ * - ported SA1100 code to PXA
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive
-+ * for more details.
-+ */
-+
-+/*
-+ * These are the bitfields for each
-+ * display depth that we support.
-+ */
-+struct pxafb_rgb {
-+ struct fb_bitfield red;
-+ struct fb_bitfield green;
-+ struct fb_bitfield blue;
-+ struct fb_bitfield transp;
-+};
-+
-+/*
-+ * This structure describes the machine which we are running on.
-+ */
-+struct pxafb_mach_info {
-+ u_long pixclock;
-+
-+ u_short xres;
-+ u_short yres;
-+
-+ u_char bpp;
-+ u_char hsync_len;
-+ u_char left_margin;
-+ u_char right_margin;
-+
-+ u_char vsync_len;
-+ u_char upper_margin;
-+ u_char lower_margin;
-+ u_char sync;
-+
-+ u_int cmap_greyscale:1,
-+ cmap_inverse:1,
-+ cmap_static:1,
-+ unused:29;
-+
-+ u_int lccr0;
-+ u_int lccr3;
-+};
-+
-+/* Shadows for LCD controller registers */
-+struct pxafb_lcd_reg {
-+ unsigned int lccr0;
-+ unsigned int lccr1;
-+ unsigned int lccr2;
-+ unsigned int lccr3;
-+};
-+
-+/* PXA LCD DMA descriptor */
-+struct pxafb_dma_descriptor {
-+ unsigned int fdadr;
-+ unsigned int fsadr;
-+ unsigned int fidr;
-+ unsigned int ldcmd;
-+};
-+
-+#define RGB_8 (0)
-+#define RGB_16 (1)
-+#define NR_RGB 2
-+
-+struct pxafb_info {
-+ struct fb_info fb;
-+ signed int currcon;
-+
-+ struct pxafb_rgb *rgb[NR_RGB];
-+
-+ u_int max_bpp;
-+ u_int max_xres;
-+ u_int max_yres;
-+
-+ /*
-+ * These are the addresses we mapped
-+ * the framebuffer memory region to.
-+ */
-+
-+ /* raw memory addresses */
-+ dma_addr_t map_dma; /* physical */
-+ u_char * map_cpu; /* virtual */
-+ u_int map_size;
-+
-+ /* addresses of pieces placed in raw buffer */
-+ u_char * screen_cpu; /* virtual address of frame buffer */
-+ dma_addr_t screen_dma; /* physical address of frame buffer */
-+ u16 * palette_cpu; /* virtual address of palette memory */
-+ dma_addr_t palette_dma; /* physical address of palette memory */
-+ u_int palette_size;
-+
-+ /* DMA descriptors */
-+ struct pxafb_dma_descriptor * dmadesc_fblow_cpu;
-+ dma_addr_t dmadesc_fblow_dma;
-+ struct pxafb_dma_descriptor * dmadesc_fbhigh_cpu;
-+ dma_addr_t dmadesc_fbhigh_dma;
-+ struct pxafb_dma_descriptor * dmadesc_palette_cpu;
-+ dma_addr_t dmadesc_palette_dma;
-+
-+ dma_addr_t fdadr0;
-+ dma_addr_t fdadr1;
-+
-+ u_int lccr0;
-+ u_int lccr3;
-+ u_int cmap_inverse:1,
-+ cmap_static:1,
-+ unused:30;
-+
-+ u_int reg_lccr0;
-+ u_int reg_lccr1;
-+ u_int reg_lccr2;
-+ u_int reg_lccr3;
-+
-+ volatile u_char state;
-+ volatile u_char task_state;
-+ struct semaphore ctrlr_sem;
-+ wait_queue_head_t ctrlr_wait;
-+ struct tq_struct task;
-+
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+#ifdef CONFIG_CPU_FREQ
-+ struct notifier_block clockchg;
-+#endif
-+};
-+
-+#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
-+
-+#define TO_INF(ptr,member) __type_entry(ptr,struct pxafb_info,member)
-+
-+/*
-+ * These are the actions for set_ctrlr_state
-+ */
-+#define C_DISABLE (0)
-+#define C_ENABLE (1)
-+#define C_DISABLE_CLKCHANGE (2)
-+#define C_ENABLE_CLKCHANGE (3)
-+#define C_REENABLE (4)
-+
-+#define PXA_NAME "PXA"
-+
-+/*
-+ * Debug macros
-+ */
-+#if DEBUG
-+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-+#else
-+# define DPRINTK(fmt, args...)
-+#endif
-+
-+/*
-+ * Minimum X and Y resolutions
-+ */
-+#define MIN_XRES 64
-+#define MIN_YRES 64
-+
-+/*
-+ * Are we configured for 8 or 16 bits per pixel?
-+ */
-+#ifdef CONFIG_FB_PXA_8BPP
-+# define PXAFB_BPP 8
-+# define PXAFB_BPP_BITS 0x03
-+#elif CONFIG_FB_PXA_16BPP
-+# define PXAFB_BPP 16
-+# define PXAFB_BPP_BITS 0x04
-+#endif
-+
-+#if defined(CONFIG_ARCH_LUBBOCK)
-+#define LCD_PIXCLOCK 150000
-+#define LCD_BPP PXAFB_BPP
-+#ifdef CONFIG_FB_PXA_QVGA
-+#define LCD_XRES 320
-+#define LCD_YRES 240
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 51
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 1
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 8
-+#define LCD_END_OF_LINE_WAIT_COUNT 1
-+#define LCD_END_OF_FRAME_WAIT_COUNT 1
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x003008F8
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+#else
-+#define LCD_XRES 640
-+#define LCD_YRES 480
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 1
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 3
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 3
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x0030087C
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+#endif
-+
-+#elif defined (CONFIG_ARCH_PXA_IDP)
-+#define LCD_PIXCLOCK 150000
-+#define LCD_BPP PXAFB_BPP
-+#define LCD_XRES 640
-+#define LCD_YRES 480
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 1
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 3
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 3
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x0030087C
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+
-+#elif defined CONFIG_PXA_CERF_PDA
-+#define LCD_PIXCLOCK 171521
-+#define LCD_BPP PXAFB_BPP
-+#define LCD_XRES 240
-+#define LCD_YRES 320
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 7
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 2
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 17
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 17
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM | LCCR0_OUM)
-+#define LCD_LCCR3 (LCCR3_PCP | LCCR3_PixClkDiv(0x12) | LCCR3_Bpp(PXAFB_BPP_BITS) | LCCR3_Acb(0x18))
-+
-+#endif
---- linux-2.4.25/drivers/video/sa1100fb.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/drivers/video/sa1100fb.c 2004-03-31 17:15:12.000000000 +0200
-@@ -2175,7 +2175,7 @@
- */
- fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
- fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-- &fbi->map_dma);
-+ &fbi->map_dma, PTE_BUFFERABLE);
-
- if (fbi->map_cpu) {
- fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
---- linux-2.4.25/fs/Config.in~2.4.25-vrs2-pxa1.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/fs/Config.in 2004-03-31 17:15:12.000000000 +0200
-@@ -51,6 +51,9 @@
- int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
- fi
- tristate 'Compressed ROM file system support' CONFIG_CRAMFS
-+dep_mbool ' Use linear addressing for cramfs' CONFIG_CRAMFS_LINEAR $CONFIG_CRAMFS
-+dep_bool ' Support XIP on linear cramfs' CONFIG_CRAMFS_LINEAR_XIP $CONFIG_CRAMFS_LINEAR
-+dep_bool ' Root file system on linear cramfs' CONFIG_ROOT_CRAMFS_LINEAR $CONFIG_CRAMFS_LINEAR
- bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
- define_bool CONFIG_RAMFS y
-
---- linux-2.4.25/fs/cramfs/inode.c~2.4.25-vrs2-pxa1.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/fs/cramfs/inode.c 2004-03-31 17:15:12.000000000 +0200
-@@ -4,11 +4,29 @@
- * Copyright (C) 1999 Linus Torvalds.
- *
- * This file is released under the GPL.
-- */
--
--/*
-+ *
- * These are the VFS interfaces to the compressed rom filesystem.
- * The actual compression is based on zlib, see the other files.
-+ *
-+ * Linear Addressing code
-+ * Copyright (C) 2000 Shane Nay.
-+ *
-+ * Allows you to have a linearly addressed cramfs filesystem.
-+ * Saves the need for buffer, and the munging of the buffer.
-+ * Savings a bit over 32k with default PAGE_SIZE, BUFFER_SIZE
-+ * etc. Usefull on embedded platform with ROM :-).
-+ *
-+ * Downsides- Currently linear addressed cramfs partitions
-+ * don't co-exist with block cramfs partitions.
-+ *
-+ * 28-Dec-2000: XIP mode for linear cramfs
-+ * Copyright (C) 2000 Robert Leslie <rob@mars.org>
-+ *
-+ * Dynamic allocation of linear cramfs space by Nicolas Pitre
-+ * Copyright (C) 2003 Monta Vista Software, Inc.
-+ *
-+ * Linear cramfs now requires that you pass the physaddr= parameter to
-+ * the mount process. Allows for multiple linear cramfs partitions.
- */
-
- #include <linux/module.h>
-@@ -16,10 +34,12 @@
- #include <linux/pagemap.h>
- #include <linux/init.h>
- #include <linux/string.h>
-+#include <linux/kernel.h>
- #include <linux/locks.h>
- #include <linux/blkdev.h>
- #include <linux/cramfs_fs.h>
- #include <asm/semaphore.h>
-+#include <asm/io.h>
-
- #include <asm/uaccess.h>
-
-@@ -28,6 +48,8 @@
- #define CRAMFS_SB_BLOCKS u.cramfs_sb.blocks
- #define CRAMFS_SB_FILES u.cramfs_sb.files
- #define CRAMFS_SB_FLAGS u.cramfs_sb.flags
-+#define CRAMFS_SB_LINEAR_PHYS_ADDR u.cramfs_sb.linear_phys_addr
-+#define CRAMFS_SB_LINEAR_VIRT_ADDR u.cramfs_sb.linear_virt_addr
-
- static struct super_operations cramfs_ops;
- static struct inode_operations cramfs_dir_inode_operations;
-@@ -42,6 +64,74 @@
- #define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
- #define OFFSET(x) ((x)->i_ino)
-
-+
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+
-+static int cramfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ unsigned long address, length;
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+
-+ /* this is only used in the case of read-only maps for XIP */
-+
-+ if (vma->vm_flags & VM_WRITE)
-+ return generic_file_mmap(file, vma);
-+
-+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
-+ return -EINVAL;
-+
-+ address = PAGE_ALIGN(sb->CRAMFS_SB_LINEAR_PHYS_ADDR + OFFSET(inode));
-+ address += vma->vm_pgoff << PAGE_SHIFT;
-+
-+ length = vma->vm_end - vma->vm_start;
-+
-+ if (length > inode->i_size)
-+ length = inode->i_size;
-+
-+ length = PAGE_ALIGN(length);
-+
-+
-+#if 0
-+ /* Doing the following makes it slower and more broken. bdl */
-+ /*
-+ * Accessing memory above the top the kernel knows about or
-+ * through a file pointer that was marked O_SYNC will be
-+ * done non-cached.
-+ */
-+ vma->vm_page_prot =
-+ __pgprot((pgprot_val(vma->vm_page_prot) & ~_CACHE_MASK)
-+ | _CACHE_UNCACHED);
-+#endif
-+
-+ /*
-+ * Don't dump addresses that are not real memory to a core file.
-+ */
-+ vma->vm_flags |= VM_IO;
-+ flush_tlb_page(vma, address);
-+ if (remap_page_range(vma->vm_start, address, length,
-+ vma->vm_page_prot))
-+ return -EAGAIN;
-+
-+#ifdef DEBUG_CRAMFS_XIP
-+ printk("cramfs_mmap: mapped %s at 0x%08lx, length %lu to vma 0x%08lx"
-+ ", page_prot 0x%08lx\n",
-+ file->f_dentry->d_name.name, address, length,
-+ vma->vm_start, pgprot_val(vma->vm_page_prot));
-+#endif
-+
-+ return 0;
-+}
-+
-+static struct file_operations cramfs_linear_xip_fops = {
-+ read: generic_file_read,
-+ mmap: cramfs_mmap,
-+};
-+
-+#define CRAMFS_INODE_IS_XIP(x) ((x)->i_mode & S_ISVTX)
-+
-+#endif
-+
- static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
- {
- struct inode * inode = new_inode(sb);
-@@ -60,7 +150,11 @@
- without -noleaf option. */
- insert_inode_hash(inode);
- if (S_ISREG(inode->i_mode)) {
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+ inode->i_fop = CRAMFS_INODE_IS_XIP(inode) ? &cramfs_linear_xip_fops : &generic_ro_fops;
-+#else
- inode->i_fop = &generic_ro_fops;
-+#endif
- inode->i_data.a_ops = &cramfs_aops;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &cramfs_dir_inode_operations;
-@@ -76,6 +170,18 @@
- return inode;
- }
-
-+#ifdef CONFIG_CRAMFS_LINEAR
-+/*
-+ * Return a pointer to the block in the linearly addressed cramfs image.
-+ */
-+static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
-+{
-+ if (!len)
-+ return NULL;
-+ return (void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + offset);
-+}
-+
-+#else /* Not linear addressing - aka regular block mode. */
- /*
- * We have our own block cache: don't fill up the buffer cache
- * with the rom-image, because the way the filesystem is set
-@@ -186,23 +292,65 @@
- }
- return read_buffers[buffer] + offset;
- }
--
-+#endif /* !CONFIG_CRAMFS_LINEAR */
-
- static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
- {
-+#ifndef CONFIG_CRAMFS_LINEAR
- int i;
-+#else
-+ char *p;
-+#endif
- struct cramfs_super super;
- unsigned long root_offset;
- struct super_block * retval = NULL;
-
-- set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-
-+#ifndef CONFIG_CRAMFS_LINEAR
-+
-+ set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
-+
- /* Invalidate the read buffers on mount: think disk change.. */
- for (i = 0; i < READ_BUFFERS; i++)
- buffer_blocknr[i] = -1;
-
-+#else
-+
-+ /*
-+ * The physical location of the cramfs image is specified as
-+ * a mount parameter. This parameter is mandatory for obvious
-+ * reasons. Some validation is made on the phys address but this
-+ * is not exhaustive and we count on the fact that someone using
-+ * this feature is supposed to know what he/she's doing.
-+ */
-+ if (!data || !(p = strstr((char *)data, "physaddr="))) {
-+ printk(KERN_ERR "cramfs: unknown physical address for linear cramfs image\n");
-+ goto out;
-+ }
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR = simple_strtoul(p + 9, NULL, 0);
-+ if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR & (PAGE_SIZE-1)) {
-+ printk(KERN_ERR "cramfs: physical address 0x%lx for linear cramfs isn't aligned to a page boundary\n",
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
-+ goto out;
-+ }
-+ if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR == 0) {
-+ printk(KERN_ERR "cramfs: physical address for linear cramfs image can't be 0\n");
-+ goto out;
-+ }
-+ printk(KERN_INFO "cramfs: checking physical address 0x%lx for linear cramfs image\n",
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
-+
-+ /* Map only one page for now. Will remap it when fs size is known. */
-+ sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
-+ ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, PAGE_SIZE);
-+ if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
-+ printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
-+ goto out;
-+ }
-+#endif
-+
- down(&read_mutex);
- /* Read the first block and get the superblock from it */
- memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
-@@ -254,8 +402,26 @@
- /* Set it all up.. */
- sb->s_op = &cramfs_ops;
- sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
-+
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ /* Remap the whole filesystem now */
-+ iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
-+ printk(KERN_INFO "cramfs: linear cramfs image appears to be %lu KB in size\n",
-+ sb->CRAMFS_SB_SIZE/1024);
-+ sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
-+ ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, sb->CRAMFS_SB_SIZE);
-+ if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
-+ printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
-+ goto out;
-+ }
-+#endif
-+
- retval = sb;
- out:
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ if (!retval && sb->CRAMFS_SB_LINEAR_VIRT_ADDR)
-+ iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
-+#endif
- return retval;
- }
-
-@@ -388,6 +554,18 @@
-
- maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- bytes_filled = 0;
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+ if (page->index < maxblock && CRAMFS_INODE_IS_XIP(inode)) {
-+ struct super_block *sb = inode->i_sb;
-+ u32 blkptr_offset = PAGE_ALIGN(OFFSET(inode)) +
-+ page->index * PAGE_CACHE_SIZE;
-+ memcpy( page_address(page),
-+ (void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + blkptr_offset),
-+ PAGE_CACHE_SIZE );
-+ bytes_filled = PAGE_CACHE_SIZE;
-+ pgdata = kmap(page);
-+ } else
-+#endif
- if (page->index < maxblock) {
- struct super_block *sb = inode->i_sb;
- u32 blkptr_offset = OFFSET(inode) + page->index*4;
-@@ -444,7 +622,11 @@
- statfs: cramfs_statfs,
- };
-
-+#ifndef CONFIG_CRAMFS_LINEAR
- static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
-+#else
-+static DECLARE_FSTYPE(cramfs_fs_type, "cramfs", cramfs_read_super, 0);
-+#endif
-
- static int __init init_cramfs_fs(void)
- {
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/fs/cramfs/mkcramfs.c 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,821 @@
-+/*
-+ * mkcramfs - make a cramfs file system, optionally with XIP files.
-+ *
-+ * Copyright (C) 1999-2001 Transmeta Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <sys/types.h>
-+#include <stdio.h>
-+#include <sys/stat.h>
-+#include <unistd.h>
-+#include <sys/mman.h>
-+#include <sys/fcntl.h>
-+#include <dirent.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <assert.h>
-+#include <getopt.h>
-+#include <linux/cramfs_fs.h>
-+#include <zlib.h>
-+
-+#define PAD_SIZE 512 /* only 0 and 512 supported by kernel */
-+
-+static const char *progname = "mkcramfs";
-+
-+/* N.B. If you change the disk format of cramfs, please update fs/cramfs/README. */
-+
-+/* Input status of 0 to print help and exit without an error. */
-+static void usage(int status)
-+{
-+ FILE *stream = status ? stderr : stdout;
-+
-+ fprintf(stream, "usage: %s [-h] [-e edition] [-i file] [-n name] dirname outfile\n"
-+ " -h print this help\n"
-+ " -E make all warnings errors (non-zero exit status)\n"
-+ " -e edition set edition number (part of fsid)\n"
-+ " -i file insert a file image into the filesystem (requires >= 2.4.0)\n"
-+ " -n name set name of cramfs filesystem\n"
-+ " -p pad by %d bytes for boot code\n"
-+ " -s sort directory entries (old option, ignored)\n"
-+ " -x make marked files eXecute In Place\n"
-+ " -z make explicit holes (requires >= 2.3.39)\n"
-+ " dirname root of the filesystem to be compressed\n"
-+ " outfile output file\n", progname, PAD_SIZE);
-+
-+ exit(status);
-+}
-+
-+#define PAGE_SIZE (4096)
-+#define PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
-+#define ROM_OFFSET 0
-+#define ROM_ALIGN(x) (PAGE_ALIGN((x) + ROM_OFFSET) - ROM_OFFSET)
-+#define PAGE_CACHE_SIZE (4096)
-+/* The kernel assumes PAGE_CACHE_SIZE as block size. */
-+static unsigned int blksize = PAGE_CACHE_SIZE;
-+static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
-+static int image_length = 0;
-+
-+/*
-+ * If opt_holes is set, then mkcramfs can create explicit holes in the
-+ * data, which saves 26 bytes per hole (which is a lot smaller a
-+ * saving than most most filesystems).
-+ *
-+ * Note that kernels up to at least 2.3.39 don't support cramfs holes,
-+ * which is why this is turned off by default.
-+ */
-+static int opt_edition = 0;
-+static int opt_errors = 0;
-+static int opt_holes = 0;
-+static int opt_xip = 0;
-+static int opt_pad = 0;
-+static char *opt_image = NULL;
-+static char *opt_name = NULL;
-+
-+static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
-+
-+#ifndef MIN
-+# define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
-+#endif
-+
-+/* In-core version of inode / directory entry. */
-+struct entry {
-+ /* stats */
-+ char *name;
-+ unsigned int mode, size, uid, gid;
-+
-+ /* FS data */
-+ void *uncompressed;
-+ /* points to other identical file */
-+ struct entry *same;
-+ unsigned int offset; /* pointer to compressed data in archive */
-+ unsigned int dir_offset; /* Where in the archive is the directory entry? */
-+
-+ /* organization */
-+ struct entry *child; /* null for non-directories and empty directories */
-+ struct entry *next;
-+};
-+
-+/*
-+ * The longest file name component to allow for in the input directory tree.
-+ * Ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
-+ * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
-+ * >255-byte names in the input directory tree given that such names get
-+ * truncated to 255 bytes when written to cramfs.
-+ */
-+#define MAX_INPUT_NAMELEN 255
-+
-+static int find_identical_file(struct entry *orig,struct entry *newfile)
-+{
-+ if(orig==newfile) return 1;
-+ if(!orig) return 0;
-+ if(orig->size==newfile->size && orig->uncompressed && !memcmp(orig->uncompressed,newfile->uncompressed,orig->size)) {
-+ newfile->same=orig;
-+ return 1;
-+ }
-+ return find_identical_file(orig->child,newfile) ||
-+ find_identical_file(orig->next,newfile);
-+}
-+
-+static void eliminate_doubles(struct entry *root,struct entry *orig) {
-+ if(orig) {
-+ if(orig->size && orig->uncompressed)
-+ find_identical_file(root,orig);
-+ eliminate_doubles(root,orig->child);
-+ eliminate_doubles(root,orig->next);
-+ }
-+}
-+
-+/*
-+ * We define our own sorting function instead of using alphasort which
-+ * uses strcoll and changes ordering based on locale information.
-+ */
-+static int cramsort (const void *a, const void *b)
-+{
-+ return strcmp ((*(const struct dirent **) a)->d_name,
-+ (*(const struct dirent **) b)->d_name);
-+}
-+
-+static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
-+{
-+ struct dirent **dirlist;
-+ int totalsize = 0, dircount, dirindex;
-+ char *path, *endpath;
-+ size_t len = strlen(name);
-+
-+ /* Set up the path. */
-+ /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
-+ path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
-+ if (!path) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ memcpy(path, name, len);
-+ endpath = path + len;
-+ *endpath = '/';
-+ endpath++;
-+
-+ /* read in the directory and sort */
-+ dircount = scandir(name, &dirlist, 0, cramsort);
-+
-+ if (dircount < 0) {
-+ perror(name);
-+ exit(8);
-+ }
-+
-+ /* process directory */
-+ for (dirindex = 0; dirindex < dircount; dirindex++) {
-+ struct dirent *dirent;
-+ struct entry *entry;
-+ struct stat st;
-+ int size;
-+ size_t namelen;
-+
-+ dirent = dirlist[dirindex];
-+
-+ /* Ignore "." and ".." - we won't be adding them to the archive */
-+ if (dirent->d_name[0] == '.') {
-+ if (dirent->d_name[1] == '\0')
-+ continue;
-+ if (dirent->d_name[1] == '.') {
-+ if (dirent->d_name[2] == '\0')
-+ continue;
-+ }
-+ }
-+ namelen = strlen(dirent->d_name);
-+ if (namelen > MAX_INPUT_NAMELEN) {
-+ fprintf(stderr,
-+ "Very long (%u bytes) filename `%s' found.\n"
-+ " Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile. Exiting.\n",
-+ namelen, dirent->d_name);
-+ exit(8);
-+ }
-+ memcpy(endpath, dirent->d_name, namelen + 1);
-+
-+ if (lstat(path, &st) < 0) {
-+ perror(endpath);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ entry = calloc(1, sizeof(struct entry));
-+ if (!entry) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ entry->name = strdup(dirent->d_name);
-+ if (!entry->name) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ if (namelen > 255) {
-+ /* Can't happen when reading from ext2fs. */
-+
-+ /* TODO: we ought to avoid chopping in half
-+ multi-byte UTF8 characters. */
-+ entry->name[namelen = 255] = '\0';
-+ warn_namelen = 1;
-+ }
-+ entry->mode = st.st_mode;
-+ entry->size = st.st_size;
-+ entry->uid = st.st_uid;
-+ if (entry->uid >= 1 << CRAMFS_UID_WIDTH)
-+ warn_uid = 1;
-+ entry->gid = st.st_gid;
-+ if (entry->gid >= 1 << CRAMFS_GID_WIDTH)
-+ /* TODO: We ought to replace with a default
-+ gid instead of truncating; otherwise there
-+ are security problems. Maybe mode should
-+ be &= ~070. Same goes for uid once Linux
-+ supports >16-bit uids. */
-+ warn_gid = 1;
-+ size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
-+ *fslen_ub += size;
-+ if (S_ISDIR(st.st_mode)) {
-+ entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
-+ } else if (S_ISREG(st.st_mode)) {
-+ /* TODO: We ought to open files in do_compress, one
-+ at a time, instead of amassing all these memory
-+ maps during parse_directory (which don't get used
-+ until do_compress anyway). As it is, we tend to
-+ get EMFILE errors (especially if mkcramfs is run
-+ by non-root).
-+
-+ While we're at it, do analagously for symlinks
-+ (which would just save a little memory). */
-+ int fd = open(path, O_RDONLY);
-+ if (fd < 0) {
-+ perror(path);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ if (entry->size) {
-+ if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) {
-+ warn_size = 1;
-+ entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
-+ }
-+
-+ entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
-+ if (-1 == (int) (long) entry->uncompressed) {
-+ perror("mmap");
-+ exit(8);
-+ }
-+ }
-+ close(fd);
-+ } else if (S_ISLNK(st.st_mode)) {
-+ entry->uncompressed = malloc(entry->size);
-+ if (!entry->uncompressed) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ if (readlink(path, entry->uncompressed, entry->size) < 0) {
-+ perror(path);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
-+ /* maybe we should skip sockets */
-+ entry->size = 0;
-+ } else {
-+ entry->size = st.st_rdev;
-+ if (entry->size & -(1<<CRAMFS_SIZE_WIDTH))
-+ warn_dev = 1;
-+ }
-+
-+ if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
-+ int blocks = ((entry->size - 1) / blksize + 1);
-+
-+ /* block pointers & data expansion allowance + data */
-+ if(entry->size)
-+ *fslen_ub += (4+26)*blocks + entry->size + 3;
-+ }
-+
-+ if (opt_xip && entry->mode & S_ISVTX) {
-+ /* worse case, depending on where the offsets falls,
-+ * a single XIP entry could expand the sizeof the
-+ * file system by 8k, since we're aligning the start
-+ * and end on page boundary.
-+ */
-+ *fslen_ub += 2*PAGE_CACHE_SIZE;
-+ }
-+
-+ /* Link it into the list */
-+ *prev = entry;
-+ prev = &entry->next;
-+ totalsize += size;
-+ }
-+ free(path);
-+ free(dirlist); /* allocated by scandir() with malloc() */
-+ return totalsize;
-+}
-+
-+/* Returns sizeof(struct cramfs_super), which includes the root inode. */
-+static unsigned int write_superblock(struct entry *root, char *base, int size)
-+{
-+ struct cramfs_super *super = (struct cramfs_super *) base;
-+ unsigned int offset = sizeof(struct cramfs_super) + image_length;
-+
-+ if (opt_pad) {
-+ offset += opt_pad;
-+ }
-+
-+ super->magic = CRAMFS_MAGIC;
-+ super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS;
-+ if (opt_holes)
-+ super->flags |= CRAMFS_FLAG_HOLES;
-+ if (image_length > 0)
-+ super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET;
-+ super->size = size;
-+ memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
-+
-+ super->fsid.crc = crc32(0L, Z_NULL, 0);
-+ super->fsid.edition = opt_edition;
-+ super->fsid.blocks = total_blocks;
-+ super->fsid.files = total_nodes;
-+
-+ memset(super->name, 0x00, sizeof(super->name));
-+ if (opt_name)
-+ strncpy(super->name, opt_name, sizeof(super->name));
-+ else
-+ strncpy(super->name, "Compressed", sizeof(super->name));
-+
-+ super->root.mode = root->mode;
-+ super->root.uid = root->uid;
-+ super->root.gid = root->gid;
-+ super->root.size = root->size;
-+ super->root.offset = offset >> 2;
-+
-+ return offset;
-+}
-+
-+static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
-+{
-+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
-+#ifdef DEBUG
-+ assert ((offset & 3) == 0);
-+#endif /* DEBUG */
-+ if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
-+ fprintf(stderr, "filesystem too big. Exiting.\n");
-+ exit(8);
-+ }
-+ inode->offset = (offset >> 2);
-+}
-+
-+
-+/*
-+ * We do a width-first printout of the directory
-+ * entries, using a stack to remember the directories
-+ * we've seen.
-+ */
-+#define MAXENTRIES (100)
-+static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
-+{
-+ int stack_entries = 0;
-+ struct entry *entry_stack[MAXENTRIES];
-+
-+ for (;;) {
-+ int dir_start = stack_entries;
-+ while (entry) {
-+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
-+ size_t len = strlen(entry->name);
-+
-+ entry->dir_offset = offset;
-+
-+ inode->mode = entry->mode;
-+ inode->uid = entry->uid;
-+ inode->gid = entry->gid;
-+ inode->size = entry->size;
-+ inode->offset = 0;
-+ /* Non-empty directories, regfiles and symlinks will
-+ write over inode->offset later. */
-+
-+ offset += sizeof(struct cramfs_inode);
-+ total_nodes++; /* another node */
-+ memcpy(base + offset, entry->name, len);
-+ /* Pad up the name to a 4-byte boundary */
-+ while (len & 3) {
-+ *(base + offset + len) = '\0';
-+ len++;
-+ }
-+ inode->namelen = len >> 2;
-+ offset += len;
-+
-+ /* TODO: this may get it wrong for chars >= 0x80.
-+ Most filesystems use UTF8 encoding for filenames,
-+ whereas the console is a single-byte character
-+ set like iso-latin-1. */
-+ printf(" %s\n", entry->name);
-+ if (entry->child) {
-+ if (stack_entries >= MAXENTRIES) {
-+ fprintf(stderr, "Exceeded MAXENTRIES. Raise this value in mkcramfs.c and recompile. Exiting.\n");
-+ exit(8);
-+ }
-+ entry_stack[stack_entries] = entry;
-+ stack_entries++;
-+ }
-+ entry = entry->next;
-+ }
-+
-+ /*
-+ * Reverse the order the stack entries pushed during
-+ * this directory, for a small optimization of disk
-+ * access in the created fs. This change makes things
-+ * `ls -UR' order.
-+ */
-+ {
-+ struct entry **lo = entry_stack + dir_start;
-+ struct entry **hi = entry_stack + stack_entries;
-+ struct entry *tmp;
-+
-+ while (lo < --hi) {
-+ tmp = *lo;
-+ *lo++ = *hi;
-+ *hi = tmp;
-+ }
-+ }
-+
-+ /* Pop a subdirectory entry from the stack, and recurse. */
-+ if (!stack_entries)
-+ break;
-+ stack_entries--;
-+ entry = entry_stack[stack_entries];
-+
-+ set_data_offset(entry, base, offset);
-+ printf("'%s':\n", entry->name);
-+ entry = entry->child;
-+ }
-+ return offset;
-+}
-+
-+static int is_zero(char const *begin, unsigned len)
-+{
-+ if (opt_holes)
-+ /* Returns non-zero iff the first LEN bytes from BEGIN are
-+ all NULs. */
-+ return (len-- == 0 ||
-+ (begin[0] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[1] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[2] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[3] == '\0' &&
-+ memcmp(begin, begin + 4, len) == 0))))))));
-+ else
-+ /* Never create holes. */
-+ return 0;
-+}
-+
-+static unsigned int do_xip(char *base, unsigned int offset,
-+ char const *name, char *uncompressed,
-+ unsigned int size)
-+{
-+ unsigned int start, end;
-+
-+ /* align to page boundary */
-+
-+ start = ROM_ALIGN(offset);
-+ memset(base + offset, 0, start - offset);
-+
-+ memcpy(base + start, uncompressed, size);
-+
-+ /* pad to page boundary */
-+
-+ end = ROM_ALIGN(start + size);
-+ memset(base + start + size, 0, end - (start + size));
-+
-+ printf("XIP (%u+%u bytes)\toffset %u\t%s\n",
-+ size, (end - offset) - size, offset, name);
-+
-+ return end;
-+}
-+
-+/*
-+ * One 4-byte pointer per block and then the actual blocked
-+ * output. The first block does not need an offset pointer,
-+ * as it will start immediately after the pointer block;
-+ * so the i'th pointer points to the end of the i'th block
-+ * (i.e. the start of the (i+1)'th block or past EOF).
-+ *
-+ * Note that size > 0, as a zero-sized file wouldn't ever
-+ * have gotten here in the first place.
-+ */
-+static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size)
-+{
-+ unsigned long original_size = size;
-+ unsigned long original_offset = offset;
-+ unsigned long new_size;
-+ unsigned long blocks = (size - 1) / blksize + 1;
-+ unsigned long curr = offset + 4 * blocks;
-+ int change;
-+
-+ total_blocks += blocks;
-+
-+ do {
-+ unsigned long len = 2 * blksize;
-+ unsigned int input = size;
-+ if (input > blksize)
-+ input = blksize;
-+ size -= input;
-+ if (!is_zero (uncompressed, input)) {
-+ compress(base + curr, &len, uncompressed, input);
-+ curr += len;
-+ }
-+ uncompressed += input;
-+
-+ if (len > blksize*2) {
-+ /* (I don't think this can happen with zlib.) */
-+ printf("AIEEE: block \"compressed\" to > 2*blocklength (%ld)\n", len);
-+ exit(8);
-+ }
-+
-+ *(u32 *) (base + offset) = curr;
-+ offset += 4;
-+ } while (size);
-+
-+ curr = (curr + 3) & ~3;
-+ new_size = curr - original_offset;
-+ /* TODO: Arguably, original_size in these 2 lines should be
-+ st_blocks * 512. But if you say that then perhaps
-+ administrative data should also be included in both. */
-+ change = new_size - original_size;
-+ printf("%6.2f%% (%+d bytes)\toffset %lu\t%s\n",
-+ (change * 100) / (double) original_size, change, original_offset, name);
-+
-+ return curr;
-+}
-+
-+
-+/*
-+ * Traverse the entry tree, writing data for every item that has
-+ * non-null entry->compressed (i.e. every symlink and non-empty
-+ * regfile).
-+ */
-+static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
-+{
-+ do {
-+ if (entry->uncompressed) {
-+ if(entry->same) {
-+ set_data_offset(entry, base, entry->same->offset);
-+ entry->offset=entry->same->offset;
-+ } else {
-+ set_data_offset(entry, base, offset);
-+ entry->offset=offset;
-+ if (opt_xip && entry->mode & S_ISVTX)
-+ offset = do_xip(base, offset, entry->name, entry->uncompressed, entry->size);
-+ else
-+ offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size);
-+ }
-+ }
-+ else if (entry->child)
-+ offset = write_data(entry->child, base, offset);
-+ entry=entry->next;
-+ } while (entry);
-+ return offset;
-+}
-+
-+static unsigned int write_file(char *file, char *base, unsigned int offset)
-+{
-+ int fd;
-+ char *buf;
-+
-+ fd = open(file, O_RDONLY);
-+ if (fd < 0) {
-+ perror(file);
-+ exit(8);
-+ }
-+ buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0);
-+ memcpy(base + offset, buf, image_length);
-+ munmap(buf, image_length);
-+ close (fd);
-+ /* Pad up the image_length to a 4-byte boundary */
-+ while (image_length & 3) {
-+ *(base + offset + image_length) = '\0';
-+ image_length++;
-+ }
-+ return (offset + image_length);
-+}
-+
-+/*
-+ * Maximum size fs you can create is roughly 256MB. (The last file's
-+ * data must begin within 256MB boundary but can extend beyond that.)
-+ *
-+ * Note that if you want it to fit in a ROM then you're limited to what the
-+ * hardware and kernel can support (64MB?).
-+ */
-+#define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \
-+ + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \
-+ + (1 << CRAMFS_SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
-+
-+
-+/*
-+ * Usage:
-+ *
-+ * mkcramfs directory-name outfile
-+ *
-+ * where "directory-name" is simply the root of the directory
-+ * tree that we want to generate a compressed filesystem out
-+ * of.
-+ */
-+int main(int argc, char **argv)
-+{
-+ struct stat st; /* used twice... */
-+ struct entry *root_entry;
-+ char *rom_image;
-+ ssize_t offset, written;
-+ int fd;
-+ /* initial guess (upper-bound) of required filesystem size */
-+ loff_t fslen_ub = sizeof(struct cramfs_super);
-+ char const *dirname, *outfile;
-+ u32 crc = crc32(0L, Z_NULL, 0);
-+ int c; /* for getopt */
-+
-+ total_blocks = 0;
-+
-+ if (argc)
-+ progname = argv[0];
-+
-+ /* command line options */
-+ while ((c = getopt(argc, argv, "hEe:i:n:psxz")) != EOF) {
-+ switch (c) {
-+ case 'h':
-+ usage(0);
-+ case 'E':
-+ opt_errors = 1;
-+ break;
-+ case 'e':
-+ opt_edition = atoi(optarg);
-+ break;
-+ case 'i':
-+ opt_image = optarg;
-+ if (lstat(opt_image, &st) < 0) {
-+ perror(opt_image);
-+ exit(16);
-+ }
-+ image_length = st.st_size; /* may be padded later */
-+ fslen_ub += (image_length + 3); /* 3 is for padding */
-+ break;
-+ case 'n':
-+ opt_name = optarg;
-+ break;
-+ case 'p':
-+ opt_pad = PAD_SIZE;
-+ fslen_ub += PAD_SIZE;
-+ break;
-+ case 's':
-+ /* old option, ignored */
-+ break;
-+ case 'x':
-+ opt_xip = 1;
-+ break;
-+ case 'z':
-+ opt_holes = 1;
-+ break;
-+ }
-+ }
-+
-+ if ((argc - optind) != 2)
-+ usage(16);
-+ dirname = argv[optind];
-+ outfile = argv[optind + 1];
-+
-+ if (stat(dirname, &st) < 0) {
-+ perror(dirname);
-+ exit(16);
-+ }
-+ fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-+
-+ root_entry = calloc(1, sizeof(struct entry));
-+ if (!root_entry) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ root_entry->mode = st.st_mode;
-+ root_entry->uid = st.st_uid;
-+ root_entry->gid = st.st_gid;
-+
-+ root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub);
-+
-+ /* always allocate a multiple of blksize bytes because that's
-+ what we're going to write later on */
-+ fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1;
-+
-+ if (fslen_ub > MAXFSLEN) {
-+ fprintf(stderr,
-+ "warning: guestimate of required size (upper bound) is %LdMB, but maximum image size is %uMB. We might die prematurely.\n",
-+ fslen_ub >> 20,
-+ MAXFSLEN >> 20);
-+ fslen_ub = MAXFSLEN;
-+ }
-+
-+ /* find duplicate files. TODO: uses the most inefficient algorithm
-+ possible. */
-+ eliminate_doubles(root_entry,root_entry);
-+
-+ /* TODO: Why do we use a private/anonymous mapping here
-+ followed by a write below, instead of just a shared mapping
-+ and a couple of ftruncate calls? Is it just to save us
-+ having to deal with removing the file afterwards? If we
-+ really need this huge anonymous mapping, we ought to mmap
-+ in smaller chunks, so that the user doesn't need nn MB of
-+ RAM free. If the reason is to be able to write to
-+ un-mmappable block devices, then we could try shared mmap
-+ and revert to anonymous mmap if the shared mmap fails. */
-+ rom_image = mmap(NULL, fslen_ub?fslen_ub:1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+
-+ if (-1 == (int) (long) rom_image) {
-+ perror("ROM image map");
-+ exit(8);
-+ }
-+
-+ /* Skip the first opt_pad bytes for boot loader code */
-+ offset = opt_pad;
-+ memset(rom_image, 0x00, opt_pad);
-+
-+ /* Skip the superblock and come back to write it later. */
-+ offset += sizeof(struct cramfs_super);
-+
-+ /* Insert a file image. */
-+ if (opt_image) {
-+ printf("Including: %s\n", opt_image);
-+ offset = write_file(opt_image, rom_image, offset);
-+ }
-+
-+ offset = write_directory_structure(root_entry->child, rom_image, offset);
-+ printf("Directory data: %d bytes\n", offset);
-+
-+ offset = write_data(root_entry, rom_image, offset);
-+
-+ /* We always write a multiple of blksize bytes, so that
-+ losetup works. */
-+ offset = ((offset - 1) | (blksize - 1)) + 1;
-+ printf("Everything: %d kilobytes\n", offset >> 10);
-+
-+ /* Write the superblock now that we can fill in all of the fields. */
-+ write_superblock(root_entry, rom_image+opt_pad, offset);
-+ printf("Super block: %d bytes\n", sizeof(struct cramfs_super));
-+
-+ /* Put the checksum in. */
-+ crc = crc32(crc, (rom_image+opt_pad), (offset-opt_pad));
-+ ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc;
-+ printf("CRC: %x\n", crc);
-+
-+ /* Check to make sure we allocated enough space. */
-+ if (fslen_ub < offset) {
-+ fprintf(stderr, "not enough space allocated for ROM image (%Ld allocated, %d used)\n",
-+ fslen_ub, offset);
-+ exit(8);
-+ }
-+
-+ written = write(fd, rom_image, offset);
-+ if (written < 0) {
-+ perror("ROM image");
-+ exit(8);
-+ }
-+ if (offset != written) {
-+ fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
-+ exit(8);
-+ }
-+
-+ /* (These warnings used to come at the start, but they scroll off the
-+ screen too quickly.) */
-+ if (warn_namelen) /* (can't happen when reading from ext2fs) */
-+ fprintf(stderr, /* bytes, not chars: think UTF8. */
-+ "warning: filenames truncated to 255 bytes.\n");
-+ if (warn_skip)
-+ fprintf(stderr, "warning: files were skipped due to errors.\n");
-+ if (warn_size)
-+ fprintf(stderr,
-+ "warning: file sizes truncated to %luMB (minus 1 byte).\n",
-+ 1L << (CRAMFS_SIZE_WIDTH - 20));
-+ if (warn_uid) /* (not possible with current Linux versions) */
-+ fprintf(stderr,
-+ "warning: uids truncated to %u bits. (This may be a security concern.)\n",
-+ CRAMFS_UID_WIDTH);
-+ if (warn_gid)
-+ fprintf(stderr,
-+ "warning: gids truncated to %u bits. (This may be a security concern.)\n",
-+ CRAMFS_GID_WIDTH);
-+ if (warn_dev)
-+ fprintf(stderr,
-+ "WARNING: device numbers truncated to %u bits. This almost certainly means\n"
-+ "that some device files will be wrong.\n",
-+ CRAMFS_OFFSET_WIDTH);
-+ if (opt_errors &&
-+ (warn_namelen||warn_skip||warn_size||warn_uid||warn_gid||warn_dev))
-+ exit(8);
-+ return 0;
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/bitfield.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,113 @@
-+/*
-+ * FILE bitfield.h
-+ *
-+ * Version 1.1
-+ * Author Copyright (c) Marc A. Viredaz, 1998
-+ * DEC Western Research Laboratory, Palo Alto, CA
-+ * Date April 1998 (April 1997)
-+ * System Advanced RISC Machine (ARM)
-+ * Language C or ARM Assembly
-+ * Purpose Definition of macros to operate on bit fields.
-+ */
-+
-+
-+
-+#ifndef __BITFIELD_H
-+#define __BITFIELD_H
-+
-+#ifndef __ASSEMBLY__
-+#define UData(Data) ((unsigned long) (Data))
-+#else
-+#define UData(Data) (Data)
-+#endif
-+
-+
-+/*
-+ * MACRO: Fld
-+ *
-+ * Purpose
-+ * The macro "Fld" encodes a bit field, given its size and its shift value
-+ * with respect to bit 0.
-+ *
-+ * Note
-+ * A more intuitive way to encode bit fields would have been to use their
-+ * mask. However, extracting size and shift value information from a bit
-+ * field's mask is cumbersome and might break the assembler (255-character
-+ * line-size limit).
-+ *
-+ * Input
-+ * Size Size of the bit field, in number of bits.
-+ * Shft Shift value of the bit field with respect to bit 0.
-+ *
-+ * Output
-+ * Fld Encoded bit field.
-+ */
-+
-+#define Fld(Size, Shft) (((Size) << 16) + (Shft))
-+
-+
-+/*
-+ * MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit
-+ *
-+ * Purpose
-+ * The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return
-+ * the size, shift value, mask, aligned mask, and first bit of a
-+ * bit field.
-+ *
-+ * Input
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FSize Size of the bit field, in number of bits.
-+ * FShft Shift value of the bit field with respect to bit 0.
-+ * FMsk Mask for the bit field.
-+ * FAlnMsk Mask for the bit field, aligned on bit 0.
-+ * F1stBit First bit of the bit field.
-+ */
-+
-+#define FSize(Field) ((Field) >> 16)
-+#define FShft(Field) ((Field) & 0x0000FFFF)
-+#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))
-+#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
-+#define F1stBit(Field) (UData (1) << FShft (Field))
-+
-+
-+/*
-+ * MACRO: FInsrt
-+ *
-+ * Purpose
-+ * The macro "FInsrt" inserts a value into a bit field by shifting the
-+ * former appropriately.
-+ *
-+ * Input
-+ * Value Bit-field value.
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FInsrt Bit-field value positioned appropriately.
-+ */
-+
-+#define FInsrt(Value, Field) \
-+ (UData (Value) << FShft (Field))
-+
-+
-+/*
-+ * MACRO: FExtr
-+ *
-+ * Purpose
-+ * The macro "FExtr" extracts the value of a bit field by masking and
-+ * shifting it appropriately.
-+ *
-+ * Input
-+ * Data Data containing the bit-field to be extracted.
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FExtr Bit-field value.
-+ */
-+
-+#define FExtr(Data, Field) \
-+ ((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
-+
-+
-+#endif /* __BITFIELD_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/cerf.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,177 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/cerf.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * Add CerfBoard Specifics here...
-+ */
-+
-+/*
-+ * Memory sizes
-+ */
-+
-+#define CERF_RAM_BASE 0xa0000000
-+
-+#ifdef CONFIG_PXA_CERF_RAM_128MB
-+#define CERF_RAM_SIZE 128*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_64MB)
-+#define CERF_RAM_SIZE 64*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_32MB)
-+#define CERF_RAM_SIZE 32*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_16MB)
-+#define CERF_RAM_SIZE 16*1024*1024
-+#endif
-+
-+/*
-+ * CS memory timing via Static Memory Control Register (MSC0-2)
-+ */
-+
-+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
-+
-+#define MSC_RBUFF_SHIFT 15
-+#define MSC_RBUFF_SLOW (0)
-+#define MSC_RBUFF_FAST (1)
-+#define MSC_RBUFF(x) ((x)<<MSC_RBUFF_SHIFT)
-+
-+#define MSC_RRR_SHIFT 12
-+#define MSC_RRR(x) ((x)<<MSC_RRR_SHIFT)
-+
-+#define MSC_RDN_SHIFT 8
-+#define MSC_RDN(x) ((x)<<MSC_RDN_SHIFT)
-+
-+#define MSC_RDF_SHIFT 4
-+#define MSC_RDF(x) ((x)<<MSC_RDF_SHIFT)
-+
-+#define MSC_RBW_SHIFT 3
-+#define MSC_RBW(x) ((x)<<MSC_RBW_SHIFT)
-+
-+#define MSC_RT_SHIFT 0
-+#define MSC_RT(x) ((x)<<MSC_RT_SHIFT)
-+
-+/*
-+ * IO Pins for devices
-+ */
-+
-+#define CERF_FLASH_BASE 0xe8000000
-+#define CERF_FLASH_SIZE 0x02000000
-+#define CERF_FLASH_PHYS PXA_CS0_PHYS
-+
-+#define CERF_ETH_BASE 0xf0000000
-+#define CERF_ETH_SIZE 0x00100000
-+#define CERF_ETH_PHYS PXA_CS1_PHYS
-+
-+#define CERF_BT_BASE 0xf2000000
-+#define CERF_BT_SIZE 0x00100000
-+#define CERF_BT_PHYS PXA_CS2_PHYS
-+
-+#define CERF_SERIAL_BASE 0xf3000000
-+#define CERF_SERIAL_SIZE 0x00100000
-+#define CERF_SERIAL_PHYS PXA_CS3_PHYS
-+
-+#define CERF_CPLD_BASE 0xf1000000
-+#define CERF_CPLD_SIZE 0x00100000
-+#define CERF_CPLD_PHYS PXA_CS4_PHYS
-+
-+#define CERF_PDA_CPLD_WRCLRINT (0x0)
-+#define CERF_PDA_CPLD_BRIGHTNESS (0x2)
-+#define CERF_PDA_CPLD_KEYPAD_A (0x6)
-+#define CERF_PDA_CPLD_BATTFAULT (0x8)
-+#define CERF_PDA_CPLD_KEYPAD_B (0xa)
-+#define CERF_PDA_CPLD_SOUND_ENA (0xc)
-+
-+#define CERF_PDA_SOUND_ENABLE 0x1
-+#define CERF_PDA_DEFAULT_BRIGHTNESS 0x9
-+
-+/*
-+ * Access functions (registers are 4-bit wide)
-+ */
-+
-+#define CERF_PDA_CPLD CERF_CPLD_BASE
-+
-+#define CERF_PDA_CPLD_Get(x, y) (*((char*)(CERF_PDA_CPLD + (x))) & (y))
-+#define CERF_PDA_CPLD_Set(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) | (y))
-+#define CERF_PDA_CPLD_UnSet(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) & ~(y))
-+
-+/*
-+ * IO and IRQ settings for cs8900 ethernet chip
-+ */
-+#define CERF_ETH_IO CERF_ETH_BASE
-+#define CERF_ETH_IRQ GPIO_2_80_TO_IRQ(21)
-+
-+/*
-+ * We only have one LED on the XScale CerfPDA so only the
-+ * time or idle should ever be selected.
-+ */
-+#define CERF_HEARTBEAT_LED 0x1
-+#define CERF_SYS_BUSY_LED 0x2
-+
-+#define CERF_HEARTBEAT_LED_GPIO 16 // GPIO 4
-+#define CERF_SYS_BUSY_LED_GPIO 16 // GPIO 4
-+
-+#define CERF_HEARTBEAT_LED_ON (GPSR0 = CERF_HEARTBEAT_LED_GPIO)
-+#define CERF_HEARTBEAT_LED_OFF (GPCR0 = CERF_HEARTBEAT_LED_GPIO)
-+#define CERF_SYS_BUSY_LED_ON (GPSR0 = CERF_SYS_BUSY_LED_GPIO)
-+#define CERF_SYS_BUSY_LED_OFF (GPCR0 = CERF_SYS_BUSY_LED_GPIO)
-+
-+/*
-+ * UCB 1400 gpio
-+ */
-+
-+#define CERF_GPIO_UCB1400_IRQ 32
-+
-+#define UCB_IO_0 (1 << 0)
-+#define UCB_IO_1 (1 << 1)
-+#define UCB_IO_2 (1 << 2)
-+#define UCB_IO_3 (1 << 3)
-+#define UCB_IO_4 (1 << 4)
-+#define UCB_IO_5 (1 << 5)
-+#define UCB_IO_6 (1 << 6)
-+#define UCB_IO_7 (1 << 7)
-+#define UCB_IO_8 (1 << 8)
-+#define UCB_IO_9 (1 << 9)
-+
-+#define UCB1400_GPIO_CONT_CS UCB_IO_0
-+#define UCB1400_GPIO_CONT_DOWN UCB_IO_1
-+#define UCB1400_GPIO_CONT_INC UCB_IO_2
-+#define UCB1400_GPIO_CONT_ENA UCB_IO_3
-+#define UCB1400_GPIO_LCD_RESET UCB_IO_4
-+#define UCB1400_GPIO_IRDA_ENABLE UCB_IO_5
-+#define UCB1400_GPIO_BT_ENABLE UCB_IO_6
-+#define UCB1400_GPIO_TEST_P1 UCB_IO_7
-+#define UCB1400_GPIO_TEST_P2 UCB_IO_8
-+#define UCB1400_GPIO_TEST_P3 UCB_IO_9
-+
-+/*
-+ * IRQ for devices
-+ */
-+#define UCB1400_IRQ(x) (NR_IRQS + 1 + (x))
-+
-+#define IRQ_UCB1400_IO0 UCB1400_IRQ(0)
-+#define IRQ_UCB1400_IO1 UCB1400_IRQ(1)
-+#define IRQ_UCB1400_IO2 UCB1400_IRQ(2)
-+#define IRQ_UCB1400_IO3 UCB1400_IRQ(3)
-+#define IRQ_UCB1400_IO4 UCB1400_IRQ(4)
-+#define IRQ_UCB1400_IO5 UCB1400_IRQ(5)
-+#define IRQ_UCB1400_IO6 UCB1400_IRQ(6)
-+#define IRQ_UCB1400_IO7 UCB1400_IRQ(7)
-+#define IRQ_UCB1400_IO8 UCB1400_IRQ(8)
-+#define IRQ_UCB1400_IO9 UCB1400_IRQ(9)
-+
-+#define IRQ_UCB1400_CONT_CS IRQ_UCB1400_IO0
-+#define IRQ_UCB1400_CONT_DOWN IRQ_UCB1400_IO1
-+#define IRQ_UCB1400_CONT_INC IRQ_UCB1400_IO2
-+#define IRQ_UCB1400_CONT_ENA IRQ_UCB1400_IO3
-+#define IRQ_UCB1400_LCD_RESET IRQ_UCB1400_IO4
-+#define IRQ_UCB1400_IRDA_ENABLE IRQ_UCB1400_IO5
-+#define IRQ_UCB1400_BT_ENABLE IRQ_UCB1400_IO6
-+#define IRQ_UCB1400_TEST_P1 IRQ_UCB1400_IO7
-+#define IRQ_UCB1400_TEST_P2 IRQ_UCB1400_IO8
-+#define IRQ_UCB1400_TEST_P3 IRQ_UCB1400_IO9
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/cerf_ucb1400gpio.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,30 @@
-+/*
-+ * cerf_ucb1400gpio.h
-+ *
-+ * UCB1400 GPIO control stuff for the cerf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+/* -- lcd -- */
-+extern void cerf_ucb1400gpio_lcd_enable( void);
-+extern void cerf_ucb1400gpio_lcd_disable( void);
-+extern void cerf_ucb1400gpio_lcd_contrast_step( int direction);
-+
-+/* -- irda -- */
-+extern void cerf_ucb1400gpio_irda_enable( void);
-+extern void cerf_ucb1400gpio_irda_disable( void);
-+
-+/* -- bt -- */
-+extern void cerf_ucb1400gpio_bt_enable( void);
-+extern void cerf_ucb1400gpio_bt_disable( void);
-+
-+/* -- init -- */
-+extern int cerf_ucb1400gpio_init(void);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/csb226.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,99 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/csb226.h
-+ *
-+ * Author: Robert Schwebel (stolen from lubbock.h)
-+ * Created: Oct 30, 2002
-+ * Copyright: Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define CSB226_FPGA_PHYS PXA_CS2_PHYS
-+
-+#define CSB226_FPGA_VIRT (0xf0000000) /* phys 0x08000000 */
-+#define CSB226_ETH_BASE (0xf1000000) /* phys 0x0c000000 */
-+
-+#define CSB226_P2V(x) ((x) - CSB226_FPGA_PHYS + CSB226_FPGA_VIRT)
-+#define CSB226_V2P(x) ((x) - CSB226_FPGA_VIRT + CSB226_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CSB226_REG(x) (*((volatile unsigned long *)CSB226_P2V(x)))
-+#else
-+# define __CSB226_REG(x) CSB226_P2V(x)
-+#endif
-+
-+
-+/* register physical addresses */
-+#define _CSB226_MISC_WR (CSB226_FPGA_PHYS + 0x080)
-+#define _CSB226_MISC_RD (CSB226_FPGA_PHYS + 0x090)
-+#define _CSB226_IRQ_MASK_EN (CSB226_FPGA_PHYS + 0x0C0)
-+#define _CSB226_IRQ_SET_CLR (CSB226_FPGA_PHYS + 0x0D0)
-+#define _CSB226_GP (CSB226_FPGA_PHYS + 0x100)
-+
-+
-+
-+/* register virtual addresses */
-+
-+#define CSB226_MISC_WR __CSB226_REG(_CSB226_MISC_WR)
-+#define CSB226_MISC_RD __CSB226_REG(_CSB226_MISC_RD)
-+#define CSB226_IRQ_MASK_EN __CSB226_REG(_CSB226_IRQ_MASK_EN)
-+#define CSB226_IRQ_SET_CLR __CSB226_REG(_CSB226_IRQ_SET_CLR)
-+#define CSB226_GP __CSB226_REG(_CSB226_GP)
-+
-+
-+/* GPIOs */
-+
-+#define GPIO_CSB226_IRQ 0
-+#define IRQ_GPIO_CSB226_IRQ IRQ_GPIO0
-+
-+
-+/*
-+ * LED macros
-+ */
-+
-+// #define LEDS_BASE LUB_DISC_BLNK_LED
-+
-+// 8 discrete leds available for general use:
-+
-+/*
-+#define D28 0x1
-+#define D27 0x2
-+#define D26 0x4
-+#define D25 0x8
-+#define D24 0x10
-+#define D23 0x20
-+#define D22 0x40
-+#define D21 0x80
-+*/
-+
-+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
-+* be sure to not monkey with them here.
-+*/
-+
-+/*
-+#define HEARTBEAT_LED D28
-+#define SYS_BUSY_LED D27
-+#define HEXLEDS_BASE LUB_HEXLED
-+
-+#define HEARTBEAT_LED_ON (LEDS_BASE &= ~HEARTBEAT_LED)
-+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
-+#define SYS_BUSY_LED_OFF (LEDS_BASE |= SYS_BUSY_LED)
-+#define SYS_BUSY_LED_ON (LEDS_BASE &= ~SYS_BUSY_LED)
-+
-+// use x = D26-D21 for these, please...
-+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
-+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
-+*/
-+
-+#ifndef __ASSEMBLY__
-+
-+//extern int hexled_val = 0;
-+
-+#endif
-+
-+/*
-+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
-+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
-+*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/dma.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,49 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/dma.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __ASM_ARCH_DMA_H
-+#define __ASM_ARCH_DMA_H
-+
-+#define MAX_DMA_ADDRESS 0xffffffff
-+
-+/* No DMA as the rest of the world see it */
-+#define MAX_DMA_CHANNELS 0
-+
-+/*
-+ * Descriptor structure for PXA's DMA engine
-+ * Note: this structure must always be aligned to a 16-byte boundary.
-+ */
-+
-+typedef struct {
-+ volatile u32 ddadr; /* Points to the next descriptor + flags */
-+ volatile u32 dsadr; /* DSADR value for the current transfer */
-+ volatile u32 dtadr; /* DTADR value for the current transfer */
-+ volatile u32 dcmd; /* DCMD value for the current transfer */
-+} pxa_dma_desc;
-+
-+/*
-+ * DMA registration
-+ */
-+
-+typedef enum {
-+ DMA_PRIO_HIGH = 0,
-+ DMA_PRIO_MEDIUM = 4,
-+ DMA_PRIO_LOW = 8
-+} pxa_dma_prio;
-+
-+int pxa_request_dma (char *name,
-+ pxa_dma_prio prio,
-+ void (*irq_handler)(int, void *, struct pt_regs *),
-+ void *data);
-+
-+void pxa_free_dma (int dma_ch);
-+
-+#endif /* _ASM_ARCH_DMA_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/hardware.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/hardware.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef __ASM_ARCH_HARDWARE_H
-+#define __ASM_ARCH_HARDWARE_H
-+
-+#include <linux/config.h>
-+#include <asm/mach-types.h>
-+
-+
-+/*
-+ * These are statically mapped PCMCIA IO space for designs using it as a
-+ * generic IO bus, typically with ISA parts, hardwired IDE interfaces, etc.
-+ * The actual PCMCIA code is mapping required IO region at run time.
-+ */
-+#define PCMCIA_IO_0_BASE 0xf6000000
-+#define PCMCIA_IO_1_BASE 0xf7000000
-+
-+
-+/*
-+ * XIP kernel text mapping.
-+ * Note: the exact virtual address is also specified in arch/arm/Makefile.
-+ */
-+#ifdef CONFIG_XIP_KERNEL
-+#define KERNEL_XIP_BASE_PHYS (CONFIG_XIP_PHYS_ADDR & 0xffe00000)
-+#define KERNEL_XIP_BASE_VIRT 0xe8000000
-+#endif
-+
-+
-+/*
-+ * We requires absolute addresses.
-+ */
-+#define PCIO_BASE 0
-+
-+/*
-+ * Workarounds for at least 2 errata so far require this.
-+ * The mapping is set in mach-pxa/generic.c.
-+ */
-+#define UNCACHED_PHYS_0 0xff000000
-+#define UNCACHED_ADDR UNCACHED_PHYS_0
-+
-+/*
-+ * Intel PXA internal I/O mappings:
-+ *
-+ * 0x40000000 - 0x41ffffff <--> 0xf8000000 - 0xf9ffffff
-+ * 0x44000000 - 0x45ffffff <--> 0xfa000000 - 0xfbffffff
-+ * 0x48000000 - 0x49ffffff <--> 0xfc000000 - 0xfdffffff
-+ */
-+
-+#define io_p2v(x) ( ((x) | 0xbe000000) ^ (~((x) >> 1) & 0x06000000) )
-+#define io_v2p( x ) ( ((x) & 0x41ffffff) ^ ( ((x) & 0x06000000) << 1) )
-+
-+#ifndef __ASSEMBLY__
-+
-+#if 0
-+# define __REG(x) (*((volatile u32 *)io_p2v(x)))
-+#else
-+/*
-+ * This __REG() version gives the same results as the one above, except
-+ * that we are fooling gcc somehow so it generates far better and smaller
-+ * assembly code for access to contigous registers. It's a shame that gcc
-+ * doesn't guess this by itself.
-+ */
-+#include <asm/types.h>
-+typedef struct { volatile u32 offset[4096]; } __regbase;
-+# define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-+# define __REG(x) __REGP(io_p2v(x))
-+#endif
-+
-+/* Let's kick gcc's ass again... */
-+# define __REG2(x,y) \
-+ ( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-+ : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
-+
-+# define __PREG(x) (io_v2p((u32)&(x)))
-+
-+#else
-+
-+# define __REG(x) io_p2v(x)
-+# define __PREG(x) io_v2p(x)
-+
-+#endif
-+
-+#include "pxa-regs.h"
-+
-+#ifndef __ASSEMBLY__
-+
-+/*
-+ * GPIO edge detection for IRQs:
-+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
-+ * This must be called *before* the corresponding IRQ is registered.
-+ * Use this instead of directly setting GRER/GFER.
-+ */
-+#define GPIO_FALLING_EDGE 1
-+#define GPIO_RISING_EDGE 2
-+#define GPIO_BOTH_EDGES 3
-+extern void set_GPIO_IRQ_edge( int gpio_nr, int edge_mask );
-+
-+/*
-+ * Handy routine to set GPIO alternate functions
-+ */
-+extern void set_GPIO_mode( int gpio_mode );
-+
-+/*
-+ * return current lclk frequency in units of 10kHz
-+ */
-+extern unsigned int get_lclk_frequency_10khz(void);
-+
-+/*
-+ * return current clk frequency in units of 1kHz
-+ */
-+extern unsigned int get_clk_frequency_khz( int info);
-+
-+#endif
-+
-+
-+/*
-+ * Implementation specifics
-+ */
-+
-+//#ifdef CONFIG_ARCH_LUBBOCK
-+#include "lubbock.h"
-+//#endif
-+
-+//#ifdef CONFIG_ARCH_PXA_IDP
-+#include "idp.h"
-+//#endif
-+
-+//#ifdef CONFIG_ARCH_PXA_CERF
-+#include "cerf.h"
-+//#endif
-+
-+#endif /* _ASM_ARCH_HARDWARE_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/ide.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,59 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/ide.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ * Originally based upon linux/include/asm-arm/arch-sa1100/ide.h
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+
-+
-+/*
-+ * Set up a hw structure for a specified data port, control port and IRQ.
-+ * This should follow whatever the default interface uses.
-+ */
-+static __inline__ void
-+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
-+{
-+ ide_ioreg_t reg;
-+
-+ memset(hw, 0, sizeof(*hw));
-+
-+ reg = (ide_ioreg_t)data_port;
-+
-+ hw->io_ports[IDE_DATA_OFFSET] = reg + 0;
-+ hw->io_ports[IDE_ERROR_OFFSET] = reg + 1;
-+ hw->io_ports[IDE_NSECTOR_OFFSET] = reg + 2;
-+ hw->io_ports[IDE_SECTOR_OFFSET] = reg + 3;
-+ hw->io_ports[IDE_LCYL_OFFSET] = reg + 4;
-+ hw->io_ports[IDE_HCYL_OFFSET] = reg + 5;
-+ hw->io_ports[IDE_SELECT_OFFSET] = reg + 6;
-+ hw->io_ports[IDE_STATUS_OFFSET] = reg + 7;
-+
-+ hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-+
-+ if (irq)
-+ *irq = 0;
-+}
-+
-+
-+/*
-+ * Register the standard ports for this architecture with the IDE driver.
-+ */
-+static __inline__ void
-+ide_init_default_hwifs(void)
-+{
-+ /* Nothing to declare... */
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/idp.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,468 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/idp.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
-+ *
-+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
-+ * Initial code
-+ *
-+ */
-+
-+
-+/*
-+ * Note: this file must be safe to include in assembly files
-+ */
-+
-+/* comment out following if you have a rev01 board */
-+#define PXA_IDP_REV02 1
-+//#undef PXA_IDP_REV02
-+
-+#ifdef PXA_IDP_REV02
-+
-+//Use this as well for 0017-x004 and greater pcb's:
-+#define PXA_IDP_REV04 1
-+
-+#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
-+#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define IDP_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define IDP_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define IDP_ETH_PHYS (PXA_CS5_PHYS + 0x03400000)
-+#define IDP_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define IDP_CPLD_PHYS (PXA_CS5_PHYS + 0x03C00000)
-+
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define IDP_IDE_BASE (0xf0000000)
-+#define IDP_IDE_SIZE (1*1024*1024)
-+
-+#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-+#define IDP_ETH_SIZE (1*1024*1024)
-+#define ETH_BASE IDP_ETH_BASE //smc9194 driver compatibility issue
-+
-+#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
-+#define IDP_COREVOLT_SIZE (1*1024*1024)
-+
-+#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-+#define IDP_CPLD_SIZE (1*1024*1024)
-+
-+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-+#error Your custom IO space is getting a bit large !!
-+#endif
-+
-+#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define _IDP_CPLD_REV (IDP_CPLD_PHYS + 0x00)
-+#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
-+#define _IDP_CPLD_LED_CONTROL (IDP_CPLD_PHYS + 0x08)
-+#define _IDP_CPLD_KB_COL_HIGH (IDP_CPLD_PHYS + 0x0C)
-+#define _IDP_CPLD_KB_COL_LOW (IDP_CPLD_PHYS + 0x10)
-+#define _IDP_CPLD_PCCARD_EN (IDP_CPLD_PHYS + 0x14)
-+#define _IDP_CPLD_GPIOH_DIR (IDP_CPLD_PHYS + 0x18)
-+#define _IDP_CPLD_GPIOH_VALUE (IDP_CPLD_PHYS + 0x1C)
-+#define _IDP_CPLD_GPIOL_DIR (IDP_CPLD_PHYS + 0x20)
-+#define _IDP_CPLD_GPIOL_VALUE (IDP_CPLD_PHYS + 0x24)
-+#define _IDP_CPLD_PCCARD_PWR (IDP_CPLD_PHYS + 0x28)
-+#define _IDP_CPLD_MISC_CTRL (IDP_CPLD_PHYS + 0x2C)
-+#define _IDP_CPLD_LCD (IDP_CPLD_PHYS + 0x30)
-+#define _IDP_CPLD_FLASH_WE (IDP_CPLD_PHYS + 0x34)
-+
-+#define _IDP_CPLD_KB_ROW (IDP_CPLD_PHYS + 0x50)
-+#define _IDP_CPLD_PCCARD0_STATUS (IDP_CPLD_PHYS + 0x54)
-+#define _IDP_CPLD_PCCARD1_STATUS (IDP_CPLD_PHYS + 0x58)
-+#define _IDP_CPLD_MISC_STATUS (IDP_CPLD_PHYS + 0x5C)
-+
-+/* FPGA register virtual addresses */
-+
-+#define IDP_CPLD_REV __CPLD_REG(_IDP_CPLD_REV)
-+#define IDP_CPLD_PERIPH_PWR __CPLD_REG(_IDP_CPLD_PERIPH_PWR)
-+#define IDP_CPLD_LED_CONTROL __CPLD_REG(_IDP_CPLD_LED_CONTROL)
-+#define IDP_CPLD_KB_COL_HIGH __CPLD_REG(_IDP_CPLD_KB_COL_HIGH)
-+#define IDP_CPLD_KB_COL_LOW __CPLD_REG(_IDP_CPLD_KB_COL_LOW)
-+#define IDP_CPLD_PCCARD_EN __CPLD_REG(_IDP_CPLD_PCCARD_EN)
-+#define IDP_CPLD_GPIOH_DIR __CPLD_REG(_IDP_CPLD_GPIOH_DIR)
-+#define IDP_CPLD_GPIOH_VALUE __CPLD_REG(_IDP_CPLD_GPIOH_VALUE)
-+#define IDP_CPLD_GPIOL_DIR __CPLD_REG(_IDP_CPLD_GPIOL_DIR)
-+#define IDP_CPLD_GPIOL_VALUE __CPLD_REG(_IDP_CPLD_GPIOL_VALUE)
-+#define IDP_CPLD_PCCARD_PWR __CPLD_REG(_IDP_CPLD_PCCARD_PWR)
-+#define IDP_CPLD_MISC_CTRL __CPLD_REG(_IDP_CPLD_MISC_CTRL)
-+#define IDP_CPLD_LCD __CPLD_REG(_IDP_CPLD_LCD)
-+#define IDP_CPLD_FLASH_WE __CPLD_REG(_IDP_CPLD_FLASH_WE)
-+
-+#define IDP_CPLD_KB_ROW __CPLD_REG(_IDP_CPLD_KB_ROW)
-+#define IDP_CPLD_PCCARD0_STATUS __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)
-+#define IDP_CPLD_PCCARD1_STATUS __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)
-+#define IDP_CPLD_MISC_STATUS __CPLD_REG(_IDP_CPLD_MISC_STATUS)
-+
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+// IDP_CPLD_PCCARD_PWR
-+#define PCC0_PWR0 (1 << 0)
-+#define PCC0_PWR1 (1 << 1)
-+#define PCC0_PWR2 (1 << 2)
-+#define PCC0_PWR3 (1 << 3)
-+#define PCC1_PWR0 (1 << 4)
-+#define PCC1_PWR1 (1 << 5)
-+#define PCC1_PWR2 (1 << 6)
-+#define PCC1_PWR3 (1 << 7)
-+
-+// IDP_CPLD_PCCARD_EN
-+#define PCC0_RESET (1 << 6)
-+#define PCC1_RESET (1 << 7)
-+#define PCC0_ENABLE (1 << 0)
-+#define PCC1_ENABLE (1 << 1)
-+
-+// IDP_CPLD_PCCARDx_STATUS
-+#define _PCC_WRPROT (1 << 7) // 7-4 read as low true
-+#define _PCC_RESET (1 << 6)
-+#define _PCC_IRQ (1 << 5)
-+#define _PCC_INPACK (1 << 4)
-+#define PCC_BVD2 (1 << 3)
-+#define PCC_BVD1 (1 << 2)
-+#define PCC_VS2 (1 << 1)
-+#define PCC_VS1 (1 << 0)
-+
-+#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x)))
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON() (IDP_CPLD_LCD |= (1<<1))
-+#define FB_BACKLIGHT_OFF() (IDP_CPLD_LCD &= ~(1<<1))
-+
-+#define FB_PWR_ON() (IDP_CPLD_LCD |= (1<< 0))
-+#define FB_PWR_OFF() (IDP_CPLD_LCD &= ~(1<<0))
-+
-+#define FB_VLCD_ON() (IDP_CPLD_LCD |= (1<<2))
-+#define FB_VLCD_OFF() (IDP_CPLD_LCD &= ~(1<<2))
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#ifdef PXA_IDP_REV04
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(5)
-+#define IDE_IRQ IRQ_GPIO(21)
-+#else
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-+#define IDE_IRQ IRQ_GPIO(5)
-+#endif
-+
-+#define TOUCH_PANEL_IRQ_EDGE GPIO_FALLING_EDGE
-+
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define ETHERNET_IRQ IRQ_GPIO(4)
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define PCMCIA_S0_CD_VALID IRQ_GPIO(7)
-+#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S1_CD_VALID IRQ_GPIO(8)
-+#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S0_RDYINT IRQ_GPIO(19)
-+#define PCMCIA_S1_RDYINT IRQ_GPIO(22)
-+
-+/*
-+ * Macros for LED Driver
-+ */
-+
-+/* leds 0 = ON */
-+#define IDP_HB_LED (1<<5)
-+#define IDP_BUSY_LED (1<<6)
-+
-+#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-+
-+#define IDP_WRITE_LEDS(value) (IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() ((IDP_CPLD_FLASH_WE) &= ~(0x1))
-+#define FLASH_WRITE_PROTECT_ENABLE() ((IDP_CPLD_FLASH_WE) |= (0x1))
-+
-+/*
-+ * macros for matrix keyboard driver
-+ */
-+
-+#define KEYBD_MATRIX_NUMBER_INPUTS 7
-+#define KEYBD_MATRIX_NUMBER_OUTPUTS 14
-+
-+#define KEYBD_MATRIX_INVERT_OUTPUT_LOGIC FALSE
-+#define KEYBD_MATRIX_INVERT_INPUT_LOGIC FALSE
-+
-+#define KEYBD_MATRIX_SETTLING_TIME_US 100
-+#define KEYBD_MATRIX_KEYSTATE_DEBOUNCE_CONSTANT 2
-+
-+#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \
-+{\
-+ IDP_CPLD_KB_COL_LOW = outputs;\
-+ IDP_CPLD_KB_COL_HIGH = outputs >> 7;\
-+}
-+
-+#define KEYBD_MATRIX_GET_INPUTS(inputs) \
-+{\
-+ inputs = (IDP_CPLD_KB_ROW & 0x7f);\
-+}
-+
-+//------------------------------------------------------------------------------
-+
-+#else // must be rev 01
-+
-+/* -----------------------------------------------------------------------------
-+ * following is for rev01 boards only
-+ */
-+
-+#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
-+#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define IDP_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define IDP_CTRL_PORT_PHYS (PXA_CS5_PHYS + 0x02C00000)
-+#define IDP_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define IDP_ETH_PHYS (PXA_CS5_PHYS + 0x03400000)
-+#define IDP_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define IDP_CPLD_PHYS (PXA_CS5_PHYS + 0x03C00000)
-+
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define IDP_CTRL_PORT_BASE (0xf0000000)
-+#define IDP_CTRL_PORT_SIZE (1*1024*1024)
-+
-+#define IDP_IDE_BASE (IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
-+#define IDP_IDE_SIZE (1*1024*1024)
-+
-+#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-+#define IDP_ETH_SIZE (1*1024*1024)
-+
-+#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
-+#define IDP_COREVOLT_SIZE (1*1024*1024)
-+
-+#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-+#define IDP_CPLD_SIZE (1*1024*1024)
-+
-+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-+#error Your custom IO space is getting a bit large !!
-+#endif
-+
-+#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define _IDP_CPLD_LED_CONTROL (IDP_CPLD_PHYS + 0x00)
-+#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
-+#define _IDP_CPLD_CIR (IDP_CPLD_PHYS + 0x08)
-+#define _IDP_CPLD_KB_COL_HIGH (IDP_CPLD_PHYS + 0x0C)
-+#define _IDP_CPLD_KB_COL_LOW (IDP_CPLD_PHYS + 0x10)
-+#define _IDP_CPLD_PCCARD_EN (IDP_CPLD_PHYS + 0x14)
-+#define _IDP_CPLD_GPIOH_DIR (IDP_CPLD_PHYS + 0x18)
-+#define _IDP_CPLD_GPIOH_VALUE (IDP_CPLD_PHYS + 0x1C)
-+#define _IDP_CPLD_GPIOL_DIR (IDP_CPLD_PHYS + 0x20)
-+#define _IDP_CPLD_GPIOL_VALUE (IDP_CPLD_PHYS + 0x24)
-+#define _IDP_CPLD_MISC (IDP_CPLD_PHYS + 0x28)
-+#define _IDP_CPLD_PCCARD0_STATUS (IDP_CPLD_PHYS + 0x2C)
-+#define _IDP_CPLD_PCCARD1_STATUS (IDP_CPLD_PHYS + 0x30)
-+
-+/* FPGA register virtual addresses */
-+#define IDP_CPLD_LED_CONTROL __CPLD_REG(_IDP_CPLD_LED_CONTROL) /* write only */
-+#define IDP_CPLD_PERIPH_PWR __CPLD_REG(_IDP_CPLD_PERIPH_PWR) /* write only */
-+#define IDP_CPLD_CIR __CPLD_REG(_IDP_CPLD_CIR) /* write only */
-+#define IDP_CPLD_KB_COL_HIGH __CPLD_REG(_IDP_CPLD_KB_COL_HIGH) /* write only */
-+#define IDP_CPLD_KB_COL_LOW __CPLD_REG(_IDP_CPLD_KB_COL_LOW) /* write only */
-+#define IDP_CPLD_PCCARD_EN __CPLD_REG(_IDP_CPLD_PCCARD_EN) /* write only */
-+#define IDP_CPLD_GPIOH_DIR __CPLD_REG(_IDP_CPLD_GPIOH_DIR) /* write only */
-+#define IDP_CPLD_GPIOH_VALUE __CPLD_REG(_IDP_CPLD_GPIOH_VALUE) /* write only */
-+#define IDP_CPLD_GPIOL_DIR __CPLD_REG(_IDP_CPLD_GPIOL_DIR) /* write only */
-+#define IDP_CPLD_GPIOL_VALUE __CPLD_REG(_IDP_CPLD_GPIOL_VALUE) /* write only */
-+#define IDP_CPLD_MISC __CPLD_REG(_IDP_CPLD_MISC) /* read only */
-+#define IDP_CPLD_PCCARD0_STATUS __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS) /* read only */
-+#define IDP_CPLD_PCCARD1_STATUS __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS) /* read only */
-+
-+
-+#ifndef __ASSEMBLY__
-+
-+/* shadow registers for write only registers */
-+extern unsigned int idp_cpld_led_control_shadow;
-+extern unsigned int idp_cpld_periph_pwr_shadow;
-+extern unsigned int idp_cpld_cir_shadow;
-+extern unsigned int idp_cpld_kb_col_high_shadow;
-+extern unsigned int idp_cpld_kb_col_low_shadow;
-+extern unsigned int idp_cpld_pccard_en_shadow;
-+extern unsigned int idp_cpld_gpioh_dir_shadow;
-+extern unsigned int idp_cpld_gpioh_value_shadow;
-+extern unsigned int idp_cpld_gpiol_dir_shadow;
-+extern unsigned int idp_cpld_gpiol_value_shadow;
-+
-+extern unsigned int idp_control_port_shadow;
-+
-+/*
-+ * macros to write to write only register
-+ *
-+ * none of these macros are protected from
-+ * multiple drivers using them in interrupt context.
-+ */
-+
-+#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
-+{\
-+ idp_cpld_led_control_shadow = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
-+ IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-+}
-+#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
-+{\
-+ idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
-+ IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
-+}
-+#define WRITE_IDP_CPLD_CIR(value, mask) \
-+{\
-+ idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
-+ IDP_CPLD_CIR = idp_cpld_cir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
-+{\
-+ idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
-+ IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
-+}
-+#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
-+{\
-+ idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
-+ IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
-+}
-+#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
-+{\
-+ idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
-+ IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
-+{\
-+ idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
-+ IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
-+{\
-+ idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
-+ IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
-+{\
-+ idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
-+ IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
-+{\
-+ idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
-+ IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
-+}
-+
-+#define WRITE_IDP_CONTROL_PORT(value, mask) \
-+{\
-+ idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
-+ (*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
-+}
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-+#define TOUCH_PANEL_IRQ_EGDE GPIO_FALLING_EDGE
-+
-+#define ETHERNET_IRQ IRQ_GPIO(4)
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+
-+
-+/* control port */
-+#define IDP_CONTROL_PORT_PCSLOT0_0 (1 << 0)
-+#define IDP_CONTROL_PORT_PCSLOT0_1 (1 << 1)
-+#define IDP_CONTROL_PORT_PCSLOT0_2 (1 << 2)
-+#define IDP_CONTROL_PORT_PCSLOT0_3 (1 << 3)
-+#define IDP_CONTROL_PORT_PCSLOT1_1 (1 << 4)
-+#define IDP_CONTROL_PORT_PCSLOT1_2 (1 << 5)
-+#define IDP_CONTROL_PORT_PCSLOT1_3 (1 << 6)
-+#define IDP_CONTROL_PORT_PCSLOT1_4 (1 << 7)
-+#define IDP_CONTROL_PORT_SERIAL1_EN (1 << 9)
-+#define IDP_CONTROL_PORT_SERIAL2_EN (1 << 10)
-+#define IDP_CONTROL_PORT_SERIAL3_EN (1 << 11)
-+#define IDP_CONTROL_PORT_IRDA_FIR (1 << 12)
-+#define IDP_CONTROL_PORT_IRDA_M0 (1 << 13)
-+#define IDP_CONTROL_PORT_IRDA_M1 (1 << 14)
-+#define IDP_CONTROL_PORT_I2S_PWR (1 << 15)
-+#define IDP_CONTROL_PORT_FLASH_WP (1 << 19)
-+#define IDP_CONTROL_PORT_MILL_EN (1 << 20)
-+#define IDP_CONTROL_PORT_LCD_PWR (1 << 21)
-+#define IDP_CONTROL_PORT_LCD_BKLEN (1 << 22)
-+#define IDP_CONTROL_PORT_LCD_ENAVLCD (1 << 23)
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
-+#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
-+
-+#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
-+#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
-+
-+#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
-+#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
-+
-+#endif
-+
-+
-+/*
-+ * Macros for LED Driver
-+ */
-+
-+/* leds 0 = ON */
-+#define IDP_HB_LED 0x1
-+#define IDP_BUSY_LED 0x2
-+
-+#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-+
-+#define IDP_WRITE_LEDS(value) WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
-+#define FLASH_WRITE_PROTECT_ENABLE() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/innokom.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,47 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/innokom.h
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+/*
-+ * GPIOs
-+ */
-+#define GPIO_INNOKOM_RESET 3
-+#define GPIO_INNOKOM_SW_UPDATE 11
-+#define GPIO_INNOKOM_ETH 59
-+
-+/*
-+ * ethernet chip (SMSC91C111)
-+ */
-+#define INNOKOM_ETH_PHYS PXA_CS5_PHYS
-+#define INNOKOM_ETH_BASE (0xf0000000) /* phys 0x14000000 */
-+#define INNOKOM_ETH_SIZE (1*1024*1024)
-+#define INNOKOM_ETH_IRQ IRQ_GPIO(GPIO_INNOKOM_ETH)
-+#define INNOKOM_ETH_IRQ_EDGE GPIO_RISING_EDGE
-+
-+/*
-+ * virtual to physical conversion macros
-+ */
-+#define INNOKOM_P2V(x) ((x) - INNOKOM_FPGA_PHYS + INNOKOM_FPGA_VIRT)
-+#define INNOKOM_V2P(x) ((x) - INNOKOM_FPGA_VIRT + INNOKOM_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __INNOKOM_REG(x) (*((volatile unsigned long *)INNOKOM_P2V(x)))
-+#else
-+# define __INNOKOM_REG(x) INNOKOM_P2V(x)
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/io.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,34 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/io.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __ASM_ARM_ARCH_IO_H
-+#define __ASM_ARM_ARCH_IO_H
-+
-+#define IO_SPACE_LIMIT 0xffffffff
-+
-+/*
-+ * We don't actually have real ISA nor PCI buses, but there is so many
-+ * drivers out there that might just work if we fake them...
-+ */
-+#define __io(a) (a)
-+#define __mem_pci(a) ((unsigned long)(a))
-+#define __mem_isa(a) ((unsigned long)(a))
-+
-+/*
-+ * Generic virtual read/write
-+ */
-+#define __arch_getw(a) (*(volatile unsigned short *)(a))
-+#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-+
-+#define iomem_valid_addr(iomem,sz) (1)
-+#define iomem_to_phys(iomem) (iomem)
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/irq.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,19 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/irq.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define fixup_irq(x) (x)
-+
-+/*
-+ * This prototype is required for cascading of multiplexed interrupts.
-+ * Since it doesn't exist elsewhere, we'll put it here for now.
-+ */
-+extern void do_IRQ(int irq, struct pt_regs *regs);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/irqs.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,137 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/irqs.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define PXA_IRQ_SKIP 7 /* The first 7 IRQs are not yet used */
-+#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
-+
-+#define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error */
-+#define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
-+#define IRQ_GPIO1 PXA_IRQ(9) /* GPIO1 Edge Detect */
-+#define IRQ_GPIO_2_80 PXA_IRQ(10) /* GPIO[2-80] Edge Detect */
-+#define IRQ_USB PXA_IRQ(11) /* USB Service */
-+#define IRQ_PMU PXA_IRQ(12) /* Performance Monitoring Unit */
-+#define IRQ_I2S PXA_IRQ(13) /* I2S Interrupt */
-+#define IRQ_AC97 PXA_IRQ(14) /* AC97 Interrupt */
-+#define IRQ_ASSP PXA_IRQ(15) /* Audio SSP Service Request */
-+#define IRQ_NSSP PXA_IRQ(16) /* Network SSP Service Request */
-+#define IRQ_LCD PXA_IRQ(17) /* LCD Controller Service Request */
-+#define IRQ_I2C PXA_IRQ(18) /* I2C Service Request */
-+#define IRQ_ICP PXA_IRQ(19) /* ICP Transmit/Receive/Error */
-+#define IRQ_STUART PXA_IRQ(20) /* STUART Transmit/Receive/Error */
-+#define IRQ_BTUART PXA_IRQ(21) /* BTUART Transmit/Receive/Error */
-+#define IRQ_FFUART PXA_IRQ(22) /* FFUART Transmit/Receive/Error*/
-+#define IRQ_MMC PXA_IRQ(23) /* MMC Status/Error Detection */
-+#define IRQ_SSP PXA_IRQ(24) /* SSP Service Request */
-+#define IRQ_DMA PXA_IRQ(25) /* DMA Channel Service Request */
-+#define IRQ_OST0 PXA_IRQ(26) /* OS Timer match 0 */
-+#define IRQ_OST1 PXA_IRQ(27) /* OS Timer match 1 */
-+#define IRQ_OST2 PXA_IRQ(28) /* OS Timer match 2 */
-+#define IRQ_OST3 PXA_IRQ(29) /* OS Timer match 3 */
-+#define IRQ_RTC1Hz PXA_IRQ(30) /* RTC HZ Clock Tick */
-+#define IRQ_RTCAlrm PXA_IRQ(31) /* RTC Alarm */
-+
-+#define GPIO_2_80_TO_IRQ(x) \
-+ PXA_IRQ((x) - 2 + 32)
-+#define IRQ_GPIO(x) (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
-+
-+#define IRQ_TO_GPIO_2_80(i) \
-+ ((i) - PXA_IRQ(32) + 2)
-+#define IRQ_TO_GPIO(i) ((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
-+
-+#define NR_IRQS (IRQ_GPIO(80) + 1)
-+
-+#if defined(CONFIG_SA1111)
-+
-+#define IRQ_SA1111_START (IRQ_GPIO(80) + 1)
-+#define SA1111_IRQ(x) (IRQ_SA1111_START + (x))
-+
-+#define IRQ_GPAIN0 SA1111_IRQ(0)
-+#define IRQ_GPAIN1 SA1111_IRQ(1)
-+#define IRQ_GPAIN2 SA1111_IRQ(2)
-+#define IRQ_GPAIN3 SA1111_IRQ(3)
-+#define IRQ_GPBIN0 SA1111_IRQ(4)
-+#define IRQ_GPBIN1 SA1111_IRQ(5)
-+#define IRQ_GPBIN2 SA1111_IRQ(6)
-+#define IRQ_GPBIN3 SA1111_IRQ(7)
-+#define IRQ_GPBIN4 SA1111_IRQ(8)
-+#define IRQ_GPBIN5 SA1111_IRQ(9)
-+#define IRQ_GPCIN0 SA1111_IRQ(10)
-+#define IRQ_GPCIN1 SA1111_IRQ(11)
-+#define IRQ_GPCIN2 SA1111_IRQ(12)
-+#define IRQ_GPCIN3 SA1111_IRQ(13)
-+#define IRQ_GPCIN4 SA1111_IRQ(14)
-+#define IRQ_GPCIN5 SA1111_IRQ(15)
-+#define IRQ_GPCIN6 SA1111_IRQ(16)
-+#define IRQ_GPCIN7 SA1111_IRQ(17)
-+#define IRQ_MSTXINT SA1111_IRQ(18)
-+#define IRQ_MSRXINT SA1111_IRQ(19)
-+#define IRQ_MSSTOPERRINT SA1111_IRQ(20)
-+#define IRQ_TPTXINT SA1111_IRQ(21)
-+#define IRQ_TPRXINT SA1111_IRQ(22)
-+#define IRQ_TPSTOPERRINT SA1111_IRQ(23)
-+#define SSPXMTINT SA1111_IRQ(24)
-+#define SSPRCVINT SA1111_IRQ(25)
-+#define SSPROR SA1111_IRQ(26)
-+#define AUDXMTDMADONEA SA1111_IRQ(32)
-+#define AUDRCVDMADONEA SA1111_IRQ(33)
-+#define AUDXMTDMADONEB SA1111_IRQ(34)
-+#define AUDRCVDMADONEB SA1111_IRQ(35)
-+#define AUDTFSR SA1111_IRQ(36)
-+#define AUDRFSR SA1111_IRQ(37)
-+#define AUDTUR SA1111_IRQ(38)
-+#define AUDROR SA1111_IRQ(39)
-+#define AUDDTS SA1111_IRQ(40)
-+#define AUDRDD SA1111_IRQ(41)
-+#define AUDSTO SA1111_IRQ(42)
-+#define USBPWR SA1111_IRQ(43)
-+#define NIRQHCIM SA1111_IRQ(44)
-+#define HCIBUFFACC SA1111_IRQ(45)
-+#define HCIRMTWKP SA1111_IRQ(46)
-+#define NHCIMFCIR SA1111_IRQ(47)
-+#define PORT_RESUME SA1111_IRQ(48)
-+#define S0_READY_NINT SA1111_IRQ(49)
-+#define S1_READY_NINT SA1111_IRQ(50)
-+#define S0_CD_VALID SA1111_IRQ(51)
-+#define S1_CD_VALID SA1111_IRQ(52)
-+#define S0_BVD1_STSCHG SA1111_IRQ(53)
-+#define S1_BVD1_STSCHG SA1111_IRQ(54)
-+
-+#define SA1111_IRQ_MAX SA1111_IRQ(54)
-+
-+#undef NR_IRQS
-+#define NR_IRQS (SA1111_IRQ_MAX + 1)
-+
-+#endif // defined(CONFIG_SA1111)
-+
-+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP)
-+#if CONFIG_SA1111
-+#define LUBBOCK_IRQ(x) (SA1111_IRQ_MAX + 1 + (x))
-+#else
-+#define LUBBOCK_IRQ(x) (IRQ_GPIO(80) + 1 + (x))
-+#endif
-+
-+#define LUBBOCK_SD_IRQ LUBBOCK_IRQ(0)
-+#define LUBBOCK_SA1111_IRQ LUBBOCK_IRQ(1)
-+#define LUBBOCK_USB_IRQ LUBBOCK_IRQ(2)
-+#define LUBBOCK_ETH_IRQ LUBBOCK_IRQ(3)
-+#define LUBBOCK_UCB1400_IRQ LUBBOCK_IRQ(4)
-+#define LUBBOCK_BB_IRQ LUBBOCK_IRQ(5)
-+#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
-+#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
-+
-+#undef NR_IRQS
-+#define NR_IRQS (LUBBOCK_LAST_IRQ + 1)
-+
-+#endif // CONFIG_ARCH_LUBBOCK
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/keyboard.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,29 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/keyboard.h
-+ *
-+ * This file contains the architecture specific keyboard definitions
-+ */
-+
-+#ifndef _PXA_KEYBOARD_H
-+#define _PXA_KEYBOARD_H
-+
-+#include <linux/config.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+
-+extern struct kbd_ops_struct *kbd_ops;
-+
-+#define kbd_disable_irq() do { } while(0);
-+#define kbd_enable_irq() do { } while(0);
-+
-+extern int sa1111_kbd_init_hw(void);
-+
-+static inline void kbd_init_hw(void)
-+{
-+ if (machine_is_lubbock())
-+ sa1111_kbd_init_hw();
-+}
-+
-+
-+#endif /* _PXA_KEYBOARD_H */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/lubbock.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,113 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/lubbock.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define LUBBOCK_FPGA_PHYS PXA_CS2_PHYS
-+#define LUBBOCK_FPGA_VIRT (0xf0000000) /* phys 0x08000000 */
-+#define LUBBOCK_ETH_PHYS PXA_CS3_PHYS
-+#define LUBBOCK_ETH_VIRT (0xf1000000)
-+#define LUBBOCK_SA1111_BASE (0xf4000000) /* phys 0x10000000 */
-+
-+#define LUB_P2V(x) ((x) - LUBBOCK_FPGA_PHYS + LUBBOCK_FPGA_VIRT)
-+#define LUB_V2P(x) ((x) - LUBBOCK_FPGA_VIRT + LUBBOCK_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __LUB_REG(x) (*((volatile unsigned long *)LUB_P2V(x)))
-+#else
-+# define __LUB_REG(x) LUB_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define WHOAMI 0 // card ID's (see programmers manual)
-+#define HEX_LED 0x10 // R/W access to 8 7 segment displays
-+#define DISC_BLNK_LED 0x40 // R/W [15-8] enables for hex leds, [7-0] discrete LEDs
-+#define CONF_SWITCHES 0x50 // RO [1] flash wrt prot, [0] 0= boot from rom, 1= flash
-+#define USER_SWITCHES 0x60 // RO [15-8] dip switches, [7-0] 2 hex encoding switches
-+#define MISC_WR 0x80 // R/W various system controls -see manual
-+#define MISC_RD 0x90 // RO various system status bits -see manual
-+//#define LUB_IRQ_MASK_EN 0xC0 // R/W 0= mask, 1= enable of TS, codec, ethernet, USB, SA1111, and card det. irq's
-+//#define LUB_IRQ_SET_CLR 0xD0 // R/W 1= set, 0 = clear IRQ's from TS, codec, etc...
-+//#define LUB_GP 0x100 // R/W [15-0] 16 bits of general purpose I/o for hacking
-+
-+
-+/* FPGA register physical addresses */
-+#define _LUB_WHOAMI (LUBBOCK_FPGA_PHYS + 0x000)
-+#define _LUB_HEXLED (LUBBOCK_FPGA_PHYS + 0x010)
-+#define _LUB_DISC_BLNK_LED (LUBBOCK_FPGA_PHYS + 0x040)
-+#define _LUB_CONF_SWITCHES (LUBBOCK_FPGA_PHYS + 0x050)
-+#define _LUB_USER_SWITCHES (LUBBOCK_FPGA_PHYS + 0x060)
-+#define _LUB_MISC_WR (LUBBOCK_FPGA_PHYS + 0x080)
-+#define _LUB_MISC_RD (LUBBOCK_FPGA_PHYS + 0x090)
-+#define _LUB_IRQ_MASK_EN (LUBBOCK_FPGA_PHYS + 0x0C0)
-+#define _LUB_IRQ_SET_CLR (LUBBOCK_FPGA_PHYS + 0x0D0)
-+#define _LUB_GP (LUBBOCK_FPGA_PHYS + 0x100)
-+
-+/* FPGA register virtual addresses */
-+#define LUB_WHOAMI __LUB_REG(_LUB_WHOAMI)
-+#define LUB_HEXLED __LUB_REG(_LUB_HEXLED)
-+#define LUB_DISC_BLNK_LED __LUB_REG(_LUB_DISC_BLNK_LED)
-+#define LUB_CONF_SWITCHES __LUB_REG(_LUB_CONF_SWITCHES)
-+#define LUB_USER_SWITCHES __LUB_REG(_LUB_USER_SWITCHES)
-+#define LUB_MISC_WR __LUB_REG(_LUB_MISC_WR)
-+#define LUB_MISC_RD __LUB_REG(_LUB_MISC_RD)
-+#define LUB_IRQ_MASK_EN __LUB_REG(_LUB_IRQ_MASK_EN)
-+#define LUB_IRQ_SET_CLR __LUB_REG(_LUB_IRQ_SET_CLR)
-+#define LUB_GP __LUB_REG(_LUB_GP)
-+
-+/* GPIOs */
-+
-+#define GPIO_LUBBOCK_IRQ 0
-+#define IRQ_GPIO_LUBBOCK_IRQ IRQ_GPIO0
-+
-+
-+/*
-+ * LED macros
-+ */
-+
-+#define LEDS_BASE LUB_DISC_BLNK_LED
-+
-+// 8 discrete leds available for general use:
-+
-+#define D28 0x1
-+#define D27 0x2
-+#define D26 0x4
-+#define D25 0x8
-+#define D24 0x10
-+#define D23 0x20
-+#define D22 0x40
-+#define D21 0x80
-+
-+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
-+* be sure to not monkey with them here.
-+*/
-+
-+#define HEARTBEAT_LED D28
-+#define SYS_BUSY_LED D27
-+#define HEXLEDS_BASE LUB_HEXLED
-+
-+#define HEARTBEAT_LED_ON (LEDS_BASE &= ~HEARTBEAT_LED)
-+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
-+#define SYS_BUSY_LED_OFF (LEDS_BASE |= SYS_BUSY_LED)
-+#define SYS_BUSY_LED_ON (LEDS_BASE &= ~SYS_BUSY_LED)
-+
-+// use x = D26-D21 for these, please...
-+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
-+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
-+
-+#ifndef __ASSEMBLY__
-+
-+//extern int hexled_val = 0;
-+
-+#endif
-+
-+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
-+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/memory.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,106 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/memory.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef __ASM_ARCH_MEMORY_H
-+#define __ASM_ARCH_MEMORY_H
-+
-+
-+/*
-+ * Task size: 3GB
-+ */
-+#define TASK_SIZE (0xc0000000UL)
-+#define TASK_SIZE_26 (0x04000000UL)
-+
-+/*
-+ * This decides where the kernel will search for a free chunk of vm
-+ * space during mmap's.
-+ */
-+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-+
-+/*
-+ * Page offset: 3GB
-+ */
-+#define PAGE_OFFSET (0xc0000000UL)
-+
-+/*
-+ * Physical DRAM offset.
-+ */
-+#define PHYS_OFFSET (0xa0000000UL)
-+
-+/*
-+ * physical vs virtual ram conversion
-+ */
-+#define __virt_to_phys__is_a_macro
-+#define __phys_to_virt__is_a_macro
-+#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
-+#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
-+
-+/*
-+ * Virtual view <-> DMA view memory address translations
-+ * virt_to_bus: Used to translate the virtual address to an
-+ * address suitable to be passed to set_dma_addr
-+ * bus_to_virt: Used to convert an address for DMA operations
-+ * to an address that the kernel can use.
-+ */
-+#define __virt_to_bus__is_a_macro
-+#define __bus_to_virt__is_a_macro
-+#define __virt_to_bus(x) __virt_to_phys(x)
-+#define __bus_to_virt(x) __phys_to_virt(x)
-+
-+#ifdef CONFIG_DISCONTIGMEM
-+/*
-+ * The nodes are matched with the physical SDRAM banks as follows:
-+ *
-+ * node 0: 0xa0000000-0xa3ffffff --> 0xc0000000-0xc3ffffff
-+ * node 1: 0xa4000000-0xa7ffffff --> 0xc4000000-0xc7ffffff
-+ * node 2: 0xa8000000-0xabffffff --> 0xc8000000-0xcbffffff
-+ * node 3: 0xac000000-0xafffffff --> 0xcc000000-0xcfffffff
-+ */
-+
-+#define NR_NODES 4
-+
-+/*
-+ * Given a kernel address, find the home node of the underlying memory.
-+ */
-+#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 26)
-+
-+/*
-+ * Given a page frame number, convert it to a node id.
-+ */
-+#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
-+
-+/*
-+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
-+ * and returns the mem_map of that node.
-+ */
-+#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-+
-+/*
-+ * Given a page frame number, find the owning node of the memory
-+ * and returns the mem_map of that node.
-+ */
-+#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
-+
-+/*
-+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
-+ * and returns the index corresponding to the appropriate page in the
-+ * node's mem_map.
-+ */
-+#define LOCAL_MAP_NR(addr) \
-+ (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
-+
-+#else
-+
-+#define PFN_TO_NID(addr) (0)
-+
-+#endif
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/param.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,3 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/param.h
-+ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/pcmcia.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,65 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/pcmcia.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ * Originally based upon linux/include/asm-arm/arch-sa1100/pcmcia.h
-+ *
-+ */
-+
-+#ifndef _ASM_ARCH_PCMCIA
-+#define _ASM_ARCH_PCMCIA
-+
-+
-+/* Ideally, we'd support up to MAX_SOCK sockets, but PXA250 only
-+ * provides support for a maximum of two.
-+ */
-+#define PXA_PCMCIA_MAX_SOCK (2)
-+
-+
-+#ifndef __ASSEMBLY__
-+
-+struct pcmcia_init {
-+ void (*handler)(int irq, void *dev, struct pt_regs *regs);
-+};
-+
-+struct pcmcia_state {
-+ unsigned detect: 1,
-+ ready: 1,
-+ bvd1: 1,
-+ bvd2: 1,
-+ wrprot: 1,
-+ vs_3v: 1,
-+ vs_Xv: 1;
-+};
-+
-+struct pcmcia_state_array {
-+ unsigned int size;
-+ struct pcmcia_state *state;
-+};
-+
-+struct pcmcia_irq_info {
-+ unsigned int sock;
-+ unsigned int irq;
-+};
-+
-+struct pcmcia_low_level {
-+ int (*init)(struct pcmcia_init *);
-+ int (*shutdown)(void);
-+ int (*socket_state)(struct pcmcia_state_array *);
-+ int (*get_irq_info)(struct pcmcia_irq_info *);
-+ int (*configure_socket)(unsigned int, socket_state_t *);
-+};
-+
-+extern struct pcmcia_low_level *pcmcia_low_level;
-+
-+#endif /* __ASSEMBLY__ */
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/pxa-regs.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,1327 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/pxa-regs.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef _PXA_REGS_H_
-+#define _PXA_REGS_H_
-+
-+#include "bitfield.h"
-+
-+
-+// FIXME hack so that SA-1111.h will work [cb]
-+
-+#ifndef __ASSEMBLY__
-+typedef unsigned short Word16 ;
-+typedef unsigned int Word32 ;
-+typedef Word32 Word ;
-+typedef Word Quad [4] ;
-+typedef void *Address ;
-+typedef void (*ExcpHndlr) (void) ;
-+#endif
-+
-+/*
-+ * PXA Chip selects
-+ */
-+
-+#define PXA_CS0_PHYS 0x00000000
-+#define PXA_CS1_PHYS 0x04000000
-+#define PXA_CS2_PHYS 0x08000000
-+#define PXA_CS3_PHYS 0x0C000000
-+#define PXA_CS4_PHYS 0x10000000
-+#define PXA_CS5_PHYS 0x14000000
-+
-+
-+/*
-+ * Personal Computer Memory Card International Association (PCMCIA) sockets
-+ */
-+
-+#define PCMCIAPrtSp 0x04000000 /* PCMCIA Partition Space [byte] */
-+#define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */
-+#define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */
-+#define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */
-+#define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */
-+
-+#define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */
-+#define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */
-+#define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */
-+#define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */
-+
-+#define PCMCIA1Sp PCMCIASp /* PCMCIA 1 Space [byte] */
-+#define PCMCIA1IOSp PCMCIAIOSp /* PCMCIA 1 I/O Space [byte] */
-+#define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */
-+#define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */
-+
-+#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \
-+ (0x20000000 + (Nb)*PCMCIASp)
-+#define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */
-+#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \
-+ (_PCMCIA (Nb) + 2*PCMCIAPrtSp)
-+#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \
-+ (_PCMCIA (Nb) + 3*PCMCIAPrtSp)
-+
-+#define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */
-+#define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */
-+#define _PCMCIA0Attr _PCMCIAAttr (0) /* PCMCIA 0 Attribute */
-+#define _PCMCIA0Mem _PCMCIAMem (0) /* PCMCIA 0 Memory */
-+
-+#define _PCMCIA1 _PCMCIA (1) /* PCMCIA 1 */
-+#define _PCMCIA1IO _PCMCIAIO (1) /* PCMCIA 1 I/O */
-+#define _PCMCIA1Attr _PCMCIAAttr (1) /* PCMCIA 1 Attribute */
-+#define _PCMCIA1Mem _PCMCIAMem (1) /* PCMCIA 1 Memory */
-+
-+
-+
-+/*
-+ * DMA Controller
-+ */
-+
-+#define DCSR0 __REG(0x40000000) /* DMA Control / Status Register for Channel 0 */
-+#define DCSR1 __REG(0x40000004) /* DMA Control / Status Register for Channel 1 */
-+#define DCSR2 __REG(0x40000008) /* DMA Control / Status Register for Channel 2 */
-+#define DCSR3 __REG(0x4000000c) /* DMA Control / Status Register for Channel 3 */
-+#define DCSR4 __REG(0x40000010) /* DMA Control / Status Register for Channel 4 */
-+#define DCSR5 __REG(0x40000014) /* DMA Control / Status Register for Channel 5 */
-+#define DCSR6 __REG(0x40000018) /* DMA Control / Status Register for Channel 6 */
-+#define DCSR7 __REG(0x4000001c) /* DMA Control / Status Register for Channel 7 */
-+#define DCSR8 __REG(0x40000020) /* DMA Control / Status Register for Channel 8 */
-+#define DCSR9 __REG(0x40000024) /* DMA Control / Status Register for Channel 9 */
-+#define DCSR10 __REG(0x40000028) /* DMA Control / Status Register for Channel 10 */
-+#define DCSR11 __REG(0x4000002c) /* DMA Control / Status Register for Channel 11 */
-+#define DCSR12 __REG(0x40000030) /* DMA Control / Status Register for Channel 12 */
-+#define DCSR13 __REG(0x40000034) /* DMA Control / Status Register for Channel 13 */
-+#define DCSR14 __REG(0x40000038) /* DMA Control / Status Register for Channel 14 */
-+#define DCSR15 __REG(0x4000003c) /* DMA Control / Status Register for Channel 15 */
-+
-+#define DCSR(x) __REG2(0x40000000, (x) << 2)
-+
-+#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */
-+#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */
-+#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */
-+#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */
-+#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */
-+#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */
-+#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */
-+#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */
-+
-+#define DINT __REG(0x400000f0) /* DMA Interrupt Register */
-+
-+#define DRCMR0 __REG(0x40000100) /* Request to Channel Map Register for DREQ 0 */
-+#define DRCMR1 __REG(0x40000104) /* Request to Channel Map Register for DREQ 1 */
-+#define DRCMR2 __REG(0x40000108) /* Request to Channel Map Register for I2S receive Request */
-+#define DRCMR3 __REG(0x4000010c) /* Request to Channel Map Register for I2S transmit Request */
-+#define DRCMR4 __REG(0x40000110) /* Request to Channel Map Register for BTUART receive Request */
-+#define DRCMR5 __REG(0x40000114) /* Request to Channel Map Register for BTUART transmit Request. */
-+#define DRCMR6 __REG(0x40000118) /* Request to Channel Map Register for FFUART receive Request */
-+#define DRCMR7 __REG(0x4000011c) /* Request to Channel Map Register for FFUART transmit Request */
-+#define DRCMR8 __REG(0x40000120) /* Request to Channel Map Register for AC97 microphone Request */
-+#define DRCMR9 __REG(0x40000124) /* Request to Channel Map Register for AC97 modem receive Request */
-+#define DRCMR10 __REG(0x40000128) /* Request to Channel Map Register for AC97 modem transmit Request */
-+#define DRCMR11 __REG(0x4000012c) /* Request to Channel Map Register for AC97 audio receive Request */
-+#define DRCMR12 __REG(0x40000130) /* Request to Channel Map Register for AC97 audio transmit Request */
-+#define DRCMR13 __REG(0x40000134) /* Request to Channel Map Register for SSP receive Request */
-+#define DRCMR14 __REG(0x40000138) /* Request to Channel Map Register for SSP transmit Request */
-+#define DRCMR15 __REG(0x4000013c) /* Reserved */
-+#define DRCMR16 __REG(0x40000140) /* Reserved */
-+#define DRCMR17 __REG(0x40000144) /* Request to Channel Map Register for ICP receive Request */
-+#define DRCMR18 __REG(0x40000148) /* Request to Channel Map Register for ICP transmit Request */
-+#define DRCMR19 __REG(0x4000014c) /* Request to Channel Map Register for STUART receive Request */
-+#define DRCMR20 __REG(0x40000150) /* Request to Channel Map Register for STUART transmit Request */
-+#define DRCMR21 __REG(0x40000154) /* Request to Channel Map Register for MMC receive Request */
-+#define DRCMR22 __REG(0x40000158) /* Request to Channel Map Register for MMC transmit Request */
-+#define DRCMR23 __REG(0x4000015c) /* Reserved */
-+#define DRCMR24 __REG(0x40000160) /* Reserved */
-+#define DRCMR25 __REG(0x40000164) /* Request to Channel Map Register for USB endpoint 1 Request */
-+#define DRCMR26 __REG(0x40000168) /* Request to Channel Map Register for USB endpoint 2 Request */
-+#define DRCMR27 __REG(0x4000016C) /* Request to Channel Map Register for USB endpoint 3 Request */
-+#define DRCMR28 __REG(0x40000170) /* Request to Channel Map Register for USB endpoint 4 Request */
-+#define DRCMR29 __REG(0x40000174) /* Reserved */
-+#define DRCMR30 __REG(0x40000178) /* Request to Channel Map Register for USB endpoint 6 Request */
-+#define DRCMR31 __REG(0x4000017C) /* Request to Channel Map Register for USB endpoint 7 Request */
-+#define DRCMR32 __REG(0x40000180) /* Request to Channel Map Register for USB endpoint 8 Request */
-+#define DRCMR33 __REG(0x40000184) /* Request to Channel Map Register for USB endpoint 9 Request */
-+#define DRCMR34 __REG(0x40000188) /* Reserved */
-+#define DRCMR35 __REG(0x4000018C) /* Request to Channel Map Register for USB endpoint 11 Request */
-+#define DRCMR36 __REG(0x40000190) /* Request to Channel Map Register for USB endpoint 12 Request */
-+#define DRCMR37 __REG(0x40000194) /* Request to Channel Map Register for USB endpoint 13 Request */
-+#define DRCMR38 __REG(0x40000198) /* Request to Channel Map Register for USB endpoint 14 Request */
-+#define DRCMR39 __REG(0x4000019C) /* Reserved */
-+
-+#define DRCMRRXSADR DRCMR2
-+#define DRCMRTXSADR DRCMR3
-+#define DRCMRRXBTRBR DRCMR4
-+#define DRCMRTXBTTHR DRCMR5
-+#define DRCMRRXFFRBR DRCMR6
-+#define DRCMRTXFFTHR DRCMR7
-+#define DRCMRRXMCDR DRCMR8
-+#define DRCMRRXMODR DRCMR9
-+#define DRCMRTXMODR DRCMR10
-+#define DRCMRRXPCDR DRCMR11
-+#define DRCMRTXPCDR DRCMR12
-+#define DRCMRRXSSDR DRCMR13
-+#define DRCMRTXSSDR DRCMR14
-+#define DRCMRRXICDR DRCMR17
-+#define DRCMRTXICDR DRCMR18
-+#define DRCMRRXSTRBR DRCMR19
-+#define DRCMRTXSTTHR DRCMR20
-+#define DRCMRRXMMC DRCMR21
-+#define DRCMRTXMMC DRCMR22
-+
-+#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */
-+#define DRCMR_CHLNUM 0x0f /* mask for Channel Number (read / write) */
-+
-+#define DDADR0 __REG(0x40000200) /* DMA Descriptor Address Register Channel 0 */
-+#define DSADR0 __REG(0x40000204) /* DMA Source Address Register Channel 0 */
-+#define DTADR0 __REG(0x40000208) /* DMA Target Address Register Channel 0 */
-+#define DCMD0 __REG(0x4000020c) /* DMA Command Address Register Channel 0 */
-+#define DDADR1 __REG(0x40000210) /* DMA Descriptor Address Register Channel 1 */
-+#define DSADR1 __REG(0x40000214) /* DMA Source Address Register Channel 1 */
-+#define DTADR1 __REG(0x40000218) /* DMA Target Address Register Channel 1 */
-+#define DCMD1 __REG(0x4000021c) /* DMA Command Address Register Channel 1 */
-+#define DDADR2 __REG(0x40000220) /* DMA Descriptor Address Register Channel 2 */
-+#define DSADR2 __REG(0x40000224) /* DMA Source Address Register Channel 2 */
-+#define DTADR2 __REG(0x40000228) /* DMA Target Address Register Channel 2 */
-+#define DCMD2 __REG(0x4000022c) /* DMA Command Address Register Channel 2 */
-+#define DDADR3 __REG(0x40000230) /* DMA Descriptor Address Register Channel 3 */
-+#define DSADR3 __REG(0x40000234) /* DMA Source Address Register Channel 3 */
-+#define DTADR3 __REG(0x40000238) /* DMA Target Address Register Channel 3 */
-+#define DCMD3 __REG(0x4000023c) /* DMA Command Address Register Channel 3 */
-+#define DDADR4 __REG(0x40000240) /* DMA Descriptor Address Register Channel 4 */
-+#define DSADR4 __REG(0x40000244) /* DMA Source Address Register Channel 4 */
-+#define DTADR4 __REG(0x40000248) /* DMA Target Address Register Channel 4 */
-+#define DCMD4 __REG(0x4000024c) /* DMA Command Address Register Channel 4 */
-+#define DDADR5 __REG(0x40000250) /* DMA Descriptor Address Register Channel 5 */
-+#define DSADR5 __REG(0x40000254) /* DMA Source Address Register Channel 5 */
-+#define DTADR5 __REG(0x40000258) /* DMA Target Address Register Channel 5 */
-+#define DCMD5 __REG(0x4000025c) /* DMA Command Address Register Channel 5 */
-+#define DDADR6 __REG(0x40000260) /* DMA Descriptor Address Register Channel 6 */
-+#define DSADR6 __REG(0x40000264) /* DMA Source Address Register Channel 6 */
-+#define DTADR6 __REG(0x40000268) /* DMA Target Address Register Channel 6 */
-+#define DCMD6 __REG(0x4000026c) /* DMA Command Address Register Channel 6 */
-+#define DDADR7 __REG(0x40000270) /* DMA Descriptor Address Register Channel 7 */
-+#define DSADR7 __REG(0x40000274) /* DMA Source Address Register Channel 7 */
-+#define DTADR7 __REG(0x40000278) /* DMA Target Address Register Channel 7 */
-+#define DCMD7 __REG(0x4000027c) /* DMA Command Address Register Channel 7 */
-+#define DDADR8 __REG(0x40000280) /* DMA Descriptor Address Register Channel 8 */
-+#define DSADR8 __REG(0x40000284) /* DMA Source Address Register Channel 8 */
-+#define DTADR8 __REG(0x40000288) /* DMA Target Address Register Channel 8 */
-+#define DCMD8 __REG(0x4000028c) /* DMA Command Address Register Channel 8 */
-+#define DDADR9 __REG(0x40000290) /* DMA Descriptor Address Register Channel 9 */
-+#define DSADR9 __REG(0x40000294) /* DMA Source Address Register Channel 9 */
-+#define DTADR9 __REG(0x40000298) /* DMA Target Address Register Channel 9 */
-+#define DCMD9 __REG(0x4000029c) /* DMA Command Address Register Channel 9 */
-+#define DDADR10 __REG(0x400002a0) /* DMA Descriptor Address Register Channel 10 */
-+#define DSADR10 __REG(0x400002a4) /* DMA Source Address Register Channel 10 */
-+#define DTADR10 __REG(0x400002a8) /* DMA Target Address Register Channel 10 */
-+#define DCMD10 __REG(0x400002ac) /* DMA Command Address Register Channel 10 */
-+#define DDADR11 __REG(0x400002b0) /* DMA Descriptor Address Register Channel 11 */
-+#define DSADR11 __REG(0x400002b4) /* DMA Source Address Register Channel 11 */
-+#define DTADR11 __REG(0x400002b8) /* DMA Target Address Register Channel 11 */
-+#define DCMD11 __REG(0x400002bc) /* DMA Command Address Register Channel 11 */
-+#define DDADR12 __REG(0x400002c0) /* DMA Descriptor Address Register Channel 12 */
-+#define DSADR12 __REG(0x400002c4) /* DMA Source Address Register Channel 12 */
-+#define DTADR12 __REG(0x400002c8) /* DMA Target Address Register Channel 12 */
-+#define DCMD12 __REG(0x400002cc) /* DMA Command Address Register Channel 12 */
-+#define DDADR13 __REG(0x400002d0) /* DMA Descriptor Address Register Channel 13 */
-+#define DSADR13 __REG(0x400002d4) /* DMA Source Address Register Channel 13 */
-+#define DTADR13 __REG(0x400002d8) /* DMA Target Address Register Channel 13 */
-+#define DCMD13 __REG(0x400002dc) /* DMA Command Address Register Channel 13 */
-+#define DDADR14 __REG(0x400002e0) /* DMA Descriptor Address Register Channel 14 */
-+#define DSADR14 __REG(0x400002e4) /* DMA Source Address Register Channel 14 */
-+#define DTADR14 __REG(0x400002e8) /* DMA Target Address Register Channel 14 */
-+#define DCMD14 __REG(0x400002ec) /* DMA Command Address Register Channel 14 */
-+#define DDADR15 __REG(0x400002f0) /* DMA Descriptor Address Register Channel 15 */
-+#define DSADR15 __REG(0x400002f4) /* DMA Source Address Register Channel 15 */
-+#define DTADR15 __REG(0x400002f8) /* DMA Target Address Register Channel 15 */
-+#define DCMD15 __REG(0x400002fc) /* DMA Command Address Register Channel 15 */
-+
-+#define DDADR(x) __REG2(0x40000200, (x) << 4)
-+#define DSADR(x) __REG2(0x40000204, (x) << 4)
-+#define DTADR(x) __REG2(0x40000208, (x) << 4)
-+#define DCMD(x) __REG2(0x4000020c, (x) << 4)
-+
-+#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */
-+#define DDADR_STOP (1 << 0) /* Stop (read / write) */
-+
-+#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */
-+#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */
-+#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */
-+#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */
-+#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */
-+#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */
-+#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */
-+#define DCMD_BURST8 (1 << 16) /* 8 byte burst */
-+#define DCMD_BURST16 (2 << 16) /* 16 byte burst */
-+#define DCMD_BURST32 (3 << 16) /* 32 byte burst */
-+#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */
-+#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */
-+#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */
-+#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
-+
-+/* default combinations */
-+#define DCMD_RXPCDR (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
-+#define DCMD_RXMCDR (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
-+#define DCMD_TXPCDR (DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
-+
-+
-+/*
-+ * UARTs
-+ */
-+
-+/* Full Function UART (FFUART) */
-+#define FFUART FFRBR
-+#define FFRBR __REG(0x40100000) /* Receive Buffer Register (read only) */
-+#define FFTHR __REG(0x40100000) /* Transmit Holding Register (write only) */
-+#define FFIER __REG(0x40100004) /* Interrupt Enable Register (read/write) */
-+#define FFIIR __REG(0x40100008) /* Interrupt ID Register (read only) */
-+#define FFFCR __REG(0x40100008) /* FIFO Control Register (write only) */
-+#define FFLCR __REG(0x4010000C) /* Line Control Register (read/write) */
-+#define FFMCR __REG(0x40100010) /* Modem Control Register (read/write) */
-+#define FFLSR __REG(0x40100014) /* Line Status Register (read only) */
-+#define FFMSR __REG(0x40100018) /* Modem Status Register (read only) */
-+#define FFSPR __REG(0x4010001C) /* Scratch Pad Register (read/write) */
-+#define FFISR __REG(0x40100020) /* Infrared Selection Register (read/write) */
-+#define FFDLL __REG(0x40100000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define FFDLH __REG(0x40100004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+/* Bluetooth UART (BTUART) */
-+#define BTUART BTRBR
-+#define BTRBR __REG(0x40200000) /* Receive Buffer Register (read only) */
-+#define BTTHR __REG(0x40200000) /* Transmit Holding Register (write only) */
-+#define BTIER __REG(0x40200004) /* Interrupt Enable Register (read/write) */
-+#define BTIIR __REG(0x40200008) /* Interrupt ID Register (read only) */
-+#define BTFCR __REG(0x40200008) /* FIFO Control Register (write only) */
-+#define BTLCR __REG(0x4020000C) /* Line Control Register (read/write) */
-+#define BTMCR __REG(0x40200010) /* Modem Control Register (read/write) */
-+#define BTLSR __REG(0x40200014) /* Line Status Register (read only) */
-+#define BTMSR __REG(0x40200018) /* Modem Status Register (read only) */
-+#define BTSPR __REG(0x4020001C) /* Scratch Pad Register (read/write) */
-+#define BTISR __REG(0x40200020) /* Infrared Selection Register (read/write) */
-+#define BTDLL __REG(0x40200000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define BTDLH __REG(0x40200004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+/* Standard UART (STUART) */
-+#define STUART STRBR
-+#define STRBR __REG(0x40700000) /* Receive Buffer Register (read only) */
-+#define STTHR __REG(0x40700000) /* Transmit Holding Register (write only) */
-+#define STIER __REG(0x40700004) /* Interrupt Enable Register (read/write) */
-+#define STIIR __REG(0x40700008) /* Interrupt ID Register (read only) */
-+#define STFCR __REG(0x40700008) /* FIFO Control Register (write only) */
-+#define STLCR __REG(0x4070000C) /* Line Control Register (read/write) */
-+#define STMCR __REG(0x40700010) /* Modem Control Register (read/write) */
-+#define STLSR __REG(0x40700014) /* Line Status Register (read only) */
-+#define STMSR __REG(0x40700018) /* Reserved */
-+#define STSPR __REG(0x4070001C) /* Scratch Pad Register (read/write) */
-+#define STISR __REG(0x40700020) /* Infrared Selection Register (read/write) */
-+#define STDLL __REG(0x40700000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define STDLH __REG(0x40700004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+#define IER_DMAE (1 << 7) /* DMA Requests Enable */
-+#define IER_UUE (1 << 6) /* UART Unit Enable */
-+#define IER_NRZE (1 << 5) /* NRZ coding Enable */
-+#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */
-+#define IER_MIE (1 << 3) /* Modem Interrupt Enable */
-+#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */
-+#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */
-+#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */
-+
-+#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */
-+#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */
-+#define IIR_TOD (1 << 3) /* Time Out Detected */
-+#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */
-+#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */
-+#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */
-+
-+#define FCR_ITL2 (1 << 7) /* Interrupt Trigger Level */
-+#define FCR_ITL1 (1 << 6) /* Interrupt Trigger Level */
-+#define FCR_RESETTF (1 << 2) /* Reset Transmitter FIFO */
-+#define FCR_RESETRF (1 << 1) /* Reset Receiver FIFO */
-+#define FCR_TRFIFOE (1 << 0) /* Transmit and Receive FIFO Enable */
-+#define FCR_ITL_1 (0)
-+#define FCR_ITL_8 (FCR_ITL1)
-+#define FCR_ITL_16 (FCR_ITL2)
-+#define FCR_ITL_32 (FCR_ITL2|FCR_ITL1)
-+
-+#define LCR_DLAB (1 << 7) /* Divisor Latch Access Bit */
-+#define LCR_SB (1 << 6) /* Set Break */
-+#define LCR_STKYP (1 << 5) /* Sticky Parity */
-+#define LCR_EPS (1 << 4) /* Even Parity Select */
-+#define LCR_PEN (1 << 3) /* Parity Enable */
-+#define LCR_STB (1 << 2) /* Stop Bit */
-+#define LCR_WLS1 (1 << 1) /* Word Length Select */
-+#define LCR_WLS0 (1 << 0) /* Word Length Select */
-+
-+#define LSR_FIFOE (1 << 7) /* FIFO Error Status */
-+#define LSR_TEMT (1 << 6) /* Transmitter Empty */
-+#define LSR_TDRQ (1 << 5) /* Transmit Data Request */
-+#define LSR_BI (1 << 4) /* Break Interrupt */
-+#define LSR_FE (1 << 3) /* Framing Error */
-+#define LSR_PE (1 << 2) /* Parity Error */
-+#define LSR_OE (1 << 1) /* Overrun Error */
-+#define LSR_DR (1 << 0) /* Data Ready */
-+
-+#define MCR_LOOP (1 << 4) */
-+#define MCR_OUT2 (1 << 3) /* force MSR_DCD in loopback mode */
-+#define MCR_OUT1 (1 << 2) /* force MSR_RI in loopback mode */
-+#define MCR_RTS (1 << 1) /* Request to Send */
-+#define MCR_DTR (1 << 0) /* Data Terminal Ready */
-+
-+#define MSR_DCD (1 << 7) /* Data Carrier Detect */
-+#define MSR_RI (1 << 6) /* Ring Indicator */
-+#define MSR_DSR (1 << 5) /* Data Set Ready */
-+#define MSR_CTS (1 << 4) /* Clear To Send */
-+#define MSR_DDCD (1 << 3) /* Delta Data Carrier Detect */
-+#define MSR_TERI (1 << 2) /* Trailing Edge Ring Indicator */
-+#define MSR_DDSR (1 << 1) /* Delta Data Set Ready */
-+#define MSR_DCTS (1 << 0) /* Delta Clear To Send */
-+
-+/*
-+ * IrSR (Infrared Selection Register)
-+ */
-+#define STISR_RXPL (1 << 4) /* Receive Data Polarity */
-+#define STISR_TXPL (1 << 3) /* Transmit Data Polarity */
-+#define STISR_XMODE (1 << 2) /* Transmit Pulse Width Select */
-+#define STISR_RCVEIR (1 << 1) /* Receiver SIR Enable */
-+#define STISR_XMITIR (1 << 0) /* Transmitter SIR Enable */
-+
-+
-+/*
-+ * I2C registers
-+ */
-+
-+#define IBMR __REG(0x40301680) /* I2C Bus Monitor Register - IBMR */
-+#define IDBR __REG(0x40301688) /* I2C Data Buffer Register - IDBR */
-+#define ICR __REG(0x40301690) /* I2C Control Register - ICR */
-+#define ISR __REG(0x40301698) /* I2C Status Register - ISR */
-+#define ISAR __REG(0x403016A0) /* I2C Slave Address Register - ISAR */
-+
-+#define ICR_START (1 << 0) /* start bit */
-+#define ICR_STOP (1 << 1) /* stop bit */
-+#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */
-+#define ICR_TB (1 << 3) /* transfer byte bit */
-+#define ICR_MA (1 << 4) /* master abort */
-+#define ICR_SCLE (1 << 5) /* master clock enable */
-+#define ICR_IUE (1 << 6) /* unit enable */
-+#define ICR_GCD (1 << 7) /* general call disable */
-+#define ICR_ITEIE (1 << 8) /* enable tx interrupts */
-+#define ICR_IRFIE (1 << 9) /* enable rx interrupts */
-+#define ICR_BEIE (1 << 10) /* enable bus error ints */
-+#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */
-+#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */
-+#define ICR_SADIE (1 << 13) /* slave address detected int enable */
-+#define ICR_UR (1 << 14) /* unit reset */
-+
-+#define ISR_RWM (1 << 0) /* read/write mode */
-+#define ISR_ACKNAK (1 << 1) /* ack/nak status */
-+#define ISR_UB (1 << 2) /* unit busy */
-+#define ISR_IBB (1 << 3) /* bus busy */
-+#define ISR_SSD (1 << 4) /* slave stop detected */
-+#define ISR_ALD (1 << 5) /* arbitration loss detected */
-+#define ISR_ITE (1 << 6) /* tx buffer empty */
-+#define ISR_IRF (1 << 7) /* rx buffer full */
-+#define ISR_GCAD (1 << 8) /* general call address detected */
-+#define ISR_SAD (1 << 9) /* slave address detected */
-+#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
-+
-+
-+/*
-+ * Serial Audio Controller
-+ */
-+
-+/* FIXME: This clash with SA1111 defines */
-+#ifndef CONFIG_SA1111
-+#define SACR0 __REG(0x40400000) /* Global Control Register */
-+#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
-+#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
-+#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */
-+#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */
-+#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
-+#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
-+#endif
-+
-+
-+/*
-+ * AC97 Controller registers
-+ */
-+
-+#define POCR __REG(0x40500000) /* PCM Out Control Register */
-+#define POCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define PICR __REG(0x40500004) /* PCM In Control Register */
-+#define PICR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define MCCR __REG(0x40500008) /* Mic In Control Register */
-+#define MCCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define GCR __REG(0x4050000C) /* Global Control Register */
-+#define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */
-+#define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */
-+#define GCR_SECRDY_IEN (1 << 9) /* Secondary Ready Interrupt Enable */
-+#define GCR_PRIRDY_IEN (1 << 8) /* Primary Ready Interrupt Enable */
-+#define GCR_SECRES_IEN (1 << 5) /* Secondary Resume Interrupt Enable */
-+#define GCR_PRIRES_IEN (1 << 4) /* Primary Resume Interrupt Enable */
-+#define GCR_ACLINK_OFF (1 << 3) /* AC-link Shut Off */
-+#define GCR_WARM_RST (1 << 2) /* AC97 Warm Reset */
-+#define GCR_COLD_RST (1 << 1) /* AC'97 Cold Reset (0 = active) */
-+#define GCR_GIE (1 << 0) /* Codec GPI Interrupt Enable */
-+
-+#define POSR __REG(0x40500010) /* PCM Out Status Register */
-+#define POSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define PISR __REG(0x40500014) /* PCM In Status Register */
-+#define PISR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MCSR __REG(0x40500018) /* Mic In Status Register */
-+#define MCSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define GSR __REG(0x4050001C) /* Global Status Register */
-+#define GSR_CDONE (1 << 19) /* Command Done */
-+#define GSR_SDONE (1 << 18) /* Status Done */
-+#define GSR_RDCS (1 << 15) /* Read Completion Status */
-+#define GSR_BIT3SLT12 (1 << 14) /* Bit 3 of slot 12 */
-+#define GSR_BIT2SLT12 (1 << 13) /* Bit 2 of slot 12 */
-+#define GSR_BIT1SLT12 (1 << 12) /* Bit 1 of slot 12 */
-+#define GSR_SECRES (1 << 11) /* Secondary Resume Interrupt */
-+#define GSR_PRIRES (1 << 10) /* Primary Resume Interrupt */
-+#define GSR_SCR (1 << 9) /* Secondary Codec Ready */
-+#define GSR_PCR (1 << 8) /* Primary Codec Ready */
-+#define GSR_MINT (1 << 7) /* Mic In Interrupt */
-+#define GSR_POINT (1 << 6) /* PCM Out Interrupt */
-+#define GSR_PIINT (1 << 5) /* PCM In Interrupt */
-+#define GSR_MOINT (1 << 2) /* Modem Out Interrupt */
-+#define GSR_MIINT (1 << 1) /* Modem In Interrupt */
-+#define GSR_GSCI (1 << 0) /* Codec GPI Status Change Interrupt */
-+
-+#define CAR __REG(0x40500020) /* CODEC Access Register */
-+#define CAR_CAIP (1 << 0) /* Codec Access In Progress */
-+
-+#define PCDR __REG(0x40500040) /* PCM FIFO Data Register */
-+#define MCDR __REG(0x40500060) /* Mic-in FIFO Data Register */
-+
-+#define MOCR __REG(0x40500100) /* Modem Out Control Register */
-+#define MOCR_FEIE (1 << 3) /* FIFO Error */
-+
-+#define MICR __REG(0x40500108) /* Modem In Control Register */
-+#define MICR_FEIE (1 << 3) /* FIFO Error */
-+
-+#define MOSR __REG(0x40500110) /* Modem Out Status Register */
-+#define MOSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MISR __REG(0x40500118) /* Modem In Status Register */
-+#define MISR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MODR __REG(0x40500140) /* Modem FIFO Data Register */
-+
-+#define PAC_REG_BASE __REG(0x40500200) /* Primary Audio Codec */
-+#define SAC_REG_BASE __REG(0x40500300) /* Secondary Audio Codec */
-+#define PMC_REG_BASE __REG(0x40500400) /* Primary Modem Codec */
-+#define SMC_REG_BASE __REG(0x40500500) /* Secondary Modem Codec */
-+
-+
-+/*
-+ * USB Device Controller
-+ */
-+#define UDC_RES1 __REG(0x40600004) /* UDC Undocumented - Reserved1 */
-+#define UDC_RES2 __REG(0x40600008) /* UDC Undocumented - Reserved2 */
-+#define UDC_RES3 __REG(0x4060000C) /* UDC Undocumented - Reserved3 */
-+
-+#define UDCCR __REG(0x40600000) /* UDC Control Register */
-+#define UDCCR_UDE (1 << 0) /* UDC enable */
-+#define UDCCR_UDA (1 << 1) /* UDC active */
-+#define UDCCR_RSM (1 << 2) /* Device resume */
-+#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */
-+#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */
-+#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */
-+#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */
-+#define UDCCR_REM (1 << 7) /* Reset interrupt mask */
-+
-+#define UDCCS0 __REG(0x40600010) /* UDC Endpoint 0 Control/Status Register */
-+#define UDCCS0_OPR (1 << 0) /* OUT packet ready */
-+#define UDCCS0_IPR (1 << 1) /* IN packet ready */
-+#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */
-+#define UDCCS0_SST (1 << 4) /* Sent stall */
-+#define UDCCS0_FST (1 << 5) /* Force stall */
-+#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */
-+#define UDCCS0_SA (1 << 7) /* Setup active */
-+
-+/* Bulk IN - Endpoint 1,6,11 */
-+#define UDCCS1 __REG(0x40600014) /* UDC Endpoint 1 (IN) Control/Status Register */
-+#define UDCCS6 __REG(0x40600028) /* UDC Endpoint 6 (IN) Control/Status Register */
-+#define UDCCS11 __REG(0x4060003C) /* UDC Endpoint 11 (IN) Control/Status Register */
-+
-+#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_BI_SST (1 << 4) /* Sent stall */
-+#define UDCCS_BI_FST (1 << 5) /* Force stall */
-+#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */
-+
-+/* Bulk OUT - Endpoint 2,7,12 */
-+#define UDCCS2 __REG(0x40600018) /* UDC Endpoint 2 (OUT) Control/Status Register */
-+#define UDCCS7 __REG(0x4060002C) /* UDC Endpoint 7 (OUT) Control/Status Register */
-+#define UDCCS12 __REG(0x40600040) /* UDC Endpoint 12 (OUT) Control/Status Register */
-+
-+#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */
-+#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */
-+#define UDCCS_BO_DME (1 << 3) /* DMA enable */
-+#define UDCCS_BO_SST (1 << 4) /* Sent stall */
-+#define UDCCS_BO_FST (1 << 5) /* Force stall */
-+#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */
-+#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */
-+
-+/* Isochronous IN - Endpoint 3,8,13 */
-+#define UDCCS3 __REG(0x4060001C) /* UDC Endpoint 3 (IN) Control/Status Register */
-+#define UDCCS8 __REG(0x40600030) /* UDC Endpoint 8 (IN) Control/Status Register */
-+#define UDCCS13 __REG(0x40600044) /* UDC Endpoint 13 (IN) Control/Status Register */
-+
-+#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */
-+
-+/* Isochronous OUT - Endpoint 4,9,14 */
-+#define UDCCS4 __REG(0x40600020) /* UDC Endpoint 4 (OUT) Control/Status Register */
-+#define UDCCS9 __REG(0x40600034) /* UDC Endpoint 9 (OUT) Control/Status Register */
-+#define UDCCS14 __REG(0x40600048) /* UDC Endpoint 14 (OUT) Control/Status Register */
-+
-+#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */
-+#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */
-+#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */
-+#define UDCCS_IO_DME (1 << 3) /* DMA enable */
-+#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */
-+#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */
-+
-+/* Interrupt IN - Endpoint 5,10,15 */
-+#define UDCCS5 __REG(0x40600024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */
-+#define UDCCS10 __REG(0x40600038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */
-+#define UDCCS15 __REG(0x4060004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */
-+
-+#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_INT_SST (1 << 4) /* Sent stall */
-+#define UDCCS_INT_FST (1 << 5) /* Force stall */
-+#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */
-+
-+#define UFNRH __REG(0x40600060) /* UDC Frame Number Register High */
-+#define UFNRL __REG(0x40600064) /* UDC Frame Number Register Low */
-+#define UBCR2 __REG(0x40600068) /* UDC Byte Count Reg 2 */
-+#define UBCR4 __REG(0x4060006c) /* UDC Byte Count Reg 4 */
-+#define UBCR7 __REG(0x40600070) /* UDC Byte Count Reg 7 */
-+#define UBCR9 __REG(0x40600074) /* UDC Byte Count Reg 9 */
-+#define UBCR12 __REG(0x40600078) /* UDC Byte Count Reg 12 */
-+#define UBCR14 __REG(0x4060007c) /* UDC Byte Count Reg 14 */
-+#define UDDR0 __REG(0x40600080) /* UDC Endpoint 0 Data Register */
-+#define UDDR1 __REG(0x40600100) /* UDC Endpoint 1 Data Register */
-+#define UDDR2 __REG(0x40600180) /* UDC Endpoint 2 Data Register */
-+#define UDDR3 __REG(0x40600200) /* UDC Endpoint 3 Data Register */
-+#define UDDR4 __REG(0x40600400) /* UDC Endpoint 4 Data Register */
-+#define UDDR5 __REG(0x406000A0) /* UDC Endpoint 5 Data Register */
-+#define UDDR6 __REG(0x40600600) /* UDC Endpoint 6 Data Register */
-+#define UDDR7 __REG(0x40600680) /* UDC Endpoint 7 Data Register */
-+#define UDDR8 __REG(0x40600700) /* UDC Endpoint 8 Data Register */
-+#define UDDR9 __REG(0x40600900) /* UDC Endpoint 9 Data Register */
-+#define UDDR10 __REG(0x406000C0) /* UDC Endpoint 10 Data Register */
-+#define UDDR11 __REG(0x40600B00) /* UDC Endpoint 11 Data Register */
-+#define UDDR12 __REG(0x40600B80) /* UDC Endpoint 12 Data Register */
-+#define UDDR13 __REG(0x40600C00) /* UDC Endpoint 13 Data Register */
-+#define UDDR14 __REG(0x40600E00) /* UDC Endpoint 14 Data Register */
-+#define UDDR15 __REG(0x406000E0) /* UDC Endpoint 15 Data Register */
-+
-+#define UICR0 __REG(0x40600050) /* UDC Interrupt Control Register 0 */
-+
-+#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */
-+#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */
-+#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */
-+#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */
-+#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */
-+#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */
-+#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */
-+#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */
-+
-+#define UICR1 __REG(0x40600054) /* UDC Interrupt Control Register 1 */
-+
-+#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */
-+#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */
-+#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */
-+#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */
-+#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */
-+#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */
-+#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */
-+#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */
-+
-+#define USIR0 __REG(0x40600058) /* UDC Status Interrupt Register 0 */
-+
-+#define USIR0_IR0 (1 << 0) /* Interrup request ep 0 */
-+#define USIR0_IR1 (1 << 1) /* Interrup request ep 1 */
-+#define USIR0_IR2 (1 << 2) /* Interrup request ep 2 */
-+#define USIR0_IR3 (1 << 3) /* Interrup request ep 3 */
-+#define USIR0_IR4 (1 << 4) /* Interrup request ep 4 */
-+#define USIR0_IR5 (1 << 5) /* Interrup request ep 5 */
-+#define USIR0_IR6 (1 << 6) /* Interrup request ep 6 */
-+#define USIR0_IR7 (1 << 7) /* Interrup request ep 7 */
-+
-+#define USIR1 __REG(0x4060005C) /* UDC Status Interrupt Register 1 */
-+
-+#define USIR1_IR8 (1 << 0) /* Interrup request ep 8 */
-+#define USIR1_IR9 (1 << 1) /* Interrup request ep 9 */
-+#define USIR1_IR10 (1 << 2) /* Interrup request ep 10 */
-+#define USIR1_IR11 (1 << 3) /* Interrup request ep 11 */
-+#define USIR1_IR12 (1 << 4) /* Interrup request ep 12 */
-+#define USIR1_IR13 (1 << 5) /* Interrup request ep 13 */
-+#define USIR1_IR14 (1 << 6) /* Interrup request ep 14 */
-+#define USIR1_IR15 (1 << 7) /* Interrup request ep 15 */
-+
-+
-+/*
-+ * Fast Infrared Communication Port
-+ */
-+
-+#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */
-+#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */
-+#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */
-+#define ICDR __REG(0x4080000c) /* ICP Data Register */
-+#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */
-+#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */
-+
-+#define ICCR0_AME (1 << 7) /* Adress match enable */
-+#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */
-+#define ICCR0_RIE (1 << 5) /* Recieve FIFO interrupt enable */
-+#define ICCR0_RXE (1 << 4) /* Receive enable */
-+#define ICCR0_TXE (1 << 3) /* Transmit enable */
-+#define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */
-+#define ICCR0_LBM (1 << 1) /* Loopback mode */
-+#define ICCR0_ITR (1 << 0) /* IrDA transmission */
-+
-+#define ICSR0_FRE (1 << 5) /* Framing error */
-+#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */
-+#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */
-+#define ICSR0_RAB (1 << 2) /* Receiver abort */
-+#define ICSR0_TUR (1 << 1) /* Trunsmit FIFO underun */
-+#define ICSR0_EIF (1 << 0) /* End/Error in FIFO */
-+
-+#define ICSR1_ROR (1 << 6) /* Receiver FIFO underrun */
-+#define ICSR1_CRE (1 << 5) /* CRC error */
-+#define ICSR1_EOF (1 << 4) /* End of frame */
-+#define ICSR1_TNF (1 << 3) /* Transmit FIFO not full */
-+#define ICSR1_RNE (1 << 2) /* Receive FIFO not empty */
-+#define ICSR1_TBY (1 << 1) /* Tramsmiter busy flag */
-+#define ICSR1_RSY (1 << 0) /* Recevier synchronized flag */
-+
-+
-+/*
-+ * Real Time Clock
-+ */
-+
-+#define RCNR __REG(0x40900000) /* RTC Count Register */
-+#define RTAR __REG(0x40900004) /* RTC Alarm Register */
-+#define RTSR __REG(0x40900008) /* RTC Status Register */
-+#define RTTR __REG(0x4090000C) /* RTC Timer Trim Register */
-+
-+#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
-+#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
-+#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
-+#define RTSR_AL (1 << 0) /* RTC alarm detected */
-+
-+
-+/*
-+ * OS Timer & Match Registers
-+ */
-+
-+#define OSMR0 __REG(0x40A00000) /* */
-+#define OSMR1 __REG(0x40A00004) /* */
-+#define OSMR2 __REG(0x40A00008) /* */
-+#define OSMR3 __REG(0x40A0000C) /* */
-+#define OSCR __REG(0x40A00010) /* OS Timer Counter Register */
-+#define OSSR __REG(0x40A00014) /* OS Timer Status Register */
-+#define OWER __REG(0x40A00018) /* OS Timer Watchdog Enable Register */
-+#define OIER __REG(0x40A0001C) /* OS Timer Interrupt Enable Register */
-+
-+#define OSSR_M3 (1 << 3) /* Match status channel 3 */
-+#define OSSR_M2 (1 << 2) /* Match status channel 2 */
-+#define OSSR_M1 (1 << 1) /* Match status channel 1 */
-+#define OSSR_M0 (1 << 0) /* Match status channel 0 */
-+
-+#define OWER_WME (1 << 0) /* Watchdog Match Enable */
-+
-+#define OIER_E3 (1 << 3) /* Interrupt enable channel 3 */
-+#define OIER_E2 (1 << 2) /* Interrupt enable channel 2 */
-+#define OIER_E1 (1 << 1) /* Interrupt enable channel 1 */
-+#define OIER_E0 (1 << 0) /* Interrupt enable channel 0 */
-+
-+
-+/*
-+ * Pulse Width Modulator
-+ */
-+
-+#define PWM_CTRL0 __REG(0x40B00000) /* PWM 0 Control Register */
-+#define PWM_PWDUTY0 __REG(0x40B00004) /* PWM 0 Duty Cycle Register */
-+#define PWM_PERVAL0 __REG(0x40B00008) /* PWM 0 Period Control Register */
-+
-+#define PWM_CTRL1 __REG(0x40C00000) /* PWM 1Control Register */
-+#define PWM_PWDUTY1 __REG(0x40C00004) /* PWM 1 Duty Cycle Register */
-+#define PWM_PERVAL1 __REG(0x40C00008) /* PWM 1 Period Control Register */
-+
-+
-+/*
-+ * Interrupt Controller
-+ */
-+
-+#define ICIP __REG(0x40D00000) /* Interrupt Controller IRQ Pending Register */
-+#define ICMR __REG(0x40D00004) /* Interrupt Controller Mask Register */
-+#define ICLR __REG(0x40D00008) /* Interrupt Controller Level Register */
-+#define ICFP __REG(0x40D0000C) /* Interrupt Controller FIQ Pending Register */
-+#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
-+#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */
-+
-+
-+/*
-+ * General Purpose I/O
-+ */
-+
-+#define GPLR0 __REG(0x40E00000) /* GPIO Pin-Level Register GPIO<31:0> */
-+#define GPLR1 __REG(0x40E00004) /* GPIO Pin-Level Register GPIO<63:32> */
-+#define GPLR2 __REG(0x40E00008) /* GPIO Pin-Level Register GPIO<80:64> */
-+
-+#define GPDR0 __REG(0x40E0000C) /* GPIO Pin Direction Register GPIO<31:0> */
-+#define GPDR1 __REG(0x40E00010) /* GPIO Pin Direction Register GPIO<63:32> */
-+#define GPDR2 __REG(0x40E00014) /* GPIO Pin Direction Register GPIO<80:64> */
-+
-+#define GPSR0 __REG(0x40E00018) /* GPIO Pin Output Set Register GPIO<31:0> */
-+#define GPSR1 __REG(0x40E0001C) /* GPIO Pin Output Set Register GPIO<63:32> */
-+#define GPSR2 __REG(0x40E00020) /* GPIO Pin Output Set Register GPIO<80:64> */
-+
-+#define GPCR0 __REG(0x40E00024) /* GPIO Pin Output Clear Register GPIO<31:0> */
-+#define GPCR1 __REG(0x40E00028) /* GPIO Pin Output Clear Register GPIO <63:32> */
-+#define GPCR2 __REG(0x40E0002C) /* GPIO Pin Output Clear Register GPIO <80:64> */
-+
-+#define GRER0 __REG(0x40E00030) /* GPIO Rising-Edge Detect Register GPIO<31:0> */
-+#define GRER1 __REG(0x40E00034) /* GPIO Rising-Edge Detect Register GPIO<63:32> */
-+#define GRER2 __REG(0x40E00038) /* GPIO Rising-Edge Detect Register GPIO<80:64> */
-+
-+#define GFER0 __REG(0x40E0003C) /* GPIO Falling-Edge Detect Register GPIO<31:0> */
-+#define GFER1 __REG(0x40E00040) /* GPIO Falling-Edge Detect Register GPIO<63:32> */
-+#define GFER2 __REG(0x40E00044) /* GPIO Falling-Edge Detect Register GPIO<80:64> */
-+
-+#define GEDR0 __REG(0x40E00048) /* GPIO Edge Detect Status Register GPIO<31:0> */
-+#define GEDR1 __REG(0x40E0004C) /* GPIO Edge Detect Status Register GPIO<63:32> */
-+#define GEDR2 __REG(0x40E00050) /* GPIO Edge Detect Status Register GPIO<80:64> */
-+
-+#define GAFR0_L __REG(0x40E00054) /* GPIO Alternate Function Select Register GPIO<15:0> */
-+#define GAFR0_U __REG(0x40E00058) /* GPIO Alternate Function Select Register GPIO<31:16> */
-+#define GAFR1_L __REG(0x40E0005C) /* GPIO Alternate Function Select Register GPIO<47:32> */
-+#define GAFR1_U __REG(0x40E00060) /* GPIO Alternate Function Select Register GPIO<63:48> */
-+#define GAFR2_L __REG(0x40E00064) /* GPIO Alternate Function Select Register GPIO<79:64> */
-+#define GAFR2_U __REG(0x40E00068) /* GPIO Alternate Function Select Register GPIO 80 */
-+
-+/* More handy macros. The argument is a literal GPIO number. */
-+
-+#define GPIO_bit(x) (1 << ((x) & 0x1f))
-+#define GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3)
-+#define GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3)
-+#define GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3)
-+#define GPCR(x) __REG2(0x40E00024, ((x) & 0x60) >> 3)
-+#define GRER(x) __REG2(0x40E00030, ((x) & 0x60) >> 3)
-+#define GFER(x) __REG2(0x40E0003C, ((x) & 0x60) >> 3)
-+#define GEDR(x) __REG2(0x40E00048, ((x) & 0x60) >> 3)
-+#define GAFR(x) __REG2(0x40E00054, ((x) & 0x70) >> 2)
-+
-+/* GPIO alternate function assignments */
-+
-+#define GPIO1_RST 1 /* reset */
-+#define GPIO6_MMCCLK 6 /* MMC Clock */
-+#define GPIO8_48MHz 7 /* 48 MHz clock output */
-+#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */
-+#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */
-+#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */
-+#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */
-+#define GPIO12_32KHz 12 /* 32 kHz out */
-+#define GPIO13_MBGNT 13 /* memory controller grant */
-+#define GPIO14_MBREQ 14 /* alternate bus master request */
-+#define GPIO15_nCS_1 15 /* chip select 1 */
-+#define GPIO16_PWM0 16 /* PWM0 output */
-+#define GPIO17_PWM1 17 /* PWM1 output */
-+#define GPIO18_RDY 18 /* Ext. Bus Ready */
-+#define GPIO19_DREQ1 19 /* External DMA Request */
-+#define GPIO20_DREQ0 20 /* External DMA Request */
-+#define GPIO23_SCLK 23 /* SSP clock */
-+#define GPIO24_SFRM 24 /* SSP Frame */
-+#define GPIO25_STXD 25 /* SSP transmit */
-+#define GPIO26_SRXD 26 /* SSP receive */
-+#define GPIO27_SEXTCLK 27 /* SSP ext_clk */
-+#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */
-+#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */
-+#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */
-+#define GPIO31_SYNC 31 /* AC97/I2S sync */
-+#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */
-+#define GPIO33_nCS_5 33 /* chip select 5 */
-+#define GPIO34_FFRXD 34 /* FFUART receive */
-+#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */
-+#define GPIO35_FFCTS 35 /* FFUART Clear to send */
-+#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */
-+#define GPIO37_FFDSR 37 /* FFUART data set ready */
-+#define GPIO38_FFRI 38 /* FFUART Ring Indicator */
-+#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */
-+#define GPIO39_FFTXD 39 /* FFUART transmit data */
-+#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */
-+#define GPIO41_FFRTS 41 /* FFUART request to send */
-+#define GPIO42_BTRXD 42 /* BTUART receive data */
-+#define GPIO43_BTTXD 43 /* BTUART transmit data */
-+#define GPIO44_BTCTS 44 /* BTUART clear to send */
-+#define GPIO45_BTRTS 45 /* BTUART request to send */
-+#define GPIO46_ICPRXD 46 /* ICP receive data */
-+#define GPIO46_STRXD 46 /* STD_UART receive data */
-+#define GPIO47_ICPTXD 47 /* ICP transmit data */
-+#define GPIO47_STTXD 47 /* STD_UART transmit data */
-+#define GPIO48_nPOE 48 /* Output Enable for Card Space */
-+#define GPIO49_nPWE 49 /* Write Enable for Card Space */
-+#define GPIO50_nPIOR 50 /* I/O Read for Card Space */
-+#define GPIO51_nPIOW 51 /* I/O Write for Card Space */
-+#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */
-+#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */
-+#define GPIO53_MMCCLK 53 /* MMC Clock */
-+#define GPIO54_MMCCLK 54 /* MMC Clock */
-+#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */
-+#define GPIO55_nPREG 55 /* Card Address bit 26 */
-+#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */
-+#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */
-+#define GPIO58_LDD_0 58 /* LCD data pin 0 */
-+#define GPIO59_LDD_1 59 /* LCD data pin 1 */
-+#define GPIO60_LDD_2 60 /* LCD data pin 2 */
-+#define GPIO61_LDD_3 61 /* LCD data pin 3 */
-+#define GPIO62_LDD_4 62 /* LCD data pin 4 */
-+#define GPIO63_LDD_5 63 /* LCD data pin 5 */
-+#define GPIO64_LDD_6 64 /* LCD data pin 6 */
-+#define GPIO65_LDD_7 65 /* LCD data pin 7 */
-+#define GPIO66_LDD_8 66 /* LCD data pin 8 */
-+#define GPIO66_MBREQ 66 /* alternate bus master req */
-+#define GPIO67_LDD_9 67 /* LCD data pin 9 */
-+#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */
-+#define GPIO68_LDD_10 68 /* LCD data pin 10 */
-+#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */
-+#define GPIO69_LDD_11 69 /* LCD data pin 11 */
-+#define GPIO69_MMCCLK 69 /* MMC_CLK */
-+#define GPIO70_LDD_12 70 /* LCD data pin 12 */
-+#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */
-+#define GPIO71_LDD_13 71 /* LCD data pin 13 */
-+#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */
-+#define GPIO72_LDD_14 72 /* LCD data pin 14 */
-+#define GPIO72_32kHz 72 /* 32 kHz clock */
-+#define GPIO73_LDD_15 73 /* LCD data pin 15 */
-+#define GPIO73_MBGNT 73 /* Memory controller grant */
-+#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */
-+#define GPIO75_LCD_LCLK 75 /* LCD line clock */
-+#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */
-+#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */
-+#define GPIO78_nCS_2 78 /* chip select 2 */
-+#define GPIO79_nCS_3 79 /* chip select 3 */
-+#define GPIO80_nCS_4 80 /* chip select 4 */
-+
-+/* GPIO alternate function mode & direction */
-+
-+#define GPIO_IN 0x000
-+#define GPIO_OUT 0x080
-+#define GPIO_ALT_FN_1_IN 0x100
-+#define GPIO_ALT_FN_1_OUT 0x180
-+#define GPIO_ALT_FN_2_IN 0x200
-+#define GPIO_ALT_FN_2_OUT 0x280
-+#define GPIO_ALT_FN_3_IN 0x300
-+#define GPIO_ALT_FN_3_OUT 0x380
-+#define GPIO_MD_MASK_NR 0x07f
-+#define GPIO_MD_MASK_DIR 0x080
-+#define GPIO_MD_MASK_FN 0x300
-+
-+#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN)
-+#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT)
-+#define GPIO8_48MHz_MD ( 8 | GPIO_ALT_FN_1_OUT)
-+#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT)
-+#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT)
-+#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT)
-+#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT)
-+#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT)
-+#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT)
-+#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN)
-+#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT)
-+#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT)
-+#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT)
-+#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
-+#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
-+#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
-+#define GPIO23_SCLK_md (23 | GPIO_ALT_FN_2_OUT)
-+#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
-+#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
-+#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN)
-+#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN)
-+#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN)
-+#define GPIO28_BITCLK_I2S_MD (28 | GPIO_ALT_FN_2_IN)
-+#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
-+#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
-+#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
-+#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
-+#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT)
-+#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT)
-+#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN)
-+#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT)
-+#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN)
-+#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT)
-+#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN)
-+#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
-+#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
-+#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
-+#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
-+#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
-+#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT)
-+#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT)
-+#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN)
-+#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT)
-+#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN)
-+#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT)
-+#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN)
-+#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN)
-+#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT)
-+#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT)
-+#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
-+#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT)
-+#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT)
-+#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
-+#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
-+#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
-+#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
-+#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT)
-+#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT)
-+#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT)
-+#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN)
-+#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN)
-+#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT)
-+#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT)
-+#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT)
-+#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT)
-+#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT)
-+#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT)
-+#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT)
-+#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT)
-+#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT)
-+#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN)
-+#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT)
-+#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT)
-+#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT)
-+#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT)
-+#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT)
-+#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT)
-+#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT)
-+#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT)
-+#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT)
-+#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT)
-+#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT)
-+#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT)
-+#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT)
-+#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT)
-+#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT)
-+#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT)
-+#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT)
-+#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT)
-+#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT)
-+#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT)
-+#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
-+
-+
-+/*
-+ * Power Manager
-+ */
-+
-+#define PMCR __REG(0x40F00000) /* Power Manager Control Register */
-+#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status Register */
-+#define PSPR __REG(0x40F00008) /* Power Manager Scratch Pad Register */
-+#define PWER __REG(0x40F0000C) /* Power Manager Wake-up Enable Register */
-+#define PRER __REG(0x40F00010) /* Power Manager GPIO Rising-Edge Detect Enable Register */
-+#define PFER __REG(0x40F00014) /* Power Manager GPIO Falling-Edge Detect Enable Register */
-+#define PEDR __REG(0x40F00018) /* Power Manager GPIO Edge Detect Status Register */
-+#define PCFR __REG(0x40F0001C) /* Power Manager General Configuration Register */
-+#define PGSR0 __REG(0x40F00020) /* Power Manager GPIO Sleep State Register for GP[31-0] */
-+#define PGSR1 __REG(0x40F00024) /* Power Manager GPIO Sleep State Register for GP[63-32] */
-+#define PGSR2 __REG(0x40F00028) /* Power Manager GPIO Sleep State Register for GP[84-64] */
-+#define RCSR __REG(0x40F00030) /* Reset Controller Status Register */
-+
-+#define PSSR_RDH (1 << 5) /* Read Disable Hold */
-+#define PSSR_PH (1 << 4) /* Peripheral Control Hold */
-+#define PSSR_VFS (1 << 2) /* VDD Fault Status */
-+#define PSSR_BFS (1 << 1) /* Battery Fault Status */
-+#define PSSR_SSS (1 << 0) /* Software Sleep Status */
-+
-+#define PCFR_DS (1 << 3) /* Deep Sleep Mode */
-+#define PCFR_FS (1 << 2) /* Float Static Chip Selects */
-+#define PCFR_FP (1 << 1) /* Float PCMCIA controls */
-+#define PCFR_OPDE (1 << 0) /* 3.6864 MHz oscillator power-down enable */
-+
-+#define RCSR_GPR (1 << 3) /* GPIO Reset */
-+#define RCSR_SMR (1 << 2) /* Sleep Mode */
-+#define RCSR_WDR (1 << 1) /* Watchdog Reset */
-+#define RCSR_HWR (1 << 0) /* Hardware Reset */
-+
-+
-+/*
-+ * SSP Serial Port Registers
-+ */
-+
-+#define SSCR0 __REG(0x41000000) /* SSP Control Register 0 */
-+#define SSCR1 __REG(0x41000004) /* SSP Control Register 1 */
-+#define SSSR __REG(0x41000008) /* SSP Status Register */
-+#define SSITR __REG(0x4100000C) /* SSP Interrupt Test Register */
-+#define SSDR __REG(0x41000010) /* (Write / Read) SSP Data Write Register/SSP Data Read Register */
-+
-+
-+/*
-+ * MultiMediaCard (MMC) controller
-+ */
-+
-+#define MMC_STRPCL __REG(0x41100000) /* Control to start and stop MMC clock */
-+#define MMC_STAT __REG(0x41100004) /* MMC Status Register (read only) */
-+#define MMC_CLKRT __REG(0x41100008) /* MMC clock rate */
-+#define MMC_SPI __REG(0x4110000c) /* SPI mode control bits */
-+#define MMC_CMDAT __REG(0x41100010) /* Command/response/data sequence control */
-+#define MMC_RESTO __REG(0x41100014) /* Expected response time out */
-+#define MMC_RDTO __REG(0x41100018) /* Expected data read time out */
-+#define MMC_BLKLEN __REG(0x4110001c) /* Block length of data transaction */
-+#define MMC_NOB __REG(0x41100020) /* Number of blocks, for block mode */
-+#define MMC_PRTBUF __REG(0x41100024) /* Partial MMC_TXFIFO FIFO written */
-+#define MMC_I_MASK __REG(0x41100028) /* Interrupt Mask */
-+#define MMC_I_REG __REG(0x4110002c) /* Interrupt Register (read only) */
-+#define MMC_CMD __REG(0x41100030) /* Index of current command */
-+#define MMC_ARGH __REG(0x41100034) /* MSW part of the current command argument */
-+#define MMC_ARGL __REG(0x41100038) /* LSW part of the current command argument */
-+#define MMC_RES __REG(0x4110003c) /* Response FIFO (read only) */
-+#define MMC_RXFIFO __REG(0x41100040) /* Receive FIFO (read only) */
-+#define MMC_TXFIFO __REG(0x41100044) /* Transmit FIFO (write only) */
-+
-+
-+/*
-+ * Core Clock
-+ */
-+
-+#define CCCR __REG(0x41300000) /* Core Clock Configuration Register */
-+#define CKEN __REG(0x41300004) /* Clock Enable Register */
-+#define OSCC __REG(0x41300008) /* Oscillator Configuration Register */
-+
-+#define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */
-+#define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */
-+#define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */
-+
-+#define CKEN16_LCD (1 << 16) /* LCD Unit Clock Enable */
-+#define CKEN14_I2C (1 << 14) /* I2C Unit Clock Enable */
-+#define CKEN13_FICP (1 << 13) /* FICP Unit Clock Enable */
-+#define CKEN12_MMC (1 << 12) /* MMC Unit Clock Enable */
-+#define CKEN11_USB (1 << 11) /* USB Unit Clock Enable */
-+#define CKEN8_I2S (1 << 8) /* I2S Unit Clock Enable */
-+#define CKEN7_BTUART (1 << 7) /* BTUART Unit Clock Enable */
-+#define CKEN6_FFUART (1 << 6) /* FFUART Unit Clock Enable */
-+#define CKEN5_STUART (1 << 5) /* STUART Unit Clock Enable */
-+#define CKEN3_SSP (1 << 3) /* SSP Unit Clock Enable */
-+#define CKEN2_AC97 (1 << 2) /* AC97 Unit Clock Enable */
-+#define CKEN1_PWM1 (1 << 1) /* PWM1 Clock Enable */
-+#define CKEN0_PWM0 (1 << 0) /* PWM0 Clock Enable */
-+
-+#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
-+#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
-+
-+
-+/*
-+ * LCD
-+ */
-+
-+#define LCCR0 __REG(0x44000000) /* LCD Controller Control Register 0 */
-+#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
-+#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
-+#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
-+#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
-+#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
-+#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
-+#define LIIDR __REG(0x4400003C) /* LCD Controller Interrupt ID Register */
-+#define TMEDRGBR __REG(0x44000040) /* TMED RGB Seed Register */
-+#define TMEDCR __REG(0x44000044) /* TMED Control Register */
-+
-+#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
-+#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
-+#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
-+#define LDCMD0 __REG(0x4400020C) /* DMA Channel 0 Command Register */
-+#define FDADR1 __REG(0x44000210) /* DMA Channel 1 Frame Descriptor Address Register */
-+#define FSADR1 __REG(0x44000214) /* DMA Channel 1 Frame Source Address Register */
-+#define FIDR1 __REG(0x44000218) /* DMA Channel 1 Frame ID Register */
-+#define LDCMD1 __REG(0x4400021C) /* DMA Channel 1 Command Register */
-+
-+#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
-+#define LCCR0_CMS (1 << 1) /* Color = 0, Monochrome = 1 */
-+#define LCCR0_SDS (1 << 2) /* Single Panel = 0, Dual Panel = 1 */
-+#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
-+#define LCCR0_SFM (1 << 4) /* Start of frame mask */
-+#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
-+#define LCCR0_EFM (1 << 6) /* End of Frame mask */
-+#define LCCR0_PAS (1 << 7) /* Passive = 0, Active = 1 */
-+#define LCCR0_BLE (1 << 8) /* Little Endian = 0, Big Endian = 1 */
-+#define LCCR0_DPD (1 << 9) /* Double Pixel mode, 4 pixel value = 0, 8 pixle values = 1 */
-+#define LCCR0_DIS (1 << 10) /* LCD Disable */
-+#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
-+#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
-+#define LCCR0_PDD_S 12
-+#define LCCR0_BM (1 << 20) /* Branch mask */
-+#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
-+
-+#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
-+#define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \
-+ (((Pixel) - 1) << FShft (LCCR1_PPL))
-+
-+#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
-+#define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \
-+ /* pulse Width [1..64 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_HSW))
-+
-+#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */
-+ /* count - 1 [Tpix] */
-+#define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \
-+ /* [1..256 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_ELW))
-+
-+#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
-+ /* Wait count - 1 [Tpix] */
-+#define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \
-+ /* [1..256 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_BLW))
-+
-+
-+#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
-+#define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \
-+ (((Line) - 1) << FShft (LCCR2_LPP))
-+
-+#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */
-+ /* Width - 1 [Tln] (L_FCLK) */
-+#define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \
-+ /* Width [1..64 Tln] */ \
-+ (((Tln) - 1) << FShft (LCCR2_VSW))
-+
-+#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
-+ /* count [Tln] */
-+#define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \
-+ /* [0..255 Tln] */ \
-+ ((Tln) << FShft (LCCR2_EFW))
-+
-+#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
-+ /* Wait count [Tln] */
-+#define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \
-+ /* [0..255 Tln] */ \
-+ ((Tln) << FShft (LCCR2_BFW))
-+
-+#if 0
-+#define LCCR3_PCD (0xff) /* Pixel clock divisor */
-+#define LCCR3_ACB (0xff << 8) /* AC Bias pin frequency */
-+#define LCCR3_ACB_S 8
-+#endif
-+
-+#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
-+#define LCCR3_API_S 16
-+#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
-+#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
-+#define LCCR3_PCP (1 << 22) /* pixel clock polarity */
-+#define LCCR3_OEP (1 << 23) /* output enable polarity */
-+#if 0
-+#define LCCR3_BPP (7 << 24) /* bits per pixel */
-+#define LCCR3_BPP_S 24
-+#endif
-+#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
-+
-+
-+#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
-+#define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \
-+ (((Div) << FShft (LCCR3_PCD)))
-+
-+
-+#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
-+#define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \
-+ (((Bpp) << FShft (LCCR3_BPP)))
-+
-+#define LCCR3_ACB Fld (8, 8) /* AC Bias */
-+#define LCCR3_Acb(Acb) /* BAC Bias */ \
-+ (((Acb) << FShft (LCCR3_ACB)))
-+
-+#define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */
-+ /* pulse active High */
-+#define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */
-+
-+#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */
-+ /* active High */
-+#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */
-+ /* active Low */
-+
-+#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-+#define LCSR_SOF (1 << 1) /* Start of frame */
-+#define LCSR_BER (1 << 2) /* Bus error */
-+#define LCSR_ABC (1 << 3) /* AC Bias count */
-+#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-+#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-+#define LCSR_OU (1 << 6) /* output FIFO underrun */
-+#define LCSR_QD (1 << 7) /* quick disable */
-+#define LCSR_EOF (1 << 8) /* end of frame */
-+#define LCSR_BS (1 << 9) /* branch status */
-+#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-+
-+#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-+
-+#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-+#define LCSR_SOF (1 << 1) /* Start of frame */
-+#define LCSR_BER (1 << 2) /* Bus error */
-+#define LCSR_ABC (1 << 3) /* AC Bias count */
-+#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-+#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-+#define LCSR_OU (1 << 6) /* output FIFO underrun */
-+#define LCSR_QD (1 << 7) /* quick disable */
-+#define LCSR_EOF (1 << 8) /* end of frame */
-+#define LCSR_BS (1 << 9) /* branch status */
-+#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-+
-+#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-+
-+/*
-+ * Memory controller
-+ */
-+
-+#define MDCNFG __REG(0x48000000) /* SDRAM Configuration Register 0 */
-+#define MDREFR __REG(0x48000004) /* SDRAM Refresh Control Register */
-+#define MSC0 __REG(0x48000008) /* Static Memory Control Register 0 */
-+#define MSC1 __REG(0x4800000C) /* Static Memory Control Register 1 */
-+#define MSC2 __REG(0x48000010) /* Static Memory Control Register 2 */
-+#define MECR __REG(0x48000014) /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
-+#define SXLCR __REG(0x48000018) /* LCR value to be written to SDRAM-Timing Synchronous Flash */
-+#define SXCNFG __REG(0x4800001C) /* Synchronous Static Memory Control Register */
-+#define SXMRS __REG(0x48000024) /* MRS value to be written to Synchronous Flash or SMROM */
-+#define MCMEM0 __REG(0x48000028) /* Card interface Common Memory Space Socket 0 Timing */
-+#define MCMEM1 __REG(0x4800002C) /* Card interface Common Memory Space Socket 1 Timing */
-+#define MCATT0 __REG(0x48000030) /* Card interface Attribute Space Socket 0 Timing Configuration */
-+#define MCATT1 __REG(0x48000034) /* Card interface Attribute Space Socket 1 Timing Configuration */
-+#define MCIO0 __REG(0x48000038) /* Card interface I/O Space Socket 0 Timing Configuration */
-+#define MCIO1 __REG(0x4800003C) /* Card interface I/O Space Socket 1 Timing Configuration */
-+#define MDMRS __REG(0x48000040) /* MRS value to be written to SDRAM */
-+#define BOOT_DEF __REG(0x48000044) /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
-+
-+#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */
-+#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */
-+#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */
-+#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */
-+#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */
-+#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */
-+#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */
-+#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */
-+#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */
-+#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */
-+#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */
-+#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */
-+#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/serial.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,51 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/serial.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#define BAUD_BASE 921600
-+
-+/* Standard COM flags */
-+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
-+
-+#define STD_SERIAL_PORT_DEFNS \
-+ { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&FFUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_FFUART, \
-+ flags: STD_COM_FLAGS, \
-+ }, { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&BTUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_BTUART, \
-+ flags: STD_COM_FLAGS, \
-+ }, { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&STUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_STUART, \
-+ flags: STD_COM_FLAGS, \
-+ }
-+
-+#define RS_TABLE_SIZE 8
-+
-+#define EXTRA_SERIAL_PORT_DEFNS
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/system.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,32 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/system.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "hardware.h"
-+
-+static inline void arch_idle(void)
-+{
-+ cpu_do_idle();
-+}
-+
-+static inline void arch_reset(char mode)
-+{
-+ if (mode == 's') {
-+ /* Jump into ROM at address 0 */
-+ cpu_reset(0);
-+ } else {
-+ /* Initialize the watchdog and let it fire */
-+ OWER = OWER_WME;
-+ OSSR = OSSR_M3;
-+ OSMR3 = OSCR + 368640; /* ... in 100 ms */
-+ }
-+}
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/time.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,86 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/time.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+static inline unsigned long pxa_get_rtc_time(void)
-+{
-+ return RCNR;
-+}
-+
-+static int pxa_set_rtc(void)
-+{
-+ unsigned long current_time = xtime.tv_sec;
-+
-+ if (RTSR & RTSR_ALE) {
-+ /* make sure not to forward the clock over an alarm */
-+ unsigned long alarm = RTAR;
-+ if (current_time >= alarm && alarm >= RCNR)
-+ return -ERESTARTSYS;
-+ }
-+ RCNR = current_time;
-+ return 0;
-+}
-+
-+/* IRQs are disabled before entering here from do_gettimeofday() */
-+static unsigned long pxa_gettimeoffset (void)
-+{
-+ unsigned long ticks_to_match, elapsed, usec;
-+
-+ /* Get ticks before next timer match */
-+ ticks_to_match = OSMR0 - OSCR;
-+
-+ /* We need elapsed ticks since last match */
-+ elapsed = LATCH - ticks_to_match;
-+
-+ /* Now convert them to usec */
-+ usec = (unsigned long)(elapsed*tick)/LATCH;
-+
-+ return usec;
-+}
-+
-+static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ long flags;
-+ int next_match;
-+
-+ do_profile(regs);
-+
-+ /* Loop until we get ahead of the free running timer.
-+ * This ensures an exact clock tick count and time acuracy.
-+ * IRQs are disabled inside the loop to ensure coherence between
-+ * lost_ticks (updated in do_timer()) and the match reg value, so we
-+ * can use do_gettimeofday() from interrupt handlers.
-+ */
-+ do {
-+ do_leds();
-+ do_set_rtc();
-+ save_flags_cli( flags );
-+ do_timer(regs);
-+ OSSR = OSSR_M0; /* Clear match on timer 0 */
-+ next_match = (OSMR0 += LATCH);
-+ restore_flags( flags );
-+ } while( (signed long)(next_match - OSCR) <= 0 );
-+}
-+
-+extern inline void setup_timer (void)
-+{
-+ gettimeoffset = pxa_gettimeoffset;
-+ set_rtc = pxa_set_rtc;
-+ xtime.tv_sec = pxa_get_rtc_time();
-+ timer_irq.handler = pxa_timer_interrupt;
-+ OSMR0 = 0; /* set initial match at 0 */
-+ OSSR = 0xf; /* clear status on all timers */
-+ setup_arm_irq(IRQ_OST0, &timer_irq);
-+ OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */
-+ OSCR = 0; /* initialize free-running timer, force first match */
-+}
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/timex.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,17 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/timex.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * PXA250/210 timer
-+ */
-+#define CLOCK_TICK_RATE 3686400
-+#define CLOCK_TICK_FACTOR 80
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/trizeps2.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,206 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/trizeps2.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Luc De Cock, Teradyne DS, Ltd.
-+ *
-+ * 2002-10-10: Initial code started from idp.h
-+ */
-+
-+
-+/*
-+ * Note: this file must be safe to include in assembly files
-+ */
-+
-+/* comment out following if you have a board with 32MB RAM */
-+//#define PXA_TRIZEPS2_64MB 1
-+#undef PXA_TRIZEPS2_64MB
-+
-+#define TRIZEPS2_FLASH_PHYS (PXA_CS0_PHYS)
-+#define TRIZEPS2_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define TRIZEPS2_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define TRIZEPS2_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define TRIZEPS2_ETH_PHYS (0x0C800000)
-+#define TRIZEPS2_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define TRIZEPS2_BCR_PHYS (0x0E000000)
-+#define TRIZEPS2_CPLD_PHYS (0x0C000000)
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define TRIZEPS2_IDE_BASE (0xf0000000)
-+#define TRIZEPS2_IDE_SIZE (1*1024*1024)
-+
-+#define TRIZEPS2_ETH_BASE (0xf1000000)
-+#define TRIZEPS2_ETH_SIZE (1*1024*1024)
-+#define ETH_BASE TRIZEPS2_ETH_BASE //smc9194 driver compatibility issue
-+
-+#define TRIZEPS2_COREVOLT_BASE (TRIZEPS2_ETH_BASE + TRIZEPS2_ETH_SIZE)
-+#define TRIZEPS2_COREVOLT_SIZE (1*1024*1024)
-+
-+#define TRIZEPS2_BCR_BASE (0xf0000000)
-+#define TRIZEPS2_BCR_SIZE (1*1024*1024)
-+
-+#define BCR_P2V(x) ((x) - TRIZEPS2_BCR_PHYS + TRIZEPS2_BCR_BASE)
-+#define BCR_V2P(x) ((x) - TRIZEPS2_BCR_BASE + TRIZEPS2_BCR_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __BCR_REG(x) (*((volatile unsigned short *)BCR_P2V(x)))
-+#else
-+# define __BCR_REG(x) BCR_P2V(x)
-+#endif
-+
-+/* board level registers */
-+#define TRIZEPS2_CPLD_BASE (0xf0100000)
-+#define CPLD_P2V(x) ((x) - TRIZEPS2_CPLD_PHYS + TRIZEPS2_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - TRIZEPS2_CPLD_BASE + TRIZEPS2_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned short *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+#define _TRIZEPS2_PCCARD_STATUS (0x0c000000)
-+#define TRIZEPS2_PCCARD_STATUS __CPLD_REG(_TRIZEPS2_PCCARD_STATUS)
-+
-+/*
-+ * CS memory timing via Static Memory Control Register (MSC0-2)
-+ */
-+
-+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
-+
-+#define MSC_RBUFF_SHIFT 15
-+#define MSC_RBUFF(x) ((x)<<MSC_RBUFF_SHIFT)
-+#define MSC_RBUFF_SLOW MSC_RBUFF(0)
-+#define MSC_RBUFF_FAST MSC_RBUFF(1)
-+
-+#define MSC_RRR_SHIFT 12
-+#define MSC_RRR(x) ((x)<<MSC_RRR_SHIFT)
-+
-+#define MSC_RDN_SHIFT 8
-+#define MSC_RDN(x) ((x)<<MSC_RDN_SHIFT)
-+
-+#define MSC_RDF_SHIFT 4
-+#define MSC_RDF(x) ((x)<<MSC_RDF_SHIFT)
-+
-+#define MSC_RBW_SHIFT 3
-+#define MSC_RBW(x) ((x)<<MSC_RBW_SHIFT)
-+#define MSC_RBW_16 MSC_RBW(1)
-+#define MSC_RBW_32 MSC_RBW(0)
-+
-+#define MSC_RT_SHIFT 0
-+#define MSC_RT(x) ((x)<<MSC_RT_SHIFT)
-+
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+// TRIZEPS2_BCR_PCCARD_PWR
-+#define PCC_3V (1 << 0)
-+#define PCC_5V (1 << 1)
-+#define PCC_EN1 (1 << 2)
-+#define PCC_EN0 (1 << 3)
-+
-+// TRIZEPS2_BCR_PCCARD_EN
-+#define PCC_RESET (1 << 6)
-+#define PCC_ENABLE (1 << 0)
-+
-+// TRIZEPS2_BSR_PCCARDx_STATUS
-+#define _PCC_WRPROT (1 << 7) // 7-4 read as low true
-+#define _PCC_RESET (1 << 6)
-+#define _PCC_IRQ (1 << 5)
-+#define _PCC_INPACK (1 << 4)
-+#define PCC_BVD1 (1 << 0)
-+#define PCC_BVD2 (1 << 1)
-+#define PCC_VS1 (1 << 2)
-+#define PCC_VS2 (1 << 3)
-+
-+// TRIZEPS2_BCR_CONTROL bits
-+#define BCR_LCD_ON (1 << 4)
-+#define BCR_LCD_OFF (0)
-+#define BCR_LCD_MASK (1 << 4)
-+#define BCR_PCMCIA_RESET (1 << 7)
-+#define BCR_PCMCIA_NORMAL (0)
-+
-+#define PCC_DETECT (GPLR(24) & GPIO_bit(24))
-+#define PCC_READY (GPLR(1) & GPIO_bit(1))
-+
-+// Board Control Register
-+#define _TRIZEPS2_BCR_CONTROL (TRIZEPS2_BCR_PHYS)
-+#define TRIZEPS2_BCR_CONTROL __BCR_REG(_TRIZEPS2_BCR_CONTROL)
-+
-+// Board TTL-IO register
-+#define TRIZEPS2_TTLIO_PHYS (0x0d800000)
-+#define TRIZEPS2_TTLIO_BASE (0xf2000000)
-+// various ioctl cmds
-+#define TTLIO_RESET 0
-+#define TTLIO_GET 1
-+#define TTLIO_SET 2
-+#define TTLIO_UNSET 3
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON()
-+#define FB_BACKLIGHT_OFF()
-+
-+#define FB_PWR_ON()
-+#define FB_PWR_OFF()
-+
-+#define FB_VLCD_ON() WRITE_TRIZEPS2_BCR(BCR_LCD_ON,BCR_LCD_MASK);
-+#define FB_VLCD_OFF() WRITE_TRIZEPS2_BCR(BCR_LCD_OFF,BCR_LCD_MASK);
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#define GPIO_TOUCH_PANEL_IRQ 2
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(GPIO_TOUCH_PANEL_IRQ)
-+#define GPIO_ETHERNET_IRQ 19
-+#define ETHERNET_IRQ IRQ_GPIO(GPIO_ETHERNET_IRQ)
-+#define GPIO_TTLIO_IRQ 23
-+#define TTLIO_IRQ IRQ_GPIO(GPIO_TTLIO_IRQ)
-+
-+#define TOUCH_PANEL_IRQ_EDGE GPIO_FALLING_EDGE
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define PCMCIA_S_CD_VALID IRQ_GPIO(24)
-+#define PCMCIA_S_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S_RDYINT IRQ_GPIO(1)
-+#define PCMCIA_S_RDYINT_EDGE GPIO_FALLING_EDGE
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() // ((TRIZEPS2_CPLD_FLASH_WE) &= ~(0x1))
-+#define FLASH_WRITE_PROTECT_ENABLE() // ((TRIZEPS2_CPLD_FLASH_WE) |= (0x1))
-+
-+/* shadow registers for write only registers */
-+#ifndef __ASSEMBLY__
-+extern unsigned short trizeps2_bcr_shadow;
-+#endif
-+
-+/*
-+ * macros to write to write only register
-+ *
-+ * none of these macros are protected from
-+ * multiple drivers using them in interrupt context.
-+ */
-+
-+#define WRITE_TRIZEPS2_BCR(value, mask) \
-+{\
-+ trizeps2_bcr_shadow = ((value & mask) | (trizeps2_bcr_shadow & ~mask));\
-+ TRIZEPS2_BCR_CONTROL = trizeps2_bcr_shadow;\
-+}
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/uncompress.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,42 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/uncompress.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define FFUART ((volatile unsigned long *)0x40100000)
-+#define BTUART ((volatile unsigned long *)0x40200000)
-+#define STUART ((volatile unsigned long *)0x40700000)
-+
-+#define UART FFUART
-+
-+
-+static __inline__ void putc(char c)
-+{
-+ while (!(UART[5] & 0x20));
-+ UART[0] = c;
-+}
-+
-+/*
-+ * This does not append a newline
-+ */
-+static void puts(const char *s)
-+{
-+ while (*s) {
-+ putc(*s);
-+ if (*s == '\n')
-+ putc('\r');
-+ s++;
-+ }
-+}
-+
-+/*
-+ * nothing to do
-+ */
-+#define arch_decomp_setup()
-+#define arch_decomp_wdog()
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-pxa/vmalloc.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,23 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/vmalloc.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * Just any arbitrary offset to the start of the vmalloc VM area: the
-+ * current 8MB value just means that there will be a 8MB "hole" after the
-+ * physical memory until the kernel virtual memory starts. That means that
-+ * any out-of-bounds memory accesses will hopefully be caught.
-+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
-+ * area for the same reason. ;)
-+ */
-+#define VMALLOC_OFFSET (8*1024*1024)
-+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-+#define VMALLOC_END (0xe8000000)
---- linux-2.4.25/include/asm-arm/assembler.h~2.4.25-vrs2-pxa1.patch 2000-08-13 18:54:15.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/assembler.h 2004-03-31 17:15:12.000000000 +0200
-@@ -13,3 +13,26 @@
-
- #include <asm/proc/ptrace.h>
- #include <asm/proc/assembler.h>
-+
-+/*
-+ * Endian independent macros for shifting bytes within registers.
-+ */
-+#ifndef __ARMEB__
-+#define pull lsr
-+#define push lsl
-+#define byte(x) (x*8)
-+#else
-+#define pull lsl
-+#define push lsr
-+#define byte(x) ((3-x)*8)
-+#endif
-+
-+/*
-+ * Data preload for architectures that support it
-+ */
-+#if __LINUX_ARM_ARCH__ >= 5
-+#define PLD(code...) code
-+#else
-+#define PLD(code...)
-+#endif
-+
---- linux-2.4.25/include/asm-arm/bitops.h~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/bitops.h 2004-03-31 17:15:12.000000000 +0200
-@@ -91,6 +91,8 @@
- return (((unsigned char *) addr)[nr >> 3] >> (nr & 7)) & 1;
- }
-
-+#if __LINUX_ARM_ARCH__ < 5
-+
- /*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
-@@ -117,6 +119,23 @@
-
- #define ffs(x) generic_ffs(x)
-
-+#else
-+
-+/*
-+ * On ARMv5 and above those functions can be implemented around
-+ * the clz instruction for much better code efficiency.
-+ */
-+
-+extern __inline__ int generic_fls(int x);
-+#define fls(x) \
-+ ( __builtin_constant_p(x) ? generic_fls(x) : \
-+ ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
-+#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
-+#define __ffs(x) (ffs(x) - 1)
-+#define ffz(x) __ffs( ~(x) )
-+
-+#endif
-+
- /*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
---- linux-2.4.25/include/asm-arm/io.h~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/io.h 2004-03-31 17:15:12.000000000 +0200
-@@ -168,7 +168,7 @@
- * devices. This is the "generic" version. The PCI specific version
- * is in pci.h
- */
--extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
-+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags);
- extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
- extern void consistent_sync(void *vaddr, size_t size, int rw);
-
---- linux-2.4.25/include/asm-arm/memory.h~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/memory.h 2004-03-31 17:15:12.000000000 +0200
-@@ -123,6 +123,9 @@
- ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size)); \
- })
-
-+/* We want large page mapping possible */
-+#define VMALLOC_ALIGN 0x10000
-+
- #endif
-
- /*
---- linux-2.4.25/include/asm-arm/proc-armv/pgtable.h~2.4.25-vrs2-pxa1.patch 2001-08-12 20:14:00.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-armv/pgtable.h 2004-03-31 17:15:12.000000000 +0200
-@@ -15,9 +15,6 @@
- #ifndef __ASM_PROC_PGTABLE_H
- #define __ASM_PROC_PGTABLE_H
-
--#include <asm/proc/domain.h>
--#include <asm/arch/vmalloc.h>
--
- /*
- * entries per page directory level: they are two-level, so
- * we don't really have any PMD directory.
-@@ -26,27 +23,92 @@
- #define PTRS_PER_PMD 1
- #define PTRS_PER_PGD 4096
-
--/****************
--* PMD functions *
--****************/
--
--/* PMD types (actually level 1 descriptor) */
--#define PMD_TYPE_MASK 0x0003
--#define PMD_TYPE_FAULT 0x0000
--#define PMD_TYPE_TABLE 0x0001
--#define PMD_TYPE_SECT 0x0002
--#define PMD_UPDATABLE 0x0010
--#define PMD_SECT_CACHEABLE 0x0008
--#define PMD_SECT_BUFFERABLE 0x0004
--#define PMD_SECT_AP_WRITE 0x0400
--#define PMD_SECT_AP_READ 0x0800
-+/*
-+ * Hardware page table definitions.
-+ *
-+ * + Level 1 descriptor (PMD)
-+ * - common
-+ */
-+#define PMD_TYPE_MASK (3 << 0)
-+#define PMD_TYPE_FAULT (0 << 0)
-+#define PMD_TYPE_TABLE (1 << 0)
-+#define PMD_TYPE_SECT (2 << 0)
-+#define PMD_UPDATABLE (1 << 4)
- #define PMD_DOMAIN(x) ((x) << 5)
-+#define PMD_PROTECTION (1 << 9) /* v5 */
-+/*
-+ * - section
-+ */
-+#define PMD_SECT_BUFFERABLE (1 << 2)
-+#define PMD_SECT_CACHEABLE (1 << 3)
-+#define PMD_SECT_AP_WRITE (1 << 10)
-+#define PMD_SECT_AP_READ (1 << 11)
-+#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
-+/*
-+ * - coarse table
-+ */
-+
-+/*
-+ * + Level 2 descriptor (PTE)
-+ * - common
-+ */
-+#define PTE_TYPE_MASK (3 << 0)
-+#define PTE_TYPE_FAULT (0 << 0)
-+#define PTE_TYPE_LARGE (1 << 0)
-+#define PTE_TYPE_SMALL (2 << 0)
-+#define PTE_TYPE_EXT (3 << 0) /* v5 */
-+#define PTE_BUFFERABLE (1 << 2)
-+#define PTE_CACHEABLE (1 << 3)
-+
-+/*
-+ * - extended small page/tiny page
-+ */
-+#define PTE_EXT_AP_UNO_SRO (0 << 4)
-+#define PTE_EXT_AP_UNO_SRW (1 << 4)
-+#define PTE_EXT_AP_URO_SRW (2 << 4)
-+#define PTE_EXT_AP_URW_SRW (3 << 4)
-+#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
-+
-+/*
-+ * - small page
-+ */
-+#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
-+#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
-+#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
-+#define PTE_SMALL_AP_URW_SRW (0xff << 4)
-+#define PTE_AP_READ PTE_SMALL_AP_URO_SRW
-+#define PTE_AP_WRITE PTE_SMALL_AP_UNO_SRW
-+
-+/*
-+ * "Linux" PTE definitions.
-+ *
-+ * We keep two sets of PTEs - the hardware and the linux version.
-+ * This allows greater flexibility in the way we map the Linux bits
-+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
-+ * bits.
-+ *
-+ * The PTE table pointer refers to the hardware entries; the "Linux"
-+ * entries are stored 1024 bytes below.
-+ */
-+#define L_PTE_PRESENT (1 << 0)
-+#define L_PTE_YOUNG (1 << 1)
-+#define L_PTE_BUFFERABLE (1 << 2) /* matches PTE */
-+#define L_PTE_CACHEABLE (1 << 3) /* matches PTE */
-+#define L_PTE_USER (1 << 4)
-+#define L_PTE_WRITE (1 << 5)
-+#define L_PTE_EXEC (1 << 6)
-+#define L_PTE_DIRTY (1 << 7)
-+
-+#ifndef __ASSEMBLY__
-+
-+#include <asm/proc/domain.h>
-+#include <asm/arch/vmalloc.h>
-
- #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
- #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
-
- #define pmd_bad(pmd) (pmd_val(pmd) & 2)
--#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp,pmd)
-+#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd)
-
- static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
- {
-@@ -75,49 +137,8 @@
- return __phys_to_virt(ptr);
- }
-
--/****************
--* PTE functions *
--****************/
--
--/* PTE types (actually level 2 descriptor) */
--#define PTE_TYPE_MASK 0x0003
--#define PTE_TYPE_FAULT 0x0000
--#define PTE_TYPE_LARGE 0x0001
--#define PTE_TYPE_SMALL 0x0002
--#define PTE_AP_READ 0x0aa0
--#define PTE_AP_WRITE 0x0550
--#define PTE_CACHEABLE 0x0008
--#define PTE_BUFFERABLE 0x0004
--
- #define set_pte(ptep, pte) cpu_set_pte(ptep,pte)
-
--/* We now keep two sets of ptes - the physical and the linux version.
-- * This gives us many advantages, and allows us greater flexibility.
-- *
-- * The Linux pte's contain:
-- * bit meaning
-- * 0 page present
-- * 1 young
-- * 2 bufferable - matches physical pte
-- * 3 cacheable - matches physical pte
-- * 4 user
-- * 5 write
-- * 6 execute
-- * 7 dirty
-- * 8-11 unused
-- * 12-31 virtual page address
-- *
-- * These are stored at the pte pointer; the physical PTE is at -1024bytes
-- */
--#define L_PTE_PRESENT (1 << 0)
--#define L_PTE_YOUNG (1 << 1)
--#define L_PTE_BUFFERABLE (1 << 2)
--#define L_PTE_CACHEABLE (1 << 3)
--#define L_PTE_USER (1 << 4)
--#define L_PTE_WRITE (1 << 5)
--#define L_PTE_EXEC (1 << 6)
--#define L_PTE_DIRTY (1 << 7)
--
- /*
- * The following macros handle the cache and bufferable bits...
- */
-@@ -162,5 +183,8 @@
- * Mark the prot value as uncacheable and unbufferable.
- */
- #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
-+#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE)
-+
-+#endif /* __ASSEMBLY__ */
-
- #endif /* __ASM_PROC_PGTABLE_H */
---- linux-2.4.25/include/asm-arm/proc-armv/processor.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-armv/processor.h 2004-03-31 17:15:12.000000000 +0200
-@@ -23,6 +23,9 @@
- #define KERNEL_STACK_SIZE PAGE_SIZE
-
- struct context_save_struct {
-+#ifdef CONFIG_CPU_XSCALE
-+ long long acc0;
-+#endif
- unsigned long cpsr;
- unsigned long r4;
- unsigned long r5;
-@@ -35,7 +38,11 @@
- unsigned long pc;
- };
-
-+#ifdef CONFIG_CPU_XSCALE
-+#define INIT_CSS (struct context_save_struct){ 0, SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-+#else
- #define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-+#endif
-
- #define EXTRA_THREAD_STRUCT \
- unsigned int domain;
---- linux-2.4.25/include/asm-arm/proc-fns.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-fns.h 2004-03-31 17:15:12.000000000 +0200
-@@ -124,6 +124,14 @@
- # define CPU_NAME sa1100
- # endif
- # endif
-+# ifdef CONFIG_CPU_XSCALE
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME xscale
-+# endif
-+# endif
- #endif
-
- #ifndef MULTI_CPU
---- linux-2.4.25/include/asm-arm/procinfo.h~2.4.25-vrs2-pxa1.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/procinfo.h 2004-03-31 17:15:12.000000000 +0200
-@@ -55,7 +55,8 @@
- #define HWCAP_FAST_MULT 16
- #define HWCAP_FPA 32
- #define HWCAP_VFP 64
--#define HWCAP_EDSP 128
-+#define HWCAP_EDSP 128 /* El Segundo */
- #define HWCAP_JAVA 256
-+#define HWCAP_XSCALE 512 /* XScale DSP co-processor */
-
- #endif
---- linux-2.4.25/include/asm-arm/uaccess.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/uaccess.h 2004-03-31 17:15:12.000000000 +0200
-@@ -86,7 +86,7 @@
- __get_user_x(__r1, __p, __e, 1, "lr"); \
- break; \
- case 2: \
-- __get_user_x(__r1, __p, __e, 2, "r2", "lr"); \
-+ __get_user_x(__r1, __p, __e, 2, "ip", "lr"); \
- break; \
- case 4: \
- __get_user_x(__r1, __p, __e, 4, "lr"); \
---- linux-2.4.25/include/linux/cramfs_fs_sb.h~2.4.25-vrs2-pxa1.patch 2001-07-20 01:14:53.000000000 +0200
-+++ linux-2.4.25/include/linux/cramfs_fs_sb.h 2004-03-31 17:15:12.000000000 +0200
-@@ -10,6 +10,10 @@
- unsigned long blocks;
- unsigned long files;
- unsigned long flags;
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ unsigned long linear_phys_addr;
-+ char * linear_virt_addr;
-+#endif
- };
-
- #endif
---- linux-2.4.25/include/linux/i2c-id.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/linux/i2c-id.h 2004-03-31 17:15:12.000000000 +0200
-@@ -100,6 +100,10 @@
- #define I2C_DRIVERID_SAA7191 57 /* video decoder */
- #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
-
-+#define I2C_DRIVERID_DS1307 46 /* real time clock: DS1307 */
-+#define I2C_DRIVERID_24LC64 47 /* EEprom 24LC64 */
-+#define I2C_DRIVERID_FM24CLB4 48 /* EEprom FM24CLB4 */
-+
- #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
- #define I2C_DRIVERID_EXP1 0xF1
- #define I2C_DRIVERID_EXP2 0xF2
-@@ -172,6 +176,8 @@
-
- #define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
-
-+#define I2C_ALGO_PXA 0x400000 /* Intel PXA I2C algorithm */
-+
- #define I2C_ALGO_EXP 0x800000 /* experimental */
-
- #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
---- linux-2.4.25/include/linux/serial.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/linux/serial.h 2004-03-31 17:15:12.000000000 +0200
-@@ -75,11 +75,13 @@
- #define PORT_16654 11
- #define PORT_16850 12
- #define PORT_RSA 13 /* RSA-DV II/S card */
--#define PORT_MAX 13
-+#define PORT_PXA 14
-+#define PORT_MAX 14
-
- #define SERIAL_IO_PORT 0
- #define SERIAL_IO_HUB6 1
- #define SERIAL_IO_MEM 2
-+#define SERIAL_IO_MEM32 3
-
- struct serial_uart_config {
- char *name;
---- linux-2.4.25/include/linux/serial_reg.h~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/include/linux/serial_reg.h 2004-03-31 17:15:12.000000000 +0200
-@@ -119,6 +119,14 @@
- #define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
-
- /*
-+ * The Intel PXA250/210 chip defines those bits
-+ */
-+#define UART_IER_DMAE 0x80 /* DMA Requests Enable */
-+#define UART_IER_UUE 0x40 /* UART Unit Enable */
-+#define UART_IER_NRZE 0x20 /* NRZ coding Enable */
-+#define UART_IER_RTOIE 0x10 /* Receiver Time Out Interrupt Enable */
-+
-+/*
- * These are the definitions for the Modem Control Register
- */
- #define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/mmc/ioctl.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,25 @@
-+/*
-+ * linux/include/linux/mmc/ioctl.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: ioctl.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_IOCTL_H__
-+#define __MMC_IOCTL_H__
-+
-+#include <asm/ioctl.h>
-+
-+/* IOCTL commands provided by MMC subsystem */
-+#define IOCMMCSTRNSMODE _IOW('I',0x0f01,int)
-+#define IOCMMCGTRNSMODE _IOR('I',0x0f02,int)
-+#define IOCMMCGCARDESC _IOR('I',0x0f03,int) /* FIXME */
-+#define IOCMMCGBLKSZMAX _IOR('I',0x0f04,ssize_t)
-+#define IOCMMCGNOBMAX _IOR('I',0x0f05,ssize_t)
-+
-+#endif /* __MMC_IOCTL_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/mmc/mmc.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,143 @@
-+/*
-+ * linux/include/linux/mmc/mmc.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc.h,v 0.2.1.2 2002/07/25 16:29:47 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_H__
-+#define __MMC_H__
-+
-+#include <linux/types.h>
-+#include <mmc/types.h>
-+
-+/*
-+ * MMC card type
-+ */
-+enum _mmc_type {
-+ MMC_CARD_TYPE_RO = 1,
-+ MMC_CARD_TYPE_RW,
-+ MMC_CARD_TYPE_IO
-+};
-+
-+/*
-+ * MMC card state
-+ */
-+enum _mmc_state {
-+ MMC_CARD_STATE_IDLE = 1,
-+ MMC_CARD_STATE_READY,
-+ MMC_CARD_STATE_IDENT,
-+ MMC_CARD_STATE_STNBY,
-+ MMC_CARD_STATE_TRAN,
-+ MMC_CARD_STATE_DATA,
-+ MMC_CARD_STATE_RCV,
-+ MMC_CARD_STATE_DIS,
-+ MMC_CARD_STATE_UNPLUGGED=0xff
-+};
-+
-+/*
-+ * Data transfer mode
-+ */
-+enum _mmc_transfer_mode {
-+ MMC_TRANSFER_MODE_STREAM = 1,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ MMC_TRANSFER_MODE_UNDEFINED = -1
-+};
-+
-+struct _mmc_card_csd_rec { /* CSD register contents */
-+/* FIXME: BYTE_ORDER */
-+ u8 ecc:2,
-+ file_format:2,
-+ tmp_write_protect:1,
-+ perm_write_protect:1,
-+ copy:1,
-+ file_format_grp:1;
-+ u64 content_prot_app:1,
-+ rsvd3:4,
-+ write_bl_partial:1,
-+ write_bl_len:4,
-+ r2w_factor:3,
-+ default_ecc:2,
-+ wp_grp_enable:1,
-+ wp_grp_size:5,
-+ erase_grp_mult:5,
-+ erase_grp_size:5,
-+ c_size_mult:3,
-+ vdd_w_curr_max:3,
-+ vdd_w_curr_min:3,
-+ vdd_r_curr_max:3,
-+ vdd_r_curr_min:3,
-+ c_size:12,
-+ rsvd2:2,
-+ dsr_imp:1,
-+ read_blk_misalign:1,
-+ write_blk_misalign:1,
-+ read_bl_partial:1;
-+
-+ u16 read_bl_len:4,
-+ ccc:12;
-+ u8 tran_speed;
-+ u8 nsac;
-+ u8 taac;
-+ u8 rsvd1:2,
-+ spec_vers:4,
-+ csd_structure:2;
-+};
-+
-+struct _mmc_card_cid_rec { /* CID register contents */
-+/* FIXME: BYTE_ORDER */
-+ u8 mdt_year:4,
-+ mdt_mon:4;
-+ u32 psn;
-+ u8 prv_minor:4,
-+ prv_major:4;
-+ u8 pnm[6];
-+ u16 oid;
-+ u8 mid;
-+};
-+
-+/*
-+ * Public card description
-+ */
-+struct _mmc_card_info_rec {
-+ mmc_type_t type;
-+ mmc_transfer_mode_t transfer_mode; /* current data transfer mode */
-+ __u16 rca; /* card's RCA assigned during initialization */
-+ struct _mmc_card_csd_rec csd;
-+ struct _mmc_card_cid_rec cid;
-+ __u32 tran_speed; /* kbits */
-+ __u16 read_bl_len;
-+ __u16 write_bl_len;
-+ size_t capacity; /* card's capacity in bytes */
-+};
-+
-+/*
-+ * Micsellaneous defines
-+ */
-+#ifndef SEEK_SET
-+#define SEEK_SET (0)
-+#endif
-+
-+#ifndef SEEK_CUR
-+#define SEEK_CUR (1)
-+#endif
-+
-+#ifndef SEEK_END
-+#define SEEK_END (2)
-+#endif
-+
-+#ifndef TRUE
-+#define TRUE (1)
-+#endif
-+
-+#ifndef FALSE
-+#define FALSE (0)
-+#endif
-+
-+#endif /* __MMC_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/mmc/types.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,29 @@
-+/*
-+ * linux/include/linux/mmc/types.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: types.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_TYPES_H__
-+#define __MMC_TYPES_H__
-+
-+/* MMC card */
-+typedef enum _mmc_type mmc_type_t;
-+typedef enum _mmc_state mmc_state_t;
-+typedef enum _mmc_transfer_mode mmc_transfer_mode_t;
-+
-+typedef struct _mmc_card_csd_rec mmc_card_csd_rec_t;
-+typedef struct _mmc_card_cid_rec mmc_card_cid_rec_t;
-+
-+typedef struct _mmc_card_info_rec mmc_card_info_rec_t;
-+typedef struct _mmc_card_info_rec *mmc_card_info_t;
-+
-+typedef enum _mmc_error mmc_error_t;
-+
-+#endif /* __MMC_TYPES_H__ */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/video/lcdctrl.h 2004-03-31 17:15:12.000000000 +0200
-@@ -0,0 +1,61 @@
-+/*
-+ * lcdctrl.h
-+ *
-+ * Generic LCD control for brightness, contrast, etc.
-+ * Device specific drivers implement a lcdctrl_device and
-+ * provides access to it via lcdctrl_device_get_ops().
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+#ifndef __LCD_CONTROL_H
-+#define __LCD_CONTROL_H
-+
-+#define _LCDCTRL_IOCTL_ON 1
-+#define _LCDCTRL_IOCTL_OFF 2
-+#define _LCDCTRL_IOCTL_INTENSITY 3
-+#define _LCDCTRL_IOCTL_BRIGHTNESS 4
-+#define _LCDCTRL_IOCTL_CONTRAST 5
-+#define _LCDCTRL_IOCTL_GET_BRIGHTNESS 6
-+#define _LCDCTRL_IOCTL_GET_CONTRAST 7
-+#define _LCDCTRL_IOCTL_GET_INTENSITY 8
-+
-+#define _LCD_CONTROL_NAME "lcdctrl"
-+
-+#define LCD_NO_SYNC 0
-+#define LCD_SYNC_NEEDED 1
-+
-+int lcdctrl_enable( void);
-+int lcdctrl_disable( void);
-+
-+/* intensity, contrast, and brightness take values
-+ * between 0..100.
-+ */
-+int lcdctrl_set_intensity( int intensity);
-+int lcdctrl_set_contrast( int contrast, int sync);
-+int lcdctrl_set_brightness( int brightness);
-+
-+int lcdctrl_get_intensity( void);
-+int lcdctrl_get_contrast( void);
-+int lcdctrl_get_brightness( void);
-+
-+struct lcdctrl_device
-+{
-+ int (*init)( int*, int*, int*);
-+ int (*enable)(void);
-+ int (*disable)(void);
-+ int (*set_intensity)( int i);
-+ int (*set_brightness)( int b);
-+ int (*set_contrast)( int c, int sync);
-+};
-+
-+int lcdctrl_init( void);
-+
-+#endif
---- linux-2.4.25/init/do_mounts.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/init/do_mounts.c 2004-03-31 17:15:12.000000000 +0200
-@@ -394,6 +394,16 @@
- }
- #endif
-
-+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
-+static int __init mount_linear_cramfs_root(void)
-+{
-+ void *data = root_mount_data;
-+ if (sys_mount("/dev/root","/root","cramfs",root_mountflags,data) == 0)
-+ return 1;
-+ return 0;
-+}
-+#endif
-+
- static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
- {
- void *handle;
-@@ -759,6 +769,16 @@
-
- static void __init mount_root(void)
- {
-+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
-+ if (ROOT_DEV == MKDEV(0, 0)) {
-+ if (mount_linear_cramfs_root()) {
-+ sys_chdir("/root");
-+ ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
-+ printk("VFS: Mounted root (linear cramfs filesystem).\n");
-+ return;
-+ }
-+ }
-+#endif
- #ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == NFS_MAJOR
- && MINOR(ROOT_DEV) == NFS_MINOR) {
---- linux-2.4.25/mm/memory.c~2.4.25-vrs2-pxa1.patch 2004-03-31 17:15:09.000000000 +0200
-+++ linux-2.4.25/mm/memory.c 2004-03-31 17:15:12.000000000 +0200
-@@ -1018,6 +1018,41 @@
- return 1; /* Minor fault */
-
- bad_wp_page:
-+ if (pte_present(pte) && pte_read(pte)) {
-+ /*
-+ * Handle COW of XIP memory.
-+ * Note that the source memory actually isn't a ram page so
-+ * no struct page is associated to the source pte.
-+ */
-+ char *dst;
-+ int ret;
-+
-+ spin_unlock(&mm->page_table_lock);
-+ new_page = alloc_page(GFP_HIGHUSER);
-+ if (!new_page)
-+ return -1;
-+
-+ /* copy XIP data to memory */
-+ dst = kmap_atomic(new_page, KM_USER0);
-+ ret = copy_from_user(dst, (void*)address, PAGE_SIZE);
-+ kunmap_atomic(dst, KM_USER0);
-+
-+ /* make sure pte didn't change while we dropped the lock */
-+ spin_lock(&mm->page_table_lock);
-+ if (!ret && pte_same(*page_table, pte)) {
-+ ++mm->rss;
-+ break_cow(vma, new_page, address, page_table);
-+ lru_cache_add(new_page);
-+ spin_unlock(&mm->page_table_lock);
-+ return 1; /* Minor fault */
-+ }
-+
-+ /* pte changed: back off */
-+ spin_unlock(&mm->page_table_lock);
-+ page_cache_release(new_page);
-+ return ret ? -1 : 1;
-+ }
-+
- spin_unlock(&mm->page_table_lock);
- printk("do_wp_page: bogus page at address %08lx\n", address);
- return -1;
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2.patch
deleted file mode 100644
index 7f8a7f9a31..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/2.4.25-vrs2.patch
+++ /dev/null
@@ -1,86979 +0,0 @@
-
-#
-# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
-#
-
---- linux-2.4.25/Documentation/Configure.help~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/Documentation/Configure.help 2004-03-31 17:15:08.000000000 +0200
-@@ -4837,6 +4837,13 @@
- Say Y to enable support for Permedia2 AGP frame buffer card from
- 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
-
-+Permedia3 support (EXPERIMENTAL)
-+CONFIG_FB_PM3
-+ This is the frame buffer device driver for the 3DLabs Permedia3
-+ chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
-+ similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
-+ and maybe other boards.
-+
- Phase5 CVisionPPC/BVisionPPC support
- CONFIG_FB_PM2_CVPPC
- Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
-@@ -13125,6 +13132,17 @@
- The module will be called tmspci.o. If you want to compile it
- as a module, say M here and read <file:Documentation/modules.txt>.
-
-+Altera ether00 support
-+CONFIG_ETHER00
-+ This is the driver for Altera's ether00 ethernet mac IP core. Say
-+ Y here if you want to build support for this into the kernel. It
-+ is also available as a module (say M here) that can be inserted/
-+ removed from the kernel at the same time as the PLD is configured.
-+ If this driver is running on an epxa10 development board then it
-+ will generate a suitable hw address based on the board serial
-+ number (MTD support is required for this). Otherwise you will
-+ need to set a suitable hw address using ifconfig.
-+
- Generic TMS380 ISA support
- CONFIG_TMSISA
- This tms380 module supports generic TMS380-based ISA cards.
-@@ -15069,6 +15087,16 @@
- support" be compiled as a module for this driver to be used
- properly.
-
-+Altera's uart00 serial driver
-+CONFIG_SERIAL_UART00
-+ Say Y here if you want to use the hard logic uart on Excalibur. This
-+ driver also supports soft logic implentations of this uart core.
-+
-+Serial console on uart00
-+CONFIG_SERIAL_UART00_CONSOLE
-+ Say Y here if you want to support a serial console on an Excalibur
-+ hard logic uart or uart00 IP core.
-+
- USB ConnectTech WhiteHEAT Serial Driver
- CONFIG_USB_SERIAL_WHITEHEAT
- Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
-@@ -19085,6 +19113,20 @@
- <file:Documentation/modules.txt>.
- The module will be called i2c-velleman.o.
-
-+Guide GPIO adapter
-+CONFIG_I2C_GUIDE
-+ This supports the Iders GUIDE I2C bit-bashing adapter. If you have
-+ selected the GUIDE A07 as your ARM system type, you cannot deselect
-+ this option, as it is required for proper operation of the GUIDE.
-+
-+ This interface uses /dev/i2c-0 (major 89, minor 0).
-+
-+ Say Y if you own such an adapter.
-+
-+ This driver is also available as a module. If you want to compile
-+ it as a module, say M here and read Documentation/modules.txt. The
-+ module will be called i2c-guide.o.
-+
- I2C PCF 8584 interfaces
- CONFIG_I2C_ALGOPCF
- This allows you to use a range of I2C adapters called PCF adapters.
-@@ -20230,6 +20272,17 @@
- <file:Documentation/modules.txt>. The module will be called
- softdog.o.
-
-+SA1100 Internal Watchdog
-+CONFIG_SA1100_WATCHDOG
-+ Watchdog timer embedded into SA11x0 chips. This will reboot your
-+ system when timeout is reached.
-+ NOTE, that once enabled, this timer cannot be disabled.
-+
-+ This driver is also available as a module ( = code which can be
-+ inserted in and removed from the running kernel whenever you want).
-+ If you want to compile it as a module, say M here and read
-+ Documentation/modules.txt. The module will be called sa1100_wdt.o.
-+
- Berkshire Products PC Watchdog
- CONFIG_PCWATCHDOG
- This is the driver for the Berkshire Products PC Watchdog card.
-@@ -21891,6 +21944,30 @@
- from RME. If you want to acess advanced features of the card, read
- Documentation/sound/rme96xx.
-
-+Assabet audio (UDA1341) support
-+CONFIG_SOUND_ASSABET_UDA1341
-+ Say Y or M if you have an Intel Assabet evaluation board and want to
-+ use the Philips UDA 1341 audio chip (the one that drives the stereo
-+ audio output) on the SA1100 SSP port.
-+
-+Compaq iPAQ audio support
-+CONFIG_SOUND_H3600_UDA1341
-+ Say Y or M if you have a Compaq iPaq handheld computer and want to
-+ use its Philips UDA 1341 audio chip.
-+
-+Audio support for SA1111/UDA1341
-+CONFIG_SOUND_SA1111_UDA1341
-+ Say Y or M if you have an SA11x0 system with a Philips UDA 1341
-+ connected to the SA11x1. An example of such a system is the Intel
-+ Assabet evaluation board connected to a Neponset expansion board.
-+
-+Generic DAC on the SA11x0 SSP port
-+CONFIG_SOUND_SA1100SSP
-+ Say Y or M if you have an SA-11x0 system with a DAC on the SSP port.
-+ The LART has an Burr-Brown PCM 1710 digital to analog convertor on
-+ the SSP port, so you want to say Y or M for the LART. It might work
-+ on other SA-1100 platforms, too, but this is not tested.
-+
- Are you using a crosscompiler
- CONFIG_CROSSCOMPILE
- Say Y here if you are compiling the kernel on a different
-@@ -25594,6 +25671,20 @@
- Say Y if configuring for a Pangolin.
- Say N otherwise.
-
-+Shannon
-+CONFIG_SA1100_SHANNON
-+ The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
-+ limited edition webphone produced by Philips. The Shannon is a SA1100
-+ platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
-+ and a telco interface.
-+
-+Simputer
-+CONFIG_SA1100_SIMPUTER
-+ Say Y here if you are using an Intel(R) StrongARM(R) SA-1110
-+ based Simputer. See http://www.simputer.org/ for information
-+ on the Simputer. The Simputer software is actively maintained
-+ by PicoPeta Simputers Pvt. Ltd. (http://www.picopeta.com)
-+
- Victor
- CONFIG_SA1100_VICTOR
- Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
-@@ -25601,6 +25692,14 @@
- <http://www.visuaide.com/pagevictor.en.html> for information on
- this system.
-
-+Radisys Corp. Tulsa
-+CONFIG_SA1100_PFS168
-+ The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based
-+ computer which includes the SA-1111 Microprocessor Companion Chip and other
-+ custom I/O designed to add connectivity and multimedia features for vending
-+ and business machine applications. Say Y here if you require support for
-+ this target.
-+
- # Choice: cerf_ram
- Cerf on-board RAM size
- CONFIG_SA1100_CERF_8MB
-@@ -25668,37 +25767,65 @@
- Say Y if you want support for the ARM920T processor.
- Otherwise, say N.
-
--Support ARM1020 processor
--CONFIG_CPU_ARM1020
-- The ARM1020 is the cached version of the ARM10 processor,
-- with an addition of a floating-point unit.
-+Support ARM922T processor
-+CONFIG_CPU_ARM922T
-+ The ARM922T is a version of the ARM920T, but with smaller
-+ instruction and data caches. It is used in Altera's
-+ Excalibur XA device family.
-
-- Say Y if you want support for the ARM1020 processor.
-+ Say Y if you want support for the ARM922T processor.
- Otherwise, say N.
-
--Disable I-Cache
-+Disable instruction cache
- CONFIG_CPU_ICACHE_DISABLE
-- Say Y here to disable the processor instruction cache. Unless
-- you have a reason not to or are unsure, say N.
-+ Say Y here to disable the processor instruction cache. Unless
-+ you have a reason to do this, say N.
-
--Disable D-Cache
-+Disable data cache
- CONFIG_CPU_DCACHE_DISABLE
-- Say Y here to disable the processor data cache. Unless
-- you have a reason not to or are unsure, say N.
-+ Say Y here to disable the processor data cache. Unless
-+ you have a reason to do this, say N.
-
--Force write through D-cache
-+Use data cache in writethrough mode
- CONFIG_CPU_DCACHE_WRITETHROUGH
-- Say Y here to use the data cache in write-through mode. Unless you
-- specifically require this or are unsure, say N.
-+ Say Y here to use the data cache in writethough mode. Unless you
-+ specifically require this, say N.
-
--Round robin I and D cache replacement algorithm
-+Support ARM1020 processor
-+CONFIG_CPU_ARM1020
-+ The ARM1020 is the 32K cached version of the ARM10 processor,
-+ with an addition of a floating-point unit.
-+
-+ Say Y if you want support for the ARM1020 processor.
-+ Otherwise, say N.
-+
-+Support ARM1022 processor
-+CONFIG_CPU_ARM1022
-+ The ARM1022E is the 16K cached version of the ARM10 processor,
-+ with an addition of a floating-point unit.
-+
-+ Say Y if you want support for the ARM1022 processor.
-+ Otherwise, say N.
-+
-+Force round-robin cache line replacement
- CONFIG_CPU_CACHE_ROUND_ROBIN
-- Say Y here to use the predictable round-robin cache replacement
-- policy. Unless you specifically require this or are unsure, say N.
-+ Say Y here to force the caches to use a round-robin
-+ algorithm when picking a cache line to evict. Unless you
-+ specifically require this, say N.
-+
-+Disable the write buffer
-+CONFIG_CPU_WB_DISABLE
-+ Say Y here to turn off the write buffer (if possible)
-+ Unless you specifically require this, say N. Note that
-+ not all ARM processors allow the write buffer to be
-+ disabled.
-
- Disable branch prediction
- CONFIG_CPU_BPREDICT_DISABLE
-- Say Y here to disable branch prediction. If unsure, say N.
-+ The ARM10 family of processors support branch prediction,
-+ which can significantly speed up execution of loops.
-+ Say Y here to disable branch prediction. Unless you
-+ specifically require this, say N.
-
- Compressed boot loader in ROM/flash
- CONFIG_ZBOOT_ROM
-@@ -25745,6 +25872,11 @@
- Say Y here if you are using the inhand electronics OmniMeter. See
- <http://www.inhandelectronics.com/html/omni1.html> for details.
-
-+HP Laboratories BadgePAD 4
-+CONFIG_SA1100_BADGE4
-+ Say Y here if you want to build a kernel for the HP Laboratories
-+ BadgePAD 4.
-+
- Load kernel using Angel Debug Monitor
- CONFIG_ANGELBOOT
- Say Y if you plan to load the kernel using Angel, ARM Ltd's target
-@@ -25757,6 +25889,15 @@
- board includes 2 serial ports, Ethernet, IRDA, and expansion headers.
- It comes with 16 MB SDRAM and 8 MB flash ROM.
-
-+GUIDEA07
-+CONFIG_ARCH_GUIDEA07
-+ Say Y if you are using a GUIDE (A07) board.
-+
-+ This board is based on the cs89712 processor and shares much common
-+ hardware with the CDB89712 configuration. When you select this
-+ option and the CDB89712 becomes enabled also, don't worry. It's
-+ supposed to be that way.
-+
- CLPS-711X internal ROM bootstrap
- CONFIG_EP72XX_ROM_BOOT
- If you say Y here, your CLPS711x-based kernel will use the bootstrap
-@@ -25785,19 +25926,27 @@
- You may say N here if you are going to load the Acorn FPEmulator
- early in the bootup.
-
-+Math emulation 80-bit support
-+CONFIG_FPE_NWFPE_XP
-+ Say Y to include 80-bit support in the kernel floating-point
-+ emulator. Otherwise, only 32 and 64-bit support is compiled in.
-+ Note that gcc does not generate 80-bit operations by default,
-+ so in most cases this option only enlarges the size of the
-+ floating point emulator without any good reason.
-+
-+ You almost surely want to say N here.
-+
- FastFPE math emulation
- CONFIG_FPE_FASTFPE
- Say Y here to include the FAST floating point emulator in the kernel.
-- This is an experimental much faster emulator which has only 32 bit
-+ This is an experimental much faster emulator which now also has full
- precision for the mantissa. It does not support any exceptions.
-- This makes it very simple, it is approximately 4-8 times faster than
-- NWFPE.
-+ It is very simple, and approximately 3-6 times faster than NWFPE.
-
-- It should be sufficient for most programs. It is definitely not
-- suitable if you do scientific calculations that need double
-- precision for iteration formulas that sum up lots of very small
-- numbers. If you do not feel you need a faster FP emulation you
-- should better choose NWFPE.
-+ It should be sufficient for most programs. It may be not suitable
-+ for scientific calculations, but you have to check this for yourself.
-+ If you do not feel you need a faster FP emulation you should better
-+ choose NWFPE.
-
- It is also possible to say M to build the emulator as a module
- (fastfpe.o). But keep in mind that you should only load the FP
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/arm/Porting 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,135 @@
-+Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
-+
-+Initial definitions
-+-------------------
-+
-+The following symbol definitions rely on you knowing the translation that
-+__virt_to_phys() does for your machine. This macro converts the passed
-+virtual address to a physical address. Normally, it is simply:
-+
-+ phys = virt - PAGE_OFFSET + PHYS_OFFSET
-+
-+
-+Decompressor Symbols
-+--------------------
-+
-+ZTEXTADDR
-+ Start address of decompressor. There's no point in talking about
-+ virtual or physical addresses here, since the MMU will be off at
-+ the time when you call the decompressor code. You normally call
-+ the kernel at this address to start it booting. This doesn't have
-+ to be located in RAM, it can be in flash or other read-only or
-+ read-write addressable medium.
-+
-+ZBSSADDR
-+ Start address of zero-initialised work area for the decompressor.
-+ This must be pointing at RAM. The decompressor will zero initialise
-+ this for you. Again, the MMU will be off.
-+
-+ZRELADDR
-+ This is the address where the decompressed kernel will be written,
-+ and eventually executed. The following constraint must be valid:
-+
-+ __virt_to_phys(TEXTADDR) == ZRELADDR
-+
-+ The initial part of the kernel is carefully coded to be position
-+ independent.
-+
-+INITRD_PHYS
-+ Physical address to place the initial RAM disk. Only relevant if
-+ you are using the bootpImage stuff (which only works on the old
-+ struct param_struct).
-+
-+INITRD_VIRT
-+ Virtual address of the initial RAM disk. The following constraint
-+ must be valid:
-+
-+ __virt_to_phys(INITRD_VIRT) == INITRD_PHYS
-+
-+PARAMS_PHYS
-+ Physical address of the struct param_struct or tag list, giving the
-+ kernel various parameters about its execution environment.
-+
-+
-+Kernel Symbols
-+--------------
-+
-+PHYS_OFFSET
-+ Physical start address of the first bank of RAM.
-+
-+PAGE_OFFSET
-+ Virtual start address of the first bank of RAM. During the kernel
-+ boot phase, virtual address PAGE_OFFSET will be mapped to physical
-+ address PHYS_OFFSET, along with any other mappings you supply.
-+ This should be the same value as TASK_SIZE.
-+
-+TASK_SIZE
-+ The maximum size of a user process in bytes. Since user space
-+ always starts at zero, this is the maximum address that a user
-+ process can access+1. The user space stack grows down from this
-+ address.
-+
-+ Any virtual address below TASK_SIZE is deemed to be user process
-+ area, and therefore managed dynamically on a process by process
-+ basis by the kernel. I'll call this the user segment.
-+
-+ Anything above TASK_SIZE is common to all processes. I'll call
-+ this the kernel segment.
-+
-+ (In other words, you can't put IO mappings below TASK_SIZE, and
-+ hence PAGE_OFFSET).
-+
-+TEXTADDR
-+ Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
-+ This is where the kernel image ends up. With the latest kernels,
-+ it must be located at 32768 bytes into a 128MB region. Previous
-+ kernels placed a restriction of 256MB here.
-+
-+DATAADDR
-+ Virtual address for the kernel data segment. Must not be defined
-+ when using the decompressor.
-+
-+VMALLOC_START
-+VMALLOC_END
-+ Virtual addresses bounding the vmalloc() area. There must not be
-+ any static mappings in this area; vmalloc will overwrite them.
-+ The addresses must also be in the kernel segment (see above).
-+ Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
-+ last virtual RAM address (found using variable high_memory).
-+
-+VMALLOC_OFFSET
-+ Offset normally incorporated into VMALLOC_START to provide a hole
-+ between virtual RAM and the vmalloc area. We do this to allow
-+ out of bounds memory accesses (eg, something writing off the end
-+ of the mapped memory map) to be caught. Normally set to 8MB.
-+
-+Architecture Specific Macros
-+----------------------------
-+
-+BOOT_MEM(pram,pio,vio)
-+ `pram' specifies the physical start address of RAM. Must always
-+ be present, and should be the same as PHYS_OFFSET.
-+
-+ `pio' is the physical address of an 8MB region containing IO for
-+ use with the debugging macros in arch/arm/kernel/debug-armv.S.
-+
-+ `vio' is the virtual address of the 8MB debugging region.
-+
-+ It is expected that the debugging region will be re-initialised
-+ by the architecture specific code later in the code (via the
-+ MAPIO function).
-+
-+BOOT_PARAMS
-+ Same as, and see PARAMS_PHYS.
-+
-+FIXUP(func)
-+ Machine specific fixups, run before memory subsystems have been
-+ initialised.
-+
-+MAPIO(func)
-+ Machine specific function to map IO areas (including the debug
-+ region above).
-+
-+INITIRQ(func)
-+ Machine specific function to initialise interrupts.
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/arm/mem_alignment 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,58 @@
-+Too many problems poped up because of unnoticed misaligned memory access in
-+kernel code lately. Therefore the alignment fixup is now unconditionally
-+configured in for SA11x0 based targets. According to Alan Cox, this is a
-+bad idea to configure it out, but Russell King has some good reasons for
-+doing so on some f***ed up ARM architectures like the EBSA110. However
-+this is not the case on many design I'm aware of, like all SA11x0 based
-+ones.
-+
-+Of course this is a bad idea to rely on the alignment trap to perform
-+unaligned memory access in general. If those access are predictable, you
-+are better to use the macros provided by include/asm/unaligned.h. The
-+alignment trap can fixup misaligned access for the exception cases, but at
-+a high performance cost. It better be rare.
-+
-+Now for user space applications, it is possible to configure the alignment
-+trap to SIGBUS any code performing unaligned access (good for debugging bad
-+code), or even fixup the access by software like for kernel code. The later
-+mode isn't recommended for performance reasons (just think about the
-+floating point emulation that works about the same way). Fix your code
-+instead!
-+
-+Please note that randomly changing the behaviour without good thought is
-+real bad - it changes the behaviour of all unaligned instructions in user
-+space, and might cause programs to fail unexpectedly.
-+
-+To change the alignment trap behavior, simply echo a number into
-+/proc/sys/debug/alignment. The number is made up from various bits:
-+
-+bit behavior when set
-+--- -----------------
-+
-+0 A user process performing an unaligned memory access
-+ will cause the kernel to print a message indicating
-+ process name, pid, pc, instruction, address, and the
-+ fault code.
-+
-+1 The kernel will attempt to fix up the user process
-+ performing the unaligned access. This is of course
-+ slow (think about the floating point emulator) and
-+ not recommended for production use.
-+
-+2 The kernel will send a SIGBUS signal to the user process
-+ performing the unaligned access.
-+
-+Note that not all combinations are supported - only values 0 through 5.
-+(6 and 7 don't make sense).
-+
-+For example, the following will turn on the warnings, but without
-+fixing up or sending SIGBUS signals:
-+
-+ echo 1 > /proc/sys/debug/alignment
-+
-+You can also read the content of the same file to get statistical
-+information on unaligned access occurrences plus the current mode of
-+operation for user space code.
-+
-+
-+Nicolas Pitre, Mar 13, 2001. Modified Russell King, Nov 30, 2001.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/arm/memory.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,74 @@
-+ Kernel Memory Layout on ARM Linux
-+
-+ Russell King <rmk@arm.linux.org.uk>
-+ April 27, 2003 (2.5.68)
-+
-+This document describes the virtual memory layout which the Linux
-+kernel uses for ARM processors. It indicates which regions are
-+free for platforms to use, and which are used by generic code.
-+
-+The ARM CPU is capable of addressing a maximum of 4GB virtual memory
-+space, and this must be shared between user space processes, the
-+kernel, and hardware devices.
-+
-+As the ARM architecture matures, it becomes necessary to reserve
-+certain regions of VM space for use for new facilities; therefore
-+this document may reserve more VM space over time.
-+
-+Start End Use
-+--------------------------------------------------------------------------
-+ffff8000 ffffffff copy_user_page / clear_user_page use.
-+ For SA11xx and Xscale, this is used to
-+ setup a minicache mapping.
-+
-+ffff1000 ffff7fff Reserved.
-+ Platforms must not use this address range.
-+
-+ffff0000 ffff0fff CPU vector page.
-+ The CPU vectors are mapped here if the
-+ CPU supports vector relocation (control
-+ register V bit.)
-+
-+ffe00000 fffeffff Free for platform use, not recommended.
-+
-+ffc00000 ffdfffff 2MB consistent memory mapping.
-+ Memory returned by the consistent_alloc
-+ low level function will be dynamically
-+ mapped here.
-+
-+ff000000 ffbfffff Free for platform use, not recommended.
-+
-+VMALLOC_END ff000000 Free for platform use, recommended.
-+
-+VMALLOC_START VMALLOC_END vmalloc() / ioremap() space.
-+ Memory returned by vmalloc/ioremap will
-+ be dynamically placed in this region.
-+ VMALLOC_START may be based upon the value
-+ of the high_memory variable.
-+
-+PAGE_OFFSET high_memory Kernel direct-mapped RAM region.
-+ This maps the platforms RAM, and typically
-+ maps all platform RAM in a 1:1 relationship.
-+
-+TASK_SIZE PAGE_OFFSET Kernel module space
-+ Kernel modules inserted via insmod are
-+ placed here using dynamic mappings.
-+
-+00001000 TASK_SIZE User space mappings
-+ Per-thread mappings are placed here via
-+ the mmap() system call.
-+
-+00000000 00000fff CPU vector page / null pointer trap
-+ CPUs which do not support vector remapping
-+ place their vector page here. NULL pointer
-+ dereferences by both the kernel and user
-+ space are also caught via this mapping.
-+
-+Please note that mappings which collide with the above areas may result
-+in a non-bootable kernel, or may cause the kernel to (eventually) panic
-+at run time.
-+
-+Since future CPUs may impact the kernel mapping layout, user programs
-+must not access any memory which is not mapped inside their 0x0001000
-+to TASK_SIZE address range. If they wish to access these areas, they
-+must set up their own mappings using open() and mmap().
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq/core.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,94 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U F r e q C o r e
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+ David Kimdon <dwhedon@debian.org>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. CPUFreq core and interfaces
-+2. CPUFreq notifiers
-+
-+1. General Information
-+=======================
-+
-+The CPUFreq core code is located in linux/kernel/cpufreq.c. This
-+cpufreq code offers a standardized interface for the CPUFreq
-+architecture drivers (those pieces of code that do actual
-+frequency transitions), as well as to "notifiers". These are device
-+drivers or other part of the kernel that need to be informed of
-+policy changes (ex. thermal modules like ACPI) or of all
-+frequency changes (ex. timing code) or even need to force certain
-+speed limits (like LCD drivers on ARM architecture). Additionally, the
-+kernel "constant" loops_per_jiffy is updated on frequency changes
-+here.
-+
-+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
-+which make sure that the cpufreq processor driver is correctly
-+registered with the core, and will not be unloaded until
-+cpufreq_put_cpu is called.
-+
-+2. CPUFreq notifiers
-+====================
-+
-+CPUFreq notifiers conform to the standard kernel notifier interface.
-+See linux/include/linux/notifier.h for details on notifiers.
-+
-+There are two different CPUFreq notifiers - policy notifiers and
-+transition notifiers.
-+
-+
-+2.1 CPUFreq policy notifiers
-+----------------------------
-+
-+These are notified when a new policy is intended to be set. Each
-+CPUFreq policy notifier is called three times for a policy transition:
-+
-+1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if
-+ they see a need for this - may it be thermal considerations or
-+ hardware limitations.
-+
-+2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid
-+ hardware failure.
-+
-+3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
-+ - if two hardware drivers failed to agree on a new policy before this
-+ stage, the incompatible hardware shall be shut down, and the user
-+ informed of this.
-+
-+The phase is specified in the second argument to the notifier.
-+
-+The third argument, a void *pointer, points to a struct cpufreq_policy
-+consisting of five values: cpu, min, max, policy and max_cpu_freq. min
-+and max are the lower and upper frequencies (in kHz) of the new
-+policy, policy the new policy, cpu the number of the affected CPU or
-+CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported
-+CPU frequency. This value is given for informational purposes only.
-+
-+
-+2.2 CPUFreq transition notifiers
-+--------------------------------
-+
-+These are notified twice when the CPUfreq driver switches the CPU core
-+frequency and this change has any external implications.
-+
-+The second argument specifies the phase - CPUFREQ_PRECHANGE or
-+CPUFREQ_POSTCHANGE.
-+
-+The third argument is a struct cpufreq_freqs with the following
-+values:
-+cpu - number of the affected CPU or CPUFREQ_ALL_CPUS
-+old - old frequency
-+new - new frequency
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq/cpu-drivers.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,210 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U D r i v e r s
-+
-+ - information for developers -
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. What To Do?
-+1.1 Initialization
-+1.2 Per-CPU Initialization
-+1.3 verify
-+1.4 target or setpolicy?
-+1.5 target
-+1.6 setpolicy
-+2. Frequency Table Helpers
-+
-+
-+
-+1. What To Do?
-+==============
-+
-+So, you just got a brand-new CPU / chipset with datasheets and want to
-+add cpufreq support for this CPU / chipset? Great. Here are some hints
-+on what is neccessary:
-+
-+
-+1.1 Initialization
-+------------------
-+
-+First of all, in an __initcall level 7 or later (preferrably
-+module_init() so that your driver is modularized) function check
-+whether this kernel runs on the right CPU and the right chipset. If
-+so, register a struct cpufreq_driver with the CPUfreq core using
-+cpufreq_register_driver()
-+
-+What shall this struct cpufreq_driver contain?
-+
-+cpufreq_driver.name - The name of this driver.
-+
-+cpufreq_driver.init - A pointer to the per-CPU initialization
-+ function.
-+
-+cpufreq_driver.verify - A pointer to a "verfication" funciton.
-+
-+cpufreq_driver.setpolicy _or_
-+cpufreq_driver.target - See below on the differences.
-+
-+And optionally
-+
-+cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
-+
-+cpufreq_driver.attr - A pointer to a NULL-terminated list of
-+ "struct freq_attr" which allow to
-+ export values to sysfs.
-+
-+
-+1.2 Per-CPU Initialization
-+--------------------------
-+
-+Whenever a new CPU is registered with the device model, or after the
-+cpufreq driver registers itself, the per-CPU initialization fucntion
-+cpufreq_driver.init is called. It takes a struct cpufreq_policy
-+*policy as argument. What to do now?
-+
-+If necessary, activate the CPUfreq support on your CPU (unlock that
-+register etc.).
-+
-+Then, the driver must fill in the following values:
-+
-+policy->cpuinfo.min_freq _and_
-+policy->cpuinfo.max_freq - the minimum and maximum frequency
-+ (in kHz) which is supported by
-+ this CPU
-+policy->cpuinfo.transition_latency the time it takes on this CPU to
-+ switch between two frequencies (if
-+ appropriate, else specify
-+ CPUFREQ_ETERNAL)
-+
-+policy->cur The current operating frequency of
-+ this CPU (if appropriate)
-+policy->min,
-+policy->max,
-+policy->policy and, if neccessary,
-+policy->governor must contain the "default policy" for
-+ this CPU. A few moments later,
-+ cpufreq_driver.verify and either
-+ cpufreq_driver.setpolicy or
-+ cpufreq_driver.target is called with
-+ these values.
-+
-+For setting some of these values, the frequency table helpers might be
-+helpful. See the section 2 for more information on them.
-+
-+
-+1.3 verify
-+------------
-+
-+When the user decides a new policy (consisting of
-+"policy,governor,min,max") shall be set, this policy must be validated
-+so that incompatible values can be corrected. For verifying these
-+values, a frequency table helper and/or the
-+cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
-+int min_freq, unsigned int max_freq) function might be helpful. See
-+section 2 for details on frequency table helpers.
-+
-+You need to make sure that at least one valid frequency (or operating
-+range) is within policy->min and policy->max. If necessary, increase
-+policy->max fist, and only if this is no solution, decreas policy->min.
-+
-+
-+1.4 target or setpolicy?
-+----------------------------
-+
-+Most cpufreq drivers or even most cpu frequency scaling algorithms
-+only allow the CPU to be set to one frequency. For these, you use the
-+->target call.
-+
-+Some cpufreq-capable processors switch the frequency between certain
-+limits on their own. These shall use the ->setpolicy call
-+
-+
-+1.4. target
-+-------------
-+
-+The target call has three arguments: struct cpufreq_policy *policy,
-+unsigned int target_frequency, unsigned int relation.
-+
-+The CPUfreq driver must set the new frequency when called here. The
-+actual frequency must be determined using the following rules:
-+
-+- keep close to "target_freq"
-+- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!)
-+- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal
-+ target_freq. ("L for lowest, but no lower than")
-+- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal
-+ target_freq. ("H for highest, but no higher than")
-+
-+Here again the frequency table helper might assist you - see section 3
-+for details.
-+
-+
-+1.5 setpolicy
-+---------------
-+
-+The setpolicy call only takes a struct cpufreq_policy *policy as
-+argument. You need to set the lower limit of the in-processor or
-+in-chipset dynamic frequency switching to policy->min, the upper limit
-+to policy->max, and -if supported- select a performance-oriented
-+setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
-+powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
-+the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
-+
-+
-+
-+2. Frequency Table Helpers
-+==========================
-+
-+As most cpufreq processors only allow for being set to a few specific
-+frequencies, a "frequency table" with some functions might assist in
-+some work of the processor driver. Such a "frequency table" consists
-+of an array of struct cpufreq_freq_table entries, with any value in
-+"index" you want to use, and the corresponding frequency in
-+"frequency". At the end of the table, you need to add a
-+cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And
-+if you want to skip one entry in the table, set the frequency to
-+CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
-+order.
-+
-+By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table);
-+the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
-+policy->min and policy->max are set to the same values. This is
-+helpful for the per-CPU initialization stage.
-+
-+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table);
-+assures that at least one valid frequency is within policy->min and
-+policy->max, and all other criteria are met. This is helpful for the
-+->verify call.
-+
-+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table,
-+ unsigned int target_freq,
-+ unsigned int relation,
-+ unsigned int *index);
-+
-+is the corresponding frequency table helper for the ->target
-+stage. Just pass the values to this function, and the unsigned int
-+index returns the number of the frequency table entry which contains
-+the frequency the CPU shall be set to. PLEASE NOTE: This is not the
-+"index" which is in this cpufreq_table_entry.index, but instead
-+cpufreq_table[index]. So, the new frequency is
-+cpufreq_table[index].frequency, and the value you stored into the
-+frequency table "index" field is
-+cpufreq_table[index].index.
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq/governors.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,155 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U F r e q G o v e r n o r s
-+
-+ - information for users and developers -
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. What is a CPUFreq Governor?
-+
-+2. Governors In the Linux Kernel
-+2.1 Performance
-+2.2 Powersave
-+2.3 Userspace
-+
-+3. The Governor Interface in the CPUfreq Core
-+
-+
-+
-+1. What Is A CPUFreq Governor?
-+==============================
-+
-+Most cpufreq drivers (in fact, all except one, longrun) or even most
-+cpu frequency scaling algorithms only offer the CPU to be set to one
-+frequency. In order to offer dynamic frequency scaling, the cpufreq
-+core must be able to tell these drivers of a "target frequency". So
-+these specific drivers will be transformed to offer a "->target"
-+call instead of the existing "->setpolicy" call. For "longrun", all
-+stays the same, though.
-+
-+How to decide what frequency within the CPUfreq policy should be used?
-+That's done using "cpufreq governors". Two are already in this patch
-+-- they're the already existing "powersave" and "performance" which
-+set the frequency statically to the lowest or highest frequency,
-+respectively. At least two more such governors will be ready for
-+addition in the near future, but likely many more as there are various
-+different theories and models about dynamic frequency scaling
-+around. Using such a generic interface as cpufreq offers to scaling
-+governors, these can be tested extensively, and the best one can be
-+selected for each specific use.
-+
-+Basically, it's the following flow graph:
-+
-+CPU can be set to switch independetly | CPU can only be set
-+ within specific "limits" | to specific frequencies
-+
-+ "CPUfreq policy"
-+ consists of frequency limits (policy->{min,max})
-+ and CPUfreq governor to be used
-+ / \
-+ / \
-+ / the cpufreq governor decides
-+ / (dynamically or statically)
-+ / what target_freq to set within
-+ / the limits of policy->{min,max}
-+ / \
-+ / \
-+ Using the ->setpolicy call, Using the ->target call,
-+ the limits and the the frequency closest
-+ "policy" is set. to target_freq is set.
-+ It is assured that it
-+ is within policy->{min,max}
-+
-+
-+2. Governors In the Linux Kernel
-+================================
-+
-+2.1 Performance
-+---------------
-+
-+The CPUfreq governor "performance" sets the CPU statically to the
-+highest frequency within the borders of scaling_min_freq and
-+scaling_max_freq.
-+
-+
-+2.1 Powersave
-+-------------
-+
-+The CPUfreq governor "powersave" sets the CPU statically to the
-+lowest frequency within the borders of scaling_min_freq and
-+scaling_max_freq.
-+
-+
-+2.2 Userspace
-+-------------
-+
-+The CPUfreq governor "userspace" allows the user, or any userspace
-+program running with UID "root", to set the CPU to a specifc frequency
-+by making a sysfs file "scaling_setspeed" available in the CPU-device
-+directory.
-+
-+
-+
-+3. The Governor Interface in the CPUfreq Core
-+=============================================
-+
-+A new governor must register itself with the CPUfreq core using
-+"cpufreq_register_governor". The struct cpufreq_governor, which has to
-+be passed to that function, must contain the following values:
-+
-+governor->name - A unique name for this governor
-+governor->governor - The governor callback function
-+governor->owner - .THIS_MODULE for the governor module (if
-+ appropriate)
-+
-+The governor->governor callback is called with the current (or to-be-set)
-+cpufreq_policy struct for that CPU, and an unsigned int event. The
-+following events are currently defined:
-+
-+CPUFREQ_GOV_START: This governor shall start its duty for the CPU
-+ policy->cpu
-+CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU
-+ policy->cpu
-+CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to
-+ policy->min and policy->max.
-+
-+If you need other "events" externally of your driver, _only_ use the
-+cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the
-+CPUfreq core to ensure proper locking.
-+
-+
-+The CPUfreq governor may call the CPU processor driver using one of
-+these two functions:
-+
-+inline int cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation);
-+
-+inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation);
-+
-+target_freq must be within policy->min and policy->max, of course.
-+What's the difference between these two functions? When your governor
-+still is in a direct code path of a call to governor->governor, the
-+cpufreq_driver_sem lock is still held in the cpufreq core, and there's
-+no need to lock it again (in fact, this would cause a deadlock). So
-+use cpufreq_driver_target only in these cases. In all other cases (for
-+example, when there's a "daemonized" function that wakes up every
-+second), use cpufreq_driver_target_l to lock the cpufreq_driver_sem
-+before the command is passed to the cpufreq processor driver.
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq/index.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,56 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+
-+Documents in this directory:
-+----------------------------
-+core.txt - General description of the CPUFreq core and
-+ of CPUFreq notifiers
-+
-+cpu-drivers.txt - How to implement a new cpufreq processor driver
-+
-+governors.txt - What are cpufreq governors and how to
-+ implement them?
-+
-+index.txt - File index, Mailing list and Links (this document)
-+
-+user-guide.txt - User Guide to CPUFreq
-+
-+
-+Mailing List
-+------------
-+There is a CPU frequency changing CVS commit and general list where
-+you can report bugs, problems or submit patches. To post a message,
-+send an email to cpufreq@www.linux.org.uk, to subscribe go to
-+http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
-+mailing list are available to subscribers at
-+http://www.linux.org.uk/mailman/private/cpufreq/.
-+
-+
-+Links
-+-----
-+the FTP archives:
-+* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
-+
-+how to access the CVS repository:
-+* http://cvs.arm.linux.org.uk/
-+
-+the CPUFreq Mailing list:
-+* http://www.linux.org.uk/mailman/listinfo/cpufreq
-+
-+Clock and voltage scaling for the SA-1100:
-+* http://www.lart.tudelft.nl/projects/scaling
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq/user-guide.txt 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,166 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ U S E R G U I D E
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. Supported Architectures and Processors
-+1.1 ARM
-+1.2 x86
-+1.3 sparc64
-+
-+2. "Policy" / "Governor"?
-+2.1 Policy
-+2.2 Governor
-+
-+3. How to change the CPU cpufreq policy and/or speed
-+3.1 Preferred interface: sysfs
-+3.2 Deprecated interfaces
-+
-+
-+
-+1. Supported Architectures and Processors
-+=========================================
-+
-+1.1 ARM
-+-------
-+
-+The following ARM processors are supported by cpufreq:
-+
-+ARM Integrator
-+ARM-SA1100
-+ARM-SA1110
-+
-+
-+1.2 x86
-+-------
-+
-+The following processors for the x86 architecture are supported by cpufreq:
-+
-+AMD Elan - SC400, SC410
-+AMD mobile K6-2+
-+AMD mobile K6-3+
-+Cyrix Media GXm
-+Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets
-+Intel Pentium 4, Intel Xeon
-+National Semiconductors Geode GX
-+Transmeta Crusoe
-+varios processors on some ACPI 2.0-compatible systems [**]
-+
-+[*] only certain Intel mobile PIII processors are supported. If you
-+know that you own a speedstep-capable processor, pass the option
-+"speedstep_coppermine=1" to the module speedstep.o
-+
-+[**] Only if "ACPI Processor Performance States" are available
-+to the ACPI<->BIOS interface.
-+
-+
-+1.3 sparc64
-+-----------
-+
-+The following processors for the sparc64 architecture are supported by
-+cpufreq:
-+
-+UltraSPARC-III
-+
-+
-+
-+2. "Policy" / "Governor" ?
-+==========================
-+
-+Some CPU frequency scaling-capable processor switch between varios
-+frequencies and operating voltages "on the fly" without any kernel or
-+user involvement. This guarantuees very fast switching to a frequency
-+which is high enough to serve the user's needs, but low enough to save
-+power.
-+
-+
-+2.1 Policy
-+----------
-+
-+On these systems, all you can do is select the lower and upper
-+frequency limit as well as whether you want more aggressive
-+power-saving or more instantly avaialble processing power.
-+
-+
-+2.2 Governor
-+------------
-+
-+On all other cpufreq implementations, these boundaries still need to
-+be set. Then, a "governor" must be selected. Such a "governor" decides
-+what speed the processor shall run within the boundaries. One such
-+"governor" is the "userspace" governor. This one allows the user - or
-+a yet-to-implement userspace program - to decide what specific speed
-+the processor shall run at.
-+
-+
-+3. How to change the CPU cpufreq policy and/or speed
-+====================================================
-+
-+3.1 Preferred Interface: sysfs
-+------------------------------
-+
-+The preferred interface is located in the sysfs filesystem. If you
-+mounted it at /sys, the cpufreq interface is located in a subdirectory
-+"cpufreq" within the cpu-device directory
-+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
-+
-+cpuinfo_min_freq : this file shows the minimum operating
-+ frequency the processor can run at(in kHz)
-+cpuinfo_max_freq : this file shows the maximum operating
-+ frequency the processor can run at(in kHz)
-+scaling_driver : this file shows what cpufreq driver is
-+ used to set the frequency on this CPU
-+
-+scaling_available_governors : this file shows the CPUfreq governors
-+ available in this kernel. You can see the
-+ currently activated governor in
-+
-+scaling_governor, and by "echoing" the name of another
-+ governor you can change it. Please note
-+ that some governors won't load - they only
-+ work on some specific architectures or
-+ processors.
-+scaling_min_freq and
-+scaling_max_freq show the current "policy limits" (in
-+ kHz). By echoing new values into these
-+ files, you can change these limits.
-+
-+
-+If you have selected the "userspace" governor which allows you to
-+set the CPU operating frequency to a specific value, you can read out
-+the current frequency in
-+
-+scaling_setspeed. By "echoing" a new frequency into this
-+ you can change the speed of the CPU,
-+ but only within the limits of
-+ scaling_min_freq and scaling_max_freq.
-+
-+
-+3.2 Deprecated Interfaces
-+-------------------------
-+
-+Depending on your kernel configuration, you might find the following
-+cpufreq-related files:
-+/proc/cpufreq
-+/proc/sys/cpu/*/speed
-+/proc/sys/cpu/*/speed-min
-+/proc/sys/cpu/*/speed-max
-+
-+These are files for deprecated interfaces to cpufreq, which offer far
-+less functionality. Because of this, these interfaces aren't described
-+here.
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/cpufreq-old 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,332 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+
-+
-+
-+ Dominik Brodowski <devel@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+
-+Contents:
-+---------
-+1. Supported architectures
-+2. User interface
-+2.1 Sample script for command line interface
-+3. CPUFreq core and interfaces
-+3.1 General information
-+3.2 CPUFreq notifiers
-+3.3 CPUFreq architecture drivers
-+4. Mailing list and Links
-+
-+
-+
-+1. Supported architectures
-+==========================
-+
-+Some architectures detect the lowest and highest possible speed
-+settings, while others rely on user information on this. For the
-+latter, a boot parameter is required, for the former, you can specify
-+one to set the limits between speed settings may occur.
-+The boot parameter has the following syntax:
-+
-+ cpufreq=minspeed-maxspeed
-+
-+with both minspeed and maxspeed being given in kHz. To set the lower
-+limit to 59 MHz and the upper limit to 221 MHz, specify:
-+
-+ cpufreq=59000-221000
-+
-+Check the "Speed Limits Detection" information below on whether
-+the driver detects the lowest and highest allowed speed setting
-+automatically.
-+
-+
-+ARM Integrator:
-+ SA 1100, SA1110
-+--------------------------------
-+ Speed Limits Detection: On Integrators, the minimum speed is set
-+ and the maximum speed has to be specified using the boot
-+ parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz)
-+
-+
-+AMD Elan:
-+ SC400, SC410
-+--------------------------------
-+ Speed Limits Detection: Not implemented. You need to specify the
-+ minimum and maximum frequency in the boot parameter (see above).
-+
-+
-+VIA Cyrix Longhaul:
-+ VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3,
-+ VIA Cyrix Ezra, VIA Cyrix Ezra-T
-+--------------------------------
-+ Speed Limits Detection: working. No need for boot parameters.
-+ NOTE: Support for certain processors is currently disabled,
-+ waiting on updated docs from VIA.
-+
-+
-+Intel SpeedStep:
-+ certain mobile Intel Pentium III (Coppermine), and all mobile
-+ Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms.
-+--------------------------------
-+ Speed Limits Detection: working. No need for boot parameters.
-+ NOTE:
-+ 1.) mobile Intel Pentium III (Coppermine):
-+ The SpeedStep interface may only be used on SpeedStep
-+ capable processors. Unforunately, due to lack of documentation,
-+ such detection is not yet possible on mobile Intel PIII
-+ (Coppermine) processors. In order to activate SpeedStep on such a
-+ processor, you have to remove one line manually in
-+ linux/drivers/arch/i386/speedstep.c
-+
-+
-+P4 CPU Clock Modulation:
-+ Intel Pentium 4 Xeon processors
-+--------------------------------
-+ Speed Limits Detection: Not implemented. You need to specify the
-+ minimum and maximum frequency in the boot parameter (see above).
-+
-+
-+
-+2. User Interface
-+=================
-+
-+CPUFreq uses a "sysctl" interface which is located in
-+ /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or
-+ /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels.
-+
-+
-+In this directory, you will find three files of importance for
-+CPUFreq: speed-max, speed-min, and speed:
-+
-+speed shows the current CPU frequency in kHz,
-+speed-min the minimal supported CPU frequency, and
-+speed-max the maximal supported CPU frequency.
-+
-+Please note that you might have to specify these limits as a boot
-+parameter depending on the architecture (see above).
-+
-+
-+To change the CPU frequency, "echo" the desired CPU frequency (in kHz)
-+to speed. For example, to set the CPU speed to the lowest/highest
-+allowed frequency do:
-+
-+root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed
-+root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed
-+
-+
-+2.1 Sample script for command line interface
-+**********************************************
-+
-+
-+Michael Ossmann <mike@ossmann.com> has written a small command line
-+interface for the infinitely lazy.
-+
-+#!/bin/bash
-+#
-+# /usr/local/bin/freq
-+# simple command line interface to cpufreq
-+
-+[ -n "$1" ] && case "$1" in
-+ "min" )
-+ # set frequency to minimum
-+ cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed
-+ ;;
-+ "max" )
-+ # set frequency to maximum
-+ cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed
-+ ;;
-+ * )
-+ echo "Usage: $0 [min|max]"
-+ echo " min: set frequency to minimum and display new frequency"
-+ echo " max: set frequency to maximum and display new frequency"
-+ echo " no options: display current frequency"
-+ exit 1
-+ ;;
-+esac
-+
-+# display current frequency
-+cat /proc/sys/cpu/0/speed
-+exit 0
-+
-+
-+
-+3. CPUFreq core and interfaces
-+===============================
-+
-+3.1 General information
-+*************************
-+
-+The CPUFreq core code is located in linux/kernel/cpufreq.c. This
-+cpufreq code offers a standardized interface for the CPUFreq
-+architecture drivers (those pieces of code that do the actual
-+frequency transition), as well as to "notifiers". These are device
-+drivers or other part of the kernel that need to be informed of
-+frequency changes (like timing code) or even need to force certain
-+speed limits (like LCD drivers on ARM architecture). Aditionally, the
-+kernel "constant" loops_per_jiffy is updated on frequency changes
-+here.
-+
-+
-+3.2 CPUFreq notifiers
-+***********************
-+
-+CPUFreq notifiers are kernel code that need to be called to either
-+a) define certain minimum or maximum speed settings,
-+b) be informed of frequency changes in advance of the transition, or
-+c) be informed of frequency changes directly after the transition.
-+
-+A standard kernel notifier interface is offered for this. See
-+linux/include/linux/notifier.h for details on notifiers.
-+
-+
-+Data and value passed to CPUFreq notifiers
-+------------------------------------------
-+The second argument passed to any notifier is an unsigned int stating
-+the phase of the transition:
-+CPUFREQ_MINMAX during the process of determing a valid new CPU
-+ frequency,
-+CPUFREQ_PRECHANGE right before the transition, and
-+CPUFREQ_POSTCHANGE right after the transition.
-+
-+The third argument, a void *pointer, points to a struct
-+cpufreq_freqs. This consists of four values: min, max, cur and new.
-+
-+min and max are the current speed limits. Please note: Never update
-+these values directly, use cpufreq_updateminmax(struct cpufreq_freqs
-+*freqs, unsigned int min, unsigned int max) instead. cur is the
-+current/old speed, and new is the new speed, but might only be valid
-+on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
-+
-+Each notifier gets called all three times on any transition:
-+
-+CPUFREQ_MINMAX
-+Here the notifier is supposed to update the min and max values to the
-+limits the protected device / kernel code needs. As stated above,
-+always use cpufreq_updateminmax for this.
-+
-+CPUFREQ_PRECHANGE
-+CPUFREQ_POSTCHANGE
-+Here the notifier is supposed to update all internal (e.g. device
-+driver) code which is dependend on the CPU frequency.
-+
-+
-+3.3 CPUFreq architecture drivers
-+**********************************
-+
-+CPUFreq architecture drivers are the pieces of kernel code that
-+actually perform CPU frequency transitions. These need to be
-+initialised seperately (seperate initcalls), and may be
-+modularized. They interact with the CPUFreq core in the following way:
-+
-+
-+cpufreq_register()
-+------------------
-+cpufreq_register registers an arch driver to the CPUFreq core. Please
-+note that only one arch driver may be registered at any time, -EBUSY
-+is returned when an arch driver is already registered. The argument to
-+cpufreq_register, cpufreq_driver_t driver, is described later.
-+
-+
-+cpufreq_unregister()
-+--------------------
-+cpufreq_unregister unregisters an arch driver, e.g. on module
-+unloading. Please note that there is no check done that this is called
-+from the driver which actually registered itself to the core, so
-+please only call this function when you are sure the arch driver got
-+registered correctly before.
-+
-+
-+struct cpufreq_driver
-+----------------
-+On initialisation, the arch driver is supposed to pass the following
-+entries in struct cpufreq_driver cpufreq_driver:
-+
-+cpufreq_verify_t validate: This is a pointer to a function with the
-+following definition:
-+ unsigned int validating_function (unsigned int kHz).
-+It is called right before a transition occurs. The proposed new
-+speed setting is passed as an argument in kHz; the validating code
-+should verify this is a valid speed setting which is currently
-+supported by the CPU. It shall return the closest valid CPU frequency
-+in kHz.
-+
-+cpufreq_setspeed_t setspeed: This is a pointer to a function with the
-+following definition:
-+ void setspeed_function (unsigned int kHz).
-+This function shall perform the transition to the new CPU frequency
-+given as argument in kHz. Note that this argument is exactly the same
-+as the one returned by cpufreq_verify_t validate.
-+
-+
-+unsigned int freq.cur: The current CPU core frequency. Note that this
-+is a requirement while the next two entries are optional.
-+
-+
-+unsigned int freq.min (optional): The minimal CPU core frequency this
-+CPU supports. This value may be limited further by the
-+cpufreq_verify_t validate function, and so this value should be the
-+minimal core frequency allowed "theoretically" on this system in this
-+configuration.
-+
-+
-+unsigned int freq.max (optional): The maximum CPU core frequency this
-+CPU supports. This value may be limited further by the
-+cpufreq_verify_t validate function, and so this value should be the
-+maximum core frequency allowed "theoretically" on this system in this
-+configuration.
-+
-+
-+Some Requirements to CPUFreq architecture drivers
-+-------------------------------------------------
-+* Only call cpufreq_register() when the ability to switch CPU
-+ frequencies is _verified_ or can't be missing
-+* cpufreq_unregister() may only be called if cpufreq_register() has
-+ been successfully(!) called before
-+* All CPUs have to be set to the same speed whenever setspeed() is
-+ called
-+* Be aware that there is currently no error management in the
-+ setspeed() code in the CPUFreq core. So only call yourself a
-+ cpufreq_driver if you are really a working cpufreq_driver!
-+
-+
-+
-+4. Mailing list and Links
-+**************************
-+
-+
-+Mailing List
-+------------
-+There is a CPU frequency changing CVS commit and general list where
-+you can report bugs, problems or submit patches. To post a message,
-+send an email to cpufreq@www.linux.org.uk, to subscribe go to
-+http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
-+mailing list are available to subscribers at
-+http://www.linux.org.uk/mailman/private/cpufreq/.
-+
-+
-+Links
-+-----
-+the FTP archives:
-+* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
-+
-+how to access the CVS repository:
-+* http://www.arm.linux.org.uk/cvs/
-+
-+the CPUFreq Mailing list:
-+* http://www.linux.org.uk/mailman/listinfo/cpufreq
-+
-+Clock and voltage scaling for the SA-1100:
-+* http://www.lart.tudelft.nl/projects/scaling
-+
-+CPUFreq project homepage
-+* http://www.brodo.de/cpufreq/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/l3/structure 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,36 @@
-+L3 Bus Driver
-+-------------
-+
-+The structure of the driver is as follows:
-+
-+ +----------+ +----------+ +----------+
-+ | client 1 | | client 2 | | client 3 |
-+ +-----^----+ +----^-----+ +----^-----+
-+ | | |
-+ +-----v--------------v---------------v-----+
-+ | |
-+ +-----^-------+ +-------^-----+
-+ | | core | |
-+ +-----v----+ | | +----v-----+
-+ | device | | | | device |
-+ | driver 1 | | | | driver 2 |
-+ +-----^----+ | | +----^-----+
-+ | | services | |
-+ +-----v-------+ +-------v-----+
-+ | |
-+ +-----------------^----^-------------------+
-+ | |
-+ | +-v---------+
-+ | | algorithm |
-+ | | driver |
-+ | +-v---------+
-+ | |
-+ +-v----v-+
-+ | bus |
-+ | driver |
-+ +--------+
-+
-+Clients talk to the core to attach device drivers and bus adapters, and
-+to instruct device drivers to perform actions. Device drivers then talk
-+to the core to perform L3 bus transactions via the algorithm driver and
-+ultimately bus driver.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/Documentation/serial/driver 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,208 @@
-+
-+ Low Level Serial API
-+ --------------------
-+
-+
-+ $Id: driver,v 1.3 2001/11/24 23:24:47 rmk Exp $
-+
-+
-+This document is meant as a brief overview of some aspects of the new serial
-+driver. It is not complete, any questions you have should be directed to
-+<rmk@arm.linux.org.uk>
-+
-+The reference implementation is contained within serial_amba.c.
-+
-+
-+
-+Low Level Serial Hardware Driver
-+--------------------------------
-+
-+The low level serial hardware driver is responsible for supplying port
-+information (defined by uart_port) and a set of control methods (defined
-+by uart_ops) to the core serial driver. The low level driver is also
-+responsible for handling interrupts for the port, and providing any
-+console support.
-+
-+
-+Console Support
-+---------------
-+
-+The serial core provides a few helper functions. This includes identifing
-+the correct port structure (via uart_get_console) and decoding command line
-+arguments (uart_parse_options).
-+
-+
-+Locking
-+-------
-+
-+Generally, all locking is done by the core driver, except for the interrupt
-+functions. It is the responsibility of the low level hardware driver to
-+perform the necessary locking there using info->lock. (since it is running
-+in an interrupt, you only need to use spin_lock() and spin_unlock() from
-+the interrupt handler).
-+
-+
-+uart_ops
-+--------
-+
-+The uart_ops structure is the main interface between serial_core and the
-+hardware specific driver. It contains all the methods to control the
-+hardware.
-+
-+ tx_empty(port)
-+ This function tests whether the transmitter fifo and shifter
-+ for the port described by 'port' is empty. If it is empty,
-+ this function should return TIOCSER_TEMT, otherwise return 0.
-+ If the port does not support this operation, then it should
-+ return TIOCSER_TEMT.
-+
-+ set_mctrl(port, mctrl)
-+ This function sets the modem control lines for port described
-+ by 'port' to the state described by mctrl. The relevant bits
-+ of mctrl are:
-+ - TIOCM_RTS RTS signal.
-+ - TIOCM_DTR DTR signal.
-+ - TIOCM_OUT1 OUT1 signal.
-+ - TIOCM_OUT2 OUT2 signal.
-+ If the appropriate bit is set, the signal should be driven
-+ active. If the bit is clear, the signal should be driven
-+ inactive.
-+
-+ get_mctrl(port)
-+ Returns the current state of modem control inputs. The state
-+ of the outputs should not be returned, since the core keeps
-+ track of their state. The state information should include:
-+ - TIOCM_DCD state of DCD signal
-+ - TIOCM_CTS state of CTS signal
-+ - TIOCM_DSR state of DSR signal
-+ - TIOCM_RI state of RI signal
-+ The bit is set if the signal is currently driven active. If
-+ the port does not support CTS, DCD or DSR, the driver should
-+ indicate that the signal is permanently active. If RI is
-+ not available, the signal should not be indicated as active.
-+
-+ stop_tx(port,from_tty)
-+ Stop transmitting characters. This might be due to the CTS
-+ line becoming inactive or the tty layer indicating we want
-+ to stop transmission.
-+
-+ start_tx(port,nonempty,from_tty)
-+ start transmitting characters. (incidentally, nonempty will
-+ always be nonzero, and shouldn't be used - it will be dropped).
-+
-+ stop_rx(port)
-+ Stop receiving characters; the port is in the process of
-+ being closed.
-+
-+ enable_ms(port)
-+ Enable the modem status interrupts.
-+
-+ break_ctl(port,ctl)
-+ Control the transmission of a break signal. If ctl is
-+ nonzero, the break signal should be transmitted. The signal
-+ should be terminated when another call is made with a zero
-+ ctl.
-+
-+ startup(port,info)
-+ Grab any interrupt resources and initialise any low level driver
-+ state. Enable the port for reception. It should not activate
-+ RTS nor DTR; this will be done via a separate call to set_mctrl.
-+
-+ shutdown(port,info)
-+ Disable the port, disable any break condition that may be in
-+ effect, and free any interrupt resources. It should not disable
-+ RTS nor DTR; this will have already been done via a separate
-+ call to set_mctrl.
-+
-+ change_speed(port,cflag,iflag,quot)
-+ Change the port parameters, including word length, parity, stop
-+ bits. Update read_status_mask and ignore_status_mask to indicate
-+ the types of events we are interested in receiving. Relevant
-+ cflag bits are:
-+ CSIZE - word size
-+ CSTOPB - 2 stop bits
-+ PARENB - parity enable
-+ PARODD - odd parity (when PARENB is in force)
-+ CREAD - enable reception of characters (if not set,
-+ still receive characters from the port, but
-+ throw them away.
-+ CRTSCTS - if set, enable CTS status change reporting
-+ CLOCAL - if not set, enable modem status change
-+ reporting.
-+ Relevant iflag bits are:
-+ INPCK - enable frame and parity error events to be
-+ passed to the TTY layer.
-+ BRKINT
-+ PARMRK - both of these enable break events to be
-+ passed to the TTY layer.
-+
-+ IGNPAR - ignore parity and framing errors
-+ IGNBRK - ignore break errors, If IGNPAR is also
-+ set, ignore overrun errors as well.
-+ The interaction of the iflag bits is as follows (parity error
-+ given as an example):
-+ Parity error INPCK IGNPAR
-+ None n/a n/a character received
-+ Yes n/a 0 character discarded
-+ Yes 0 1 character received, marked as
-+ TTY_NORMAL
-+ Yes 1 1 character received, marked as
-+ TTY_PARITY
-+
-+ pm(port,state,oldstate)
-+ perform any power management related activities on the specified
-+ port. state indicates the new state (defined by ACPI D0-D3),
-+ oldstate indicates the previous state. Essentially, D0 means
-+ fully on, D3 means powered down.
-+
-+ This function should not be used to grab any resources.
-+
-+ type(port)
-+ Return a pointer to a string constant describing the specified
-+ port, or return NULL, in which case the string 'unknown' is
-+ substituted.
-+
-+ release_port(port)
-+ Release any memory and IO region resources currently in use by
-+ the port.
-+
-+ request_port(port)
-+ Request any memory and IO region resources required by the port.
-+ If any fail, no resources should be registered when this function
-+ returns, and it should return -EBUSY on failure.
-+
-+ config_port(port,type)
-+ Perform any autoconfiguration steps required for the port. `type`
-+ contains a bit mask of the required configuration. UART_CONFIG_TYPE
-+ indicates that the port requires detection and identification.
-+ port->type should be set to the type found, or PORT_UNKNOWN if
-+ no port was detected.
-+
-+ UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
-+ which should be probed using standard kernel autoprobing techniques.
-+ This is not necessary on platforms where ports have interrupts
-+ internally hard wired (eg, system on a chip implementations).
-+
-+ verify_port(port,serinfo)
-+ Verify the new serial port information contained within serinfo is
-+ suitable for this port type.
-+
-+ ioctl(port,cmd,arg)
-+ Perform any port specific IOCTLs. IOCTL commands must be defined
-+ using the standard numbering system found in <asm/ioctl.h>
-+
-+
-+Other notes
-+-----------
-+
-+It is intended some day to drop the 'unused' entries from uart_port, and
-+allow low level drivers to register their own individual uart_port's with
-+the core. This will allow drivers to use uart_port as a pointer to a
-+structure containing both the uart_port entry with their own extensions,
-+thus:
-+
-+ struct my_port {
-+ struct uart_port port;
-+ int my_stuff;
-+ };
-+
---- linux-2.4.25/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/Makefile 2004-03-31 17:15:08.000000000 +0200
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 25
--EXTRAVERSION =
-+EXTRAVERSION =-vrs2
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
-@@ -137,7 +137,10 @@
-
- DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
- DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
--DRIVERS-y += drivers/char/char.o \
-+DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
-+DRIVERS-$(CONFIG_L3) += drivers/l3/l3.o
-+DRIVERS-y += drivers/serial/serial.o \
-+ drivers/char/char.o \
- drivers/block/block.o \
- drivers/misc/misc.o \
- drivers/net/net.o
-@@ -161,6 +164,7 @@
- DRIVERS-y += drivers/cdrom/driver.o
- endif
-
-+DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o
- DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
- DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
- DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
-@@ -186,7 +190,6 @@
- DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o
- DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
- DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
--DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
- DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
- DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
- DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o
-@@ -194,6 +197,8 @@
- DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
- DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
- DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
-+DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
-+DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o
-
- DRIVERS := $(DRIVERS-y)
-
-@@ -273,11 +278,6 @@
-
- export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
-
--.S.s:
-- $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
--.S.o:
-- $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $<
--
- Version: dummy
- @rm -f include/linux/compile.h
-
---- linux-2.4.25/Rules.make~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/Rules.make 2004-03-31 17:15:08.000000000 +0200
-@@ -51,15 +51,15 @@
- #
-
- %.s: %.c
-- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
-+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@
-
- %.i: %.c
-- $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
-+ $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) $< > $@
-
- %.o: %.c
-- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
-+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -c -o $@ $<
- @ ( \
-- echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \
-+ echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$(*F)) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$(*F)) $$(CFLAGS_$@))))' ; \
- echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
- echo 'endif' \
- ) > $(dir $@)/.$(notdir $@).flags
-@@ -272,7 +272,8 @@
- endif # CONFIG_MODVERSIONS
-
- ifneq "$(strip $(export-objs))" ""
--$(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
-+$(export-objs): $(TOPDIR)/include/linux/modversions.h
-+$(export-objs): %.o: %.c
- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
- @ ( \
- echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
---- linux-2.4.25/arch/alpha/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/alpha/config.in 2004-03-31 17:15:08.000000000 +0200
-@@ -7,6 +7,7 @@
- define_bool CONFIG_UID16 n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Kernel configuration of Linux for Alpha machines"
-
---- linux-2.4.25/arch/arm/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/Makefile 2004-03-31 17:15:08.000000000 +0200
-@@ -52,7 +52,7 @@
-
- CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
- CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
--AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
-+AFLAGS +=$(apcs-y) $(arch-y) -msoft-float
-
- ifeq ($(CONFIG_CPU_26),y)
- PROCESSOR := armo
---- linux-2.4.25/arch/arm/boot/compressed/head.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/boot/compressed/head.S 2004-03-31 17:15:08.000000000 +0200
-@@ -40,6 +40,14 @@
- .macro writeb, rb
- strb \rb, [r3, #0x3f8 << 2]
- .endm
-+#elif defined(CONFIG_ARCH_RISCSTATION)
-+ .macro loadsp, rb
-+ mov \rb, #0x03000000
-+ orr \rb, \rb, #0x00010000
-+ .endm
-+ .macro writeb, rb
-+ strb \rb, [r3, #0x3f8 << 2]
-+ .endm
- #elif defined(CONFIG_ARCH_INTEGRATOR)
- .macro loadsp, rb
- mov \rb, #0x16000000
-@@ -396,6 +404,20 @@
- mcr p15, 0, r0, c1, c0, 0 @ load control register
- mov pc, r12
-
-+__arm7_cache_on:
-+ mov r12, lr
-+ bl __setup_mmu
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
-+ mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
-+ mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
-+ mov r0, #-1
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access control
-+ mov r0, #0x7d
-+ mcr p15, 0, r0, c1, c0, 0 @ load control register
-+ mov pc, r12
-+
-+
- /*
- * All code following this line is relocatable. It is relocated by
- * the above code to the end of the decompressed kernel image and
-@@ -480,9 +502,9 @@
-
- .word 0x41007000 @ ARM7/710
- .word 0xfff8fe00
-+ b __arm7_cache_on
- b __arm7_cache_off
-- b __arm7_cache_off
-- mov pc, lr
-+ b __armv3_cache_flush
-
- .word 0x41807200 @ ARM720T (writethrough)
- .word 0xffffff00
-@@ -490,14 +512,14 @@
- b __armv4_cache_off
- mov pc, lr
-
-- .word 0x41129200 @ ARM920T
-- .word 0xff00fff0
-+ .word 0x41009200 @ ARM920T, ARM922T, ARM926TEJ-S
-+ .word 0xff00ff90
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
-
-- .word 0x41029220 @ ARM922T
-- .word 0xff00fff0
-+ .word 0x4100a200 @ ARM1020T/E, ARM1022E, ARM1026TEJ-S
-+ .word 0xff00ff90
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
---- linux-2.4.25/arch/arm/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/arm/config.in 2004-03-31 17:15:08.000000000 +0200
-@@ -144,6 +144,7 @@
- mainmenu_option next_comment
- comment 'AT91RM9200 Implementations'
- dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
-+dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200
- endmenu
-
- mainmenu_option next_comment
-@@ -189,6 +190,12 @@
- define_bool CONFIG_ARCH_ACORN n
- fi
-
-+if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
-+ define_bool CONFIG_PLD y
-+else
-+ define_bool CONFIG_PLD n
-+fi
-+
- #####################################################################
- # Footbridge support
- if [ "$CONFIG_ARCH_CO285" = "y" -o \
-@@ -315,26 +322,42 @@
- # ARM922T
- if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
- define_bool CONFIG_CPU_ARM922T y
-- define_bool CONFIG_PLD y
- else
-- define_bool CONFIG_CPU_ARM922T n
-- define_bool CONFIG_PLD n
-+ if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM922T(Excalibur) processor' CONFIG_ARM922T
-+ else
-+ define_bool CONFIG_CPU_ARM922T n
-+ fi
- fi
-
- # ARM926T
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-- bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
-+ bool 'Support ARM926TEJ-S processor' CONFIG_CPU_ARM926T
- else
- define_bool CONFIG_CPU_ARM926T n
- fi
-
- # ARM1020
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-- bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
-+ bool 'Support ARM1020T (Rev0) processor' CONFIG_CPU_ARM1020
- else
- define_bool CONFIG_CPU_ARM1020 n
- fi
-
-+# ARM1020E
-+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM1020E (Rev1) processor' CONFIG_CPU_ARM1020E
-+else
-+ define_bool CONFIG_CPU_ARM1020E n
-+fi
-+
-+# ARM1022
-+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM1022 processor' CONFIG_CPU_ARM1020E
-+else
-+ define_bool CONFIG_CPU_ARM1022 n
-+fi
-+
- # ARM1026EJ-S
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
- bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026
-@@ -388,25 +411,29 @@
-
- if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
- "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
-- "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
-+ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
-+ "$CONFIG_CPU_ARM1022" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
- dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
- fi
- if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
- "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
-+ "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
- "$CONFIG_CPU_ARM1026" = "y" ]; then
- bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE
- bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE
-- if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then
-+ if [ "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
- bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH
- fi
- fi
- if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
-+ "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
- "$CONFIG_CPU_ARM1026" = "y" ]; then
- if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
- bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN
- fi
- fi
--if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
-+if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
-+ "$CONFIG_CPU_ARM1026" = "y" -o "$CONFIG_CPU_ARM1022" = "y" ]; then
- bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE
- fi
-
-@@ -729,10 +756,7 @@
- dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
- dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
- dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
--
--int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
--
- endmenu
-
--source crypto/Config.in
- source lib/Config.in
-+
---- linux-2.4.25/arch/arm/def-configs/at91rm9200dk~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/arm/def-configs/at91rm9200dk 2004-03-31 17:15:08.000000000 +0200
-@@ -111,6 +111,7 @@
- # AT91RM9200 Implementations
- #
- CONFIG_ARCH_AT91RM9200DK=y
-+# CONFIG_MACH_CSB337 is not set
-
- #
- # CLPS711X/EP721X Implementations
-@@ -125,6 +126,7 @@
- # CONFIG_ARCH_EP7211 is not set
- # CONFIG_ARCH_EP7212 is not set
- # CONFIG_ARCH_ACORN is not set
-+# CONFIG_PLD is not set
- # CONFIG_FOOTBRIDGE is not set
- # CONFIG_FOOTBRIDGE_HOST is not set
- # CONFIG_FOOTBRIDGE_ADDIN is not set
-@@ -135,9 +137,10 @@
- # CONFIG_CPU_ARM720T is not set
- CONFIG_CPU_ARM920T=y
- # CONFIG_CPU_ARM922T is not set
--# CONFIG_PLD is not set
- # CONFIG_CPU_ARM926T is not set
- # CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1020E is not set
-+# CONFIG_CPU_ARM1022 is not set
- # CONFIG_CPU_ARM1026 is not set
- # CONFIG_CPU_SA110 is not set
- # CONFIG_CPU_SA1100 is not set
-@@ -146,6 +149,7 @@
- # CONFIG_ARM_THUMB is not set
- # CONFIG_CPU_ICACHE_DISABLE is not set
- # CONFIG_CPU_DCACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
- # CONFIG_DISCONTIGMEM is not set
-
- #
-@@ -164,6 +168,7 @@
- # CONFIG_BSD_PROCESS_ACCT is not set
- CONFIG_SYSCTL=y
- CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
- # CONFIG_FPE_FASTFPE is not set
- CONFIG_KCORE_ELF=y
- # CONFIG_KCORE_AOUT is not set
-@@ -173,6 +178,9 @@
- # CONFIG_PM is not set
- # CONFIG_ARTHUR is not set
- CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20210000,3145728 root=/dev/ram rw"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+# CONFIG_LEDS_CPU is not set
- CONFIG_ALIGNMENT_TRAP=y
-
- #
-@@ -204,6 +212,7 @@
- # CONFIG_MTD_CFI_ADV_OPTIONS is not set
- # CONFIG_MTD_CFI_INTELEXT is not set
- CONFIG_MTD_CFI_AMDSTD=y
-+# CONFIG_MTD_CFI_STAA is not set
- # CONFIG_MTD_RAM is not set
- # CONFIG_MTD_ROM is not set
- # CONFIG_MTD_ABSENT is not set
-@@ -230,7 +239,9 @@
- # CONFIG_MTD_AUTCPU12 is not set
- # CONFIG_MTD_EDB7312 is not set
- # CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
- # CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-
- #
- # Self-contained MTD device drivers
-@@ -250,9 +261,9 @@
- # NAND Flash Device Drivers
- #
- CONFIG_MTD_NAND=y
--CONFIG_MTD_NAND_ECC=y
- # CONFIG_MTD_NAND_VERIFY_WRITE is not set
--CONFIG_MTD_AT91_SMARTMEDIA=y
-+CONFIG_MTD_NAND_IDS=y
-+# CONFIG_MTD_AT91_SMARTMEDIA is not set
-
- #
- # Plug and Play configuration
-@@ -269,6 +280,7 @@
- # CONFIG_BLK_CPQ_DA is not set
- # CONFIG_BLK_CPQ_CISS_DA is not set
- # CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_CISS_MONITOR_THREAD is not set
- # CONFIG_BLK_DEV_DAC960 is not set
- # CONFIG_BLK_DEV_UMEM is not set
- # CONFIG_BLK_DEV_LOOP is not set
-@@ -276,6 +288,7 @@
- CONFIG_BLK_DEV_RAM=y
- CONFIG_BLK_DEV_RAM_SIZE=8192
- CONFIG_BLK_DEV_INITRD=y
-+# CONFIG_BLK_STATS is not set
-
- #
- # Multi-device support (RAID and LVM)
-@@ -312,6 +325,12 @@
- # CONFIG_SYN_COOKIES is not set
- # CONFIG_IPV6 is not set
- # CONFIG_KHTTPD is not set
-+
-+#
-+# SCTP Configuration (EXPERIMENTAL)
-+#
-+CONFIG_IPV6_SCTP__=y
-+# CONFIG_IP_SCTP is not set
- # CONFIG_ATM is not set
- # CONFIG_VLAN_8021Q is not set
- # CONFIG_IPX is not set
-@@ -382,10 +401,12 @@
- #
- # CONFIG_ACENIC is not set
- # CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
- # CONFIG_MYRI_SBUS is not set
- # CONFIG_NS83820 is not set
- # CONFIG_HAMACHI is not set
- # CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
- # CONFIG_SK98LIN is not set
- # CONFIG_TIGON3 is not set
- # CONFIG_FDDI is not set
-@@ -455,6 +476,8 @@
- # CONFIG_INPUT_MOUSEDEV is not set
- # CONFIG_INPUT_JOYDEV is not set
- # CONFIG_INPUT_EVDEV is not set
-+# CONFIG_INPUT_UINPUT is not set
-+# CONFIG_INPUT_MX1TS is not set
-
- #
- # Character devices
-@@ -502,6 +525,7 @@
- #
- CONFIG_I2C=y
- # CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_SCx200_ACB is not set
- # CONFIG_I2C_ALGOPCF is not set
- CONFIG_I2C_AT91=y
- CONFIG_I2C_CHARDEV=y
-@@ -528,6 +552,11 @@
- #
- # CONFIG_INPUT_GAMEPORT is not set
- # CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-
- #
- # Watchdog Cards
-@@ -536,12 +565,14 @@
- CONFIG_WATCHDOG_NOWAYOUT=y
- # CONFIG_ACQUIRE_WDT is not set
- # CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM1535_WDT is not set
- # CONFIG_ALIM7101_WDT is not set
- # CONFIG_SC520_WDT is not set
- # CONFIG_PCWATCHDOG is not set
- # CONFIG_21285_WATCHDOG is not set
- # CONFIG_977_WATCHDOG is not set
- # CONFIG_SA1100_WATCHDOG is not set
-+# CONFIG_EPXA_WATCHDOG is not set
- # CONFIG_OMAHA_WATCHDOG is not set
- CONFIG_AT91_WATCHDOG=y
- # CONFIG_EUROTECH_WDT is not set
-@@ -551,11 +582,16 @@
- # CONFIG_MIXCOMWD is not set
- # CONFIG_60XX_WDT is not set
- # CONFIG_SC1200_WDT is not set
-+# CONFIG_SCx200_WDT is not set
- # CONFIG_SOFT_WATCHDOG is not set
- # CONFIG_W83877F_WDT is not set
- # CONFIG_WDT is not set
- # CONFIG_WDTPCI is not set
- # CONFIG_MACHZ_WDT is not set
-+# CONFIG_AMD7XX_TCO is not set
-+# CONFIG_SCx200 is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
- # CONFIG_NVRAM is not set
- # CONFIG_RTC is not set
- CONFIG_AT91_RTC=y
-@@ -568,6 +604,10 @@
- #
- # CONFIG_FTAPE is not set
- # CONFIG_AGP is not set
-+
-+#
-+# Direct Rendering Manager (XFree86 DRI support)
-+#
- # CONFIG_DRM is not set
-
- #
-@@ -579,6 +619,7 @@
- # File systems
- #
- # CONFIG_QUOTA is not set
-+# CONFIG_QFMT_V2 is not set
- # CONFIG_AUTOFS_FS is not set
- # CONFIG_AUTOFS4_FS is not set
- # CONFIG_REISERFS_FS is not set
-@@ -588,6 +629,9 @@
- # CONFIG_ADFS_FS_RW is not set
- # CONFIG_AFFS_FS is not set
- # CONFIG_HFS_FS is not set
-+# CONFIG_HFSPLUS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
- # CONFIG_BFS_FS is not set
- # CONFIG_EXT3_FS is not set
- # CONFIG_JBD is not set
-@@ -605,6 +649,9 @@
- # CONFIG_ISO9660_FS is not set
- # CONFIG_JOLIET is not set
- # CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
- # CONFIG_MINIX_FS is not set
- # CONFIG_VXFS_FS is not set
- # CONFIG_NTFS_FS is not set
-@@ -624,6 +671,11 @@
- # CONFIG_UDF_RW is not set
- # CONFIG_UFS_FS is not set
- # CONFIG_UFS_FS_WRITE is not set
-+# CONFIG_XFS_FS is not set
-+# CONFIG_XFS_QUOTA is not set
-+# CONFIG_XFS_RT is not set
-+# CONFIG_XFS_TRACE is not set
-+# CONFIG_XFS_DEBUG is not set
-
- #
- # Network File Systems
-@@ -632,9 +684,11 @@
- # CONFIG_INTERMEZZO_FS is not set
- # CONFIG_NFS_FS is not set
- # CONFIG_NFS_V3 is not set
-+# CONFIG_NFS_DIRECTIO is not set
- # CONFIG_ROOT_NFS is not set
- # CONFIG_NFSD is not set
- # CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
- # CONFIG_SUNRPC is not set
- # CONFIG_LOCKD is not set
- # CONFIG_SMB_FS is not set
-@@ -648,7 +702,6 @@
- # CONFIG_NCPFS_NLS is not set
- # CONFIG_NCPFS_EXTRAS is not set
- # CONFIG_ZISOFS_FS is not set
--# CONFIG_ZLIB_FS_INFLATE is not set
-
- #
- # Partition Types
-@@ -674,16 +727,18 @@
- # CONFIG_USB_DEBUG is not set
- # CONFIG_USB_DEVICEFS is not set
- # CONFIG_USB_BANDWIDTH is not set
--# CONFIG_USB_LONG_TIMEOUT is not set
- # CONFIG_USB_EHCI_HCD is not set
- # CONFIG_USB_UHCI is not set
- # CONFIG_USB_UHCI_ALT is not set
- # CONFIG_USB_OHCI is not set
- # CONFIG_USB_OHCI_SA1111 is not set
-+# CONFIG_USB_SL811HS_ALT is not set
-+# CONFIG_USB_SL811HS is not set
- CONFIG_USB_OHCI_AT91=y
- # CONFIG_USB_AUDIO is not set
- # CONFIG_USB_EMI26 is not set
- # CONFIG_USB_BLUETOOTH is not set
-+# CONFIG_USB_MIDI is not set
- # CONFIG_USB_STORAGE is not set
- # CONFIG_USB_STORAGE_DEBUG is not set
- # CONFIG_USB_STORAGE_DATAFAB is not set
-@@ -692,6 +747,7 @@
- # CONFIG_USB_STORAGE_DPCM is not set
- # CONFIG_USB_STORAGE_HP8200e is not set
- # CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_SDDR55 is not set
- # CONFIG_USB_STORAGE_JUMPSHOT is not set
- # CONFIG_USB_ACM is not set
- # CONFIG_USB_PRINTER is not set
-@@ -700,7 +756,10 @@
- # CONFIG_USB_HIDDEV is not set
- # CONFIG_USB_KBD is not set
- # CONFIG_USB_MOUSE is not set
-+# CONFIG_USB_AIPTEK is not set
- # CONFIG_USB_WACOM is not set
-+# CONFIG_USB_KBTAB is not set
-+# CONFIG_USB_POWERMATE is not set
- # CONFIG_USB_DC2XX is not set
- # CONFIG_USB_MDC800 is not set
- # CONFIG_USB_SCANNER is not set
-@@ -718,35 +777,16 @@
- # USB Serial Converter support
- #
- # CONFIG_USB_SERIAL is not set
--# CONFIG_USB_SERIAL_GENERIC is not set
--# CONFIG_USB_SERIAL_BELKIN is not set
--# CONFIG_USB_SERIAL_WHITEHEAT is not set
--# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
--# CONFIG_USB_SERIAL_EMPEG is not set
--# CONFIG_USB_SERIAL_FTDI_SIO is not set
--# CONFIG_USB_SERIAL_VISOR is not set
--# CONFIG_USB_SERIAL_IPAQ is not set
--# CONFIG_USB_SERIAL_IR is not set
--# CONFIG_USB_SERIAL_EDGEPORT is not set
--# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
--# CONFIG_USB_SERIAL_KEYSPAN is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
--# CONFIG_USB_SERIAL_MCT_U232 is not set
--# CONFIG_USB_SERIAL_KLSI is not set
--# CONFIG_USB_SERIAL_PL2303 is not set
--# CONFIG_USB_SERIAL_CYBERJACK is not set
--# CONFIG_USB_SERIAL_XIRCOM is not set
--# CONFIG_USB_SERIAL_OMNINET is not set
- # CONFIG_USB_RIO500 is not set
- # CONFIG_USB_AUERSWALD is not set
-+# CONFIG_USB_TIGL is not set
- # CONFIG_USB_BRLVGER is not set
-+# CONFIG_USB_LCD is not set
-+
-+#
-+# Support for USB gadgets
-+#
-+# CONFIG_USB_GADGET is not set
-
- #
- # Bluetooth support
-@@ -770,3 +810,10 @@
- CONFIG_DEBUG_LL=y
- # CONFIG_DEBUG_DC21285_PORT is not set
- # CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_CRC32=y
-+# CONFIG_ZLIB_INFLATE is not set
-+# CONFIG_ZLIB_DEFLATE is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/def-configs/csb337 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,760 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+CONFIG_ARCH_AT91RM9200=y
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# AT91RM9200 Implementations
-+#
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+CONFIG_MACH_CSB337=y
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_PLD is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+CONFIG_CPU_ARM920T=y
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1020E is not set
-+# CONFIG_CPU_ARM1022 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+# CONFIG_CPU_32v3 is not set
-+CONFIG_CPU_32v4=y
-+# CONFIG_ARM_THUMB is not set
-+# CONFIG_CPU_ICACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20210000,3145728 root=/dev/ram rw"
-+# CONFIG_LEDS is not set
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+# CONFIG_MTD_PARTITIONS is not set
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+CONFIG_MTD_JEDECPROBE=y
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+CONFIG_MTD_ROM=y
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+CONFIG_MTD_PHYSMAP=y
-+CONFIG_MTD_PHYSMAP_START=10000000
-+CONFIG_MTD_PHYSMAP_LEN=200000
-+CONFIG_MTD_PHYSMAP_BUSWIDTH=2
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+CONFIG_MTD_AT91_DATAFLASH=y
-+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+CONFIG_MTD_NAND=y
-+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-+CONFIG_MTD_NAND_IDS=y
-+# CONFIG_MTD_AT91_SMARTMEDIA is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_CISS_MONITOR_THREAD is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+# CONFIG_BLK_DEV_INITRD is not set
-+# CONFIG_BLK_STATS is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+
-+#
-+# SCTP Configuration (EXPERIMENTAL)
-+#
-+CONFIG_IPV6_SCTP__=y
-+# CONFIG_IP_SCTP is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+CONFIG_AT91_ETHER=y
-+# CONFIG_AT91_ETHER_RMII is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+# CONFIG_INPUT_UINPUT is not set
-+# CONFIG_INPUT_MX1TS is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+# CONFIG_SERIAL is not set
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+CONFIG_AT91_SPIDEV=y
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+CONFIG_SERIAL_AT91=y
-+CONFIG_SERIAL_AT91_CONSOLE=y
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
-+# CONFIG_UNIX98_PTYS is not set
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_SCx200_ACB is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_AT91=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+CONFIG_I2C_DS1307=y
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-+
-+#
-+# Watchdog Cards
-+#
-+CONFIG_WATCHDOG=y
-+CONFIG_WATCHDOG_NOWAYOUT=y
-+# CONFIG_ACQUIRE_WDT is not set
-+# CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM1535_WDT is not set
-+# CONFIG_ALIM7101_WDT is not set
-+# CONFIG_SC520_WDT is not set
-+# CONFIG_PCWATCHDOG is not set
-+# CONFIG_21285_WATCHDOG is not set
-+# CONFIG_977_WATCHDOG is not set
-+# CONFIG_SA1100_WATCHDOG is not set
-+# CONFIG_EPXA_WATCHDOG is not set
-+# CONFIG_OMAHA_WATCHDOG is not set
-+CONFIG_AT91_WATCHDOG=y
-+# CONFIG_EUROTECH_WDT is not set
-+# CONFIG_IB700_WDT is not set
-+# CONFIG_WAFER_WDT is not set
-+# CONFIG_I810_TCO is not set
-+# CONFIG_MIXCOMWD is not set
-+# CONFIG_60XX_WDT is not set
-+# CONFIG_SC1200_WDT is not set
-+# CONFIG_SCx200_WDT is not set
-+# CONFIG_SOFT_WATCHDOG is not set
-+# CONFIG_W83877F_WDT is not set
-+# CONFIG_WDT is not set
-+# CONFIG_WDTPCI is not set
-+# CONFIG_MACHZ_WDT is not set
-+# CONFIG_AMD7XX_TCO is not set
-+# CONFIG_SCx200 is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_AT91_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+
-+#
-+# Direct Rendering Manager (XFree86 DRI support)
-+#
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_QFMT_V2 is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_HFSPLUS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+# CONFIG_JFFS2_FS is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+# CONFIG_DEVPTS_FS is not set
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+# CONFIG_XFS_FS is not set
-+# CONFIG_XFS_QUOTA is not set
-+# CONFIG_XFS_RT is not set
-+# CONFIG_XFS_TRACE is not set
-+# CONFIG_XFS_DEBUG is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_NFS_DIRECTIO is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Support for USB gadgets
-+#
-+# CONFIG_USB_GADGET is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
-+# CONFIG_DEBUG_ERRORS is not set
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_CRC32=y
-+# CONFIG_ZLIB_INFLATE is not set
-+# CONFIG_ZLIB_DEFLATE is not set
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/CPDO.S 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,682 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the number
-+represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
-+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+
-+The parameters to these functions are r0=destination pointer, r1 and r2
-+source pointers. r4 is the instruction. They may use r0-r8 and r14. They return
-+to fastfpe_next, except CPDO_rnf_core which expects the return address in r14.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_adf
-+CPDO_adf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+ cmp r7,#0x7fffffff
-+ cmpne r8,#0x7fffffff
-+ beq CPDO_adf_extra
-+
-+ cmp r1,r2
-+ bne CPDO_suf_s
-+
-+CPDO_adf_s:
-+ subs r2,r7,r8
-+ bge CPDO_adf_2nd
-+
-+ mov r7,r8
-+ rsb r2,r2,#0
-+ cmp r2,#32
-+ ble CPDO_adf_1st2
-+
-+ sub r2,r2,#32
-+ cmp r2,#32
-+ movgt r2,#32
-+ mov r5,r3,lsr r2
-+ mov r3,#0
-+ b CPDO_adf_add
-+
-+CPDO_adf_1st2:
-+ rsb r8,r2,#32
-+ mov r5,r5,lsr r2
-+ orr r5,r5,r3,lsl r8
-+ mov r3,r3,lsr r2 @ 1. op normalized
-+ b CPDO_adf_add
-+
-+CPDO_adf_2nd:
-+ cmp r2,#32
-+ ble CPDO_adf_2nd2
-+
-+ sub r2,r2,#32
-+ cmp r2,#32
-+ movgt r2,#32
-+ mov r6,r4,lsr r2
-+ mov r4,#0
-+ b CPDO_adf_add
-+
-+CPDO_adf_2nd2:
-+ rsb r8,r2,#32
-+ mov r6,r6,lsr r2
-+ orr r6,r6,r4,lsl r8
-+ mov r4,r4,lsr r2 @ 2. op normalized
-+
-+CPDO_adf_add:
-+ adds r5,r5,r6
-+ adcs r3,r3,r4 @ do addition
-+ bcc CPDO_adf_end
-+
-+ add r7,r7,#1
-+ movs r3,r3,rrx
-+ mov r5,r5,rrx @ correct for overflow
-+
-+CPDO_adf_end:
-+ cmp r7,#0x20000000
-+ bge CPDO_inf
-+
-+ stmia r0,{r1,r3,r5,r7}
-+ b fastfpe_next
-+
-+CPDO_adf_extra:
-+ cmp r7,#0x7fffffff @ was it the 1st ?
-+ bne CPDO_infnan_2 @ no it was the 2nd
-+ cmp r8,#0x7fffffff @ if 1st, 2nd too ?
-+ bne CPDO_infnan_1 @ no only 1st
-+ cmp r3,#0
-+ cmpeq r4,#0
-+ bne CPDO_nan_12
-+ b CPDO_inf
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDO_infnan_1:
-+ stmia r0,{r1,r3,r5,r7}
-+ b fastfpe_next
-+
-+CPDO_infnan_2:
-+ stmia r0,{r2,r4,r6,r8}
-+ b fastfpe_next
-+
-+CPDO_nan_12:
-+ orr r2,r3,r4
-+ b CPDO_inf_1
-+
-+CPDO_nan:
-+ mov r2,#0x40000000 @ create non signalling NaN
-+ b CPDO_inf_1
-+
-+CPDO_inf:
-+ mov r2,#0
-+CPDO_inf_1:
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+CPDO_store_1234:
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+CPDO_zero:
-+ mov r1,#0
-+CPDO_zero_1:
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_suf
-+CPDO_suf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+CPDO_suf_l:
-+ cmp r7,#0x7fffffff
-+ cmpne r8,#0x7fffffff
-+ beq CPDO_suf_extra
-+
-+ cmp r1,r2
-+ bne CPDO_adf_s
-+
-+CPDO_suf_s:
-+ subs r2,r7,r8 @ determine greater number
-+ bgt CPDO_suf_2nd @ first number is greater
-+ blt CPDO_suf_1st @ second number is greater
-+ cmp r3,r4 @ also mantissa is important
-+ cmpeq r5,r6
-+ bhi CPDO_suf_2nd @ first number is greater
-+ beq CPDO_zero
-+
-+CPDO_suf_1st:
-+ eor r1,r1,#0x80000000 @ second number is greater, invert sign
-+ mov r7,r8
-+ rsb r2,r2,#0
-+ cmp r2,#32
-+ ble CPDO_suf_1st2
-+
-+ sub r2,r2,#32
-+ cmp r2,#32
-+ movgt r2,#32
-+ mov r5,r3,lsr r2
-+ mov r3,#0
-+ b CPDO_suf_1st_sub
-+
-+CPDO_suf_1st2:
-+ rsb r8,r2,#32
-+ mov r5,r5,lsr r2
-+ orr r5,r5,r3,lsl r8
-+ mov r3,r3,lsr r2 @ 1. op normalized
-+
-+CPDO_suf_1st_sub:
-+ subs r5,r6,r5 @ do subtraction
-+ sbc r3,r4,r3
-+ b CPDO_suf_norm
-+
-+CPDO_suf_2nd:
-+ cmp r2,#32
-+ ble CPDO_suf_2nd2
-+
-+ sub r2,r2,#32
-+ cmp r2,#32
-+ movgt r2,#32
-+ mov r6,r4,lsr r2
-+ mov r4,#0
-+ b CPDO_suf_2nd_sub
-+
-+CPDO_suf_2nd2:
-+ rsb r8,r2,#32
-+ mov r6,r6,lsr r2
-+ orr r6,r6,r4,lsl r8
-+ mov r4,r4,lsr r2 @ 2. op normalized
-+
-+CPDO_suf_2nd_sub:
-+ subs r5,r5,r6
-+ sbc r3,r3,r4 @ do subtraction
-+
-+CPDO_suf_norm:
-+ teq r3,#0 @ normalize 32bit
-+ moveq r3,r5
-+ moveq r5,#0
-+ subeq r7,r7,#32
-+
-+ cmp r3,#0x00010000 @ 16bit
-+ movcc r3,r3,lsl#16
-+ orrcc r3,r3,r5,lsr#16
-+ movcc r5,r5,lsl#16
-+ subcc r7,r7,#16
-+
-+ cmp r3,#0x01000000 @ 8bit
-+ movcc r3,r3,lsl#8
-+ orrcc r3,r3,r5,lsr#24
-+ movcc r5,r5,lsl#8
-+ subcc r7,r7,#8
-+
-+ cmp r3,#0x10000000 @ 4bit
-+ movcc r3,r3,lsl#4
-+ orrcc r3,r3,r5,lsr#28
-+ movcc r5,r5,lsl#4
-+ subcc r7,r7,#4
-+
-+ cmp r3,#0x40000000 @ 2bit
-+ movcc r3,r3,lsl#2
-+ orrcc r3,r3,r5,lsr#30
-+ movcc r5,r5,lsl#2
-+ subcc r7,r7,#2
-+
-+ cmp r3,#0x80000000 @ 1bit
-+ movcc r3,r3,lsl#1
-+ orrcc r3,r3,r5,lsr#31
-+ movcc r5,r5,lsl#1
-+ subcc r7,r7,#1
-+
-+ cmp r7,#0xe0000000
-+ ble CPDO_zero_1
-+
-+ stmia r0,{r1,r3,r5,r7}
-+ b fastfpe_next
-+
-+CPDO_suf_extra:
-+ cmp r7,#0x7fffffff @ was it the 1st ?
-+ eorne r2,r2,#0x80000000 @ change sign, might have been INF
-+ bne CPDO_infnan_2 @ no it was the 2nd
-+ cmp r8,#0x7fffffff @ if 1st, 2nd too ?
-+ bne CPDO_infnan_1 @ no only 1st
-+ cmp r3,#0
-+ cmpeq r4,#0
-+ bne CPDO_nan_12
-+ b CPDO_nan @ here is difference with adf !
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rsf
-+CPDO_rsf:
-+ mov r3,r2
-+ ldmia r1,{r2,r4,r6,r8}
-+ ldmia r3,{r1,r3,r5,r7}
-+ b CPDO_suf_l
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_muf
-+CPDO_muf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+ cmp r7,#0x7fffffff
-+ cmpne r8,#0x7fffffff
-+ beq CPDO_muf_extra
-+
-+ eor r1,r1,r2
-+ adds r8,r7,r8
-+ bvs CPDO_zero_1
-+
-+ umull r7,r2,r3,r4
-+ umull r14,r3,r6,r3
-+ adds r7,r7,r3 @ r2|r7|r14 = r2|r7|#0 + #0|r3|r14
-+ adc r2,r2,#0
-+ umull r4,r3,r5,r4
-+ adds r14,r14,r4 @ r2|r7|r14 += #0|r3|r4
-+ adcs r7,r7,r3
-+ adc r2,r2,#0
-+ umull r4,r3,r5,r6
-+ adds r14,r14,r3 @ r2|r7|r14 += #0|#0|r3
-+ adcs r7,r7,#0
-+ adcs r2,r2,#0
-+
-+ bpl CPDO_muf_norm
-+
-+ add r8,r8,#1
-+ b CPDO_muf_end
-+
-+CPDO_muf_norm:
-+ adds r14,r14,r14
-+ adcs r7,r7,r7
-+ adcs r2,r2,r2
-+
-+CPDO_muf_end:
-+ cmp r8,#0x20000000
-+ bge CPDO_inf
-+ cmp r8,#0xe0000000
-+ ble CPDO_zero_1
-+ stmia r0,{r1,r2,r7,r8}
-+ b fastfpe_next
-+
-+CPDO_muf_extra:
-+ cmp r7,#0x7fffffff @ was it the first?
-+ bne CPDO_muf_extra_2nd @ no, so it was the second
-+ cmp r8,#0x7fffffff @ yes, second too?
-+ bne CPDO_muf_extra_1st @ no, only first
-+ orr r3,r3,r4 @ if both inf -> inf, otherwise nan
-+ eor r1,r1,r2 @ sign for the inf case
-+ b CPDO_infnan_1
-+
-+CPDO_muf_extra_1st:
-+ cmp r3,#0 @ is it a nan?
-+ bne CPDO_infnan_1
-+ cmp r8,#0x80000000 @ is the second 0?
-+ beq CPDO_nan
-+ eor r1,r1,r2 @ correct sign for inf
-+ b CPDO_inf
-+
-+CPDO_muf_extra_2nd:
-+ cmp r4,#0 @ is it a nan?
-+ bne CPDO_infnan_2
-+ cmp r7,#0x80000000 @ is the first 0?
-+ beq CPDO_nan
-+ eor r1,r1,r2 @ correct sign for inf
-+ b CPDO_inf
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_dvf
-+CPDO_dvf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+CPDO_dvf_l:
-+ cmp r7,#0x7fffffff
-+ cmpne r8,#0x7fffffff
-+ beq CPDO_dvf_extra
-+ cmp r8,#0x80000000
-+ beq CPDO_dvf_by0
-+
-+ eor r1,r1,r2
-+ cmp r7,#0x80000000
-+ beq CPDO_zero_1
-+
-+ sub r8,r7,r8
-+
-+ mov r2,#0
-+ mov r7,#1
-+
-+ cmp r3,r4
-+ cmpeq r5,r6
-+ bcs CPDO_dvf_loop_
-+
-+ sub r8,r8,#1
-+
-+CPDO_dvf_loop:
-+ adds r5,r5,r5
-+ adcs r3,r3,r3
-+ bcs CPDO_dvf_anyway
-+CPDO_dvf_loop_:
-+ subs r5,r5,r6
-+ sbcs r3,r3,r4
-+ bcs CPDO_dvf_okay
-+
-+ adds r5,r5,r6
-+ adc r3,r3,r4
-+ adds r7,r7,r7
-+ adcs r2,r2,r2
-+ bcc CPDO_dvf_loop
-+ b CPDO_dvf_end
-+
-+CPDO_dvf_anyway:
-+ adcs r7,r7,r7
-+ adcs r2,r2,r2
-+ bcs CPDO_dvf_end
-+ subs r5,r5,r6
-+ sbc r3,r3,r4
-+ b CPDO_dvf_loop
-+
-+CPDO_dvf_okay:
-+ adcs r7,r7,r7
-+ adcs r2,r2,r2
-+ bcc CPDO_dvf_loop
-+
-+CPDO_dvf_end:
-+ b CPDO_muf_end
-+
-+CPDO_dvf_by0:
-+ cmp R7,#0x80000000
-+ beq CPDO_nan @ first also 0 -> nan
-+ eor r1,r1,r2 @ otherwise calculatesign for inf
-+ b CPDO_inf
-+
-+CPDO_dvf_extra:
-+ cmp r7,#0x7fffffff @ was it the first?
-+ bne CPDO_dvf_extra_2nd @ no, so it was the second
-+ cmp r8,#0x7fffffff @ yes, second too?
-+ bne CPDO_dvf_extra_1st @ no, only first
-+ orrs r3,r3,r4
-+ beq CPDO_nan @ if both inf -> create nan
-+ b CPDO_nan_12 @ otherwise keep nan
-+
-+CPDO_dvf_extra_1st:
-+ eor r1,r1,r2 @ correct sign for inf
-+ b CPDO_infnan_1
-+
-+CPDO_dvf_extra_2nd:
-+ cmp r4,#0 @ is it a nan?
-+ bne CPDO_infnan_2
-+ eor r1,r1,r2 @ correct sign for zero
-+ b CPDO_zero_1
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rdf
-+CPDO_rdf:
-+ mov r3,r2
-+ ldmia r1,{r2,r4,r6,r8}
-+ ldmia r3,{r1,r3,r5,r7}
-+ b CPDO_dvf_l
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rmf
-+CPDO_rmf:
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_mvf
-+CPDO_mvf:
-+ ldmia r2,{r1,r2,r3,r4}
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_mnf
-+CPDO_mnf:
-+ ldmia r2,{r1,r2,r3,r4}
-+ eor r1,r1,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_abs
-+CPDO_abs:
-+ ldmia r2,{r1,r2,r3,r4}
-+ bic r1,r1,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_sqt
-+CPDO_sqt:
-+ ldmia r2,{r1,r2,r3,r4}
-+ cmp r1,#0
-+ bne CPDO_nan
-+ cmp r4,#0x7fffffff
-+ beq CPDO_store_1234
-+
-+ tst r4,r4,lsr#1 @carry=exponent bit 0
-+ bcc CPDO_sqt_exponenteven
-+ adds r3,r3,r3
-+ adcs r2,r2,r2 @carry is needed in loop!
-+CPDO_sqt_exponenteven:
-+ mov r4,r4,asr #1
-+ str r4,[r0,#12]
-+
-+ mov r4,#0x80000000
-+ mov r5,#0
-+ sub r2,r2,#0x80000000
-+
-+ mov r8,#0x40000000
-+ mov r14,#0x80000000
-+
-+ mov r1,#1
-+ b CPDO_sqt_loop1_first
-+CPDO_sqt_loop1:
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+CPDO_sqt_loop1_first:
-+ add r6,r4,r8,lsr r1 @r7 const = r5
-+ bcs CPDO_sqt_loop1_1
-+ cmp r2,r6
-+ cmpeq r3,r5 @r5 for r7
-+ bcc CPDO_sqt_loop1_0
-+CPDO_sqt_loop1_1:
-+ orr r4,r4,r14,lsr r1
-+ subs r3,r3,r5 @r5 for r7
-+ sbc r2,r2,r6
-+CPDO_sqt_loop1_0:
-+ add r1,r1,#1
-+ cmp r1,#30
-+ ble CPDO_sqt_loop1
-+
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_between_1
-+ adds r7,r5,#0x80000000
-+ adc r6,r4,#0
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_between_0
-+CPDO_sqt_between_1:
-+ orr r4,r4,#0x00000001
-+ subs r3,r3,r5
-+ sbc r2,r2,r4
-+ subs r3,r3,#0x80000000
-+ sbc r2,r2,#0
-+CPDO_sqt_between_0:
-+ mov r1,#0
-+
-+CPDO_sqt_loop2:
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_loop2_1
-+ adds r7,r5,r8,lsr r1
-+ adc r6,r4,#0
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_loop2_0
-+CPDO_sqt_loop2_1:
-+ orr r5,r5,r14,lsr r1
-+ subs r3,r3,r5
-+ sbc r2,r2,r4
-+ subs r3,r3,r8,lsr r1
-+ sbc r2,r2,#0
-+CPDO_sqt_loop2_0:
-+ add r1,r1,#1
-+ cmp r1,#30
-+ ble CPDO_sqt_loop2
-+
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_after_1
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_after_0
-+CPDO_sqt_after_1:
-+ orr r5,r5,#0x00000001
-+CPDO_sqt_after_0:
-+
-+ mov r1,#0
-+ stmia r0,{r1,r4,r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rnd
-+CPDO_rnd:
-+ ldmia r2,{r1,r2,r3,r5}
-+ bl CPDO_rnd_core
-+
-+CPDO_rnd_store:
-+ stmia r0,{r1,r2,r3,r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rnd_core
-+CPDO_rnd_core:
-+ and r4,r4,#0x00000060
-+ add pc,pc,r4,lsr#3
-+ mov r0,r0
-+ b CPDO_rnd_N
-+ b CPDO_rnd_P
-+ b CPDO_rnd_M
-+ b CPDO_rnd_Z
-+
-+CPDO_rnd_N:
-+ cmp r5,#-1
-+ blt CPDO_rnd_zero
-+ cmp r5,#63
-+ movge pc,r14
-+ mov r4,#0x40000000
-+ cmp r5,#31
-+ bge CPDO_rnd_N_2
-+
-+ adds r2,r2,r4,lsr r5
-+ bcc CPDO_rnd_end
-+ b CPDO_rnd_end_norm
-+
-+CPDO_rnd_N_2:
-+CPDO_rnd_P_2:
-+ sub r6,r5,#32
-+ adds r3,r3,r4,ror r6 @ror ist needed to handle a -1 correctly
-+ adcs r2,r2,#0
-+ bcc CPDO_rnd_end
-+ b CPDO_rnd_end_norm
-+
-+CPDO_rnd_P:
-+ tst r1,#0x80000000
-+ bne CPDO_rnd_M_entry
-+CPDO_rnd_P_entry:
-+ cmp r5,#0
-+ blt CPDO_rnd_P_small
-+ cmp r5,#63
-+ movge pc,r14
-+ mov r4,#0x7fffffff
-+ cmp r5,#32
-+ bge CPDO_rnd_P_2
-+
-+ adds r3,r3,#0xffffffff
-+ adcs r2,r2,r4,lsr r5
-+ bcc CPDO_rnd_end
-+ b CPDO_rnd_end_norm
-+
-+CPDO_rnd_P_small:
-+ cmp r5,#0x80000000
-+ moveq pc,r14
-+ b CPDO_rnd_one
-+
-+CPDO_rnd_M:
-+ tst r1,#0x80000000
-+ bne CPDO_rnd_P_entry
-+CPDO_rnd_M_entry:
-+ cmp r5,#0
-+ blt CPDO_rnd_zero
-+ cmp r5,#63
-+ movge pc,r14
-+
-+ b CPDO_rnd_end
-+
-+CPDO_rnd_Z:
-+ cmp r5,#0
-+ blt CPDO_rnd_zero
-+ cmp r5,#63
-+ movge pc,r14
-+ b CPDO_rnd_end
-+
-+CPDO_rnd_end_norm:
-+ add r5,r5,#1
-+ movs r2,r2,rrx
-+ mov r3,r3,rrx
-+CPDO_rnd_end:
-+ rsbs r4,r5,#31
-+ bmi CPDO_rnd_end_2
-+ mov r3,#0
-+ mov r2,r2,lsr r4
-+ mov r2,r2,lsl r4
-+ mov pc,r14
-+
-+CPDO_rnd_end_2:
-+ rsb r4,r5,#63
-+ mov r3,r3,lsr r4
-+ mov r3,r3,lsl r4
-+ mov pc,r14
-+
-+CPDO_rnd_one:
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r5,#0
-+ mov pc,r14
-+
-+CPDO_rnd_zero:
-+ mov r1,#0
-+ mov r2,#0
-+ mov r3,#0
-+ mov r5,#0x80000000
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/CPDT.S 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,430 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the number
-+represented is infinity if the high 32 mantissa bit are also 0, otherwise it is
-+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_single
-+CPDT_load_single:
-+ ldr r1,[r6]
-+
-+ and r2,r1,#0x80000000 @ r2 = sign
-+
-+ mov r5,r1,lsr#23
-+ bics r5,r5,#0x100
-+ beq CPDT_ls_e0 @ exponent = 0; zero/denormalized
-+ teq r5,#255
-+ beq CPDT_ls_e255 @ exponent = 255; infinity/NaN
-+
-+ sub r5,r5,#127 @ r5 = exponent, remove normalized bias
-+
-+ mov r3,r1,lsl#8
-+ orr r3,r3,#0x80000000
-+ mov r4,#0 @ r3,r4 = mantissa
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ls_e0:
-+ movs r3,r1,lsl#9
-+ beq CPDT_load_zero
-+
-+ mov r5,#-127
-+
-+CPDT_ls_e0_norm:
-+ tst r3,#0x80000000
-+ subeq r5,r5,#1
-+ moveq r3,r3,lsl#1
-+ beq CPDT_ls_e0_norm
-+
-+ mov r4,#0
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ls_e255:
-+ mov r3,r1,lsl#9
-+ mov r4,#0
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_load_zero:
-+ mov r3,#0
-+ mov r4,#0
-+ mov r5,#0x80000000
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_double
-+CPDT_load_double:
-+ ldr r1,[r6]
-+ ldr r6,[r6,#4]
-+
-+ and r2,r1,#0x80000000 @ r2 = sign
-+
-+ mov r5,r1,lsr#20
-+ bics r5,r5,#0x800
-+ beq CPDT_ld_e0 @ exponent = 0; zero/denormalized
-+ add r4,r5,#1
-+ teq r4,#2048
-+ beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN
-+
-+ add r5,r5,#1
-+ sub r5,r5,#1024 @ r5 = exponent, remove normalized bias
-+
-+ mov r3,r1,lsl#11
-+ orr r3,r3,#0x80000000
-+ orr r3,r3,r6,lsr #21
-+ mov r4,r6,lsl#11 @ r3,r4 = mantissa
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ld_e0:
-+ mov r3,r1,lsl#12
-+ orr r3,r3,r6,lsr#20
-+ movs r4,r6,lsl#12
-+ teqeq r3,#0
-+ beq CPDT_load_zero
-+
-+ mov r5,#1
-+ sub r5,r5,#1024
-+
-+CPDT_ld_e0_norm:
-+ tst r3,#0x80000000
-+ subeq r5,r5,#1
-+ moveqs r4,r4,lsl#1
-+ adceq r3,r3,r3
-+ beq CPDT_ld_e0_norm
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ld_e2047:
-+ mov r3,r1,lsl#12
-+ orr r3,r3,r6,lsr#1
-+ bic r6,r6,#0x80000000
-+ orr r3,r3,r6 @ to get all fraction bits !
-+ mov r4,#0
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_extended
-+CPDT_load_extended:
-+ ldr r1,[r6]
-+ ldr r3,[r6,#4]
-+ ldr r4,[r6,#8]
-+
-+ and r2,r1,#0x80000000
-+ bics r5,r1,#0x80000000
-+ beq CPDT_le_e0
-+ add r1,r5,#1
-+ teq r4,#32768
-+ beq CPDT_le_e32767
-+
-+ add r5,r5,#1
-+ sub r5,r5,#16384
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_le_e0:
-+ teq r3,#0
-+ teqeq r4,#0
-+ beq CPDT_load_zero
-+
-+ mov r5,#2
-+ sub r5,r5,#16384
-+ b CPDT_ld_e0_norm
-+
-+CPDT_le_e32767:
-+ mov r3,r3,lsl#1
-+ orr r3,r3,r4,lsr#1
-+ bic r4,r4,#0x80000000
-+ orr r3,r3,r4
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_decimal
-+CPDT_load_decimal:
-+
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_single
-+CPDT_store_single:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#-127
-+ ble CPDT_ss_e0
-+ cmp r4,#128
-+ bge CPDT_ss_e255
-+
-+ adds r2,r2,#1<<7 @ round to nearest
-+ bcs CPDT_ss_rnd_ovfl @ very very seldom taken
-+
-+CPDT_ss_store:
-+ add r4,r4,#127
-+ orr r1,r1,r4,lsl#23
-+
-+ bic r2,r2,#0x80000000
-+ orr r1,r1,r2,lsr#8
-+
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+CPDT_ss_rnd_ovfl:
-+ add r4,r4,#1
-+ cmp r4,#128
-+ bge CPDT_ss_e255
-+
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ b CPDT_ss_store
-+
-+CPDT_ss_e0:
-+ cmp r4,#-150
-+ ble CPDT_ss_zero
-+
-+ add r4,r4,#126
-+CPDT_ss_unnormalize:
-+ mov r2,r2,lsr#1
-+ adds r4,r4,#1
-+ bne CPDT_ss_unnormalize
-+
-+ orr r1,r1,r2,lsr#8
-+
-+CPDT_ss_zero:
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+CPDT_ss_e255:
-+ cmp r4,#0x7fffffff
-+ bne CPDT_ss_inf
-+ cmp r2,#0
-+ beq CPDT_ss_inf
-+
-+ orr r1,r1,#0x00200000 @ for safety so that it is not INF
-+ orr r1,r1,r2,lsr#9 @ get highest bit of mantissa
-+
-+CPDT_ss_inf:
-+ orr r1,r1,#0x7f000000
-+ orr r1,r1,#0x00800000
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_double
-+CPDT_store_double:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#1024 @ this check has to be first, or
-+ bge CPDT_sd_e2047 @ overflow can occur on second !
-+ add r0,r4,#3
-+ cmp r0,#-1023+3 @ cmp with -1023
-+ ble CPDT_sd_e0
-+
-+ adds r3,r3,#1<<10 @ round to nearest
-+ adcs r2,r2,#0
-+ bcs CPDT_sd_rnd_ovfl @ very very seldom taken
-+
-+CPDT_sd_store:
-+ sub r4,r4,#1
-+ add r4,r4,#1024
-+ orr r1,r1,r4,lsl#20
-+
-+ bic r2,r2,#0x80000000
-+ orr r1,r1,r2,lsr#11
-+
-+ mov r2,r2,lsl#21
-+ orr r2,r2,r3,lsr#11
-+
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_rnd_ovfl:
-+ add r4,r4,#1
-+ cmp r4,#1024
-+ bge CPDT_sd_e2047
-+
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ b CPDT_sd_store
-+
-+CPDT_sd_e0:
-+ add r0,r4,#1075-1024
-+ cmp r0,#-1024
-+ ble CPDT_sd_zero
-+
-+ add r4,r4,#1024
-+ sub r4,r4,#2
-+CPDT_sd_unnormalize:
-+ movs r2,r2,lsr#1
-+ mov r3,r3,rrx
-+ adds r4,r4,#1
-+ bne CPDT_sd_unnormalize
-+
-+ orr r1,r1,r2,lsr#11
-+ mov r2,r2,lsl#21
-+ orr r2,r2,r3,lsr#11
-+
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_zero:
-+ mov r2,#0
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_e2047:
-+ cmp r4,#0x7fffffff
-+ bne CPDT_sd_inf
-+ cmp r2,#0
-+ beq CPDT_sd_inf
-+
-+ orr r1,r1,#0x00040000 @ for safety so that it is not INF
-+ orr r1,r1,r2,lsr#12 @ get highest bit of mantissa
-+
-+CPDT_sd_inf:
-+ orr r1,r1,#0x7f000000
-+ orr r1,r1,#0x00f00000
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_extended
-+CPDT_store_extended:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#16384 @ this check has to be first, or
-+ bge CPDT_se_e32767 @ overflow can occur with second !
-+ add r0,r4,#63
-+ cmp r0,#-16383+63
-+ ble CPDT_se_e0
-+
-+ sub r4,r4,#1
-+ add r4,r4,#16384
-+ orr r1,r1,r4
-+
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_e0:
-+ add r0,r4,#16446-16384
-+ cmp r0,#-16384
-+ ble CPDT_se_zero
-+
-+ add r4,r4,#16384
-+ sub r4,r4,#2
-+CPDT_se_unnormalize:
-+ movs r2,r2,lsr#1
-+ mov r3,r3,rrx
-+ adds r4,r4,#1
-+ bne CPDT_se_unnormalize
-+
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_zero:
-+ mov r2,#0
-+ mov r3,#0
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_e32767:
-+ cmp r4,#0x7fffffff
-+ bne CPDT_se_inf
-+ cmp r2,#0
-+ beq CPDT_se_inf
-+
-+ mov r2,r2,lsl#1
-+ orr r2,r2,#0x20000000
-+
-+CPDT_se_inf:
-+ orr r1,r1,#0x00007f00
-+ orr r1,r1,#0x000000ff
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_decimal
-+CPDT_store_decimal:
-+
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_sfm
-+CPDT_sfm:
-+ add r2,r10,r0,lsr#8
-+ ldr r4,[r2,#0]
-+ ldr r3,[r2,#4]
-+ bic r3,r3,#0x80000000
-+ orr r3,r3,r4
-+ str r3,[r6],#4
-+ ldr r3,[r2,#8]
-+ str r3,[r6],#4
-+ ldr r3,[r2,#12]
-+ str r3,[r6],#4
-+
-+ add r0,r0,#1<<12
-+ and r0,r0,#7<<12
-+ subs r1,r1,#1
-+ bne CPDT_sfm
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_lfm
-+CPDT_lfm:
-+ add r2,r10,r0,lsr#8
-+ ldr r4,[r6],#4
-+ and r3,r4,#0x80000000
-+ str r3,[r2,#0]
-+ ldr r3,[r6],#4
-+ str r3,[r2,#8]
-+ ldr r3,[r6],#4
-+ str r3,[r2,#12]
-+
-+ cmp r3,#0x80000000 @ does the exp indicate zero?
-+ biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
-+ beq CPDT_lfm_storer4
-+ cmp r3,#0x7fffffff @ does the exp indicate inf or NaN?
-+ biceq r4,r4,#0x80000000 @ if so, indicate 'denormalized'
-+ beq CPDT_lfm_storer4
-+ orrne r4,r4,#0x80000000 @ otherwise, set normalized bit
-+
-+CPDT_lfm_storer4:
-+ str r4,[r2,#4]
-+
-+ add r0,r0,#1<<12
-+ and r0,r0,#7<<12
-+ subs r1,r1,#1
-+ bne CPDT_lfm
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/CPRT.S 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,185 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used
-+just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the
-+number
-+represented is infinity if the high 32 mantissa bit are also 0, otherwise it
-+is
-+a NaN. The low 32 mantissa bit are 0 if the number represented is infinity.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .text
-+ .globl CPRT_flt
-+CPRT_flt:
-+ add r0,r13,r0,lsr#10
-+ ldr r2,[r0]
-+ mov r3,#0
-+ cmp r2,#0
-+ beq CPRT_flt_zero
-+
-+ ands r0,r2,#0x80000000
-+ rsbne r2,r2,#0
-+ mov r4,#31
-+
-+ cmp r2,#0x00010000
-+ movcc r2,r2,lsl#16
-+ subcc r4,r4,#16
-+
-+ cmp r2,#0x01000000
-+ movcc r2,r2,lsl#8
-+ subcc r4,r4,#8
-+
-+ cmp r2,#0x10000000
-+ movcc r2,r2,lsl#4
-+ subcc r4,r4,#4
-+
-+ cmp r2,#0x40000000
-+ movcc r2,r2,lsl#2
-+ subcc r4,r4,#2
-+
-+ cmp r2,#0x80000000
-+ movcc r2,r2,lsl#1
-+ subcc r4,r4,#1
-+
-+ stmia r1,{r0,r2,r3,r4}
-+ b fastfpe_next
-+
-+CPRT_flt_zero:
-+ mov r0,#0
-+ mov r4,#0x80000000
-+ stmia r1,{r0,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_fix
-+CPRT_fix:
-+ ldmia r2,{r1,r2,r3,r5}
-+ bl CPDO_rnd_core
-+
-+CPRT_back:
-+ add r0,r13,r0,lsr#10
-+ cmp r5,#0
-+ blt CPRT_int_zero
-+ cmp r5,#30
-+ bgt CPRT_overflow
-+
-+ rsb r5,r5,#31
-+ mov r2,r2,lsr r5
-+ tst r1,#0x80000000
-+ rsbne r2,r2,#0
-+
-+ str r2,[r0]
-+ b fastfpe_next
-+
-+CPRT_int_zero:
-+ mov r2,#0
-+ str r2,[r0]
-+ b fastfpe_next
-+
-+CPRT_overflow:
-+ mov r2,#0x80000000
-+ tst r1,#0x80000000
-+ subeq r2,r2,#1
-+ str r2,[r0]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_wfs
-+CPRT_wfs:
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_rfs
-+CPRT_rfs:
-+ add r0,r13,r0,lsr#10
-+ mov r1,#0x02000000 @ Software Emulation, not Acorn FPE
-+ str r1,[r0]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_cmf
-+CPRT_cmf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+CPRT_cmf_e:
-+ ldr r0,[r13,#16*4]
-+
-+ cmp r7,#0x7fffffff
-+ bic r0,r0,#0xf0000000
-+
-+ cmpeq r3,#0xffffffff
-+ beq CPRT_cmf_unordered
-+ cmp r8,#0x7fffffff
-+ cmpeq r4,#0xffffffff
-+ beq CPRT_cmf_unordered
-+
-+ cmp r1,r2
-+ beq CPRT_cmf_equalsign
-+ b CPRT_cmf_sign
-+
-+CPRT_cmf_equalsign:
-+ cmp r7,r8
-+ beq CPRT_cmf_equalexponent
-+ bgt CPRT_cmf_sign
-+ b CPRT_cmf_signb
-+
-+CPRT_cmf_equalexponent:
-+ cmp r3,r4
-+ cmpeq r5,r6
-+ beq CPRT_cmf_equal
-+ bhi CPRT_cmf_sign
-+ b CPRT_cmf_signb
-+
-+CPRT_cmf_sign:
-+ cmp r7,#0x80000000 @ (0.0 == -0.0)?
-+ cmpeq r7,r8
-+ beq CPRT_cmf_equal
-+ tst r1,#0x80000000
-+ orreq r0,r0,#0x20000000
-+ orrne r0,r0,#0x80000000
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_signb:
-+ tst r1,#0x80000000
-+ orrne r0,r0,#0x20000000
-+ orreq r0,r0,#0x80000000
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_equal:
-+ orr r0,r0,#0x60000000
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_unordered:
-+ orr r0,r0,#0x10000000
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_cnf
-+CPRT_cnf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+ eor r2,r2,#0x80000000
-+ b CPRT_cmf_e
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/Makefile 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,25 @@
-+#
-+# linux/arch/arm/fastfpe/Makefile
-+#
-+# Copyright (C) Peter Teichmann
-+#
-+
-+O_TARGET := fast-math-emu.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+fastfpe-objs := module.o entry.o CPDO.o CPRT.o CPDT.o
-+
-+list-multi := fastfpe.o
-+
-+obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o
-+
-+USE_STANDARD_AS_RULE := true
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastfpe.o: $(fastfpe-objs)
-+ $(LD) -r -o $@ $(fastfpe-objs)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/entry.S 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,295 @@
-+/*
-+At entry the registers contain the following information:
-+
-+r14 return address for undefined exception return
-+r9 return address for return from exception
-+r13 user registers on stack, offset 0 up to offset 4*15 contains
-+ registers r0..15, then the psr
-+r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr)
-+
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .data
-+fp_const:
-+ .word 0, 0x00000000, 0, 0x80000000 @ 0
-+ .word 0, 0x80000000, 0, 0 @ 1
-+ .word 0, 0x80000000, 0, 1 @ 2
-+ .word 0, 0xc0000000, 0, 1 @ 3
-+ .word 0, 0x80000000, 0, 2 @ 4
-+ .word 0, 0xa0000000, 0, 2 @ 5
-+ .word 0, 0x80000000, 0, -1 @ 0.5
-+ .word 0, 0xa0000000, 0, 3 @ 10
-+fp_undef:
-+ .word 0
-+fp_cond:
-+ .word 0xf0f0 @ eq
-+ .word 0x0f0f @ ne
-+ .word 0xcccc @ cs
-+ .word 0x3333 @ cc
-+ .word 0xff00 @ mi
-+ .word 0x00ff @ pl
-+ .word 0xaaaa @ vs
-+ .word 0x5555 @ vc
-+ .word 0x0c0c @ hi
-+ .word 0xf3f3 @ ls
-+ .word 0xaa55 @ ge
-+ .word 0x55aa @ lt
-+ .word 0x0a05 @ gt
-+ .word 0xf5fa @ le
-+ .word 0xffff @ al
-+ .word 0x0000 @ nv
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .text
-+ .globl fastfpe_enter
-+fastfpe_enter:
-+ ldr r4,=fp_undef
-+ str r14,[r4] @ to free one register
-+ add r10,r10,#4 @ to make the code simpler
-+ ldr r4,[r13,#60] @ r4=saved PC
-+ ldr r4,[r4,#-4] @ r4=trapped instruction
-+ and r1,r4,#0x00000f00 @ r1=coprocessor << 8
-+next_enter:
-+ cmp r1,#1<<8 @ copro 1 ?
-+ beq copro_1
-+ cmp r1,#2<<8
-+ movne pc,r14
-+
-+copro_2:
-+ and r1,r4,#0x0f000000
-+ cmp r1,#0x0c000000 @ CPDT with post indexing
-+ cmpne r1,#0x0d000000 @ CPDT with pre indexing
-+ beq CPDT_M_enter
-+ mov pc,r14
-+
-+copro_1:
-+ and r1,r4,#0x0f000000
-+ cmp r1,#0x0e000000 @ CPDO
-+ beq CPDO_CPRT_enter
-+ cmp r1,#0x0c000000 @ CPDT with post indexing
-+ cmpne r1,#0x0d000000 @ CPDT with pre indexing
-+ beq CPDT_1_enter
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl fastfpe_next
-+fastfpe_next:
-+ ldr r5,[r13,#60]
-+next_after_cond:
-+__x1:
-+ ldrt r4,[r5],#4
-+
-+ ldr r0,=fp_cond @ check condition of next instruction
-+ ldr r1,[r13,#64] @ psr containing flags
-+ mov r2,r4,lsr#28
-+ mov r1,r1,lsr#28
-+ ldr r0,[r0,r2,lsl#2]
-+ mov r0,r0,lsr r1
-+ tst r0,#1
-+ beq next_after_cond @ must not necessarily have been an
-+ @ FP instruction !
-+ and r1,r4,#0x0f000000 @ Test for copro instruction
-+ cmp r1,#0x0c000000
-+ rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1
-+ movlt pc,r9 @ next is no copro instruction, return
-+
-+ ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8
-+ cmpne r1,#3<<8
-+ movge pc,r9 @ copro = 0 or >=3, return
-+
-+ str r5,[r13,#60] @ save updated pc
-+ b next_enter
-+
-+/*---------------------------------------------------------------------------*/
-+
-+undefined:
-+ ldr r4,=fp_undef
-+ ldr pc,[r4]
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDT_1_enter:
-+ and r5,r4,#0x000f0000 @ r5=base register number << 16
-+ ldr r6,[r13,r5,lsr#14] @ r6=base address
-+ cmp r5,#0x000f0000 @ base register = pc ?
-+ addeq r6,r6,#4
-+ and r7,r4,#0x000000ff @ r7=offset value
-+
-+ tst r4,#0x00800000 @ up or down?
-+ addne r7,r6,r7,lsl#2
-+ subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset
-+ tst r4,#0x01000000 @ preindexing ?
-+ movne r6,r7
-+ tst r4,#0x00200000 @ write back ?
-+ cmpne r5,#0x000f0000 @ base register = pc ?
-+ strne r7,[r13,r5,lsr#14]
-+
-+ and r0,r4,#0x00007000 @ r0=fp register number << 12
-+ add r0,r10,r0,lsr#8 @ r0=address of fp register
-+ mov r1,#0
-+ tst r4,#0x00008000
-+ orrne r1,r1,#1 @ T0
-+ tst r4,#0x00400000
-+ orrne r1,r1,#2 @ T1
-+ tst r4,#0x00100000
-+ orrne r1,r1,#4 @ L/S
-+
-+ add pc,pc,r1,lsl#2
-+ mov r0,r0
-+ b CPDT_store_single @ these functions get
-+ b CPDT_store_double @ r0=address of fp register
-+ b CPDT_store_extended @ r6=address of data
-+ b undefined @ CPDT_store_decimal
-+ b CPDT_load_single
-+ b CPDT_load_double
-+ b CPDT_load_extended
-+ b undefined @ CPDT_load_decimal
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDT_M_enter:
-+ and r5,r4,#0x000f0000 @ r5=base register number << 16
-+ ldr r6,[r13,r5,lsr#14] @ r6=base address
-+ cmp r5,#0x000f0000 @ base register = pc ?
-+ addeq r6,r6,#4
-+ and r7,r4,#0x000000ff @ r7=offset value
-+
-+ tst r4,#0x00800000 @ up or down?
-+ addne r7,r6,r7,lsl#2
-+ subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset
-+ tst r4,#0x01000000 @ preindexing ?
-+ movne r6,r7
-+ tst r4,#0x00200000 @ write back ?
-+ cmpne r5,#0x000f0000 @ base register = pc ?
-+ strne r7,[r13,r5,lsr#14]
-+
-+ and r0,r4,#0x00007000 @ r0=fp register number << 12
-+ and r1,r4,#0x00008000
-+ mov r1,r1,lsr#15 @ N0
-+ and r2,r4,#0x00400000
-+ orrs r1,r1,r2,lsr#21 @ N1
-+ addeq r1,r1,#4 @ r1=register count
-+
-+ tst r4,#0x00100000 @ load/store
-+ beq CPDT_sfm
-+ b CPDT_lfm
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDO_CPRT_enter:
-+ tst r4,#0x00000010
-+ bne CPRT_enter
-+
-+ and r0,r4,#0x00007000
-+ add r0,r10,r0,lsr#8 @ r0=address of Fd
-+ and r1,r4,#0x00070000
-+ add r1,r10,r1,lsr#12 @ r1=address of Fn
-+ tst r4,#0x00000008
-+ bne CPDO_const
-+ and r2,r4,#0x00000007
-+ add r2,r10,r2,lsl#4 @ r2=address of Fm
-+
-+CPDO_constback:
-+ and r3,r4,#0x00f00000
-+ tst r4,#0x00008000
-+ orrne r3,r3,#0x01000000
-+
-+ add pc,pc,r3,lsr#18
-+ mov r0,r0
-+ b CPDO_adf
-+ b CPDO_muf
-+ b CPDO_suf
-+ b CPDO_rsf
-+ b CPDO_dvf
-+ b CPDO_rdf
-+ b undefined
-+ b undefined
-+ b undefined @ CPDO_rmf
-+ b CPDO_muf
-+ b CPDO_dvf
-+ b CPDO_rdf
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b CPDO_mvf
-+ b CPDO_mnf
-+ b CPDO_abs
-+ b CPDO_rnd
-+ b CPDO_sqt
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b CPDO_rnd
-+ b fastfpe_next
-+
-+CPDO_const:
-+ ldr r2,=fp_const
-+ and r3,r4,#0x00000007
-+ add r2,r2,r3,lsl#4
-+ b CPDO_constback
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPRT_enter:
-+ and r0,r4,#0x0000f000 @ r0=Rd<<12
-+ and r1,r4,#0x00070000
-+ add r1,r10,r1,lsr#12 @ r1=address of Fn
-+ tst r4,#0x00000008
-+ bne CPRT_const
-+ and r2,r4,#0x00000007
-+ add r2,r10,r2,lsl#4 @ r2=address of Fm
-+
-+CPRT_constback:
-+ and r3,r4,#0x00f00000
-+
-+ add pc,pc,r3,lsr#18
-+ mov r0,r0
-+ b CPRT_flt
-+ b CPRT_fix
-+ b CPRT_wfs
-+ b CPRT_rfs
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b undefined
-+ b CPRT_cmf
-+ b undefined
-+ b CPRT_cnf
-+ b undefined
-+ b CPRT_cmf
-+ b undefined
-+ b CPRT_cnf
-+
-+CPRT_const:
-+ ldr r2,=fp_const
-+ and r3,r4,#0x00000007
-+ add r2,r2,r3,lsl#4
-+ b CPRT_constback
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ @ The fetch of the next instruction to emulate could fault
-+
-+ .section .fixup,"ax"
-+ .align
-+__f1:
-+ mov pc,r9
-+ .previous
-+ .section __ex_table,"a"
-+ .align 3
-+ .long __x1,__f1
-+ .previous
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/fastfpe/module.c 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,78 @@
-+/*
-+ Fast Floating Point Emulator
-+ (c) Peter Teichmann <mail@peter-teichmann.de>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+
-+#ifndef MODULE
-+#define kern_fp_enter fp_enter
-+
-+extern char fpe_type[];
-+#endif
-+
-+static void (*orig_fp_enter)(void); /* old kern_fp_enter value */
-+extern void (*kern_fp_enter)(void); /* current FP handler */
-+extern void fastfpe_enter(void); /* forward declarations */
-+
-+#ifdef MODULE
-+/*
-+ * Return 0 if we can be unloaded. This can only happen if
-+ * kern_fp_enter is still pointing at fastfpe_enter
-+ */
-+static int fpe_unload(void)
-+{
-+ return (kern_fp_enter == fastfpe_enter) ? 0 : 1;
-+}
-+#endif
-+
-+static int __init fpe_init(void)
-+{
-+#ifdef MODULE
-+ if (!mod_member_present(&__this_module, can_unload))
-+ return -EINVAL;
-+ __this_module.can_unload = fpe_unload;
-+#else
-+ if (fpe_type[0] && strcmp(fpe_type, "fastfpe"))
-+ return 0;
-+#endif
-+
-+ printk("Fast Floating Point Emulator V0.9 (c) Peter Teichmann.\n");
-+
-+ /* Save pointer to the old FP handler and then patch ourselves in */
-+ orig_fp_enter = kern_fp_enter;
-+ kern_fp_enter = fastfpe_enter;
-+
-+ return 0;
-+}
-+
-+static void __exit fpe_exit(void)
-+{
-+ /* Restore the values we saved earlier. */
-+ kern_fp_enter = orig_fp_enter;
-+}
-+
-+module_init(fpe_init);
-+module_exit(fpe_exit);
-+
-+MODULE_AUTHOR("Peter Teichmann <mail@peter-teichmann.de>");
-+MODULE_DESCRIPTION("Fast floating point emulator with full precision");
---- linux-2.4.25/arch/arm/kernel/calls.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/calls.S 2004-03-31 17:15:08.000000000 +0200
-@@ -115,7 +115,7 @@
- .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */
- .long SYMBOL_NAME(sys_statfs)
- /* 100 */ .long SYMBOL_NAME(sys_fstatfs)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 101 was sys_ioperm */
- .long SYMBOL_NAME(sys_socketcall)
- .long SYMBOL_NAME(sys_syslog)
- .long SYMBOL_NAME(sys_setitimer)
-@@ -126,7 +126,7 @@
- .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */
- /* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */
- .long SYMBOL_NAME(sys_vhangup)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 112 was sys_idle */
- .long SYMBOL_NAME(sys_syscall) /* call a syscall */
- .long SYMBOL_NAME(sys_wait4)
- /* 115 */ .long SYMBOL_NAME(sys_swapoff)
-@@ -137,7 +137,7 @@
- /* 120 */ .long SYMBOL_NAME(sys_clone_wapper)
- .long SYMBOL_NAME(sys_setdomainname)
- .long SYMBOL_NAME(sys_newuname)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 123 was sys_modify_ldt */
- .long SYMBOL_NAME(sys_adjtimex)
- /* 125 */ .long SYMBOL_NAME(sys_mprotect)
- .long SYMBOL_NAME(sys_sigprocmask)
-@@ -180,7 +180,7 @@
- .long SYMBOL_NAME(sys_arm_mremap)
- .long SYMBOL_NAME(sys_setresuid16)
- /* 165 */ .long SYMBOL_NAME(sys_getresuid16)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 166 was sys_vm86 */
- .long SYMBOL_NAME(sys_query_module)
- .long SYMBOL_NAME(sys_poll)
- .long SYMBOL_NAME(sys_nfsservctl)
---- linux-2.4.25/arch/arm/kernel/dma-rpc.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/dma-rpc.c 2004-03-31 17:15:08.000000000 +0200
-@@ -26,19 +26,6 @@
- #include <asm/mach/dma.h>
- #include <asm/hardware/iomd.h>
-
--#if 0
--typedef enum {
-- dma_size_8 = 1,
-- dma_size_16 = 2,
-- dma_size_32 = 4,
-- dma_size_128 = 16
--} dma_size_t;
--
--typedef struct {
-- dma_size_t transfersize;
--} dma_t;
--#endif
--
- #define TRANSFER_SIZE 2
-
- #define CURA (0)
-@@ -48,10 +35,6 @@
- #define CR (IOMD_IO0CR - IOMD_IO0CURA)
- #define ST (IOMD_IO0ST - IOMD_IO0CURA)
-
--#define state_prog_a 0
--#define state_wait_a 1
--#define state_wait_b 2
--
- static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
- {
- unsigned long end, offset, flags = 0;
-@@ -65,7 +48,7 @@
- if (end > PAGE_SIZE)
- end = PAGE_SIZE;
-
-- if (offset + (int) TRANSFER_SIZE > end)
-+ if (offset + TRANSFER_SIZE >= end)
- flags |= DMA_END_L;
-
- sg->length = end - TRANSFER_SIZE;
-@@ -103,27 +86,31 @@
- if (!(status & DMA_ST_INT))
- return;
-
-- if (status & DMA_ST_OFL && !dma->sg)
-- break;
--
-- iomd_get_next_sg(&dma->cur_sg, dma);
-+ if ((dma->state ^ status) & DMA_ST_AB)
-+ iomd_get_next_sg(&dma->cur_sg, dma);
-
- switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
- case DMA_ST_OFL: /* OIA */
- case DMA_ST_AB: /* .IB */
- iomd_writel(dma->cur_sg.dma_address, base + CURA);
- iomd_writel(dma->cur_sg.length, base + ENDA);
-+ dma->state = DMA_ST_AB;
- break;
-
- case DMA_ST_OFL | DMA_ST_AB: /* OIB */
- case 0: /* .IA */
- iomd_writel(dma->cur_sg.dma_address, base + CURB);
- iomd_writel(dma->cur_sg.length, base + ENDB);
-+ dma->state = 0;
- break;
- }
-+
-+ if (status & DMA_ST_OFL &&
-+ dma->cur_sg.length == (DMA_END_S|DMA_END_L))
-+ break;
- } while (1);
-
-- iomd_writeb(0, base + CR);
-+ dma->state = ~DMA_ST_AB;
- disable_irq(irq);
- }
-
-@@ -158,6 +145,7 @@
- }
-
- iomd_writeb(DMA_CR_C, dma_base + CR);
-+ dma->state = DMA_ST_AB;
- }
-
- if (dma->dma_mode == DMA_MODE_READ)
-@@ -171,13 +159,11 @@
- {
- unsigned long dma_base = dma->dma_base;
- unsigned long flags;
-- unsigned int ctrl;
-
- local_irq_save(flags);
-- ctrl = iomd_readb(dma_base + CR);
-- if (ctrl & DMA_CR_E)
-+ if (dma->state != ~DMA_ST_AB)
- disable_irq(dma->dma_irq);
-- iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
-+ iomd_writeb(0, dma_base + CR);
- local_irq_restore(flags);
- }
-
---- linux-2.4.25/arch/arm/kernel/entry-armv.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/entry-armv.S 2004-03-31 17:15:08.000000000 +0200
-@@ -677,12 +677,11 @@
- mrs r9, cpsr @ Enable interrupts if they were
- tst r3, #I_BIT
- biceq r9, r9, #I_BIT @ previously
-- mov r0, r2 @ *** remove once everyones in sync
- /*
- * This routine must not corrupt r9
- */
- #ifdef MULTI_CPU
-- ldr r4, .LCprocfns @ pass r0, r3 to
-+ ldr r4, .LCprocfns @ pass r2, r3 to
- mov lr, pc @ processor code
- ldr pc, [r4] @ call processor specific code
- #else
-@@ -788,9 +787,8 @@
- stmdb r5, {sp, lr}^
- alignment_trap r7, r7, __temp_abt
- zero_fp
-- mov r0, r2 @ remove once everyones in sync
- #ifdef MULTI_CPU
-- ldr r4, .LCprocfns @ pass r0, r3 to
-+ ldr r4, .LCprocfns @ pass r2, r3 to
- mov lr, pc @ processor code
- ldr pc, [r4] @ call processor specific code
- #else
-@@ -840,7 +838,8 @@
- adrsvc al, r9, ret_from_exception @ r9 = normal FP return
- adrsvc al, lr, fpundefinstr @ lr = undefined instr return
-
--call_fpe: get_current_task r10
-+call_fpe: enable_irq r10
-+ get_current_task r10
- mov r8, #1
- strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
- ldr r4, .LCfp
---- linux-2.4.25/arch/arm/kernel/head-armv.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/head-armv.S 2004-03-31 17:15:08.000000000 +0200
-@@ -1,7 +1,7 @@
- /*
- * linux/arch/arm/kernel/head-armv.S
- *
-- * Copyright (C) 1994-1999 Russell King
-+ * Copyright (C) 1994-2003 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
-@@ -163,10 +163,10 @@
- */
- .type __ret, %function
- __ret: ldr lr, __switch_data
-- mcr p15, 0, r0, c1, c0
-- mrc p15, 0, r0, c1, c0, 0 @ read it back.
-- mov r0, r0
-- mov r0, r0
-+ mcr p15, 0, r0, c1, c0, 0
-+ mrc p15, 0, r3, c0, c0, 0
-+ mov r3, r3
-+ mov r3, r3
- mov pc, lr
-
- /*
-@@ -214,6 +214,11 @@
- */
- __create_page_tables:
- pgtbl r4, r5 @ page table address
-+#if defined(CONFIG_CPU_DCACHE_DISABLE)
-+ bic r8, r8, #0x00c @ clear B, C
-+#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
-+ bic r8, r8, #0x004 @ clear B
-+#endif
-
- /*
- * Clear the 16K level 1 swapper page table
---- linux-2.4.25/arch/arm/kernel/irq.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/irq.c 2004-03-31 17:15:08.000000000 +0200
-@@ -549,7 +549,7 @@
- kfree(action);
- goto out;
- }
-- printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
-+ printk(KERN_ERR "Trying to free IRQ%d\n",irq);
- #ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
- #endif
---- linux-2.4.25/arch/arm/kernel/ptrace.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/ptrace.c 2004-03-31 17:15:08.000000000 +0200
-@@ -725,11 +725,8 @@
- goto out_tsk;
- }
- ret = -ESRCH;
-- if (!(child->ptrace & PT_PTRACED))
-- goto out_tsk;
-- if (child->state != TASK_STOPPED && request != PTRACE_KILL)
-- goto out_tsk;
-- if (child->p_pptr != current)
-+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
-+ if (ret)
- goto out_tsk;
-
- ret = do_ptrace(request, child, addr, data);
---- linux-2.4.25/arch/arm/kernel/semaphore.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/semaphore.c 2004-03-31 17:15:08.000000000 +0200
-@@ -193,7 +193,7 @@
- bl __down_interruptible \n\
- mov ip, r0 \n\
- ldmfd sp!, {r0 - r3, pc}^ \n\
--
-+ \n\
- .align 5 \n\
- .globl __down_trylock_failed \n\
- __down_trylock_failed: \n\
---- linux-2.4.25/arch/arm/kernel/signal.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/kernel/signal.c 2004-03-31 17:15:08.000000000 +0200
-@@ -641,10 +641,7 @@
- /* FALLTHRU */
-
- default:
-- sigaddset(&current->pending.signal, signr);
-- recalc_sigpending(current);
-- current->flags |= PF_SIGNALED;
-- do_exit(exit_code);
-+ sig_exit(signr, exit_code, &info);
- /* NOTREACHED */
- }
- }
---- linux-2.4.25/arch/arm/lib/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/Makefile 2004-03-31 17:15:08.000000000 +0200
-@@ -15,7 +15,7 @@
- strnlen_user.o strchr.o strrchr.o testchangebit.o \
- testclearbit.o testsetbit.o uaccess.o getuser.o \
- putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
-- ucmpdi2.o udivdi3.o lib1funcs.o
-+ ucmpdi2.o udivdi3.o lib1funcs.o div64.o
- obj-m :=
- obj-n :=
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/div64.S 2004-03-31 17:15:08.000000000 +0200
-@@ -0,0 +1,59 @@
-+#include <linux/linkage.h>
-+
-+#ifndef __ARMEB__
-+ql .req r0 @ quotient low
-+qh .req r1 @ quotient high
-+onl .req r0 @ original dividend low
-+onh .req r1 @ original dividend high
-+nl .req r4 @ dividend low
-+nh .req r5 @ dividend high
-+res .req r4 @ result
-+#else
-+ql .req r1
-+qh .req r0
-+onl .req r1
-+onh .req r0
-+nl .req r5
-+nh .req r4
-+res .req r5
-+#endif
-+
-+dl .req r3 @ divisor low
-+dh .req r2 @ divsor high
-+
-+
-+ENTRY(do_div64)
-+ stmfd sp!, {r4, r5, lr}
-+ mov nl, onl
-+ movs nh, onh @ if high bits are zero
-+ movne lr, #33
-+ moveq lr, #1 @ only divide low bits
-+ moveq nh, onl
-+
-+ tst dh, #0x80000000
-+ bne 2f
-+1: cmp nh, dh
-+ bls 2f
-+ add lr, lr, #1
-+ movs dh, dh, lsl #1 @ left justify disor
-+ bpl 1b
-+
-+2: movs nh, onh
-+ moveq dl, dh
-+ moveq dh, #0
-+ movne dl, #0
-+ mov ql, #0
-+ mov qh, #0
-+3: subs ip, nl, dl @ trial subtraction
-+ sbcs ip, nh, dh
-+ movcs nh, ip @ only update if successful
-+ subcs nl, nl, dl @ (repeat the subtraction)
-+ adcs ql, ql, ql @ C=1 if successful, shift into
-+ adc qh, qh, qh @ quotient
-+ movs dh, dh, lsr #1 @ shift base high part right
-+ mov dl, dl, rrx @ shift base low part right
-+ subs lr, lr, #1
-+ bne 3b
-+
-+ mov r2, res
-+ ldmfd sp!, {r4, r5, pc}
---- linux-2.4.25/arch/arm/lib/putuser.S~2.4.25-vrs2.patch 2001-10-11 18:04:57.000000000 +0200
-+++ linux-2.4.25/arch/arm/lib/putuser.S 2004-03-31 17:15:09.000000000 +0200
-@@ -30,11 +30,11 @@
-
- .global __put_user_1
- __put_user_1:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #1
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #1
-+ cmp r0, ip
- 1: strlsbt r1, [r0]
- movls r0, #0
- movls pc, lr
-@@ -42,11 +42,11 @@
-
- .global __put_user_2
- __put_user_2:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #2
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #2
-+ cmp r0, ip
- 2: strlsbt r1, [r0], #1
- movls r1, r1, lsr #8
- 3: strlsbt r1, [r0]
-@@ -56,11 +56,11 @@
-
- .global __put_user_4
- __put_user_4:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #4
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #4
-+ cmp r0, ip
- 4: strlst r1, [r0]
- movls r0, #0
- movls pc, lr
---- linux-2.4.25/arch/arm/mach-integrator/pci_v3.c~2.4.25-vrs2.patch 2003-06-13 16:51:29.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-integrator/pci_v3.c 2004-03-31 17:15:09.000000000 +0200
-@@ -21,7 +21,6 @@
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <linux/config.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/ptrace.h>
-@@ -32,6 +31,7 @@
- #include <linux/init.h>
-
- #include <asm/hardware.h>
-+#include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/system.h>
- #include <asm/mach/pci.h>
-@@ -447,15 +447,16 @@
- #define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
- #define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
-
--static int v3_fault(unsigned long addr, struct pt_regs *regs)
-+static int
-+v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- unsigned long pc = instruction_pointer(regs);
- unsigned long instr = *(unsigned long *)pc;
- #if 0
- char buf[128];
-
-- sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-- addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
-+ sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-+ addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
- v3_readb(V3_LB_ISTAT));
- printk(KERN_DEBUG "%s", buf);
- printascii(buf);
-@@ -523,8 +524,6 @@
- #endif
- }
-
--extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
--
- /*
- * V3_LB_BASE? - local bus address
- * V3_LB_MAP? - pci bus address
-@@ -539,7 +538,10 @@
- /*
- * Hook in our fault handler for PCI errors
- */
-- external_fault = v3_fault;
-+ hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch");
-+ hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch");
-+ hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
-+ hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
-
- spin_lock_irqsave(&v3_lock, flags);
-
-@@ -629,7 +631,7 @@
- #if 0
- ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
- if (ret)
-- printk(KERN_ERR "PCI: unable to grab local bus timeout ".
-+ printk(KERN_ERR "PCI: unable to grab local bus timeout "
- "interrupt: %d\n", ret);
- #endif
- }
---- linux-2.4.25/arch/arm/mach-sa1100/pm.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/pm.c 2004-03-31 17:15:09.000000000 +0200
-@@ -21,6 +21,8 @@
- *
- * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
- * Storage is local on the stack now.
-+ * 2003-06-25: Jeff Corrall <jcorrall@mac.com>
-+ * Saved the GPIO levels for resume after sleep.
- */
- #include <linux/config.h>
- #include <linux/init.h>
-@@ -70,13 +72,20 @@
- int pm_do_suspend(void)
- {
- unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+ unsigned long sleep_save_gpsr;
-+ unsigned long sleep_save_gpcr;
-+ unsigned long delta;
-
- cli();
-
- leds_event(led_stop);
-
- /* preserve current time */
-- RCNR = xtime.tv_sec;
-+ delta = xtime.tv_sec - RCNR;
-+
-+ /* save the current state of the GPIO output pins */
-+ sleep_save_gpsr = GPDR & GPLR;
-+ sleep_save_gpcr = GPDR & ~GPLR;
-
- /* save vital registers */
- SAVE(OSCR);
-@@ -121,6 +130,10 @@
- printk(KERN_DEBUG "*** made it back from resume\n");
- #endif
-
-+ /* restore GPIO output state before enabling the pins */
-+ GPSR = sleep_save_gpsr;
-+ GPCR = sleep_save_gpcr;
-+
- /* restore registers */
- RESTORE(GPDR);
- RESTORE(GRER);
-@@ -151,7 +164,7 @@
- RESTORE(ICMR);
-
- /* restore current time */
-- xtime.tv_sec = RCNR;
-+ xtime.tv_sec = RCNR + delta;
-
- leds_event(led_start);
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/sa1100_usb.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,193 @@
-+/*
-+ * sa1100_usb.h
-+ *
-+ * Public interface to the sa1100 USB core. For use by client modules
-+ * like usb-eth and usb-char.
-+ *
-+ */
-+
-+#ifndef _SA1100_USB_H
-+#define _SA1100_USB_H
-+#include <asm/byteorder.h>
-+
-+typedef void (*usb_callback_t)(int flag, int size);
-+
-+/* in usb_ctl.c (see also descriptor methods at bottom of file) */
-+
-+// Open the USB client for client and initialize data structures
-+// to default values, but _do not_ start UDC.
-+int sa1100_usb_open( const char * client_name );
-+
-+// Start UDC running
-+int sa1100_usb_start( void );
-+
-+// Immediately stop udc, fire off completion routines w/-EINTR
-+int sa1100_usb_stop( void ) ;
-+
-+// Disconnect client from usb core
-+int sa1100_usb_close( void ) ;
-+
-+// set notify callback for when core reaches configured state
-+// return previous pointer (if any)
-+typedef void (*usb_notify_t)(void);
-+usb_notify_t sa1100_set_configured_callback( usb_notify_t callback );
-+
-+/* in usb_send.c */
-+int sa1100_usb_xmitter_avail( void );
-+int sa1100_usb_send(char *buf, int len, usb_callback_t callback);
-+void sa1100_usb_send_reset(void);
-+
-+/* in usb_recev.c */
-+int sa1100_usb_recv(char *buf, int len, usb_callback_t callback);
-+void sa1100_usb_recv_reset(void);
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Descriptor Management
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define DescriptorHeader \
-+ __u8 bLength; \
-+ __u8 bDescriptorType
-+
-+
-+// --- Device Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bcdUSB; /* USB specification revision number in BCD */
-+ __u8 bDeviceClass; /* USB class for entire device */
-+ __u8 bDeviceSubClass; /* USB subclass information for entire device */
-+ __u8 bDeviceProtocol; /* USB protocol information for entire device */
-+ __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
-+ __u16 idVendor; /* USB vendor ID */
-+ __u16 idProduct; /* USB product ID */
-+ __u16 bcdDevice; /* vendor assigned device release number */
-+ __u8 iManufacturer; /* index of manufacturer string */
-+ __u8 iProduct; /* index of string that describes product */
-+ __u8 iSerialNumber; /* index of string containing device serial number */
-+ __u8 bNumConfigurations; /* number fo configurations */
-+} __attribute__ ((packed)) device_desc_t;
-+
-+// --- Configuration Descriptor ------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
-+ __u8 bNumInterfaces; /* number of interfaces in this cfg */
-+ __u8 bConfigurationValue; /* used to uniquely ID this cfg */
-+ __u8 iConfiguration; /* index of string describing configuration */
-+ __u8 bmAttributes; /* bitmap of attributes for ths cfg */
-+ __u8 MaxPower; /* power draw in 2ma units */
-+} __attribute__ ((packed)) config_desc_t;
-+
-+// bmAttributes:
-+enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40,
-+ USB_CONFIG_BUSPOWERED=0x80 };
-+// MaxPower:
-+#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
-+
-+// --- Interface Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
-+ __u8 bAlternateSetting; /* ids an alternate setting for this interface */
-+ __u8 bNumEndpoints; /* number of endpoints in this interface */
-+ __u8 bInterfaceClass; /* USB class info applying to this interface */
-+ __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
-+ __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
-+ __u8 iInterface; /* index of string describing interface */
-+} __attribute__ ((packed)) intf_desc_t;
-+
-+// --- Endpoint Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
-+ __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
-+ __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
-+ __u8 bInterval; /* polling interval for this ep in this cfg */
-+} __attribute__ ((packed)) ep_desc_t;
-+
-+// bEndpointAddress:
-+enum { USB_OUT= 0, USB_IN=1 };
-+#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
-+// bmAttributes:
-+enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 };
-+
-+// --- String Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
-+} __attribute__ ((packed)) string_desc_t;
-+
-+/*=======================================================
-+ * Handy helpers when working with above
-+ *
-+ */
-+// these are x86-style 16 bit "words" ...
-+#define make_word_c( w ) __constant_cpu_to_le16(w)
-+#define make_word( w ) __cpu_to_le16(w)
-+
-+// descriptor types
-+enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3,
-+ USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 };
-+
-+
-+/*=======================================================
-+ * Default descriptor layout for SA-1100 and SA-1110 UDC
-+ */
-+
-+/* "config descriptor buffer" - that is, one config,
-+ ..one interface and 2 endpoints */
-+struct cdb {
-+ config_desc_t cfg;
-+ intf_desc_t intf;
-+ ep_desc_t ep1;
-+ ep_desc_t ep2;
-+} __attribute__ ((packed));
-+
-+
-+/* all SA device descriptors */
-+typedef struct {
-+ device_desc_t dev; /* device descriptor */
-+ struct cdb b; /* bundle of descriptors for this cfg */
-+} __attribute__ ((packed)) desc_t;
-+
-+
-+/*=======================================================
-+ * Descriptor API
-+ */
-+
-+/* Get the address of the statically allocated desc_t structure
-+ in the usb core driver. Clients can modify this between
-+ the time they call sa1100_usb_open() and sa1100_usb_start()
-+*/
-+desc_t *
-+sa1100_usb_get_descriptor_ptr( void );
-+
-+
-+/* Set a pointer to the string descriptor at "index". The driver
-+ ..has room for 8 string indicies internally. Index zero holds
-+ ..a LANGID code and is set to US English by default. Inidices
-+ ..1-7 are available for use in the config descriptors as client's
-+ ..see fit. This pointer is assumed to be good as long as the
-+ ..SA usb core is open (so statically allocate them). Returnes -EINVAL
-+ ..if index out of range */
-+int sa1100_usb_set_string_descriptor( int index, string_desc_t * p );
-+
-+/* reverse of above */
-+string_desc_t *
-+sa1100_usb_get_string_descriptor( int index );
-+
-+/* kmalloc() a string descriptor and convert "p" to unicode in it */
-+string_desc_t *
-+sa1100_usb_kmalloc_string_descriptor( const char * p );
-+
-+
-+
-+
-+
-+
-+#endif /* _SA1100_USB_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/sa1111-ohci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,140 @@
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/pci.h>
-+#include <linux/mm.h>
-+
-+#ifdef CONFIG_USB_OHCI
-+
-+/*
-+ * The SA-1111 errata says that the DMA hardware needs to be exercised
-+ * before the clocks are turned on to work properly. This code does
-+ * a tiny dma transfer to prime to hardware.
-+ *
-+ * What DMA errata? I've checked October 1999 and February 2001, both
-+ * of which do not mention such a bug, let alone any details of this
-+ * work-around.
-+ */
-+static void __init sa1111_dma_setup(void)
-+{
-+ dma_addr_t dma_buf;
-+ void * vbuf;
-+
-+ /* DMA init & setup */
-+
-+ /* WARNING: The SA-1111 L3 function is used as part of this
-+ * SA-1111 DMA errata workaround.
-+ *
-+ * N.B., When the L3 function is enabled, it uses GPIO_B<4:5>
-+ * and takes precedence over the PS/2 mouse and GPIO_B
-+ * functions. Refer to "Intel StrongARM SA-1111 Microprocessor
-+ * Companion Chip, Sect 10.2" for details. So this "fix" may
-+ * "break" support of either PS/2 mouse or GPIO_B if
-+ * precautions are not taken to avoid collisions in
-+ * configuration and use of these pins. AFAIK, no precautions
-+ * are taken at this time. So it is likely that the action
-+ * taken here may cause problems in PS/2 mouse and/or GPIO_B
-+ * pin use elsewhere.
-+ *
-+ * But wait, there's more... What we're doing here is
-+ * obviously altogether a bad idea. We're indiscrimanately bit
-+ * flipping config for a few different functions here which
-+ * are "owned" by other drivers. This needs to be handled
-+ * better than it is being done here at this time. */
-+
-+ /* prime the dma engine with a tiny dma */
-+ SKPCR |= SKPCR_I2SCLKEN;
-+ SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN;
-+
-+ SACR0 |= 0x00003305;
-+ SACR1 = 0x00000000;
-+
-+ /*
-+ * We need memory below 1MB.
-+ * NOTE: consistent_alloc gives you some random virtual
-+ * address as its return value, and the DMA address via
-+ * the dma_addr_t pointer.
-+ */
-+ vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
-+
-+ SADTSA = (unsigned long)dma_buf;
-+ SADTCA = 4;
-+
-+ SADTCS |= 0x00000011;
-+ SKPCR |= SKPCR_DCLKEN;
-+
-+ /* wait */
-+ udelay(100);
-+
-+ /* clear reserved but, then disable SAC */
-+ SACR0 &= ~(0x00000002);
-+ SACR0 &= ~(0x00000001);
-+
-+ /* toggle bit clock direction */
-+ SACR0 |= 0x00000004;
-+ SACR0 &= ~(0x00000004);
-+
-+ SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN);
-+
-+ SKPCR &= ~SKPCR_I2SCLKEN;
-+
-+ consistent_free(vbuf, 4, dma_buf);
-+}
-+
-+/*
-+ * reset the SA-1111 usb controller and turn on it's clocks
-+ */
-+int __init sa1111_ohci_hcd_init(void)
-+{
-+ unsigned int usb_reset = 0;
-+
-+ if (machine_is_xp860() ||
-+ machine_has_neponset() ||
-+ machine_is_pfs168() ||
-+ machine_is_badge4())
-+ usb_reset = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
-+
-+ /*
-+ * turn on USB clocks
-+ */
-+ SKPCR |= SKPCR_UCLKEN;
-+ udelay(100);
-+
-+ /*
-+ * Force USB reset
-+ */
-+ USB_RESET = USB_RESET_FORCEIFRESET;
-+ USB_RESET |= USB_RESET_FORCEHCRESET;
-+ udelay(100);
-+
-+ /*
-+ * Take out of reset
-+ */
-+ USB_RESET = 0;
-+
-+ /*
-+ * set power sense and control lines (this from the diags code)
-+ */
-+ USB_RESET = usb_reset;
-+
-+ /*
-+ * Huh? This is a _read only_ register --rmk
-+ */
-+ USB_STATUS = 0;
-+
-+ udelay(10);
-+
-+ /*
-+ * compensate for dma bug
-+ */
-+ sa1111_dma_setup();
-+
-+ return 0;
-+}
-+
-+void sa1111_ohci_hcd_cleanup(void)
-+{
-+ /* turn the USB clock off */
-+ SKPCR &= ~SKPCR_UCLKEN;
-+}
-+
-+#endif /* CONFIG_USB_OHCI */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb-char.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,723 @@
-+/*
-+ * (C) Copyright 2000-2001 Extenex Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * usb-char.c
-+ *
-+ * Miscellaneous character device interface for SA1100 USB function
-+ * driver.
-+ *
-+ * Background:
-+ * The SA1100 function driver ported from the Compaq Itsy project
-+ * has an interface, usb-eth.c, to feed network packets over the
-+ * usb wire and into the Linux TCP/IP stack.
-+ *
-+ * This file replaces that one with a simple character device
-+ * interface that allows unstructured "byte pipe" style reads and
-+ * writes over the USB bulk endpoints by userspace programs.
-+ *
-+ * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
-+ * when set, (the default) causes the ethernet interface to be used.
-+ * When not set, this more pedestrian character interface is linked
-+ * in instead.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ * ward.willats@extenex.com
-+ *
-+ * To do:
-+ * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
-+ * uses and get bytes out at the same time DMA is going on. Investigate:
-+ * a) changing usb_recv to use alloc_consistent() at client request; or
-+ * b) non-ring-buffer based data structures. In the meantime, I am using
-+ * a bounce buffer. Simple, but wasteful.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/cache.h>
-+#include <linux/poll.h>
-+#include <linux/circ_buf.h>
-+#include <linux/timer.h>
-+
-+#include <asm/io.h>
-+#include <asm/semaphore.h>
-+#include <asm/proc/page.h>
-+#include <asm/mach-types.h>
-+
-+#include "usb-char.h"
-+#include "sa1100_usb.h"
-+
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Driver Options
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define VERSION "0.4"
-+
-+
-+#define VERBOSITY 1
-+
-+#if VERBOSITY
-+# define PRINTK(x, a...) printk (x, ## a)
-+#else
-+# define PRINTK(x, a...) /**/
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals - Macros - Enums - Structures
-+//////////////////////////////////////////////////////////////////////////////
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+typedef int bool; enum { false = 0, true = 1 };
-+
-+static const char pszMe[] = "usbchr: ";
-+
-+static wait_queue_head_t wq_read;
-+static wait_queue_head_t wq_write;
-+static wait_queue_head_t wq_poll;
-+
-+/* Serialze multiple writers onto the transmit hardware
-+.. since we sleep the writer during transmit to stay in
-+.. sync. (Multiple writers don't make much sense, but..) */
-+static DECLARE_MUTEX( xmit_sem );
-+
-+// size of usb DATA0/1 packets. 64 is standard maximum
-+// for bulk transport, though most hosts seem to be able
-+// to handle larger.
-+#define TX_PACKET_SIZE 64
-+#define RX_PACKET_SIZE 64
-+#define RBUF_SIZE (4*PAGE_SIZE)
-+
-+static struct wcirc_buf {
-+ char *buf;
-+ int in;
-+ int out;
-+} rx_ring = { NULL, 0, 0 };
-+
-+static struct {
-+ unsigned long cnt_rx_complete;
-+ unsigned long cnt_rx_errors;
-+ unsigned long bytes_rx;
-+ unsigned long cnt_tx_timeouts;
-+ unsigned long cnt_tx_errors;
-+ unsigned long bytes_tx;
-+} charstats;
-+
-+
-+static char * tx_buf = NULL;
-+static char * packet_buffer = NULL;
-+static int sending = 0;
-+static int usb_ref_count = 0;
-+static int last_tx_result = 0;
-+static int last_rx_result = 0;
-+static int last_tx_size = 0;
-+static struct timer_list tx_timer;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+static char * what_the_f( int e );
-+static void free_txrx_buffers( void );
-+static void twiddle_descriptors( void );
-+static void free_string_descriptors( void ) ;
-+static int usbc_open( struct inode *pInode, struct file *pFile );
-+static void rx_done_callback_packet_buffer( int flag, int size );
-+
-+static void tx_timeout( unsigned long );
-+static void tx_done_callback( int flag, int size );
-+
-+static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
-+static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument );
-+static int usbc_close( struct inode *pInode, struct file *pFile );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+static void extenex_configured_notify_proc( void );
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static char * what_the_f( int e )
-+{
-+ char * p;
-+ switch( e ) {
-+ case 0:
-+ p = "noErr";
-+ break;
-+ case -ENODEV:
-+ p = "ENODEV - usb not in config state";
-+ break;
-+ case -EBUSY:
-+ p = "EBUSY - another request on the hardware";
-+ break;
-+ case -EAGAIN:
-+ p = "EAGAIN";
-+ break;
-+ case -EINTR:
-+ p = "EINTR - interrupted\n";
-+ break;
-+ case -EPIPE:
-+ p = "EPIPE - zero length xfer\n";
-+ break;
-+ default:
-+ p = "????";
-+ break;
-+ }
-+ return p;
-+}
-+
-+static void free_txrx_buffers( void )
-+{
-+ if ( rx_ring.buf != NULL ) {
-+ kfree( rx_ring.buf );
-+ rx_ring.buf = NULL;
-+ }
-+ if ( packet_buffer != NULL ) {
-+ kfree( packet_buffer );
-+ packet_buffer = NULL;
-+ }
-+ if ( tx_buf != NULL ) {
-+ kfree( tx_buf );
-+ tx_buf = NULL;
-+ }
-+}
-+
-+/* twiddle_descriptors()
-+ * It is between open() and start(). Setup descriptors.
-+ */
-+static void twiddle_descriptors( void )
-+{
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ string_desc_t * pString;
-+
-+ pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
-+ pDesc->b.ep1.bmAttributes = USB_EP_BULK;
-+ pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
-+ pDesc->b.ep2.bmAttributes = USB_EP_BULK;
-+
-+ if ( machine_is_extenex1() ) {
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ pDesc->dev.idVendor = make_word_c( 0xC9F );
-+ pDesc->dev.idProduct = 1;
-+ pDesc->dev.bcdDevice = make_word_c( 0x0001 );
-+ pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
-+ pDesc->b.cfg.MaxPower = 0;
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "Extenex" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 1, pString );
-+ pDesc->dev.iManufacturer = 1;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "Handheld Theater" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 2, pString );
-+ pDesc->dev.iProduct = 2;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "00000000" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 3, pString );
-+ pDesc->dev.iSerialNumber = 3;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 4, pString );
-+ pDesc->b.intf.iInterface = 4;
-+ }
-+ sa1100_set_configured_callback( extenex_configured_notify_proc );
-+#endif
-+ }
-+}
-+
-+static void free_string_descriptors( void )
-+{
-+ if ( machine_is_extenex1() ) {
-+ string_desc_t * pString;
-+ int i;
-+ for( i = 1 ; i <= 4 ; i++ ) {
-+ pString = sa1100_usb_get_string_descriptor( i );
-+ if ( pString )
-+ kfree( pString );
-+ }
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// ASYNCHRONOUS
-+//////////////////////////////////////////////////////////////////////////////
-+static void kick_start_rx( void )
-+{
-+ if ( usb_ref_count ) {
-+ int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ if ( total_space >= RX_PACKET_SIZE ) {
-+ sa1100_usb_recv( packet_buffer,
-+ RX_PACKET_SIZE,
-+ rx_done_callback_packet_buffer
-+ );
-+ }
-+ }
-+}
-+/*
-+ * rx_done_callback_packet_buffer()
-+ * We have completed a DMA xfer into the temp packet buffer.
-+ * Move to ring.
-+ *
-+ * flag values:
-+ * on init, -EAGAIN
-+ * on reset, -EINTR
-+ * on RPE, -EIO
-+ * on short packet -EPIPE
-+ */
-+static void
-+rx_done_callback_packet_buffer( int flag, int size )
-+{
-+ charstats.cnt_rx_complete++;
-+
-+ if ( flag == 0 || flag == -EPIPE ) {
-+ size_t n;
-+
-+ charstats.bytes_rx += size;
-+
-+ n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ n = MIN( n, size );
-+ size -= n;
-+
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
-+ rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
-+ rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
-+
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+
-+ last_rx_result = 0;
-+
-+ kick_start_rx();
-+
-+ } else if ( flag != -EAGAIN ) {
-+ charstats.cnt_rx_errors++;
-+ last_rx_result = flag;
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+ }
-+ else /* init, start a read */
-+ kick_start_rx();
-+}
-+
-+
-+static void tx_timeout( unsigned long unused )
-+{
-+ printk( "%stx timeout\n", pszMe );
-+ sa1100_usb_send_reset();
-+ charstats.cnt_tx_timeouts++;
-+}
-+
-+
-+// on init, -EAGAIN
-+// on reset, -EINTR
-+// on TPE, -EIO
-+static void tx_done_callback( int flags, int size )
-+{
-+ if ( flags == 0 )
-+ charstats.bytes_tx += size;
-+ else
-+ charstats.cnt_tx_errors++;
-+ last_tx_size = size;
-+ last_tx_result = flags;
-+ sending = 0;
-+ wake_up_interruptible( &wq_write );
-+ wake_up_interruptible( &wq_poll );
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Workers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static int usbc_open( struct inode *pInode, struct file *pFile )
-+{
-+ int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
-+
-+ /* start usb core */
-+ retval = sa1100_usb_open( "usb-char" );
-+ if ( retval ) return retval;
-+
-+ /* allocate memory */
-+ if ( usb_ref_count == 0 ) {
-+ tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+ if ( tx_buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.buf =
-+ (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
-+
-+ if ( rx_ring.buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+
-+ packet_buffer =
-+ (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+
-+ if ( packet_buffer == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.in = rx_ring.out = 0;
-+ memset( &charstats, 0, sizeof( charstats ) );
-+ sending = 0;
-+ last_tx_result = 0;
-+ last_tx_size = 0;
-+ }
-+
-+ /* modify default descriptors */
-+ twiddle_descriptors();
-+
-+ retval = sa1100_usb_start();
-+ if ( retval ) {
-+ printk( "%sAGHH! Could not USB core\n", pszMe );
-+ free_txrx_buffers();
-+ return retval;
-+ }
-+ usb_ref_count++; /* must do _before_ kick_start() */
-+ MOD_INC_USE_COUNT;
-+ kick_start_rx();
-+ return 0;
-+
-+ malloc_fail:
-+ free_txrx_buffers();
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Read endpoint. Note that you can issue a read to an
-+ * unconfigured endpoint. Eventually, the host may come along
-+ * and configure underneath this module and data will appear.
-+ */
-+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval;
-+ int flags;
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%sread()\n", pszMe );
-+
-+ local_irq_save( flags );
-+ if ( last_rx_result == 0 ) {
-+ local_irq_restore( flags );
-+ } else { /* an error happended and receiver is paused */
-+ local_irq_restore( flags );
-+ last_rx_result = 0;
-+ kick_start_rx();
-+ }
-+
-+ add_wait_queue( &wq_read, &wait );
-+ while( 1 ) {
-+ ssize_t bytes_avail;
-+ ssize_t bytes_to_end;
-+
-+ set_current_state( TASK_INTERRUPTIBLE );
-+
-+ /* snap ring buf state */
-+ local_irq_save( flags );
-+ bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ local_irq_restore( flags );
-+
-+ if ( bytes_avail != 0 ) {
-+ ssize_t bytes_to_move = MIN( stCount, bytes_avail );
-+ retval = 0; // will be bytes transfered
-+ if ( bytes_to_move != 0 ) {
-+ size_t n = MIN( bytes_to_end, bytes_to_move );
-+ if ( copy_to_user( pUserBuffer,
-+ &rx_ring.buf[ rx_ring.out ],
-+ n ) ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ bytes_to_move -= n;
-+ retval += n;
-+ // might go 1 char off end, so wrap
-+ rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
-+ if ( copy_to_user( pUserBuffer + n,
-+ &rx_ring.buf[ rx_ring.out ],
-+ bytes_to_move )
-+ ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_ring.out += bytes_to_move; // cannot wrap
-+ retval += bytes_to_move;
-+ kick_start_rx();
-+ }
-+ break;
-+ }
-+ else if ( last_rx_result ) {
-+ retval = last_rx_result;
-+ break;
-+ }
-+ else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
-+ retval = -EAGAIN;
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) { // no data, can sleep, but signal
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule(); // no data, can sleep
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_read, &wait );
-+
-+ if ( retval < 0 )
-+ printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
-+ return retval;
-+}
-+
-+/*
-+ * Write endpoint. This routine attempts to break the passed in buffer
-+ * into usb DATA0/1 packet size chunks and send them to the host.
-+ * (The lower-level driver tries to do this too, but easier for us
-+ * to manage things here.)
-+ *
-+ * We are at the mercy of the host here, in that it must send an IN
-+ * token to us to pull this data back, so hopefully some higher level
-+ * protocol is expecting traffic to flow in that direction so the host
-+ * is actually polling us. To guard against hangs, a 5 second timeout
-+ * is used.
-+ *
-+ * This routine takes some care to only report bytes sent that have
-+ * actually made it across the wire. Thus we try to stay in lockstep
-+ * with the completion routine and only have one packet on the xmit
-+ * hardware at a time. Multiple simultaneous writers will get
-+ * "undefined" results.
-+ *
-+ */
-+static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval = 0;
-+ ssize_t stSent = 0;
-+
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
-+
-+ down( &xmit_sem ); // only one thread onto the hardware at a time
-+
-+ while( stCount != 0 && retval == 0 ) {
-+ int nThisTime = MIN( TX_PACKET_SIZE, stCount );
-+ copy_from_user( tx_buf, pUserBuffer, nThisTime );
-+ sending = nThisTime;
-+ retval = sa1100_usb_send( tx_buf, nThisTime, tx_done_callback );
-+ if ( retval < 0 ) {
-+ char * p = what_the_f( retval );
-+ printk( "%sCould not queue xmission. rc=%d - %s\n",
-+ pszMe, retval, p );
-+ sending = 0;
-+ break;
-+ }
-+ /* now have something on the diving board */
-+ add_wait_queue( &wq_write, &wait );
-+ tx_timer.expires = jiffies + ( HZ * 5 );
-+ add_timer( &tx_timer );
-+ while( 1 ) {
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ if ( sending == 0 ) { /* it jumped into the pool */
-+ del_timer( &tx_timer );
-+ retval = last_tx_result;
-+ if ( retval == 0 ) {
-+ stSent += last_tx_size;
-+ pUserBuffer += last_tx_size;
-+ stCount -= last_tx_size;
-+ }
-+ else
-+ printk( "%sxmission error rc=%d - %s\n",
-+ pszMe, retval, what_the_f(retval) );
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) {
-+ del_timer( &tx_timer );
-+ printk( "%ssignal\n", pszMe );
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_write, &wait );
-+ }
-+
-+ up( &xmit_sem );
-+
-+ if ( 0 == retval )
-+ retval = stSent;
-+ return retval;
-+}
-+
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
-+{
-+ unsigned int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%poll()\n", pszMe );
-+
-+ poll_wait( pFile, &wq_poll, pWait );
-+
-+ if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
-+ retval |= POLLIN | POLLRDNORM;
-+ if ( sa1100_usb_xmitter_avail() )
-+ retval |= POLLOUT | POLLWRNORM;
-+ return retval;
-+}
-+
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument )
-+{
-+ int retval = 0;
-+
-+ switch( nCmd ) {
-+
-+ case USBC_IOC_FLUSH_RECEIVER:
-+ sa1100_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ break;
-+
-+ case USBC_IOC_FLUSH_TRANSMITTER:
-+ sa1100_usb_send_reset();
-+ break;
-+
-+ case USBC_IOC_FLUSH_ALL:
-+ sa1100_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ sa1100_usb_send_reset();
-+ break;
-+
-+ default:
-+ retval = -ENOIOCTLCMD;
-+ break;
-+
-+ }
-+ return retval;
-+}
-+
-+
-+static int usbc_close( struct inode *pInode, struct file * pFile )
-+{
-+ PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
-+ if ( --usb_ref_count == 0 ) {
-+ down( &xmit_sem );
-+ sa1100_usb_stop();
-+ free_txrx_buffers();
-+ free_string_descriptors();
-+ del_timer( &tx_timer );
-+ sa1100_usb_close();
-+ up( &xmit_sem );
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+#include "../../../drivers/char/ex_gpio.h"
-+void extenex_configured_notify_proc( void )
-+{
-+ if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
-+ printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
-+}
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Initialization
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static struct file_operations usbc_fops = {
-+ owner: THIS_MODULE,
-+ open: usbc_open,
-+ read: usbc_read,
-+ write: usbc_write,
-+ poll: usbc_poll,
-+ ioctl: usbc_ioctl,
-+ release: usbc_close,
-+};
-+
-+static struct miscdevice usbc_misc_device = {
-+ USBC_MINOR, "usb_char", &usbc_fops
-+};
-+
-+/*
-+ * usbc_init()
-+ */
-+
-+int __init usbc_init( void )
-+{
-+ int rc;
-+
-+#if !defined( CONFIG_ARCH_SA1100 )
-+ return -ENODEV;
-+#endif
-+
-+ if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
-+ printk( KERN_WARNING "%sCould not register device 10, "
-+ "%d. (%d)\n", pszMe, USBC_MINOR, rc );
-+ return -EBUSY;
-+ }
-+
-+ // initialize wait queues
-+ init_waitqueue_head( &wq_read );
-+ init_waitqueue_head( &wq_write );
-+ init_waitqueue_head( &wq_poll );
-+
-+ // initialize tx timeout timer
-+ init_timer( &tx_timer );
-+ tx_timer.function = tx_timeout;
-+
-+ printk( KERN_INFO "USB Function Character Driver Interface"
-+ " - %s, (C) 2001, Extenex Corp.\n", VERSION
-+ );
-+
-+ return rc;
-+}
-+
-+void __exit usbc_exit( void )
-+{
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(usbc_init);
-+module_exit(usbc_exit);
-+
-+
-+
-+// end: usb-char.c
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb-char.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2001 Extenex Corporation
-+ *
-+ * usb-char.h
-+ *
-+ * Character device emulation client for SA-1100 client usb core.
-+ *
-+ *
-+ *
-+ */
-+#ifndef _USB_CHAR_H
-+#define _USB_CHAR_H
-+
-+#define USBC_MAJOR 10 /* miscellaneous character device */
-+#define USBC_MINOR 240 /* in the "reserved for local use" range */
-+
-+#define USBC_MAGIC 0x8E
-+
-+/* zap everything in receive ring buffer */
-+#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
-+
-+/* reset transmitter */
-+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
-+
-+/* do both of above */
-+#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
-+
-+
-+
-+
-+
-+
-+#endif /* _USB_CHAR_H */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb-eth.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,447 @@
-+ /*
-+ * Ethernet driver for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original initial ethernet test driver
-+ * Copyright (c) Compaq Computer Corporation, 1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
-+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
-+ * Now, since we do not know what size of packet we are receiving
-+ * last usb packet in sequence will always be less than max packet
-+ * receive endpoint can accept.
-+ * Now the only way to check correct start of frame is to compare
-+ * MAC address. Also now we are stalling on each receive error.
-+ *
-+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
-+ * aligned buffer, but this breaks IP code (unaligned access).
-+ *
-+ * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
-+ * they are disabled now.
-+ *
-+ * 03/06/2001 - Readded "zerocopy" receive path (tunable).
-+ *
-+ */
-+
-+// Define DMA_NO_COPY if you want data to arrive directly into the
-+// receive network buffers, instead of arriving into bounce buffer
-+// and then get copied to network buffer.
-+// This does not work correctly right now.
-+#undef DMA_NO_COPY
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/timer.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/random.h>
-+
-+#include "sa1100_usb.h"
-+
-+
-+#define ETHERNET_VENDOR_ID 0x49f
-+#define ETHERNET_PRODUCT_ID 0x505A
-+#define MAX_PACKET 32768
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+
-+// Should be global, so that insmod can change these
-+int usb_rsize=64;
-+int usb_wsize=64;
-+
-+static struct usbe_info_t {
-+ struct net_device *dev;
-+ u16 packet_id;
-+ struct net_device_stats stats;
-+} usbe_info;
-+
-+static char usb_eth_name[16] = "usbf";
-+static struct net_device usb_eth_device;
-+static struct sk_buff *cur_tx_skb, *next_tx_skb;
-+static struct sk_buff *cur_rx_skb, *next_rx_skb;
-+static volatile int terminating;
-+#ifndef DMA_NO_COPY
-+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
-+#endif
-+
-+static int usb_change_mtu (struct net_device *net, int new_mtu)
-+{
-+ if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
-+ return -EINVAL;
-+ // no second zero-length packet read wanted after mtu-sized packets
-+ if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
-+ return -EDOM;
-+
-+ net->mtu = new_mtu;
-+ return 0;
-+}
-+
-+static struct sk_buff *
-+usb_new_recv_skb(void)
-+{
-+ struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
-+
-+ if (skb) {
-+ skb_reserve(skb, 2);
-+ }
-+ return skb;
-+}
-+
-+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
-+static void
-+usb_recv_callback(int flag, int size)
-+{
-+ struct sk_buff *skb;
-+
-+ if (terminating)
-+ return;
-+
-+ skb = cur_rx_skb;
-+
-+ /* flag validation */
-+ if (flag == 0) {
-+ if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
-+ usbe_info.stats.rx_over_errors++;
-+ goto error;
-+ }
-+#ifndef DMA_NO_COPY
-+ memcpy(skb->tail,dmabuf,size);
-+#endif
-+ skb_put(skb, size);
-+ } else {
-+ if (flag == -EIO) {
-+ usbe_info.stats.rx_errors++;
-+ }
-+ goto error;
-+ }
-+
-+ /* validate packet length */
-+ if (size == usb_rsize ) {
-+ /* packet not complete yet */
-+ skb = NULL;
-+ }
-+
-+ /*
-+ * At this point skb is non null if we have a complete packet.
-+ * If so take a fresh skb right away and restart USB receive without
-+ * further delays, then process the packet. Otherwise resume USB
-+ * receive on the current skb and exit.
-+ */
-+
-+ if (skb)
-+ cur_rx_skb = next_rx_skb;
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize,
-+ usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ if (!skb)
-+ return;
-+
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!next_rx_skb) {
-+ /*
-+ * We can't aford loosing buffer space...
-+ * So we drop the current packet and recycle its skb.
-+ */
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ usbe_info.stats.rx_dropped++;
-+ skb_trim(skb, 0);
-+ next_rx_skb = skb;
-+ return;
-+ }
-+ if ( skb->len >= sizeof(struct ethhdr)) {
-+ if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
-+ // This frame is not for us. nor it is broadcast
-+ usbe_info.stats.rx_frame_errors++;
-+ kfree_skb(skb);
-+ goto error;
-+ }
-+ }
-+
-+ if (skb->len) {
-+ int status;
-+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
-+
-+ skb->dev = &usb_eth_device;
-+ skb->protocol = eth_type_trans (skb, &usb_eth_device);
-+ usbe_info.stats.rx_packets++;
-+ usbe_info.stats.rx_bytes += skb->len;
-+ skb->ip_summed = CHECKSUM_NONE;
-+ status = netif_rx (skb);
-+ if (status != NET_RX_SUCCESS)
-+ printk("netif_rx failed with code %d\n",status);
-+ } else {
-+error:
-+ /*
-+ * Error due to HW addr mismatch, or IO error.
-+ * Recycle the current skb and reset USB reception.
-+ */
-+ skb_trim(cur_rx_skb, 0);
-+// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
-+#endif
-+ }
-+}
-+
-+
-+static void
-+usb_send_callback(int flag, int size)
-+{
-+ struct net_device *dev = usbe_info.dev;
-+ struct net_device_stats *stats;
-+ struct sk_buff *skb=cur_tx_skb;
-+ int ret;
-+
-+ if (terminating)
-+ return;
-+
-+ stats = &usbe_info.stats;
-+ switch (flag) {
-+ case 0:
-+ stats->tx_packets++;
-+ stats->tx_bytes += size;
-+ break;
-+ case -EIO:
-+ stats->tx_errors++;
-+ break;
-+ default:
-+ stats->tx_dropped++;
-+ break;
-+ }
-+
-+ cur_tx_skb = next_tx_skb;
-+ next_tx_skb = NULL;
-+ dev_kfree_skb_irq(skb);
-+ if (!cur_tx_skb)
-+ return;
-+
-+ dev->trans_start = jiffies;
-+ ret = sa1100_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb_irq(cur_tx_skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ netif_wake_queue(dev);
-+}
-+
-+static int
-+usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ int ret;
-+ unsigned long flags;
-+
-+ if (next_tx_skb) {
-+ printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
-+ return 1;
-+ }
-+
-+ if (skb_shared (skb)) {
-+ struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
-+ if (!skb2) {
-+ usbe_info.stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 1;
-+ }
-+ skb = skb2;
-+ }
-+
-+ if ((skb->len % usb_wsize) == 0) {
-+ skb->len++; // other side will ignore this one, anyway.
-+ }
-+
-+ local_irq_save(flags);
-+ if (cur_tx_skb) {
-+ next_tx_skb = skb;
-+ netif_stop_queue(dev);
-+ } else {
-+ cur_tx_skb = skb;
-+ dev->trans_start = jiffies;
-+ ret = sa1100_usb_send(skb->data, skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb(skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ }
-+ local_irq_restore(flags);
-+ return 0;
-+}
-+
-+static void
-+usb_xmit_timeout(struct net_device *dev )
-+{
-+ sa1100_usb_send_reset();
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+
-+static int
-+usb_eth_open(struct net_device *dev)
-+{
-+ terminating = 0;
-+ cur_tx_skb = next_tx_skb = NULL;
-+ cur_rx_skb = usb_new_recv_skb();
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!cur_rx_skb || !next_rx_skb) {
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+ return -ENOMEM;;
-+ }
-+
-+ MOD_INC_USE_COUNT;
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ return 0;
-+}
-+
-+static int
-+usb_eth_release(struct net_device *dev)
-+{
-+ terminating = 1;
-+ sa1100_usb_send_reset();
-+ sa1100_usb_recv_reset();
-+ if (cur_tx_skb)
-+ kfree_skb(cur_tx_skb);
-+ if (next_tx_skb)
-+ kfree_skb(next_tx_skb);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static struct net_device_stats *
-+usb_eth_stats(struct net_device *dev)
-+{
-+ struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
-+ struct net_device_stats *stats=NULL;
-+
-+ if (priv)
-+ stats = &priv->stats;
-+ return stats;
-+}
-+
-+static int
-+usb_eth_probe(struct net_device *dev)
-+{
-+ u8 node_id [ETH_ALEN];
-+
-+ get_random_bytes (node_id, sizeof node_id);
-+ node_id [0] &= 0xfe; // clear multicast bit
-+
-+ /*
-+ * Assign the hardware address of the board:
-+ * generate it randomly, as there can be many such
-+ * devices on the bus.
-+ */
-+ memcpy (dev->dev_addr, node_id, sizeof node_id);
-+
-+ dev->open = usb_eth_open;
-+ dev->change_mtu = usb_change_mtu;
-+ dev->stop = usb_eth_release;
-+ dev->hard_start_xmit = usb_eth_xmit;
-+ dev->get_stats = usb_eth_stats;
-+ dev->watchdog_timeo = 1*HZ;
-+ dev->tx_timeout = usb_xmit_timeout;
-+ dev->priv = &usbe_info;
-+
-+ usbe_info.dev = dev;
-+
-+ /* clear the statistics */
-+ memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
-+
-+ ether_setup(dev);
-+ dev->flags &= ~IFF_MULTICAST;
-+ dev->flags &= ~IFF_BROADCAST;
-+ //dev->flags |= IFF_NOARP;
-+
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+MODULE_PARM(usb_rsize, "1i");
-+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa1100");
-+MODULE_PARM(usb_wsize, "1i");
-+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa1100 to host");
-+#endif
-+
-+static int __init
-+usb_eth_init(void)
-+{
-+ int rc;
-+
-+#ifndef DMA_NO_COPY
-+ dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
-+ if (!dmabuf)
-+ return -ENOMEM;
-+#endif
-+ strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
-+ usb_eth_device.init = usb_eth_probe;
-+ if (register_netdev(&usb_eth_device) != 0)
-+ return -EIO;
-+
-+ rc = sa1100_usb_open( "usb-eth" );
-+ if ( rc == 0 ) {
-+ string_desc_t * pstr;
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+
-+ pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
-+ pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
-+ pd->dev.idVendor = ETHERNET_VENDOR_ID;
-+ pd->dev.idProduct = ETHERNET_PRODUCT_ID;
-+ pstr = sa1100_usb_kmalloc_string_descriptor( "SA1100 USB NIC" );
-+ if ( pstr ) {
-+ sa1100_usb_set_string_descriptor( 1, pstr );
-+ pd->dev.iProduct = 1;
-+ }
-+ rc = sa1100_usb_start();
-+ }
-+ return rc;
-+}
-+
-+module_init(usb_eth_init);
-+
-+static void __exit
-+usb_eth_cleanup(void)
-+{
-+ string_desc_t * pstr;
-+ sa1100_usb_stop();
-+ sa1100_usb_close();
-+ if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL )
-+ kfree( pstr );
-+#ifndef DMA_NO_COPY
-+ kfree(dmabuf);
-+#endif
-+ unregister_netdev(&usb_eth_device);
-+}
-+
-+module_exit(usb_eth_cleanup);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb_ctl.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,774 @@
-+ /*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation, 2001
-+ *
-+ * usb_ctl.c
-+ *
-+ * SA1100 USB controller core driver.
-+ *
-+ * This file provides interrupt routing and overall coordination
-+ * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2).
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+
-+int usbctl_next_state_on_event( int event );
-+static void udc_int_hndlr(int, void *, struct pt_regs *);
-+static void initialize_descriptors( void );
-+static void soft_connect_hook( int enable );
-+static void udc_disable(void);
-+static void udc_enable(void);
-+
-+#if CONFIG_PROC_FS
-+#define PROC_NODE_NAME "sausb"
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals
-+//////////////////////////////////////////////////////////////////////////////
-+static const char pszMe[] = "usbctl: ";
-+struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
-+
-+/* device descriptors */
-+static desc_t desc;
-+
-+#define MAX_STRING_DESC 8
-+static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
-+static string_desc_t sd_zero; /* special sd_zero holds language codes */
-+
-+// called when configured
-+static usb_notify_t configured_callback = NULL;
-+
-+enum { kStateZombie = 0, kStateZombieSuspend = 1,
-+ kStateDefault = 2, kStateDefaultSuspend = 3,
-+ kStateAddr = 4, kStateAddrSuspend = 5,
-+ kStateConfig = 6, kStateConfigSuspend = 7
-+};
-+
-+static int device_state_machine[8][6] = {
-+// suspend reset resume adddr config deconfig
-+/* zombie */ { kStateZombieSuspend, kStateDefault, kError, kError, kError, kError },
-+/* zom sus */ { kError, kStateDefault, kStateZombie, kError, kError, kError },
-+/* default */ { kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError },
-+/* def sus */ { kError, kStateDefault, kStateDefault, kError, kError, kError },
-+/* addr */ { kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError },
-+/* addr sus */{ kError, kStateDefault, kStateAddr, kError, kError, kError },
-+/* config */ { kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr },
-+/* cfg sus */ { kError, kStateDefault, kStateConfig, kError, kError, kError }
-+};
-+
-+/* "device state" is the usb device framework state, as opposed to the
-+ "state machine state" which is whatever the driver needs and is much
-+ more fine grained
-+*/
-+static int sm_state_to_device_state[8] =
-+// zombie zom suspend default default sus
-+{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
-+// addr addr sus config config sus
-+ USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
-+};
-+
-+static char * state_names[8] =
-+{ "zombie", "zombie suspended", "default", "default suspended",
-+ "address", "address suspended", "configured", "config suspended"
-+};
-+
-+static char * event_names[6] =
-+{ "suspend", "reset", "resume",
-+ "address assigned", "configure", "de-configure"
-+};
-+
-+static char * device_state_names[] =
-+{ "not attached", "attached", "powered", "default",
-+ "address", "configured", "suspended" };
-+
-+static int sm_state = kStateZombie;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Async
-+//////////////////////////////////////////////////////////////////////////////
-+static void core_kicker(void);
-+
-+static inline void enable_resume_mask_suspend( void );
-+static inline void enable_suspend_mask_resume(void);
-+
-+static void
-+udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ __u32 status = Ser0UDCSR;
-+
-+ /* ReSeT Interrupt Request - UDC has been reset */
-+ if ( status & UDCSR_RSTIR )
-+ {
-+ if ( usbctl_next_state_on_event( kEvReset ) != kError )
-+ {
-+ /* starting 20ms or so reset sequence now... */
-+ printk("%sResetting\n", pszMe);
-+ ep0_reset(); // just set state to idle
-+ ep1_reset(); // flush dma, clear false stall
-+ ep2_reset(); // flush dma, clear false stall
-+ }
-+ // mask reset ints, they flood during sequence, enable
-+ // suspend and resume
-+ Ser0UDCCR |= UDCCR_REM; // mask reset
-+ Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume
-+ UDC_flip( Ser0UDCSR, status ); // clear all pending sources
-+ return; // <-- no reason to continue if resetting
-+ }
-+ // else we have done something other than reset, so be sure reset enabled
-+ UDC_clear( Ser0UDCCR, UDCCR_REM );
-+
-+ /* RESume Interrupt Request */
-+ if ( status & UDCSR_RESIR )
-+ {
-+ usbctl_next_state_on_event( kEvResume );
-+ core_kicker();
-+ enable_suspend_mask_resume();
-+ }
-+
-+ /* SUSpend Interrupt Request */
-+ if ( status & UDCSR_SUSIR )
-+ {
-+ usbctl_next_state_on_event( kEvSuspend );
-+ enable_resume_mask_suspend();
-+ }
-+
-+ UDC_flip(Ser0UDCSR, status); // clear all pending sources
-+
-+ if (status & UDCSR_EIR)
-+ ep0_int_hndlr();
-+
-+ if (status & UDCSR_RIR)
-+ ep1_int_hndlr(status);
-+
-+ if (status & UDCSR_TIR)
-+ ep2_int_hndlr(status);
-+}
-+
-+static inline void enable_resume_mask_suspend( void )
-+{
-+ int i = 0;
-+
-+ while( 1 ) {
-+ Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events
-+ udelay( i );
-+ if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR) )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_resume(): Could not set SUSIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+
-+ i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR &= ~UDCCR_RESIM;
-+ udelay( i );
-+ if ( ( Ser0UDCCR & UDCCR_RESIM ) == 0
-+ ||
-+ (Ser0UDCSR & UDCSR_RSTIR)
-+ )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_resume(): Could not clear RESIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+}
-+
-+static inline void enable_suspend_mask_resume(void)
-+{
-+ int i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR |= UDCCR_RESIM; // mask future resume events
-+ udelay( i );
-+ if ( Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR) )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_suspend(): Could not set RESIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+ i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR &= ~UDCCR_SUSIM;
-+ udelay( i );
-+ if ( ( Ser0UDCCR & UDCCR_SUSIM ) == 0
-+ ||
-+ (Ser0UDCSR & UDCSR_RSTIR)
-+ )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_suspend(): Could not clear SUSIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Public Interface
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* Open SA usb core on behalf of a client, but don't start running */
-+
-+int
-+sa1100_usb_open( const char * client )
-+{
-+ if ( usbd_info.client_name != NULL )
-+ return -EBUSY;
-+
-+ usbd_info.client_name = (char*) client;
-+ memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
-+ memset(string_desc_array, 0, sizeof(string_desc_array));
-+
-+ /* hack to start in zombie suspended state */
-+ sm_state = kStateZombieSuspend;
-+ usbd_info.state = USB_STATE_SUSPENDED;
-+
-+ /* create descriptors for enumeration */
-+ initialize_descriptors();
-+
-+ printk( "%sOpened for %s\n", pszMe, client );
-+ return 0;
-+}
-+
-+/* Start running. Must have called usb_open (above) first */
-+int
-+sa1100_usb_start( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+
-+ /* start UDC internal machinery running */
-+ udc_enable();
-+ udelay( 100 );
-+
-+ /* clear stall - receiver seems to start stalled? 19Jan01ww */
-+ /* also clear other stuff just to be thurough 22Feb01ww */
-+ UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
-+ UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );
-+
-+ /* mask everything */
-+ Ser0UDCCR = 0xFC;
-+
-+ /* flush DMA and fire through some -EAGAINs */
-+ ep1_init( usbd_info.dmach_rx );
-+ ep2_init( usbd_info.dmach_tx );
-+
-+ /* give endpoint notification we are starting */
-+ ep1_state_change_notify( USB_STATE_SUSPENDED );
-+ ep2_state_change_notify( USB_STATE_SUSPENDED );
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* clear all top-level sources */
-+ Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR |
-+ UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
-+
-+ /* EXERIMENT - a short line in the spec says toggling this
-+ ..bit diddles the internal state machine in the udc to
-+ ..expect a suspend */
-+ Ser0UDCCR |= UDCCR_RESIM;
-+ /* END EXPERIMENT 10Feb01ww */
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* enable interrupts. If you are unplugged you will
-+ immediately get a suspend interrupt. If you are plugged
-+ and have a soft connect-circuit, you will get a reset
-+ If you are plugged without a soft-connect, I think you
-+ also get suspend. In short, start with suspend masked
-+ and everything else enabled */
-+ UDC_write( Ser0UDCCR, UDCCR_SUSIM );
-+
-+ printk( "%sStarted for %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Stop USB core from running */
-+int
-+sa1100_usb_stop( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ /* mask everything */
-+ Ser0UDCCR = 0xFC;
-+ ep1_reset();
-+ ep2_reset();
-+ udc_disable();
-+ printk( "%sStopped\n", pszMe );
-+ return 0;
-+}
-+
-+/* Tell SA core client is through using it */
-+int
-+sa1100_usb_close( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ usbd_info.client_name = NULL;
-+ printk( "%sClosed\n", pszMe );
-+ return 0;
-+}
-+
-+/* set a proc to be called when device is configured */
-+usb_notify_t sa1100_set_configured_callback( usb_notify_t func )
-+{
-+ usb_notify_t retval = configured_callback;
-+ configured_callback = func;
-+ return retval;
-+}
-+
-+/*====================================================
-+ * Descriptor Manipulation.
-+ * Use these between open() and start() above to setup
-+ * the descriptors for your device.
-+ *
-+ */
-+
-+/* get pointer to static default descriptor */
-+desc_t *
-+sa1100_usb_get_descriptor_ptr( void ) { return &desc; }
-+
-+/* optional: set a string descriptor */
-+int
-+sa1100_usb_set_string_descriptor( int i, string_desc_t * p )
-+{
-+ int retval;
-+ if ( i < MAX_STRING_DESC ) {
-+ string_desc_array[i] = p;
-+ retval = 0;
-+ } else {
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+/* optional: get a previously set string descriptor */
-+string_desc_t *
-+sa1100_usb_get_string_descriptor( int i )
-+{
-+ return ( i < MAX_STRING_DESC )
-+ ? string_desc_array[i]
-+ : NULL;
-+}
-+
-+
-+/* optional: kmalloc and unicode up a string descriptor */
-+string_desc_t *
-+sa1100_usb_kmalloc_string_descriptor( const char * p )
-+{
-+ string_desc_t * pResult = NULL;
-+
-+ if ( p ) {
-+ int len = strlen( p );
-+ int uni_len = len * sizeof( __u16 );
-+ pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
-+ if ( pResult != NULL ) {
-+ int i;
-+ pResult->bLength = uni_len + 2;
-+ pResult->bDescriptorType = USB_DESC_STRING;
-+ for( i = 0; i < len ; i++ ) {
-+ pResult->bString[i] = make_word( (__u16) p[i] );
-+ }
-+ }
-+ }
-+ return pResult;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Exports to rest of driver
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* called by the int handler here and the two endpoint files when interesting
-+ .."events" happen */
-+
-+int
-+usbctl_next_state_on_event( int event )
-+{
-+ int next_state = device_state_machine[ sm_state ][ event ];
-+ if ( next_state != kError )
-+ {
-+ int next_device_state = sm_state_to_device_state[ next_state ];
-+ printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ],
-+ state_names[ next_state ], device_state_names[ next_device_state ] );
-+
-+ sm_state = next_state;
-+ if ( usbd_info.state != next_device_state )
-+ {
-+ if ( configured_callback != NULL
-+ &&
-+ next_device_state == USB_STATE_CONFIGURED
-+ &&
-+ usbd_info.state != USB_STATE_SUSPENDED
-+ ) {
-+ configured_callback();
-+ }
-+ usbd_info.state = next_device_state;
-+ ep1_state_change_notify( next_device_state );
-+ ep2_state_change_notify( next_device_state );
-+ }
-+ }
-+#if 0
-+ else
-+ printk( "%s%s --> [%s] --> ??? is an error.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ] );
-+#endif
-+ return next_state;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* setup default descriptors */
-+
-+static void
-+initialize_descriptors(void)
-+{
-+ desc.dev.bLength = sizeof( device_desc_t );
-+ desc.dev.bDescriptorType = USB_DESC_DEVICE;
-+ desc.dev.bcdUSB = 0x100; /* 1.0 */
-+ desc.dev.bDeviceClass = 0xFF; /* vendor specific */
-+ desc.dev.bDeviceSubClass = 0;
-+ desc.dev.bDeviceProtocol = 0;
-+ desc.dev.bMaxPacketSize0 = 8; /* ep0 max fifo size */
-+ desc.dev.idVendor = 0; /* vendor ID undefined */
-+ desc.dev.idProduct = 0; /* product */
-+ desc.dev.bcdDevice = 0; /* vendor assigned device release num */
-+ desc.dev.iManufacturer = 0; /* index of manufacturer string */
-+ desc.dev.iProduct = 0; /* index of product description string */
-+ desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
-+ desc.dev.bNumConfigurations = 1;
-+
-+ desc.b.cfg.bLength = sizeof( config_desc_t );
-+ desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
-+ desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
-+ desc.b.cfg.bNumInterfaces = 1;
-+ desc.b.cfg.bConfigurationValue = 1;
-+ desc.b.cfg.iConfiguration = 0;
-+ desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
-+ desc.b.cfg.MaxPower = USB_POWER( 500 );
-+
-+ desc.b.intf.bLength = sizeof( intf_desc_t );
-+ desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
-+ desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
-+ desc.b.intf.bAlternateSetting = 0;
-+ desc.b.intf.bNumEndpoints = 2;
-+ desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
-+ desc.b.intf.bInterfaceSubClass = 0;
-+ desc.b.intf.bInterfaceProtocol = 0;
-+ desc.b.intf.iInterface = 0;
-+
-+ desc.b.ep1.bLength = sizeof( ep_desc_t );
-+ desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT );
-+ desc.b.ep1.bmAttributes = USB_EP_BULK;
-+ desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep1.bInterval = 0;
-+
-+ desc.b.ep2.bLength = sizeof( ep_desc_t );
-+ desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN );
-+ desc.b.ep2.bmAttributes = USB_EP_BULK;
-+ desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep2.bInterval = 0;
-+
-+ /* set language */
-+ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
-+ sd_zero.bDescriptorType = USB_DESC_STRING;
-+ sd_zero.bLength = sizeof( string_desc_t );
-+ sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
-+ sa1100_usb_set_string_descriptor( 0, &sd_zero );
-+}
-+
-+/* soft_connect_hook()
-+ * Some devices have platform-specific circuitry to make USB
-+ * not seem to be plugged in, even when it is. This allows
-+ * software to control when a device 'appears' on the USB bus
-+ * (after Linux has booted and this driver has loaded, for
-+ * example). If you have such a circuit, control it here.
-+ */
-+static void
-+soft_connect_hook( int enable )
-+{
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ if (machine_is_extenex1() ) {
-+ if ( enable ) {
-+ PPDR |= PPC_USB_SOFT_CON;
-+ PPSR |= PPC_USB_SOFT_CON;
-+ } else {
-+ PPSR &= ~PPC_USB_SOFT_CON;
-+ PPDR &= ~PPC_USB_SOFT_CON;
-+ }
-+ }
-+#endif
-+}
-+
-+/* disable the UDC at the source */
-+static void
-+udc_disable(void)
-+{
-+ soft_connect_hook( 0 );
-+ UDC_set( Ser0UDCCR, UDCCR_UDD );
-+}
-+
-+
-+/* enable the udc at the source */
-+static void
-+udc_enable(void)
-+{
-+ UDC_clear(Ser0UDCCR, UDCCR_UDD);
-+}
-+
-+// HACK DEBUG 3Mar01ww
-+// Well, maybe not, it really seems to help! 08Mar01ww
-+static void
-+core_kicker( void )
-+{
-+ __u32 car = Ser0UDCAR;
-+ __u32 imp = Ser0UDCIMP;
-+ __u32 omp = Ser0UDCOMP;
-+
-+ UDC_set( Ser0UDCCR, UDCCR_UDD );
-+ udelay( 300 );
-+ UDC_clear(Ser0UDCCR, UDCCR_UDD);
-+
-+ Ser0UDCAR = car;
-+ Ser0UDCIMP = imp;
-+ Ser0UDCOMP = omp;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Proc Filesystem Support
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#if CONFIG_PROC_FS
-+
-+#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
-+#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
-+#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
-+#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
-+
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ const char * num_fmt = "%25.25s: %8.8lX\n";
-+ const char * cnt_fmt = "%25.25s: %lu\n";
-+ const char * yn_fmt = "%25.25s: %s\n";
-+ const char * yes = "YES";
-+ const char * no = "NO";
-+ unsigned long v;
-+ char * p = page;
-+ int len;
-+
-+ SAY( "SA1100 USB Controller Core\n" );
-+ SAY( "USB state: %s (%s) %d\n",
-+ device_state_names[ sm_state_to_device_state[ sm_state ] ],
-+ state_names[ sm_state ],
-+ sm_state );
-+
-+ SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
-+ SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
-+ SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
-+ SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
-+
-+ SAY( "\n" );
-+
-+ v = Ser0UDCAR;
-+ SAY( "%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v );
-+ v = Ser0UDCIMP;
-+ SAY( "%25.25s: %ld (%8.8lX)\n", "IN max packet size", v+1, v );
-+ v = Ser0UDCOMP;
-+ SAY( "%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v );
-+
-+ v = Ser0UDCCR;
-+ SAY( "\nUDC Mask Register\n" );
-+ SAYV( v );
-+ SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
-+ SAYC( "Suspend interrupts masked", ( v & UDCCR_SUSIM ) ? yes : no );
-+ SAYC( "Resume interrupts masked", ( v & UDCCR_RESIM ) ? yes : no );
-+ SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
-+
-+ v = Ser0UDCSR;
-+ SAY( "\nUDC Interrupt Request Register\n" );
-+ SAYV( v );
-+ SAYC( "Reset pending", ( v & UDCSR_RSTIR ) ? yes : no );
-+ SAYC( "Suspend pending", ( v & UDCSR_SUSIR ) ? yes : no );
-+ SAYC( "Resume pending", ( v & UDCSR_RESIR ) ? yes : no );
-+ SAYC( "ep0 pending", ( v & UDCSR_EIR ) ? yes : no );
-+ SAYC( "receiver pending", ( v & UDCSR_RIR ) ? yes : no );
-+ SAYC( "tramsitter pending", ( v & UDCSR_TIR ) ? yes : no );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ SAYC( "\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden" );
-+#endif
-+
-+#if 0
-+ v = Ser0UDCCS0;
-+ SAY( "\nUDC Endpoint Zero Status Register\n" );
-+ SAYV( v );
-+ SAYC( "Out Packet Ready", ( v & UDCCS0_OPR ) ? yes : no );
-+ SAYC( "In Packet Ready", ( v & UDCCS0_IPR ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS0_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS0_FST ) ? yes : no );
-+ SAYC( "Data End", ( v & UDCCS0_DE ) ? yes : no );
-+ SAYC( "Data Setup End", ( v & UDCCS0_SE ) ? yes : no );
-+ SAYC( "Serviced (SO)", ( v & UDCCS0_SO ) ? yes : no );
-+
-+ v = Ser0UDCCS1;
-+ SAY( "\nUDC Receiver Status Register\n" );
-+ SAYV( v );
-+ SAYC( "Receive Packet Complete", ( v & UDCCS1_RPC ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS1_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS1_FST ) ? yes : no );
-+ SAYC( "Receive Packet Error", ( v & UDCCS1_RPE ) ? yes : no );
-+ SAYC( "Receive FIFO not empty", ( v & UDCCS1_RNE ) ? yes : no );
-+
-+ v = Ser0UDCCS2;
-+ SAY( "\nUDC Transmitter Status Register\n" );
-+ SAYV( v );
-+ SAYC( "FIFO has < 8 of 16 chars", ( v & UDCCS2_TFS ) ? yes : no );
-+ SAYC( "Transmit Packet Complete", ( v & UDCCS2_TPC ) ? yes : no );
-+ SAYC( "Transmit FIFO underrun", ( v & UDCCS2_TUR ) ? yes : no );
-+ SAYC( "Transmit Packet Error", ( v & UDCCS2_TPE ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS2_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS2_FST ) ? yes : no );
-+#endif
-+
-+ len = ( p - page ) - off;
-+ if ( len < 0 )
-+ len = 0;
-+ *eof = ( len <=count ) ? 1 : 0;
-+ *start = page + off;
-+ return len;
-+}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Module Initialization and Shutdown
-+//////////////////////////////////////////////////////////////////////////////
-+/*
-+ * usbctl_init()
-+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs
-+ * entry. Leave UDC disabled.
-+ */
-+int __init usbctl_init( void )
-+{
-+ int retval = 0;
-+
-+ udc_disable();
-+
-+ memset( &usbd_info, 0, sizeof( usbd_info ) );
-+
-+#if CONFIG_PROC_FS
-+ create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
-+#endif
-+
-+ /* setup rx dma */
-+ retval = sa1100_request_dma(&usbd_info.dmach_rx, "USB receive", DMA_Ser0UDCRd);
-+ if (retval) {
-+ printk("%sunable to register for rx dma rc=%d\n", pszMe, retval );
-+ goto err_rx_dma;
-+ }
-+
-+ /* setup tx dma */
-+ retval = sa1100_request_dma(&usbd_info.dmach_tx, "USB transmit", DMA_Ser0UDCWr);
-+ if (retval) {
-+ printk("%sunable to register for tx dma rc=%d\n",pszMe,retval);
-+ goto err_tx_dma;
-+ }
-+
-+ /* now allocate the IRQ. */
-+ retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, SA_INTERRUPT,
-+ "SA USB core", NULL);
-+ if (retval) {
-+ printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
-+ goto err_irq;
-+ }
-+
-+ printk( "SA1100 USB Controller Core Initialized\n");
-+ return 0;
-+
-+err_irq:
-+ sa1100_free_dma(usbd_info.dmach_tx);
-+ usbd_info.dmach_tx = 0;
-+err_tx_dma:
-+ sa1100_free_dma(usbd_info.dmach_rx);
-+ usbd_info.dmach_rx = 0;
-+err_rx_dma:
-+ return retval;
-+}
-+/*
-+ * usbctl_exit()
-+ * Release DMA and interrupt resources
-+ */
-+void __exit usbctl_exit( void )
-+{
-+ printk("Unloading SA1100 USB Controller\n");
-+
-+ udc_disable();
-+
-+#if CONFIG_PROC_FS
-+ remove_proc_entry ( PROC_NODE_NAME, NULL);
-+#endif
-+
-+ sa1100_free_dma(usbd_info.dmach_rx);
-+ sa1100_free_dma(usbd_info.dmach_tx);
-+ free_irq(IRQ_Ser0UDC, NULL);
-+}
-+
-+EXPORT_SYMBOL( sa1100_usb_open );
-+EXPORT_SYMBOL( sa1100_usb_start );
-+EXPORT_SYMBOL( sa1100_usb_stop );
-+EXPORT_SYMBOL( sa1100_usb_close );
-+
-+
-+EXPORT_SYMBOL( sa1100_usb_get_descriptor_ptr );
-+EXPORT_SYMBOL( sa1100_usb_set_string_descriptor );
-+EXPORT_SYMBOL( sa1100_usb_get_string_descriptor );
-+EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor );
-+
-+
-+module_init( usbctl_init );
-+module_exit( usbctl_exit );
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb_ctl.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,123 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation 2001
-+ *
-+ * usb_ctl.h
-+ *
-+ * PRIVATE interface used to share info among components of the SA-1100 USB
-+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
-+ * should use sa1100_usb.h.
-+ *
-+ */
-+
-+#ifndef _USB_CTL_H
-+#define _USB_CTL_H
-+
-+#include <asm/dma.h> /* dmach_t */
-+
-+
-+/*
-+ * These states correspond to those in the USB specification v1.0
-+ * in chapter 8, Device Framework.
-+ */
-+enum { USB_STATE_NOTATTACHED=0, USB_STATE_ATTACHED=1,USB_STATE_POWERED=2,
-+ USB_STATE_DEFAULT=3, USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5,
-+ USB_STATE_SUSPENDED=6};
-+
-+struct usb_stats_t {
-+ unsigned long ep0_fifo_write_failures;
-+ unsigned long ep0_bytes_written;
-+ unsigned long ep0_fifo_read_failures;
-+ unsigned long ep0_bytes_read;
-+};
-+
-+struct usb_info_t
-+{
-+ char * client_name;
-+ dmach_t dmach_tx, dmach_rx;
-+ int state;
-+ unsigned char address;
-+ struct usb_stats_t stats;
-+};
-+
-+/* in usb_ctl.c */
-+extern struct usb_info_t usbd_info;
-+
-+/*
-+ * Function Prototypes
-+ */
-+enum { kError=-1, kEvSuspend=0, kEvReset=1,
-+ kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 };
-+int usbctl_next_state_on_event( int event );
-+
-+/* endpoint zero */
-+void ep0_reset(void);
-+void ep0_int_hndlr(void);
-+
-+/* receiver */
-+void ep1_state_change_notify( int new_state );
-+int ep1_recv(void);
-+int ep1_init(int chn);
-+void ep1_int_hndlr(int status);
-+void ep1_reset(void);
-+void ep1_stall(void);
-+
-+/* xmitter */
-+void ep2_state_change_notify( int new_state );
-+void ep2_reset(void);
-+int ep2_init(int chn);
-+void ep2_int_hndlr(int status);
-+void ep2_stall(void);
-+
-+#define UDC_write(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) = (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: write %#x to %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while((reg) != (val)); \
-+}
-+
-+#define UDC_set(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) |= (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: set %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while(!((reg) & (val))); \
-+}
-+
-+#define UDC_clear(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) &= ~(val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while((reg) & (val)); \
-+}
-+
-+#define UDC_flip(reg, val) { \
-+ int i = 10000; \
-+ (reg) = (val); \
-+ do { \
-+ (reg) = (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while(((reg) & (val))); \
-+}
-+
-+
-+#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}}
-+#endif /* _USB_CTL_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb_ep0.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,911 @@
-+/*
-+ * Copyright (C) Extenex Corporation 2001
-+ * Much folklore gleaned from original code:
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ *
-+ * usb_ep0.c - SA1100 USB controller driver.
-+ * Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for details. (Especially since Intel docs are full of
-+ * errors about ep0 operation.) ward.willats@extenex.com.
-+ *
-+ * Intel also has a "Universal Serial Bus Client Device
-+ * Validation for the StrongARM SA-1100 Microprocessor"
-+ * document, which has flow charts and assembler test driver,
-+ * but be careful, since it is just for validation and not
-+ * a "real world" solution.
-+ *
-+ * A summary of three types of data-returning setups:
-+ *
-+ * 1. Setup request <= 8 bytes. That is, requests that can
-+ * be fullfilled in one write to the FIFO. DE is set
-+ * with IPR in queue_and_start_write(). (I don't know
-+ * if there really are any of these!)
-+ *
-+ * 2. Setup requests > 8 bytes (requiring more than one
-+ * IN to get back to the host), and we have at least
-+ * as much or more data than the host requested. In
-+ * this case we pump out everything we've got, and
-+ * when the final interrupt comes in due to the UDC
-+ * clearing the last IPR, we just set DE.
-+ *
-+ * 3. Setup requests > 8 bytes, but we don't have enough
-+ * data to satisfy the request. In this case, we send
-+ * everything we've got, and when the final interrupt
-+ * comes in due to the UDC clearing the last IPR
-+ * we write nothing to the FIFO and set both IPR and DE
-+ * so the UDC sends an empty packet and forces the host
-+ * to perform short packet retirement instead of stalling
-+ * out.
-+ *
-+ */
-+
-+#include <linux/delay.h>
-+#include "sa1100_usb.h" /* public interface */
-+#include "usb_ctl.h" /* private stuff */
-+
-+
-+// 1 == lots of trace noise, 0 = only "important' stuff
-+#define VERBOSITY 0
-+
-+enum { true = 1, false = 0 };
-+typedef int bool;
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+#if 1 && !defined( ASSERT )
-+# define ASSERT(expr) \
-+ if(!(expr)) { \
-+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-+ #expr,__FILE__,__FUNCTION__,__LINE__); \
-+ }
-+#else
-+# define ASSERT(expr)
-+#endif
-+
-+#if VERBOSITY
-+#define PRINTKD(fmt, args...) printk( fmt , ## args)
-+#else
-+#define PRINTKD(fmt, args...)
-+#endif
-+
-+/*================================================
-+ * USB Protocol Stuff
-+ */
-+
-+/* Request Codes */
-+enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3,
-+ SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7,
-+ GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10,
-+ SET_INTERFACE=11 };
-+
-+
-+/* USB Device Requests */
-+typedef struct
-+{
-+ __u8 bmRequestType;
-+ __u8 bRequest;
-+ __u16 wValue;
-+ __u16 wIndex;
-+ __u16 wLength;
-+} usb_dev_request_t __attribute__ ((packed));
-+
-+/***************************************************************************
-+Prototypes
-+***************************************************************************/
-+/* "setup handlers" -- the main functions dispatched to by the
-+ .. isr. These represent the major "modes" of endpoint 0 operaton */
-+static void sh_setup_begin(void); /* setup begin (idle) */
-+static void sh_write( void ); /* writing data */
-+static void sh_write_with_empty_packet( void ); /* empty packet at end of xfer*/
-+/* called before both sh_write routines above */
-+static void common_write_preamble( void );
-+
-+/* other subroutines */
-+static __u32 queue_and_start_write( void * p, int req, int act );
-+static void write_fifo( void );
-+static int read_fifo( usb_dev_request_t * p );
-+static void get_descriptor( usb_dev_request_t * pReq );
-+
-+/* some voodo helpers 01Mar01ww */
-+static void set_cs_bits( __u32 set_bits );
-+static void set_de( void );
-+static void set_ipr( void );
-+static void set_ipr_and_de( void );
-+static bool clear_opr( void );
-+
-+/***************************************************************************
-+Inline Helpers
-+***************************************************************************/
-+
-+/* Data extraction from usb_request_t fields */
-+enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };
-+static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }
-+
-+static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }
-+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
-+
-+/* following is hook for self-powered flag in GET_STATUS. Some devices
-+ .. might like to override and return real info */
-+static inline bool self_powered_hook( void ) { return true; }
-+
-+/* print string descriptor */
-+static inline void psdesc( string_desc_t * p )
-+{
-+ int i;
-+ int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
-+ printk( "'" );
-+ for( i = 0 ; i < nchars ; i++ ) {
-+ printk( "%c", (char) p->bString[i] );
-+ }
-+ printk( "'\n" );
-+}
-+
-+
-+#if VERBOSITY
-+/* "pcs" == "print control status" */
-+static inline void pcs( void )
-+{
-+ __u32 foo = Ser0UDCCS0;
-+ printk( "%8.8X: %s %s %s %s\n",
-+ foo,
-+ foo & UDCCS0_SE ? "SE" : "",
-+ foo & UDCCS0_OPR ? "OPR" : "",
-+ foo & UDCCS0_IPR ? "IPR" : "",
-+ foo & UDCCS0_SST ? "SST" : ""
-+ );
-+}
-+static inline void preq( usb_dev_request_t * pReq )
-+{
-+ static char * tnames[] = { "dev", "intf", "ep", "oth" };
-+ static char * rnames[] = { "std", "class", "vendor", "???" };
-+ char * psz;
-+ switch( pReq->bRequest ) {
-+ case GET_STATUS: psz = "get stat"; break;
-+ case CLEAR_FEATURE: psz = "clr feat"; break;
-+ case SET_FEATURE: psz = "set feat"; break;
-+ case SET_ADDRESS: psz = "set addr"; break;
-+ case GET_DESCRIPTOR: psz = "get desc"; break;
-+ case SET_DESCRIPTOR: psz = "set desc"; break;
-+ case GET_CONFIGURATION: psz = "get cfg"; break;
-+ case SET_CONFIGURATION: psz = "set cfg"; break;
-+ case GET_INTERFACE: psz = "get intf"; break;
-+ case SET_INTERFACE: psz = "set intf"; break;
-+ default: psz = "unknown"; break;
-+ }
-+ printk( "- [%s: %s req to %s. dir=%s]\n", psz,
-+ rnames[ (pReq->bmRequestType >> 5) & 3 ],
-+ tnames[ pReq->bmRequestType & 3 ],
-+ ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
-+}
-+
-+#else
-+static inline void pcs( void ){}
-+static inline void preq( void ){}
-+#endif
-+
-+/***************************************************************************
-+Globals
-+***************************************************************************/
-+static const char pszMe[] = "usbep0: ";
-+
-+/* pointer to current setup handler */
-+static void (*current_handler)(void) = sh_setup_begin;
-+
-+/* global write struct to keep write
-+ ..state around across interrupts */
-+static struct {
-+ unsigned char *p;
-+ int bytes_left;
-+} wr;
-+
-+/***************************************************************************
-+Public Interface
-+***************************************************************************/
-+
-+/* reset received from HUB (or controller just went nuts and reset by itself!)
-+ so udc core has been reset, track this state here */
-+void
-+ep0_reset(void)
-+{
-+ /* reset state machine */
-+ current_handler = sh_setup_begin;
-+ wr.p = NULL;
-+ wr.bytes_left = 0;
-+ usbd_info.address=0;
-+}
-+
-+/* handle interrupt for endpoint zero */
-+void
-+ep0_int_hndlr( void )
-+{
-+ PRINTKD( "/\\(%d)\n", Ser0UDCAR );
-+ pcs();
-+
-+ /* if not in setup begin, we are returning data.
-+ execute a common preamble to both write handlers
-+ */
-+ if ( current_handler != sh_setup_begin )
-+ common_write_preamble();
-+
-+ (*current_handler)();
-+
-+ PRINTKD( "---\n" );
-+ pcs();
-+ PRINTKD( "\\/\n" );
-+}
-+
-+/***************************************************************************
-+Setup Handlers
-+***************************************************************************/
-+/*
-+ * sh_setup_begin()
-+ * This setup handler is the "idle" state of endpoint zero. It looks for OPR
-+ * (OUT packet ready) to see if a setup request has been been received from the
-+ * host. Requests without a return data phase are immediately handled. Otherwise,
-+ * in the case of GET_XXXX the handler may be set to one of the sh_write_xxxx
-+ * data pumpers if more than 8 bytes need to get back to the host.
-+ *
-+ */
-+static void
-+sh_setup_begin( void )
-+{
-+ unsigned char status_buf[2]; /* returned in GET_STATUS */
-+ usb_dev_request_t req;
-+ int request_type;
-+ int n;
-+ __u32 cs_bits;
-+ __u32 address;
-+ __u32 cs_reg_in = Ser0UDCCS0;
-+
-+ if (cs_reg_in & UDCCS0_SST) {
-+ PRINTKD( "%ssetup begin: sent stall. Continuing\n", pszMe );
-+ set_cs_bits( UDCCS0_SST );
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_SE ) {
-+ PRINTKD( "%ssetup begin: Early term of setup. Continuing\n", pszMe );
-+ set_cs_bits( UDCCS0_SSE ); /* clear setup end */
-+ }
-+
-+ /* Be sure out packet ready, otherwise something is wrong */
-+ if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
-+ /* we can get here early...if so, we'll int again in a moment */
-+ PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ /* read the setup request */
-+ n = read_fifo( &req );
-+ if ( n != sizeof( req ) ) {
-+ printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
-+ " Stalling out...\n",
-+ pszMe, sizeof( req ), n );
-+ /* force stall, serviced out */
-+ set_cs_bits( UDCCS0_FST | UDCCS0_SO );
-+ goto sh_sb_end;
-+ }
-+
-+ /* Is it a standard request? (not vendor or class request) */
-+ request_type = type_code_from_request( req.bmRequestType );
-+ if ( request_type != 0 ) {
-+ printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
-+ pszMe, request_type );
-+ set_cs_bits( UDCCS0_DE | UDCCS0_SO );
-+ goto sh_sb_end;
-+ }
-+
-+#if VERBOSITY
-+ {
-+ unsigned char * pdb = (unsigned char *) &req;
-+ PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
-+ pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
-+ );
-+ preq( &req );
-+ }
-+#endif
-+
-+ /* Handle it */
-+ switch( req.bRequest ) {
-+
-+ /* This first bunch have no data phase */
-+
-+ case SET_ADDRESS:
-+ address = (__u32) (req.wValue & 0x7F);
-+ /* when SO and DE sent, UDC will enter status phase and ack,
-+ ..propagating new address to udc core. Next control transfer
-+ ..will be on the new address. You can't see the change in a
-+ ..read back of CAR until then. (about 250us later, on my box).
-+ ..The original Intel driver sets S0 and DE and code to check
-+ ..that address has propagated here. I tried this, but it
-+ ..would only work sometimes! The rest of the time it would
-+ ..never propagate and we'd spin forever. So now I just set
-+ ..it and pray...
-+ */
-+ Ser0UDCAR = address;
-+ usbd_info.address = address;
-+ usbctl_next_state_on_event( kEvAddress );
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ printk( "%sI have been assigned address: %d\n", pszMe, address );
-+ break;
-+
-+
-+ case SET_CONFIGURATION:
-+ if ( req.wValue == 1 ) {
-+ /* configured */
-+ if (usbctl_next_state_on_event( kEvConfig ) != kError){
-+ /* (re)set the out and in max packet sizes */
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ __u32 out = __le16_to_cpu( pDesc->b.ep1.wMaxPacketSize );
-+ __u32 in = __le16_to_cpu( pDesc->b.ep2.wMaxPacketSize );
-+ Ser0UDCOMP = ( out - 1 );
-+ Ser0UDCIMP = ( in - 1 );
-+ printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in );
-+ }
-+ } else if ( req.wValue == 0 ) {
-+ /* de-configured */
-+ if (usbctl_next_state_on_event( kEvDeConfig ) != kError )
-+ printk( "%sDe-Configured\n", pszMe );
-+ } else {
-+ printk( "%ssetup phase: Unknown "
-+ "\"set configuration\" data %d\n",
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+ case CLEAR_FEATURE:
-+ /* could check data length, direction...26Jan01ww */
-+ if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */
-+ int ep = windex_to_ep_num( req.wIndex );
-+ if ( ep == 1 ) {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ " on receiver\n", pszMe );
-+ ep1_reset();
-+ }
-+ else if ( ep == 2 ) {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ "on xmitter\n", pszMe );
-+ ep2_reset();
-+ } else {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ "on unsupported ep # %d\n",
-+ pszMe, ep );
-+ }
-+ } else {
-+ printk( "%sUnsupported feature selector (%d) "
-+ "in clear feature. Ignored.\n" ,
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+ case SET_FEATURE:
-+ if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */
-+ int ep = windex_to_ep_num( req.wValue );
-+ if ( ep == 1 ) {
-+ printk( "%set feature \"endpoint halt\" "
-+ "on receiver\n", pszMe );
-+ ep1_stall();
-+ }
-+ else if ( ep == 2 ) {
-+ printk( "%sset feature \"endpoint halt\" "
-+ " on xmitter\n", pszMe );
-+ ep2_stall();
-+ } else {
-+ printk( "%sset feature \"endpoint halt\" "
-+ "on unsupported ep # %d\n",
-+ pszMe, ep );
-+ }
-+ }
-+ else {
-+ printk( "%sUnsupported feature selector "
-+ "(%d) in set feature\n",
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+
-+ /* The rest have a data phase that writes back to the host */
-+ case GET_STATUS:
-+ /* return status bit flags */
-+ status_buf[0] = status_buf[1] = 0;
-+ n = request_target(req.bmRequestType);
-+ switch( n ) {
-+ case kTargetDevice:
-+ if ( self_powered_hook() )
-+ status_buf[0] |= 1;
-+ break;
-+ case kTargetInterface:
-+ break;
-+ case kTargetEndpoint:
-+ /* return stalled bit */
-+ n = windex_to_ep_num( req.wIndex );
-+ if ( n == 1 )
-+ status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4;
-+ else if ( n == 2 )
-+ status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5;
-+ else {
-+ printk( "%sUnknown endpoint (%d) "
-+ "in GET_STATUS\n", pszMe, n );
-+ }
-+ break;
-+ default:
-+ printk( "%sUnknown target (%d) in GET_STATUS\n",
-+ pszMe, n );
-+ /* fall thru */
-+ break;
-+ }
-+ cs_bits = queue_and_start_write( status_buf,
-+ req.wLength,
-+ sizeof( status_buf ) );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case GET_DESCRIPTOR:
-+ get_descriptor( &req );
-+ break;
-+
-+ case GET_CONFIGURATION:
-+ status_buf[0] = (usbd_info.state == USB_STATE_CONFIGURED)
-+ ? 1
-+ : 0;
-+ cs_bits = queue_and_start_write( status_buf, req.wLength, 1 );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case GET_INTERFACE:
-+ printk( "%sfixme: get interface not supported\n", pszMe );
-+ cs_bits = queue_and_start_write( NULL, req.wLength, 0 );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case SET_INTERFACE:
-+ printk( "%sfixme: set interface not supported\n", pszMe );
-+ set_cs_bits( UDCCS0_DE | UDCCS0_SO );
-+ break;
-+ default :
-+ printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
-+ break;
-+ } /* switch( bRequest ) */
-+
-+sh_sb_end:
-+ return;
-+
-+}
-+/*
-+ * common_wrtie_preamble()
-+ * Called before execution of sh_write() or sh_write_with_empty_packet()
-+ * Handles common abort conditions.
-+ *
-+ */
-+static void common_write_preamble( void )
-+{
-+ /* If "setup end" has been set, the usb controller has
-+ ..terminated a setup transaction before we set DE. This
-+ ..happens during enumeration with some hosts. For example,
-+ ..the host will ask for our device descriptor and specify
-+ ..a return of 64 bytes. When we hand back the first 8, the
-+ ..host will know our max packet size and turn around and
-+ ..issue a new setup immediately. This causes the UDC to auto-ack
-+ ..the new setup and set SE. We must then "unload" (process)
-+ ..the new setup, which is what will happen after this preamble
-+ ..is finished executing.
-+ */
-+ __u32 cs_reg_in = Ser0UDCCS0;
-+
-+ if ( cs_reg_in & UDCCS0_SE ) {
-+ PRINTKD( "%swrite_preamble(): Early termination of setup\n", pszMe );
-+ Ser0UDCCS0 = UDCCS0_SSE; /* clear setup end */
-+ current_handler = sh_setup_begin;
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_SST ) {
-+ PRINTKD( "%swrite_preamble(): UDC sent stall\n", pszMe );
-+ Ser0UDCCS0 = UDCCS0_SST; /* clear setup end */
-+ current_handler = sh_setup_begin;
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_OPR ) {
-+ PRINTKD( "%swrite_preamble(): see OPR. Stopping write to "
-+ "handle new SETUP\n", pszMe );
-+ /* very rarely, you can get OPR and leftover IPR. Try to clear */
-+ UDC_clear( Ser0UDCCS0, UDCCS0_IPR );
-+ current_handler = sh_setup_begin;
-+ }
-+}
-+
-+/*
-+ * sh_write()
-+ * This is the setup handler when we are in the data return phase of
-+ * a setup request and have as much (or more) data than the host
-+ * requested. If we enter this routine and bytes left is zero, the
-+ * last data packet has gone (int is because IPR was just cleared)
-+ * so we just set DE and reset. Otheriwse, we write another packet
-+ * and set IPR.
-+ */
-+static void sh_write()
-+{
-+ PRINTKD( "W\n" );
-+
-+ if ( Ser0UDCCS0 & UDCCS0_IPR ) {
-+ PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
-+ return;
-+ }
-+
-+ /* If bytes left is zero, we are coming in on the
-+ ..interrupt after the last packet went out. And
-+ ..we know we don't have to empty packet this transfer
-+ ..so just set DE and we are done */
-+
-+ if ( 0 == wr.bytes_left ) {
-+ /* that's it, so data end */
-+ set_de();
-+ wr.p = NULL; /* be anal */
-+ current_handler = sh_setup_begin;
-+ } else {
-+ /* Otherwise, more data to go */
-+ write_fifo();
-+ set_ipr();
-+ }
-+}
-+/*
-+ * sh_write_with_empty_packet()
-+ * This is the setup handler when we don't have enough data to
-+ * satisfy the host's request. After we send everything we've got
-+ * we must send an empty packet (by setting IPR and DE) so the
-+ * host can perform "short packet retirement" and not stall.
-+ *
-+ */
-+static void sh_write_with_empty_packet( void )
-+{
-+ __u32 cs_reg_out = 0;
-+ PRINTKD( "WE\n" );
-+
-+ if ( Ser0UDCCS0 & UDCCS0_IPR ) {
-+ PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
-+ return;
-+ }
-+
-+ /* If bytes left is zero, we are coming in on the
-+ ..interrupt after the last packet went out.
-+ ..we must do short packet suff, so set DE and IPR
-+ */
-+
-+ if ( 0 == wr.bytes_left ) {
-+ set_ipr_and_de();
-+ wr.p = NULL;
-+ current_handler = sh_setup_begin;
-+ PRINTKD( "%ssh_write empty() Sent empty packet \n", pszMe );
-+ } else {
-+ write_fifo(); /* send data */
-+ set_ipr(); /* flag a packet is ready */
-+ }
-+ Ser0UDCCS0 = cs_reg_out;
-+}
-+
-+/***************************************************************************
-+Other Private Subroutines
-+***************************************************************************/
-+/*
-+ * queue_and_start_write()
-+ * p == data to send
-+ * req == bytes host requested
-+ * act == bytes we actually have
-+ * Returns: bits to be flipped in ep0 control/status register
-+ *
-+ * Called from sh_setup_begin() to begin a data return phase. Sets up the
-+ * global "wr"-ite structure and load the outbound FIFO with data.
-+ * If can't send all the data, set appropriate handler for next interrupt.
-+ *
-+ */
-+static __u32 queue_and_start_write( void * in, int req, int act )
-+{
-+ __u32 cs_reg_bits = UDCCS0_IPR;
-+ unsigned char * p = (unsigned char*) in;
-+
-+ PRINTKD( "Qr=%d a=%d\n",req,act );
-+
-+ /* thou shalt not enter data phase until the serviced OUT is clear */
-+ if ( ! clear_opr() ) {
-+ printk( "%sSO did not clear OPR\n", pszMe );
-+ return ( UDCCS0_DE | UDCCS0_SO ) ;
-+ }
-+ wr.p = p;
-+ wr.bytes_left = MIN( act, req );
-+
-+ write_fifo();
-+
-+ if ( 0 == wr.bytes_left ) {
-+ cs_reg_bits |= UDCCS0_DE; /* out in 1 so data end */
-+ wr.p = NULL; /* be anal */
-+ }
-+ else if ( act < req ) /* we are going to short-change host */
-+ current_handler = sh_write_with_empty_packet; /* so need nul to not stall */
-+ else /* we have as much or more than requested */
-+ current_handler = sh_write;
-+
-+ return cs_reg_bits; /* note: IPR was set uncondtionally at start of routine */
-+}
-+/*
-+ * write_fifo()
-+ * Stick bytes in the 8 bytes endpoint zero FIFO.
-+ * This version uses a variety of tricks to make sure the bytes
-+ * are written correctly. 1. The count register is checked to
-+ * see if the byte went in, and the write is attempted again
-+ * if not. 2. An overall counter is used to break out so we
-+ * don't hang in those (rare) cases where the UDC reverses
-+ * direction of the FIFO underneath us without notification
-+ * (in response to host aborting a setup transaction early).
-+ *
-+ */
-+static void write_fifo( void )
-+{
-+ int bytes_this_time = MIN( wr.bytes_left, 8 );
-+ int bytes_written = 0;
-+ int i=0;
-+
-+ PRINTKD( "WF=%d: ", bytes_this_time );
-+
-+ while( bytes_this_time-- ) {
-+ PRINTKD( "%2.2X ", *wr.p );
-+ i = 0;
-+ do {
-+ Ser0UDCD0 = *wr.p;
-+ udelay( 20 ); /* voodo 28Feb01ww */
-+ i++;
-+ } while( Ser0UDCWC == bytes_written && i < 10 );
-+ if ( i == 50 ) {
-+ printk( "%swrite_fifo: write failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_write_failures++;
-+ }
-+
-+ wr.p++;
-+ bytes_written++;
-+ }
-+ wr.bytes_left -= bytes_written;
-+
-+ /* following propagation voodo so maybe caller writing IPR in
-+ ..a moment might actually get it to stick 28Feb01ww */
-+ udelay( 300 );
-+
-+ usbd_info.stats.ep0_bytes_written += bytes_written;
-+ PRINTKD( "L=%d WCR=%8.8X\n", wr.bytes_left, Ser0UDCWC );
-+}
-+/*
-+ * read_fifo()
-+ * Read 1-8 bytes out of FIFO and put in request.
-+ * Called to do the initial read of setup requests
-+ * from the host. Return number of bytes read.
-+ *
-+ * Like write fifo above, this driver uses multiple
-+ * reads checked agains the count register with an
-+ * overall timeout.
-+ *
-+ */
-+static int
-+read_fifo( usb_dev_request_t * request )
-+{
-+ int bytes_read = 0;
-+ int fifo_count;
-+ int i;
-+
-+ unsigned char * pOut = (unsigned char*) request;
-+
-+ fifo_count = ( Ser0UDCWC & 0xFF );
-+
-+ ASSERT( fifo_count <= 8 );
-+ PRINTKD( "RF=%d ", fifo_count );
-+
-+ while( fifo_count-- ) {
-+ i = 0;
-+ do {
-+ *pOut = (unsigned char) Ser0UDCD0;
-+ udelay( 10 );
-+ } while( ( Ser0UDCWC & 0xFF ) != fifo_count && i < 10 );
-+ if ( i == 10 ) {
-+ printk( "%sread_fifo(): read failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_read_failures++;
-+ }
-+ pOut++;
-+ bytes_read++;
-+ }
-+
-+ PRINTKD( "fc=%d\n", bytes_read );
-+ usbd_info.stats.ep0_bytes_read++;
-+ return bytes_read;
-+}
-+
-+/*
-+ * get_descriptor()
-+ * Called from sh_setup_begin to handle data return
-+ * for a GET_DESCRIPTOR setup request.
-+ */
-+static void get_descriptor( usb_dev_request_t * pReq )
-+{
-+ __u32 cs_bits = 0;
-+ string_desc_t * pString;
-+ ep_desc_t * pEndpoint;
-+
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ int type = pReq->wValue >> 8;
-+ int idx = pReq->wValue & 0xFF;
-+
-+ switch( type ) {
-+ case USB_DESC_DEVICE:
-+ cs_bits =
-+ queue_and_start_write( &pDesc->dev,
-+ pReq->wLength,
-+ pDesc->dev.bLength );
-+ break;
-+
-+ // return config descriptor buffer, cfg, intf, 2 ep
-+ case USB_DESC_CONFIG:
-+ cs_bits =
-+ queue_and_start_write( &pDesc->b,
-+ pReq->wLength,
-+ sizeof( struct cdb ) );
-+ break;
-+
-+ // not quite right, since doesn't do language code checking
-+ case USB_DESC_STRING:
-+ pString = sa1100_usb_get_string_descriptor( idx );
-+ if ( pString ) {
-+ if ( idx != 0 ) { // if not language index
-+ printk( "%sReturn string %d: ", pszMe, idx );
-+ psdesc( pString );
-+ }
-+ cs_bits =
-+ queue_and_start_write( pString,
-+ pReq->wLength,
-+ pString->bLength );
-+ }
-+ else {
-+ printk("%sunkown string index %d Stall.\n", pszMe, idx );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ }
-+ break;
-+
-+ case USB_DESC_INTERFACE:
-+ if ( idx == pDesc->b.intf.bInterfaceNumber ) {
-+ cs_bits =
-+ queue_and_start_write( &pDesc->b.intf,
-+ pReq->wLength,
-+ pDesc->b.intf.bLength );
-+ }
-+ break;
-+
-+ case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
-+ if ( idx == 1 )
-+ pEndpoint = &pDesc->b.ep1;
-+ else if ( idx == 2 )
-+ pEndpoint = &pDesc->b.ep2;
-+ else
-+ pEndpoint = NULL;
-+ if ( pEndpoint ) {
-+ cs_bits =
-+ queue_and_start_write( pEndpoint,
-+ pReq->wLength,
-+ pEndpoint->bLength );
-+ } else {
-+ printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ }
-+ break;
-+
-+
-+ default :
-+ printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ break;
-+
-+ }
-+ set_cs_bits( cs_bits );
-+}
-+
-+
-+/* some voodo I am adding, since the vanilla macros just aren't doing it 1Mar01ww */
-+
-+#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE )
-+#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS ))
-+#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE)
-+
-+static void set_cs_bits( __u32 bits )
-+{
-+ if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST ) )
-+ Ser0UDCCS0 = bits;
-+ else if ( (bits & BOTH_BITS) == BOTH_BITS )
-+ set_ipr_and_de();
-+ else if ( bits & UDCCS0_IPR )
-+ set_ipr();
-+ else if ( bits & UDCCS0_DE )
-+ set_de();
-+}
-+
-+static void set_de( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= UDCCS0_DE;
-+ } else {
-+ PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( Ser0UDCCS0 & UDCCS0_DE )
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_DE, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+static void set_ipr( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= UDCCS0_IPR;
-+ } else {
-+ PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( Ser0UDCCS0 & UDCCS0_IPR )
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_IPR, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+
-+
-+static void set_ipr_and_de( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= BOTH_BITS;
-+ } else {
-+ PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS)
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+static bool clear_opr( void )
-+{
-+ int i = 10000;
-+ bool is_clear;
-+ do {
-+ Ser0UDCCS0 = UDCCS0_SO;
-+ is_clear = ! ( Ser0UDCCS0 & UDCCS0_OPR );
-+ if ( i-- <= 0 ) {
-+ printk( "%sclear_opr(): failed\n", pszMe );
-+ break;
-+ }
-+ } while( ! is_clear );
-+ return is_clear;
-+}
-+
-+
-+
-+
-+
-+/* end usb_ep0.c */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb_recv.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,205 @@
-+/*
-+ * Generic receive layer for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+
-+static char *ep1_buf;
-+static int ep1_len;
-+static usb_callback_t ep1_callback;
-+static char *ep1_curdmabuf;
-+static dma_addr_t ep1_curdmapos;
-+static int ep1_curdmalen;
-+static int ep1_remain;
-+static int dmachn_rx;
-+static int rx_pktsize;
-+
-+static int naking;
-+
-+static void
-+ep1_start(void)
-+{
-+ sa1100_dma_flush_all(dmachn_rx);
-+ if (!ep1_curdmalen) {
-+ ep1_curdmalen = rx_pktsize;
-+ if (ep1_curdmalen > ep1_remain)
-+ ep1_curdmalen = ep1_remain;
-+ ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ }
-+ sa1100_dma_queue_buffer(dmachn_rx, NULL, ep1_curdmapos, ep1_curdmalen);
-+ if ( naking ) {
-+ /* turn off NAK of OUT packets, if set */
-+ UDC_flip( Ser0UDCCS1, UDCCS1_RPC );
-+ naking = 0;
-+ }
-+}
-+
-+static void
-+ep1_done(int flag)
-+{
-+ int size = ep1_len - ep1_remain;
-+
-+ if (!ep1_len)
-+ return;
-+ if (ep1_curdmalen)
-+ pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ ep1_len = ep1_curdmalen = 0;
-+ if (ep1_callback) {
-+ ep1_callback(flag, size);
-+ }
-+}
-+
-+void
-+ep1_state_change_notify( int new_state )
-+{
-+
-+}
-+
-+void
-+ep1_stall( void )
-+{
-+ /* SET_FEATURE force stall at UDC */
-+ UDC_set( Ser0UDCCS1, UDCCS1_FST );
-+}
-+
-+int
-+ep1_init(int chn)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ dmachn_rx = chn;
-+ sa1100_dma_flush_all(dmachn_rx);
-+ ep1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep1_reset(void)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ sa1100_dma_flush_all(dmachn_rx);
-+ UDC_clear(Ser0UDCCS1, UDCCS1_FST);
-+ ep1_done(-EINTR);
-+}
-+
-+void
-+ep1_int_hndlr(int udcsr)
-+{
-+ dma_addr_t dma_addr;
-+ unsigned int len;
-+ int status = Ser0UDCCS1;
-+
-+ if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
-+
-+ if (status & UDCCS1_RPC) {
-+
-+ if (!ep1_curdmalen) {
-+ printk("usb_recv: RPC for non-existent buffer\n");
-+ naking=1;
-+ return;
-+ }
-+
-+ sa1100_dma_stop(dmachn_rx);
-+
-+ if (status & UDCCS1_SST) {
-+ printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP);
-+ UDC_flip(Ser0UDCCS1, UDCCS1_SST);
-+ ep1_done(-EIO); // UDC aborted current transfer, so we do
-+ return;
-+ }
-+
-+ if (status & UDCCS1_RPE) {
-+ printk("usb_recv: RPError %x\n", status);
-+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
-+ ep1_done(-EIO);
-+ return;
-+ }
-+
-+ sa1100_dma_get_current(dmachn_rx, NULL, &dma_addr);
-+ pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ len = dma_addr - ep1_curdmapos;
-+ if (len < ep1_curdmalen) {
-+ char *buf = ep1_curdmabuf + len;
-+ while (Ser0UDCCS1 & UDCCS1_RNE) {
-+ if (len >= ep1_curdmalen) {
-+ printk("usb_recv: too much data in fifo\n");
-+ break;
-+ }
-+ *buf++ = Ser0UDCDR;
-+ len++;
-+ }
-+ } else if (Ser0UDCCS1 & UDCCS1_RNE) {
-+ printk("usb_recv: fifo screwed, shouldn't contain data\n");
-+ len = 0;
-+ }
-+ ep1_curdmalen = 0; /* dma unmap already done */
-+ ep1_remain -= len;
-+ naking = 1;
-+ ep1_done((len) ? 0 : -EPIPE);
-+ }
-+ /* else, you can get here if we are holding NAK */
-+}
-+
-+int
-+sa1100_usb_recv(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (ep1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep1_buf = buf;
-+ ep1_len = len;
-+ ep1_callback = callback;
-+ ep1_remain = len;
-+ ep1_curdmabuf = buf;
-+ ep1_curdmalen = 0;
-+ ep1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv);
-+
-+void
-+sa1100_usb_recv_reset(void)
-+{
-+ ep1_reset();
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv_reset);
-+
-+void
-+sa1100_usb_recv_stall(void)
-+{
-+ ep1_stall();
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv_stall);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mach-sa1100/usb_send.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,205 @@
-+/*
-+ * Generic xmit layer for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware
-+ * bug, I think. green@iXcelerator.com
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h> // for the massive_attack hack 28Feb01ww
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+#include <asm/byteorder.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+
-+static char *ep2_buf;
-+static int ep2_len;
-+static usb_callback_t ep2_callback;
-+static dma_addr_t ep2_dma;
-+static dma_addr_t ep2_curdmapos;
-+static int ep2_curdmalen;
-+static int ep2_remain;
-+static int dmachn_tx;
-+static int tx_pktsize;
-+
-+/* device state is changing, async */
-+void
-+ep2_state_change_notify( int new_state )
-+{
-+}
-+
-+/* set feature stall executing, async */
-+void
-+ep2_stall( void )
-+{
-+ UDC_set( Ser0UDCCS2, UDCCS2_FST ); /* force stall at UDC */
-+}
-+
-+static void
-+ep2_start(void)
-+{
-+ if (!ep2_len)
-+ return;
-+
-+ ep2_curdmalen = tx_pktsize;
-+ if (ep2_curdmalen > ep2_remain)
-+ ep2_curdmalen = ep2_remain;
-+
-+ /* must do this _before_ queue buffer.. */
-+ UDC_flip( Ser0UDCCS2,UDCCS2_TPC ); /* stop NAKing IN tokens */
-+ UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
-+
-+ /* Remove if never seen...8Mar01ww */
-+ {
-+ int massive_attack = 20;
-+ while ( Ser0UDCIMP != ep2_curdmalen-1 && massive_attack-- ) {
-+ printk( "usbsnd: Oh no you don't! Let me spin..." );
-+ udelay( 500 );
-+ printk( "and try again...\n" );
-+ UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
-+ }
-+ if ( massive_attack != 20 ) {
-+ if ( Ser0UDCIMP != ep2_curdmalen-1 )
-+ printk( "usbsnd: Massive attack FAILED :-( %d\n",
-+ 20 - massive_attack );
-+ else
-+ printk( "usbsnd: Massive attack WORKED :-) %d\n",
-+ 20 - massive_attack );
-+ }
-+ }
-+ /* End remove if never seen... 8Mar01ww */
-+
-+ Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
-+ sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen);
-+}
-+
-+static void
-+ep2_done(int flag)
-+{
-+ int size = ep2_len - ep2_remain;
-+ if (ep2_len) {
-+ pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE);
-+ ep2_len = 0;
-+ if (ep2_callback)
-+ ep2_callback(flag, size);
-+ }
-+}
-+
-+int
-+ep2_init(int chn)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ dmachn_tx = chn;
-+ sa1100_dma_flush_all(dmachn_tx);
-+ ep2_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep2_reset(void)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ UDC_clear(Ser0UDCCS2, UDCCS2_FST);
-+ sa1100_dma_flush_all(dmachn_tx);
-+ ep2_done(-EINTR);
-+}
-+
-+void
-+ep2_int_hndlr(int udcsr)
-+{
-+ int status = Ser0UDCCS2;
-+
-+ if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
-+ Ser0UDCAR = usbd_info.address;
-+
-+ UDC_flip(Ser0UDCCS2, UDCCS2_SST);
-+
-+ if (status & UDCCS2_TPC) {
-+ sa1100_dma_flush_all(dmachn_tx);
-+
-+ if (status & (UDCCS2_TPE | UDCCS2_TUR)) {
-+ printk("usb_send: transmit error %x\n", status);
-+ ep2_done(-EIO);
-+ } else {
-+#if 1 // 22Feb01ww/Oleg
-+ ep2_curdmapos += ep2_curdmalen;
-+ ep2_remain -= ep2_curdmalen;
-+#else
-+ ep2_curdmapos += Ser0UDCIMP + 1; // this is workaround
-+ ep2_remain -= Ser0UDCIMP + 1; // for case when setting of Ser0UDCIMP was failed
-+#endif
-+
-+ if (ep2_remain != 0) {
-+ ep2_start();
-+ } else {
-+ ep2_done(0);
-+ }
-+ }
-+ } else {
-+ printk("usb_send: Not TPC: UDCCS2 = %x\n", status);
-+ }
-+}
-+
-+int
-+sa1100_usb_send(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+
-+ if (ep2_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep2_buf = buf;
-+ ep2_len = len;
-+ ep2_dma = pci_map_single(NULL, buf, len, PCI_DMA_TODEVICE);
-+ ep2_callback = callback;
-+ ep2_remain = len;
-+ ep2_curdmapos = ep2_dma;
-+ ep2_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+
-+void
-+sa1100_usb_send_reset(void)
-+{
-+ ep2_reset();
-+}
-+
-+int sa1100_usb_xmitter_avail( void )
-+{
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+ if (ep2_len)
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+
-+EXPORT_SYMBOL(sa1100_usb_xmitter_avail);
-+EXPORT_SYMBOL(sa1100_usb_send);
-+EXPORT_SYMBOL(sa1100_usb_send_reset);
---- linux-2.4.25/arch/arm/mm/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -39,6 +39,8 @@
- p-$(CONFIG_CPU_ARM925T) += proc-arm925.o
- p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
- p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
-+p-$(CONFIG_CPU_ARM1020E) += proc-arm1020E.o
-+p-$(CONFIG_CPU_ARM1022) += proc-arm1022.o
- p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
- p-$(CONFIG_CPU_SA110) += proc-sa110.o
- p-$(CONFIG_CPU_SA1100) += proc-sa110.o
---- linux-2.4.25/arch/arm/mm/alignment.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/alignment.c 2004-03-31 17:15:09.000000000 +0200
-@@ -11,7 +11,6 @@
- #include <linux/config.h>
- #include <linux/compiler.h>
- #include <linux/signal.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -19,7 +18,6 @@
- #include <linux/ptrace.h>
- #include <linux/mman.h>
- #include <linux/mm.h>
--#include <linux/interrupt.h>
- #include <linux/proc_fs.h>
- #include <linux/bitops.h>
- #include <linux/init.h>
-@@ -30,9 +28,7 @@
- #include <asm/pgtable.h>
- #include <asm/unaligned.h>
-
--extern void
--do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-- int error_code, struct pt_regs *regs);
-+#include "fault.h"
-
- /*
- * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
-@@ -130,31 +126,6 @@
- return count;
- }
-
--/*
-- * This needs to be done after sysctl_init, otherwise sys/ will be
-- * overwritten. Actually, this shouldn't be in sys/ at all since
-- * it isn't a sysctl, and it doesn't contain sysctl information.
-- * We now locate it in /proc/cpu/alignment instead.
-- */
--static int __init alignment_init(void)
--{
-- struct proc_dir_entry *res;
--
-- res = proc_mkdir("cpu", NULL);
-- if (!res)
-- return -ENOMEM;
--
-- res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
-- if (!res)
-- return -ENOMEM;
--
-- res->read_proc = proc_alignment_read;
-- res->write_proc = proc_alignment_write;
--
-- return 0;
--}
--
--__initcall(alignment_init);
- #endif /* CONFIG_PROC_FS */
-
- union offset_union {
-@@ -429,7 +400,7 @@
- * For alignment faults on the ARM922T/ARM920T the MMU makes
- * the FSR (and hence addr) equal to the updated base address
- * of the multiple access rather than the restored value.
-- * Switch this messsage off if we've got a ARM92[02], otherwise
-+ * Switch this message off if we've got a ARM92[02], otherwise
- * [ls]dm alignment faults are noisy!
- */
- #if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T)
-@@ -486,7 +457,8 @@
- return TYPE_ERROR;
- }
-
--int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
-+static int
-+do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- union offset_union offset;
- unsigned long instr, instrptr;
-@@ -541,7 +513,7 @@
- case SHIFT_RORRRX:
- if (shiftval == 0) {
- offset.un >>= 1;
-- if (regs->ARM_cpsr & CC_C_BIT)
-+ if (regs->ARM_cpsr & PSR_C_BIT)
- offset.un |= 1 << 31;
- } else
- offset.un = offset.un >> shiftval |
-@@ -577,7 +549,7 @@
- /*
- * We got a fault - fix it up, or die.
- */
-- do_bad_area(current, current->mm, addr, error_code, regs);
-+ do_bad_area(current, current->mm, addr, fsr, regs);
- return 0;
-
- bad:
-@@ -594,8 +566,8 @@
-
- if (ai_usermode & 1)
- printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
-- "Address=0x%08lx Code 0x%02x\n", current->comm,
-- current->pid, instrptr, instr, addr, error_code);
-+ "Address=0x%08lx FSR 0x%03x\n", current->comm,
-+ current->pid, instrptr, instr, addr, fsr);
-
- if (ai_usermode & 2)
- goto fixup;
-@@ -607,3 +579,34 @@
-
- return 0;
- }
-+
-+/*
-+ * This needs to be done after sysctl_init, otherwise sys/ will be
-+ * overwritten. Actually, this shouldn't be in sys/ at all since
-+ * it isn't a sysctl, and it doesn't contain sysctl information.
-+ * We now locate it in /proc/cpu/alignment instead.
-+ */
-+static int __init alignment_init(void)
-+{
-+#ifdef CONFIG_PROC_FS
-+ struct proc_dir_entry *res;
-+
-+ res = proc_mkdir("cpu", NULL);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res->read_proc = proc_alignment_read;
-+ res->write_proc = proc_alignment_write;
-+#endif
-+
-+ hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
-+ hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
-+
-+ return 0;
-+}
-+
-+__initcall(alignment_init);
---- linux-2.4.25/arch/arm/mm/fault-armv.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/fault-armv.c 2004-03-31 17:15:09.000000000 +0200
-@@ -2,116 +2,90 @@
- * linux/arch/arm/mm/fault-armv.c
- *
- * Copyright (C) 1995 Linus Torvalds
-- * Modifications for ARM processor (c) 1995-2001 Russell King
-+ * Modifications for ARM processor (c) 1995-2003 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
--#include <linux/config.h>
--#include <linux/signal.h>
- #include <linux/sched.h>
- #include <linux/kernel.h>
--#include <linux/errno.h>
--#include <linux/string.h>
- #include <linux/types.h>
- #include <linux/ptrace.h>
--#include <linux/mman.h>
- #include <linux/mm.h>
--#include <linux/interrupt.h>
--#include <linux/proc_fs.h>
- #include <linux/bitops.h>
- #include <linux/init.h>
-
--#include <asm/system.h>
--#include <asm/uaccess.h>
- #include <asm/pgalloc.h>
- #include <asm/pgtable.h>
-+#include <asm/io.h>
-
--extern void show_pte(struct mm_struct *mm, unsigned long addr);
--extern int do_page_fault(unsigned long addr, int error_code,
-- struct pt_regs *regs);
--extern int do_translation_fault(unsigned long addr, int error_code,
-- struct pt_regs *regs);
--extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-- unsigned long addr, int error_code,
-- struct pt_regs *regs);
--
--#ifdef CONFIG_ALIGNMENT_TRAP
--extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs);
--#else
--#define do_alignment do_bad
--#endif
--
-+#include "fault.h"
-
- /*
- * Some section permission faults need to be handled gracefully.
- * They can happen due to a __{get,put}_user during an oops.
- */
- static int
--do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- struct task_struct *tsk = current;
-- do_bad_area(tsk, tsk->active_mm, addr, error_code, regs);
-+ do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
- return 0;
- }
-
- /*
-- * Hook for things that need to trap external faults. Note that
-- * we don't guarantee that this will be the final version of the
-- * interface.
-- */
--int (*external_fault)(unsigned long addr, struct pt_regs *regs);
--
--static int
--do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs)
--{
-- if (external_fault)
-- return external_fault(addr, regs);
-- return 1;
--}
--
--/*
- * This abort handler always returns "fault".
- */
- static int
--do_bad(unsigned long addr, int error_code, struct pt_regs *regs)
-+do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- return 1;
- }
-
--static const struct fsr_info {
-- int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
-+static struct fsr_info {
-+ int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
- int sig;
- const char *name;
- } fsr_info[] = {
- { do_bad, SIGSEGV, "vector exception" },
-- { do_alignment, SIGILL, "alignment exception" },
-+ { do_bad, SIGILL, "alignment exception" },
- { do_bad, SIGKILL, "terminal exception" },
-- { do_alignment, SIGILL, "alignment exception" },
-- { do_external_fault, SIGBUS, "external abort on linefetch" },
-+ { do_bad, SIGILL, "alignment exception" },
-+ { do_bad, SIGBUS, "external abort on linefetch" },
- { do_translation_fault, SIGSEGV, "section translation fault" },
-- { do_external_fault, SIGBUS, "external abort on linefetch" },
-+ { do_bad, SIGBUS, "external abort on linefetch" },
- { do_page_fault, SIGSEGV, "page translation fault" },
-- { do_external_fault, SIGBUS, "external abort on non-linefetch" },
-+ { do_bad, SIGBUS, "external abort on non-linefetch" },
- { do_bad, SIGSEGV, "section domain fault" },
-- { do_external_fault, SIGBUS, "external abort on non-linefetch" },
-+ { do_bad, SIGBUS, "external abort on non-linefetch" },
- { do_bad, SIGSEGV, "page domain fault" },
- { do_bad, SIGBUS, "external abort on translation" },
- { do_sect_fault, SIGSEGV, "section permission fault" },
- { do_bad, SIGBUS, "external abort on translation" },
-- { do_page_fault, SIGSEGV, "page permission fault" }
-+ { do_page_fault, SIGSEGV, "page permission fault" },
- };
-
-+void __init
-+hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
-+ int sig, const char *name)
-+{
-+ if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) {
-+ fsr_info[nr].fn = fn;
-+ fsr_info[nr].sig = sig;
-+ fsr_info[nr].name = name;
-+ }
-+}
-+
- /*
- * Dispatch a data abort to the relevant handler.
- */
- asmlinkage void
--do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
-+do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- const struct fsr_info *inf = fsr_info + (fsr & 15);
-
-- if (!inf->fn(addr, error_code, regs))
-+ if (!inf->fn(addr, fsr, regs))
- return;
-
- printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
-@@ -127,25 +101,28 @@
- do_translation_fault(addr, 0, regs);
- }
-
-+static unsigned long shared_pte_mask = L_PTE_CACHEABLE;
-+
- /*
- * We take the easy way out of this problem - we make the
- * PTE uncacheable. However, we leave the write buffer on.
- */
--static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
-+static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
- {
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte, entry;
-+ int ret = 0;
-
- pgd = pgd_offset(vma->vm_mm, address);
- if (pgd_none(*pgd))
-- return;
-+ goto no_pgd;
- if (pgd_bad(*pgd))
- goto bad_pgd;
-
- pmd = pmd_offset(pgd, address);
- if (pmd_none(*pmd))
-- return;
-+ goto no_pmd;
- if (pmd_bad(*pmd))
- goto bad_pmd;
-
-@@ -156,27 +133,30 @@
- * If this page isn't present, or is already setup to
- * fault (ie, is old), we can safely ignore any issues.
- */
-- if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) {
-+ if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
- flush_cache_page(vma, address);
-- pte_val(entry) &= ~L_PTE_CACHEABLE;
-+ pte_val(entry) &= ~shared_pte_mask;
- set_pte(pte, entry);
- flush_tlb_page(vma, address);
-+ ret = 1;
- }
-- return;
-+ return ret;
-
- bad_pgd:
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
-- return;
-+no_pgd:
-+ return 0;
-
- bad_pmd:
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
-- return;
-+no_pmd:
-+ return 0;
- }
-
- static void
--make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
-+make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
- {
- struct vm_area_struct *mpnt;
- struct mm_struct *mm = vma->vm_mm;
-@@ -210,14 +190,17 @@
- if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
- continue;
-
-+ off = mpnt->vm_start + (off << PAGE_SHIFT);
-+
- /*
- * Ok, it is within mpnt. Fix it up.
- */
-- adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
-- aliases ++;
-+ aliases += adjust_pte(mpnt, off);
- }
- if (aliases)
- adjust_pte(vma, addr);
-+ else if (dirty)
-+ flush_cache_page(vma, addr);
- }
-
- /*
-@@ -242,11 +225,85 @@
- return;
- page = pfn_to_page(pfn);
- if (page->mapping) {
-- if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
-+ int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
-+
-+ if (dirty) {
- unsigned long kvirt = (unsigned long)page_address(page);
- cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
- }
-
-- make_coherent(vma, addr, page);
-+ make_coherent(vma, addr, page, dirty);
-+ }
-+}
-+
-+/*
-+ * Check whether the write buffer has physical address aliasing
-+ * issues. If it has, we need to avoid them for the case where
-+ * we have several shared mappings of the same object in user
-+ * space.
-+ */
-+static int __init check_writebuffer(unsigned long *p1, unsigned long *p2)
-+{
-+ register unsigned long zero = 0, one = 1, val;
-+
-+ mb();
-+ *p1 = one;
-+ mb();
-+ *p2 = zero;
-+ mb();
-+ val = *p1;
-+ mb();
-+ return val != zero;
-+}
-+
-+static inline void *map_page(struct page *page)
-+{
-+ void *map;
-+
-+ map = __ioremap(page_to_phys(page), PAGE_SIZE, L_PTE_BUFFERABLE);
-+ if (map)
-+ get_page(page);
-+ return map;
-+}
-+
-+static inline void unmap_page(void *map)
-+{
-+ iounmap(map);
-+}
-+
-+void __init check_writebuffer_bugs(void)
-+{
-+ struct page *page;
-+ const char *reason;
-+ unsigned long v = 1;
-+
-+ printk(KERN_INFO "CPU: Testing write buffer: ");
-+
-+ page = alloc_page(GFP_KERNEL);
-+ if (page) {
-+ unsigned long *p1, *p2;
-+
-+ p1 = map_page(page);
-+ p2 = map_page(page);
-+
-+ if (p1 && p2) {
-+ v = check_writebuffer(p1, p2);
-+ reason = "enabling work-around";
-+ } else {
-+ reason = "unable to map memory\n";
-+ }
-+
-+ unmap_page(p1);
-+ unmap_page(p2);
-+ put_page(page);
-+ } else {
-+ reason = "unable to grab page\n";
-+ }
-+
-+ if (v) {
-+ printk("FAIL - %s\n", reason);
-+ shared_pte_mask |= L_PTE_BUFFERABLE;
-+ } else {
-+ printk("pass\n");
- }
- }
---- linux-2.4.25/arch/arm/mm/fault-common.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/fault-common.c 2004-03-31 17:15:09.000000000 +0200
-@@ -11,21 +11,17 @@
- #include <linux/config.h>
- #include <linux/signal.h>
- #include <linux/sched.h>
--#include <linux/kernel.h>
--#include <linux/errno.h>
- #include <linux/string.h>
--#include <linux/types.h>
- #include <linux/ptrace.h>
--#include <linux/mman.h>
- #include <linux/mm.h>
- #include <linux/interrupt.h>
--#include <linux/proc_fs.h>
- #include <linux/init.h>
-
- #include <asm/system.h>
--#include <asm/uaccess.h>
- #include <asm/pgtable.h>
--#include <asm/unaligned.h>
-+#include <asm/uaccess.h>
-+
-+#include "fault.h"
-
- #ifdef CONFIG_CPU_26
- #define FAULT_CODE_WRITE 0x02
-@@ -34,13 +30,11 @@
- #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
- #else
- /*
-- * On 32-bit processors, we define "mode" to be zero when reading,
-- * non-zero when writing. This now ties up nicely with the polarity
-- * of the 26-bit machines, and also means that we avoid the horrible
-- * gcc code for "int val = !other_val;".
-+ * "code" is actually the FSR register. Bit 11 set means the
-+ * instruction was performing a write.
- */
--#define DO_COW(m) (m)
--#define READ_FAULT(m) (!(m))
-+#define DO_COW(code) ((code) & (1 << 11))
-+#define READ_FAULT(code) (!DO_COW(code))
- #endif
-
- /*
-@@ -54,16 +48,17 @@
- if (!mm)
- mm = &init_mm;
-
-- printk(KERN_ALERT "mm = %p pgd = %p\n", mm, mm->pgd);
--
- fs = get_fs();
- set_fs(get_ds());
-+
- do {
-- pgd_t pg, *pgd = pgd_offset(mm, addr);
-+ pgd_t pg, *pgd;
- pmd_t pm, *pmd;
- pte_t pt, *pte;
-
-- printk(KERN_ALERT "*pgd = ");
-+ printk(KERN_ALERT "pgd = %p\n", mm->pgd);
-+ pgd = pgd_offset(mm, addr);
-+ printk(KERN_ALERT "[%08lx] *pgd=", addr);
-
- if (__get_user(pgd_val(pg), (unsigned long *)pgd)) {
- printk("(faulted)");
-@@ -122,7 +117,7 @@
- * Oops. The kernel tried to access some page that wasn't present.
- */
- static void
--__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
-+__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
- {
- unsigned long fixup;
-@@ -148,7 +143,7 @@
- "paging request", addr);
-
- show_pte(mm, addr);
-- die("Oops", regs, error_code);
-+ die("Oops", regs, fsr);
- do_exit(SIGKILL);
- }
-
-@@ -157,20 +152,20 @@
- * User mode accesses just cause a SIGSEGV
- */
- static void
--__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
-- int code, struct pt_regs *regs)
-+__do_user_fault(struct task_struct *tsk, unsigned long addr,
-+ unsigned int fsr, int code, struct pt_regs *regs)
- {
- struct siginfo si;
-
- #ifdef CONFIG_DEBUG_USER
- printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
- "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
-- tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
-+ tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, fsr);
- show_regs(regs);
- #endif
-
- tsk->thread.address = addr;
-- tsk->thread.error_code = error_code;
-+ tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- si.si_signo = SIGSEGV;
- si.si_errno = 0;
-@@ -181,20 +176,20 @@
-
- void
- do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-- int error_code, struct pt_regs *regs)
-+ unsigned int fsr, struct pt_regs *regs)
- {
- /*
- * If we are in kernel mode at this point, we
- * have no context to handle this fault with.
- */
- if (user_mode(regs))
-- __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
-+ __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
- else
-- __do_kernel_fault(mm, addr, error_code, regs);
-+ __do_kernel_fault(mm, addr, fsr, regs);
- }
-
- static int
--__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
-+__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct task_struct *tsk)
- {
- struct vm_area_struct *vma;
-@@ -212,7 +207,7 @@
- * memory access, so we can handle it.
- */
- good_area:
-- if (READ_FAULT(error_code)) /* read? */
-+ if (READ_FAULT(fsr)) /* read? */
- mask = VM_READ|VM_EXEC;
- else
- mask = VM_WRITE;
-@@ -227,7 +222,7 @@
- * than endlessly redo the fault.
- */
- survive:
-- fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
-+ fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
-
- /*
- * Handle the "normal" cases first - successful and sigbus
-@@ -260,7 +255,7 @@
- return fault;
- }
-
--int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- struct task_struct *tsk;
- struct mm_struct *mm;
-@@ -277,7 +272,7 @@
- goto no_context;
-
- down_read(&mm->mmap_sem);
-- fault = __do_page_fault(mm, addr, error_code, tsk);
-+ fault = __do_page_fault(mm, addr, fsr, tsk);
- up_read(&mm->mmap_sem);
-
- /*
-@@ -308,7 +303,7 @@
- printk("VM: killing process %s\n", tsk->comm);
- do_exit(SIGKILL);
- } else
-- __do_user_fault(tsk, addr, error_code, fault == -1 ?
-+ __do_user_fault(tsk, addr, fsr, fault == -1 ?
- SEGV_ACCERR : SEGV_MAPERR, regs);
- return 0;
-
-@@ -323,7 +318,7 @@
- * or user mode.
- */
- tsk->thread.address = addr;
-- tsk->thread.error_code = error_code;
-+ tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- force_sig(SIGBUS, tsk);
- #ifdef CONFIG_DEBUG_USER
-@@ -336,7 +331,7 @@
- return 0;
-
- no_context:
-- __do_kernel_fault(mm, addr, error_code, regs);
-+ __do_kernel_fault(mm, addr, fsr, regs);
- return 0;
- }
-
-@@ -357,21 +352,23 @@
- * interrupt or a critical region, and should only copy the information
- * from the master page table, nothing more.
- */
--int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+int do_translation_fault(unsigned long addr, unsigned int fsr,
-+ struct pt_regs *regs)
- {
- struct task_struct *tsk;
-- struct mm_struct *mm;
- int offset;
- pgd_t *pgd, *pgd_k;
- pmd_t *pmd, *pmd_k;
-
- if (addr < TASK_SIZE)
-- return do_page_fault(addr, error_code, regs);
-+ return do_page_fault(addr, fsr, regs);
-
- offset = __pgd_offset(addr);
-
- /*
- * FIXME: CP15 C1 is write only on ARMv3 architectures.
-+ * You really need to read the value in the page table
-+ * register, not a copy.
- */
- pgd = cpu_get_pgd() + offset;
- pgd_k = init_mm.pgd + offset;
-@@ -395,8 +392,7 @@
-
- bad_area:
- tsk = current;
-- mm = tsk->active_mm;
-
-- do_bad_area(tsk, mm, addr, error_code, regs);
-+ do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
- return 0;
- }
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/fault.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,9 @@
-+void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-+ unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
-+void show_pte(struct mm_struct *mm, unsigned long addr);
-+
-+int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
-+int do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
---- linux-2.4.25/arch/arm/mm/init.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/init.c 2004-03-31 17:15:09.000000000 +0200
-@@ -9,7 +9,6 @@
- */
- #include <linux/config.h>
- #include <linux/signal.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -18,7 +17,6 @@
- #include <linux/mman.h>
- #include <linux/mm.h>
- #include <linux/swap.h>
--#include <linux/swapctl.h>
- #include <linux/smp.h>
- #include <linux/init.h>
- #include <linux/bootmem.h>
---- linux-2.4.25/arch/arm/mm/ioremap.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/ioremap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -144,7 +144,7 @@
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
-- size = PAGE_ALIGN(last_addr) - phys_addr;
-+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
- /*
- * Ok, go for it..
---- linux-2.4.25/arch/arm/mm/mm-armv.c~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
-+++ linux-2.4.25/arch/arm/mm/mm-armv.c 2004-03-31 17:15:09.000000000 +0200
-@@ -9,7 +9,6 @@
- *
- * Page table sludge for ARM v3 and v4 processor architectures.
- */
--#include <linux/sched.h>
- #include <linux/mm.h>
- #include <linux/init.h>
- #include <linux/bootmem.h>
-@@ -390,6 +389,9 @@
- init_maps->bufferable = 0;
-
- create_mapping(init_maps);
-+
-+ flush_cache_all();
-+ flush_tlb_all();
- }
-
- /*
---- linux-2.4.25/arch/arm/mm/proc-arm1020.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm1020.S 2004-03-31 17:15:09.000000000 +0200
-@@ -65,18 +65,21 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm1020_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -170,10 +173,10 @@
- #endif
- subs r3, r3, #1
- cmp r3, #0
-- bge 2b @ entries 3F to 0
-+ bhs 2b @ entries 3F to 0
- subs r1, r1, #1
- cmp r1, #0
-- bge 1b @ segments 7 to 0
-+ bhs 1b @ segments 7 to 0
- #endif
-
- #ifndef CONFIG_CPU_ICACHE_DISABLE
-@@ -201,7 +204,7 @@
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm1020_cache_clean_invalidate_all_r2
-+ bhi cpu_arm1020_cache_clean_invalidate_all_r2
- mcr p15, 0, r3, c7, c10, 4
- #ifndef CONFIG_CPU_DCACHE_DISABLE
- 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-@@ -214,7 +217,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #endif
-
- #ifndef CONFIG_CPU_ICACHE_DISABLE
-@@ -302,7 +305,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #else
- /* D cache off, but still drain the write buffer */
- mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-@@ -328,7 +331,7 @@
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm1020_cache_clean_invalidate_all_r2
-+ bhi cpu_arm1020_cache_clean_invalidate_all_r2
- mcr p15, 0, r3, c7, c10, 4
- #ifndef CONFIG_CPU_DCACHE_DISABLE
- 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-@@ -341,7 +344,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #endif
-
- #ifndef CONFIG_CPU_BPREDICT_DISABLE
-@@ -488,7 +491,7 @@
- mov r0, r0
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -541,10 +544,10 @@
- #endif
- subs r3, r3, #1
- cmp r3, #0
-- bge 2b @ entries 3F to 0
-+ bhs 2b @ entries 3F to 0
- subs r1, r1, #1
- cmp r1, #0
-- bge 1b @ segments 15 to 0
-+ bhs 1b @ segments 15 to 0
-
- #endif
- mov r1, #0
-@@ -603,7 +606,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-@@ -740,12 +743,12 @@
-
- .type cpu_arch_name, #object
- cpu_arch_name:
-- .asciz "armv4"
-+ .asciz "armv5t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
- cpu_elf_name:
-- .asciz "v4"
-+ .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
- .align
-
-@@ -753,9 +756,9 @@
-
- .type __arm1020_proc_info,#object
- __arm1020_proc_info:
-- .long 0x4100a200
-- .long 0xff00fff0
-- .long 0x00000c02 @ mmuflags
-+ .long 0x4104a200 @ ARM 1020T (Architecture v5T)
-+ .long 0xff0ffff0
-+ .long 0x00000c0e @ mmuflags
- b __arm1020_setup
- .long cpu_arch_name
- .long cpu_elf_name
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm1020E.S 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,718 @@
-+/*
-+ * linux/arch/arm/mm/proc-arm1020E.S: MMU functions for ARM1020E
-+ *
-+ * Copyright (C) 2000 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *
-+ * These are the low level assembler for performing cache and TLB
-+ * functions on the arm1020E.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/config.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * This is the maximum size of an area which will be invalidated
-+ * using the single invalidate entry instructions. Anything larger
-+ * than this, and we go for the whole cache.
-+ *
-+ * This value should be chosen such that we choose the cheapest
-+ * alternative.
-+ */
-+#define MAX_AREA_SIZE 32768
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define DCACHELINESIZE 32
-+#define ICACHELINESIZE 32
-+
-+/*
-+ * and the page size
-+ */
-+#define LOG2PAGESIZE 12 /* == 4096 Bytes */
-+#define PAGESIZE (1 << LOG2PAGESIZE)
-+
-+/*
-+ * create some useful conditional macro definitions
-+ * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
-+ */
-+#ifdef CONFIG_CPU_DCACHE_DISABLE
-+ #undef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #undef CONFIG_CPU_DCACHE_ENABLE
-+#else
-+ #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #else
-+ #define CONFIG_CPU_DCACHE_WRITEBACK
-+ #endif
-+ #define CONFIG_CPU_DCACHE_ENABLE
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_DISABLE
-+ #undef CONFIG_CPU_ICACHE_ENABLE
-+#else
-+ #define CONFIG_CPU_ICACHE_ENABLE
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_arm1020E_data_abort()
-+ *
-+ * obtain information about current aborted instruction
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = cpsr
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR
-+ * r3 = corrupted
-+ * r4 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_check_bugs()
-+ */
-+ENTRY(cpu_arm1020E_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_proc_init()
-+ */
-+ENTRY(cpu_arm1020E_proc_init)
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_proc_fin()
-+ */
-+ENTRY(cpu_arm1020E_proc_fin)
-+ stmfd sp!, {lr}
-+ mov ip, #F_BIT | I_BIT | SVC_MODE
-+ msr cpsr_c, ip
-+ bl cpu_arm1020E_cache_clean_invalidate_all
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1000 @ ...i............
-+ bic r0, r0, #0x000e @ ............wca.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1020E_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_reset)
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
-+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
-+ bic ip, ip, #0x000f @ ............wcam
-+ bic ip, ip, #0x1100 @ ...i...s........
-+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
-+ mov pc, r0
-+
-+/*
-+ * cpu_arm1020E_do_idle()
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_do_idle)
-+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+
-+/*
-+ * cpu_arm1020E_cache_clean_invalidate_all()
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. we should preserve r0 and ip at all times
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_arm1020E_cache_clean_invalidate_all_r2:
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r1, #0x0F << 5 @ 16 segments
-+1: orr r3, r1, #63 << 26 @ 64 entries
-+2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
-+ subs r3, r3, #1 << 26
-+ bcs 2b
-+ subs r1, r1, #1 << 5
-+ bcs 1b @ segments 15 to 0
-+#endif
-+
-+ mov r1, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
-+#endif
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_cache_clean_invalidate_range)
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - must include end point (r1)!
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_flush_ram_page(page)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * page: page to clean and invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_flush_ram_page)
-+ mov r1, #PAGESIZE
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1020E_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that we must clean the D-cached entries
-+ * around the boundaries if the start and/or end address are not cache
-+ * aligned.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_invalidate_range)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ bic r0, r0, #DCACHELINESIZE - 1
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ tst r0, #DCACHELINESIZE - 1
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
-+ tst r1, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
-+#endif
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+
-+ /* Even if the D cache is off still drain the write buffer */
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_range)
-+
-+ mov r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+#endif
-+
-+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * page: virtual address of page to clean from dcache
-+ *
-+ * Note:
-+ * we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_page)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ mov r1, #PAGESIZE
-+1:
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_entry)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1020E_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * This is a little misleading, it is not intended to clean out
-+ * the i-cache but to make sure that any data written to the
-+ * range is made consistent. This means that when we execute code
-+ * in that region, everything works as we expect.
-+ *
-+ * This generally means writing back data in the Dcache and
-+ * write buffer and invalidating the Icache over that region
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
-+ * loop twice, once for i-cache, once for d-cache)
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_icache_invalidate_range)
-+ bic r0, r0, #ICACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ movhs r2, #1
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - includes r1 entry
-+
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+ENTRY(cpu_arm1020E_icache_invalidate_page)
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ add r1, r0, #PAGESIZE
-+ b cpu_arm1020E_icache_invalidate_range
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_all)
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_range)
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE
-+ bhs cpu_arm1020E_tlb_invalidate_all
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r3, #PAGESIZE
-+ sub r3, r3, #1
-+ bic r0, r0, r3
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ bls 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_page)
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ mov pc, lr
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_arm1020E_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pgd)
-+ stmfd sp!, {lr}
-+ bl cpu_arm1020E_cache_clean_invalidate_all @ preserves r0
-+ mov r1, #0
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1020E_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pmd)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r2, r1, #0x0a @ C & Section
-+ tst r2, #0x0b
-+ biceq r1, r1, #4 @ clear bufferable bit
-+#endif
-+ str r1, [r0]
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
-+
-+ bic r2, r1, #0xff0
-+ bic r2, r2, #3
-+ orr r2, r2, #HPTE_TYPE_SMALL
-+
-+ tst r1, #LPTE_USER @ User?
-+ orrne r2, r2, #HPTE_AP_READ
-+
-+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #HPTE_AP_WRITE
-+
-+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
-+ movne r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r3, r2, #0x0a @ C and Small Page?
-+ tst r3, #0x0b @ if so..
-+ biceq r2, r2, #0x04 @ clear the bufferable bit
-+#endif
-+ str r2, [r0] @ hardware version
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+
-+cpu_manu_name:
-+ .asciz "ARM"
-+ENTRY(cpu_arm1020E_name)
-+ .ascii "Arm1020E"
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ .ascii "i"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "d"
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ .ascii "(wt)"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "(wb)"
-+#endif
-+#endif
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ .ascii "B"
-+#endif
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ .ascii "RR"
-+#endif
-+ .ascii "\0"
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__arm1020E_setup:
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
-+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+
-+ mrc p15, 0, r0, c1, c0, 0 @ Read current control register
-+/*
-+ * The only thing worth keeping from the initial control register is the endian bit
-+ */
-+
-+ and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
-+ orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
-+/*
-+ * Turn on what we want.
-+ */
-+ orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
-+ orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
-+ orr r0, r0, #0x2000 @ ..V............. Enable high vectors
-+
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
-+#endif
-+
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
-+#endif
-+
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ orr r0, r0, #0x0004 @ .............C.. Enable D cache
-+#endif
-+#ifndef CONFIG_CPU_WB_DISABLE
-+ orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ orr r0, r0, #0x1000 @ ...I............ Enable I Cache
-+#endif
-+
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+ .type arm1020E_processor_functions, #object
-+arm1020E_processor_functions:
-+ .word cpu_arm1020E_data_abort
-+ .word cpu_arm1020E_check_bugs
-+ .word cpu_arm1020E_proc_init
-+ .word cpu_arm1020E_proc_fin
-+ .word cpu_arm1020E_reset
-+ .word cpu_arm1020E_do_idle
-+
-+ /* cache */
-+ .word cpu_arm1020E_cache_clean_invalidate_all
-+ .word cpu_arm1020E_cache_clean_invalidate_range
-+ .word cpu_arm1020E_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_arm1020E_dcache_invalidate_range
-+ .word cpu_arm1020E_dcache_clean_range
-+ .word cpu_arm1020E_dcache_clean_page
-+ .word cpu_arm1020E_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_arm1020E_icache_invalidate_range
-+ .word cpu_arm1020E_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_arm1020E_tlb_invalidate_all
-+ .word cpu_arm1020E_tlb_invalidate_range
-+ .word cpu_arm1020E_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_arm1020E_set_pgd
-+ .word cpu_arm1020E_set_pmd
-+ .word cpu_arm1020E_set_pte
-+ .size arm1020E_processor_functions, . - arm1020E_processor_functions
-+
-+ .type cpu_arm1020E_info, #object
-+cpu_arm1020E_info:
-+ .long cpu_manu_name
-+ .long cpu_arm1020E_name
-+ .size cpu_arm1020E_info, . - cpu_arm1020E_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5te"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __arm1020E_proc_info,#object
-+__arm1020E_proc_info:
-+ .long 0x4105a200 @ ARM 1020E (Architecture v5TE)
-+ .long 0xff0ffff0
-+ .long 0x00000c1e @ mmuflags
-+ b __arm1020E_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-+ .long cpu_arm1020E_info
-+ .long arm1020E_processor_functions
-+ .size __arm1020E_proc_info, . - __arm1020E_proc_info
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm1022.S 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,716 @@
-+/*
-+ * linux/arch/arm/mm/proc-arm1022.S: MMU functions for ARM1022E
-+ *
-+ * Copyright (C) 2000 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *
-+ * These are the low level assembler for performing cache and TLB
-+ * functions on the arm1022E.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/config.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * This is the maximum size of an area which will be invalidated
-+ * using the single invalidate entry instructions. Anything larger
-+ * than this, and we go for the whole cache.
-+ *
-+ * This value should be chosen such that we choose the cheapest
-+ * alternative.
-+ */
-+#define MAX_AREA_SIZE 16384
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define DCACHELINESIZE 32
-+#define ICACHELINESIZE 32
-+
-+/*
-+ * and the page size
-+ */
-+#define LOG2PAGESIZE 12 /* == 4096 Bytes */
-+#define PAGESIZE (1 << LOG2PAGESIZE)
-+
-+/*
-+ * create some useful conditional macro definitions
-+ * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
-+ */
-+#ifdef CONFIG_CPU_DCACHE_DISABLE
-+ #undef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #undef CONFIG_CPU_DCACHE_ENABLE
-+#else
-+ #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #else
-+ #define CONFIG_CPU_DCACHE_WRITEBACK
-+ #endif
-+ #define CONFIG_CPU_DCACHE_ENABLE
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_DISABLE
-+ #undef CONFIG_CPU_ICACHE_ENABLE
-+#else
-+ #define CONFIG_CPU_ICACHE_ENABLE
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_arm1022_data_abort()
-+ *
-+ * obtain information about current aborted instruction
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = cpsr
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR
-+ * r3 = corrupted
-+ * r4 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_check_bugs()
-+ */
-+ENTRY(cpu_arm1022_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_proc_init()
-+ */
-+ENTRY(cpu_arm1022_proc_init)
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_proc_fin()
-+ */
-+ENTRY(cpu_arm1022_proc_fin)
-+ stmfd sp!, {lr}
-+ mov ip, #F_BIT | I_BIT | SVC_MODE
-+ msr cpsr_c, ip
-+ bl cpu_arm1022_cache_clean_invalidate_all
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1000 @ ...i............
-+ bic r0, r0, #0x000e @ ............wca.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1022_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_reset)
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
-+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
-+ bic ip, ip, #0x000f @ ............wcam
-+ bic ip, ip, #0x1100 @ ...i...s........
-+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
-+ mov pc, r0
-+
-+/*
-+ * cpu_arm1022_do_idle()
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_do_idle)
-+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+
-+/*
-+ * cpu_arm1022_cache_clean_invalidate_all()
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. we should preserve r0 and ip at all times
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_arm1022_cache_clean_invalidate_all_r2:
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r1, #7 << 5 @ 8 segments
-+1: orr r3, r1, #63 << 26 @ 64 entries
-+2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
-+ subs r3, r3, #1 << 26
-+ bcs 2b
-+ subs r1, r1, #1 << 5
-+ bcs 1b @ segments 7 to 0
-+#endif
-+
-+ mov r1, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
-+#endif
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_cache_clean_invalidate_range)
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - must include end point (r1)!
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_flush_ram_page(page)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * page: page to clean and invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_flush_ram_page)
-+ mov r1, #PAGESIZE
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1022_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that we must clean the D-cached entries
-+ * around the boundaries if the start and/or end address are not cache
-+ * aligned.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_invalidate_range)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ bic r0, r0, #DCACHELINESIZE - 1
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ tst r0, #DCACHELINESIZE - 1
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
-+ tst r1, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
-+#endif
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+
-+ /* Even if the D cache is off still drain the write buffer */
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_range)
-+
-+ mov r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+#endif
-+
-+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * page: virtual address of page to clean from dcache
-+ *
-+ * Note:
-+ * we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_page)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ mov r1, #PAGESIZE
-+1:
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_entry)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1022_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * This is a little misleading, it is not intended to clean out
-+ * the i-cache but to make sure that any data written to the
-+ * range is made consistent. This means that when we execute code
-+ * in that region, everything works as we expect.
-+ *
-+ * This generally means writing back data in the Dcache and
-+ * write buffer and invalidating the Icache over that region
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
-+ * loop twice, once for i-cache, once for d-cache)
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_icache_invalidate_range)
-+ bic r0, r0, #ICACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ movhs r2, #1
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - includes r1 entry
-+
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+ENTRY(cpu_arm1022_icache_invalidate_page)
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ add r1, r0, #PAGESIZE
-+ b cpu_arm1022_icache_invalidate_range
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_all)
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_range)
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE
-+ bhs cpu_arm1022_tlb_invalidate_all
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r3, #PAGESIZE
-+ sub r3, r3, #1
-+ bic r0, r0, r3
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ bls 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_page)
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ mov pc, lr
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_arm1022_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pgd)
-+ stmfd sp!, {lr}
-+ bl cpu_arm1022_cache_clean_invalidate_all @ preserves r0
-+ mov r1, #0
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1022_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pmd)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r2, r1, #0x0a @ C & Section
-+ tst r2, #0x0b
-+ biceq r1, r1, #4 @ clear bufferable bit
-+#endif
-+ str r1, [r0]
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
-+
-+ bic r2, r1, #0xff0
-+ bic r2, r2, #3
-+ orr r2, r2, #HPTE_TYPE_SMALL
-+
-+ tst r1, #LPTE_USER @ User?
-+ orrne r2, r2, #HPTE_AP_READ
-+
-+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #HPTE_AP_WRITE
-+
-+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
-+ movne r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r3, r2, #0x0a @ C and Small Page?
-+ tst r3, #0x0b @ if so..
-+ biceq r2, r2, #0x04 @ clear the bufferable bit
-+#endif
-+ str r2, [r0] @ hardware version
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+
-+cpu_manu_name:
-+ .asciz "ARM"
-+ENTRY(cpu_arm1022_name)
-+ .ascii "Arm1022E"
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ .ascii "i"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "d"
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ .ascii "(wt)"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "(wb)"
-+#endif
-+#endif
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ .ascii "B"
-+#endif
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ .ascii "RR"
-+#endif
-+ .ascii "\0"
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__arm1022_setup:
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
-+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+
-+ mrc p15, 0, r0, c1, c0, 0 @ Read current control register
-+/*
-+ * The only thing worth keeping from the initial control register is the endian bit
-+ */
-+
-+ and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
-+ orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
-+/*
-+ * Turn on what we want.
-+ */
-+ orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
-+ orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
-+ orr r0, r0, #0x2000 @ ..V............. Enable high vectors
-+
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
-+#endif
-+
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
-+#endif
-+
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ orr r0, r0, #0x0004 @ .............C.. Enable D cache
-+#endif
-+#ifndef CONFIG_CPU_WB_DISABLE
-+ orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ orr r0, r0, #0x1000 @ ...I............ Enable I Cache
-+#endif
-+
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+ .type arm1022_processor_functions, #object
-+arm1022_processor_functions:
-+ .word cpu_arm1022_data_abort
-+ .word cpu_arm1022_check_bugs
-+ .word cpu_arm1022_proc_init
-+ .word cpu_arm1022_proc_fin
-+ .word cpu_arm1022_reset
-+ .word cpu_arm1022_do_idle
-+
-+ /* cache */
-+ .word cpu_arm1022_cache_clean_invalidate_all
-+ .word cpu_arm1022_cache_clean_invalidate_range
-+ .word cpu_arm1022_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_arm1022_dcache_invalidate_range
-+ .word cpu_arm1022_dcache_clean_range
-+ .word cpu_arm1022_dcache_clean_page
-+ .word cpu_arm1022_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_arm1022_icache_invalidate_range
-+ .word cpu_arm1022_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_arm1022_tlb_invalidate_all
-+ .word cpu_arm1022_tlb_invalidate_range
-+ .word cpu_arm1022_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_arm1022_set_pgd
-+ .word cpu_arm1022_set_pmd
-+ .word cpu_arm1022_set_pte
-+ .size arm1022_processor_functions, . - arm1022_processor_functions
-+
-+ .type cpu_arm1022_info, #object
-+cpu_arm1022_info:
-+ .long cpu_manu_name
-+ .long cpu_arm1022_name
-+ .size cpu_arm1022_info, . - cpu_arm1022_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5t"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __arm1022_proc_info,#object
-+__arm1022_proc_info:
-+ .long 0x4100a220 @ ARM 1022
-+ .long 0xff00fff0
-+ .long 0x00000c1e @ mmuflags
-+ b __arm1022_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-+ .long cpu_arm1022_info
-+ .long arm1022_processor_functions
-+ .size __arm1022_proc_info, . - __arm1022_proc_info
---- linux-2.4.25/arch/arm/mm/proc-arm1026.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm1026.S 2004-03-31 17:15:09.000000000 +0200
-@@ -66,19 +66,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm1026_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r2, r3, #0b1101 @ Check for translation error
-- sub r1, r2, #0b0101
--
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
--
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -254,7 +259,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -279,7 +284,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-@@ -309,7 +314,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -330,7 +335,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -473,7 +478,7 @@
- biceq r1, r1, #4 @ clear bufferable bit
- #endif
- str r1, [r0]
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -494,7 +499,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-@@ -634,12 +639,12 @@
-
- .type cpu_arch_name, #object
- cpu_arch_name:
-- .asciz "armv5EJ"
-+ .asciz "armv5tej"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
- cpu_elf_name:
-- .asciz "v5EJ"
-+ .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
- .align
-
---- linux-2.4.25/arch/arm/mm/proc-arm6,7.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm6,7.S 2004-03-31 17:15:09.000000000 +0200
-@@ -72,7 +72,7 @@
- 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
- add r0, r0, #4096
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- ENTRY(cpu_arm7_tlb_invalidate_range)
-@@ -85,7 +85,7 @@
- 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
- add r0, r0, #0x4000
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
- #endif
-
-@@ -110,15 +110,13 @@
- * Purpose : obtain information about current aborted instruction
- *
- * Returns : r0 = address of abort
-- * : r1 != 0 if writing
-- * : r3 = FSR
-+ * : r1 = FSR, bit 11 set if writing
-+ * : r3 = corrupted
- * : sp = pointer to registers
- */
-
- ENTRY(cpu_arm6_data_abort)
- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #14 << 24
- teq r2, #8 << 24 @ was it ldm/stm
- bne Ldata_simple
-@@ -144,14 +142,14 @@
- addeq r7, r0, r7, lsl #2 @ Do correction (signed)
- Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
- Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ bic r1, r1, #1 << 11 | 1 << 10
-+ tst r4, #1 << 20
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- ENTRY(cpu_arm7_data_abort)
- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #15 << 24
- add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
- movs pc, lr
-@@ -336,7 +334,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-arm720.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm720.S 2004-03-31 17:15:09.000000000 +0200
-@@ -97,7 +97,7 @@
- 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4)
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -124,8 +124,8 @@
- * picture. Unfortunately, this does happen. We live with it.
- *
- * Returns : r0 = address of abort
-- * : r1 != 0 if writing
-- * : r3 = FSR
-+ * : r1 = FSR, bit 11 set if writing
-+ * : r3 = corrupted
- * : sp = pointer to registers
- */
-
-@@ -150,16 +150,16 @@
- addeq r7, r0, r7, lsl #2 @ Do correction (signed)
- Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
- Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ bic r1, r1, #1 << 11 | 1 << 10
-+ tst r4, #1 << 20
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- ENTRY(cpu_arm720_data_abort)
-- tst r3, #T_BIT
-+ tst r3, #PSR_T_BIT
- bne .data_thumb_abort
-- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldr r4, [r2] @ read instruction causing problem
- and r2, r4, #15 << 24
- add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
- movs pc, lr
-@@ -270,9 +270,9 @@
- b Ldata_saver7
-
- .data_thumb_abort:
-- ldrh r4, [r0] @ read instruction
-- tst r4, r4, lsr #12 @ C = bit 11
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldrh r4, [r2] @ read instruction
-+ tst r4, #1 << 11
-+ orrne r4, r4, #1 << 20
- and r2, r4, #15 << 12
- add pc, pc, r2, lsr #10 @ lookup in table
- nop
-@@ -318,8 +318,8 @@
- and r0, r0, #15 @ number of regs to transfer
- ldr r7, [sp, #13 << 2]
- tst r4, #1 << 11
-- addne r7, r7, r0, lsl #2 @ increment SP if PUSH
-- subeq r7, r7, r0, lsr #2 @ decrement SP if POP
-+ addeq r7, r7, r0, lsl #2 @ increment SP if PUSH
-+ subne r7, r7, r0, lsl #2 @ decrement SP if POP
- str r7, [sp, #13 << 2]
- b Ldata_simple
-
-@@ -336,7 +336,7 @@
- and r0, r0, #15 @ number of regs to transfer
- and r5, r4, #7 << 8
- ldr r7, [sp, r5, lsr #6]
-- sub r7, r7, r0, lsr #2 @ always decrement
-+ sub r7, r7, r0, lsl #2 @ always decrement
- str r7, [sp, r5, lsr #6]
- b Ldata_simple
-
-@@ -418,7 +418,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-arm920.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm920.S 2004-03-31 17:15:09.000000000 +0200
-@@ -71,12 +71,16 @@
- */
- .align 5
- ENTRY(cpu_arm920_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -186,10 +190,9 @@
- .align 5
- ENTRY(cpu_arm920_cache_clean_invalidate_range)
- bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
-- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -207,7 +210,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -253,18 +256,17 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
- mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
- #endif @ clean D entry
- bic r0, r0, #DCACHELINESIZE - 1
-- bic r1, r1, #DCACHELINESIZE - 1
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -279,20 +281,17 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
--
-- bic r1, r1, #DCACHELINESIZE -1
-- add r1, r1, #DCACHELINESIZE
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
-
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
- subs r1, r1, #DCACHELINESIZE
-- bpl 1b
-+ bcs 1b
- #endif
- mcr p15, 0, r2, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -312,7 +311,7 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -333,7 +332,7 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -365,16 +364,13 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
--
-- bic r1, r1, #ICACHELINESIZE - 1
-- add r1, r1, #ICACHELINESIZE
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
-
- 1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry
- mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
- add r0, r0, #ICACHELINESIZE
- subs r1, r1, #ICACHELINESIZE
-- bne 1b
-+ bcs 1b
-
- mov r0, #0
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -418,13 +414,12 @@
- mov r3, #PAGESIZE
- sub r3, r3, #1
- bic r0, r0, r3
-- bic r1, r1, r3
-
- 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -457,7 +452,6 @@
- ENTRY(cpu_arm920_set_pgd)
- mov ip, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-- /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
- mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
- #else
- @ && 'Clean & Invalidate whole DCache'
-@@ -514,7 +508,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-arm922.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm922.S 2004-03-31 17:15:09.000000000 +0200
-@@ -62,17 +62,20 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- */
- .align 5
- ENTRY(cpu_arm922_data_abort)
-- ldr r1, [r0] @ read aborted instruction
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- tst r1, r1, lsr #21 @ C = bit 20
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- sbc r1, r1, r1 @ r1 = C - 1
-- and r3, r3, #255
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -185,7 +188,7 @@
- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -203,7 +206,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -249,7 +252,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -260,7 +263,7 @@
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -275,12 +278,12 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
-
- bic r1, r1, #DCACHELINESIZE -1
- add r1, r1, #DCACHELINESIZE
-@@ -308,7 +311,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -329,7 +332,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -361,7 +364,7 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
-
- bic r1, r1, #ICACHELINESIZE - 1
- add r1, r1, #ICACHELINESIZE
-@@ -420,7 +423,7 @@
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -510,7 +513,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-arm925.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm925.S 2004-03-31 17:15:09.000000000 +0200
-@@ -69,24 +69,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm925_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r4, c5, c0, 0 @ get FSR
--
-- tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
-- ldrneh r1, [r2] @ Read aborted Thumb instruction
-- tstne r1, r1, lsr #12 @ C = bit 11
--
-- ldreq r1, [r2] @ Read aborted ARM instruction
-- tsteq r1, r1, lsr #21 @ C = bit 20
--
-- sbc r1, r1, r1 @ r1 = C - 1
-- and r3, r4, #255
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT @ Thumb?
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ L = 0 -> write
-+ orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
- /*
-@@ -207,7 +207,7 @@
- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_ARM925_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -225,7 +225,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -282,7 +282,7 @@
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -302,7 +302,7 @@
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
-
- bic r1, r1, #DCACHELINESIZE -1
- add r1, r1, #DCACHELINESIZE
-@@ -383,7 +383,7 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
-
- bic r1, r1, #ICACHELINESIZE - 1
- add r1, r1, #ICACHELINESIZE
-@@ -443,7 +443,7 @@
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -532,7 +532,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-arm926.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-arm926.S 2004-03-31 17:15:09.000000000 +0200
-@@ -66,28 +66,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm926_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r4, c5, c0, 0 @ get FSR
--
-- tst r3, #1<<24 @ Check for Jbit (NE -> found)
-- movne r3, #-1 @ Mark as writing
-- bne 2f
--
-- tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
-- ldrneh r1, [r2] @ Read aborted Thumb instruction
-- ldreq r1, [r2] @ Read aborted ARM instruction
-- movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20
-- tsteq r1, r1, lsr #21 @ C = bit 20
--
-- sbc r1, r1, r1 @ r1 = C - 1
--2:
-- and r3, r4, #255
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT @ Thumb?
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ L = 0 -> write
-+ orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
- /*
-@@ -263,7 +259,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -288,7 +284,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-@@ -318,7 +314,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -339,7 +335,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -482,7 +478,7 @@
- biceq r1, r1, #4 @ clear bufferable bit
- #endif
- str r1, [r0]
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -503,7 +499,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/mm/proc-sa110.S~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/mm/proc-sa110.S 2004-03-31 17:15:09.000000000 +0200
-@@ -86,12 +86,12 @@
- .align 5
- ENTRY(cpu_sa110_data_abort)
- ENTRY(cpu_sa1100_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldr r3, [r2] @ read aborted instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -551,7 +551,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.25/arch/arm/tools/mach-types~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/arm/tools/mach-types 2004-03-31 17:15:09.000000000 +0200
-@@ -6,7 +6,7 @@
- # To add an entry into this database, please see Documentation/arm/README,
- # or contact rmk@arm.linux.org.uk
- #
--# Last update: Sat Jun 28 12:10:54 2003
-+# Last update: Tue Feb 10 17:10:34 2004
- #
- # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
- #
-@@ -202,7 +202,7 @@
- fester SA1100_FESTER FESTER 191
- gpi ARCH_GPI GPI 192
- smdk2410 ARCH_SMDK2410 SMDK2410 193
--premium ARCH_PREMIUM PREMIUM 194
-+i519 ARCH_I519 I519 194
- nexio SA1100_NEXIO NEXIO 195
- bitbox SA1100_BITBOX BITBOX 196
- g200 SA1100_G200 G200 197
-@@ -228,7 +228,7 @@
- arnold SA1100_ARNOLD ARNOLD 217
- psiboard SA1100_PSIBOARD PSIBOARD 218
- jz8028 ARCH_JZ8028 JZ8028 219
--h5400 ARCH_IPAQ3 IPAQ3 220
-+h5400 ARCH_H5400 H5400 220
- forte SA1100_FORTE FORTE 221
- acam SA1100_ACAM ACAM 222
- abox SA1100_ABOX ABOX 223
-@@ -259,7 +259,7 @@
- stork_egg ARCH_STORK_EGG STORK_EGG 248
- wismo SA1100_WISMO WISMO 249
- ezlinx ARCH_EZLINX EZLINX 250
--at91rm9200 ARCH_AT91 AT91 251
-+at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
- orion ARCH_ORION ORION 252
- neptune ARCH_NEPTUNE NEPTUNE 253
- hackkit SA1100_HACKKIT HACKKIT 254
-@@ -300,7 +300,7 @@
- inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
- adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
- iyonix ARCH_IYONIX IYONIX 291
--damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
-+damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
- meg03 ARCH_MEG03 MEG03 293
- pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
- nwsc ARCH_NWSC NWSC 295
-@@ -356,3 +356,111 @@
- seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
- ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
- h1940 ARCH_H1940 H1940 347
-+scorpio ARCH_SCORPIO SCORPIO 348
-+viva ARCH_VIVA VIVA 349
-+pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
-+csb335 ARCH_CSB335 CSB335 351
-+ixrd425 ARCH_IXRD425 IXRD425 352
-+iq80315 ARCH_IQ80315 IQ80315 353
-+nmp7312 ARCH_NMP7312 NMP7312 354
-+cx861xx ARCH_CX861XX CX861XX 355
-+enp2611 ARCH_ENP2611 ENP2611 356
-+xda SA1100_XDA XDA 357
-+csir_ims ARCH_CSIR_IMS CSIR_IMS 358
-+ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
-+pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
-+toto ARCH_TOTO TOTO 361
-+s3c2440 ARCH_S3C2440 S3C2440 362
-+ks8695p ARCH_KS8695P KS8695P 363
-+se4000 ARCH_SE4000 SE4000 364
-+quadriceps ARCH_QUADRICEPS QUADRICEPS 365
-+bronco ARCH_BRONCO BRONCO 366
-+esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
-+esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
-+s5c7375 ARCH_S5C7375 S5C7375 369
-+spearhead ARCH_SPEARHEAD SPEARHEAD 370
-+pantera ARCH_PANTERA PANTERA 371
-+prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
-+gumstik ARCH_GUMSTIK GUMSTIK 373
-+rcube ARCH_RCUBE RCUBE 374
-+rea_olv ARCH_REA_OLV REA_OLV 375
-+pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
-+s3c3410 ARCH_S3C3410 S3C3410 377
-+espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
-+mp1x ARCH_MP1X MP1X 379
-+at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
-+adsvgx ARCH_ADSVGX ADSVGX 381
-+omap1610 ARCH_OMAP1610 OMAP1610 382
-+pelee ARCH_PELEE PELEE 383
-+e7xx ARCH_E7XX E7XX 384
-+iq80331 ARCH_IQ80331 IQ80331 385
-+versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
-+kev7a400 MACH_KEV7A400 KEV7A400 388
-+lpd7a400 MACH_LPD7A400 LPD7A400 389
-+lpd7a404 MACH_LPD7A404 LPD7A404 390
-+fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
-+janus2m ARCH_JANUS2M JANUS2M 392
-+embtf MACH_EMBTF EMBTF 393
-+hpm MACH_HPM HPM 394
-+smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
-+smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
-+streetracer MACH_STREETRACER STREETRACER 397
-+eframe MACH_EFRAME EFRAME 398
-+csb337 MACH_CSB337 CSB337 399
-+pxa_lark MACH_PXA_LARK PXA_LARK 400
-+pxa_pnp2110 MACH_PNP2110 PNP2110 401
-+tcc72x MACH_TCC72X TCC72X 402
-+altair MACH_ALTAIR ALTAIR 403
-+kc3 MACH_KC3 KC3 404
-+sinteftd MACH_SINTEFTD SINTEFTD 405
-+mainstone MACH_MAINSTONE MAINSTONE 406
-+aday4x MACH_ADAY4X ADAY4X 407
-+lite300 MACH_LITE300 LITE300 408
-+s5c7376 MACH_S5C7376 S5C7376 409
-+mt02 MACH_MT02 MT02 410
-+mport3s MACH_MPORT3S MPORT3S 411
-+ra_alpha MACH_RA_ALPHA RA_ALPHA 412
-+xcep MACH_XCEP XCEP 413
-+arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414
-+stargate MACH_STARGATE STARGATE 415
-+armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
-+elroy_jack MACH_ELROY_JACK ELROY_JACK 417
-+backend MACH_BACKEND BACKEND 418
-+s5linbox MACH_S5LINBOX S5LINBOX 419
-+nomadik MACH_NOMADIK NOMADIK 420
-+ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
-+at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
-+corgi MACH_CORGI CORGI 423
-+poodle MACH_POODLE POODLE 424
-+ten MACH_TEN TEN 425
-+roverp5p MACH_ROVERP5P ROVERP5P 426
-+sc2700 MACH_SC2700 SC2700 427
-+ex_eagle MACH_EX_EAGLE EX_EAGLE 428
-+nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
-+nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
-+blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
-+i819 MACH_I819 I819 432
-+ixmb995e MACH_IXMB995E IXMB995E 433
-+skyrider MACH_SKYRIDER SKYRIDER 434
-+skyhawk MACH_SKYHAWK SKYHAWK 435
-+enterprise MACH_ENTERPRISE ENTERPRISE 436
-+dep2410 MACH_DEP2410 DEP2410 437
-+armcore MACH_ARMCORE ARMCORE 438
-+hobbit MACH_HOBBIT HOBBIT 439
-+h7210 MACH_H7210 H7210 440
-+pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
-+acc MACH_ACC ACC 442
-+esl_sarva MACH_ESL_SARVA ESL_SARVA 443
-+xm250 MACH_XM250 XM250 444
-+t6tc1xb MACH_T6TC1XB T6TC1XB 445
-+ess710 MACH_ESS710 ESS710 446
-+mx3ads MACH_MX3ADS MX3ADS 447
-+himalaya MACH_HIMALAYA HIMALAYA 448
-+bolfenk MACH_BOLFENK BOLFENK 449
-+at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
-+edb9312 MACH_EDB9312 EDB9312 451
-+omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
-+aximx3 MACH_AXIMX3 AXIMX3 453
-+eb67xdip MACH_EB67XDIP EB67XDIP 454
-+webtxs MACH_WEBTXS WEBTXS 455
-+hawk MACH_HAWK HAWK 456
---- linux-2.4.25/arch/i386/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/i386/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -9,6 +9,7 @@
-
- define_bool CONFIG_UID16 y
-
-+define_bool CONFIG_GENERIC_ISA_DMA y
- mainmenu_option next_comment
- comment 'Code maturity level options'
- bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
---- linux-2.4.25/arch/i386/kernel/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
-+++ linux-2.4.25/arch/i386/kernel/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -7,8 +7,8 @@
- #
- # Note 2! The CFLAGS definitions are now in the main makefile...
-
--.S.o:
-- $(CC) $(AFLAGS) -traditional -c $< -o $*.o
-+USE_STANDARD_AS_RULE := true
-+EXTRA_AFLAGS := -traditional
-
- all: kernel.o head.o init_task.o
-
---- linux-2.4.25/arch/i386/kernel/apm.c~2.4.25-vrs2.patch 2003-08-25 13:44:39.000000000 +0200
-+++ linux-2.4.25/arch/i386/kernel/apm.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1267,6 +1267,7 @@
- as->suspend_wait = 0;
- as->suspend_result = err;
- }
-+ ignore_normal_resume = 1;
- wake_up_interruptible(&apm_suspend_waitqueue);
- return err;
- }
-@@ -1319,6 +1320,8 @@
- if (ignore_bounce
- && ((jiffies - last_resume) > bounce_interval))
- ignore_bounce = 0;
-+ if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
-+ ignore_normal_resume = 0;
-
- switch (event) {
- case APM_SYS_STANDBY:
---- linux-2.4.25/arch/i386/lib/Makefile~2.4.25-vrs2.patch 2001-09-10 16:31:30.000000000 +0200
-+++ linux-2.4.25/arch/i386/lib/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -2,8 +2,7 @@
- # Makefile for i386-specific library files..
- #
-
--.S.o:
-- $(CC) $(AFLAGS) -c $< -o $*.o
-+USE_STANDARD_AS_RULE := true
-
- L_TARGET = lib.a
-
---- linux-2.4.25/arch/i386/math-emu/Makefile~2.4.25-vrs2.patch 2000-12-29 23:07:20.000000000 +0100
-+++ linux-2.4.25/arch/i386/math-emu/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -2,15 +2,15 @@
- # Makefile for wm-FPU-emu
- #
-
-+USE_STANDARD_AS_RULE := true
-+
- O_TARGET := math.o
-
- #DEBUG = -DDEBUGGING
- DEBUG =
- PARANOID = -DPARANOID
- CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
--
--.S.o:
-- $(CC) $(AFLAGS) $(PARANOID) -c $<
-+EXTRA_AFLAGS := $(PARANOID)
-
- # From 'C' language sources:
- C_OBJS =fpu_entry.o errors.o \
---- linux-2.4.25/arch/ia64/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/ia64/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -25,6 +25,7 @@
- define_bool CONFIG_SBUS n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- choice 'IA-64 processor type' \
- "Itanium CONFIG_ITANIUM \
---- linux-2.4.25/arch/m68k/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/m68k/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -6,6 +6,7 @@
- define_bool CONFIG_UID16 y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Linux/68k Kernel Configuration"
-
---- linux-2.4.25/arch/mips/config.in~2.4.25-vrs2.patch 2002-11-29 00:53:09.000000000 +0100
-+++ linux-2.4.25/arch/mips/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -5,5 +5,6 @@
- define_bool CONFIG_MIPS y
- define_bool CONFIG_MIPS32 y
- define_bool CONFIG_MIPS64 n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- source arch/mips/config-shared.in
---- linux-2.4.25/arch/parisc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/parisc/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -9,6 +9,7 @@
- define_bool CONFIG_UID16 n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.25/arch/ppc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/ppc/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -6,6 +6,7 @@
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
- define_bool CONFIG_HAVE_DEC_LOCK y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Linux/PowerPC Kernel Configuration"
-
---- linux-2.4.25/arch/sh/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/sh/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -9,6 +9,7 @@
- define_bool CONFIG_UID16 y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.25/arch/sparc/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.25/arch/sparc/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -6,6 +6,7 @@
-
- define_bool CONFIG_UID16 y
- define_bool CONFIG_HIGHMEM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.25/arch/sparc64/config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/arch/sparc64/config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -41,6 +41,7 @@
- define_bool CONFIG_HAVE_DEC_LOCK y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
- define_bool CONFIG_ISA n
- define_bool CONFIG_ISAPNP n
- define_bool CONFIG_EISA n
---- linux-2.4.25/drivers/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:19.000000000 +0100
-+++ linux-2.4.25/drivers/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -8,9 +8,9 @@
-
- mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \
- message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
-- fc4 net/hamradio i2c acpi bluetooth usb/gadget
-+ fc4 net/hamradio i2c l3 acpi bluetooth serial usb/gadget
-
--subdir-y := parport char block net sound misc media cdrom hotplug
-+subdir-y := parport serial char block net sound misc media cdrom hotplug pld
- subdir-m := $(subdir-y)
-
-
-@@ -45,8 +45,12 @@
- # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
- subdir-$(CONFIG_HAMRADIO) += net/hamradio
- subdir-$(CONFIG_I2C) += i2c
-+subdir-$(CONFIG_L3) += l3
- subdir-$(CONFIG_ACPI_BOOT) += acpi
-
- subdir-$(CONFIG_BLUEZ) += bluetooth
-+subdir-$(CONFIG_SSI) += ssi
-+
-+subdir-$(CONFIG_ARCH_AT91RM9200)+= at91
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.25/drivers/acorn/char/i2c.c~2.4.25-vrs2.patch 2004-01-05 14:53:56.000000000 +0100
-+++ linux-2.4.25/drivers/acorn/char/i2c.c 2004-03-31 17:15:09.000000000 +0200
-@@ -166,7 +166,6 @@
- break;
-
- case RTC_RD_TIME:
-- memset(&rtctm, 0, sizeof(struct rtc_time));
- get_rtc_time(&rtc_raw, &year);
- rtctm.tm_sec = rtc_raw.secs;
- rtctm.tm_min = rtc_raw.mins;
---- linux-2.4.25/drivers/acorn/net/ether1.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/net/ether1.c 2004-03-31 17:15:09.000000000 +0200
-@@ -80,7 +80,7 @@
- #define BUS_16 16
- #define BUS_8 8
-
--static const card_ids __init ether1_cids[] = {
-+static card_ids __initdata ether1_cids[] = {
- { MANU_ACORN, PROD_ACORN_ETHER1 },
- { 0xffff, 0xffff }
- };
---- linux-2.4.25/drivers/acorn/net/ether3.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/net/ether3.c 2004-03-31 17:15:09.000000000 +0200
-@@ -75,7 +75,7 @@
- #include "ether3.h"
-
- static unsigned int net_debug = NET_DEBUG;
--static const card_ids __init ether3_cids[] = {
-+static card_ids __initdata ether3_cids[] = {
- { MANU_ANT2, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHERB },
---- linux-2.4.25/drivers/acorn/net/etherh.c~2.4.25-vrs2.patch 2003-08-25 13:44:40.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/net/etherh.c 2004-03-31 17:15:09.000000000 +0200
-@@ -57,7 +57,7 @@
-
- static unsigned int net_debug = NET_DEBUG;
-
--static const card_ids __init etherh_cids[] = {
-+static card_ids __initdata etherh_cids[] = {
- { MANU_ANT, PROD_ANT_ETHERM },
- { MANU_I3, PROD_I3_ETHERLAN500 },
- { MANU_I3, PROD_I3_ETHERLAN600 },
---- linux-2.4.25/drivers/acorn/scsi/cumana_1.c~2.4.25-vrs2.patch 2001-09-14 00:21:32.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/scsi/cumana_1.c 2004-03-31 17:15:09.000000000 +0200
-@@ -153,20 +153,20 @@
- ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
- outb(0x00, instance->io_port - 577);
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq == IRQ_NONE) {
-+ if (instance->irq == SCSI_IRQ_NONE) {
- printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
- printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
- }
-
- printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -185,7 +185,7 @@
- {
- int i;
-
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- linux-2.4.25/drivers/acorn/scsi/ecoscsi.c~2.4.25-vrs2.patch 2002-08-03 02:39:43.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/scsi/ecoscsi.c 2004-03-31 17:15:09.000000000 +0200
-@@ -106,7 +106,7 @@
- instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
- instance->io_port = 0x80ce8000;
- instance->n_io_port = 144;
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
-
- if (check_region (instance->io_port, instance->n_io_port)) {
- scsi_unregister (instance);
-@@ -130,20 +130,20 @@
- return 0;
- }
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq != IRQ_NONE) {
-+ if (instance->irq != SCSI_IRQ_NONE) {
- printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
- printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
- }
-
- printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -157,7 +157,7 @@
-
- int ecoscsi_release (struct Scsi_Host *shpnt)
- {
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- linux-2.4.25/drivers/acorn/scsi/oak.c~2.4.25-vrs2.patch 2001-10-11 18:04:57.000000000 +0200
-+++ linux-2.4.25/drivers/acorn/scsi/oak.c 2004-03-31 17:15:09.000000000 +0200
-@@ -97,7 +97,7 @@
- };
-
- #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
--#define OAK_IRQ(card) (IRQ_NONE)
-+#define OAK_IRQ(card) (SCSI_IRQ_NONE)
- /*
- * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
- *
-@@ -136,20 +136,20 @@
- instance->n_io_port = 255;
- request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq != IRQ_NONE) {
-+ if (instance->irq != SCSI_IRQ_NONE) {
- printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
- printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
- }
-
- printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -172,7 +172,7 @@
- {
- int i;
-
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,23 @@
-+#
-+# Makefile for the AT91RM9200-specific Linux kernel device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (not a .c file).
-+
-+O_TARGET := at91drv.o
-+
-+subdir-y := serial net watchdog rtc usb i2c spi mtd
-+subdir-m := $(subdir-y)
-+
-+obj-$(CONFIG_SERIAL_AT91) += serial/at91serial.o
-+obj-$(CONFIG_AT91_ETHER) += net/at91net.o
-+obj-$(CONFIG_AT91_WATCHDOG) += watchdog/at91wdt.o
-+obj-$(CONFIG_AT91_RTC) += rtc/at91rtc.o
-+obj-$(CONFIG_USB) += usb/at91usb.o
-+obj-$(CONFIG_I2C_AT91) += i2c/at91i2c.o
-+obj-$(CONFIG_AT91_SPIDEV) += spi/at91spi.o
-+obj-$(CONFIG_MTD_AT91_DATAFLASH) += spi/at91spi.o mtd/at91mtd.o
-+obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += mtd/at91mtd.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/i2c/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/i2c/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 I2C (TWI) device drivers
-+#
-+
-+O_TARGET := at91i2c.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_I2C_AT91) += at91_i2c.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/i2c/at91_i2c.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,257 @@
-+/*
-+ i2c Support for Atmel's AT91RM9200 Two-Wire Interface
-+
-+ (c) Rick Bronson
-+
-+ Borrowed heavily from original work by:
-+ Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/types.h>
-+#include <linux/delay.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+
-+#include <asm/arch/AT91RM9200_TWI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_i2c.h"
-+
-+#define DBG(x...) do {\
-+ if (debug > 0) \
-+ printk(KERN_DEBUG "i2c:" x); \
-+ } while(0)
-+
-+int debug = 0;
-+
-+static struct at91_i2c_local *at91_i2c_device;
-+
-+/*
-+ * Poll the i2c status register until the specified bit is set.
-+ * Returns 0 if timed out (100 msec)
-+ */
-+static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) {
-+ int loop_cntr = 10000;
-+ do {
-+ udelay(10);
-+ } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0));
-+
-+ return (loop_cntr > 0);
-+}
-+
-+/*
-+ * Generic i2c master transfer entrypoint
-+ */
-+static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
-+{
-+ struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data;
-+ AT91PS_TWI twi = (AT91PS_TWI) device->base_addr;
-+
-+ struct i2c_msg *pmsg;
-+ int length;
-+ unsigned char *buf;
-+
-+ /*
-+ * i2c_smbus_xfer_emulated() in drivers/i2c/i2c-core.c states:
-+ * "... In the case of writing, we need to use only one message;
-+ * when reading, we need two..."
-+ */
-+
-+ pmsg = msgs; /* look at 1st message, it contains the address/command */
-+ if (num >= 1 && num <= 2) {
-+ DBG("xfer: doing %s %d bytes to 0x%02x - %d messages\n",
-+ pmsg->flags & I2C_M_RD ? "read" : "write",
-+ pmsg->len, pmsg->buf[0], num);
-+
-+ /* Set the TWI Master Mode Register */
-+ twi->TWI_MMR = (pmsg->addr << 16) | (pmsg->len << 8)
-+ | ((pmsg + 1)->flags & I2C_M_RD ? AT91C_TWI_MREAD : 0);
-+
-+ /* Set TWI Internal Address Register with first messages data field */
-+ if (pmsg->len == 1)
-+ twi->TWI_IADR = pmsg->buf[0];
-+ else if (pmsg->len == 2)
-+ twi->TWI_IADR = pmsg->buf[0] << 8 | pmsg->buf[1];
-+ else /* must be 3 */
-+ twi->TWI_IADR = pmsg->buf[0] << 16 | pmsg->buf[1] << 8 | pmsg->buf[2];
-+
-+ /* 1st message contains the address/command */
-+ if (num > 1)
-+ pmsg++; /* go to real message */
-+
-+ length = pmsg->len;
-+ buf = pmsg->buf;
-+ if (length && buf) { /* sanity check */
-+ if (pmsg->flags & I2C_M_RD) {
-+ twi->TWI_CR = AT91C_TWI_START;
-+ while (length--) {
-+ if (!length)
-+ twi->TWI_CR = AT91C_TWI_STOP;
-+ /* Wait until transfer is finished */
-+ if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) {
-+ printk(KERN_ERR "at91_i2c: timeout 1\n");
-+ return 0;
-+ }
-+ *buf++ = twi->TWI_RHR;
-+ }
-+ if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
-+ printk(KERN_ERR "at91_i2c: timeout 2\n");
-+ return 0;
-+ }
-+ } else {
-+ twi->TWI_CR = AT91C_TWI_START;
-+ while (length--) {
-+ twi->TWI_THR = *buf++;
-+ if (!length)
-+ twi->TWI_CR = AT91C_TWI_STOP;
-+ if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) {
-+ printk(KERN_ERR "at91_i2c: timeout 3\n");
-+ return 0;
-+ }
-+ }
-+ /* Wait until transfer is finished */
-+ if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
-+ printk(KERN_ERR "at91_i2c: timeout 4\n");
-+ return 0;
-+ }
-+ }
-+ }
-+ DBG("transfer complete\n");
-+ return num;
-+ }
-+ else {
-+ printk(KERN_ERR "at91_i2c: unexpected number of messages: %d\n", num);
-+ return 0;
-+ }
-+}
-+
-+/*
-+ * Return list of supported functionality
-+ */
-+static u32 at91_func(struct i2c_adapter *adapter)
-+{
-+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
-+ | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
-+ | I2C_FUNC_SMBUS_BLOCK_DATA;
-+}
-+
-+/*
-+ * Open
-+ */
-+static void at91_inc(struct i2c_adapter *adapter)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+/*
-+ * Close
-+ */
-+static void at91_dec(struct i2c_adapter *adapter)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+/* For now, we only handle combined mode (smbus) */
-+static struct i2c_algorithm at91_algorithm = {
-+ name:"at91 i2c",
-+ id:I2C_ALGO_SMBUS,
-+ master_xfer:at91_xfer,
-+ functionality:at91_func,
-+};
-+
-+/*
-+ * Main initialization routine
-+ */
-+static int __init i2c_at91_init(void)
-+{
-+ AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI;
-+ struct at91_i2c_local *device;
-+ int rc;
-+
-+ AT91_CfgPIO_TWI();
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */
-+
-+ twi->TWI_IDR = 0x3ff; /* Disable all interrupts */
-+ twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */
-+ twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */
-+
-+ /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */
-+ twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8);
-+
-+ device = (struct at91_i2c_local *) kmalloc(sizeof(struct at91_i2c_local), GFP_KERNEL);
-+ if (device == NULL) {
-+ printk(KERN_ERR "at91_i2c: can't allocate inteface!\n");
-+ return -ENOMEM;
-+ }
-+ memset(device, 0, sizeof(struct at91_i2c_local));
-+ at91_i2c_device = device;
-+
-+ sprintf(device->adapter.name, "AT91RM9200");
-+ device->adapter.data = (void *) device;
-+ device->adapter.id = I2C_ALGO_SMBUS;
-+ device->adapter.algo = &at91_algorithm;
-+ device->adapter.algo_data = NULL;
-+ device->adapter.inc_use = at91_inc;
-+ device->adapter.dec_use = at91_dec;
-+ device->adapter.client_register = NULL;
-+ device->adapter.client_unregister = NULL;
-+ device->base_addr = AT91C_VA_BASE_TWI;
-+
-+ rc = i2c_add_adapter(&device->adapter);
-+ if (rc) {
-+ printk(KERN_ERR "at91_i2c: Adapter %s registration failed\n", device->adapter.name);
-+ device->adapter.data = NULL;
-+ kfree(device);
-+ }
-+ else
-+ printk(KERN_INFO "Found AT91 i2c\n");
-+ return rc;
-+}
-+
-+/*
-+ * Clean up routine
-+ */
-+static void __exit i2c_at91_cleanup(void)
-+{
-+ struct at91_i2c_local *device = at91_i2c_device;
-+ int rc;
-+
-+ rc = i2c_del_adapter(&device->adapter);
-+ device->adapter.data = NULL;
-+ kfree(device);
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */
-+
-+ /* We aren't that prepared to deal with this... */
-+ if (rc)
-+ printk(KERN_ERR "at91_i2c: i2c_del_adapter failed (%i), that's bad!\n", rc);
-+}
-+
-+module_init(i2c_at91_init);
-+module_exit(i2c_at91_cleanup);
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("I2C driver for Atmel AT91RM9200");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(debug, "i");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/i2c/at91_i2c.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,43 @@
-+/*
-+ i2c Support for Atmel's AT91RM9200 Two-Wire Interface
-+
-+ (c) Rick Bronson
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+*/
-+
-+#ifndef AT91_I2C_H
-+#define AT91_I2C_H
-+
-+#define AT91C_TWI_CLOCK 100000
-+#define AT91C_TWI_SCLOCK (10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK)
-+#define AT91C_TWI_CKDIV1 (2 << 16) /* TWI clock divider. NOTE: see Errata #22 */
-+
-+#if (AT91C_TWI_SCLOCK % 10) >= 5
-+#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5)
-+#else
-+#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6)
-+#endif
-+#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2)
-+
-+#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16)
-+
-+/* Physical interface */
-+struct at91_i2c_local {
-+ struct i2c_adapter adapter;
-+ unsigned long base_addr;
-+};
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/mtd/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,19 @@
-+# File: drivers/at91/mtd/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 MTD devices.
-+# Includes: NAND flash (SmartMedia) & DataFlash
-+#
-+
-+O_TARGET := at91mtd.o
-+
-+export-objs :=
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_MTD_AT91_DATAFLASH) += at91_dataflash.o
-+obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += at91_nand.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/mtd/at91_dataflash.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,495 @@
-+/*
-+ * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/slab.h>
-+#include <linux/pci.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/arch/AT91RM9200_SPI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_dataflash.h"
-+#include "../spi/at91_spi.h"
-+
-+#undef DEBUG_DATAFLASH
-+
-+/* Detected DataFlash devices */
-+static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES];
-+static int nr_devices = 0;
-+
-+/* ......................................................................... */
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+
-+static struct mtd_partition *mtd_parts = 0;
-+static int mtd_parts_nr = 0;
-+
-+#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-+
-+static struct mtd_partition static_partitions[] =
-+{
-+ {
-+ name: "bootloader",
-+ offset: 0,
-+ size: 64 * 1024, /* 64 Kb */
-+ mask_flags: MTD_WRITEABLE /* read-only */
-+ },
-+ {
-+ name: "kernel",
-+ offset: MTDPART_OFS_NXTBLK,
-+ size: 768 *1024, /* 768 Kb */
-+ },
-+ {
-+ name: "filesystem",
-+ offset: MTDPART_OFS_NXTBLK,
-+ size: MTDPART_SIZ_FULL,
-+ }
-+};
-+
-+int parse_cmdline_partitions(struct mtd_info *master,
-+ struct mtd_partition **pparts, const char *mtd_id);
-+
-+#endif
-+
-+/* ......................................................................... */
-+
-+/* Allocate a single SPI transfer descriptor. We're assuming that if multiple
-+ SPI transfers occur at the same time, spi_access_bus() will serialize them.
-+ If this is not valid, then either (i) each dataflash 'priv' structure
-+ needs it's own transfer descriptor, (ii) we lock this one, or (iii) use
-+ another mechanism. */
-+struct spi_transfer_list* spi_transfer_desc;
-+
-+/*
-+ * Perform a SPI transfer to access the DataFlash device.
-+ */
-+int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len,
-+ char* txnext, int txnext_len, char* rxnext, int rxnext_len)
-+{
-+ struct spi_transfer_list* list = spi_transfer_desc;
-+
-+ list->tx[0] = tx; list->txlen[0] = tx_len;
-+ list->rx[0] = rx; list->rxlen[0] = rx_len;
-+
-+ list->tx[1] = txnext; list->txlen[1] = txnext_len;
-+ list->rx[1] = rxnext; list->rxlen[1] = rxnext_len;
-+
-+ list->nr_transfers = nr;
-+
-+ return spi_transfer(list);
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Poll the DataFlash device until it is READY.
-+ */
-+void at91_dataflash_waitready(void)
-+{
-+ char* command = kmalloc(2, GFP_KERNEL);
-+
-+ if (!command)
-+ return;
-+
-+ do {
-+ command[0] = OP_READ_STATUS;
-+ command[1] = 0;
-+
-+ do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
-+ } while ((command[1] & 0x80) == 0);
-+
-+ kfree(command);
-+}
-+
-+/*
-+ * Return the status of the DataFlash device.
-+ */
-+unsigned short at91_dataflash_status(void)
-+{
-+ unsigned short status;
-+ char* command = kmalloc(2, GFP_KERNEL);
-+
-+ if (!command)
-+ return 0;
-+
-+ command[0] = OP_READ_STATUS;
-+ command[1] = 0;
-+
-+ do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
-+ status = command[1];
-+
-+ kfree(command);
-+ return status;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Erase a block of flash.
-+ */
-+int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int pageaddr;
-+ char* command;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len);
-+#endif
-+
-+ /* Sanity checks */
-+ if (instr->addr + instr->len > mtd->size)
-+ return -EINVAL;
-+ if ((instr->len != mtd->erasesize) || (instr->len != priv->page_size))
-+ return -EINVAL;
-+ if ((instr->addr % priv->page_size) != 0)
-+ return -EINVAL;
-+
-+ command = kmalloc(4, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ /* Calculate flash page address */
-+ pageaddr = (instr->addr / priv->page_size) << priv->page_offset;
-+
-+ command[0] = OP_ERASE_PAGE;
-+ command[1] = (pageaddr & 0x00FF0000) >> 16;
-+ command[2] = (pageaddr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr);
-+#endif
-+
-+ /* Send command to SPI device */
-+ spi_access_bus(priv->spi);
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+
-+ at91_dataflash_waitready(); /* poll status until ready */
-+ spi_release_bus(priv->spi);
-+
-+ kfree(command);
-+
-+ /* Inform MTD subsystem that erase is complete */
-+ instr->state = MTD_ERASE_DONE;
-+ if (instr->callback)
-+ instr->callback(instr);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Read from the DataFlash device.
-+ * from : Start offset in flash device
-+ * len : Amount to read
-+ * retlen : About of data actually read
-+ * buf : Buffer containing the data
-+ */
-+int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int addr;
-+ char* command;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_read: %lli .. %lli\n", from, from+len);
-+#endif
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len)
-+ return 0;
-+ if (from + len > mtd->size)
-+ return -EINVAL;
-+
-+ /* Calculate flash page/byte address */
-+ addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size);
-+
-+ command = kmalloc(8, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ command[0] = OP_READ_CONTINUOUS;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = (addr & 0x000000FF);
-+#ifdef DEBUG_DATAFLASH
-+ printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+
-+ /* Send command to SPI device */
-+ spi_access_bus(priv->spi);
-+ do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len);
-+ spi_release_bus(priv->spi);
-+
-+ *retlen = len;
-+ kfree(command);
-+ return 0;
-+}
-+
-+/*
-+ * Write to the DataFlash device.
-+ * to : Start offset in flash device
-+ * len : Amount to write
-+ * retlen : Amount of data actually written
-+ * buf : Buffer containing the data
-+ */
-+int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int pageaddr, addr, offset, writelen;
-+ size_t remaining;
-+ char *writebuf;
-+ unsigned short status;
-+ int res = 0;
-+ char* command;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_write: %lli .. %lli\n", to, to+len);
-+#endif
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len)
-+ return 0;
-+ if (to + len > mtd->size)
-+ return -EINVAL;
-+
-+ command = kmalloc(4, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ pageaddr = ((unsigned)to / priv->page_size);
-+ offset = ((unsigned)to % priv->page_size);
-+ if (offset + len > priv->page_size)
-+ writelen = priv->page_size - offset;
-+ else
-+ writelen = len;
-+ writebuf = buf;
-+ remaining = len;
-+
-+ /* Gain access to the SPI bus */
-+ spi_access_bus(priv->spi);
-+
-+ while (remaining > 0) {
-+#ifdef DEBUG_DATAFLASH
-+ printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen);
-+#endif
-+
-+ /* (1) Transfer to Buffer1 */
-+ if (writelen != priv->page_size) {
-+ addr = pageaddr << priv->page_offset;
-+ command[0] = OP_TRANSFER_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+ at91_dataflash_waitready();
-+ }
-+
-+ /* (2) Program via Buffer1 */
-+ addr = (pageaddr << priv->page_offset) + offset;
-+ command[0] = OP_PROGRAM_VIA_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = (addr & 0x000000FF);
-+#ifdef DEBUG_DATAFLASH
-+ printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, writebuf, writelen);
-+ at91_dataflash_waitready();
-+
-+ /* (3) Compare to Buffer1 */
-+ addr = pageaddr << priv->page_offset;
-+ command[0] = OP_COMPARE_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+ at91_dataflash_waitready();
-+
-+ /* Get result of the compare operation */
-+ status = at91_dataflash_status();
-+ if ((status & 0x40) == 1) {
-+ printk("at91_dataflash: Write error on page %i\n", pageaddr);
-+ remaining = 0;
-+ res = -EIO;
-+ }
-+
-+ remaining = remaining - writelen;
-+ pageaddr++;
-+ offset = 0;
-+ writebuf += writelen;
-+ *retlen += writelen;
-+
-+ if (remaining > priv->page_size)
-+ writelen = priv->page_size;
-+ else
-+ writelen = remaining;
-+ }
-+
-+ /* Release SPI bus */
-+ spi_release_bus(priv->spi);
-+
-+ kfree(command);
-+ return res;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Initialize and register DataFlash device with MTD subsystem.
-+ */
-+int add_dataflash(int channel, char *name, int size, int pagesize, int pageoffset)
-+{
-+ struct mtd_info *device;
-+ struct dataflash_local *priv;
-+#ifdef CONFIG_MTD_CMDLINE_PARTS
-+ char mtdID[14];
-+#endif
-+
-+ if (nr_devices >= DATAFLASH_MAX_DEVICES) {
-+ printk(KERN_ERR "at91_dataflash: Too many devices detected\n");
-+ return 0;
-+ }
-+
-+ device = (struct mtd_info *) kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+ if (!device)
-+ return -ENOMEM;
-+ memset(device, 0, sizeof(struct mtd_info));
-+
-+ device->name = name;
-+ device->size = size;
-+ device->erasesize = pagesize;
-+ device->module = THIS_MODULE;
-+ device->type = MTD_NORFLASH;
-+ device->flags = MTD_CAP_NORFLASH;
-+ device->erase = at91_dataflash_erase;
-+ device->read = at91_dataflash_read;
-+ device->write = at91_dataflash_write;
-+
-+ priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL);
-+ if (!priv) {
-+ kfree(device);
-+ return -ENOMEM;
-+ }
-+ memset(priv, 0, sizeof(struct dataflash_local));
-+
-+ priv->spi = channel;
-+ priv->page_size = pagesize;
-+ priv->page_offset = pageoffset;
-+ device->priv = priv;
-+
-+ mtd_devices[nr_devices] = device;
-+ nr_devices++;
-+ printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, size);
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+#ifdef CONFIG_MTD_CMDLINE_PARTS
-+ sprintf(mtdID, "dataflash%i", nr_devices-1);
-+ mtd_parts_nr = parse_cmdline_partitions(device, &mtd_parts, mtdID);
-+#endif
-+ if (mtd_parts_nr <= 0) {
-+ mtd_parts = static_partitions;
-+ mtd_parts_nr = NB_OF(static_partitions);
-+ }
-+
-+ return add_mtd_partitions(device, mtd_parts, mtd_parts_nr);
-+#else
-+ return add_mtd_device(device);
-+#endif
-+}
-+
-+/*
-+ * Detect and initialize DataFlash device connected to specified SPI channel.
-+ */
-+int at91_dataflash_detect(int channel)
-+{
-+ int res = 0;
-+ unsigned short status;
-+
-+ spi_access_bus(channel);
-+ status = at91_dataflash_status();
-+ if (status != 0xff) { /* no dataflash device there */
-+ switch (status & 0x3c) {
-+ case 0x2c: /* 1 0 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB161B", 4096*528, 528, 10);
-+ break;
-+ case 0x34: /* 1 1 0 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB321B", 8192*528, 528, 10);
-+ break;
-+ case 0x3c: /* 1 1 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB642", 8192*1056, 1056, 11);
-+ break;
-+ default:
-+ printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c);
-+ }
-+ }
-+ spi_release_bus(channel);
-+
-+ return res;
-+}
-+
-+int __init at91_dataflash_init(void)
-+{
-+ spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
-+ if (!spi_transfer_desc)
-+ return -ENOMEM;
-+
-+ /* DataFlash (SPI chip select 0) */
-+ at91_dataflash_detect(0);
-+
-+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-+ /* DataFlash card (SPI chip select 3) */
-+ AT91_CfgPIO_DataFlashCard();
-+ at91_dataflash_detect(3);
-+#endif
-+
-+ return 0;
-+}
-+
-+void __exit at91_dataflash_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) {
-+ if (mtd_devices[i]) {
-+#ifdef CONFIG_MTD_PARTITIONS
-+ del_mtd_partitions(mtd_devices[i]);
-+#else
-+ del_mtd_device(mtd_devices[i]);
-+#endif
-+ kfree(mtd_devices[i]->priv);
-+ kfree(mtd_devices[i]);
-+ }
-+ }
-+ nr_devices = 0;
-+ kfree(spi_transfer_desc);
-+}
-+
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(at91_dataflash_init);
-+module_exit(at91_dataflash_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200")
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/mtd/at91_dataflash.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,42 @@
-+/*
-+ * Atmel DataFlash driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_DATAFLASH_H
-+#define AT91_DATAFLASH_H
-+
-+#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */
-+
-+#define OP_READ_CONTINUOUS 0xE8
-+#define OP_READ_PAGE 0xD2
-+#define OP_READ_BUFFER1 0xD4
-+#define OP_READ_BUFFER2 0xD6
-+#define OP_READ_STATUS 0xD7
-+
-+#define OP_ERASE_PAGE 0x81
-+#define OP_ERASE_BLOCK 0x50
-+
-+#define OP_TRANSFER_BUF1 0x53
-+#define OP_TRANSFER_BUF2 0x55
-+#define OP_COMPARE_BUF1 0x60
-+#define OP_COMPARE_BUF2 0x61
-+
-+#define OP_PROGRAM_VIA_BUF1 0x82
-+#define OP_PROGRAM_VIA_BUF2 0x85
-+
-+struct dataflash_local
-+{
-+ int spi; /* SPI chip-select number */
-+
-+ unsigned int page_size; /* number of bytes per page */
-+ unsigned short page_offset; /* page offset in flash address */
-+};
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/mtd/at91_nand.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,328 @@
-+/*
-+ * drivers/at91/mtd/at91_nand.c
-+ *
-+ * Copyright (c) 2003 Rick Bronson
-+ *
-+ * Derived from drivers/mtd/nand/autcpu12.c
-+ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
-+ *
-+ * Derived from drivers/mtd/spia.c
-+ * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/io.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/sizes.h>
-+
-+#include <asm/arch/pio.h>
-+#include "at91_nand.h"
-+
-+/*
-+ * MTD structure for AT91 board
-+ */
-+static struct mtd_info *at91_mtd = NULL;
-+static struct nand_chip *my_nand_chip = NULL;
-+
-+static int at91_fio_base;
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+
-+/*
-+ * Define partitions for flash devices
-+ */
-+
-+static struct mtd_partition partition_info32k[] = {
-+ { name: "AT91 NAND partition 1, kernel",
-+ offset: 0,
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 2, filesystem",
-+ offset: 1 * SZ_1M,
-+ size: 16 * SZ_1M },
-+ { name: "AT91 NAND partition 3a, storage",
-+ offset: (1 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3b, storage",
-+ offset: (2 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3c, storage",
-+ offset: (3 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3d, storage",
-+ offset: (4 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+};
-+
-+static struct mtd_partition partition_info64k[] = {
-+ { name: "AT91 NAND partition 1, kernel",
-+ offset: 0,
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 2, filesystem",
-+ offset: 1 * SZ_1M,
-+ size: 16 * SZ_1M },
-+ { name: "AT91 NAND partition 3, storage",
-+ offset: (1 * SZ_1M) + (16 * SZ_1M),
-+ size: 47 * SZ_1M },
-+};
-+
-+#endif
-+
-+/*
-+ * Hardware specific access to control-lines
-+ */
-+static void at91_hwcontrol(int cmd)
-+{
-+ struct nand_chip *my_nand = my_nand_chip;
-+ switch(cmd)
-+ {
-+ case NAND_CTL_SETCLE:
-+ my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_CLE;
-+ break;
-+ case NAND_CTL_CLRCLE:
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ break;
-+ case NAND_CTL_SETALE:
-+ my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_ALE;
-+ break;
-+ case NAND_CTL_CLRALE:
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ break;
-+ case NAND_CTL_SETNCE:
-+ break;
-+ case NAND_CTL_CLRNCE:
-+ break;
-+ }
-+}
-+
-+/*
-+ * Send command to NAND device
-+ */
-+static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
-+{
-+ register struct nand_chip *my_nand = mtd->priv;
-+
-+ /* Begin command latch cycle */
-+ register unsigned long NAND_IO_ADDR = my_nand->IO_ADDR_W + AT91_SMART_MEDIA_CLE;
-+
-+ /*
-+ * Write out the command to the device.
-+ */
-+ if (command != NAND_CMD_SEQIN)
-+ writeb (command, NAND_IO_ADDR);
-+ else {
-+ if (mtd->oobblock == 256 && column >= 256) {
-+ column -= 256;
-+ writeb (NAND_CMD_RESET, NAND_IO_ADDR);
-+ writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ else
-+ if (mtd->oobblock == 512 && column >= 256) {
-+ if (column < 512) {
-+ column -= 256;
-+ writeb (NAND_CMD_READ1, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ } else {
-+ column -= 512;
-+ writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ } else {
-+ writeb (NAND_CMD_READ0, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ }
-+
-+ /* Set ALE and clear CLE to start address cycle */
-+ NAND_IO_ADDR = at91_fio_base;
-+
-+ if (column != -1 || page_addr != -1)
-+ NAND_IO_ADDR += AT91_SMART_MEDIA_ALE;
-+
-+ /* Serially input address */
-+ if (column != -1)
-+ writeb (column, NAND_IO_ADDR);
-+ if (page_addr != -1) {
-+ writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR);
-+ writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR);
-+ /* One more address cycle for higher density devices */
-+ if (mtd->size & 0x0c000000) {
-+ writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR);
-+ }
-+ }
-+
-+ /* wait until command is processed */
-+ while (!my_nand->dev_ready())
-+ ;
-+}
-+
-+/*
-+ * Read the Device Ready pin.
-+ */
-+static int at91_device_ready(void)
-+{
-+ return AT91_PIO_SmartMedia_RDY();
-+}
-+/*
-+ * Main initialization routine
-+ */
-+static int __init at91_init (void)
-+{
-+ struct nand_chip *my_nand;
-+ int err = 0;
-+
-+ /* Allocate memory for MTD device structure and private data */
-+ at91_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
-+ if (!at91_mtd) {
-+ printk ("Unable to allocate AT91 NAND MTD device structure.\n");
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ /* map physical adress */
-+ at91_fio_base = (unsigned long) ioremap(AT91_SMARTMEDIA_BASE, SZ_8M);
-+ if(!at91_fio_base) {
-+ printk("ioremap AT91 NAND failed\n");
-+ err = -EIO;
-+ goto out_mtd;
-+ }
-+
-+ /* Get pointer to private data */
-+ my_nand_chip = my_nand = (struct nand_chip *) (&at91_mtd[1]);
-+
-+ /* Initialize structures */
-+ memset((char *) at91_mtd, 0, sizeof(struct mtd_info));
-+ memset((char *) my_nand, 0, sizeof(struct nand_chip));
-+
-+ /* Link the private data with the MTD structure */
-+ at91_mtd->priv = my_nand;
-+
-+ /* Set address of NAND IO lines */
-+ my_nand->IO_ADDR_R = at91_fio_base;
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ my_nand->hwcontrol = at91_hwcontrol;
-+ my_nand->dev_ready = at91_device_ready;
-+ my_nand->cmdfunc = at91_nand_command; /* we need our own */
-+ my_nand->eccmode = NAND_ECC_SOFT; /* enable ECC */
-+ /* 20 us command delay time */
-+ my_nand->chip_delay = 20;
-+
-+ /* Setup Smart Media, first enable the address range of CS3 */
-+ AT91_SYS->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;
-+ /* set the bus interface characteristics based on
-+ tDS Data Set up Time 30 - ns
-+ tDH Data Hold Time 20 - ns
-+ tALS ALE Set up Time 20 - ns
-+ 16ns at 60 MHz ~= 3 */
-+#define AT91C_SM_ID_RWH (5 << 28) /* orig = 5 */
-+#define AT91C_SM_RWH (1 << 28) /* orig = 1 */
-+#define AT91C_SM_RWS (0 << 24) /* orig = 0 */
-+#define AT91C_SM_TDF (1 << 8) /* orig = 1 */
-+#define AT91C_SM_NWS (5) /* orig = 3 */
-+ AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS |
-+ AT91C_SMC2_ACSS_STANDARD |
-+ AT91C_SMC2_DBW_8 | AT91C_SM_TDF |
-+ AT91C_SMC2_WSEN | AT91C_SM_NWS);
-+
-+ AT91_CfgPIO_SmartMedia();
-+
-+ if (AT91_PIO_SmartMedia_CardDetect())
-+ printk ("No ");
-+ printk ("SmartMedia card inserted.\n");
-+
-+ /* Scan to find existance of the device */
-+ if (nand_scan (at91_mtd)) {
-+ err = -ENXIO;
-+ goto out_ior;
-+ }
-+
-+ /* Allocate memory for internal data buffer */
-+ my_nand->data_buf = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
-+ if (!my_nand->data_buf) {
-+ printk ("Unable to allocate AT91 NAND data buffer.\n");
-+ err = -ENOMEM;
-+ goto out_ior;
-+ }
-+
-+ /* Allocate memory for internal data buffer */
-+ my_nand->data_cache = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
-+ if (!my_nand->data_cache) {
-+ printk ("Unable to allocate AT91 NAND data cache.\n");
-+ err = -ENOMEM;
-+ goto out_buf;
-+ }
-+ my_nand->cache_page = -1;
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+ /* Register the partitions */
-+ switch(at91_mtd->size)
-+ {
-+ case SZ_32M:
-+ err = add_mtd_partitions(at91_mtd, partition_info32k,
-+ ARRAY_SIZE (partition_info32k));
-+ break;
-+ case SZ_64M:
-+ err = add_mtd_partitions(at91_mtd, partition_info64k,
-+ ARRAY_SIZE (partition_info64k));
-+ break;
-+ default:
-+ printk ("Unsupported SmartMedia device\n");
-+ err = -ENXIO;
-+ goto out_cac;
-+ }
-+#else
-+ err = add_mtd_device(at91_mtd);
-+#endif
-+ goto out;
-+
-+ out_cac:
-+ kfree (my_nand->data_cache);
-+ out_buf:
-+ kfree (my_nand->data_buf);
-+ out_ior:
-+ iounmap((void *)at91_fio_base);
-+ out_mtd:
-+ kfree (at91_mtd);
-+ out:
-+ return err;
-+}
-+
-+/*
-+ * Clean up routine
-+ */
-+static void __exit at91_cleanup (void)
-+{
-+ struct nand_chip *my_nand = (struct nand_chip *) &at91_mtd[1];
-+
-+ /* Unregister partitions */
-+ del_mtd_partitions(at91_mtd);
-+
-+ /* Unregister the device */
-+ del_mtd_device (at91_mtd);
-+
-+ /* Free internal data buffers */
-+ kfree (my_nand->data_buf);
-+ kfree (my_nand->data_cache);
-+
-+ /* unmap physical adress */
-+ iounmap((void *)at91_fio_base);
-+
-+ /* Free the MTD device structure */
-+ kfree (at91_mtd);
-+}
-+
-+module_init(at91_init);
-+module_exit(at91_cleanup);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/mtd/at91_nand.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,27 @@
-+/*
-+ * AT91RM9200 specific NAND (SmartMedia) defines
-+ *
-+ * (c) 2003 Rick Bronson
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef __AT91_NAND_H
-+#define __AT91_NAND_H
-+
-+#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */
-+#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/net/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/net/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 ethernet device drivers
-+#
-+
-+O_TARGET := at91net.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_ETHER) += at91_ether.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/net/at91_ether.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,877 @@
-+/*
-+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
-+ * Initial version by Rick Bronson 01/11/2003
-+ *
-+ * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
-+ * (Polaroid Corporation)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/config.h>
-+#include <linux/mii.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <asm/io.h>
-+#include <linux/pci.h>
-+#include <linux/crc32.h>
-+#include <asm/uaccess.h>
-+#include <linux/ethtool.h>
-+
-+#include <asm/arch/AT91RM9200_EMAC.h>
-+#include <asm/arch/pio.h>
-+#include "at91_ether.h"
-+
-+static struct net_device at91_dev;
-+
-+/* ........................... PHY INTERFACE ........................... */
-+
-+/*
-+ * Enable the MDIO bit in MAC control register
-+ * When not called from an interrupt-handler, access to the PHY must be
-+ * protected by a spinlock.
-+ */
-+static void enable_mdi(AT91PS_EMAC regs)
-+{
-+ regs->EMAC_CTL |= AT91C_EMAC_MPE; /* enable management port */
-+}
-+
-+/*
-+ * Disable the MDIO bit in the MAC control register
-+ */
-+static void disable_mdi(AT91PS_EMAC regs)
-+{
-+ regs->EMAC_CTL &= ~AT91C_EMAC_MPE; /* disable management port */
-+}
-+
-+/*
-+ * Write value to the a PHY register
-+ * Note: MDI interface is assumed to already have been enabled.
-+ */
-+static void write_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int value)
-+{
-+ regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W
-+ | ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff);
-+
-+ /* Wait until IDLE bit in Network Status register is cleared */
-+ // TODO: Enforce some maximum loop-count?
-+ while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
-+}
-+
-+/*
-+ * Read value stored in a PHY register.
-+ * Note: MDI interface is assumed to already have been enabled.
-+ */
-+static void read_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int *value)
-+{
-+ regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R
-+ | ((phy_addr & 0x1f) << 23) | (address << 18);
-+
-+ /* Wait until IDLE bit in Network Status register is cleared */
-+ // TODO: Enforce some maximum loop-count?
-+ while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
-+
-+ *value = (regs->EMAC_MAN & 0x0000ffff);
-+}
-+
-+/* ........................... PHY MANAGEMENT .......................... */
-+
-+/*
-+ * Access the PHY to determine the current Link speed and Mode, and update the
-+ * MAC accordingly.
-+ * If no link or auto-negotiation is busy, then no changes are made.
-+ * Returns: 0 : OK
-+ * -1 : No link
-+ * -2 : AutoNegotiation still in progress
-+ */
-+static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) {
-+ unsigned int bmsr, bmcr, lpa, mac_cfg;
-+ unsigned int speed, duplex;
-+
-+ /* Link status is latched, so read twice to get current value */
-+ read_phy(regs, 0, MII_BMSR, &bmsr);
-+ read_phy(regs, 0, MII_BMSR, &bmsr);
-+ if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */
-+
-+ read_phy(regs, 0, MII_BMCR, &bmcr);
-+ if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
-+ if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */
-+
-+ read_phy(regs, 0, MII_LPA, &lpa);
-+ if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-+ else speed = SPEED_10;
-+ if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-+ else duplex = DUPLEX_HALF;
-+ } else {
-+ speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-+ duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-+ }
-+
-+ /* Update the MAC */
-+ mac_cfg = regs->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
-+ if (speed == SPEED_100) {
-+ if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
-+ else /* 100 Half Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD;
-+ } else {
-+ if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_FD;
-+ else /* 10 Half Duplex */
-+ regs->EMAC_CFG = mac_cfg;
-+ }
-+
-+ printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-+ return 0;
-+}
-+
-+/*
-+ * Handle interrupts from the PHY
-+ */
-+static void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = (struct net_device *) dev_id;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
-+ int status;
-+ unsigned int phy;
-+
-+ enable_mdi(emac);
-+ if (lp->phy_type == MII_DM9161_ID)
-+ read_phy(emac, 0, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
-+ else if (lp->phy_type == MII_LXT971A_ID)
-+ read_phy(emac, 0, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
-+
-+ status = AT91_SYS->PIOC_ISR; /* acknowledge interrupt in PIO */
-+
-+ status = update_linkspeed(dev, emac);
-+ if (status == -1) { /* link is down */
-+ netif_carrier_off(dev);
-+ printk(KERN_INFO "%s: Link down.\n", dev->name);
-+ } else if (status == -2) { /* auto-negotiation in progress */
-+ /* Do nothing - another interrupt generated when negotiation complete */
-+ } else { /* link is operational */
-+ netif_carrier_on(dev);
-+ }
-+ disable_mdi(emac);
-+}
-+
-+/*
-+ * Initialize and enable the PHY interrupt when link-state changes
-+ */
-+static void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int dsintr, status;
-+
-+ // TODO: Check error code. Really need a generic PIO (interrupt)
-+ // layer since we're really only interested in the PC4 (DK) or PC2 (CSB337) line.
-+ (void) request_irq(AT91C_ID_PIOC, at91ether_phy_interrupt, 0, dev->name, dev);
-+
-+ status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_IER = AT91C_PIO_PC2; /* Enable interrupt */
-+#else
-+ AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */
-+#endif
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
-+ read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
-+ dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
-+ write_phy(regs, 0, MII_DSINTR_REG, dsintr);
-+ }
-+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-+ read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
-+ dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
-+ write_phy(regs, 0, MII_ISINTE_REG, dsintr);
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+}
-+
-+/*
-+ * Disable the PHY interrupt
-+ */
-+static void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int dsintr;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
-+ read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
-+ dsintr = dsintr | 0xf00; /* set bits 8..11 */
-+ write_phy(regs, 0, MII_DSINTR_REG, dsintr);
-+ }
-+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-+ read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
-+ dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
-+ write_phy(regs, 0, MII_ISINTE_REG, dsintr);
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_IDR = AT91C_PIO_PC2; /* Disable interrupt */
-+#else
-+ AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */
-+#endif
-+ free_irq(AT91C_ID_PIOC, dev); /* Free interrupt handler */
-+}
-+
-+/*
-+ * Perform a software reset of the PHY.
-+ */
-+static void reset_phy(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int bmcr;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ /* Perform PHY reset */
-+ write_phy(regs, 0, MII_BMCR, BMCR_RESET);
-+
-+ /* Wait until PHY reset is complete */
-+ do {
-+ read_phy(regs, 0, MII_BMCR, &bmcr);
-+ } while (!(bmcr && BMCR_RESET));
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+}
-+
-+
-+/* ......................... ADDRESS MANAGEMENT ........................ */
-+
-+/*
-+ * Set the ethernet MAC address in dev->dev_addr
-+ */
-+static void get_mac_address(struct net_device *dev) {
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ char addr[6];
-+ unsigned int hi, lo;
-+
-+ /* Check if bootloader set address in Specific-Address 1 */
-+ hi = regs->EMAC_SA1H;
-+ lo = regs->EMAC_SA1L;
-+ addr[0] = (lo & 0xff);
-+ addr[1] = (lo & 0xff00) >> 8;
-+ addr[2] = (lo & 0xff0000) >> 16;
-+ addr[3] = (lo & 0xff000000) >> 24;
-+ addr[4] = (hi & 0xff);
-+ addr[5] = (hi & 0xff00) >> 8;
-+
-+ if (is_valid_ether_addr(addr)) {
-+ memcpy(dev->dev_addr, &addr, 6);
-+ return;
-+ }
-+
-+ /* Check if bootloader set address in Specific-Address 2 */
-+ hi = regs->EMAC_SA2H;
-+ lo = regs->EMAC_SA2L;
-+ addr[0] = (lo & 0xff);
-+ addr[1] = (lo & 0xff00) >> 8;
-+ addr[2] = (lo & 0xff0000) >> 16;
-+ addr[3] = (lo & 0xff000000) >> 24;
-+ addr[4] = (hi & 0xff);
-+ addr[5] = (hi & 0xff00) >> 8;
-+
-+ if (is_valid_ether_addr(addr)) {
-+ memcpy(dev->dev_addr, &addr, 6);
-+ return;
-+ }
-+}
-+
-+/*
-+ * Program the hardware MAC address from dev->dev_addr.
-+ */
-+static void update_mac_address(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ regs->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]);
-+ regs->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]);
-+}
-+
-+#ifdef AT91_ETHER_ADDR_CONFIGURABLE
-+/*
-+ * Store the new hardware address in dev->dev_addr, and update the MAC.
-+ */
-+static int set_mac_address(struct net_device *dev, void* addr)
-+{
-+ struct sockaddr *address = addr;
-+
-+ if (!is_valid_ether_addr(address->sa_data))
-+ return -EADDRNOTAVAIL;
-+
-+ memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-+ update_mac_address(dev);
-+
-+ printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
-+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-+
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Add multicast addresses to the internal multicast-hash table.
-+ */
-+static void at91ether_sethashtable(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct dev_mc_list *curr;
-+ unsigned char mc_filter[2];
-+ unsigned int i, bitnr;
-+
-+ mc_filter[0] = mc_filter[1] = 0;
-+
-+ curr = dev->mc_list;
-+ for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
-+ if (!curr) break; /* unexpected end of list */
-+
-+ bitnr = ether_crc(ETH_ALEN, curr->dmi_addr) >> 26;
-+ mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-+ }
-+
-+ regs->EMAC_HSH = mc_filter[1];
-+ regs->EMAC_HSL = mc_filter[0];
-+}
-+
-+/*
-+ * Enable/Disable promiscuous and multicast modes.
-+ */
-+static void at91ether_set_rx_mode(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */
-+ regs->EMAC_CFG |= AT91C_EMAC_CAF;
-+ } else if (dev->flags & (~IFF_PROMISC)) { /* Disable promiscuous mode */
-+ regs->EMAC_CFG &= ~AT91C_EMAC_CAF;
-+ }
-+
-+ if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
-+ regs->EMAC_HSH = -1;
-+ regs->EMAC_HSL = -1;
-+ regs->EMAC_CFG |= AT91C_EMAC_MTI;
-+ } else if (dev->mc_count > 0) { /* Enable specific multicasts */
-+ at91ether_sethashtable(dev, regs);
-+ regs->EMAC_CFG |= AT91C_EMAC_MTI;
-+ } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
-+ regs->EMAC_HSH = 0;
-+ regs->EMAC_HSL = 0;
-+ regs->EMAC_CFG &= ~AT91C_EMAC_MTI;
-+ }
-+}
-+
-+/* ............................... IOCTL ............................... */
-+
-+static int mdio_read(struct net_device *dev, int phy_id, int location)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ unsigned int value;
-+
-+ read_phy(regs, phy_id, location, &value);
-+ return value;
-+}
-+
-+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ write_phy(regs, phy_id, location, value);
-+}
-+
-+/*
-+ * ethtool support.
-+ */
-+static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ u32 ethcmd;
-+ int res = 0;
-+
-+ if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-+ return -EFAULT;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ switch (ethcmd) {
-+ case ETHTOOL_GSET: {
-+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-+ res = mii_ethtool_gset(&lp->mii, &ecmd);
-+ if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
-+ ecmd.supported = SUPPORTED_FIBRE;
-+ ecmd.port = PORT_FIBRE;
-+ }
-+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-+ res = -EFAULT;
-+ break;
-+ }
-+ case ETHTOOL_SSET: {
-+ struct ethtool_cmd ecmd;
-+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-+ res = -EFAULT;
-+ else
-+ res = mii_ethtool_sset(&lp->mii, &ecmd);
-+ break;
-+ }
-+ case ETHTOOL_NWAY_RST: {
-+ res = mii_nway_restart(&lp->mii);
-+ break;
-+ }
-+ case ETHTOOL_GLINK: {
-+ struct ethtool_value edata = { ETHTOOL_GLINK };
-+ edata.data = mii_link_ok(&lp->mii);
-+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
-+ res = -EFAULT;
-+ break;
-+ }
-+ default:
-+ res = -EOPNOTSUPP;
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ return res;
-+}
-+
-+/*
-+ * User-space ioctl interface.
-+ */
-+static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+ switch(cmd) {
-+ case SIOCETHTOOL:
-+ return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data);
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+}
-+
-+/* ................................ MAC ................................ */
-+
-+/*
-+ * Initialize and start the Receiver and Transmit subsystems
-+ */
-+static void at91ether_start(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ int i;
-+ struct recv_desc_bufs *dlist, *dlist_phys;
-+
-+ dlist = lp->dlist;
-+ dlist_phys = lp->dlist_phys;
-+
-+ for (i = 0; i < MAX_RX_DESCR; i++) {
-+ dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-+ dlist->descriptors[i].size = 0;
-+ }
-+
-+ /* Set the Wrap bit on the last descriptor */
-+ dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
-+
-+ /* Reset buffer index */
-+ lp->rxBuffIndex = 0;
-+
-+ /* Program address of descriptor list in Rx Buffer Queue register */
-+ regs->EMAC_RBQP = (AT91_REG) dlist_phys;
-+
-+ /* Enable Receive and Transmit */
-+ regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE);
-+}
-+
-+/*
-+ * Open the ethernet interface
-+ */
-+static int at91ether_open(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ return -EADDRNOTAVAIL;
-+
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Re-enable Peripheral clock */
-+ regs->EMAC_CTL |= AT91C_EMAC_CSR; /* Clear internal statistics */
-+
-+ /* Enable PHY interrupt */
-+ enable_phyirq(dev, regs);
-+
-+ /* Enable MAC interrupts */
-+ regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
-+ | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
-+ | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
-+
-+ /* Determine current link speed */
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+ (void) update_linkspeed(dev, regs);
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ at91ether_start(dev);
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+/*
-+ * Close the interface
-+ */
-+static int at91ether_close(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ /* Disable Receiver and Transmitter */
-+ regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE);
-+
-+ /* Disable PHY interrupt */
-+ disable_phyirq(dev, regs);
-+
-+ /* Disable MAC interrupts */
-+ regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
-+ | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
-+ | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
-+
-+ netif_stop_queue(dev);
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
-+
-+ return 0;
-+}
-+
-+/*
-+ * Transmit packet.
-+ */
-+static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+
-+ if (regs->EMAC_TSR & AT91C_EMAC_BNQ) {
-+ netif_stop_queue(dev);
-+
-+ /* Store packet information (to free when Tx completed) */
-+ lp->skb = skb;
-+ lp->skb_length = skb->len;
-+ lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE);
-+ lp->stats.tx_bytes += skb->len;
-+
-+ /* Set address of the data in the Transmit Address register */
-+ regs->EMAC_TAR = lp->skb_physaddr;
-+ /* Set length of the packet in the Transmit Control register */
-+ regs->EMAC_TCR = skb->len;
-+
-+ dev->trans_start = jiffies;
-+ } else {
-+ printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");
-+ return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
-+ on this skb, he also reports -ENETDOWN and printk's, so either
-+ we free and return(0) or don't free and return 1 */
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Update the current statistics from the internal statistics registers.
-+ */
-+static struct net_device_stats *at91ether_stats(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ int ale, lenerr, seqe, lcol, ecol;
-+
-+ if (netif_running(dev)) {
-+ lp->stats.rx_packets += regs->EMAC_OK; /* Good frames received */
-+ ale = regs->EMAC_ALE;
-+ lp->stats.rx_frame_errors += ale; /* Alignment errors */
-+ lenerr = regs->EMAC_ELR + regs->EMAC_USF;
-+ lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
-+ seqe = regs->EMAC_SEQE;
-+ lp->stats.rx_crc_errors += seqe; /* CRC error */
-+ lp->stats.rx_fifo_errors += regs->EMAC_DRFC; /* Receive buffer not available */
-+ lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB);
-+
-+ lp->stats.tx_packets += regs->EMAC_FRA; /* Frames successfully transmitted */
-+ lp->stats.tx_fifo_errors += regs->EMAC_TUE; /* Transmit FIFO underruns */
-+ lp->stats.tx_carrier_errors += regs->EMAC_CSE; /* Carrier Sense errors */
-+ lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE; /* Heartbeat error */
-+
-+ lcol = regs->EMAC_LCOL;
-+ ecol = regs->EMAC_ECOL;
-+ lp->stats.tx_window_errors += lcol; /* Late collisions */
-+ lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
-+
-+ lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol);
-+ }
-+ return &lp->stats;
-+}
-+
-+/*
-+ * Extract received frame from buffer descriptors and sent to upper layers.
-+ * (Called from interrupt context)
-+ */
-+static void at91ether_rx(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ struct recv_desc_bufs *dlist;
-+ unsigned char *p_recv;
-+ struct sk_buff *skb;
-+ unsigned int pktlen;
-+
-+ dlist = lp->dlist;
-+ while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-+ p_recv = dlist->recv_buf[lp->rxBuffIndex];
-+ pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
-+ skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
-+ if (skb != NULL) {
-+ skb_reserve(skb, 2);
-+ memcpy(skb_put(skb, pktlen), p_recv, pktlen);
-+
-+ skb->dev = dev;
-+ skb->protocol = eth_type_trans(skb, dev);
-+ skb->len = pktlen;
-+ dev->last_rx = jiffies;
-+ lp->stats.rx_bytes += pktlen;
-+ netif_rx(skb);
-+ }
-+ else {
-+ lp->stats.rx_dropped += 1;
-+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-+ }
-+
-+ if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-+ lp->stats.multicast++;
-+
-+ dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
-+ if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
-+ lp->rxBuffIndex = 0;
-+ else
-+ lp->rxBuffIndex++;
-+ }
-+}
-+
-+/*
-+ * MAC interrupt handler
-+ */
-+static void at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = (struct net_device *) dev_id;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
-+ unsigned long intstatus;
-+
-+ /* MAC Interrupt Status register indicates what interrupts are pending.
-+ It is automatically cleared once read. */
-+ intstatus = emac->EMAC_ISR;
-+
-+ if (intstatus & AT91C_EMAC_RCOM) /* Receive complete */
-+ at91ether_rx(dev);
-+
-+ if (intstatus & AT91C_EMAC_TCOM) { /* Transmit complete */
-+ /* The TCOM bit is set even if the transmission failed. */
-+ if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY))
-+ lp->stats.tx_errors += 1;
-+
-+ dev_kfree_skb_irq(lp->skb);
-+ pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE);
-+ netif_wake_queue(dev);
-+ }
-+
-+ if (intstatus & AT91C_EMAC_RBNA)
-+ printk("%s: RBNA error\n", dev->name);
-+ if (intstatus & AT91C_EMAC_ROVR)
-+ printk("%s: ROVR error\n", dev->name);
-+}
-+
-+/*
-+ * Initialize the ethernet interface
-+ */
-+static int at91ether_setup(struct net_device *dev, unsigned long phy_type)
-+{
-+ struct at91_private *lp;
-+ AT91PS_EMAC regs;
-+ static int already_initialized = 0;
-+ unsigned int val;
-+
-+ if (already_initialized)
-+ return 0;
-+
-+ dev = init_etherdev(dev, sizeof(struct at91_private));
-+ dev->base_addr = AT91C_VA_BASE_EMAC;
-+ dev->irq = AT91C_ID_EMAC;
-+ SET_MODULE_OWNER(dev);
-+
-+ /* Install the interrupt handler */
-+ if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev))
-+ return -EBUSY;
-+
-+ /* Allocate memory for private data structure */
-+ lp = (struct at91_private *) kmalloc(sizeof(struct at91_private), GFP_KERNEL);
-+ if (lp == NULL) {
-+ free_irq(dev->irq, dev);
-+ return -ENOMEM;
-+ }
-+ memset(lp, 0, sizeof(struct at91_private));
-+ dev->priv = lp;
-+
-+ /* Allocate memory for DMA Receive descriptors */
-+ lp->dlist = (struct recv_desc_bufs *) consistent_alloc(GFP_DMA | GFP_KERNEL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys);
-+ if (lp->dlist == NULL) {
-+ kfree(dev->priv);
-+ free_irq(dev->irq, dev);
-+ return -ENOMEM;
-+ }
-+
-+ spin_lock_init(&lp->lock);
-+
-+ ether_setup(dev);
-+ dev->open = at91ether_open;
-+ dev->stop = at91ether_close;
-+ dev->hard_start_xmit = at91ether_tx;
-+ dev->get_stats = at91ether_stats;
-+ dev->set_multicast_list = at91ether_set_rx_mode;
-+ dev->do_ioctl = at91ether_ioctl;
-+
-+#ifdef AT91_ETHER_ADDR_CONFIGURABLE
-+ dev->set_mac_address = set_mac_address;
-+#endif
-+
-+ get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
-+ update_mac_address(dev); /* Program ethernet address into MAC */
-+
-+ regs = (AT91PS_EMAC) dev->base_addr;
-+ regs->EMAC_CTL = 0;
-+
-+#ifdef CONFIG_AT91_ETHER_RMII
-+ regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII;
-+#else
-+ regs->EMAC_CFG = AT91C_EMAC_BIG;
-+#endif
-+ if (phy_type == MII_LXT971A_ID)
-+ regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; /* MDIO clock = system clock/64 */
-+
-+ if (phy_type == MII_DM9161_ID) {
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ read_phy(regs, 0, MII_DSCR_REG, &val);
-+ if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
-+ lp->phy_media = PORT_FIBRE;
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+ }
-+
-+ lp->mii.dev = dev; /* Support for ethtool */
-+ lp->mii.mdio_read = mdio_read;
-+ lp->mii.mdio_write = mdio_write;
-+
-+ lp->phy_type = phy_type; /* Type of PHY connected */
-+
-+ /* Determine current link speed */
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+ (void) update_linkspeed(dev, regs);
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ /* Display ethernet banner */
-+ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
-+ dev->name, (uint) dev->base_addr, dev->irq,
-+ regs->EMAC_CFG & AT91C_EMAC_SPD ? "100-" : "10-",
-+ regs->EMAC_CFG & AT91C_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-+ if (phy_type == MII_DM9161_ID)
-+ printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-+ else if (phy_type == MII_LXT971A_ID)
-+ printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-+
-+ already_initialized = 1;
-+ return 0;
-+}
-+
-+/*
-+ * Detect MAC and PHY and perform initialization
-+ */
-+static int at91ether_probe(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;
-+ unsigned int phyid1, phyid2;
-+ int detected = -1;
-+
-+ /* Configure the hardware - RMII vs MII mode */
-+#ifdef CONFIG_AT91_ETHER_RMII
-+ AT91_CfgPIO_EMAC_RMII();
-+#else
-+ AT91_CfgPIO_EMAC_MII();
-+#endif
-+
-+ AT91_CfgPIO_EMAC_PHY(); /* Configure PHY interrupt */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */
-+
-+ /* Read the PHY ID registers */
-+ enable_mdi(regs);
-+ read_phy(regs, 0, MII_PHYSID1, &phyid1);
-+ read_phy(regs, 0, MII_PHYSID2, &phyid2);
-+ disable_mdi(regs);
-+
-+ /* Davicom 9161: PHY_ID1 = 0x181 PHY_ID2 = B881 */
-+ if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) {
-+ detected = at91ether_setup(dev, MII_DM9161_ID);
-+ }
-+ /* Intel LXT971A: PHY_ID1 = 0x13 PHY_ID2 = 78E0 */
-+ else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {
-+ detected = at91ether_setup(dev, MII_LXT971A_ID);
-+ }
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
-+
-+ return detected;
-+}
-+
-+static int __init at91ether_init(void)
-+{
-+ if (!at91ether_probe(&at91_dev))
-+ return register_netdev(&at91_dev);
-+
-+ return -1;
-+}
-+
-+static void __exit at91ether_exit(void)
-+{
-+ unregister_netdev(&at91_dev);
-+}
-+
-+module_init(at91ether_init)
-+module_exit(at91ether_exit)
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-+MODULE_AUTHOR("Andrew Victor");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/net/at91_ether.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,81 @@
-+/*
-+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
-+ * Initial version by Rick Bronson.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_ETHERNET
-+#define AT91_ETHERNET
-+
-+#undef AT91_ETHER_ADDR_CONFIGURABLE /* MAC address can be changed? */
-+
-+
-+/* Davicom 9161 PHY */
-+#define MII_DM9161_ID 0x0181b880
-+
-+/* Davicom specific registers */
-+#define MII_DSCR_REG 16
-+#define MII_DSCSR_REG 17
-+#define MII_DSINTR_REG 21
-+
-+/* Intel LXT971A PHY */
-+#define MII_LXT971A_ID 0x001378E0
-+
-+/* Intel specific registers */
-+#define MII_ISINTE_REG 18
-+#define MII_ISINTS_REG 19
-+
-+/* ........................................................................ */
-+
-+#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
-+#define MAX_RX_DESCR 9 /* max number of receive buffers */
-+
-+#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
-+#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
-+
-+#define EMAC_BROADCAST 0x80000000 /* broadcast address */
-+#define EMAC_MULTICAST 0x40000000 /* multicast address */
-+#define EMAC_UNICAST 0x20000000 /* unicast address */
-+
-+struct rbf_t
-+{
-+ unsigned int addr;
-+ unsigned long size;
-+};
-+
-+struct recv_desc_bufs
-+{
-+ struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
-+ char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
-+};
-+
-+struct at91_private
-+{
-+ struct net_device_stats stats;
-+ struct mii_if_info mii; /* ethtool support */
-+
-+ /* PHY */
-+ unsigned long phy_type; /* type of PHY (PHY_ID) */
-+ spinlock_t lock; /* lock for MDI interface */
-+ short phy_media; /* media interface type */
-+
-+ /* Transmit */
-+ struct sk_buff *skb; /* holds skb until xmit interrupt completes */
-+ dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
-+ int skb_length; /* saved skb length for pci_unmap_single */
-+
-+ /* Receive */
-+ int rxBuffIndex; /* index into receive descriptor list */
-+ struct recv_desc_bufs *dlist; /* descriptor list address */
-+ struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
-+};
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/rtc/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/rtc/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 real time clock device drivers
-+#
-+
-+O_TARGET := at91rtc.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_RTC) += at91_rtc.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/rtc/at91_rtc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,441 @@
-+/*
-+ * Real Time Clock interface for Linux on Atmel AT91RM9200
-+ *
-+ * Copyright (c) 2002 Rick Bronson
-+ *
-+ * Based on sa1100-rtc.c by Nils Faerber
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russell King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+
-+#define AT91_RTC_FREQ 1
-+#define EPOCH 1970
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define AT91_RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define AT91_RTC_PF 0x40
-+#define AT91_RTC_AF 0x20
-+#define AT91_RTC_UF 0x10
-+
-+#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
-+#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
-+
-+static unsigned long rtc_status = 0;
-+static unsigned long rtc_irq_data;
-+static unsigned int at91_alarm_year = EPOCH;
-+
-+static struct fasync_struct *at91_rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait);
-+static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_update);
-+static spinlock_t at91_rtc_updlock; /* some spinlocks for saving/restoring interrupt levels */
-+extern spinlock_t at91_rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+static const unsigned short int __mon_yday[2][13] =
-+{
-+ /* Normal years. */
-+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-+ /* Leap years. */
-+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-+};
-+
-+/*
-+ * Returns day since start of the year [0-365]
-+ * (from drivers/char/efirtc.c)
-+ */
-+static inline int compute_yday(int year, int month, int day)
-+{
-+ return __mon_yday[is_leap(year)][month] + day-1;
-+}
-+
-+/*
-+ * Set current time and date in RTC
-+ */
-+static void at91_rtc_settime(struct rtc_time *tval)
-+{
-+ unsigned long flags;
-+
-+ /* Stop Time/Calendar from counting */
-+ AT91_SYS->RTC_CR |= (AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
-+
-+ spin_lock_irqsave(&at91_rtc_updlock, flags); /* stop int's else we wakeup b4 we sleep */
-+ AT91_SYS->RTC_IER = AT91C_RTC_ACKUPD;
-+ interruptible_sleep_on(&at91_rtc_update); /* wait for ACKUPD interrupt to hit */
-+ spin_unlock_irqrestore(&at91_rtc_updlock, flags);
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD;
-+
-+ AT91_SYS->RTC_TIMR = BIN2BCD(tval->tm_sec) << 0
-+ | BIN2BCD(tval->tm_min) << 8
-+ | BIN2BCD(tval->tm_hour) << 16;
-+
-+ AT91_SYS->RTC_CALR = BIN2BCD((tval->tm_year + 1900) / 100) /* century */
-+ | BIN2BCD(tval->tm_year % 100) << 8 /* year */
-+ | BIN2BCD(tval->tm_mon + 1) << 16 /* tm_mon starts at zero */
-+ | BIN2BCD(tval->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
-+ | BIN2BCD(tval->tm_mday) << 24;
-+
-+ /* Restart Time/Calendar */
-+ AT91_SYS->RTC_CR &= ~(AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
-+}
-+
-+/*
-+ * Decode time/date into rtc_time structure
-+ */
-+static void at91_rtc_decodetime(AT91_REG *timereg, AT91_REG *calreg, struct rtc_time *tval)
-+{
-+ unsigned int time, date;
-+
-+ do { /* must read twice in case it changes */
-+ time = *timereg;
-+ date = *calreg;
-+ } while ((time != *timereg) || (date != *calreg));
-+
-+ tval->tm_sec = BCD2BIN((time & AT91C_RTC_SEC) >> 0);
-+ tval->tm_min = BCD2BIN((time & AT91C_RTC_MIN) >> 8);
-+ tval->tm_hour = BCD2BIN((time & AT91C_RTC_HOUR) >> 16);
-+
-+ /* The Calendar Alarm register does not have a field for
-+ the year - so these will return an invalid value. When an
-+ alarm is set, at91_alarm_year wille store the current year. */
-+ tval->tm_year = BCD2BIN(date & AT91C_RTC_CENT) * 100; /* century */
-+ tval->tm_year += BCD2BIN((date & AT91C_RTC_YEAR) >> 8); /* year */
-+
-+ tval->tm_wday = BCD2BIN((date & AT91C_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
-+ tval->tm_mon = BCD2BIN(((date & AT91C_RTC_MONTH) >> 16) - 1);
-+ tval->tm_mday = BCD2BIN((date & AT91C_RTC_DATE) >> 24);
-+}
-+
-+/*
-+ * IRQ handler for the RTC
-+ */
-+static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR;
-+
-+ /* update irq data & counter */
-+ if (rtsr) { /* this interrupt is shared! Is it ours? */
-+ if (rtsr & AT91C_RTC_ALARM)
-+ rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF);
-+ if (rtsr & AT91C_RTC_SECEV)
-+ rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF);
-+ if (rtsr & AT91C_RTC_ACKUPD)
-+ wake_up_interruptible(&at91_rtc_update);
-+ rtc_irq_data += 0x100;
-+ AT91_SYS->RTC_SCCR = rtsr; /* clear status reg */
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&at91_rtc_wait);
-+ kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN);
-+ }
-+}
-+
-+static int at91_rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit(1, &rtc_status))
-+ return -EBUSY;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int at91_rtc_release(struct inode *inode, struct file *file)
-+{
-+ rtc_status = 0;
-+ return 0;
-+}
-+
-+static int at91_rtc_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &at91_rtc_async_queue);
-+}
-+
-+static unsigned int at91_rtc_poll(struct file *file, poll_table * wait)
-+{
-+ poll_wait(file, &at91_rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&at91_rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq(&at91_rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+ retval = put_user(data, (unsigned long *) buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&at91_rtc_wait, &wait);
-+ return retval;
-+}
-+
-+/*
-+ * Handle commands from user-space
-+ */
-+static int at91_rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct rtc_time tm, tm2;
-+ int ret = 0;
-+
-+ spin_lock_irq(&at91_rtc_lock);
-+ switch (cmd) {
-+ case RTC_AIE_OFF: /* alarm off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ALARM;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_AIE_ON: /* alarm on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_ALARM;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_UIE_OFF: /* update off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_UIE_ON: /* update on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_PIE_OFF: /* periodic off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_PIE_ON: /* periodic on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_ALM_READ: /* read alarm */
-+ memset(&tm, 0, sizeof(struct rtc_time));
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
-+ tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
-+ tm.tm_year = at91_alarm_year - 1900;
-+ ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
-+ break;
-+ case RTC_ALM_SET: /* set alarm */
-+ if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2)))
-+ ret = -EFAULT;
-+ else {
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ at91_alarm_year = tm.tm_year;
-+ if ((unsigned) tm2.tm_hour < 24) /* do some range checking */
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned) tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned) tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+ AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0
-+ | BIN2BCD(tm.tm_min) << 8
-+ | BIN2BCD(tm.tm_hour) << 16
-+ | AT91C_RTC_HOUREN | AT91C_RTC_MINEN
-+ | AT91C_RTC_SECEN;
-+ AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
-+ | BIN2BCD(tm.tm_mday) << 24
-+ | AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN;
-+ }
-+ break;
-+ case RTC_RD_TIME: /* read time */
-+ memset(&tm, 0, sizeof(struct rtc_time));
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
-+ tm.tm_year = tm.tm_year - 1900;
-+ ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
-+ break;
-+ case RTC_SET_TIME: /* set time */
-+ if (!capable(CAP_SYS_TIME))
-+ ret = -EACCES;
-+ else {
-+ if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm)))
-+ ret = -EFAULT;
-+ else {
-+ int tm_year = tm.tm_year + 1900;
-+ if (tm_year < EPOCH
-+ || (unsigned) tm.tm_mon >= 12
-+ || tm.tm_mday < 1
-+ || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year)))
-+ || (unsigned) tm.tm_hour >= 24
-+ || (unsigned) tm.tm_min >= 60
-+ || (unsigned) tm.tm_sec >= 60)
-+ ret = -EINVAL;
-+ else
-+ at91_rtc_settime(&tm);
-+ }
-+ }
-+ break;
-+ case RTC_IRQP_READ: /* read periodic alarm frequency */
-+ ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
-+ break;
-+ case RTC_IRQP_SET: /* set periodic alarm frequency */
-+ if (arg != AT91_RTC_FREQ)
-+ ret = -EINVAL;
-+ break;
-+ case RTC_EPOCH_READ: /* read epoch */
-+ ret = put_user(EPOCH, (unsigned long *) arg);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+ return ret;
-+}
-+
-+/*
-+ * Provide RTC information in /proc/driver/rtc
-+ */
-+static int at91_rtc_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH);
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ at91_alarm_year, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no");
-+ p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no");
-+ p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no");
-+ p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static struct file_operations at91_rtc_fops = {
-+ owner:THIS_MODULE,
-+ llseek:no_llseek,
-+ read:at91_rtc_read,
-+ poll:at91_rtc_poll,
-+ ioctl:at91_rtc_ioctl,
-+ open:at91_rtc_open,
-+ release:at91_rtc_release,
-+ fasync:at91_rtc_fasync,
-+};
-+
-+static struct miscdevice at91_rtc_miscdev = {
-+ minor:RTC_MINOR,
-+ name:"rtc",
-+ fops:&at91_rtc_fops,
-+};
-+
-+/*
-+ * Initialize and install RTC driver
-+ */
-+static int __init at91_rtc_init(void)
-+{
-+ int ret;
-+
-+ AT91_SYS->RTC_CR = 0;
-+ AT91_SYS->RTC_MR = 0; /* put in 24 hour format */
-+ /* Disable all interrupts */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
-+
-+ spin_lock_init(&at91_rtc_updlock);
-+ spin_lock_init(&at91_rtc_lock);
-+
-+ misc_register(&at91_rtc_miscdev);
-+ create_proc_read_entry("driver/rtc", 0, 0, at91_rtc_read_proc, NULL);
-+ ret = request_irq(AT91C_ID_SYS, at91_rtc_interrupt, SA_SHIRQ,
-+ "at91_rtc", &rtc_status);
-+ if (ret) {
-+ printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91C_ID_SYS);
-+ remove_proc_entry("driver/rtc", NULL);
-+ misc_deregister(&at91_rtc_miscdev);
-+ return ret;
-+ }
-+
-+ printk(KERN_INFO "AT91 Real Time Clock driver\n");
-+ return 0;
-+}
-+
-+/*
-+ * Disable and remove the RTC driver
-+ */
-+static void __exit at91_rtc_exit(void)
-+{
-+ /* Disable all interrupts */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
-+ free_irq(AT91C_ID_SYS, &rtc_status);
-+
-+ rtc_status = 0;
-+ remove_proc_entry("driver/rtc", NULL);
-+ misc_deregister(&at91_rtc_miscdev);
-+}
-+
-+module_init(at91_rtc_init);
-+module_exit(at91_rtc_exit);
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("AT91 Realtime Clock Driver (AT91_RTC)");
-+MODULE_LICENSE("GPL");
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/serial/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/serial/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 serial and console device drivers
-+#
-+
-+O_TARGET := at91serial.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/serial/at91_serial.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,870 @@
-+/*
-+ * linux/drivers/char/at91_serial.c
-+ *
-+ * Driver for Atmel AT91RM9200 Serial ports
-+ *
-+ * Copyright (c) Rick Bronson
-+ *
-+ * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/arch/AT91RM9200_USART.h>
-+#include <asm/mach/serial_at91rm9200.h>
-+#include <asm/arch/pio.h>
-+
-+
-+#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#define SERIAL_AT91_MAJOR TTY_MAJOR
-+#define CALLOUT_AT91_MAJOR TTYAUX_MAJOR
-+#define MINOR_START 64
-+
-+#define AT91C_VA_BASE_DBGU ((unsigned long) &(AT91_SYS->DBGU_CR))
-+#define AT91_ISR_PASS_LIMIT 256
-+
-+#define UART_PUT_CR(port,v) ((AT91PS_USART)(port)->membase)->US_CR = v
-+#define UART_GET_MR(port) ((AT91PS_USART)(port)->membase)->US_MR
-+#define UART_PUT_MR(port,v) ((AT91PS_USART)(port)->membase)->US_MR = v
-+#define UART_PUT_IER(port,v) ((AT91PS_USART)(port)->membase)->US_IER = v
-+#define UART_PUT_IDR(port,v) ((AT91PS_USART)(port)->membase)->US_IDR = v
-+#define UART_GET_IMR(port) ((AT91PS_USART)(port)->membase)->US_IMR
-+#define UART_GET_CSR(port) ((AT91PS_USART)(port)->membase)->US_CSR
-+#define UART_GET_CHAR(port) ((AT91PS_USART)(port)->membase)->US_RHR
-+#define UART_PUT_CHAR(port,v) ((AT91PS_USART)(port)->membase)->US_THR = v
-+#define UART_GET_BRGR(port) ((AT91PS_USART)(port)->membase)->US_BRGR
-+#define UART_PUT_BRGR(port,v) ((AT91PS_USART)(port)->membase)->US_BRGR = v
-+#define UART_PUT_RTOR(port,v) ((AT91PS_USART)(port)->membase)->US_RTOR = v
-+
-+// #define UART_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only
-+
-+ /* PDC registers */
-+#define UART_PUT_PTCR(port,v) ((AT91PS_USART)(port)->membase)->US_PTCR = v
-+#define UART_PUT_RPR(port,v) ((AT91PS_USART)(port)->membase)->US_RPR = v
-+#define UART_PUT_RCR(port,v) ((AT91PS_USART)(port)->membase)->US_RCR = v
-+#define UART_GET_RCR(port) ((AT91PS_USART)(port)->membase)->US_RCR
-+#define UART_PUT_RNPR(port,v) ((AT91PS_USART)(port)->membase)->US_RNPR = v
-+#define UART_PUT_RNCR(port,v) ((AT91PS_USART)(port)->membase)->US_RNCR = v
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *at91_table[AT91C_NR_UART];
-+static struct termios *at91_termios[AT91C_NR_UART], *at91_termios_locked[AT91C_NR_UART];
-+
-+const int at91_serialmap[AT91C_NR_UART] = AT91C_UART_MAP;
-+
-+static int (*at91_open)(struct uart_port *);
-+static void (*at91_close)(struct uart_port *);
-+
-+#ifdef SUPPORT_SYSRQ
-+static struct console at91_console;
-+#endif
-+
-+/*
-+ * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
-+ */
-+static u_int at91_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_CSR(port) & AT91C_US_TXEMPTY ? TIOCSER_TEMT : 0;
-+}
-+
-+/*
-+ * Set state of the modem control output lines
-+ */
-+static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned int control = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ control |= AT91C_US_RTSEN;
-+ else
-+ control |= AT91C_US_RTSDIS;
-+
-+ if (mctrl & TIOCM_DTR)
-+ control |= AT91C_US_DTREN;
-+ else
-+ control |= AT91C_US_DTRDIS;
-+
-+ UART_PUT_CR(port,control);
-+}
-+
-+/*
-+ * Get state of the modem control input lines
-+ */
-+static u_int at91_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int status, ret = 0;
-+
-+ status = UART_GET_CSR(port);
-+ if (status & AT91C_US_DCD)
-+ ret |= TIOCM_CD;
-+ if (status & AT91C_US_CTS)
-+ ret |= TIOCM_CTS;
-+ if (status & AT91C_US_DSR)
-+ ret |= TIOCM_DSR;
-+ if (status & AT91C_US_RI)
-+ ret |= TIOCM_RI;
-+
-+ return ret;
-+}
-+
-+/*
-+ * Stop transmitting.
-+ */
-+static void at91_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ UART_PUT_IDR(port, AT91C_US_TXRDY);
-+ port->read_status_mask &= ~AT91C_US_TXRDY;
-+}
-+
-+/*
-+ * Start transmitting.
-+ */
-+static void at91_start_tx(struct uart_port *port, u_int from_tty)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ port->read_status_mask |= AT91C_US_TXRDY;
-+ UART_PUT_IER(port, AT91C_US_TXRDY);
-+ local_irq_restore(flags);
-+}
-+
-+/*
-+ * Stop receiving - port is in process of being closed.
-+ */
-+static void at91_stop_rx(struct uart_port *port)
-+{
-+ UART_PUT_IDR(port, AT91C_US_RXRDY);
-+}
-+
-+/*
-+ * Enable modem status interrupts
-+ */
-+static void at91_enable_ms(struct uart_port *port)
-+{
-+ UART_PUT_IER(port, AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC);
-+}
-+
-+/*
-+ * Control the transmission of a break signal
-+ */
-+static void at91_break_ctl(struct uart_port *port, int break_state)
-+{
-+ if (break_state != 0)
-+ UART_PUT_CR(port, AT91C_US_STTBRK); /* start break */
-+ else
-+ UART_PUT_CR(port, AT91C_US_STPBRK); /* stop break */
-+}
-+
-+/*
-+ * Characters received (called from interrupt handler)
-+ */
-+static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = UART_GET_CSR(port);
-+ while (status & (AT91C_US_RXRDY)) {
-+ ch = UART_GET_CHAR(port);
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ port->icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UART_GET_CSR(port);
-+ }
-+out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+handle_error:
-+ if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
-+ UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
-+ if (status & (AT91C_US_PARE))
-+ port->icount.parity++;
-+ else if (status & (AT91C_US_FRAME))
-+ port->icount.frame++;
-+ if (status & (AT91C_US_OVRE))
-+ port->icount.overrun++;
-+
-+ if (status & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+
-+ status &= port->read_status_mask;
-+
-+ UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
-+ if (status & AT91C_US_PARE)
-+ flg = TTY_PARITY;
-+ else if (status & AT91C_US_FRAME)
-+ flg = TTY_FRAME;
-+
-+ if (status & AT91C_US_OVRE) {
-+ /*
-+ * overrun does *not* affect the character
-+ * we read from the FIFO
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+/*
-+ * Transmit characters (called from interrupt handler)
-+ */
-+static void at91_tx_chars(struct uart_port *port)
-+{
-+ struct circ_buf *xmit = &port->info->xmit;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ at91_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ while (UART_GET_CSR(port) & AT91C_US_TXRDY) {
-+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ }
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ at91_stop_tx(port, 0);
-+}
-+
-+/*
-+ * Interrupt handler
-+ */
-+static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pending, pass_counter = 0;
-+
-+ status = UART_GET_CSR(port);
-+ pending = status & port->read_status_mask;
-+ if (pending) {
-+ do {
-+ if (pending & AT91C_US_RXRDY)
-+ at91_rx_chars(port, regs);
-+
-+ /* Clear the relevent break bits */
-+ if (pending & AT91C_US_RXBRK) {
-+ UART_PUT_CR(port, AT91C_US_RSTSTA);
-+ port->icount.brk++;
-+#ifdef SUPPORT_SYSRQ
-+ if (port->line == at91_console.index && !port->sysrq) {
-+ port->sysrq = jiffies + HZ*5;
-+ }
-+#endif
-+ }
-+
-+ // TODO: All reads to CSR will clear these interrupts!
-+ if (pending & AT91C_US_RIIC) port->icount.rng++;
-+ if (pending & AT91C_US_DSRIC) port->icount.dsr++;
-+ if (pending & AT91C_US_DCDIC) {
-+ port->icount.dcd++;
-+ uart_handle_dcd_change(port, status & AT91C_US_DCD);
-+ }
-+ if (pending & AT91C_US_CTSIC) {
-+ port->icount.cts++;
-+ uart_handle_cts_change(port, status & AT91C_US_CTS);
-+ }
-+ if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC))
-+ wake_up_interruptible(&port->info->delta_msr_wait);
-+
-+ if (pending & AT91C_US_TXRDY)
-+ at91_tx_chars(port);
-+ if (pass_counter++ > AT91_ISR_PASS_LIMIT)
-+ break;
-+
-+ status = UART_GET_CSR(port);
-+ pending = status & port->read_status_mask;
-+ } while (pending);
-+ }
-+}
-+
-+/*
-+ * Perform initialization and enable port for reception
-+ */
-+static int at91_startup(struct uart_port *port)
-+{
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
-+ if (retval) {
-+ printk("at91_serial: at91_startup - Can't get irq\n");
-+ return retval;
-+ }
-+ /*
-+ * If there is a specific "open" function (to register
-+ * control line interrupts)
-+ */
-+ if (at91_open) {
-+ retval = at91_open(port);
-+ if (retval) {
-+ free_irq(port->irq, port);
-+ return retval;
-+ }
-+ }
-+
-+ /* Enable peripheral clock if required */
-+ if (port->irq != AT91C_ID_SYS)
-+ AT91_SYS->PMC_PCER = 1 << port->irq;
-+
-+ port->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE
-+ | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK;
-+ /*
-+ * Finally, clear and enable interrupts
-+ */
-+ UART_PUT_IDR(port, -1);
-+ UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */
-+ UART_PUT_IER(port, AT91C_US_RXRDY); /* do receive only */
-+ return 0;
-+}
-+
-+/*
-+ * Disable the port
-+ */
-+static void at91_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+
-+ /*
-+ * If there is a specific "close" function (to unregister
-+ * control line interrupts)
-+ */
-+ if (at91_close)
-+ at91_close(port);
-+
-+ /*
-+ * Disable all interrupts, port and break condition.
-+ */
-+ UART_PUT_CR(port, AT91C_US_RSTSTA);
-+ UART_PUT_IDR(port, -1);
-+
-+ /* Disable peripheral clock if required */
-+ if (port->irq != AT91C_ID_SYS)
-+ AT91_SYS->PMC_PCDR = 1 << port->irq;
-+}
-+
-+static struct uart_ops at91_pops; /* forward declaration */
-+
-+/*
-+ * Change the port parameters
-+ */
-+static void at91_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ unsigned long flags;
-+ unsigned int mode, imr;
-+
-+ /* Get current mode register */
-+ mode = UART_GET_MR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR);
-+
-+ /* byte size */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ mode |= AT91C_US_CHRL_5_BITS;
-+ break;
-+ case CS6:
-+ mode |= AT91C_US_CHRL_6_BITS;
-+ break;
-+ case CS7:
-+ mode |= AT91C_US_CHRL_7_BITS;
-+ break;
-+ default:
-+ mode |= AT91C_US_CHRL_8_BITS;
-+ break;
-+ }
-+
-+ /* stop bits */
-+ if (cflag & CSTOPB)
-+ mode |= AT91C_US_NBSTOP_2_BIT;
-+
-+ /* parity */
-+ if (cflag & PARENB) {
-+ if (cflag & CMSPAR) { /* Mark or Space parity */
-+ if (cflag & PARODD)
-+ mode |= AT91C_US_PAR_MARK;
-+ else
-+ mode |= AT91C_US_PAR_SPACE;
-+ }
-+ else if (cflag & PARODD)
-+ mode |= AT91C_US_PAR_ODD;
-+ else
-+ mode |= AT91C_US_PAR_EVEN;
-+ }
-+ else
-+ mode |= AT91C_US_PAR_NONE;
-+
-+ port->read_status_mask |= AT91C_US_OVRE;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= AT91C_US_RXBRK;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE);
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= AT91C_US_RXBRK;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AT91C_US_OVRE;
-+ }
-+
-+ // TODO: Ignore all characters if CREAD is set.
-+
-+ /* first, disable interrupts and drain transmitter */
-+ local_irq_save(flags);
-+ imr = UART_GET_IMR(port); /* get interrupt mask */
-+ UART_PUT_IDR(port, -1); /* disable all interrupts */
-+ local_irq_restore(flags);
-+ while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }
-+
-+ /* disable receiver and transmitter */
-+ UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);
-+
-+ /* set the parity, stop bits and data size */
-+ UART_PUT_MR(port, mode);
-+
-+ /* set the baud rate */
-+ UART_PUT_BRGR(port, quot);
-+ UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);
-+
-+ /* restore interrupts */
-+ UART_PUT_IER(port, imr);
-+
-+ /* CTS flow-control and modem-status interrupts */
-+ if (UART_ENABLE_MS(uart, cflag))
-+ at91_pops.enable_ms(uart);
-+}
-+
-+/*
-+ * Return string describing the specified port
-+ */
-+static const char *at91_type(struct uart_port *port)
-+{
-+ return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'.
-+ */
-+static void at91_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase,
-+ port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'.
-+ */
-+static int at91_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase,
-+ port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K,
-+ "at91_serial") != NULL ? 0 : -EBUSY;
-+
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void at91_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_AT91RM9200;
-+ at91_request_port(port);
-+ }
-+}
-+
-+/*
-+ * Verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
-+ ret = -EINVAL;
-+ if (port->irq != ser->irq)
-+ ret = -EINVAL;
-+ if (ser->io_type != SERIAL_IO_MEM)
-+ ret = -EINVAL;
-+ if (port->uartclk / 16 != ser->baud_base)
-+ ret = -EINVAL;
-+ if ((void *)port->mapbase != ser->iomem_base)
-+ ret = -EINVAL;
-+ if (port->iobase != ser->port)
-+ ret = -EINVAL;
-+ if (ser->hub6 != 0)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops at91_pops = {
-+ tx_empty: at91_tx_empty,
-+ set_mctrl: at91_set_mctrl,
-+ get_mctrl: at91_get_mctrl,
-+ stop_tx: at91_stop_tx,
-+ start_tx: at91_start_tx,
-+ stop_rx: at91_stop_rx,
-+ enable_ms: at91_enable_ms,
-+ break_ctl: at91_break_ctl,
-+ startup: at91_startup,
-+ shutdown: at91_shutdown,
-+ change_speed: at91_change_speed,
-+ type: at91_type,
-+ release_port: at91_release_port,
-+ request_port: at91_request_port,
-+ config_port: at91_config_port,
-+ verify_port: at91_verify_port,
-+};
-+
-+static struct uart_port at91_ports[AT91C_NR_UART];
-+
-+void __init at91_init_ports(void)
-+{
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ at91_ports[i].iotype = SERIAL_IO_MEM;
-+ at91_ports[i].flags = ASYNC_BOOT_AUTOCONF;
-+ at91_ports[i].uartclk = AT91C_MASTER_CLOCK;
-+ at91_ports[i].ops = &at91_pops;
-+ at91_ports[i].fifosize = 1;
-+ at91_ports[i].line = i;
-+ }
-+}
-+
-+void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
-+{
-+ if (fns->enable_ms)
-+ at91_pops.enable_ms = fns->enable_ms;
-+ if (fns->get_mctrl)
-+ at91_pops.get_mctrl = fns->get_mctrl;
-+ if (fns->set_mctrl)
-+ at91_pops.set_mctrl = fns->set_mctrl;
-+ at91_open = fns->open;
-+ at91_close = fns->close;
-+ at91_pops.pm = fns->pm;
-+ at91_pops.set_wake = fns->set_wake;
-+}
-+
-+/*
-+ * Setup ports.
-+ */
-+void __init at91_register_uart(int idx, int port)
-+{
-+ if ((idx < 0) || (idx >= AT91C_NR_UART)) {
-+ printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);
-+ return;
-+ }
-+
-+ switch (port) {
-+ case 0:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US0;
-+ at91_ports[idx].irq = AT91C_ID_US0;
-+ AT91_CfgPIO_USART0();
-+ break;
-+ case 1:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US1;
-+ at91_ports[idx].irq = AT91C_ID_US1;
-+ AT91_CfgPIO_USART1();
-+ break;
-+ case 2:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US2;
-+ at91_ports[idx].irq = AT91C_ID_US2;
-+ AT91_CfgPIO_USART2();
-+ break;
-+ case 3:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US3;
-+ at91_ports[idx].irq = AT91C_ID_US3;
-+ AT91_CfgPIO_USART3();
-+ break;
-+ case 4:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;
-+ at91_ports[idx].irq = AT91C_ID_SYS;
-+ AT91_CfgPIO_DBGU();
-+ break;
-+ default:
-+ printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);
-+ }
-+}
-+
-+#ifdef CONFIG_SERIAL_AT91_CONSOLE
-+
-+/*
-+ * Interrupts are disabled on entering
-+ */
-+static void at91_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = at91_ports + co->index;
-+ unsigned int status, i, imr;
-+
-+ /*
-+ * First, save IMR and then disable interrupts
-+ */
-+ imr = UART_GET_IMR(port); /* get interrupt mask */
-+ UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (!(status & AT91C_US_TXRDY));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (!(status & AT91C_US_TXRDY));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore IMR
-+ */
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (status & AT91C_US_TXRDY);
-+ UART_PUT_IER(port, imr); /* set interrupts back the way they were */
-+}
-+
-+static kdev_t at91_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index);
-+}
-+
-+/*
-+ * If the port was already initialised (eg, by a boot loader), try to determine
-+ * the current setup.
-+ */
-+static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ unsigned int mr, quot;
-+
-+// TODO: CR is a write-only register
-+// unsigned int cr;
-+//
-+// cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN);
-+// if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) {
-+// /* ok, the port was enabled */
-+//
-+// mr = UART_GET_MR(port) & AT91C_US_PAR;
-+//
-+// *parity = 'n';
-+// if (mr == AT91C_US_PAR_EVEN)
-+// *parity = 'e';
-+// else if (mr == AT91C_US_PAR_ODD)
-+// *parity = 'o';
-+// }
-+
-+ mr = UART_GET_MR(port) & AT91C_US_CHRL;
-+ if (mr == AT91C_US_CHRL_8_BITS)
-+ *bits = 8;
-+ else
-+ *bits = 7;
-+
-+ quot = UART_GET_BRGR(port);
-+ *baud = port->uartclk / (16 * (quot));
-+}
-+
-+static int __init at91_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(at91_ports, AT91C_NR_UART, co);
-+
-+ // TODO: The console port should be initialized, and clock enabled if
-+ // we're not relying on the bootloader to do it.
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ at91_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console at91_console = {
-+ name: "ttyS",
-+ write: at91_console_write,
-+ device: at91_console_device,
-+ setup: at91_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: AT91C_CONSOLE,
-+};
-+
-+#define AT91_CONSOLE_DEVICE &at91_console
-+
-+void __init at91_console_init(void)
-+{
-+ at91_init_ports();
-+ register_console(&at91_console);
-+}
-+
-+#else
-+#define AT91_CONSOLE_DEVICE NULL
-+#endif
-+
-+static struct uart_driver at91_reg = {
-+ owner: THIS_MODULE,
-+ normal_major: SERIAL_AT91_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ normal_name: "ttyS%d",
-+ callout_name: "cua%d",
-+#else
-+ normal_name: "ttyS",
-+ callout_name: "cua",
-+#endif
-+ normal_driver: &normal,
-+ callout_major: CALLOUT_AT91_MAJOR,
-+ callout_driver: &callout,
-+ table: at91_table,
-+ termios: at91_termios,
-+ termios_locked: at91_termios_locked,
-+ minor: MINOR_START,
-+ nr: AT91C_NR_UART,
-+ cons: AT91_CONSOLE_DEVICE,
-+};
-+
-+static int __init at91_serial_init(void)
-+{
-+ int ret, i;
-+
-+ at91_init_ports();
-+
-+ ret = uart_register_driver(&at91_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ if (at91_serialmap[i] >= 0)
-+ uart_add_one_port(&at91_reg, &at91_ports[i]);
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit at91_serial_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ if (at91_serialmap[i] >= 0)
-+ uart_remove_one_port(&at91_reg, &at91_ports[i]);
-+ }
-+
-+ uart_unregister_driver(&at91_reg);
-+}
-+
-+module_init(at91_serial_init);
-+module_exit(at91_serial_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("AT91 generic serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/spi/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,17 @@
-+# File: drivers/at91/spi/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 SPI device drivers
-+#
-+
-+O_TARGET := at91spi.o
-+
-+export-objs := at91_spi.o
-+
-+obj-y := at91_spi.o
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_SPIDEV) += at91_spidev.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/spi/at91_spi.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,275 @@
-+/*
-+ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+#include <linux/module.h>
-+#include <asm/semaphore.h>
-+#include <linux/pci.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+
-+#include <asm/arch/AT91RM9200_SPI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_spi.h"
-+
-+#undef DEBUG_SPI
-+
-+static struct spi_local spi_dev[NR_SPI_DEVICES]; /* state of the SPI devices */
-+static int spi_enabled = 0;
-+static struct semaphore spi_lock; /* protect access to SPI bus */
-+static int current_device = -1; /* currently selected SPI device */
-+
-+DECLARE_COMPLETION(transfer_complete);
-+
-+/* SPI controller device */
-+AT91PS_SPI controller = (AT91PS_SPI) AT91C_VA_BASE_SPI;
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Access and enable the SPI bus.
-+ * This MUST be called before any transfers are performed.
-+ */
-+void spi_access_bus(short device)
-+{
-+ /* Ensure that requested device is valid */
-+ if ((device < 0) || (device >= NR_SPI_DEVICES))
-+ panic("at91_spi: spi_access_bus called with invalid device");
-+
-+ if (spi_enabled == 0) {
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Enable Peripheral clock */
-+ controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
-+#ifdef DEBUG_SPI
-+ printk("SPI on\n");
-+#endif
-+ }
-+ MOD_INC_USE_COUNT;
-+ spi_enabled++;
-+
-+ /* Lock the SPI bus */
-+ down(&spi_lock);
-+ current_device = device;
-+
-+ /* Enable PIO */
-+ if (!spi_dev[device].pio_enabled) {
-+ switch (device) {
-+ case 0: AT91_CfgPIO_SPI_CS0();
-+ case 1: AT91_CfgPIO_SPI_CS1();
-+ case 2: AT91_CfgPIO_SPI_CS2();
-+ case 3: AT91_CfgPIO_SPI_CS3();
-+ }
-+ spi_dev[device].pio_enabled = 1;
-+#ifdef DEBUG_SPI
-+ printk("SPI CS%i enabled\n", device);
-+#endif
-+ }
-+
-+ /* Configure SPI bus for device */
-+ controller->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (spi_dev[device].pcs << 16);
-+}
-+
-+/*
-+ * Relinquish control of the SPI bus.
-+ */
-+void spi_release_bus(short device)
-+{
-+ if (device != current_device)
-+ panic("at91_spi: spi_release called with invalid device");
-+
-+ /* Release the SPI bus */
-+ current_device = -1;
-+ up(&spi_lock);
-+
-+ spi_enabled--;
-+ MOD_DEC_USE_COUNT;
-+ if (spi_enabled == 0) {
-+ controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Disable Peripheral clock */
-+#ifdef DEBUG_SPI
-+ printk("SPI off\n");
-+#endif
-+ }
-+}
-+
-+/*
-+ * Perform a data transfer over the SPI bus
-+ */
-+int spi_transfer(struct spi_transfer_list* list)
-+{
-+ struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
-+
-+ if (!list)
-+ panic("at91_spi: spi_transfer called with NULL transfer list");
-+ if (current_device == -1)
-+ panic("at91_spi: spi_transfer called without acquiring bus");
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI transfer start [%i]\n", list->nr_transfers);
-+#endif
-+
-+ /* Store transfer list */
-+ device->xfers = list;
-+ list->curr = 0;
-+
-+ /* Assume there must be at least one transfer */
-+ device->tx = pci_map_single(NULL, list->tx[0], list->txlen[0], PCI_DMA_TODEVICE);
-+ device->rx = pci_map_single(NULL, list->rx[0], list->rxlen[0], PCI_DMA_FROMDEVICE);
-+
-+ /* Program PDC registers */
-+ controller->SPI_TPR = device->tx;
-+ controller->SPI_RPR = device->rx;
-+ controller->SPI_TCR = list->txlen[0];
-+ controller->SPI_RCR = list->rxlen[0];
-+
-+ /* Is there a second transfer? */
-+ if (list->nr_transfers > 1) {
-+ device->txnext = pci_map_single(NULL, list->tx[1], list->txlen[1], PCI_DMA_TODEVICE);
-+ device->rxnext = pci_map_single(NULL, list->rx[1], list->rxlen[1], PCI_DMA_FROMDEVICE);
-+
-+ /* Program Next PDC registers */
-+ controller->SPI_TNPR = device->txnext;
-+ controller->SPI_RNPR = device->rxnext;
-+ controller->SPI_TNCR = list->txlen[1];
-+ controller->SPI_RNCR = list->rxlen[1];
-+ }
-+ else {
-+ device->txnext = 0;
-+ device->rxnext = 0;
-+ controller->SPI_TNCR = 0;
-+ controller->SPI_RNCR = 0;
-+ }
-+
-+ // TODO: If we are doing consecutive transfers (at high speed, or
-+ // small buffers), then it might be worth modifying the 'Delay between
-+ // Consecutive Transfers' in the CSR registers.
-+ // This is an issue if we cannot chain the next buffer fast enough
-+ // in the interrupt handler.
-+
-+ /* Enable transmitter and receiver */
-+ controller->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
-+
-+ controller->SPI_IER = AT91C_SPI_SPENDRX; /* enable buffer complete interrupt */
-+ wait_for_completion(&transfer_complete);
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI transfer end\n");
-+#endif
-+
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Handle interrupts from the SPI controller.
-+ */
-+void spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status;
-+ struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
-+ struct spi_transfer_list *list = device->xfers;
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI interrupt %i\n", current_device);
-+#endif
-+
-+ if (!list)
-+ panic("at91_spi: spi_interrupt with a NULL transfer list");
-+
-+ status = controller->SPI_SR & controller->SPI_IMR; /* read status */
-+
-+ pci_unmap_single(NULL, device->tx, list->txlen[list->curr], PCI_DMA_TODEVICE);
-+ pci_unmap_single(NULL, device->rx, list->rxlen[list->curr], PCI_DMA_FROMDEVICE);
-+
-+ device->tx = device->txnext; /* move next transfer to current transfer */
-+ device->rx = device->rxnext;
-+
-+ list->curr = list->curr + 1;
-+ if (list->curr == list->nr_transfers) { /* all transfers complete */
-+ controller->SPI_IDR = AT91C_SPI_SPENDRX; /* disable interrupt */
-+
-+ /* Disable transmitter and receiver */
-+ controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
-+
-+ device->xfers = NULL;
-+ complete(&transfer_complete);
-+ }
-+ else if (list->curr+1 == list->nr_transfers) { /* no more next transfers */
-+ device->txnext = 0;
-+ device->rxnext = 0;
-+ controller->SPI_TNCR = 0;
-+ controller->SPI_RNCR = 0;
-+ }
-+ else {
-+ int i = (list->curr)+1;
-+
-+ device->txnext = pci_map_single(NULL, list->tx[i], list->txlen[i], PCI_DMA_TODEVICE);
-+ device->rxnext = pci_map_single(NULL, list->rx[i], list->rxlen[i], PCI_DMA_FROMDEVICE);
-+ controller->SPI_TNPR = device->txnext;
-+ controller->SPI_RNPR = device->rxnext;
-+ controller->SPI_TNCR = list->txlen[i];
-+ controller->SPI_RNCR = list->rxlen[i];
-+ }
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Initialize the SPI controller
-+ */
-+static int __init at91_spi_init(void)
-+{
-+ init_MUTEX(&spi_lock);
-+
-+ AT91_CfgPIO_SPI();
-+
-+ controller->SPI_CR = AT91C_SPI_SWRST; /* software reset of SPI controller */
-+
-+ /* Set Chip Select registers to good defaults */
-+ controller->SPI_CSR0 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR1 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR2 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR3 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+
-+ controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
-+
-+ memset(&spi_dev, 0, sizeof(spi_dev));
-+ spi_dev[0].pcs = 0xE;
-+ spi_dev[1].pcs = 0xD;
-+ spi_dev[2].pcs = 0xB;
-+ spi_dev[3].pcs = 0x7;
-+
-+ if (request_irq(AT91C_ID_SPI, spi_interrupt, 0, "spi", NULL))
-+ return -EBUSY;
-+
-+ controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
-+
-+ return 0;
-+}
-+
-+static void at91_spi_exit(void)
-+{
-+ controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
-+
-+ free_irq(AT91C_ID_SPI, 0);
-+}
-+
-+
-+EXPORT_SYMBOL(spi_access_bus);
-+EXPORT_SYMBOL(spi_release_bus);
-+EXPORT_SYMBOL(spi_transfer);
-+
-+module_init(at91_spi_init);
-+module_exit(at91_spi_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200")
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/spi/at91_spi.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,56 @@
-+/*
-+ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_SPI_H
-+#define AT91_SPI_H
-+
-+/* Maximum number of buffers in a single SPI transfer.
-+ * DataFlash uses maximum of 2
-+ * spidev interface supports up to 8.
-+ */
-+#define MAX_SPI_TRANSFERS 8
-+
-+#define NR_SPI_DEVICES 4 /* number of devices on SPI bus */
-+
-+#define DATAFLASH_CLK 6000000
-+#define DEFAULT_SPI_BAUD AT91C_MASTER_CLOCK / (2 * DATAFLASH_CLK)
-+
-+#define SPI_MAJOR 153 /* registered device number */
-+
-+/*
-+ * Describes the buffers for a SPI transfer.
-+ * A transmit & receive buffer must be specified for each transfer
-+ */
-+struct spi_transfer_list {
-+ void* tx[MAX_SPI_TRANSFERS]; /* transmit */
-+ int txlen[MAX_SPI_TRANSFERS];
-+ void* rx[MAX_SPI_TRANSFERS]; /* receive */
-+ int rxlen[MAX_SPI_TRANSFERS];
-+ int nr_transfers; /* number of transfers */
-+ int curr; /* current transfer */
-+};
-+
-+struct spi_local {
-+ unsigned int pcs; /* Peripheral Chip Select value */
-+ short pio_enabled; /* has PIO been enabled? */
-+
-+ struct spi_transfer_list *xfers; /* current transfer list */
-+ dma_addr_t tx, rx; /* DMA address for current transfer */
-+ dma_addr_t txnext, rxnext; /* DMA address for next transfer */
-+};
-+
-+
-+/* Exported functions */
-+extern void spi_access_bus(short device);
-+extern void spi_release_bus(short device);
-+extern int spi_transfer(struct spi_transfer_list* list);
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/spi/at91_spidev.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,226 @@
-+/*
-+ * User-space interface to the SPI bus on Atmel AT91RM9200
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on SPI driver by Rick Bronson
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/iobuf.h>
-+#include <linux/highmem.h>
-+
-+#ifdef CONFIG_DEVFS_FS
-+#include <linux/devfs_fs_kernel.h>
-+#endif
-+
-+#include "at91_spi.h"
-+
-+#undef DEBUG_SPIDEV
-+
-+#ifdef CONFIG_DEVFS_FS
-+static devfs_handle_t devfs_handle = NULL;
-+static devfs_handle_t devfs_spi[NR_SPI_DEVICES];
-+#endif
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Read or Write to SPI bus.
-+ */
-+static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset)
-+{
-+ unsigned int spi_device = (unsigned int) file->private_data;
-+ struct kiobuf *iobuf;
-+ unsigned int ofs, pagelen;
-+ int res, i;
-+
-+ struct spi_transfer_list* list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
-+ if (!list)
-+ return -ENOMEM;
-+
-+ res = alloc_kiovec(1, &iobuf);
-+ if (res) {
-+ kfree(list);
-+ return res;
-+ }
-+
-+ res = map_user_kiobuf(READ, iobuf, (unsigned long) buf, count);
-+ if (res) {
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+ return res;
-+ }
-+
-+ /* More pages than transfer slots in spi_transfer_list */
-+ if (iobuf->nr_pages >= MAX_SPI_TRANSFERS) {
-+ unmap_kiobuf(iobuf);
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+ return -EFBIG;
-+ }
-+
-+#ifdef DEBUG_SPIDEV
-+ printk("spidev_rd_rw: %i %i\n", count, iobuf->nr_pages);
-+#endif
-+
-+ /* Set default return value = transfer length */
-+ res = count;
-+
-+ /*
-+ * At this point, the virtual area buf[0] .. buf[count-1] will have
-+ * corresponding pages mapped in the physical memory and locked until
-+ * we unmap the kiobuf. The pages cannot be swapped out or moved
-+ * around.
-+ */
-+ ofs = iobuf->offset;
-+ pagelen = PAGE_SIZE - iobuf->offset;
-+ if (count < pagelen)
-+ pagelen = count;
-+
-+ for (i = 0; i < iobuf->nr_pages; i++) {
-+ list->tx[i] = list->rx[i] = page_address(iobuf->maplist[i]) + ofs;
-+ list->txlen[i] = list->rxlen[i] = pagelen;
-+
-+#ifdef DEBUG_SPIDEV
-+ printk(" %i: %x (%i)\n", i, list->tx[i], list->txlen[i]);
-+#endif
-+
-+ ofs = 0; /* all subsequent transfers start at beginning of a page */
-+ count = count - pagelen;
-+ pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE;
-+ }
-+ list->nr_transfers = iobuf->nr_pages;
-+
-+ /* Perform transfer on SPI bus */
-+ spi_access_bus(spi_device);
-+ spi_transfer(list);
-+ spi_release_bus(spi_device);
-+
-+ unmap_kiobuf(iobuf);
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+
-+ return res;
-+}
-+
-+int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ int spi_device = MINOR(inode->i_rdev);
-+
-+ if (spi_device >= NR_SPI_DEVICES)
-+ return -ENODEV;
-+
-+ // TODO: This interface can be used to configure the SPI bus.
-+ // Configurable options could include: Speed, Clock Polarity, Clock Phase
-+
-+ switch(cmd) {
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+/*
-+ * Open the SPI device
-+ */
-+int spidev_open(struct inode *inode, struct file *file)
-+{
-+ unsigned int spi_device = MINOR(inode->i_rdev);
-+
-+ if (spi_device >= NR_SPI_DEVICES)
-+ return -ENODEV;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ /*
-+ * 'private_data' is actually a pointer, but we overload it with the
-+ * value we want to store.
-+ */
-+ (unsigned int) file->private_data = spi_device;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Close the SPI device
-+ */
-+static int spidev_close(struct inode *inode, struct file *file)
-+{
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+static struct file_operations spidev_fops = {
-+ owner: THIS_MODULE,
-+ llseek: no_llseek,
-+ read: spidev_rd_wr,
-+ write: spidev_rd_wr,
-+ ioctl: spidev_ioctl,
-+ open: spidev_open,
-+ release: spidev_close,
-+};
-+
-+/*
-+ * Install the SPI /dev interface driver
-+ */
-+static int __init at91_spidev_init(void)
-+{
-+ int i;
-+ char name[3];
-+
-+#ifdef CONFIG_DEVFS_FS
-+ if (devfs_register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
-+#else
-+ if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
-+#endif
-+ printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR);
-+ return -EIO;
-+ }
-+
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_handle = devfs_mk_dir(NULL, "spi", NULL);
-+
-+ for (i = 0; i < NR_SPI_DEVICES; i++) {
-+ sprintf (name, "%d", i);
-+ devfs_spi[i] = devfs_register (devfs_handle, name,
-+ DEVFS_FL_DEFAULT, SPI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
-+ &spidev_fops, NULL);
-+ }
-+#endif
-+ printk(KERN_INFO "AT91 SPI driver loaded\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Remove the SPI /dev interface driver
-+ */
-+static void at91_spidev_exit(void)
-+{
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_unregister(devfs_handle);
-+ if (devfs_unregister_chrdev(SPI_MAJOR, "spi")) {
-+#else
-+ if (unregister_chrdev(SPI_MAJOR,"spi")) {
-+#endif
-+ printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR);
-+ return;
-+ }
-+}
-+
-+module_init(at91_spidev_init);
-+module_exit(at91_spidev_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200")
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/usb/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,17 @@
-+# File: drivers/at91/usb/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 USB device drivers
-+#
-+
-+O_TARGET := at91usb.o
-+
-+export-objs :=
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_USB_OHCI_AT91) += at91_usb-ohci.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/usb/at91_usb-ohci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,81 @@
-+/*
-+ * linux/drivers/at91/usb/at91_usb_ohci-at91.c
-+ *
-+ * (c) Rick Bronson
-+ *
-+ * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
-+ * original OHCI driver modifications, and reworked into a cleaner form
-+ * by Russell King <rmk@arm.linux.org.uk>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/usb.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+
-+#include <asm/arch/AT91RM9200_UHP.h>
-+
-+/*
-+ NOTE:
-+ The following is so that we don't have to include usb-ohci.h or pci.h as the
-+ usb-ohci.c driver needs these routines even when the architecture
-+ has no PCI bus...
-+*/
-+
-+extern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase,
-+ unsigned long flags, void *ohci, const char *name,
-+ const char *slot_name);
-+extern void hc_remove_ohci(void *ohci);
-+
-+static void *at91_ohci;
-+AT91PS_UHP ohci_regs;
-+
-+static int __init at91_ohci_init(void)
-+{
-+ int ret;
-+
-+ ohci_regs = ioremap(AT91_UHP_BASE, SZ_4K);
-+ if (!ohci_regs) {
-+ printk(KERN_ERR "at91_usb-ohci: ioremap failed\n");
-+ return -EIO;
-+ }
-+
-+ /* Now, enable the USB clock */
-+ AT91_SYS->PMC_SCER = AT91C_PMC_UHP; /* enable system clock */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_UHP; /* enable peripheral clock */
-+
-+ /* Take Hc out of reset */
-+ ohci_regs->UHP_HcControl = 2 << 6;
-+
-+ /* Initialise the generic OHCI driver. */
-+ ret = hc_add_ohci((struct pci_dev *) 1, AT91C_ID_UHP,
-+ (void *)ohci_regs, 0, &at91_ohci,
-+ "usb-ohci", "at91");
-+ if (ret)
-+ iounmap(ohci_regs);
-+
-+ return ret;
-+}
-+
-+static void __exit at91_ohci_exit(void)
-+{
-+ hc_remove_ohci(at91_ohci);
-+
-+ /* Force UHP_Hc to reset */
-+ ohci_regs->UHP_HcControl = 0;
-+
-+ /* Stop the USB clock. */
-+ AT91_SYS->PMC_SCDR = AT91C_PMC_UHP; /* disable system clock */
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_UHP; /* disable peripheral clock */
-+
-+ iounmap(ohci_regs);
-+}
-+
-+module_init(at91_ohci_init);
-+module_exit(at91_ohci_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/watchdog/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/watchdog/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 watchdog device driver
-+#
-+
-+O_TARGET := at91wdt.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/at91/watchdog/at91_wdt.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,193 @@
-+/*
-+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <asm/uaccess.h>
-+#include <linux/init.h>
-+
-+#define WDT_DEFAULT_TIME 5 /* 5 seconds */
-+#define WDT_MAX_TIME 256 /* 256 seconds */
-+
-+static int at91wdt_time = WDT_DEFAULT_TIME;
-+static int at91wdt_busy;
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Disable the watchdog.
-+ */
-+void at91_wdt_stop(void)
-+{
-+ AT91_SYS->ST_WDMR = AT91C_ST_EXTEN;
-+}
-+
-+/*
-+ * Enable and reset the watchdog.
-+ */
-+void at91_wdt_start(void)
-+{
-+ AT91_SYS->ST_WDMR = AT91C_ST_EXTEN | AT91C_ST_RSTEN | (((65536 * at91wdt_time) >> 8) & AT91C_ST_WDV);
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Watchdog device is opened, and watchdog starts running.
-+ */
-+static int at91_wdt_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit(1, &at91wdt_busy))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+
-+ /*
-+ * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
-+ *
-+ * Since WDV is a 16-bit counter, the maximum period is
-+ * 65536 / 0.256 = 256 seconds.
-+ */
-+
-+ at91_wdt_start();
-+ return 0;
-+}
-+
-+/*
-+ * Close the watchdog device.
-+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
-+ * disabled.
-+ */
-+static int at91_wdt_close(struct inode *inode, struct file *file)
-+{
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ /* Disable the watchdog when file is closed */
-+ at91_wdt_stop();
-+#endif
-+
-+ at91wdt_busy = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/*
-+ * Handle commands from user-space.
-+ */
-+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ unsigned int new_value;
-+ static struct watchdog_info info = {
-+ identity: "at91 watchdog",
-+ options: WDIOF_SETTIMEOUT,
-+ };
-+
-+ switch(cmd) {
-+ case WDIOC_KEEPALIVE:
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
-+ return 0;
-+
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &info, sizeof(info));
-+
-+ case WDIOC_SETTIMEOUT:
-+ if (get_user(new_value, (int *)arg))
-+ return -EFAULT;
-+ if ((new_value <= 0) || (new_value > WDT_MAX_TIME))
-+ return -EINVAL;
-+
-+ /* Restart watchdog with new time */
-+ at91wdt_time = new_value;
-+ at91_wdt_start();
-+
-+ /* Return current value */
-+ return put_user(at91wdt_time, (int *)arg);
-+
-+ case WDIOC_GETTIMEOUT:
-+ return put_user(at91wdt_time, (int *)arg);
-+
-+ case WDIOC_GETSTATUS:
-+ return put_user(0, (int *)arg);
-+
-+ case WDIOC_SETOPTIONS:
-+ if (get_user(new_value, (int *)arg))
-+ return -EFAULT;
-+ if (new_value & WDIOS_DISABLECARD)
-+ at91_wdt_stop();
-+ if (new_value & WDIOS_ENABLECARD)
-+ at91_wdt_start();
-+ return 0;
-+
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+/*
-+ * Pat the watchdog whenever device is written to.
-+ */
-+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ if (len) {
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
-+ return len;
-+ }
-+
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+static struct file_operations at91wdt_fops =
-+{
-+ .owner = THIS_MODULE,
-+ .ioctl = at91_wdt_ioctl,
-+ .open = at91_wdt_open,
-+ .release = at91_wdt_close,
-+ .write = at91_wdt_write,
-+};
-+
-+static struct miscdevice at91wdt_miscdev =
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "watchdog",
-+ .fops = &at91wdt_fops,
-+};
-+
-+static int __init at91_wdt_init(void)
-+{
-+ int res;
-+
-+ res = misc_register(&at91wdt_miscdev);
-+ if (res)
-+ return res;
-+
-+ printk("AT91 Watchdog Timer enabled (%d seconds)\n", WDT_DEFAULT_TIME);
-+ return 0;
-+}
-+
-+static void __exit at91_wdt_exit(void)
-+{
-+ misc_deregister(&at91wdt_miscdev);
-+}
-+
-+module_init(at91_wdt_init);
-+module_exit(at91_wdt_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200")
---- linux-2.4.25/drivers/block/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:32.000000000 +0200
-+++ linux-2.4.25/drivers/block/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -27,11 +27,17 @@
- obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o
- obj-$(CONFIG_BLK_DEV_XD) += xd.o
- obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
--obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
-+obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
- obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
- obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
- obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
-
- subdir-$(CONFIG_PARIDE) += paride
-
-+ifeq ($(CONFIG_ARCH_ACORN),y)
-+mod-subdirs += ../acorn/block
-+subdir-y += ../acorn/block
-+obj-y += ../acorn/block/acorn-block.o
-+endif
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.25/drivers/block/ll_rw_blk.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/block/ll_rw_blk.c 2004-03-31 17:15:09.000000000 +0200
-@@ -32,6 +32,19 @@
- #include <linux/slab.h>
- #include <linux/module.h>
-
-+/* Maybe something to cleanup in 2.3?
-+ * We shouldn't touch 0x3f2 on machines which don't have a PC floppy controller
-+ * - it may contain something else which could cause a system hang. This is
-+ * now selected by a configuration option, but maybe it ought to be in the
-+ * floppy code itself? - rmk
-+ */
-+#if defined(__i386__) || (defined(__arm__) && defined(CONFIG_ARCH_ACORN))
-+#define FLOPPY_BOOT_DISABLE
-+#endif
-+#ifdef CONFIG_BLK_DEV_FD
-+#undef FLOPPY_BOOT_DISABLE
-+#endif
-+
- /*
- * MAC Floppy IWM hooks
- */
-@@ -524,7 +537,7 @@
- elevator_init(&q->elevator, ELEVATOR_LINUS);
- blk_init_free_list(q);
- q->request_fn = rfn;
-- q->back_merge_fn = ll_back_merge_fn;
-+ q->back_merge_fn = ll_back_merge_fn;
- q->front_merge_fn = ll_front_merge_fn;
- q->merge_requests_fn = ll_merge_requests_fn;
- q->make_request_fn = __make_request;
-@@ -1540,7 +1553,7 @@
- mfm_init();
- #endif
- #ifdef CONFIG_PARIDE
-- { extern void paride_init(void); paride_init(); };
-+ { extern void paride_init(void); paride_init(); }
- #endif
- #ifdef CONFIG_MAC_FLOPPY
- swim3_init();
-@@ -1554,12 +1567,14 @@
- #ifdef CONFIG_ATARI_FLOPPY
- atari_floppy_init();
- #endif
-+#ifdef CONFIG_BLK_DEV_FD1772
-+ fd1772_init();
-+#endif
- #ifdef CONFIG_BLK_DEV_FD
- floppy_init();
--#else
--#if defined(__i386__) /* Do we even need this? */
-- outb_p(0xc, 0x3f2);
- #endif
-+#ifdef FLOPPY_BOOT_DISABLE
-+ outb_p(0xc, 0x3f2);
- #endif
- #ifdef CONFIG_CDU31A
- cdu31a_init();
-@@ -1617,7 +1632,7 @@
- jsfd_init();
- #endif
- return 0;
--};
-+}
-
- EXPORT_SYMBOL(io_request_lock);
- EXPORT_SYMBOL(end_that_request_first);
---- linux-2.4.25/drivers/cdrom/cdrom.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/cdrom/cdrom.c 2004-03-31 17:15:09.000000000 +0200
-@@ -246,8 +246,8 @@
- #define CD_DVD 0x80
-
- /* Define this to remove _all_ the debugging messages */
--/* #define ERRLOGMASK CD_NOTHING */
--#define ERRLOGMASK (CD_WARNING)
-+#define ERRLOGMASK CD_NOTHING
-+/* #define ERRLOGMASK (CD_WARNING) */
- /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
- /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
-
---- linux-2.4.25/drivers/char/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/char/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -20,10 +20,10 @@
- if [ "$CONFIG_IA64" = "y" ]; then
- bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP
- fi
-- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-- tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
-- tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
-- fi
-+fi
-+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-+ dep_tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_SERIAL
-+ dep_tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL $CONFIG_SERIAL
- fi
- dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
- if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
-@@ -132,18 +132,6 @@
- bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL
- fi
- fi
--fi
--if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
-- tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
--fi
--if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-- bool 'DC21285 serial port support' CONFIG_SERIAL_21285
-- if [ "$CONFIG_SERIAL_21285" = "y" ]; then
-- if [ "$CONFIG_OBSOLETE" = "y" ]; then
-- bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
-- fi
-- bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
-- fi
- if [ "$CONFIG_PARISC" = "y" ]; then
- bool ' PDC software console support' CONFIG_PDC_CONSOLE
- fi
-@@ -168,6 +156,16 @@
- if [ "$CONFIG_CPU_VR41XX" = "y" ]; then
- bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU
- fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV
-+fi
-+
-+source drivers/serial/Config.in
-+
-+if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then
-+ tristate 'Anakin touchscreen support' CONFIG_TOUCHSCREEN_ANAKIN
-+fi
-+
- bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
- if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
- int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
-@@ -190,6 +188,12 @@
-
- source drivers/i2c/Config.in
-
-+if [ "$CONFIG_I2C" != "n" ]; then
-+ dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C
-+fi
-+
-+source drivers/l3/Config.in
-+
- mainmenu_option next_comment
- comment 'Mice'
- tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
-@@ -245,11 +249,13 @@
- tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
- tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
- tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
-- if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-- tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
-- if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
-- tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
-- fi
-+ if [ "$CONFIG_ARM" = "y" ]; then
-+ dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
-+ dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
-+ dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
-+ dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
-+ dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
-+ dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
- fi
- tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
- tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
-@@ -326,6 +332,15 @@
- if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
- tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
- fi
-+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
-+fi
-+if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
-+fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC
-+fi
-
- tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
- tristate 'Siemens R3964 line discipline' CONFIG_R3964
---- linux-2.4.25/drivers/char/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/char/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -29,7 +29,7 @@
-
- mod-subdirs := joystick ftape drm drm-4.0 pcmcia
-
--list-multi :=
-+list-multi :=
-
- KEYMAP =defkeymap.o
- KEYBD =pc_keyb.o
-@@ -106,11 +106,39 @@
- endif
-
- ifeq ($(ARCH),arm)
-- ifneq ($(CONFIG_PC_KEYMAP),y)
-- KEYMAP =
-+ KEYMAP :=
-+ KEYBD :=
-+ ifeq ($(CONFIG_PC_KEYMAP),y)
-+ KEYMAP := defkeymap.o
- endif
-- ifneq ($(CONFIG_PC_KEYB),y)
-- KEYBD =
-+ ifeq ($(CONFIG_PC_KEYB),y)
-+ KEYBD += pc_keyb.o
-+ endif
-+ ifeq ($(CONFIG_KMI_KEYB),y)
-+ KEYBD += amba_kmi_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1111),y)
-+ KEYBD += sa1111_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_EDB7211),y)
-+ KEYBD += edb7211_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_AUTCPU12),y)
-+ KEYMAP := defkeymap.o
-+ KEYBD += clps711x_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
-+ KEYMAP = gckeymap.o
-+ KEYBD += gc_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
-+ KEYBD += cerf_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_FORTUNET),y)
-+ KEYMAP := defkeymap.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_GUIDEA07),y)
-+ KEYMAP := defkeymap.o
- endif
- endif
-
-@@ -172,11 +200,9 @@
- obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
- obj-$(CONFIG_SERIAL) += $(SERIAL)
- obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
--obj-$(CONFIG_SERIAL_21285) += serial_21285.o
--obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
--obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
- obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o
- obj-$(CONFIG_SERIAL_DEC) += decserial.o
-+obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o
-
- ifndef CONFIG_SUN_KEYBOARD
- obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
-@@ -253,6 +279,8 @@
- obj-$(CONFIG_SGI_DS1286) += ds1286.o
- obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
- obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
-+obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
-+obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
- ifeq ($(CONFIG_PPC),)
- obj-$(CONFIG_NVRAM) += nvram.o
- endif
-@@ -291,6 +319,7 @@
- obj-$(CONFIG_NWFLASH) += nwflash.o
- obj-$(CONFIG_SCx200) += scx200.o
- obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
-+obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o
-
- # Only one watchdog can succeed. We probe the hardware watchdog
- # drivers first, then the softdog driver. This means if your hardware
-@@ -319,16 +348,28 @@
- obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
- obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
- obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
-+obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
-+obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o
-+obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o
- obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
- obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
- obj-$(CONFIG_INDYDOG) += indydog.o
- obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
-
-+# I2C char devices
-+obj-$(CONFIG_I2C_DS1307) += ds1307.o
-+
- subdir-$(CONFIG_MWAVE) += mwave
- ifeq ($(CONFIG_MWAVE),y)
- obj-y += mwave/mwave.o
- endif
-
-+ifeq ($(CONFIG_ARCH_ACORN),y)
-+mod-subdirs += ../acorn/char
-+subdir-y += ../acorn/char
-+obj-y += ../acorn/char/acorn-char.o
-+endif
-+
- subdir-$(CONFIG_IPMI_HANDLER) += ipmi
- ifeq ($(CONFIG_IPMI_HANDLER),y)
- obj-y += ipmi/ipmi.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/amba_kmi_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,999 @@
-+/*
-+ * linux/drivers/char/amba_kmi_keyb.c
-+ *
-+ * AMBA Keyboard and Mouse Interface Driver
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * This keyboard driver drives a PS/2 keyboard and mouse connected
-+ * to the KMI interfaces. The KMI interfaces are nothing more than
-+ * a uart; there is no inteligence in them to do keycode translation.
-+ * We leave all that up to the keyboard itself.
-+ *
-+ * FIXES:
-+ * dirk.uffmann@nokia.com: enabled PS/2 reconnection
-+ */
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h> /* for in_interrupt */
-+#include <linux/timer.h>
-+#include <linux/init.h>
-+#include <linux/delay.h> /* for udelay */
-+#include <linux/kbd_kern.h> /* for keyboard_tasklet */
-+#include <linux/kbd_ll.h>
-+
-+#include <asm/io.h>
-+#include <asm/hardware/amba_kmi.h>
-+#include <asm/mach/amba_kmi.h>
-+#include <asm/keyboard.h>
-+
-+//#define DEBUG(s) printk s
-+#define DEBUG(s) do { } while (0)
-+
-+#define CONFIG_AMBA_PS2_RECONNECT
-+
-+#define KMI_BASE (kmi->base)
-+
-+#define KMI_RESET 0x00
-+#define KMI_RESET_POR 0x01
-+#define KMI_RESET_DONE 0x02
-+
-+#define KMI_NO_ACK 0xffff
-+
-+#define PS2_O_RESET 0xff
-+#define PS2_O_RESEND 0xfe
-+#define PS2_O_DISABLE 0xf5
-+#define PS2_O_ENABLE 0xf4
-+#define PS2_O_ECHO 0xee
-+
-+/*
-+ * Keyboard
-+ */
-+#define PS2_O_SET_DEFAULT 0xf6
-+#define PS2_O_SET_RATE_DELAY 0xf3
-+#define PS2_O_SET_SCANSET 0xf0
-+#define PS2_O_INDICATORS 0xed
-+
-+/*
-+ * Mouse
-+ */
-+#define PS2_O_SET_SAMPLE 0xf3
-+#define PS2_O_SET_STREAM 0xea
-+#define PS2_O_SET_RES 0xe8
-+#define PS2_O_SET_SCALE21 0xe7
-+#define PS2_O_SET_SCALE11 0xe6
-+#define PS2_O_REQ_STATUS 0xe9
-+
-+/*
-+ * Responses
-+ */
-+#define PS2_I_RESEND 0xfe
-+#define PS2_I_DIAGFAIL 0xfc
-+#define PS2_I_ACK 0xfa
-+#define PS2_I_BREAK 0xf0
-+#define PS2_I_ECHO 0xee
-+#define PS2_I_BAT_OK 0xaa
-+
-+static char *kmi_type[] = { "Keyboard", "Mouse" };
-+
-+static struct kmi_info *kmi_keyb;
-+static struct kmi_info *kmi_mouse;
-+
-+static inline void __kmi_send(struct kmi_info *kmi, u_int val)
-+{
-+ u_int status;
-+
-+ do {
-+ status = __raw_readb(KMISTAT);
-+ } while (!(status & KMISTAT_TXEMPTY));
-+
-+ kmi->resend_count += 1;
-+ __raw_writeb(val, KMIDATA);
-+}
-+
-+static void kmi_send(struct kmi_info *kmi, u_int val)
-+{
-+ kmi->last_tx = val;
-+ kmi->resend_count = -1;
-+ __kmi_send(kmi, val);
-+}
-+
-+static u_int kmi_send_and_wait(struct kmi_info *kmi, u_int val, u_int timeo)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ if (kmi->present == 0)
-+ return KMI_NO_ACK;
-+
-+ kmi->res = KMI_NO_ACK;
-+ kmi->last_tx = val;
-+ kmi->resend_count = -1;
-+
-+ if (current->pid != 0 && !in_interrupt()) {
-+ add_wait_queue(&kmi->wait_q, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ __kmi_send(kmi, val);
-+ schedule_timeout(timeo);
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&kmi->wait_q, &wait);
-+ } else {
-+ int i;
-+
-+ __kmi_send(kmi, val);
-+ for (i = 0; i < 1000; i++) {
-+ if (kmi->res != KMI_NO_ACK)
-+ break;
-+ udelay(100);
-+ }
-+ }
-+
-+ return kmi->res;
-+}
-+
-+/*
-+ * This lot should probably be separated into a separate file...
-+ */
-+#ifdef CONFIG_KMI_MOUSE
-+
-+#include <linux/fs.h> /* for struct file_ops */
-+#include <linux/poll.h> /* for poll_table */
-+#include <linux/miscdevice.h> /* for struct miscdev */
-+#include <linux/random.h> /* for add_mouse_randomness */
-+#include <linux/slab.h> /* for kmalloc */
-+#include <linux/smp_lock.h> /* for {un,}lock_kernel */
-+#include <linux/spinlock.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define BUF_SZ 2048
-+
-+static spinlock_t kmi_mouse_lock;
-+static int kmi_mouse_count;
-+static struct queue {
-+ u_int head;
-+ u_int tail;
-+ struct fasync_struct *fasync;
-+ unsigned char buf[BUF_SZ];
-+} *queue;
-+
-+#define queue_empty() (queue->head == queue->tail)
-+
-+static u_char get_from_queue(void)
-+{
-+ unsigned long flags;
-+ u_char res;
-+
-+ spin_lock_irqsave(&kmi_mouse_lock, flags);
-+ res = queue->buf[queue->tail];
-+ queue->tail = (queue->tail + 1) & (BUF_SZ-1);
-+ spin_unlock_irqrestore(&kmi_mouse_lock, flags);
-+
-+ return res;
-+}
-+
-+static ssize_t
-+kmi_mouse_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ ssize_t i = count;
-+
-+ if (queue_empty()) {
-+ int ret;
-+
-+ if (file->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ ret = wait_event_interruptible(kmi_mouse->wait_q, !queue_empty());
-+ if (ret)
-+ return ret;
-+ }
-+ while (i > 0 && !queue_empty()) {
-+ u_char c;
-+ c = get_from_queue();
-+ put_user(c, buf++);
-+ i--;
-+ }
-+ if (count - i)
-+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-+ return count - i;
-+}
-+
-+static ssize_t
-+kmi_mouse_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-+{
-+ ssize_t retval = 0;
-+
-+ if (count > 32)
-+ count = 32;
-+
-+ do {
-+ char c;
-+ get_user(c, buf++);
-+ kmi_send_and_wait(kmi_mouse, c, HZ);
-+ retval++;
-+ } while (--count);
-+
-+ if (retval)
-+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-+
-+ return retval;
-+}
-+
-+static unsigned int
-+kmi_mouse_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait(file, &kmi_mouse->wait_q, wait);
-+ return (!queue_empty()) ? POLLIN | POLLRDNORM : 0;
-+}
-+
-+static int
-+kmi_mouse_release(struct inode *inode, struct file *file)
-+{
-+ lock_kernel();
-+ fasync_helper(-1, file, 0, &queue->fasync);
-+ if (--kmi_mouse_count == 0)
-+ kmi_send_and_wait(kmi_mouse, PS2_O_DISABLE, HZ);
-+ unlock_kernel();
-+ return 0;
-+}
-+
-+static int
-+kmi_mouse_open(struct inode *inode, struct file *file)
-+{
-+ if (kmi_mouse_count++)
-+ return 0;
-+ queue->head = queue->tail = 0;
-+ kmi_send_and_wait(kmi_mouse, PS2_O_ENABLE, HZ);
-+ return 0;
-+}
-+
-+static int
-+kmi_mouse_fasync(int fd, struct file *filp, int on)
-+{
-+ int retval = fasync_helper(fd, filp, on, &queue->fasync);
-+ if (retval > 0)
-+ retval = 0;
-+ return retval;
-+}
-+
-+static struct file_operations ps_fops = {
-+ read: kmi_mouse_read,
-+ write: kmi_mouse_write,
-+ poll: kmi_mouse_poll,
-+ open: kmi_mouse_open,
-+ release: kmi_mouse_release,
-+ fasync: kmi_mouse_fasync,
-+};
-+
-+static struct miscdevice ps_mouse = {
-+ minor: PSMOUSE_MINOR,
-+ name: "psaux",
-+ fops: &ps_fops,
-+};
-+
-+static u_char kmi_mse_init_string[] = {
-+ PS2_O_DISABLE,
-+ PS2_O_SET_SAMPLE, 100,
-+ PS2_O_SET_RES, 3,
-+ PS2_O_SET_SCALE21
-+};
-+
-+/*
-+ * The "normal" mouse scancode processing
-+ */
-+static void kmi_mse_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+ u_int head;
-+
-+ add_mouse_randomness(val);
-+
-+#ifdef CONFIG_AMBA_PS2_RECONNECT
-+ /* Try to detect a hot-plug event on the PS/2 mouse port */
-+ switch (kmi->hotplug_state) {
-+ case 0:
-+ /* Maybe we lost contact... */
-+ if (val == PS2_I_BAT_OK) {
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ }
-+ break;
-+
-+ case 1:
-+ /* Again, maybe (but only maybe) we lost contact... */
-+ if (val == 0) {
-+ kmi->hotplug_state++;
-+ kmi_send(kmi, PS2_O_REQ_STATUS);
-+ DEBUG(("%s: Got 0xAA 0x00. Sent Status Request\n", kmi->name));
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: No 0x00 followed 0xAA. No reconnect.\n", kmi->name));
-+ }
-+ break;
-+
-+ case 2:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK)
-+ kmi->hotplug_state++;
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 3:
-+ /* check if data reporting is still enabled, then no POR has happend */
-+ kmi->reconnect = !(val & 1<<5);
-+ DEBUG(("%s: Data reporting disabled?: (%d)\n", kmi->name, kmi->reconnect));
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ break;
-+
-+ case 4:
-+ /* Eat up one status byte */
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ break;
-+
-+ case 5:
-+ /* Eat up another status byte */
-+ if (kmi->reconnect) {
-+ kmi->config_num = 0;
-+ kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
-+ kmi->config_num++;
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: False Alarm...\n", kmi->name));
-+ }
-+ break;
-+
-+ case 6:
-+ if (val == PS2_I_ACK && kmi->config_num < sizeof(kmi_mse_init_string)) {
-+ kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
-+ kmi->config_num++;
-+ DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
-+ } else {
-+ if (val == PS2_I_ACK) {
-+ DEBUG(("%s: Now enable the mouse again...\n", kmi->name));
-+ queue->head = queue->tail = 0;
-+ kmi_send(kmi, PS2_O_ENABLE);
-+ kmi->hotplug_state++;
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ }
-+ break;
-+
-+ case 7:
-+ /* Eat up last acknowledge from enable */
-+ if (val == PS2_I_ACK)
-+ printk(KERN_ERR "%s: reconnected\n", kmi->name);
-+ else
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+
-+ kmi->hotplug_state = 0;
-+ break;
-+
-+ } /* switch (kmi->hotplug_state) */
-+
-+ /* while inside hotplug mechanism, don't misinterpret values */
-+ if (kmi->hotplug_state > 2)
-+ return;
-+#endif
-+
-+ /* We are waiting for the mouse to respond to a kmi_send_and_wait() */
-+ if (kmi->res == KMI_NO_ACK) {
-+ if (val == PS2_I_RESEND) {
-+ if (kmi->resend_count < 5)
-+ __kmi_send(kmi, kmi->last_tx);
-+ else {
-+ printk(KERN_ERR "%s: too many resends\n", kmi->name);
-+ return;
-+ }
-+ }
-+
-+ if (val == PS2_I_ACK) {
-+ kmi->res = val;
-+ wake_up(&kmi->wait_q);
-+ }
-+ return;
-+ }
-+
-+ /* The mouse autonomously send new data, so wake up mouse_read() */
-+ if (queue) {
-+ head = queue->head;
-+ queue->buf[head] = val;
-+ head = (head + 1) & (BUF_SZ - 1);
-+ if (head != queue->tail) {
-+ queue->head = head;
-+ kill_fasync(&queue->fasync, SIGIO, POLL_IN);
-+ wake_up_interruptible(&kmi->wait_q);
-+ }
-+ }
-+}
-+
-+static int kmi_init_mouse(struct kmi_info *kmi)
-+{
-+ u_int ret, i;
-+
-+ if (kmi->present) {
-+ kmi->rx = kmi_mse_intr;
-+
-+ for (i = 0; i < sizeof(kmi_mse_init_string); i++) {
-+ ret = kmi_send_and_wait(kmi, kmi_mse_init_string[i], HZ);
-+ if (ret != PS2_I_ACK)
-+ printk("%s: didn't get ack (0x%2.2x)\n",
-+ kmi->name, ret);
-+ }
-+ }
-+
-+ queue = kmalloc(sizeof(*queue), GFP_KERNEL);
-+ if (queue) {
-+ memset(queue, 0, sizeof(*queue));
-+ misc_register(&ps_mouse);
-+ ret = 0;
-+ } else
-+ ret = -ENOMEM;
-+
-+ return ret;
-+}
-+#endif /* CONFIG_KMI_MOUSE */
-+
-+/*
-+ * The "program" we send to the keyboard to set it up how we want it:
-+ * - default typematic delays
-+ * - scancode set 1
-+ */
-+static u_char kmi_kbd_init_string[] = {
-+ PS2_O_DISABLE,
-+ PS2_O_SET_DEFAULT,
-+ PS2_O_SET_SCANSET, 0x01,
-+ PS2_O_ENABLE
-+};
-+
-+static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs);
-+
-+static int __kmi_init_keyboard(struct kmi_info *kmi)
-+{
-+ u_int ret, i;
-+
-+ if (!kmi->present)
-+ return 0;
-+
-+ kmi->rx = kmi_kbd_intr;
-+
-+ for (i = 0; i < sizeof(kmi_kbd_init_string); i++) {
-+ ret = kmi_send_and_wait(kmi, kmi_kbd_init_string[i], HZ);
-+ if (ret != PS2_I_ACK)
-+ printk("%s: didn't ack (0x%2.2x)\n",
-+ kmi->name, ret);
-+ }
-+
-+ return 0;
-+}
-+
-+static void kmi_kbd_init_tasklet(unsigned long k)
-+{
-+ struct kmi_info *kmi = (struct kmi_info *)k;
-+ __kmi_init_keyboard(kmi);
-+}
-+
-+static DECLARE_TASKLET_DISABLED(kmikbd_init_tasklet, kmi_kbd_init_tasklet, 0);
-+
-+/*
-+ * The "normal" keyboard scancode processing
-+ */
-+static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+#ifdef CONFIG_AMBA_PS2_RECONNECT
-+ /* Try to detect a hot-plug event on the PS/2 keyboard port */
-+ switch (kmi->hotplug_state) {
-+ case 0:
-+ /* Maybe we lost contact... */
-+ if (val == PS2_I_BAT_OK) {
-+ kmi_send(kmi, PS2_O_SET_SCANSET);
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ }
-+ break;
-+
-+ case 1:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK) {
-+ /* Request scan code set: '2' if POR has happend, '1' is false alarm */
-+ kmi_send(kmi, 0);
-+ kmi->hotplug_state++;
-+ }
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 2:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK)
-+ kmi->hotplug_state++;
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 3:
-+ kmi->hotplug_state = 0;
-+ if (val == 2) {
-+ DEBUG(("%s: POR detected. Scan code is: (%d)\n", kmi->name, val));
-+ kmi->present = 1;
-+ tasklet_schedule(&kmikbd_init_tasklet);
-+ printk(KERN_ERR "%s: reconnected\n", kmi->name);
-+ return;
-+ }
-+ else
-+ DEBUG(("%s: False Alarm...\n", kmi->name));
-+ break;
-+
-+ } /* switch (kmi->hotplug_state) */
-+#endif
-+
-+ if (val == PS2_I_DIAGFAIL) {
-+ printk(KERN_ERR "%s: diagnostic failed\n", kmi->name);
-+ return;
-+ }
-+
-+ /* We are waiting for the keyboard to respond to a kmi_send_and_wait() */
-+ if (kmi->res == KMI_NO_ACK) {
-+ if (val == PS2_I_RESEND) {
-+ if (kmi->resend_count < 5)
-+ __kmi_send(kmi, kmi->last_tx);
-+ else {
-+ printk(KERN_ERR "%s: too many resends\n", kmi->name);
-+ return;
-+ }
-+ }
-+
-+ if (val >= 0xee) {
-+ kmi->res = val;
-+ wake_up(&kmi->wait_q);
-+ }
-+ return;
-+ }
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+ handle_scancode(val, !(val & 0x80));
-+ tasklet_schedule(&keyboard_tasklet);
-+#endif
-+}
-+
-+static void kmi_intr(int nr, void *devid, struct pt_regs *regs)
-+{
-+ struct kmi_info *kmi = devid;
-+ u_int status = __raw_readb(KMIIR);
-+
-+ if (status & KMIIR_RXINTR) {
-+ u_int val = __raw_readb(KMIDATA);
-+
-+ if (kmi->rx)
-+ kmi->rx(kmi, val, regs);
-+ }
-+}
-+
-+static int kmi_init_keyboard(struct kmi_info *kmi)
-+{
-+ kmikbd_init_tasklet.data = (unsigned long)kmi;
-+ tasklet_enable(&kmikbd_init_tasklet);
-+
-+ return __kmi_init_keyboard(kmi);
-+}
-+
-+/*
-+ * Reset interrupt handler
-+ */
-+static void __init
-+kmi_reset_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+ if (kmi->state == KMI_RESET) {
-+ if (val == PS2_I_ACK)
-+ kmi->state = KMI_RESET_POR;
-+ else {
-+ val = KMI_NO_ACK;
-+ goto finished;
-+ }
-+ } else if (kmi->state == KMI_RESET_POR) {
-+finished:
-+ kmi->res = val;
-+ kmi->state = KMI_RESET_DONE;
-+ kmi->rx = NULL;
-+ wake_up(&kmi->wait_q);
-+ }
-+}
-+
-+/*
-+ * Reset the device plugged into this interface
-+ */
-+static int __init kmi_reset(struct kmi_info *kmi)
-+{
-+ u_int res;
-+ int ret = 0;
-+
-+ kmi->state = KMI_RESET;
-+ kmi->rx = kmi_reset_intr;
-+ res = kmi_send_and_wait(kmi, PS2_O_RESET, HZ);
-+ kmi->rx = NULL;
-+
-+ if (res != PS2_I_BAT_OK) {
-+ printk(KERN_ERR "%s: reset failed; ", kmi->name);
-+ if (kmi->res != KMI_NO_ACK)
-+ printk("code 0x%2.2x\n", kmi->res);
-+ else
-+ printk("no ack\n");
-+ ret = -EINVAL;
-+ }
-+ return ret;
-+}
-+
-+static int __init kmi_init_one_interface(struct kmi_info *kmi)
-+{
-+ u_int stat;
-+ int ret = -ENODEV;
-+
-+ init_waitqueue_head(&kmi->wait_q);
-+
-+ printk(KERN_INFO "%s at 0x%8.8x on irq %d (%s)\n", kmi->name,
-+ kmi->base, kmi->irq, kmi_type[kmi->type]);
-+
-+ /*
-+ * Initialise the KMI interface
-+ */
-+ __raw_writeb(kmi->divisor, KMICLKDIV);
-+ __raw_writeb(KMICR_EN, KMICR);
-+
-+ /*
-+ * Check that the data and clock lines are OK.
-+ */
-+ stat = __raw_readb(KMISTAT);
-+ if ((stat & (KMISTAT_IC|KMISTAT_ID)) != (KMISTAT_IC|KMISTAT_ID)) {
-+ printk(KERN_ERR "%s: %s%s%sline%s stuck low\n", kmi->name,
-+ (stat & KMISTAT_IC) ? "" : "clock ",
-+ (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "and ",
-+ (stat & KMISTAT_ID) ? "" : "data ",
-+ (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "s");
-+ goto bad;
-+ }
-+
-+ /*
-+ * Claim the appropriate interrupts
-+ */
-+ ret = request_irq(kmi->irq, kmi_intr, 0, kmi->name, kmi);
-+ if (ret)
-+ goto bad;
-+
-+ /*
-+ * Enable the receive interrupt, and reset the device.
-+ */
-+ __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
-+ kmi->present = 1;
-+ kmi->present = kmi_reset(kmi) == 0;
-+
-+ switch (kmi->type) {
-+ case KMI_KEYBOARD:
-+ ret = kmi_init_keyboard(kmi);
-+ break;
-+
-+#ifdef CONFIG_KMI_MOUSE
-+ case KMI_MOUSE:
-+ ret = kmi_init_mouse(kmi);
-+ break;
-+#endif
-+ }
-+
-+ return ret;
-+
-+bad:
-+ /*
-+ * Oh dear, the interface was bad, disable it.
-+ */
-+ __raw_writeb(0, KMICR);
-+ return ret;
-+}
-+
-+#ifdef CONFIG_VT
-+/*
-+ * The fragment between #ifdef above and #endif * CONFIG_VT *
-+ * is from the pc_keyb.c driver. It is not copyrighted under the
-+ * above notice. This code is by various authors; please see
-+ * drivers/char/pc_keyb.c for further information.
-+ */
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+#define E1_PAUSE 119
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static u_char e0_keys[128] = {
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ E0_KPENTER, E0_RCTRL, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, E0_KPSLASH, 0, E0_PRSCR,
-+ E0_RALT, 0, 0, 0,
-+ 0, E0_F13, E0_F14, E0_HELP,
-+ E0_DO, E0_F17, 0, 0,
-+ 0, 0, E0_BREAK, E0_HOME,
-+ E0_UP, E0_PGUP, 0, E0_LEFT,
-+ E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, E0_MSLW,
-+ E0_MSRW, E0_MSTM, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, E0_MACRO,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0
-+};
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+u_char kmi_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+int kmi_kbd_setkeycode(u_int scancode, u_int keycode)
-+{
-+ if (scancode < 128 || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int kmi_kbd_getkeycode(u_int scancode)
-+{
-+ if (scancode < 128 || scancode > 255)
-+ return -EINVAL;
-+ return e0_keys[scancode - 128];
-+}
-+
-+int kmi_kbd_translate(u_char scancode, u_char *keycode, char raw_mode)
-+{
-+ static int prev_scancode = 0;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xff is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ int old_scancode = prev_scancode;
-+
-+ prev_scancode = 0;
-+ switch (old_scancode) {
-+ case 0xe0:
-+ /*
-+ * The keyboard maintains its own internal caps lock
-+ * and num lock status. In caps lock mode, E0 AA
-+ * precedes make code and E0 2A follows break code.
-+ * In numlock mode, E0 2A precedes make code, and
-+ * E0 AA follows break code. We do our own book-
-+ * keeping, so we will just ignore these.
-+ *
-+ * For my keyboard there is no caps lock mode, but
-+ * there are both Shift-L and Shift-R modes. The
-+ * former mode generates E0 2A / E0 AA pairs, the
-+ * latter E0 B6 / E0 36 pairs. So, we should also
-+ * ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scancode e0 %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+
-+ case 0xe1:
-+ if (scancode == 0x1d)
-+ prev_scancode = 0x100;
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scancode e1 %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+
-+ case 0x100:
-+ if (scancode == 0x45)
-+ *keycode = E1_PAUSE;
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scan code e1 1d %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+char kmi_kbd_unexpected_up(u_char keycode)
-+{
-+ return 0x80;
-+}
-+
-+void kmi_kbd_leds(u_char leds)
-+{
-+ struct kmi_info *kmi = kmi_keyb;
-+ u_int ret;
-+
-+ if (kmi) {
-+ ret = kmi_send_and_wait(kmi, PS2_O_INDICATORS, HZ);
-+ if (ret != KMI_NO_ACK)
-+ ret = kmi_send_and_wait(kmi, leds, HZ);
-+ if (ret == KMI_NO_ACK)
-+ kmi->present = 0;
-+ }
-+}
-+
-+int __init kmi_kbd_init(void)
-+{
-+ int ret = -ENODEV;
-+
-+ if (kmi_keyb) {
-+ strcpy(kmi_keyb->name, "kmikbd");
-+ ret = kmi_init_one_interface(kmi_keyb);
-+ }
-+
-+ if (ret == 0) {
-+ k_setkeycode = kmi_kbd_setkeycode;
-+ k_getkeycode = kmi_kbd_getkeycode;
-+ k_translate = kmi_kbd_translate;
-+ k_unexpected_up = kmi_kbd_unexpected_up;
-+ k_leds = kmi_kbd_leds;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_xlate = kmi_kbd_sysrq_xlate;
-+ k_sysrq_key = 0x54;
-+#endif
-+ }
-+
-+ return ret;
-+}
-+
-+#endif /* CONFIG_VT */
-+
-+int register_kmi(struct kmi_info *kmi)
-+{
-+ struct kmi_info **kmip = NULL;
-+ int ret;
-+
-+ if (kmi->type == KMI_KEYBOARD)
-+ kmip = &kmi_keyb;
-+ else if (kmi->type == KMI_MOUSE)
-+ kmip = &kmi_mouse;
-+
-+ ret = -EINVAL;
-+ if (kmip) {
-+ ret = -EBUSY;
-+ if (!*kmip) {
-+ *kmip = kmi;
-+ ret = 0;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_KMI_MOUSE
-+static int __init kmi_init(void)
-+{
-+ int ret = -ENODEV;
-+
-+ if (kmi_mouse) {
-+ strcpy(kmi_mouse->name, "kmimouse");
-+ ret = kmi_init_one_interface(kmi_mouse);
-+ }
-+
-+ return ret;
-+}
-+
-+__initcall(kmi_init);
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/anakin_ts.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,208 @@
-+/*
-+ * linux/drivers/char/anakin_ts.c
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 18-Apr-2001 TTC Created
-+ * 23-Oct-2001 dwmw2 Cleanup
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/wait.h>
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/init.h>
-+#include <linux/compiler.h>
-+#include <linux/interrupt.h>
-+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+
-+/*
-+ * TSBUF_SIZE must be a power of two
-+ */
-+#define ANAKIN_TS_MINOR 16
-+#define TSBUF_SIZE 256
-+#define NEXT(index) (((index) + 1) & (TSBUF_SIZE - 1))
-+
-+static unsigned short buffer[TSBUF_SIZE][4];
-+static int head, tail;
-+static DECLARE_WAIT_QUEUE_HEAD(queue);
-+static DECLARE_MUTEX(open_sem);
-+static spinlock_t tailptr_lock = SPIN_LOCK_UNLOCKED;
-+static struct fasync_struct *fasync;
-+
-+/*
-+ * Interrupt handler and standard file operations
-+ */
-+static void
-+anakin_ts_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status = __raw_readl(IO_BASE + IO_CONTROLLER + 0x24);
-+
-+ /*
-+ * iPAQ format (u16 pressure, x, y, millisecs)
-+ */
-+ switch (status >> 20 & 3) {
-+ case 0:
-+ return;
-+ case 2:
-+ buffer[head][0] = 0;
-+ break;
-+ default:
-+ buffer[head][0] = 0x7f;
-+ }
-+
-+ if (unlikely((volatile int)tail == NEXT(head))) {
-+ /* Run out of space in the buffer. Move the tail pointer */
-+ spin_lock(&tailptr_lock);
-+
-+ if ((volatile int)tail == NEXT(head)) {
-+ tail = NEXT(NEXT(head));
-+ }
-+ spin_unlock(&tailptr_lock);
-+ }
-+
-+ buffer[head][1] = status >> 2 & 0xff;
-+ buffer[head][2] = status >> 12 & 0xff;
-+ buffer[head][3] = jiffies;
-+ mb();
-+ head = NEXT(head);
-+
-+ wake_up_interruptible(&queue);
-+ kill_fasync(&fasync, SIGIO, POLL_IN);
-+
-+}
-+
-+static ssize_t
-+anakin_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
-+{
-+ unsigned short data[4];
-+ ssize_t written = 0;
-+
-+ if (head == tail) {
-+ if (filp->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ if (wait_event_interruptible(queue, (volatile int)head != (volatile int)tail))
-+ return -ERESTARTSYS;
-+ }
-+
-+ while ((volatile int)head != (volatile int)tail && count >= sizeof data) {
-+ /* Copy the data out with the spinlock held, so the
-+ interrupt can't fill the buffer and move the tail
-+ pointer while we're doing it */
-+ spin_lock_irq(&tailptr_lock);
-+
-+ memcpy(data, buffer[tail], sizeof data);
-+ tail = NEXT(tail);
-+
-+ spin_unlock_irq(&tailptr_lock);
-+
-+ if (copy_to_user(buf, data, sizeof data))
-+ return -EFAULT;
-+ count -= sizeof data;
-+ buf += sizeof data;
-+ written += sizeof data;
-+ }
-+ return written ? written : -EINVAL;
-+}
-+
-+static unsigned int
-+anakin_ts_poll(struct file *filp, poll_table *wait)
-+{
-+ poll_wait(filp, &queue, wait);
-+ return head != tail ? POLLIN | POLLRDNORM : 0;
-+}
-+
-+static int
-+anakin_ts_ioctl(struct inode *inode, struct file *filp,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ /*
-+ * Future ioctl goes here
-+ */
-+ return 0;
-+}
-+
-+static int
-+anakin_ts_open(struct inode *inode, struct file *filp)
-+{
-+ if (down_trylock(&open_sem))
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+static int
-+anakin_ts_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &fasync);
-+}
-+
-+static int
-+anakin_ts_release(struct inode *inode, struct file *filp)
-+{
-+ anakin_ts_fasync(-1, filp, 0);
-+ up(&open_sem);
-+ return 0;
-+}
-+
-+static struct file_operations anakin_ts_fops = {
-+ owner: THIS_MODULE,
-+ read: anakin_ts_read,
-+ poll: anakin_ts_poll,
-+ ioctl: anakin_ts_ioctl,
-+ open: anakin_ts_open,
-+ release: anakin_ts_release,
-+ fasync: anakin_ts_fasync,
-+};
-+
-+static struct miscdevice anakin_ts_miscdev = {
-+ ANAKIN_TS_MINOR,
-+ "anakin_ts",
-+ &anakin_ts_fops
-+};
-+
-+/*
-+ * Initialization and exit routines
-+ */
-+int __init
-+anakin_ts_init(void)
-+{
-+ int retval;
-+
-+ if ((retval = request_irq(IRQ_TOUCHSCREEN, anakin_ts_handler,
-+ SA_INTERRUPT, "anakin_ts", 0))) {
-+ printk(KERN_WARNING "anakin_ts: failed to get IRQ\n");
-+ return retval;
-+ }
-+ __raw_writel(1, IO_BASE + IO_CONTROLLER + 8);
-+ misc_register(&anakin_ts_miscdev);
-+
-+ printk(KERN_NOTICE "Anakin touchscreen driver initialised\n");
-+
-+ return 0;
-+}
-+
-+void __exit
-+anakin_ts_exit(void)
-+{
-+ __raw_writel(0, IO_BASE + IO_CONTROLLER + 8);
-+ free_irq(IRQ_TOUCHSCREEN, 0);
-+ misc_deregister(&anakin_ts_miscdev);
-+}
-+
-+module_init(anakin_ts_init);
-+module_exit(anakin_ts_exit);
-+
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_DESCRIPTION("Anakin touchscreen driver");
-+MODULE_SUPPORTED_DEVICE("touchscreen/anakin");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/cerf_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,380 @@
-+/*
-+ cerf_keyb.c: This is the end. Daniel is writing a device driver!!!
-+*/
-+#include <linux/config.h>
-+
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/mm.h>
-+#include <linux/signal.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/delay.h>
-+#include <linux/random.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/smp_lock.h>
-+#include <linux/timer.h>
-+
-+#include <asm/keyboard.h>
-+#include <asm/bitops.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+
-+#include <asm/io.h>
-+
-+#define KBD_REPORT_UNKN
-+
-+#define KBD_REPORT_ERR /* Report keyboard errors */
-+#define KBD_REPORT_UNKN /* Report unknown scan codes */
-+#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */
-+#define KBD_NO_DATA (-1) /* No data */
-+#define KBD_REPEAT_START (0x20)
-+#define KBD_REPEAT_CONTINUE (0x05)
-+#define KBD_KEY_DOWN_MAX (0x10)
-+#define UINT_LEN (20)
-+#define SC_LIM (69)
-+#define KBD_ROWS (5)
-+#define KBD_COLUMNS (8)
-+
-+#define KBD_KEYUP (0x80)
-+#define KBD_MODESCAN (0x7f)
-+#define KBD_CAPSSCAN (0x3a)
-+#define KBD_SHIFTSCAN (0x2a)
-+#define KBD_NUMCURSCAN (0x7c)
-+#define KBD_CTRLSCAN (0x1d)
-+#define KBD_ALTSCAN (0x38)
-+
-+#define KBD_UP_OFF (0)
-+#define KBD_UP_ON (1)
-+#define KBD_DOWN (2)
-+#define KBD_DOWN_HOLD (3)
-+
-+
-+
-+static unsigned char handle_kbd_event(void);
-+static unsigned char kbd_read_input(void);
-+static void column_set(unsigned int column);
-+static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]);
-+
-+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
-+static struct timer_list kbd_timer;
-+
-+static short mode_ena = 0;
-+static short numcur_ena = 0;
-+static short shift_ena = 0;
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+#define E1_PAUSE 119
-+#define E0_MACRO 112
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+#define E0_OK 124
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00},
-+ {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00},
-+ {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00},
-+ {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00},
-+ {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00}
-+};
-+
-+static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
-+ {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, //
-+ {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00},
-+ {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, //
-+ {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00}
-+};
-+
-+static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
-+ {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00},
-+ {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00},
-+ {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00},
-+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00}
-+};
-+
-+static void column_set(unsigned int column)
-+{
-+ if (column < 0)
-+ {
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
-+ }
-+ else
-+ {
-+ if(column < 4)
-+ {
-+ CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF);
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
-+ }
-+ else
-+ {
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
-+ CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF);
-+ }
-+ }
-+}
-+
-+static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS])
-+{
-+ int i, j;
-+
-+ for(i = 0; i < KBD_COLUMNS; i++)
-+ {
-+ column_set(i);
-+ udelay(50);
-+ for(j = 0; j < KBD_ROWS; j++)
-+ {
-+ if(mode_ena)
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0;
-+ else if(numcur_ena)
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0;
-+ else
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0;
-+ }
-+ }
-+ column_set(-1);
-+
-+ return 0;
-+}
-+
-+static unsigned char kbd_read_input(void)
-+{
-+ int i, j, k, l;
-+ unsigned char prev;
-+ static unsigned char count = 0;
-+
-+ static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0}};
-+ unsigned char inputcode[KBD_ROWS][KBD_COLUMNS];
-+
-+ memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS));
-+ scancodes(inputcode);
-+
-+ for(i = 0; i < KBD_COLUMNS; i++)
-+ {
-+ for(j = 0; j < KBD_ROWS; j++)
-+ {
-+// if(oldcodes[j][i] == 0xe0)
-+// oldcodes[j][i] =
-+ if(oldcodes[j][i] != inputcode[j][i])
-+ {
-+ // Value of the key before entering this function
-+ prev = oldcodes[j][i];
-+
-+ // KEYUP
-+ if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP))
-+ {
-+ oldcodes[j][i] |= KBD_KEYUP;
-+
-+ if(mode_ena == KBD_UP_ON)
-+ mode_ena = KBD_UP_OFF;
-+ if(prev == KBD_MODESCAN)
-+ if(mode_ena == KBD_DOWN_HOLD)
-+ mode_ena = KBD_UP_OFF;
-+ else if(mode_ena == KBD_DOWN)
-+ mode_ena = KBD_UP_ON;
-+ if(mode_ena == KBD_DOWN)
-+ mode_ena = KBD_DOWN_HOLD;
-+ }
-+ // RESET KEYUP
-+ else if(oldcodes[j][i] & KBD_KEYUP)
-+ oldcodes[j][i] = 0;
-+ // KEY DOWN
-+ else
-+ {
-+ oldcodes[j][i] = inputcode[j][i];
-+
-+ // Parse out mode modifiers before the keyboard interpreter can touch them
-+ if(inputcode[j][i] == KBD_MODESCAN)
-+ {
-+ if(!mode_ena)
-+ mode_ena = KBD_DOWN;
-+ continue;
-+ }
-+ if(inputcode[j][i] == KBD_NUMCURSCAN)
-+ {
-+ numcur_ena = numcur_ena?0:1;
-+ continue;
-+ }
-+ }
-+ //printk("Modified: (%#x,%#x), ipv:%#x, To: (%#.2x), From: (%#.2x), Flags:%d,%d,%d\r\n", j, i, inputcode[j][i], oldcodes[j][i], prev, mode_ena, shift_ena, numcur_ena);
-+ return oldcodes[j][i];
-+ }
-+ }
-+ }
-+
-+ return (unsigned char)(KBD_NO_DATA);
-+}
-+
-+int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode;
-+
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+static inline void handle_keyboard_event(unsigned char scancode)
-+{
-+ if(scancode != (unsigned char)(KBD_NO_DATA))
-+ {
-+#ifdef CONFIG_VT
-+ handle_scancode(scancode, !(scancode & KBD_KEYUP));
-+#endif
-+ tasklet_schedule(&keyboard_tasklet);
-+ }
-+}
-+
-+static unsigned char handle_kbd_event(void)
-+{
-+ unsigned char scancode;
-+
-+ scancode = kbd_read_input();
-+ handle_keyboard_event(scancode);
-+
-+ return 0;
-+}
-+
-+/* Handle the automatic interrupts handled by the timer */
-+static void keyboard_interrupt(unsigned long foo)
-+{
-+ spin_lock_irq(&kbd_controller_lock);
-+ handle_kbd_event();
-+ spin_unlock_irq(&kbd_controller_lock);
-+
-+ kbd_timer.expires = 8 + jiffies;
-+ kbd_timer.data = 0x00000000;
-+ kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
-+
-+ add_timer(&kbd_timer);
-+}
-+
-+void cerf_leds(unsigned char leds)
-+{
-+}
-+char cerf_unexpected_up(unsigned char keycode)
-+{
-+return 0;
-+}
-+int cerf_getkeycode(unsigned int scancode)
-+{
-+return 0;
-+}
-+int cerf_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+return 0;
-+}
-+
-+void cerf_kbd_init_hw(void)
-+{
-+ printk("Starting Cerf PDA Keyboard Driver... ");
-+
-+ k_setkeycode = cerf_setkeycode;
-+ k_getkeycode = cerf_getkeycode;
-+ k_translate = cerf_kbd_translate;
-+ k_unexpected_up = cerf_unexpected_up;
-+ k_leds = cerf_leds;
-+
-+ GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24));
-+ kbd_timer.expires = 40 + jiffies;
-+ kbd_timer.data = 0x00000000;
-+ kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
-+
-+ add_timer(&kbd_timer);
-+
-+ printk("Done\r\n");
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/clps711x_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,547 @@
-+/*
-+ * drivers/char/clps711x_keyb.c
-+ *
-+ * Copyright (C) 2001 Thomas Gleixner <gleixner@autronix.de>
-+ *
-+ * based on drivers/edb7211_keyb.c, which is copyright (C) 2000 Bluemug Inc.
-+ *
-+ * Keyboard driver for ARM Linux on EP7xxx and CS89712 processors
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation. See the file COPYING
-+ * in the main directory of this archive for more details.
-+ *
-+ *
-+ * Hardware:
-+ *
-+ * matrix scan keyboards based on EP7209,7211,7212,7312 and CS89712
-+ * on chip keyboard scanner.
-+ * Adaption for different machines is done in init function.
-+ *
-+ * Basic Function:
-+ *
-+ * Basicly the driver is interrupt driven. It sets all column drivers
-+ * high. If any key is pressed, a interrupt occures. Now a seperate scan of
-+ * each column is done. This scan is timer based, because we use a keyboard
-+ * interface with decoupling capacitors (neccecary if you want to survive
-+ * EMC compliance tests). Always one line is set high. When next timer event
-+ * occures the scan data on port A are valid. This makes also sure, that no
-+ * spurious keys are scanned. The kbd int on these CPU's is not deglitched!
-+ * After scanning all columns, we switch back to int mode, if no key is
-+ * pressed. If any is pressed we reschedule the scan within a programmable
-+ * delay. If we would switch back to interrupt mode as long as a key is pressed,
-+ * we come right back to the interrupt, because the int. is level triggered !
-+ * The timer based scan of the seperate columns can also be done in one
-+ * timer event (set fastscan to 1).
-+ *
-+ * Summary:
-+ * The design of this keyboard controller chip is stupid at all !
-+ *
-+ * Matrix translation:
-+ * The matrix translation table is based on standard XT scancodes. Maybe
-+ * you have to adjust the KEYISPRINTABLE macro if you set other codes.
-+ *
-+ * HandyKey:
-+ *
-+ * On small matrix keyboards you don't have enough keys for operation.
-+ * The intention was to implement a operation mode as it's used on handys.
-+ * You can rotate trough four scancode levels and produce e.g. with a 4x3
-+ * matrix 4*3*4 = 48 different keycodes. That's basicly enough for editing
-+ * filenames or things like that. The HandyKey function takes care about
-+ * nonprintable keys like cursors, backspace, del ...
-+ * If a key is pressed and is a printable keycode, the code is put to the
-+ * main keyboard handler and a cursor left is applied. If you press the same
-+ * key again, the current character is deleted and the next level character
-+ * is applied. (e.g. 1, a, b, c, 1 ....). If you press a different key, the
-+ * driver applies cursor right, before processing the new key.
-+ * The autocomplete feature moves the cursor right, if you do not press a
-+ * key within a programmable time.
-+ * If HandyKey is off, the keyboard behaviour is that of a standard keyboard
-+ * HandyKey can be en/disabled from userspace with the proc/keyboard entry
-+ *
-+ * proc/keyboard:
-+ *
-+ * Read access gives back the actual state of the HandyKey function
-+ * h:0 Disabled
-+ * h:1 Enabled
-+ * Write access has two functions. Changing the HandyKey mode and applying
-+ * a different scancode translation table.
-+ * Syntax is: h:0 disable Handykey
-+ * h:1 enabled Handykey
-+ * t:array[256] of bytes Transfer translation table
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/ptrace.h>
-+#include <linux/signal.h>
-+#include <linux/timer.h>
-+#include <linux/tqueue.h>
-+#include <linux/random.h>
-+#include <linux/ctype.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/delay.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/keyboard.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/uaccess.h>
-+
-+#include <asm/io.h>
-+#include <asm/system.h>
-+
-+void clps711x_kbd_init_hw(void);
-+
-+/*
-+ * Values for the keyboard column scan control register.
-+ */
-+#define KBSC_HI 0x0 /* All driven high */
-+#define KBSC_LO 0x1 /* All driven low */
-+#define KBSC_X 0x2 /* All high impedance */
-+#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
-+#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
-+#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
-+#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
-+#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
-+#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
-+#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
-+#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
-+
-+/*
-+* Keycodes for cursor left/right and delete (used by HandyKey)
-+*/
-+#define KEYCODE_CLEFT 0x4b
-+#define KEYCODE_CRIGHT 0x4d
-+#define KEYCODE_DEL 0x53
-+#define KEYISPRINTABLE(code) ( (code > 0x01 && code < 0x37 && code != 0x1c \
-+ && code != 0x0e) || code == 0x39)
-+
-+/* Simple translation table for the SysRq keys */
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char clps711x_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * This table maps row/column keyboard matrix positions to XT scancodes.
-+ * It's a default table, which can be overriden by writing to proc/keyboard
-+ */
-+#ifdef CONFIG_ARCH_AUTCPU12
-+static unsigned char autcpu12_scancode[256] =
-+{
-+/* Column:
-+ Row 0 1 2 3 4 5 6 7 */
-+/* A0 */ 0x08, 0x09, 0x0a, 0x0e, 0x05, 0x06, 0x00, 0x00,
-+/* A1 */ 0x07, 0x53, 0x02, 0x03, 0x04, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x0b, 0x33, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x1e, 0x20, 0x22, 0x0e, 0x24, 0x32, 0x00, 0x00,
-+/* A1 */ 0x19, 0x53, 0x1f, 0x2f, 0x15, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x39, 0x34, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x30, 0x12, 0x23, 0x0e, 0x25, 0x31, 0x00, 0x00,
-+/* A1 */ 0x10, 0x53, 0x14, 0x11, 0x2c, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x0b, 0x27, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x2e, 0x21, 0x17, 0x0e, 0x26, 0x18, 0x00, 0x00,
-+/* A1 */ 0x13, 0x53, 0x16, 0x2D, 0x04, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x39, 0x35, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+};
-+#endif
-+
-+static int keys[8];
-+static int new_keys[8];
-+static int previous_keys[8];
-+
-+static int fastscan;
-+static int scan_interval;
-+static int scan_delay;
-+static int last_column;
-+static int key_is_pressed;
-+
-+static unsigned char *act_scancode;
-+
-+static struct kbd_handy_key {
-+ int ena;
-+ int code;
-+ int shift;
-+ int autocomplete;
-+ unsigned long expires;
-+ unsigned long delay;
-+ unsigned char left;
-+ unsigned char right;
-+ unsigned char del;
-+} khandy;
-+
-+static struct tq_struct kbd_process_task;
-+static struct timer_list clps711x_kbd_timer;
-+static struct timer_list clps711x_kbdhandy_timer;
-+static struct proc_dir_entry *clps711x_keyboard_proc_entry = NULL;
-+
-+/*
-+ * Translate a raw keycode to an XT keyboard scancode.
-+ */
-+static int clps711x_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ *keycode = act_scancode[scancode];
-+ return 1;
-+}
-+
-+/*
-+* Initialize handykey structure
-+* clear code, clear shift
-+* scan scancode for cursor right/left and delete
-+*/
-+static void clps711x_handykey_init(void) {
-+
-+ int i;
-+
-+ khandy.ena = 0;
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ for(i = 0; i < 64; i++) {
-+ switch(act_scancode[i]) {
-+ case KEYCODE_CLEFT: khandy.left = i; break;
-+ case KEYCODE_CRIGHT: khandy.right = i; break;
-+ case KEYCODE_DEL: khandy.del = i; break;
-+ }
-+ }
-+}
-+
-+/*
-+* Check for handy key and process it
-+*/
-+void inline clps711x_checkhandy(int col, int row) {
-+
-+ int scode, down;
-+ unsigned char kcode;
-+
-+ scode = (row<<3) + col;
-+ down = keys[col]>>row & 0x01;
-+ kcode = act_scancode[scode];
-+
-+ if (!khandy.ena) {
-+ if (khandy.code) {
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ }
-+
-+ if(!kcode)
-+ return;
-+
-+ if (!down || !khandy.ena) {
-+ if (khandy.ena && KEYISPRINTABLE(act_scancode[scode]))
-+ khandy.autocomplete = 1;
-+ else
-+ handle_scancode(scode + khandy.shift, down);
-+ return;
-+ }
-+
-+ khandy.autocomplete = 0;
-+ if (KEYISPRINTABLE(kcode)) {
-+ if (khandy.code) {
-+ if(khandy.code == (scode|0x100)) {
-+ handle_scancode(khandy.del,1);
-+ handle_scancode(khandy.del,0);
-+ khandy.shift = khandy.shift < 3*64 ? khandy.shift + 64 : 0 ;
-+ } else {
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ khandy.shift = 0;
-+ }
-+ }
-+ handle_scancode(scode + khandy.shift, 1);
-+ handle_scancode(scode + khandy.shift, 0);
-+ khandy.code = scode | 0x100;
-+ handle_scancode(khandy.left,1);
-+ handle_scancode(khandy.left,0);
-+ } else {
-+ if (khandy.code) {
-+ khandy.code = 0;
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+ khandy.shift = 0;
-+ handle_scancode(scode, down);
-+ }
-+}
-+
-+
-+/*
-+ * Process the new key data
-+ */
-+static void clps711x_kbd_process(void* data)
-+{
-+ int col,row,res;
-+
-+ for (col = 0; col < 8; col++) {
-+ if (( res = previous_keys[col] ^ keys[col]) == 0)
-+ continue;
-+ for(row = 0; row < 8; row++) {
-+ if ( ((res >> row) & 0x01) != 0)
-+ clps711x_checkhandy(col,row);
-+ }
-+ }
-+ /* Update the state variables. */
-+ memcpy(previous_keys, keys, 8 * sizeof(int));
-+
-+ /* reschedule, if autocomplete pending */
-+ if (khandy.autocomplete) {
-+ khandy.expires = jiffies + khandy.delay;
-+ mod_timer(&clps711x_kbdhandy_timer,khandy.expires);
-+ }
-+
-+}
-+
-+static char clps711x_unexpected_up(unsigned char scancode)
-+{
-+ return 0200;
-+}
-+
-+/*
-+* Handle timer event, for autocomplete function
-+* Reschedule keyboard process task
-+*/
-+static void clps711x_kbdhandy_timeout(unsigned long data)
-+{
-+ if(khandy.autocomplete) {
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+}
-+
-+/*
-+* Handle timer event, while in pollmode
-+*/
-+static void clps711x_kbd_timeout(unsigned long data)
-+{
-+ int i;
-+ unsigned long flags;
-+ /*
-+ * read bits of actual column or all columns in fastscan-mode
-+ */
-+ for (i = 0; i < 8; i++) {
-+ new_keys[last_column - KBSC_COL0] = clps_readb(PADR) & 0xff;
-+ key_is_pressed |= new_keys[last_column - KBSC_COL0];
-+ last_column = last_column < KBSC_COL7 ? last_column + 1 : KBSC_COL0;
-+ local_irq_save(flags);
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | last_column, SYSCON1);
-+ local_irq_restore(flags);
-+ /*
-+ * For fastscan, apply a short delay to settle scanlines
-+ * else break and wait for next timeout
-+ */
-+ if (fastscan)
-+ udelay(5);
-+ else
-+ break;
-+ }
-+
-+ if (key_is_pressed)
-+ khandy.autocomplete = 0;
-+
-+ /*
-+ * switch to interupt mode, if all columns scanned and no key pressed
-+ * else reschedule scan
-+ */
-+ if (last_column == KBSC_COL0) {
-+ if (!key_is_pressed) {
-+ local_irq_save(flags);
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_HI, SYSCON1);
-+ local_irq_restore(flags);
-+ clps_writel(0,KBDEOI);
-+ enable_irq(IRQ_KBDINT);
-+ } else {
-+ clps711x_kbd_timer.expires = jiffies + scan_interval;
-+ add_timer(&clps711x_kbd_timer);
-+ }
-+ key_is_pressed = 0;
-+ memcpy(keys, new_keys, 8 * sizeof(int));
-+ for (i = 0; i < 8; i++) {
-+ if (previous_keys[i] != keys[i]) {
-+ queue_task(&kbd_process_task, &tq_timer);
-+ return;
-+ }
-+ }
-+ } else {
-+ clps711x_kbd_timer.expires = jiffies + scan_delay;
-+ add_timer(&clps711x_kbd_timer);
-+ }
-+}
-+
-+/*
-+* Keyboard interrupt, change to scheduling mode
-+*/
-+static void clps711x_kbd_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+ disable_irq(IRQ_KBDINT);
-+ khandy.autocomplete = 0;
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_COL0, SYSCON1);
-+ clps711x_kbd_timer.expires = jiffies + scan_delay;
-+ add_timer(&clps711x_kbd_timer);
-+}
-+
-+
-+static int clps711x_kbd_proc_keyboard_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ if (count < 2)
-+ return -EINVAL;
-+
-+ return sprintf(page,"h:%d\n",khandy.ena);
-+}
-+
-+static int clps711x_kbd_proc_keyboard_write(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ unsigned char buf[260];
-+
-+ if (count < 3|| count > 258)
-+ return -EINVAL;
-+ if (copy_from_user(buf, buffer, count))
-+ return -EFAULT;
-+ if (buf[1] != ':')
-+ return -EINVAL;
-+
-+ if (buf[0] == 'h') {
-+ switch (buf[2]) {
-+ case '0':
-+ case '1':
-+ case '2': khandy.ena = buf[2]-'0'; return count;
-+ }
-+ }
-+
-+ if (buf[0] == 't' && count == 258) {
-+ memcpy(act_scancode,buf+2,256);
-+ /* rescan cursor left/right and del */
-+ clps711x_handykey_init();
-+ return count;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+
-+/*
-+ * Initialize the keyboard hardware.
-+ * Set all columns high
-+ * Install interrupt handler
-+ *
-+ * Machine dependent parameters:
-+ *
-+ * fastscan: 0 = timer based scan for each column
-+ * 1 = full scan is done in one timer event
-+ * scan_delay: time between column scans
-+ * setup even if you use fastscan (leeds to timer mode)
-+ * scan_interval: time between full scans
-+ * handy.delay: timeout before last entry get's automatically valid
-+ *
-+ */
-+void __init clps711x_kbd_init_hw(void)
-+{
-+
-+ /*
-+ * put here machine dependent init stuff
-+ */
-+ if (machine_is_autcpu12()) {
-+ fastscan = 0;
-+ scan_interval = 50*HZ/1000;
-+ scan_delay = 20*HZ/1000;
-+ khandy.delay = 750*HZ/1000;
-+ act_scancode = autcpu12_scancode;
-+ } else {
-+ printk("No initialization, keyboard killed\n");
-+ return;
-+ }
-+
-+ last_column = KBSC_COL0;
-+ key_is_pressed = 0;
-+
-+ clps711x_handykey_init();
-+
-+ /* Register the /proc entry */
-+ clps711x_keyboard_proc_entry = create_proc_entry("keyboard", 0444,
-+ &proc_root);
-+ if (clps711x_keyboard_proc_entry == NULL)
-+ printk("Couldn't create the /proc entry for the keyboard\n");
-+ else {
-+ clps711x_keyboard_proc_entry->read_proc =
-+ &clps711x_kbd_proc_keyboard_read;
-+ clps711x_keyboard_proc_entry->write_proc =
-+ &clps711x_kbd_proc_keyboard_write;
-+ }
-+
-+ /* Initialize the matrix processing task. */
-+ k_translate = clps711x_translate;
-+ k_unexpected_up = clps711x_unexpected_up;
-+ kbd_process_task.routine = clps711x_kbd_process;
-+ kbd_process_task.data = 0;
-+
-+ /* Setup the timer for keyboard polling, after kbd int */
-+ init_timer(&clps711x_kbd_timer);
-+ clps711x_kbd_timer.function = clps711x_kbd_timeout;
-+ clps711x_kbd_timer.data = 0;
-+ init_timer(&clps711x_kbdhandy_timer);
-+ clps711x_kbdhandy_timer.function = clps711x_kbdhandy_timeout;
-+ clps711x_kbdhandy_timer.data = 1;
-+
-+ /* Initialise scan hardware, request int */
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_HI, SYSCON1);
-+ request_irq(IRQ_KBDINT, clps711x_kbd_int, 0,"keyboard", NULL);
-+
-+ printk("clps711x keyboard init done\n");
-+
-+}
---- linux-2.4.25/drivers/char/console.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/char/console.c 2004-03-31 17:15:09.000000000 +0200
-@@ -72,8 +72,14 @@
- *
- * Removed console_lock, enabled interrupts across all console operations
- * 13 March 2001, Andrew Morton
-+ *
-+ * Split out con_write_ctrl_* functions from do_con_write & changed
-+ * vc_state to function pointer
-+ * by Russell King <rmk@arm.linux.org.uk>, July 1998
- */
-
-+#define CONSOLE_WIP
-+
- #include <linux/module.h>
- #include <linux/sched.h>
- #include <linux/tty.h>
-@@ -228,7 +234,7 @@
- static inline unsigned short *screenpos(int currcons, int offset, int viewed)
- {
- unsigned short *p;
--
-+
- if (!viewed)
- p = (unsigned short *)(origin + offset);
- else if (!sw->con_screen_pos)
-@@ -729,7 +735,7 @@
- else {
- unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
- if (!p) {
-- for (i = first; i < currcons; i++)
-+ for (i = first; i< currcons; i++)
- if (newscreens[i])
- kfree(newscreens[i]);
- return -ENOMEM;
-@@ -847,7 +853,7 @@
- /* the default colour table, for VGA+ colour systems */
- int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
- 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
--int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
-+int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
- 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
- int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
- 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
-@@ -1393,6 +1399,19 @@
- need_wrap = 0;
- }
-
-+static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int);
-+
- enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
- EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
- ESpalette };
-@@ -1402,7 +1421,7 @@
- {
- top = 0;
- bottom = video_num_lines;
-- vc_state = ESnormal;
-+ vc_state = con_write_ctrl_ESnormal;
- ques = 0;
- translate = set_translate(LAT1_MAP,currcons);
- G0_charset = LAT1_MAP;
-@@ -1500,328 +1519,426 @@
- disp_ctrl = 0;
- return;
- case 24: case 26:
-- vc_state = ESnormal;
-+ vc_state = con_write_ctrl_ESnormal;
- return;
- case 27:
-- vc_state = ESesc;
-+ vc_state = con_write_ctrl_ESesc;
- return;
- case 127:
- del(currcons);
- return;
- case 128+27:
-- vc_state = ESsquare;
-+ vc_state = con_write_ctrl_ESsquare;
- return;
- }
-- switch(vc_state) {
-- case ESesc:
-- vc_state = ESnormal;
-- switch (c) {
-- case '[':
-- vc_state = ESsquare;
-- return;
-- case ']':
-- vc_state = ESnonstd;
-- return;
-- case '%':
-- vc_state = ESpercent;
-- return;
-- case 'E':
-- cr(currcons);
-- lf(currcons);
-- return;
-- case 'M':
-- ri(currcons);
-- return;
-- case 'D':
-- lf(currcons);
-- return;
-- case 'H':
-- tab_stop[x >> 5] |= (1 << (x & 31));
-- return;
-- case 'Z':
-- respond_ID(tty);
-- return;
-- case '7':
-- save_cur(currcons);
-- return;
-- case '8':
-- restore_cur(currcons);
-- return;
-- case '(':
-- vc_state = ESsetG0;
-- return;
-- case ')':
-- vc_state = ESsetG1;
-- return;
-- case '#':
-- vc_state = EShash;
-- return;
-- case 'c':
-- reset_terminal(currcons,1);
-- return;
-- case '>': /* Numeric keypad */
-- clr_kbd(kbdapplic);
-- return;
-- case '=': /* Appl. keypad */
-- set_kbd(kbdapplic);
-- return;
-+ vc_state(currcons, tty, c);
-+}
-+
-+static int con_write_utf(int currcons, int c)
-+{
-+ unsigned int chr;
-+
-+ /* Combine UTF-8 into Unicode */
-+ /* Incomplete characters silently ignored */
-+ if (c < 0x80) {
-+ utf_count = 0;
-+ return c;
-+ }
-+
-+ if (utf_count > 0 && (c & 0xc0) == 0x80) {
-+ chr = (utf_char << 6) | (c & 0x3f);
-+ utf_count--;
-+ if (utf_count == 0)
-+ return chr;
-+ } else {
-+ unsigned int count;
-+ if ((c & 0xe0) == 0xc0) {
-+ count = 1;
-+ chr = (c & 0x1f);
-+ } else if ((c & 0xf0) == 0xe0) {
-+ count = 2;
-+ chr = (c & 0x0f);
-+ } else if ((c & 0xf8) == 0xf0) {
-+ count = 3;
-+ chr = (c & 0x07);
-+ } else if ((c & 0xfc) == 0xf8) {
-+ count = 4;
-+ chr = (c & 0x03);
-+ } else if ((c & 0xfe) == 0xfc) {
-+ count = 5;
-+ chr = (c & 0x01);
-+ } else {
-+ count = 0;
-+ chr = 0;
- }
-- return;
-- case ESnonstd:
-- if (c=='P') { /* palette escape sequence */
-- for (npar=0; npar<NPAR; npar++)
-- par[npar] = 0 ;
-- npar = 0 ;
-- vc_state = ESpalette;
-- return;
-- } else if (c=='R') { /* reset palette */
-- reset_palette(currcons);
-- vc_state = ESnormal;
-- } else
-- vc_state = ESnormal;
-- return;
-- case ESpalette:
-- if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-- par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
-- if (npar==7) {
-- int i = par[0]*3, j = 1;
-- palette[i] = 16*par[j++];
-- palette[i++] += par[j++];
-- palette[i] = 16*par[j++];
-- palette[i++] += par[j++];
-- palette[i] = 16*par[j++];
-- palette[i] += par[j];
-- set_palette(currcons);
-- vc_state = ESnormal;
-- }
-- } else
-- vc_state = ESnormal;
-- return;
-- case ESsquare:
-- for(npar = 0 ; npar < NPAR ; npar++)
-- par[npar] = 0;
-- npar = 0;
-- vc_state = ESgetpars;
-- if (c == '[') { /* Function key */
-- vc_state=ESfunckey;
-- return;
-+ utf_count = count;
-+ }
-+
-+ utf_char = chr;
-+ return -1;
-+}
-+
-+static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch (c) {
-+ case '[':
-+ vc_state = con_write_ctrl_ESsquare;
-+ break;
-+ case ']':
-+ vc_state = con_write_ctrl_ESnonstd;
-+ break;
-+ case '%':
-+ vc_state = con_write_ctrl_ESpercent;
-+ break;
-+ case 'E':
-+ cr(currcons);
-+ lf(currcons);
-+ break;
-+ case 'M':
-+ ri(currcons);
-+ break;
-+ case 'D':
-+ lf(currcons);
-+ break;
-+ case 'H':
-+ tab_stop[x >> 5] |= (1 << (x & 31));
-+ break;
-+ case 'Z':
-+ respond_ID(tty);
-+ break;
-+ case '7':
-+ save_cur(currcons);
-+ break;
-+ case '8':
-+ restore_cur(currcons);
-+ return 1;
-+ case '(':
-+ vc_state = con_write_ctrl_ESsetG0;
-+ break;
-+ case ')':
-+ vc_state = con_write_ctrl_ESsetG1;
-+ break;
-+ case '#':
-+ vc_state = con_write_ctrl_EShash;
-+ break;
-+ case 'c':
-+ reset_terminal(currcons,1);
-+ return 1;
-+ case '>': /* Numeric keypad */
-+ clr_kbd(kbdapplic);
-+ break;
-+ case '=': /* Appl. keypad */
-+ set_kbd(kbdapplic);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case 'P': /* palette escape sequence */
-+ for (npar=0; npar<NPAR; npar++)
-+ par[npar] = 0 ;
-+ npar = 0 ;
-+ vc_state = con_write_ctrl_ESpalette;
-+ break;
-+ case 'R': /* reset palette */
-+ reset_palette (currcons);
-+ default:
-+ vc_state = con_write_ctrl_ESnormal;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-+ par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
-+ if (npar==7) {
-+ int i = par[0]*3, j = 1;
-+ palette[i] = 16*par[j++];
-+ palette[i++] += par[j++];
-+ palette[i] = 16*par[j++];
-+ palette[i++] += par[j++];
-+ palette[i] = 16*par[j++];
-+ palette[i] += par[j];
-+ set_palette(currcons);
-+ vc_state = con_write_ctrl_ESnormal;
- }
-- ques = (c=='?');
-- if (ques)
-- return;
-- case ESgetpars:
-- if (c==';' && npar<NPAR-1) {
-- npar++;
-- return;
-- } else if (c>='0' && c<='9') {
-- par[npar] *= 10;
-- par[npar] += c-'0';
-- return;
-- } else vc_state=ESgotpars;
-- case ESgotpars:
-- vc_state = ESnormal;
-- switch(c) {
-- case 'h':
-- set_mode(currcons,1);
-- return;
-- case 'l':
-- set_mode(currcons,0);
-- return;
-- case 'c':
-- if (ques) {
-- if (par[0])
-- cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
-- else
-- cursor_type = CUR_DEFAULT;
-- return;
-- }
-- break;
-- case 'm':
-- if (ques) {
-- clear_selection();
-- if (par[0])
-- complement_mask = par[0]<<8 | par[1];
-- else
-- complement_mask = s_complement_mask;
-- return;
-- }
-- break;
-- case 'n':
-- if (!ques) {
-- if (par[0] == 5)
-- status_report(tty);
-- else if (par[0] == 6)
-- cursor_report(currcons,tty);
-- }
-- return;
-+ } else
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ for(npar = 0 ; npar < NPAR ; npar++)
-+ par[npar] = 0;
-+ npar = 0;
-+ vc_state = con_write_ctrl_ESgetpars;
-+ if (c == '[') { /* Function key */
-+ vc_state = con_write_ctrl_ESfunckey;
-+ return 0;
-+ }
-+ ques = (c=='?');
-+ if (ques)
-+ return 0;
-+ return con_write_ctrl_ESgetpars(currcons, tty, c);
-+}
-+
-+static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ if (c==';' && npar<NPAR-1) {
-+ npar++;
-+ return 0;
-+ } else if (c>='0' && c<='9') {
-+ par[npar] *= 10;
-+ par[npar] += c-'0';
-+ return 0;
-+ } else vc_state = con_write_ctrl_ESgotpars;
-+ return con_write_ctrl_ESgotpars(currcons, tty, c);
-+}
-+
-+static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch(c) {
-+ case 'h':
-+ set_mode(currcons,1);
-+ return 0;
-+ case 'l':
-+ set_mode(currcons,0);
-+ return 0;
-+ case 'c':
-+ if (ques) {
-+ if (par[0])
-+ cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
-+ else
-+ cursor_type = CUR_DEFAULT;
-+ return 0;
- }
-+ break;
-+ case 'm':
- if (ques) {
-- ques = 0;
-- return;
-+ clear_selection();
-+ if (par[0])
-+ complement_mask = par[0]<<8 | par[1];
-+ else
-+ complement_mask = s_complement_mask;
-+ return 0;
- }
-- switch(c) {
-- case 'G': case '`':
-- if (par[0]) par[0]--;
-- gotoxy(currcons,par[0],y);
-- return;
-- case 'A':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x,y-par[0]);
-- return;
-- case 'B': case 'e':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x,y+par[0]);
-- return;
-- case 'C': case 'a':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x+par[0],y);
-- return;
-- case 'D':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x-par[0],y);
-- return;
-- case 'E':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,0,y+par[0]);
-- return;
-- case 'F':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,0,y-par[0]);
-- return;
-- case 'd':
-- if (par[0]) par[0]--;
-- gotoxay(currcons,x,par[0]);
-- return;
-- case 'H': case 'f':
-- if (par[0]) par[0]--;
-- if (par[1]) par[1]--;
-- gotoxay(currcons,par[1],par[0]);
-- return;
-- case 'J':
-- csi_J(currcons,par[0]);
-- return;
-- case 'K':
-- csi_K(currcons,par[0]);
-- return;
-- case 'L':
-- csi_L(currcons,par[0]);
-- return;
-- case 'M':
-- csi_M(currcons,par[0]);
-- return;
-- case 'P':
-- csi_P(currcons,par[0]);
-- return;
-- case 'c':
-- if (!par[0])
-- respond_ID(tty);
-- return;
-- case 'g':
-- if (!par[0])
-- tab_stop[x >> 5] &= ~(1 << (x & 31));
-- else if (par[0] == 3) {
-- tab_stop[0] =
-- tab_stop[1] =
-- tab_stop[2] =
-- tab_stop[3] =
-- tab_stop[4] = 0;
-- }
-- return;
-- case 'm':
-- csi_m(currcons);
-- return;
-- case 'q': /* DECLL - but only 3 leds */
-- /* map 0,1,2,3 to 0,1,2,4 */
-- if (par[0] < 4)
-- setledstate(kbd_table + currcons,
-- (par[0] < 3) ? par[0] : 4);
-- return;
-- case 'r':
-- if (!par[0])
-- par[0]++;
-- if (!par[1])
-- par[1] = video_num_lines;
-- /* Minimum allowed region is 2 lines */
-- if (par[0] < par[1] &&
-- par[1] <= video_num_lines) {
-- top=par[0]-1;
-- bottom=par[1];
-- gotoxay(currcons,0,0);
-- }
-- return;
-- case 's':
-- save_cur(currcons);
-- return;
-- case 'u':
-- restore_cur(currcons);
-- return;
-- case 'X':
-- csi_X(currcons, par[0]);
-- return;
-- case '@':
-- csi_at(currcons,par[0]);
-- return;
-- case ']': /* setterm functions */
-- setterm_command(currcons);
-- return;
-+ break;
-+ case 'n':
-+ if (!ques) {
-+ if (par[0] == 5)
-+ status_report(tty);
-+ else if (par[0] == 6)
-+ cursor_report(currcons,tty);
- }
-- return;
-- case ESpercent:
-- vc_state = ESnormal;
-- switch (c) {
-- case '@': /* defined in ISO 2022 */
-- utf = 0;
-- return;
-- case 'G': /* prelim official escape code */
-- case '8': /* retained for compatibility */
-- utf = 1;
-- return;
-+ return 0;
-+ }
-+ if (ques) {
-+ ques = 0;
-+ return 0;
-+ }
-+ switch(c) {
-+ case 'G': case '`':
-+ if (par[0]) par[0]--;
-+ gotoxy(currcons,par[0],y);
-+ break;
-+ case 'A':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x,y-par[0]);
-+ break;
-+ case 'B': case 'e':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x,y+par[0]);
-+ break;
-+ case 'C': case 'a':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x+par[0],y);
-+ break;
-+ case 'D':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x-par[0],y);
-+ break;
-+ case 'E':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,0,y+par[0]);
-+ break;
-+ case 'F':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,0,y-par[0]);
-+ break;
-+ case 'd':
-+ if (par[0]) par[0]--;
-+ gotoxay(currcons,x,par[0]);
-+ break;
-+ case 'H': case 'f':
-+ if (par[0]) par[0]--;
-+ if (par[1]) par[1]--;
-+ gotoxay(currcons,par[1],par[0]);
-+ break;
-+ case 'J':
-+ csi_J(currcons,par[0]);
-+ break;
-+ case 'K':
-+ csi_K(currcons,par[0]);
-+ break;
-+ case 'L':
-+ csi_L(currcons,par[0]);
-+ break;
-+ case 'M':
-+ csi_M(currcons,par[0]);
-+ break;
-+ case 'P':
-+ csi_P(currcons,par[0]);
-+ break;
-+ case 'c':
-+ if (!par[0])
-+ respond_ID(tty);
-+ break;
-+ case 'g':
-+ if (!par[0])
-+ tab_stop[x >> 5] &= ~(1 << (x & 31));
-+ else if (par[0] == 3) {
-+ tab_stop[0] =
-+ tab_stop[1] =
-+ tab_stop[2] =
-+ tab_stop[3] =
-+ tab_stop[4] = 0;
- }
-- return;
-- case ESfunckey:
-- vc_state = ESnormal;
-- return;
-- case EShash:
-- vc_state = ESnormal;
-- if (c == '8') {
-- /* DEC screen alignment test. kludge :-) */
-- video_erase_char =
-- (video_erase_char & 0xff00) | 'E';
-- csi_J(currcons, 2);
-- video_erase_char =
-- (video_erase_char & 0xff00) | ' ';
-- do_update_region(currcons, origin, screenbuf_size/2);
-+ break;
-+ case 'm':
-+ csi_m(currcons);
-+ return 1;
-+ case 'q': /* DECLL - but only 3 leds */
-+ /* map 0,1,2,3 to 0,1,2,4 */
-+ if (par[0] < 4)
-+ setledstate(kbd_table + currcons,
-+ (par[0] < 3) ? par[0] : 4);
-+ break;
-+ case 'r':
-+ if (!par[0])
-+ par[0]++;
-+ if (!par[1])
-+ par[1] = video_num_lines;
-+ /* Minimum allowed region is 2 lines */
-+ if (par[0] < par[1] &&
-+ par[1] <= video_num_lines) {
-+ top=par[0]-1;
-+ bottom=par[1];
-+ gotoxay(currcons,0,0);
- }
-- return;
-- case ESsetG0:
-- if (c == '0')
-- G0_charset = GRAF_MAP;
-- else if (c == 'B')
-- G0_charset = LAT1_MAP;
-- else if (c == 'U')
-- G0_charset = IBMPC_MAP;
-- else if (c == 'K')
-- G0_charset = USER_MAP;
-- if (charset == 0)
-- translate = set_translate(G0_charset,currcons);
-- vc_state = ESnormal;
-- return;
-- case ESsetG1:
-- if (c == '0')
-- G1_charset = GRAF_MAP;
-- else if (c == 'B')
-- G1_charset = LAT1_MAP;
-- else if (c == 'U')
-- G1_charset = IBMPC_MAP;
-- else if (c == 'K')
-- G1_charset = USER_MAP;
-- if (charset == 1)
-- translate = set_translate(G1_charset,currcons);
-- vc_state = ESnormal;
-- return;
-- default:
-- vc_state = ESnormal;
-+ break;
-+ case 's':
-+ save_cur(currcons);
-+ break;
-+ case 'u':
-+ restore_cur(currcons);
-+ return 1;
-+ case 'X':
-+ csi_X(currcons, par[0]);
-+ break;
-+ case '@':
-+ csi_at(currcons,par[0]);
-+ break;
-+ case ']': /* setterm functions */
-+ setterm_command(currcons);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch (c) {
-+ case '@': /* defined in ISO 2022 */
-+ utf = 0;
-+ break;
-+ case 'G': /* prelim official escape code */
-+ case '8': /* retained for compatibility */
-+ utf = 1;
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ if (c == '8') {
-+ /* DEC screen alignment test. kludge :-) */
-+ video_erase_char =
-+ (video_erase_char & 0xff00) | 'E';
-+ csi_J(currcons, 2);
-+ video_erase_char =
-+ (video_erase_char & 0xff00) | ' ';
-+ do_update_region(currcons, origin, screenbuf_size/2);
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case '0':
-+ G0_charset = GRAF_MAP;
-+ break;
-+ case 'B':
-+ G0_charset = LAT1_MAP;
-+ break;
-+ case 'U':
-+ G0_charset = IBMPC_MAP;
-+ break;
-+ case 'K':
-+ G0_charset = USER_MAP;
-+ break;
-+ }
-+ if (charset == 0) {
-+ translate = set_translate(G0_charset,currcons);
-+ return 1;
-+ }
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case '0':
-+ G1_charset = GRAF_MAP;
-+ break;
-+ case 'B':
-+ G1_charset = LAT1_MAP;
-+ break;
-+ case 'U':
-+ G1_charset = IBMPC_MAP;
-+ break;
-+ case 'K':
-+ G1_charset = USER_MAP;
-+ break;
-+ }
-+ if (charset == 1) {
-+ translate = set_translate(G1_charset,currcons);
-+ return 1;
- }
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
- }
-
- /* This is a temporary buffer used to prepare a tty console write
-@@ -1855,7 +1972,7 @@
- unsigned long draw_from = 0, draw_to = 0;
- struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
- u16 himask, charmask;
-- const unsigned char *orig_buf = NULL;
-+ const unsigned char *orig_buf;
- int orig_count;
-
- if (in_interrupt())
-@@ -1913,42 +2030,12 @@
- count--;
-
- if (utf) {
-- /* Combine UTF-8 into Unicode */
-- /* Incomplete characters silently ignored */
-- if(c > 0x7f) {
-- if (utf_count > 0 && (c & 0xc0) == 0x80) {
-- utf_char = (utf_char << 6) | (c & 0x3f);
-- utf_count--;
-- if (utf_count == 0)
-- tc = c = utf_char;
-- else continue;
-- } else {
-- if ((c & 0xe0) == 0xc0) {
-- utf_count = 1;
-- utf_char = (c & 0x1f);
-- } else if ((c & 0xf0) == 0xe0) {
-- utf_count = 2;
-- utf_char = (c & 0x0f);
-- } else if ((c & 0xf8) == 0xf0) {
-- utf_count = 3;
-- utf_char = (c & 0x07);
-- } else if ((c & 0xfc) == 0xf8) {
-- utf_count = 4;
-- utf_char = (c & 0x03);
-- } else if ((c & 0xfe) == 0xfc) {
-- utf_count = 5;
-- utf_char = (c & 0x01);
-- } else
-- utf_count = 0;
-+ tc = con_write_utf(currcons, c);
-+ if (tc < 0)
- continue;
-- }
-- } else {
-- tc = c;
-- utf_count = 0;
-- }
-- } else { /* no utf */
-- tc = translate[toggle_meta ? (c|0x80) : c];
-- }
-+ c = tc;
-+ } else /* no utf */
-+ tc = translate[toggle_meta ? (c|0x80) : c];
-
- /* If the original code was a control character we
- * only allow a glyph to be displayed if the code is
-@@ -1966,7 +2053,7 @@
- && (c != 127 || disp_ctrl)
- && (c != 128+27);
-
-- if (vc_state == ESnormal && ok) {
-+ if (vc_state == con_write_ctrl_ESnormal && ok) {
- /* Now try to find out how to display it */
- tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
- if ( tc == -4 ) {
-@@ -2112,7 +2199,7 @@
- if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
- currcons = kmsg_redirect - 1;
-
-- /* read `x' only after setting currecons properly (otherwise
-+ /* read `x' only after setting currcons properly (otherwise
- the `x' macro will read the x of the foreground console). */
- myx = x;
-
-@@ -2475,8 +2562,8 @@
- console_driver.init_termios = tty_std_termios;
- console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
- /* Tell tty_register_driver() to skip consoles because they are
-- * registered before kmalloc() is ready. We'll patch them in later.
-- * See comments at console_init(); see also con_init_devfs().
-+ * registered before kmalloc() is ready. We'll patch them in later.
-+ * See comments at console_init(); see also con_init_devfs().
- */
- console_driver.flags |= TTY_DRIVER_NO_DEVFS;
- console_driver.refcount = &console_refcount;
-@@ -2719,7 +2806,7 @@
-
- if (console_blank_hook && console_blank_hook(1))
- return;
-- if (vesa_blank_mode)
-+ if (vesa_blank_mode)
- sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
- }
-
-@@ -2893,7 +2980,7 @@
- if (!op->height) { /* Need to guess font height [compat] */
- int h, i;
- u8 *charmap = op->data, tmp;
--
-+
- /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
- so that we can get rid of this soon */
- if (!(op->flags & KD_FONT_FLAG_OLD))
-@@ -2940,18 +3027,18 @@
- op->data = old_op.data;
- if (!rc && !set) {
- int c = (op->width+7)/8 * 32 * op->charcount;
--
-+
- if (op->data && op->charcount > old_op.charcount)
- rc = -ENOSPC;
- if (!(op->flags & KD_FONT_FLAG_OLD)) {
-- if (op->width > old_op.width ||
-+ if (op->width > old_op.width ||
- op->height > old_op.height)
- rc = -ENOSPC;
- } else {
- if (op->width != 8)
- rc = -EIO;
- else if ((old_op.height && op->height > old_op.height) ||
-- op->height > 32)
-+ op->height > 32)
- rc = -ENOSPC;
- }
- if (!rc && op->data && copy_to_user(op->data, temp, c))
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/ds1307.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,604 @@
-+/*
-+ * ds1307.c
-+ *
-+ * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/poll.h>
-+#include <linux/i2c.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/rtc.h>
-+#include <linux/string.h>
-+#include <linux/miscdevice.h>
-+#include <linux/proc_fs.h>
-+
-+#include "ds1307.h"
-+
-+#define DEBUG 0
-+
-+#if DEBUG
-+static unsigned int rtc_debug = DEBUG;
-+#else
-+#define rtc_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
-+
-+struct i2c_driver ds1307_driver;
-+struct i2c_client *ds1307_i2c_client = 0;
-+
-+static unsigned short ignore[] = { I2C_CLIENT_END };
-+static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
-+
-+static struct i2c_client_address_data addr_data = {
-+ normal_i2c: normal_addr,
-+ normal_i2c_range: ignore,
-+ probe: ignore,
-+ probe_range: ignore,
-+ ignore: ignore,
-+ ignore_range: ignore,
-+ force: ignore,
-+};
-+
-+static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
-+static int ds1307_rtc_open(struct inode *inode, struct file *file);
-+static int ds1307_rtc_release(struct inode *inode, struct file *file);
-+
-+static struct file_operations rtc_fops = {
-+ owner: THIS_MODULE,
-+ ioctl: ds1307_rtc_ioctl,
-+ open: ds1307_rtc_open,
-+ release: ds1307_rtc_release,
-+};
-+
-+static struct miscdevice ds1307_rtc_miscdev = {
-+ RTC_MINOR,
-+ "rtc",
-+ &rtc_fops
-+};
-+
-+static int ds1307_probe(struct i2c_adapter *adap);
-+static int ds1307_detach(struct i2c_client *client);
-+static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
-+
-+struct i2c_driver ds1307_driver = {
-+ name: "DS1307",
-+ id: I2C_DRIVERID_DS1307,
-+ flags: I2C_DF_NOTIFY,
-+ attach_adapter: ds1307_probe,
-+ detach_client: ds1307_detach,
-+ command: ds1307_command
-+};
-+
-+static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
-+
-+#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */
-+
-+static int
-+ds1307_readram( char *buf, int len)
-+{
-+ unsigned long flags;
-+ unsigned char ad[1] = { 0 };
-+ int ret;
-+ struct i2c_msg msgs[2] = {
-+ { ds1307_i2c_client->addr , 0, 1, ad },
-+ { ds1307_i2c_client->addr , I2C_M_RD, len, buf } };
-+
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+
-+ return ret;
-+}
-+
-+static void
-+ds1307_dumpram( void)
-+{
-+ unsigned char buf[DS1307_RAM_SIZE];
-+ int ret;
-+
-+ ret = ds1307_readram( buf, DS1307_RAM_SIZE);
-+
-+ if( ret > 0)
-+ {
-+ int i;
-+ for( i=0; i<DS1307_RAM_SIZE; i++)
-+ {
-+ printk ("%02X ", buf[i]);
-+ if( (i%8) == 7) printk ("\n");
-+ }
-+ printk ("\n");
-+ }
-+}
-+
-+static void
-+ds1307_enable_clock( int enable)
-+{
-+ unsigned char buf[2], ad[1] = { 0 };
-+ struct i2c_msg msgs[2] = {
-+ { ds1307_i2c_client->addr , 0, 1, ad },
-+ { ds1307_i2c_client->addr , I2C_M_RD, 1, buf }
-+ };
-+ unsigned char ctrl_info;
-+ int ret;
-+
-+ if( enable)
-+ ctrl_info = SQW_ENABLE | RATE_32768HZ;
-+ else
-+ ctrl_info = SQW_DISABLE;
-+ ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
-+
-+ /* read addr 0 (Clock-Halt bit and second counter */
-+ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
-+
-+ if( enable)
-+ buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
-+ else
-+ buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
-+ buf[0] = 0; /* control register address on DS1307 */
-+
-+ ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
-+}
-+
-+static int
-+ds1307_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind)
-+{
-+ struct i2c_client *c;
-+ unsigned char buf[1], ad[1] = { 7 };
-+ struct i2c_msg msgs[2] = {
-+ { addr , 0, 1, ad },
-+ { addr , I2C_M_RD, 1, buf }
-+ };
-+ int ret;
-+
-+ c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
-+ if (!c)
-+ return -ENOMEM;
-+
-+ strcpy(c->name, "DS1307");
-+ c->id = ds1307_driver.id;
-+ c->flags = 0;
-+ c->addr = addr;
-+ c->adapter = adap;
-+ c->driver = &ds1307_driver;
-+ c->data = NULL;
-+
-+ ret = i2c_transfer(c->adapter, msgs, 2);
-+
-+ if ( ret == 2 )
-+ {
-+ DAT(c) = buf[0];
-+ }
-+ else
-+ printk ("ds1307_attach(): i2c_transfer() returned %d.\n",ret);
-+
-+ ds1307_i2c_client = c;
-+ ds1307_enable_clock( 1);
-+
-+ return i2c_attach_client(c);
-+}
-+
-+static int
-+ds1307_probe(struct i2c_adapter *adap)
-+{
-+ return i2c_probe(adap, &addr_data, ds1307_attach);
-+}
-+
-+static int
-+ds1307_detach(struct i2c_client *client)
-+{
-+ i2c_detach_client(client);
-+ ds1307_enable_clock( 0);
-+
-+ return 0;
-+}
-+
-+static void
-+ds1307_convert_to_time( struct rtc_time *dt, char *buf)
-+{
-+ dt->tm_sec = BCD_TO_BIN(buf[0]);
-+ dt->tm_min = BCD_TO_BIN(buf[1]);
-+
-+ if ( TWELVE_HOUR_MODE(buf[2]) )
-+ {
-+ dt->tm_hour = HOURS_12(buf[2]);
-+ if (HOURS_AP(buf[2])) /* PM */
-+ {
-+ dt->tm_hour += 12;
-+ }
-+ }
-+ else /* 24-hour-mode */
-+ {
-+ dt->tm_hour = HOURS_24(buf[2]);
-+ }
-+
-+ dt->tm_mday = BCD_TO_BIN(buf[4]);
-+ /* dt->tm_mon is zero-based */
-+ dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
-+ /* year is 1900 + dt->tm_year */
-+ dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
-+
-+ if( rtc_debug > 2)
-+ {
-+ printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
-+ printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon);
-+ printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
-+ printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
-+ printk("ds1307_get_datetime: min = %d\n", dt->tm_min);
-+ printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec);
-+ }
-+}
-+
-+static int
-+ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
-+{
-+ unsigned char buf[7], addr[1] = { 0 };
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, I2C_M_RD, 7, buf }
-+ };
-+ int ret = -EIO;
-+
-+ memset(buf, 0, sizeof(buf));
-+
-+ ret = i2c_transfer(client->adapter, msgs, 2);
-+
-+ if (ret == 2) {
-+ ds1307_convert_to_time( dt, buf);
-+ ret = 0;
-+ }
-+ else
-+ printk("ds1307_get_datetime(), i2c_transfer() returned %d\n",ret);
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
-+{
-+ unsigned char buf[8];
-+ int ret, len = 4;
-+
-+ if( rtc_debug > 2)
-+ {
-+ printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
-+ printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon);
-+ printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
-+ printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
-+ printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min);
-+ printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec);
-+ }
-+
-+ buf[0] = 0; /* register address on DS1307 */
-+ buf[1] = (BIN_TO_BCD(dt->tm_sec));
-+ buf[2] = (BIN_TO_BCD(dt->tm_min));
-+ buf[3] = (BIN_TO_BCD(dt->tm_hour));
-+
-+ if (datetoo) {
-+ len = 8;
-+ /* we skip buf[4] as we don't use day-of-week. */
-+ buf[5] = (BIN_TO_BCD(dt->tm_mday));
-+ buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
-+ /* The year only ranges from 0-99, we are being passed an offset from 1900,
-+ * and the chip calulates leap years based on 2000, thus we adjust by 100.
-+ */
-+ buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
-+ }
-+ ret = i2c_master_send(client, (char *)buf, len);
-+ if (ret == len)
-+ ret = 0;
-+ else
-+ printk("ds1307_set_datetime(), i2c_master_send() returned %d\n",ret);
-+
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
-+{
-+ *ctrl = DAT(client);
-+
-+ return 0;
-+}
-+
-+static int
-+ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
-+{
-+ unsigned char buf[2];
-+ int ret;
-+
-+
-+ buf[0] = 7; /* control register address on DS1307 */
-+ buf[1] = *cinfo;
-+ /* save the control reg info in the client data field so that get_ctrl
-+ * function doesn't have to do an I2C transfer to get it.
-+ */
-+ DAT(client) = buf[1];
-+
-+ ret = i2c_master_send(client, (char *)buf, 2);
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
-+{
-+ unsigned char addr[1];
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, I2C_M_RD, mem->nr, mem->data }
-+ };
-+
-+ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
-+ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
-+ return -EINVAL;
-+
-+ addr[0] = mem->loc;
-+
-+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-+}
-+
-+static int
-+ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
-+{
-+ unsigned char addr[1];
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, 0, mem->nr, mem->data }
-+ };
-+
-+ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
-+ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
-+ return -EINVAL;
-+
-+ addr[0] = mem->loc;
-+
-+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-+}
-+
-+static int
-+ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
-+{
-+ switch (cmd) {
-+ case DS1307_GETDATETIME:
-+ return ds1307_get_datetime(client, arg);
-+
-+ case DS1307_SETTIME:
-+ return ds1307_set_datetime(client, arg, 0);
-+
-+ case DS1307_SETDATETIME:
-+ return ds1307_set_datetime(client, arg, 1);
-+
-+ case DS1307_GETCTRL:
-+ return ds1307_get_ctrl(client, arg);
-+
-+ case DS1307_SETCTRL:
-+ return ds1307_set_ctrl(client, arg);
-+
-+ case DS1307_MEM_READ:
-+ return ds1307_read_mem(client, arg);
-+
-+ case DS1307_MEM_WRITE:
-+ return ds1307_write_mem(client, arg);
-+
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+static int
-+ds1307_rtc_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int
-+ds1307_rtc_release(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int
-+ds1307_rtc_ioctl( struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ unsigned long flags;
-+ struct rtc_time wtime;
-+ int status = 0;
-+
-+ switch (cmd) {
-+ default:
-+ case RTC_UIE_ON:
-+ case RTC_UIE_OFF:
-+ case RTC_PIE_ON:
-+ case RTC_PIE_OFF:
-+ case RTC_AIE_ON:
-+ case RTC_AIE_OFF:
-+ case RTC_ALM_SET:
-+ case RTC_ALM_READ:
-+ case RTC_IRQP_READ:
-+ case RTC_IRQP_SET:
-+ case RTC_EPOCH_READ:
-+ case RTC_EPOCH_SET:
-+ case RTC_WKALM_SET:
-+ case RTC_WKALM_RD:
-+ status = -EINVAL;
-+ break;
-+
-+ case RTC_RD_TIME:
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+
-+ if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
-+ status = -EFAULT;
-+ break;
-+
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ {
-+ status = -EACCES;
-+ break;
-+ }
-+
-+ if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
-+ {
-+ status = -EFAULT;
-+ break;
-+ }
-+
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+ break;
-+ }
-+
-+ return status;
-+}
-+
-+static char *
-+ds1307_mon2str( unsigned int mon)
-+{
-+ char *mon2str[12] = {
-+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-+ };
-+ if( mon > 11) return "error";
-+ else return mon2str[ mon];
-+}
-+
-+static int ds1307_rtc_proc_output( char *buf)
-+{
-+#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
-+ unsigned char ram[DS1307_RAM_SIZE];
-+ int ret;
-+
-+ char *p = buf;
-+
-+ ret = ds1307_readram( ram, DS1307_RAM_SIZE);
-+ if( ret > 0)
-+ {
-+ int i;
-+ struct rtc_time dt;
-+ char text[9];
-+
-+ p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
-+
-+ ds1307_convert_to_time( &dt, ram);
-+ p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n",
-+ dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
-+ dt.tm_hour, dt.tm_min, dt.tm_sec);
-+
-+ p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80));
-+ p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40));
-+ p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
-+ p += sprintf(p, "Freq : ");
-+
-+ switch( ram[7] & 0x03)
-+ {
-+ case RATE_1HZ:
-+ p += sprintf(p, "1Hz\n");
-+ break;
-+ case RATE_4096HZ:
-+ p += sprintf(p, "4.096kHz\n");
-+ break;
-+ case RATE_8192HZ:
-+ p += sprintf(p, "8.192kHz\n");
-+ break;
-+ case RATE_32768HZ:
-+ default:
-+ p += sprintf(p, "32.768kHz\n");
-+ break;
-+
-+ }
-+
-+ p += sprintf(p, "RAM dump:\n");
-+ text[8]='\0';
-+ for( i=0; i<DS1307_RAM_SIZE; i++)
-+ {
-+ p += sprintf(p, "%02X ", ram[i]);
-+
-+ if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
-+ text[i%8] = ram[i];
-+ if( (i%8) == 7) p += sprintf(p, "%s\n",text);
-+ }
-+ p += sprintf(p, "\n");
-+ }
-+ else
-+ {
-+ p += sprintf(p, "Failed to read RTC memory!\n");
-+ }
-+
-+ return p - buf;
-+}
-+
-+static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ int len = ds1307_rtc_proc_output (page);
-+ if (len <= off+count) *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len>count) len = count;
-+ if (len<0) len = 0;
-+ return len;
-+}
-+
-+static __init int ds1307_init(void)
-+{
-+ int retval=0;
-+
-+ if( slave_address != 0xffff)
-+ {
-+ normal_addr[0] = slave_address;
-+ }
-+
-+ if( normal_addr[0] == 0xffff)
-+ {
-+ printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
-+ normal_addr[0]);
-+ return -EINVAL;
-+ }
-+
-+ retval = i2c_add_driver(&ds1307_driver);
-+
-+ if (retval==0)
-+ {
-+ misc_register (&ds1307_rtc_miscdev);
-+ create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
-+ printk("I2C: DS1307 RTC driver successfully loaded\n");
-+
-+ if( rtc_debug) ds1307_dumpram();
-+ }
-+ return retval;
-+}
-+
-+static __exit void ds1307_exit(void)
-+{
-+ remove_proc_entry (PROC_DS1307_NAME, NULL);
-+ misc_deregister(&ds1307_rtc_miscdev);
-+ i2c_del_driver(&ds1307_driver);
-+}
-+
-+module_init(ds1307_init);
-+module_exit(ds1307_exit);
-+
-+MODULE_PARM (slave_address, "i");
-+MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
-+
-+MODULE_AUTHOR ("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/ds1307.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,58 @@
-+/*
-+ * ds1307.h
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#ifndef DS1307_H
-+#define DS1307_H
-+
-+#if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337)
-+ #define DS1307_I2C_SLAVE_ADDR 0x68
-+#else
-+ #define DS1307_I2C_SLAVE_ADDR 0xffff
-+#endif
-+
-+#define DS1307_RAM_ADDR_START 0x08
-+#define DS1307_RAM_ADDR_END 0x3F
-+#define DS1307_RAM_SIZE 0x40
-+
-+#define PROC_DS1307_NAME "driver/ds1307"
-+
-+struct rtc_mem {
-+ unsigned int loc;
-+ unsigned int nr;
-+ unsigned char *data;
-+};
-+
-+#define DS1307_GETDATETIME 0
-+#define DS1307_SETTIME 1
-+#define DS1307_SETDATETIME 2
-+#define DS1307_GETCTRL 3
-+#define DS1307_SETCTRL 4
-+#define DS1307_MEM_READ 5
-+#define DS1307_MEM_WRITE 6
-+
-+#define SQW_ENABLE 0x10 /* Square Wave Enable */
-+#define SQW_DISABLE 0x00 /* Square Wave disable */
-+
-+#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */
-+#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */
-+#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */
-+#define RATE_1HZ 0x00 /* Rate Select 1Hz */
-+
-+#define CLOCK_HALT 0x80 /* Clock Halt */
-+
-+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-+
-+#define TWELVE_HOUR_MODE(n) (((n)>>6)&1)
-+#define HOURS_AP(n) (((n)>>5)&1)
-+#define HOURS_12(n) BCD_TO_BIN((n)&0x1F)
-+#define HOURS_24(n) BCD_TO_BIN((n)&0x3F)
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/edb7211_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,335 @@
-+/*
-+ * drivers/char/edb7211_keyb.c
-+ *
-+ * Copyright (C) 2000 Blue Mug, Inc. All Rights Reserved.
-+ *
-+ * EDB7211 Keyboard driver for ARM Linux.
-+ *
-+ * The EP7211 keyboard hardware only supports generating interrupts for 64 keys.
-+ * The EBD7211's keyboard has 84 keys. Therefore we need to poll for keys,
-+ * instead of waiting for interrupts.
-+ *
-+ * In a real-world hardware situation, this would be a bad thing. It would
-+ * kill power management.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/ptrace.h>
-+#include <linux/signal.h>
-+#include <linux/timer.h>
-+#include <linux/tqueue.h>
-+#include <linux/random.h>
-+#include <linux/ctype.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/delay.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/keyboard.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/io.h>
-+#include <asm/system.h>
-+
-+
-+/*
-+ * The number of jiffies between keyboard scans.
-+ */
-+#define KEYBOARD_SCAN_INTERVAL 5
-+
-+/*
-+ * Values for the keyboard column scan control register.
-+ */
-+#define KBSC_HI 0x0 /* All driven high */
-+#define KBSC_LO 0x1 /* All driven low */
-+#define KBSC_X 0x2 /* All high impedance */
-+#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
-+#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
-+#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
-+#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
-+#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
-+#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
-+#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
-+#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
-+
-+
-+/* XXX: Figure out what these values should be... */
-+/* Simple translation table for the SysRq keys */
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char edb7211_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * Row/column to scancode mappings.
-+ *
-+ * This table maps row/column keyboard matrix positions to XT scancodes.
-+ *
-+ * The port A rows come first, followed by the extended rows.
-+ */
-+static unsigned char colrow_2_scancode[128] =
-+{
-+/* Column:
-+ Row 0 1 2 3 4 5 6 7 */
-+/* A0 */ 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x40, 0x41,
-+/* A1 */ 0x02, 0x07, 0x06, 0x05, 0x04, 0x03, 0x08, 0x09,
-+/* A2 */ 0x0f, 0x14, 0x13, 0x12, 0x11, 0x10, 0x15, 0x16,
-+/* A3 */ 0x3a, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x23, 0x24,
-+/* A4 */ 0x29, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x31, 0x32,
-+/* A5 */ 0x39, 0x35, 0x6F, 0x52, 0x00, 0x6B, 0x34, 0x33,
-+/* A6 */ 0x6A, 0x27, 0x28, 0x00, 0x1c, 0x6D, 0x26, 0x25,
-+/* A7 */ 0x67, 0x19, 0x1a, 0x1b, 0x2b, 0x68, 0x18, 0x17,
-+/* E0 */ 0x6C, 0x0c, 0x0d, 0x0e, 0x00, 0x66, 0x0b, 0x0a,
-+/* E1 */ 0x69, 0x44, 0x45, 0x37, 0x46, 0x77, 0x43, 0x42,
-+/* E2 */ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E3 */ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E4 */ 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E5 */ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E6 */ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E7 */ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+
-+/*
-+ * A bitfield array which contains the state of the keyboard after the last
-+ * scan. A bit set in this array corresponds to a key down. Only the lower
-+ * 16 bits of each array element are used.
-+ */
-+static unsigned long previous_keys[8];
-+static unsigned long keys[8];
-+
-+
-+/* This will be set to a non-zero value if a key was found to be pressed
-+ * in the last scan. */
-+static int key_is_pressed;
-+
-+static struct tq_struct kbd_process_task;
-+static struct timer_list edb7211_kbd_timer;
-+
-+/*
-+ * External methods.
-+ */
-+void edb7211_kbd_init_hw(void);
-+
-+/*
-+ * Internal methods.
-+ */
-+static int edb7211_kbd_scan_matrix(u_long* keys);
-+static void edb7211_kbd_timeout(unsigned long data);
-+static void edb7211_kbd_process(void* data);
-+
-+/*
-+ * Translate a raw keycode to an XT keyboard scancode.
-+ */
-+static int
-+edb7211_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ *keycode = colrow_2_scancode[scancode & 0x7f];
-+ return 1;
-+}
-+
-+/*
-+ * Scan the keyboard matrix; for each key that is pressed, set the
-+ * corresponding bit in the bitfield array.
-+ *
-+ * The parameter is expected to be an array of 8 32-bit values. Only the lower
-+ * 16 bits of each value is used. Each value contains the row bits for the
-+ * corresponding column.
-+ */
-+static int
-+edb7211_kbd_scan_matrix(u_long* keys)
-+{
-+ int column, row, key_pressed;
-+ unsigned char port_a_data, ext_port_data;
-+
-+ key_pressed = 0;
-+
-+ /* Drive all the columns low. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_LO,
-+ SYSCON1);
-+
-+ for (column = 0; column < 8; column++) {
-+
-+ /* Drive the column high. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) |
-+ (KBSC_COL0 + column), SYSCON1);
-+
-+ /* Read port A and the extended port. */
-+ port_a_data = clps_readb(PADR) & 0xff;
-+ ext_port_data = __raw_readb(EP7211_VIRT_EXTKBD) & 0xff;
-+
-+ /* Drive all columns tri-state. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ /* Look at each column in port A. */
-+ for (row=0; row < 8; row++) {
-+ /* If the row's bit is set, set the bit in the bitfield.
-+ * Otherwise, clear it.
-+ */
-+ if (port_a_data & (1 << row)) {
-+ keys[column] |= (1 << row);
-+ key_pressed = 1;
-+ } else {
-+ keys[column] &= ~(1 << row);
-+ }
-+ }
-+
-+ /* Look at each column in the extended port. */
-+ for (row=0; row < 8; row++) {
-+ /* If the row's bit is set, set the bit in the bitfield.
-+ * Otherwise, clear it.
-+ */
-+ if (ext_port_data & (1 << row)) {
-+ keys[column] |= (1 << (row + 8));
-+ key_pressed = 1;
-+ } else {
-+ keys[column] &= ~(1 << (row + 8));
-+ }
-+ }
-+
-+ /*
-+ * Short delay: The example code for the EDB7211 runs an empty
-+ * loop 256 times. At this rate, there were some spurious keys
-+ * generated. I doubled the delay to let the column drives
-+ * settle some.
-+ */
-+ for (row=0; row < 512; row++) { }
-+ }
-+
-+ /* If we could use interrupts, we would drive all columns high so
-+ * that interrupts will be generated on key presses. But we can't,
-+ * so we leave all columns floating.
-+ */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ return key_pressed;
-+}
-+
-+/*
-+ * XXX: This is really ugly; this needs to be reworked to have less levels of
-+ * indentation.
-+ */
-+static void
-+edb7211_kbd_timeout(unsigned long data)
-+{
-+ /* Schedule the next timer event. */
-+ edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
-+ add_timer(&edb7211_kbd_timer);
-+
-+ if (edb7211_kbd_scan_matrix(keys) || key_is_pressed) {
-+ queue_task(&kbd_process_task, &tq_timer);
-+ } else {
-+ key_is_pressed = 0;
-+ }
-+}
-+
-+/*
-+ * Process the keys that have been pressed.
-+ */
-+static void
-+edb7211_kbd_process(void* data)
-+{
-+ int i;
-+
-+ /* First check if any keys have been released. */
-+ if (key_is_pressed) {
-+ for (i=0; i < 8; i++) {
-+ if (previous_keys[i]) {
-+ int row;
-+
-+ for (row=0; row < 16; row++) {
-+ if ((previous_keys[i] & (1 << row)) &&
-+ !(keys[i] & (1 << row))) {
-+ /* Generate the up event. */
-+ handle_scancode(
-+ (row<<3)+i, 0);
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ key_is_pressed = 0;
-+
-+ /* Now scan the keys and send press events. */
-+ for (i=0; i < 8; i++) {
-+ if (keys[i]) {
-+ int row;
-+
-+ for (row=0; row < 16; row++) {
-+ if (keys[i] & (1 << row)) {
-+ if (previous_keys[i] & (1 << row)) {
-+ /* Generate the hold event. */
-+ handle_scancode((row<<3)+i, 1);
-+ } else {
-+ /* Generate the down event. */
-+ handle_scancode((row<<3)+i, 1);
-+ }
-+
-+ key_is_pressed = 1;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Update the state variables. */
-+ memcpy(previous_keys, keys, 8 * sizeof(unsigned long));
-+}
-+
-+static char edb7211_unexpected_up(unsigned char scancode)
-+{
-+ return 0200;
-+}
-+
-+static void edb7211_leds(unsigned char leds)
-+{
-+}
-+
-+/*
-+ * Initialize the keyboard hardware. Set the column drives low and
-+ * start the timer.
-+ */
-+void __init
-+edb7211_kbd_init_hw(void)
-+{
-+ k_translate = edb7211_translate;
-+ k_unexpected_up = edb7211_unexpected_up;
-+ k_leds = edb7211_leds;
-+
-+ /*
-+ * If we had the ability to use interrupts, we would want to drive all
-+ * columns high. But we have more keys than can generate interrupts, so
-+ * we leave them floating.
-+ */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ /* Initialize the matrix processing task. */
-+ kbd_process_task.routine = edb7211_kbd_process;
-+ kbd_process_task.data = NULL;
-+
-+ /* Setup the timer to poll the keyboard. */
-+ init_timer(&edb7211_kbd_timer);
-+ edb7211_kbd_timer.function = edb7211_kbd_timeout;
-+ edb7211_kbd_timer.data = (unsigned long)NULL;
-+ edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
-+ add_timer(&edb7211_kbd_timer);
-+}
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/epxa_wdt.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,178 @@
-+/*
-+ * Watchdog driver for the Altera Excalibur EPXA1DB
-+ *
-+ * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
-+ * Based on SA11x0 Watchdog driver by Oleg Drokin <green@crimea.edu>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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 material is provided "AS-IS" and at no charge
-+ *
-+ * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
-+ *
-+ * 1/08/2003 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+
-+#define WATCHDOG00_TYPE (volatile unsigned int*)
-+#include <asm/arch/watchdog00.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 30 /* (secs) Default is 30 seconds */
-+
-+static int margin = TIMER_MARGIN; /* in seconds */
-+static int epxa1wdt_users;
-+static unsigned char last_written_byte;
-+
-+#ifdef CONFIG_WATCHDOG_NOWAYOUT
-+static int nowayout=1;
-+#else
-+static int nowayout=0;
-+#endif
-+
-+#ifdef MODULE
-+MODULE_PARM(margin,"i");
-+MODULE_PARM(nowayout, "i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int epxa1dog_open(struct inode *inode, struct file *file)
-+{
-+ if(test_and_set_bit(1,&epxa1wdt_users))
-+ return -EBUSY;
-+
-+ /* Reset the Watchdog, just to be sure we don't set
-+ a value close to actual value of WDOG_COUNT register */
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+
-+ /* Activate EPXA1DB Watchdog timer */
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
-+
-+ last_written_byte = 'V'; //in case user opens it only to ioctl
-+ return 0;
-+}
-+
-+static int epxa1dog_release(struct inode *inode, struct file *file)
-+{
-+ /*
-+ * Shut off the timer and set lock bit when no special
-+ * character 'V' was last written
-+ */
-+
-+ if ((last_written_byte != 'V') && (nowayout)) {
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)) |= WDOG_CR_LK_MSK;
-+ printk("No special character 'V' was written to Watchdog just before closing it\n");
-+ printk("WATCHDOG LOCKED - Reboot expected!!!\n");
-+ } else
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))=0;
-+
-+ epxa1wdt_users = 0;
-+
-+ return 0;
-+}
-+
-+static ssize_t epxa1dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Reset Watchdog timer. */
-+ if(len) {
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+ last_written_byte = *data;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int epxa1dog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ static struct watchdog_info ident = {
-+ identity: "EPXA Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+// case WDIOC_GETSTATUS: //TODO
-+// return put_user(0,(int *)arg);
-+// case WDIOC_GETBOOTSTATUS: //TODO
-+// return 0;
-+ case WDIOC_KEEPALIVE:
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+ return 0;
-+ case WDIOC_SETTIMEOUT:
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
-+ return 0;
-+ case WDIOC_GETTIMEOUT:
-+ return put_user( ((*WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)))/EXC_INPUT_CLK_FREQUENCY), (int*)arg);
-+ }
-+}
-+
-+static struct file_operations epxa1dog_fops = {
-+ .owner = THIS_MODULE,
-+ .write = epxa1dog_write,
-+ .ioctl = epxa1dog_ioctl,
-+ .open = epxa1dog_open,
-+ .release = epxa1dog_release,
-+};
-+
-+static struct miscdevice epxa1dog_miscdev=
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "EPXA watchdog",
-+ .fops = &epxa1dog_fops
-+};
-+
-+static int __init epxa1dog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&epxa1dog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("EPXA Watchdog Timer: timer margin %d sec\n", margin);
-+ printk("EPXA Watchdog Timer: no way out is %s\n", nowayout ? "enabled" : "disabled");
-+
-+ return 0;
-+}
-+
-+static void __exit epxa1dog_exit(void)
-+{
-+ misc_deregister(&epxa1dog_miscdev);
-+}
-+
-+module_init(epxa1dog_init);
-+module_exit(epxa1dog_exit);
-+
-+MODULE_AUTHOR("Krzysztof Marianski <kmarian@konin.lm.pl>");
-+MODULE_DESCRIPTION("EPXA Watchdog Timer");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/gc_kbmap.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,162 @@
-+
-+
-+#define KK_NONE 0x7f
-+#define KK_ESC 0x00
-+#define KK_F1 0x01
-+#define KK_F2 0x02
-+#define KK_F3 0x03
-+#define KK_F4 0x04
-+#define KK_F5 0x05
-+#define KK_F6 0x06
-+#define KK_F7 0x07
-+#define KK_F8 0x08
-+#define KK_F9 0x09
-+#define KK_F10 0x0a
-+#define KK_F11 0x0b
-+#define KK_F12 0x0c
-+#define KK_PRNT 0x0d
-+#define KK_SCRL 0x0e
-+#define KK_BRK 0x0f
-+#define KK_AGR 0x10
-+#define KK_1 0x11
-+#define KK_2 0x12
-+#define KK_3 0x13
-+#define KK_4 0x14
-+#define KK_5 0x15
-+#define KK_6 0x16
-+#define KK_7 0x17
-+#define KK_8 0x18
-+#define KK_9 0x19
-+#define KK_0 0x1a
-+#define KK_MINS 0x1b
-+#define KK_EQLS 0x1c
-+#define KK_BKSP 0x1e
-+#define KK_INS 0x1f
-+#define KK_HOME 0x20
-+#define KK_PGUP 0x21
-+#define KK_NUML 0x22
-+#define KP_SLH 0x23
-+#define KP_STR 0x24
-+#define KP_MNS 0x3a
-+#define KK_TAB 0x26
-+#define KK_Q 0x27
-+#define KK_W 0x28
-+#define KK_E 0x29
-+#define KK_R 0x2a
-+#define KK_T 0x2b
-+#define KK_Y 0x2c
-+#define KK_U 0x2d
-+#define KK_I 0x2e
-+#define KK_O 0x2f
-+#define KK_P 0x30
-+#define KK_LSBK 0x31
-+#define KK_RSBK 0x32
-+#define KK_ENTR 0x47
-+#define KK_DEL 0x34
-+#define KK_END 0x35
-+#define KK_PGDN 0x36
-+#define KP_7 0x37
-+#define KP_8 0x38
-+#define KP_9 0x39
-+#define KP_PLS 0x4b
-+#define KK_CAPS 0x5d
-+#define KK_A 0x3c
-+#define KK_S 0x3d
-+#define KK_D 0x3e
-+#define KK_F 0x3f
-+#define KK_G 0x40
-+#define KK_H 0x41
-+#define KK_J 0x42
-+#define KK_K 0x43
-+#define KK_L 0x44
-+#define KK_SEMI 0x45
-+#define KK_SQOT 0x46
-+#define KK_HASH 0x1d
-+#define KP_4 0x48
-+#define KP_5 0x49
-+#define KP_6 0x4a
-+#define KK_LSFT 0x4c
-+#define KK_BSLH 0x33
-+#define KK_Z 0x4e
-+#define KK_X 0x4f
-+#define KK_C 0x50
-+#define KK_V 0x51
-+#define KK_B 0x52
-+#define KK_N 0x53
-+#define KK_M 0x54
-+#define KK_COMA 0x55
-+#define KK_DOT 0x56
-+#define KK_FSLH 0x57
-+#define KK_RSFT 0x58
-+#define KK_UP 0x59
-+#define KP_1 0x5a
-+#define KP_2 0x5b
-+#define KP_3 0x5c
-+#define KP_ENT 0x67
-+#define KK_LCTL 0x3b
-+#define KK_LALT 0x5e
-+#define KK_SPCE 0x5f
-+#define KK_RALT 0x60
-+#define KK_RCTL 0x61
-+#define KK_LEFT 0x62
-+#define KK_DOWN 0x63
-+#define KK_RGHT 0x64
-+#define KP_0 0x65
-+#define KP_DOT 0x66
-+
-+static char kbmap[128] = {
-+KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_AGR, KK_BSLH, KK_TAB, KK_Z, KK_A, KK_X, KK_NONE,
-+KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_ESC, KK_DEL, KK_Q, KK_CAPS, KK_S, KK_C, KK_3,
-+KK_NONE, KK_1, KK_NONE, KK_W, KK_NONE, KK_D, KK_V, KK_4,
-+KK_NONE, KK_2, KK_T, KK_E, KK_NONE, KK_F, KK_B, KK_5,
-+KK_NONE, KK_9, KK_Y, KK_R, KK_K, KK_G, KK_N, KK_6,
-+KK_NONE, KK_0, KK_U, KK_O, KK_L, KK_H, KK_M, KK_7,
-+KK_NONE, KK_MINS, KK_I, KK_P, KK_SEMI, KK_J, KK_COMA, KK_8,
-+KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_BSLH, KK_FSLH, KK_DOT, KK_NONE,
-+KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP, KK_LEFT, KK_SPCE, KK_RGHT,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+static char kbmapFN[128] = {
-+KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3,
-+KK_NONE, KK_F1, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4,
-+KK_NONE, KK_F2, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5,
-+KK_NONE, KK_F9, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6,
-+KK_NONE, KK_F10, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7,
-+KK_NONE, KK_NUML, KK_NONE, KK_INS, KK_PRNT, KK_NONE, KK_NONE, KK_F8,
-+KK_NONE, KK_BRK, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+static char kbmapNL[128] = {
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KP_9, KK_NONE, KK_NONE, KP_2, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KP_STR, KP_4, KP_6, KP_3, KK_NONE, KP_0, KP_7,
-+KK_NONE, KK_NONE, KP_5, KP_MNS, KP_PLS, KP_1, KK_NONE, KP_8,
-+KK_NONE, KK_NONE, KP_ENT, KK_NONE, KK_NONE, KP_SLH, KP_DOT, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/gc_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,1145 @@
-+/*
-+ * linux/arch/arm/drivers/char/gc_keyb.c
-+ *
-+ * Copyright 2000 Applied Data Systems
-+ *
-+ * Keyboard & Smartio driver for GraphicsClient ARM Linux.
-+ * Graphics Client is SA1110 based single board computer by
-+ * Applied Data Systems (http://www.applieddata.net)
-+ *
-+ * Change log:
-+ * 7-10/6/01 Thomas Thaele <tthaele@papenmeier.de>
-+ * - Added Keyboard Sniffer on /dev/sio12 <minor = 12>
-+ * - First implementation of PC- compatible Scancodes (thanks to pc_keyb.c)
-+ * 3/23/01 Woojung Huh
-+ * Power Management added
-+ * 12/01/00 Woojung Huh
-+ * Bug fixed
-+ * 11/16/00 Woojung Huh [whuh@applieddata.net]
-+ * Added smartio device driver on it
-+ */
-+
-+/*
-+ * Introduced setkeycode, ketkeycode for the GC+ by Thomas Thaele
-+ * <tthaele@papenmeier.de> GC+ now performs like a real PC on the keyboard.
-+ * Warning: this code is still beta! PrntScrn and Pause keys are not
-+ * completely tested and implemented!!! Keyboard driver can be confused
-+ * by hacking like crazy on the keyboard. (hardware problem on serial line?)
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/kbd_kern.h>
-+
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/keyboard.h>
-+#include <linux/tqueue.h>
-+#include <linux/proc_fs.h>
-+#include <linux/pm.h>
-+
-+#define ADS_AVR_IRQ 63
-+
-+#define SMARTIO_IOCTL_BASES 's'
-+#define SMARTIO_KPD_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 0, int)
-+#define SMARTIO_KPD_SETUP _IOW(SMARTIO_IOCTL_BASES, 1, short)
-+#define SMARTIO_BL_CONTROL _IOW(SMARTIO_IOCTL_BASES, 2, char)
-+#define SMARTIO_BL_CONTRAST _IOW(SMARTIO_IOCTL_BASES, 3, char)
-+#define SMARTIO_PORT_CONFIG _IOW(SMARTIO_IOCTL_BASES, 4, char)
-+#define SMARTIO_SNIFFER_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 5, long)
-+
-+
-+/* Simple translation table for the SysRq keys */
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char pckbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+#define E1_PAUSE 119
-+
-+/*
-+ * The keycodes below are randomly located in 89-95,112-118,120-127.
-+ * They could be thrown away (and all occurrences below replaced by 0),
-+ * but that would force many users to use the `setkeycodes' utility, where
-+ * they needed not before. It does not matter that there are duplicates, as
-+ * long as no duplication occurs for any single keyboard.
-+ */
-+#define SC_LIM 89
-+
-+#define FOCUS_PF1 85 /* actual code! */
-+#define FOCUS_PF2 89
-+#define FOCUS_PF3 90
-+#define FOCUS_PF4 91
-+#define FOCUS_PF5 92
-+#define FOCUS_PF6 93
-+#define FOCUS_PF7 94
-+#define FOCUS_PF8 95
-+#define FOCUS_PF9 120
-+#define FOCUS_PF10 121
-+#define FOCUS_PF11 122
-+#define FOCUS_PF12 123
-+
-+#define JAP_86 124
-+/* tfj@olivia.ping.dk:
-+ * The four keys are located over the numeric keypad, and are
-+ * labelled A1-A4. It's an rc930 keyboard, from
-+ * Regnecentralen/RC International, Now ICL.
-+ * Scancodes: 59, 5a, 5b, 5c.
-+ */
-+#define RGN1 124
-+#define RGN2 125
-+#define RGN3 126
-+#define RGN4 127
-+
-+static unsigned char high_keys[128 - SC_LIM] = {
-+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
-+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
-+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
-+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
-+};
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ if (scancode < 128)
-+ high_keys[scancode - SC_LIM] = keycode;
-+ else
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int gc_kbd_getkeycode(unsigned int scancode)
-+{
-+ return
-+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
-+ (scancode < 128) ? high_keys[scancode - SC_LIM] :
-+ e0_keys[scancode - 128];
-+}
-+
-+int gc_kbd_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ /*
-+ * usually it will be 0xe0, but a Pause key generates
-+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
-+ */
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
-+ *keycode = E1_PAUSE;
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ /*
-+ * The keyboard maintains its own internal caps lock and
-+ * num lock statuses. In caps lock mode E0 AA precedes make
-+ * code and E0 2A follows break code. In num lock mode,
-+ * E0 2A precedes make code and E0 AA follows break code.
-+ * We do our own book-keeping, so we will just ignore these.
-+ */
-+ /*
-+ * For my keyboard there is no caps lock mode, but there are
-+ * both Shift-L and Shift-R modes. The former mode generates
-+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
-+ * So, we should also ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else if (scancode >= SC_LIM) {
-+ /* This happens with the FOCUS 9000 keyboard
-+ Its keys PF1..PF12 are reported to generate
-+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
-+ Moreover, unless repeated, they do not generate
-+ key-down events, so we have to zero up_flag below */
-+ /* Also, Japanese 86/106 keyboards are reported to
-+ generate 0x73 and 0x7d for \ - and \ | respectively. */
-+ /* Also, some Brazilian keyboard is reported to produce
-+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
-+
-+ *keycode = high_keys[scancode - SC_LIM];
-+
-+ if (!*keycode) {
-+ if (!raw_mode) {
-+#ifdef KBD_REPORT_UNKN
-+ printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
-+ " - ignored\n", scancode);
-+#endif
-+ }
-+ return 0;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+// this table converts the hardware dependent codes of a MF-2 Keyboard to
-+// the codes normally comming out of a i8042. This table is 128 Bytes too
-+// big, but for stability reasons it should be kept like it is!
-+// There is no range checking in the code!
-+static int mf_two_kbdmap[256] = {
-+ 00, 67, 65, 63, 61, 59, 60, 88, 00, 68, 66, 64, 62, 15, 41, 00,
-+ 00, 56, 42, 00, 29, 16, 02, 00, 00, 00, 44, 31, 30, 17, 03, 00,
-+ 00, 46, 45, 32, 18, 05, 04, 00, 00, 57, 47, 33, 20, 19, 06, 00,
-+ 00, 49, 48, 35, 34, 21, 7, 00, 00, 00, 50, 36, 22, 8, 9, 00,
-+ 00, 51, 37, 23, 24, 11, 10, 00, 00, 52, 53, 38, 39, 25, 12, 00,
-+ 00, 00, 40, 00, 26, 13, 00, 00, 58, 54, 28, 27, 00, 43, 00, 00,
-+ 00, 86, 00, 00, 00, 00, 14, 00, 00, 79, 00, 75, 71, 00, 00, 00,
-+ 82, 83, 80, 76, 77, 72, 01, 69, 87, 78, 81, 74, 55, 73, 70, 00,
-+ 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 };
-+
-+
-+// some texts displayed by the proc_file_system
-+static char *kbd_sniff[2] = { "off", "on" };
-+static char *kbd_sniff_mode[2] = { "passive", "active" };
-+
-+#define PASSIVE 0
-+#define ACTIVE 1
-+
-+// is the sniffer active (1) or inactive (0)
-+static int SNIFFER = 0;
-+// do we get a copy (SNIFFMODE = PASSIVE) or do we get the original data (SNIFFMODE = ACTIVE)
-+// and have to reinsert the data
-+static int SNIFFMODE = PASSIVE;
-+
-+// we allow only one process to sniff
-+static int sniffer_in_use = 0;
-+
-+// timeout for the keyboard sniffer -1 = blocking, otherwise timeout in msecs
-+static long sniffer_timeout = -1;
-+
-+// the value we sniffed from the keyboard
-+static int sniffed_value;
-+
-+static char *smartio_version = "1.02 MF-II compatibility patch <tthaele@papenmeier.de>";
-+static char *smartio_date = "Aug-27-2001";
-+
-+static int sio_reset_flag;
-+static int kbd_press_flag;
-+
-+static void send_SSP_msg(unchar *pBuf, int num)
-+{
-+ ushort tmp;
-+ int i;
-+
-+ for (i=0;i<num;i++) {
-+ while ((Ser4SSSR & SSSR_TNF) == 0);
-+ tmp = pBuf[i];
-+ Ser4SSDR = (tmp << 8);
-+ }
-+
-+ // Throw away Echo
-+ for (i=0;i<num;i++) {
-+ while ((Ser4SSSR & SSSR_RNE) == 0);
-+ tmp = Ser4SSDR;
-+ }
-+}
-+
-+static unchar ReadSSPByte(void)
-+{
-+ if (Ser4SSSR & SSSR_ROR) {
-+ printk("%s() : Overrun\n", __FUNCTION__);
-+ return 0;
-+ }
-+
-+ Ser4SSDR = 0x00;
-+
-+ while ((Ser4SSSR & SSSR_RNE) == 0);
-+
-+ return ((unchar) Ser4SSDR);
-+}
-+
-+static ulong read_SSP_response(int num)
-+{
-+ int i;
-+ ulong ret;
-+
-+ // discard leading 0x00 and command echo 0 (command group value)
-+ while (ReadSSPByte() == 0);
-+ // discard command echo 1 (command code value)
-+ ReadSSPByte();
-+
-+ // data from SMARTIO
-+ // It assumes LSB first.
-+ // NOTE:Some command uses MSB first order
-+ ret = 0;
-+ for (i=0;i<num;i++) {
-+ ret |= ReadSSPByte() << (8*i);
-+ }
-+
-+ return ret;
-+}
-+
-+typedef struct t_SMARTIO_CMD {
-+ unchar Group;
-+ unchar Code;
-+ unchar Opt[2];
-+} SMARTIO_CMD;
-+
-+static SMARTIO_CMD RD_INT_CMD = { 0x83, 0x01, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_KBD_CMD = { 0x83, 0x02, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_ADC_CMD = { 0x83, 0x28, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_KPD_CMD = { 0x83, 0x04, { 0x00, 0x00 } };
-+
-+static volatile ushort adc_value;
-+static volatile unchar kpd_value;
-+static unsigned int kpd_timeout = 10000; // 10000 msec
-+
-+static ulong kbd_int, kpd_int, adc_int;
-+
-+static void smartio_interrupt_task(void *data);
-+
-+static struct tq_struct tq_smartio = {
-+ { NULL, NULL }, // struct list_head
-+ 0, // unsigned long sync
-+ smartio_interrupt_task, // void (*routine)(void *)
-+ NULL, // void *data
-+};
-+
-+DECLARE_WAIT_QUEUE_HEAD(smartio_queue);
-+DECLARE_WAIT_QUEUE_HEAD(smartio_adc_queue);
-+DECLARE_WAIT_QUEUE_HEAD(smartio_kpd_queue);
-+DECLARE_WAIT_QUEUE_HEAD(keyboard_done_queue);
-+DECLARE_WAIT_QUEUE_HEAD(sniffer_queue);
-+
-+static spinlock_t smartio_busy_lock = SPIN_LOCK_UNLOCKED;
-+static atomic_t smartio_busy = ATOMIC_INIT(0);
-+
-+static int f_five_pressed = 0;
-+static int f_seven_pressed = 0;
-+//static int e_null_counter = 0;
-+//static int f_null_counter = 0;
-+//static int keydown = 0;
-+static unchar previous_code = 0;
-+//static int e0 = 0;
-+
-+static void smartio_interrupt_task(void *arg)
-+{
-+ unchar code;
-+ unsigned long flags;
-+ unchar dummy;
-+
-+ spin_lock_irqsave(&smartio_busy_lock, flags);
-+ if (atomic_read(&smartio_busy) == 1) {
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+ queue_task(&tq_smartio, &tq_timer);
-+ }
-+ else {
-+ atomic_set(&smartio_busy, 1);
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+ }
-+
-+ /* Read SMARTIO Interrupt Status to check which Interrupt is occurred
-+ * and Clear SMARTIO Interrupt */
-+ send_SSP_msg((unchar *) &RD_INT_CMD, 2);
-+ code = (unchar) (read_SSP_response(1) & 0xFF);
-+
-+#ifdef CONFIG_VT
-+ if (code & 0x04) { // Keyboard Interrupt
-+ kbd_int++;
-+ /* Read Scan code */
-+ send_SSP_msg((unchar *) &RD_KBD_CMD, 2);
-+ code = (unchar) (read_SSP_response(1) & 0xFF);
-+ dummy = code & 0x80;
-+ if ((code == 0xE0) || (code == 0xE1) || (code == 0xF0)) { // combined code
-+ if (code == 0xF0) {
-+ if (!previous_code) {
-+ code = 0xE0;
-+ previous_code = 0xF0;
-+ } else {
-+ code = mf_two_kbdmap[code & 0x7F] | dummy;
-+ previous_code = 0;
-+ }
-+ } else if (code == 0xE0) {
-+ if (previous_code != 0) {
-+ code = mf_two_kbdmap[code & 0x7F] | dummy;
-+ previous_code = 0;
-+ } else previous_code = code;
-+ } else { // 0xE1
-+ if (!previous_code) {
-+ code = mf_two_kbdmap[code &0x7F] | dummy;
-+ previous_code = 0;
-+ } else {
-+ previous_code = code;
-+ }
-+ }
-+ } else {
-+ if (code == 0x03) {
-+ f_five_pressed = 1;
-+ } else if (code == 0x83) {
-+ if (f_five_pressed != 0) {
-+ f_five_pressed = 0;
-+ code = 0x03;
-+ } else if (f_seven_pressed == 0) {
-+ f_seven_pressed = 1;
-+ code = 2;
-+ dummy = 0;
-+ } else {
-+ f_seven_pressed = 0;
-+ code = 2;
-+ }
-+ }
-+ previous_code = 0;
-+ code &= 0x7F;
-+ code = mf_two_kbdmap[code] | dummy;
-+ }
-+ sniffed_value = (ushort)code;
-+ if (SNIFFER) wake_up_interruptible(&sniffer_queue);
-+ if (SNIFFMODE == PASSIVE) {
-+ handle_scancode( code, (code & 0x80) ? 0 : 1 );
-+ if (code & 0x80) {
-+ wake_up_interruptible(&keyboard_done_queue);
-+ mdelay(10); // this makes the whole thing a bit more stable
-+ // keyboard handling can be corrupted when hitting
-+ // thousands of keys like crazy. kbd_translate might catch up
-+ // with irq routine? or there is simply a buffer overflow on
-+ // the serial device? somehow it looses some key sequences.
-+ // if a break code is lost or coruppted the keyboard starts
-+ // to autorepeat like crazy and appears to hang.
-+ // this needs further investigations! Thomas
-+ kbd_press_flag = 0;
-+ }
-+ else
-+ kbd_press_flag = 1;
-+ }
-+ code = 0; // prevent furthermore if ... then to react!
-+ }
-+#endif
-+ // ADC resolution is 10bit (0x000 ~ 0x3FF)
-+ if (code & 0x02) { // ADC Complete Interrupt
-+ adc_int++;
-+ send_SSP_msg((unchar *) &RD_ADC_CMD, 2);
-+ adc_value = (ushort) (read_SSP_response(2) & 0x3FF);
-+ wake_up_interruptible(&smartio_adc_queue);
-+ }
-+
-+ if (code & 0x08) { // Keypad interrupt
-+ kpd_int++;
-+ send_SSP_msg((unchar *) &RD_KPD_CMD, 2);
-+ kpd_value = (unchar) (read_SSP_response(1) & 0xFF);
-+ wake_up_interruptible(&smartio_kpd_queue);
-+ }
-+
-+ spin_lock_irqsave(&smartio_busy_lock, flags);
-+ atomic_set(&smartio_busy, 0);
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+
-+ enable_irq(ADS_AVR_IRQ);
-+
-+ wake_up_interruptible(&smartio_queue);
-+}
-+
-+static void gc_sio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+
-+ // *NOTE*
-+ // ADS SMARTIO interrupt is cleared after reading interrupt status
-+ // from smartio.
-+ // disable SMARTIO IRQ here and re-enable at samrtio_bh.
-+ // 11/13/00 Woojung
-+ disable_irq(ADS_AVR_IRQ);
-+
-+ queue_task(&tq_smartio, &tq_immediate);
-+ mark_bh(IMMEDIATE_BH);
-+}
-+
-+char gc_kbd_unexpected_up(unsigned char keycode)
-+{
-+ return 0;
-+}
-+
-+static inline void gc_sio_init(void)
-+{
-+ GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); // Output
-+ GPDR &= ~GPIO_GPIO11;
-+
-+ // Alternative Function
-+ GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13);
-+
-+ Ser4SSCR0 = 0xA707;
-+ Ser4SSSR = SSSR_ROR;
-+ Ser4SSCR1 = 0x0010;
-+ Ser4SSCR0 = 0xA787;
-+
-+ // Reset SMARTIO
-+ ADS_AVR_REG &= 0xFE;
-+ mdelay(300); // 10 mSec
-+ ADS_AVR_REG |= 0x01;
-+ mdelay(10); // 10 mSec
-+
-+}
-+
-+void __init gc_kbd_init_hw(void)
-+{
-+ printk (KERN_INFO "Graphics Client keyboard driver v1.0\n");
-+
-+ k_setkeycode = gc_kbd_setkeycode;
-+ k_getkeycode = gc_kbd_getkeycode;
-+ k_translate = gc_kbd_translate;
-+ k_unexpected_up = gc_kbd_unexpected_up;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_key = 0x54;
-+ /* sysrq table??? --rmk */
-+#endif
-+
-+ gc_sio_init();
-+
-+ if (request_irq(ADS_AVR_IRQ,gc_sio_interrupt,0,"smartio", NULL) != 0)
-+ printk("Could not allocate SMARTIO IRQ!\n");
-+
-+ sio_reset_flag = 1;
-+}
-+
-+/* SMARTIO ADC Interface */
-+#define SMARTIO_VERSION 0
-+#define SMARTIO_PORT_A 1
-+#define SMARTIO_PORT_B 2
-+#define SMARTIO_PORT_C 3
-+#define SMARTIO_PORT_D 4
-+#define SMARTIO_SELECT_OPTION 5
-+#define SMARTIO_BACKLITE 6
-+#define SMARTIO_KEYPAD 7
-+#define SMARTIO_ADC 8
-+#define SMARTIO_VEE_PWM 9
-+#define SMARTIO_SLEEP 11
-+#define SMARTIO_KBD_SNIFFER 12
-+
-+static SMARTIO_CMD CONV_ADC_CMD = { 0x80, 0x28, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_PORT_CMD = { 0x82, 0x00, { 0x00, 0x00 } };
-+
-+static SMARTIO_CMD READ_DEVVER_CMD = { 0x82, 0x05, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_DEVTYPE_CMD = { 0x82, 0x06, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_FWLEVEL_CMD = { 0x82, 0x07, { 0x00, 0x00 } };
-+
-+static int lock_smartio(unsigned long *flags)
-+{
-+ spin_lock_irqsave(&smartio_busy_lock, *flags);
-+ if (atomic_read(&smartio_busy) == 1) {
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+ interruptible_sleep_on(&smartio_queue);
-+ }
-+ else {
-+ atomic_set(&smartio_busy, 1);
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+ }
-+
-+ return 1;
-+}
-+
-+static int unlock_smartio(unsigned long *flags)
-+{
-+ spin_lock_irqsave(&smartio_busy_lock, *flags);
-+ atomic_set(&smartio_busy, 0);
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+
-+ return 1;
-+}
-+
-+static ushort read_sio_adc(int channel)
-+{
-+ unsigned long flags;
-+
-+ if ((channel < 0) || (channel > 7))
-+ return 0xFFFF;
-+
-+ CONV_ADC_CMD.Opt[0] = (unchar) channel;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONV_ADC_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ interruptible_sleep_on(&smartio_adc_queue);
-+
-+ return adc_value & 0x3FF;
-+}
-+
-+static ushort read_sio_port(int port)
-+{
-+ unsigned long flags;
-+ ushort ret;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ READ_PORT_CMD.Code = (unchar) port;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_PORT_CMD, 2);
-+ ret = read_SSP_response(1);
-+ unlock_smartio(&flags);
-+
-+ return ret;
-+}
-+
-+static ushort read_sio_kpd(void)
-+{
-+ long timeout;
-+
-+ // kpd_timeout is mSec order
-+ // interrupt_sleep_on_timeout is based on 10msec timer tick
-+ if (kpd_timeout == -1) {
-+ interruptible_sleep_on(&smartio_kpd_queue);
-+ }
-+ else {
-+ timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue,
-+ kpd_timeout/10);
-+ if (timeout == 0) {
-+ // timeout without keypad input
-+ return 0xFFFF;
-+ }
-+ }
-+ return kpd_value;
-+}
-+
-+static ushort read_sio_sniff(void)
-+{
-+ long timeout;
-+
-+ // kpd_timeout is mSec order
-+ // interrupt_sleep_on_timeout is based on 10msec timer tick
-+ if (sniffer_timeout == -1) {
-+ interruptible_sleep_on(&sniffer_queue);
-+ }
-+ else {
-+ timeout = interruptible_sleep_on_timeout(&sniffer_queue,
-+ sniffer_timeout/10);
-+ if (timeout == 0) {
-+ // timeout without keypad input
-+ return -1;
-+ }
-+ }
-+ return (ushort)sniffed_value;
-+}
-+
-+static struct sio_ver {
-+ uint DevVer;
-+ uint DevType;
-+ uint FwLevel;
-+};
-+
-+static ushort read_sio_version(struct sio_ver *ptr)
-+{
-+ unsigned long flags;
-+ ushort ret;
-+
-+ // Read Device Version
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2);
-+ ret = read_SSP_response(1);
-+ unlock_smartio(&flags);
-+ ptr->DevVer = (uint)ret;
-+ // Read Device Type
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2);
-+ ret = read_SSP_response(2);
-+ unlock_smartio(&flags);
-+ // swap MSB & LSB
-+ ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
-+ ptr->DevType = (uint)ret;
-+ // Read Firmware Level
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2);
-+ ret = read_SSP_response(2);
-+ unlock_smartio(&flags);
-+ // swap MSB & LSB
-+ ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
-+ ptr->FwLevel = (uint)ret;
-+
-+ return 0;
-+}
-+
-+static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ struct inode *inode = file->f_dentry->d_inode;
-+ unsigned int minor = MINOR(inode->i_rdev);
-+ ushort *ret = (ushort *)buf;
-+
-+ switch (minor) {
-+ case SMARTIO_ADC:
-+ if ((*ret = read_sio_adc(buf[0])) != 0xFFFF)
-+ return sizeof(ushort); // 2 bytes
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if ((*ret = read_sio_port(minor)) != 0xFFFF)
-+ return sizeof(ushort);
-+ case SMARTIO_VERSION:
-+ if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF)
-+ return sizeof(struct sio_ver);
-+ case SMARTIO_KEYPAD:
-+ if ((*ret = read_sio_kpd()) != 0xFFFF)
-+ return sizeof(ushort);
-+ case SMARTIO_KBD_SNIFFER:
-+ if ((*ret = read_sio_sniff()) != (ushort)-1)
-+ return 1;
-+ default :
-+ return -ENXIO;
-+ }
-+}
-+
-+static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } };
-+
-+static ushort write_sio_port(int port, unchar value)
-+{
-+ unsigned long flags;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ WRITE_PORT_CMD.Code = (unchar) port;
-+ WRITE_PORT_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort write_sio_select(unchar select)
-+{
-+ unsigned long flags;
-+
-+ if ((select < 1) || (select > 2))
-+ return 0xFFFF;
-+
-+ SELECT_OPT_CMD.Code = (unchar) (select + 0x28);
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_backlite(int cmd, int value)
-+{
-+ unsigned long flags;
-+
-+ if (cmd == SMARTIO_BL_CONTRAST) {
-+ value &= 0xFF;
-+ CONTRAST_BL_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3);
-+ unlock_smartio(&flags);
-+ }
-+ else if (cmd == SMARTIO_BL_CONTROL) {
-+ if (value == 0x00) {
-+ // Backlite OFF
-+ CONTROL_BL_CMD.Code = 0x24;
-+ }
-+ else {
-+ // Backlite ON
-+ CONTROL_BL_CMD.Code = 0x23;
-+ }
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2);
-+ unlock_smartio(&flags);
-+ }
-+ else
-+ return 0xFFFF;
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_keypad(int x, int y)
-+{
-+ unsigned long flags;
-+
-+ if ( (x<1) || (x>8) || (y<1) || (y>8)) {
-+ return 0xFFFF;
-+ }
-+
-+ CONTROL_KPD_CMD.Opt[0] = (unchar) x;
-+ CONTROL_KPD_CMD.Opt[1] = (unchar) y;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_vee(int value)
-+{
-+ unsigned long flags;
-+
-+ value &= 0xFF;
-+ CONTROL_VEE_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos)
-+{
-+ struct inode *inode = file->f_dentry->d_inode;
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ switch (minor) {
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if (write_sio_port(minor, buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_SELECT_OPTION:
-+ if (write_sio_select(buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_BACKLITE:
-+ if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_KEYPAD:
-+ if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF)
-+ return 2;
-+ case SMARTIO_VEE_PWM:
-+ if (control_sio_vee(buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_KBD_SNIFFER:
-+ // here are the scancodes injected
-+ handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1);
-+ wake_up_interruptible(&keyboard_done_queue);
-+ // give some time to process! File IO is a bit faster than manual typing ;-)
-+ udelay(10000);
-+ return 1;
-+ default:
-+ return -ENXIO;
-+ }
-+}
-+
-+static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait)
-+{
-+ return 0;
-+}
-+
-+static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
-+
-+static ushort ioctl_sio_port(int port, unchar value)
-+{
-+ unsigned long flags;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08
-+ if (port == SMARTIO_PORT_B) {
-+ // Port B has 4 bits only
-+ IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F;
-+ }
-+ else
-+ IOCTL_PORT_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+ unchar *buf = (unchar *)arg;
-+
-+ switch (minor) {
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if (cmd == SMARTIO_PORT_CONFIG) {
-+ if (ioctl_sio_port(minor, buf[0]) != 0xFFFF)
-+ return 0;
-+ }
-+ return -EINVAL;
-+ case SMARTIO_SELECT_OPTION:
-+ if (write_sio_select(buf[0]) != 0xFFFF) return 0;
-+ return -EINVAL;
-+ case SMARTIO_BACKLITE:
-+ if (cmd == SMARTIO_BL_CONTROL) {
-+ if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0;
-+ }
-+ else if (cmd == SMARTIO_BL_CONTRAST) {
-+ if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0;
-+ }
-+ else return -EINVAL;
-+ case SMARTIO_KEYPAD:
-+ if (cmd == SMARTIO_KPD_TIMEOUT) {
-+ kpd_timeout = *(long*)buf;
-+ return 0;
-+ }
-+ else if (cmd == SMARTIO_KPD_SETUP) {
-+ if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0;
-+ }
-+ return -EINVAL;
-+ case SMARTIO_VEE_PWM:
-+ if (control_sio_vee(buf[0]) != 0xFFFF) return 0;
-+ return -EINVAL;
-+ case SMARTIO_KBD_SNIFFER:
-+ if (cmd == SMARTIO_SNIFFER_TIMEOUT) {
-+ sniffer_timeout = *(long*)buf;
-+ if (sniffer_timeout < 0) sniffer_timeout = -1;
-+ // the value will be devided by 10 later on
-+ if (!sniffer_timeout) sniffer_timeout = 10;
-+ return 0;
-+ }
-+ return -EINVAL;
-+ default:
-+ return -ENXIO;
-+ }
-+}
-+
-+static int sio_open(struct inode *inode, struct file *file)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ // we open all by default. we only have a special handler for the kbd sniffer
-+ switch (minor) {
-+ case SMARTIO_KBD_SNIFFER:
-+ if (sniffer_in_use) return -EBUSY;
-+ sniffer_in_use = 1;
-+ SNIFFER = 1;
-+ // sniff in active or passive mode
-+ if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0;
-+ // do we have a blocking or non blocking sniffer?
-+ if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1;
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int sio_close(struct inode *inode, struct file *file)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ switch (minor) {
-+ case SMARTIO_KBD_SNIFFER:
-+ SNIFFER = 0;
-+ SNIFFMODE = 0;
-+ sniffer_in_use = 0;
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static struct file_operations sio_fops = {
-+ read: sio_read,
-+ write: sio_write,
-+ poll: sio_poll,
-+ ioctl: sio_ioctl,
-+ open: sio_open,
-+ release: sio_close,
-+};
-+
-+static struct proc_dir_entry *sio_dir, *parent_dir = NULL;
-+
-+#define SMARTIO_MAJOR 58
-+#define MAJOR_NR SMARTIO_MAJOR
-+
-+#define PROC_NAME "sio"
-+
-+static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data)
-+{
-+ char *p = buf;
-+
-+ p += sprintf(p, "ADS SMARTIO Status: \n");
-+ p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int);
-+ p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int);
-+ p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int);
-+ p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]);
-+
-+ return (p-buf);
-+}
-+
-+#ifdef CONFIG_PM
-+static int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ switch (rqst) {
-+ case PM_RESUME:
-+ gc_sio_init();
-+ break;
-+ case PM_SUSPEND:
-+ // 4/5/01 Woojung
-+ // It checks Keybard received pair of press/release code.
-+ // System can sleep before receiving release code
-+ if (kbd_press_flag) {
-+ interruptible_sleep_on(&keyboard_done_queue);
-+ }
-+ break;
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+void __init sio_init(void)
-+{
-+ if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) {
-+ printk("smartio : unable to get major %d\n", MAJOR_NR);
-+ return;
-+ }
-+ else {
-+ printk("smartio driver initialized. version %s, date:%s\n",
-+ smartio_version, smartio_date);
-+
-+ if (sio_reset_flag != 1) {
-+ gc_sio_init();
-+ if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){
-+ printk("smartio : Could not allocate IRQ!\n");
-+ return;
-+ }
-+ }
-+
-+ if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) {
-+ printk("smartio : Unable to create /proc entry\n");
-+ return;
-+ }
-+ else {
-+ sio_dir->read_proc = sio_read_proc;
-+#ifdef CONFIG_PM
-+ pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback);
-+#endif
-+ }
-+ }
-+}
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/gckeymap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,262 @@
-+/* Do not edit this file! It was automatically generated by */
-+/* loadkeys --mktable defkeymap.map > defkeymap.c */
-+
-+#include <linux/types.h>
-+#include <linux/keyboard.h>
-+#include <linux/kd.h>
-+
-+u_short plain_map[NR_KEYS] = {
-+ 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
-+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
-+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
-+ 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
-+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
-+ 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
-+ 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
-+ 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
-+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short shift_map[NR_KEYS] = {
-+ 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
-+ 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
-+ 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
-+ 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
-+ 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
-+ 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
-+ 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
-+ 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
-+ 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short altgr_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
-+ 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
-+ 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
-+ 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
-+ 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
-+ 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
-+ 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
-+ 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
-+ 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
-+ 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short ctrl_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
-+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
-+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
-+ 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
-+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
-+ 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
-+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
-+ 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
-+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short shift_ctrl_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
-+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
-+ 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
-+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
-+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short alt_map[NR_KEYS] = {
-+ 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
-+ 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
-+ 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
-+ 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
-+ 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
-+ 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
-+ 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
-+ 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
-+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
-+ 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
-+ 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
-+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short ctrl_alt_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
-+ 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
-+ 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
-+ 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
-+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
-+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+ushort *key_maps[MAX_NR_KEYMAPS] = {
-+ plain_map, shift_map, altgr_map, 0,
-+ ctrl_map, shift_ctrl_map, 0, 0,
-+ alt_map, 0, 0, 0,
-+ ctrl_alt_map, 0
-+};
-+
-+unsigned int keymap_count = 7;
-+
-+/*
-+ * Philosophy: most people do not define more strings, but they who do
-+ * often want quite a lot of string space. So, we statically allocate
-+ * the default and allocate dynamically in chunks of 512 bytes.
-+ */
-+
-+char func_buf[] = {
-+ '\033', '[', '[', 'A', 0,
-+ '\033', '[', '[', 'B', 0,
-+ '\033', '[', '[', 'C', 0,
-+ '\033', '[', '[', 'D', 0,
-+ '\033', '[', '[', 'E', 0,
-+ '\033', '[', '1', '7', '~', 0,
-+ '\033', '[', '1', '8', '~', 0,
-+ '\033', '[', '1', '9', '~', 0,
-+ '\033', '[', '2', '0', '~', 0,
-+ '\033', '[', '2', '1', '~', 0,
-+ '\033', '[', '2', '3', '~', 0,
-+ '\033', '[', '2', '4', '~', 0,
-+ '\033', '[', '2', '5', '~', 0,
-+ '\033', '[', '2', '6', '~', 0,
-+ '\033', '[', '2', '8', '~', 0,
-+ '\033', '[', '2', '9', '~', 0,
-+ '\033', '[', '3', '1', '~', 0,
-+ '\033', '[', '3', '2', '~', 0,
-+ '\033', '[', '3', '3', '~', 0,
-+ '\033', '[', '3', '4', '~', 0,
-+ '\033', '[', '1', '~', 0,
-+ '\033', '[', '2', '~', 0,
-+ '\033', '[', '3', '~', 0,
-+ '\033', '[', '4', '~', 0,
-+ '\033', '[', '5', '~', 0,
-+ '\033', '[', '6', '~', 0,
-+ '\033', '[', 'M', 0,
-+ '\033', '[', 'P', 0,
-+};
-+
-+char *funcbufptr = func_buf;
-+int funcbufsize = sizeof(func_buf);
-+int funcbufleft = 0; /* space left */
-+
-+char *func_table[MAX_NR_FUNC] = {
-+ func_buf + 0,
-+ func_buf + 5,
-+ func_buf + 10,
-+ func_buf + 15,
-+ func_buf + 20,
-+ func_buf + 25,
-+ func_buf + 31,
-+ func_buf + 37,
-+ func_buf + 43,
-+ func_buf + 49,
-+ func_buf + 55,
-+ func_buf + 61,
-+ func_buf + 67,
-+ func_buf + 73,
-+ func_buf + 79,
-+ func_buf + 85,
-+ func_buf + 91,
-+ func_buf + 97,
-+ func_buf + 103,
-+ func_buf + 109,
-+ func_buf + 115,
-+ func_buf + 120,
-+ func_buf + 125,
-+ func_buf + 130,
-+ func_buf + 135,
-+ func_buf + 140,
-+ func_buf + 145,
-+ 0,
-+ 0,
-+ func_buf + 149,
-+ 0,
-+};
-+
-+struct kbdiacr accent_table[MAX_DIACR] = {
-+ {'`', 'A', '\300'}, {'`', 'a', '\340'},
-+ {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
-+ {'^', 'A', '\302'}, {'^', 'a', '\342'},
-+ {'~', 'A', '\303'}, {'~', 'a', '\343'},
-+ {'"', 'A', '\304'}, {'"', 'a', '\344'},
-+ {'O', 'A', '\305'}, {'o', 'a', '\345'},
-+ {'0', 'A', '\305'}, {'0', 'a', '\345'},
-+ {'A', 'A', '\305'}, {'a', 'a', '\345'},
-+ {'A', 'E', '\306'}, {'a', 'e', '\346'},
-+ {',', 'C', '\307'}, {',', 'c', '\347'},
-+ {'`', 'E', '\310'}, {'`', 'e', '\350'},
-+ {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
-+ {'^', 'E', '\312'}, {'^', 'e', '\352'},
-+ {'"', 'E', '\313'}, {'"', 'e', '\353'},
-+ {'`', 'I', '\314'}, {'`', 'i', '\354'},
-+ {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
-+ {'^', 'I', '\316'}, {'^', 'i', '\356'},
-+ {'"', 'I', '\317'}, {'"', 'i', '\357'},
-+ {'-', 'D', '\320'}, {'-', 'd', '\360'},
-+ {'~', 'N', '\321'}, {'~', 'n', '\361'},
-+ {'`', 'O', '\322'}, {'`', 'o', '\362'},
-+ {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
-+ {'^', 'O', '\324'}, {'^', 'o', '\364'},
-+ {'~', 'O', '\325'}, {'~', 'o', '\365'},
-+ {'"', 'O', '\326'}, {'"', 'o', '\366'},
-+ {'/', 'O', '\330'}, {'/', 'o', '\370'},
-+ {'`', 'U', '\331'}, {'`', 'u', '\371'},
-+ {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
-+ {'^', 'U', '\333'}, {'^', 'u', '\373'},
-+ {'"', 'U', '\334'}, {'"', 'u', '\374'},
-+ {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
-+ {'T', 'H', '\336'}, {'t', 'h', '\376'},
-+ {'s', 's', '\337'}, {'"', 'y', '\377'},
-+ {'s', 'z', '\337'}, {'i', 'j', '\377'},
-+};
-+
-+unsigned int accent_table_size = 68;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/gckeymap.map 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,357 @@
-+# Default kernel keymap. This uses 7 modifier combinations.
-+keymaps 0-2,4-5,8,12
-+# Change the above line into
-+# keymaps 0-2,4-6,8,12
-+# in case you want the entries
-+# altgr control keycode 83 = Boot
-+# altgr control keycode 111 = Boot
-+# below.
-+#
-+# In fact AltGr is used very little, and one more keymap can
-+# be saved by mapping AltGr to Alt (and adapting a few entries):
-+# keycode 100 = Alt
-+#
-+keycode 1 = Escape Escape
-+ alt keycode 1 = Meta_Escape
-+keycode 2 = one exclam
-+ alt keycode 2 = Meta_one
-+keycode 3 = two at at
-+ control keycode 3 = nul
-+ shift control keycode 3 = nul
-+ alt keycode 3 = Meta_two
-+keycode 4 = three numbersign
-+ control keycode 4 = Escape
-+ alt keycode 4 = Meta_three
-+keycode 5 = four dollar dollar
-+ control keycode 5 = Control_backslash
-+ alt keycode 5 = Meta_four
-+keycode 6 = five percent
-+ control keycode 6 = Control_bracketright
-+ alt keycode 6 = Meta_five
-+keycode 7 = six asciicircum
-+ control keycode 7 = Control_asciicircum
-+ alt keycode 7 = Meta_six
-+keycode 8 = seven ampersand braceleft
-+ control keycode 8 = Control_underscore
-+ alt keycode 8 = Meta_seven
-+keycode 9 = eight asterisk bracketleft
-+ control keycode 9 = Delete
-+ alt keycode 9 = Meta_eight
-+keycode 10 = nine parenleft bracketright
-+ alt keycode 10 = Meta_nine
-+keycode 11 = zero parenright braceright
-+ alt keycode 11 = Meta_zero
-+keycode 12 = minus underscore backslash
-+ control keycode 12 = Control_underscore
-+ shift control keycode 12 = Control_underscore
-+ alt keycode 12 = Meta_minus
-+keycode 13 = equal plus
-+ alt keycode 13 = Meta_equal
-+keycode 14 = Delete Delete
-+ control keycode 14 = BackSpace
-+ alt keycode 14 = Meta_Delete
-+keycode 15 = Tab Tab
-+ alt keycode 15 = Meta_Tab
-+keycode 16 = q
-+keycode 17 = w
-+keycode 18 = e
-+ altgr keycode 18 = Hex_E
-+keycode 19 = r
-+keycode 20 = t
-+keycode 21 = y
-+keycode 22 = u
-+keycode 23 = i
-+keycode 24 = o
-+keycode 25 = p
-+keycode 26 = bracketleft braceleft
-+ control keycode 26 = Escape
-+ alt keycode 26 = Meta_bracketleft
-+keycode 27 = bracketright braceright asciitilde
-+ control keycode 27 = Control_bracketright
-+ alt keycode 27 = Meta_bracketright
-+keycode 28 = Return
-+ alt keycode 28 = Meta_Control_m
-+keycode 29 = Control
-+keycode 30 = a
-+ altgr keycode 30 = Hex_A
-+keycode 31 = s
-+keycode 32 = d
-+ altgr keycode 32 = Hex_D
-+keycode 33 = f
-+ altgr keycode 33 = Hex_F
-+keycode 34 = g
-+keycode 35 = h
-+keycode 36 = j
-+keycode 37 = k
-+keycode 38 = l
-+keycode 39 = semicolon colon
-+ alt keycode 39 = Meta_semicolon
-+keycode 40 = apostrophe quotedbl
-+ control keycode 40 = Control_g
-+ alt keycode 40 = Meta_apostrophe
-+keycode 41 = grave asciitilde
-+ control keycode 41 = nul
-+ alt keycode 41 = Meta_grave
-+keycode 42 = Shift
-+keycode 43 = backslash bar
-+ control keycode 43 = Control_backslash
-+ alt keycode 43 = Meta_backslash
-+keycode 44 = z
-+keycode 45 = x
-+keycode 46 = c
-+ altgr keycode 46 = Hex_C
-+keycode 47 = v
-+keycode 48 = b
-+ altgr keycode 48 = Hex_B
-+keycode 49 = n
-+keycode 50 = m
-+keycode 51 = comma less
-+ alt keycode 51 = Meta_comma
-+keycode 52 = period greater
-+ control keycode 52 = Compose
-+ alt keycode 52 = Meta_period
-+keycode 53 = slash question
-+ control keycode 53 = Delete
-+ alt keycode 53 = Meta_slash
-+keycode 54 = Shift
-+keycode 55 = KP_Multiply
-+keycode 56 = Alt
-+keycode 57 = space space
-+ control keycode 57 = nul
-+ alt keycode 57 = Meta_space
-+keycode 58 = Caps_Lock
-+keycode 59 = F1 F11 Console_13
-+ control keycode 59 = F1
-+ alt keycode 59 = Console_1
-+ control alt keycode 59 = Console_1
-+keycode 60 = F2 F12 Console_14
-+ control keycode 60 = F2
-+ alt keycode 60 = Console_2
-+ control alt keycode 60 = Console_2
-+keycode 61 = F3 F13 Console_15
-+ control keycode 61 = F3
-+ alt keycode 61 = Console_3
-+ control alt keycode 61 = Console_3
-+keycode 62 = F4 F14 Console_16
-+ control keycode 62 = F4
-+ alt keycode 62 = Console_4
-+ control alt keycode 62 = Console_4
-+keycode 63 = F5 F15 Console_17
-+ control keycode 63 = F5
-+ alt keycode 63 = Console_5
-+ control alt keycode 63 = Console_5
-+keycode 64 = F6 F16 Console_18
-+ control keycode 64 = F6
-+ alt keycode 64 = Console_6
-+ control alt keycode 64 = Console_6
-+keycode 65 = F7 F17 Console_19
-+ control keycode 65 = F7
-+ alt keycode 65 = Console_7
-+ control alt keycode 65 = Console_7
-+keycode 66 = F8 F18 Console_20
-+ control keycode 66 = F8
-+ alt keycode 66 = Console_8
-+ control alt keycode 66 = Console_8
-+keycode 67 = F9 F19 Console_21
-+ control keycode 67 = F9
-+ alt keycode 67 = Console_9
-+ control alt keycode 67 = Console_9
-+keycode 68 = F10 F20 Console_22
-+ control keycode 68 = F10
-+ alt keycode 68 = Console_10
-+ control alt keycode 68 = Console_10
-+keycode 69 = Num_Lock
-+ shift keycode 69 = Bare_Num_Lock
-+keycode 70 = Scroll_Lock Show_Memory Show_Registers
-+ control keycode 70 = Show_State
-+ alt keycode 70 = Scroll_Lock
-+keycode 71 = KP_7
-+ alt keycode 71 = Ascii_7
-+ altgr keycode 71 = Hex_7
-+keycode 72 = KP_8
-+ alt keycode 72 = Ascii_8
-+ altgr keycode 72 = Hex_8
-+keycode 73 = KP_9
-+ alt keycode 73 = Ascii_9
-+ altgr keycode 73 = Hex_9
-+keycode 74 = KP_Subtract
-+keycode 75 = KP_4
-+ alt keycode 75 = Ascii_4
-+ altgr keycode 75 = Hex_4
-+keycode 76 = KP_5
-+ alt keycode 76 = Ascii_5
-+ altgr keycode 76 = Hex_5
-+keycode 77 = KP_6
-+ alt keycode 77 = Ascii_6
-+ altgr keycode 77 = Hex_6
-+keycode 78 = KP_Add
-+keycode 79 = KP_1
-+ alt keycode 79 = Ascii_1
-+ altgr keycode 79 = Hex_1
-+keycode 80 = KP_2
-+ alt keycode 80 = Ascii_2
-+ altgr keycode 80 = Hex_2
-+keycode 81 = KP_3
-+ alt keycode 81 = Ascii_3
-+ altgr keycode 81 = Hex_3
-+keycode 82 = KP_0
-+ alt keycode 82 = Ascii_0
-+ altgr keycode 82 = Hex_0
-+keycode 83 = KP_Period
-+# altgr control keycode 83 = Boot
-+ control alt keycode 83 = Boot
-+keycode 84 = Last_Console
-+keycode 85 =
-+keycode 86 = less greater bar
-+ alt keycode 86 = Meta_less
-+keycode 87 = F11 F11 Console_23
-+ control keycode 87 = F11
-+ alt keycode 87 = Console_11
-+ control alt keycode 87 = Console_11
-+keycode 88 = F12 F12 Console_24
-+ control keycode 88 = F12
-+ alt keycode 88 = Console_12
-+ control alt keycode 88 = Console_12
-+keycode 89 =
-+keycode 90 =
-+keycode 91 =
-+keycode 92 =
-+keycode 93 =
-+keycode 94 =
-+keycode 95 =
-+keycode 96 = KP_Enter
-+keycode 97 = Control
-+keycode 98 = KP_Divide
-+keycode 99 = Control_backslash
-+ control keycode 99 = Control_backslash
-+ alt keycode 99 = Control_backslash
-+keycode 100 = AltGr
-+keycode 101 = Break
-+keycode 102 = Find
-+keycode 103 = Up
-+keycode 104 = Prior
-+ shift keycode 104 = Scroll_Backward
-+keycode 105 = Left
-+ alt keycode 105 = Decr_Console
-+keycode 106 = Right
-+ alt keycode 106 = Incr_Console
-+keycode 107 = Select
-+keycode 108 = Down
-+keycode 109 = Next
-+ shift keycode 109 = Scroll_Forward
-+keycode 110 = Insert
-+keycode 111 = Remove
-+# altgr control keycode 111 = Boot
-+ control alt keycode 111 = Boot
-+keycode 112 = Macro
-+keycode 113 = F13
-+keycode 114 = F14
-+keycode 115 = Help
-+keycode 116 = Do
-+keycode 117 = F17
-+keycode 118 = KP_MinPlus
-+keycode 119 = Pause
-+keycode 120 =
-+keycode 121 =
-+keycode 122 =
-+keycode 123 =
-+keycode 124 =
-+keycode 125 =
-+keycode 126 =
-+keycode 127 =
-+string F1 = "\033[[A"
-+string F2 = "\033[[B"
-+string F3 = "\033[[C"
-+string F4 = "\033[[D"
-+string F5 = "\033[[E"
-+string F6 = "\033[17~"
-+string F7 = "\033[18~"
-+string F8 = "\033[19~"
-+string F9 = "\033[20~"
-+string F10 = "\033[21~"
-+string F11 = "\033[23~"
-+string F12 = "\033[24~"
-+string F13 = "\033[25~"
-+string F14 = "\033[26~"
-+string F15 = "\033[28~"
-+string F16 = "\033[29~"
-+string F17 = "\033[31~"
-+string F18 = "\033[32~"
-+string F19 = "\033[33~"
-+string F20 = "\033[34~"
-+string Find = "\033[1~"
-+string Insert = "\033[2~"
-+string Remove = "\033[3~"
-+string Select = "\033[4~"
-+string Prior = "\033[5~"
-+string Next = "\033[6~"
-+string Macro = "\033[M"
-+string Pause = "\033[P"
-+compose '`' 'A' to 'À'
-+compose '`' 'a' to 'à'
-+compose '\'' 'A' to 'Á'
-+compose '\'' 'a' to 'á'
-+compose '^' 'A' to 'Â'
-+compose '^' 'a' to 'â'
-+compose '~' 'A' to 'Ã'
-+compose '~' 'a' to 'ã'
-+compose '"' 'A' to 'Ä'
-+compose '"' 'a' to 'ä'
-+compose 'O' 'A' to 'Å'
-+compose 'o' 'a' to 'å'
-+compose '0' 'A' to 'Å'
-+compose '0' 'a' to 'å'
-+compose 'A' 'A' to 'Å'
-+compose 'a' 'a' to 'å'
-+compose 'A' 'E' to 'Æ'
-+compose 'a' 'e' to 'æ'
-+compose ',' 'C' to 'Ç'
-+compose ',' 'c' to 'ç'
-+compose '`' 'E' to 'È'
-+compose '`' 'e' to 'è'
-+compose '\'' 'E' to 'É'
-+compose '\'' 'e' to 'é'
-+compose '^' 'E' to 'Ê'
-+compose '^' 'e' to 'ê'
-+compose '"' 'E' to 'Ë'
-+compose '"' 'e' to 'ë'
-+compose '`' 'I' to 'Ì'
-+compose '`' 'i' to 'ì'
-+compose '\'' 'I' to 'Í'
-+compose '\'' 'i' to 'í'
-+compose '^' 'I' to 'Î'
-+compose '^' 'i' to 'î'
-+compose '"' 'I' to 'Ï'
-+compose '"' 'i' to 'ï'
-+compose '-' 'D' to 'Ð'
-+compose '-' 'd' to 'ð'
-+compose '~' 'N' to 'Ñ'
-+compose '~' 'n' to 'ñ'
-+compose '`' 'O' to 'Ò'
-+compose '`' 'o' to 'ò'
-+compose '\'' 'O' to 'Ó'
-+compose '\'' 'o' to 'ó'
-+compose '^' 'O' to 'Ô'
-+compose '^' 'o' to 'ô'
-+compose '~' 'O' to 'Õ'
-+compose '~' 'o' to 'õ'
-+compose '"' 'O' to 'Ö'
-+compose '"' 'o' to 'ö'
-+compose '/' 'O' to 'Ø'
-+compose '/' 'o' to 'ø'
-+compose '`' 'U' to 'Ù'
-+compose '`' 'u' to 'ù'
-+compose '\'' 'U' to 'Ú'
-+compose '\'' 'u' to 'ú'
-+compose '^' 'U' to 'Û'
-+compose '^' 'u' to 'û'
-+compose '"' 'U' to 'Ü'
-+compose '"' 'u' to 'ü'
-+compose '\'' 'Y' to 'Ý'
-+compose '\'' 'y' to 'ý'
-+compose 'T' 'H' to 'Þ'
-+compose 't' 'h' to 'þ'
-+compose 's' 's' to 'ß'
-+compose '"' 'y' to 'ÿ'
-+compose 's' 'z' to 'ß'
-+compose 'i' 'j' to 'ÿ'
---- linux-2.4.25/drivers/char/generic_serial.c~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
-+++ linux-2.4.25/drivers/char/generic_serial.c 2004-03-31 17:15:09.000000000 +0200
-@@ -883,6 +883,9 @@
- if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
- }
-
-+ /*
-+ * should be using tty_get_baud_rate() here -- rmk
-+ */
- baudrate = tiosp->c_cflag & CBAUD;
- if (baudrate & CBAUDEX) {
- baudrate &= ~CBAUDEX;
-@@ -957,6 +960,11 @@
- unsigned long flags;
- unsigned long page;
-
-+ /*
-+ * Do we expect to allocate tmp_buf from an interrupt routine?
-+ * If not, then save_flags() cli() and restore_flags() are
-+ * redundant here and should be replaced by a semaphore. -- rmk
-+ */
- save_flags (flags);
- if (!tmp_buf) {
- page = get_free_page(GFP_KERNEL);
-@@ -976,6 +984,11 @@
- if (port->flags & ASYNC_INITIALIZED)
- return 0;
-
-+ /*
-+ * Do we expect to allocate xmit_buf from an interrupt routine?
-+ * If not, then save_flags() cli() and restore_flags() are
-+ * redundant here and should be replaced by a semaphore. -- rmk
-+ */
- if (!port->xmit_buf) {
- /* We may sleep in get_free_page() */
- unsigned long tmp;
-@@ -1016,7 +1029,7 @@
- struct serial_struct sio;
-
- if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-- return(-EFAULT);
-+ return -EFAULT;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((sio.baud_base != port->baud_base) ||
---- linux-2.4.25/drivers/char/keyboard.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/char/keyboard.c 2004-03-31 17:15:09.000000000 +0200
-@@ -14,13 +14,17 @@
- * `Sticky' modifier keys, 951006.
- *
- * 11-11-96: SAK should now work in the raw mode (Martin Mares)
-- *
-+ *
- * Modified to provide 'generic' keyboard support by Hamish Macdonald
- * Merge with the m68k keyboard driver and split-off of the PC low-level
- * parts by Geert Uytterhoeven, May 1997
- *
- * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
- * 30-07-98: Dead keys redone, aeb@cwi.nl.
-+ *
-+ * 04-04-1998: Added keyboard autorepeat support (some keyboards don't
-+ * autorepeat, and some keyboard changers interfere with keyboard
-+ * autorepeat settings). - Russell King (rmk@arm.linux.org.uk)
- */
-
- #include <linux/config.h>
-@@ -30,6 +34,7 @@
- #include <linux/tty_flip.h>
- #include <linux/mm.h>
- #include <linux/string.h>
-+#include <linux/timer.h>
- #include <linux/random.h>
- #include <linux/init.h>
-
-@@ -61,6 +66,14 @@
- #define KBD_DEFLOCK 0
- #endif
-
-+/*
-+ * Default autorepeat settings.
-+ * DEFAULT_REPEAT_TIMEOUT is the timeout from the keypress to the first repeat
-+ * DEFAULT_REPEAT_INTERVAL is the timeout between successive repeats
-+ */
-+#define DEFAULT_REPEAT_TIMEOUT HZ*300/1000
-+#define DEFAULT_REPEAT_INTERVAL HZ*30/1000
-+
- void (*kbd_ledfunc)(unsigned int led);
- EXPORT_SYMBOL(handle_scancode);
- EXPORT_SYMBOL(kbd_ledfunc);
-@@ -82,21 +95,25 @@
- static unsigned long key_down[256/BITS_PER_LONG];
-
- static int dead_key_next;
--/*
-+/*
- * In order to retrieve the shift_state (for the mouse server), either
-- * the variable must be global, or a new procedure must be created to
-+ * the variable must be global, or a new procedure must be created to
- * return the value. I chose the former way.
- */
- int shift_state;
- static int npadch = -1; /* -1 or number assembled on pad */
- static unsigned char diacr;
- static char rep; /* flag telling character repeat */
-+static int kbd_repeatkeycode= -1;
-+static int kbd_repeattimeout = DEFAULT_REPEAT_TIMEOUT;
-+static int kbd_repeatinterval= DEFAULT_REPEAT_INTERVAL;
- struct kbd_struct kbd_table[MAX_NR_CONSOLES];
- static struct tty_struct **ttytab;
- static struct kbd_struct * kbd = kbd_table;
- static struct tty_struct * tty;
- static unsigned char prev_scancode;
-
-+static void kbd_processkeycode(unsigned char scancode, char up_flag, int autorepeat);
- void compute_shiftstate(void);
-
- typedef void (*k_hand)(unsigned char value, char up_flag);
-@@ -163,7 +180,8 @@
- * string, and in both cases we might assume that it is
- * in utf-8 already.
- */
--void to_utf8(ushort c) {
-+void to_utf8(ushort c)
-+{
- if (c < 0x80)
- put_queue(c); /* 0******* */
- else if (c < 0x800) {
-@@ -182,17 +200,23 @@
- * Translation of escaped scancodes to keycodes.
- * This is now user-settable (for machines were it makes sense).
- */
--
- int setkeycode(unsigned int scancode, unsigned int keycode)
- {
-- return kbd_setkeycode(scancode, keycode);
-+ return kbd_setkeycode(scancode, keycode);
- }
-
- int getkeycode(unsigned int scancode)
- {
-- return kbd_getkeycode(scancode);
-+ return kbd_getkeycode(scancode);
- }
-
-+static void key_callback(unsigned long nr);
-+
-+static struct timer_list key_autorepeat_timer =
-+{
-+ function: key_callback
-+};
-+
- void handle_scancode(unsigned char scancode, int down)
- {
- unsigned char keycode;
-@@ -201,6 +225,7 @@
- char have_keycode;
-
- pm_access(pm_kbd);
-+
- add_keyboard_randomness(scancode | up_flag);
-
- tty = ttytab? ttytab[fg_console]: NULL;
-@@ -223,15 +248,15 @@
- if (raw_mode) {
- /*
- * The following is a workaround for hardware
-- * which sometimes send the key release event twice
-+ * which sometimes send the key release event twice
- */
- unsigned char next_scancode = scancode|up_flag;
- if (have_keycode && up_flag && next_scancode==prev_scancode) {
- /* unexpected 2nd release event */
- } else {
-- /*
-+ /*
- * Only save previous scancode if it was a key-up
-- * and had a single-byte scancode.
-+ * and had a single-byte scancode.
- */
- if (!have_keycode)
- prev_scancode = 1;
-@@ -256,12 +281,35 @@
- * return the keycode if in MEDIUMRAW mode.
- */
-
-+ kbd_processkeycode(keycode, up_flag, 0);
-+
-+out:
-+ do_poke_blanked_console = 1;
-+ schedule_console_callback();
-+}
-+
-+static void
-+kbd_processkeycode(unsigned char keycode, char up_flag, int autorepeat)
-+{
-+ char raw_mode = (kbd->kbdmode == VC_RAW);
-+
- if (up_flag) {
- rep = 0;
- if(!test_and_clear_bit(keycode, key_down))
- up_flag = kbd_unexpected_up(keycode);
-- } else
-+ } else {
- rep = test_and_set_bit(keycode, key_down);
-+ /* If the keyboard autorepeated for us, ignore it.
-+ * We do our own autorepeat processing.
-+ */
-+ if (rep && !autorepeat)
-+ return;
-+ }
-+
-+ if (kbd_repeatkeycode == keycode || !up_flag || raw_mode) {
-+ kbd_repeatkeycode = -1;
-+ del_timer(&key_autorepeat_timer);
-+ }
-
- #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
- if (keycode == SYSRQ_KEY) {
-@@ -275,6 +323,23 @@
- }
- #endif
-
-+ /*
-+ * Calculate the next time when we have to do some autorepeat
-+ * processing. Note that we do not do autorepeat processing
-+ * while in raw mode but we do do autorepeat processing in
-+ * medium raw mode.
-+ */
-+ if (!up_flag && !raw_mode) {
-+ kbd_repeatkeycode = keycode;
-+ if (vc_kbd_mode(kbd, VC_REPEAT)) {
-+ if (rep)
-+ key_autorepeat_timer.expires = jiffies + kbd_repeatinterval;
-+ else
-+ key_autorepeat_timer.expires = jiffies + kbd_repeattimeout;
-+ add_timer(&key_autorepeat_timer);
-+ }
-+ }
-+
- if (kbd->kbdmode == VC_MEDIUMRAW) {
- /* soon keycodes will require more than one byte */
- put_queue(keycode + up_flag);
-@@ -343,9 +408,24 @@
- #endif
- }
- }
-+ rep = 0;
- out:
-- do_poke_blanked_console = 1;
-- schedule_console_callback();
-+}
-+
-+/*
-+ * This clears the key down arrays when the keyboard is reset. On
-+ * keyboard reset, this must be called before any keycodes are
-+ * received.
-+ */
-+void kbd_reset_kdown(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_SHIFT; i++)
-+ k_down[i] = 0;
-+ for (i = 0; i < SIZE(key_down); i++)
-+ key_down[i] = 0;
-+ shift_state = 0;
- }
-
- void put_queue(int ch)
-@@ -453,7 +533,7 @@
- static void decr_console(void)
- {
- int i;
--
-+
- for (i = fg_console-1; i != fg_console; i--) {
- if (i == -1)
- i = MAX_NR_CONSOLES-1;
-@@ -531,7 +611,7 @@
- {
- }
-
--static void do_null()
-+static void do_null(void)
- {
- compute_shiftstate();
- }
-@@ -646,8 +726,8 @@
-
- static void do_pad(unsigned char value, char up_flag)
- {
-- static const char *pad_chars = "0123456789+-*/\015,.?()";
-- static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
-+ static const char *pad_chars = "0123456789+-*/\015,.?()#";
-+ static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
-
- if (up_flag)
- return; /* no action, if this is a key release */
-@@ -748,9 +828,10 @@
- }
- }
-
--/* called after returning from RAW mode or when changing consoles -
-- recompute k_down[] and shift_state from key_down[] */
--/* maybe called when keymap is undefined, so that shiftkey release is seen */
-+/* Called after returning from RAW mode or when changing consoles -
-+ * recompute k_down[] and shift_state from key_down[]
-+ * Maybe called when keymap is undefined so that shift key release is seen
-+ */
- void compute_shiftstate(void)
- {
- int i, j, k, sym, val;
-@@ -829,19 +910,22 @@
- }
-
- /*
-- * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
-- * or (ii) whatever pattern of lights people want to show using KDSETLED,
-- * or (iii) specified bits of specified words in kernel memory.
-+ * The leds display either
-+ * (i) the status of NumLock, CapsLock, ScrollLock, or
-+ * (ii) whatever pattern of lights people want to show using KDSETLED, or
-+ * (iii) specified bits of specified words in kernel memory.
- */
-
- static unsigned char ledstate = 0xff; /* undefined */
- static unsigned char ledioctl;
-
--unsigned char getledstate(void) {
-+unsigned char getledstate(void)
-+{
- return ledstate;
- }
-
--void setledstate(struct kbd_struct *kbd, unsigned int led) {
-+void setledstate(struct kbd_struct *kbd, unsigned int led)
-+{
- if (!(led & ~7)) {
- ledioctl = led;
- kbd->ledmode = LED_SHOW_IOCTL;
-@@ -857,7 +941,8 @@
- } ledptrs[3];
-
- void register_leds(int console, unsigned int led,
-- unsigned int *addr, unsigned int mask) {
-+ unsigned int *addr, unsigned int mask)
-+{
- struct kbd_struct *kbd = kbd_table + console;
- if (led < 3) {
- ledptrs[led].addr = addr;
-@@ -868,7 +953,8 @@
- kbd->ledmode = LED_SHOW_FLAGS;
- }
-
--static inline unsigned char getleds(void){
-+static inline unsigned char getleds(void)
-+{
- struct kbd_struct *kbd = kbd_table + fg_console;
- unsigned char leds;
-
-@@ -915,6 +1001,19 @@
- {
- unsigned char leds = getleds();
-
-+ if (rep && kbd_repeatkeycode != -1) {
-+ tty = ttytab? ttytab[fg_console]: NULL;
-+ kbd = kbd_table + fg_console;
-+
-+ /* This prevents the kbd_key routine from being called
-+ * twice, once by this BH, and once by the interrupt
-+ * routine.
-+ */
-+ kbd_disable_irq();
-+ kbd_processkeycode(kbd_repeatkeycode, 0, 1);
-+ kbd_enable_irq();
-+ }
-+
- if (leds != ledstate) {
- ledstate = leds;
- kbd_leds(leds);
-@@ -937,6 +1036,12 @@
- tasklet_enable(&keyboard_tasklet);
- }
-
-+static void key_callback(unsigned long nr)
-+{
-+ rep = 1;
-+ tasklet_schedule(&keyboard_tasklet);
-+}
-+
- typedef void (pm_kbd_func) (void);
-
- pm_callback pm_kbd_request_override = NULL;
-@@ -953,7 +1058,7 @@
- kbd0.slockstate = 0;
- kbd0.modeflags = KBD_DEFMODE;
- kbd0.kbdmode = VC_XLATE;
--
-+
- for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
- kbd_table[i] = kbd0;
-
-@@ -963,7 +1068,7 @@
-
- tasklet_enable(&keyboard_tasklet);
- tasklet_schedule(&keyboard_tasklet);
--
-+
- pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override);
-
- return 0;
---- linux-2.4.25/drivers/char/mem.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/char/mem.c 2004-03-31 17:15:09.000000000 +0200
-@@ -27,9 +27,6 @@
- #include <asm/io.h>
- #include <asm/pgalloc.h>
-
--#ifdef CONFIG_I2C
--extern int i2c_init_all(void);
--#endif
- #ifdef CONFIG_FB
- extern void fbmem_init(void);
- #endif
-@@ -740,9 +737,6 @@
- printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- memory_devfs_register();
- rand_initialize();
--#ifdef CONFIG_I2C
-- i2c_init_all();
--#endif
- #if defined (CONFIG_FB)
- fbmem_init();
- #endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/omaha-rtc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,566 @@
-+/*
-+ * (C) ARM Limited 2002.
-+ *
-+ * Real Time Clock interface for Linux on Omaha
-+ *
-+ * Based on sa1100-rtc.c
-+ *
-+ * Copyright (c) 2000 Nils Faerber
-+ *
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russell King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
-+ * - added periodic timer capability using OSMR1
-+ * - flag compatibility with other RTC chips
-+ * - permission checks for ioctls
-+ * - major cleanup, partial rewrite
-+ *
-+ * 0.03 2001-03-07 CIH <cih@coventive.com>
-+ * - Modify the bug setups RTC clock.
-+ *
-+ * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
-+ * - removed mktime(), added alarm irq clear
-+ *
-+ * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
-+ * - initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+#include <linux/mc146818rtc.h>
-+
-+#define DRIVER_VERSION "1.00"
-+
-+#define epoch 1970
-+
-+#define TIMER_FREQ 3686400
-+
-+#define RTC_DEF_DIVIDER 32768 - 1
-+#define RTC_DEF_TRIM 0
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define RTC_PF 0x40
-+#define RTC_AF 0x20
-+#define RTC_UF 0x10
-+
-+// bitdefs for rtc registers
-+#define TICNT_ENABLE 0x80 // Enable tick interrupt
-+#define TICNT_PERIOD 0x7F // Divisor required for 1Hz tick
-+#define RTC_ENABLE 0x1 // Enable bit for RTC
-+
-+static unsigned long rtc_status;
-+static unsigned long rtc_irq_data;
-+static unsigned long rtc_freq = 1024;
-+
-+static struct fasync_struct *rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
-+
-+extern spinlock_t rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+// all the alarm and rtc registers
-+static volatile unsigned int almsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMSEC);
-+static volatile unsigned int almmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMIN);
-+static volatile unsigned int almhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMHOUR);
-+static volatile unsigned int almday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMDAY);
-+static volatile unsigned int almmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMON);
-+static volatile unsigned int almyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMYEAR);
-+
-+static volatile unsigned int bcdsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDSEC);
-+static volatile unsigned int bcdmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMIN);
-+static volatile unsigned int bcdhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDHOUR);
-+static volatile unsigned int bcdday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDAY);
-+static volatile unsigned int bcddate = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDATE);
-+static volatile unsigned int bcdmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMON);
-+static volatile unsigned int bcdyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDYEAR);
-+
-+/*
-+ * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
-+ */
-+
-+static void decodetime (unsigned long t, struct rtc_time *tval)
-+{
-+ long days, month, year, rem;
-+
-+ days = t / 86400;
-+ rem = t % 86400;
-+ tval->tm_hour = rem / 3600;
-+ rem %= 3600;
-+ tval->tm_min = rem / 60;
-+ tval->tm_sec = rem % 60;
-+ tval->tm_wday = (4 + days) % 7;
-+
-+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-+
-+ year = epoch;
-+ while (days >= (365 + is_leap(year))) {
-+ unsigned long yg = year + days / 365;
-+ days -= ((yg - year) * 365
-+ + LEAPS_THRU_END_OF (yg - 1)
-+ - LEAPS_THRU_END_OF (year - 1));
-+ year = yg;
-+ }
-+ tval->tm_year = year - 1900;
-+ tval->tm_yday = days + 1;
-+
-+ month = 0;
-+ if (days >= 31) {
-+ days -= 31;
-+ month++;
-+ if (days >= (28 + is_leap(year))) {
-+ days -= (28 + is_leap(year));
-+ month++;
-+ while (days >= days_in_mo[month]) {
-+ days -= days_in_mo[month];
-+ month++;
-+ }
-+ }
-+ }
-+ tval->tm_mon = month;
-+ tval->tm_mday = days + 1;
-+}
-+
-+// Get alarm time in seconds
-+static unsigned long get_alarm_time(void)
-+{
-+ int sec, min,hour,date,mon,year;
-+
-+ // Read data from h/w
-+ year = __raw_readb(almyear);
-+ mon = __raw_readb(almmon);
-+ date = __raw_readb(almday);
-+ hour = __raw_readb(almhour);
-+ min = __raw_readb(almmin);
-+ sec = __raw_readb(almsec);
-+
-+ // convert all the data into binary
-+ year = BCD_TO_BIN(year);
-+ mon = BCD_TO_BIN(mon);
-+ date = BCD_TO_BIN(date);
-+ hour = BCD_TO_BIN(hour);
-+ min = BCD_TO_BIN(min);
-+ sec = BCD_TO_BIN(sec);
-+
-+ // convert year to 19xx or 20xx as appropriate
-+ if (year > 69)
-+ year += 1900;
-+ else
-+ year += 2000;
-+
-+ // Now calculate number of seconds since time began...
-+ return mktime(year,mon,date,hour,min,sec);
-+}
-+
-+// Get rtc time in seconds
-+static unsigned long get_rtc_time(void)
-+{
-+ int sec,min,hour,day,date,mon,year;
-+
-+ // Read data from h/w
-+ year = __raw_readb(bcdyear);
-+ mon = __raw_readb(bcdmon);
-+ date = __raw_readb(bcdday);
-+ day = __raw_readb(bcddate);
-+ hour = __raw_readb(bcdhour);
-+ min = __raw_readb(bcdmin);
-+ sec = __raw_readb(bcdsec);
-+
-+ // convert all the data into binary
-+ year = BCD_TO_BIN(year);
-+ mon = BCD_TO_BIN(mon);
-+ date = BCD_TO_BIN(date);
-+ day = BCD_TO_BIN(day);
-+ hour = BCD_TO_BIN(hour);
-+ min = BCD_TO_BIN(min);
-+ sec = BCD_TO_BIN(sec);
-+
-+ // convert year to 19xx or 20xx as appropriate
-+ if (year > 69)
-+ year += 1900;
-+ else
-+ year += 2000;
-+
-+ // Now calculate number of seconds since time began...
-+ return mktime(year,mon,date,hour,min,sec);
-+}
-+
-+/* Sets time of alarm */
-+static void set_alarm_time(struct rtc_time *tval)
-+{
-+
-+ int sec,min,hour,day,mon,year;
-+
-+ // Convert data from binary to 8-bit bcd
-+ sec = BIN_TO_BCD(tval->tm_sec);
-+ min = BIN_TO_BCD(tval->tm_min);
-+ hour = BIN_TO_BCD(tval->tm_hour);
-+ day = BIN_TO_BCD(tval->tm_mday);
-+ mon = BIN_TO_BCD(tval->tm_mon);
-+
-+ // Year is special
-+ year = tval->tm_year;
-+ if(year > 1999)
-+ year -=2000;
-+ else
-+ year -=1900;
-+
-+ year = BIN_TO_BCD(year);
-+
-+ // Write all the registers
-+ __raw_writeb(year,almyear);
-+ __raw_writeb(mon,almmon);
-+ __raw_writeb(day,almday);
-+ __raw_writeb(hour,almhour);
-+ __raw_writeb(min,almmin);
-+ __raw_writeb(sec,almsec);
-+}
-+
-+/* Sets time of alarm */
-+static void set_rtc_time(struct rtc_time *tval)
-+{
-+
-+ int sec,min,hour,day,date,mon,year;
-+
-+ // Convert data from binary to 8-bit bcd
-+ sec = BIN_TO_BCD(tval->tm_sec);
-+ min = BIN_TO_BCD(tval->tm_min);
-+ hour = BIN_TO_BCD(tval->tm_hour);
-+ day = BIN_TO_BCD(tval->tm_mday);
-+ date = BIN_TO_BCD(tval->tm_wday);
-+ mon = BIN_TO_BCD(tval->tm_mon);
-+
-+ // Year is special
-+ year = tval->tm_year;
-+ if(year > 1999)
-+ year -=2000;
-+ else
-+ year -=1900;
-+
-+ year = BIN_TO_BCD(year);
-+
-+ // Write all the registers
-+ __raw_writeb(year,bcdyear);
-+ __raw_writeb(mon,bcdmon);
-+ __raw_writeb(date,bcddate);
-+ __raw_writeb(day,bcdday);
-+ __raw_writeb(hour,bcdhour);
-+ __raw_writeb(min,bcdmin);
-+ __raw_writeb(sec,bcdsec);
-+}
-+
-+static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /* update irq data & counter */
-+ rtc_irq_data += 0x100;
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static int rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit (1, &rtc_status))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int rtc_release(struct inode *inode, struct file *file)
-+{
-+ rtc_status = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int rtc_fasync (int fd, struct file *filp, int on)
-+{
-+ return fasync_helper (fd, filp, on, &rtc_async_queue);
-+}
-+
-+static unsigned int rtc_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait (file, &rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq (&rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+
-+ spin_unlock_irq (&rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+
-+ retval = put_user(data, (unsigned long *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&rtc_wait, &wait);
-+ return retval;
-+}
-+
-+static int rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ volatile unsigned int rtcalm = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCALM);
-+ volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
-+
-+ struct rtc_time tm, tm2;
-+ switch (cmd) {
-+ case RTC_AIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(0,rtcalm);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_AIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(0x7F,rtcalm);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(~TICNT_ENABLE,ticnt);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(TICNT_ENABLE|TICNT_PERIOD,ticnt);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ // Periodic int not available
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ // Periodic int not available
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_ALM_READ:
-+ decodetime(get_alarm_time(),&tm);
-+ break;
-+ case RTC_ALM_SET:
-+ if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
-+ return -EFAULT;
-+ decodetime(get_rtc_time(),&tm);
-+ if ((unsigned)tm2.tm_hour < 24)
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned)tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned)tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+
-+ // Munge (as per sa1100)
-+ tm.tm_year+=1900;
-+ tm.tm_mon+=1;
-+
-+ // Set the alarm
-+ set_alarm_time(&tm);
-+ return 0;
-+ case RTC_RD_TIME:
-+ decodetime (get_rtc_time(), &tm);
-+ break;
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ return -EACCES;
-+ if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
-+ return -EFAULT;
-+ tm.tm_year += 1900;
-+ if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
-+ tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
-+ (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
-+ (unsigned)tm.tm_hour >= 24 ||
-+ (unsigned)tm.tm_min >= 60 ||
-+ (unsigned)tm.tm_sec >= 60)
-+ return -EINVAL;
-+ tm.tm_mon +=1; // wierd: same as sa1100 though (gets month wrong otherwise!)
-+ set_rtc_time(&tm);
-+ return 0;
-+ case RTC_IRQP_READ:
-+ return put_user(rtc_freq, (unsigned long *)arg);
-+ case RTC_IRQP_SET:
-+ if (arg < 1 || arg > TIMER_FREQ)
-+ return -EINVAL;
-+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-+ return -EACCES;
-+ rtc_freq = arg;
-+ return 0;
-+ case RTC_EPOCH_READ:
-+ return put_user (epoch, (unsigned long *)arg);
-+ default:
-+ return -EINVAL;
-+ }
-+ return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
-+}
-+
-+static struct file_operations rtc_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = rtc_llseek,
-+ .read = rtc_read,
-+ .poll = rtc_poll,
-+ .ioctl = rtc_ioctl,
-+ .open = rtc_open,
-+ .release = rtc_release,
-+ .fasync = rtc_fasync,
-+};
-+
-+static struct miscdevice omahartc_miscdev = {
-+ .minor = RTC_MINOR,
-+ .name = "rtc",
-+ .fops = &rtc_fops,
-+};
-+
-+static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ decodetime (get_rtc_time(), &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
-+ decodetime (get_alarm_time(), &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init rtc_init(void)
-+{
-+ volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
-+ volatile unsigned int rtccon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCCON);
-+ int ret;
-+
-+ misc_register (&omahartc_miscdev);
-+ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
-+
-+ // Enable RTC
-+ __raw_writel(RTC_ENABLE,rtccon);
-+
-+ // Acquire 1Hz timer
-+ ret = request_irq (OMAHA_INT_TICK, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_TICK);
-+ goto IRQ_TICK_failed;
-+ }
-+
-+ // Acquire RTC (Alarm interrupt)
-+ ret = request_irq (OMAHA_INT_RTC, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_RTC);
-+ goto IRQ_RTC_failed;
-+ }
-+
-+ printk (KERN_INFO "Omaha Real Time Clock driver v" DRIVER_VERSION "\n");
-+
-+ // Program tick interrupt divisor to generate real 1Hz clock and enable the interrupt
-+ __raw_writeb(TICNT_ENABLE|TICNT_PERIOD,ticnt);
-+
-+ return 0;
-+
-+IRQ_TICK_failed:
-+ free_irq (OMAHA_INT_TICK, NULL);
-+IRQ_RTC_failed:
-+ free_irq(OMAHA_INT_RTC, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&omahartc_miscdev);
-+ return ret;
-+}
-+
-+static void __exit rtc_exit(void)
-+{
-+ free_irq (OMAHA_INT_TICK, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&omahartc_miscdev);
-+}
-+
-+module_init(rtc_init);
-+module_exit(rtc_exit);
-+
-+MODULE_AUTHOR("ARM Limited <support@arm.com>");
-+MODULE_DESCRIPTION("Omaha Realtime Clock Driver (RTC)");
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/omaha_wdt.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,193 @@
-+/*
-+ * Watchdog driver for the Omaha
-+ * (C) ARM Limited 2002.
-+ *
-+ * Based on sa1100_wdt.c
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ * Based on SoftDog driver by Alan Cox <alan@redhat.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.
-+ *
-+ * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
-+ * warranty for any of this software. This material is provided
-+ * "AS-IS" and at no charge.
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ *
-+ * 27/11/2000 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 8 /* (secs) Default is 1 minute */
-+#define WT_TPS 7812 /* Watchdog ticks per second. */
-+#define WT_ENABLE 0x21 // Enable bits for watchdog
-+#define WT_CLKSEL_128 0x18 // Select 1/128 divider
-+
-+static int omaha_margin = TIMER_MARGIN; /* in seconds */
-+static int omahawdt_users;
-+static int pre_margin;
-+#ifdef MODULE
-+MODULE_PARM(omaha_margin,"i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int omahadog_open(struct inode *inode, struct file *file)
-+{
-+ volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
-+ volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
-+ volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
-+ unsigned int tmp;
-+
-+ if(test_and_set_bit(1,&omahawdt_users))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ /* Activate omaha Watchdog timer */
-+
-+ /* Assume that uhal has set up pre-scaler according
-+ * to the system clock frequency (don't change it!)
-+ *
-+ * Ie. all counting occurs at 1MHz / 128 = 7812.5Hz
-+ *
-+ * Since we have 16-bit counter, maximum period is
-+ * 65536/7812.5 = 8.338608 seconds!
-+ */
-+
-+ pre_margin = WT_TPS * omaha_margin;
-+
-+ // Set count to the maximum
-+ __raw_writel(pre_margin,wtcnt);
-+
-+ // Set the clock division factor
-+ tmp = __raw_readl(wtcon);
-+ tmp |= WT_CLKSEL_128;
-+ __raw_writel(tmp,wtcon);
-+
-+ // Program an initial count into WTDAT
-+ __raw_writel(0x8000,wtdat);
-+
-+ // enable the watchdog
-+ tmp = __raw_readl(wtcon);
-+ tmp |= WT_ENABLE;
-+
-+ __raw_writel(tmp,wtcon);
-+
-+ return 0;
-+}
-+
-+static int omahadog_release(struct inode *inode, struct file *file)
-+{
-+ volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
-+ unsigned int tmp;
-+
-+ /*
-+ * Shut off the timer.
-+ * Lock it in if it's a module and we defined ...NOWAYOUT
-+ */
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ tmp = __raw_readl(wtcon);
-+ tmp &= ~WT_ENABLE;
-+ __raw_writel(tmp,wtcon);
-+#endif
-+ omahawdt_users = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static ssize_t omahadog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
-+
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Refresh timer. */
-+ if(len) {
-+ __raw_writel(pre_margin,wtcnt);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int omahadog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
-+ static struct watchdog_info ident = {
-+ identity: "omaha Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+ case WDIOC_GETSTATUS:
-+ return put_user(0,(int *)arg);
-+ case WDIOC_GETBOOTSTATUS:
-+ return 0;
-+ case WDIOC_KEEPALIVE:
-+ __raw_writel(pre_margin,wtdat);
-+ return 0;
-+ }
-+}
-+
-+static struct file_operations omahadog_fops=
-+{
-+ .owner = THIS_MODULE,
-+ .write = omahadog_write,
-+ .ioctl = omahadog_ioctl,
-+ .open = omahadog_open,
-+ .release = omahadog_release,
-+};
-+
-+static struct miscdevice omahadog_miscdev=
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "omaha watchdog",
-+ .fops = &omahadog_fops
-+};
-+
-+static int __init omahadog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&omahadog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("Omaha Watchdog Timer: timer margin %d sec\n", omaha_margin);
-+
-+ return 0;
-+}
-+
-+static void __exit omahadog_exit(void)
-+{
-+ misc_deregister(&omahadog_miscdev);
-+}
-+
-+module_init(omahadog_init);
-+module_exit(omahadog_exit);
---- linux-2.4.25/drivers/char/pcmcia/Config.in~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
-+++ linux-2.4.25/drivers/char/pcmcia/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -5,7 +5,13 @@
- mainmenu_option next_comment
- comment 'PCMCIA character devices'
-
--dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_SERIAL
-+if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL_8250" = "y" ]; then
-+ dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS y
-+else
-+ if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_SERIAL_8250" = "m" ]; then
-+ dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS m
-+ fi
-+fi
- if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" ]; then
- define_bool CONFIG_PCMCIA_CHRDEV y
- fi
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/pcmcia/memory_cs.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,214 @@
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/mtd.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/cs.h>
-+#include <pcmcia/cistpl.h>
-+#include <pcmcia/ciscode.h>
-+#include <pcmcia/ds.h>
-+#include <pcmcia/cisreg.h>
-+
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/mtd.h>
-+
-+static dev_info_t dev_info = "memory_cs";
-+static dev_link_t *dev_list;
-+
-+struct memcs_dev {
-+ dev_link_t link;
-+ struct map_info map;
-+};
-+
-+static __u8 mem_cs_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 mem_cs_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 mem_cs_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return readl(map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_copy_from(struct map_info *map, void *to, unsigned long ofs, ssize_t size)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + ofs, size);
-+}
-+
-+static void mem_cs_write8(struct map_info *map, __u8 val, unsigned long ofs)
-+{
-+ writeb(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_write16(struct map_info *map, __u16 val, unsigned long ofs)
-+{
-+ writew(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_write32(struct map_info *map, __u32 val, unsigned long ofs)
-+{
-+ writel(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_copy_to(struct map_info *map, unsigned long ofs, const void *to, ssize_t size)
-+{
-+ memcpy_toio(map->map_priv_1 + ofs, from, size);
-+}
-+
-+static void mem_cs_release(u_long arg);
-+
-+static void mem_cs_detach(dev_link_t *link)
-+{
-+ del_timer(&link->release);
-+ if (link->state & DEV_CONFIG) {
-+ mem_cs_release((u_long)link);
-+ if (link->state & DEV_STALE_CONFIG) {
-+ link->state |= DEV_STALE_LINK;
-+ return;
-+ }
-+ }
-+
-+ if (link->handle)
-+ CardServices(DeregisterClient, link->handle);
-+
-+ kfree(link);
-+}
-+
-+static void mem_cs_release(u_long arg)
-+{
-+ dev_link_t *link = (dev_link_t *)arg;
-+
-+ link->dev = NULL;
-+ if (link->win) {
-+ CardServices(ReleaseWindow, link->win);
-+ }
-+ link->state &= ~DEV_CONFIG;
-+
-+ if (link->state & DEV_STALE_LINK)
-+ mem_cs_detach(link);
-+}
-+
-+static void mem_cs_config(dev_link_t *link)
-+{
-+ struct memcs_dev *dev = link->priv;
-+ cs_status_t status;
-+ win_req_t req;
-+
-+ link->state |= DEV_CONFIG;
-+
-+ req.Attributes = word_width ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8;
-+ req.Base = 0;
-+ req.Size = 0;
-+ req.AccessSpeed = mem_speed;
-+
-+ link->win = (window_handle_t)link->handle;
-+
-+ CS_CHECK(RequestWindow, &link->win, &req);
-+
-+ CS_CHECK(GetStatus, link->handle, &status);
-+
-+ dev->map.buswidth = word_width ? 2 : 1;
-+ dev->map.size = req.Size;
-+ dev->map.map_priv_1 = ioremap(req.Base, req.Size);
-+}
-+
-+static int
-+mem_cs_event(event_t event, int priority, event_callback_args_t *args)
-+{
-+ dev_link_t *link = args->client_data;
-+
-+ switch (event) {
-+ case CS_EVENT_CARD_REMOVAL:
-+ link->state &= ~DEV_PRESENT;
-+ if (link->state & DEV_CONFIG)
-+ mod_timer(&link->release, jiffies + HZ/20);
-+ break;
-+
-+ case CS_EVENT_CARD_INSERTION:
-+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-+ mem_cs_config(link);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static dev_link_t *mem_cs_attach(void)
-+{
-+ struct memcs_dev *dev;
-+ client_reg_t clnt;
-+
-+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-+ if (dev) {
-+ memset(dev, 0, sizeof(*dev));
-+
-+ dev->map.read8 = mem_cs_read8;
-+ dev->map.read16 = mem_cs_read16;
-+ dev->map.read32 = mem_cs_read32;
-+ dev->map.copy_from = mem_cs_copy_from;
-+ dev->map.write8 = mem_cs_write8;
-+ dev->map.write16 = mem_cs_write16;
-+ dev->map.write32 = mem_cs_write32;
-+ dev->map.copy_to = mem_cs_copy_to;
-+
-+ dev->link.release.function = &mem_cs_release;
-+ dev->link.release.data = (u_long)link;
-+ dev->link.priv = dev;
-+
-+ dev->link.next = dev_list;
-+ dev_list = &dev->link;
-+
-+ clnt.dev_info = &dev_info;
-+ clnt.Attributes = INOF_IO_CLIENT | INFO_CARD_SHARE;
-+ clnt.EventMask =
-+ CS_EVENT_WRITE_PROTECT | CS_EVENT_CARD_INSERTION |
-+ CS_EVENT_CARD_REMOVAL | CS_EVENT_BATTERY_DEAD |
-+ CS_EVENT_BATTERY_LOW;
-+
-+ clnt.event_handler = &mem_cs_event;
-+ clnt.Version = 0x0210;
-+ clnt.event_callback_args.client_data = &dev->link;
-+
-+ ret = CardServices(RegisterClient, &dev->link.handle, &clnt);
-+ if (ret != CS_SUCCESS) {
-+ error_info_t err = { RegisterClient, ret };
-+ CardServices(ReportError, dev->link.handle, &err);
-+ mem_cs_detach(&dev->link);
-+ dev = NULL;
-+ }
-+ }
-+
-+ return &dev->link;
-+}
-+
-+static int __init mem_cs_init(void)
-+{
-+ servinfo_t serv;
-+
-+ CardServices(GetCardServicesInfo, &serv);
-+ if (serv.Revision != CS_RELEASE_CODE) {
-+ printk(KERN_NOTICE "memory_cs: Card services release "
-+ "does not match\n");
-+ return -ENXIO;
-+ }
-+ register_pccard_driver(&dev_info, mem_cs_attach, mem_cs_detach);
-+ return 0;
-+}
-+
-+static void __exit mem_cs_exit(void)
-+{
-+ unregister_pccard_driver(&dev_info);
-+ while (dev_list != NULL)
-+ memory_detach(dev_list);
-+}
-+
-+module_init(mem_cs_init);
-+module_exit(mem_cs_exit);
-+
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/sa1100-rtc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,474 @@
-+/*
-+ * Real Time Clock interface for Linux on StrongARM SA1100
-+ *
-+ * Copyright (c) 2000 Nils Faerber
-+ *
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russel King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
-+ * - added periodic timer capability using OSMR1
-+ * - flag compatibility with other RTC chips
-+ * - permission checks for ioctls
-+ * - major cleanup, partial rewrite
-+ *
-+ * 0.03 2001-03-07 CIH <cih@coventive.com>
-+ * - Modify the bug setups RTC clock.
-+ *
-+ * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
-+ * - removed mktime(), added alarm irq clear
-+ *
-+ * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
-+ * - initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+
-+#define DRIVER_VERSION "1.00"
-+
-+#define TIMER_FREQ 3686400
-+
-+#define RTC_DEF_DIVIDER 32768 - 1
-+#define RTC_DEF_TRIM 0
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define RTC_PF 0x40
-+#define RTC_AF 0x20
-+#define RTC_UF 0x10
-+
-+static unsigned long rtc_status;
-+static unsigned long rtc_irq_data;
-+static unsigned long rtc_freq = 1024;
-+
-+static struct fasync_struct *rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
-+
-+extern spinlock_t rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+/*
-+ * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
-+ */
-+
-+static void decodetime (unsigned long t, struct rtc_time *tval)
-+{
-+ long days, month, year, rem;
-+
-+ days = t / 86400;
-+ rem = t % 86400;
-+ tval->tm_hour = rem / 3600;
-+ rem %= 3600;
-+ tval->tm_min = rem / 60;
-+ tval->tm_sec = rem % 60;
-+ tval->tm_wday = (4 + days) % 7;
-+
-+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-+
-+ year = 1970 + days / 365;
-+ days -= ((year - 1970) * 365
-+ + LEAPS_THRU_END_OF (year - 1)
-+ - LEAPS_THRU_END_OF (1970 - 1));
-+ if (days < 0) {
-+ year -= 1;
-+ days += 365 + is_leap(year);
-+ }
-+ tval->tm_year = year - 1900;
-+ tval->tm_yday = days + 1;
-+
-+ month = 0;
-+ if (days >= 31) {
-+ days -= 31;
-+ month++;
-+ if (days >= (28 + is_leap(year))) {
-+ days -= (28 + is_leap(year));
-+ month++;
-+ while (days >= days_in_mo[month]) {
-+ days -= days_in_mo[month];
-+ month++;
-+ }
-+ }
-+ }
-+ tval->tm_mon = month;
-+ tval->tm_mday = days + 1;
-+}
-+
-+static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int rtsr = RTSR;
-+
-+ /* clear interrupt sources */
-+ RTSR = 0;
-+ RTSR = (RTSR_AL|RTSR_HZ);
-+
-+ /* clear alarm interrupt if it has occurred */
-+ if (rtsr & RTSR_AL)
-+ rtsr &= ~RTSR_ALE;
-+ RTSR = rtsr & (RTSR_ALE|RTSR_HZE);
-+
-+ /* update irq data & counter */
-+ if (rtsr & RTSR_AL)
-+ rtc_irq_data |= (RTC_AF|RTC_IRQF);
-+ if (rtsr & RTSR_HZ)
-+ rtc_irq_data |= (RTC_UF|RTC_IRQF);
-+ rtc_irq_data += 0x100;
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /*
-+ * If we match for the first time, the periodic interrupt flag won't
-+ * be set. If it is, then we did wrap around (very unlikely but
-+ * still possible) and compute the amount of missed periods.
-+ * The match reg is updated only when the data is actually retrieved
-+ * to avoid unnecessary interrupts.
-+ */
-+ OSSR = OSSR_M1; /* clear match on timer1 */
-+ if (rtc_irq_data & RTC_PF) {
-+ rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8;
-+ } else {
-+ rtc_irq_data += (0x100|RTC_PF|RTC_IRQF);
-+ }
-+
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static int rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit (1, &rtc_status))
-+ return -EBUSY;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int rtc_release(struct inode *inode, struct file *file)
-+{
-+ spin_lock_irq (&rtc_lock);
-+ RTSR = 0;
-+ RTSR = (RTSR_AL|RTSR_HZ);
-+ OIER &= ~OIER_E1;
-+ OSSR = OSSR_M1;
-+ spin_unlock_irq (&rtc_lock);
-+ rtc_status = 0;
-+ return 0;
-+}
-+
-+static int rtc_fasync (int fd, struct file *filp, int on)
-+{
-+ return fasync_helper (fd, filp, on, &rtc_async_queue);
-+}
-+
-+static unsigned int rtc_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait (file, &rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq (&rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+
-+ if (data & RTC_PF) {
-+ /* interpolate missed periods and set match for the next one */
-+ unsigned long period = TIMER_FREQ/rtc_freq;
-+ unsigned long oscr = OSCR;
-+ unsigned long osmr1 = OSMR1;
-+ unsigned long missed = (oscr - osmr1)/period;
-+ data += missed << 8;
-+ OSSR = OSSR_M1; /* clear match on timer 1 */
-+ OSMR1 = osmr1 + (missed + 1)*period;
-+ /* ensure we didn't miss another match in the mean time */
-+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) {
-+ data += 0x100;
-+ OSSR = OSSR_M1; /* clear match on timer 1 */
-+ OSMR1 = osmr1 + period;
-+ }
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+
-+ retval = put_user(data, (unsigned long *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&rtc_wait, &wait);
-+ return retval;
-+}
-+
-+static int rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct rtc_time tm, tm2;
-+
-+ switch (cmd) {
-+ case RTC_AIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR &= ~RTSR_ALE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_AIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR |= RTSR_ALE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR &= ~RTSR_HZE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR |= RTSR_HZE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ OIER &= ~OIER_E1;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_ON:
-+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
-+ return -EACCES;
-+ spin_lock_irq(&rtc_lock);
-+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
-+ OIER |= OIER_E1;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_ALM_READ:
-+ decodetime (RTAR, &tm);
-+ break;
-+ case RTC_ALM_SET:
-+ if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
-+ return -EFAULT;
-+ decodetime (RCNR, &tm);
-+ if ((unsigned)tm2.tm_hour < 24)
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned)tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned)tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+ RTAR = mktime ( tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-+ tm.tm_hour, tm.tm_min, tm.tm_sec);
-+ return 0;
-+ case RTC_RD_TIME:
-+ decodetime (RCNR, &tm);
-+ break;
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ return -EACCES;
-+ if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
-+ return -EFAULT;
-+ tm.tm_year += 1900;
-+ if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 ||
-+ tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
-+ (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
-+ (unsigned)tm.tm_hour >= 24 ||
-+ (unsigned)tm.tm_min >= 60 ||
-+ (unsigned)tm.tm_sec >= 60)
-+ return -EINVAL;
-+ RCNR = mktime ( tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
-+ tm.tm_hour, tm.tm_min, tm.tm_sec);
-+ return 0;
-+ case RTC_IRQP_READ:
-+ return put_user(rtc_freq, (unsigned long *)arg);
-+ case RTC_IRQP_SET:
-+ if (arg < 1 || arg > TIMER_FREQ)
-+ return -EINVAL;
-+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-+ return -EACCES;
-+ rtc_freq = arg;
-+ return 0;
-+ case RTC_EPOCH_READ:
-+ return put_user (1970, (unsigned long *)arg);
-+ default:
-+ return -EINVAL;
-+ }
-+ return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
-+}
-+
-+static struct file_operations rtc_fops = {
-+ owner: THIS_MODULE,
-+ llseek: rtc_llseek,
-+ read: rtc_read,
-+ poll: rtc_poll,
-+ ioctl: rtc_ioctl,
-+ open: rtc_open,
-+ release: rtc_release,
-+ fasync: rtc_fasync,
-+};
-+
-+static struct miscdevice sa1100rtc_miscdev = {
-+ RTC_MINOR,
-+ "rtc",
-+ &rtc_fops
-+};
-+
-+static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ decodetime (RCNR, &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1970);
-+ decodetime (RTAR, &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR);
-+ p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" );
-+ p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no");
-+ p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no");
-+ p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init rtc_init(void)
-+{
-+ int ret;
-+
-+ misc_register (&sa1100rtc_miscdev);
-+ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
-+ ret = request_irq (IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC1Hz);
-+ goto IRQ_RTC1Hz_failed;
-+ }
-+ ret = request_irq (IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
-+ if (ret) {
-+ printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCAlrm);
-+ goto IRQ_RTCAlrm_failed;
-+ }
-+ ret = request_irq (IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL);
-+ if (ret) {
-+ printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_OST1);
-+ goto IRQ_OST1_failed;
-+ }
-+
-+ printk (KERN_INFO "SA1100 Real Time Clock driver v" DRIVER_VERSION "\n");
-+
-+ /*
-+ * According to the manual we should be able to let RTTR be zero
-+ * and then a default diviser for a 32.768KHz clock is used.
-+ * Apparently this doesn't work, at least for my SA1110 rev 5.
-+ * If the clock divider is uninitialized then reset it to the
-+ * default value to get the 1Hz clock.
-+ */
-+ if (RTTR == 0) {
-+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-+ printk (KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
-+ /* The current RTC value probably doesn't make sense either */
-+ RCNR = 0;
-+ }
-+
-+ return 0;
-+
-+IRQ_OST1_failed:
-+ free_irq (IRQ_RTCAlrm, NULL);
-+IRQ_RTCAlrm_failed:
-+ free_irq (IRQ_RTC1Hz, NULL);
-+IRQ_RTC1Hz_failed:
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&sa1100rtc_miscdev);
-+ return ret;
-+}
-+
-+static void __exit rtc_exit(void)
-+{
-+ free_irq (IRQ_OST1, NULL);
-+ free_irq (IRQ_RTCAlrm, NULL);
-+ free_irq (IRQ_RTC1Hz, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&sa1100rtc_miscdev);
-+}
-+
-+module_init(rtc_init);
-+module_exit(rtc_exit);
-+
-+MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
-+MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/sa1100_wdt.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,150 @@
-+/*
-+ * Watchdog driver for the SA11x0
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ * Based on SoftDog driver by Alan Cox <alan@redhat.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.
-+ *
-+ * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
-+ * warranty for any of this software. This material is provided
-+ * "AS-IS" and at no charge.
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ *
-+ * 27/11/2000 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
-+
-+static int sa1100_margin = TIMER_MARGIN; /* in seconds */
-+static int sa1100wdt_users;
-+static int pre_margin;
-+#ifdef MODULE
-+MODULE_PARM(sa1100_margin,"i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int sa1100dog_open(struct inode *inode, struct file *file)
-+{
-+ if(test_and_set_bit(1,&sa1100wdt_users))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ /* Activate SA1100 Watchdog timer */
-+ pre_margin=3686400 * sa1100_margin;
-+ OSMR3 = OSCR + pre_margin;
-+ OSSR = OSSR_M3;
-+ OWER = OWER_WME;
-+ OIER |= OIER_E3;
-+ return 0;
-+}
-+
-+static int sa1100dog_release(struct inode *inode, struct file *file)
-+{
-+ /*
-+ * Shut off the timer.
-+ * Lock it in if it's a module and we defined ...NOWAYOUT
-+ */
-+ OSMR3 = OSCR + pre_margin;
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ OIER &= ~OIER_E3;
-+#endif
-+ sa1100wdt_users = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Refresh OSMR3 timer. */
-+ if(len) {
-+ OSMR3 = OSCR + pre_margin;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int sa1100dog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ static struct watchdog_info ident = {
-+ identity: "SA1100 Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+ case WDIOC_GETSTATUS:
-+ return put_user(0,(int *)arg);
-+ case WDIOC_GETBOOTSTATUS:
-+ return put_user((RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0, (int *)arg);
-+ case WDIOC_KEEPALIVE:
-+ OSMR3 = OSCR + pre_margin;
-+ return 0;
-+ }
-+}
-+
-+static struct file_operations sa1100dog_fops=
-+{
-+ owner: THIS_MODULE,
-+ write: sa1100dog_write,
-+ ioctl: sa1100dog_ioctl,
-+ open: sa1100dog_open,
-+ release: sa1100dog_release,
-+};
-+
-+static struct miscdevice sa1100dog_miscdev=
-+{
-+ WATCHDOG_MINOR,
-+ "SA1100 watchdog",
-+ &sa1100dog_fops
-+};
-+
-+static int __init sa1100dog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&sa1100dog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
-+
-+ return 0;
-+}
-+
-+static void __exit sa1100dog_exit(void)
-+{
-+ misc_deregister(&sa1100dog_miscdev);
-+}
-+
-+module_init(sa1100dog_init);
-+module_exit(sa1100dog_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/char/sa1111_keyb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,1153 @@
-+/*
-+ * SA1111 PS/2 keyboard/mouse driver
-+ *
-+ * 2000 by VASARA RESEARCH INC.
-+ *
-+ * Changelog:
-+ * Jun.xx,2000: Kunihiko IMAI <imai@vasara.co.jp>
-+ * Port to 2.4.0test1-ac19-rmk1-np1
-+ * Apr.17,2000: Takafumi Kawana <kawana@pro.or.jp>
-+ * Internal Release for XP860
-+ *
-+ *
-+ * This driver is based on linux/drivers/char/pc_keyb.c
-+ * Original declaration follows:
-+
-+ *
-+ * linux/drivers/char/pc_keyb.c
-+ *
-+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
-+ * See keyboard.c for the whole history.
-+ *
-+ * Major cleanup by Martin Mares, May 1997
-+ *
-+ * Combined the keyboard and PS/2 mouse handling into one file,
-+ * because they share the same hardware.
-+ * Johan Myreen <jem@iki.fi> 1998-10-08.
-+ *
-+ * Code fixes to handle mouse ACKs properly.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/mm.h>
-+#include <linux/signal.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/delay.h>
-+#include <linux/random.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/ioport.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+
-+#include <asm/io.h>
-+
-+/* Some configuration switches are present in the include file... */
-+
-+#include <linux/pc_keyb.h>
-+#include <asm/keyboard.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#define KBD_STAT_RXB (1<<4)
-+#define KBD_STAT_RXF (1<<5)
-+#define KBD_STAT_TXB (1<<6)
-+#define KBD_STAT_TXE (1<<7)
-+#define KBD_STAT_STP (1<<8)
-+
-+#define MSE_STAT_RXB (1<<4)
-+#define MSE_STAT_RXF (1<<5)
-+#define MSE_STAT_TXB (1<<6)
-+#define MSE_STAT_TXE (1<<7)
-+#define MSE_STAT_STP (1<<8)
-+
-+/* Simple translation table for the SysRq keys */
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char sa1111_sysrq_xlate[128] = "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+// static void kbd_write_command_w(int data);
-+static void kbd_write_output_w(int data);
-+
-+spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
-+static void handle_kbd_event(void);
-+
-+/* used only by send_data - set by keyboard_interrupt */
-+static volatile unsigned char reply_expected = 0;
-+static volatile unsigned char acknowledge = 0;
-+static volatile unsigned char resend = 0;
-+
-+
-+#if defined CONFIG_PSMOUSE
-+/*
-+ * PS/2 Auxiliary Device
-+ */
-+
-+static int __init psaux_init(void);
-+
-+static struct aux_queue *queue; /* Mouse data buffer. */
-+static int aux_count = 0;
-+/* used when we send commands to the mouse that expect an ACK. */
-+static unsigned char mouse_reply_expected = 0;
-+
-+#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
-+#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
-+
-+#define MAX_RETRIES 60 /* some aux operations take long time */
-+#endif /* CONFIG_PSMOUSE */
-+
-+/*
-+ * Wait for keyboard controller input buffer to drain.
-+ *
-+ * Don't use 'jiffies' so that we don't depend on
-+ * interrupts..
-+ *
-+ * Quote from PS/2 System Reference Manual:
-+ *
-+ * "Address hex 0060 and address hex 0064 should be written only when
-+ * the input-buffer-full bit and output-buffer-full bit in the
-+ * Controller Status register are set 0."
-+ */
-+
-+static void kb_wait(void)
-+{
-+ unsigned long timeout = KBC_TIMEOUT;
-+
-+ do {
-+ /*
-+ * "handle_kbd_event()" will handle any incoming events
-+ * while we wait - keypresses or mouse movement.
-+ */
-+ handle_kbd_event();
-+ if (KBDSTAT & KBD_STAT_TXE)
-+ return;
-+ mdelay(1);
-+ timeout--;
-+ }
-+ while (timeout);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING "Keyboard timed out[1]\n");
-+#endif
-+}
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+/* for USB 106 keyboard */
-+#define E0_YEN 124
-+#define E0_BACKSLASH 89
-+
-+
-+#define E1_PAUSE 119
-+
-+/*
-+ * The keycodes below are randomly located in 89-95,112-118,120-127.
-+ * They could be thrown away (and all occurrences below replaced by 0),
-+ * but that would force many users to use the `setkeycodes' utility, where
-+ * they needed not before. It does not matter that there are duplicates, as
-+ * long as no duplication occurs for any single keyboard.
-+ */
-+#define SC_LIM 89
-+
-+#define FOCUS_PF1 85 /* actual code! */
-+#define FOCUS_PF2 89
-+#define FOCUS_PF3 90
-+#define FOCUS_PF4 91
-+#define FOCUS_PF5 92
-+#define FOCUS_PF6 93
-+#define FOCUS_PF7 94
-+#define FOCUS_PF8 95
-+#define FOCUS_PF9 120
-+#define FOCUS_PF10 121
-+#define FOCUS_PF11 122
-+#define FOCUS_PF12 123
-+
-+#define JAP_86 124
-+/* tfj@olivia.ping.dk:
-+ * The four keys are located over the numeric keypad, and are
-+ * labelled A1-A4. It's an rc930 keyboard, from
-+ * Regnecentralen/RC International, Now ICL.
-+ * Scancodes: 59, 5a, 5b, 5c.
-+ */
-+#define RGN1 124
-+#define RGN2 125
-+#define RGN3 126
-+#define RGN4 127
-+
-+static unsigned char high_keys[128 - SC_LIM] = {
-+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
-+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
-+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
-+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
-+};
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+int sa1111_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ if (scancode < 128)
-+ high_keys[scancode - SC_LIM] = keycode;
-+ else
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int sa1111_getkeycode(unsigned int scancode)
-+{
-+ return
-+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
-+ (scancode <
-+ 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];
-+}
-+
-+static int do_acknowledge(unsigned char scancode)
-+{
-+ if (reply_expected) {
-+ /* Unfortunately, we must recognise these codes only if we know they
-+ * are known to be valid (i.e., after sending a command), because there
-+ * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
-+ * keys with such codes :(
-+ */
-+ if (scancode == KBD_REPLY_ACK) {
-+ acknowledge = 1;
-+ reply_expected = 0;
-+ return 0;
-+ } else if (scancode == KBD_REPLY_RESEND) {
-+ resend = 1;
-+ reply_expected = 0;
-+ return 0;
-+ }
-+ /* Should not happen... */
-+#if 0
-+ printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
-+ scancode);
-+#endif
-+ }
-+ return 1;
-+}
-+
-+int
-+sa1111_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode = 0;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ /*
-+ * usually it will be 0xe0, but a Pause key generates
-+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
-+ */
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ }
-+ else if (prev_scancode == 0x100
-+ && scancode == 0x45) {
-+ *keycode = E1_PAUSE;
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO
-+ "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ /*
-+ * The keyboard maintains its own internal caps lock and
-+ * num lock statuses. In caps lock mode E0 AA precedes make
-+ * code and E0 2A follows break code. In num lock mode,
-+ * E0 2A precedes make code and E0 AA follows break code.
-+ * We do our own book-keeping, so we will just ignore these.
-+ */
-+ /*
-+ * For my keyboard there is no caps lock mode, but there are
-+ * both Shift-L and Shift-R modes. The former mode generates
-+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
-+ * So, we should also ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO
-+ "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else if (scancode >= SC_LIM) {
-+ /* This happens with the FOCUS 9000 keyboard
-+ Its keys PF1..PF12 are reported to generate
-+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
-+ Moreover, unless repeated, they do not generate
-+ key-down events, so we have to zero up_flag below */
-+ /* Also, Japanese 86/106 keyboards are reported to
-+ generate 0x73 and 0x7d for \ - and \ | respectively. */
-+ /* Also, some Brazilian keyboard is reported to produce
-+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
-+
-+ *keycode = high_keys[scancode - SC_LIM];
-+
-+ if (!*keycode) {
-+ if (!raw_mode) {
-+#ifdef KBD_REPORT_UNKN
-+ printk(KERN_INFO
-+ "keyboard: unrecognized scancode (%02x)"
-+ " - ignored\n", scancode);
-+#endif
-+ }
-+ return 0;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+char sa1111_unexpected_up(unsigned char keycode)
-+{
-+ /* unexpected, but this can happen: maybe this was a key release for a
-+ FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
-+ if (keycode >= SC_LIM || keycode == 85)
-+ return 0;
-+ else
-+ return 0200;
-+}
-+
-+static unsigned char kbd_exists = 1;
-+
-+static inline void handle_keyboard_event(unsigned char scancode)
-+{
-+#ifdef CONFIG_VT
-+ kbd_exists = 1;
-+ if (do_acknowledge(scancode))
-+ handle_scancode(scancode, !(scancode & 0x80));
-+#endif
-+ tasklet_schedule(&keyboard_tasklet);
-+}
-+
-+/*
-+ * This reads the keyboard status port, and does the
-+ * appropriate action.
-+ *
-+ * It requires that we hold the keyboard controller
-+ * spinlock.
-+ */
-+static void handle_kbd_event(void)
-+{
-+ unsigned int status = KBDSTAT;
-+ unsigned int work = 10000;
-+ unsigned char scancode;
-+
-+ while (status & KBD_STAT_RXF) {
-+ while (status & KBD_STAT_RXF) {
-+ scancode = KBDDATA & 0xff;
-+ if (!(status & KBD_STAT_STP))
-+ handle_keyboard_event(scancode);
-+ if (!--work) {
-+ printk(KERN_ERR
-+ "pc_keyb: keyboard controller jammed (0x%02X).\n",
-+ status);
-+ return;
-+ }
-+ status = KBDSTAT;
-+ }
-+ work = 10000;
-+ }
-+
-+ if (status & KBD_STAT_STP)
-+ KBDSTAT = KBD_STAT_STP;
-+}
-+
-+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long flags;
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ handle_kbd_event();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * send_data sends a character to the keyboard and waits
-+ * for an acknowledge, possibly retrying if asked to. Returns
-+ * the success status.
-+ *
-+ * Don't use 'jiffies', so that we don't depend on interrupts
-+ */
-+static int send_data(unsigned char data)
-+{
-+ int retries = 3;
-+
-+ do {
-+ unsigned long timeout = KBD_TIMEOUT;
-+
-+ acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
-+ resend = 0;
-+ reply_expected = 1;
-+ kbd_write_output_w(data);
-+ for (;;) {
-+ if (acknowledge)
-+ return 1;
-+ if (resend)
-+ break;
-+ mdelay(1);
-+ if (!--timeout) {
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING
-+ "keyboard: Timeout - AT keyboard not present?\n");
-+#endif
-+ return 0;
-+ }
-+ }
-+ }
-+ while (retries-- > 0);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING
-+ "keyboard: Too many NACKs -- noisy kbd cable?\n");
-+#endif
-+ return 0;
-+}
-+
-+void sa1111_leds(unsigned char leds)
-+{
-+ if (kbd_exists
-+ && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
-+ send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
-+ kbd_exists = 0;
-+ }
-+}
-+
-+#define KBD_NO_DATA (-1) /* No data */
-+#define KBD_BAD_DATA (-2) /* Parity or other error */
-+
-+static int __init kbd_read_data(void)
-+{
-+ int retval = KBD_NO_DATA;
-+ unsigned int status;
-+
-+ status = KBDSTAT;
-+ if (status & KBD_STAT_RXF) {
-+ unsigned char data = KBDDATA;
-+
-+ retval = data;
-+ if (status & KBD_STAT_STP)
-+ retval = KBD_BAD_DATA;
-+ }
-+ return retval;
-+}
-+
-+static void __init kbd_clear_input(void)
-+{
-+ int maxread = 100; /* Random number */
-+
-+ do {
-+ if (kbd_read_data() == KBD_NO_DATA)
-+ break;
-+ }
-+ while (--maxread);
-+}
-+
-+static int __init kbd_wait_for_input(void)
-+{
-+ long timeout = KBD_INIT_TIMEOUT;
-+
-+ do {
-+ int retval = kbd_read_data();
-+ if (retval >= 0)
-+ return retval;
-+ mdelay(1);
-+ }
-+ while (--timeout);
-+ return -1;
-+}
-+
-+#if 0
-+static void kbd_write_command_w(int data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ kb_wait();
-+ kbd_write_command(data);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+#endif
-+
-+static void kbd_write_output_w(int data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ kb_wait();
-+ KBDDATA = data & 0xff;
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Test the keyboard interface. We basically check to make sure that
-+ * we can drive each line to the keyboard independently of each other.
-+ */
-+static int kbdif_test(void)
-+{
-+ int ret = 0;
-+
-+ KBDCR = KBDCR_ENA | KBDCR_FKC;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBD) {
-+ printk("Keyboard interface test failed[1]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ KBDCR = KBDCR_ENA;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != (KBDSTAT_KBC | KBDSTAT_KBD)) {
-+ printk("Keyboard interface test failed[2]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ KBDCR = KBDCR_ENA | KBDCR_FKD;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBC) {
-+ printk("Keyboard interface test failed[3]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ return ret;
-+}
-+
-+static char *__init initialize_kbd(void)
-+{
-+ int status;
-+
-+ /*
-+ * Test the keyboard interface.
-+ */
-+ kbdif_test();
-+
-+ /*
-+ * Ok, drop the force low bits, and wait a while,
-+ * and clear the stop bit error flag.
-+ */
-+ KBDCR = KBDCR_ENA;
-+ udelay(4);
-+ KBDSTAT = KBD_STAT_STP;
-+
-+ /*
-+ * Ok, we're now ready to talk to the keyboard. Reset
-+ * it, just to make sure we're starting in a sane state.
-+ *
-+ * Set up to try again if the keyboard asks for RESEND.
-+ */
-+ do {
-+ KBDDATA = KBD_CMD_RESET;
-+ status = kbd_wait_for_input();
-+ if (status == KBD_REPLY_ACK)
-+ break;
-+ if (status != KBD_REPLY_RESEND)
-+ return "Keyboard reset failed, no ACK";
-+ } while (1);
-+
-+ if (kbd_wait_for_input() != KBD_REPLY_POR)
-+ return "Keyboard reset failed, no POR";
-+
-+ /*
-+ * Set keyboard controller mode. During this, the keyboard should be
-+ * in the disabled state.
-+ *
-+ * Set up to try again if the keyboard asks for RESEND.
-+ */
-+ do {
-+ kbd_write_output_w(KBD_CMD_DISABLE);
-+ status = kbd_wait_for_input();
-+ if (status == KBD_REPLY_ACK)
-+ break;
-+ if (status != KBD_REPLY_RESEND)
-+ return "Disable keyboard: no ACK";
-+ } while (1);
-+
-+#if 0 /*@@@ */
-+ kbd_write_command_w(KBD_CCMD_WRITE_MODE);
-+ kbd_write_output_w(KBD_MODE_KBD_INT
-+ | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE |
-+ KBD_MODE_KCC);
-+
-+ /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
-+ kbd_write_command_w(KBD_CCMD_READ_MODE);
-+ if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
-+ /*
-+ * If the controller does not support conversion,
-+ * Set the keyboard to scan-code set 1.
-+ */
-+ kbd_write_output_w(0xF0);
-+ kbd_wait_for_input();
-+ kbd_write_output_w(0x01);
-+ kbd_wait_for_input();
-+ }
-+#else
-+ kbd_write_output_w(0xf0);
-+ kbd_wait_for_input();
-+ kbd_write_output_w(0x01);
-+ kbd_wait_for_input();
-+#endif
-+
-+
-+ kbd_write_output_w(KBD_CMD_ENABLE);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Enable keyboard: no ACK";
-+
-+ /*
-+ * Finally, set the typematic rate to maximum.
-+ */
-+ kbd_write_output_w(KBD_CMD_SET_RATE);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Set rate: no ACK";
-+ kbd_write_output_w(0x00);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Set rate: no ACK";
-+
-+ return NULL;
-+}
-+
-+int __init sa1111_kbd_init_hw(void)
-+{
-+ char *msg;
-+ int ret;
-+
-+ if (!request_mem_region(_KBDCR, 512, "keyboard"))
-+ return -EBUSY;
-+
-+ SKPCR |= SKPCR_PTCLKEN;
-+ KBDCLKDIV = 0;
-+ KBDPRECNT = 127;
-+
-+ /* Flush any pending input. */
-+ kbd_clear_input();
-+
-+ msg = initialize_kbd();
-+ if (msg)
-+ printk(KERN_WARNING "initialize_kbd: %s\n", msg);
-+
-+#if defined CONFIG_PSMOUSE
-+ psaux_init();
-+#endif
-+
-+ k_setkeycode = sa1111_setkeycode;
-+ k_getkeycode = sa1111_getkeycode;
-+ k_translate = sa1111_translate;
-+ k_unexpected_up = sa1111_unexpected_up;
-+ k_leds = sa1111_leds;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_xlate = sa1111_sysrq_xlate;
-+ k_sysrq_key = 0x54;
-+#endif
-+
-+ /* Ok, finally allocate the IRQ, and off we go.. */
-+ ret = request_irq(IRQ_TPRXINT, keyboard_interrupt, 0, "keyboard", NULL);
-+ if (ret)
-+ release_mem_region(_KBDCR, 512);
-+
-+ return ret;
-+}
-+
-+#if defined CONFIG_PSMOUSE
-+
-+static inline void handle_mouse_event(unsigned char scancode)
-+{
-+ if (mouse_reply_expected) {
-+ if (scancode == AUX_ACK) {
-+ mouse_reply_expected--;
-+ return;
-+ }
-+ mouse_reply_expected = 0;
-+ }
-+
-+ add_mouse_randomness(scancode);
-+ if (aux_count) {
-+ int head = queue->head;
-+
-+ queue->buf[head] = scancode;
-+ head = (head + 1) & (AUX_BUF_SIZE - 1);
-+ if (head != queue->tail) {
-+ queue->head = head;
-+ if (queue->fasync)
-+ kill_fasync(&queue->fasync, SIGIO,
-+ POLL_IN);
-+ wake_up_interruptible(&queue->proc_list);
-+ }
-+ }
-+}
-+
-+static void handle_mse_event(void)
-+{
-+ unsigned int msests = MSESTAT;
-+ unsigned int work = 10000;
-+ unsigned char scancode;
-+
-+ while (msests & MSE_STAT_RXF) {
-+ while (msests & MSE_STAT_RXF) {
-+ scancode = MSEDATA & 0xff;
-+ if (!(msests & MSE_STAT_STP))
-+ handle_mouse_event(scancode);
-+ if (!--work) {
-+ printk(KERN_ERR
-+ "pc_keyb: mouse controller jammed (0x%02X).\n",
-+ msests);
-+ return;
-+ /*XXX*/}
-+ msests = MSESTAT;
-+ }
-+ work = 10000;
-+ }
-+}
-+
-+static void ms_wait(void)
-+{
-+ unsigned long timeout = KBC_TIMEOUT;
-+
-+ do {
-+ /*
-+ * "handle_kbd_event()" will handle any incoming events
-+ * while we wait - keypresses or mouse movement.
-+ */
-+ handle_mse_event();
-+ if (MSESTAT & MSE_STAT_TXE)
-+ return;
-+ mdelay(1);
-+ timeout--;
-+ }
-+ while (timeout);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING "Mouse timed out[1]\n");
-+#endif
-+}
-+
-+static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ handle_mse_event();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Check if this is a dual port controller.
-+ */
-+static int __init detect_auxiliary_port(void)
-+{
-+ unsigned long flags;
-+ int loops = 10;
-+ int retval = 0;
-+
-+ /* Check if the BIOS detected a device on the auxiliary port. */
-+ if (aux_device_present == 0xaa)
-+ return 1;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+
-+ /* Put the value 0x5A in the output buffer using the "Write
-+ * Auxiliary Device Output Buffer" command (0xD3). Poll the
-+ * Status Register for a while to see if the value really
-+ * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
-+ * bit is also set to 1 in the Status Register, we assume this
-+ * controller has an Auxiliary Port (a.k.a. Mouse Port).
-+ */
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
-+
-+ SKPCR |= SKPCR_PMCLKEN;
-+
-+ MSECLKDIV = 0;
-+ MSEPRECNT = 127;
-+ MSECR = MSECR_ENA;
-+ mdelay(50);
-+ MSEDATA = 0xf4;
-+ mdelay(50);
-+
-+ do {
-+ unsigned int msests = MSESTAT;
-+
-+ if (msests & MSE_STAT_RXF) {
-+ do {
-+ msests = MSEDATA; /* dummy read */
-+ mdelay(50);
-+ msests = MSESTAT;
-+ }
-+ while (msests & MSE_STAT_RXF);
-+ printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
-+ retval = 1;
-+ break;
-+ }
-+ mdelay(1);
-+ }
-+ while (--loops);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+
-+ return retval;
-+}
-+
-+/*
-+ * Send a byte to the mouse.
-+ */
-+static void aux_write_dev(int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
-+ ms_wait();
-+ MSEDATA = val;
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Send a byte to the mouse & handle returned ack
-+ */
-+static void aux_write_ack(int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
-+ ms_wait();
-+ MSEDATA = val;
-+ /* we expect an ACK in response. */
-+ mouse_reply_expected++;
-+ ms_wait();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+static unsigned char get_from_queue(void)
-+{
-+ unsigned char result;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ result = queue->buf[queue->tail];
-+ queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+ return result;
-+}
-+
-+
-+static inline int queue_empty(void)
-+{
-+ return queue->head == queue->tail;
-+}
-+
-+static int fasync_aux(int fd, struct file *filp, int on)
-+{
-+ int retval;
-+
-+ retval = fasync_helper(fd, filp, on, &queue->fasync);
-+ if (retval < 0)
-+ return retval;
-+ return 0;
-+}
-+
-+
-+/*
-+ * Random magic cookie for the aux device
-+ */
-+#define AUX_DEV ((void *)queue)
-+
-+static int release_aux(struct inode *inode, struct file *file)
-+{
-+ fasync_aux(-1, file, 0);
-+ if (--aux_count)
-+ return 0;
-+ // kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
-+ // kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
-+ aux_write_ack(AUX_DISABLE_DEV); /* Disable aux device */
-+ MSECR &= ~MSECR_ENA;
-+ free_irq(IRQ_MSRXINT, AUX_DEV);
-+ return 0;
-+}
-+
-+/*
-+ * Install interrupt handler.
-+ * Enable auxiliary device.
-+ */
-+
-+static int open_aux(struct inode *inode, struct file *file)
-+{
-+ if (aux_count++) {
-+ return 0;
-+ }
-+ queue->head = queue->tail = 0; /* Flush input queue */
-+ /* Don't enable the mouse controller until we've registered IRQ handler */
-+ if (request_irq(IRQ_MSRXINT, mouse_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
-+ aux_count--;
-+ return -EBUSY;
-+ }
-+ MSECLKDIV = 0;
-+ MSEPRECNT = 127;
-+ MSECR &= ~MSECR_ENA;
-+ mdelay(50);
-+ MSECR = MSECR_ENA;
-+ mdelay(50);
-+ MSEDATA = 0xf4;
-+ mdelay(50);
-+ if (MSESTAT & 0x0100) {
-+ MSESTAT = 0x0100; /* clear IRQ status */
-+ }
-+/* kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); *//* Enable the
-+ auxiliary port on
-+ controller. */
-+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
-+ // kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
-+
-+ // send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
-+
-+ return 0;
-+}
-+
-+/*
-+ * Put bytes from input queue to buffer.
-+ */
-+
-+static ssize_t
-+read_aux(struct file *file, char *buffer, size_t count, loff_t * ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ ssize_t i = count;
-+ unsigned char c;
-+
-+ if (queue_empty()) {
-+ if (file->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ add_wait_queue(&queue->proc_list, &wait);
-+ repeat:
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (queue_empty() && !signal_pending(current)) {
-+ schedule();
-+ goto repeat;
-+ }
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&queue->proc_list, &wait);
-+ }
-+ while (i > 0 && !queue_empty()) {
-+ c = get_from_queue();
-+ put_user(c, buffer++);
-+ i--;
-+ }
-+ if (count - i) {
-+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-+ return count - i;
-+ }
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+ return 0;
-+}
-+
-+/*
-+ * Write to the aux device.
-+ */
-+
-+static ssize_t
-+write_aux(struct file *file, const char *buffer, size_t count,
-+ loff_t * ppos)
-+{
-+ ssize_t retval = 0;
-+
-+ if (count) {
-+ ssize_t written = 0;
-+
-+ if (count > 32)
-+ count = 32; /* Limit to 32 bytes. */
-+ do {
-+ char c;
-+ get_user(c, buffer++);
-+ aux_write_dev(c);
-+ written++;
-+ }
-+ while (--count);
-+ retval = -EIO;
-+ if (written) {
-+ retval = written;
-+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+static unsigned int aux_poll(struct file *file, poll_table * wait)
-+{
-+ poll_wait(file, &queue->proc_list, wait);
-+ if (!queue_empty())
-+ return POLLIN | POLLRDNORM;
-+ return 0;
-+}
-+
-+struct file_operations psaux_fops = {
-+ read: read_aux,
-+ write: write_aux,
-+ poll: aux_poll,
-+ open: open_aux,
-+ release: release_aux,
-+ fasync: fasync_aux,
-+};
-+
-+/*
-+ * Initialize driver.
-+ */
-+static struct miscdevice psaux_mouse = {
-+ PSMOUSE_MINOR, "psaux", &psaux_fops
-+};
-+
-+
-+static int __init psaux_init(void)
-+{
-+ int ret;
-+
-+ if (!request_mem_region(_MSECR, 512, "psaux"))
-+ return -EBUSY;
-+
-+ if (!detect_auxiliary_port()) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ misc_register(&psaux_mouse);
-+ queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-+ memset(queue, 0, sizeof(*queue));
-+ queue->head = queue->tail = 0;
-+ init_waitqueue_head(&queue->proc_list);
-+
-+#ifdef CONFIG_PSMOUSE
-+ aux_write_ack(AUX_SET_SAMPLE);
-+ aux_write_ack(100); /* 100 samples/sec */
-+ aux_write_ack(AUX_SET_RES);
-+ aux_write_ack(3); /* 8 counts per mm */
-+ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
-+#endif
-+ ret = 0;
-+
-+ out:
-+ if (ret)
-+ release_mem_region(_MSECR, 512);
-+ return ret;
-+}
-+
-+#endif /* CONFIG_PSMOUSE */
---- linux-2.4.25/drivers/char/serial.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/char/serial.c 2004-03-31 17:15:09.000000000 +0200
-@@ -4527,6 +4527,14 @@
- }
-
- /*
-+ * If there is exactly one port of 8 bytes, use it.
-+ */
-+ if (num_port == 1 && pci_resource_len(dev, first_port) == 8) {
-+ board->flags = first_port;
-+ return 0;
-+ }
-+
-+ /*
- * If there is 1 or 0 iomem regions, and exactly one port, use
- * it.
- */
---- linux-2.4.25/drivers/char/serial_21285.c~2.4.25-vrs2.patch
-+++ linux-2.4.25/drivers/char/serial_21285.c
--/*
-- * linux/drivers/char/serial_21285.c
-- *
-- * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
-- *
-- * Based on drivers/char/serial.c
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/errno.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/interrupt.h>
--#include <linux/tty.h>
--#include <linux/tty_flip.h>
--#include <linux/serial.h>
--#include <linux/major.h>
--#include <linux/ptrace.h>
--#include <linux/ioport.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/init.h>
--#include <linux/console.h>
--
--#include <asm/io.h>
--#include <asm/irq.h>
--#include <asm/uaccess.h>
--#include <asm/dec21285.h>
--#include <asm/hardware.h>
--
--#define BAUD_BASE (mem_fclk_21285/64)
--
--#define SERIAL_21285_NAME "ttyFB"
--#define SERIAL_21285_MAJOR 204
--#define SERIAL_21285_MINOR 4
--
--#define SERIAL_21285_AUXNAME "cuafb"
--#define SERIAL_21285_AUXMAJOR 205
--#define SERIAL_21285_AUXMINOR 4
--
--static struct tty_driver rs285_driver, callout_driver;
--static int rs285_refcount;
--static struct tty_struct *rs285_table[1];
--
--static struct termios *rs285_termios[1];
--static struct termios *rs285_termios_locked[1];
--
--static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
--static struct tty_struct *rs285_tty;
--static int rs285_use_count;
--
--static int rs285_write_room(struct tty_struct *tty)
--{
-- return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
--}
--
--static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- if (!rs285_tty) {
-- disable_irq(IRQ_CONRX);
-- return;
-- }
-- while (!(*CSR_UARTFLG & 0x10)) {
-- int ch, flag;
-- ch = *CSR_UARTDR;
-- flag = *CSR_RXSTAT;
-- if (flag & 4)
-- tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
-- if (flag & 2)
-- flag = TTY_PARITY;
-- else if (flag & 1)
-- flag = TTY_FRAME;
-- tty_insert_flip_char(rs285_tty, ch, flag);
-- }
-- tty_flip_buffer_push(rs285_tty);
--}
--
--static void rs285_send_xchar(struct tty_struct *tty, char ch)
--{
-- x_char = ch;
-- enable_irq(IRQ_CONTX);
--}
--
--static void rs285_throttle(struct tty_struct *tty)
--{
-- if (I_IXOFF(tty))
-- rs285_send_xchar(tty, STOP_CHAR(tty));
--}
--
--static void rs285_unthrottle(struct tty_struct *tty)
--{
-- if (I_IXOFF(tty)) {
-- if (x_char)
-- x_char = 0;
-- else
-- rs285_send_xchar(tty, START_CHAR(tty));
-- }
--}
--
--static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- while (!(*CSR_UARTFLG & 0x20)) {
-- if (x_char) {
-- *CSR_UARTDR = x_char;
-- x_char = 0;
-- continue;
-- }
-- if (putp == getp) {
-- disable_irq(IRQ_CONTX);
-- break;
-- }
-- *CSR_UARTDR = *getp;
-- if (++getp >= wbuf + sizeof(wbuf))
-- getp = wbuf;
-- }
-- if (rs285_tty)
-- wake_up_interruptible(&rs285_tty->write_wait);
--}
--
--static inline int rs285_xmit(int ch)
--{
-- if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
-- return 0;
-- *putp = ch;
-- if (++putp >= wbuf + sizeof(wbuf))
-- putp = wbuf;
-- enable_irq(IRQ_CONTX);
-- return 1;
--}
--
--static int rs285_write(struct tty_struct *tty, int from_user,
-- const u_char * buf, int count)
--{
-- int i;
--
-- if (from_user && verify_area(VERIFY_READ, buf, count))
-- return -EINVAL;
--
-- for (i = 0; i < count; i++) {
-- char ch;
-- if (from_user)
-- __get_user(ch, buf + i);
-- else
-- ch = buf[i];
-- if (!rs285_xmit(ch))
-- break;
-- }
-- return i;
--}
--
--static void rs285_put_char(struct tty_struct *tty, u_char ch)
--{
-- rs285_xmit(ch);
--}
--
--static int rs285_chars_in_buffer(struct tty_struct *tty)
--{
-- return sizeof(wbuf) - rs285_write_room(tty);
--}
--
--static void rs285_flush_buffer(struct tty_struct *tty)
--{
-- disable_irq(IRQ_CONTX);
-- putp = getp = wbuf;
-- if (x_char)
-- enable_irq(IRQ_CONTX);
--}
--
--static inline void rs285_set_cflag(int cflag)
--{
-- int h_lcr, baud, quot;
--
-- switch (cflag & CSIZE) {
-- case CS5:
-- h_lcr = 0x10;
-- break;
-- case CS6:
-- h_lcr = 0x30;
-- break;
-- case CS7:
-- h_lcr = 0x50;
-- break;
-- default: /* CS8 */
-- h_lcr = 0x70;
-- break;
--
-- }
-- if (cflag & CSTOPB)
-- h_lcr |= 0x08;
-- if (cflag & PARENB)
-- h_lcr |= 0x02;
-- if (!(cflag & PARODD))
-- h_lcr |= 0x04;
--
-- switch (cflag & CBAUD) {
-- case B200: baud = 200; break;
-- case B300: baud = 300; break;
-- case B1200: baud = 1200; break;
-- case B1800: baud = 1800; break;
-- case B2400: baud = 2400; break;
-- case B4800: baud = 4800; break;
-- default:
-- case B9600: baud = 9600; break;
-- case B19200: baud = 19200; break;
-- case B38400: baud = 38400; break;
-- case B57600: baud = 57600; break;
-- case B115200: baud = 115200; break;
-- }
--
-- /*
-- * The documented expression for selecting the divisor is:
-- * BAUD_BASE / baud - 1
-- * However, typically BAUD_BASE is not divisible by baud, so
-- * we want to select the divisor that gives us the minimum
-- * error. Therefore, we want:
-- * int(BAUD_BASE / baud - 0.5) ->
-- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
-- * int((BAUD_BASE - (baud >> 1)) / baud)
-- */
-- quot = (BAUD_BASE - (baud >> 1)) / baud;
--
-- *CSR_UARTCON = 0;
-- *CSR_L_UBRLCR = quot & 0xff;
-- *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
-- *CSR_H_UBRLCR = h_lcr;
-- *CSR_UARTCON = 1;
--}
--
--static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
--{
-- if (old && tty->termios->c_cflag == old->c_cflag)
-- return;
-- rs285_set_cflag(tty->termios->c_cflag);
--}
--
--
--static void rs285_stop(struct tty_struct *tty)
--{
-- disable_irq(IRQ_CONTX);
--}
--
--static void rs285_start(struct tty_struct *tty)
--{
-- enable_irq(IRQ_CONTX);
--}
--
--static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
--{
-- int orig_jiffies = jiffies;
-- while (*CSR_UARTFLG & 8) {
-- current->state = TASK_INTERRUPTIBLE;
-- schedule_timeout(1);
-- if (signal_pending(current))
-- break;
-- if (timeout && time_after(jiffies, orig_jiffies + timeout))
-- break;
-- }
-- current->state = TASK_RUNNING;
--}
--
--static int rs285_open(struct tty_struct *tty, struct file *filp)
--{
-- int line;
--
-- MOD_INC_USE_COUNT;
-- line = MINOR(tty->device) - tty->driver.minor_start;
-- if (line) {
-- MOD_DEC_USE_COUNT;
-- return -ENODEV;
-- }
--
-- tty->driver_data = NULL;
-- if (!rs285_tty)
-- rs285_tty = tty;
--
-- enable_irq(IRQ_CONRX);
-- rs285_use_count++;
-- return 0;
--}
--
--static void rs285_close(struct tty_struct *tty, struct file *filp)
--{
-- if (!--rs285_use_count) {
-- rs285_wait_until_sent(tty, 0);
-- disable_irq(IRQ_CONRX);
-- disable_irq(IRQ_CONTX);
-- rs285_tty = NULL;
-- }
-- MOD_DEC_USE_COUNT;
--}
--
--static int __init rs285_init(void)
--{
-- int baud = B9600;
--
-- if (machine_is_personal_server())
-- baud = B57600;
--
-- rs285_driver.magic = TTY_DRIVER_MAGIC;
-- rs285_driver.driver_name = "serial_21285";
-- rs285_driver.name = SERIAL_21285_NAME;
-- rs285_driver.major = SERIAL_21285_MAJOR;
-- rs285_driver.minor_start = SERIAL_21285_MINOR;
-- rs285_driver.num = 1;
-- rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
-- rs285_driver.subtype = SERIAL_TYPE_NORMAL;
-- rs285_driver.init_termios = tty_std_termios;
-- rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
-- rs285_driver.flags = TTY_DRIVER_REAL_RAW;
-- rs285_driver.refcount = &rs285_refcount;
-- rs285_driver.table = rs285_table;
-- rs285_driver.termios = rs285_termios;
-- rs285_driver.termios_locked = rs285_termios_locked;
--
-- rs285_driver.open = rs285_open;
-- rs285_driver.close = rs285_close;
-- rs285_driver.write = rs285_write;
-- rs285_driver.put_char = rs285_put_char;
-- rs285_driver.write_room = rs285_write_room;
-- rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
-- rs285_driver.flush_buffer = rs285_flush_buffer;
-- rs285_driver.throttle = rs285_throttle;
-- rs285_driver.unthrottle = rs285_unthrottle;
-- rs285_driver.send_xchar = rs285_send_xchar;
-- rs285_driver.set_termios = rs285_set_termios;
-- rs285_driver.stop = rs285_stop;
-- rs285_driver.start = rs285_start;
-- rs285_driver.wait_until_sent = rs285_wait_until_sent;
--
-- callout_driver = rs285_driver;
-- callout_driver.name = SERIAL_21285_AUXNAME;
-- callout_driver.major = SERIAL_21285_AUXMAJOR;
-- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
--
-- if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
-- panic("Couldn't get rx irq for rs285");
--
-- if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
-- panic("Couldn't get tx irq for rs285");
--
-- if (tty_register_driver(&rs285_driver))
-- printk(KERN_ERR "Couldn't register 21285 serial driver\n");
-- if (tty_register_driver(&callout_driver))
-- printk(KERN_ERR "Couldn't register 21285 callout driver\n");
--
-- return 0;
--}
--
--static void __exit rs285_fini(void)
--{
-- unsigned long flags;
-- int ret;
--
-- save_flags(flags);
-- cli();
-- ret = tty_unregister_driver(&callout_driver);
-- if (ret)
-- printk(KERN_ERR "Unable to unregister 21285 callout driver "
-- "(%d)\n", ret);
-- ret = tty_unregister_driver(&rs285_driver);
-- if (ret)
-- printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
-- ret);
-- free_irq(IRQ_CONTX, NULL);
-- free_irq(IRQ_CONRX, NULL);
-- restore_flags(flags);
--}
--
--module_init(rs285_init);
--module_exit(rs285_fini);
--
--#ifdef CONFIG_SERIAL_21285_CONSOLE
--/************** console driver *****************/
--
--static void rs285_console_write(struct console *co, const char *s, u_int count)
--{
-- int i;
--
-- disable_irq(IRQ_CONTX);
-- for (i = 0; i < count; i++) {
-- while (*CSR_UARTFLG & 0x20);
-- *CSR_UARTDR = s[i];
-- if (s[i] == '\n') {
-- while (*CSR_UARTFLG & 0x20);
-- *CSR_UARTDR = '\r';
-- }
-- }
-- enable_irq(IRQ_CONTX);
--}
--
--static kdev_t rs285_console_device(struct console *c)
--{
-- return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
--}
--
--static int __init rs285_console_setup(struct console *co, char *options)
--{
-- int baud = 9600;
-- int bits = 8;
-- int parity = 'n';
-- int cflag = CREAD | HUPCL | CLOCAL;
--
-- if (machine_is_personal_server())
-- baud = 57600;
--
-- if (options) {
-- char *s = options;
-- baud = simple_strtoul(options, NULL, 10);
-- while (*s >= '0' && *s <= '9')
-- s++;
-- if (*s)
-- parity = *s++;
-- if (*s)
-- bits = *s - '0';
-- }
--
-- /*
-- * Now construct a cflag setting.
-- */
-- switch (baud) {
-- case 1200:
-- cflag |= B1200;
-- break;
-- case 2400:
-- cflag |= B2400;
-- break;
-- case 4800:
-- cflag |= B4800;
-- break;
-- case 9600:
-- cflag |= B9600;
-- break;
-- case 19200:
-- cflag |= B19200;
-- break;
-- case 38400:
-- cflag |= B38400;
-- break;
-- case 57600:
-- cflag |= B57600;
-- break;
-- case 115200:
-- cflag |= B115200;
-- break;
-- default:
-- cflag |= B9600;
-- break;
-- }
-- switch (bits) {
-- case 7:
-- cflag |= CS7;
-- break;
-- default:
-- cflag |= CS8;
-- break;
-- }
-- switch (parity) {
-- case 'o':
-- case 'O':
-- cflag |= PARODD;
-- break;
-- case 'e':
-- case 'E':
-- cflag |= PARENB;
-- break;
-- }
-- co->cflag = cflag;
-- rs285_set_cflag(cflag);
-- rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
-- if (options)
-- rs285_console_write(NULL, options, strlen(options));
-- else
-- rs285_console_write(NULL, "no options", 10);
-- rs285_console_write(NULL, "\n", 1);
--
-- return 0;
--}
--
--static struct console rs285_cons =
--{
-- name: SERIAL_21285_NAME,
-- write: rs285_console_write,
-- device: rs285_console_device,
-- setup: rs285_console_setup,
-- flags: CON_PRINTBUFFER,
-- index: -1,
--};
--
--void __init rs285_console_init(void)
--{
-- register_console(&rs285_cons);
--}
--
--#endif /* CONFIG_SERIAL_21285_CONSOLE */
--
--MODULE_LICENSE("GPL");
--EXPORT_NO_SYMBOLS;
---- linux-2.4.25/drivers/char/serial_amba.c~2.4.25-vrs2.patch
-+++ linux-2.4.25/drivers/char/serial_amba.c
--/*
-- * linux/drivers/char/serial_amba.c
-- *
-- * Driver for AMBA serial ports
-- *
-- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-- *
-- * Copyright 1999 ARM Limited
-- * Copyright (C) 2000 Deep Blue Solutions Ltd.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- *
-- *
-- * This is a generic driver for ARM AMBA-type serial ports. They
-- * have a lot of 16550-like features, but are not register compatable.
-- * Note that although they do have CTS, DCD and DSR inputs, they do
-- * not have an RI input, nor do they have DTR or RTS outputs. If
-- * required, these have to be supplied via some other means (eg, GPIO)
-- * and hooked into this driver.
-- *
-- * This could very easily become a generic serial driver for dumb UARTs
-- * (eg, {82,16x}50, 21285, SA1100).
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/errno.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/interrupt.h>
--#include <linux/tty.h>
--#include <linux/tty_flip.h>
--#include <linux/major.h>
--#include <linux/string.h>
--#include <linux/fcntl.h>
--#include <linux/ptrace.h>
--#include <linux/ioport.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/init.h>
--#include <linux/circ_buf.h>
--#include <linux/serial.h>
--#include <linux/console.h>
--#include <linux/sysrq.h>
--
--#include <asm/system.h>
--#include <asm/io.h>
--#include <asm/irq.h>
--#include <asm/uaccess.h>
--#include <asm/bitops.h>
--
--#include <asm/hardware/serial_amba.h>
--
--#define SERIAL_AMBA_NAME "ttyAM"
--#define SERIAL_AMBA_MAJOR 204
--#define SERIAL_AMBA_MINOR 16
--#define SERIAL_AMBA_NR 2
--
--#define CALLOUT_AMBA_NAME "cuaam"
--#define CALLOUT_AMBA_MAJOR 205
--#define CALLOUT_AMBA_MINOR 16
--#define CALLOUT_AMBA_NR SERIAL_AMBA_NR
--
--#ifndef TRUE
--#define TRUE 1
--#endif
--#ifndef FALSE
--#define FALSE 0
--#endif
--
--#define DEBUG 0
--#define DEBUG_LEDS 0
--
--#if DEBUG_LEDS
--extern int get_leds(void);
--extern int set_leds(int);
--#endif
--
--/*
-- * Access routines for the AMBA UARTs
-- */
--#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR)
--#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR)
--#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR)
--#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
--#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR)
--#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR)
--#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
--#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L)
--#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
--#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M)
--#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
--#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H)
--#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
--#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
--#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
--#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
--
--#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
--#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
--
--/*
-- * Things needed by tty driver
-- */
--static struct tty_driver ambanormal_driver, ambacallout_driver;
--static int ambauart_refcount;
--static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
--static struct termios *ambauart_termios[SERIAL_AMBA_NR];
--static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
--
--#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
--#define SUPPORT_SYSRQ
--#endif
--
--/*
-- * Things needed internally to this driver
-- */
--
--/*
-- * tmp_buf is used as a temporary buffer by serial_write. We need to
-- * lock it in case the copy_from_user blocks while swapping in a page,
-- * and some other program tries to do a serial write at the same time.
-- * Since the lock will only come under contention when the system is
-- * swapping and available memory is low, it makes sense to share one
-- * buffer across all the serial ports, since it significantly saves
-- * memory if large numbers of serial ports are open.
-- */
--static u_char *tmp_buf;
--static DECLARE_MUTEX(tmp_buf_sem);
--
--#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
--
--/* number of characters left in xmit buffer before we ask for more */
--#define WAKEUP_CHARS 256
--#define AMBA_ISR_PASS_LIMIT 256
--
--#define EVT_WRITE_WAKEUP 0
--
--struct amba_icount {
-- __u32 cts;
-- __u32 dsr;
-- __u32 rng;
-- __u32 dcd;
-- __u32 rx;
-- __u32 tx;
-- __u32 frame;
-- __u32 overrun;
-- __u32 parity;
-- __u32 brk;
-- __u32 buf_overrun;
--};
--
--/*
-- * Static information about the port
-- */
--struct amba_port {
-- unsigned int uart_base;
-- unsigned int irq;
-- unsigned int uartclk;
-- unsigned int fifosize;
-- unsigned int tiocm_support;
-- void (*set_mctrl)(struct amba_port *, u_int mctrl);
--};
--
--/*
-- * This is the state information which is persistent across opens
-- */
--struct amba_state {
-- struct amba_icount icount;
-- unsigned int line;
-- unsigned int close_delay;
-- unsigned int closing_wait;
-- unsigned int custom_divisor;
-- unsigned int flags;
-- struct termios normal_termios;
-- struct termios callout_termios;
--
-- int count;
-- struct amba_info *info;
--};
--
--#define AMBA_XMIT_SIZE 1024
--/*
-- * This is the state information which is only valid when the port is open.
-- */
--struct amba_info {
-- struct amba_port *port;
-- struct amba_state *state;
-- struct tty_struct *tty;
-- unsigned char x_char;
-- unsigned char old_status;
-- unsigned char read_status_mask;
-- unsigned char ignore_status_mask;
-- struct circ_buf xmit;
-- unsigned int flags;
--#ifdef SUPPORT_SYSRQ
-- unsigned long sysrq;
--#endif
--
-- unsigned int event;
-- unsigned int timeout;
-- unsigned int lcr_h;
-- unsigned int mctrl;
-- int blocked_open;
-- pid_t session;
-- pid_t pgrp;
--
-- struct tasklet_struct tlet;
--
-- wait_queue_head_t open_wait;
-- wait_queue_head_t close_wait;
-- wait_queue_head_t delta_msr_wait;
--};
--
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
--static struct console ambauart_cons;
--#endif
--static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
--static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
--
--#if 1 //def CONFIG_SERIAL_INTEGRATOR
--static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
--{
--}
--
--static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
-- {
-- uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE),
-- irq: IRQ_UARTINT0,
-- uartclk: 14745600,
-- fifosize: 8,
-- set_mctrl: amba_set_mctrl_null,
-- },
-- {
-- uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE),
-- irq: IRQ_UARTINT1,
-- uartclk: 14745600,
-- fifosize: 8,
-- set_mctrl: amba_set_mctrl_null,
-- }
--};
--#endif
--
--static struct amba_state amba_state[SERIAL_AMBA_NR];
--
--static void ambauart_enable_rx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_disable_rx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_enable_tx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr |= AMBA_UARTCR_TIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_disable_tx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr &= ~AMBA_UARTCR_TIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_stop(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- ambauart_disable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--static void ambauart_start(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- if (info->xmit.head != info->xmit.tail
-- && info->xmit.buf)
-- ambauart_enable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--
--/*
-- * This routine is used by the interrupt handler to schedule
-- * processing in the software interrupt portion of the driver.
-- */
--static void ambauart_event(struct amba_info *info, int event)
--{
-- info->event |= 1 << event;
-- tasklet_schedule(&info->tlet);
--}
--
--static void
--#ifdef SUPPORT_SYSRQ
--ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
--#else
--ambauart_rx_chars(struct amba_info *info)
--#endif
--{
-- struct tty_struct *tty = info->tty;
-- unsigned int status, ch, rsr, flg, ignored = 0;
-- struct amba_icount *icount = &info->state->icount;
-- struct amba_port *port = info->port;
--
-- status = UART_GET_FR(port);
-- while (UART_RX_DATA(status)) {
-- ch = UART_GET_CHAR(port);
--
-- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-- goto ignore_char;
-- icount->rx++;
--
-- flg = TTY_NORMAL;
--
-- /*
-- * Note that the error handling code is
-- * out of the main execution path
-- */
-- rsr = UART_GET_RSR(port);
-- if (rsr & AMBA_UARTRSR_ANY)
-- goto handle_error;
--#ifdef SUPPORT_SYSRQ
-- if (info->sysrq) {
-- if (ch && time_before(jiffies, info->sysrq)) {
-- handle_sysrq(ch, regs, NULL, NULL);
-- info->sysrq = 0;
-- goto ignore_char;
-- }
-- info->sysrq = 0;
-- }
--#endif
-- error_return:
-- *tty->flip.flag_buf_ptr++ = flg;
-- *tty->flip.char_buf_ptr++ = ch;
-- tty->flip.count++;
-- ignore_char:
-- status = UART_GET_FR(port);
-- }
--out:
-- tty_flip_buffer_push(tty);
-- return;
--
--handle_error:
-- if (rsr & AMBA_UARTRSR_BE) {
-- rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
-- icount->brk++;
--
--#ifdef SUPPORT_SYSRQ
-- if (info->state->line == ambauart_cons.index) {
-- if (!info->sysrq) {
-- info->sysrq = jiffies + HZ*5;
-- goto ignore_char;
-- }
-- }
--#endif
-- } else if (rsr & AMBA_UARTRSR_PE)
-- icount->parity++;
-- else if (rsr & AMBA_UARTRSR_FE)
-- icount->frame++;
-- if (rsr & AMBA_UARTRSR_OE)
-- icount->overrun++;
--
-- if (rsr & info->ignore_status_mask) {
-- if (++ignored > 100)
-- goto out;
-- goto ignore_char;
-- }
-- rsr &= info->read_status_mask;
--
-- if (rsr & AMBA_UARTRSR_BE)
-- flg = TTY_BREAK;
-- else if (rsr & AMBA_UARTRSR_PE)
-- flg = TTY_PARITY;
-- else if (rsr & AMBA_UARTRSR_FE)
-- flg = TTY_FRAME;
--
-- if (rsr & AMBA_UARTRSR_OE) {
-- /*
-- * CHECK: does overrun affect the current character?
-- * ASSUMPTION: it does not.
-- */
-- *tty->flip.flag_buf_ptr++ = flg;
-- *tty->flip.char_buf_ptr++ = ch;
-- tty->flip.count++;
-- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-- goto ignore_char;
-- ch = 0;
-- flg = TTY_OVERRUN;
-- }
--#ifdef SUPPORT_SYSRQ
-- info->sysrq = 0;
--#endif
-- goto error_return;
--}
--
--static void ambauart_tx_chars(struct amba_info *info)
--{
-- struct amba_port *port = info->port;
-- int count;
--
-- if (info->x_char) {
-- UART_PUT_CHAR(port, info->x_char);
-- info->state->icount.tx++;
-- info->x_char = 0;
-- return;
-- }
-- if (info->xmit.head == info->xmit.tail
-- || info->tty->stopped
-- || info->tty->hw_stopped) {
-- ambauart_disable_tx_interrupt(info);
-- return;
-- }
--
-- count = port->fifosize;
-- do {
-- UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-- info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
-- info->state->icount.tx++;
-- if (info->xmit.head == info->xmit.tail)
-- break;
-- } while (--count > 0);
--
-- if (CIRC_CNT(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE) < WAKEUP_CHARS)
-- ambauart_event(info, EVT_WRITE_WAKEUP);
--
-- if (info->xmit.head == info->xmit.tail) {
-- ambauart_disable_tx_interrupt(info);
-- }
--}
--
--static void ambauart_modem_status(struct amba_info *info)
--{
-- unsigned int status, delta;
-- struct amba_icount *icount = &info->state->icount;
--
-- status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
--
-- delta = status ^ info->old_status;
-- info->old_status = status;
--
-- if (!delta)
-- return;
--
-- if (delta & AMBA_UARTFR_DCD) {
-- icount->dcd++;
--#ifdef CONFIG_HARD_PPS
-- if ((info->flags & ASYNC_HARDPPS_CD) &&
-- (status & AMBA_UARTFR_DCD)
-- hardpps();
--#endif
-- if (info->flags & ASYNC_CHECK_CD) {
-- if (status & AMBA_UARTFR_DCD)
-- wake_up_interruptible(&info->open_wait);
-- else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_CALLOUT_NOHUP))) {
-- if (info->tty)
-- tty_hangup(info->tty);
-- }
-- }
-- }
--
-- if (delta & AMBA_UARTFR_DSR)
-- icount->dsr++;
--
-- if (delta & AMBA_UARTFR_CTS) {
-- icount->cts++;
--
-- if (info->flags & ASYNC_CTS_FLOW) {
-- status &= AMBA_UARTFR_CTS;
--
-- if (info->tty->hw_stopped) {
-- if (status) {
-- info->tty->hw_stopped = 0;
-- ambauart_enable_tx_interrupt(info);
-- ambauart_event(info, EVT_WRITE_WAKEUP);
-- }
-- } else {
-- if (!status) {
-- info->tty->hw_stopped = 1;
-- ambauart_disable_tx_interrupt(info);
-- }
-- }
-- }
-- }
-- wake_up_interruptible(&info->delta_msr_wait);
--
--}
--
--static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- struct amba_info *info = dev_id;
-- unsigned int status, pass_counter = 0;
--
--#if DEBUG_LEDS
-- // tell the world
-- set_leds(get_leds() | RED_LED);
--#endif
--
-- status = UART_GET_INT_STATUS(info->port);
-- do {
-- /*
-- * FIXME: what about clearing the interrupts?
-- */
--
-- if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
--#ifdef SUPPORT_SYSRQ
-- ambauart_rx_chars(info, regs);
--#else
-- ambauart_rx_chars(info);
--#endif
-- if (status & AMBA_UARTIIR_TIS)
-- ambauart_tx_chars(info);
-- if (status & AMBA_UARTIIR_MIS)
-- ambauart_modem_status(info);
-- if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
-- break;
--
-- status = UART_GET_INT_STATUS(info->port);
-- } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
--
--#if DEBUG_LEDS
-- // tell the world
-- set_leds(get_leds() & ~RED_LED);
--#endif
--}
--
--static void ambauart_tasklet_action(unsigned long data)
--{
-- struct amba_info *info = (struct amba_info *)data;
-- struct tty_struct *tty;
--
-- tty = info->tty;
-- if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
-- return;
--
-- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-- tty->ldisc.write_wakeup)
-- (tty->ldisc.write_wakeup)(tty);
-- wake_up_interruptible(&tty->write_wait);
--}
--
--static int ambauart_startup(struct amba_info *info)
--{
-- unsigned long flags;
-- unsigned long page;
-- int retval = 0;
--
-- page = get_zeroed_page(GFP_KERNEL);
-- if (!page)
-- return -ENOMEM;
--
-- save_flags(flags); cli();
--
-- if (info->flags & ASYNC_INITIALIZED) {
-- free_page(page);
-- goto errout;
-- }
--
-- if (info->xmit.buf)
-- free_page(page);
-- else
-- info->xmit.buf = (unsigned char *) page;
--
-- /*
-- * Allocate the IRQ
-- */
-- retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
-- if (retval) {
-- if (capable(CAP_SYS_ADMIN)) {
-- if (info->tty)
-- set_bit(TTY_IO_ERROR, &info->tty->flags);
-- retval = 0;
-- }
-- goto errout;
-- }
--
-- info->mctrl = 0;
-- if (info->tty->termios->c_cflag & CBAUD)
-- info->mctrl = TIOCM_RTS | TIOCM_DTR;
-- info->port->set_mctrl(info->port, info->mctrl);
--
-- /*
-- * initialise the old status of the modem signals
-- */
-- info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
--
-- /*
-- * Finally, enable interrupts
-- */
-- ambauart_enable_rx_interrupt(info);
--
-- if (info->tty)
-- clear_bit(TTY_IO_ERROR, &info->tty->flags);
-- info->xmit.head = info->xmit.tail = 0;
--
-- /*
-- * Set up the tty->alt_speed kludge
-- */
-- if (info->tty) {
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-- info->tty->alt_speed = 57600;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-- info->tty->alt_speed = 115200;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-- info->tty->alt_speed = 230400;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-- info->tty->alt_speed = 460800;
-- }
--
-- /*
-- * and set the speed of the serial port
-- */
-- ambauart_change_speed(info, 0);
--
-- info->flags |= ASYNC_INITIALIZED;
-- restore_flags(flags);
-- return 0;
--
--errout:
-- restore_flags(flags);
-- return retval;
--}
--
--/*
-- * This routine will shutdown a serial port; interrupts are disabled, and
-- * DTR is dropped if the hangup on close termio flag is on.
-- */
--static void ambauart_shutdown(struct amba_info *info)
--{
-- unsigned long flags;
--
-- if (!(info->flags & ASYNC_INITIALIZED))
-- return;
--
-- save_flags(flags); cli(); /* Disable interrupts */
--
-- /*
-- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-- * here so the queue might never be woken up
-- */
-- wake_up_interruptible(&info->delta_msr_wait);
--
-- /*
-- * Free the IRQ
-- */
-- free_irq(info->port->irq, info);
--
-- if (info->xmit.buf) {
-- unsigned long pg = (unsigned long) info->xmit.buf;
-- info->xmit.buf = NULL;
-- free_page(pg);
-- }
--
-- /*
-- * disable all interrupts, disable the port
-- */
-- UART_PUT_CR(info->port, 0);
--
-- /* disable break condition and fifos */
-- UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
-- ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
--
-- if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-- info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
-- info->port->set_mctrl(info->port, info->mctrl);
--
-- /* kill off our tasklet */
-- tasklet_kill(&info->tlet);
-- if (info->tty)
-- set_bit(TTY_IO_ERROR, &info->tty->flags);
--
-- info->flags &= ~ASYNC_INITIALIZED;
-- restore_flags(flags);
--}
--
--static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
--{
-- unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
-- unsigned long flags;
--
-- if (!info->tty || !info->tty->termios)
-- return;
--
-- cflag = info->tty->termios->c_cflag;
--
--#if DEBUG
-- printk("ambauart_set_cflag(0x%x) called\n", cflag);
--#endif
-- /* byte size and parity */
-- switch (cflag & CSIZE) {
-- case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break;
-- case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break;
-- case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break;
-- default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
-- }
-- if (cflag & CSTOPB) {
-- lcr_h |= AMBA_UARTLCR_H_STP2;
-- bits ++;
-- }
-- if (cflag & PARENB) {
-- lcr_h |= AMBA_UARTLCR_H_PEN;
-- bits++;
-- if (!(cflag & PARODD))
-- lcr_h |= AMBA_UARTLCR_H_EPS;
-- }
-- if (info->port->fifosize > 1)
-- lcr_h |= AMBA_UARTLCR_H_FEN;
--
-- do {
-- /* Determine divisor based on baud rate */
-- baud = tty_get_baud_rate(info->tty);
-- if (!baud)
-- baud = 9600;
--
-- if (baud == 38400 &&
-- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-- quot = info->state->custom_divisor;
-- else
-- quot = (info->port->uartclk / (16 * baud)) - 1;
--
-- if (!quot && old_termios) {
-- info->tty->termios->c_cflag &= ~CBAUD;
-- info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
-- old_termios = NULL;
-- }
-- } while (quot == 0 && old_termios);
--
-- /* As a last resort, if the quotient is zero, default to 9600 bps */
-- if (!quot)
-- quot = (info->port->uartclk / (16 * 9600)) - 1;
--
-- info->timeout = (info->port->fifosize * HZ * bits * quot) /
-- (info->port->uartclk / 16);
-- info->timeout += HZ/50; /* Add .02 seconds of slop */
--
-- if (cflag & CRTSCTS)
-- info->flags |= ASYNC_CTS_FLOW;
-- else
-- info->flags &= ~ASYNC_CTS_FLOW;
-- if (cflag & CLOCAL)
-- info->flags &= ~ASYNC_CHECK_CD;
-- else
-- info->flags |= ASYNC_CHECK_CD;
--
-- /*
-- * Set up parity check flag
-- */
--#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
--
-- info->read_status_mask = AMBA_UARTRSR_OE;
-- if (I_INPCK(info->tty))
-- info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-- if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-- info->read_status_mask |= AMBA_UARTRSR_BE;
--
-- /*
-- * Characters to ignore
-- */
-- info->ignore_status_mask = 0;
-- if (I_IGNPAR(info->tty))
-- info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-- if (I_IGNBRK(info->tty)) {
-- info->ignore_status_mask |= AMBA_UARTRSR_BE;
-- /*
-- * If we're ignoring parity and break indicators,
-- * ignore overruns to (for real raw support).
-- */
-- if (I_IGNPAR(info->tty))
-- info->ignore_status_mask |= AMBA_UARTRSR_OE;
-- }
--
-- /* first, disable everything */
-- save_flags(flags); cli();
-- old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
--
-- if ((info->flags & ASYNC_HARDPPS_CD) ||
-- (cflag & CRTSCTS) ||
-- !(cflag & CLOCAL))
-- old_cr |= AMBA_UARTCR_MSIE;
--
-- UART_PUT_CR(info->port, 0);
-- restore_flags(flags);
--
-- /* Set baud rate */
-- UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
-- UART_PUT_LCRL(info->port, (quot & 0xff));
--
-- /*
-- * ----------v----------v----------v----------v-----
-- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
-- * ----------^----------^----------^----------^-----
-- */
-- UART_PUT_LCRH(info->port, lcr_h);
-- UART_PUT_CR(info->port, old_cr);
--}
--
--static void ambauart_put_char(struct tty_struct *tty, u_char ch)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (!tty || !info->xmit.buf)
-- return;
--
-- save_flags(flags); cli();
-- if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
-- info->xmit.buf[info->xmit.head] = ch;
-- info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
-- }
-- restore_flags(flags);
--}
--
--static void ambauart_flush_chars(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (info->xmit.head == info->xmit.tail
-- || tty->stopped
-- || tty->hw_stopped
-- || !info->xmit.buf)
-- return;
--
-- save_flags(flags); cli();
-- ambauart_enable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--static int ambauart_write(struct tty_struct *tty, int from_user,
-- const u_char * buf, int count)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- int c, ret = 0;
--
-- if (!tty || !info->xmit.buf || !tmp_buf)
-- return 0;
--
-- save_flags(flags);
-- if (from_user) {
-- down(&tmp_buf_sem);
-- while (1) {
-- int c1;
-- c = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (count < c)
-- c = count;
-- if (c <= 0)
-- break;
--
-- c -= copy_from_user(tmp_buf, buf, c);
-- if (!c) {
-- if (!ret)
-- ret = -EFAULT;
-- break;
-- }
-- cli();
-- c1 = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (c1 < c)
-- c = c1;
-- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
-- info->xmit.head = (info->xmit.head + c) &
-- (AMBA_XMIT_SIZE - 1);
-- restore_flags(flags);
-- buf += c;
-- count -= c;
-- ret += c;
-- }
-- up(&tmp_buf_sem);
-- } else {
-- cli();
-- while (1) {
-- c = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (count < c)
-- c = count;
-- if (c <= 0)
-- break;
-- memcpy(info->xmit.buf + info->xmit.head, buf, c);
-- info->xmit.head = (info->xmit.head + c) &
-- (AMBA_XMIT_SIZE - 1);
-- buf += c;
-- count -= c;
-- ret += c;
-- }
-- restore_flags(flags);
-- }
-- if (info->xmit.head != info->xmit.tail
-- && !tty->stopped
-- && !tty->hw_stopped)
-- ambauart_enable_tx_interrupt(info);
-- return ret;
--}
--
--static int ambauart_write_room(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
--
-- return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
--}
--
--static int ambauart_chars_in_buffer(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
--
-- return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
--}
--
--static void ambauart_flush_buffer(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
--#if DEBUG
-- printk("ambauart_flush_buffer(%d) called\n",
-- MINOR(tty->device) - tty->driver.minor_start);
--#endif
-- save_flags(flags); cli();
-- info->xmit.head = info->xmit.tail = 0;
-- restore_flags(flags);
-- wake_up_interruptible(&tty->write_wait);
-- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-- tty->ldisc.write_wakeup)
-- (tty->ldisc.write_wakeup)(tty);
--}
--
--/*
-- * This function is used to send a high-priority XON/XOFF character to
-- * the device
-- */
--static void ambauart_send_xchar(struct tty_struct *tty, char ch)
--{
-- struct amba_info *info = tty->driver_data;
--
-- info->x_char = ch;
-- if (ch)
-- ambauart_enable_tx_interrupt(info);
--}
--
--static void ambauart_throttle(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (I_IXOFF(tty))
-- ambauart_send_xchar(tty, STOP_CHAR(tty));
--
-- if (tty->termios->c_cflag & CRTSCTS) {
-- save_flags(flags); cli();
-- info->mctrl &= ~TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--}
--
--static void ambauart_unthrottle(struct tty_struct *tty)
--{
-- struct amba_info *info = (struct amba_info *) tty->driver_data;
-- unsigned long flags;
--
-- if (I_IXOFF(tty)) {
-- if (info->x_char)
-- info->x_char = 0;
-- else
-- ambauart_send_xchar(tty, START_CHAR(tty));
-- }
--
-- if (tty->termios->c_cflag & CRTSCTS) {
-- save_flags(flags); cli();
-- info->mctrl |= TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--}
--
--static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
--{
-- struct amba_state *state = info->state;
-- struct amba_port *port = info->port;
-- struct serial_struct tmp;
--
-- memset(&tmp, 0, sizeof(tmp));
-- tmp.type = 0;
-- tmp.line = state->line;
-- tmp.port = port->uart_base;
-- if (HIGH_BITS_OFFSET)
-- tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
-- tmp.irq = port->irq;
-- tmp.flags = 0;
-- tmp.xmit_fifo_size = port->fifosize;
-- tmp.baud_base = port->uartclk / 16;
-- tmp.close_delay = state->close_delay;
-- tmp.closing_wait = state->closing_wait;
-- tmp.custom_divisor = state->custom_divisor;
--
-- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-- return -EFAULT;
-- return 0;
--}
--
--static int set_serial_info(struct amba_info *info,
-- struct serial_struct *newinfo)
--{
-- struct serial_struct new_serial;
-- struct amba_state *state, old_state;
-- struct amba_port *port;
-- unsigned long new_port;
-- unsigned int i, change_irq, change_port;
-- int retval = 0;
--
-- if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-- return -EFAULT;
--
-- state = info->state;
-- old_state = *state;
-- port = info->port;
--
-- new_port = new_serial.port;
-- if (HIGH_BITS_OFFSET)
-- new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
--
-- change_irq = new_serial.irq != port->irq;
-- change_port = new_port != port->uart_base;
--
-- if (!capable(CAP_SYS_ADMIN)) {
-- if (change_irq || change_port ||
-- (new_serial.baud_base != port->uartclk / 16) ||
-- (new_serial.close_delay != state->close_delay) ||
-- (new_serial.xmit_fifo_size != port->fifosize) ||
-- ((new_serial.flags & ~ASYNC_USR_MASK) !=
-- (state->flags & ~ASYNC_USR_MASK)))
-- return -EPERM;
-- state->flags = ((state->flags & ~ASYNC_USR_MASK) |
-- (new_serial.flags & ASYNC_USR_MASK));
-- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-- (new_serial.flags & ASYNC_USR_MASK));
-- state->custom_divisor = new_serial.custom_divisor;
-- goto check_and_exit;
-- }
--
-- if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-- (new_serial.baud_base < 9600))
-- return -EINVAL;
--
-- if (new_serial.type && change_port) {
-- for (i = 0; i < SERIAL_AMBA_NR; i++)
-- if ((port != amba_ports + i) &&
-- amba_ports[i].uart_base != new_port)
-- return -EADDRINUSE;
-- }
--
-- if ((change_port || change_irq) && (state->count > 1))
-- return -EBUSY;
--
-- /*
-- * OK, past this point, all the error checking has been done.
-- * At this point, we start making changes.....
-- */
-- port->uartclk = new_serial.baud_base * 16;
-- state->flags = ((state->flags & ~ASYNC_FLAGS) |
-- (new_serial.flags & ASYNC_FLAGS));
-- info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
-- (info->flags & ASYNC_INTERNAL_FLAGS));
-- state->custom_divisor = new_serial.custom_divisor;
-- state->close_delay = new_serial.close_delay * HZ / 100;
-- state->closing_wait = new_serial.closing_wait * HZ / 100;
-- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-- port->fifosize = new_serial.xmit_fifo_size;
--
-- if (change_port || change_irq) {
-- /*
-- * We need to shutdown the serial port at the old
-- * port/irq combination.
-- */
-- ambauart_shutdown(info);
-- port->irq = new_serial.irq;
-- port->uart_base = new_port;
-- }
--
--check_and_exit:
-- if (!port->uart_base)
-- return 0;
-- if (info->flags & ASYNC_INITIALIZED) {
-- if ((old_state.flags & ASYNC_SPD_MASK) !=
-- (state->flags & ASYNC_SPD_MASK) ||
-- (old_state.custom_divisor != state->custom_divisor)) {
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-- info->tty->alt_speed = 57600;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-- info->tty->alt_speed = 115200;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-- info->tty->alt_speed = 230400;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-- info->tty->alt_speed = 460800;
-- ambauart_change_speed(info, NULL);
-- }
-- } else
-- retval = ambauart_startup(info);
-- return retval;
--}
--
--
--/*
-- * get_lsr_info - get line status register info
-- */
--static int get_lsr_info(struct amba_info *info, unsigned int *value)
--{
-- unsigned int result, status;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- status = UART_GET_FR(info->port);
-- restore_flags(flags);
-- result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
--
-- /*
-- * If we're about to load something into the transmit
-- * register, we'll pretend the transmitter isn't empty to
-- * avoid a race condition (depending on when the transmit
-- * interrupt happens).
-- */
-- if (info->x_char ||
-- ((CIRC_CNT(info->xmit.head, info->xmit.tail,
-- AMBA_XMIT_SIZE) > 0) &&
-- !info->tty->stopped && !info->tty->hw_stopped))
-- result &= TIOCSER_TEMT;
--
-- return put_user(result, value);
--}
--
--static int get_modem_info(struct amba_info *info, unsigned int *value)
--{
-- unsigned int result = info->mctrl;
-- unsigned int status;
--
-- status = UART_GET_FR(info->port);
-- if (status & AMBA_UARTFR_DCD)
-- result |= TIOCM_CAR;
-- if (status & AMBA_UARTFR_DSR)
-- result |= TIOCM_DSR;
-- if (status & AMBA_UARTFR_CTS)
-- result |= TIOCM_CTS;
--
-- return put_user(result, value);
--}
--
--static int set_modem_info(struct amba_info *info, unsigned int cmd,
-- unsigned int *value)
--{
-- unsigned int arg, old;
-- unsigned long flags;
--
-- if (get_user(arg, value))
-- return -EFAULT;
--
-- old = info->mctrl;
-- switch (cmd) {
-- case TIOCMBIS:
-- info->mctrl |= arg;
-- break;
--
-- case TIOCMBIC:
-- info->mctrl &= ~arg;
-- break;
--
-- case TIOCMSET:
-- info->mctrl = arg;
-- break;
--
-- default:
-- return -EINVAL;
-- }
-- save_flags(flags); cli();
-- if (old != info->mctrl)
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- return 0;
--}
--
--static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- unsigned int lcr_h;
--
-- save_flags(flags); cli();
-- lcr_h = UART_GET_LCRH(info->port);
-- if (break_state == -1)
-- lcr_h |= AMBA_UARTLCR_H_BRK;
-- else
-- lcr_h &= ~AMBA_UARTLCR_H_BRK;
-- UART_PUT_LCRH(info->port, lcr_h);
-- restore_flags(flags);
--}
--
--static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
-- unsigned int cmd, unsigned long arg)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_icount cprev, cnow;
-- struct serial_icounter_struct icount;
-- unsigned long flags;
--
-- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-- if (tty->flags & (1 << TTY_IO_ERROR))
-- return -EIO;
-- }
--
-- switch (cmd) {
-- case TIOCMGET:
-- return get_modem_info(info, (unsigned int *)arg);
-- case TIOCMBIS:
-- case TIOCMBIC:
-- case TIOCMSET:
-- return set_modem_info(info, cmd, (unsigned int *)arg);
-- case TIOCGSERIAL:
-- return get_serial_info(info,
-- (struct serial_struct *)arg);
-- case TIOCSSERIAL:
-- return set_serial_info(info,
-- (struct serial_struct *)arg);
-- case TIOCSERGETLSR: /* Get line status register */
-- return get_lsr_info(info, (unsigned int *)arg);
-- /*
-- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-- * - mask passed in arg for lines of interest
-- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-- * Caller should use TIOCGICOUNT to see which one it was
-- */
-- case TIOCMIWAIT:
-- save_flags(flags); cli();
-- /* note the counters on entry */
-- cprev = info->state->icount;
-- /* Force modem status interrupts on */
-- UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
-- restore_flags(flags);
-- while (1) {
-- interruptible_sleep_on(&info->delta_msr_wait);
-- /* see if a signal did it */
-- if (signal_pending(current))
-- return -ERESTARTSYS;
-- save_flags(flags); cli();
-- cnow = info->state->icount; /* atomic copy */
-- restore_flags(flags);
-- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-- return -EIO; /* no change => error */
-- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-- return 0;
-- }
-- cprev = cnow;
-- }
-- /* NOTREACHED */
--
-- /*
-- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-- * Return: write counters to the user passed counter struct
-- * NB: both 1->0 and 0->1 transitions are counted except for
-- * RI where only 0->1 is counted.
-- */
-- case TIOCGICOUNT:
-- save_flags(flags); cli();
-- cnow = info->state->icount;
-- restore_flags(flags);
-- icount.cts = cnow.cts;
-- icount.dsr = cnow.dsr;
-- icount.rng = cnow.rng;
-- icount.dcd = cnow.dcd;
-- icount.rx = cnow.rx;
-- icount.tx = cnow.tx;
-- icount.frame = cnow.frame;
-- icount.overrun = cnow.overrun;
-- icount.parity = cnow.parity;
-- icount.brk = cnow.brk;
-- icount.buf_overrun = cnow.buf_overrun;
--
-- return copy_to_user((void *)arg, &icount, sizeof(icount))
-- ? -EFAULT : 0;
--
-- default:
-- return -ENOIOCTLCMD;
-- }
-- return 0;
--}
--
--static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- unsigned int cflag = tty->termios->c_cflag;
--
-- if ((cflag ^ old_termios->c_cflag) == 0 &&
-- RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
-- return;
--
-- ambauart_change_speed(info, old_termios);
--
-- /* Handle transition to B0 status */
-- if ((old_termios->c_cflag & CBAUD) &&
-- !(cflag & CBAUD)) {
-- save_flags(flags); cli();
-- info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--
-- /* Handle transition away from B0 status */
-- if (!(old_termios->c_cflag & CBAUD) &&
-- (cflag & CBAUD)) {
-- save_flags(flags); cli();
-- info->mctrl |= TIOCM_DTR;
-- if (!(cflag & CRTSCTS) ||
-- !test_bit(TTY_THROTTLED, &tty->flags))
-- info->mctrl |= TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--
-- /* Handle turning off CRTSCTS */
-- if ((old_termios->c_cflag & CRTSCTS) &&
-- !(cflag & CRTSCTS)) {
-- tty->hw_stopped = 0;
-- ambauart_start(tty);
-- }
--
--#if 0
-- /*
-- * No need to wake up processes in open wait, since they
-- * sample the CLOCAL flag once, and don't recheck it.
-- * XXX It's not clear whether the current behavior is correct
-- * or not. Hence, this may change.....
-- */
-- if (!(old_termios->c_cflag & CLOCAL) &&
-- (tty->termios->c_cflag & CLOCAL))
-- wake_up_interruptible(&info->open_wait);
--#endif
--}
--
--static void ambauart_close(struct tty_struct *tty, struct file *filp)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_state *state;
-- unsigned long flags;
--
-- if (!info)
-- return;
--
-- state = info->state;
--
--#if DEBUG
-- printk("ambauart_close() called\n");
--#endif
--
-- save_flags(flags); cli();
--
-- if (tty_hung_up_p(filp)) {
-- MOD_DEC_USE_COUNT;
-- restore_flags(flags);
-- return;
-- }
--
-- if ((tty->count == 1) && (state->count != 1)) {
-- /*
-- * Uh, oh. tty->count is 1, which means that the tty
-- * structure will be freed. state->count should always
-- * be one in these conditions. If it's greater than
-- * one, we've got real problems, since it means the
-- * serial port won't be shutdown.
-- */
-- printk("ambauart_close: bad serial port count; tty->count is 1, "
-- "state->count is %d\n", state->count);
-- state->count = 1;
-- }
-- if (--state->count < 0) {
-- printk("rs_close: bad serial port count for %s%d: %d\n",
-- tty->driver.name, info->state->line, state->count);
-- state->count = 0;
-- }
-- if (state->count) {
-- MOD_DEC_USE_COUNT;
-- restore_flags(flags);
-- return;
-- }
-- info->flags |= ASYNC_CLOSING;
-- restore_flags(flags);
-- /*
-- * Save the termios structure, since this port may have
-- * separate termios for callout and dialin.
-- */
-- if (info->flags & ASYNC_NORMAL_ACTIVE)
-- info->state->normal_termios = *tty->termios;
-- if (info->flags & ASYNC_CALLOUT_ACTIVE)
-- info->state->callout_termios = *tty->termios;
-- /*
-- * Now we wait for the transmit buffer to clear; and we notify
-- * the line discipline to only process XON/XOFF characters.
-- */
-- tty->closing = 1;
-- if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-- tty_wait_until_sent(tty, info->state->closing_wait);
-- /*
-- * At this point, we stop accepting input. To do this, we
-- * disable the receive line status interrupts.
-- */
-- if (info->flags & ASYNC_INITIALIZED) {
-- ambauart_disable_rx_interrupt(info);
-- /*
-- * Before we drop DTR, make sure the UART transmitter
-- * has completely drained; this is especially
-- * important if there is a transmit FIFO!
-- */
-- ambauart_wait_until_sent(tty, info->timeout);
-- }
-- ambauart_shutdown(info);
-- if (tty->driver.flush_buffer)
-- tty->driver.flush_buffer(tty);
-- if (tty->ldisc.flush_buffer)
-- tty->ldisc.flush_buffer(tty);
-- tty->closing = 0;
-- info->event = 0;
-- info->tty = NULL;
-- if (info->blocked_open) {
-- if (info->state->close_delay) {
-- set_current_state(TASK_INTERRUPTIBLE);
-- schedule_timeout(info->state->close_delay);
-- }
-- wake_up_interruptible(&info->open_wait);
-- }
-- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
-- ASYNC_CLOSING);
-- wake_up_interruptible(&info->close_wait);
-- MOD_DEC_USE_COUNT;
--}
--
--static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
--{
-- struct amba_info *info = (struct amba_info *) tty->driver_data;
-- unsigned long char_time, expire;
-- unsigned int status;
--
-- if (info->port->fifosize == 0)
-- return;
--
-- /*
-- * Set the check interval to be 1/5 of the estimated time to
-- * send a single character, and make it at least 1. The check
-- * interval should also be less than the timeout.
-- *
-- * Note: we have to use pretty tight timings here to satisfy
-- * the NIST-PCTS.
-- */
-- char_time = (info->timeout - HZ/50) / info->port->fifosize;
-- char_time = char_time / 5;
-- if (char_time == 0)
-- char_time = 1;
-- if (timeout && timeout < char_time)
-- char_time = timeout;
-- /*
-- * If the transmitter hasn't cleared in twice the approximate
-- * amount of time to send the entire FIFO, it probably won't
-- * ever clear. This assumes the UART isn't doing flow
-- * control, which is currently the case. Hence, if it ever
-- * takes longer than info->timeout, this is probably due to a
-- * UART bug of some kind. So, we clamp the timeout parameter at
-- * 2*info->timeout.
-- */
-- if (!timeout || timeout > 2 * info->timeout)
-- timeout = 2 * info->timeout;
--
-- expire = jiffies + timeout;
--#if DEBUG
-- printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
-- MINOR(tty->device) - tty->driver.minor_start, jiffies,
-- expire);
--#endif
-- while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
-- set_current_state(TASK_INTERRUPTIBLE);
-- schedule_timeout(char_time);
-- if (signal_pending(current))
-- break;
-- if (timeout && time_after(jiffies, expire))
-- break;
-- status = UART_GET_FR(info->port);
-- }
-- set_current_state(TASK_RUNNING);
--}
--
--static void ambauart_hangup(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_state *state = info->state;
--
-- ambauart_flush_buffer(tty);
-- if (info->flags & ASYNC_CLOSING)
-- return;
-- ambauart_shutdown(info);
-- info->event = 0;
-- state->count = 0;
-- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
-- info->tty = NULL;
-- wake_up_interruptible(&info->open_wait);
--}
--
--static int block_til_ready(struct tty_struct *tty, struct file *filp,
-- struct amba_info *info)
--{
-- DECLARE_WAITQUEUE(wait, current);
-- struct amba_state *state = info->state;
-- unsigned long flags;
-- int do_clocal = 0, extra_count = 0, retval;
--
-- /*
-- * If the device is in the middle of being closed, then block
-- * until it's done, and then try again.
-- */
-- if (tty_hung_up_p(filp) ||
-- (info->flags & ASYNC_CLOSING)) {
-- if (info->flags & ASYNC_CLOSING)
-- interruptible_sleep_on(&info->close_wait);
-- return (info->flags & ASYNC_HUP_NOTIFY) ?
-- -EAGAIN : -ERESTARTSYS;
-- }
--
-- /*
-- * If this is a callout device, then just make sure the normal
-- * device isn't being used.
-- */
-- if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-- if (info->flags & ASYNC_NORMAL_ACTIVE)
-- return -EBUSY;
-- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_SESSION_LOCKOUT) &&
-- (info->session != current->session))
-- return -EBUSY;
-- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_PGRP_LOCKOUT) &&
-- (info->pgrp != current->pgrp))
-- return -EBUSY;
-- info->flags |= ASYNC_CALLOUT_ACTIVE;
-- return 0;
-- }
--
-- /*
-- * If non-blocking mode is set, or the port is not enabled,
-- * then make the check up front and then exit.
-- */
-- if ((filp->f_flags & O_NONBLOCK) ||
-- (tty->flags & (1 << TTY_IO_ERROR))) {
-- if (info->flags & ASYNC_CALLOUT_ACTIVE)
-- return -EBUSY;
-- info->flags |= ASYNC_NORMAL_ACTIVE;
-- return 0;
-- }
--
-- if (info->flags & ASYNC_CALLOUT_ACTIVE) {
-- if (state->normal_termios.c_cflag & CLOCAL)
-- do_clocal = 1;
-- } else {
-- if (tty->termios->c_cflag & CLOCAL)
-- do_clocal = 1;
-- }
--
-- /*
-- * Block waiting for the carrier detect and the line to become
-- * free (i.e., not in use by the callout). While we are in
-- * this loop, state->count is dropped by one, so that
-- * rs_close() knows when to free things. We restore it upon
-- * exit, either normal or abnormal.
-- */
-- retval = 0;
-- add_wait_queue(&info->open_wait, &wait);
-- save_flags(flags); cli();
-- if (!tty_hung_up_p(filp)) {
-- extra_count = 1;
-- state->count--;
-- }
-- restore_flags(flags);
-- info->blocked_open++;
-- while (1) {
-- save_flags(flags); cli();
-- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (tty->termios->c_cflag & CBAUD)) {
-- info->mctrl = TIOCM_DTR | TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- }
-- restore_flags(flags);
-- set_current_state(TASK_INTERRUPTIBLE);
-- if (tty_hung_up_p(filp) ||
-- !(info->flags & ASYNC_INITIALIZED)) {
-- if (info->flags & ASYNC_HUP_NOTIFY)
-- retval = -EAGAIN;
-- else
-- retval = -ERESTARTSYS;
-- break;
-- }
-- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- !(info->flags & ASYNC_CLOSING) &&
-- (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
-- break;
-- if (signal_pending(current)) {
-- retval = -ERESTARTSYS;
-- break;
-- }
-- schedule();
-- }
-- set_current_state(TASK_RUNNING);
-- remove_wait_queue(&info->open_wait, &wait);
-- if (extra_count)
-- state->count++;
-- info->blocked_open--;
-- if (retval)
-- return retval;
-- info->flags |= ASYNC_NORMAL_ACTIVE;
-- return 0;
--}
--
--static struct amba_info *ambauart_get(int line)
--{
-- struct amba_info *info;
-- struct amba_state *state = amba_state + line;
--
-- state->count++;
-- if (state->info)
-- return state->info;
-- info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
-- if (info) {
-- memset(info, 0, sizeof(struct amba_info));
-- init_waitqueue_head(&info->open_wait);
-- init_waitqueue_head(&info->close_wait);
-- init_waitqueue_head(&info->delta_msr_wait);
-- info->flags = state->flags;
-- info->state = state;
-- info->port = amba_ports + line;
-- tasklet_init(&info->tlet, ambauart_tasklet_action,
-- (unsigned long)info);
-- }
-- if (state->info) {
-- kfree(info);
-- return state->info;
-- }
-- state->info = info;
-- return info;
--}
--
--static int ambauart_open(struct tty_struct *tty, struct file *filp)
--{
-- struct amba_info *info;
-- int retval, line = MINOR(tty->device) - tty->driver.minor_start;
--
--#if DEBUG
-- printk("ambauart_open(%d) called\n", line);
--#endif
--
-- // is this a line that we've got?
-- MOD_INC_USE_COUNT;
-- if (line >= SERIAL_AMBA_NR) {
-- MOD_DEC_USE_COUNT;
-- return -ENODEV;
-- }
--
-- info = ambauart_get(line);
-- if (!info)
-- return -ENOMEM;
--
-- tty->driver_data = info;
-- info->tty = tty;
-- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
--
-- /*
-- * Make sure we have the temporary buffer allocated
-- */
-- if (!tmp_buf) {
-- unsigned long page = get_zeroed_page(GFP_KERNEL);
-- if (tmp_buf)
-- free_page(page);
-- else if (!page) {
-- MOD_DEC_USE_COUNT;
-- return -ENOMEM;
-- }
-- tmp_buf = (u_char *)page;
-- }
--
-- /*
-- * If the port is in the middle of closing, bail out now.
-- */
-- if (tty_hung_up_p(filp) ||
-- (info->flags & ASYNC_CLOSING)) {
-- if (info->flags & ASYNC_CLOSING)
-- interruptible_sleep_on(&info->close_wait);
-- MOD_DEC_USE_COUNT;
-- return -EAGAIN;
-- }
--
-- /*
-- * Start up the serial port
-- */
-- retval = ambauart_startup(info);
-- if (retval) {
-- MOD_DEC_USE_COUNT;
-- return retval;
-- }
--
-- retval = block_til_ready(tty, filp, info);
-- if (retval) {
-- MOD_DEC_USE_COUNT;
-- return retval;
-- }
--
-- if ((info->state->count == 1) &&
-- (info->flags & ASYNC_SPLIT_TERMIOS)) {
-- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-- *tty->termios = info->state->normal_termios;
-- else
-- *tty->termios = info->state->callout_termios;
-- }
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-- if (ambauart_cons.cflag && ambauart_cons.index == line) {
-- tty->termios->c_cflag = ambauart_cons.cflag;
-- ambauart_cons.cflag = 0;
-- }
--#endif
-- ambauart_change_speed(info, NULL);
-- info->session = current->session;
-- info->pgrp = current->pgrp;
-- return 0;
--}
--
--int __init ambauart_init(void)
--{
-- int i;
--
-- ambanormal_driver.magic = TTY_DRIVER_MAGIC;
-- ambanormal_driver.driver_name = "serial_amba";
-- ambanormal_driver.name = SERIAL_AMBA_NAME;
-- ambanormal_driver.major = SERIAL_AMBA_MAJOR;
-- ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
-- ambanormal_driver.num = SERIAL_AMBA_NR;
-- ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
-- ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
-- ambanormal_driver.init_termios = tty_std_termios;
-- ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
-- ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-- ambanormal_driver.refcount = &ambauart_refcount;
-- ambanormal_driver.table = ambauart_table;
-- ambanormal_driver.termios = ambauart_termios;
-- ambanormal_driver.termios_locked = ambauart_termios_locked;
--
-- ambanormal_driver.open = ambauart_open;
-- ambanormal_driver.close = ambauart_close;
-- ambanormal_driver.write = ambauart_write;
-- ambanormal_driver.put_char = ambauart_put_char;
-- ambanormal_driver.flush_chars = ambauart_flush_chars;
-- ambanormal_driver.write_room = ambauart_write_room;
-- ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
-- ambanormal_driver.flush_buffer = ambauart_flush_buffer;
-- ambanormal_driver.ioctl = ambauart_ioctl;
-- ambanormal_driver.throttle = ambauart_throttle;
-- ambanormal_driver.unthrottle = ambauart_unthrottle;
-- ambanormal_driver.send_xchar = ambauart_send_xchar;
-- ambanormal_driver.set_termios = ambauart_set_termios;
-- ambanormal_driver.stop = ambauart_stop;
-- ambanormal_driver.start = ambauart_start;
-- ambanormal_driver.hangup = ambauart_hangup;
-- ambanormal_driver.break_ctl = ambauart_break_ctl;
-- ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
-- ambanormal_driver.read_proc = NULL;
--
-- /*
-- * The callout device is just like the normal device except for
-- * the major number and the subtype code.
-- */
-- ambacallout_driver = ambanormal_driver;
-- ambacallout_driver.name = CALLOUT_AMBA_NAME;
-- ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
-- ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
-- ambacallout_driver.read_proc = NULL;
-- ambacallout_driver.proc_entry = NULL;
--
-- if (tty_register_driver(&ambanormal_driver))
-- panic("Couldn't register AMBA serial driver\n");
-- if (tty_register_driver(&ambacallout_driver))
-- panic("Couldn't register AMBA callout driver\n");
--
-- for (i = 0; i < SERIAL_AMBA_NR; i++) {
-- struct amba_state *state = amba_state + i;
-- state->line = i;
-- state->close_delay = 5 * HZ / 10;
-- state->closing_wait = 30 * HZ;
-- state->callout_termios = ambacallout_driver.init_termios;
-- state->normal_termios = ambanormal_driver.init_termios;
-- }
--
-- return 0;
--}
--
--__initcall(ambauart_init);
--
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
--/************** console driver *****************/
--
--/*
-- * This code is currently never used; console->read is never called.
-- * Therefore, although we have an implementation, we don't use it.
-- * FIXME: the "const char *s" should be fixed to "char *s" some day.
-- * (when the definition in include/linux/console.h is also fixed)
-- */
--#ifdef used_and_not_const_char_pointer
--static int ambauart_console_read(struct console *co, const char *s, u_int count)
--{
-- struct amba_port *port = &amba_ports[co->index];
-- unsigned int status;
-- char *w;
-- int c;
--#if DEBUG
-- printk("ambauart_console_read() called\n");
--#endif
--
-- c = 0;
-- w = s;
-- while (c < count) {
-- status = UART_GET_FR(port);
-- if (UART_RX_DATA(status)) {
-- *w++ = UART_GET_CHAR(port);
-- c++;
-- } else {
-- // nothing more to get, return
-- return c;
-- }
-- }
-- // return the count
-- return c;
--}
--#endif
--
--/*
-- * Print a string to the serial port trying not to disturb
-- * any possible real use of the port...
-- *
-- * The console must be locked when we get here.
-- */
--static void ambauart_console_write(struct console *co, const char *s, u_int count)
--{
-- struct amba_port *port = &amba_ports[co->index];
-- unsigned int status, old_cr;
-- int i;
--
-- /*
-- * First save the CR then disable the interrupts
-- */
-- old_cr = UART_GET_CR(port);
-- UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
--
-- /*
-- * Now, do each character
-- */
-- for (i = 0; i < count; i++) {
-- do {
-- status = UART_GET_FR(port);
-- } while (!UART_TX_READY(status));
-- UART_PUT_CHAR(port, s[i]);
-- if (s[i] == '\n') {
-- do {
-- status = UART_GET_FR(port);
-- } while (!UART_TX_READY(status));
-- UART_PUT_CHAR(port, '\r');
-- }
-- }
--
-- /*
-- * Finally, wait for transmitter to become empty
-- * and restore the TCR
-- */
-- do {
-- status = UART_GET_FR(port);
-- } while (status & AMBA_UARTFR_BUSY);
-- UART_PUT_CR(port, old_cr);
--}
--
--static kdev_t ambauart_console_device(struct console *c)
--{
-- return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
--}
--
--static int __init ambauart_console_setup(struct console *co, char *options)
--{
-- struct amba_port *port;
-- int baud = 38400;
-- int bits = 8;
-- int parity = 'n';
-- u_int cflag = CREAD | HUPCL | CLOCAL;
-- u_int lcr_h, quot;
--
-- if (co->index >= SERIAL_AMBA_NR)
-- co->index = 0;
--
-- port = &amba_ports[co->index];
--
-- if (options) {
-- char *s = options;
-- baud = simple_strtoul(s, NULL, 10);
-- while (*s >= '0' && *s <= '9')
-- s++;
-- if (*s) parity = *s++;
-- if (*s) bits = *s - '0';
-- }
--
-- /*
-- * Now construct a cflag setting.
-- */
-- switch (baud) {
-- case 1200: cflag |= B1200; break;
-- case 2400: cflag |= B2400; break;
-- case 4800: cflag |= B4800; break;
-- default: cflag |= B9600; baud = 9600; break;
-- case 19200: cflag |= B19200; break;
-- case 38400: cflag |= B38400; break;
-- case 57600: cflag |= B57600; break;
-- case 115200: cflag |= B115200; break;
-- }
-- switch (bits) {
-- case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break;
-- default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break;
-- }
-- switch (parity) {
-- case 'o':
-- case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
-- case 'e':
-- case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
-- AMBA_UARTLCR_H_EPS; break;
-- }
--
-- co->cflag = cflag;
--
-- if (port->fifosize > 1)
-- lcr_h |= AMBA_UARTLCR_H_FEN;
--
-- quot = (port->uartclk / (16 * baud)) - 1;
--
-- UART_PUT_LCRL(port, (quot & 0xff));
-- UART_PUT_LCRM(port, (quot >> 8));
-- UART_PUT_LCRH(port, lcr_h);
--
-- /* we will enable the port as we need it */
-- UART_PUT_CR(port, 0);
--
-- return 0;
--}
--
--static struct console ambauart_cons =
--{
-- name: SERIAL_AMBA_NAME,
-- write: ambauart_console_write,
--#ifdef used_and_not_const_char_pointer
-- read: ambauart_console_read,
--#endif
-- device: ambauart_console_device,
-- setup: ambauart_console_setup,
-- flags: CON_PRINTBUFFER,
-- index: -1,
--};
--
--void __init ambauart_console_init(void)
--{
-- register_console(&ambauart_cons);
--}
--
--#endif /* CONFIG_SERIAL_AMBA_CONSOLE */
--
--MODULE_LICENSE("GPL");
--EXPORT_NO_SYMBOLS;
---- linux-2.4.25/drivers/char/tty_io.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/char/tty_io.c 2004-03-31 17:15:09.000000000 +0200
-@@ -19,7 +19,7 @@
- * Also restructured routines so that there is more of a separation
- * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
- * the low-level tty routines (serial.c, pty.c, console.c). This
-- * makes for cleaner and more compact code. -TYT, 9/17/92
-+ * makes for cleaner and more compact code. -TYT, 9/17/92
- *
- * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
- * which can be dynamically activated and de-activated by the line
-@@ -41,7 +41,7 @@
- *
- * New TIOCLINUX variants added.
- * -- mj@k332.feld.cvut.cz, 19-Nov-95
-- *
-+ *
- * Restrict vt switching via ioctl()
- * -- grif@cs.ucr.edu, 5-Dec-95
- *
-@@ -151,8 +151,7 @@
- extern void tty3215_init(void);
- extern void tub3270_con_init(void);
- extern void tub3270_init(void);
--extern void rs285_console_init(void);
--extern void sa1100_rs_console_init(void);
-+extern void uart_console_init(void);
- extern void sgi_serial_console_init(void);
- extern void sn_sal_serial_console_init(void);
- extern void sci_console_init(void);
-@@ -164,6 +163,7 @@
- extern void txx9_serial_console_init(void);
- extern void sb1250_serial_console_init(void);
- extern void arc_console_init(void);
-+extern void rs285_console_init(void);
- extern int hvc_console_init(void);
-
- #ifndef MIN
-@@ -201,7 +201,7 @@
- else
- sprintf(buf, name,
- idx + tty->driver.name_base);
--
-+
- return buf;
- }
-
-@@ -239,7 +239,7 @@
- #ifdef CHECK_TTY_COUNT
- struct list_head *p;
- int count = 0;
--
-+
- file_list_lock();
- for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
- if(list_entry(p, struct file, f_list)->private_data == tty)
-@@ -255,7 +255,7 @@
- "!= #fd's(%d) in %s\n",
- kdevname(tty->device), tty->count, count, routine);
- return count;
-- }
-+ }
- #endif
- return 0;
- }
-@@ -264,14 +264,14 @@
- {
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
--
-+
- if (new_ldisc) {
- ldiscs[disc] = *new_ldisc;
- ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
- ldiscs[disc].num = disc;
- } else
- memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
--
-+
- return 0;
- }
-
-@@ -301,7 +301,7 @@
- o_ldisc = tty->ldisc;
-
- tty_wait_until_sent(tty, 0);
--
-+
- /* Shutdown the current discipline. */
- if (tty->ldisc.close)
- (tty->ldisc.close)(tty);
-@@ -339,7 +339,7 @@
- {
- int major, minor;
- struct tty_driver *p;
--
-+
- minor = MINOR(device);
- major = MAJOR(device);
-
-@@ -456,7 +456,7 @@
- redirect = NULL;
- }
- spin_unlock(&redirect_lock);
--
-+
- check_tty_count(tty, "do_tty_hangup");
- file_list_lock();
- for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
-@@ -473,7 +473,7 @@
- filp->f_op = &hung_up_tty_fops;
- }
- file_list_unlock();
--
-+
- /* FIXME! What are the locking issues here? This may me overdoing things.. */
- {
- unsigned long flags;
-@@ -510,7 +510,7 @@
- "error %d\n", -i);
- }
- }
--
-+
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if ((tty->session > 0) && (p->session == tty->session) &&
-@@ -550,7 +550,7 @@
- {
- #ifdef TTY_DEBUG_HANGUP
- char buf[64];
--
-+
- printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
- #endif
- schedule_task(&tty->tq_hangup);
-@@ -650,7 +650,7 @@
- wake_up_interruptible(&tty->write_wait);
- }
-
--static ssize_t tty_read(struct file * file, char * buf, size_t count,
-+static ssize_t tty_read(struct file * file, char * buf, size_t count,
- loff_t *ppos)
- {
- int i;
-@@ -707,7 +707,7 @@
- size_t count)
- {
- ssize_t ret = 0, written = 0;
--
-+
- if (file->f_flags & O_NONBLOCK) {
- if (down_trylock(&tty->atomic_write))
- return -EAGAIN;
-@@ -835,7 +835,7 @@
- struct tty_struct *tty, *o_tty;
- struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
-- struct tty_driver *driver;
-+ struct tty_driver *driver;
- int retval=0;
- int idx;
-
-@@ -845,7 +845,7 @@
-
- idx = MINOR(device) - driver->minor_start;
-
-- /*
-+ /*
- * Check whether we need to acquire the tty semaphore to avoid
- * race conditions. For now, play it safe.
- */
-@@ -859,7 +859,7 @@
- * First time open is complex, especially for PTY devices.
- * This code guarantees that either everything succeeds and the
- * TTY is ready for operation, or else the table slots are vacated
-- * and the allocated memory released. (Except that the termios
-+ * and the allocated memory released. (Except that the termios
- * and locked termios may be retained.)
- */
-
-@@ -938,13 +938,13 @@
- o_tty->link = tty;
- }
-
-- /*
-+ /*
- * All structures have been allocated, so now we install them.
-- * Failures after this point use release_mem to clean up, so
-+ * Failures after this point use release_mem to clean up, so
- * there's no need to null out the local pointers.
- */
- driver->table[idx] = tty;
--
-+
- if (!*tp_loc)
- *tp_loc = tp;
- if (!*ltp_loc)
-@@ -954,7 +954,7 @@
- (*driver->refcount)++;
- tty->count++;
-
-- /*
-+ /*
- * Structures all installed ... call the ldisc open routines.
- * If we fail here just call release_mem to clean up. No need
- * to decrement the use counts, as release_mem doesn't care.
-@@ -988,7 +988,7 @@
- if (driver->type == TTY_DRIVER_TYPE_PTY &&
- driver->subtype == PTY_TYPE_MASTER) {
- /*
-- * special case for PTY masters: only one open permitted,
-+ * special case for PTY masters: only one open permitted,
- * and the slave side open count is incremented as well.
- */
- if (tty->count) {
-@@ -1002,7 +1002,7 @@
-
- success:
- *ret_tty = tty;
--
-+
- /* All paths come through here to release the semaphore */
- end_init:
- up_tty_sem(idx);
-@@ -1080,7 +1080,7 @@
- int pty_master, tty_closing, o_tty_closing, do_sleep;
- int idx;
- char buf[64];
--
-+
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
- return;
-@@ -1138,7 +1138,7 @@
- idx, kdevname(tty->device));
- return;
- }
-- if (o_tty->termios_locked !=
-+ if (o_tty->termios_locked !=
- tty->driver.other->termios_locked[idx]) {
- printk(KERN_DEBUG "release_dev: other->termios_locked["
- "%d] not o_termios_locked for (%s)\n",
-@@ -1204,11 +1204,11 @@
- printk(KERN_WARNING "release_dev: %s: read/write wait queue "
- "active!\n", tty_name(tty, buf));
- schedule();
-- }
-+ }
-
- /*
-- * The closing flags are now consistent with the open counts on
-- * both sides, and we've completed the last operation that could
-+ * The closing flags are now consistent with the open counts on
-+ * both sides, and we've completed the last operation that could
- * block, so it's safe to proceed with closing.
- */
- if (pty_master) {
-@@ -1266,7 +1266,7 @@
- /* check whether both sides are closing ... */
- if (!tty_closing || (o_tty && !o_tty_closing))
- return;
--
-+
- #ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "freeing tty structure...");
- #endif
-@@ -1284,14 +1284,14 @@
- (o_tty->ldisc.close)(o_tty);
- o_tty->ldisc = ldiscs[N_TTY];
- }
--
-+
- /*
-- * Make sure that the tty's task queue isn't activated.
-+ * Make sure that the tty's task queue isn't activated.
- */
- run_task_queue(&tq_timer);
- flush_scheduled_tasks();
-
-- /*
-+ /*
- * The release_mem function takes care of the details of clearing
- * the slots and preserving the termios structure.
- */
-@@ -1482,7 +1482,7 @@
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
- return 0;
--
-+
- retval = fasync_helper(fd, filp, on, &tty->fasync);
- if (retval <= 0)
- return retval;
-@@ -1697,7 +1697,7 @@
-
- static int tty_generic_brk(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
- {
-- if (cmd == TCSBRK && arg)
-+ if (cmd == TCSBRK && arg)
- {
- /* tcdrain case */
- int retval = tty_check_change(tty);
-@@ -1718,7 +1718,7 @@
- {
- struct tty_struct *tty, *real_tty;
- int retval;
--
-+
- tty = (struct tty_struct *)file->private_data;
- if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
- return -EINVAL;
-@@ -1738,7 +1738,7 @@
- if (tty->driver.ioctl)
- return tty->driver.ioctl(tty, file, cmd, arg);
- return -EINVAL;
--
-+
- /* These two ioctl's always return success; even if */
- /* the driver doesn't support them. */
- case TCSBRK:
-@@ -1761,7 +1761,7 @@
- case TIOCSBRK:
- case TIOCCBRK:
- case TCSBRK:
-- case TCSBRKP:
-+ case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
-@@ -1824,7 +1824,7 @@
- case TIOCSBRK: /* Turn break on, unconditionally */
- tty->driver.break_ctl(tty, -1);
- return 0;
--
-+
- case TIOCCBRK: /* Turn break off, unconditionally */
- tty->driver.break_ctl(tty, 0);
- return 0;
-@@ -1837,7 +1837,7 @@
- if (!arg)
- return send_break(tty, HZ/4);
- return 0;
-- case TCSBRKP: /* support for POSIX tcsendbreak() */
-+ case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
- }
- if (tty->driver.ioctl) {
-@@ -1859,7 +1859,7 @@
- * prevent trojan horses by killing all processes associated with this
- * tty when the user hits the "Secure Attention Key". Required for
- * super-paranoid applications --- see the Orange Book for more details.
-- *
-+ *
- * This code could be nicer; ideally it should send a HUP, wait a few
- * seconds, then send a INT, and then a KILL signal. But you then
- * have to coordinate with the init process, since all processes associated
-@@ -1883,7 +1883,7 @@
- int session;
- int i;
- struct file *filp;
--
-+
- if (!tty)
- return;
- session = tty->session;
-@@ -1968,7 +1968,7 @@
- count = tty->flip.count;
- tty->flip.count = 0;
- restore_flags(flags);
--
-+
- tty->ldisc.receive_buf(tty, cp, fp, count);
- }
-
-@@ -2000,7 +2000,7 @@
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~CBAUDEX;
-- if (i < 1 || i+15 >= n_baud_table)
-+ if (i < 1 || i+15 >= n_baud_table)
- tty->termios->c_cflag &= ~CBAUDEX;
- else
- i += 15;
-@@ -2013,7 +2013,7 @@
- }
- return(tty->alt_speed);
- }
--
-+
- return baud_table[i];
- }
-
-@@ -2079,7 +2079,7 @@
- mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- break;
- }
-- if ( (minor < driver->minor_start) ||
-+ if ( (minor < driver->minor_start) ||
- (minor >= driver->minor_start + driver->num) ) {
- printk(KERN_ERR "Attempt to register invalid minor number "
- "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
-@@ -2132,12 +2132,12 @@
-
- if (!driver->put_char)
- driver->put_char = tty_default_put_char;
--
-+
- driver->prev = 0;
- driver->next = tty_drivers;
- if (tty_drivers) tty_drivers->prev = driver;
- tty_drivers = driver;
--
-+
- if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
- for(i = 0; i < driver->num; i++)
- tty_register_devfs(driver, 0, driver->minor_start + i);
-@@ -2156,7 +2156,7 @@
- int i, found = 0;
- struct termios *tp;
- const char *othername = NULL;
--
-+
- if (*driver->refcount)
- return -EBUSY;
-
-@@ -2166,7 +2166,7 @@
- else if (p->major == driver->major)
- othername = p->name;
- }
--
-+
- if (!found)
- return -ENOENT;
-
-@@ -2181,7 +2181,7 @@
- driver->prev->next = driver->next;
- else
- tty_drivers = driver->next;
--
-+
- if (driver->next)
- driver->next->prev = driver->prev;
-
-@@ -2221,7 +2221,7 @@
- (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
-
- /*
-- * Set up the standard termios. Individual tty drivers may
-+ * Set up the standard termios. Individual tty drivers may
- * deviate from this; this is used as a template.
- */
- memset(&tty_std_termios, 0, sizeof(struct termios));
-@@ -2233,11 +2233,11 @@
- ECHOCTL | ECHOKE | IEXTEN;
-
- /*
-- * set up the console device so that later boot sequences can
-+ * set up the console device so that later boot sequences can
- * inform about problems etc..
- */
- #ifdef CONFIG_EARLY_PRINTK
-- disable_early_printk();
-+ disable_early_printk();
- #endif
- #ifdef CONFIG_HVC_CONSOLE
- hvc_console_init();
-@@ -2288,18 +2288,12 @@
- #ifdef CONFIG_STDIO_CONSOLE
- stdio_console_init();
- #endif
--#ifdef CONFIG_SERIAL_21285_CONSOLE
-- rs285_console_init();
--#endif
--#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-- sa1100_rs_console_init();
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+ uart_console_init();
- #endif
- #ifdef CONFIG_ARC_CONSOLE
- arc_console_init();
- #endif
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-- ambauart_console_init();
--#endif
- #ifdef CONFIG_SERIAL_TX3912_CONSOLE
- tx3912_console_init();
- #endif
-@@ -2315,6 +2309,9 @@
- #ifdef CONFIG_IP22_SERIAL
- sgi_serial_console_init();
- #endif
-+#ifdef CONFIG_SERIAL_21285_CONSOLE
-+ rs285_console_init();
-+#endif
- }
-
- static struct tty_driver dev_tty_driver, dev_syscons_driver;
-@@ -2347,7 +2344,7 @@
- dev_tty_driver.num = 1;
- dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
- dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
--
-+
- if (tty_register_driver(&dev_tty_driver))
- panic("Couldn't register /dev/tty driver\n");
-
-@@ -2363,7 +2360,7 @@
- panic("Couldn't register /dev/console driver\n");
-
- /* console calls tty_register_driver() before kmalloc() works.
-- * Thus, we can't devfs_register() then. Do so now, instead.
-+ * Thus, we can't devfs_register() then. Do so now, instead.
- */
- #ifdef CONFIG_VT
- con_init_devfs();
-@@ -2381,7 +2378,7 @@
- if (tty_register_driver(&dev_ptmx_driver))
- panic("Couldn't register /dev/ptmx driver\n");
- #endif
--
-+
- #ifdef CONFIG_VT
- dev_console_driver = dev_tty_driver;
- dev_console_driver.driver_name = "/dev/vc/0";
-@@ -2441,10 +2438,10 @@
- pty_init();
- #ifdef CONFIG_MOXA_SMARTIO
- mxser_init();
--#endif
-+#endif
- #ifdef CONFIG_MOXA_INTELLIO
- moxa_init();
--#endif
-+#endif
- #ifdef CONFIG_VT
- vcs_init();
- #endif
---- linux-2.4.25/drivers/char/wdt285.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
-+++ linux-2.4.25/drivers/char/wdt285.c 2004-03-31 17:15:09.000000000 +0200
-@@ -151,7 +151,7 @@
- if (get_user(new_margin, (int *)arg))
- return -EFAULT;
- /* Arbitrary, can't find the card's limits */
-- if ((new_marg < 0) || (new_margin > 60))
-+ if ((new_margin < 0) || (new_margin > 60))
- return -EINVAL;
- soft_margin = new_margin;
- watchdog_ping();
---- linux-2.4.25/drivers/char/wdt977.c~2.4.25-vrs2.patch 2002-11-29 00:53:12.000000000 +0100
-+++ linux-2.4.25/drivers/char/wdt977.c 2004-03-31 17:15:09.000000000 +0200
-@@ -27,6 +27,7 @@
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-
- #define WATCHDOG_MINOR 130
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/Kconfig 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,38 @@
-+config CPU_FREQ_PROC_INTF
-+ tristate "/proc/cpufreq interface (deprecated)"
-+ depends on CPU_FREQ && PROC_FS
-+ help
-+ This enables the /proc/cpufreq interface for controlling
-+ CPUFreq. Please note that it is recommended to use the sysfs
-+ interface instead (which is built automatically).
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say N.
-+
-+config CPU_FREQ_GOV_USERSPACE
-+ tristate "'userspace' governor for userspace frequency scaling"
-+ depends on CPU_FREQ
-+ help
-+ Enable this cpufreq governor when you either want to set the
-+ CPU frequency manually or when an userspace programm shall
-+ be able to set the CPU dynamically, like on LART
-+ ( http://www.lart.tudelft.nl/ )
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say Y.
-+
-+config CPU_FREQ_24_API
-+ bool "/proc/sys/cpu/ interface (2.4. / OLD)"
-+ depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
-+ help
-+ This enables the /proc/sys/cpu/ sysctl interface for controlling
-+ the CPUFreq,"userspace" governor. This is the same interface
-+ as known from the.4.-kernel patches for CPUFreq, and offers
-+ the same functionality as long as "userspace" is the
-+ selected governor for the specified CPU.
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say N.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,4 @@
-+#CPUfreq governors and cross-arch helpers
-+obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
-+obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o
-+obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/cpufreq.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,720 @@
-+/*
-+ * linux/kernel/cpufreq.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+
-+#include <asm/semaphore.h>
-+/**
-+ * The "cpufreq driver" - the arch- or hardware-dependend low
-+ * level driver of CPUFreq support, and its spinlock. This lock
-+ * also protects the cpufreq_cpu_data array.
-+ */
-+static struct cpufreq_driver *cpufreq_driver;
-+static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
-+static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED;
-+
-+/* internal prototype */
-+static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
-+
-+
-+/**
-+ * Two notifier lists: the "policy" list is involved in the
-+ * validation process for a new CPU frequency policy; the
-+ * "transition" list for kernel code that needs to handle
-+ * changes to devices when the CPU clock speed changes.
-+ * The mutex locks both lists.
-+ */
-+static struct notifier_block *cpufreq_policy_notifier_list;
-+static struct notifier_block *cpufreq_transition_notifier_list;
-+static DECLARE_RWSEM (cpufreq_notifier_rwsem);
-+
-+
-+static LIST_HEAD(cpufreq_governor_list);
-+static DECLARE_MUTEX (cpufreq_governor_sem);
-+
-+/*
-+ * backport info:
-+ * we don't have a kobj we can use for ref-counting, so use a
-+ * "unsigned int policy->use_count" and an "unload_sem" [idea from
-+ * Pat Mochel's struct driver unload_sem] for proper reference counting.
-+ */
-+
-+static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
-+{
-+ struct cpufreq_policy *data;
-+ unsigned long flags;
-+
-+ if (cpu >= NR_CPUS)
-+ goto err_out;
-+
-+ /* get the cpufreq driver */
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+
-+ if (!cpufreq_driver)
-+ goto err_out_unlock;
-+
-+ /* get the CPU */
-+ data = cpufreq_cpu_data[cpu];
-+
-+ if (!data)
-+ goto err_out_unlock;
-+
-+ if (!data->use_count)
-+ goto err_out_unlock;
-+
-+ data->use_count += 1;
-+
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ return data;
-+
-+ err_out_unlock:
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ err_out:
-+ return NULL;
-+}
-+
-+static void cpufreq_cpu_put(struct cpufreq_policy *data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ data->use_count -= 1;
-+ if (!data->use_count) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ up(&data->unload_sem);
-+ return;
-+ }
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+}
-+
-+/*********************************************************************
-+ * SYSFS INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_parse_governor - parse a governor string
-+ */
-+int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
-+ struct cpufreq_governor **governor)
-+{
-+ if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
-+ *policy = CPUFREQ_POLICY_PERFORMANCE;
-+ return 0;
-+ } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
-+ *policy = CPUFREQ_POLICY_POWERSAVE;
-+ return 0;
-+ } else {
-+ struct cpufreq_governor *t;
-+ down(&cpufreq_governor_sem);
-+ if (!cpufreq_driver || !cpufreq_driver->target)
-+ goto out;
-+ list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-+ if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
-+ *governor = t;
-+ *policy = CPUFREQ_POLICY_GOVERNOR;
-+ up(&cpufreq_governor_sem);
-+ return 0;
-+ }
-+ }
-+ out:
-+ up(&cpufreq_governor_sem);
-+ }
-+ return -EINVAL;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
-+
-+
-+/* backport info:
-+ * all the sysfs stuff is missing -- of course
-+ */
-+
-+/**
-+ * cpufreq_add_dev - add a CPU device
-+ *
-+ * Adds the cpufreq interface for a CPU device.
-+ */
-+static int cpufreq_add_dev (unsigned int cpu)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy new_policy;
-+ struct cpufreq_policy *policy;
-+ unsigned long flags;
-+
-+ policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
-+ if (!policy)
-+ return -ENOMEM;
-+ memset(policy, 0, sizeof(struct cpufreq_policy));
-+
-+ policy->cpu = cpu;
-+ policy->use_count = 1;
-+ init_MUTEX_LOCKED(&policy->lock);
-+ init_MUTEX_LOCKED(&policy->unload_sem);
-+
-+ /* call driver. From then on the cpufreq must be able
-+ * to accept all calls to ->verify and ->setpolicy for this CPU
-+ */
-+ ret = cpufreq_driver->init(policy);
-+ if (ret)
-+ goto err_out;
-+
-+ memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_cpu_data[cpu] = policy;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ up(&policy->lock);
-+
-+ /* set default policy */
-+ ret = cpufreq_set_policy(&new_policy);
-+ if (ret)
-+ goto err_out_unregister;
-+
-+ return 0;
-+
-+
-+ err_out_unregister:
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_cpu_data[cpu] = NULL;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ err_out:
-+ kfree(policy);
-+ return ret;
-+}
-+
-+
-+/**
-+ * cpufreq_remove_dev - remove a CPU device
-+ *
-+ * Removes the cpufreq interface for a CPU device.
-+ */
-+static int cpufreq_remove_dev (unsigned int cpu)
-+{
-+ unsigned long flags;
-+ struct cpufreq_policy *data;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ data = cpufreq_cpu_data[cpu];
-+ if (!data) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ return -EINVAL;
-+ }
-+ cpufreq_cpu_data[cpu] = NULL;
-+
-+ data->use_count -= 1;
-+ if (!data->use_count) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ up(&data->unload_sem);
-+ } else {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ /* this will sleep until data->use_count gets to zero */
-+ down(&data->unload_sem);
-+ up(&data->unload_sem);
-+ }
-+
-+ if (cpufreq_driver->target)
-+ __cpufreq_governor(data, CPUFREQ_GOV_STOP);
-+
-+ if (cpufreq_driver->exit)
-+ cpufreq_driver->exit(data);
-+
-+ kfree(data);
-+
-+ return 0;
-+}
-+
-+
-+/*********************************************************************
-+ * NOTIFIER LISTS INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_register_notifier - register a driver with cpufreq
-+ * @nb: notifier function to register
-+ * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
-+ *
-+ * Add a driver to one of two lists: either a list of drivers that
-+ * are notified about clock rate changes (once before and once after
-+ * the transition), or a list of drivers that are notified about
-+ * changes in cpufreq policy.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_register.
-+ */
-+int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
-+{
-+ int ret;
-+
-+ down_write(&cpufreq_notifier_rwsem);
-+ switch (list) {
-+ case CPUFREQ_TRANSITION_NOTIFIER:
-+ ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
-+ break;
-+ case CPUFREQ_POLICY_NOTIFIER:
-+ ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+ up_write(&cpufreq_notifier_rwsem);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_register_notifier);
-+
-+
-+/**
-+ * cpufreq_unregister_notifier - unregister a driver with cpufreq
-+ * @nb: notifier block to be unregistered
-+ * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
-+ *
-+ * Remove a driver from the CPU frequency notifier list.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_unregister.
-+ */
-+int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
-+{
-+ int ret;
-+
-+ down_write(&cpufreq_notifier_rwsem);
-+ switch (list) {
-+ case CPUFREQ_TRANSITION_NOTIFIER:
-+ ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
-+ break;
-+ case CPUFREQ_POLICY_NOTIFIER:
-+ ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+ up_write(&cpufreq_notifier_rwsem);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_unregister_notifier);
-+
-+
-+/*********************************************************************
-+ * GOVERNORS *
-+ *********************************************************************/
-+
-+
-+int __cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation)
-+{
-+ return cpufreq_driver->target(policy, target_freq, relation);
-+}
-+EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
-+
-+
-+int cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation)
-+{
-+ unsigned int ret;
-+
-+ policy = cpufreq_cpu_get(policy->cpu);
-+ if (!policy)
-+ return -EINVAL;
-+
-+ down(&policy->lock);
-+
-+ ret = __cpufreq_driver_target(policy, target_freq, relation);
-+
-+ up(&policy->lock);
-+
-+ cpufreq_cpu_put(policy);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_driver_target);
-+
-+
-+static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
-+{
-+ int ret = 0;
-+
-+ switch (policy->policy) {
-+ case CPUFREQ_POLICY_POWERSAVE:
-+ if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
-+ ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
-+ }
-+ break;
-+ case CPUFREQ_POLICY_PERFORMANCE:
-+ if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
-+ ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
-+ }
-+ break;
-+ case CPUFREQ_POLICY_GOVERNOR:
-+ ret = policy->governor->governor(policy, event);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+int cpufreq_governor(unsigned int cpu, unsigned int event)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ down(&policy->lock);
-+ ret = __cpufreq_governor(policy, event);
-+ up(&policy->lock);
-+
-+ cpufreq_cpu_put(policy);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_governor);
-+
-+
-+int cpufreq_register_governor(struct cpufreq_governor *governor)
-+{
-+ struct cpufreq_governor *t;
-+
-+ if (!governor)
-+ return -EINVAL;
-+
-+ if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
-+ return -EBUSY;
-+ if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
-+ return -EBUSY;
-+
-+ down(&cpufreq_governor_sem);
-+
-+ list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-+ if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-+ up(&cpufreq_governor_sem);
-+ return -EBUSY;
-+ }
-+ }
-+ list_add(&governor->governor_list, &cpufreq_governor_list);
-+
-+ up(&cpufreq_governor_sem);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_register_governor);
-+
-+
-+void cpufreq_unregister_governor(struct cpufreq_governor *governor)
-+{
-+ /* backport info:
-+ * As the module usage count isn't assured in 2.4., check for removal
-+ * of running cpufreq governor
-+ */
-+ unsigned int i;
-+
-+ if (!governor)
-+ return;
-+
-+ down(&cpufreq_governor_sem);
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(i);
-+ if (!policy)
-+ goto done;
-+ down(&policy->lock);
-+
-+ if (policy->policy != CPUFREQ_POLICY_GOVERNOR)
-+ goto unlock_done;
-+ if (policy->governor != governor)
-+ goto unlock_done;
-+
-+ /* stop old one, start performance [always present] */
-+ __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-+ __cpufreq_governor(policy, CPUFREQ_GOV_START);
-+
-+ unlock_done:
-+ up(&policy->lock);
-+ done:
-+ cpufreq_cpu_put(policy);
-+ }
-+ list_del(&governor->governor_list);
-+ up(&cpufreq_governor_sem);
-+ return;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
-+
-+
-+
-+/*********************************************************************
-+ * POLICY INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_get_policy - get the current cpufreq_policy
-+ * @policy: struct cpufreq_policy into which the current cpufreq_policy is written
-+ *
-+ * Reads the current cpufreq policy.
-+ */
-+int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
-+{
-+ struct cpufreq_policy *cpu_policy;
-+ if (!policy)
-+ return -EINVAL;
-+
-+ cpu_policy = cpufreq_cpu_get(cpu);
-+ if (!cpu_policy)
-+ return -EINVAL;
-+
-+ down(&cpu_policy->lock);
-+ memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
-+ up(&cpu_policy->lock);
-+
-+ cpufreq_cpu_put(cpu_policy);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(cpufreq_get_policy);
-+
-+
-+/**
-+ * cpufreq_set_policy - set a new CPUFreq policy
-+ * @policy: policy to be set.
-+ *
-+ * Sets a new CPU frequency and voltage scaling policy.
-+ */
-+int cpufreq_set_policy(struct cpufreq_policy *policy)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy *data;
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ data = cpufreq_cpu_get(policy->cpu);
-+ if (!data)
-+ return -EINVAL;
-+
-+ /* lock this CPU */
-+ down(&data->lock);
-+
-+ memcpy(&policy->cpuinfo,
-+ &data->cpuinfo,
-+ sizeof(struct cpufreq_cpuinfo));
-+
-+ /* verify the cpu speed can be set within this limit */
-+ ret = cpufreq_driver->verify(policy);
-+ if (ret)
-+ goto error_out;
-+
-+ down_read(&cpufreq_notifier_rwsem);
-+
-+ /* adjust if necessary - all reasons */
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
-+ policy);
-+
-+ /* adjust if necessary - hardware incompatibility*/
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
-+ policy);
-+
-+ /* verify the cpu speed can be set within this limit,
-+ which might be different to the first one */
-+ ret = cpufreq_driver->verify(policy);
-+ if (ret) {
-+ up_read(&cpufreq_notifier_rwsem);
-+ goto error_out;
-+ }
-+
-+ /* notification of the new policy */
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
-+ policy);
-+
-+ up_read(&cpufreq_notifier_rwsem);
-+
-+ data->min = policy->min;
-+ data->max = policy->max;
-+
-+ if (cpufreq_driver->setpolicy) {
-+ data->policy = policy->policy;
-+ ret = cpufreq_driver->setpolicy(policy);
-+ } else {
-+ if ((policy->policy != data->policy) ||
-+ ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
-+ /* save old, working values */
-+ unsigned int old_pol = data->policy;
-+ struct cpufreq_governor *old_gov = data->governor;
-+
-+ /* end old governor */
-+ __cpufreq_governor(data, CPUFREQ_GOV_STOP);
-+
-+ /* start new governor */
-+ data->policy = policy->policy;
-+ data->governor = policy->governor;
-+ if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
-+ /* new governor failed, so re-start old one */
-+ data->policy = old_pol;
-+ data->governor = old_gov;
-+ __cpufreq_governor(data, CPUFREQ_GOV_START);
-+ }
-+ /* might be a policy change, too, so fall through */
-+ }
-+ __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
-+ }
-+
-+ error_out:
-+ up(&data->lock);
-+ cpufreq_cpu_put(data);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_set_policy);
-+
-+
-+
-+/*********************************************************************
-+ * EXTERNALLY AFFECTING FREQUENCY CHANGES *
-+ *********************************************************************/
-+
-+/**
-+ * adjust_jiffies - adjust the system "loops_per_jiffy"
-+ *
-+ * This function alters the system "loops_per_jiffy" for the clock
-+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
-+ * systems as each CPU might be scaled differently. So, use the arch
-+ * per-CPU loops_per_jiffy value wherever possible.
-+ */
-+#ifndef CONFIG_SMP
-+static unsigned long l_p_j_ref = 0;
-+static unsigned int l_p_j_ref_freq = 0;
-+
-+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
-+{
-+ if (!l_p_j_ref_freq) {
-+ l_p_j_ref = loops_per_jiffy;
-+ l_p_j_ref_freq = ci->old;
-+ }
-+ if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
-+ (val == CPUFREQ_POSTCHANGE && ci->old > ci->new))
-+ loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
-+}
-+#else
-+#define adjust_jiffies(x...) do {} while (0)
-+#endif
-+
-+
-+/**
-+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
-+ *
-+ * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
-+ * twice on all CPU frequency changes that have external effects.
-+ */
-+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
-+{
-+ down_read(&cpufreq_notifier_rwsem);
-+ switch (state) {
-+ case CPUFREQ_PRECHANGE:
-+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
-+ adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
-+ break;
-+ case CPUFREQ_POSTCHANGE:
-+ adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
-+ cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
-+ break;
-+ }
-+ up_read(&cpufreq_notifier_rwsem);
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
-+
-+
-+
-+/*********************************************************************
-+ * REGISTER / UNREGISTER CPUFREQ DRIVER *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_register_driver - register a CPU Frequency driver
-+ * @driver_data: A struct cpufreq_driver containing the values#
-+ * submitted by the CPU Frequency driver.
-+ *
-+ * Registers a CPU Frequency driver to this core code. This code
-+ * returns zero on success, -EBUSY when another driver got here first
-+ * (and isn't unregistered in the meantime).
-+ *
-+ */
-+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
-+{
-+ unsigned long flags;
-+ unsigned int i;
-+
-+ if (!driver_data || !driver_data->verify || !driver_data->init ||
-+ ((!driver_data->setpolicy) && (!driver_data->target)))
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ if (cpufreq_driver) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ return -EBUSY;
-+ }
-+ cpufreq_driver = driver_data;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ if (cpu_online(i))
-+ cpufreq_add_dev(i);
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_register_driver);
-+
-+
-+/**
-+ * cpufreq_unregister_driver - unregister the current CPUFreq driver
-+ *
-+ * Unregister the current CPUFreq driver. Only call this if you have
-+ * the right to do so, i.e. if you have succeeded in initialising before!
-+ * Returns zero if successful, and -EINVAL if the cpufreq_driver is
-+ * currently not initialised.
-+ */
-+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
-+{
-+ unsigned long flags;
-+ unsigned int i;
-+
-+ if (!cpufreq_driver || (driver != cpufreq_driver))
-+ return -EINVAL;
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ if (cpu_online(i))
-+ cpufreq_remove_dev(i);
-+ }
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_driver = NULL;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/freq_table.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,203 @@
-+/*
-+ * linux/drivers/cpufreq/freq_table.c
-+ *
-+ * Copyright (C) 2002 - 2003 Dominik Brodowski
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+
-+/*********************************************************************
-+ * FREQUENCY TABLE HELPERS *
-+ *********************************************************************/
-+
-+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table)
-+{
-+ unsigned int min_freq = ~0;
-+ unsigned int max_freq = 0;
-+ unsigned int i = 0;
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if (freq < min_freq)
-+ min_freq = freq;
-+ if (freq > max_freq)
-+ max_freq = freq;
-+ }
-+
-+ policy->min = policy->cpuinfo.min_freq = min_freq;
-+ policy->max = policy->cpuinfo.max_freq = max_freq;
-+
-+ if (policy->min == ~0)
-+ return -EINVAL;
-+ else
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
-+
-+
-+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table)
-+{
-+ unsigned int next_larger = ~0;
-+ unsigned int i = 0;
-+ unsigned int count = 0;
-+
-+ if (!cpu_online(policy->cpu))
-+ return -EINVAL;
-+
-+ cpufreq_verify_within_limits(policy,
-+ policy->cpuinfo.min_freq,
-+ policy->cpuinfo.max_freq);
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if ((freq >= policy->min) && (freq <= policy->max))
-+ count++;
-+ else if ((next_larger > freq) && (freq > policy->max))
-+ next_larger = freq;
-+ }
-+
-+ if (!count)
-+ policy->max = next_larger;
-+
-+ cpufreq_verify_within_limits(policy,
-+ policy->cpuinfo.min_freq,
-+ policy->cpuinfo.max_freq);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
-+
-+
-+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table,
-+ unsigned int target_freq,
-+ unsigned int relation,
-+ unsigned int *index)
-+{
-+ struct cpufreq_frequency_table optimal = { .index = ~0, };
-+ struct cpufreq_frequency_table suboptimal = { .index = ~0, };
-+ unsigned int i;
-+
-+ switch (relation) {
-+ case CPUFREQ_RELATION_H:
-+ optimal.frequency = 0;
-+ suboptimal.frequency = ~0;
-+ break;
-+ case CPUFREQ_RELATION_L:
-+ optimal.frequency = ~0;
-+ suboptimal.frequency = 0;
-+ break;
-+ }
-+
-+ if (!cpu_online(policy->cpu))
-+ return -EINVAL;
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if ((freq < policy->min) || (freq > policy->max))
-+ continue;
-+ switch(relation) {
-+ case CPUFREQ_RELATION_H:
-+ if (freq <= target_freq) {
-+ if (freq >= optimal.frequency) {
-+ optimal.frequency = freq;
-+ optimal.index = i;
-+ }
-+ } else {
-+ if (freq <= suboptimal.frequency) {
-+ suboptimal.frequency = freq;
-+ suboptimal.index = i;
-+ }
-+ }
-+ break;
-+ case CPUFREQ_RELATION_L:
-+ if (freq >= target_freq) {
-+ if (freq <= optimal.frequency) {
-+ optimal.frequency = freq;
-+ optimal.index = i;
-+ }
-+ } else {
-+ if (freq >= suboptimal.frequency) {
-+ suboptimal.frequency = freq;
-+ suboptimal.index = i;
-+ }
-+ }
-+ break;
-+ }
-+ }
-+ if (optimal.index > i) {
-+ if (suboptimal.index > i)
-+ return -EINVAL;
-+ *index = suboptimal.index;
-+ } else
-+ *index = optimal.index;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
-+
-+static struct cpufreq_frequency_table *show_table[NR_CPUS];
-+/**
-+ * show_scaling_governor - show the current policy for the specified CPU
-+ */
-+static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
-+{
-+ unsigned int i = 0;
-+ unsigned int cpu = policy->cpu;
-+ ssize_t count = 0;
-+ struct cpufreq_frequency_table *table;
-+
-+ if (!show_table[cpu])
-+ return -ENODEV;
-+
-+ table = show_table[cpu];
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ count += sprintf(&buf[count], "%d ", table[i].frequency);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+
-+}
-+
-+struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
-+ .attr = { .name = "scaling_available_frequencies", .mode = 0444 },
-+ .show = show_available_freqs,
-+};
-+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
-+
-+/*
-+ * if you use these, you must assure that the frequency table is valid
-+ * all the time between get_attr and put_attr!
-+ */
-+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
-+ unsigned int cpu)
-+{
-+ show_table[cpu] = table;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
-+
-+void cpufreq_frequency_table_put_attr(unsigned int cpu)
-+{
-+ show_table[cpu] = NULL;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
-+
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-+MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
-+MODULE_LICENSE ("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/proc_intf.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,244 @@
-+/*
-+ * linux/drivers/cpufreq/proc_intf.c
-+ *
-+ * Copyright (C) 2002 - 2003 Dominik Brodowski
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+#include <linux/ctype.h>
-+#include <linux/proc_fs.h>
-+#include <asm/uaccess.h>
-+
-+
-+/**
-+ * cpufreq_parse_policy - parse a policy string
-+ * @input_string: the string to parse.
-+ * @policy: the policy written inside input_string
-+ *
-+ * This function parses a "policy string" - something the user echo'es into
-+ * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
-+ * If there are invalid/missing entries, they are replaced with current
-+ * cpufreq policy.
-+ */
-+static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
-+{
-+ unsigned int min = 0;
-+ unsigned int max = 0;
-+ unsigned int cpu = 0;
-+ char str_governor[16];
-+ struct cpufreq_policy current_policy;
-+ unsigned int result = -EFAULT;
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ policy->min = 0;
-+ policy->max = 0;
-+ policy->policy = 0;
-+ policy->cpu = CPUFREQ_ALL_CPUS;
-+
-+ if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4)
-+ {
-+ policy->min = min;
-+ policy->max = max;
-+ policy->cpu = cpu;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
-+ {
-+ if (!cpufreq_get_policy(&current_policy, cpu)) {
-+ policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-+ policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-+ policy->cpu = cpu;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ }
-+
-+ if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3)
-+ {
-+ policy->min = min;
-+ policy->max = max;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+
-+ if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
-+ {
-+ if (!cpufreq_get_policy(&current_policy, cpu)) {
-+ policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-+ policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ }
-+
-+ return -EINVAL;
-+
-+scan_policy:
-+ result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
-+
-+ return result;
-+}
-+
-+/**
-+ * cpufreq_proc_read - read /proc/cpufreq
-+ *
-+ * This function prints out the current cpufreq policy.
-+ */
-+static int cpufreq_proc_read (
-+ char *page,
-+ char **start,
-+ off_t off,
-+ int count,
-+ int *eof,
-+ void *data)
-+{
-+ char *p = page;
-+ int len = 0;
-+ struct cpufreq_policy policy;
-+ unsigned int min_pctg = 0;
-+ unsigned int max_pctg = 0;
-+ unsigned int i = 0;
-+
-+ if (off != 0)
-+ goto end;
-+
-+ p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
-+ for (i=0;i<NR_CPUS;i++) {
-+ if (!cpu_online(i))
-+ continue;
-+
-+ if (cpufreq_get_policy(&policy, i))
-+ continue;
-+
-+ if (!policy.cpuinfo.max_freq)
-+ continue;
-+
-+ min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
-+ max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
-+
-+ p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
-+ i , policy.min, min_pctg, policy.max, max_pctg);
-+ switch (policy.policy) {
-+ case CPUFREQ_POLICY_POWERSAVE:
-+ p += sprintf(p, "powersave\n");
-+ break;
-+ case CPUFREQ_POLICY_PERFORMANCE:
-+ p += sprintf(p, "performance\n");
-+ break;
-+ case CPUFREQ_POLICY_GOVERNOR:
-+ p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
-+ break;
-+ default:
-+ p += sprintf(p, "INVALID\n");
-+ break;
-+ }
-+ }
-+end:
-+ len = (p - page);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len>count)
-+ len = count;
-+ if (len<0)
-+ len = 0;
-+
-+ return len;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_write - handles writing into /proc/cpufreq
-+ *
-+ * This function calls the parsing script and then sets the policy
-+ * accordingly.
-+ */
-+static int cpufreq_proc_write (
-+ struct file *file,
-+ const char *buffer,
-+ unsigned long count,
-+ void *data)
-+{
-+ int result = 0;
-+ char proc_string[42] = {'\0'};
-+ struct cpufreq_policy policy;
-+ unsigned int i = 0;
-+
-+
-+ if ((count > sizeof(proc_string) - 1))
-+ return -EINVAL;
-+
-+ if (copy_from_user(proc_string, buffer, count))
-+ return -EFAULT;
-+
-+ proc_string[count] = '\0';
-+
-+ result = cpufreq_parse_policy(proc_string, &policy);
-+ if (result)
-+ return -EFAULT;
-+
-+ if (policy.cpu == CPUFREQ_ALL_CPUS)
-+ {
-+ for (i=0; i<NR_CPUS; i++)
-+ {
-+ policy.cpu = i;
-+ if (cpu_online(i))
-+ cpufreq_set_policy(&policy);
-+ }
-+ }
-+ else
-+ cpufreq_set_policy(&policy);
-+
-+ return count;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_init - add "cpufreq" to the /proc root directory
-+ *
-+ * This function adds "cpufreq" to the /proc root directory.
-+ */
-+static int __init cpufreq_proc_init (void)
-+{
-+ struct proc_dir_entry *entry = NULL;
-+
-+ /* are these acceptable values? */
-+ entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR,
-+ &proc_root);
-+
-+ if (!entry) {
-+ printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
-+ return -EIO;
-+ } else {
-+ entry->read_proc = cpufreq_proc_read;
-+ entry->write_proc = cpufreq_proc_write;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
-+ *
-+ * This function removes "cpufreq" from the /proc root directory.
-+ */
-+static void __exit cpufreq_proc_exit (void)
-+{
-+ remove_proc_entry("cpufreq", &proc_root);
-+ return;
-+}
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-+MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
-+MODULE_LICENSE ("GPL");
-+
-+module_init(cpufreq_proc_init);
-+module_exit(cpufreq_proc_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/cpufreq/userspace.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,591 @@
-+/*
-+ * drivers/cpufreq/userspace.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
-+ *
-+ * $Id: userspace.c,v 1.4 2003/03/07 10:30:20 db Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/smp.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ctype.h>
-+#include <linux/cpufreq.h>
-+#include <linux/sysctl.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/sysfs.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ_MAX, \
-+ .data = &cpu_max_freq[cpunr], \
-+ .procname = "speed-max", \
-+ .maxlen = sizeof(cpu_max_freq[cpunr]),\
-+ .mode = 0444, \
-+ .proc_handler = proc_dointvec, }
-+
-+#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ_MIN, \
-+ .data = &cpu_min_freq[cpunr], \
-+ .procname = "speed-min", \
-+ .maxlen = sizeof(cpu_min_freq[cpunr]),\
-+ .mode = 0444, \
-+ .proc_handler = proc_dointvec, }
-+
-+#define CTL_CPU_VARS_SPEED(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ, \
-+ .procname = "speed", \
-+ .mode = 0644, \
-+ .proc_handler = cpufreq_procctl, \
-+ .strategy = cpufreq_sysctl, \
-+ .extra1 = (void*) (cpunr), }
-+
-+#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
-+ CTL_CPU_VARS_SPEED_MAX(cpunr), \
-+ CTL_CPU_VARS_SPEED_MIN(cpunr), \
-+ CTL_CPU_VARS_SPEED(cpunr), \
-+ { .ctl_name = 0, }, }
-+
-+/* the ctl_table entry for each CPU */
-+#define CPU_ENUM(s) { \
-+ .ctl_name = (CPU_NR + s), \
-+ .procname = #s, \
-+ .mode = 0555, \
-+ .child = ctl_cpu_vars_##s }
-+
-+/**
-+ * A few values needed by the userspace governor
-+ */
-+static unsigned int cpu_max_freq[NR_CPUS];
-+static unsigned int cpu_min_freq[NR_CPUS];
-+static unsigned int cpu_cur_freq[NR_CPUS];
-+static unsigned int cpu_is_managed[NR_CPUS];
-+static struct cpufreq_policy current_policy[NR_CPUS];
-+
-+static DECLARE_MUTEX (userspace_sem);
-+
-+
-+/* keep track of frequency transitions */
-+static int
-+userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-+ void *data)
-+{
-+ struct cpufreq_freqs *freq = data;
-+
-+ cpu_cur_freq[freq->cpu] = freq->new;
-+
-+ return 0;
-+}
-+
-+static struct notifier_block userspace_cpufreq_notifier_block = {
-+ .notifier_call = userspace_cpufreq_notifier
-+};
-+
-+
-+/**
-+ * cpufreq_set - set the CPU frequency
-+ * @freq: target frequency in kHz
-+ * @cpu: CPU for which the frequency is to be set
-+ *
-+ * Sets the CPU frequency to freq.
-+ */
-+int cpufreq_set(unsigned int freq, unsigned int cpu)
-+{
-+ int ret = -EINVAL;
-+
-+ down(&userspace_sem);
-+ if (!cpu_is_managed[cpu])
-+ goto err;
-+
-+ if (freq < cpu_min_freq[cpu])
-+ freq = cpu_min_freq[cpu];
-+ if (freq > cpu_max_freq[cpu])
-+ freq = cpu_max_freq[cpu];
-+
-+ ret = cpufreq_driver_target(&current_policy[cpu], freq,
-+ CPUFREQ_RELATION_L);
-+
-+ err:
-+ up(&userspace_sem);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_set);
-+
-+
-+/**
-+ * cpufreq_setmax - set the CPU to the maximum frequency
-+ * @cpu - affected cpu;
-+ *
-+ * Sets the CPU frequency to the maximum frequency supported by
-+ * this CPU.
-+ */
-+int cpufreq_setmax(unsigned int cpu)
-+{
-+ if (!cpu_is_managed[cpu] || !cpu_online(cpu))
-+ return -EINVAL;
-+ return cpufreq_set(cpu_max_freq[cpu], cpu);
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_setmax);
-+
-+
-+/**
-+ * cpufreq_get - get the current CPU frequency (in kHz)
-+ * @cpu: CPU number
-+ *
-+ * Get the CPU current (static) CPU frequency
-+ */
-+unsigned int cpufreq_get(unsigned int cpu)
-+{
-+ return cpu_cur_freq[cpu];
-+}
-+EXPORT_SYMBOL(cpufreq_get);
-+
-+
-+#ifdef CONFIG_CPU_FREQ_24_API
-+
-+
-+/*********************** cpufreq_sysctl interface ********************/
-+static int
-+cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ char buf[16], *p;
-+ int cpu = (int) ctl->extra1;
-+ int len, left = *lenp;
-+
-+ if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) {
-+ *lenp = 0;
-+ return 0;
-+ }
-+
-+ if (write) {
-+ unsigned int freq;
-+
-+ len = left;
-+ if (left > sizeof(buf))
-+ left = sizeof(buf);
-+ if (copy_from_user(buf, buffer, left))
-+ return -EFAULT;
-+ buf[sizeof(buf) - 1] = '\0';
-+
-+ freq = simple_strtoul(buf, &p, 0);
-+ cpufreq_set(freq, cpu);
-+ } else {
-+ len = sprintf(buf, "%d\n", cpufreq_get(cpu));
-+ if (len > left)
-+ len = left;
-+ if (copy_to_user(buffer, buf, len))
-+ return -EFAULT;
-+ }
-+
-+ *lenp = len;
-+ filp->f_pos += len;
-+ return 0;
-+}
-+
-+static int
-+cpufreq_sysctl(ctl_table *table, int *name, int nlen,
-+ void *oldval, size_t *oldlenp,
-+ void *newval, size_t newlen, void **context)
-+{
-+ int cpu = (int) table->extra1;
-+
-+ if (!cpu_online(cpu))
-+ return -EINVAL;
-+
-+ if (oldval && oldlenp) {
-+ size_t oldlen;
-+
-+ if (get_user(oldlen, oldlenp))
-+ return -EFAULT;
-+
-+ if (oldlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
-+ put_user(sizeof(unsigned int), oldlenp))
-+ return -EFAULT;
-+ }
-+ if (newval && newlen) {
-+ unsigned int freq;
-+
-+ if (newlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (get_user(freq, (unsigned int *)newval))
-+ return -EFAULT;
-+
-+ cpufreq_set(freq, cpu);
-+ }
-+ return 1;
-+}
-+
-+/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
-+/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
-+ CTL_TABLE_CPU_VARS(0);
-+#if NR_CPUS > 1
-+ CTL_TABLE_CPU_VARS(1);
-+#endif
-+#if NR_CPUS > 2
-+ CTL_TABLE_CPU_VARS(2);
-+#endif
-+#if NR_CPUS > 3
-+ CTL_TABLE_CPU_VARS(3);
-+#endif
-+#if NR_CPUS > 4
-+ CTL_TABLE_CPU_VARS(4);
-+#endif
-+#if NR_CPUS > 5
-+ CTL_TABLE_CPU_VARS(5);
-+#endif
-+#if NR_CPUS > 6
-+ CTL_TABLE_CPU_VARS(6);
-+#endif
-+#if NR_CPUS > 7
-+ CTL_TABLE_CPU_VARS(7);
-+#endif
-+#if NR_CPUS > 8
-+ CTL_TABLE_CPU_VARS(8);
-+#endif
-+#if NR_CPUS > 9
-+ CTL_TABLE_CPU_VARS(9);
-+#endif
-+#if NR_CPUS > 10
-+ CTL_TABLE_CPU_VARS(10);
-+#endif
-+#if NR_CPUS > 11
-+ CTL_TABLE_CPU_VARS(11);
-+#endif
-+#if NR_CPUS > 12
-+ CTL_TABLE_CPU_VARS(12);
-+#endif
-+#if NR_CPUS > 13
-+ CTL_TABLE_CPU_VARS(13);
-+#endif
-+#if NR_CPUS > 14
-+ CTL_TABLE_CPU_VARS(14);
-+#endif
-+#if NR_CPUS > 15
-+ CTL_TABLE_CPU_VARS(15);
-+#endif
-+#if NR_CPUS > 16
-+ CTL_TABLE_CPU_VARS(16);
-+#endif
-+#if NR_CPUS > 17
-+ CTL_TABLE_CPU_VARS(17);
-+#endif
-+#if NR_CPUS > 18
-+ CTL_TABLE_CPU_VARS(18);
-+#endif
-+#if NR_CPUS > 19
-+ CTL_TABLE_CPU_VARS(19);
-+#endif
-+#if NR_CPUS > 20
-+ CTL_TABLE_CPU_VARS(20);
-+#endif
-+#if NR_CPUS > 21
-+ CTL_TABLE_CPU_VARS(21);
-+#endif
-+#if NR_CPUS > 22
-+ CTL_TABLE_CPU_VARS(22);
-+#endif
-+#if NR_CPUS > 23
-+ CTL_TABLE_CPU_VARS(23);
-+#endif
-+#if NR_CPUS > 24
-+ CTL_TABLE_CPU_VARS(24);
-+#endif
-+#if NR_CPUS > 25
-+ CTL_TABLE_CPU_VARS(25);
-+#endif
-+#if NR_CPUS > 26
-+ CTL_TABLE_CPU_VARS(26);
-+#endif
-+#if NR_CPUS > 27
-+ CTL_TABLE_CPU_VARS(27);
-+#endif
-+#if NR_CPUS > 28
-+ CTL_TABLE_CPU_VARS(28);
-+#endif
-+#if NR_CPUS > 29
-+ CTL_TABLE_CPU_VARS(29);
-+#endif
-+#if NR_CPUS > 30
-+ CTL_TABLE_CPU_VARS(30);
-+#endif
-+#if NR_CPUS > 31
-+ CTL_TABLE_CPU_VARS(31);
-+#endif
-+#if NR_CPUS > 32
-+#error please extend CPU enumeration
-+#endif
-+
-+/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
-+static ctl_table ctl_cpu_table[NR_CPUS + 1] = {
-+ CPU_ENUM(0),
-+#if NR_CPUS > 1
-+ CPU_ENUM(1),
-+#endif
-+#if NR_CPUS > 2
-+ CPU_ENUM(2),
-+#endif
-+#if NR_CPUS > 3
-+ CPU_ENUM(3),
-+#endif
-+#if NR_CPUS > 4
-+ CPU_ENUM(4),
-+#endif
-+#if NR_CPUS > 5
-+ CPU_ENUM(5),
-+#endif
-+#if NR_CPUS > 6
-+ CPU_ENUM(6),
-+#endif
-+#if NR_CPUS > 7
-+ CPU_ENUM(7),
-+#endif
-+#if NR_CPUS > 8
-+ CPU_ENUM(8),
-+#endif
-+#if NR_CPUS > 9
-+ CPU_ENUM(9),
-+#endif
-+#if NR_CPUS > 10
-+ CPU_ENUM(10),
-+#endif
-+#if NR_CPUS > 11
-+ CPU_ENUM(11),
-+#endif
-+#if NR_CPUS > 12
-+ CPU_ENUM(12),
-+#endif
-+#if NR_CPUS > 13
-+ CPU_ENUM(13),
-+#endif
-+#if NR_CPUS > 14
-+ CPU_ENUM(14),
-+#endif
-+#if NR_CPUS > 15
-+ CPU_ENUM(15),
-+#endif
-+#if NR_CPUS > 16
-+ CPU_ENUM(16),
-+#endif
-+#if NR_CPUS > 17
-+ CPU_ENUM(17),
-+#endif
-+#if NR_CPUS > 18
-+ CPU_ENUM(18),
-+#endif
-+#if NR_CPUS > 19
-+ CPU_ENUM(19),
-+#endif
-+#if NR_CPUS > 20
-+ CPU_ENUM(20),
-+#endif
-+#if NR_CPUS > 21
-+ CPU_ENUM(21),
-+#endif
-+#if NR_CPUS > 22
-+ CPU_ENUM(22),
-+#endif
-+#if NR_CPUS > 23
-+ CPU_ENUM(23),
-+#endif
-+#if NR_CPUS > 24
-+ CPU_ENUM(24),
-+#endif
-+#if NR_CPUS > 25
-+ CPU_ENUM(25),
-+#endif
-+#if NR_CPUS > 26
-+ CPU_ENUM(26),
-+#endif
-+#if NR_CPUS > 27
-+ CPU_ENUM(27),
-+#endif
-+#if NR_CPUS > 28
-+ CPU_ENUM(28),
-+#endif
-+#if NR_CPUS > 29
-+ CPU_ENUM(29),
-+#endif
-+#if NR_CPUS > 30
-+ CPU_ENUM(30),
-+#endif
-+#if NR_CPUS > 31
-+ CPU_ENUM(31),
-+#endif
-+#if NR_CPUS > 32
-+#error please extend CPU enumeration
-+#endif
-+ {
-+ .ctl_name = 0,
-+ }
-+};
-+
-+static ctl_table ctl_cpu[2] = {
-+ {
-+ .ctl_name = CTL_CPU,
-+ .procname = "cpu",
-+ .mode = 0555,
-+ .child = ctl_cpu_table,
-+ },
-+ {
-+ .ctl_name = 0,
-+ }
-+};
-+
-+struct ctl_table_header *cpufreq_sysctl_table;
-+
-+static inline void cpufreq_sysctl_init(void)
-+{
-+ cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0);
-+}
-+
-+static inline void cpufreq_sysctl_exit(void)
-+{
-+ unregister_sysctl_table(cpufreq_sysctl_table);
-+}
-+
-+#else
-+#define cpufreq_sysctl_init() do {} while(0)
-+#define cpufreq_sysctl_exit() do {} while(0)
-+#endif /* CONFIG_CPU_FREQ_24API */
-+
-+
-+/************************** sysfs interface ************************/
-+static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
-+{
-+ return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
-+}
-+
-+static ssize_t
-+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
-+{
-+ unsigned int freq = 0;
-+ unsigned int ret;
-+
-+ ret = sscanf (buf, "%u", &freq);
-+ if (ret != 1)
-+ return -EINVAL;
-+
-+ cpufreq_set(freq, policy->cpu);
-+
-+ return count;
-+}
-+
-+static struct freq_attr freq_attr_scaling_setspeed = {
-+ .attr = { .name = "scaling_setspeed", .mode = 0644 },
-+ .show = show_speed,
-+ .store = store_speed,
-+};
-+
-+static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
-+ unsigned int event)
-+{
-+ unsigned int cpu = policy->cpu;
-+ switch (event) {
-+ case CPUFREQ_GOV_START:
-+ if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) ||
-+ !policy->cur)
-+ return -EINVAL;
-+ down(&userspace_sem);
-+ cpu_is_managed[cpu] = 1;
-+ cpu_min_freq[cpu] = policy->min;
-+ cpu_max_freq[cpu] = policy->max;
-+ cpu_cur_freq[cpu] = policy->cur;
-+ sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
-+ memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
-+ up(&userspace_sem);
-+ break;
-+ case CPUFREQ_GOV_STOP:
-+ down(&userspace_sem);
-+ cpu_is_managed[cpu] = 0;
-+ cpu_min_freq[cpu] = 0;
-+ cpu_max_freq[cpu] = 0;
-+ sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
-+ up(&userspace_sem);
-+ module_put(THIS_MODULE);
-+ break;
-+ case CPUFREQ_GOV_LIMITS:
-+ down(&userspace_sem);
-+ cpu_min_freq[cpu] = policy->min;
-+ cpu_max_freq[cpu] = policy->max;
-+ if (policy->max < cpu_cur_freq[cpu])
-+ cpufreq_driver_target(&current_policy[cpu], policy->max,
-+ CPUFREQ_RELATION_H);
-+ else if (policy->min > cpu_cur_freq[cpu])
-+ cpufreq_driver_target(&current_policy[cpu], policy->min,
-+ CPUFREQ_RELATION_L);
-+ memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
-+ up(&userspace_sem);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because
-+ * of this, cpu_cur_freq[] needs to be set early.
-+ */
-+#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100)
-+extern unsigned int sa11x0_getspeed(void);
-+
-+static void cpufreq_sa11x0_compat(void)
-+{
-+ cpu_cur_freq[0] = sa11x0_getspeed();
-+}
-+#else
-+#define cpufreq_sa11x0_compat() do {} while(0)
-+#endif
-+
-+
-+static struct cpufreq_governor cpufreq_gov_userspace = {
-+ .name = "userspace",
-+ .governor = cpufreq_governor_userspace,
-+ .owner = THIS_MODULE,
-+};
-+EXPORT_SYMBOL(cpufreq_gov_userspace);
-+
-+static int already_init = 0;
-+
-+int cpufreq_gov_userspace_init(void)
-+{
-+ if (!already_init) {
-+ down(&userspace_sem);
-+ cpufreq_sa11x0_compat();
-+ cpufreq_sysctl_init();
-+ cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-+ already_init = 1;
-+ up(&userspace_sem);
-+ }
-+ return cpufreq_register_governor(&cpufreq_gov_userspace);
-+}
-+EXPORT_SYMBOL(cpufreq_gov_userspace_init);
-+
-+
-+static void __exit cpufreq_gov_userspace_exit(void)
-+{
-+ cpufreq_unregister_governor(&cpufreq_gov_userspace);
-+ cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-+ cpufreq_sysctl_exit();
-+}
-+
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
-+MODULE_LICENSE ("GPL");
-+
-+module_init(cpufreq_gov_userspace_init);
-+module_exit(cpufreq_gov_userspace_exit);
---- linux-2.4.25/drivers/i2c/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -17,6 +17,15 @@
- int ' GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
- int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
- fi
-+
-+ dep_tristate ' Guide GPIO adapter' CONFIG_I2C_GUIDE $CONFIG_I2C_ALGOBIT
-+ if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ dep_tristate ' Omaha I2C interface' CONFIG_I2C_OMAHA $CONFIG_I2C
-+ fi
-+ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ dep_tristate ' Frodo I2C adapter' CONFIG_I2C_FRODO $CONFIG_I2C_ALGOBIT
-+ dep_tristate ' SA1100 I2C GPIO adapter' CONFIG_I2C_BIT_SA1100_GPIO $CONFIG_I2C_ALGOBIT
-+ fi
- fi
-
- dep_tristate 'NatSemi SCx200 ACCESS.bus' CONFIG_SCx200_ACB $CONFIG_I2C
-@@ -49,6 +58,10 @@
- dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
- fi
-
-+ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ] ; then
-+ dep_tristate 'Atmel AT91RM9200 I2C Two-Wire interface (TWI)' CONFIG_I2C_AT91 $CONFIG_I2C
-+ fi
-+
- if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
- dep_tristate 'SiByte SMBus interface' CONFIG_I2C_ALGO_SIBYTE $CONFIG_I2C
- dep_tristate ' MAX1617 Temperature Sensor' CONFIG_I2C_MAX1617 $CONFIG_I2C_ALGO_SIBYTE
---- linux-2.4.25/drivers/i2c/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -8,12 +8,21 @@
- i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
- i2c-proc.o
-
-+# Init order: core, chardev, bit adapters, pcf adapters
-+
- obj-$(CONFIG_I2C) += i2c-core.o
- obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
-+
-+# Bit adapters
- obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
- obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o
- obj-$(CONFIG_I2C_ELV) += i2c-elv.o
- obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
-+obj-$(CONFIG_I2C_GUIDE) += i2c-guide.o
-+obj-$(CONFIG_I2C_FRODO) += i2c-frodo.o
-+obj-$(CONFIG_I2C_OMAHA) += i2c-omaha.o
-+
-+# PCF adapters
- obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
- obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
- obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
-@@ -30,4 +39,3 @@
- # This is needed for automatic patch generation: sensors code ends here
-
- include $(TOPDIR)/Rules.make
--
---- linux-2.4.25/drivers/i2c/i2c-algo-bit.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-algo-bit.c 2004-03-31 17:15:09.000000000 +0200
-@@ -169,7 +169,14 @@
- * 1 if the device acknowledged
- * 0 if the device did not ack
- * -ETIMEDOUT if an error occurred (while raising the scl line)
-- */
-+
-+ * tsong@iders.ca: an instruction to disable any timeconsuming interrupt
-+ here except the heart beat of timer2 should be added before setsda(adap, sb).
-+ because when interrupt occurs during
-+ scl is set high, the interrupt service routine is served and may take long,
-+ after the interrupt returns, sda could be sampled by the device(slave)
-+ more than once, and this cause error problem.
-+*/
- static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
- {
- int i;
-@@ -582,9 +589,7 @@
- printk("\n");
- }
-
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- i2c_add_adapter(adap);
-
- return 0;
-@@ -600,15 +605,13 @@
-
- DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
-
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- return 0;
- }
-
--int __init i2c_algo_bit_init (void)
-+static int __init i2c_algo_bit_init (void)
- {
-- printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n");
-+ printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n");
- return 0;
- }
-
-@@ -617,7 +620,6 @@
- EXPORT_SYMBOL(i2c_bit_add_bus);
- EXPORT_SYMBOL(i2c_bit_del_bus);
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
- MODULE_LICENSE("GPL");
-@@ -631,12 +633,4 @@
- MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
-
--int init_module(void)
--{
-- return i2c_algo_bit_init();
--}
--
--void cleanup_module(void)
--{
--}
--#endif
-+module_init(i2c_algo_bit_init);
---- linux-2.4.25/drivers/i2c/i2c-algo-pcf.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-algo-pcf.c 2004-03-31 17:15:09.000000000 +0200
-@@ -475,9 +475,7 @@
- return i;
- }
-
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
-
- i2c_add_adapter(adap);
-
-@@ -515,13 +513,11 @@
- return res;
- DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name));
-
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- return 0;
- }
-
--int __init i2c_algo_pcf_init (void)
-+static int __init i2c_algo_pcf_init (void)
- {
- printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
- return 0;
-@@ -531,7 +527,6 @@
- EXPORT_SYMBOL(i2c_pcf_add_bus);
- EXPORT_SYMBOL(i2c_pcf_del_bus);
-
--#ifdef MODULE
- MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
- MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
- MODULE_LICENSE("GPL");
-@@ -543,13 +538,4 @@
- MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
-
--
--int init_module(void)
--{
-- return i2c_algo_pcf_init();
--}
--
--void cleanup_module(void)
--{
--}
--#endif
-+module_init(i2c_algo_pcf_init);
---- linux-2.4.25/drivers/i2c/i2c-core.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -41,7 +41,7 @@
-
- /* exclusive access to the bus */
- #define I2C_LOCK(adap) down(&adap->lock)
--#define I2C_UNLOCK(adap) up(&adap->lock)
-+#define I2C_UNLOCK(adap) up(&adap->lock)
-
- #define ADAP_LOCK() down(&adap_lock)
- #define ADAP_UNLOCK() up(&adap_lock)
-@@ -67,7 +67,7 @@
- static int driver_count;
-
- /**** debug level */
--static int i2c_debug=1;
-+static int i2c_debug = 0;
-
- /* ---------------------------------------------------
- * /proc entry declarations
-@@ -77,14 +77,14 @@
- #ifdef CONFIG_PROC_FS
-
- static int i2cproc_init(void);
--static int i2cproc_cleanup(void);
-+static void i2cproc_cleanup(void);
-
--static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
-+static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
- loff_t *ppos);
- static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
- int *eof , void *private);
-
--/* To implement the dynamic /proc/bus/i2c-? files, we need our own
-+/* To implement the dynamic /proc/bus/i2c-? files, we need our own
- implementation of the read hook */
- static struct file_operations i2cproc_operations = {
- read: i2cproc_bus_read,
-@@ -101,8 +101,8 @@
-
-
- /* ---------------------------------------------------
-- * registering functions
-- * ---------------------------------------------------
-+ * registering functions
-+ * ---------------------------------------------------
- */
-
- /* -----
-@@ -119,7 +119,7 @@
- if (NULL == adapters[i])
- break;
- if (I2C_ADAP_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
- adap->name);
- res = -ENOMEM;
-@@ -129,7 +129,7 @@
- adapters[i] = adap;
- adap_count++;
- ADAP_UNLOCK();
--
-+
- /* init data types */
- init_MUTEX(&adap->lock);
-
-@@ -157,18 +157,18 @@
- #endif /* def CONFIG_PROC_FS */
-
- /* inform drivers of new adapters */
-- DRV_LOCK();
-+ DRV_LOCK();
- for (j=0;j<I2C_DRIVER_MAX;j++)
-- if (drivers[j]!=NULL &&
-+ if (drivers[j]!=NULL &&
- (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
- /* We ignore the return code; if it fails, too bad */
- drivers[j]->attach_adapter(adap);
- DRV_UNLOCK();
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
- adap->name,i));
-
-- return 0;
-+ return 0;
-
-
- ERROR1:
-@@ -203,13 +203,13 @@
- * this or hell will break loose...
- */
- DRV_LOCK();
-- for (j = 0; j < I2C_DRIVER_MAX; j++)
-+ for (j = 0; j < I2C_DRIVER_MAX; j++)
- if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
- if ((res = drivers[j]->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
- "while detaching driver %s: driver not "
- "detached!",adap->name,drivers[j]->name);
-- goto ERROR1;
-+ goto ERROR1;
- }
- DRV_UNLOCK();
-
-@@ -241,8 +241,8 @@
-
- adapters[i] = NULL;
- adap_count--;
--
-- ADAP_UNLOCK();
-+
-+ ADAP_UNLOCK();
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
- return 0;
-
-@@ -269,7 +269,7 @@
- if (NULL == drivers[i])
- break;
- if (I2C_DRIVER_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: register_driver(%s) "
- "- enlarge I2C_DRIVER_MAX.\n",
- driver->name);
-@@ -279,11 +279,11 @@
-
- drivers[i] = driver;
- driver_count++;
--
-+
- DRV_UNLOCK(); /* driver was successfully added */
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
--
-+
- ADAP_LOCK();
-
- /* now look for instances of driver on our adapters
-@@ -314,11 +314,11 @@
- return -ENODEV;
- }
- /* Have a look at each adapter, if clients of this driver are still
-- * attached. If so, detach them to be able to kill the driver
-+ * attached. If so, detach them to be able to kill the driver
- * afterwards.
- */
- DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n"));
-- /* removing clients does not depend on the notify flag, else
-+ /* removing clients does not depend on the notify flag, else
- * invalid operation might (will!) result, when using stale client
- * pointers.
- */
-@@ -333,7 +333,7 @@
- /* DUMMY drivers do not register their clients, so we have to
- * use a trick here: we call driver->attach_adapter to
- * *detach* it! Of course, each dummy driver should know about
-- * this or hell will break loose...
-+ * this or hell will break loose...
- */
- if ((res = driver->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: while unregistering "
-@@ -345,9 +345,9 @@
- return res;
- }
- } else {
-- for (j=0;j<I2C_CLIENT_MAX;j++) {
-+ for (j=0;j<I2C_CLIENT_MAX;j++) {
- struct i2c_client *client = adap->clients[j];
-- if (client != NULL &&
-+ if (client != NULL &&
- client->driver == driver) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: "
- "detaching client %s:\n",
-@@ -376,7 +376,7 @@
- drivers[i] = NULL;
- driver_count--;
- DRV_UNLOCK();
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
- return 0;
- }
-@@ -384,7 +384,7 @@
- int i2c_check_addr (struct i2c_adapter *adapter, int addr)
- {
- int i;
-- for (i = 0; i < I2C_CLIENT_MAX ; i++)
-+ for (i = 0; i < I2C_CLIENT_MAX ; i++)
- if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
- return -EBUSY;
- return 0;
-@@ -402,7 +402,7 @@
- if (NULL == adapter->clients[i])
- break;
- if (I2C_CLIENT_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
- client->name);
- return -ENOMEM;
-@@ -410,9 +410,9 @@
-
- adapter->clients[i] = client;
- adapter->client_count++;
--
-- if (adapter->client_register)
-- if (adapter->client_register(client))
-+
-+ if (adapter->client_register)
-+ if (adapter->client_register(client))
- printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
- "to have failed for client %02x at adapter %s\n",
- client->addr,adapter->name);
-@@ -421,7 +421,7 @@
-
- if(client->flags & I2C_CLIENT_ALLOW_USE)
- client->usage_count = 0;
--
-+
- return 0;
- }
-
-@@ -440,12 +440,12 @@
- client->name);
- return -ENODEV;
- }
--
-- if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
-+
-+ if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
- (client->usage_count>0))
- return -EBUSY;
--
-- if (adapter->client_unregister != NULL)
-+
-+ if (adapter->client_unregister != NULL)
- if ((res = adapter->client_unregister(client))) {
- printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
- "client not detached",client->name);
-@@ -471,7 +471,7 @@
-
- void i2c_dec_use_client(struct i2c_client *client)
- {
--
-+
- if (client->driver->dec_use != NULL)
- client->driver->dec_use(client);
-
-@@ -479,65 +479,65 @@
- client->adapter->dec_use(client->adapter);
- }
-
--struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
-+struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
- struct i2c_client *prev)
- {
- int i,j;
--
-+
- /* Will iterate through the list of clients in each adapter of adapters-list
-- in search for a client that matches the search criteria. driver_id or
-- adapter_id are ignored if set to 0. If both are ignored this returns
-+ in search for a client that matches the search criteria. driver_id or
-+ adapter_id are ignored if set to 0. If both are ignored this returns
- first client found. */
--
-- i = j = 0;
--
-- /* set starting point */
-+
-+ i = j = 0;
-+
-+ /* set starting point */
- if(prev)
- {
- if(!(prev->adapter))
- return (struct i2c_client *) -EINVAL;
--
-+
- for(j=0; j < I2C_ADAP_MAX; j++)
- if(prev->adapter == adapters[j])
- break;
--
-+
- /* invalid starting point? */
- if (I2C_ADAP_MAX == j) {
- printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n",
- prev->name);
- return (struct i2c_client *) -ENODEV;
-- }
--
-+ }
-+
- for(i=0; i < I2C_CLIENT_MAX; i++)
- if(prev == adapters[j]->clients[i])
- break;
--
-+
- /* invalid starting point? */
- if (I2C_CLIENT_MAX == i) {
- printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n",
- prev->name);
- return (struct i2c_client *) -ENODEV;
-- }
--
-+ }
-+
- i++; /* start from one after prev */
- }
--
-+
- for(; j < I2C_ADAP_MAX; j++)
- {
- if(!adapters[j])
- continue;
--
-+
- if(adapter_id && (adapters[j]->id != adapter_id))
- continue;
--
-+
- for(; i < I2C_CLIENT_MAX; i++)
- {
- if(!adapters[j]->clients[i])
- continue;
--
-+
- if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
- continue;
-- if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
-+ if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
- return adapters[j]->clients[i];
- }
- i = 0;
-@@ -549,12 +549,12 @@
- int i2c_use_client(struct i2c_client *client)
- {
- if(client->flags & I2C_CLIENT_ALLOW_USE) {
-- if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
-+ if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
- client->usage_count++;
- else {
-- if(client->usage_count > 0)
-+ if(client->usage_count > 0)
- return -EBUSY;
-- else
-+ else
- client->usage_count++;
- }
- }
-@@ -575,9 +575,9 @@
- return -EPERM;
- }
- }
--
-+
- i2c_dec_use_client(client);
--
-+
- return 0;
- }
-
-@@ -589,7 +589,7 @@
- #ifdef CONFIG_PROC_FS
-
- /* This function generates the output for /proc/bus/i2c */
--int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
-+int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
- void *private)
- {
- int i;
-@@ -615,7 +615,7 @@
- }
-
- /* This function generates the output for /proc/bus/i2c-? */
--ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
-+ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
- loff_t *ppos)
- {
- struct inode * inode = file->f_dentry->d_inode;
-@@ -626,7 +626,7 @@
- int order[I2C_CLIENT_MAX];
-
- if (count > 4000)
-- return -EINVAL;
-+ return -EINVAL;
- len_total = file->f_pos + count;
- /* Too bad if this gets longer (unlikely) */
- if (len_total > 4000)
-@@ -641,12 +641,12 @@
- sorted by address */
- order_nr=0;
- for (j = 0; j < I2C_CLIENT_MAX; j++) {
-- if ((client = adapters[i]->clients[j]) &&
-+ if ((client = adapters[i]->clients[j]) &&
- (client->driver->id != I2C_DRIVERID_I2CDEV)) {
-- for(k = order_nr;
-- (k > 0) &&
-+ for(k = order_nr;
-+ (k > 0) &&
- adapters[i]->clients[order[k-1]]->
-- addr > client->addr;
-+ addr > client->addr;
- k--)
- order[k] = order[k-1];
- order[k] = j;
-@@ -665,7 +665,7 @@
- len = len - file->f_pos;
- if (len > count)
- len = count;
-- if (len < 0)
-+ if (len < 0)
- len = 0;
- if (copy_to_user (buf,kbuf+file->f_pos, len)) {
- kfree(kbuf);
-@@ -689,7 +689,7 @@
- printk("i2c-core.o: /proc/bus/ does not exist");
- i2cproc_cleanup();
- return -ENOENT;
-- }
-+ }
- proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
- if (!proc_bus_i2c) {
- printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
-@@ -702,14 +702,13 @@
- return 0;
- }
-
--int i2cproc_cleanup(void)
-+static void i2cproc_cleanup(void)
- {
-
- if (i2cproc_initialized >= 1) {
- remove_proc_entry("i2c",proc_bus);
- i2cproc_initialized -= 2;
- }
-- return 0;
- }
-
-
-@@ -751,10 +750,10 @@
- msg.flags = client->flags & I2C_M_TEN;
- msg.len = count;
- (const char *)msg.buf = buf;
--
-+
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
- count,client->adapter->name));
--
-+
- I2C_LOCK(adap);
- ret = adap->algo->master_xfer(adap,&msg,1);
- I2C_UNLOCK(adap);
-@@ -784,14 +783,14 @@
-
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
- count,client->adapter->name));
--
-+
- I2C_LOCK(adap);
- ret = adap->algo->master_xfer(adap,&msg,1);
- I2C_UNLOCK(adap);
--
-+
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
- ret, count, client->addr));
--
-+
- /* if everything went ok (i.e. 1 msg transmitted), return #bytes
- * transmitted, else error code.
- */
-@@ -852,7 +851,7 @@
- found = 0;
-
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
-- if (((adap_id == address_data->force[i]) ||
-+ if (((adap_id == address_data->force[i]) ||
- (address_data->force[i] == ANY_I2C_BUS)) &&
- (addr == address_data->force[i+1])) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",
-@@ -862,7 +861,7 @@
- found = 1;
- }
- }
-- if (found)
-+ if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about
-@@ -870,7 +869,7 @@
- for (i = 0;
- !found && (address_data->ignore[i] != I2C_CLIENT_END);
- i += 2) {
-- if (((adap_id == address_data->ignore[i]) ||
-+ if (((adap_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == ANY_I2C_BUS))) &&
- (addr == address_data->ignore[i+1])) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "
-@@ -890,11 +889,11 @@
- found = 1;
- }
- }
-- if (found)
-+ if (found)
- continue;
-
-- /* Now, we will do a detection, but only if it is in the normal or
-- probe entries */
-+ /* Now, we will do a detection, but only if it is in the normal or
-+ probe entries */
- for (i = 0;
- !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
- i += 1) {
-@@ -939,7 +938,7 @@
- "addr %04x\n", adap_id,addr));
- }
- }
-- if (!found)
-+ if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
-@@ -1087,11 +1086,11 @@
- I2C_SMBUS_I2C_BLOCK_DATA,&data);
- }
-
--/* Simulate a SMBus command using the i2c protocol
-+/* Simulate a SMBus command using the i2c protocol
- No checking of parameters is done! */
--static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
-+static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
- unsigned short flags,
-- char read_write, u8 command, int size,
-+ char read_write, u8 command, int size,
- union i2c_smbus_data * data)
- {
- /* So we need to generate a series of msgs. In the case of writing, we
-@@ -1101,7 +1100,7 @@
- unsigned char msgbuf0[34];
- unsigned char msgbuf1[34];
- int num = read_write == I2C_SMBUS_READ?2:1;
-- struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
-+ struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
- { addr, flags | I2C_M_RD, 0, msgbuf1 }
- };
- int i;
-@@ -1179,7 +1178,7 @@
- case I2C_SMBUS_BYTE_DATA:
- data->byte = msgbuf1[0];
- break;
-- case I2C_SMBUS_WORD_DATA:
-+ case I2C_SMBUS_WORD_DATA:
- case I2C_SMBUS_PROC_CALL:
- data->word = msgbuf1[0] | (msgbuf1[1] << 8);
- break;
-@@ -1189,7 +1188,7 @@
-
-
- s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
-- char read_write, u8 command, int size,
-+ char read_write, u8 command, int size,
- union i2c_smbus_data * data)
- {
- s32 res;
-@@ -1207,7 +1206,7 @@
-
-
- /* You should always define `functionality'; the 'else' is just for
-- backward compatibility. */
-+ backward compatibility. */
- u32 i2c_get_functionality (struct i2c_adapter *adap)
- {
- if (adap->algo->functionality)
-@@ -1233,122 +1232,12 @@
-
- init_MUTEX(&adap_lock);
- init_MUTEX(&driver_lock);
--
-- i2cproc_init();
--
-- return 0;
--}
--
--#ifndef MODULE
--#ifdef CONFIG_I2C_CHARDEV
-- extern int i2c_dev_init(void);
--#endif
--#ifdef CONFIG_I2C_ALGOBIT
-- extern int i2c_algo_bit_init(void);
--#endif
--#ifdef CONFIG_I2C_PHILIPSPAR
-- extern int i2c_bitlp_init(void);
--#endif
--#ifdef CONFIG_I2C_ELV
-- extern int i2c_bitelv_init(void);
--#endif
--#ifdef CONFIG_I2C_VELLEMAN
-- extern int i2c_bitvelle_init(void);
--#endif
--#ifdef CONFIG_I2C_BITVIA
-- extern int i2c_bitvia_init(void);
--#endif
-
--#ifdef CONFIG_I2C_ALGOPCF
-- extern int i2c_algo_pcf_init(void);
--#endif
--#ifdef CONFIG_I2C_ELEKTOR
-- extern int i2c_pcfisa_init(void);
--#endif
--
--#ifdef CONFIG_I2C_ALGO8XX
-- extern int i2c_algo_8xx_init(void);
--#endif
--#ifdef CONFIG_I2C_RPXLITE
-- extern int i2c_rpx_init(void);
--#endif
--
--#ifdef CONFIG_I2C_ALGO_SIBYTE
-- extern int i2c_algo_sibyte_init(void);
-- extern int i2c_sibyte_init(void);
--#endif
--#ifdef CONFIG_I2C_MAX1617
-- extern int i2c_max1617_init(void);
--#endif
--
--#ifdef CONFIG_I2C_PROC
-- extern int sensors_init(void);
--#endif
--
--/* This is needed for automatic patch generation: sensors code starts here */
--/* This is needed for automatic patch generation: sensors code ends here */
--
--int __init i2c_init_all(void)
--{
-- /* --------------------- global ----- */
-- i2c_init();
--
--#ifdef CONFIG_I2C_CHARDEV
-- i2c_dev_init();
--#endif
-- /* --------------------- bit -------- */
--#ifdef CONFIG_I2C_ALGOBIT
-- i2c_algo_bit_init();
--#endif
--#ifdef CONFIG_I2C_PHILIPSPAR
-- i2c_bitlp_init();
--#endif
--#ifdef CONFIG_I2C_ELV
-- i2c_bitelv_init();
--#endif
--#ifdef CONFIG_I2C_VELLEMAN
-- i2c_bitvelle_init();
--#endif
--
-- /* --------------------- pcf -------- */
--#ifdef CONFIG_I2C_ALGOPCF
-- i2c_algo_pcf_init();
--#endif
--#ifdef CONFIG_I2C_ELEKTOR
-- i2c_pcfisa_init();
--#endif
--
-- /* --------------------- 8xx -------- */
--#ifdef CONFIG_I2C_ALGO8XX
-- i2c_algo_8xx_init();
--#endif
--#ifdef CONFIG_I2C_RPXLITE
-- i2c_rpx_init();
--#endif
--
-- /* --------------------- SiByte -------- */
--#ifdef CONFIG_I2C_ALGO_SIBYTE
-- i2c_algo_sibyte_init();
-- i2c_sibyte_init();
--#endif
--#ifdef CONFIG_I2C_MAX1617
-- i2c_max1617_init();
--#endif
--
-- /* -------------- proc interface ---- */
--#ifdef CONFIG_I2C_PROC
-- sensors_init();
--#endif
--/* This is needed for automatic patch generation: sensors code starts here */
--/* This is needed for automatic patch generation: sensors code ends here */
-+ i2cproc_init();
-
- return 0;
- }
-
--#endif
--
--
--
- EXPORT_SYMBOL(i2c_add_adapter);
- EXPORT_SYMBOL(i2c_del_adapter);
- EXPORT_SYMBOL(i2c_add_driver);
-@@ -1385,7 +1274,6 @@
- EXPORT_SYMBOL(i2c_get_functionality);
- EXPORT_SYMBOL(i2c_check_functionality);
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus main module");
- MODULE_LICENSE("GPL");
-@@ -1393,13 +1281,5 @@
- MODULE_PARM(i2c_debug, "i");
- MODULE_PARM_DESC(i2c_debug,"debug level");
-
--int init_module(void)
--{
-- return i2c_init();
--}
--
--void cleanup_module(void)
--{
-- i2cproc_cleanup();
--}
--#endif
-+module_init(i2c_init);
-+module_exit(i2cproc_cleanup);
---- linux-2.4.25/drivers/i2c/i2c-dev.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-dev.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- i2c-dev.c - i2c-bus driver, char device interface
-+ i2c-dev.c - i2c-bus driver, char device interface
-
- Copyright (C) 1995-97 Simon G. Vogl
- Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
-@@ -25,7 +25,7 @@
-
- /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-
--/* The devfs code is contributed by Philipp Matthias Hahn
-+/* The devfs code is contributed by Philipp Matthias Hahn
- <pmhahn@titan.lahn.de> */
-
- /* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */
-@@ -50,19 +50,14 @@
- #include <linux/i2c.h>
- #include <linux/i2c-dev.h>
-
--#ifdef MODULE
--extern int init_module(void);
--extern int cleanup_module(void);
--#endif /* def MODULE */
--
- /* struct file_operations changed too often in the 2.1 series for nice code */
-
--static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
-+static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
- loff_t *offset);
--static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
-+static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
- loff_t *offset);
-
--static int i2cdev_ioctl (struct inode *inode, struct file *file,
-+static int i2cdev_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
- static int i2cdev_open (struct inode *inode, struct file *file);
-
-@@ -73,13 +68,8 @@
- static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
-
--#ifdef MODULE
--static
--#else
--extern
--#endif
-- int __init i2c_dev_init(void);
--static int i2cdev_cleanup(void);
-+static int __init i2c_dev_init(void);
-+static void i2cdev_cleanup(void);
-
- static struct file_operations i2cdev_fops = {
- owner: THIS_MODULE,
-@@ -185,7 +175,7 @@
- return ret;
- }
-
--int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-+int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
- {
- struct i2c_client *client = (struct i2c_client *)file->private_data;
-@@ -198,14 +188,14 @@
- unsigned long funcs;
-
- #ifdef DEBUG
-- printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
-+ printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
- MINOR(inode->i_rdev),cmd, arg);
- #endif /* DEBUG */
-
- switch ( cmd ) {
- case I2C_SLAVE:
- case I2C_SLAVE_FORCE:
-- if ((arg > 0x3ff) ||
-+ if ((arg > 0x3ff) ||
- (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
- return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
-@@ -224,8 +214,8 @@
- sizeof(unsigned long)))?-EFAULT:0;
-
- case I2C_RDWR:
-- if (copy_from_user(&rdwr_arg,
-- (struct i2c_rdwr_ioctl_data *)arg,
-+ if (copy_from_user(&rdwr_arg,
-+ (struct i2c_rdwr_ioctl_data *)arg,
- sizeof(rdwr_arg)))
- return -EFAULT;
-
-@@ -233,9 +223,9 @@
- * be sent at once */
- if (rdwr_arg.nmsgs > 42)
- return -EINVAL;
--
-+
- rdwr_pa = (struct i2c_msg *)
-- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
-+ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
- GFP_KERNEL);
-
- if (rdwr_pa == NULL) return -ENOMEM;
-@@ -312,9 +302,9 @@
- (struct i2c_smbus_ioctl_data *) arg,
- sizeof(struct i2c_smbus_ioctl_data)))
- return -EFAULT;
-- if ((data_arg.size != I2C_SMBUS_BYTE) &&
-+ if ((data_arg.size != I2C_SMBUS_BYTE) &&
- (data_arg.size != I2C_SMBUS_QUICK) &&
-- (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
-+ (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
- (data_arg.size != I2C_SMBUS_WORD_DATA) &&
- (data_arg.size != I2C_SMBUS_PROC_CALL) &&
- (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
-@@ -325,9 +315,9 @@
- #endif
- return -EINVAL;
- }
-- /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
-+ /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
- so the check is valid if size==I2C_SMBUS_QUICK too. */
-- if ((data_arg.read_write != I2C_SMBUS_READ) &&
-+ if ((data_arg.read_write != I2C_SMBUS_READ) &&
- (data_arg.read_write != I2C_SMBUS_WRITE)) {
- #ifdef DEBUG
- printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
-@@ -339,7 +329,7 @@
- /* Note that command values are always valid! */
-
- if ((data_arg.size == I2C_SMBUS_QUICK) ||
-- ((data_arg.size == I2C_SMBUS_BYTE) &&
-+ ((data_arg.size == I2C_SMBUS_BYTE) &&
- (data_arg.read_write == I2C_SMBUS_WRITE)))
- /* These are special: we do not use data */
- return i2c_smbus_xfer(client->adapter, client->addr,
-@@ -358,13 +348,13 @@
- if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
- (data_arg.size == I2C_SMBUS_BYTE))
- datasize = sizeof(data_arg.data->byte);
-- else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
-+ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
- (data_arg.size == I2C_SMBUS_PROC_CALL))
- datasize = sizeof(data_arg.data->word);
- else /* size == I2C_SMBUS_BLOCK_DATA */
- datasize = sizeof(data_arg.data->block);
-
-- if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-+ if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_WRITE)) {
- if (copy_from_user(&temp, data_arg.data, datasize))
- return -EFAULT;
-@@ -372,7 +362,7 @@
- res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- data_arg.read_write,
- data_arg.command,data_arg.size,&temp);
-- if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-+ if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_READ))) {
- if (copy_to_user(data_arg.data, &temp, datasize))
- return -EFAULT;
-@@ -479,7 +469,7 @@
- return -1;
- }
-
--int __init i2c_dev_init(void)
-+static int __init i2c_dev_init(void)
- {
- int res;
-
-@@ -509,7 +499,7 @@
- return 0;
- }
-
--int i2cdev_cleanup(void)
-+static void i2cdev_cleanup(void)
- {
- int res;
-
-@@ -517,9 +507,9 @@
- if ((res = i2c_del_driver(&i2cdev_driver))) {
- printk("i2c-dev.o: Driver deregistration failed, "
- "module not removed.\n");
-- return res;
-+ return;
- }
-- i2cdev_initialized --;
-+ i2cdev_initialized --;
- }
-
- if (i2cdev_initialized >= 1) {
-@@ -531,30 +521,17 @@
- #endif
- printk("i2c-dev.o: unable to release major %d for i2c bus\n",
- I2C_MAJOR);
-- return res;
-+ return;
- }
- i2cdev_initialized --;
- }
-- return 0;
- }
-
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
--
- MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C /dev entries driver");
- MODULE_LICENSE("GPL");
-
--int init_module(void)
--{
-- return i2c_dev_init();
--}
--
--int cleanup_module(void)
--{
-- return i2cdev_cleanup();
--}
--
--#endif /* def MODULE */
--
-+module_init(i2c_dev_init);
-+module_exit(i2cdev_cleanup);
---- linux-2.4.25/drivers/i2c/i2c-elektor.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-elektor.c 2004-03-31 17:15:09.000000000 +0200
-@@ -181,16 +181,12 @@
-
- static void pcf_isa_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void pcf_isa_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
-
-@@ -219,7 +215,7 @@
- pcf_isa_unreg,
- };
-
--int __init i2c_pcfisa_init(void)
-+static int __init i2c_pcfisa_init(void)
- {
- #ifdef __alpha__
- /* check to see we have memory mapped PCF8584 connected to the
-@@ -289,10 +285,14 @@
- return 0;
- }
-
-+static void i2c_pcfisa_exit(void)
-+{
-+ i2c_pcf_del_bus(&pcf_isa_ops);
-+ pcf_isa_exit();
-+}
-
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
- MODULE_LICENSE("GPL");
-@@ -304,15 +304,5 @@
- MODULE_PARM(mmapped, "i");
- MODULE_PARM(i2c_debug, "i");
-
--int init_module(void)
--{
-- return i2c_pcfisa_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_pcf_del_bus(&pcf_isa_ops);
-- pcf_isa_exit();
--}
--
--#endif
-+module_init(i2c_pcfisa_init);
-+module_exit(i2c_pcfisa_exit);
---- linux-2.4.25/drivers/i2c/i2c-elv.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-elv.c 2004-03-31 17:15:09.000000000 +0200
-@@ -75,7 +75,7 @@
- PortData |=2;
- }
- outb(PortData, DATA);
--}
-+}
-
- static int bit_elv_getscl(void *data)
- {
-@@ -90,7 +90,7 @@
- static int bit_elv_init(void)
- {
- if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
-- return -ENODEV;
-+ return -ENODEV;
- } else {
- /* test for ELV adap. */
- if (inb(base+1) & 0x80) { /* BUSY should be high */
-@@ -131,16 +131,12 @@
-
- static void bit_elv_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void bit_elv_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
- /* ------------------------------------------------------------------------
-@@ -164,10 +160,10 @@
- bit_elv_inc_use,
- bit_elv_dec_use,
- bit_elv_reg,
-- bit_elv_unreg,
-+ bit_elv_unreg,
- };
-
--int __init i2c_bitelv_init(void)
-+static int __init i2c_bitelv_init(void)
- {
- printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (base==0) {
-@@ -194,24 +190,19 @@
- }
-
-
-+static void __exit i2c_bitelv_exit(void)
-+{
-+ i2c_bit_del_bus(&bit_elv_ops);
-+ bit_elv_exit();
-+}
-+
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
- MODULE_LICENSE("GPL");
-
- MODULE_PARM(base, "i");
-
--int init_module(void)
--{
-- return i2c_bitelv_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bit_del_bus(&bit_elv_ops);
-- bit_elv_exit();
--}
--
--#endif
-+module_init(i2c_bitelv_init);
-+module_exit(i2c_bitelv_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-frodo.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,114 @@
-+
-+/*
-+ * linux/drivers/i2c/i2c-frodo.c
-+ *
-+ * Author: Abraham van der Merwe <abraham@2d3d.co.za>
-+ *
-+ * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
-+ * Development board (Frodo).
-+ *
-+ * This source code is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * version 2 as published by the Free Software Foundation.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/version.h>
-+#include <linux/module.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/hardware.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+static void frodo_setsda (void *data,int state)
-+{
-+ if (state)
-+ frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
-+ else
-+ frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
-+}
-+
-+static void frodo_setscl (void *data,int state)
-+{
-+ if (state)
-+ frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
-+ else
-+ frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
-+}
-+
-+static int frodo_getsda (void *data)
-+{
-+ return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SDA_IN) != 0);
-+}
-+
-+static int frodo_getscl (void *data)
-+{
-+ return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SCL_IN) != 0);
-+}
-+
-+static struct i2c_algo_bit_data bit_frodo_data = {
-+ setsda: frodo_setsda,
-+ setscl: frodo_setscl,
-+ getsda: frodo_getsda,
-+ getscl: frodo_getscl,
-+ udelay: 80,
-+ mdelay: 80,
-+ timeout: 100
-+};
-+
-+static int frodo_client_register (struct i2c_client *client)
-+{
-+ return (0);
-+}
-+
-+static int frodo_client_unregister (struct i2c_client *client)
-+{
-+ return (0);
-+}
-+
-+static void frodo_inc_use (struct i2c_adapter *adapter)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void frodo_dec_use (struct i2c_adapter *adapter)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static struct i2c_adapter frodo_ops = {
-+ name: "Frodo adapter driver",
-+ id: I2C_HW_B_FRODO,
-+ algo: NULL,
-+ algo_data: &bit_frodo_data,
-+ inc_use: frodo_inc_use,
-+ dec_use: frodo_dec_use,
-+ client_register: frodo_client_register,
-+ client_unregister: frodo_client_unregister
-+};
-+
-+static int __init i2c_frodo_init (void)
-+{
-+ return (i2c_bit_add_bus (&frodo_ops));
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+static void __exit i2c_frodo_exit (void)
-+{
-+ i2c_bit_del_bus (&frodo_ops);
-+}
-+
-+MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
-+MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
-+MODULE_LICENSE ("GPL");
-+EXPORT_NO_SYMBOLS;
-+
-+module_init (i2c_frodo_init);
-+module_exit (i2c_frodo_exit);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-guide.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,199 @@
-+/************************************************************************************\
-+Copyright : Copyright (C) 1995-2000 Simon G. Vogl
-+ Copyright 2002 IDERs Incorporated
-+File Name : i2c-guide.c
-+Description : this i2c driver uses the GPIO port B pin 0 and pin 1 on the cs89712.
-+Notes : To change the bit rate, change the structure i2c_algo_bit_data
-+ : to 10 10 100
-+Contact : tsong@iders.ca
-+License : This source code is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License
-+ version 2 as published by the Free Software Foundation.
-+\************************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <linux/ioport.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/string.h> /* for 2.0 kernels to get NULL */
-+#include <asm/errno.h> /* for 2.0 kernels to get ENODEV */
-+#include <asm/io.h>
-+
-+#include <asm/hardware/cs89712.h> // io operation ep_writel()
-+#include <asm/hardware/clps7111.h> // io operation clps_writel()
-+#include <asm/arch-clps711x/hardware.h> // io operation clps_writel()
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+/* ----- global defines ----------------------------------------------- */
-+
-+#define DEB(x) /* should be reasonable open, close &c. */
-+#define DEB2(x) /* low level debugging - very slow */
-+#define DEBE(x) x /* error messages */
-+ /* Pin Port Inverted name */
-+#define I2C_SDA 0x08 /* port B ctrl pin 3 (inv) */
-+#define I2C_SCL 0x04 /* port B ctrl pin 2 (inv) */
-+
-+#define I2C_SDAIN 0x08 /* use the same pin with output */
-+#define I2C_SCLIN 0x04 /* use the same pin with output */
-+
-+#define I2C_DMASK 0xf7 /* inverse of I2C_SDA */
-+#define I2C_CMASK 0xfb /* inverse of I2c_SCL */
-+
-+#define PORTB_PIN0_SDA_OUTPUT 0x08 /* pin 3 direction of port B output */
-+#define PORTB_PIN0_SDA_INPUT 0xf7 /* pin 3 direction of port B input */
-+
-+#define PORTB_PIN1_SCL_OUTPUT 0x04 /* pin 2 direction of port B output */
-+#define PORTB_PIN1_SCL_INPUT 0xfb /* pin 2 direction of port B input */
-+
-+int base = 0;
-+#define DEFAULT_BASE PBDR
-+
-+/* ----- local functions --------------------------------------------------- */
-+
-+static void bit_guide_setscl(void* data, int state)
-+{
-+ if (state) {
-+ // set port B pin2 input
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN1_SCL_INPUT, PBDDR);
-+ }
-+ else {
-+ // clear
-+ clps_writeb((clps_readb(PBDR)) & I2C_CMASK, PBDR);
-+ // set port B pin2 output
-+ clps_writeb((clps_readb(PBDDR)) | PORTB_PIN1_SCL_OUTPUT, PBDDR);
-+ }
-+}
-+
-+static void bit_guide_setsda(void* data, int state)
-+{
-+ if (state) {
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
-+ // float pin 0 (actually drive high by pull up resistor)
-+ // clps_writeb((clps_readb(PBDR)) | I2C_SDA, PBDR); // set Jan4 ori: eff
-+ // printk("set sda high, state=%i\n",state);
-+ }
-+ else {
-+ // clear
-+ clps_writeb((clps_readb(PBDR)) & I2C_DMASK, PBDR);
-+ // set port B pin 0 output
-+ clps_writeb((clps_readb(PBDDR)) | PORTB_PIN0_SDA_OUTPUT, PBDDR);
-+ }
-+}
-+
-+static int bit_guide_getscl(void *data)
-+{
-+ return ( 0 != ( (clps_readb(PBDR)) & I2C_SCLIN ) );
-+}
-+
-+static int bit_guide_getsda(void *data)
-+{
-+ // set port B pin 0 input Jan4 ori eff
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
-+ return ( 0 != ( (clps_readb(PBDR) ) & I2C_SDAIN ) );
-+}
-+
-+static int bit_guide_init(void)
-+{
-+ bit_guide_setsda((void*)base,1);
-+ bit_guide_setscl((void*)base,1);
-+ return 0;
-+}
-+
-+static int bit_guide_reg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static int bit_guide_unreg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static void bit_guide_inc_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_INC_USE_COUNT;
-+#endif
-+}
-+
-+static void bit_guide_dec_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_DEC_USE_COUNT;
-+#endif
-+}
-+
-+/* ------------------------------------------------------------------------
-+ * Encapsulate the above functions in the correct operations structure.
-+ * This is only done when more than one hardware adapter is supported.
-+ */
-+
-+/* last line (us, ms, timout)
-+ * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps)
-+ * 10ms not known
-+ * 100ms timeout
-+ */
-+static struct i2c_algo_bit_data bit_guide_data = {
-+ NULL,
-+ bit_guide_setsda,
-+ bit_guide_setscl,
-+ bit_guide_getsda,
-+ bit_guide_getscl,
-+ 50, 10, 100, /* orginal (non-guide) value 10, 10, 100 */
-+};
-+
-+static struct i2c_adapter bit_guide_ops = {
-+ "Guide Port B: PIN2-SCL/PIN3-SDA",
-+ I2C_HW_B_GUIDE,
-+ NULL,
-+ &bit_guide_data,
-+ bit_guide_inc_use,
-+ bit_guide_dec_use,
-+ bit_guide_reg,
-+ bit_guide_unreg,
-+};
-+
-+static int __init i2c_bitguide_init(void)
-+{
-+ printk("i2c-guide.o: Guide i2c port B adapter module.\n");
-+ clps_writeb((clps_readb(PBDDR)) & 0xfd, PBDDR); // set service reuest pb1 as input
-+ if (base==0) {
-+ /* probe some values */
-+ base=DEFAULT_BASE;
-+ bit_guide_data.data=(void*)DEFAULT_BASE;
-+ if (bit_guide_init()==0) {
-+ if(i2c_bit_add_bus(&bit_guide_ops) < 0)
-+ return -ENODEV;
-+ } else {
-+ return -ENODEV;
-+ }
-+ } else {
-+ bit_guide_data.data=(void*)base;
-+ if (bit_guide_init()==0) {
-+ if(i2c_bit_add_bus(&bit_guide_ops) < 0)
-+ return -ENODEV;
-+ } else {
-+ return -ENODEV;
-+ }
-+ }
-+ printk("i2c-guide.o: found device at %#x.\n",base);
-+ return 0;
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("T. C. Song <tsong@iders.ca>");
-+MODULE_DESCRIPTION("I2C-Bus adapter routines for Guide (cs89712) GPIO port B");
-+MODULE_LICENSE("GPL");
-+
-+MODULE_PARM(base, "i");
-+
-+module_init(i2c_bitguide_init);
-+/* for completeness, we should have a module_exit() function, but the
-+ GUIDE requires this to always be loaded. If it is unloaded, the
-+ operation of the GUIDE is undefined.
-+ Nobody has written the i2c_bitguide_exit() routine yet, so it is not included.
-+module_exit(i2c_bitguide_exit);
-+*/
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/i2c/i2c-omaha.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,276 @@
-+/* ------------------------------------------------------------------------- *
-+ Copyright ARM Limited 2002. All rights reserved.
-+
-+ i2c driver for Omaha
-+
-+ Notes:Based on i2c-elv.c
-+
-+ The S3C2400X01 has better support for I2C, but bit oriented operations
-+ are directly supported by the other I2C layers, so we use that method
-+ of performing I2C operations.
-+
-+ Copyright (C) 1995-2000 Simon G. Vogl
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-+/* ------------------------------------------------------------------------- */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <linux/ioport.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+
-+/* ----- global defines ----------------------------------------------- */
-+#define DEB(x) if (i2c_debug>=1) x;
-+#define DEB2(x) if (i2c_debug>=2) x;
-+#define DEB3(x) if (i2c_debug>=3) x
-+#define DEBE(x) x // error messages
-+#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
-+#define DEBPROTO(x) if (i2c_debug>=9) { x; }
-+ /* debug the protocol by showing transferred bits */
-+
-+/* Register and bitdefs for Omaha */
-+
-+// Port G control registers
-+static volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
-+static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT);
-+
-+static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR);
-+
-+static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
-+
-+// Open drain control registers
-+#define OPC_CMD BIT2
-+#define OPC_DAT BIT3
-+
-+// data bits in GPIO Port G data register
-+#define OMAHA_SDA BIT5
-+#define OMAHA_SCL BIT6
-+#define IIC_WP BIT3 // Write Protect for EEPROM
-+
-+// input/out select bits in GPIO G control register
-+#define IIC_BITS (BIT12|BIT10|BIT6);
-+
-+
-+/* ----- local functions ---------------------------------------------- */
-+
-+
-+static void bit_omaha_setscl(void *data, int state)
-+{
-+ unsigned int tmp;
-+
-+ if (state)
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp |= OMAHA_SCL;
-+ __raw_writel(tmp,pgdat);
-+ }
-+ else
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp &= ~OMAHA_SCL;
-+ __raw_writel(tmp,pgdat);
-+ }
-+}
-+
-+static void bit_omaha_setsda(void *data, int state)
-+{
-+ unsigned int tmp;
-+
-+ // ensure that sda is an output at the moment
-+ tmp = __raw_readl(pgcon);
-+ tmp = tmp | BIT10;
-+ __raw_writel(tmp,pgcon);
-+
-+ if (state)
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp |= OMAHA_SDA;
-+ __raw_writel(tmp,pgdat);
-+ }
-+ else
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp &= ~OMAHA_SDA;
-+ __raw_writel(tmp,pgdat);
-+ }
-+}
-+
-+static int bit_omaha_getscl(void *data)
-+{
-+ if (__raw_readl(pgdat) & OMAHA_SCL)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int bit_omaha_getsda(void *data)
-+{
-+ unsigned int tmp;
-+
-+ // ensure that sda is an output at the moment
-+ tmp = __raw_readl(pgcon);
-+ tmp = tmp & ~BIT10;
-+ __raw_writel(tmp,pgcon);
-+
-+ if (__raw_readl(pgdat) & OMAHA_SDA)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int bit_omaha_init(void)
-+{
-+ // Have we got some mmapped space?
-+ if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 )
-+ {
-+ printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base);
-+ return -ENODEV;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int bit_omaha_reg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+
-+static int bit_omaha_unreg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static void bit_omaha_inc_use(struct i2c_adapter *adap)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void bit_omaha_dec_use(struct i2c_adapter *adap)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+
-+/* ------------------------------------------------------------------------
-+ * Encapsulate the above functions in the correct operations structure.
-+ * This is only done when more than one hardware adapter is supported.
-+ */
-+static struct i2c_algo_bit_data bit_omaha_data = {
-+ NULL,
-+ bit_omaha_setsda,
-+ bit_omaha_setscl,
-+ bit_omaha_getsda,
-+ bit_omaha_getscl,
-+ 10, 10, 20, /* waits, timeout */
-+};
-+
-+static struct i2c_adapter bit_omaha_ops = {
-+ "BIT-Type Omaha I2C adapter",
-+ I2C_HW_B_OMAHA,
-+ NULL,
-+ &bit_omaha_data,
-+ bit_omaha_inc_use,
-+ bit_omaha_dec_use,
-+ bit_omaha_reg,
-+ bit_omaha_unreg,
-+};
-+
-+static int __init i2c_omaha_init (void)
-+{
-+ unsigned int tmp;
-+
-+ printk("i2c-omaha.o: i2c omaha adapter module\n");
-+
-+ if (bit_omaha_init() == 0) {
-+ if(i2c_bit_add_bus(&bit_omaha_ops) < 0)
-+ {
-+ printk("Could not add bus!\n");
-+ return -ENODEV;
-+ }
-+ } else {
-+ printk("Could not pcf_omaha_init\n");
-+ return -ENODEV;
-+ }
-+
-+ // Program Port G bits to output function
-+ tmp = __raw_readl(pgcon);
-+ tmp |= IIC_BITS;
-+ __raw_writel(tmp,pgcon);
-+
-+ // Ensure SDA and SCL are open-drain
-+ tmp = __raw_readl(opencr);
-+ tmp = tmp | OPC_CMD | OPC_DAT;
-+ __raw_writel(tmp,opencr);
-+
-+ bit_omaha_setsda((void*)base,1);
-+ bit_omaha_setscl((void*)base,1);
-+
-+ // Disable WP
-+ tmp = __raw_readl(pgdat);
-+ tmp = tmp & ~IIC_WP;
-+ __raw_writel(tmp,pgdat);
-+
-+ return 0;
-+}
-+
-+static void bit_omaha_exit(void)
-+{
-+ release_region(base , 2);
-+}
-+
-+static void i2c_omaha_exit(void)
-+{
-+
-+ i2c_bit_del_bus(&bit_omaha_ops);
-+
-+ bit_omaha_exit();
-+
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("ARM Limited <support@arm.com>");
-+MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha");
-+MODULE_LICENSE("GPL");
-+
-+MODULE_PARM(base, "i");
-+MODULE_PARM(irq, "i");
-+MODULE_PARM(clock, "i");
-+MODULE_PARM(own, "i");
-+MODULE_PARM(mmapped, "i");
-+MODULE_PARM(i2c_debug, "i");
-+
-+
-+module_init(i2c_omaha_init);
-+module_exit(i2c_omaha_exit);
-+
-+
---- linux-2.4.25/drivers/i2c/i2c-philips-par.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-philips-par.c 2004-03-31 17:15:09.000000000 +0200
-@@ -16,7 +16,7 @@
- You 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. */
--/* ------------------------------------------------------------------------- */
-+/* ------------------------------------------------------------------------- */
-
- /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
- Frodo Looijaard <frodol@dds.nl> */
-@@ -72,7 +72,7 @@
-
- static void bit_lp_setscl(void *data, int state)
- {
-- /*be cautious about state of the control register -
-+ /*be cautious about state of the control register -
- touch only the one bit needed*/
- if (state) {
- parport_write_control((struct parport *) data,
-@@ -126,7 +126,7 @@
-
- static int bit_lp_getsda2(void *data)
- {
-- return (parport_read_status((struct parport *) data) &
-+ return (parport_read_status((struct parport *) data) &
- PARPORT_STATUS_BUSY) ? 0 : 1;
- }
-
-@@ -154,7 +154,7 @@
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
--
-+
- static struct i2c_algo_bit_data bit_lp_data = {
- NULL,
- bit_lp_setsda,
-@@ -162,7 +162,7 @@
- bit_lp_getsda,
- bit_lp_getscl,
- 80, 80, 100, /* waits, timeout */
--};
-+};
-
- static struct i2c_algo_bit_data bit_lp_data2 = {
- NULL,
-@@ -171,7 +171,7 @@
- bit_lp_getsda2,
- NULL,
- 80, 80, 100, /* waits, timeout */
--};
-+};
-
- static struct i2c_adapter bit_lp_ops = {
- "Philips Parallel port adapter",
-@@ -197,7 +197,7 @@
- printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name);
-
- adapter->pdev = parport_register_device(port, "i2c-philips-par",
-- NULL, NULL, NULL,
-+ NULL, NULL, NULL,
- PARPORT_FLAG_EXCL,
- NULL);
- if (!adapter->pdev) {
-@@ -257,16 +257,16 @@
- NULL
- };
-
--int __init i2c_bitlp_init(void)
-+static int __init i2c_bitlp_init(void)
- {
- printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
-
- parport_register_driver(&i2c_driver);
--
-+
- return 0;
- }
-
--void __exit i2c_bitlp_exit(void)
-+static void __exit i2c_bitlp_exit(void)
- {
- parport_unregister_driver(&i2c_driver);
- }
-@@ -279,14 +279,5 @@
-
- MODULE_PARM(type, "i");
-
--#ifdef MODULE
--int init_module(void)
--{
-- return i2c_bitlp_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bitlp_exit();
--}
--#endif
-+module_init(i2c_bitlp_init);
-+module_exit(i2c_bitlp_exit);
---- linux-2.4.25/drivers/i2c/i2c-velleman.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/i2c/i2c-velleman.c 2004-03-31 17:15:09.000000000 +0200
-@@ -65,7 +65,7 @@
- } else {
- outb(inb(CTRL) | I2C_SCL, CTRL);
- }
--
-+
- }
-
- static void bit_velle_setsda(void *data, int state)
-@@ -75,8 +75,8 @@
- } else {
- outb(inb(CTRL) | I2C_SDA, CTRL);
- }
--
--}
-+
-+}
-
- static int bit_velle_getscl(void *data)
- {
-@@ -95,7 +95,7 @@
- base));
- return -ENODEV;
- } else {
-- request_region(base, (base == 0x3bc)? 3 : 8,
-+ request_region(base, (base == 0x3bc)? 3 : 8,
- "i2c (Vellemann adapter)");
- bit_velle_setsda((void*)base,1);
- bit_velle_setscl((void*)base,1);
-@@ -104,7 +104,7 @@
- }
-
- static void __exit bit_velle_exit(void)
--{
-+{
- release_region( base , (base == 0x3bc)? 3 : 8 );
- }
-
-@@ -121,16 +121,12 @@
-
- static void bit_velle_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void bit_velle_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
- /* ------------------------------------------------------------------------
-@@ -158,7 +154,7 @@
- bit_velle_unreg,
- };
-
--int __init i2c_bitvelle_init(void)
-+static int __init i2c_bitvelle_init(void)
- {
- printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (base==0) {
-@@ -184,24 +180,19 @@
- return 0;
- }
-
-+static void __exit i2c_bitvelle_exit(void)
-+{
-+ i2c_bit_del_bus(&bit_velle_ops);
-+ bit_velle_exit();
-+}
-+
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
- MODULE_LICENSE("GPL");
-
- MODULE_PARM(base, "i");
-
--int init_module(void)
--{
-- return i2c_bitvelle_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bit_del_bus(&bit_velle_ops);
-- bit_velle_exit();
--}
--
--#endif
-+module_init(i2c_bitvelle_init);
-+module_exit(i2c_bitvelle_exit);
---- linux-2.4.25/drivers/ide/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/ide/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -106,6 +106,9 @@
- define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS
- dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
- fi
-+ if [ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
-+ dep_bool ' RiscStation IDE' CONFIG_BLK_DEV_IDE_RISCSTATION $CONFIG_ARCH_RISCSTATION
-+ fi
- if [ "$CONFIG_AMIGA" = "y" ]; then
- dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
- dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
---- linux-2.4.25/drivers/ide/arm/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
-+++ linux-2.4.25/drivers/ide/arm/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -6,6 +6,7 @@
-
- obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
- obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
-+obj-$(CONFIG_BLK_DEV_IDE_RISCSTATION) += rstation-ide.o
-
- EXTRA_CFLAGS := -I../
-
---- linux-2.4.25/drivers/ide/arm/icside.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
-+++ linux-2.4.25/drivers/ide/arm/icside.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1,7 +1,7 @@
- /*
- * linux/drivers/ide/arm/icside.c
- *
-- * Copyright (c) 1996,1997 Russell King.
-+ * Copyright (c) 1996-2003 Russell King.
- *
- * Changelog:
- * 08-Jun-1996 RMK Created
-@@ -26,24 +26,6 @@
- #include <asm/ecard.h>
- #include <asm/io.h>
-
--#include "ide-noise.h"
--
--/*
-- * FIXME: We want to drop the the MACRO CRAP!
-- *
-- * ec->iops->in{b/w/l}
-- * ec->iops->in{b/w/l}_p
-- * ec->iops->out{b/w/l}
-- * ec->iops->out{b/w/l}_p
-- *
-- * the new core supports clean MMIO calls and other goodies
-- */
--
--/*
-- * Maximum number of interfaces per card
-- */
--#define MAX_IFS 2
--
- #define ICS_IDENT_OFFSET 0x8a0
-
- #define ICS_ARCIN_V5_INTRSTAT 0x000
-@@ -86,17 +68,20 @@
- ICS_ARCIN_V6_IDESTEPPING
- };
-
--static const card_ids icside_cids[] = {
-- { MANU_ICS, PROD_ICS_IDE },
-- { MANU_ICS2, PROD_ICS2_IDE },
-- { 0xffff, 0xffff }
-+struct icside_state {
-+ unsigned int channel;
-+ unsigned int enabled;
-+ unsigned long irq_port;
-+ unsigned long slot_port;
-+ unsigned int type;
-+ ide_hwif_t *hwif[2];
- };
-
--typedef enum {
-- ics_if_unknown,
-- ics_if_arcin_v5,
-- ics_if_arcin_v6
--} iftype_t;
-+#define ICS_TYPE_A3IN 0
-+#define ICS_TYPE_A3USER 1
-+#define ICS_TYPE_V6 3
-+#define ICS_TYPE_V5 15
-+#define ICS_TYPE_NOTYPE ((unsigned int)-1)
-
- /* ---------------- Version 5 PCB Support Functions --------------------- */
- /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
-@@ -104,8 +89,10 @@
- */
- static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int memc_port = (unsigned int)ec->irq_data;
-- outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET);
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-+
-+ outb(0, base + ICS_ARCIN_V5_INTROFFSET);
- }
-
- /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
-@@ -113,17 +100,15 @@
- */
- static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int memc_port = (unsigned int)ec->irq_data;
-- inb(memc_port + ICS_ARCIN_V5_INTROFFSET);
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-+
-+ inb(base + ICS_ARCIN_V5_INTROFFSET);
- }
-
- static const expansioncard_ops_t icside_ops_arcin_v5 = {
-- icside_irqenable_arcin_v5,
-- icside_irqdisable_arcin_v5,
-- NULL,
-- NULL,
-- NULL,
-- NULL
-+ .irqenable = icside_irqenable_arcin_v5,
-+ .irqdisable = icside_irqdisable_arcin_v5,
- };
-
-
-@@ -133,10 +118,21 @@
- */
- static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-
-- outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
-- outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ state->enabled = 1;
-+
-+ switch (state->channel) {
-+ case 0:
-+ outb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(base + ICS_ARCIN_V6_INTROFFSET_2);
-+ break;
-+ case 1:
-+ outb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(base + ICS_ARCIN_V6_INTROFFSET_1);
-+ break;
-+ }
- }
-
- /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
-@@ -144,10 +140,12 @@
- */
- static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-
-- inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
-- inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ state->enabled = 0;
-+
-+ inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
- }
-
- /* Prototype: icside_irqprobe(struct expansion_card *ec)
-@@ -155,70 +153,49 @@
- */
- static int icside_irqpending_arcin_v6(struct expansion_card *ec)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-
-- return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-- inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
-+ return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-+ inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
- }
-
- static const expansioncard_ops_t icside_ops_arcin_v6 = {
-- icside_irqenable_arcin_v6,
-- icside_irqdisable_arcin_v6,
-- icside_irqpending_arcin_v6,
-- NULL,
-- NULL,
-- NULL
-+ .irqenable = icside_irqenable_arcin_v6,
-+ .irqdisable = icside_irqdisable_arcin_v6,
-+ .irqpending = icside_irqpending_arcin_v6,
- };
-
--/* Prototype: icside_identifyif (struct expansion_card *ec)
-- * Purpose : identify IDE interface type
-- * Notes : checks the description string
-+/*
-+ * Handle routing of interrupts. This is called before
-+ * we write the command to the drive.
- */
--static iftype_t __init icside_identifyif (struct expansion_card *ec)
-+static void icside_maskproc(ide_drive_t *drive, int mask)
- {
-- unsigned int addr;
-- iftype_t iftype;
-- int id = 0;
--
-- iftype = ics_if_unknown;
--
-- addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
--
-- id = inb(addr) & 1;
-- id |= (inb(addr + 1) & 1) << 1;
-- id |= (inb(addr + 2) & 1) << 2;
-- id |= (inb(addr + 3) & 1) << 3;
--
-- switch (id) {
-- case 0: /* A3IN */
-- printk("icside: A3IN unsupported\n");
-- break;
--
-- case 1: /* A3USER */
-- printk("icside: A3USER unsupported\n");
-- break;
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct icside_state *state = hwif->hwif_data;
-+ unsigned long flags;
-
-- case 3: /* ARCIN V6 */
-- printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no);
-- iftype = ics_if_arcin_v6;
-- break;
-+ local_irq_save(flags);
-
-- case 15:/* ARCIN V5 (no id) */
-- printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no);
-- iftype = ics_if_arcin_v5;
-- break;
-+ state->channel = hwif->channel;
-
-- default:/* we don't know - complain very loudly */
-- printk("icside: ***********************************\n");
-- printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id);
-- printk("icside: ***********************************\n");
-- printk("icside: please report this to linux@arm.linux.org.uk\n");
-- printk("icside: defaulting to ARCIN V5\n");
-- iftype = ics_if_arcin_v5;
-- break;
-+ if (state->enabled && !mask) {
-+ switch (hwif->channel) {
-+ case 0:
-+ outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ break;
-+ case 1:
-+ outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ break;
-+ }
-+ } else {
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
- }
-
-- return iftype;
-+ local_irq_restore(flags);
- }
-
- #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-@@ -234,125 +211,138 @@
- #define NR_ENTRIES 256
- #define TABLE_SIZE (NR_ENTRIES * 8)
-
--static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
-+static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
- {
-- struct buffer_head *bh;
-+ ide_hwif_t *hwif = HWIF(drive);
- struct scatterlist *sg = hwif->sg_table;
-+ struct buffer_head *bh;
- int nents = 0;
-
-- if (rq->cmd == READ)
-- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-- else
-- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-- bh = rq->bh;
-- do {
-- unsigned char *virt_addr = bh->b_data;
-- unsigned int size = bh->b_size;
-+ BUG_ON(hwif->sg_dma_active);
-
-- while ((bh = bh->b_reqnext) != NULL) {
-- if ((virt_addr + size) != (unsigned char *)bh->b_data)
-- break;
-- size += bh->b_size;
-- }
-- memset(&sg[nents], 0, sizeof(*sg));
-- sg[nents].address = virt_addr;
-- sg[nents].length = size;
-- nents++;
-- } while (bh != NULL);
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-
-- return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
--}
-+ if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+ else
-+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
--static int
--icside_build_dmatable(ide_drive_t *drive, int ddir)
--{
-- return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir);
--}
-+ memset(sg, 0, sizeof(*sg));
-+ sg->address = rq->buffer;
-+ sg->length = rq->nr_sectors * SECTOR_SIZE;
-+ nents = 1;
-+ } else {
-+ if (rq->cmd == READ)
-+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+ else
-+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
--/* Teardown mappings after DMA has completed. */
--static void icside_destroy_dmatable(ide_drive_t *drive)
--{
-- struct scatterlist *sg = HWIF(drive)->sg_table;
-- int nents = HWIF(drive)->sg_nents;
-+ bh = rq->bh;
-+ do {
-+ unsigned long lastend;
-
-- pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
-+ memset(sg, 0, sizeof(*sg));
-+ sg->page = bh->b_page;
-+ lastend = bh_phys(bh);
-+
-+ do {
-+ lastend += bh->b_size;
-+ sg->length += bh->b_size;
-+
-+ bh = bh->b_reqnext;
-+ if (bh == NULL)
-+ break;
-+ } while (lastend == bh_phys(bh));
-+
-+ sg++;
-+ nents++;
-+ } while (bh != NULL);
-+ }
-+
-+ nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
-+
-+ hwif->sg_nents = nents;
- }
-
--static int
--icside_config_if(ide_drive_t *drive, int xfer_mode)
-+
-+/*
-+ * Configure the IOMD to give the appropriate timings for the transfer
-+ * mode being requested. We take the advice of the ATA standards, and
-+ * calculate the cycle time based on the transfer mode, and the EIDE
-+ * MW DMA specs that the drive provides in the IDENTIFY command.
-+ *
-+ * We have the following IOMD DMA modes to choose from:
-+ *
-+ * Type Active Recovery Cycle
-+ * A 250 (250) 312 (550) 562 (800)
-+ * B 187 250 437
-+ * C 125 (125) 125 (375) 250 (500)
-+ * D 62 125 187
-+ *
-+ * (figures in brackets are actual measured timings)
-+ *
-+ * However, we also need to take care of the read/write active and
-+ * recovery timings:
-+ *
-+ * Read Write
-+ * Mode Active -- Recovery -- Cycle IOMD type
-+ * MW0 215 50 215 480 A
-+ * MW1 80 50 50 150 C
-+ * MW2 70 25 25 120 C
-+ */
-+static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
- {
-- int func = ide_dma_off;
-+ int on = 0, cycle_time = 0, use_dma_info = 0;
-+
-+ /*
-+ * Limit the transfer speed to MW_DMA_2.
-+ */
-+ if (xfer_mode > XFER_MW_DMA_2)
-+ xfer_mode = XFER_MW_DMA_2;
-
- switch (xfer_mode) {
- case XFER_MW_DMA_2:
-- /*
-- * The cycle time is limited to 250ns by the r/w
-- * pulse width (90ns), however we should still
-- * have a maximum burst transfer rate of 8MB/s.
-- */
-- drive->drive_data = 250;
-+ cycle_time = 250;
-+ use_dma_info = 1;
- break;
-
- case XFER_MW_DMA_1:
-- drive->drive_data = 250;
-+ cycle_time = 250;
-+ use_dma_info = 1;
- break;
-
- case XFER_MW_DMA_0:
-- drive->drive_data = 480;
-+ cycle_time = 480;
- break;
-
-- default:
-- drive->drive_data = 0;
-+ case XFER_SW_DMA_2:
-+ case XFER_SW_DMA_1:
-+ case XFER_SW_DMA_0:
-+ cycle_time = 480;
- break;
- }
-
-- if (!drive->init_speed)
-- drive->init_speed = (u8) xfer_mode;
-+ /*
-+ * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
-+ * take care to note the values in the ID...
-+ */
-+ if (use_dma_info && drive->id->eide_dma_time > cycle_time)
-+ cycle_time = drive->id->eide_dma_time;
-
-- if (drive->drive_data &&
-- ide_config_drive_speed(drive, (u8) xfer_mode) == 0)
-- func = ide_dma_on;
-+ drive->drive_data = cycle_time;
-+
-+ if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0)
-+ on = 1;
- else
- drive->drive_data = 480;
-
- printk("%s: %s selected (peak %dMB/s)\n", drive->name,
- ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
-
-- drive->current_speed = (u8) xfer_mode;
--
-- return func;
--}
--
--static int
--icside_set_speed(ide_drive_t *drive, u8 speed)
--{
-- return icside_config_if(drive, speed);
--}
--
--/*
-- * dma_intr() is the handler for disk read/write DMA interrupts
-- */
--static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
--{
-- u8 dma_stat = HWIF(drive)->ide_dma_end(drive);
-- /* get drive status */
-- u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
-- int i;
-+ drive->current_speed = xfer_mode;
-
-- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
-- if (!dma_stat) {
-- struct request *rq = HWGROUP(drive)->rq;
-- rq = HWGROUP(drive)->rq;
-- for (i = rq->nr_sectors; i > 0;) {
-- i -= rq->current_nr_sectors;
-- DRIVER(drive)->end_request(drive, 1);
-- }
-- return ide_stopped;
-- }
-- printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
-- drive->name, dma_stat);
-- }
-- return DRIVER(drive)->error(drive, "dma_intr", stat);
-+ return on;
- }
-
- /*
-@@ -361,19 +351,19 @@
- * This should be defined in one place only.
- */
- struct drive_list_entry {
-- char * id_model;
-- char * id_firmware;
-+ const char * id_model;
-+ const char * id_firmware;
- };
-
--static struct drive_list_entry drive_whitelist [] = {
-+static const struct drive_list_entry drive_whitelist [] = {
- { "Micropolis 2112A", "ALL" },
- { "CONNER CTMA 4000", "ALL" },
- { "CONNER CTT8000-A", "ALL" },
- { "ST34342A", "ALL" },
-- { NULL, 0 }
-+ { NULL, NULL }
- };
-
--static struct drive_list_entry drive_blacklist [] = {
-+static const struct drive_list_entry drive_blacklist [] = {
- { "WDC AC11000H", "ALL" },
- { "WDC AC22100H", "ALL" },
- { "WDC AC32500H", "ALL" },
-@@ -407,10 +397,11 @@
- { "PLEXTOR CD-R PX-W8432T", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
-- { NULL, 0 }
-+ { NULL, NULL }
- };
-
--static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
-+static int
-+in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
- {
- for ( ; drive_table->id_model ; drive_table++)
- if ((!strcmp(drive_table->id_model, id->model)) &&
-@@ -420,41 +411,52 @@
- return 0;
- }
-
--/*
-- * For both Blacklisted and Whitelisted drives.
-- * This is setup to be called as an extern for future support
-- * to other special driver code.
-- */
--int check_drive_good_lists (ide_drive_t *drive)
-+static int icside_dma_host_off(ide_drive_t *drive)
- {
-- struct hd_driveid *id = drive->id;
-- return in_drive_list(id, drive_whitelist);
-+ return 0;
- }
-
--int check_drive_bad_lists (ide_drive_t *drive)
-+static int icside_dma_off_quietly(ide_drive_t *drive)
- {
-- struct hd_driveid *id = drive->id;
-- int blacklist = in_drive_list(id, drive_blacklist);
-- if (blacklist)
-- printk("%s: Disabling DMA for %s\n", drive->name, id->model);
-- return(blacklist);
-+ drive->using_dma = 0;
-+ return icside_dma_host_off(drive);
- }
-
--int icside_dma_check(ide_drive_t *drive)
-+static int icside_dma_off(ide_drive_t *drive)
-+{
-+ printk("%s: DMA disabled\n", drive->name);
-+ return icside_dma_off_quietly(drive);
-+}
-+
-+static int icside_dma_host_on(ide_drive_t *drive)
-+{
-+ return 0;
-+}
-+
-+static int icside_dma_on(ide_drive_t *drive)
-+{
-+ drive->using_dma = 1;
-+ return icside_dma_host_on(drive);
-+}
-+
-+static int icside_dma_check(ide_drive_t *drive)
- {
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
-- int autodma = hwif->autodma;
- int xfer_mode = XFER_PIO_2;
-+ int on;
-
-- if (!id || !(id->capability & 1) || !autodma)
-- return hwif->ide_dma_off_quietly(drive);
-+ if (!id || !(id->capability & 1) || !hwif->autodma)
-+ goto out;
-
- /*
- * Consult the list of known "bad" drives
- */
-- if (check_drive_bad_lists(drive))
-- return hwif->ide_dma_off(drive);
-+ if (in_drive_list(id, drive_blacklist)) {
-+ printk("%s: Disabling DMA for %s (blacklisted)\n",
-+ drive->name, id->model);
-+ goto out;
-+ }
-
- /*
- * Enable DMA on any drive that has multiword DMA
-@@ -473,192 +475,241 @@
- /*
- * Consult the list of known "good" drives
- */
-- if (check_drive_good_lists(drive)) {
-+ if (in_drive_list(id, drive_whitelist)) {
- if (id->eide_dma_time > 150)
- goto out;
- xfer_mode = XFER_MW_DMA_1;
- }
-
- out:
-- if (icside_config_if(drive, xfer_mode))
-- return hwif->ide_dma_on(drive);
-- return hwif->ide_dma_off(drive);
--}
-+ on = icside_set_speed(drive, xfer_mode);
-
--int icside_dma_verbose(ide_drive_t *drive)
--{
-- printk(", DMA");
-- return 1;
-+ if (on)
-+ return icside_dma_on(drive);
-+ else
-+ return icside_dma_off(drive);
- }
-
--int icside_dma_test_irq(ide_drive_t *drive)
-+static int icside_dma_end(ide_drive_t *drive)
- {
- ide_hwif_t *hwif = HWIF(drive);
-- return inb((unsigned long)hwif->hw.priv) & 1;
--}
-
--int icside_dma_host_off(ide_drive_t *drive)
--{
-- return 0;
--}
-+ drive->waiting_for_dma = 0;
-
--int icside_dma_off_quietly(ide_drive_t *drive)
--{
-- drive->using_dma = 0;
-- return icside_dma_host_off(drive);
--}
-+ disable_dma(hwif->hw.dma);
-
--int icside_dma_off(ide_drive_t *drive)
--{
-- printk("%s: DMA disabled\n", drive->name);
-- return icside_dma_off_quietly(drive);
--}
-+ /* Teardown mappings after DMA has completed. */
-+ pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents,
-+ hwif->sg_dma_direction);
-
--int icside_dma_host_on(ide_drive_t *drive)
--{
-- return 0;
--}
-+ hwif->sg_dma_active = 0;
-
--int icside_dma_on(ide_drive_t *drive)
--{
-- drive->using_dma = 1;
-- return icside_dma_host_on(drive);
-+ return get_dma_residue(hwif->hw.dma) != 0;
- }
-
--int icside_dma_begin(ide_drive_t *drive)
-+static int icside_dma_begin(ide_drive_t *drive)
- {
- ide_hwif_t *hwif = HWIF(drive);
-
-+ /* We can not enable DMA on both channels simultaneously. */
-+ BUG_ON(dma_channel_active(hwif->hw.dma));
- enable_dma(hwif->hw.dma);
- return 0;
- }
-
--int icside_dma_end(ide_drive_t *drive)
-+static int icside_dma_count(ide_drive_t *drive)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--
-- drive->waiting_for_dma = 0;
-- disable_dma(hwif->hw.dma);
-- icside_destroy_dmatable(drive);
-- return get_dma_residue(hwif->hw.dma) != 0;
-+ return icside_dma_begin(drive);
- }
-
--int icside_dma_count (ide_drive_t *drive)
-+/*
-+ * dma_intr() is the handler for disk read/write DMA interrupts
-+ */
-+static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
- {
-- return icside_dma_begin(drive);
-+ unsigned int stat;
-+ int dma_stat;
-+
-+ dma_stat = icside_dma_end(drive);
-+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
-+ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
-+ if (!dma_stat) {
-+ struct request *rq = HWGROUP(drive)->rq;
-+ int i;
-+
-+ for (i = rq->nr_sectors; i > 0; ) {
-+ i -= rq->current_nr_sectors;
-+ DRIVER(drive)->end_request(drive, 1);
-+ }
-+
-+ return ide_stopped;
-+ }
-+ printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",
-+ drive->name, dma_stat);
-+ }
-+
-+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
- }
-
--int icside_dma_read(ide_drive_t *drive)
-+static int
-+icside_dma_common(ide_drive_t *drive, struct request *rq,
-+ unsigned int dma_mode)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--// ide_task_t *args = HWGROUP(drive)->rq->special;
-- int count = 0;
-- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-- task_ioreg_t command = WIN_NOP;
-+ ide_hwif_t *hwif = HWIF(drive);
-
-- count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE);
-- if (!count)
-- return 1;
-- disable_dma(hwif->hw.dma);
-+ /*
-+ * We can not enable DMA on both channels.
-+ */
-+ BUG_ON(hwif->sg_dma_active);
-+ BUG_ON(dma_channel_active(hwif->hw.dma));
-
-- /* Route the DMA signals to
-- * to the correct interface.
-+ ide_build_sglist(drive, rq);
-+
-+ /*
-+ * Ensure that we have the right interrupt routed.
- */
-- HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
-+ icside_maskproc(drive, 0);
-
-- /* Select the correct timing
-- * for this drive
-+ /*
-+ * Route the DMA signals to the correct interface.
-+ */
-+ outb(hwif->select_data, hwif->config_data);
-+
-+ /*
-+ * Select the correct timing for this drive.
- */
- set_dma_speed(hwif->hw.dma, drive->drive_data);
-
-- set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
-- set_dma_mode(hwif->hw.dma, DMA_MODE_READ);
-+ /*
-+ * Tell the DMA engine about the SG table and
-+ * data direction.
-+ */
-+ set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);
-+ set_dma_mode(hwif->hw.dma, dma_mode);
-+
-+ return 0;
-+}
-+
-+static int icside_dma_read(ide_drive_t *drive)
-+{
-+ struct request *rq = HWGROUP(drive)->rq;
-+ task_ioreg_t cmd;
-+
-+ if (icside_dma_common(drive, rq, DMA_MODE_READ))
-+ return 1;
-
- drive->waiting_for_dma = 1;
-+
- if (drive->media != ide_disk)
- return 0;
-
-- if (HWGROUP(drive)->handler != NULL) /* paranoia check */
-- BUG();
-- ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
- /*
- * FIX ME to use only ACB ide_task_t args Struct
- */
- #if 0
- {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
- }
- #else
-- command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
-- if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-+ } else if (drive->addressing == 1) {
-+ cmd = WIN_READDMA_EXT;
-+ } else {
-+ cmd = WIN_READDMA;
- }
- #endif
-- /* issue cmd to drive */
-- HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
-
-- return icside_dma_count(drive);
-+ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-+
-+ return icside_dma_begin(drive);
- }
-
--int icside_dma_write(ide_drive_t *drive)
-+static int icside_dma_write(ide_drive_t *drive)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--// ide_task_t *args = HWGROUP(drive)->rq->special;
-- int count = 0;
-- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-- task_ioreg_t command = WIN_NOP;
-+ struct request *rq = HWGROUP(drive)->rq;
-+ task_ioreg_t cmd;
-
-- count = icside_build_dmatable(drive, PCI_DMA_TODEVICE);
-- if (!count)
-+ if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
- return 1;
-- disable_dma(hwif->hw.dma);
--
-- /* Route the DMA signals to
-- * to the correct interface.
-- */
-- HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
--
-- /* Select the correct timing
-- * for this drive
-- */
-- set_dma_speed(hwif->hw.dma, drive->drive_data);
--
-- set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
-- set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE);
-
- drive->waiting_for_dma = 1;
-+
- if (drive->media != ide_disk)
- return 0;
-
-- if (HWGROUP(drive)->handler != NULL)
-- BUG();
-- ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
- /*
- * FIX ME to use only ACB ide_task_t args Struct
- */
- #if 0
- {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
- }
- #else
-- command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
-- if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-+ } else if (drive->addressing == 1) {
-+ cmd = WIN_WRITEDMA_EXT;
-+ } else {
-+ cmd = WIN_WRITEDMA;
- }
- #endif
-- /* issue cmd to drive */
-- HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
-
-- return icside_dma_count(drive);
-+ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-+
-+ return icside_dma_begin(drive);
- }
-
--static int
--icside_setup_dma(ide_hwif_t *hwif, int autodma)
-+static int icside_dma_test_irq(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct icside_state *state = hwif->hwif_data;
-+
-+ return inb(state->irq_port +
-+ (hwif->channel ?
-+ ICS_ARCIN_V6_INTRSTAT_2 :
-+ ICS_ARCIN_V6_INTRSTAT_1)) & 1;
-+}
-+
-+static int icside_dma_verbose(ide_drive_t *drive)
-+{
-+ printk(", %s (peak %dMB/s)",
-+ ide_xfer_verbose(drive->current_speed),
-+ 2000 / drive->drive_data);
-+ return 1;
-+}
-+
-+static int icside_dma_timeout(ide_drive_t *drive)
- {
-+ printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-+
-+ if (icside_dma_test_irq(drive))
-+ return 0;
-+
-+ ide_dump_status(drive, "DMA timeout",
-+ HWIF(drive)->INB(IDE_STATUS_REG));
-+
-+ return icside_dma_end(drive);
-+}
-+
-+static int icside_dma_lostirq(ide_drive_t *drive)
-+{
-+ printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-+ return 1;
-+}
-+
-+static int icside_dma_init(ide_hwif_t *hwif)
-+{
-+ int autodma = 0;
-+
-+#ifdef CONFIG_IDEDMA_ICS_AUTO
-+ autodma = 1;
-+#endif
-+
- printk(" %s: SG-DMA", hwif->name);
-
- hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
-@@ -666,40 +717,53 @@
- if (!hwif->sg_table)
- goto failed;
-
-- hwif->dmatable_cpu = NULL;
-- hwif->dmatable_dma = 0;
-- hwif->speedproc = icside_set_speed;
-- hwif->autodma = autodma;
-+ hwif->atapi_dma = 1;
-+ hwif->mwdma_mask = 7; /* MW0..2 */
-+ hwif->swdma_mask = 7; /* SW0..2 */
-
-- hwif->ide_dma_check = icside_dma_check;
-- hwif->ide_dma_host_off = icside_dma_host_off;
-+ hwif->dmatable_cpu = NULL;
-+ hwif->dmatable_dma = 0;
-+ hwif->speedproc = icside_set_speed;
-+ hwif->autodma = autodma;
-+
-+ hwif->ide_dma_check = icside_dma_check;
-+ hwif->ide_dma_host_off = icside_dma_host_off;
- hwif->ide_dma_off_quietly = icside_dma_off_quietly;
-- hwif->ide_dma_off = icside_dma_off;
-- hwif->ide_dma_host_on = icside_dma_host_on;
-- hwif->ide_dma_on = icside_dma_on;
-- hwif->ide_dma_read = icside_dma_read;
-- hwif->ide_dma_write = icside_dma_write;
-- hwif->ide_dma_count = icside_dma_count;
-- hwif->ide_dma_begin = icside_dma_begin;
-- hwif->ide_dma_end = icside_dma_end;
-- hwif->ide_dma_verbose = icside_dma_verbose;
-- hwif->ide_dma_bad_drive = check_drive_bad_lists;
-- hwif->ide_dma_good_drive = check_drive_good_lists;
-- hwif->ide_dma_test_irq = icside_dma_test_irq;
-+ hwif->ide_dma_off = icside_dma_off;
-+ hwif->ide_dma_host_on = icside_dma_host_on;
-+ hwif->ide_dma_on = icside_dma_on;
-+ hwif->ide_dma_read = icside_dma_read;
-+ hwif->ide_dma_write = icside_dma_write;
-+ hwif->ide_dma_count = icside_dma_count;
-+ hwif->ide_dma_begin = icside_dma_begin;
-+ hwif->ide_dma_end = icside_dma_end;
-+ hwif->ide_dma_test_irq = icside_dma_test_irq;
-+ hwif->ide_dma_verbose = icside_dma_verbose;
-+ hwif->ide_dma_timeout = icside_dma_timeout;
-+ hwif->ide_dma_lostirq = icside_dma_lostirq;
-
-- printk(" capable%s\n", autodma ?
-- ", auto-enable" : "");
-+ printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
-
- return 1;
-
- failed:
-- printk(" -- ERROR, unable to allocate DMA table\n");
-+ printk(" disabled, unable to allocate DMA table\n");
- return 0;
- }
-+
-+static void icside_dma_exit(ide_hwif_t *hwif)
-+{
-+ if (hwif->sg_table) {
-+ kfree(hwif->sg_table);
-+ hwif->sg_table = NULL;
-+ }
-+}
-+#else
-+#define icside_dma_init(hwif) (0)
-+#define icside_dma_exit(hwif) do { } while (0)
- #endif
-
--static ide_hwif_t *
--icside_find_hwif(unsigned long dataport)
-+static ide_hwif_t *icside_find_hwif(unsigned long dataport)
- {
- ide_hwif_t *hwif;
- int index;
-@@ -716,13 +780,13 @@
- goto found;
- }
-
-- return NULL;
-+ hwif = NULL;
- found:
- return hwif;
- }
-
- static ide_hwif_t *
--icside_setup(unsigned long base, struct cardinfo *info, int irq)
-+icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec)
- {
- unsigned long port = base + info->dataoffset;
- ide_hwif_t *hwif;
-@@ -740,8 +804,8 @@
- }
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
- hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
-- hwif->hw.irq = irq;
-- hwif->irq = irq;
-+ hwif->hw.irq = ec->irq;
-+ hwif->irq = ec->irq;
- hwif->hw.dma = NO_DMA;
- hwif->noprobe = 0;
- hwif->chipset = ide_acorn;
-@@ -750,33 +814,39 @@
- return hwif;
- }
-
--static int __init icside_register_v5(struct expansion_card *ec, int autodma)
-+static int __init
-+icside_register_v5(struct icside_state *state, struct expansion_card *ec)
- {
- unsigned long slot_port;
- ide_hwif_t *hwif;
-
- slot_port = ecard_address(ec, ECARD_MEMC, 0);
-
-+ state->irq_port = slot_port;
-+
- ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
- ec->irqmask = 1;
-- ec->irq_data = (void *)slot_port;
-- ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
-+ ec->irq_data = state;
-+ ec->ops = &icside_ops_arcin_v5;
-
- /*
- * Be on the safe side - disable interrupts
- */
- inb(slot_port + ICS_ARCIN_V5_INTROFFSET);
-
-- hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq);
-+ hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);
-
-- return hwif ? 0 : -1;
-+ state->hwif[0] = hwif;
-+
-+ return hwif ? 0 : -ENODEV;
- }
-
--static int __init icside_register_v6(struct expansion_card *ec, int autodma)
-+static int __init
-+icside_register_v6(struct icside_state *state, struct expansion_card *ec)
- {
- unsigned long slot_port, port;
- ide_hwif_t *hwif, *mate;
-- int sel = 0;
-+ unsigned int sel = 0;
-
- slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
- port = ecard_address(ec, ECARD_EASI, ECARD_FAST);
-@@ -788,88 +858,185 @@
-
- outb(sel, slot_port);
-
-- ec->irq_data = (void *)port;
-- ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
--
- /*
- * Be on the safe side - disable interrupts
- */
- inb(port + ICS_ARCIN_V6_INTROFFSET_1);
- inb(port + ICS_ARCIN_V6_INTROFFSET_2);
-
-- hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq);
-- mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq);
-+ /*
-+ * Find and register the interfaces.
-+ */
-+ hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
-+ mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
-
--#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-- if (ec->dma != NO_DMA) {
-- if (request_dma(ec->dma, hwif->name))
-- goto no_dma;
-+ if (!hwif || !mate)
-+ return -ENODEV;
-
-- if (hwif) {
-- hwif->config_data = slot_port;
-- hwif->select_data = sel;
-- hwif->hw.dma = ec->dma;
-- hwif->hw.priv = (void *)
-- (port + ICS_ARCIN_V6_INTRSTAT_1);
-- hwif->channel = 0;
-- icside_setup_dma(hwif, autodma);
-- hwif->drives[0].autodma = autodma;
-- hwif->drives[1].autodma = autodma;
-- }
-- if (mate) {
-- mate->config_data = slot_port;
-- mate->select_data = sel | 1;
-- mate->hw.dma = ec->dma;
-- mate->hw.priv = (void *)
-- (port + ICS_ARCIN_V6_INTRSTAT_2);
-- mate->channel = 1;
-- icside_setup_dma(mate, autodma);
-- mate->drives[0].autodma = autodma;
-- mate->drives[1].autodma = autodma;
-- }
-+ state->irq_port = port;
-+ state->slot_port = slot_port;
-+ state->hwif[0] = hwif;
-+ state->hwif[1] = mate;
-+
-+ ec->irq_data = state;
-+ ec->ops = &icside_ops_arcin_v6;
-+
-+ hwif->maskproc = icside_maskproc;
-+ hwif->channel = 0;
-+ hwif->hwif_data = state;
-+ hwif->mate = mate;
-+ hwif->serialized = 1;
-+ hwif->config_data = slot_port;
-+ hwif->select_data = sel;
-+ hwif->hw.dma = ec->dma;
-+
-+ mate->maskproc = icside_maskproc;
-+ mate->channel = 1;
-+ mate->hwif_data = state;
-+ mate->mate = hwif;
-+ mate->serialized = 1;
-+ mate->config_data = slot_port;
-+ mate->select_data = sel | 1;
-+ mate->hw.dma = ec->dma;
-+
-+ if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
-+ icside_dma_init(hwif);
-+ icside_dma_init(mate);
- }
--no_dma:
--#endif
-- return hwif || mate ? 0 : -1;
-+ return 0;
- }
-
--int __init icside_init(void)
-+static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id)
- {
-- int autodma = 0;
-+ struct icside_state *state;
-+ int ret;
-
--#ifdef CONFIG_IDEDMA_ICS_AUTO
-- autodma = 1;
--#endif
-+ state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);
-+ if (!state) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-
-- ecard_startfind ();
-+ memset(state, 0, sizeof(struct icside_state));
-+ state->type = ICS_TYPE_NOTYPE;
-
-- do {
-- struct expansion_card *ec;
-- int result;
-+ {
-+ unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
-+ unsigned int type;
-
-- ec = ecard_find(0, icside_cids);
-- if (ec == NULL)
-- break;
-+ type = inb(addr) & 1;
-+ type |= (inb(addr + 1) & 1) << 1;
-+ type |= (inb(addr + 2) & 1) << 2;
-+ type |= (inb(addr + 3) & 1) << 3;
-
-- ecard_claim(ec);
-+ state->type = type;
-+ }
-
-- switch (icside_identifyif(ec)) {
-- case ics_if_arcin_v5:
-- result = icside_register_v5(ec, autodma);
-- break;
-+ switch (state->type) {
-+ case ICS_TYPE_A3IN:
-+ printk(KERN_WARNING "icside: A3IN unsupported\n");
-+ ret = -ENODEV;
-+ break;
-
-- case ics_if_arcin_v6:
-- result = icside_register_v6(ec, autodma);
-- break;
-+ case ICS_TYPE_A3USER:
-+ printk(KERN_WARNING "icside: A3USER unsupported\n");
-+ ret = -ENODEV;
-+ break;
-
-- default:
-- result = -1;
-- break;
-- }
-+ case ICS_TYPE_V5:
-+ ret = icside_register_v5(state, ec);
-+ break;
-
-- if (result)
-- ecard_release(ec);
-- } while (1);
-+ case ICS_TYPE_V6:
-+ ret = icside_register_v6(state, ec);
-+ break;
-
-- return 0;
-+ default:
-+ printk(KERN_WARNING "icside: unknown interface type\n");
-+ ret = -ENODEV;
-+ break;
-+ }
-+
-+ if (ret == 0) {
-+ ecard_set_drvdata(ec, state);
-+ } else {
-+ kfree(state);
-+ }
-+ out:
-+ return ret;
-+}
-+
-+static void __devexit icside_remove(struct expansion_card *ec)
-+{
-+ struct icside_state *state = ecard_get_drvdata(ec);
-+
-+ switch (state->type) {
-+ case ICS_TYPE_V5:
-+ /* FIXME: tell IDE to stop using the interface */
-+
-+ /* Disable interrupts */
-+ inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
-+ break;
-+
-+ case ICS_TYPE_V6:
-+ /* FIXME: tell IDE to stop using the interface */
-+ icside_dma_exit(state->hwif[1]);
-+ icside_dma_exit(state->hwif[0]);
-+
-+ if (ec->dma != NO_DMA)
-+ free_dma(ec->dma);
-+
-+ /* Disable interrupts */
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+
-+ /* Reset the ROM pointer/EASI selection */
-+ outb(0, state->slot_port);
-+ break;
-+ }
-+
-+ ecard_set_drvdata(ec, NULL);
-+ ec->ops = NULL;
-+ ec->irq_data = NULL;
-+
-+ kfree(state);
-+}
-+
-+static void icside_shutdown(struct expansion_card *ec)
-+{
-+ struct icside_state *state = ecard_get_drvdata(ec);
-+
-+ switch (state->type) {
-+ case ICS_TYPE_V5:
-+ /* Disable interrupts */
-+ inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
-+ break;
-+
-+ case ICS_TYPE_V6:
-+ /* Disable interrupts */
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+
-+ /* Reset the ROM pointer/EASI selection */
-+ outb(0, state->slot_port);
-+ break;
-+ }
-+}
-+
-+static const struct ecard_id icside_ids[] = {
-+ { MANU_ICS, PROD_ICS_IDE },
-+ { MANU_ICS2, PROD_ICS2_IDE },
-+ { 0xffff, 0xffff }
-+};
-+
-+static struct ecard_driver icside_driver = {
-+ .probe = icside_probe,
-+ .remove = __devexit_p(icside_remove),
-+ .shutdown = icside_shutdown,
-+ .id_table = icside_ids,
-+};
-+
-+int __init icside_init(void)
-+{
-+ return ecard_register_driver(&icside_driver);
- }
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ide/arm/rstation-ide.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,78 @@
-+/*
-+ * linux/drivers/ide/rs-ide.c
-+ *
-+ * Copyright (c) 2002 Ben Dooks
-+ * Copyright (c) 2002 Simtec Electronics
-+ *
-+ * Simple RiscStation IDE support
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/blkdev.h>
-+#include <linux/errno.h>
-+#include <linux/ide.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware/iomd.h>
-+#include <asm/mach-types.h>
-+#include <asm/io.h>
-+
-+#ifndef CONFIG_ARCH_RISCSTATION
-+#error "compiling this code for non-riscstation hardware is dangerous!"
-+#endif
-+
-+#define DRV_PREFIX "ide-rs"
-+
-+#define IRQ_PRI (40+3)
-+#define IRQ_SEC (40+4)
-+
-+#define PORT_BASE ((0x2b800 - 0x10000) >> 2)
-+#define SEC_OFF (0x400 >> 2)
-+
-+int __init rside_reg(unsigned long base, unsigned int irq);
-+
-+int __init rside_init(void)
-+{
-+ int iotcr;
-+
-+ if (!machine_is_riscstation()) {
-+ printk(DRV_PREFIX ": hardware is not a RiscStation!\n");
-+ return 0;
-+ }
-+
-+ /* select correct area cycle time */
-+
-+ iotcr = inb(IOMD_IOTCR);
-+ outb((iotcr & ~3) | 1, IOMD_IOTCR);
-+
-+ /* register h/w */
-+
-+ rside_reg(PORT_BASE, IRQ_PRI);
-+ rside_reg(PORT_BASE + SEC_OFF, IRQ_SEC);
-+
-+ return 0;
-+}
-+
-+
-+int __init rside_reg(unsigned long port, unsigned int irq)
-+{
-+ unsigned long addr, i;
-+ hw_regs_t hw;
-+
-+ hw.irq = irq;
-+
-+ addr = port;
-+
-+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-+ hw.io_ports[i] = (ide_ioreg_t)addr;
-+ addr += 0x40 >> 2;
-+ }
-+
-+ hw.io_ports[IDE_CONTROL_OFFSET] = port + ((0xb80 - 0x800) >> 2);
-+
-+ printk(DRV_PREFIX ": registering channel at %08lx, %08lx, irq %d\n",
-+ port, hw.io_ports[IDE_CONTROL_OFFSET], irq);
-+
-+ return ide_register_hw(&hw, NULL);
-+}
---- linux-2.4.25/drivers/ide/ide-probe.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/ide/ide-probe.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1296,11 +1296,11 @@
- hwif->name, hwif->major);
- return (hwif->present = 0);
- }
--
-+
- if (init_irq(hwif)) {
- int i = hwif->irq;
- /*
-- * It failed to initialise. Find the default IRQ for
-+ * It failed to initialise. Find the default IRQ for
- * this port and try that.
- */
- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
-@@ -1318,7 +1318,7 @@
- printk("%s: probed IRQ %d failed, using default.\n",
- hwif->name, hwif->irq);
- }
--
-+
- init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].queue = ide_get_queue;
---- linux-2.4.25/drivers/ide/ide-proc.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/ide/ide-proc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -425,6 +425,7 @@
- case ide_cy82c693: name = "cy82c693"; break;
- case ide_4drives: name = "4drives"; break;
- case ide_pmac: name = "pmac"; break;
-+ case ide_acorn: name = "acorn"; break;
- default: name = "(unknown)"; break;
- }
- len = sprintf(page, "%s\n", name);
---- linux-2.4.25/drivers/ide/ide.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/ide/ide.c 2004-03-31 17:15:09.000000000 +0200
-@@ -218,23 +218,14 @@
- static void init_hwif_data (unsigned int index)
- {
- unsigned int unit;
-- hw_regs_t hw;
- ide_hwif_t *hwif = &ide_hwifs[index];
-
- /* bulk initialize hwif & drive info with zeros */
- memset(hwif, 0, sizeof(ide_hwif_t));
-- memset(&hw, 0, sizeof(hw_regs_t));
-
- /* fill in any non-zero initial values */
- hwif->index = index;
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
-- memcpy(&hwif->hw, &hw, sizeof(hw));
-- memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
-- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
--#ifdef CONFIG_BLK_DEV_HD
-- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
-- hwif->noprobe = 1; /* may be overridden by ide_setup() */
--#endif /* CONFIG_BLK_DEV_HD */
-+ hwif->noprobe = 1;
- hwif->major = ide_hwif_to_major[index];
- hwif->name[0] = 'i';
- hwif->name[1] = 'd';
-@@ -276,6 +267,28 @@
- }
-
- /*
-+ * Old compatability function - initialise ports using ide_default_io_base
-+ */
-+static void ide_old_init_default_hwifs(void)
-+{
-+ unsigned int index;
-+ ide_ioreg_t base;
-+ ide_hwif_t *hwif;
-+
-+ for (index = 0; index < MAX_HWIFS; index++) {
-+ hwif = &ide_hwifs[index];
-+
-+ base = ide_default_io_base(index);
-+
-+ if (base) {
-+ ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq);
-+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
-+ hwif->noprobe = 0;
-+ }
-+ }
-+}
-+
-+/*
- * init_ide_data() sets reasonable default values into all fields
- * of all instances of the hwifs and drives, but only on the first call.
- * Subsequent calls have no effect (they don't wipe out anything).
-@@ -307,6 +320,7 @@
- init_hwif_data(index);
-
- /* Add default hw interfaces */
-+ ide_old_init_default_hwifs();
- ide_init_default_hwifs();
-
- idebus_parameter = 0;
-@@ -2530,6 +2544,12 @@
- rapide_init();
- }
- #endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
-+#ifdef CONFIG_BLK_DEV_IDE_RISCSTATION
-+ {
-+ extern void rside_init(void);
-+ rside_init();
-+ }
-+#endif /* CONFIG_BLK_DEV_IDE_RISCSTATION */
- #ifdef CONFIG_BLK_DEV_GAYLE
- {
- extern void gayle_init(void);
---- linux-2.4.25/drivers/ide/pci/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/ide/pci/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -15,7 +15,6 @@
- obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
- obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
- #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o
--obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
- obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
- obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
- obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
---- linux-2.4.25/drivers/ide/pci/sl82c105.c~2.4.25-vrs2.patch 2003-06-13 16:51:33.000000000 +0200
-+++ linux-2.4.25/drivers/ide/pci/sl82c105.c 2004-03-31 17:15:09.000000000 +0200
-@@ -37,7 +37,7 @@
- #ifdef DEBUG
- #define DBG(arg) printk arg
- #else
--#define DBG(fmt,...)
-+#define DBG(fmt...)
- #endif
- /*
- * SL82C105 PCI config register 0x40 bits.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ide/pci/sl82c105.c.2419 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,380 @@
-+/*
-+ * linux/drivers/ide/sl82c105.c
-+ *
-+ * SL82C105/Winbond 553 IDE driver
-+ *
-+ * Maintainer unknown.
-+ *
-+ * Changelog:
-+ *
-+ * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel
-+ * sources
-+ * 30/03/2002 RMK Add fixes specified in W83C553F errata.
-+ * (with special thanks to Todd Inglett)
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/timer.h>
-+#include <linux/mm.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/blkdev.h>
-+#include <linux/hdreg.h>
-+#include <linux/pci.h>
-+#include <linux/ide.h>
-+
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+
-+#include "ide_modes.h"
-+
-+extern char *ide_xfer_verbose (byte xfer_rate);
-+
-+/*
-+ * SL82C105 PCI config register 0x40 bits.
-+ */
-+#define CTRL_IDE_IRQB (1 << 30)
-+#define CTRL_IDE_IRQA (1 << 28)
-+#define CTRL_LEGIRQ (1 << 11)
-+#define CTRL_P1F16 (1 << 5)
-+#define CTRL_P1EN (1 << 4)
-+#define CTRL_P0F16 (1 << 1)
-+#define CTRL_P0EN (1 << 0)
-+
-+/*
-+ * Convert a PIO mode and cycle time to the required on/off
-+ * times for the interface. This has protection against run-away
-+ * timings.
-+ */
-+static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
-+{
-+ unsigned int cmd_on;
-+ unsigned int cmd_off;
-+
-+ cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
-+ cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
-+
-+ if (cmd_on > 32)
-+ cmd_on = 32;
-+ if (cmd_on == 0)
-+ cmd_on = 1;
-+
-+ if (cmd_off > 32)
-+ cmd_off = 32;
-+ if (cmd_off == 0)
-+ cmd_off = 1;
-+
-+ return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00);
-+}
-+
-+/*
-+ * Configure the drive and chipset for PIO
-+ */
-+static void config_for_pio(ide_drive_t *drive, int pio, int report)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ ide_pio_data_t p;
-+ unsigned short drv_ctrl = 0x909;
-+ unsigned int xfer_mode, reg;
-+
-+ reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-+
-+ pio = ide_get_best_pio_mode(drive, pio, 5, &p);
-+
-+ switch (pio) {
-+ default:
-+ case 0: xfer_mode = XFER_PIO_0; break;
-+ case 1: xfer_mode = XFER_PIO_1; break;
-+ case 2: xfer_mode = XFER_PIO_2; break;
-+ case 3: xfer_mode = XFER_PIO_3; break;
-+ case 4: xfer_mode = XFER_PIO_4; break;
-+ }
-+
-+ if (ide_config_drive_speed(drive, xfer_mode) == 0)
-+ drv_ctrl = get_timing_sl82c105(&p);
-+
-+ if (drive->using_dma == 0) {
-+ /*
-+ * If we are actually using MW DMA, then we can not
-+ * reprogram the interface drive control register.
-+ */
-+ pci_write_config_word(dev, reg, drv_ctrl);
-+ pci_read_config_word(dev, reg, &drv_ctrl);
-+
-+ if (report) {
-+ printk("%s: selected %s (%dns) (%04X)\n", drive->name,
-+ ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
-+ }
-+ }
-+}
-+
-+/*
-+ * Configure the drive and the chipset for DMA
-+ */
-+static int config_for_dma(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ unsigned short drv_ctrl = 0x909;
-+ unsigned int reg;
-+
-+ reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-+
-+ if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
-+ drv_ctrl = 0x0240;
-+
-+ pci_write_config_word(dev, reg, drv_ctrl);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Check to see if the drive and
-+ * chipset is capable of DMA mode
-+ */
-+static int sl82c105_check_drive(ide_drive_t *drive)
-+{
-+ ide_dma_action_t dma_func = ide_dma_off_quietly;
-+
-+ do {
-+ struct hd_driveid *id = drive->id;
-+ ide_hwif_t *hwif = HWIF(drive);
-+
-+ if (!hwif->autodma)
-+ break;
-+
-+ if (!id || !(id->capability & 1))
-+ break;
-+
-+ /* Consult the list of known "bad" drives */
-+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-+ dma_func = ide_dma_off;
-+ break;
-+ }
-+
-+ if (id->field_valid & 2) {
-+ if (id->dma_mword & 7 || id->dma_1word & 7)
-+ dma_func = ide_dma_on;
-+ break;
-+ }
-+
-+ if (ide_dmaproc(ide_dma_good_drive, drive)) {
-+ dma_func = ide_dma_on;
-+ break;
-+ }
-+ } while (0);
-+
-+ return HWIF(drive)->dmaproc(dma_func, drive);
-+}
-+
-+/*
-+ * The SL82C105 holds off all IDE interrupts while in DMA mode until
-+ * all DMA activity is completed. Sometimes this causes problems (eg,
-+ * when the drive wants to report an error condition).
-+ *
-+ * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller
-+ * state machine. We need to kick this to work around various bugs.
-+ */
-+static inline void sl82c105_reset_host(struct pci_dev *dev)
-+{
-+ u16 val;
-+
-+ pci_read_config_word(dev, 0x7e, &val);
-+ pci_write_config_word(dev, 0x7e, val | (1 << 2));
-+ pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
-+}
-+
-+/*
-+ * If we get an IRQ timeout, it might be that the DMA state machine
-+ * got confused. Fix from Todd Inglett. Details from Winbond.
-+ *
-+ * This function is called when the IDE timer expires, the drive
-+ * indicates that it is READY, and we were waiting for DMA to complete.
-+ */
-+static int sl82c105_lostirq(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
-+ unsigned long dma_base = hwif->dma_base;
-+
-+ printk("sl82c105: lost IRQ: resetting host\n");
-+
-+ /*
-+ * Check the raw interrupt from the drive.
-+ */
-+ pci_read_config_dword(dev, 0x40, &val);
-+ if (val & mask)
-+ printk("sl82c105: drive was requesting IRQ, but host lost it\n");
-+
-+ /*
-+ * Was DMA enabled? If so, disable it - we're resetting the
-+ * host. The IDE layer will be handling the drive for us.
-+ */
-+ val = inb(dma_base);
-+ if (val & 1) {
-+ outb(val & ~1, dma_base);
-+ printk("sl82c105: DMA was enabled\n");
-+ }
-+
-+ sl82c105_reset_host(dev);
-+
-+ /* ide_dmaproc would return 1, so we do as well */
-+ return 1;
-+}
-+
-+/*
-+ * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
-+ * Winbond recommend that the DMA state machine is reset prior to
-+ * setting the bus master DMA enable bit.
-+ *
-+ * The generic IDE core will have disabled the BMEN bit before this
-+ * function is called.
-+ */
-+static void sl82c105_before_bm_enable(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+
-+ sl82c105_reset_host(dev);
-+}
-+
-+/*
-+ * Our very own dmaproc. We need to intercept various calls
-+ * to fix up the SL82C105 specific behaviour.
-+ */
-+static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-+{
-+ switch (func) {
-+ case ide_dma_check:
-+ return sl82c105_check_drive(drive);
-+
-+ case ide_dma_on:
-+ if (config_for_dma(drive))
-+ func = ide_dma_off;
-+ /* fall through */
-+
-+ case ide_dma_off_quietly:
-+ case ide_dma_off:
-+ config_for_pio(drive, 4, 0);
-+ break;
-+
-+ case ide_dma_read:
-+ case ide_dma_write:
-+ case ide_dma_begin:
-+ case ide_dma_timeout:
-+ sl82c105_before_bm_enable(drive);
-+ break;
-+
-+ case ide_dma_lostirq:
-+ return sl82c105_lostirq(drive);
-+
-+ default:
-+ break;
-+ }
-+ return ide_dmaproc(func, drive);
-+}
-+
-+/*
-+ * We only deal with PIO mode here - DMA mode 'using_dma' is not
-+ * initialised at the point that this function is called.
-+ */
-+static void tune_sl82c105(ide_drive_t *drive, byte pio)
-+{
-+ config_for_pio(drive, pio, 1);
-+
-+ /*
-+ * We support 32-bit I/O on this interface, and it
-+ * doesn't have problems with interrupts.
-+ */
-+ drive->io_32bit = 1;
-+ drive->unmask = 1;
-+}
-+
-+/*
-+ * Return the revision of the Winbond bridge
-+ * which this function is part of.
-+ */
-+static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
-+{
-+ struct pci_dev *bridge;
-+ unsigned char rev;
-+
-+ /*
-+ * The bridge should be part of the same device, but function 0.
-+ */
-+ bridge = pci_find_slot(dev->bus->number,
-+ PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
-+ if (!bridge)
-+ return -1;
-+
-+ /*
-+ * Make sure it is a Winbond 553 and is an ISA bridge.
-+ */
-+ if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
-+ bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
-+ bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA)
-+ return -1;
-+
-+ /*
-+ * We need to find function 0's revision, not function 1
-+ */
-+ pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
-+
-+ return rev;
-+}
-+
-+/*
-+ * Enable the PCI device
-+ */
-+unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg)
-+{
-+ u32 val;
-+
-+ pci_read_config_dword(dev, 0x40, &val);
-+ val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16;
-+ pci_write_config_dword(dev, 0x40, val);
-+
-+ return dev->irq;
-+}
-+
-+void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
-+{
-+ unsigned int bridge_rev;
-+ byte dma_state;
-+
-+ dma_state = inb(dma_base + 2);
-+ bridge_rev = sl82c105_bridge_revision(hwif->pci_dev);
-+ if (bridge_rev <= 5) {
-+ hwif->autodma = 0;
-+ hwif->drives[0].autotune = 1;
-+ hwif->drives[1].autotune = 1;
-+ printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
-+ hwif->name, bridge_rev);
-+ dma_state &= ~0x60;
-+ } else {
-+ dma_state |= 0x60;
-+ hwif->autodma = 1;
-+ }
-+ outb(dma_state, dma_base + 2);
-+
-+ ide_setup_dma(hwif, dma_base, 8);
-+
-+ if (bridge_rev <= 5)
-+ hwif->dmaproc = NULL;
-+ else
-+ hwif->dmaproc = sl82c105_dmaproc;
-+}
-+
-+/*
-+ * Initialise the chip
-+ */
-+void __init ide_init_sl82c105(ide_hwif_t *hwif)
-+{
-+ hwif->tuneproc = tune_sl82c105;
-+}
-+
---- linux-2.4.25/drivers/input/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/input/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -15,5 +15,6 @@
- dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
- dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT
- dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT
-+dep_tristate ' MX1 touchscreen support' CONFIG_INPUT_MX1TS $CONFIG_INPUT_MOUSEDEV $CONFIG_ARCH_MX1ADS
-
- endmenu
---- linux-2.4.25/drivers/input/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/input/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -24,6 +24,7 @@
- obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
- obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
- obj-$(CONFIG_INPUT_EVDEV) += evdev.o
-+obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o
- obj-$(CONFIG_INPUT_UINPUT) += uinput.o
-
- # The global Rules.make.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/input/mx1ts.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,508 @@
-+/*
-+ * linux/drivers/misc/mx1ts.c
-+ *
-+ * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * Cloned from ucb1x00_ts.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/smp_lock.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+
-+#include <linux/input.h>
-+
-+#include "mx1ts.h"
-+
-+#define DEV_IRQ_ID "mx1-ts"
-+
-+struct mx1_ts {
-+ struct input_dev idev;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pmdev;
-+#endif
-+
-+ wait_queue_head_t irq_wait;
-+ struct completion init_exit;
-+ int use_count;
-+ u16 x_res;
-+ u16 y_res;
-+
-+ int restart:1;
-+};
-+
-+static struct mx1_ts mx1ts;
-+static u8 mx1_performing_auto_calibration = 0;
-+static u16 mx1_cal_auto_zero = 0;
-+static u16 mx1_cal_range_x = 0;
-+static u16 mx1_cal_range_y = 0;
-+
-+static int mx1_ts_startup(struct mx1_ts *ts);
-+static void mx1_ts_shutdown(struct mx1_ts *ts);
-+
-+static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs);
-+static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs);
-+static void mx1_ts_compare_int(int irq, void *dev_id, struct pt_regs *regs);
-+
-+static void mx1_ts_enable_pen_touch_interrupt(void);
-+static void mx1_ts_disable_pen_touch_interrupt(void);
-+static void mx1_ts_enable_pen_up_interrupt(void);
-+static void mx1_ts_disable_pen_up_interrupt(void);
-+static void mx1_ts_enable_auto_sample(void);
-+static void mx1_ts_disable_auto_sample(void);
-+static void mx1_ts_start_auto_calibration(void);
-+
-+static inline void mx1_reg_write(unsigned int reg, unsigned int val)
-+{
-+ *((volatile unsigned int *)reg) = val;
-+}
-+
-+static inline unsigned int mx1_reg_read(unsigned int reg)
-+{
-+ return *((volatile unsigned int *)reg);
-+}
-+
-+static inline void mx1_reg_clear_bit(unsigned int reg, unsigned int bit)
-+{
-+ *((volatile unsigned int *)reg) &= ~bit;
-+}
-+
-+static inline void mx1_reg_set_bit(unsigned int reg, unsigned int bit)
-+{
-+ *((volatile unsigned int *)reg) |= bit;
-+}
-+
-+static inline void mx1_ts_evt_add(struct mx1_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ input_report_abs(&ts->idev, ABS_X, (int)x - 32768);
-+ input_report_abs(&ts->idev, ABS_Y, (int)y - 32768);
-+ input_report_abs(&ts->idev, ABS_PRESSURE, (int)pressure);
-+}
-+
-+static inline void mx1_ts_flush_fifo(void)
-+{
-+ int i;
-+ for (i = 0; i < 12; i++)
-+ if (mx1_reg_read(ASP_ISTATR) & (ASP_PFF | ASP_PDR))
-+ mx1_reg_read(ASP_PADFIFO);
-+}
-+
-+static int mx1_ts_open(struct input_dev *idev)
-+{
-+ struct mx1_ts *ts = (struct mx1_ts *)idev;
-+
-+ mx1_performing_auto_calibration = 0;
-+ return mx1_ts_startup(ts);
-+}
-+
-+static void mx1_ts_close(struct input_dev *idev)
-+{
-+ struct mx1_ts *ts = (struct mx1_ts *)idev;
-+
-+ mx1_ts_shutdown(ts);
-+}
-+
-+static inline int mx1_ts_enable_irqs(void)
-+{
-+ int result;
-+
-+ result = request_irq(ASP_PENDATA_IRQ,
-+ mx1_ts_pendata_int,
-+ SA_INTERRUPT,
-+ DEV_IRQ_ID,
-+ DEV_IRQ_ID);
-+ if (result) {
-+ printk("Couldn't request pen data IRQ.\n");
-+ return result;
-+ }
-+
-+ result = request_irq(ASP_TOUCH_IRQ,
-+ mx1_ts_touch_int,
-+ SA_INTERRUPT,
-+ DEV_IRQ_ID,
-+ DEV_IRQ_ID);
-+ if (result) {
-+ printk("Couldn't request pen touch IRQ.\n");
-+ free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
-+ return result;
-+ }
-+
-+ return result;
-+}
-+
-+static inline int mx1_ts_disable_irqs(void)
-+{
-+ free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
-+ free_irq(ASP_TOUCH_IRQ, DEV_IRQ_ID);
-+
-+ return 0;
-+}
-+
-+static inline int mx1_ts_register(struct mx1_ts *ts)
-+{
-+ ts->idev.name = "Touchscreen panel";
-+ ts->idev.open = mx1_ts_open;
-+ ts->idev.close = mx1_ts_close;
-+
-+ __set_bit(EV_ABS, ts->idev.evbit);
-+ __set_bit(ABS_X, ts->idev.absbit);
-+ __set_bit(ABS_Y, ts->idev.absbit);
-+ __set_bit(ABS_PRESSURE, ts->idev.absbit);
-+
-+ ts->idev.absmin[ABS_X] = 0;
-+ ts->idev.absmax[ABS_X] = (u32)0x0000FFFF;
-+ ts->idev.absfuzz[ABS_X] = 50;
-+ ts->idev.absflat[ABS_X] = 0;
-+
-+ ts->idev.absmin[ABS_Y] = 0;
-+ ts->idev.absmax[ABS_Y] = (u32)0x0000FFFF;
-+ ts->idev.absfuzz[ABS_Y] = 50;
-+ ts->idev.absflat[ABS_Y] = 0;
-+
-+ input_register_device(&ts->idev);
-+
-+ return 0;
-+}
-+
-+static inline void mx1_ts_deregister(struct mx1_ts *ts)
-+{
-+ input_unregister_device(&ts->idev);
-+}
-+
-+/*
-+ * Handle the touch interrupt, generated when the pen is pressed/
-+ * released.
-+ */
-+static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /* Clear the interrupt. */
-+ mx1_reg_set_bit(ASP_ISTATR, ASP_PEN);
-+
-+ mx1_ts_disable_pen_touch_interrupt();
-+ mx1_ts_start_auto_calibration();
-+ mx1_ts_enable_pen_up_interrupt();
-+}
-+
-+/*
-+ * Handle the pen data ready interrupt, generated when pen data is
-+ * in the FIFO.
-+ */
-+static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ static unsigned int auto_zero, pen_x, pen_y, pen_u;
-+
-+ if (mx1_reg_read(ASP_ISTATR) & 0x400) {
-+ mx1_reg_set_bit(ASP_ISTATR, 0x400);
-+
-+ mx1_ts_disable_auto_sample();
-+ mx1_ts_disable_pen_up_interrupt();
-+ mx1_ts_enable_pen_touch_interrupt();
-+
-+ mx1_ts_evt_add(&mx1ts, 0, pen_x, pen_y);
-+
-+ mx1_ts_flush_fifo();
-+
-+ return;
-+ }
-+
-+ if (mx1_performing_auto_calibration) {
-+ unsigned int value;
-+
-+ mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+ mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+ mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+
-+ if ((mx1_cal_auto_zero >= mx1_cal_range_x) ||
-+ (mx1_cal_auto_zero >= mx1_cal_range_y)) {
-+ /* Invalid data. */
-+ mx1_ts_start_auto_calibration();
-+ return;
-+ }
-+
-+ mx1_cal_range_x -= mx1_cal_auto_zero;
-+ mx1_cal_range_y -= mx1_cal_auto_zero;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+ value &= ~0x04000000; /* XXX Undocumented. */
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ mx1_performing_auto_calibration = 0;
-+
-+ mx1_ts_enable_auto_sample();
-+ } else {
-+ /* There could be more than one sample in the FIFO, but we're
-+ * only going to read one per call. The interrupt will be
-+ * generated as long as there is data in the FIFO. */
-+
-+ if ((mx1_reg_read(ASP_ISTATR) & ASP_PDR) != ASP_PDR) {
-+ return;
-+ }
-+
-+ auto_zero = mx1_reg_read(ASP_PADFIFO);
-+ if (auto_zero > (mx1_cal_auto_zero + 0x200)) {
-+ return;
-+ }
-+
-+ pen_x = mx1_reg_read(ASP_PADFIFO);
-+ pen_y = mx1_reg_read(ASP_PADFIFO);
-+ pen_u = mx1_reg_read(ASP_PADFIFO);
-+
-+ pen_x = (u32)(((pen_x - mx1_cal_auto_zero) << 16) /
-+ mx1_cal_range_x);
-+ pen_y = (u32)(((pen_y - mx1_cal_auto_zero) << 16) /
-+ mx1_cal_range_y);
-+
-+ mx1_ts_evt_add(&mx1ts, pen_u, pen_x, pen_y);
-+ }
-+}
-+
-+static void mx1_ts_reset_asp(void)
-+{
-+ unsigned int value;
-+
-+ mx1_ts_flush_fifo();
-+
-+ /* Soft reset the ASP module */
-+ mx1_reg_write(ASP_ACNTLCR, ASP_SWRST);
-+
-+ /* Read back the reset value of the control register */
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Enable the clock and wait for a short while */
-+ value |= ASP_CLKEN;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+ udelay(100);
-+
-+ /* Set the value of the conrtol register. */
-+ value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Set the clock divide ratio to 2. */
-+ mx1_reg_write(ASP_CLKDIV, 0x01);
-+
-+ /* Set the sample rate control register. These values should yield
-+ * about 150 samples per second, which seems to give good smooth
-+ * lines. */
-+ value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */
-+ (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */
-+ (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */
-+ mx1_reg_write(ASP_PSMPLRG, value);
-+
-+ /* Disable the compare function. */
-+ mx1_reg_write(ASP_CMPCNTL, 0);
-+}
-+
-+static void mx1_ts_enable_auto_sample(void)
-+{
-+ unsigned int value;
-+
-+ mx1_ts_flush_fifo();
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to X then Y */
-+ value &= ~ASP_MODE_MASK;
-+ value |= ASP_MODE_ONLY_Y;
-+
-+ /* Enable auto zero. */
-+ value |= ASP_AZE;
-+
-+ /* Enable auto sample. */
-+ value |= ASP_AUTO;
-+
-+ /* Enable pen A/D. */
-+ value |= ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Enable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PFFE | ASP_PDRE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_auto_sample(void)
-+{
-+ unsigned int value;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to none */
-+ value &= ~ASP_MODE_MASK;
-+
-+ /* Disable auto zero. */
-+ value &= ~ASP_AZE;
-+
-+ /* Disable auto sample. */
-+ value &= ~ASP_AUTO;
-+
-+ /* Disable pen A/D. */
-+ value &= ~ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Disable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~(ASP_PFFE | ASP_PDRE);
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_enable_pen_touch_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen touch interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_EDGE | ASP_PIRQE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_pen_touch_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen touch interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~ASP_PIRQE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_enable_pen_up_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen up interrupt. XXX: This feature is undocumented. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_pen_up_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen up interrupt. XXX: This feature is undocumented. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_start_auto_calibration(void)
-+{
-+ unsigned int value;
-+
-+ mx1_performing_auto_calibration = 1;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to X then Y */
-+ value &= ~ASP_MODE_MASK;
-+ value |= ASP_MODE_ONLY_X;
-+
-+ /* Enable auto zero. */
-+ value |= ASP_AZE;
-+
-+ /* Enable auto calibrate. XXX: Undocumented bitfield. */
-+ value |= 0x04000000;
-+
-+ /* Enable auto sample. */
-+ value |= ASP_AUTO;
-+
-+ /* Enable pen A/D. */
-+ value |= ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Enable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PFFE | ASP_PDRE | ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static int mx1_ts_startup(struct mx1_ts *ts)
-+{
-+ int ret = 0;
-+
-+ if (ts->use_count++ != 0)
-+ goto out;
-+
-+ /*
-+ * Reset the ASP.
-+ */
-+ mx1_ts_reset_asp();
-+
-+
-+ /*
-+ * XXX: Figure out if we need this...
-+ * If we do this at all, we should allow the user to
-+ * measure and read the X and Y resistance at any time.
-+ */
-+ //ts->x_res = mx1_ts_read_xres(ts);
-+ //ts->y_res = mx1_ts_read_yres(ts);
-+
-+ mx1_ts_enable_pen_touch_interrupt();
-+
-+ out:
-+ if (ret)
-+ ts->use_count--;
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static void mx1_ts_shutdown(struct mx1_ts *ts)
-+{
-+ if (--ts->use_count == 0) {
-+ unsigned int value;
-+
-+ /* Turn off the ADC and associated circuitry. */
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+ value &= !(ASP_CLKEN | ASP_PADE | ASP_BGE);
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+ }
-+}
-+
-+/*
-+ * Initialization.
-+ */
-+static int __init mx1_ts_init(void)
-+{
-+ int ret = 0;
-+ struct mx1_ts *ts = &mx1ts;
-+
-+ mx1_ts_reset_asp();
-+
-+ /*
-+ * Enable the IRQ's
-+ */
-+ if ((ret = mx1_ts_enable_irqs()))
-+ return ret;
-+
-+ return mx1_ts_register(ts);
-+}
-+
-+static void __exit mx1_ts_exit(void)
-+{
-+ struct mx1_ts *ts = &mx1ts;
-+
-+ mx1_ts_disable_irqs();
-+ mx1_ts_deregister(ts);
-+}
-+
-+module_init(mx1_ts_init);
-+module_exit(mx1_ts_exit);
-+
-+MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
-+MODULE_DESCRIPTION("MX1 touchscreen driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/input/mx1ts.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,108 @@
-+/*
-+ * linux/drivers/misc/mx1ts.h
-+ *
-+ * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+/* Interrupt numbers */
-+#define ASP_COMPARE_IRQ 5
-+#define ASP_PENDATA_IRQ 33
-+#define ASP_TOUCH_IRQ 46
-+
-+/* Analog signal processor (ASP) control registers */
-+#define ASP_ACNTLCR 0xF0215010 /* Control register */
-+#define ASP_PSMPLRG 0xF0215014 /* Pen A/D sampe rate control */
-+#define ASP_CMPCNTL 0xF0215030 /* Compare control register */
-+#define ASP_ICNTLR 0xF0215018 /* Interrupt control register */
-+#define ASP_ISTATR 0xF021501C /* Interrupt status register */
-+#define ASP_PADFIFO 0xF0215000 /* Pen sample FIFO */
-+#define ASP_CLKDIV 0xF021502C /* Clock divide register */
-+
-+/* ASP control register bits */
-+#define ASP_CLKEN (1 << 25) /* Clock enable */
-+#define ASP_SWRST (1 << 23) /* Software reset */
-+#define ASP_U_SEL (1 << 21) /* U-channel resistor select */
-+#define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */
-+#define ASP_LVM (1 << 19) /* Low voltage output */
-+#define ASP_NM (1 << 18) /* Normal voltage output */
-+#define ASP_HPM (1 << 17) /* High voltage output */
-+#define ASP_GLO (1 << 16) /* Low gain enable */
-+#define ASP_AZE (1 << 15) /* Auto-zero enable */
-+#define ASP_AUTO (1 << 14) /* Auto sampling */
-+#define ASP_SW8 (1 << 11) /* Switch control 8 */
-+#define ASP_SW7 (1 << 10)
-+#define ASP_SW6 (1 << 9)
-+#define ASP_SW5 (1 << 8)
-+#define ASP_SW4 (1 << 7)
-+#define ASP_SW3 (1 << 6)
-+#define ASP_SW2 (1 << 5)
-+#define ASP_SW1 (1 << 4) /* Switch control 1 */
-+#define ASP_VDAE (1 << 3) /* Voice D/A enable */
-+#define ASP_VADE (1 << 2) /* Voice A/D enable */
-+#define ASP_PADE (1 << 1) /* Pen A/D enable */
-+#define ASP_BGE (1 << 0) /* Bandgap enable */
-+
-+#define ASP_MODE_MASK 0x00003000
-+#define ASP_MODE_NONE 0x00000000
-+#define ASP_MODE_ONLY_X 0x00001000
-+#define ASP_MODE_ONLY_Y 0x00002000
-+#define ASP_MODE_ONLY_U 0x00003000
-+
-+/* ASP Pen A/D sample rate control register */
-+#define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */
-+#define ASP_DMCNT_SCALE (12)
-+#define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */
-+#define ASP_BIT_SELECT_SCALE (10)
-+#define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */
-+#define ASP_IDLECNT_SCALE (4)
-+#define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */
-+#define ASP_DSCNT_SCALE (0)
-+
-+/* ASP compare control register */
-+#define ASP_INT (1 << 19) /* Interrupt status */
-+#define ASP_CC (1 << 18) /* Trigger on greater than */
-+#define ASP_INSEL_MASK (0x00030000)
-+#define ASP_INSEL_DISABLE (0x00000000)
-+#define ASP_INSEL_X (0x00010000)
-+#define ASP_INSEL_Y (0x00020000)
-+#define ASP_INSEL_U (0x00030000)
-+#define ASP_COMPARE_VAL_MASK (0x0000FFFF)
-+#define ASP_COMPARE_VAL_SCALE (0)
-+
-+/* ASP interrupt control register bits */
-+#define ASP_PUPE (1 << 10) /* Pen up XXX undocumented */
-+#define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */
-+#define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */
-+#define ASP_POL (1 << 6) /* Pen interrupt polarity */
-+#define ASP_EDGE (1 << 5) /* Edge trigger enable */
-+#define ASP_PIRQE (1 << 4) /* Pen interrupt enable */
-+#define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */
-+#define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */
-+#define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */
-+#define ASP_PDRE (1 << 0) /* Pen data ready interrupt */
-+
-+/* ASP interrupt/error status register bits */
-+#define ASP_PUP (1 << 10) /* Pen up XXX undocumented */
-+#define ASP_BGR (1 << 9) /* Bandgap ready */
-+#define ASP_VOV (1 << 8) /* Voice sample data overflow */
-+#define ASP_POV (1 << 7) /* Pen sample data overflow */
-+#define ASP_PEN (1 << 6) /* Pen interrupt */
-+#define ASP_VDAFF (1 << 5) /* VDAC FIFO full */
-+#define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */
-+#define ASP_VADFF (1 << 3) /* VADC FIFO full */
-+#define ASP_VADDR (1 << 2) /* VADC data ready */
-+#define ASP_PFF (1 << 1) /* Pen sample FIFO full */
-+#define ASP_PDR (1 << 0) /* Pen data ready */
-+
-+/* ASP Clock divide register */
-+#define ASP_PADC_CLK_MASK (0x0000001F)
-+#define ASP_PADC_CLK_SCALE (0)
-+#define ASP_VADC_CLK_MASK (0x000003E0)
-+#define ASP_VADC_CLK_SCALE (5)
-+#define ASP_VDAC_CLK_MASK (0x00003C00)
-+#define ASP_VDAC_CLK_SCALE (10)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,21 @@
-+#
-+# L3 bus configuration
-+#
-+mainmenu_option next_comment
-+comment 'L3 serial bus support'
-+
-+tristate 'L3 support' CONFIG_L3
-+dep_bool ' L3 bit-banging interfaces' CONFIG_L3_ALGOBIT $CONFIG_L3
-+dep_bool ' SA11x0 GPIO adapter' CONFIG_L3_BIT_SA1100_GPIO $CONFIG_L3_ALGOBIT $CONFIG_ARCH_SA1100
-+
-+comment 'Other L3 adapters'
-+dep_bool ' SA1111 adapter' CONFIG_L3_SA1111 $CONFIG_L3
-+endmenu
-+
-+# i2c must come before this
-+if [ "$CONFIG_L3_BIT_SA1100_GPIO" = "y" -o \
-+ "$CONFIG_I2C_BIT_SA1100_GPIO" = "y" ]; then
-+ define_bool CONFIG_BIT_SA1100_GPIO y
-+else
-+ define_bool CONFIG_BIT_SA1100_GPIO n
-+fi
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,23 @@
-+#
-+# Makefile for the L3 bus driver.
-+#
-+
-+O_TARGET := l3.o
-+
-+export-objs := l3-core.o l3-algo-bit.o
-+l3-y :=
-+l3-n :=
-+l3-drv-y :=
-+l3-drv-n :=
-+
-+# Link order:
-+# (core, adapters, algorithms, drivers) then clients
-+
-+l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o
-+l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o
-+l3-$(CONFIG_L3_SA1111) += l3-sa1111.o
-+
-+obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y)
-+
-+include $(TOPDIR)/Rules.make
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/l3-algo-bit.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,175 @@
-+/*
-+ * L3 bus algorithm module.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Note that L3 buses can share the same pins as I2C buses, so we must
-+ * _not_ generate an I2C start condition. An I2C start condition is
-+ * defined as a high-to-low transition of the data line while the clock
-+ * is high. Therefore, we must only change the data line while the
-+ * clock is low.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/algo-bit.h>
-+
-+#define setdat(adap,val) adap->setdat(adap->data, val)
-+#define setclk(adap,val) adap->setclk(adap->data, val)
-+#define setmode(adap,val) adap->setmode(adap->data, val)
-+#define setdatin(adap) adap->setdir(adap->data, 1)
-+#define setdatout(adap) adap->setdir(adap->data, 0)
-+#define getdat(adap) adap->getdat(adap->data)
-+
-+/*
-+ * Send one byte of data to the chip. Data is latched into the chip on
-+ * the rising edge of the clock.
-+ */
-+static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte)
-+{
-+ int i;
-+
-+ for (i = 0; i < 8; i++) {
-+ setclk(adap, 0);
-+ udelay(adap->data_hold);
-+ setdat(adap, byte & 1);
-+ udelay(adap->data_setup);
-+ setclk(adap, 1);
-+ udelay(adap->clock_high);
-+ byte >>= 1;
-+ }
-+}
-+
-+/*
-+ * Send a set of bytes to the chip. We need to pulse the MODE line
-+ * between each byte, but never at the start nor at the end of the
-+ * transfer.
-+ */
-+static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ if (i) {
-+ udelay(adap->mode_hold);
-+ setmode(adap, 0);
-+ udelay(adap->mode);
-+ }
-+ setmode(adap, 1);
-+ udelay(adap->mode_setup);
-+ sendbyte(adap, buf[i]);
-+ }
-+}
-+
-+/*
-+ * Read one byte of data from the chip. Data is latched into the chip on
-+ * the rising edge of the clock.
-+ */
-+static unsigned int readbyte(struct l3_algo_bit_data *adap)
-+{
-+ unsigned int byte = 0;
-+ int i;
-+
-+ for (i = 0; i < 8; i++) {
-+ setclk(adap, 0);
-+ udelay(adap->data_hold + adap->data_setup);
-+ setclk(adap, 1);
-+ if (getdat(adap))
-+ byte |= 1 << i;
-+ udelay(adap->clock_high);
-+ }
-+
-+ return byte;
-+}
-+
-+/*
-+ * Read a set of bytes from the chip. We need to pulse the MODE line
-+ * between each byte, but never at the start nor at the end of the
-+ * transfer.
-+ */
-+static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ if (i) {
-+ udelay(adap->mode_hold);
-+ setmode(adap, 0);
-+ }
-+ setmode(adap, 1);
-+ udelay(adap->mode_setup);
-+ buf[i] = readbyte(adap);
-+ }
-+}
-+
-+static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num)
-+{
-+ struct l3_algo_bit_data *adap = l3_adap->algo_data;
-+ int i;
-+
-+ /*
-+ * If we share an I2C bus, ensure that it is in STOP mode
-+ */
-+ setclk(adap, 1);
-+ setdat(adap, 1);
-+ setmode(adap, 1);
-+ setdatout(adap);
-+ udelay(adap->mode);
-+
-+ for (i = 0; i < num; i++) {
-+ struct l3_msg *pmsg = &msgs[i];
-+
-+ if (!(pmsg->flags & L3_M_NOADDR)) {
-+ setmode(adap, 0);
-+ udelay(adap->mode_setup);
-+ sendbyte(adap, pmsg->addr);
-+ udelay(adap->mode_hold);
-+ }
-+
-+ if (pmsg->flags & L3_M_RD) {
-+ setdatin(adap);
-+ readbytes(adap, pmsg->buf, pmsg->len);
-+ } else {
-+ setdatout(adap);
-+ sendbytes(adap, pmsg->buf, pmsg->len);
-+ }
-+ }
-+
-+ /*
-+ * Ensure that we leave the bus in I2C stop mode.
-+ */
-+ setclk(adap, 1);
-+ setdat(adap, 1);
-+ setmode(adap, 0);
-+ setdatin(adap);
-+
-+ return num;
-+}
-+
-+static struct l3_algorithm l3_bit_algo = {
-+ name: "L3 bit-shift algorithm",
-+ xfer: l3_xfer,
-+};
-+
-+int l3_bit_add_bus(struct l3_adapter *adap)
-+{
-+ adap->algo = &l3_bit_algo;
-+ return l3_add_adapter(adap);
-+}
-+
-+int l3_bit_del_bus(struct l3_adapter *adap)
-+{
-+ return l3_del_adapter(adap);
-+}
-+
-+EXPORT_SYMBOL(l3_bit_add_bus);
-+EXPORT_SYMBOL(l3_bit_del_bus);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/l3-bit-sa1100.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,277 @@
-+/*
-+ * linux/drivers/l3/l3-bit-sa1100.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is a combined I2C and L3 bus driver.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/ioport.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/i2c-algo-bit.h>
-+#include <linux/l3/algo-bit.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/assabet.h>
-+
-+#define NAME "l3-bit-sa1100-gpio"
-+
-+struct bit_data {
-+ unsigned int sda;
-+ unsigned int scl;
-+ unsigned int l3_mode;
-+};
-+
-+static int getsda(void *data)
-+{
-+ struct bit_data *bits = data;
-+
-+ return GPLR & bits->sda;
-+}
-+
-+#ifdef CONFIG_I2C_BIT_SA1100_GPIO
-+static void i2c_setsda(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPDR &= ~bits->sda;
-+ else {
-+ GPCR = bits->sda;
-+ GPDR |= bits->sda;
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+static void i2c_setscl(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPDR &= ~bits->scl;
-+ else {
-+ GPCR = bits->scl;
-+ GPDR |= bits->scl;
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+static int i2c_getscl(void *data)
-+{
-+ struct bit_data *bits = data;
-+
-+ return GPLR & bits->scl;
-+}
-+
-+static struct i2c_algo_bit_data i2c_bit_data = {
-+ setsda: i2c_setsda,
-+ setscl: i2c_setscl,
-+ getsda: getsda,
-+ getscl: i2c_getscl,
-+ udelay: 10,
-+ mdelay: 10,
-+ timeout: 100,
-+};
-+
-+static struct i2c_adapter i2c_adapter = {
-+ name: NAME,
-+ algo_data: &i2c_bit_data,
-+// inc_use: i2c_inc_use,
-+// dec_use: i2c_dec_use,
-+};
-+
-+#define LOCK &i2c_adapter.lock
-+
-+static int __init i2c_init(struct bit_data *bits)
-+{
-+ i2c_bit_data.data = bits;
-+ return i2c_bit_add_bus(&i2c_adapter);
-+}
-+
-+static void i2c_exit(void)
-+{
-+ i2c_bit_del_bus(&i2c_adapter);
-+}
-+
-+#else
-+static DECLARE_MUTEX(l3_lock);
-+#define LOCK &l3_lock
-+#define i2c_init(bits) (0)
-+#define i2c_exit() do { } while (0)
-+#endif
-+
-+#ifdef CONFIG_L3_BIT_SA1100_GPIO
-+/*
-+ * iPAQs need the clock line driven hard high and low.
-+ */
-+static void l3_setscl(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPSR = bits->scl;
-+ else
-+ GPCR = bits->scl;
-+ GPDR |= bits->scl;
-+ local_irq_restore(flags);
-+}
-+
-+static void l3_setsda(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+
-+ if (state)
-+ GPSR = bits->sda;
-+ else
-+ GPCR = bits->sda;
-+}
-+
-+static void l3_setdir(void *data, int in)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (in)
-+ GPDR &= ~bits->sda;
-+ else
-+ GPDR |= bits->sda;
-+ local_irq_restore(flags);
-+}
-+
-+static void l3_setmode(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+
-+ if (state)
-+ GPSR = bits->l3_mode;
-+ else
-+ GPCR = bits->l3_mode;
-+}
-+
-+static struct l3_algo_bit_data l3_bit_data = {
-+ data: NULL,
-+ setdat: l3_setsda,
-+ setclk: l3_setscl,
-+ setmode: l3_setmode,
-+ setdir: l3_setdir,
-+ getdat: getsda,
-+ data_hold: 1,
-+ data_setup: 1,
-+ clock_high: 1,
-+ mode_hold: 1,
-+ mode_setup: 1,
-+};
-+
-+static struct l3_adapter l3_adapter = {
-+ owner: THIS_MODULE,
-+ name: NAME,
-+ algo_data: &l3_bit_data,
-+ lock: LOCK,
-+};
-+
-+static int __init l3_init(struct bit_data *bits)
-+{
-+ l3_bit_data.data = bits;
-+ return l3_bit_add_bus(&l3_adapter);
-+}
-+
-+static void __exit l3_exit(void)
-+{
-+ l3_bit_del_bus(&l3_adapter);
-+}
-+#else
-+#define l3_init(bits) (0)
-+#define l3_exit() do { } while (0)
-+#endif
-+
-+static struct bit_data bit_data;
-+
-+static int __init bus_init(void)
-+{
-+ struct bit_data *bit = &bit_data;
-+ unsigned long flags;
-+ int ret;
-+
-+ if (machine_is_assabet() || machine_is_pangolin()) {
-+ bit->sda = GPIO_GPIO15;
-+ bit->scl = GPIO_GPIO18;
-+ bit->l3_mode = GPIO_GPIO17;
-+ }
-+
-+#if defined(CONFIG_SA1100_H3600) || defined(CONFIG_SA1100_H3100)
-+ if (machine_is_h3600() || machine_is_h3100()) {
-+ bit->sda = GPIO_H3600_L3_DATA;
-+ bit->scl = GPIO_H3600_L3_CLOCK;
-+ bit->l3_mode = GPIO_H3600_L3_MODE;
-+ }
-+#endif
-+
-+#ifdef CONFIG_SA1100_STORK
-+ if (machine_is_stork()) {
-+ bit->sda = GPIO_STORK_L3_I2C_SDA;
-+ bit->scl = GPIO_STORK_L3_I2C_SCL;
-+ bit->l3_mode = GPIO_STORK_L3_MODE;
-+ }
-+#endif
-+
-+ if (!bit->sda)
-+ return -ENODEV;
-+
-+ /*
-+ * Default level for L3 mode is low.
-+ * We set SCL and SDA high (i2c idle state).
-+ */
-+ local_irq_save(flags);
-+ GPDR &= ~(bit->scl | bit->sda);
-+ GPCR = bit->l3_mode | bit->scl | bit->sda;
-+ GPDR |= bit->l3_mode;
-+ local_irq_restore(flags);
-+
-+ if (machine_is_assabet()) {
-+ /*
-+ * Release reset on UCB1300, ADI7171 and UDA1341. We
-+ * need to do this here so that we can communicate on
-+ * the I2C/L3 buses.
-+ */
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ mdelay(1);
-+ ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST);
-+ mdelay(1);
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ }
-+
-+ ret = i2c_init(bit);
-+ if (ret == 0 && bit->l3_mode) {
-+ ret = l3_init(bit);
-+ if (ret)
-+ i2c_exit();
-+ }
-+
-+ return ret;
-+}
-+
-+static void __exit bus_exit(void)
-+{
-+ l3_exit();
-+ i2c_exit();
-+}
-+
-+module_init(bus_init);
-+module_exit(bus_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/l3-core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,377 @@
-+/*
-+ * linux/drivers/l3/l3-core.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * General structure taken from i2c-core.c by Simon G. Vogl
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * See linux/Documentation/l3 for further documentation.
-+ */
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/proc_fs.h>
-+#include <linux/kmod.h>
-+#include <linux/init.h>
-+#include <linux/l3/l3.h>
-+
-+static DECLARE_MUTEX(adapter_lock);
-+static LIST_HEAD(adapter_list);
-+
-+static DECLARE_MUTEX(driver_lock);
-+static LIST_HEAD(driver_list);
-+
-+/**
-+ * l3_add_adapter - register a new L3 bus adapter
-+ * @adap: l3_adapter structure for the registering adapter
-+ *
-+ * Make the adapter available for use by clients using name adap->name.
-+ * The adap->adapters list is initialised by this function.
-+ *
-+ * Returns 0;
-+ */
-+int l3_add_adapter(struct l3_adapter *adap)
-+{
-+ INIT_LIST_HEAD(&adap->clients);
-+ down(&adapter_lock);
-+ list_add(&adap->adapters, &adapter_list);
-+ up(&adapter_lock);
-+ return 0;
-+}
-+
-+/**
-+ * l3_del_adapter - unregister a L3 bus adapter
-+ * @adap: l3_adapter structure to unregister
-+ *
-+ * Remove an adapter from the list of available L3 Bus adapters.
-+ *
-+ * Returns 0;
-+ */
-+int l3_del_adapter(struct l3_adapter *adap)
-+{
-+ down(&adapter_lock);
-+ list_del(&adap->adapters);
-+ up(&adapter_lock);
-+ return 0;
-+}
-+
-+static struct l3_adapter *__l3_get_adapter(const char *name)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &adapter_list) {
-+ struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
-+
-+ if (strcmp(adap->name, name) == 0)
-+ return adap;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * l3_get_adapter - get a reference to an adapter
-+ * @name: driver name
-+ *
-+ * Obtain a l3_adapter structure for the specified adapter. If the adapter
-+ * is not currently load, then load it. The adapter will be locked in core
-+ * until all references are released via l3_put_adapter.
-+ */
-+struct l3_adapter *l3_get_adapter(const char *name)
-+{
-+ struct l3_adapter *adap;
-+ int try;
-+
-+ for (try = 0; try < 2; try ++) {
-+ down(&adapter_lock);
-+ adap = __l3_get_adapter(name);
-+ if (adap && !try_inc_mod_count(adap->owner))
-+ adap = NULL;
-+ up(&adapter_lock);
-+
-+ if (adap)
-+ break;
-+
-+ if (try == 0)
-+ request_module(name);
-+ }
-+
-+ return adap;
-+}
-+
-+/**
-+ * l3_put_adapter - release a reference to an adapter
-+ * @adap: driver to release reference
-+ *
-+ * Indicate to the L3 core that you no longer require the adapter reference.
-+ * The adapter module may be unloaded when there are no references to its
-+ * data structure.
-+ *
-+ * You must not use the reference after calling this function.
-+ */
-+void l3_put_adapter(struct l3_adapter *adap)
-+{
-+ if (adap && adap->owner)
-+ __MOD_DEC_USE_COUNT(adap->owner);
-+}
-+
-+/**
-+ * l3_add_driver - register a new L3 device driver
-+ * @driver - driver structure to make available
-+ *
-+ * Make the driver available for use by clients using name driver->name.
-+ * The driver->drivers list is initialised by this function.
-+ *
-+ * Returns 0;
-+ */
-+int l3_add_driver(struct l3_driver *driver)
-+{
-+ down(&driver_lock);
-+ list_add(&driver->drivers, &driver_list);
-+ up(&driver_lock);
-+ return 0;
-+}
-+
-+/**
-+ * l3_del_driver - unregister a L3 device driver
-+ * @driver: driver to remove
-+ *
-+ * Remove an driver from the list of available L3 Bus device drivers.
-+ *
-+ * Returns 0;
-+ */
-+int l3_del_driver(struct l3_driver *driver)
-+{
-+ down(&driver_lock);
-+ list_del(&driver->drivers);
-+ up(&driver_lock);
-+ return 0;
-+}
-+
-+static struct l3_driver *__l3_get_driver(const char *name)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &driver_list) {
-+ struct l3_driver *drv = list_entry(l, struct l3_driver, drivers);
-+
-+ if (strcmp(drv->name, name) == 0)
-+ return drv;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * l3_get_driver - get a reference to a driver
-+ * @name: driver name
-+ *
-+ * Obtain a l3_driver structure for the specified driver. If the driver is
-+ * not currently load, then load it. The driver will be locked in core
-+ * until all references are released via l3_put_driver.
-+ */
-+struct l3_driver *l3_get_driver(const char *name)
-+{
-+ struct l3_driver *drv;
-+ int try;
-+
-+ for (try = 0; try < 2; try ++) {
-+ down(&adapter_lock);
-+ drv = __l3_get_driver(name);
-+ if (drv && !try_inc_mod_count(drv->owner))
-+ drv = NULL;
-+ up(&adapter_lock);
-+
-+ if (drv)
-+ break;
-+
-+ if (try == 0)
-+ request_module(name);
-+ }
-+
-+ return drv;
-+}
-+
-+/**
-+ * l3_put_driver - release a reference to a driver
-+ * @drv: driver to release reference
-+ *
-+ * Indicate to the L3 core that you no longer require the driver reference.
-+ * The driver module may be unloaded when there are no references to its
-+ * data structure.
-+ *
-+ * You must not use the reference after calling this function.
-+ */
-+void l3_put_driver(struct l3_driver *drv)
-+{
-+ if (drv && drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+}
-+
-+/**
-+ * l3_attach_client - attach a client to an adapter and driver
-+ * @client: client structure to attach
-+ * @adap: adapter (module) name
-+ * @drv: driver (module) name
-+ *
-+ * Attempt to attach a client (a user of a device driver) to a particular
-+ * driver and adapter. If the specified driver or adapter aren't registered,
-+ * request_module is used to load the relevant modules.
-+ *
-+ * Returns 0 on success, or negative error code.
-+ */
-+int l3_attach_client(struct l3_client *client, const char *adap, const char *drv)
-+{
-+ struct l3_adapter *adapter = l3_get_adapter(adap);
-+ struct l3_driver *driver = l3_get_driver(drv);
-+ int ret = -ENOENT;
-+
-+ if (!adapter)
-+ printk(KERN_ERR "%s: unable to get adapter: %s\n",
-+ __FUNCTION__, adap);
-+ if (!driver)
-+ printk(KERN_ERR "%s: unable to get driver: %s\n",
-+ __FUNCTION__, drv);
-+
-+ if (adapter && driver) {
-+ ret = 0;
-+
-+ client->adapter = adapter;
-+ client->driver = driver;
-+
-+ list_add(&client->__adap, &adapter->clients);
-+
-+ if (driver->attach_client)
-+ ret = driver->attach_client(client);
-+ }
-+
-+ if (ret) {
-+ l3_put_driver(driver);
-+ l3_put_adapter(adapter);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * l3_detach_client - detach a client from an adapter and driver
-+ * @client: client structure to detach
-+ *
-+ * Detach the client from the adapter and driver.
-+ */
-+int l3_detach_client(struct l3_client *client)
-+{
-+ struct l3_adapter *adapter = client->adapter;
-+ struct l3_driver *driver = client->driver;
-+
-+ driver->detach_client(client);
-+
-+ client->adapter = NULL;
-+ client->driver = NULL;
-+
-+ l3_put_driver(driver);
-+ l3_put_adapter(adapter);
-+
-+ list_del(&client->__adap);
-+
-+ return 0;
-+}
-+
-+/**
-+ * l3_transfer - transfer information on an L3 bus
-+ * @adap: adapter structure to perform transfer on
-+ * @msgs: array of l3_msg structures describing transfer
-+ * @num: number of l3_msg structures
-+ *
-+ * Transfer the specified messages to/from a device on the L3 bus.
-+ *
-+ * Returns number of messages successfully transferred, otherwise negative
-+ * error code.
-+ */
-+int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
-+{
-+ int ret = -ENOSYS;
-+
-+ if (adap->algo->xfer) {
-+ down(adap->lock);
-+ ret = adap->algo->xfer(adap, msgs, num);
-+ up(adap->lock);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * l3_write - send data to a device on an L3 bus
-+ * @client: registered client structure
-+ * @addr: L3 bus address
-+ * @buf: buffer for bytes to send
-+ * @len: number of bytes to send
-+ *
-+ * Send len bytes pointed to by buf to device address addr on the L3 bus
-+ * described by client.
-+ *
-+ * Returns the number of bytes transferred, or negative error code.
-+ */
-+int l3_write(struct l3_client *client, int addr, const char *buf, int len)
-+{
-+ struct l3_adapter *adap = client->adapter;
-+ struct l3_msg msg;
-+ int ret;
-+
-+ msg.addr = addr;
-+ msg.flags = 0;
-+ msg.buf = (char *)buf;
-+ msg.len = len;
-+
-+ ret = l3_transfer(adap, &msg, 1);
-+ return ret == 1 ? len : ret;
-+}
-+
-+/**
-+ * l3_read - receive data from a device on an L3 bus
-+ * @client: registered client structure
-+ * @addr: L3 bus address
-+ * @buf: buffer for bytes to receive
-+ * @len: number of bytes to receive
-+ *
-+ * Receive len bytes from device address addr on the L3 bus described by
-+ * client to a buffer pointed to by buf.
-+ *
-+ * Returns the number of bytes transferred, or negative error code.
-+ */
-+int l3_read(struct l3_client *client, int addr, char *buf, int len)
-+{
-+ struct l3_adapter *adap = client->adapter;
-+ struct l3_msg msg;
-+ int ret;
-+
-+ msg.addr = addr;
-+ msg.flags = L3_M_RD;
-+ msg.buf = buf;
-+ msg.len = len;
-+
-+ ret = l3_transfer(adap, &msg, 1);
-+ return ret == 1 ? len : ret;
-+}
-+
-+EXPORT_SYMBOL(l3_add_adapter);
-+EXPORT_SYMBOL(l3_del_adapter);
-+EXPORT_SYMBOL(l3_get_adapter);
-+EXPORT_SYMBOL(l3_put_adapter);
-+
-+EXPORT_SYMBOL(l3_add_driver);
-+EXPORT_SYMBOL(l3_del_driver);
-+EXPORT_SYMBOL(l3_get_driver);
-+EXPORT_SYMBOL(l3_put_driver);
-+
-+EXPORT_SYMBOL(l3_attach_client);
-+EXPORT_SYMBOL(l3_detach_client);
-+
-+EXPORT_SYMBOL(l3_transfer);
-+EXPORT_SYMBOL(l3_write);
-+EXPORT_SYMBOL(l3_read);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/l3/l3-sa1111.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,118 @@
-+/*
-+ * L3 SA1111 algorithm/adapter module.
-+ *
-+ * By Russell King,
-+ * gratuitously ripped from sa1111-uda1341.c by John Dorsey.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/l3/l3.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/hardware/sa1111.h>
-+
-+static inline unsigned char l3_sa1111_recv_byte(unsigned char addr)
-+{
-+ unsigned char dat;
-+
-+ L3_CAR = addr;
-+ while ((SASR0 & SASR0_L3RD) == 0)
-+ mdelay(1);
-+ dat = L3_CDR;
-+ SASCR = SASCR_RDD;
-+ return dat;
-+}
-+
-+static void l3_sa1111_recv_msg(struct l3_msg *msg)
-+{
-+ int len = msg->len;
-+ char *p = msg->buf;
-+
-+ if (len > 1) {
-+ SACR1 |= SACR1_L3MB;
-+ while ((len--) > 1)
-+ *p++ = l3_sa1111_recv_byte(msg->addr);
-+ }
-+ SACR1 &= ~SACR1_L3MB;
-+ *p = l3_sa1111_recv_byte(msg->addr);
-+}
-+
-+static inline void l3_sa1111_send_byte(unsigned char addr, unsigned char dat)
-+{
-+ L3_CAR = addr;
-+ L3_CDR = dat;
-+ while ((SASR0 & SASR0_L3WD) == 0)
-+ mdelay(1);
-+ SASCR = SASCR_DTS;
-+}
-+
-+static void l3_sa1111_send_msg(struct l3_msg *msg)
-+{
-+ int len = msg->len;
-+ char *p = msg->buf;
-+
-+ if (len > 1) {
-+ SACR1 |= SACR1_L3MB;
-+ while ((len--) > 1)
-+ l3_sa1111_send_byte(msg->addr, *p++);
-+ }
-+ SACR1 &= ~SACR1_L3MB;
-+ l3_sa1111_send_byte(msg->addr, *p);
-+}
-+
-+static int l3_sa1111_xfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
-+{
-+ int i;
-+
-+ for (i = 0; i < num; i++) {
-+ struct l3_msg *pmsg = &msgs[i];
-+
-+ if (pmsg->flags & L3_M_RD)
-+ l3_sa1111_recv_msg(pmsg);
-+ else
-+ l3_sa1111_send_msg(pmsg);
-+ }
-+
-+ return num;
-+}
-+
-+static struct l3_algorithm l3_sa1111_algo = {
-+ name: "L3 SA1111 algorithm",
-+ xfer: l3_sa1111_xfer,
-+};
-+
-+static DECLARE_MUTEX(sa1111_lock);
-+
-+static struct l3_adapter l3_sa1111_adapter = {
-+ owner: THIS_MODULE,
-+ name: "l3-sa1111",
-+ algo: &l3_sa1111_algo,
-+ lock: &sa1111_lock,
-+};
-+
-+static int __init l3_sa1111_init(void)
-+{
-+ int ret = -ENODEV;
-+ if ((machine_is_assabet() && machine_has_neponset()) ||
-+ machine_is_jornada720() || machine_is_accelent_sa() ||
-+ machine_is_badge4())
-+ ret = l3_add_adapter(&l3_sa1111_adapter);
-+ return ret;
-+}
-+
-+static void __exit l3_sa1111_exit(void)
-+{
-+ l3_del_adapter(&l3_sa1111_adapter);
-+}
-+
-+module_init(l3_sa1111_init);
-+module_exit(l3_sa1111_exit);
---- linux-2.4.25/drivers/media/video/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/media/video/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -52,5 +52,8 @@
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
- fi
-+# unfortunately, this depends on having CONFIG_FB_CYBER2000
-+# set as well - we hook off of the VGA driver
-+dep_tristate ' NetWinder Video for Linux (EXPERIMENTAL)' CONFIG_VIDEO_CYBERPRO $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL $CONFIG_ARCH_NETWINDER
-
- endmenu
---- linux-2.4.25/drivers/media/video/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/media/video/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -16,7 +16,7 @@
- obj-n :=
- obj- :=
-
--SUB_DIRS :=
-+SUB_DIRS :=
- MOD_SUB_DIRS := $(SUB_DIRS)
- ALL_SUB_DIRS := $(SUB_DIRS)
-
-@@ -47,7 +47,8 @@
- obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
- obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
- obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
--obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
-+obj-$(CONFIG_VIDEO_CYBERPRO) += cyberpro.o i2c-old.o saa7111.o
-+obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
- obj-$(CONFIG_VIDEO_PMS) += pms.o
- obj-$(CONFIG_VIDEO_PLANB) += planb.o
- obj-$(CONFIG_VIDEO_VINO) += saa7191.o indycam.o vino.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/media/video/cyberpro.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,2091 @@
-+/*
-+ * CyberPro 2000 video capture driver for the Rebel.com NetWinder
-+ *
-+ * (C) 1999-2000 Russell King
-+ *
-+ * Re-written from Rebel.com's vidcap driver.
-+ *
-+ * Architecture
-+ * ------------
-+ * The NetWinder video capture consists of a SAA7111 video decoder chip
-+ * connected to the CyberPro feature bus. The video data is captured to
-+ * the VGA memory, where the CyberPro can overlay (by chromakeying) the
-+ * data onto the VGA display.
-+ *
-+ * The CyberPro also has some nifty features, including a second overlay
-+ * and picture in picture mode. We do not currently use these features.
-+ *
-+ * Power Saving
-+ * ------------
-+ * Please note that rev.5 NetWinders have the ability to hold the SAA7111
-+ * decoder chip into reset, which saves power. The only time at which
-+ * this is done is when the driver is unloaded, which implies that this
-+ * is compiled as a module.
-+ *
-+ * In this case, you will want the kernel to automatically load this
-+ * driver when required. Place the following line in /etc/modules.conf
-+ * to enable this:
-+ *
-+ * alias char-major-81-0 cyberpro
-+ *
-+ * The relevant modules will be automatically loaded by modprobe on a
-+ * as and when needed basis.
-+ *
-+ * Capture resolution
-+ * ------------------
-+ * The maximum useful capture resolution is:
-+ * 625-line UK: 716x576
-+ * 525-line US: ?
-+ *
-+ * Bugs
-+ * ----
-+ * 1. The CyberPro chip seems to be prone to randomly scribbling over VGA
-+ * memory [hopefully fixed with new capture enable/freeze stuff]
-+ * 2. read()ing pauses video capture, and sometimes triggers bug 1.
-+ * 3. mmap() is not supported (requires BM-DMA - see bug 4)
-+ * 4. Really, we want to do scatter BM-DMA. Is the CyberPro capable of this?
-+ * The Cyberpro seems to randomly scribble to various PCI addresses if you
-+ * transfer >16 words.
-+ * 5. We shouldn't ignore O_NONBLOCK when reading a frame.
-+ * 6. The incoming stream on the NetWinder is CCIR656, which is YUV422.
-+ * CyberPro docs also call the format we capture and overlay "YUV422",
-+ * but we actually seem to have Y, U, Y, V bytes (is this YUYV format?)
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/videodev.h>
-+#include <linux/video_decoder.h>
-+#include <linux/mm.h>
-+#include <linux/i2c-old.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/kmod.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/pgtable.h>
-+#include <asm/pgalloc.h>
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("CyberPro v4l video grabber");
-+MODULE_LICENSE("GPL");
-+
-+#include "../../video/cyber2000fb.h"
-+
-+/*
-+ * These enable various experimental features. Most of these
-+ * are just plain broken or just don't work at the moment.
-+ */
-+/*
-+ * Enable this if you want mmap() access. (see bug 4)
-+ */
-+#undef USE_MMAP
-+
-+/*
-+ * Enable this if you want mmio access. (slow)
-+ */
-+#define USE_MMIO
-+
-+/*
-+ * The V4L API is unclear whether VIDIOCSCAPTURE call is allowed while
-+ * capture is running. The default is to disallow the call.
-+ *
-+ * Define this if you do want to allow the call while capture is active.
-+ */
-+#undef ALLOW_SCAPTURE_WHILE_CAP
-+
-+/*
-+ * We capture two frames
-+ */
-+#define NR_FRAMES 2
-+
-+/*
-+ * One frame of video is 202 pages, assuming YUV422 format, 716x576
-+ */
-+#define NR_PAGES 202
-+
-+struct src_info {
-+ unsigned int offset; /* offset of source data */
-+ unsigned int x; /* source x */
-+ unsigned int y; /* source y */
-+ unsigned int width; /* source width */
-+ unsigned int height; /* source height */
-+ unsigned int format; /* source format */
-+};
-+
-+struct dst_info {
-+ unsigned int x; /* destination x */
-+ unsigned int y; /* destination y */
-+ unsigned int width; /* destination width */
-+ unsigned int height; /* destination height */
-+ unsigned int chromakey; /* chromakey */
-+ unsigned int flags; /* flags (eg, chromakey enable) */
-+};
-+
-+struct cyberpro_vidinfo;
-+
-+struct win_info {
-+ void (*init)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*set_src)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*set_win)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*ctl)(struct cyberpro_vidinfo *dp, struct win_info *wi, int on_off);
-+
-+ /* public */
-+ struct src_info src;
-+ struct dst_info dst;
-+
-+ /* private */
-+ unsigned short vid_fifo_ctl;
-+ unsigned char vid_fmt;
-+ unsigned char vid_disp_ctl1;
-+ unsigned char vid_fifo_ctl1;
-+ unsigned char vid_misc_ctl1;
-+};
-+
-+struct framebuf {
-+ unsigned int offset; /* mmap offset for this frame */
-+ unsigned int status;
-+#define FRAME_FREE 0
-+#define FRAME_DONE 1
-+#define FRAME_WAITING 2
-+#define FRAME_GRABBING 3
-+
-+ /*
-+ * Bus-Master DMA stuff. Note that we should
-+ * probably use the kiovec stuff instead.
-+ */
-+ unsigned long bus_addr[NR_PAGES]; /* list of pages */
-+ struct page *pages[NR_PAGES];
-+ void *buffer;
-+ int dbg;
-+};
-+
-+struct cyberpro_vidinfo {
-+ struct video_device *dev;
-+ struct i2c_bus *bus;
-+ struct cyberpro_info info; /* host information */
-+ unsigned char *regs;
-+ unsigned int irq; /* PCI interrupt number */
-+
-+ /* hardware configuration */
-+ unsigned int stream_fmt; /* format of stream from decoder*/
-+
-+ /* software settings */
-+ unsigned int decoder:1; /* decoder loaded */
-+ unsigned int interlace:1; /* interlace */
-+ unsigned int buf_set:1; /* VIDIOCSFBUF has been issued */
-+ unsigned int win_set:1; /* VIDIOCSWIN has been issued */
-+ unsigned int cap_active:1; /* capture is active */
-+ unsigned int ovl_active:1; /* overlay is active */
-+ unsigned int mmaped:1; /* buffer is mmap()d */
-+ unsigned int unused:25;
-+
-+ unsigned int users; /* number of users */
-+ unsigned long cap_mem_offset; /* capture framebuffer offset */
-+ void * buffer; /* kernel capture buffer */
-+ unsigned int norm; /* video standard */
-+
-+ struct video_capability cap; /* capabilities */
-+ struct video_picture pic; /* current picture settings */
-+ struct video_buffer buf; /* display parameters */
-+ struct video_capture capt; /* video capture params */
-+
-+ struct win_info *ovl; /* overlay window set */
-+ struct win_info ext; /* "Extended" window info */
-+ struct win_info v2; /* "V2" window info */
-+ struct win_info x2; /* "X2" window info */
-+
-+ unsigned int bm_offset; /* Cap memory bus master offset */
-+ unsigned int bm_index; /* Cap page index */
-+
-+#ifdef USE_MMAP
-+ unsigned int frame_idx; /* currently grabbing frame */
-+ unsigned int frame_size;
-+ struct framebuf frame[NR_FRAMES];
-+ wait_queue_head_t frame_wait;
-+#endif
-+
-+ wait_queue_head_t vbl_wait;
-+
-+ /*
-+ * cyberpro registers
-+ */
-+ unsigned char cap_mode1;
-+ unsigned char cap_mode2;
-+ unsigned char cap_miscctl;
-+ unsigned char vfac1;
-+ unsigned char vfac3;
-+};
-+
-+/*
-+ * Our access methods.
-+ */
-+#define cyberpro_writel(val,reg,dp) writel(val, (dp)->regs + (reg))
-+#define cyberpro_writew(val,reg,dp) writew(val, (dp)->regs + (reg))
-+#define cyberpro_writeb(val,reg,dp) writeb(val, (dp)->regs + (reg))
-+
-+#define cyberpro_readb(reg,dp) readb((dp)->regs + (reg))
-+
-+static inline void
-+cyberpro_grphw(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_writew((reg & 255) | val << 8, 0x3ce, dp);
-+}
-+
-+static void cyberpro_grphw8(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+}
-+
-+static unsigned char cyberpro_grphr8(int reg, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_writeb(reg, 0x3ce, dp);
-+ return cyberpro_readb(0x3cf, dp);
-+}
-+
-+static void cyberpro_grphw16(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+ cyberpro_grphw(reg + 1, val >> 8, dp);
-+}
-+
-+static void cyberpro_grphw24(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+ cyberpro_grphw(reg + 1, val >> 8, dp);
-+ cyberpro_grphw(reg + 2, val >> 16, dp);
-+}
-+
-+#if 0
-+static void
-+cyberpro_dbg_dump(void)
-+{
-+ int i;
-+ unsigned char idx[] =
-+ { 0x30, 0x3e, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
-+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad };
-+ printk(KERN_DEBUG);
-+ for (i = 0; i < sizeof(idx); i++)
-+ printk("%02x ", idx[i]);
-+ printk("\n" KERN_DEBUG);
-+ for (i = 0; i < sizeof(idx); i++)
-+ printk("%02x ", cyberpro_grphr8(idx[i]));
-+ printk("\n");
-+}
-+#endif
-+
-+/*
-+ * On the NetWinder, we can put the SAA7111 to sleep by holding
-+ * it in reset.
-+ *
-+ * Note: once we have initialised the SAA7111, we can't put it back to
-+ * sleep and expect it to keep its settings. Maybe a better solution
-+ * is to register/de-register the i2c bus in open/release?
-+ */
-+static void
-+decoder_sleep(int sleep)
-+{
-+#ifdef CONFIG_ARCH_NETWINDER
-+ extern spinlock_t gpio_lock;
-+
-+ spin_lock_irq(&gpio_lock);
-+ cpld_modify(CPLD_7111_DISABLE, sleep ? CPLD_7111_DISABLE : 0);
-+ spin_unlock_irq(&gpio_lock);
-+
-+ if (!sleep) {
-+ /*
-+ * wait 20ms for device to wake up
-+ */
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ / 50);
-+ }
-+#endif
-+}
-+
-+/* -------------------------------- I2C support ---------------------------- */
-+
-+#define I2C_DELAY 100
-+
-+static void
-+cyberpro_i2c_setlines(struct i2c_bus *bus, int ctrl, int data)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ int v;
-+
-+ v = (ctrl ? EXT_LATCH2_I2C_CLKEN : 0x00) | (data ? EXT_LATCH2_I2C_DATEN : 0x00);
-+ cyberpro_grphw8(EXT_LATCH2, v, dp);
-+
-+ udelay(I2C_DELAY);
-+}
-+
-+static int
-+cyberpro_i2c_getdataline(struct i2c_bus *bus)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ unsigned long flags;
-+ int v;
-+
-+ save_flags(flags);
-+ cli();
-+
-+ v = cyberpro_grphr8(EXT_LATCH2, dp);
-+
-+ restore_flags(flags);
-+
-+ return v & EXT_LATCH2_I2C_DAT ? 1 : 0;
-+}
-+
-+static void
-+cyberpro_i2c_attach(struct i2c_bus *bus, int id)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ int zero = 0;
-+
-+ if (id == I2C_DRIVERID_VIDEODECODER) {
-+ __u16 norm = dp->norm;
-+ i2c_control_device(bus, id, DECODER_SET_NORM, &norm);
-+ i2c_control_device(bus, id, DECODER_SET_PICTURE, &dp->pic);
-+ i2c_control_device(bus, id, DECODER_ENABLE_OUTPUT, &zero);
-+
-+ dp->decoder = 1;
-+ }
-+}
-+
-+static void
-+cyberpro_i2c_detach(struct i2c_bus *bus, int id)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+
-+ if (id == I2C_DRIVERID_VIDEODECODER)
-+ dp->decoder = 0;
-+}
-+
-+static struct i2c_bus cyberpro_i2c_bus = {
-+ name: "",
-+ id: I2C_BUSID_CYBER2000,
-+ bus_lock: SPIN_LOCK_UNLOCKED,
-+ attach_inform: cyberpro_i2c_attach,
-+ detach_inform: cyberpro_i2c_detach,
-+ i2c_setlines: cyberpro_i2c_setlines,
-+ i2c_getdataline: cyberpro_i2c_getdataline,
-+};
-+
-+/*------------------------- Extended Overlay Window -------------------------
-+ * Initialise 1st overlay window (works)
-+ */
-+static void
-+cyberpro_ext_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fifo_ctl = 0xf87c;
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
-+ EXT_VID_DISP_CTL1_NOCLIP;
-+ wi->vid_fifo_ctl1 = EXT_VID_FIFO_CTL1_INTERLEAVE |
-+ EXT_VID_FIFO_CTL1_OE_HIGH;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8 (EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ cyberpro_grphw16(EXT_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(EXT_DDA_Y_INIT, 0x0800, dp);
-+ cyberpro_grphw16(EXT_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
-+ cyberpro_grphw8 (EXT_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the extended window
-+ */
-+static void
-+cyberpro_ext_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw24(EXT_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(EXT_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (EXT_SRC_WIN_WIDTH, phase, dp);
-+ cyberpro_grphw8 (EXT_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set overlay1 window
-+ */
-+static void
-+cyberpro_ext_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = wi->src.width;
-+
-+ if (wi->dst.width >= wi->src.width * 2) {
-+ wi->vid_fmt |= EXT_VID_FMT_DBL_H_PIX;
-+ xscale *= 2;
-+ } else {
-+ wi->vid_fmt &= ~EXT_VID_FMT_DBL_H_PIX;
-+ }
-+
-+ xscale = ((xscale - /*2*/0) * 4096) / wi->dst.width;
-+ yscale = ((wi->src.height - /*2*/0) * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw16(EXT_X_START, xoff, dp);
-+ cyberpro_grphw16(EXT_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(EXT_Y_START, yoff, dp);
-+ cyberpro_grphw16(EXT_Y_END, yoff + wi->dst.height, dp);
-+ cyberpro_grphw24(EXT_COLOUR_COMPARE, wi->dst.chromakey, dp);
-+ cyberpro_grphw16(EXT_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(EXT_DDA_Y_INC, yscale, dp);
-+ cyberpro_grphw8(EXT_VID_FMT, wi->vid_fmt, dp);
-+
-+ if (wi->dst.flags & VIDEO_WINDOW_CHROMAKEY)
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_IGNORE_CCOMP;
-+ else
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_IGNORE_CCOMP;
-+}
-+
-+/*
-+ * Enable or disable the 1st overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_ext_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/*------------------------------- V2 Overlay Window -------------------------
-+ * Initialise 2nd overlay window (guesswork)
-+ */
-+static void
-+cyberpro_v2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fifo_ctl = 0xf87c;
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
-+ EXT_VID_DISP_CTL1_NOCLIP;
-+ wi->vid_fifo_ctl1 = 0x06;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8 (Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ /* No DDA init values */
-+ cyberpro_grphw16(Y_V2_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
-+ cyberpro_grphw8 (Y_V2_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the v2 window
-+ */
-+static void
-+cyberpro_v2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
-+ cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set v2 window
-+ */
-+static void
-+cyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = (wi->src.width * 4096) / wi->dst.width;
-+ yscale = (wi->src.height * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
-+ cyberpro_grphw16(X_V2_X_START, xoff, dp);
-+ cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(X_V2_Y_START, yoff, dp);
-+ cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp);
-+}
-+
-+/*
-+ * Enable or disable the 2nd overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/*--------------------------- X2 Overlay Window -----------------------------
-+ * Initialise 3rd overlay window (guesswork)
-+ */
-+static void
-+cyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = 0x40;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the x2 window
-+ */
-+static void
-+cyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
-+ cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set x2 window
-+ */
-+static void
-+cyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = (wi->src.width * 4096) / wi->dst.width;
-+ yscale = (wi->src.height * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
-+ cyberpro_grphw16(J_X2_X_START, xoff, dp);
-+ cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(J_X2_Y_START, yoff, dp);
-+ cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp);
-+}
-+
-+/*
-+ * Enable or disable the 3rd overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/* ------------------------------------------------------------------------- */
-+
-+#if 0
-+static void reset_seq(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp);
-+
-+ cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp);
-+ cyberpro_grphw8(ext_mem_ctl, 0x70, dp);
-+}
-+#endif
-+
-+#ifdef USE_MMAP
-+/*
-+ * Buffer support
-+ */
-+static int
-+cyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp,
-+ struct framebuf *frame)
-+{
-+ unsigned long addr;
-+ void *buffer;
-+ int pgidx;
-+
-+ if (frame->buffer)
-+ return 0;
-+
-+ /*
-+ * Allocate frame buffer
-+ */
-+ buffer = vmalloc(NR_PAGES * PAGE_SIZE);
-+
-+ if (frame->buffer) {
-+ vfree(buffer);
-+ return 0;
-+ }
-+
-+ if (!buffer)
-+ return -ENOMEM;
-+
-+ printk("Buffer allocated @ %p [", buffer);
-+
-+ frame->buffer = buffer;
-+ frame->dbg = 1;
-+
-+ /*
-+ * Don't leak information from the kernel.
-+ */
-+ memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE);
-+
-+ /*
-+ * Now, reserve all the pages, and calculate
-+ * each pages' bus address.
-+ */
-+ addr = (unsigned long)buffer;
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) {
-+ struct page *page;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+
-+ /*
-+ * The page should be present. If not,
-+ * vmalloc has gone nuts.
-+ */
-+ pgd = pgd_offset_k(addr);
-+ if (pgd_none(*pgd))
-+ BUG();
-+ pmd = pmd_offset(pgd, addr);
-+ if (pmd_none(*pmd))
-+ BUG();
-+ pte = pte_offset(pmd, addr);
-+ if (!pte_present(*pte))
-+ BUG();
-+
-+ page = pte_page(*pte);
-+
-+ frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page));
-+ frame->pages[pgidx] = page;
-+ SetPageReserved(page);
-+
-+ printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]);
-+ }
-+ printk("\n");
-+
-+ return 0;
-+}
-+
-+static void
-+cyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame)
-+{
-+ void *buffer;
-+ int pgidx;
-+
-+ frame->status = FRAME_FREE;
-+ buffer = frame->buffer;
-+ frame->buffer = NULL;
-+
-+ if (buffer) {
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
-+ frame->bus_addr[pgidx] = 0;
-+ ClearPageReserved(frame->pages[pgidx]);
-+ frame->pages[pgidx] = NULL;
-+ }
-+ vfree(buffer);
-+ }
-+}
-+
-+static void
-+cyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame)
-+{
-+ unsigned long bus_addr;
-+
-+ bus_addr = frame->bus_addr[dp->bm_index];
-+
-+ if (frame->dbg) {
-+ printk("Frame%d: %06x -> %08lx\n",
-+ dp->frame_idx,
-+ dp->bm_offset,
-+ bus_addr);
-+ }
-+
-+ cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW);
-+ cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH);
-+
-+ cyber2000_outw(bus_addr, BM_ADDRESS_LOW);
-+ cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH);
-+
-+ /*
-+ * One page-full only
-+ */
-+ cyber2000_outw(1023, BM_LENGTH);
-+
-+ /*
-+ * Load length
-+ */
-+ cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL);
-+
-+ /*
-+ * Enable transfer
-+ */
-+ cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL);
-+
-+ dp->bm_offset += 1024;
-+ dp->bm_index += 1;
-+}
-+
-+static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp)
-+{
-+ struct framebuf *frame = dp->frame + dp->frame_idx;
-+
-+ /*
-+ * Disable Busmaster operations
-+ */
-+ cyber2000_outw(0, BM_CONTROL);
-+
-+ if (frame->status == FRAME_GRABBING) {
-+ /*
-+ * We are still grabbing this frame to system
-+ * memory. Transfer next page if there are
-+ * more, or else flag this frame as complete.
-+ */
-+ if (dp->bm_index < NR_PAGES)
-+ cyberpro_busmaster_frame(dp);
-+ else {
-+ unsigned int idx;
-+
-+ frame->status = FRAME_DONE;
-+ frame->dbg = 0;
-+
-+ idx = dp->frame_idx + 1;
-+ if (idx >= NR_FRAMES)
-+ idx = 0;
-+
-+ dp->frame_idx = idx;
-+
-+ wake_up(&dp->frame_wait);
-+ }
-+ }
-+}
-+
-+static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat)
-+{
-+ struct framebuf *frame = dp->frame + dp->frame_idx;
-+
-+ /*
-+ * No point capturing frames if the grabber isn't active.
-+ */
-+ if (stat & EXT_ROM_UCB4GH_FREEZE)
-+ return;
-+
-+ /*
-+ * If the next buffer is ready for grabbing,
-+ * set up the bus master registers for the
-+ * transfer.
-+ */
-+ if (frame->status == FRAME_WAITING) {
-+ frame->status = FRAME_GRABBING;
-+
-+ dp->bm_offset = dp->cap_mem_offset;
-+ dp->bm_index = 0;
-+
-+ cyberpro_busmaster_frame(dp, frame);
-+ }
-+}
-+
-+static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned int offset, maxsize;
-+ int i;
-+
-+ init_waitqueue_head(&dp->frame_wait);
-+
-+ maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight;
-+ dp->frame_size = PAGE_ALIGN(maxsize);
-+ dp->frame_idx = 0;
-+
-+ for (i = offset = 0; i < NR_FRAMES; i++) {
-+ dp->frame[i].offset = offset;
-+ dp->frame[i].status = FRAME_FREE;
-+ offset += dp->frame_size;
-+ }
-+}
-+
-+static void cyberpro_frames_free(struct cyberpro_vidinfo *dp)
-+{
-+ int i;
-+
-+ dp->mmaped = 0;
-+
-+ /*
-+ * Free all frame buffers
-+ */
-+ for (i = 0; i < NR_FRAMES; i++)
-+ cyberpro_frames_free_one(dp, dp->frame + i);
-+}
-+
-+#else
-+#define cyberpro_frames_vbl(dp,stat) do { } while (0)
-+#define cyberpro_frames_init(dp) do { } while (0)
-+#define cyberpro_frames_free(dp) do { } while (0)
-+#endif
-+
-+/*
-+ * CyberPro Interrupts
-+ * -------------------
-+ *
-+ * We don't really know how to signal an IRQ clear to the chip. However,
-+ * disabling and re-enabling the capture interrupt enable seems to do what
-+ * we want.
-+ */
-+static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs)
-+{
-+ struct cyberpro_vidinfo *dp = dev_id;
-+ unsigned char old_grphidx;
-+ unsigned int status;
-+
-+ /*
-+ * Save old graphics index register
-+ */
-+ old_grphidx = cyberpro_readb(0x3ce, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ /*
-+ * Was it due to the Capture VSYNC?
-+ */
-+ if (status & EXT_ROM_UCB4GH_INTSTAT) {
-+ /*
-+ * Frob the IRQ enable bit to drop the request.
-+ */
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp);
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+
-+ cyberpro_frames_vbl(dp, status);
-+ wake_up(&dp->vbl_wait);
-+ }
-+
-+ /*
-+ * Restore graphics controller index
-+ */
-+ cyberpro_writeb(old_grphidx, 0x3ce, dp);
-+
-+#ifdef USE_MMAP
-+ /*
-+ * Do Bus-Master IRQ stuff
-+ */
-+ if (cyber2000_inb(BM_CONTROL) & (1 << 7))
-+ cyberpro_busmaster_interrupt(dp);
-+#endif
-+}
-+
-+static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned int status;
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ add_wait_queue(&dp->vbl_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) {
-+ if (on) {
-+ schedule_timeout(40 * HZ / 1000);
-+ dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ } else {
-+ dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ if (!(status & EXT_ROM_UCB4GH_FREEZE))
-+ schedule_timeout(40 * HZ / 1000);
-+ }
-+ }
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&dp->vbl_wait, &wait);
-+}
-+
-+static void cyberpro_capture_one(struct cyberpro_vidinfo *dp)
-+{
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ unsigned int status;
-+ unsigned long policy, rt_priority;
-+
-+ policy = tsk->policy;
-+ rt_priority = tsk->rt_priority;
-+
-+ tsk->policy = SCHED_FIFO;
-+ tsk->rt_priority = 1;
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ add_wait_queue(&dp->vbl_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ schedule_timeout(40 * HZ / 1000);
-+ dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(40 * HZ / 1000);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(40 * HZ / 1000);
-+
-+ dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&dp->vbl_wait, &wait);
-+
-+ tsk->policy = policy;
-+ tsk->rt_priority = rt_priority;
-+}
-+
-+static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned int xstart, xend, ystart, yend;
-+
-+ xstart = 4 + dp->capt.x;
-+ xend = xstart + dp->capt.width;
-+
-+ if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) {
-+ /* 8-bit capture */
-+ xstart *= 2;
-+ xend *= 2;
-+ }
-+
-+ xstart -= 1;
-+ xend -= 1;
-+
-+ ystart = 18 + dp->capt.y;
-+ yend = ystart + dp->capt.height / 2;
-+
-+ cyberpro_grphw16(CAP_X_START, xstart, dp);
-+ cyberpro_grphw16(CAP_X_END, xend + 1, dp);
-+ cyberpro_grphw16(CAP_Y_START, ystart, dp);
-+ cyberpro_grphw16(CAP_Y_END, yend + 2, dp);
-+
-+ /*
-+ * This should take account of capt.decimation
-+ */
-+ cyberpro_grphw16(CAP_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(CAP_DDA_X_INC, 0x1000, dp);
-+ cyberpro_grphw16(CAP_DDA_Y_INIT, 0x0800, dp);
-+ cyberpro_grphw16(CAP_DDA_Y_INC, 0x1000, dp);
-+
-+ cyberpro_grphw8(CAP_PITCH, dp->capt.width >> 2, dp);
-+}
-+
-+static void cyberpro_set_interlace(struct cyberpro_vidinfo *dp)
-+{
-+ /*
-+ * set interlace mode
-+ */
-+ if (dp->interlace) {
-+ dp->vfac3 |= VFAC_CTL3_CAP_INTERLACE;
-+ dp->cap_miscctl &= ~CAP_CTL_MISC_ODDEVEN;
-+ dp->ovl->src.height = dp->capt.height;
-+ } else {
-+ dp->vfac3 &= ~VFAC_CTL3_CAP_INTERLACE;
-+ dp->cap_miscctl |= CAP_CTL_MISC_ODDEVEN;
-+ dp->ovl->src.height = dp->capt.height / 2;
-+ }
-+
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+ cyberpro_grphw8(CAP_CTL_MISC, dp->cap_miscctl, dp);
-+
-+ dp->ovl->set_src(dp, dp->ovl);
-+
-+ if (dp->win_set)
-+ dp->ovl->set_win(dp, dp->ovl);
-+}
-+
-+/*
-+ * Calculate and set the address of the capture buffer. Note we
-+ * also update the extended memory buffer for the overlay window.
-+ *
-+ * base: phys base address of display
-+ * width: pixel width of display
-+ * height: height of display
-+ * depth: depth of display (8/16/24)
-+ * bytesperline: number of bytes on a line
-+ *
-+ * We place the capture buffer 16K after the screen.
-+ */
-+static int
-+cyberpro_set_buffer(struct cyberpro_vidinfo *dp, struct video_buffer *b)
-+{
-+ unsigned long screensize, maxbufsz;
-+
-+ if (b->height <= 0 || b->width <= 0 || b->bytesperline <= 0)
-+ return -EINVAL;
-+
-+ maxbufsz = dp->cap.maxwidth * dp->cap.maxheight * 2;
-+ screensize = b->height * b->bytesperline + 16384;
-+
-+ if ((screensize + maxbufsz) >= dp->info.fb_size)
-+ return -EINVAL;
-+
-+ dp->buf.base = b->base;
-+ dp->buf.width = b->width;
-+ dp->buf.height = b->height;
-+ dp->buf.depth = b->depth;
-+ dp->buf.bytesperline = b->bytesperline;
-+ dp->cap_mem_offset = screensize >> 2;
-+
-+ cyberpro_grphw24(CAP_MEM_START, dp->cap_mem_offset, dp);
-+
-+ /*
-+ * Setup the overlay source information.
-+ */
-+ dp->ovl->src.offset = dp->cap_mem_offset;
-+ dp->ovl->set_src(dp, dp->ovl);
-+
-+ return 0;
-+}
-+
-+static void cyberpro_hw_init(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char old;
-+
-+ /*
-+ * Enable access to bus-master registers
-+ */
-+ dp->info.enable_extregs(dp->info.info);
-+
-+ dp->vfac1 = VFAC_CTL1_PHILIPS |
-+ VFAC_CTL1_FREEZE_CAPTURE |
-+ VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ dp->vfac3 = VFAC_CTL3_CAP_IRQ;
-+
-+ dp->cap_miscctl = CAP_CTL_MISC_DISPUSED |
-+ CAP_CTL_MISC_SYNCTZOR |
-+ CAP_CTL_MISC_SYNCTZHIGH;
-+
-+ /*
-+ * Setup bus-master mode
-+ */
-+ cyberpro_grphw8(BM_CTRL1, 0x88, dp);
-+ cyberpro_grphw8(PCI_BM_CTL, PCI_BM_CTL_ENABLE, dp);
-+ cyberpro_grphw8(BM_CTRL0, 0x44, dp);
-+ cyberpro_grphw8(BM_CTRL1, 0x84, dp);
-+
-+ cyberpro_grphw24(CAP_MEM_START, 0, dp);
-+
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+ cyberpro_grphw8(VFAC_CTL2, 0, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(EXT_TV_CTL, 0x80, dp);
-+
-+ cyberpro_grphw8(EXT_CAP_CTL1, 0x3f, dp); /* disable PIP */
-+ cyberpro_grphw8(EXT_CAP_CTL2, 0xc0 | EXT_CAP_CTL2_ODDFRAMEIRQ, dp);
-+
-+ /*
-+ * Configure capture mode to match the
-+ * external video processor format
-+ */
-+ cyberpro_grphw8(EXT_CAP_MODE1, dp->cap_mode1, dp);
-+ cyberpro_grphw8(EXT_CAP_MODE2, dp->cap_mode2, dp);
-+
-+ /* setup overlay */
-+ cyberpro_grphw16(EXT_FIFO_CTL, 0x1010, dp);
-+// cyberpro_grphw16(EXT_FIFO_CTL, 0x1b0f, dp);
-+
-+ /*
-+ * Always reset the capture parameters on each open.
-+ */
-+ dp->capt.x = 0;
-+ dp->capt.y = 0;
-+ dp->capt.width = dp->cap.maxwidth;
-+ dp->capt.height = dp->cap.maxheight;
-+ dp->capt.decimation = 0;
-+ dp->capt.flags = 0;
-+
-+ cyberpro_capture_set_win(dp);
-+
-+ /*
-+ * Enable VAFC
-+ */
-+ old = cyberpro_grphr8(EXT_LATCH1, dp);
-+ cyberpro_grphw8(EXT_LATCH1, old | EXT_LATCH1_VAFC_EN, dp);
-+
-+ /*
-+ * Enable capture (we hope that VSYNC=1)
-+ */
-+ dp->vfac1 |= VFAC_CTL1_CAPTURE;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ /*
-+ * The overlay source format is always the
-+ * same as the capture stream format.
-+ */
-+ dp->ovl->src.width = dp->capt.width;
-+ dp->ovl->src.height = dp->capt.height;
-+ dp->ovl->src.format = dp->stream_fmt;
-+
-+ /*
-+ * Initialise the overlay windows
-+ */
-+ dp->ext.init(dp, &dp->ext);
-+ dp->v2.init(dp, &dp->v2);
-+ dp->x2.init(dp, &dp->x2);
-+}
-+
-+static void cyberpro_deinit(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char old;
-+
-+ /*
-+ * Stop any bus-master activity
-+ */
-+ cyberpro_writew(0, BM_CONTROL, dp);
-+
-+ /*
-+ * Shut down overlay
-+ */
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+ dp->ovl_active = 0;
-+
-+ /*
-+ * Shut down capture
-+ */
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+ dp->cap_active = 0;
-+
-+ /*
-+ * Disable all capture
-+ */
-+ cyberpro_grphw8(VFAC_CTL1, 0, dp);
-+
-+ /*
-+ * Disable VAFC
-+ */
-+ old = cyberpro_grphr8(EXT_LATCH1, dp);
-+ cyberpro_grphw8(EXT_LATCH1, old & ~EXT_LATCH1_VAFC_EN, dp);
-+
-+ /*
-+ * Disable interrupt (this allows it to float)
-+ */
-+ dp->vfac3 &= ~VFAC_CTL3_CAP_IRQ;
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+
-+ /*
-+ * Switch off bus-master mode
-+ */
-+ cyberpro_grphw8(PCI_BM_CTL, 0, dp);
-+
-+ /*
-+ * Disable access to bus-master registers
-+ */
-+ dp->info.disable_extregs(dp->info.info);
-+}
-+
-+static int cyberpro_grabber_open(struct video_device *dev, int flags)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ int ret, one = 1;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ ret = -EBUSY;
-+ if (flags || dp->users)
-+ goto out;
-+
-+ dp->users += 1;
-+
-+ if (dp->users == 1) {
-+ ret = request_irq(dp->irq, cyberpro_interrupt, SA_SHIRQ,
-+ dp->info.dev_name, dp);
-+
-+ if (ret) {
-+ dp->users -= 1;
-+ goto out;
-+ }
-+
-+ /*
-+ * Initialise the VGA chip
-+ */
-+ cyberpro_hw_init(dp);
-+
-+ /*
-+ * Enable the IRQ. This allows the IRQ to work as expected
-+ * even if the IRQ line is missing the pull-up resistor.
-+ */
-+ enable_irq(dp->irq);
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_ENABLE_OUTPUT, &one);
-+ }
-+
-+ ret = 0;
-+out:
-+ if (ret)
-+ MOD_DEC_USE_COUNT;
-+ return ret;
-+}
-+
-+static void cyberpro_grabber_close(struct video_device *dev)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+
-+ if (dp->users == 1) {
-+ int zero = 0;
-+
-+ /*
-+ * Disable the IRQ. This prevents problems with missing
-+ * pull-up resistors on the PCI interrupt line.
-+ */
-+ disable_irq(dp->irq);
-+
-+ cyberpro_frames_free(dp);
-+
-+ /*
-+ * Turn off the SAA7111 decoder
-+ */
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_ENABLE_OUTPUT, &zero);
-+
-+ /*
-+ * Disable grabber
-+ */
-+ cyberpro_deinit(dp);
-+
-+ free_irq(dp->irq, dp);
-+ }
-+
-+ dp->users -= 1;
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+/*
-+ * Our general plan here is:
-+ * 1. Set the CyberPro to perform a BM-DMA of one frame to this memory
-+ * 2. Copy the frame to the userspace
-+ *
-+ * However, BM-DMA seems to be unreliable at the moment, especially on
-+ * rev. 4 NetWinders.
-+ */
-+static long
-+cyberpro_grabber_read(struct video_device *dev, char *buf,
-+ unsigned long count, int noblock)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ int ret = -EINVAL;
-+
-+#ifdef USE_MMIO
-+ unsigned long maxbufsz = dp->capt.width * dp->capt.height * 2;
-+ char *disp = dp->info.fb + (dp->cap_mem_offset << 2);
-+
-+ /*
-+ * If the buffer is mmap()'d, we shouldn't be using read()
-+ */
-+ if (dp->mmaped)
-+ return -EINVAL;
-+
-+ if (count > maxbufsz)
-+ count = maxbufsz;
-+
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+ else
-+ cyberpro_capture_one(dp);
-+
-+ ret = (int)count;
-+ if (copy_to_user(buf, disp, count))
-+ ret = -EFAULT;
-+
-+ /*
-+ * unfreeze capture
-+ */
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 1);
-+#endif
-+
-+ return ret;
-+}
-+
-+/*
-+ * We don't support writing to the grabber
-+ * (In theory, we could allow writing to a separate region of VGA memory,
-+ * and display this using the second overlay window. This would allow us
-+ * to do video conferencing for example).
-+ */
-+static long
-+cyberpro_grabber_write(struct video_device *dev, const char *buf,
-+ unsigned long count, int noblock)
-+{
-+ return -EINVAL;
-+}
-+
-+static int
-+cyberpro_grabber_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+
-+ switch (cmd) {
-+ case VIDIOCGCAP:
-+ return copy_to_user(arg, &dp->cap, sizeof(dp->cap))
-+ ? -EFAULT : 0;
-+
-+ case VIDIOCGCHAN:
-+ {
-+ struct video_channel chan;
-+
-+ chan.channel = 0;
-+ strcpy(chan.name, "Composite");
-+ chan.tuners = 0;
-+ chan.flags = 0;
-+ chan.type = VIDEO_TYPE_CAMERA;
-+ chan.norm = dp->norm;
-+
-+ return copy_to_user(arg, &chan, sizeof(chan)) ? -EFAULT : 0;
-+ }
-+
-+ case VIDIOCGPICT:
-+ return copy_to_user(arg, &dp->pic, sizeof(dp->pic))
-+ ? -EINVAL : 0;
-+
-+ case VIDIOCGWIN:
-+ {
-+ struct video_window win;
-+
-+ win.x = dp->ovl->dst.x;
-+ win.y = dp->ovl->dst.y;
-+ win.width = dp->ovl->dst.width;
-+ win.height = dp->ovl->dst.height;
-+ win.chromakey = dp->ovl->dst.chromakey;
-+ win.flags = VIDEO_WINDOW_CHROMAKEY |
-+ (dp->interlace ? VIDEO_WINDOW_INTERLACE : 0);
-+ win.clips = NULL;
-+ win.clipcount = 0;
-+
-+ return copy_to_user(arg, &win, sizeof(win))
-+ ? -EINVAL : 0;
-+ }
-+
-+ case VIDIOCGFBUF:
-+ return copy_to_user(arg, &dp->buf, sizeof(dp->buf))
-+ ? -EINVAL : 0;
-+
-+ case VIDIOCGUNIT:
-+ {
-+ struct video_unit unit;
-+
-+ unit.video = dev->minor;
-+ unit.vbi = VIDEO_NO_UNIT;
-+ unit.radio = VIDEO_NO_UNIT;
-+ unit.audio = VIDEO_NO_UNIT;
-+ unit.teletext = VIDEO_NO_UNIT;
-+
-+ return copy_to_user(arg, &unit, sizeof(unit))
-+ ? -EINVAL : 0;
-+ }
-+
-+ case VIDIOCGCAPTURE:
-+ return copy_to_user(arg, &dp->capt, sizeof(dp->capt))
-+ ? -EFAULT : 0;
-+
-+ case VIDIOCSCHAN:
-+ {
-+ struct video_decoder_capability vdc;
-+ struct video_channel v;
-+ int ok;
-+
-+ if (copy_from_user(&v, arg, sizeof(v)))
-+ return -EFAULT;
-+
-+ if (v.channel != 0)
-+ return -EINVAL;
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_GET_CAPABILITIES, &vdc);
-+
-+ switch (v.norm) {
-+ case VIDEO_MODE_PAL:
-+ ok = vdc.flags & VIDEO_DECODER_PAL;
-+ break;
-+ case VIDEO_MODE_NTSC:
-+ ok = vdc.flags & VIDEO_DECODER_NTSC;
-+ break;
-+ case VIDEO_MODE_AUTO:
-+ ok = vdc.flags & VIDEO_DECODER_AUTO;
-+ break;
-+ default:
-+ ok = 0;
-+ }
-+ if (!ok)
-+ return -EINVAL;
-+
-+ dp->norm = v.norm;
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_SET_NORM, &v.norm);
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSPICT:
-+ {
-+ struct video_picture p;
-+
-+ if (copy_from_user(&p, arg, sizeof(p)))
-+ return -EFAULT;
-+
-+ if (p.palette != dp->stream_fmt ||
-+ p.depth != 8)
-+ return -EINVAL;
-+
-+ dp->pic = p;
-+
-+ /* p.depth sets the capture depth */
-+ /* p.palette sets the capture palette */
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_SET_PICTURE, &p);
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSWIN: /* set the size & position of the overlay window */
-+ {
-+ struct video_window w;
-+ int diff;
-+
-+ if (!dp->buf_set)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&w, arg, sizeof(w)))
-+ return -EFAULT;
-+
-+ if (w.clipcount)
-+ return -EINVAL;
-+
-+ /*
-+ * Bound the overlay window by the size of the screen
-+ */
-+ if (w.x < 0)
-+ w.x = 0;
-+ if (w.y < 0)
-+ w.y = 0;
-+
-+ if (w.x > dp->buf.width)
-+ w.x = dp->buf.width;
-+ if (w.y > dp->buf.height)
-+ w.y = dp->buf.height;
-+
-+ if (w.width < dp->capt.width)
-+ w.width = dp->capt.width;
-+ if (w.height < dp->capt.height)
-+ w.height = dp->capt.height;
-+
-+ if (w.x + w.width > dp->buf.width)
-+ w.width = dp->buf.width - w.x;
-+ if (w.y + w.height > dp->buf.height)
-+ w.height = dp->buf.height - w.y;
-+
-+ /*
-+ * We've tried to make the values fit, but
-+ * they just won't.
-+ */
-+ if (w.width < dp->capt.width || w.height < dp->capt.height)
-+ return -EINVAL;
-+
-+ diff = dp->ovl->dst.x != w.x ||
-+ dp->ovl->dst.y != w.y ||
-+ dp->ovl->dst.width != w.width ||
-+ dp->ovl->dst.height != w.height ||
-+ dp->ovl->dst.chromakey != w.chromakey ||
-+ dp->ovl->dst.flags != w.flags;
-+
-+ if (!dp->win_set || diff) {
-+ dp->ovl->dst.x = w.x;
-+ dp->ovl->dst.y = w.y;
-+ dp->ovl->dst.width = w.width;
-+ dp->ovl->dst.height = w.height;
-+ dp->ovl->dst.chromakey = w.chromakey;
-+ dp->ovl->dst.flags = w.flags;
-+
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+
-+ dp->ovl->set_win(dp, dp->ovl);
-+
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 1);
-+
-+ diff = w.flags & VIDEO_WINDOW_INTERLACE ? 1 : 0;
-+ if (!dp->win_set || dp->interlace != diff) {
-+ dp->interlace = diff;
-+ cyberpro_set_interlace(dp);
-+ }
-+ }
-+
-+ dp->win_set = 1;
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSFBUF: /* set frame buffer info */
-+ {
-+ struct video_buffer b;
-+ int ret;
-+
-+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-+ return -EPERM;
-+
-+ if (dp->cap_active)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&b, arg, sizeof(b)))
-+ return -EFAULT;
-+
-+ ret = cyberpro_set_buffer(dp, &b);
-+ if (ret == 0) {
-+ dp->buf_set = 1;
-+ dp->win_set = 0;
-+ }
-+
-+ return ret;
-+ }
-+
-+ case VIDIOCCAPTURE:
-+ {
-+ int on;
-+
-+ if (get_user(on, (int *)arg))
-+ return -EFAULT;
-+
-+ if (( on && dp->ovl_active) ||
-+ (!on && !dp->ovl_active))
-+ return 0;
-+
-+ if (on && (!dp->buf_set || !dp->win_set))
-+ return -EINVAL;
-+
-+ cyberpro_capture(dp, on);
-+ dp->cap_active = on;
-+ dp->ovl->ctl(dp, dp->ovl, on);
-+ dp->ovl_active = on;
-+
-+ return 0;
-+ }
-+
-+#ifdef USE_MMAP
-+ case VIDIOCSYNC:
-+ {
-+ DECLARE_WAITQUEUE(wait, current);
-+ int buf;
-+
-+ /*
-+ * The buffer must have been mmaped
-+ * for this call to work.
-+ */
-+ if (!dp->mmaped)
-+ return -EINVAL;
-+
-+ if (get_user(buf, (int *)arg))
-+ return -EFAULT;
-+
-+ if (buf < 0 || buf >= NR_FRAMES)
-+ return -EINVAL;
-+
-+ switch (dp->frame[buf].status) {
-+ case FRAME_FREE:
-+ return -EINVAL;
-+
-+ case FRAME_WAITING:
-+ case FRAME_GRABBING:
-+ add_wait_queue(&dp->frame_wait, &wait);
-+ while (1) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (signal_pending(current))
-+ break;
-+ if (dp->frame[buf].status == FRAME_DONE)
-+ break;
-+ schedule();
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&dp->frame_wait, &wait);
-+ if (signal_pending(current))
-+ return -EINTR;
-+ /*FALLTHROUGH*/
-+ case FRAME_DONE:
-+ dp->frame[buf].status = FRAME_FREE;
-+ break;
-+ }
-+ return 0;
-+ }
-+
-+ case VIDIOCMCAPTURE:
-+ {
-+ struct video_mmap vmap;
-+
-+ /*
-+ * The buffer must have been mmaped
-+ * for this call to work.
-+ */
-+ if (!dp->mmaped)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&vmap, arg, sizeof(vmap)))
-+ return -EFAULT;
-+
-+ /*
-+ * We can only capture in our source format/size.
-+ */
-+ if (vmap.frame >= NR_FRAMES ||
-+ vmap.format != dp->stream_fmt ||
-+ vmap.width != dp->capt.width ||
-+ vmap.height != dp->capt.height)
-+ return -EINVAL;
-+
-+ if (dp->frame[vmap.frame].status == FRAME_WAITING ||
-+ dp->frame[vmap.frame].status == FRAME_GRABBING)
-+ return -EBUSY;
-+
-+ dp->frame[vmap.frame].status = FRAME_WAITING;
-+ return 0;
-+ }
-+
-+ case VIDIOCGMBUF:
-+ {
-+ struct video_mbuf vmb;
-+ unsigned int i;
-+
-+ vmb.frames = NR_FRAMES;
-+ vmb.size = dp->frame_size * NR_FRAMES;
-+
-+ for (i = 0; i < NR_FRAMES; i++)
-+ vmb.offsets[i] = dp->frame[i].offset;
-+
-+ return copy_to_user(arg, &vmb, sizeof(vmb)) ? -EFAULT : 0;
-+ }
-+#endif
-+
-+ case VIDIOCSCAPTURE:
-+ {
-+ struct video_capture capt;
-+
-+#ifndef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->cap_active)
-+ return -EINVAL;
-+#endif
-+
-+ if (copy_from_user(&capt, arg, sizeof(capt)))
-+ return -EFAULT;
-+
-+ if (capt.x < 0 || capt.width < 0 ||
-+ capt.y < 0 || capt.height < 0 ||
-+ capt.x + capt.width > dp->cap.maxwidth ||
-+ capt.y + capt.height > dp->cap.maxheight)
-+ return -EINVAL;
-+
-+ /*
-+ * The capture width must be a multiple of 4
-+ */
-+ if (dp->capt.width & 3)
-+ return -EINVAL;
-+
-+ dp->capt.x = capt.x;
-+ dp->capt.y = capt.y;
-+ dp->capt.width = capt.width;
-+ dp->capt.height = capt.height;
-+#ifdef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+#endif
-+ cyberpro_capture_set_win(dp);
-+
-+ /*
-+ * Update the overlay window information
-+ */
-+ dp->ovl->src.width = capt.width;
-+ dp->ovl->src.height = capt.height;
-+
-+ dp->ovl->set_src(dp, dp->ovl);
-+ if (dp->win_set)
-+ dp->ovl->set_win(dp, dp->ovl);
-+
-+#ifdef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 1);
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 1);
-+#endif
-+ return 0;
-+ }
-+
-+ case VIDIOCGTUNER: /* no tuner */
-+ case VIDIOCSTUNER:
-+ return -EINVAL;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+#ifdef USE_MMAP
-+static int
-+cyberpro_grabber_mmap(struct video_device *dev, const char *addr, unsigned long size)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ unsigned long vaddr = (unsigned long)addr;
-+ pgprot_t prot;
-+ int frame_idx, ret = -EINVAL;
-+
-+#if defined(__arm__)
-+ prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_USER | L_PTE_WRITE | L_PTE_DIRTY);
-+#elif defined(__i386__)
-+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED);
-+ if (boot_cpu_data.x86 > 3)
-+ pgprot_val(prot) |= _PAGE_PCD;
-+#else
-+#error "Unsupported architecture"
-+#endif
-+
-+ /*
-+ * The mmap() request must have the correct size.
-+ */
-+ if (size != NR_FRAMES * dp->frame_size)
-+ goto out;
-+
-+ /*
-+ * If it's already mapped, don't re-do
-+ */
-+ if (dp->mmaped)
-+ goto out;
-+ dp->mmaped = 1;
-+
-+ /*
-+ * Map in each frame
-+ */
-+ for (frame_idx = 0; frame_idx < NR_FRAMES; frame_idx++) {
-+ struct framebuf *frame;
-+ int pgidx;
-+
-+ frame = dp->frame + frame_idx;
-+
-+ ret = cyberpro_alloc_frame_buffer(dp, frame);
-+
-+ /*
-+ * If an error occurs, we can be lazy and leave what we've
-+ * been able to do. Our release function will free any
-+ * allocated buffers, and do_mmap_pgoff() will zap any
-+ * inserted mappings.
-+ */
-+ if (ret)
-+ goto out2;
-+
-+ /*
-+ * Map in each page on a page by page basis. This is just
-+ * a little on the inefficient side, but it's only run once.
-+ */
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
-+ unsigned long virt;
-+
-+ virt = page_address(frame->pages[pgidx]);
-+
-+ ret = remap_page_range(vaddr, virt_to_phys((void *)virt),
-+ PAGE_SIZE, prot);
-+
-+ if (ret)
-+ goto out2;
-+
-+ vaddr += PAGE_SIZE;
-+ }
-+ }
-+
-+ out2:
-+ if (ret)
-+ dp->mmaped = 0;
-+ out:
-+ return ret;
-+}
-+#endif
-+
-+static int __init cyberpro_grabber_init_done(struct video_device *dev)
-+{
-+ struct cyberpro_vidinfo *dp;
-+ struct cyberpro_info *info = dev->priv;
-+ int ret;
-+
-+ dp = kmalloc(sizeof(*dp), GFP_KERNEL);
-+ if (!dp)
-+ return -ENOMEM;
-+
-+ memset(dp, 0, sizeof(*dp));
-+
-+ dev->priv = dp;
-+ dp->info = *info;
-+ dp->dev = dev;
-+ dp->bus = &cyberpro_i2c_bus;
-+ dp->regs = info->regs;
-+ dp->irq = info->dev->irq;
-+
-+ strcpy(dp->cap.name, dev->name);
-+ dp->cap.type = dev->type;
-+ dp->cap.channels = 1;
-+ dp->cap.audios = 0;
-+ dp->cap.minwidth = 32;
-+ dp->cap.maxwidth = 716;
-+ dp->cap.minheight = 32;
-+ dp->cap.maxheight = 576;
-+
-+ dp->pic.brightness = 32768;
-+ dp->pic.hue = 32768;
-+ dp->pic.colour = 32768;
-+ dp->pic.contrast = 32768;
-+ dp->pic.whiteness = 0;
-+ dp->pic.depth = 8;
-+ dp->pic.palette = VIDEO_PALETTE_YUV422;
-+
-+ /* dp->buf is setup by the user */
-+ /* dp->cap_mem_offset setup by dp->buf */
-+
-+ dp->norm = VIDEO_MODE_AUTO;
-+
-+ /*
-+ * The extended overlay window
-+ */
-+ dp->ext.init = cyberpro_ext_init;
-+ dp->ext.set_src = cyberpro_ext_set_src;
-+ dp->ext.set_win = cyberpro_ext_set_win;
-+ dp->ext.ctl = cyberpro_ext_ctl;
-+
-+ /*
-+ * The V2 overlay window
-+ */
-+ dp->v2.init = cyberpro_v2_init;
-+ dp->v2.set_src = cyberpro_v2_set_src;
-+ dp->v2.set_win = cyberpro_v2_set_win;
-+ dp->v2.ctl = cyberpro_v2_ctl;
-+
-+ /*
-+ * The X2 overlay window
-+ */
-+ dp->x2.init = cyberpro_x2_init;
-+ dp->x2.set_src = cyberpro_x2_set_src;
-+ dp->x2.set_win = cyberpro_x2_set_win;
-+ dp->x2.ctl = cyberpro_x2_ctl;
-+
-+ /*
-+ * Set the overlay window which we shall be using
-+ */
-+ dp->ovl = &dp->ext;
-+
-+ dp->cap_mode1 = EXT_CAP_MODE1_ALTFIFO;
-+
-+ /*
-+ * Initialise hardware specific values.
-+ * - CCIR656 8bit mode (YUV422 data)
-+ * - Ignore Hgood signal
-+ * - Invert Odd/Even field signal
-+ */
-+ dp->cap_mode1 |= EXT_CAP_MODE1_CCIR656 | EXT_CAP_MODE1_8BIT;
-+ dp->cap_mode2 = EXT_CAP_MODE2_FIXSONY | EXT_CAP_MODE2_DATEND |
-+ EXT_CAP_MODE2_CCIRINVOE;
-+ dp->stream_fmt = VIDEO_PALETTE_YUV422;
-+
-+
-+ init_waitqueue_head(&dp->vbl_wait);
-+ cyberpro_frames_init(dp);
-+
-+ /*
-+ * wake up the decoder
-+ */
-+ decoder_sleep(0);
-+
-+ dp->bus->data = dp;
-+ strncpy(dp->bus->name, dev->name, sizeof(dp->bus->name));
-+
-+ pci_set_master(dp->info.dev);
-+
-+ ret = i2c_register_bus(dp->bus);
-+
-+ /*
-+ * If we successfully registered the bus, but didn't initialise
-+ * the decoder (because its driver is not present), request
-+ * that it is loaded.
-+ */
-+ if (ret == 0 && !dp->decoder)
-+ request_module("saa7111");
-+
-+ /*
-+ * If that didn't work, then we're out of luck.
-+ */
-+ if (ret == 0 && !dp->decoder) {
-+ i2c_unregister_bus(dp->bus);
-+ ret = -ENXIO;
-+ }
-+
-+ if (ret) {
-+ kfree(dp);
-+
-+ /*
-+ * put the decoder back to sleep
-+ */
-+ decoder_sleep(1);
-+ }
-+
-+ return ret;
-+}
-+
-+static struct video_device cyberpro_grabber = {
-+ name: "",
-+ type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
-+ VID_TYPE_CHROMAKEY | VID_TYPE_SCALES |
-+ VID_TYPE_SUBCAPTURE,
-+ hardware: 0,
-+ open: cyberpro_grabber_open,
-+ close: cyberpro_grabber_close,
-+ read: cyberpro_grabber_read,
-+ write: cyberpro_grabber_write,
-+ ioctl: cyberpro_grabber_ioctl,
-+#ifdef USE_MMAP
-+ mmap: cyberpro_grabber_mmap,
-+#endif
-+ initialize: cyberpro_grabber_init_done,
-+};
-+
-+int init_cyber2000fb_viddev(void)
-+{
-+ struct cyberpro_info info;
-+
-+ if (!cyber2000fb_attach(&info, 0))
-+ return -ENXIO;
-+
-+ strncpy(cyberpro_grabber.name, info.dev_name, sizeof(cyberpro_grabber.name));
-+
-+ cyberpro_grabber.priv = &info;
-+
-+ return video_register_device(&cyberpro_grabber, VFL_TYPE_GRABBER, -1);
-+}
-+
-+/*
-+ * This can be cleaned up when the SAA7111 code is fixed.
-+ */
-+#ifdef MODULE
-+static int __init cyberpro_init(void)
-+{
-+ disable_irq(35);
-+ return init_cyber2000fb_viddev();
-+}
-+
-+static void __exit cyberpro_exit(void)
-+{
-+ video_unregister_device(&cyberpro_grabber);
-+ kfree(cyberpro_grabber.priv);
-+ i2c_unregister_bus(&cyberpro_i2c_bus);
-+
-+ /*
-+ * put the decoder back to sleep
-+ */
-+ decoder_sleep(1);
-+
-+ cyber2000fb_detach(0);
-+}
-+
-+module_init(cyberpro_init);
-+module_exit(cyberpro_exit);
-+#endif
---- linux-2.4.25/drivers/media/video/i2c-old.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/media/video/i2c-old.c 2004-03-31 17:15:09.000000000 +0200
-@@ -36,11 +36,20 @@
- static struct i2c_driver *drivers[I2C_DRIVER_MAX];
- static int bus_count = 0, driver_count = 0;
-
-+extern int saa7111_init(void);
-+extern int saa7185_init(void);
-+extern int bt819_init(void);
-+extern int bt856_init(void);
-+
- int i2c_init(void)
- {
- printk(KERN_INFO "i2c: initialized%s\n",
- scan ? " (i2c bus scan enabled)" : "");
-
-+#if defined(CONFIG_VIDEO_CYBERPRO)
-+ saa7111_init();
-+#endif
-+
- return 0;
- }
-
-@@ -52,10 +61,10 @@
- int i,j,ack=1;
- unsigned char addr;
- LOCK_FLAGS;
--
-+
- /* probe for device */
- LOCK_I2C_BUS(bus);
-- for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
-+ for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
- {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,addr,0);
-@@ -87,8 +96,8 @@
- device->addr = addr;
-
- /* Attach */
--
-- if (driver->attach(device)!=0)
-+
-+ if (driver->attach(device)!=0)
- {
- kfree(device);
- return;
-@@ -114,7 +123,7 @@
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->driver->devices[i])
- break;
-- if (I2C_DEVICE_MAX == i)
-+ if (I2C_DEVICE_MAX == i)
- {
- printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
- device->name);
-@@ -126,7 +135,7 @@
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->bus->devices[i])
- break;
-- if (I2C_DEVICE_MAX == i)
-+ if (I2C_DEVICE_MAX == i)
- {
- printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
- device->name);
-@@ -158,19 +167,19 @@
- busses[i] = bus;
- bus_count++;
- REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
--
-+
- MOD_INC_USE_COUNT;
-
-- if (scan)
-+ if (scan)
- {
- /* scan whole i2c bus */
- LOCK_I2C_BUS(bus);
-- for (i = 0; i < 256; i+=2)
-+ for (i = 0; i < 256; i+=2)
- {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,i,0);
- i2c_stop(bus);
-- if (!ack)
-+ if (!ack)
- {
- printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
- bus->name,i);
-@@ -198,20 +207,20 @@
- for (i = 0; i < I2C_BUS_MAX; i++)
- if (bus == busses[i])
- break;
-- if (I2C_BUS_MAX == i)
-+ if (I2C_BUS_MAX == i)
- {
- printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
- bus->name);
- return -ENODEV;
- }
--
-+
- MOD_DEC_USE_COUNT;
--
-+
- busses[i] = NULL;
- bus_count--;
- REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
-
-- return 0;
-+ return 0;
- }
-
- /* ----------------------------------------------------------------------- */
-@@ -231,9 +240,9 @@
-
- drivers[i] = driver;
- driver_count++;
--
-+
- MOD_INC_USE_COUNT;
--
-+
- REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
-
- /* Probe available busses */
-@@ -256,7 +265,7 @@
- for (i = 0; i < I2C_DRIVER_MAX; i++)
- if (driver == drivers[i])
- break;
-- if (I2C_DRIVER_MAX == i)
-+ if (I2C_DRIVER_MAX == i)
- {
- printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
- driver->name);
-@@ -264,7 +273,7 @@
- }
-
- MOD_DEC_USE_COUNT;
--
-+
- drivers[i] = NULL;
- driver_count--;
- REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
-@@ -328,7 +337,7 @@
- int i2c_ack(struct i2c_bus *bus)
- {
- int ack;
--
-+
- I2C_SET(bus,0,1);
- I2C_SET(bus,1,1);
- ack = I2C_GET(bus);
-@@ -339,7 +348,7 @@
- int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
- {
- int i, ack;
--
-+
- I2C_SET(bus,0,0);
- for (i=7; i>=0; i--)
- (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
-@@ -354,9 +363,9 @@
- {
- int i;
- unsigned char data=0;
--
-+
- I2C_SET(bus,0,1);
-- for (i=7; i>=0; i--)
-+ for (i=7; i>=0; i--)
- {
- I2C_SET(bus,1,1);
- if (I2C_GET(bus))
-@@ -373,7 +382,7 @@
- int i2c_read(struct i2c_bus *bus, unsigned char addr)
- {
- int ret;
--
-+
- if (bus->i2c_read)
- return bus->i2c_read(bus, addr);
-
---- linux-2.4.25/drivers/media/video/saa7111.c~2.4.25-vrs2.patch 2001-09-30 21:26:06.000000000 +0200
-+++ linux-2.4.25/drivers/media/video/saa7111.c 2004-03-31 17:15:09.000000000 +0200
-@@ -20,9 +20,9 @@
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
--
--#include <linux/module.h>
-+#include <linux/config.h>
- #include <linux/init.h>
-+#include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
-@@ -149,7 +149,11 @@
- 0x0d, 0x00, /* 0d - HUE=0 */
- 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
- 0x0f, 0x00, /* 0f - reserved */
-+#ifndef CONFIG_ARCH_NETWINDER
- 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
-+#else
-+ 0x10, 0xc8, /* 10 - OFTS=YUV-CCIR656, HDEL=0, VLRN=1, YDEL=0 */
-+#endif
- 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
- 0x12, 0x00, /* 12 - output control 2 */
- 0x13, 0x00, /* 13 - output control 3 */
---- linux-2.4.25/drivers/message/i2o/i2o_core.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/message/i2o/i2o_core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1665,14 +1665,14 @@
- }
- memset(status, 0, 4);
-
-- msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
-- msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
-- msg[2]=core_context;
-- msg[3]=0;
-- msg[4]=0;
-- msg[5]=0;
-- msg[6]=virt_to_bus(status);
-- msg[7]=0; /* 64bit host FIXME */
-+ writel(EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
-+ writel(I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0, msg + 3);
-+ writel(0, msg + 4);
-+ writel(0, msg + 5);
-+ writel(virt_to_bus(status), msg + 6);
-+ writel(0, msg + 7); /* 64bit host FIXME */
-
- i2o_post_message(c,m);
-
-@@ -1781,15 +1781,15 @@
- return -ETIMEDOUT;
- msg=(u32 *)(c->mem_offset+m);
-
-- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-- msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-- msg[2]=core_context;
-- msg[3]=0;
-- msg[4]=0;
-- msg[5]=0;
-- msg[6]=virt_to_bus(c->status_block);
-- msg[7]=0; /* 64bit host FIXME */
-- msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
-+ writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
-+ writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0, msg + 3);
-+ writel(0, msg + 4);
-+ writel(0, msg + 5);
-+ writel(virt_to_bus(c->status_block), msg + 6);
-+ writel(0, msg + 7); /* 64bit host FIXME */
-+ writel(sizeof(i2o_status_block), msg + 8); /* always 88 bytes */
-
- i2o_post_message(c,m);
-
-@@ -2193,15 +2193,15 @@
- }
- memset(status, 0, 4);
-
-- msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
-- msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
-- msg[2]= core_context;
-- msg[3]= 0x0106; /* Transaction context */
-- msg[4]= 4096; /* Host page frame size */
-+ writel(EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6, msg + 0);
-+ writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0x0106, msg + 3); /* Transaction context */
-+ writel(PAGE_SIZE, msg + 4); /* Host page frame size */
- /* Frame size is in words. 256 bytes a frame for now */
-- msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size in words and Initcode */
-- msg[6]= 0xD0000004; /* Simple SG LE, EOB */
-- msg[7]= virt_to_bus(status);
-+ writel(MSG_FRAME_SIZE<<16|0x80, msg + 5);/* Outbound msg frame size in words and Initcode */
-+ writel(0xD0000004, msg + 6); /* Simple SG LE, EOB */
-+ writel(virt_to_bus(status), msg + 7);
-
- i2o_post_message(c,m);
-
---- linux-2.4.25/drivers/message/i2o/i2o_pci.c~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
-+++ linux-2.4.25/drivers/message/i2o/i2o_pci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -390,4 +390,4 @@
- MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
- module_init(i2o_pci_core_attach);
- module_exit(i2o_pci_core_detach);
--
-\ No newline at end of file
-+
---- linux-2.4.25/drivers/misc/Config.in~2.4.25-vrs2.patch 1999-12-26 00:04:56.000000000 +0100
-+++ linux-2.4.25/drivers/misc/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -1,7 +1,17 @@
- #
--# Misc strange devices
-+# MCP drivers
- #
- mainmenu_option next_comment
--comment 'Misc devices'
-+comment 'Multimedia Capabilities Port drivers'
-+
-+bool 'Multimedia drivers' CONFIG_MCP
-+
-+# Interface drivers
-+dep_bool 'Support SA1100 MCP interface' CONFIG_MCP_SA1100 $CONFIG_MCP $CONFIG_ARCH_SA1100
-+
-+# Chip drivers
-+dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
-+dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
-+dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
-
- endmenu
---- linux-2.4.25/drivers/misc/Makefile~2.4.25-vrs2.patch 2000-12-29 23:07:22.000000000 +0100
-+++ linux-2.4.25/drivers/misc/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -11,6 +11,14 @@
-
- O_TARGET := misc.o
-
-+export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
-+
-+obj-$(CONFIG_MCP) += mcp-core.o
-+obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
-+obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
-+obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-+
- include $(TOPDIR)/Rules.make
-
- fastdep:
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/mcp-core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,155 @@
-+/*
-+ * linux/drivers/misc/mcp-core.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * Generic MCP (Multimedia Communications Port) layer. All MCP locking
-+ * is solely held within this file.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/smp.h>
-+
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "mcp.h"
-+
-+/**
-+ * mcp_set_telecom_divisor - set the telecom divisor
-+ * @mcp: MCP interface structure
-+ * @div: SIB clock divisor
-+ *
-+ * Set the telecom divisor on the MCP interface. The resulting
-+ * sample rate is SIBCLOCK/div.
-+ */
-+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ mcp->set_telecom_divisor(mcp, div);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_set_audio_divisor - set the audio divisor
-+ * @mcp: MCP interface structure
-+ * @div: SIB clock divisor
-+ *
-+ * Set the audio divisor on the MCP interface.
-+ */
-+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ mcp->set_audio_divisor(mcp, div);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_reg_write - write a device register
-+ * @mcp: MCP interface structure
-+ * @reg: 4-bit register index
-+ * @val: 16-bit data value
-+ *
-+ * Write a device register. The MCP interface must be enabled
-+ * to prevent this function hanging.
-+ */
-+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ mcp->reg_write(mcp, reg, val);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+}
-+
-+/**
-+ * mcp_reg_read - read a device register
-+ * @mcp: MCP interface structure
-+ * @reg: 4-bit register index
-+ *
-+ * Read a device register and return its value. The MCP interface
-+ * must be enabled to prevent this function hanging.
-+ */
-+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
-+{
-+ unsigned long flags;
-+ unsigned int val;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ val = mcp->reg_read(mcp, reg);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+
-+ return val;
-+}
-+
-+/**
-+ * mcp_enable - enable the MCP interface
-+ * @mcp: MCP interface to enable
-+ *
-+ * Enable the MCP interface. Each call to mcp_enable will need
-+ * a corresponding call to mcp_disable to disable the interface.
-+ */
-+void mcp_enable(struct mcp *mcp)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ if (mcp->use_count++ == 0)
-+ mcp->enable(mcp);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_disable - disable the MCP interface
-+ * @mcp: MCP interface to disable
-+ *
-+ * Disable the MCP interface. The MCP interface will only be
-+ * disabled once the number of calls to mcp_enable matches the
-+ * number of calls to mcp_disable.
-+ */
-+void mcp_disable(struct mcp *mcp)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ if (--mcp->use_count == 0)
-+ mcp->disable(mcp);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+}
-+
-+
-+/*
-+ * This needs re-working
-+ */
-+static struct mcp *mcp_if;
-+
-+struct mcp *mcp_get(void)
-+{
-+ return mcp_if;
-+}
-+
-+int mcp_register(struct mcp *mcp)
-+{
-+ if (mcp_if)
-+ return -EBUSY;
-+ if (mcp->owner)
-+ __MOD_INC_USE_COUNT(mcp->owner);
-+ mcp_if = mcp;
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(mcp_set_telecom_divisor);
-+EXPORT_SYMBOL(mcp_set_audio_divisor);
-+EXPORT_SYMBOL(mcp_reg_write);
-+EXPORT_SYMBOL(mcp_reg_read);
-+EXPORT_SYMBOL(mcp_enable);
-+EXPORT_SYMBOL(mcp_disable);
-+EXPORT_SYMBOL(mcp_get);
-+EXPORT_SYMBOL(mcp_register);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Core multimedia communications port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/mcp-sa1100.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,180 @@
-+/*
-+ * linux/drivers/misc/mcp-sa1100.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * SA1100 MCP (Multimedia Communications Port) driver.
-+ *
-+ * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/spinlock.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+
-+#include "mcp.h"
-+
-+static void
-+mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
-+{
-+ unsigned int mccr0;
-+
-+ divisor /= 32;
-+
-+ mccr0 = Ser4MCCR0 & ~0x00007f00;
-+ mccr0 |= divisor << 8;
-+ Ser4MCCR0 = mccr0;
-+}
-+
-+static void
-+mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
-+{
-+ unsigned int mccr0;
-+
-+ divisor /= 32;
-+
-+ mccr0 = Ser4MCCR0 & ~0x0000007f;
-+ mccr0 |= divisor;
-+ Ser4MCCR0 = mccr0;
-+}
-+
-+/*
-+ * Write data to the device. The bit should be set after 3 subframe
-+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
-+ * We really should try doing something more productive while we
-+ * wait.
-+ */
-+static void
-+mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ int ret = -ETIME;
-+ int i;
-+
-+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
-+
-+ for (i = 0; i < 2; i++) {
-+ udelay(mcp->rw_timeout);
-+ if (Ser4MCSR & MCSR_CWC) {
-+ ret = 0;
-+ break;
-+ }
-+ }
-+
-+ if (ret < 0)
-+ printk(KERN_WARNING "mcp: write timed out\n");
-+}
-+
-+/*
-+ * Read data from the device. The bit should be set after 3 subframe
-+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
-+ * We really should try doing something more productive while we
-+ * wait.
-+ */
-+static unsigned int
-+mcp_sa1100_read(struct mcp *mcp, unsigned int reg)
-+{
-+ int ret = -ETIME;
-+ int i;
-+
-+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
-+
-+ for (i = 0; i < 2; i++) {
-+ udelay(mcp->rw_timeout);
-+ if (Ser4MCSR & MCSR_CRC) {
-+ ret = Ser4MCDR2 & 0xffff;
-+ break;
-+ }
-+ }
-+
-+ if (ret < 0)
-+ printk(KERN_WARNING "mcp: read timed out\n");
-+
-+ return ret;
-+}
-+
-+static void mcp_sa1100_enable(struct mcp *mcp)
-+{
-+ Ser4MCSR = -1;
-+ Ser4MCCR0 |= MCCR0_MCE;
-+}
-+
-+static void mcp_sa1100_disable(struct mcp *mcp)
-+{
-+ Ser4MCCR0 &= ~MCCR0_MCE;
-+}
-+
-+struct mcp mcp_sa1100 = {
-+ owner: THIS_MODULE,
-+ lock: SPIN_LOCK_UNLOCKED,
-+ sclk_rate: 11981000,
-+ dma_audio_rd: DMA_Ser4MCP0Rd,
-+ dma_audio_wr: DMA_Ser4MCP0Wr,
-+ dma_telco_rd: DMA_Ser4MCP1Rd,
-+ dma_telco_wr: DMA_Ser4MCP1Wr,
-+ set_telecom_divisor: mcp_sa1100_set_telecom_divisor,
-+ set_audio_divisor: mcp_sa1100_set_audio_divisor,
-+ reg_write: mcp_sa1100_write,
-+ reg_read: mcp_sa1100_read,
-+ enable: mcp_sa1100_enable,
-+ disable: mcp_sa1100_disable,
-+};
-+
-+/*
-+ * This needs re-working
-+ */
-+static int mcp_sa1100_init(void)
-+{
-+ struct mcp *mcp = &mcp_sa1100;
-+ int ret = -ENODEV;
-+
-+ if (machine_is_accelent_sa() ||
-+ machine_is_adsbitsy() || machine_is_assabet() ||
-+ machine_is_cerf() || machine_is_flexanet() ||
-+ machine_is_freebird() || machine_is_graphicsclient() ||
-+ machine_is_graphicsmaster() || machine_is_lart() ||
-+ machine_is_omnimeter() || machine_is_pfs168() ||
-+ machine_is_shannon() || machine_is_simpad() ||
-+ machine_is_simputer() || machine_is_yopy()) {
-+ /*
-+ * Setup the PPC unit correctly.
-+ */
-+ PPDR &= ~PPC_RXD4;
-+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-+ PSDR |= PPC_RXD4;
-+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-+
-+ Ser4MCSR = -1;
-+ Ser4MCCR1 = 0;
-+ Ser4MCCR0 = 0x00007f7f | MCCR0_ADM;
-+
-+ /*
-+ * Calculate the read/write timeout (us) from the bit clock
-+ * rate. This is the period for 3 64-bit frames. Always
-+ * round this time up.
-+ */
-+ mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
-+ mcp->sclk_rate;
-+
-+ ret = mcp_register(mcp);
-+ }
-+
-+ return ret;
-+}
-+
-+module_init(mcp_sa1100_init);
-+EXPORT_SYMBOL(mcp_sa1100_init);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/mcp.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,44 @@
-+/*
-+ * linux/drivers/misc/mcp.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef MCP_H
-+#define MCP_H
-+
-+struct mcp {
-+ struct module *owner;
-+ spinlock_t lock;
-+ int use_count;
-+ unsigned int sclk_rate;
-+ unsigned int rw_timeout;
-+ dma_device_t dma_audio_rd;
-+ dma_device_t dma_audio_wr;
-+ dma_device_t dma_telco_rd;
-+ dma_device_t dma_telco_wr;
-+ void (*set_telecom_divisor)(struct mcp *, unsigned int);
-+ void (*set_audio_divisor)(struct mcp *, unsigned int);
-+ void (*reg_write)(struct mcp *, unsigned int, unsigned int);
-+ unsigned int (*reg_read)(struct mcp *, unsigned int);
-+ void (*enable)(struct mcp *);
-+ void (*disable)(struct mcp *);
-+};
-+
-+void mcp_set_telecom_divisor(struct mcp *, unsigned int);
-+void mcp_set_audio_divisor(struct mcp *, unsigned int);
-+void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
-+unsigned int mcp_reg_read(struct mcp *, unsigned int);
-+void mcp_enable(struct mcp *);
-+void mcp_disable(struct mcp *);
-+
-+/* noddy implementation alert! */
-+struct mcp *mcp_get(void);
-+int mcp_register(struct mcp *);
-+
-+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-audio.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,378 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-audio.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/list.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+
-+#include "ucb1x00.h"
-+
-+#include "../drivers/sound/sa1100-audio.h"
-+
-+#define MAGIC 0x41544154
-+
-+struct ucb1x00_audio {
-+ struct file_operations fops;
-+ struct file_operations mops;
-+ struct ucb1x00 *ucb;
-+ audio_stream_t output_stream;
-+ audio_stream_t input_stream;
-+ audio_state_t state;
-+ unsigned int rate;
-+ int dev_id;
-+ int mix_id;
-+ unsigned int daa_oh_bit;
-+ unsigned int telecom;
-+ unsigned int magic;
-+ unsigned int ctrl_a;
-+ unsigned int ctrl_b;
-+
-+ /* mixer info */
-+ unsigned int mod_cnt;
-+ unsigned short output_level;
-+ unsigned short input_level;
-+};
-+
-+#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC)
-+#define DEV_MASK REC_MASK
-+
-+static int
-+ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg)
-+{
-+ struct ucb1x00_audio *ucba;
-+ unsigned int val, gain;
-+ int ret = 0;
-+
-+ ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops);
-+
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ if (cmd == SOUND_MIXER_INFO) {
-+ struct mixer_info mi;
-+
-+ strncpy(mi.id, "UCB1x00", sizeof(mi.id));
-+ strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name));
-+ mi.modify_counter = ucba->mod_cnt;
-+ return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0;
-+ }
-+
-+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
-+ unsigned int left, right;
-+
-+ ret = get_user(val, (unsigned int *)arg);
-+ if (ret)
-+ goto out;
-+
-+ left = val & 255;
-+ right = val >> 8;
-+
-+ if (left > 100)
-+ left = 100;
-+ if (right > 100)
-+ right = 100;
-+
-+ gain = (left + right) / 2;
-+
-+ ret = -EINVAL;
-+ if (!ucba->telecom) {
-+ switch(_IOC_NR(cmd)) {
-+ case SOUND_MIXER_VOLUME:
-+ ucba->output_level = gain | gain << 8;
-+ ucba->mod_cnt++;
-+ ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
-+ ((gain * 31) / 100);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
-+ ucba->ctrl_b);
-+ ret = 0;
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ ucba->input_level = gain | gain << 8;
-+ ucba->mod_cnt++;
-+ ucba->ctrl_a = (ucba->ctrl_a & 0x7f) |
-+ (((gain * 31) / 100) << 7);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A,
-+ ucba->ctrl_a);
-+ ret = 0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
-+ switch (_IOC_NR(cmd)) {
-+ case SOUND_MIXER_VOLUME:
-+ val = ucba->output_level;
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ val = ucba->input_level;
-+ break;
-+
-+ case SOUND_MIXER_RECSRC:
-+ case SOUND_MIXER_RECMASK:
-+ val = ucba->telecom ? 0 : REC_MASK;
-+ break;
-+
-+ case SOUND_MIXER_DEVMASK:
-+ val = ucba->telecom ? 0 : DEV_MASK;
-+ break;
-+
-+ case SOUND_MIXER_CAPS:
-+ case SOUND_MIXER_STEREODEVS:
-+ val = 0;
-+ break;
-+
-+ default:
-+ val = 0;
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ if (ret == 0)
-+ ret = put_user(val, (int *)arg);
-+ }
-+ out:
-+ return ret;
-+}
-+
-+static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate)
-+{
-+ unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32;
-+ unsigned int div;
-+
-+ div = (div_rate + (rate / 2)) / rate;
-+ if (div < 6)
-+ div = 6;
-+ if (div > 127)
-+ div = 127;
-+
-+ ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div;
-+
-+ if (ucba->telecom) {
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0);
-+ ucb1x00_set_telecom_divisor(ucba->ucb, div * 32);
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a);
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b);
-+ } else {
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0);
-+ ucb1x00_set_audio_divisor(ucba->ucb, div * 32);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b);
-+ }
-+
-+ ucba->rate = div_rate / div;
-+
-+ return ucba->rate;
-+}
-+
-+static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba)
-+{
-+ return ucba->rate;
-+}
-+
-+static void ucb1x00_audio_startup(void *data)
-+{
-+ struct ucb1x00_audio *ucba = data;
-+
-+ ucb1x00_enable(ucba->ucb);
-+ ucb1x00_audio_setrate(ucba, ucba->rate);
-+
-+ ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA);
-+
-+ /*
-+ * Take off-hook
-+ */
-+ if (ucba->daa_oh_bit)
-+ ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit);
-+}
-+
-+static void ucb1x00_audio_shutdown(void *data)
-+{
-+ struct ucb1x00_audio *ucba = data;
-+
-+ /*
-+ * Place on-hook
-+ */
-+ if (ucba->daa_oh_bit)
-+ ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0);
-+
-+ ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0);
-+ ucb1x00_disable(ucba->ucb);
-+}
-+
-+static int
-+ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ struct ucb1x00_audio *ucba;
-+ int val, ret = 0;
-+
-+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
-+
-+ /*
-+ * Make sure we have our magic number
-+ */
-+ if (ucba->magic != MAGIC)
-+ return -ENODEV;
-+
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ if (val != 0)
-+ return -EINVAL;
-+ val = 0;
-+ break;
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ val = 1;
-+ break;
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ val = ucb1x00_audio_setrate(ucba, val);
-+ break;
-+
-+ case SOUND_PCM_READ_RATE:
-+ val = ucb1x00_audio_getrate(ucba);
-+ break;
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ val = AFMT_S16_LE;
-+ break;
-+
-+ default:
-+ return ucb1x00_mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return put_user(val, (int *)arg);
-+}
-+
-+static int ucb1x00_audio_open(struct inode *inode, struct file *file)
-+{
-+ struct ucb1x00_audio *ucba;
-+
-+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
-+
-+ return sa1100_audio_attach(inode, file, &ucba->state);
-+}
-+
-+static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb)
-+{
-+ struct ucb1x00_audio *ucba;
-+
-+ ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
-+ if (ucba) {
-+ memset(ucba, 0, sizeof(*ucba));
-+
-+ ucba->magic = MAGIC;
-+ ucba->ucb = ucb;
-+ ucba->fops.owner = THIS_MODULE;
-+ ucba->fops.open = ucb1x00_audio_open;
-+ ucba->mops.owner = THIS_MODULE;
-+ ucba->mops.ioctl = ucb1x00_mixer_ioctl;
-+ ucba->state.output_stream = &ucba->output_stream;
-+ ucba->state.input_stream = &ucba->input_stream;
-+ ucba->state.data = ucba;
-+ ucba->state.hw_init = ucb1x00_audio_startup;
-+ ucba->state.hw_shutdown = ucb1x00_audio_shutdown;
-+ ucba->state.client_ioctl = ucb1x00_audio_ioctl;
-+
-+ /* There is a bug in the StrongARM causes corrupt MCP data to be sent to
-+ * the codec when the FIFOs are empty and writes are made to the OS timer
-+ * match register 0. To avoid this we must make sure that data is always
-+ * sent to the codec.
-+ */
-+ ucba->state.need_tx_for_rx = 1;
-+
-+ init_MUTEX(&ucba->state.sem);
-+ ucba->rate = 8000;
-+ }
-+ return ucba;
-+}
-+
-+static struct ucb1x00_audio *audio, *telecom;
-+
-+static int __init ucb1x00_audio_init(void)
-+{
-+ struct ucb1x00 *ucb = ucb1x00_get();
-+ struct ucb1x00_audio *a;
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ a = ucb1x00_audio_alloc(ucb);
-+ if (a) {
-+ a->state.input_dma = ucb->mcp->dma_audio_rd;
-+ a->state.input_id = "UCB1x00 audio in";
-+ a->state.output_dma = ucb->mcp->dma_audio_wr;
-+ a->state.output_id = "UCB1x00 audio out";
-+ a->dev_id = register_sound_dsp(&a->fops, -1);
-+ a->mix_id = register_sound_mixer(&a->mops, -1);
-+ a->ctrl_a = 0;
-+ a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA;
-+ audio = a;
-+ }
-+
-+ a = ucb1x00_audio_alloc(ucb);
-+ if (a) {
-+#if 0
-+ a->daa_oh_bit = UCB_IO_8;
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_io_write(ucb, a->daa_oh_bit, 0);
-+ ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit);
-+ ucb1x00_disable(ucb);
-+#endif
-+
-+ a->telecom = 1;
-+ a->state.input_dma = ucb->mcp->dma_telco_rd;
-+ a->state.input_id = "UCB1x00 telco in";
-+ a->state.output_dma = ucb->mcp->dma_telco_wr;
-+ a->state.output_id = "UCB1x00 telco out";
-+ a->dev_id = register_sound_dsp(&a->fops, -1);
-+ a->mix_id = register_sound_mixer(&a->mops, -1);
-+ a->ctrl_a = 0;
-+ a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA;
-+ telecom = a;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_audio_exit(void)
-+{
-+ unregister_sound_dsp(telecom->dev_id);
-+ unregister_sound_dsp(audio->dev_id);
-+ unregister_sound_mixer(telecom->mix_id);
-+ unregister_sound_mixer(audio->mix_id);
-+}
-+
-+module_init(ucb1x00_audio_init);
-+module_exit(ucb1x00_audio_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 telecom/audio driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,651 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-core.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * The UCB1x00 core driver provides basic services for handling IO,
-+ * the ADC, interrupts, and accessing registers. It is designed
-+ * such that everything goes through this layer, thereby providing
-+ * a consistent locking methodology, as well as allowing the drivers
-+ * to be used on other non-MCP-enabled hardware platforms.
-+ *
-+ * Note that all locks are private to this file. Nothing else may
-+ * touch them.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/shannon.h>
-+
-+#include "ucb1x00.h"
-+
-+/**
-+ * ucb1x00_io_set_dir - set IO direction
-+ * @ucb: UCB1x00 structure describing chip
-+ * @in: bitfield of IO pins to be set as inputs
-+ * @out: bitfield of IO pins to be set as outputs
-+ *
-+ * Set the IO direction of the ten general purpose IO pins on
-+ * the UCB1x00 chip. The @in bitfield has priority over the
-+ * @out bitfield, in that if you specify a pin as both input
-+ * and output, it will end up as an input.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function takes a spinlock, disabling interrupts.
-+ */
-+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ucb->io_lock, flags);
-+ ucb->io_dir |= out;
-+ ucb->io_dir &= ~in;
-+
-+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
-+ spin_unlock_irqrestore(&ucb->io_lock, flags);
-+}
-+
-+/**
-+ * ucb1x00_io_write - set or clear IO outputs
-+ * @ucb: UCB1x00 structure describing chip
-+ * @set: bitfield of IO pins to set to logic '1'
-+ * @clear: bitfield of IO pins to set to logic '0'
-+ *
-+ * Set the IO output state of the specified IO pins. The value
-+ * is retained if the pins are subsequently configured as inputs.
-+ * The @clear bitfield has priority over the @set bitfield -
-+ * outputs will be cleared.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function takes a spinlock, disabling interrupts.
-+ */
-+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ucb->io_lock, flags);
-+ ucb->io_out |= set;
-+ ucb->io_out &= ~clear;
-+
-+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
-+ spin_unlock_irqrestore(&ucb->io_lock, flags);
-+}
-+
-+/**
-+ * ucb1x00_io_read - read the current state of the IO pins
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return a bitfield describing the logic state of the ten
-+ * general purpose IO pins.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function does not take any semaphores or spinlocks.
-+ */
-+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
-+{
-+ return ucb1x00_reg_read(ucb, UCB_IO_DATA);
-+}
-+
-+/*
-+ * UCB1300 data sheet says we must:
-+ * 1. enable ADC => 5us (including reference startup time)
-+ * 2. select input => 51*tsibclk => 4.3us
-+ * 3. start conversion => 102*tsibclk => 8.5us
-+ * (tsibclk = 1/11981000)
-+ * Period between SIB 128-bit frames = 10.7us
-+ */
-+
-+/**
-+ * ucb1x00_adc_enable - enable the ADC converter
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
-+ * Any code wishing to use the ADC converter must call this
-+ * function prior to using it.
-+ *
-+ * This function takes the ADC semaphore to prevent two or more
-+ * concurrent uses, and therefore may sleep. As a result, it
-+ * can only be called from process context, not interrupt
-+ * context.
-+ *
-+ * You should release the ADC as soon as possible using
-+ * ucb1x00_adc_disable.
-+ */
-+void ucb1x00_adc_enable(struct ucb1x00 *ucb)
-+{
-+ down(&ucb->adc_sem);
-+
-+ ucb->adc_cr |= UCB_ADC_ENA;
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
-+}
-+
-+/**
-+ * ucb1x00_adc_read - read the specified ADC channel
-+ * @ucb: UCB1x00 structure describing chip
-+ * @adc_channel: ADC channel mask
-+ * @sync: wait for syncronisation pulse.
-+ *
-+ * Start an ADC conversion and wait for the result. Note that
-+ * synchronised ADC conversions (via the ADCSYNC pin) must wait
-+ * until the trigger is asserted and the conversion is finished.
-+ *
-+ * This function currently spins waiting for the conversion to
-+ * complete (2 frames max without sync).
-+ *
-+ * If called for a synchronised ADC conversion, it may sleep
-+ * with the ADC semaphore held.
-+ */
-+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
-+{
-+ unsigned int val;
-+
-+ if (sync)
-+ adc_channel |= UCB_ADC_SYNC_ENA;
-+
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
-+
-+ for (;;) {
-+ val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
-+ if (val & UCB_ADC_DAT_VAL)
-+ break;
-+ /* yield to other processes */
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+
-+ return UCB_ADC_DAT(val);
-+}
-+
-+/**
-+ * ucb1x00_adc_disable - disable the ADC converter
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Disable the ADC converter and release the ADC semaphore.
-+ */
-+void ucb1x00_adc_disable(struct ucb1x00 *ucb)
-+{
-+ ucb->adc_cr &= ~UCB_ADC_ENA;
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
-+ ucb1x00_disable(ucb);
-+
-+ up(&ucb->adc_sem);
-+}
-+
-+#ifdef CONFIG_PM
-+static int ucb1x00_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data;
-+ unsigned int isr;
-+
-+ if (rqst == PM_RESUME) {
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+ ucb1x00_disable(ucb);
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * UCB1x00 Interrupt handling.
-+ *
-+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
-+ * Since we need to read an internal register, we must re-enable
-+ * SIBCLK to talk to the chip. We leave the clock running until
-+ * we have finished processing all interrupts from the chip.
-+ */
-+static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ struct ucb1x00 *ucb = devid;
-+ struct ucb1x00_irq *irq;
-+ unsigned int isr, i;
-+
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-+ if (isr & 1 && irq->fn)
-+ irq->fn(i, irq->devid);
-+ ucb1x00_disable(ucb);
-+}
-+
-+/**
-+ * ucb1x00_hook_irq - hook a UCB1x00 interrupt
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @fn: function to call when interrupt is triggered
-+ * @devid: device id to pass to interrupt handler
-+ *
-+ * Hook the specified interrupt. You can only register one handler
-+ * for each interrupt source. The interrupt source is not enabled
-+ * by this function; use ucb1x00_enable_irq instead.
-+ *
-+ * Interrupt handlers will be called with other interrupts enabled.
-+ *
-+ * Returns zero on success, or one of the following errors:
-+ * -EINVAL if the interrupt index is invalid
-+ * -EBUSY if the interrupt has already been hooked
-+ */
-+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
-+{
-+ struct ucb1x00_irq *irq;
-+ int ret = -EINVAL;
-+
-+ if (idx < 16) {
-+ irq = ucb->irq_handler + idx;
-+ ret = -EBUSY;
-+
-+ spin_lock_irq(&ucb->lock);
-+ if (irq->fn == NULL) {
-+ irq->devid = devid;
-+ irq->fn = fn;
-+ ret = 0;
-+ }
-+ spin_unlock_irq(&ucb->lock);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @edges: interrupt edges to enable
-+ *
-+ * Enable the specified interrupt to trigger on %UCB_RISING,
-+ * %UCB_FALLING or both edges. The interrupt should have been
-+ * hooked by ucb1x00_hook_irq.
-+ */
-+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
-+{
-+ unsigned long flags;
-+
-+ if (idx < 16) {
-+ spin_lock_irqsave(&ucb->lock, flags);
-+
-+ ucb1x00_enable(ucb);
-+ if (edges & UCB_RISING) {
-+ ucb->irq_ris_enbl |= 1 << idx;
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ }
-+ if (edges & UCB_FALLING) {
-+ ucb->irq_fal_enbl |= 1 << idx;
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ }
-+ ucb1x00_disable(ucb);
-+ spin_unlock_irqrestore(&ucb->lock, flags);
-+ }
-+}
-+
-+/**
-+ * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
-+ * @ucb: UCB1x00 structure describing chip
-+ * @edges: interrupt edges to disable
-+ *
-+ * Disable the specified interrupt triggering on the specified
-+ * (%UCB_RISING, %UCB_FALLING or both) edges.
-+ */
-+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
-+{
-+ unsigned long flags;
-+
-+ if (idx < 16) {
-+ spin_lock_irqsave(&ucb->lock, flags);
-+
-+ ucb1x00_enable(ucb);
-+ if (edges & UCB_RISING) {
-+ ucb->irq_ris_enbl &= ~(1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ }
-+ if (edges & UCB_FALLING) {
-+ ucb->irq_fal_enbl &= ~(1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ }
-+ ucb1x00_disable(ucb);
-+ spin_unlock_irqrestore(&ucb->lock, flags);
-+ }
-+}
-+
-+/**
-+ * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @devid: device id.
-+ *
-+ * Disable the interrupt source and remove the handler. devid must
-+ * match the devid passed when hooking the interrupt.
-+ *
-+ * Returns zero on success, or one of the following errors:
-+ * -EINVAL if the interrupt index is invalid
-+ * -ENOENT if devid does not match
-+ */
-+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
-+{
-+ struct ucb1x00_irq *irq;
-+ int ret;
-+
-+ if (idx >= 16)
-+ goto bad;
-+
-+ irq = ucb->irq_handler + idx;
-+ ret = -ENOENT;
-+
-+ spin_lock_irq(&ucb->lock);
-+ if (irq->devid == devid) {
-+ ucb->irq_ris_enbl &= ~(1 << idx);
-+ ucb->irq_fal_enbl &= ~(1 << idx);
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ ucb1x00_disable(ucb);
-+
-+ irq->fn = NULL;
-+ irq->devid = NULL;
-+ ret = 0;
-+ }
-+ spin_unlock_irq(&ucb->lock);
-+ return ret;
-+
-+bad:
-+ printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx);
-+ return -EINVAL;
-+}
-+
-+/*
-+ * Try to probe our interrupt, rather than relying on lots of
-+ * hard-coded machine dependencies. For reference, the expected
-+ * IRQ mappings are:
-+ *
-+ * Machine Default IRQ
-+ * adsbitsy IRQ_GPCIN4
-+ * cerf IRQ_GPIO_UCB1200_IRQ
-+ * flexanet IRQ_GPIO_GUI
-+ * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
-+ * graphicsclient IRQ_GRAPHICSCLIENT_UCB1200
-+ * graphicsmaster IRQ_GRAPHICSMASTER_UCB1200
-+ * lart LART_IRQ_UCB1200
-+ * omnimeter IRQ_GPIO23
-+ * pfs168 IRQ_GPIO_UCB1300_IRQ
-+ * simpad IRQ_GPIO_UCB1300_IRQ
-+ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
-+ * yopy IRQ_GPIO_UCB1200_IRQ
-+ */
-+static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb)
-+{
-+ unsigned long mask;
-+
-+ mask = probe_irq_on();
-+ if (!mask)
-+ return NO_IRQ;
-+
-+ /*
-+ * Enable the ADC interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ /*
-+ * Cause an ADC interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
-+
-+ /*
-+ * Wait for the conversion to complete.
-+ */
-+ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
-+
-+ /*
-+ * Disable and clear interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ /*
-+ * Read triggered interrupt.
-+ */
-+ return probe_irq_off(mask);
-+}
-+
-+/*
-+ * This configures the UCB1x00 layer depending on the machine type
-+ * we're running on. The UCB1x00 drivers should not contain any
-+ * machine dependencies.
-+ *
-+ * We can get rid of some of these dependencies by using existing
-+ * facilities provided by the kernel - namely IRQ probing. The
-+ * machine specific files are expected to setup the IRQ levels on
-+ * initialisation. With any luck, we'll get rid of all the
-+ * machine dependencies here.
-+ */
-+static int __init ucb1x00_configure(struct ucb1x00 *ucb)
-+{
-+ unsigned int irq_gpio_pin = 0;
-+ int irq, default_irq = NO_IRQ;
-+
-+ if (machine_is_adsbitsy())
-+ default_irq = IRQ_GPCIN4;
-+
-+// if (machine_is_assabet())
-+// default_irq = IRQ_GPIO23;
-+
-+#ifdef CONFIG_SA1100_CERF
-+ if (machine_is_cerf())
-+ default_irq = IRQ_GPIO_UCB1200_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_FREEBIRD
-+ if (machine_is_freebird())
-+ default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ;
-+#endif
-+#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
-+// if (machine_is_graphicsclient())
-+// default_irq = IRQ_GRAPHICSCLIENT_UCB1200;
-+#endif
-+#if defined(CONFIG_SA1100_GRAPICSMASTER)
-+ if (machine_is_graphicsmaster())
-+ default_irq = IRQ_GRAPHICSMASTER_UCB1200;
-+#endif
-+#ifdef CONFIG_SA1100_LART
-+ if (machine_is_lart()) {
-+ default_irq = LART_IRQ_UCB1200;
-+ irq_gpio_pin = LART_GPIO_UCB1200;
-+ }
-+#endif
-+ if (machine_is_omnimeter())
-+ default_irq = IRQ_GPIO23;
-+
-+#ifdef CONFIG_SA1100_PFS168
-+ if (machine_is_pfs168())
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (machine_is_simpad())
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+ irq_gpio_pin = GPIO_UCB1300_IRQ;
-+ }
-+#endif
-+ if (machine_is_shannon())
-+ default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC;
-+#ifdef CONFIG_SA1100_YOPY
-+ if (machine_is_yopy())
-+ default_irq = IRQ_GPIO_UCB1200_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_ACCELENT
-+ if (machine_is_accelent_sa()) {
-+ ucb->irq = IRQ_GPIO_UCB1200_IRQ;
-+ irq_gpio_pin = GPIO_UCB1200_IRQ;
-+ }
-+#endif
-+
-+ /*
-+ * Eventually, this will disappear.
-+ */
-+ if (irq_gpio_pin)
-+ set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
-+
-+ irq = ucb1x00_detect_irq(ucb);
-+ if (irq != NO_IRQ) {
-+ if (default_irq != NO_IRQ && irq != default_irq)
-+ printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n",
-+ irq, default_irq);
-+ if (irq == default_irq)
-+ printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. "
-+ "Please remove machine dependencies from "
-+ "ucb1x00-core.c\n", irq);
-+ ucb->irq = irq;
-+ } else {
-+ printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n",
-+ default_irq);
-+ ucb->irq = default_irq;
-+ }
-+
-+ return ucb->irq == NO_IRQ ? -ENODEV : 0;
-+}
-+
-+struct ucb1x00 *my_ucb;
-+
-+/**
-+ * ucb1x00_get - get the UCB1x00 structure describing a chip
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the UCB1x00 structure describing a chip.
-+ *
-+ * FIXME: Currently very noddy indeed, which currently doesn't
-+ * matter since we only support one chip.
-+ */
-+struct ucb1x00 *ucb1x00_get(void)
-+{
-+ return my_ucb;
-+}
-+
-+static int __init ucb1x00_init(void)
-+{
-+ struct mcp *mcp;
-+ unsigned int id;
-+ int ret = -ENODEV;
-+
-+ mcp = mcp_get();
-+ if (!mcp)
-+ goto no_mcp;
-+
-+ mcp_enable(mcp);
-+ id = mcp_reg_read(mcp, UCB_ID);
-+
-+ if (id != UCB_ID_1200 && id != UCB_ID_1300) {
-+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
-+ goto out;
-+ }
-+
-+ my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
-+ ret = -ENOMEM;
-+ if (!my_ucb)
-+ goto out;
-+
-+ if (machine_is_shannon()) {
-+ /* reset the codec */
-+ GPDR |= SHANNON_GPIO_CODEC_RESET;
-+ GPCR = SHANNON_GPIO_CODEC_RESET;
-+ GPSR = SHANNON_GPIO_CODEC_RESET;
-+
-+ }
-+
-+ memset(my_ucb, 0, sizeof(struct ucb1x00));
-+
-+ spin_lock_init(&my_ucb->lock);
-+ spin_lock_init(&my_ucb->io_lock);
-+ sema_init(&my_ucb->adc_sem, 1);
-+
-+ my_ucb->id = id;
-+ my_ucb->mcp = mcp;
-+
-+ ret = ucb1x00_configure(my_ucb);
-+ if (ret)
-+ goto out;
-+
-+ ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
-+ if (ret) {
-+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
-+ my_ucb->irq, ret);
-+ kfree(my_ucb);
-+ my_ucb = NULL;
-+ goto out;
-+ }
-+
-+#ifdef CONFIG_PM
-+ my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm);
-+ if (my_ucb->pmdev == NULL)
-+ printk("ucb1x00: unable to register in PM.\n");
-+ else
-+ my_ucb->pmdev->data = my_ucb;
-+#endif
-+
-+out:
-+ mcp_disable(mcp);
-+no_mcp:
-+ return ret;
-+}
-+
-+static void __exit ucb1x00_exit(void)
-+{
-+ free_irq(my_ucb->irq, my_ucb);
-+ kfree(my_ucb);
-+}
-+
-+module_init(ucb1x00_init);
-+module_exit(ucb1x00_exit);
-+
-+EXPORT_SYMBOL(ucb1x00_get);
-+
-+EXPORT_SYMBOL(ucb1x00_io_set_dir);
-+EXPORT_SYMBOL(ucb1x00_io_write);
-+EXPORT_SYMBOL(ucb1x00_io_read);
-+
-+EXPORT_SYMBOL(ucb1x00_adc_enable);
-+EXPORT_SYMBOL(ucb1x00_adc_read);
-+EXPORT_SYMBOL(ucb1x00_adc_disable);
-+
-+EXPORT_SYMBOL(ucb1x00_hook_irq);
-+EXPORT_SYMBOL(ucb1x00_free_irq);
-+EXPORT_SYMBOL(ucb1x00_enable_irq);
-+EXPORT_SYMBOL(ucb1x00_disable_irq);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 core driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00-ts.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,664 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-ts.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 21-Jan-2002 <jco@ict.es> :
-+ *
-+ * Added support for synchronous A/D mode. This mode is useful to
-+ * avoid noise induced in the touchpanel by the LCD, provided that
-+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
-+ * It is important to note that the signal connected to the ADCSYNC
-+ * pin should provide pulses even when the LCD is blanked, otherwise
-+ * a pen touch needed to unblank the LCD will never be read.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/smp_lock.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+#include <asm/semaphore.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Define this if you want the UCB1x00 stuff to talk to the input layer
-+ */
-+#undef USE_INPUT
-+
-+#ifndef USE_INPUT
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/poll.h>
-+
-+/*
-+ * This structure is nonsense - millisecs is not very useful
-+ * since the field size is too small. Also, we SHOULD NOT
-+ * be exposing jiffies to user space directly.
-+ */
-+struct ts_event {
-+ u16 pressure;
-+ u16 x;
-+ u16 y;
-+ u16 pad;
-+ struct timeval stamp;
-+};
-+
-+#define NR_EVENTS 16
-+
-+#else
-+
-+#include <linux/input.h>
-+
-+#endif
-+
-+struct ucb1x00_ts {
-+#ifdef USE_INPUT
-+ struct input_dev idev;
-+#endif
-+ struct ucb1x00 *ucb;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pmdev;
-+#endif
-+
-+ wait_queue_head_t irq_wait;
-+ struct semaphore sem;
-+ struct completion init_exit;
-+ struct task_struct *rtask;
-+ int use_count;
-+ u16 x_res;
-+ u16 y_res;
-+
-+#ifndef USE_INPUT
-+ struct fasync_struct *fasync;
-+ wait_queue_head_t read_wait;
-+ u8 evt_head;
-+ u8 evt_tail;
-+ struct ts_event events[NR_EVENTS];
-+#endif
-+ int restart:1;
-+ int adcsync:1;
-+};
-+
-+static struct ucb1x00_ts ucbts;
-+static int adcsync = UCB_NOSYNC;
-+
-+static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);
-+static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);
-+
-+#ifndef USE_INPUT
-+
-+#define ucb1x00_ts_evt_pending(ts) ((volatile u8)(ts)->evt_head != (ts)->evt_tail)
-+#define ucb1x00_ts_evt_get(ts) ((ts)->events + (ts)->evt_tail)
-+#define ucb1x00_ts_evt_pull(ts) ((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1))
-+#define ucb1x00_ts_evt_clear(ts) ((ts)->evt_head = (ts)->evt_tail = 0)
-+
-+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ int next_head;
-+
-+ next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);
-+ if (next_head != ts->evt_tail) {
-+ ts->events[ts->evt_head].pressure = pressure;
-+ ts->events[ts->evt_head].x = x;
-+ ts->events[ts->evt_head].y = y;
-+ do_gettimeofday(&ts->events[ts->evt_head].stamp);
-+ ts->evt_head = next_head;
-+
-+ if (ts->fasync)
-+ kill_fasync(&ts->fasync, SIGIO, POLL_IN);
-+ wake_up_interruptible(&ts->read_wait);
-+ }
-+}
-+
-+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_ts_evt_add(ts, 0, 0, 0);
-+}
-+
-+/*
-+ * User space driver interface.
-+ */
-+static ssize_t
-+ucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct ucb1x00_ts *ts = filp->private_data;
-+ char *ptr = buffer;
-+ int err = 0;
-+
-+ add_wait_queue(&ts->read_wait, &wait);
-+ while (count >= sizeof(struct ts_event)) {
-+ err = -ERESTARTSYS;
-+ if (signal_pending(current))
-+ break;
-+
-+ if (ucb1x00_ts_evt_pending(ts)) {
-+ struct ts_event *evt = ucb1x00_ts_evt_get(ts);
-+
-+ err = copy_to_user(ptr, evt, sizeof(struct ts_event));
-+ ucb1x00_ts_evt_pull(ts);
-+
-+ if (err)
-+ break;
-+
-+ ptr += sizeof(struct ts_event);
-+ count -= sizeof(struct ts_event);
-+ continue;
-+ }
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ err = -EAGAIN;
-+ if (filp->f_flags & O_NONBLOCK)
-+ break;
-+ schedule();
-+ }
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&ts->read_wait, &wait);
-+
-+ return ptr == buffer ? err : ptr - buffer;
-+}
-+
-+static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+ int ret = 0;
-+
-+ poll_wait(filp, &ts->read_wait, wait);
-+ if (ucb1x00_ts_evt_pending(ts))
-+ ret = POLLIN | POLLRDNORM;
-+
-+ return ret;
-+}
-+
-+static int ucb1x00_ts_fasync(int fd, struct file *filp, int on)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+
-+ return fasync_helper(fd, filp, on, &ts->fasync);
-+}
-+
-+static int ucb1x00_ts_open(struct inode *inode, struct file *filp)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+ int ret = 0;
-+
-+ ret = ucb1x00_ts_startup(ts);
-+ if (ret == 0)
-+ filp->private_data = ts;
-+
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static int ucb1x00_ts_release(struct inode *inode, struct file *filp)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+
-+ down(&ts->sem);
-+ ucb1x00_ts_fasync(-1, filp, 0);
-+ ucb1x00_ts_shutdown(ts);
-+ up(&ts->sem);
-+
-+ return 0;
-+}
-+
-+static struct file_operations ucb1x00_fops = {
-+ owner: THIS_MODULE,
-+ read: ucb1x00_ts_read,
-+ poll: ucb1x00_ts_poll,
-+ open: ucb1x00_ts_open,
-+ release: ucb1x00_ts_release,
-+ fasync: ucb1x00_ts_fasync,
-+};
-+
-+/*
-+ * The official UCB1x00 touchscreen is a miscdevice:
-+ * 10 char Non-serial mice, misc features
-+ * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen
-+ */
-+static struct miscdevice ucb1x00_ts_dev = {
-+ minor: 14,
-+ name: "touchscreen/ucb1x00",
-+ fops: &ucb1x00_fops,
-+};
-+
-+static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
-+{
-+ init_waitqueue_head(&ts->read_wait);
-+ return misc_register(&ucb1x00_ts_dev);
-+}
-+
-+static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
-+{
-+ misc_deregister(&ucb1x00_ts_dev);
-+}
-+
-+#else
-+
-+#define ucb1x00_ts_evt_clear(ts) do { } while (0)
-+
-+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ input_report_abs(&ts->idev, ABS_X, x);
-+ input_report_abs(&ts->idev, ABS_Y, y);
-+ input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
-+}
-+
-+static int ucb1x00_ts_open(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-+
-+ return ucb1x00_ts_startup(ts);
-+}
-+
-+static void ucb1x00_ts_close(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-+
-+ down(&ts->sem);
-+ ucb1x00_ts_shutdown(ts);
-+ up(&ts->sem);
-+}
-+
-+static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
-+{
-+ ts->idev.name = "Touchscreen panel";
-+ ts->idev.idproduct = ts->ucb->id;
-+ ts->idev.open = ucb1x00_ts_open;
-+ ts->idev.close = ucb1x00_ts_close;
-+
-+ __set_bit(EV_ABS, ts->idev.evbit);
-+ __set_bit(ABS_X, ts->idev.absbit);
-+ __set_bit(ABS_Y, ts->idev.absbit);
-+ __set_bit(ABS_PRESSURE, ts->idev.absbit);
-+
-+ input_register_device(&ts->idev);
-+
-+ return 0;
-+}
-+
-+static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
-+{
-+ input_unregister_device(&ts->idev);
-+}
-+
-+#endif
-+
-+/*
-+ * Switch to interrupt mode.
-+ */
-+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
-+}
-+
-+/*
-+ * Switch to pressure mode, and read pressure. We don't need to wait
-+ * here, since both plates are being driven.
-+ */
-+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to X position mode and measure Y plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y position mode and measure X plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to X plate resistance mode. Set MX to ground, PX to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y plate resistance mode. Set MY to ground, PY to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+/*
-+ * This is a RT kernel thread that handles the ADC accesses
-+ * (mainly so we can use semaphores in the UCB1200 core code
-+ * to serialise accesses to the ADC).
-+ */
-+static int ucb1x00_thread(void *_ts)
-+{
-+ struct ucb1x00_ts *ts = _ts;
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ int valid;
-+
-+ ts->rtask = tsk;
-+
-+ daemonize();
-+ reparent_to_init();
-+ strcpy(tsk->comm, "ktsd");
-+ tsk->tty = NULL;
-+ /*
-+ * We could run as a real-time thread. However, thus far
-+ * this doesn't seem to be necessary.
-+ */
-+// tsk->policy = SCHED_FIFO;
-+// tsk->rt_priority = 1;
-+
-+ /* only want to receive SIGKILL */
-+ spin_lock_irq(&tsk->sigmask_lock);
-+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-+ recalc_sigpending(tsk);
-+ spin_unlock_irq(&tsk->sigmask_lock);
-+
-+ complete(&ts->init_exit);
-+
-+ valid = 0;
-+
-+ add_wait_queue(&ts->irq_wait, &wait);
-+ for (;;) {
-+ unsigned int x, y, p, val;
-+ signed long timeout;
-+
-+ ts->restart = 0;
-+
-+ ucb1x00_adc_enable(ts->ucb);
-+
-+ x = ucb1x00_ts_read_xpos(ts);
-+ y = ucb1x00_ts_read_ypos(ts);
-+ p = ucb1x00_ts_read_pressure(ts);
-+
-+ /*
-+ * Switch back to interrupt mode.
-+ */
-+ ucb1x00_ts_mode_int(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ / 100);
-+ if (signal_pending(tsk))
-+ break;
-+
-+ ucb1x00_enable(ts->ucb);
-+ val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
-+
-+ if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+
-+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * If we spat out a valid sample set last time,
-+ * spit out a "pen off" sample here.
-+ */
-+ if (valid) {
-+ ucb1x00_ts_event_release(ts);
-+ valid = 0;
-+ }
-+
-+ timeout = MAX_SCHEDULE_TIMEOUT;
-+ } else {
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * Filtering is policy. Policy belongs in user
-+ * space. We therefore leave it to user space
-+ * to do any filtering they please.
-+ */
-+ if (!ts->restart) {
-+ ucb1x00_ts_evt_add(ts, p, x, y);
-+ valid = 1;
-+ }
-+
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ timeout = HZ / 100;
-+ }
-+
-+ schedule_timeout(timeout);
-+ if (signal_pending(tsk))
-+ break;
-+ }
-+
-+ remove_wait_queue(&ts->irq_wait, &wait);
-+
-+ ts->rtask = NULL;
-+ ucb1x00_ts_evt_clear(ts);
-+ complete_and_exit(&ts->init_exit, 0);
-+}
-+
-+/*
-+ * We only detect touch screen _touches_ with this interrupt
-+ * handler, and even then we just schedule our task.
-+ */
-+static void ucb1x00_ts_irq(int idx, void *id)
-+{
-+ struct ucb1x00_ts *ts = id;
-+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-+ wake_up(&ts->irq_wait);
-+}
-+
-+static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
-+{
-+ int ret = 0;
-+
-+ if (down_interruptible(&ts->sem))
-+ return -EINTR;
-+
-+ if (ts->use_count++ != 0)
-+ goto out;
-+
-+ if (ts->rtask)
-+ panic("ucb1x00: rtask running?");
-+
-+ init_waitqueue_head(&ts->irq_wait);
-+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
-+ if (ret < 0)
-+ goto out;
-+
-+ /*
-+ * If we do this at all, we should allow the user to
-+ * measure and read the X and Y resistance at any time.
-+ */
-+ ucb1x00_adc_enable(ts->ucb);
-+ ts->x_res = ucb1x00_ts_read_xres(ts);
-+ ts->y_res = ucb1x00_ts_read_yres(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ init_completion(&ts->init_exit);
-+ ret = kernel_thread(ucb1x00_thread, ts, 0);
-+ if (ret >= 0) {
-+ wait_for_completion(&ts->init_exit);
-+ ret = 0;
-+ } else {
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ }
-+
-+ out:
-+ if (ret)
-+ ts->use_count--;
-+ up(&ts->sem);
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts)
-+{
-+ if (--ts->use_count == 0) {
-+ if (ts->rtask) {
-+ send_sig(SIGKILL, ts->rtask, 1);
-+ wait_for_completion(&ts->init_exit);
-+ }
-+
-+ ucb1x00_enable(ts->ucb);
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
-+ ucb1x00_disable(ts->ucb);
-+ }
-+}
-+
-+#ifdef CONFIG_PM
-+static int ucb1x00_ts_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *) (dev->data);
-+
-+ if (rqst == PM_RESUME && ts->rtask != NULL) {
-+ /*
-+ * Restart the TS thread to ensure the
-+ * TS interrupt mode is set up again
-+ * after sleep.
-+ */
-+ ts->restart = 1;
-+ wake_up(&ts->irq_wait);
-+ }
-+ return 0;
-+}
-+#endif
-+
-+
-+/*
-+ * Initialisation.
-+ */
-+static int __init ucb1x00_ts_init(void)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+
-+ ts->ucb = ucb1x00_get();
-+ if (!ts->ucb)
-+ return -ENODEV;
-+
-+ ts->adcsync = adcsync;
-+ init_MUTEX(&ts->sem);
-+
-+#ifdef CONFIG_PM
-+ ts->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_ts_pm);
-+ if (ts->pmdev == NULL)
-+ printk("ucb1x00_ts: unable to register in PM.\n");
-+ else
-+ ts->pmdev->data = ts;
-+#endif
-+ return ucb1x00_ts_register(ts);
-+}
-+
-+static void __exit ucb1x00_ts_exit(void)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+
-+ ucb1x00_ts_deregister(ts);
-+
-+#ifdef CONFIG_PM
-+ if (ts->pmdev)
-+ pm_unregister(ts->pmdev);
-+#endif
-+}
-+
-+#ifndef MODULE
-+
-+/*
-+ * Parse kernel command-line options.
-+ *
-+ * syntax : ucbts=[sync|nosync],...
-+ */
-+static int __init ucb1x00_ts_setup(char *str)
-+{
-+ char *p;
-+
-+ while ((p = strsep(&str, ",")) != NULL) {
-+ if (strcmp(p, "sync") == 0)
-+ adcsync = UCB_SYNC;
-+ }
-+
-+ return 1;
-+}
-+
-+__setup("ucbts=", ucb1x00_ts_setup);
-+
-+#else
-+
-+MODULE_PARM(adcsync, "i");
-+MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal");
-+
-+#endif
-+
-+module_init(ucb1x00_ts_init);
-+module_exit(ucb1x00_ts_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/misc/ucb1x00.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,232 @@
-+/*
-+ * linux/drivers/misc/ucb1x00.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef UCB1200_H
-+#define UCB1200_H
-+
-+#define UCB_IO_DATA 0x00
-+#define UCB_IO_DIR 0x01
-+
-+#define UCB_IO_0 (1 << 0)
-+#define UCB_IO_1 (1 << 1)
-+#define UCB_IO_2 (1 << 2)
-+#define UCB_IO_3 (1 << 3)
-+#define UCB_IO_4 (1 << 4)
-+#define UCB_IO_5 (1 << 5)
-+#define UCB_IO_6 (1 << 6)
-+#define UCB_IO_7 (1 << 7)
-+#define UCB_IO_8 (1 << 8)
-+#define UCB_IO_9 (1 << 9)
-+
-+#define UCB_IE_RIS 0x02
-+#define UCB_IE_FAL 0x03
-+#define UCB_IE_STATUS 0x04
-+#define UCB_IE_CLEAR 0x04
-+#define UCB_IE_ADC (1 << 11)
-+#define UCB_IE_TSPX (1 << 12)
-+#define UCB_IE_TSMX (1 << 13)
-+#define UCB_IE_TCLIP (1 << 14)
-+#define UCB_IE_ACLIP (1 << 15)
-+
-+#define UCB_IRQ_TSPX 12
-+
-+#define UCB_TC_A 0x05
-+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
-+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
-+
-+#define UCB_TC_B 0x06
-+#define UCB_TC_B_VOICE_ENA (1 << 3)
-+#define UCB_TC_B_CLIP (1 << 4)
-+#define UCB_TC_B_ATT (1 << 6)
-+#define UCB_TC_B_SIDE_ENA (1 << 11)
-+#define UCB_TC_B_MUTE (1 << 13)
-+#define UCB_TC_B_IN_ENA (1 << 14)
-+#define UCB_TC_B_OUT_ENA (1 << 15)
-+
-+#define UCB_AC_A 0x07
-+#define UCB_AC_B 0x08
-+#define UCB_AC_B_LOOP (1 << 8)
-+#define UCB_AC_B_MUTE (1 << 13)
-+#define UCB_AC_B_IN_ENA (1 << 14)
-+#define UCB_AC_B_OUT_ENA (1 << 15)
-+
-+#define UCB_TS_CR 0x09
-+#define UCB_TS_CR_TSMX_POW (1 << 0)
-+#define UCB_TS_CR_TSPX_POW (1 << 1)
-+#define UCB_TS_CR_TSMY_POW (1 << 2)
-+#define UCB_TS_CR_TSPY_POW (1 << 3)
-+#define UCB_TS_CR_TSMX_GND (1 << 4)
-+#define UCB_TS_CR_TSPX_GND (1 << 5)
-+#define UCB_TS_CR_TSMY_GND (1 << 6)
-+#define UCB_TS_CR_TSPY_GND (1 << 7)
-+#define UCB_TS_CR_MODE_INT (0 << 8)
-+#define UCB_TS_CR_MODE_PRES (1 << 8)
-+#define UCB_TS_CR_MODE_POS (2 << 8)
-+#define UCB_TS_CR_BIAS_ENA (1 << 11)
-+#define UCB_TS_CR_TSPX_LOW (1 << 12)
-+#define UCB_TS_CR_TSMX_LOW (1 << 13)
-+
-+#define UCB_ADC_CR 0x0a
-+#define UCB_ADC_SYNC_ENA (1 << 0)
-+#define UCB_ADC_VREFBYP_CON (1 << 1)
-+#define UCB_ADC_INP_TSPX (0 << 2)
-+#define UCB_ADC_INP_TSMX (1 << 2)
-+#define UCB_ADC_INP_TSPY (2 << 2)
-+#define UCB_ADC_INP_TSMY (3 << 2)
-+#define UCB_ADC_INP_AD0 (4 << 2)
-+#define UCB_ADC_INP_AD1 (5 << 2)
-+#define UCB_ADC_INP_AD2 (6 << 2)
-+#define UCB_ADC_INP_AD3 (7 << 2)
-+#define UCB_ADC_EXT_REF (1 << 5)
-+#define UCB_ADC_START (1 << 7)
-+#define UCB_ADC_ENA (1 << 15)
-+
-+#define UCB_ADC_DATA 0x0b
-+#define UCB_ADC_DAT_VAL (1 << 15)
-+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-+
-+#define UCB_ID 0x0c
-+#define UCB_ID_1200 0x1004
-+#define UCB_ID_1300 0x1005
-+
-+#define UCB_MODE 0x0d
-+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
-+#define UCB_MODE_AUD_OFF_CAN (1 << 13)
-+
-+#include "mcp.h"
-+
-+struct ucb1x00;
-+
-+struct ucb1x00_irq {
-+ void *devid;
-+ void (*fn)(int, void *);
-+};
-+
-+struct ucb1x00 {
-+ spinlock_t lock;
-+ struct mcp *mcp;
-+ struct pm_dev *pmdev;
-+ unsigned int irq;
-+ struct semaphore adc_sem;
-+ spinlock_t io_lock;
-+ u16 id;
-+ u16 io_dir;
-+ u16 io_out;
-+ u16 adc_cr;
-+ u16 irq_fal_enbl;
-+ u16 irq_ris_enbl;
-+ struct ucb1x00_irq irq_handler[16];
-+};
-+
-+/**
-+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the SIB clock rate in Hz.
-+ */
-+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
-+{
-+ return mcp_get_sclk_rate(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_enable - enable the UCB1x00 SIB clock
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Enable the SIB clock. This can be called multiple times.
-+ */
-+static inline void ucb1x00_enable(struct ucb1x00 *ucb)
-+{
-+ mcp_enable(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_disable - disable the UCB1x00 SIB clock
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Disable the SIB clock. The SIB clock will only be disabled
-+ * when the number of ucb1x00_enable calls match the number of
-+ * ucb1x00_disable calls.
-+ */
-+static inline void ucb1x00_disable(struct ucb1x00 *ucb)
-+{
-+ mcp_disable(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_reg_write - write a UCB1x00 register
-+ * @ucb: UCB1x00 structure describing chip
-+ * @reg: UCB1x00 4-bit register index to write
-+ * @val: UCB1x00 16-bit value to write
-+ *
-+ * Write the UCB1x00 register @reg with value @val. The SIB
-+ * clock must be running for this function to return.
-+ */
-+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
-+{
-+ mcp_reg_write(ucb->mcp, reg, val);
-+}
-+
-+/**
-+ * ucb1x00_reg_read - read a UCB1x00 register
-+ * @ucb: UCB1x00 structure describing chip
-+ * @reg: UCB1x00 4-bit register index to write
-+ *
-+ * Read the UCB1x00 register @reg and return its value. The SIB
-+ * clock must be running for this function to return.
-+ */
-+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
-+{
-+ return mcp_reg_read(ucb->mcp, reg);
-+}
-+/**
-+ * ucb1x00_set_audio_divisor -
-+ * @ucb: UCB1x00 structure describing chip
-+ * @div: SIB clock divisor
-+ */
-+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
-+{
-+ mcp_set_audio_divisor(ucb->mcp, div);
-+}
-+
-+/**
-+ * ucb1x00_set_telecom_divisor -
-+ * @ucb: UCB1x00 structure describing chip
-+ * @div: SIB clock divisor
-+ */
-+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
-+{
-+ mcp_set_telecom_divisor(ucb->mcp, div);
-+}
-+
-+struct ucb1x00 *ucb1x00_get(void);
-+
-+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
-+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
-+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
-+
-+#define UCB_NOSYNC (0)
-+#define UCB_SYNC (1)
-+
-+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
-+void ucb1x00_adc_enable(struct ucb1x00 *ucb);
-+void ucb1x00_adc_disable(struct ucb1x00 *ucb);
-+
-+/*
-+ * Which edges of the IRQ do you want to control today?
-+ */
-+#define UCB_RISING (1 << 0)
-+#define UCB_FALLING (1 << 1)
-+
-+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
-+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
-+
-+#endif
---- linux-2.4.25/drivers/mtd/chips/cfi_probe.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/chips/cfi_probe.c 2004-03-31 17:15:09.000000000 +0200
-@@ -65,6 +65,10 @@
- return 0;
- }
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-+
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
- if (!qry_present(map,base,cfi))
-@@ -84,6 +88,8 @@
- /* Eep. This chip also had the QRY marker.
- * Is it an alias for the new one? */
- cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
-
- /* If the QRY marker goes away, it's an alias */
- if (!qry_present(map, chips[i].start, cfi)) {
-@@ -96,7 +102,8 @@
- * too and if it's the same, assume it's an alias. */
- /* FIXME: Use other modes to do a proper check */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
--
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
- if (qry_present(map, base, cfi)) {
- printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
- map->name, base, chips[i].start);
-@@ -119,6 +126,10 @@
- /* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
-+
- printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
- map->name, cfi->interleave, cfi->device_type*8, base,
- map->buswidth*8);
-@@ -165,6 +176,20 @@
- cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
- cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
-
-+ /*
-+ * ST screwed up the CFI interface for buffer writes on their parts,
-+ * so this needs to be fixed up by hand here.
-+ *
-+ * A possible enhancment is that instead of just reverting back
-+ * to word write (as this does), we could use the ST specific double
-+ * word write instead.
-+ */
-+
-+ if (cfi_read_query(map,base) == 0x20){
-+ cfi->cfiq->BufWriteTimeoutTyp = 0;
-+ cfi->cfiq->BufWriteTimeoutMax = 0;
-+ }
-+
- #ifdef DEBUG_CFI
- /* Dump the information therein */
- print_cfi_ident(cfi->cfiq);
-@@ -182,6 +207,9 @@
- /* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
- return 1;
- }
-
---- linux-2.4.25/drivers/mtd/devices/Config.in~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/devices/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -17,6 +17,15 @@
- if [ "$CONFIG_SA1100_LART" = "y" ]; then
- dep_tristate ' 28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD
- fi
-+if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then
-+ dep_tristate ' SyncFlash driver for MX1ADS' CONFIG_MTD_SYNCFLASH $CONFIG_MTD
-+fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ dep_tristate ' AT91RM9200 DataFlash support' CONFIG_MTD_AT91_DATAFLASH $CONFIG_MTD
-+ if [ "$CONFIG_MTD_AT91_DATAFLASH" = "y" -o "$CONFIG_MTD_AT91_DATAFLASH" = "m" ]; then
-+ bool ' Enable DataFlash card? ' CONFIG_MTD_AT91_DATAFLASH_CARD
-+ fi
-+fi
- dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD
- if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then
- int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096
---- linux-2.4.25/drivers/mtd/devices/Makefile~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
-+++ linux-2.4.25/drivers/mtd/devices/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -21,6 +21,7 @@
- obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
- obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
- obj-$(CONFIG_MTD_LART) += lart.o
-+obj-$(CONFIG_MTD_SYNCFLASH) += syncflash.o
- obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
-
- include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/devices/syncflash.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,615 @@
-+/*
-+ * MTD driver for Micron SyncFlash flash memory.
-+ *
-+ * Author: Jon McClintock <jonm@bluemug.com>
-+ *
-+ * Based loosely upon the LART flash driver, authored by Abraham vd Merwe
-+ * <abraham@2d3d.co.za>.
-+ *
-+ * Copyright 2003, Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * This code is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * References:
-+ *
-+ * [1] Micron SyncFlash homepage
-+ * - http://www.syncflash.com/
-+ *
-+ * [2] MT28S4M16LC -- 4Mx16 SyncFlash memory datasheet
-+ * - http://syncflash.com/pdfs/datasheets/mt28s4m16lc_6.pdf
-+ *
-+ * [3] MTD internal API documentation
-+ * - http://www.linux-mtd.infradead.org/tech/
-+ *
-+ * Limitations:
-+ *
-+ * Even though this driver is written for Micron SyncFlash, it is quite
-+ * specific to the Motorola MX1 ADS development board.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/version.h>
-+#include <linux/errno.h>
-+#include <linux/mtd/mtd.h>
-+#include <asm/io.h>
-+
-+/* partition support */
-+#define HAVE_PARTITIONS
-+#ifdef HAVE_PARTITIONS
-+#include <linux/mtd/partitions.h>
-+#endif
-+
-+#ifndef CONFIG_ARCH_MX1ADS
-+#error The SyncFlash driver currently only supports the MX1 ADS platform.
-+#endif
-+
-+/*
-+ * General flash configuration parameters.
-+ */
-+#define BUSWIDTH 4
-+#define FLASH_BLOCKSIZE (256 * 1024 * BUSWIDTH)
-+#define FLASH_NUMBLOCKS 16
-+
-+#define BUSWIDTH 4
-+#define FLASH_ADDRESS IO_ADDRESS(MX1ADS_FLASH_BASE)
-+
-+#define FLASH_MANUFACTURER 0x002C002C
-+#define FLASH_DEVICE_ID 0x00D300D3
-+
-+/*
-+ * The size and extent of the bootloader in flash.
-+ */
-+#define NUM_BOOTLOADER_BLOCKS 1
-+#define BOOTLOADER_START 0x00000000
-+#define BOOTLOADER_LEN (NUM_BOOTLOADER_BLOCKS * FLASH_BLOCKSIZE)
-+
-+/*
-+ * The size and extent of the kernel in flash.
-+ */
-+#define NUM_KERNEL_BLOCKS 1
-+#define KERNEL_START (BOOTLOADER_START + BOOTLOADER_LEN)
-+#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE)
-+
-+/* File system */
-+#define NUM_FILESYSTEM_BLOCKS 14
-+#define FILESYSTEM_START (KERNEL_START + KERNEL_LEN)
-+#define FILESYSTEM_LEN (NUM_FILESYSTEM_BLOCKS * FLASH_BLOCKSIZE)
-+
-+
-+/*
-+ * SDRAM controller register location and values. These are very specific
-+ * to the MX1.
-+ */
-+#define SDRAMC_REGISTER IO_ADDRESS(0x00221004)
-+
-+/*
-+ * This the mask we use to get the start of a block from a given address.
-+ */
-+#define BLOCK_MASK (0xFFF00000)
-+
-+/*
-+ * This is the A10 address line of the SyncFlash; it's used to initiate
-+ * a precharge command.
-+ */
-+#define SYNCFLASH_A10 (0x00100000)
-+
-+/*
-+ * SDRAM controller MODE settings.
-+ */
-+#define CMD_NORMAL (0x81020300) /* Normal Mode */
-+#define CMD_PREC (CMD_NORMAL + 0x10000000) /* Precharge command */
-+#define CMD_AUTO (CMD_NORMAL + 0x20000000) /* Auto refresh */
-+#define CMD_LMR (CMD_NORMAL + 0x30000000) /* Load Mode Register */
-+#define CMD_LCR (CMD_NORMAL + 0x60000000) /* LCR Command */
-+#define CMD_PROGRAM (CMD_NORMAL + 0x70000000) /* SyncFlash Program */
-+
-+/*
-+ * SyncFlash LCR Commands adjusted for the DBMX1 AHB internal address bus .
-+ */
-+#define LCR_READ_STATUS (0x0001C000) /* 0x70 */
-+#define LCR_READ_CONFIG (0x00024000) /* 0x90 */
-+#define LCR_ERASE_CONFIRM (0x00008000) /* 0x20 */
-+#define LCR_ERASE_NVMODE (0x0000C000) /* 0x30 */
-+#define LCR_PROG_NVMODE (0x00028000) /* 0xA0 */
-+#define LCR_SR_CLEAR (0x00014000) /* 0x50 */
-+
-+/*
-+ * Status register bits
-+ */
-+#define SR_VPS_ERROR (1 << 8) /* Power-Up status error */
-+#define SR_ISM_READY (1 << 7) /* State machine isn't busy */
-+#define SR_ERASE_ERROR (1 << 5) /* Erase/Unprotect error */
-+#define SR_PROGRAM_ERROR (1 << 4) /* Program/Protect error */
-+#define SR_DEVICE_PROTECTED (1 << 3) /* Device is protected */
-+#define SR_ISM_STATUS_H (1 << 2) /* Bank ISM status, high bit */
-+#define SR_ISM_STATUS_L (1 << 1) /* Bank ISM status, low bit */
-+#define SR_DEVICE_ISM_STATUS (1 << 0) /* ISM is device-level */
-+
-+#define SR_ERROR (SR_VPS_ERROR|SR_ERASE_ERROR|SR_PROGRAM_ERROR|SR_DEVICE_PROTECTED)
-+
-+#define STATUS_VALUE(a) ((a) | ((a) << 16))
-+
-+/*
-+ * Device configuration register offsets
-+ */
-+#define DC_MANUFACTURER (0 * BUSWIDTH)
-+#define DC_DEVICE_ID (1 * BUSWIDTH)
-+#define DC_BLOCK_PROTECT (2 * BUSWIDTH)
-+#define DC_DEVICE_PROTECT (3 * BUSWIDTH)
-+
-+#define FL_WORD(addr) (*(volatile unsigned long*)(addr))
-+
-+static char module_name[] = "syncflash";
-+
-+inline __u8 read8 (__u32 offset)
-+{
-+ return *(volatile __u8 *) (FLASH_ADDRESS + offset);
-+}
-+
-+inline __u32 read32 (__u32 offset)
-+{
-+ return *(volatile __u32 *) (FLASH_ADDRESS + offset);
-+}
-+
-+inline void write32 (__u32 x,__u32 offset)
-+{
-+ *(volatile __u32 *) (FLASH_ADDRESS + offset) = x;
-+}
-+
-+static __u32 read_device_configuration_register(__u32 reg_number)
-+{
-+ __u32 tmp;
-+
-+ /* Setup the SDRAM controller to issue an LCR command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+
-+ /* Perform a read to issue the Read Device Configuration Command. */
-+ tmp = read32(LCR_READ_CONFIG);
-+
-+ /* Return the SDRAM controller to normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+
-+ /* Return the value of the specified register. */
-+ tmp = read32(reg_number);
-+
-+ return tmp;
-+}
-+
-+/*
-+ * Get the status of the flash devices.
-+ */
-+static __u32 flash_read_status()
-+{
-+ __u32 status, tmp;
-+
-+ /* Enter the SyncFlash Program READ/WRITE mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
-+
-+ /* Read the status register. */
-+ status = read32(LCR_READ_STATUS);
-+
-+ /* Clear the status register. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+ tmp = read32(LCR_SR_CLEAR);
-+
-+ /* Return to Normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+
-+ return status;
-+}
-+
-+/*
-+ * Loop until both write state machines are ready.
-+ */
-+static __u32 flash_status_wait()
-+{
-+ __u32 status;
-+ do {
-+ status = flash_read_status();
-+ } while ((status & STATUS_VALUE(SR_ISM_READY)) !=
-+ STATUS_VALUE(SR_ISM_READY));
-+ return status;
-+}
-+
-+/*
-+ * Loop until the Write State machine is ready, then do a full error
-+ * check. Clear status and leave the flash in Read Array mode; return
-+ * 0 for no error, -1 for error.
-+ */
-+static int flash_status_full_check()
-+{
-+ __u32 status;
-+
-+ status = flash_status_wait() & STATUS_VALUE(SR_ERROR);
-+ return status ? -EIO : 0;
-+}
-+
-+/*
-+ * Return the flash to the normal mode.
-+ */
-+static void flash_normal_mode()
-+{
-+ __u32 tmp;
-+
-+ /* First issue a precharge all command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(SYNCFLASH_A10);
-+
-+ /* Now place the SDRAM controller in Normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+}
-+
-+/*
-+ * Probe for SyncFlash memory on MX1ADS board.
-+ *
-+ * Returns 1 if we found SyncFlash memory, 0 otherwise.
-+ */
-+static int flash_probe (void)
-+{
-+ __u32 manufacturer, device_id;
-+
-+ /* For some reason, the first read doesn't work, so we do it
-+ * twice. */
-+ manufacturer = read_device_configuration_register(DC_MANUFACTURER);
-+ manufacturer = read_device_configuration_register(DC_MANUFACTURER);
-+ device_id = read_device_configuration_register(DC_DEVICE_ID);
-+
-+ printk("SyncFlash probe: manufacturer 0x%08lx, device_id 0x%08lx\n",
-+ manufacturer, device_id);
-+ return (manufacturer == FLASH_MANUFACTURER &&
-+ device_id == FLASH_DEVICE_ID);
-+}
-+
-+/*
-+ * Erase one block of flash memory at offset ``offset'' which is any
-+ * address within the block which should be erased.
-+ *
-+ * Returns 0 if successful, -1 otherwise.
-+ */
-+static inline int erase_block (__u32 offset)
-+{
-+ __u32 tmp;
-+
-+ /* Mask off the lower bits of the address to get the first address
-+ * in the flash block. */
-+ offset &= (__u32)BLOCK_MASK;
-+
-+ /* Perform a read and precharge of the bank before the LCR|ACT|WRIT
-+ * sequence to avoid the inadvertent precharge command occurring
-+ * during the LCR_ACT_WRIT sequence. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+ tmp = read32(offset);
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(offset);
-+
-+ /* Now start the actual erase. */
-+
-+ /* LCR|ACT|WRIT sequence */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+ write32(0, offset + LCR_ERASE_CONFIRM);
-+
-+ /* Return to normal mode to issue the erase confirm. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+ write32(0xD0D0D0D0, offset);
-+
-+ if (flash_status_full_check()) {
-+ printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",
-+ module_name, offset);
-+ return (-1);
-+ }
-+
-+ flash_normal_mode();
-+
-+ return 0;
-+}
-+
-+static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
-+{
-+ __u32 addr,len;
-+ int i,first;
-+
-+ /* sanity checks */
-+ if (instr->addr + instr->len > mtd->size) return (-EINVAL);
-+
-+ /*
-+ * check that both start and end of the requested erase are
-+ * aligned with the erasesize at the appropriate addresses.
-+ *
-+ * skip all erase regions which are ended before the start of
-+ * the requested erase. Actually, to save on the calculations,
-+ * we skip to the first erase region which starts after the
-+ * start of the requested erase, and then go back one.
-+ */
-+ for (i = 0; (i < mtd->numeraseregions) &&
-+ (instr->addr >= mtd->eraseregions[i].offset); i++) ;
-+ i--;
-+
-+ /*
-+ * ok, now i is pointing at the erase region in which this
-+ * erase request starts. Check the start of the requested
-+ * erase range is aligned with the erase size which is in
-+ * effect here.
-+ */
-+ if (instr->addr & (mtd->eraseregions[i].erasesize - 1))
-+ return (-EINVAL);
-+
-+ /* Remember the erase region we start on */
-+ first = i;
-+
-+ /*
-+ * next, check that the end of the requested erase is aligned
-+ * with the erase region at that address.
-+ *
-+ * as before, drop back one to point at the region in which
-+ * the address actually falls
-+ */
-+ for (;
-+ (i < mtd->numeraseregions) &&
-+ ((instr->addr + instr->len) >= mtd->eraseregions[i].offset) ;
-+ i++) ;
-+ i--;
-+
-+ /* is the end aligned on a block boundary? */
-+ if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1))
-+ return (-EINVAL);
-+
-+ addr = instr->addr;
-+ len = instr->len;
-+
-+ i = first;
-+
-+ /* now erase those blocks */
-+ while (len)
-+ {
-+ if (erase_block (addr))
-+ {
-+ instr->state = MTD_ERASE_FAILED;
-+ return (-EIO);
-+ }
-+
-+ addr += mtd->eraseregions[i].erasesize;
-+ len -= mtd->eraseregions[i].erasesize;
-+
-+ if (addr == (mtd->eraseregions[i].offset +
-+ (mtd->eraseregions[i].erasesize *
-+ mtd->eraseregions[i].numblocks)))
-+ i++;
-+ }
-+
-+ instr->state = MTD_ERASE_DONE;
-+ if (instr->callback) instr->callback (instr);
-+
-+ return (0);
-+}
-+
-+static int flash_read (struct mtd_info *mtd, loff_t from,
-+ size_t len, size_t *retlen, u_char *buf)
-+{
-+ /* Sanity checks. */
-+ if (!len) return (0);
-+ if (from + len > mtd->size) return (-EINVAL);
-+
-+ /* Ensure that we are in normal mode. */
-+ flash_normal_mode();
-+
-+ /* We always read len bytes. */
-+ *retlen = len;
-+
-+ /* first, we read bytes until we reach a dword boundary */
-+ if (from & (BUSWIDTH - 1))
-+ {
-+ int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
-+ while (len && gap--) *buf++ = read8(from++), len--;
-+ }
-+
-+ /* now we read dwords until we reach a non-dword boundary */
-+ while (len >= BUSWIDTH)
-+ {
-+ *((__u32 *) buf) = read32(from);
-+
-+ buf += BUSWIDTH;
-+ from += BUSWIDTH;
-+ len -= BUSWIDTH;
-+ }
-+
-+ /* top up the last unaligned bytes */
-+ if (len & (BUSWIDTH - 1))
-+ while (len--) *buf++ = read8(from++);
-+
-+ return (0);
-+}
-+
-+/*
-+ * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
-+ * must be 32 bits, i.e. it must be on a dword boundary.
-+ *
-+ * Returns 0 if successful, -1 otherwise.
-+ */
-+static int flash_write_dword(__u32 offset, __u32 x)
-+{
-+ __u32 tmp;
-+
-+ /* First issue a precharge all command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(SYNCFLASH_A10);
-+
-+ /* Enter the SyncFlash programming mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
-+ write32(x, offset);
-+
-+ /* Wait for the write to complete. */
-+ flash_status_wait();
-+
-+ /* Return to normal mode. */
-+ flash_normal_mode();
-+
-+ return 0;
-+}
-+
-+static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
-+{
-+ __u8 tmp[4];
-+ int i,n;
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len) return (0);
-+ if (to + len > mtd->size) return (-EINVAL);
-+
-+ /* First, we write a 0xFF.... padded byte until we reach a
-+ * dword boundary. */
-+ if (to & (BUSWIDTH - 1))
-+ {
-+ __u32 aligned = to & ~(BUSWIDTH - 1);
-+ int gap = to - aligned;
-+
-+ i = n = 0;
-+
-+ while (gap--) tmp[i++] = 0xFF;
-+ while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
-+ while (i < BUSWIDTH) tmp[i++] = 0xFF;
-+
-+ if (flash_write_dword(aligned, *((__u32 *) tmp)))
-+ return (-EIO);
-+
-+ to += n;
-+ buf += n;
-+ *retlen += n;
-+ }
-+
-+ /* Now we write dwords until we reach a non-dword boundary. */
-+ while (len >= BUSWIDTH)
-+ {
-+ if (flash_write_dword (to,*((__u32 *) buf))) return (-EIO);
-+
-+ to += BUSWIDTH;
-+ buf += BUSWIDTH;
-+ *retlen += BUSWIDTH;
-+ len -= BUSWIDTH;
-+ }
-+
-+ /* Top up the last unaligned bytes, padded with 0xFF.... */
-+ if (len & (BUSWIDTH - 1))
-+ {
-+ i = n = 0;
-+
-+ while (len--) tmp[i++] = buf[n++];
-+ while (i < BUSWIDTH) tmp[i++] = 0xFF;
-+
-+ if (flash_write_dword (to,*((__u32 *) tmp))) return (-EIO);
-+
-+ *retlen += n;
-+ }
-+
-+ return flash_status_full_check();
-+}
-+
-+
-+
-+#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-+
-+static struct mtd_info mtd;
-+
-+static struct mtd_erase_region_info erase_regions[] =
-+{
-+ /* flash blocks */
-+ {
-+ offset: 0x00000000,
-+ erasesize: FLASH_BLOCKSIZE,
-+ numblocks: FLASH_NUMBLOCKS
-+ },
-+};
-+
-+#ifdef HAVE_PARTITIONS
-+static struct mtd_partition syncflash_partitions[] =
-+{
-+ /* bootloader */
-+ {
-+ name: "bootloader",
-+ offset: BOOTLOADER_START,
-+ size: BOOTLOADER_LEN,
-+ mask_flags: 0
-+ },
-+ /* Kernel */
-+ {
-+ name: "kernel",
-+ offset: KERNEL_START, /* MTDPART_OFS_APPEND */
-+ size: KERNEL_LEN,
-+ mask_flags: 0
-+ },
-+ /* file system */
-+ {
-+ name: "file system",
-+ offset: FILESYSTEM_START, /* MTDPART_OFS_APPEND */
-+ size: FILESYSTEM_LEN, /* MTDPART_SIZ_FULL */
-+ mask_flags: 0
-+ }
-+};
-+#endif
-+
-+int __init syncflash_init (void)
-+{
-+ int result;
-+
-+ memset (&mtd,0,sizeof (mtd));
-+
-+ printk ("MTD driver for Micron SyncFlash.\n");
-+ printk ("%s: Probing for SyncFlash on MX1ADS...\n",module_name);
-+
-+ if (!flash_probe ())
-+ {
-+ printk (KERN_WARNING "%s: Found no SyncFlash devices\n",
-+ module_name);
-+ return (-ENXIO);
-+ }
-+
-+ printk ("%s: Found a SyncFlash device.\n",module_name);
-+
-+ mtd.name = module_name;
-+ mtd.type = MTD_NORFLASH;
-+ mtd.flags = MTD_CAP_NORFLASH;
-+ mtd.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS;
-+
-+ mtd.erasesize = FLASH_BLOCKSIZE;
-+ mtd.numeraseregions = NB_OF(erase_regions);
-+ mtd.eraseregions = erase_regions;
-+
-+ mtd.module = THIS_MODULE;
-+
-+ mtd.erase = flash_erase;
-+ mtd.read = flash_read;
-+ mtd.write = flash_write;
-+
-+#ifndef HAVE_PARTITIONS
-+ result = add_mtd_device(&mtd);
-+#else
-+ result = add_mtd_partitions(&mtd,
-+ syncflash_partitions,
-+ NB_OF(syncflash_partitions));
-+#endif
-+
-+ return (result);
-+}
-+
-+void __exit syncflash_exit (void)
-+{
-+#ifndef HAVE_PARTITIONS
-+ del_mtd_device (&mtd);
-+#else
-+ del_mtd_partitions (&mtd);
-+#endif
-+}
-+
-+module_init (syncflash_init);
-+module_exit (syncflash_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
-+MODULE_DESCRIPTION("MTD driver for Micron MT28S4M16LC SyncFlash on MX1ADS board");
-+
-+
---- linux-2.4.25/drivers/mtd/maps/Config.in~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -81,10 +81,10 @@
- dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS
- dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE
- dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310
-- dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
-- dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET
-+ dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_FORTUNET
-+ dep_tristate ' CFI Flash device mapped on Epxa' CONFIG_MTD_EPXA $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
- dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12
-- dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI
-+ dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_ARCH_EDB7212 $CONFIG_MTD_CFI
- dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE
- dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA
- fi
---- linux-2.4.25/drivers/mtd/maps/Makefile~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -3,11 +3,7 @@
- #
- # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $
-
--BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/)
--
--ifeq ($(BELOW25),y)
- O_TARGET := mapslink.o
--endif
-
- # Chip mappings
- obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
-@@ -17,7 +13,7 @@
- obj-$(CONFIG_MTD_DC21285) += dc21285.o
- obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
- obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
--obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
-+obj-$(CONFIG_MTD_EPXA) += epxa-flash.o
- obj-$(CONFIG_MTD_IQ80310) += iq80310.o
- obj-$(CONFIG_MTD_L440GX) += l440gx.o
- obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
-@@ -29,9 +25,9 @@
- obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
- ifneq ($(CONFIG_MTD_PHYSMAP),n)
- ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8)
-- obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
-+ obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
- else
-- obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
-+ obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
- endif
- endif
- obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
-@@ -39,6 +35,9 @@
- obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
- obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
- obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
-+ifeq ($(CONFIG_ASSABET_NEPONSET),y)
-+ obj-$(CONFIG_MTD_SA1100) += neponset-flash.o
-+endif
- obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
- obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
- obj-$(CONFIG_MTD_NETSC520) += netsc520.o
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/epxa-flash.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,234 @@
-+/*
-+ * Flash memory access on EPXA based devices
-+ *
-+ * (C) 2000 Nicolas Pitre <nico@cam.org>
-+ * Copyright (C) 2001 Altera Corporation
-+ * Copyright (C) 2001 Red Hat, Inc.
-+ *
-+ * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#ifdef CONFIG_EPXA10DB
-+#define BOARD_NAME "EPXA10DB"
-+#else
-+#define BOARD_NAME "EPXA1DB"
-+#endif
-+
-+static int nr_parts = 0;
-+static struct mtd_partition *parts;
-+
-+static struct mtd_info *mymtd;
-+
-+extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
-+static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readl(map->map_priv_1 + ofs);
-+}
-+
-+static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + from, len);
-+}
-+
-+static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ __raw_writeb(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ __raw_writew(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ __raw_writel(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy_toio(map->map_priv_1 + to, from, len);
-+}
-+
-+static struct map_info epxa_map = {
-+ .name = "EPXA flash",
-+ .size = FLASH_SIZE,
-+ .buswidth = 2,
-+ .read8 = epxa_read8,
-+ .read16 = epxa_read16,
-+ .read32 = epxa_read32,
-+ .copy_from = epxa_copy_from,
-+ .write8 = epxa_write8,
-+ .write16 = epxa_write16,
-+ .write32 = epxa_write32,
-+ .copy_to = epxa_copy_to
-+};
-+
-+static int __init epxa_mtd_init(void)
-+{
-+ int i;
-+
-+ printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-+ epxa_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_START, FLASH_SIZE);
-+ if (!epxa_map.map_priv_1) {
-+ printk("Failed to ioremap %s flash\n",BOARD_NAME);
-+ return -EIO;
-+ }
-+
-+ mymtd = do_map_probe("cfi_probe", &epxa_map);
-+ if (!mymtd) {
-+ iounmap((void *)epxa_map.map_priv_1);
-+ return -ENXIO;
-+ }
-+
-+ mymtd->module = THIS_MODULE;
-+
-+ /* Unlock the flash device. */
-+ if(mymtd->unlock){
-+ for (i=0; i<mymtd->numeraseregions;i++){
-+ int j;
-+ for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
-+ mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
-+ }
-+ }
-+ }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ nr_parts = parse_redboot_partitions(mymtd, &parts);
-+
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+#endif
-+#ifdef CONFIG_MTD_AFS_PARTS
-+ nr_parts = parse_afs_partitions(mymtd, &parts);
-+
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+#endif
-+
-+ /* No recognised partitioning schemes found - use defaults */
-+ nr_parts = epxa_default_partitions(mymtd, &parts);
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+
-+ /* If all else fails... */
-+ add_mtd_device(mymtd);
-+ return 0;
-+}
-+
-+static void __exit epxa_mtd_cleanup(void)
-+{
-+ if (mymtd) {
-+ if (nr_parts)
-+ del_mtd_partitions(mymtd);
-+ else
-+ del_mtd_device(mymtd);
-+ map_destroy(mymtd);
-+ }
-+ if (epxa_map.map_priv_1) {
-+ iounmap((void *)epxa_map.map_priv_1);
-+ epxa_map.map_priv_1 = 0;
-+ }
-+}
-+
-+
-+/*
-+ * This will do for now, once we decide which bootldr we're finally
-+ * going to use then we'll remove this function and do it properly
-+ *
-+ * Partions are currently (as offsets from base of flash):
-+ * 0x00000000 - 0x003FFFFF - bootloader (!)
-+ * 0x00400000 - 0x00FFFFFF - Flashdisk
-+ */
-+
-+static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
-+{
-+ struct mtd_partition *parts;
-+ int ret;
-+ int npartitions = 0;
-+ char *names;
-+ const char *name = "jffs";
-+
-+ printk("Using default partitions for %s\n",BOARD_NAME);
-+ npartitions=1;
-+ parts = kmalloc(npartitions*sizeof(*parts)+strlen(name)+1, GFP_KERNEL);
-+ if (!parts) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ memzero(parts,npartitions*sizeof(*parts)+strlen(name));
-+
-+ names = (char *)&parts[npartitions];
-+ parts[0].name = names;
-+ names += strlen(name) + 1;
-+ strcpy(parts[0].name, name);
-+
-+#ifdef CONFIG_EPXA10DB_R2
-+ parts[0].size = FLASH_SIZE-0x00400000;
-+ parts[0].offset = 0x00400000;
-+#elif defined CONFIG_EPXA10DB_R3
-+ parts[0].size = 0x00800000;
-+ parts[0].offset = 0x00800000;
-+#else
-+ parts[0].size = FLASH_SIZE-0x00180000;
-+ parts[0].offset = 0x00180000;
-+#endif
-+ ret = npartitions;
-+
-+ out:
-+ *pparts = parts;
-+ return ret;
-+}
-+
-+
-+module_init(epxa_mtd_init);
-+module_exit(epxa_mtd_cleanup);
-+
-+MODULE_AUTHOR("Clive Davies");
-+MODULE_DESCRIPTION("Altera epxa mtd flash map");
-+MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/mtd/maps/epxa10db-flash.c~2.4.25-vrs2.patch
-+++ linux-2.4.25/drivers/mtd/maps/epxa10db-flash.c
--/*
-- * Flash memory access on EPXA based devices
-- *
-- * (C) 2000 Nicolas Pitre <nico@cam.org>
-- * Copyright (C) 2001 Altera Corporation
-- * Copyright (C) 2001 Red Hat, Inc.
-- *
-- * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/kernel.h>
--#include <asm/io.h>
--#include <linux/mtd/mtd.h>
--#include <linux/mtd/map.h>
--#include <linux/mtd/partitions.h>
--
--#include <asm/hardware.h>
--#ifdef CONFIG_EPXA10DB
--#define BOARD_NAME "EPXA10DB"
--#else
--#define BOARD_NAME "EPXA1DB"
--#endif
--
--static int nr_parts = 0;
--static struct mtd_partition *parts;
--
--static struct mtd_info *mymtd;
--
--extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
--static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
--
--static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readb(map->map_priv_1 + ofs);
--}
--
--static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readw(map->map_priv_1 + ofs);
--}
--
--static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readl(map->map_priv_1 + ofs);
--}
--
--static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
--{
-- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
--}
--
--static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
--{
-- __raw_writeb(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
--{
-- __raw_writew(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
--{
-- __raw_writel(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
--{
-- memcpy_toio((void *)(map->map_priv_1 + to), from, len);
--}
--
--
--
--static struct map_info epxa_map = {
-- name: "EPXA flash",
-- size: FLASH_SIZE,
-- buswidth: 2,
-- read8: epxa_read8,
-- read16: epxa_read16,
-- read32: epxa_read32,
-- copy_from: epxa_copy_from,
-- write8: epxa_write8,
-- write16: epxa_write16,
-- write32: epxa_write32,
-- copy_to: epxa_copy_to
--};
--
--
--static int __init epxa_mtd_init(void)
--{
-- int i;
--
-- printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-- epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
-- if (!epxa_map.map_priv_1) {
-- printk("Failed to ioremap %s flash\n",BOARD_NAME);
-- return -EIO;
-- }
--
-- mymtd = do_map_probe("cfi_probe", &epxa_map);
-- if (!mymtd) {
-- iounmap((void *)epxa_map.map_priv_1);
-- return -ENXIO;
-- }
--
-- mymtd->module = THIS_MODULE;
--
-- /* Unlock the flash device. */
-- if(mymtd->unlock){
-- for (i=0; i<mymtd->numeraseregions;i++){
-- int j;
-- for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
-- mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
-- }
-- }
-- }
--
--#ifdef CONFIG_MTD_REDBOOT_PARTS
-- nr_parts = parse_redboot_partitions(mymtd, &parts);
--
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--#endif
--#ifdef CONFIG_MTD_AFS_PARTS
-- nr_parts = parse_afs_partitions(mymtd, &parts);
--
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--#endif
--
-- /* No recognised partitioning schemes found - use defaults */
-- nr_parts = epxa_default_partitions(mymtd, &parts);
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--
-- /* If all else fails... */
-- add_mtd_device(mymtd);
-- return 0;
--}
--
--static void __exit epxa_mtd_cleanup(void)
--{
-- if (mymtd) {
-- if (nr_parts)
-- del_mtd_partitions(mymtd);
-- else
-- del_mtd_device(mymtd);
-- map_destroy(mymtd);
-- }
-- if (epxa_map.map_priv_1) {
-- iounmap((void *)epxa_map.map_priv_1);
-- epxa_map.map_priv_1 = 0;
-- }
--}
--
--
--/*
-- * This will do for now, once we decide which bootldr we're finally
-- * going to use then we'll remove this function and do it properly
-- *
-- * Partions are currently (as offsets from base of flash):
-- * 0x00000000 - 0x003FFFFF - bootloader (!)
-- * 0x00400000 - 0x00FFFFFF - Flashdisk
-- */
--
--static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
--{
-- struct mtd_partition *parts;
-- int ret, i;
-- int npartitions = 0;
-- char *names;
-- const char *name = "jffs";
--
-- printk("Using default partitions for %s\n",BOARD_NAME);
-- npartitions=1;
-- parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
-- memzero(parts,npartitions*sizeof(*parts)+strlen(name));
-- if (!parts) {
-- ret = -ENOMEM;
-- goto out;
-- }
-- i=0;
-- names = (char *)&parts[npartitions];
-- parts[i].name = names;
-- names += strlen(name) + 1;
-- strcpy(parts[i].name, name);
--
--#ifdef CONFIG_EPXA10DB
-- parts[i].size = FLASH_SIZE-0x00400000;
-- parts[i].offset = 0x00400000;
--#else
-- parts[i].size = FLASH_SIZE-0x00180000;
-- parts[i].offset = 0x00180000;
--#endif
--
-- out:
-- *pparts = parts;
-- return npartitions;
--}
--
--
--module_init(epxa_mtd_init);
--module_exit(epxa_mtd_cleanup);
--
--MODULE_AUTHOR("Clive Davies");
--MODULE_DESCRIPTION("Altera epxa mtd flash map");
--MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/neponset-flash.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,109 @@
-+/*
-+ * Flash memory access on SA11x0 based devices
-+ *
-+ * (C) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * $Id: neponset-flash.c,v 1.18 2001/07/14 00:59:17 thockin Exp $
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/arch/assabet.h>
-+
-+static __u8 read8(struct map_info *map, unsigned long ofs)
-+{
-+ return readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 read16(struct map_info *map, unsigned long ofs)
-+{
-+ return readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 read32(struct map_info *map, unsigned long ofs)
-+{
-+ return readl(map->map_priv_1 + ofs);
-+}
-+
-+static void copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + from, len);
-+}
-+
-+static void write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ writeb(d, map->map_priv_1 + adr);
-+}
-+
-+static void write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ writew(d, map->map_priv_1 + adr);
-+}
-+
-+static void write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ writel(d, map->map_priv_1 + adr);
-+}
-+
-+static void copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy_toio(map->map_priv_1 + to, from, len);
-+}
-+
-+#define MAX_SZ (32 * 1024 * 1024)
-+
-+static struct map_info neponset_map = {
-+ name: "Neponset",
-+ size: MAX_SZ,
-+ buswidth: 4,
-+ read8: read8,
-+ read16: read16,
-+ read32: read32,
-+ copy_from: copy_from,
-+ write8: write8,
-+ write16: write16,
-+ write32: write32,
-+ copy_to: copy_to,
-+};
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static struct mtd_info *neponset_mtd;
-+
-+int __init neponset_mtd_init(void)
-+{
-+ if (!machine_is_assabet() || !machine_has_neponset())
-+ return -ENODEV;
-+
-+ neponset_map.map_priv_1 = (unsigned int)ioremap(0x08000000, MAX_SZ);
-+ if (!neponset_map.map_priv_1)
-+ return -ENOMEM;
-+
-+ neponset_mtd = do_map_probe("cfi_probe", &neponset_map);
-+ if (!neponset_mtd)
-+ return -ENXIO;
-+ neponset_mtd->module = THIS_MODULE;
-+ add_mtd_device(neponset_mtd);
-+ return 0;
-+}
-+
-+static void __exit neponset_mtd_cleanup(void)
-+{
-+ if (neponset_mtd)
-+ map_destroy(neponset_mtd);
-+ if (neponset_map.map_priv_1)
-+ iounmap((void *)neponset_map.map_priv_1);
-+}
-+
-+module_init(neponset_mtd_init);
-+module_exit(neponset_mtd_cleanup);
---- linux-2.4.25/drivers/mtd/maps/sa1100-flash.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/mtd/maps/sa1100-flash.c 2004-03-31 17:15:09.000000000 +0200
-@@ -97,6 +97,32 @@
- * entries. Thanks.
- */
-
-+#ifdef CONFIG_SA1100_ADSAGC
-+#define ADSAGC_FLASH_SIZE 0x02000000
-+static struct mtd_partition adsagc_partitions[] = {
-+ {
-+ name: "bootROM",
-+ size: 0x80000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "zImage",
-+ size: 0x100000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "ramdisk.gz",
-+ size: 0x300000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "User FS",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_ADSBITSY
- #define ADSBITSY_FLASH_SIZE 0x02000000
- static struct mtd_partition adsbitsy_partitions[] = {
-@@ -123,6 +149,32 @@
- };
- #endif
-
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+#define ADSBITSYPLUS_FLASH_SIZE 0x02000000
-+static struct mtd_partition adsbitsyplus_partitions[] = {
-+ {
-+ name: "bootROM",
-+ size: 0x80000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "zImage",
-+ size: 0x100000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "ramdisk.gz",
-+ size: 0x300000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "User FS",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_ASSABET
- /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
- #define ASSABET4_FLASH_SIZE 0x00400000
-@@ -438,7 +490,7 @@
- #endif
-
- #ifdef CONFIG_SA1100_GRAPHICSMASTER
--#define GRAPHICSMASTER_FLASH_SIZE 0x01000000
-+#define GRAPHICSMASTER_FLASH_SIZE 0x02000000
- static struct mtd_partition graphicsmaster_partitions[] = {
- {
- name: "zImage",
-@@ -507,6 +559,38 @@
- }
- #endif
-
-+#ifdef CONFIG_SA1100_HACKKIT
-+#define HACKKIT_FLASH_SIZE 0x01000000
-+static struct mtd_partition hackkit_partitions[] = {
-+ {
-+ name: "BLOB",
-+ size: 0x00040000,
-+ offset: 0x00000000,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "config",
-+ size: 0x00040000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "kernel",
-+ size: 0x00100000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "initrd",
-+ size: 0x00180000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "rootfs",
-+ size: 0x700000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "data",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- #define HUW_WEBPANEL_FLASH_SIZE 0x01000000
- static struct mtd_partition huw_webpanel_partitions[] = {
-@@ -555,12 +639,12 @@
- offset: 0x00540000,
- }, {
- name: "JORNADA720 usr local",
-- size: 0 /* will expand to the end of the flash */
-+ size: 0, /* will expand to the end of the flash */
- offset: 0x00d00000,
- }
- };
-
--static void jornada720_set_vpp(int vpp)
-+static void jornada720_set_vpp(struct map_info *map, int vpp)
- {
- if (vpp)
- PPSR |= 0x80;
-@@ -571,6 +655,27 @@
-
- #endif
-
-+#ifdef CONFIG_SA1100_NANOENGINE
-+/* nanoEngine has one 28F320B3B Flash part in bank 0: */
-+#define NANOENGINE_FLASH_SIZE 0x00400000
-+static struct mtd_partition nanoengine_partitions[] = {
-+ {
-+ name: "nanoEngine boot firmware and parameter table",
-+ size: 0x00010000, /* 32K */
-+ offset: 0x00000000,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ },{
-+ name: "kernel/initrd reserved",
-+ size: 0x002f0000,
-+ offset: 0x00010000,
-+ },{
-+ name: "experimental filesystem allocation",
-+ size: 0x00100000,
-+ offset: 0x00300000,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_PANGOLIN
- #define PANGOLIN_FLASH_SIZE 0x04000000
- static struct mtd_partition pangolin_partitions[] = {
-@@ -699,6 +804,32 @@
- };
- #endif /* CONFIG_SA1100_SIMPAD */
-
-+#ifdef CONFIG_SA1100_SIMPUTER
-+#define SIMPUTER_FLASH_SIZE 0x02000000
-+static struct mtd_partition simputer_partitions[] = {
-+ {
-+ name: "blob+logo",
-+ offset: 0,
-+ size: 0x00040000
-+ },
-+ {
-+ name: "kernel",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x000C0000
-+ },
-+ {
-+ name: "/(cramfs)",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00200000
-+ },
-+ {
-+ name: "/usr/local(jffs2)",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL /* expand till the end */
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_STORK
- #define STORK_FLASH_SIZE 0x02000000
- static struct mtd_partition stork_partitions[] = {
-@@ -766,7 +897,7 @@
- #endif
-
- extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
--extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
-
- static struct mtd_partition *parsed_parts;
- static struct mtd_info *mymtd;
-@@ -787,6 +918,14 @@
- */
- part_type = "static";
-
-+#ifdef CONFIG_SA1100_ADSAGC
-+ if (machine_is_adsagc()) {
-+ parts = adsagc_partitions;
-+ nb_parts = ARRAY_SIZE(adsagc_partitions);
-+ sa1100_map.size = ADSAGC_FLASH_SIZE;
-+ sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_ADSBITSY
- if (machine_is_adsbitsy()) {
- parts = adsbitsy_partitions;
-@@ -795,6 +934,14 @@
- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
- }
- #endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ parts = adsbitsyplus_partitions;
-+ nb_parts = ARRAY_SIZE(adsbitsyplus_partitions);
-+ sa1100_map.size = ADSBITSYPLUS_FLASH_SIZE;
-+ sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_ASSABET
- if (machine_is_assabet()) {
- parts = assabet_partitions;
-@@ -869,6 +1016,13 @@
- sa1100_map.set_vpp = h3600_set_vpp;
- }
- #endif
-+#ifdef CONFIG_SA1100_HACKKIT
-+ if (machine_is_hackkit()) {
-+ parts = hackkit_partitions;
-+ nb_parts = ARRAY_SIZE(hackkit_partitions);
-+ sa1100_map.size = HACKKIT_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- if (machine_is_huw_webpanel()) {
- parts = huw_webpanel_partitions;
-@@ -884,6 +1038,13 @@
- sa1100_map.set_vpp = jornada720_set_vpp;
- }
- #endif
-+#ifdef CONFIG_SA1100_NANOENGINE
-+ if (machine_is_nanoengine()) {
-+ parts = nanoengine_partitions;
-+ nb_parts = ARRAY_SIZE(nanoengine_partitions);
-+ sa1100_map.size = NANOENGINE_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_PANGOLIN
- if (machine_is_pangolin()) {
- parts = pangolin_partitions;
-@@ -919,6 +1080,13 @@
- sa1100_map.size = SIMPAD_FLASH_SIZE;
- }
- #endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ parts = simputer_partitions;
-+ nb_parts = ARRAY_SIZE(simputer_partitions);
-+ sa1100_map.size = SIMPUTER_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- parts = stork_partitions;
-@@ -953,7 +1121,9 @@
- * specific machine settings might have been set above.
- */
- printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
-- mymtd = do_map_probe("cfi_probe", &sa1100_map);
-+ mymtd = do_map_probe("jedec_probe", &sa1100_map);
-+ if (!mymtd)
-+ mymtd = do_map_probe("cfi_probe", &sa1100_map);
- ret = -ENXIO;
- if (!mymtd)
- goto out_err;
---- linux-2.4.25/drivers/net/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/net/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -30,9 +30,15 @@
- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
- source drivers/acorn/net/Config.in
- fi
-+ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate ' AT91RM9200 Ethernet support' CONFIG_AT91_ETHER
-+ if [ "$CONFIG_AT91_ETHER" = "y" -o "$CONFIG_AT91_ETHER" = "m" ]; then
-+ bool ' RMII interface? ' CONFIG_AT91_ETHER_RMII
-+ fi
-+ fi
- fi
- if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
-- tristate ' Altera Ether00 support' CONFIG_ETHER00
-+ tristate ' Altera Ether00 support' CONFIG_ETHER00
- fi
- if [ "$CONFIG_PPC" = "y" ]; then
- dep_tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE $CONFIG_ALL_PPC
---- linux-2.4.25/drivers/net/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/net/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -243,6 +243,7 @@
- # non-drivers/net drivers who want mii lib
- obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
- obj-$(CONFIG_USB_USBNET) += mii.o
-+obj-$(CONFIG_AT91_ETHER) += mii.o
-
- ifeq ($(CONFIG_ARCH_ACORN),y)
- mod-subdirs += ../acorn/net
-@@ -267,4 +268,3 @@
-
- rcpci.o: $(rcpci-objs)
- $(LD) -r -o $@ $(rcpci-objs)
--
---- linux-2.4.25/drivers/net/am79c961a.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/net/am79c961a.c 2004-03-31 17:15:09.000000000 +0200
-@@ -54,25 +54,36 @@
- #ifdef __arm__
- static void write_rreg(u_long base, u_int reg, u_int val)
- {
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- str%?h %0, [%2, #-4] @ NET_RDP
-- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "str%?h %0, [%2, #-4] @ NET_RDP"
-+ : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
- }
-
- static inline unsigned short read_rreg(u_long base_addr, u_int reg)
- {
- unsigned short v;
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- ldr%?h %0, [%2, #-4] @ NET_RDP
-- " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "ldr%?h %0, [%2, #-4] @ NET_RDP"
-+ : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
- return v;
- }
-
- static inline void write_ireg(u_long base, u_int reg, u_int val)
- {
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- str%?h %0, [%2, #8] @ NET_IDP
-- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "str%?h %0, [%2, #8] @ NET_IDP"
-+ : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+}
-+
-+static inline unsigned short read_ireg(u_long base_addr, u_int reg)
-+{
-+ u_short v;
-+ __asm__(
-+ "str%?h %1, [%2] @ NAT_RAP\n\t"
-+ "str%?h %0, [%2, #8] @ NET_IDP\n\t"
-+ : "=r" (v)
-+ : "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ return v;
- }
-
- #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
-@@ -91,16 +102,16 @@
- }
- while (length > 8) {
- unsigned int tmp, tmp2;
-- __asm__ __volatile__("
-- ldm%?ia %1!, {%2, %3}
-- str%?h %2, [%0], #4
-- mov%? %2, %2, lsr #16
-- str%?h %2, [%0], #4
-- str%?h %3, [%0], #4
-- mov%? %3, %3, lsr #16
-- str%?h %3, [%0], #4
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
-- : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldm%?ia %1!, {%2, %3}\n\t"
-+ "str%?h %2, [%0], #4\n\t"
-+ "mov%? %2, %2, lsr #16\n\t"
-+ "str%?h %2, [%0], #4\n\t"
-+ "str%?h %3, [%0], #4\n\t"
-+ "mov%? %3, %3, lsr #16\n\t"
-+ "str%?h %3, [%0], #4"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
-+ : "0" (offset), "1" (buf));
- length -= 8;
- }
- while (length > 0) {
-@@ -118,36 +129,36 @@
- length = (length + 1) & ~1;
- if ((int)buf & 2) {
- unsigned int tmp;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- str%?b %2, [%1], #1
-- mov%? %2, %2, lsr #8
-- str%?b %2, [%1], #1
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "str%?b %2, [%1], #1\n\t"
-+ "mov%? %2, %2, lsr #8\n\t"
-+ "str%?b %2, [%1], #1"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
- length -= 2;
- }
- while (length > 8) {
- unsigned int tmp, tmp2, tmp3;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- ldr%?h %3, [%0], #4
-- orr%? %2, %2, %3, lsl #16
-- ldr%?h %3, [%0], #4
-- ldr%?h %4, [%0], #4
-- orr%? %3, %3, %4, lsl #16
-- stm%?ia %1!, {%2, %3}
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
-- : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "ldr%?h %3, [%0], #4\n\t"
-+ "orr%? %2, %2, %3, lsl #16\n\t"
-+ "ldr%?h %3, [%0], #4\n\t"
-+ "ldr%?h %4, [%0], #4\n\t"
-+ "orr%? %3, %3, %4, lsl #16\n\t"
-+ "stm%?ia %1!, {%2, %3}"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
-+ : "0" (offset), "1" (buf));
- length -= 8;
- }
- while (length > 0) {
- unsigned int tmp;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- str%?b %2, [%1], #1
-- mov%? %2, %2, lsr #8
-- str%?b %2, [%1], #1
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "str%?b %2, [%1], #1\n\t"
-+ "mov%? %2, %2, lsr #8\n\t"
-+ "str%?b %2, [%1], #1"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
- length -= 2;
- }
- }
-@@ -254,9 +265,27 @@
- write_rreg (dev->base_addr, BASERXH, 0);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
-+ write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
- write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
- }
-
-+static void am79c961_timer(unsigned long data)
-+{
-+ struct net_device *dev = (struct net_device *)data;
-+ struct dev_priv *priv = (struct dev_priv *)dev->priv;
-+ unsigned int lnkstat, carrier;
-+
-+ lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
-+ carrier = netif_carrier_ok(dev);
-+
-+ if (lnkstat && !carrier)
-+ netif_carrier_on(dev);
-+ else if (!lnkstat && carrier)
-+ netif_carrier_off(dev);
-+
-+ mod_timer(&priv->timer, jiffies + 5*HZ);
-+}
-+
- /*
- * Open/initialize the board.
- */
-@@ -274,6 +303,11 @@
-
- am79c961_init_for_open(dev);
-
-+ netif_carrier_off(dev);
-+
-+ priv->timer.expires = jiffies;
-+ add_timer(&priv->timer);
-+
- netif_start_queue(dev);
-
- return 0;
-@@ -288,7 +322,10 @@
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
- unsigned long flags;
-
-+ del_timer_sync(&priv->timer);
-+
- netif_stop_queue(dev);
-+ netif_carrier_off(dev);
-
- spin_lock_irqsave(priv->chip_lock, flags);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-@@ -413,15 +450,6 @@
- unsigned int hdraddr, bufaddr;
- unsigned int head;
- unsigned long flags;
--
-- /* FIXME: I thought the 79c961 could do padding - RMK ??? */
-- if(length < ETH_ZLEN)
-- {
-- skb = skb_padto(skb, ETH_ZLEN);
-- if(skb == NULL)
-- return 0;
-- length = ETH_ZLEN;
-- }
-
- head = priv->txhead;
- hdraddr = priv->txhdr + (head << 3);
-@@ -431,7 +459,7 @@
- head = 0;
-
- am_writebuffer (dev, bufaddr, skb->data, length);
-- am_writeword (dev, hdraddr + 4, -length);
-+ am_writeword (dev, hdraddr + 4, -skb->len);
- am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
- priv->txhead = head;
-
-@@ -448,6 +476,8 @@
- if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
- netif_stop_queue(dev);
-
-+ priv->stats.tx_bytes += skb->len;
-+
- dev_kfree_skb(skb);
-
- return 0;
-@@ -520,6 +550,7 @@
- am79c961_tx(struct net_device *dev, struct dev_priv *priv)
- {
- do {
-+ signed short len;
- u_int hdraddr;
- u_int status;
-
-@@ -555,6 +586,8 @@
- continue;
- }
- priv->stats.tx_packets ++;
-+ len = am_readword (dev, hdraddr + 4);
-+ priv->stats.tx_bytes += -len;
- } while (priv->txtail != priv->txhead);
-
- netif_wake_queue(dev);
-@@ -565,17 +598,23 @@
- {
- struct net_device *dev = (struct net_device *)dev_id;
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
-- u_int status;
-+ u_int status, n = 100;
-
-- status = read_rreg(dev->base_addr, CSR0);
-- write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
-+ do {
-+ status = read_rreg(dev->base_addr, CSR0);
-+ write_rreg(dev->base_addr, CSR0, status &
-+ (CSR0_IENA|CSR0_TINT|CSR0_RINT|
-+ CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
-
-- if (status & CSR0_RINT)
-- am79c961_rx(dev, priv);
-- if (status & CSR0_TINT)
-- am79c961_tx(dev, priv);
-- if (status & CSR0_MISS)
-- priv->stats.rx_dropped ++;
-+ if (status & CSR0_RINT)
-+ am79c961_rx(dev, priv);
-+ if (status & CSR0_TINT)
-+ am79c961_tx(dev, priv);
-+ if (status & CSR0_MISS)
-+ priv->stats.rx_dropped ++;
-+ if (status & CSR0_CERR)
-+ mod_timer(&priv->timer, jiffies);
-+ } while (--n && status & (CSR0_RINT | CSR0_TINT));
- }
-
- /*
-@@ -587,10 +626,10 @@
- {
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
-
-- spin_lock_irq(priv->chip_lock);
-+ spin_lock_irq(&priv->chip_lock);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
-- spin_unlock_irq(priv->chip_lock);
-+ spin_unlock_irq(&priv->chip_lock);
-
- am79c961_ramtest(dev, 0x66);
- am79c961_ramtest(dev, 0x99);
-@@ -655,6 +694,11 @@
- printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
- }
-
-+ spin_lock_init(&priv->chip_lock);
-+ init_timer(&priv->timer);
-+ priv->timer.data = (unsigned long)dev;
-+ priv->timer.function = am79c961_timer;
-+
- if (am79c961_hw_init(dev))
- goto release;
-
---- linux-2.4.25/drivers/net/am79c961a.h~2.4.25-vrs2.patch 2000-09-19 00:15:22.000000000 +0200
-+++ linux-2.4.25/drivers/net/am79c961a.h 2004-03-31 17:15:09.000000000 +0200
-@@ -58,6 +58,18 @@
- #define CSR3_BABLM 0x4000
- #define CSR3_MASKALL 0x5F00
-
-+#define CSR4 4
-+#define CSR4_JABM 0x0001
-+#define CSR4_JAB 0x0002
-+#define CSR4_TXSTRTM 0x0004
-+#define CSR4_TXSTRT 0x0008
-+#define CSR4_RCVCCOM 0x0010
-+#define CSR4_RCVCCO 0x0020
-+#define CSR4_MFCOM 0x0100
-+#define CSR4_MFCO 0x0200
-+#define CSR4_ASTRP_RCV 0x0400
-+#define CSR4_APAD_XMIT 0x0800
-+
- #define CTRL1 5
- #define CTRL1_SPND 0x0001
-
-@@ -93,6 +105,8 @@
- #define SIZERXR 76
- #define SIZETXR 78
-
-+#define CSR_MFC 112
-+
- #define RMD_ENP 0x0100
- #define RMD_STP 0x0200
- #define RMD_CRC 0x0800
-@@ -112,6 +126,9 @@
- #define TST_UFLO 0x4000
- #define TST_BUFF 0x8000
-
-+#define ISALED0 0x0004
-+#define ISALED0_LNKST 0x8000
-+
- struct dev_priv {
- struct net_device_stats stats;
- unsigned long rxbuffer[RX_BUFFERS];
-@@ -123,6 +140,7 @@
- unsigned long rxhdr;
- unsigned long txhdr;
- spinlock_t chip_lock;
-+ struct timer_list timer;
- };
-
- extern int am79c961_probe (struct net_device *dev);
---- linux-2.4.25/drivers/net/cirrus.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/net/cirrus.c 2004-03-31 17:15:09.000000000 +0200
-@@ -75,6 +75,7 @@
- typedef struct {
- struct net_device_stats stats;
- u16 txlen;
-+ u16 txafter; /* Default is After5 (0) */
- } cirrus_t;
-
- typedef struct {
-@@ -230,13 +231,19 @@
- cirrus_t *priv = (cirrus_t *) dev->priv;
- u16 status;
-
-+ /* Tx start must be done with irq disabled
-+ * else status can be wrong */
-+ disable_irq (dev->irq);
-+
- netif_stop_queue (dev);
-
-- cirrus_write (dev,PP_TxCMD,TxStart (After5));
-+ cirrus_write (dev,PP_TxCMD,TxStart (priv->txafter));
- cirrus_write (dev,PP_TxLength,skb->len);
-
- status = cirrus_read (dev,PP_BusST);
-
-+ enable_irq (dev->irq);
-+
- if ((status & TxBidErr)) {
- printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
- priv->stats.tx_errors++;
-@@ -249,7 +256,6 @@
- printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
- priv->stats.tx_errors++;
- priv->txlen = 0;
-- /* FIXME: store skb and send it in interrupt handler */
- return (1);
- }
-
-@@ -310,11 +316,18 @@
- }
- if ((RegContent (status) & TxUnderrun)) {
- priv->stats.tx_errors++;
-- priv->stats.tx_fifo_errors++;
-+ /* Shift start tx, if underruns come too often */
-+ switch (priv->stats.tx_fifo_errors++) {
-+ case 3: priv->txafter = After381; break;
-+ case 6: priv->txafter = After1021; break;
-+ case 9: priv->txafter = AfterAll; break;
-+ }
-+ }
-+ /* Wakeup only for tx events ! */
-+ if ((RegContent (status) & (TxUnderrun | Rdy4Tx))) {
-+ priv->txlen = 0;
-+ netif_wake_queue (dev);
- }
-- /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
-- priv->txlen = 0;
-- netif_wake_queue (dev);
- break;
-
- case TxCOL:
-@@ -428,7 +441,7 @@
- else
- cirrus_clear (dev,PP_RxCTL,PromiscuousA);
-
-- if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
-+ if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
- cirrus_set (dev,PP_RxCTL,MulticastA);
- else
- cirrus_clear (dev,PP_RxCTL,MulticastA);
---- linux-2.4.25/drivers/net/cs89x0.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/net/cs89x0.c 2004-03-31 17:15:09.000000000 +0200
-@@ -115,6 +115,7 @@
-
- */
-
-+#include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/types.h>
-@@ -427,18 +428,18 @@
- /* if they give us an odd I/O address, then do ONE write to
- the address port, to get it back to address zero, where we
- expect to find the EISA signature word. An IO with a base of 0x3
-- will skip the test for the ADD_PORT. */
-+ will skip the test for the ADD_PORT. */
- if (ioaddr & 1) {
- if (net_debug > 1)
- printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
-- if ((ioaddr & 2) != 2)
-+ if ((ioaddr & 2) != 2)
- if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
- printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, inw((ioaddr & ~3)+ ADD_PORT));
- retval = -ENODEV;
- goto out2;
- }
-- ioaddr &= ~3;
-+ ioaddr &= ~3;
- outw(PP_ChipID, ioaddr + ADD_PORT);
- }
- printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
-@@ -446,7 +447,7 @@
- if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
- printk(KERN_ERR "%s: incorrect signature 0x%x\n",
- dev->name, inw(ioaddr + DATA_PORT));
-- retval = -ENODEV;
-+ retval = -ENODEV;
- goto out2;
- }
-
-@@ -477,7 +478,7 @@
- dev->base_addr);
-
- reset_chip(dev);
--
-+
- /* Here we read the current configuration of the chip. If there
- is no Extended EEPROM then the idea is to not disturb the chip
- configuration, it should have been correctly setup by automatic
---- linux-2.4.25/drivers/net/ether00.c~2.4.25-vrs2.patch 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.25/drivers/net/ether00.c 2004-03-31 17:15:09.000000000 +0200
-@@ -38,6 +38,7 @@
- #include <asm/arch/ether00.h>
- #include <asm/arch/tdkphy.h>
-
-+static int ether00_get_ethernet_address(struct net_device* dev);
-
- MODULE_AUTHOR("Clive Davies");
- MODULE_DESCRIPTION("Altera Ether00 IP core driver");
-@@ -734,8 +735,11 @@
- int result,tmp;
- struct net_priv* priv;
-
-- if (!is_valid_ether_addr(dev->dev_addr))
-- return -EINVAL;
-+ if (!ether00_get_ethernet_address(dev)){
-+ printk("%s: Invalid ethernet MAC address. Please set using "
-+ "ifconfig\n", dev->name);
-+ return -EINVAL;
-+ }
-
- dev->base_addr=(unsigned int)ioremap_nocache(base,SZ_4K);
-
-@@ -906,10 +910,9 @@
- }
-
-
--static void ether00_get_ethernet_address(struct net_device* dev)
-+static int ether00_get_ethernet_address(struct net_device* dev)
- {
- struct mtd_info *mymtd=NULL;
-- int i;
- size_t retlen;
-
- /*
-@@ -926,11 +929,7 @@
- #ifdef CONFIG_ARCH_CAMELOT
- #ifdef CONFIG_MTD
- /* get the mtd_info structure for the first mtd device*/
-- for(i=0;i<MAX_MTD_DEVICES;i++){
-- mymtd=get_mtd_device(NULL,i);
-- if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
-- break;
-- }
-+ mymtd=get_mtd_device(NULL,0);
-
- if(!mymtd || !mymtd->read_user_prot_reg){
- printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
-@@ -947,9 +946,7 @@
- #endif
- #endif
-
-- if (!is_valid_ether_addr(dev->dev_addr))
-- printk("%s: Invalid ethernet MAC address. Please set using "
-- "ifconfig\n", dev->name);
-+ return (is_valid_ether_addr(dev->dev_addr));
-
- }
-
-@@ -966,8 +963,6 @@
- dev->tx_timeout=ether00_tx_timeout;
- dev->watchdog_timeo=TX_TIMEOUT;
-
-- ether00_get_ethernet_address(dev);
--
- SET_MODULE_OWNER(dev);
- return 0;
- }
---- linux-2.4.25/drivers/net/irda/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/net/irda/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -40,7 +40,7 @@
- dep_tristate 'VIA IrCC (Experimental)' CONFIG_VIA_IRCC_FIR $CONFIG_IRDA
- fi
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA
-+ dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
- fi
-
- endmenu
---- linux-2.4.25/drivers/net/irda/sa1100_ir.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/net/irda/sa1100_ir.c 2004-03-31 17:15:09.000000000 +0200
-@@ -38,11 +38,7 @@
-
- #include <asm/arch/assabet.h>
-
--#ifndef CONFIG_SA1100_H3600
--#define clr_h3600_egpio(x) do { } while (0)
--#define set_h3600_egpio(x) do { } while (0)
--#endif
--
-+/* Yopy wants fixing */
- #ifndef GPIO_IRDA_FIR
- #define GPIO_IRDA_FIR (0)
- #endif
-@@ -174,8 +170,8 @@
-
- if (machine_is_assabet())
- ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
-- if (machine_is_h3600())
-- clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
-+ if (machine_is_h3xxx())
-+ clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
- if (machine_is_yopy())
- PPSR &= ~GPIO_IRDA_FIR;
-
-@@ -199,8 +195,8 @@
-
- if (machine_is_assabet())
- ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
-- if (machine_is_h3600())
-- set_h3600_egpio(EGPIO_H3600_IR_FSEL);
-+ if (machine_is_h3xxx())
-+ set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
- if (machine_is_yopy())
- PPSR |= GPIO_IRDA_FIR;
-
-@@ -246,10 +242,7 @@
- static inline int
- sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state)
- {
-- if (state)
-- set_h3600_egpio(EGPIO_H3600_IR_ON);
-- else
-- clr_h3600_egpio(EGPIO_H3600_IR_ON);
-+ assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
- return 0;
- }
-
-@@ -283,7 +276,7 @@
-
- if (machine_is_assabet())
- ret = sa1100_irda_set_power_assabet(si, state);
-- if (machine_is_h3600())
-+ if (machine_is_h3xxx())
- ret = sa1100_irda_set_power_h3600(si, state);
- if (machine_is_yopy())
- ret = sa1100_irda_set_power_yopy(si, state);
-@@ -727,11 +720,6 @@
- netif_wake_queue(dev);
- }
-
--/*
-- * Note that we will never build up a backlog of frames; the protocol is a
-- * half duplex protocol which basically means we transmit a frame, we
-- * receive a frame, we transmit the next frame etc.
-- */
- static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- struct sa1100_irda *si = dev->priv;
-@@ -758,6 +746,8 @@
- }
-
- if (!IS_FIR(si)) {
-+ netif_stop_queue(dev);
-+
- si->tx_buff.data = si->tx_buff.head;
- si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
- si->tx_buff.truesize);
---- linux-2.4.25/drivers/net/irda/w83977af_ir.c~2.4.25-vrs2.patch 2002-11-29 00:53:13.000000000 +0100
-+++ linux-2.4.25/drivers/net/irda/w83977af_ir.c 2004-03-31 17:15:09.000000000 +0200
-@@ -205,7 +205,7 @@
-
- /* FIXME: The HP HDLS-1100 does not support 1152000! */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-- IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-+ IR_115200/*|IR_576000|IR_1152000|(IR_4000000 << 8)*/;
-
- /* The HP HDLS-1100 needs 1 ms according to the specs */
- self->qos.min_turn_time.bits = qos_mtt_bits;
-@@ -1341,7 +1341,7 @@
- case SIOCSBANDWIDTH: /* Set bandwidth */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
-- goto out;
-+ break;
- }
- w83977af_change_speed(self, irq->ifr_baudrate);
- break;
---- linux-2.4.25/drivers/net/smc9194.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
-+++ linux-2.4.25/drivers/net/smc9194.c 2004-03-31 17:15:09.000000000 +0200
-@@ -12,8 +12,8 @@
- . AUI/TP selection ( mine has 10Base2/10BaseT select )
- .
- . Arguments:
-- . io = for the base address
-- . irq = for the IRQ
-+ . io = for the base address
-+ . irq = for the IRQ
- . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 )
- .
- . author:
-@@ -51,12 +51,21 @@
- . allocation
- . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
- . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
-+ . 06/23/01 Russell King Separate out IO functions for different bus
-+ . types.
-+ . Use dev->name instead of CARDNAME for printk
-+ . Add ethtool support, full duplex support
-+ . Add LAN91C96 support.
- . 11/08/01 Matt Domsch Use common crc32 function
- ----------------------------------------------------------------------------*/
-
-+#define DRV_NAME "smc9194"
-+#define DRV_VERSION "0.15"
-+
- static const char version[] =
-- "smc9194.c:v0.14 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
-+ DRV_NAME ".c:v" DRV_VERSION " 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
-
-+#include <linux/config.h>
- #include <linux/module.h>
- #include <linux/version.h>
- #include <linux/kernel.h>
-@@ -69,16 +78,26 @@
- #include <linux/in.h>
- #include <linux/slab.h>
- #include <linux/string.h>
-+#include <linux/delay.h>
- #include <linux/init.h>
- #include <linux/crc32.h>
--#include <asm/bitops.h>
--#include <asm/io.h>
- #include <linux/errno.h>
-+#include <linux/ethtool.h>
-
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
-
-+#include <asm/bitops.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/hardware.h>
-+#include <asm/arch/assabet.h>
-+#endif
-+
- #include "smc9194.h"
- /*------------------------------------------------------------------------
- .
-@@ -152,29 +171,27 @@
- -------------------------------------------------------------------------*/
- #define CARDNAME "SMC9194"
-
-+static const char *chip_ids[15] = {
-+ NULL,
-+ NULL,
-+ NULL,
-+ "SMC91C90/91C92", /* 3 */
-+ "SMC91C94/91C96", /* 4 */
-+ "SMC91C95", /* 5 */
-+ NULL,
-+ "SMC91C100", /* 7 */
-+ "SMC91C100FD", /* 8 */
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL
-+};
-
--/* store this information for the driver.. */
--struct smc_local {
-- /*
-- these are things that the kernel wants me to keep, so users
-- can find out semi-useless statistics of how well the card is
-- performing
-- */
-- struct net_device_stats stats;
--
-- /*
-- If I have to wait until memory is available to send
-- a packet, I will store the skbuff here, until I get the
-- desired memory. Then, I'll send it out and free it.
-- */
-- struct sk_buff * saved_skb;
--
-- /*
-- . This keeps track of how many packets that I have
-- . sent out. When an TX_EMPTY interrupt comes, I know
-- . that all of these have been sent.
-- */
-- int packets_waiting;
-+static const char * interfaces[2] = {
-+ "TP",
-+ "AUI"
- };
-
-
-@@ -202,6 +219,11 @@
- static int smc_open(struct net_device *dev);
-
- /*
-+ . This handles the ethtool interface
-+*/
-+static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-+
-+/*
- . Our watchdog timed out. Called by the networking layer
- */
- static void smc_timeout(struct net_device *dev);
-@@ -217,11 +239,11 @@
- . This routine allows the proc file system to query the driver's
- . statistics.
- */
--static struct net_device_stats * smc_query_statistics( struct net_device *dev);
-+static struct net_device_stats * smc_query_statistics(struct net_device *dev);
-
- /*
-- . Finally, a call to set promiscuous mode ( for TCPDUMP and related
-- . programs ) and multicast modes.
-+ . Finally, a call to set promiscuous mode (for TCPDUMP and related
-+ . programs) and multicast modes.
- */
- static void smc_set_multicast_list(struct net_device *dev);
-
-@@ -240,12 +262,12 @@
- . This is a separate procedure to handle the receipt of a packet, to
- . leave the interrupt code looking slightly cleaner
- */
--static inline void smc_rcv( struct net_device *dev );
-+static inline void smc_rcv(struct net_device *dev);
- /*
- . This handles a TX interrupt, which is only called when an error
- . relating to a packet is sent.
- */
--static inline void smc_tx( struct net_device * dev );
-+static inline void smc_tx(struct net_device * dev);
-
- /*
- ------------------------------------------------------------
-@@ -261,39 +283,287 @@
- */
- static int smc_probe(struct net_device *dev, int ioaddr);
-
--/*
-- . A rather simple routine to print out a packet for debugging purposes.
--*/
--#if SMC_DEBUG > 2
--static void print_packet( byte *, int );
--#endif
--
--#define tx_done(dev) 1
--
- /* this is called to actually send the packet to the chip */
--static void smc_hardware_send_packet( struct net_device * dev );
-+static void smc_hardware_send_packet(struct net_device * dev);
-
- /* Since I am not sure if I will have enough room in the chip's ram
- . to store the packet, I call this routine, which either sends it
- . now, or generates an interrupt when the card is ready for the
- . packet */
--static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
-+static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *dev);
-
- /* this does a soft reset on the device */
--static void smc_reset( int ioaddr );
-+static void smc_reset(struct net_device *dev);
-
- /* Enable Interrupts, Receive, and Transmit */
--static void smc_enable( int ioaddr );
-+static void smc_enable(struct net_device *dev);
-
- /* this puts the device in an inactive state */
--static void smc_shutdown( int ioaddr );
-+static void smc_shutdown(struct net_device *dev);
-
- /* This routine will find the IRQ of the driver if one is not
- . specified in the input to the device. */
--static int smc_findirq( int ioaddr );
-+static int smc_findirq(struct net_device *dev);
-
-+#ifndef CONFIG_ASSABET_NEPONSET
- /*
-- . Function: smc_reset( int ioaddr )
-+ * These functions allow us to handle IO addressing as we wish - this
-+ * ethernet controller can be connected to a variety of busses. Some
-+ * busses do not support 16 bit or 32 bit transfers. --rmk
-+ */
-+static inline u8 smc_inb(u_int base, u_int reg)
-+{
-+ return inb(base + reg);
-+}
-+
-+static inline u16 smc_inw(u_int base, u_int reg)
-+{
-+ return inw(base + reg);
-+}
-+
-+static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ /* QUESTION: Like in the TX routine, do I want
-+ to send the DWORDs or the bytes first, or some
-+ mixture. A mixture might improve already slow PIO
-+ performance */
-+ PRINTK3((" Reading %d dwords (and %d bytes) \n",
-+ len >> 2, len & 3));
-+ insl(port, data, len >> 2);
-+ /* read the left over bytes */
-+ insb(port, data + (len & ~3), len & 3);
-+#else
-+ PRINTK3((" Reading %d words and %d byte(s) \n",
-+ len >> 1, len & 1));
-+ insw(port, data, len >> 1);
-+ if (len & 1) {
-+ data += len & ~1;
-+ *data = inb(port);
-+ }
-+#endif
-+}
-+
-+static inline void smc_outb(u8 val, u_int base, u_int reg)
-+{
-+ outb(val, base + reg);
-+}
-+
-+static inline void smc_outw(u16 val, u_int base, u_int reg)
-+{
-+ outw(val, base + reg);
-+}
-+
-+static inline void smc_outl(u32 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ outl(val, port);
-+#else
-+ outw(val, port);
-+ outw(val >> 16, port);
-+#endif
-+}
-+
-+static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ if (len & 2) {
-+ outsl(port, data, len >> 2);
-+ outw(*((word *)(data + (len & ~3))), port);
-+ }
-+ else
-+ outsl(port, data, len >> 2);
-+#else
-+ outsw(port, data, len >> 1);
-+#endif
-+}
-+
-+
-+/*-------------------------------------------------------------------------
-+ . I define some macros to make it easier to do somewhat common
-+ . or slightly complicated, repeated tasks.
-+ --------------------------------------------------------------------------*/
-+
-+/* select a register bank, 0 to 3 */
-+
-+#define SMC_SELECT_BANK(x) \
-+ { \
-+ smc_outw(x, ioaddr, BANK_SELECT); \
-+ }
-+
-+/* define a small delay for the reset */
-+#define SMC_DELAY() \
-+ { \
-+ smc_inw(ioaddr, RCR); \
-+ smc_inw(ioaddr, RCR); \
-+ smc_inw(ioaddr, RCR); \
-+ }
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) \
-+ { \
-+ byte mask; \
-+ mask = smc_inb(ioaddr, INT_MASK); \
-+ mask |= (x); \
-+ smc_outb(mask, ioaddr, INT_MASK); \
-+ }
-+
-+/* this sets the absolutel interrupt mask */
-+#define SMC_SET_INT(x) \
-+ { \
-+ smc_outw((x), INT_MASK); \
-+ }
-+
-+#else
-+
-+#undef SMC_IO_EXTENT
-+#define SMC_IO_EXTENT (16 << 2)
-+
-+/*
-+ * These functions allow us to handle IO addressing as we wish - this
-+ * ethernet controller can be connected to a variety of busses. Some
-+ * busses do not support 16 bit or 32 bit transfers. --rmk
-+ */
-+static inline u8 smc_inb(u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ return readb(port);
-+}
-+
-+static inline u16 smc_inw(u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ return readb(port) | readb(port + 4) << 8;
-+}
-+
-+static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg * 4;
-+
-+ insb(port, data, len);
-+}
-+
-+static inline void smc_outb(u8 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+}
-+
-+static inline void smc_outw(u16 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+ writeb(val >> 8, port + 4);
-+}
-+
-+static inline void smc_outl(u32 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+ writeb(val >> 8, port + 4);
-+ writeb(val >> 16, port + 8);
-+ writeb(val >> 24, port + 12);
-+}
-+
-+static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg * 4;
-+
-+ outsb(port, data, len & ~1);
-+}
-+
-+/*-------------------------------------------------------------------------
-+ . I define some macros to make it easier to do somewhat common
-+ . or slightly complicated, repeated tasks.
-+ --------------------------------------------------------------------------*/
-+
-+/* select a register bank, 0 to 3 */
-+
-+#define SMC_SELECT_BANK(x) \
-+ { \
-+ smc_outb(x, ioaddr, BANK_SELECT); \
-+ }
-+
-+/* define a small delay for the reset */
-+#define SMC_DELAY() \
-+ { \
-+ smc_inb(ioaddr, RCR); \
-+ smc_inb(ioaddr, RCR); \
-+ smc_inb(ioaddr, RCR); \
-+ }
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) \
-+ { \
-+ byte mask; \
-+ mask = smc_inb(ioaddr, INT_MASK); \
-+ mask |= (x); \
-+ smc_outb(mask, ioaddr, INT_MASK); \
-+ }
-+
-+/* this sets the absolutel interrupt mask */
-+#define SMC_SET_INT(x) \
-+ { \
-+ smc_outb((x), ioaddr, INT_MASK); \
-+ }
-+
-+#endif
-+
-+/*
-+ . A rather simple routine to print out a packet for debugging purposes.
-+*/
-+#if SMC_DEBUG > 2
-+static void print_packet(byte * buf, int length)
-+{
-+ int i;
-+ int remainder;
-+ int lines;
-+
-+ printk("Packet of length %d \n", length);
-+ lines = length / 16;
-+ remainder = length % 16;
-+
-+ for (i = 0; i < lines ; i ++) {
-+ int cur;
-+
-+ for (cur = 0; cur < 8; cur ++) {
-+ byte a, b;
-+
-+ a = *(buf ++);
-+ b = *(buf ++);
-+ printk("%02x%02x ", a, b);
-+ }
-+ printk("\n");
-+ }
-+ for (i = 0; i < remainder/2 ; i++) {
-+ byte a, b;
-+
-+ a = *(buf ++);
-+ b = *(buf ++);
-+ printk("%02x%02x ", a, b);
-+ }
-+ if (remainder & 1) {
-+ byte a;
-+
-+ a = *buf++;
-+ printk("%02x", a);
-+ }
-+ printk("\n");
-+}
-+#else
-+#define print_packet(buf,len) do { } while (0)
-+#endif
-+
-+/*
-+ . Function: smc_reset(struct net_device *dev)
- . Purpose:
- . This sets the SMC91xx chip to its normal state, hopefully from whatever
- . mess that any other DOS driver has put it in.
-@@ -309,36 +579,37 @@
- . 5. clear all interrupts
- .
- */
--static void smc_reset( int ioaddr )
-+static void smc_reset(struct net_device *dev)
- {
-+ u_int ioaddr = dev->base_addr;
-+
- /* This resets the registers mostly to defaults, but doesn't
- affect EEPROM. That seems unnecessary */
-- SMC_SELECT_BANK( 0 );
-- outw( RCR_SOFTRESET, ioaddr + RCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outw(RCR_SOFTRESET, ioaddr, RCR);
-
- /* this should pause enough for the chip to be happy */
-- SMC_DELAY( );
-+ SMC_DELAY();
-
- /* Set the transmit and receive configuration registers to
- default values */
-- outw( RCR_CLEAR, ioaddr + RCR );
-- outw( TCR_CLEAR, ioaddr + TCR );
-+ smc_outw(RCR_CLEAR, ioaddr, RCR);
-+ smc_outw(TCR_CLEAR, ioaddr, TCR);
-
- /* set the control register to automatically
- release successfully transmitted packets, to make the best
- use out of our limited memory */
-- SMC_SELECT_BANK( 1 );
-- outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL );
-+ SMC_SELECT_BANK(1);
-+ smc_outw(smc_inw(ioaddr, CONTROL) | CTL_AUTO_RELEASE, ioaddr, CONTROL);
-
- /* Reset the MMU */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_RESET, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_RESET, ioaddr, MMU_CMD);
-
- /* Note: It doesn't seem that waiting for the MMU busy is needed here,
- but this is a place where future chipsets _COULD_ break. Be wary
- of issuing another MMU command right after this */
--
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
- }
-
- /*
-@@ -349,20 +620,21 @@
- . 2. Enable the receiver
- . 3. Enable interrupts
- */
--static void smc_enable( int ioaddr )
-+static void smc_enable(struct net_device *dev)
- {
-- SMC_SELECT_BANK( 0 );
-+ u_int ioaddr = dev->base_addr;
-+ SMC_SELECT_BANK(0);
- /* see the header file for options in TCR/RCR NORMAL*/
-- outw( TCR_NORMAL, ioaddr + TCR );
-- outw( RCR_NORMAL, ioaddr + RCR );
-+ smc_outw(TCR_NORMAL, ioaddr, TCR);
-+ smc_outw(RCR_NORMAL, ioaddr, RCR);
-
- /* now, enable interrupts */
-- SMC_SELECT_BANK( 2 );
-- outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(SMC_INTERRUPT_MASK);
- }
-
- /*
-- . Function: smc_shutdown
-+ . Function: smc_shutdown(struct net_device *dev)
- . Purpose: closes down the SMC91xxx chip.
- . Method:
- . 1. zero the interrupt mask
-@@ -375,26 +647,28 @@
- . the manual says that it will wake up in response to any I/O requests
- . in the register space. Empirical results do not show this working.
- */
--static void smc_shutdown( int ioaddr )
-+static void smc_shutdown(struct net_device *dev)
- {
-+ u_int ioaddr = dev->base_addr;
-+
- /* no more interrupts for me */
-- SMC_SELECT_BANK( 2 );
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(0);
-
- /* and tell the card to stay away from that nasty outside world */
-- SMC_SELECT_BANK( 0 );
-- outb( RCR_CLEAR, ioaddr + RCR );
-- outb( TCR_CLEAR, ioaddr + TCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outb(RCR_CLEAR, ioaddr, RCR);
-+ smc_outb(TCR_CLEAR, ioaddr, TCR);
- #if 0
- /* finally, shut the chip down */
-- SMC_SELECT_BANK( 1 );
-- outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL );
-+ SMC_SELECT_BANK(1);
-+ smc_outw(smc_inw(ioaddr, CONTROL), CTL_POWERDOWN, ioaddr, CONTROL);
- #endif
- }
-
-
- /*
-- . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
-+ . Function: smc_setmulticast(int ioaddr, int count, dev_mc_list * adds)
- . Purpose:
- . This sets the internal hardware table to filter out unwanted multicast
- . packets before they take up memory.
-@@ -411,26 +685,28 @@
- */
-
-
--static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) {
-+static void smc_setmulticast(struct net_device *dev, int count, struct dev_mc_list * addrs)
-+{
-+ u_int ioaddr = dev->base_addr;
- int i;
-- unsigned char multicast_table[ 8 ];
-+ unsigned char multicast_table[8];
- struct dev_mc_list * cur_addr;
- /* table for flipping the order of 3 bits */
- unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
-
- /* start with a table of all zeros: reject all */
-- memset( multicast_table, 0, sizeof( multicast_table ) );
-+ memset(multicast_table, 0, sizeof(multicast_table));
-
- cur_addr = addrs;
-- for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
-+ for (i = 0; i < count ; i ++, cur_addr = cur_addr->next) {
- int position;
-
- /* do we have a pointer here? */
-- if ( !cur_addr )
-+ if (!cur_addr)
- break;
- /* make sure this is a multicast address - shouldn't this
- be a given if we have it here ? */
-- if ( !( *cur_addr->dmi_addr & 1 ) )
-+ if (!(*cur_addr->dmi_addr & 1))
- continue;
-
- /* only use the low order bits */
-@@ -442,15 +718,15 @@
-
- }
- /* now, the table can be loaded into the chipset */
-- SMC_SELECT_BANK( 3 );
-+ SMC_SELECT_BANK(3);
-
-- for ( i = 0; i < 8 ; i++ ) {
-- outb( multicast_table[i], ioaddr + MULTICAST1 + i );
-+ for (i = 0; i < 8 ; i++) {
-+ smc_outb(multicast_table[i], ioaddr, MULTICAST1 + i);
- }
- }
-
- /*
-- . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
-+ . Function: smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *)
- . Purpose:
- . Attempt to allocate memory for a packet, if chip-memory is not
- . available, then tell the card to generate an interrupt when it
-@@ -465,10 +741,10 @@
- . o (NO): Enable interrupts and let the interrupt handler deal with it.
- . o (YES):Send it now.
- */
--static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
-+static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- unsigned short ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- word length;
- unsigned short numPages;
- word time_out;
-@@ -477,15 +753,16 @@
- /* Well, I want to send the packet.. but I don't know
- if I can send it right now... */
-
-- if ( lp->saved_skb) {
-+ if (lp->saved_skb) {
- /* THIS SHOULD NEVER HAPPEN. */
- lp->stats.tx_aborted_errors++;
-- printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
-+ printk("%s: Bad Craziness - sent packet while busy.\n",
-+ dev->name);
- return 1;
- }
-
- length = skb->len;
--
-+
- if(length < ETH_ZLEN)
- {
- skb = skb_padto(skb, ETH_ZLEN);
-@@ -497,18 +774,18 @@
- length = ETH_ZLEN;
- }
- lp->saved_skb = skb;
--
-+
- /*
- ** The MMU wants the number of pages to be the number of 256 bytes
-- ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
-+ ** 'pages', minus 1 (since a packet can't ever have 0 pages :))
- **
- ** Pkt size for allocating is data length +6 (for additional status words,
- ** length and ctl!) If odd size last byte is included in this header.
- */
-- numPages = ((length & 0xfffe) + 6) / 256;
-+ numPages = ((length & 0xfffe) + 6) / 256;
-
-- if (numPages > 7 ) {
-- printk(CARDNAME": Far too big packet error. \n");
-+ if (numPages > 7) {
-+ printk("%s: Far too big packet error.\n", dev->name);
- /* freeing the packet is a good thing here... but should
- . any packets of this size get down here? */
- dev_kfree_skb (skb);
-@@ -517,12 +794,13 @@
- netif_wake_queue(dev);
- return 0;
- }
-+
- /* either way, a packet is waiting now */
- lp->packets_waiting++;
-
- /* now, try to allocate the memory */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_ALLOC | numPages, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_ALLOC | numPages, ioaddr, MMU_CMD);
- /*
- . Performance Hack
- .
-@@ -539,21 +817,21 @@
- do {
- word status;
-
-- status = inb( ioaddr + INTERRUPT );
-- if ( status & IM_ALLOC_INT ) {
-+ status = smc_inb(ioaddr, INTERRUPT);
-+ if (status & IM_ALLOC_INT) {
- /* acknowledge the interrupt */
-- outb( IM_ALLOC_INT, ioaddr + INTERRUPT );
-- break;
-+ smc_outb(IM_ALLOC_INT, ioaddr, INTERRUPT);
-+ break;
- }
-- } while ( -- time_out );
-+ } while (-- time_out);
-
-- if ( !time_out ) {
-+ if (!time_out) {
- /* oh well, wait until the chip finds memory later */
-- SMC_ENABLE_INT( IM_ALLOC_INT );
-- PRINTK2((CARDNAME": memory allocation deferred. \n"));
-+ SMC_ENABLE_INT(IM_ALLOC_INT);
-+ PRINTK2(("%s: memory allocation deferred.\n", dev->name));
- /* it's deferred, but I'll handle it later */
-- return 0;
-- }
-+ return 0;
-+ }
- /* or YES! I can send the packet now.. */
- smc_hardware_send_packet(dev);
- netif_wake_queue(dev);
-@@ -561,46 +839,46 @@
- }
-
- /*
-- . Function: smc_hardware_send_packet(struct net_device * )
-+ . Function: smc_hardware_send_packet(struct net_device *)
- . Purpose:
- . This sends the actual packet to the SMC9xxx chip.
- .
- . Algorithm:
- . First, see if a saved_skb is available.
-- . ( this should NOT be called if there is no 'saved_skb'
-+ . (this should NOT be called if there is no 'saved_skb'
- . Now, find the packet number that the chip allocated
- . Point the data pointers at it in memory
- . Set the length word in the chip's memory
- . Dump the packet to chip memory
-- . Check if a last byte is needed ( odd length packet )
-+ . Check if a last byte is needed (odd length packet)
- . if so, set the control flag right
- . Tell the card to send it
- . Enable the transmit interrupt, so I know if it failed
- . Free the kernel data if I actually sent it.
- */
--static void smc_hardware_send_packet( struct net_device * dev )
-+static void smc_hardware_send_packet(struct net_device *dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- byte packet_no;
-- struct sk_buff * skb = lp->saved_skb;
-- word length;
-- unsigned short ioaddr;
-- byte * buf;
--
-- ioaddr = dev->base_addr;
-+ struct sk_buff *skb = lp->saved_skb;
-+ word length, lastword;
-+ u_int ioaddr = dev->base_addr;
-+ byte packet_no;
-+ byte *buf;
-
-- if ( !skb ) {
-- PRINTK((CARDNAME": In XMIT with no packet to send \n"));
-+ if (!skb) {
-+ PRINTK(("%s: In XMIT with no packet to send\n", dev->name));
- return;
- }
-+
- length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- buf = skb->data;
-
- /* If I get here, I _know_ there is a packet slot waiting for me */
-- packet_no = inb( ioaddr + PNR_ARR + 1 );
-- if ( packet_no & 0x80 ) {
-+ packet_no = smc_inb(ioaddr, PNR_ARR + 1);
-+ if (packet_no & 0x80) {
- /* or isn't there? BAD CHIP! */
-- printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
-+ printk(KERN_DEBUG "%s: Memory allocation failed.\n",
-+ dev->name);
- dev_kfree_skb_any(skb);
- lp->saved_skb = NULL;
- netif_wake_queue(dev);
-@@ -608,26 +886,19 @@
- }
-
- /* we have a packet address, so tell the card to use it */
-- outb( packet_no, ioaddr + PNR_ARR );
-+ smc_outb(packet_no, ioaddr, PNR_ARR);
-
- /* point to the beginning of the packet */
-- outw( PTR_AUTOINC , ioaddr + POINTER );
-+ smc_outw(PTR_AUTOINC, ioaddr, POINTER);
-
-- PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length ));
--#if SMC_DEBUG > 2
-- print_packet( buf, length );
--#endif
-+ PRINTK3(("%s: Trying to xmit packet of length %x\n",
-+ dev->name, length));
-
-- /* send the packet length ( +6 for status, length and ctl byte )
-- and the status word ( set to zeros ) */
--#ifdef USE_32_BIT
-- outl( (length +6 ) << 16 , ioaddr + DATA_1 );
--#else
-- outw( 0, ioaddr + DATA_1 );
-- /* send the packet length ( +6 for status words, length, and ctl*/
-- outb( (length+6) & 0xFF,ioaddr + DATA_1 );
-- outb( (length+6) >> 8 , ioaddr + DATA_1 );
--#endif
-+ print_packet(buf, length);
-+
-+ /* send the packet length (+6 for status, length and ctl byte)
-+ and the status word (set to zeros) */
-+ smc_outl((length + 6) << 16, ioaddr, DATA_1);
-
- /* send the actual data
- . I _think_ it's faster to send the longs first, and then
-@@ -636,32 +907,22 @@
- . a good idea to check which is optimal? But that could take
- . almost as much time as is saved?
- */
--#ifdef USE_32_BIT
-- if ( length & 0x2 ) {
-- outsl(ioaddr + DATA_1, buf, length >> 2 );
-- outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-- }
-- else
-- outsl(ioaddr + DATA_1, buf, length >> 2 );
--#else
-- outsw(ioaddr + DATA_1 , buf, (length ) >> 1);
--#endif
-- /* Send the last byte, if there is one. */
-+ smc_outs(ioaddr, DATA_1, buf, length);
-
-- if ( (length & 1) == 0 ) {
-- outw( 0, ioaddr + DATA_1 );
-- } else {
-- outb( buf[length -1 ], ioaddr + DATA_1 );
-- outb( 0x20, ioaddr + DATA_1);
-- }
-+ /* Send the last byte, if there is one. */
-+ if ((length & 1) == 0)
-+ lastword = 0;
-+ else
-+ lastword = 0x2000 | buf[length - 1];
-+ smc_outw(lastword, ioaddr, DATA_1);
-
- /* enable the interrupts */
-- SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
-+ SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
-
- /* and let the chipset deal with it */
-- outw( MC_ENQUEUE , ioaddr + MMU_CMD );
-+ smc_outw(MC_ENQUEUE, ioaddr, MMU_CMD);
-
-- PRINTK2((CARDNAME": Sent packet of length %d \n",length));
-+ PRINTK2(("%s: Sent packet of length %d\n", dev->name, length));
-
- lp->saved_skb = NULL;
- dev_kfree_skb_any (skb);
-@@ -676,7 +937,7 @@
-
- /*-------------------------------------------------------------------------
- |
-- | smc_init( struct net_device * dev )
-+ | smc_init(struct net_device * dev)
- | Input parameters:
- | dev->base_addr == 0, try to find all possible locations
- | dev->base_addr == 1, return failure code
-@@ -691,6 +952,65 @@
- */
- int __init smc_init(struct net_device *dev)
- {
-+ int ret = -ENODEV;
-+#if defined(CONFIG_ASSABET_NEPONSET)
-+ if (machine_is_assabet() && machine_has_neponset()) {
-+ unsigned int *addr;
-+ unsigned char ecor;
-+ unsigned long flags;
-+
-+ NCR_0 |= NCR_ENET_OSC_EN;
-+ dev->irq = IRQ_NEPONSET_SMC9196;
-+
-+ /*
-+ * Map the attribute space. This is overkill, but clean.
-+ */
-+ addr = ioremap(0x18000000 + (1 << 25), 64 * 1024 * 4);
-+ if (!addr)
-+ return -ENOMEM;
-+
-+ /*
-+ * Reset the device. We must disable IRQs around this.
-+ */
-+ local_irq_save(flags);
-+ ecor = readl(addr + ECOR) & ~ECOR_RESET;
-+ writel(ecor | ECOR_RESET, addr + ECOR);
-+ udelay(100);
-+
-+ /*
-+ * The device will ignore all writes to the enable bit while
-+ * reset is asserted, even if the reset bit is cleared in the
-+ * same write. Must clear reset first, then enable the device.
-+ */
-+ writel(ecor, addr + ECOR);
-+ writel(ecor | ECOR_ENABLE, addr + ECOR);
-+
-+ /*
-+ * Force byte mode.
-+ */
-+ writel(readl(addr + ECSR) | ECSR_IOIS8, addr + ECSR);
-+ local_irq_restore(flags);
-+
-+ iounmap(addr);
-+
-+ /*
-+ * Wait for the chip to wake up.
-+ */
-+ mdelay(1);
-+
-+ /*
-+ * Map the real registers.
-+ */
-+ addr = ioremap(0x18000000, 8 * 1024);
-+ if (!addr)
-+ return -ENOMEM;
-+
-+ ret = smc_probe(dev, (int)addr);
-+ if (ret)
-+ iounmap(addr);
-+ }
-+
-+#elif defined(CONFIG_ISA)
- int i;
- int base_addr = dev->base_addr;
-
-@@ -708,7 +1028,8 @@
- return 0;
-
- /* couldn't find anything */
-- return -ENODEV;
-+#endif
-+ return ret;
- }
-
- /*----------------------------------------------------------------------
-@@ -718,10 +1039,11 @@
- . interrupt, so an auto-detect routine can detect it, and find the IRQ,
- ------------------------------------------------------------------------
- */
--int __init smc_findirq( int ioaddr )
-+int __init smc_findirq(struct net_device *dev)
- {
- int timeout = 20;
- unsigned long cookie;
-+ u_int ioaddr = dev->base_addr;
-
-
- /* I have to do a STI() here, because this is called from
-@@ -737,26 +1059,25 @@
- * when done.
- */
-
--
-+ /* enable ALLOCation interrupts ONLY. */
- SMC_SELECT_BANK(2);
-- /* enable ALLOCation interrupts ONLY */
-- outb( IM_ALLOC_INT, ioaddr + INT_MASK );
-+ SMC_SET_INT(IM_ALLOC_INT);
-
- /*
- . Allocate 512 bytes of memory. Note that the chip was just
- . reset so all the memory is available
- */
-- outw( MC_ALLOC | 1, ioaddr + MMU_CMD );
-+ smc_outw(MC_ALLOC | 1, ioaddr, MMU_CMD);
-
- /*
- . Wait until positive that the interrupt has been generated
- */
-- while ( timeout ) {
-+ while (timeout) {
- byte int_status;
-
-- int_status = inb( ioaddr + INTERRUPT );
-+ int_status = smc_inb(ioaddr, INTERRUPT);
-
-- if ( int_status & IM_ALLOC_INT )
-+ if (int_status & IM_ALLOC_INT)
- break; /* got the interrupt */
- timeout--;
- }
-@@ -775,7 +1096,7 @@
- SMC_DELAY();
-
- /* and disable all interrupts again */
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
-
- /* clear hardware interrupts again, because that's how it
- was when I was called... */
-@@ -785,8 +1106,87 @@
- return probe_irq_off(cookie);
- }
-
-+static int __init smc_probe_chip(struct net_device *dev, int ioaddr)
-+{
-+ unsigned int temp;
-+
-+ /* First, see if the high byte is 0x33 */
-+ temp = smc_inw(ioaddr, BANK_SELECT);
-+ if ((temp & 0xFF00) != 0x3300)
-+ return -ENODEV;
-+
-+ /* The above MIGHT indicate a device, but I need to write to further
-+ test this. */
-+ smc_outw(0, ioaddr, BANK_SELECT);
-+ temp = smc_inw(ioaddr, BANK_SELECT);
-+ if ((temp & 0xFF00) != 0x3300)
-+ return -ENODEV;
-+
-+#ifndef CONFIG_ASSABET_NEPONSET
-+ /* well, we've already written once, so hopefully another time won't
-+ hurt. This time, I need to switch the bank register to bank 1,
-+ so I can access the base address register */
-+ SMC_SELECT_BANK(1);
-+ temp = smc_inw(ioaddr, BASE);
-+ if (ioaddr != (temp >> 3 & 0x3E0)) {
-+ printk("%s: IOADDR %x doesn't match configuration (%x)."
-+ "Probably not a SMC chip\n", dev->name,
-+ ioaddr, (base_address_register >> 3) & 0x3E0);
-+ /* well, the base address register didn't match. Must not have
-+ been a SMC chip after all. */
-+ return -ENODEV;
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+/*
-+ . If dev->irq is 0, then the device has to be banged on to see
-+ . what the IRQ is.
-+ .
-+ . This banging doesn't always detect the IRQ, for unknown reasons.
-+ . a workaround is to reset the chip and try again.
-+ .
-+ . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-+ . be what is requested on the command line. I don't do that, mostly
-+ . because the card that I have uses a non-standard method of accessing
-+ . the IRQs, and because this _should_ work in most configurations.
-+ .
-+ . Specifying an IRQ is done with the assumption that the user knows
-+ . what (s)he is doing. No checking is done!!!!
-+ .
-+*/
-+static int __init smc_probe_irq(struct net_device *dev)
-+{
-+ if (dev->irq < 2) {
-+ int trials;
-+
-+ trials = 3;
-+ while (trials--) {
-+ dev->irq = smc_findirq(dev);
-+ if (dev->irq)
-+ break;
-+ /* kick the card and try again */
-+ smc_reset(dev);
-+ }
-+ }
-+ if (dev->irq == 0) {
-+ printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
-+ dev->name);
-+ return -ENODEV;
-+ }
-+
-+ /*
-+ * Some machines (eg, PCs) need to cannonicalize their IRQs.
-+ */
-+ dev->irq = irq_cannonicalize(dev->irq);
-+
-+ return 0;
-+}
-+
- /*----------------------------------------------------------------------
-- . Function: smc_probe( int ioaddr )
-+ . Function: smc_probe(struct net_device *dev, int ioaddr)
- .
- . Purpose:
- . Tests to see if a given ioaddr points to an SMC9xxx chip.
-@@ -816,16 +1216,14 @@
- */
- static int __init smc_probe(struct net_device *dev, int ioaddr)
- {
-+ struct smc_local *smc;
- int i, memory, retval;
- static unsigned version_printed;
-- unsigned int bank;
-
- const char *version_string;
-- const char *if_string;
-
- /* registers */
- word revision_register;
-- word base_address_register;
- word configuration_register;
- word memory_info_register;
- word memory_cfg_register;
-@@ -834,44 +1232,24 @@
- if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
- return -EBUSY;
-
-- /* First, see if the high byte is 0x33 */
-- bank = inw( ioaddr + BANK_SELECT );
-- if ( (bank & 0xFF00) != 0x3300 ) {
-- retval = -ENODEV;
-- goto err_out;
-- }
-- /* The above MIGHT indicate a device, but I need to write to further
-- test this. */
-- outw( 0x0, ioaddr + BANK_SELECT );
-- bank = inw( ioaddr + BANK_SELECT );
-- if ( (bank & 0xFF00 ) != 0x3300 ) {
-- retval = -ENODEV;
-- goto err_out;
-- }
-- /* well, we've already written once, so hopefully another time won't
-- hurt. This time, I need to switch the bank register to bank 1,
-- so I can access the base address register */
-- SMC_SELECT_BANK(1);
-- base_address_register = inw( ioaddr + BASE );
-- if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) {
-- printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)."
-- "Probably not a SMC chip\n",
-- ioaddr, base_address_register >> 3 & 0x3E0 );
-- /* well, the base address register didn't match. Must not have
-- been a SMC chip after all. */
-- retval = -ENODEV;
-+ /*
-+ * Do the basic probes.
-+ */
-+ retval = smc_probe_chip(dev, ioaddr);
-+ if (retval)
- goto err_out;
-- }
-
- /* check if the revision register is something that I recognize.
- These might need to be added to later, as future revisions
- could be added. */
- SMC_SELECT_BANK(3);
-- revision_register = inw( ioaddr + REVISION );
-- if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) {
-+ revision_register = smc_inw(ioaddr, REVISION);
-+ version_string = chip_ids[(revision_register >> 4) & 15];
-+ if (!version_string) {
- /* I don't recognize this chip, so... */
-- printk(CARDNAME ": IO %x: Unrecognized revision register:"
-- " %x, Contact author. \n", ioaddr, revision_register );
-+ printk("%s: IO %x: unrecognized revision register: %x, "
-+ "contact author.\n", dev->name, ioaddr,
-+ revision_register);
-
- retval = -ENODEV;
- goto err_out;
-@@ -882,138 +1260,122 @@
- against the hardware address, or do some other tests. */
-
- if (version_printed++ == 0)
-- printk("%s", version);
-+ printk(KERN_INFO "%s", version);
-
- /* fill in some of the fields */
- dev->base_addr = ioaddr;
-
- /*
-- . Get the MAC address ( bank 1, regs 4 - 9 )
-+ . Get the MAC address (bank 1, regs 4 - 9)
- */
-- SMC_SELECT_BANK( 1 );
-- for ( i = 0; i < 6; i += 2 ) {
-+ SMC_SELECT_BANK(1);
-+ for (i = 0; i < 6; i += 2) {
- word address;
-
-- address = inw( ioaddr + ADDR0 + i );
-- dev->dev_addr[ i + 1] = address >> 8;
-- dev->dev_addr[ i ] = address & 0xFF;
-+ address = smc_inw(ioaddr, ADDR0 + i);
-+ dev->dev_addr[i + 1] = address >> 8;
-+ dev->dev_addr[i] = address & 0xFF;
- }
-
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ printk("%s: Invalid ethernet MAC address. Please set using "
-+ "ifconfig\n", dev->name);
-+
- /* get the memory information */
-
-- SMC_SELECT_BANK( 0 );
-- memory_info_register = inw( ioaddr + MIR );
-- memory_cfg_register = inw( ioaddr + MCR );
-- memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */
-- memory *= 256 * ( memory_info_register & 0xFF );
-+ SMC_SELECT_BANK(0);
-+ memory_info_register = smc_inw(ioaddr, MIR);
-+ memory_cfg_register = smc_inw(ioaddr, MCR);
-+ memory = (memory_cfg_register >> 9) & 0x7; /* multiplier */
-+ memory *= 256 * (memory_info_register & 0xFF);
-+
-+ /* now, reset the chip, and put it into a known state */
-+ smc_reset(dev);
-
- /*
-- Now, I want to find out more about the chip. This is sort of
-- redundant, but it's cleaner to have it in both, rather than having
-- one VERY long probe procedure.
-- */
-- SMC_SELECT_BANK(3);
-- revision_register = inw( ioaddr + REVISION );
-- version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
-- if ( !version_string ) {
-- /* I shouldn't get here because this call was done before.... */
-- retval = -ENODEV;
-+ * Ok, now that we have everything in a
-+ * sane state, probe for the interrupt.
-+ */
-+ retval = smc_probe_irq(dev);
-+ if (retval)
- goto err_out;
-- }
-
-- /* is it using AUI or 10BaseT ? */
-- if ( dev->if_port == 0 ) {
-- SMC_SELECT_BANK(1);
-- configuration_register = inw( ioaddr + CONFIG );
-- if ( configuration_register & CFG_AUI_SELECT )
-- dev->if_port = 2;
-- else
-- dev->if_port = 1;
-+ /* Initialize the private structure. */
-+ if (dev->priv == NULL) {
-+ dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
-+ if (dev->priv == NULL) {
-+ retval = -ENOMEM;
-+ goto err_out;
-+ }
- }
-- if_string = interfaces[ dev->if_port - 1 ];
-
-- /* now, reset the chip, and put it into a known state */
-- smc_reset( ioaddr );
-+ smc = dev->priv;
-+
-+ /* set the private data to zero by default */
-+ memset(smc, 0, sizeof(struct smc_local));
-
- /*
-- . If dev->irq is 0, then the device has to be banged on to see
-- . what the IRQ is.
-- .
-- . This banging doesn't always detect the IRQ, for unknown reasons.
-- . a workaround is to reset the chip and try again.
-- .
-- . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-- . be what is requested on the command line. I don't do that, mostly
-- . because the card that I have uses a non-standard method of accessing
-- . the IRQs, and because this _should_ work in most configurations.
-- .
-- . Specifying an IRQ is done with the assumption that the user knows
-- . what (s)he is doing. No checking is done!!!!
-- .
-- */
-- if ( dev->irq < 2 ) {
-- int trials;
-+ * Get the interface characteristics.
-+ * is it using AUI or 10BaseT ?
-+ */
-+ switch (dev->if_port) {
-+ case IF_PORT_10BASET:
-+ smc->port = PORT_TP;
-+ break;
-
-- trials = 3;
-- while ( trials-- ) {
-- dev->irq = smc_findirq( ioaddr );
-- if ( dev->irq )
-- break;
-- /* kick the card and try again */
-- smc_reset( ioaddr );
-+ case IF_PORT_AUI:
-+ smc->port = PORT_AUI;
-+ break;
-+
-+ default:
-+ SMC_SELECT_BANK(1);
-+ configuration_register = smc_inw(ioaddr, CONFIG);
-+ if (configuration_register & CFG_AUI_SELECT) {
-+ dev->if_port = IF_PORT_AUI;
-+ smc->port = PORT_AUI;
-+ } else {
-+ dev->if_port = IF_PORT_10BASET;
-+ smc->port = PORT_TP;
- }
-- }
-- if (dev->irq == 0 ) {
-- printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
-- retval = -ENODEV;
-- goto err_out;
-+ break;
- }
-
-- /* now, print out the card info, in a short format.. */
-+ /* all interfaces are half-duplex by default */
-+ smc->duplex = DUPLEX_HALF;
-
-- printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
-- version_string, revision_register & 0xF, ioaddr, dev->irq,
-- if_string, memory );
-+ /* now, print out the card info, in a short format.. */
-+ printk("%s: %s (rev %d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
-+ version_string, revision_register & 15, ioaddr, dev->irq,
-+ interfaces[smc->port], memory);
- /*
- . Print the Ethernet address
- */
- printk("ADDR: ");
- for (i = 0; i < 5; i++)
-- printk("%2.2x:", dev->dev_addr[i] );
-- printk("%2.2x \n", dev->dev_addr[5] );
--
--
-- /* Initialize the private structure. */
-- if (dev->priv == NULL) {
-- dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
-- if (dev->priv == NULL) {
-- retval = -ENOMEM;
-- goto err_out;
-- }
-- }
-- /* set the private data to zero by default */
-- memset(dev->priv, 0, sizeof(struct smc_local));
-+ printk("%2.2x:", dev->dev_addr[i]);
-+ printk("%2.2x\n", dev->dev_addr[5]);
-
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
-
- /* Grab the IRQ */
-- retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-- if (retval) {
-+ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-+ if (retval) {
- printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
- dev->irq, retval);
- kfree(dev->priv);
- dev->priv = NULL;
-- goto err_out;
-- }
-+ goto err_out;
-+ }
-
-- dev->open = smc_open;
-- dev->stop = smc_close;
-- dev->hard_start_xmit = smc_wait_to_send_packet;
-- dev->tx_timeout = smc_timeout;
-- dev->watchdog_timeo = HZ/20;
-- dev->get_stats = smc_query_statistics;
-- dev->set_multicast_list = smc_set_multicast_list;
-+ dev->open = smc_open;
-+ dev->stop = smc_close;
-+ dev->hard_start_xmit = smc_wait_to_send_packet;
-+ dev->tx_timeout = smc_timeout;
-+ dev->watchdog_timeo = HZ/20;
-+ dev->get_stats = smc_query_statistics;
-+ dev->set_multicast_list = smc_set_multicast_list;
-+ dev->do_ioctl = smc_ioctl;
-
- return 0;
-
-@@ -1022,42 +1384,43 @@
- return retval;
- }
-
--#if SMC_DEBUG > 2
--static void print_packet( byte * buf, int length )
-+/*
-+ * This is responsible for setting the chip appropriately
-+ * for the interface type. This should only be called while
-+ * the interface is up and running.
-+ */
-+static void smc_set_port(struct net_device *dev)
- {
--#if 0
-- int i;
-- int remainder;
-- int lines;
--
-- printk("Packet of length %d \n", length );
-- lines = length / 16;
-- remainder = length % 16;
--
-- for ( i = 0; i < lines ; i ++ ) {
-- int cur;
-+ struct smc_local *smc = dev->priv;
-+ u_int ioaddr = dev->base_addr;
-+ u_int val;
-
-- for ( cur = 0; cur < 8; cur ++ ) {
-- byte a, b;
-+ SMC_SELECT_BANK(1);
-+ val = smc_inw(ioaddr, CONFIG);
-+ switch (smc->port) {
-+ case PORT_TP:
-+ val &= ~CFG_AUI_SELECT;
-+ break;
-
-- a = *(buf ++ );
-- b = *(buf ++ );
-- printk("%02x%02x ", a, b );
-- }
-- printk("\n");
-+ case PORT_AUI:
-+ val |= CFG_AUI_SELECT;
-+ break;
- }
-- for ( i = 0; i < remainder/2 ; i++ ) {
-- byte a, b;
-+ smc_outw(val, ioaddr, CONFIG);
-
-- a = *(buf ++ );
-- b = *(buf ++ );
-- printk("%02x%02x ", a, b );
-+ SMC_SELECT_BANK(0);
-+ val = smc_inw(ioaddr, TCR);
-+ switch (smc->duplex) {
-+ case DUPLEX_HALF:
-+ val &= ~TCR_FDSE;
-+ break;
-+
-+ case DUPLEX_FULL:
-+ val |= TCR_FDSE;
-+ break;
- }
-- printk("\n");
--#endif
-+ smc_outw(val, ioaddr, TCR);
- }
--#endif
--
-
- /*
- * Open and Initialize the board
-@@ -1067,48 +1430,141 @@
- */
- static int smc_open(struct net_device *dev)
- {
-- int ioaddr = dev->base_addr;
-+ struct smc_local *smc = dev->priv;
-+ u_int ioaddr = dev->base_addr;
-+ int i;
-
-- int i; /* used to set hw ethernet address */
-+ /*
-+ * Check that the address is valid. If its not, refuse
-+ * to bring the device up. The user must specify an
-+ * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-+ */
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ return -EINVAL;
-
- /* clear out all the junk that was put here before... */
-- memset(dev->priv, 0, sizeof(struct smc_local));
-+ smc->saved_skb = NULL;
-+ smc->packets_waiting = 0;
-
- /* reset the hardware */
--
-- smc_reset( ioaddr );
-- smc_enable( ioaddr );
-+ smc_reset(dev);
-+ smc_enable(dev);
-
- /* Select which interface to use */
--
-- SMC_SELECT_BANK( 1 );
-- if ( dev->if_port == 1 ) {
-- outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
-- ioaddr + CONFIG );
-- }
-- else if ( dev->if_port == 2 ) {
-- outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT,
-- ioaddr + CONFIG );
-- }
-+ smc_set_port(dev);
-
- /*
-- According to Becker, I have to set the hardware address
-+ According to Becker, I have to set the hardware address
- at this point, because the (l)user can set it with an
- ioctl. Easily done...
- */
-- SMC_SELECT_BANK( 1 );
-- for ( i = 0; i < 6; i += 2 ) {
-+ SMC_SELECT_BANK(1);
-+ for (i = 0; i < 6; i += 2) {
- word address;
-
-- address = dev->dev_addr[ i + 1 ] << 8 ;
-- address |= dev->dev_addr[ i ];
-- outw( address, ioaddr + ADDR0 + i );
-+ address = dev->dev_addr[i + 1] << 8 ;
-+ address |= dev->dev_addr[i];
-+ smc_outw(address, ioaddr, ADDR0 + i);
- }
-
- netif_start_queue(dev);
- return 0;
- }
-
-+/*
-+ * This is our template. Fill the rest in at run-time
-+ */
-+static const struct ethtool_cmd ecmd_template = {
-+ supported: SUPPORTED_10baseT_Half |
-+ SUPPORTED_10baseT_Full |
-+ SUPPORTED_TP |
-+ SUPPORTED_AUI,
-+ speed: SPEED_10,
-+ autoneg: AUTONEG_DISABLE,
-+ maxtxpkt: 1,
-+ maxrxpkt: 1,
-+ transceiver: XCVR_INTERNAL,
-+};
-+
-+static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+ struct smc_local *smc = dev->priv;
-+ u32 etcmd;
-+ int ret = -EINVAL;
-+
-+ if (cmd != SIOCETHTOOL)
-+ return -EOPNOTSUPP;
-+
-+ if (get_user(etcmd, (u32 *)rq->ifr_data))
-+ return -EFAULT;
-+
-+ switch (etcmd) {
-+ case ETHTOOL_GSET: {
-+ struct ethtool_cmd ecmd = ecmd_template;
-+
-+ ecmd.cmd = etcmd;
-+ ecmd.port = smc->port;
-+ ecmd.duplex = smc->duplex;
-+
-+ ret = copy_to_user(rq->ifr_data, &ecmd, sizeof(ecmd))
-+ ? -EFAULT : 0;
-+ break;
-+ }
-+
-+ case ETHTOOL_SSET: {
-+ struct ethtool_cmd ecmd;
-+
-+ ret = -EPERM;
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+
-+ ret = -EFAULT;
-+ if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
-+ break;
-+
-+ /*
-+ * Sanity-check the arguments.
-+ */
-+ ret = -EINVAL;
-+ if (ecmd.autoneg != AUTONEG_DISABLE)
-+ break;
-+ if (ecmd.speed != SPEED_10)
-+ break;
-+ if (ecmd.duplex != DUPLEX_HALF && ecmd.duplex != DUPLEX_FULL)
-+ break;
-+ if (ecmd.port != PORT_TP && ecmd.port != PORT_AUI)
-+ break;
-+
-+ smc->port = ecmd.port;
-+ smc->duplex = ecmd.duplex;
-+
-+ if (netif_running(dev))
-+ smc_set_port(dev);
-+
-+ ret = 0;
-+ break;
-+ }
-+
-+ case ETHTOOL_GDRVINFO: {
-+ struct ethtool_drvinfo edrv;
-+
-+ memset(&edrv, 0, sizeof(edrv));
-+
-+ edrv.cmd = etcmd;
-+ strcpy(edrv.driver, DRV_NAME);
-+ strcpy(edrv.version, DRV_VERSION);
-+ sprintf(edrv.bus_info, "ISA:%8.8lx:%d",
-+ dev->base_addr, dev->irq);
-+
-+ ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv))
-+ ? -EFAULT : 0;
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
- /*--------------------------------------------------------
- . Called by the kernel to send a packet out into the void
- . of the net. This routine is largely based on
-@@ -1120,12 +1576,10 @@
- {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
-- printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
-- tx_done(dev) ? "IRQ conflict" :
-- "network cable problem");
-+ printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
- /* "kick" the adaptor */
-- smc_reset( dev->base_addr );
-- smc_enable( dev->base_addr );
-+ smc_reset(dev);
-+ smc_enable(dev);
- dev->trans_start = jiffies;
- /* clear anything saved */
- ((struct smc_local *)dev->priv)->saved_skb = NULL;
-@@ -1145,10 +1599,10 @@
- .
- ---------------------------------------------------------------------*/
-
--static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-+static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
- {
- struct net_device *dev = dev_id;
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
-
- byte status;
-@@ -1161,45 +1615,45 @@
-
-
-
-- PRINTK3((CARDNAME": SMC interrupt started \n"));
-+ PRINTK3(("%s: SMC interrupt started\n", dev->name));
-
-- saved_bank = inw( ioaddr + BANK_SELECT );
-+ saved_bank = smc_inw(ioaddr, BANK_SELECT);
-
- SMC_SELECT_BANK(2);
-- saved_pointer = inw( ioaddr + POINTER );
-+ saved_pointer = smc_inw(ioaddr, POINTER);
-
-- mask = inb( ioaddr + INT_MASK );
-+ mask = smc_inb(ioaddr, INT_MASK);
- /* clear all interrupts */
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
-
-
- /* set a timeout value, so I don't stay here forever */
- timeout = 4;
-
-- PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
-+ PRINTK2((KERN_WARNING "%s: MASK IS %x\n", dev->name, mask));
- do {
- /* read the status flag, and mask it */
-- status = inb( ioaddr + INTERRUPT ) & mask;
-- if (!status )
-+ status = smc_inb(ioaddr, INTERRUPT) & mask;
-+ if (!status)
- break;
-
-- PRINTK3((KERN_WARNING CARDNAME
-- ": Handling interrupt status %x \n", status ));
-+ PRINTK3((KERN_WARNING "%s: handling interrupt status %x\n",
-+ dev->name, status));
-
- if (status & IM_RCV_INT) {
- /* Got a packet(s). */
-- PRINTK2((KERN_WARNING CARDNAME
-- ": Receive Interrupt\n"));
-+ PRINTK2((KERN_WARNING "%s: receive interrupt\n",
-+ dev->name));
- smc_rcv(dev);
-- } else if (status & IM_TX_INT ) {
-- PRINTK2((KERN_WARNING CARDNAME
-- ": TX ERROR handled\n"));
-+ } else if (status & IM_TX_INT) {
-+ PRINTK2((KERN_WARNING "%s: TX ERROR handled\n",
-+ dev->name));
- smc_tx(dev);
-- outb(IM_TX_INT, ioaddr + INTERRUPT );
-- } else if (status & IM_TX_EMPTY_INT ) {
-+ smc_outb(IM_TX_INT, ioaddr, INTERRUPT);
-+ } else if (status & IM_TX_EMPTY_INT) {
- /* update stats */
-- SMC_SELECT_BANK( 0 );
-- card_stats = inw( ioaddr + COUNTER );
-+ SMC_SELECT_BANK(0);
-+ card_stats = smc_inw(ioaddr, COUNTER);
- /* single collisions */
- lp->stats.collisions += card_stats & 0xF;
- card_stats >>= 4;
-@@ -1208,60 +1662,63 @@
-
- /* these are for when linux supports these statistics */
-
-- SMC_SELECT_BANK( 2 );
-- PRINTK2((KERN_WARNING CARDNAME
-- ": TX_BUFFER_EMPTY handled\n"));
-- outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
-+ SMC_SELECT_BANK(2);
-+ PRINTK2((KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
-+ dev->name));
-+ smc_outb(IM_TX_EMPTY_INT, ioaddr, INTERRUPT);
- mask &= ~IM_TX_EMPTY_INT;
- lp->stats.tx_packets += lp->packets_waiting;
- lp->packets_waiting = 0;
-
-- } else if (status & IM_ALLOC_INT ) {
-- PRINTK2((KERN_DEBUG CARDNAME
-- ": Allocation interrupt \n"));
-+ } else if (status & IM_ALLOC_INT) {
-+ PRINTK2((KERN_DEBUG "%s: Allocation interrupt\n",
-+ dev->name));
- /* clear this interrupt so it doesn't happen again */
- mask &= ~IM_ALLOC_INT;
-
-- smc_hardware_send_packet( dev );
-+ smc_hardware_send_packet(dev);
-
- /* enable xmit interrupts based on this */
-- mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
-+ mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
-
- /* and let the card send more packets to me */
- netif_wake_queue(dev);
-
-- PRINTK2((CARDNAME": Handoff done successfully.\n"));
-- } else if (status & IM_RX_OVRN_INT ) {
-+ PRINTK2(("%s: Handoff done successfully.\n",
-+ dev->name));
-+ } else if (status & IM_RX_OVRN_INT) {
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
-- outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
-- } else if (status & IM_EPH_INT ) {
-- PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
-- } else if (status & IM_ERCV_INT ) {
-- PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
-- outb( IM_ERCV_INT, ioaddr + INTERRUPT );
-+ smc_outb(IM_RX_OVRN_INT, ioaddr, INTERRUPT);
-+ } else if (status & IM_EPH_INT) {
-+ PRINTK(("%s: UNSUPPORTED: EPH INTERRUPT\n",
-+ dev->name));
-+ } else if (status & IM_ERCV_INT) {
-+ PRINTK(("%s: UNSUPPORTED: ERCV INTERRUPT\n",
-+ dev->name));
-+ smc_outb(IM_ERCV_INT, ioaddr, INTERRUPT);
- }
-- } while ( timeout -- );
-+ } while (timeout --);
-
-
- /* restore state register */
-- SMC_SELECT_BANK( 2 );
-- outb( mask, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(mask);
-
-- PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
-- outw( saved_pointer, ioaddr + POINTER );
-+ PRINTK3((KERN_WARNING "%s: MASK is now %x\n", dev->name, mask));
-+ smc_outw(saved_pointer, ioaddr, POINTER);
-
-- SMC_SELECT_BANK( saved_bank );
-+ SMC_SELECT_BANK(saved_bank);
-
-- PRINTK3((CARDNAME ": Interrupt done\n"));
-+ PRINTK3(("%s: Interrupt done\n", dev->name));
- return;
- }
-
- /*-------------------------------------------------------------
- .
-- . smc_rcv - receive a packet from the card
-+ . smc_rcv - receive a packet from the card
- .
-- . There is ( at least ) a packet waiting to be read from
-+ . There is (at least) a packet waiting to be read from
- . chip-memory.
- .
- . o Read the status
-@@ -1272,55 +1729,57 @@
- static void smc_rcv(struct net_device *dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- int packet_number;
- word status;
- word packet_length;
-
- /* assume bank 2 */
-
-- packet_number = inw( ioaddr + FIFO_PORTS );
-+ packet_number = smc_inw(ioaddr, FIFO_PORTS);
-
-- if ( packet_number & FP_RXEMPTY ) {
-+ if (packet_number & FP_RXEMPTY) {
- /* we got called , but nothing was on the FIFO */
-- PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n"));
-+ PRINTK(("%s: WARNING: smc_rcv with nothing on FIFO.\n",
-+ dev->name));
- /* don't need to restore anything */
- return;
- }
-
- /* start reading from the start of the packet */
-- outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );
-+ smc_outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr, POINTER);
-
- /* First two words are status and packet_length */
-- status = inw( ioaddr + DATA_1 );
-- packet_length = inw( ioaddr + DATA_1 );
-+ status = smc_inw(ioaddr, DATA_1);
-+ packet_length = smc_inw(ioaddr, DATA_1);
-
- packet_length &= 0x07ff; /* mask off top bits */
-
-- PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ));
-+ PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length));
- /*
- . the packet length contains 3 extra words :
- . status, length, and an extra word with an odd byte .
- */
- packet_length -= 6;
-
-- if ( !(status & RS_ERRORS ) ){
-+ if (!(status & RS_ERRORS)){
- /* do stuff to make a new packet */
- struct sk_buff * skb;
- byte * data;
-
- /* read one extra byte */
-- if ( status & RS_ODDFRAME )
-+ if (status & RS_ODDFRAME)
- packet_length++;
-
- /* set multicast stats */
-- if ( status & RS_MULTICAST )
-+ if (status & RS_MULTICAST)
- lp->stats.multicast++;
-
-- skb = dev_alloc_skb( packet_length + 5);
-+ skb = dev_alloc_skb(packet_length + 5);
-
-- if ( skb == NULL ) {
-- printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
-+ if (skb == NULL) {
-+ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-+ dev->name);
- lp->stats.rx_dropped++;
- goto done;
- }
-@@ -1330,36 +1789,15 @@
- ! in the worse case
- */
-
-- skb_reserve( skb, 2 ); /* 16 bit alignment */
-+ skb_reserve(skb, 2); /* 16 bit alignment */
-
- skb->dev = dev;
-- data = skb_put( skb, packet_length);
-+ data = skb_put(skb, packet_length);
-
--#ifdef USE_32_BIT
-- /* QUESTION: Like in the TX routine, do I want
-- to send the DWORDs or the bytes first, or some
-- mixture. A mixture might improve already slow PIO
-- performance */
-- PRINTK3((" Reading %d dwords (and %d bytes) \n",
-- packet_length >> 2, packet_length & 3 ));
-- insl(ioaddr + DATA_1 , data, packet_length >> 2 );
-- /* read the left over bytes */
-- insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC),
-- packet_length & 0x3 );
--#else
-- PRINTK3((" Reading %d words and %d byte(s) \n",
-- (packet_length >> 1 ), packet_length & 1 ));
-- insw(ioaddr + DATA_1 , data, packet_length >> 1);
-- if ( packet_length & 1 ) {
-- data += packet_length & ~1;
-- *(data++) = inb( ioaddr + DATA_1 );
-- }
--#endif
--#if SMC_DEBUG > 2
-- print_packet( data, packet_length );
--#endif
-+ smc_ins(ioaddr, DATA_1, data, packet_length);
-+ print_packet(data, packet_length);
-
-- skb->protocol = eth_type_trans(skb, dev );
-+ skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
-@@ -1368,15 +1806,17 @@
- /* error ... */
- lp->stats.rx_errors++;
-
-- if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++;
-- if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
-+ if (status & RS_ALGNERR)
-+ lp->stats.rx_frame_errors++;
-+ if (status & (RS_TOOSHORT | RS_TOOLONG))
- lp->stats.rx_length_errors++;
-- if ( status & RS_BADCRC) lp->stats.rx_crc_errors++;
-+ if (status & RS_BADCRC)
-+ lp->stats.rx_crc_errors++;
- }
-
- done:
- /* error or good, tell the card to get rid of this packet */
-- outw( MC_RELEASE, ioaddr + MMU_CMD );
-+ smc_outw(MC_RELEASE, ioaddr, MMU_CMD);
- }
-
-
-@@ -1389,62 +1829,64 @@
- . Algorithm:
- . Save pointer and packet no
- . Get the packet no from the top of the queue
-- . check if it's valid ( if not, is this an error??? )
-+ . check if it's valid (if not, is this an error???)
- . read the status word
- . record the error
-- . ( resend? Not really, since we don't want old packets around )
-+ . (resend? Not really, since we don't want old packets around)
- . Restore saved values
- ************************************************************************/
--static void smc_tx( struct net_device * dev )
-+static void smc_tx(struct net_device * dev)
- {
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
- byte saved_packet;
- byte packet_no;
- word tx_status;
-
-
-- /* assume bank 2 */
-+ /* assume bank 2 */
-
-- saved_packet = inb( ioaddr + PNR_ARR );
-- packet_no = inw( ioaddr + FIFO_PORTS );
-+ saved_packet = smc_inb(ioaddr, PNR_ARR);
-+ packet_no = smc_inw(ioaddr, FIFO_PORTS);
- packet_no &= 0x7F;
-
- /* select this as the packet to read from */
-- outb( packet_no, ioaddr + PNR_ARR );
-+ smc_outb(packet_no, ioaddr, PNR_ARR);
-
- /* read the first word from this packet */
-- outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER );
-+ smc_outw(PTR_AUTOINC | PTR_READ, ioaddr, POINTER);
-
-- tx_status = inw( ioaddr + DATA_1 );
-- PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status ));
-+ tx_status = smc_inw(ioaddr, DATA_1);
-+ PRINTK3(("%s: TX DONE STATUS: %4x\n", dev->name, tx_status));
-
- lp->stats.tx_errors++;
-- if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++;
-- if ( tx_status & TS_LATCOL ) {
-- printk(KERN_DEBUG CARDNAME
-- ": Late collision occurred on last xmit.\n");
-+ if (tx_status & TS_LOSTCAR)
-+ lp->stats.tx_carrier_errors++;
-+ if (tx_status & TS_LATCOL) {
-+ printk(KERN_DEBUG "%s: Late collision occurred on "
-+ "last xmit.\n", dev->name);
- lp->stats.tx_window_errors++;
- }
- #if 0
-- if ( tx_status & TS_16COL ) { ... }
-+ if (tx_status & TS_16COL) { ... }
- #endif
-
-- if ( tx_status & TS_SUCCESS ) {
-- printk(CARDNAME": Successful packet caused interrupt \n");
-+ if (tx_status & TS_SUCCESS) {
-+ printk("%s: Successful packet caused interrupt\n",
-+ dev->name);
- }
- /* re-enable transmit */
-- SMC_SELECT_BANK( 0 );
-- outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outw(smc_inw(ioaddr, TCR) | TCR_ENABLE, ioaddr, TCR);
-
- /* kill the packet */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_FREEPKT, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_FREEPKT, ioaddr, MMU_CMD);
-
- /* one less packet waiting for me */
- lp->packets_waiting--;
-
-- outb( saved_packet, ioaddr + PNR_ARR );
-+ smc_outb(saved_packet, ioaddr, PNR_ARR);
- return;
- }
-
-@@ -1460,7 +1902,7 @@
- {
- netif_stop_queue(dev);
- /* clear everything */
-- smc_shutdown( dev->base_addr );
-+ smc_shutdown(dev);
-
- /* Update the statistics here. */
- return 0;
-@@ -1481,16 +1923,16 @@
- .
- . This routine will, depending on the values passed to it,
- . either make it accept multicast packets, go into
-- . promiscuous mode ( for TCPDUMP and cousins ) or accept
-+ . promiscuous mode (for TCPDUMP and cousins) or accept
- . a select set of multicast packets
- */
- static void smc_set_multicast_list(struct net_device *dev)
- {
-- short ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
-
- SMC_SELECT_BANK(0);
-- if ( dev->flags & IFF_PROMISC )
-- outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
-+ if (dev->flags & IFF_PROMISC)
-+ smc_outw(smc_inw(ioaddr, RCR) | RCR_PROMISC, ioaddr, RCR);
-
- /* BUG? I never disable promiscuous mode if multicasting was turned on.
- Now, I turn off promiscuous mode, but I don't do anything to multicasting
-@@ -1502,34 +1944,34 @@
- checked before the table is
- */
- else if (dev->flags & IFF_ALLMULTI)
-- outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
-+ smc_outw(smc_inw(ioaddr, RCR) | RCR_ALMUL, ioaddr, RCR);
-
- /* We just get all multicast packets even if we only want them
- . from one source. This will be changed at some future
- . point. */
-- else if (dev->mc_count ) {
-+ else if (dev->mc_count) {
- /* support hardware multicasting */
-
- /* be sure I get rid of flags I might have set */
-- outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
-- ioaddr + RCR );
-+ smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
-+ ioaddr, RCR);
- /* NOTE: this has to set the bank, so make sure it is the
- last thing called. The bank is set to zero at the top */
-- smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
-+ smc_setmulticast(dev, dev->mc_count, dev->mc_list);
- }
-- else {
-- outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
-- ioaddr + RCR );
-+ else {
-+ smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
-+ ioaddr, RCR);
-
- /*
- since I'm disabling all multicast entirely, I need to
- clear the multicast list
- */
-- SMC_SELECT_BANK( 3 );
-- outw( 0, ioaddr + MULTICAST1 );
-- outw( 0, ioaddr + MULTICAST2 );
-- outw( 0, ioaddr + MULTICAST3 );
-- outw( 0, ioaddr + MULTICAST4 );
-+ SMC_SELECT_BANK(3);
-+ smc_outw(0, ioaddr, MULTICAST1);
-+ smc_outw(0, ioaddr, MULTICAST2);
-+ smc_outw(0, ioaddr, MULTICAST3);
-+ smc_outw(0, ioaddr, MULTICAST4);
- }
- }
-
-@@ -1550,21 +1992,26 @@
-
- int init_module(void)
- {
-- int result;
--
- if (io == 0)
-- printk(KERN_WARNING
-- CARDNAME": You shouldn't use auto-probing with insmod!\n" );
-+ printk(KERN_WARNING CARDNAME
-+ ": You shouldn't use auto-probing with insmod!\n");
-+
-+ /*
-+ * Note: dev->if_port has changed to be 2.4 compliant.
-+ * We keep the ifport insmod parameter the same though.
-+ */
-+ switch (ifport) {
-+ case 1: devSMC9194.if_port = IF_PORT_10BASET; break;
-+ case 2: devSMC9194.if_port = IF_PORT_AUI; break;
-+ default: devSMC9194.if_port = 0; break;
-+ }
-
- /* copy the parameters from insmod into the device structure */
- devSMC9194.base_addr = io;
- devSMC9194.irq = irq;
-- devSMC9194.if_port = ifport;
-- devSMC9194.init = smc_init;
-- if ((result = register_netdev(&devSMC9194)) != 0)
-- return result;
-+ devSMC9194.init = smc_init;
-
-- return 0;
-+ return register_netdev(&devSMC9194);
- }
-
- void cleanup_module(void)
---- linux-2.4.25/drivers/net/smc9194.h~2.4.25-vrs2.patch 2001-09-08 21:13:55.000000000 +0200
-+++ linux-2.4.25/drivers/net/smc9194.h 2004-03-31 17:15:09.000000000 +0200
-@@ -63,10 +63,11 @@
-
- #define TCR 0 /* transmit control register */
- #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
-+#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
-+#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
- #define TCR_FDUPLX 0x0800 /* receive packets sent out */
- #define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
--#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
--#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
-+#define TCR_FDSE 0x8000 /* full duplex, switched ethernet */
-
- #define TCR_CLEAR 0 /* do NOTHING */
- /* the normal settings for the TCR register : */
-@@ -107,7 +108,10 @@
- #define CTL_CR_ENABLE 0x40
- #define CTL_TE_ENABLE 0x0020
- #define CTL_AUTO_RELEASE 0x0800
--#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
-+#define CTL_EPROM_SELECT 0x0004
-+#define CTL_EPROM_RELOAD 0x0002
-+#define CTL_EPROM_STORE 0x0001
-+#define CTL_EPROM_ACCESS (CTL_EPROM_RELOAD | CTL_EPROM_STORE) /* high if Eprom is being read */
-
- /* BANK 2 */
- #define MMU_CMD 0
-@@ -130,7 +134,6 @@
- #define PTR_READ 0x2000
- #define PTR_RCV 0x8000
- #define PTR_AUTOINC 0x4000
--#define PTR_AUTO_INC 0x0040
-
- #define DATA_1 8
- #define DATA_2 10
-@@ -162,17 +165,6 @@
- #define CHIP_9195 5
- #define CHIP_91100 7
-
--static const char * chip_ids[ 15 ] = {
-- NULL, NULL, NULL,
-- /* 3 */ "SMC91C90/91C92",
-- /* 4 */ "SMC91C94",
-- /* 5 */ "SMC91C95",
-- NULL,
-- /* 7 */ "SMC91C100",
-- /* 8 */ "SMC91C100FD",
-- NULL, NULL, NULL,
-- NULL, NULL, NULL};
--
- /*
- . Transmit status bits
- */
-@@ -192,40 +184,20 @@
- #define RS_MULTICAST 0x0001
- #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
-
--static const char * interfaces[ 2 ] = { "TP", "AUI" };
--
--/*-------------------------------------------------------------------------
-- . I define some macros to make it easier to do somewhat common
-- . or slightly complicated, repeated tasks.
-- --------------------------------------------------------------------------*/
--
--/* select a register bank, 0 to 3 */
--
--#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); }
--
--/* define a small delay for the reset */
--#define SMC_DELAY() { inw( ioaddr + RCR );\
-- inw( ioaddr + RCR );\
-- inw( ioaddr + RCR ); }
--
--/* this enables an interrupt in the interrupt mask register */
--#define SMC_ENABLE_INT(x) {\
-- unsigned char mask;\
-- SMC_SELECT_BANK(2);\
-- mask = inb( ioaddr + INT_MASK );\
-- mask |= (x);\
-- outb( mask, ioaddr + INT_MASK ); \
--}
--
--/* this disables an interrupt from the interrupt mask register */
-+/*
-+ * SMC91C96 ethernet config and status registers.
-+ * These are in the "attribute" space.
-+ */
-+#define ECOR 0x8000
-+#define ECOR_RESET 0x80
-+#define ECOR_LEVEL_IRQ 0x40
-+#define ECOR_WR_ATTRIB 0x04
-+#define ECOR_ENABLE 0x01
-
--#define SMC_DISABLE_INT(x) {\
-- unsigned char mask;\
-- SMC_SELECT_BANK(2);\
-- mask = inb( ioaddr + INT_MASK );\
-- mask &= ~(x);\
-- outb( mask, ioaddr + INT_MASK ); \
--}
-+#define ECSR 0x8002
-+#define ECSR_IOIS8 0x20
-+#define ECSR_PWRDWN 0x04
-+#define ECSR_INT 0x02
-
- /*----------------------------------------------------------------------
- . Define the interrupts that I want to receive from the card
-@@ -237,5 +209,36 @@
- --------------------------------------------------------------------------*/
- #define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT)
-
-+/* store this information for the driver.. */
-+struct smc_local {
-+ /*
-+ these are things that the kernel wants me to keep, so users
-+ can find out semi-useless statistics of how well the card is
-+ performing
-+ */
-+ struct net_device_stats stats;
-+
-+ /*
-+ If I have to wait until memory is available to send
-+ a packet, I will store the skbuff here, until I get the
-+ desired memory. Then, I'll send it out and free it.
-+ */
-+ struct sk_buff * saved_skb;
-+
-+ /*
-+ . This keeps track of how many packets that I have
-+ . sent out. When an TX_EMPTY interrupt comes, I know
-+ . that all of these have been sent.
-+ */
-+ int packets_waiting;
-+
-+ /*
-+ . Interface status. These correspond to the parameters
-+ . in the ethtool_cmd structure.
-+ */
-+ u8 duplex;
-+ u8 port;
-+};
-+
- #endif /* _SMC_9194_H_ */
-
---- linux-2.4.25/drivers/parport/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/parport/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -27,7 +27,8 @@
- dep_tristate ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA $CONFIG_PCMCIA $CONFIG_PARPORT_PC $CONFIG_HOTPLUG
- fi
- if [ "$CONFIG_ARM" = "y" ]; then
-- dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
-+ dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT $CONFIG_ARCH_ARC
-+ dep_tristate ' Accelent SA1110 IDP' CONFIG_PARPORT_IDP $CONFIG_PARPORT $CONFIG_SA1100_ACCELENT
- fi
- if [ "$CONFIG_AMIGA" = "y" ]; then
- dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
---- linux-2.4.25/drivers/parport/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/parport/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -29,6 +29,7 @@
- obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
- obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
- obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
-+obj-$(CONFIG_PARPORT_IDP) += parport_idp.o
- obj-$(CONFIG_PARPORT_IP22) += parport_ip22.o
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.25/drivers/parport/init.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
-+++ linux-2.4.25/drivers/parport/init.c 2004-03-31 17:15:09.000000000 +0200
-@@ -164,6 +164,9 @@
- #ifdef CONFIG_PARPORT_SUNBPP
- parport_sunbpp_init();
- #endif
-+#ifdef CONFIG_PARPORT_IDP
-+ parport_idp_init();
-+#endif
- return 0;
- }
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/parport/parport_idp.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,247 @@
-+/* Low-level polled-mode parallel port routines for the Accelent IDP
-+ *
-+ * Author: Rich Dulabahn <rich@accelent.com>
-+ *
-+ * Inspiration taken from parport_amiga.c and parport_atari.c.
-+ *
-+ * To use, under menuconfig:
-+ * 1) Turn on <*> Accelent IDP under Parallel port setup
-+ * 2) Turn on <*> Parallel printer support under Character devices
-+ *
-+ * This will give you parport0 configured as /dev/lp0
-+ *
-+ * To make the correct /dev/lp* entries, enter /dev and type this:
-+ *
-+ * mknod lp0 c 6 0
-+ * mknod lp1 c 6 1
-+ * mknod lp2 c 6 2
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/parport.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * Parallel data port is port H, data
-+ * Parallel data direction is port H, direction
-+ * Control port is port I, data, lowest 4 bits
-+ * Status port is port G, data, upper 5 bits
-+ */
-+
-+#define INPUTPOWERHANDLER 0
-+/* masks */
-+#define CONTROL_MASK 0x0f
-+#define STATUS_MASK 0xf8
-+
-+#undef DEBUG
-+
-+#ifdef DEBUG
-+#define DPRINTK printk
-+#else
-+#define DPRINTK(stuff...)
-+#endif
-+
-+static struct parport *this_port = NULL;
-+
-+static unsigned char
-+parport_idp_read_data(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTH_DATA;
-+ DPRINTK("read_data:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_write_data(struct parport *p, unsigned char data)
-+{
-+ IDP_FPGA_PORTH_DATA = data;
-+ DPRINTK("write_data:0x%x\n",data);
-+}
-+
-+static unsigned char
-+parport_idp_read_control(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTI_DATA & CONTROL_MASK;
-+ DPRINTK("read_control:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_write_control(struct parport *p, unsigned char control)
-+{
-+ unsigned int temp;
-+
-+ temp = IDP_FPGA_PORTH_DATA;
-+ temp &= ~CONTROL_MASK;
-+ IDP_FPGA_PORTI_DATA = (temp | (control & CONTROL_MASK));
-+DPRINTK("write_control:0x%x\n",control);
-+}
-+
-+static unsigned char
-+parport_idp_frob_control(struct parport *p, unsigned char mask,
-+ unsigned char val)
-+{
-+ unsigned char c;
-+
-+/* From the parport-lowlevel.txt file...*/
-+/* This is equivalent to reading from the control register, masking out
-+the bits in mask, exclusive-or'ing with the bits in val, and writing
-+the result to the control register. */
-+
-+/* Easy enough, right? */
-+
-+ c = parport_idp_read_control(p);
-+ parport_idp_write_control(p, (c & ~mask) ^ val);
-+ DPRINTK("frob_control:0x%x\n",c);
-+ return c;
-+}
-+
-+static unsigned char
-+parport_idp_read_status(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTG_DATA & STATUS_MASK;
-+ c ^= 0x80; /* toggle S7 bit, active low */
-+ DPRINTK("read_status:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_init_state(struct pardevice *d, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_save_state(struct parport *p, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_restore_state(struct parport *p, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+}
-+
-+static void
-+parport_idp_enable_irq(struct parport *p)
-+{
-+}
-+
-+static void
-+parport_idp_disable_irq(struct parport *p)
-+{
-+}
-+
-+static void
-+parport_idp_data_forward(struct parport *p)
-+{
-+ IDP_FPGA_PORTH_DIR = 0x00; /* 0 sets to output */
-+ DPRINTK("data_forward:0x%x\n",0);
-+}
-+
-+static void
-+parport_idp_data_reverse(struct parport *p)
-+{
-+ IDP_FPGA_PORTH_DIR = 0xff; /* and 1 sets to input */
-+ DPRINTK("data_reverse:0x%x\n",0xff);
-+}
-+
-+static void
-+parport_idp_inc_use_count(void)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void
-+parport_idp_dec_use_count(void)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static struct parport_operations parport_idp_ops = {
-+ parport_idp_write_data,
-+ parport_idp_read_data,
-+
-+ parport_idp_write_control,
-+ parport_idp_read_control,
-+ parport_idp_frob_control,
-+
-+ parport_idp_read_status,
-+
-+ parport_idp_enable_irq,
-+ parport_idp_disable_irq,
-+
-+ parport_idp_data_forward,
-+ parport_idp_data_reverse,
-+
-+ parport_idp_init_state,
-+ parport_idp_save_state,
-+ parport_idp_restore_state,
-+
-+ parport_idp_inc_use_count,
-+ parport_idp_dec_use_count,
-+
-+ parport_ieee1284_epp_write_data,
-+ parport_ieee1284_epp_read_data,
-+ parport_ieee1284_epp_write_addr,
-+ parport_ieee1284_epp_read_addr,
-+
-+ parport_ieee1284_ecp_write_data,
-+ parport_ieee1284_ecp_read_data,
-+ parport_ieee1284_ecp_write_addr,
-+
-+ parport_ieee1284_write_compat,
-+ parport_ieee1284_read_nibble,
-+ parport_ieee1284_read_byte,
-+};
-+
-+
-+int __init
-+parport_idp_init(void)
-+{
-+ struct parport *p;
-+
-+ p = parport_register_port((unsigned long)0,PARPORT_IRQ_NONE,PARPORT_DMA_NONE,&parport_idp_ops);
-+
-+ if (!p) return 0; /* return 0 on failure */
-+
-+ this_port=p;
-+ printk("%s: Accelent IDP parallel port registered.\n", p->name);
-+ parport_proc_register(p);
-+ parport_announce_port(p);
-+
-+ return 1;
-+}
-+
-+#ifdef MODULE
-+
-+MODULE_AUTHOR("Rich Dulabahn");
-+MODULE_DESCRIPTION("Parport Driver for Accelent IDP");
-+MODULE_SUPPORTED_DEVICE("Accelent IDP builtin Parallel Port");
-+MODULE_LICENSE("GPL");
-+
-+int
-+init_module(void)
-+{
-+ return parport_idp_init() ? 0 : -ENODEV;
-+}
-+
-+void
-+cleanup_module(void)
-+{
-+ parport_proc_unregister(this_port);
-+ parport_unregister_port(this_port);
-+}
-+#endif
-+
---- linux-2.4.25/drivers/pci/Makefile~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/pci/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -13,7 +13,7 @@
-
- export-objs := pci.o
-
--obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
-+obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o bridge.o
- obj-$(CONFIG_PROC_FS) += proc.o
-
- ifndef CONFIG_SPARC64
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pci/bridge.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,149 @@
-+
-+/*
-+ * Copyright (c) 2001 Red Hat, Inc. All rights reserved.
-+ *
-+ * This software may be freely redistributed under the terms
-+ * of the GNU public license.
-+ *
-+ * You 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.
-+ *
-+ * Author: Arjan van de Ven <arjanv@redhat.com>
-+ *
-+ */
-+
-+
-+/*
-+ * Generic PCI driver for PCI bridges for powermanagement purposes
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+
-+static struct pci_device_id bridge_pci_table[] __devinitdata = {
-+ {/* handle all PCI bridges */
-+ class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
-+ class_mask: ~0,
-+ vendor: PCI_ANY_ID,
-+ device: PCI_ANY_ID,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+ },
-+ {0,},
-+};
-+
-+static int bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force);
-+int pci_generic_resume_compare(struct pci_dev *pdev);
-+
-+int pci_bridge_force_restore = 0;
-+
-+
-+
-+
-+static int __init bridge_setup(char *str)
-+{
-+ if (!strcmp(str,"force"))
-+ pci_bridge_force_restore = 1;
-+ else if (!strcmp(str,"noforce"))
-+ pci_bridge_force_restore = 0;
-+ return 0;
-+}
-+
-+__setup("resume=",bridge_setup);
-+
-+
-+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force)
-+{
-+ struct list_head *list;
-+ int error = 0;
-+
-+ list_for_each(list, &bus->children) {
-+ error = pci_bridge_save_state_bus(pci_bus_b(list),force);
-+ if (error) return error;
-+ }
-+ list_for_each(list, &bus->devices) {
-+ pci_generic_suspend_save(pci_dev_b(list),0);
-+ }
-+ return 0;
-+}
-+
-+
-+static int pci_bridge_restore_state_bus(struct pci_bus *bus, int force)
-+{
-+ struct list_head *list;
-+ int error = 0;
-+ static int printed_warning=0;
-+
-+ list_for_each(list, &bus->children) {
-+ error = pci_bridge_restore_state_bus(pci_bus_b(list),force);
-+ if (error) return error;
-+ }
-+ list_for_each(list, &bus->devices) {
-+ if (force)
-+ pci_generic_resume_restore(pci_dev_b(list));
-+ else {
-+ error = pci_generic_resume_compare(pci_dev_b(list));
-+ if (error && !printed_warning++) {
-+ printk(KERN_WARNING "resume warning: bios doesn't restore PCI state properly\n");
-+ printk(KERN_WARNING "resume warning: if resume failed, try booting with resume=force\n");
-+ }
-+ if (error)
-+ return error;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int bridge_suspend(struct pci_dev *dev, u32 force)
-+{
-+ pci_generic_suspend_save(dev,force);
-+ if (dev->subordinate)
-+ pci_bridge_save_state_bus(dev->subordinate,force);
-+ return 0;
-+}
-+
-+static int bridge_resume(struct pci_dev *dev)
-+{
-+
-+ pci_generic_resume_restore(dev);
-+ if (dev->subordinate)
-+ pci_bridge_restore_state_bus(dev->subordinate,pci_bridge_force_restore);
-+ return 0;
-+}
-+
-+
-+MODULE_DEVICE_TABLE(pci, bridge_pci_table);
-+static struct pci_driver bridge_ops = {
-+ name: "PCI Bridge",
-+ id_table: bridge_pci_table,
-+ probe: bridge_probe,
-+ suspend: bridge_suspend,
-+ resume: bridge_resume
-+};
-+
-+static int __devinit bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-+{
-+ return 0;
-+}
-+
-+static int __init bridge_init(void)
-+{
-+ pci_register_driver(&bridge_ops);
-+ return 0;
-+}
-+
-+static void __exit bridge_exit(void)
-+{
-+ pci_unregister_driver(&bridge_ops);
-+}
-+
-+
-+module_init(bridge_init)
-+module_exit(bridge_exit)
-+
---- linux-2.4.25/drivers/pci/pci.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/pci/pci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -359,6 +359,48 @@
- return 0;
- }
-
-+int
-+pci_compare_state(struct pci_dev *dev, u32 *buffer)
-+{
-+ int i;
-+ unsigned int temp;
-+
-+ if (buffer) {
-+ for (i = 0; i < 16; i++) {
-+ pci_read_config_dword(dev,i*4,&temp);
-+ if (temp!=buffer[i])
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state)
-+{
-+ if (pdev)
-+ pci_save_state(pdev,pdev->saved_state);
-+ return 0;
-+}
-+
-+int pci_generic_resume_restore(struct pci_dev *pdev)
-+{
-+ if (pdev)
-+ pci_restore_state(pdev,pdev->saved_state);
-+ return 0;
-+}
-+
-+int pci_generic_resume_compare(struct pci_dev *pdev)
-+{
-+ int retval=0;
-+ if (pdev)
-+ retval = pci_compare_state(pdev,pdev->saved_state);
-+ return retval;
-+}
-+
-+EXPORT_SYMBOL(pci_generic_suspend_save);
-+EXPORT_SYMBOL(pci_generic_resume_restore);
-+EXPORT_SYMBOL(pci_generic_resume_compare);
-+
- /**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
---- linux-2.4.25/drivers/pci/setup-bus.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
-+++ linux-2.4.25/drivers/pci/setup-bus.c 2004-03-31 17:15:09.000000000 +0200
-@@ -12,6 +12,8 @@
- /*
- * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
- * PCI-PCI bridges cleanup, sorted resource allocation.
-+ * May 2001, Russell King <rmk@arm.linux.org.uk>
-+ * Allocate prefetchable memory regions where available.
- * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
- * Converted to allocation in 3 passes, which gives
- * tighter packing. Prefetchable range support.
-@@ -160,8 +162,10 @@
- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
-
- /* Check if we have VGA behind the bridge.
-- Enable ISA in either case (FIXME!). */
-- l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
-+ Enable ISA in either case. */
-+ l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ?
-+ PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_NO_ISA :
-+ PCI_BRIDGE_CTL_NO_ISA;
- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
- }
-
---- linux-2.4.25/drivers/pcmcia/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -14,21 +14,19 @@
-
- tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA
- if [ "$CONFIG_PCMCIA" != "n" ]; then
-+ # yes, I really mean the following...
-+ if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ define_bool CONFIG_PCMCIA_PROBE y
-+ fi
- if [ "$CONFIG_PCI" != "n" ]; then
- bool ' CardBus support' CONFIG_CARDBUS
- fi
-+ dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
-+ bool ' i82365 compatible bridge support' CONFIG_I82365
- bool ' Databook TCIC host bridge support' CONFIG_TCIC
- if [ "$CONFIG_HD64465" = "y" ]; then
- dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
- fi
-- dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
-- bool ' i82365 compatible bridge support' CONFIG_I82365
-- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_PCMCIA
-- fi
-- if [ "$CONFIG_8xx" = "y" ]; then
-- dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA
-- fi
- if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
- dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
- if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then
-@@ -44,5 +42,9 @@
- dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA
- fi
- fi
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
-+ dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
-+fi
-
- endmenu
---- linux-2.4.25/drivers/pcmcia/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -65,15 +65,18 @@
- au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o
- au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o
-
-+obj-$(CONFIG_PCMCIA_CLPS6700) += clps6700.o
- obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
--obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
- obj-$(CONFIG_PCMCIA_SIBYTE) += sibyte_generic.o
-
- sa1100_cs-objs-y := sa1100_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_ADSAGC) += sa1100_graphicsmaster.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSYPLUS) += sa1100_adsbitsyplus.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
- sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_CONSUS) += sa1100_neponset.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
- sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
- sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
---- linux-2.4.25/drivers/pcmcia/cistpl.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/cistpl.c 2004-03-31 17:15:09.000000000 +0200
-@@ -286,7 +286,7 @@
- s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
- if (!(s->cap.features & SS_CAP_STATIC_MAP))
-- release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
-+ release_mem_resource(s->cis_mem.sys_start, s->cap.map_size);
- bus_iounmap(s->cap.bus, s->cis_virt);
- s->cis_mem.sys_start = 0;
- s->cis_virt = NULL;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/clps6700.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,498 @@
-+/*
-+ * linux/drivers/pcmcia/clps6700.c
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/proc_fs.h>
-+#include <linux/spinlock.h>
-+#include <linux/init.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/page.h>
-+
-+#include <asm/arch/syspld.h>
-+#include <asm/hardware/clps7111.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/ss.h>
-+
-+#include "clps6700.h"
-+
-+#define DEBUG
-+
-+MODULE_AUTHOR("Russell King");
-+MODULE_DESCRIPTION("CL-PS6700 PCMCIA socket driver");
-+
-+#define NR_CLPS6700 2
-+
-+struct clps6700_skt {
-+ u_int nr;
-+ u_int physbase;
-+ u_int regbase;
-+ u_int pmr;
-+ u_int cpcr;
-+ u_int cpcr_3v3;
-+ u_int cpcr_5v0;
-+ u_int cur_pmr;
-+ u_int cur_cicr;
-+ u_int cur_pcimr;
-+ u_int cur_cpcr;
-+ void (*handler)(void *, u_int);
-+ void *handler_info;
-+
-+ u_int ev_pending;
-+ spinlock_t ev_lock;
-+};
-+
-+static struct clps6700_skt *skts[NR_CLPS6700];
-+
-+static int clps6700_sock_init(u_int sock)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+ skt->cur_cicr = 0;
-+ skt->cur_pmr = skt->pmr;
-+ skt->cur_pcimr = 0;
-+ skt->cur_cpcr = skt->cpcr;
-+
-+#ifdef DEBUG
-+ printk("skt%d: sock_init()\n", sock);
-+#endif
-+
-+ __raw_writel(skt->cur_pmr, skt->regbase + PMR);
-+ __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
-+ __raw_writel(0x01f8, skt->regbase + SICR);
-+ __raw_writel(0x0000, skt->regbase + DMACR);
-+ __raw_writel(skt->cur_cicr, skt->regbase + CICR);
-+ __raw_writel(0x1f00, skt->regbase + CITR0A);
-+ __raw_writel(0x0000, skt->regbase + CITR0B);
-+ __raw_writel(0x1f00, skt->regbase + CITR1A);
-+ __raw_writel(0x0000, skt->regbase + CITR1B);
-+ __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
-+
-+ /*
-+ * Enable Auto Idle Mode in PM register
-+ */
-+ __raw_writel(-1, skt->regbase + PCIRR1);
-+ __raw_writel(-1, skt->regbase + PCIRR2);
-+ __raw_writel(-1, skt->regbase + PCIRR3);
-+
-+ return 0;
-+}
-+
-+static int clps6700_suspend(u_int sock)
-+{
-+ return 0;
-+}
-+
-+static int clps6700_register_callback(u_int sock, void (*handler)(void *, u_int), void *info)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+#ifdef DEBUG
-+ printk("skt%d: register_callback: %p (%p)\n", sock, handler, info);
-+#endif
-+
-+ skt->handler_info = info;
-+ skt->handler = handler;
-+
-+ return 0;
-+}
-+
-+static int clps6700_inquire_socket(u_int sock, socket_cap_t *cap)
-+{
-+ cap->features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN;
-+ cap->irq_mask = 0; /* available IRQs for this socket */
-+ cap->map_size = PAGE_SIZE; /* minimum mapping size */
-+ cap->pci_irq = 0; /* PCI interrupt number */
-+ cap->cb_dev = NULL;
-+ cap->bus = NULL;
-+ return 0;
-+}
-+
-+static int __clps6700_get_status(struct clps6700_skt *skt)
-+{
-+ unsigned int v, val;
-+
-+ v = __raw_readl(skt->regbase + PCIILR);
-+ val = 0;
-+ if ((v & (PCM_CD1 | PCM_CD2)) == 0)
-+ val |= SS_DETECT;
-+ if ((v & (PCM_BVD2 | PCM_BVD1)) == PCM_BVD1)
-+ val |= SS_BATWARN;
-+ if ((v & PCM_BVD2) == 0)
-+ val |= SS_BATDEAD;
-+
-+ if (v & PCM_RDYL)
-+ val |= SS_READY;
-+ if (v & PCM_VS1)
-+ val |= SS_3VCARD;
-+ if (v & PCM_VS2)
-+ val |= SS_XVCARD;
-+
-+#ifdef DEBUG
-+ printk("skt%d: PCIILR: %08x -> (%s %s %s %s %s %s)\n",
-+ skt->nr, v,
-+ val & SS_READY ? "rdy" : "---",
-+ val & SS_DETECT ? "det" : "---",
-+ val & SS_BATWARN ? "bw" : "--",
-+ val & SS_BATDEAD ? "bd" : "--",
-+ val & SS_3VCARD ? "3v" : "--",
-+ val & SS_XVCARD ? "xv" : "--");
-+#endif
-+ return val;
-+}
-+
-+static int clps6700_get_status(u_int sock, u_int *valp)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+ *valp = __clps6700_get_status(skt);
-+
-+ return 0; /* not used! */
-+}
-+
-+static int clps6700_get_socket(u_int sock, socket_state_t *state)
-+{
-+ return -EINVAL;
-+}
-+
-+static int clps6700_set_socket(u_int sock, socket_state_t *state)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+ unsigned long flags;
-+ u_int cpcr = skt->cur_cpcr, pmr = skt->cur_pmr, cicr = skt->cur_cicr;
-+ u_int pcimr = 0;
-+
-+ cicr &= ~(CICR_ENABLE | CICR_RESET | CICR_IOMODE);
-+
-+ if (state->flags & SS_PWR_AUTO)
-+ pmr |= PMR_DCAR | PMR_PDCR;
-+
-+ /*
-+ * Note! We must NOT assert the Card Enable bit until reset has
-+ * been de-asserted. Some cards indicate not ready, which then
-+ * hangs our next access. (Bug in CLPS6700?)
-+ */
-+ if (state->flags & SS_RESET)
-+ cicr |= CICR_RESET | CICR_RESETOE;
-+ else if (state->flags & SS_OUTPUT_ENA)
-+ cicr |= CICR_ENABLE;
-+
-+ if (state->flags & SS_IOCARD) {
-+ cicr |= CICR_IOMODE;
-+
-+/* if (state->csc_mask & SS_STSCHG)*/
-+ } else {
-+ if (state->csc_mask & SS_BATDEAD)
-+ pcimr |= PCM_BVD2;
-+ if (state->csc_mask & SS_BATWARN)
-+ pcimr |= PCM_BVD1;
-+ if (state->csc_mask & SS_READY)
-+ pcimr |= PCM_RDYL;
-+ }
-+
-+ if (state->csc_mask & SS_DETECT)
-+ pcimr |= PCM_CD1 | PCM_CD2;
-+
-+ switch (state->Vcc) {
-+ case 0: break;
-+ case 33: cpcr |= skt->cpcr_3v3; pmr |= PMR_CPE; break;
-+ case 50: cpcr |= skt->cpcr_5v0; pmr |= PMR_CPE; break;
-+ default: return -EINVAL;
-+ }
-+
-+#ifdef DEBUG
-+ printk("skt%d: PMR: %04x, CPCR: %04x, CICR: %04x PCIMR: %04x "
-+ "(Vcc = %d, flags = %c%c%c%c, csc = %c%c%c%c%c)\n",
-+ sock, pmr, cpcr, cicr, pcimr, state->Vcc,
-+ state->flags & SS_RESET ? 'r' : '-',
-+ state->flags & SS_PWR_AUTO ? 'p' : '-',
-+ state->flags & SS_IOCARD ? 'i' : '-',
-+ state->flags & SS_OUTPUT_ENA ? 'o' : '-',
-+ state->csc_mask & SS_STSCHG ? 's' : '-',
-+ state->csc_mask & SS_BATDEAD ? 'd' : '-',
-+ state->csc_mask & SS_BATWARN ? 'w' : '-',
-+ state->csc_mask & SS_READY ? 'r' : '-',
-+ state->csc_mask & SS_DETECT ? 'c' : '-');
-+#endif
-+
-+ save_flags_cli(flags);
-+
-+ if (skt->cur_cpcr != cpcr) {
-+ skt->cur_cpcr = cpcr;
-+ __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
-+ }
-+
-+ if (skt->cur_pmr != pmr) {
-+ skt->cur_pmr = pmr;
-+ __raw_writel(skt->cur_pmr, skt->regbase + PMR);
-+ }
-+ if (skt->cur_pcimr != pcimr) {
-+ skt->cur_pcimr = pcimr;
-+ __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
-+ }
-+ if (skt->cur_cicr != cicr) {
-+ skt->cur_cicr = cicr;
-+ __raw_writel(skt->cur_cicr, skt->regbase + CICR);
-+ }
-+
-+ restore_flags(flags);
-+
-+ return 0;
-+}
-+
-+static int clps6700_get_io_map(u_int sock, struct pccard_io_map *io)
-+{
-+ return -EINVAL;
-+}
-+
-+static int clps6700_set_io_map(u_int sock, struct pccard_io_map *io)
-+{
-+ printk("skt%d: iomap: %d: speed %d, flags %X start %X stop %X\n",
-+ sock, io->map, io->speed, io->flags, io->start, io->stop);
-+ return 0;
-+}
-+
-+static int clps6700_get_mem_map(u_int sock, struct pccard_mem_map *mem)
-+{
-+ return -EINVAL;
-+}
-+
-+/*
-+ * Set the memory map attributes for this socket. (ie, mem->speed)
-+ * Note that since we have SS_CAP_STATIC_MAP set, we don't need to do
-+ * any mapping here at all; we just need to return the address (suitable
-+ * for ioremap) to map the requested space in mem->sys_start.
-+ *
-+ * flags & MAP_ATTRIB indicates whether we want attribute space.
-+ */
-+static int clps6700_set_mem_map(u_int sock, struct pccard_mem_map *mem)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+ u_int off;
-+
-+ printk("skt%d: memmap: %d: speed %d, flags %X start %lX stop %lX card %X\n",
-+ sock, mem->map, mem->speed, mem->flags, mem->sys_start,
-+ mem->sys_stop, mem->card_start);
-+
-+ if (mem->flags & MAP_ATTRIB)
-+ off = CLPS6700_ATTRIB_BASE;
-+ else
-+ off = CLPS6700_MEM_BASE;
-+
-+ mem->sys_start = skt->physbase + off;
-+ mem->sys_start += mem->card_start;
-+
-+ return 0;
-+}
-+
-+static void clps6700_proc_setup(u_int sock, struct proc_dir_entry *base)
-+{
-+}
-+
-+static struct pccard_operations clps6700_operations = {
-+ init: clps6700_sock_init,
-+ suspend: clps6700_suspend,
-+ register_callback: clps6700_register_callback,
-+ inquire_socket: clps6700_inquire_socket,
-+ get_status: clps6700_get_status,
-+ get_socket: clps6700_get_socket,
-+ set_socket: clps6700_set_socket,
-+ get_io_map: clps6700_get_io_map,
-+ set_io_map: clps6700_set_io_map,
-+ get_mem_map: clps6700_get_mem_map,
-+ set_mem_map: clps6700_set_mem_map,
-+ proc_setup: clps6700_proc_setup
-+};
-+
-+static void clps6700_bh(void *dummy)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_CLPS6700; i++) {
-+ struct clps6700_skt *skt = skts[i];
-+ unsigned long flags;
-+ u_int events;
-+
-+ if (!skt)
-+ continue;
-+
-+ /*
-+ * Note! We must read the pending event state
-+ * with interrupts disabled, otherwise we race
-+ * with our own interrupt routine!
-+ */
-+ spin_lock_irqsave(&skt->ev_lock, flags);
-+ events = skt->ev_pending;
-+ skt->ev_pending = 0;
-+ spin_unlock_irqrestore(&skt->ev_lock, flags);
-+
-+ if (skt->handler && events)
-+ skt->handler(skt->handler_info, events);
-+ }
-+}
-+
-+static struct tq_struct clps6700_task = {
-+ routine: clps6700_bh
-+};
-+
-+static void clps6700_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct clps6700_skt *skt = dev_id;
-+ u_int val, events;
-+
-+ val = __raw_readl(skt->regbase + PCISR);
-+ if (!val)
-+ return;
-+
-+ __raw_writel(val, skt->regbase + PCICR);
-+
-+ events = 0;
-+ if (val & (PCM_CD1 | PCM_CD2))
-+ events |= SS_DETECT;
-+ if (val & PCM_BVD1)
-+ events |= SS_BATWARN;
-+ if (val & PCM_BVD2)
-+ events |= SS_BATDEAD;
-+ if (val & PCM_RDYL)
-+ events |= SS_READY;
-+
-+ spin_lock(&skt->ev_lock);
-+ skt->ev_pending |= events;
-+ spin_unlock(&skt->ev_lock);
-+ schedule_task(&clps6700_task);
-+}
-+
-+static int __init clps6700_init_skt(int nr)
-+{
-+ struct clps6700_skt *skt;
-+ int ret;
-+
-+ skt = kmalloc(sizeof(struct clps6700_skt), GFP_KERNEL);
-+ if (!skt)
-+ return -ENOMEM;
-+
-+ memset(skt, 0, sizeof(struct clps6700_skt));
-+
-+ spin_lock_init(&skt->ev_lock);
-+
-+ skt->nr = nr;
-+ skt->physbase = nr ? CS5_PHYS_BASE : CS4_PHYS_BASE;
-+ skt->pmr = PMR_AUTOIDLE | PMR_MCPE | PMR_CDWEAK;
-+ skt->cpcr = CPCR_PDIR(PCTL1|PCTL0);
-+ skt->cpcr_3v3 = CPCR_PON(PCTL0);
-+ skt->cpcr_5v0 = CPCR_PON(PCTL0); /* we only do 3v3 */
-+
-+ skt->cur_pmr = skt->pmr;
-+
-+ skt->regbase = (u_int)ioremap(skt->physbase + CLPS6700_REG_BASE,
-+ CLPS6700_REG_SIZE);
-+ ret = -ENOMEM;
-+ if (!skt->regbase)
-+ goto err_free;
-+
-+ skts[nr] = skt;
-+
-+ ret = request_irq(IRQ_EINT3, clps6700_interrupt,
-+ SA_SHIRQ, "pcmcia", skt);
-+
-+ if (ret) {
-+ printk(KERN_ERR "clps6700: unable to grab irq%d (%d)\n",
-+ IRQ_EINT3, ret);
-+ goto err_unmap;
-+ }
-+ return 0;
-+
-+err_unmap:
-+ iounmap((void *)skt->regbase);
-+err_free:
-+ kfree(skt);
-+ skts[nr] = NULL;
-+ return ret;
-+}
-+
-+static void clps6700_free_resources(void)
-+{
-+ int i;
-+
-+ for (i = NR_CLPS6700; i >= 0; i--) {
-+ struct clps6700_skt *skt = skts[i];
-+
-+ skts[i] = NULL;
-+ if (skt == NULL)
-+ continue;
-+
-+ free_irq(IRQ_EINT3, skt);
-+ if (skt->regbase) {
-+ __raw_writel(skt->pmr, skt->regbase + PMR);
-+ __raw_writel(skt->cpcr, skt->regbase + CPCR);
-+ __raw_writel(0, skt->regbase + CICR);
-+ __raw_writel(0, skt->regbase + PCIMR);
-+ }
-+ iounmap((void *)skt->regbase);
-+ kfree(skt);
-+ }
-+}
-+
-+static int __init clps6700_init(void)
-+{
-+ unsigned int v;
-+ int err, nr;
-+
-+ PLD_CF = 0;
-+ v = clps_readl(SYSCON2) | SYSCON2_PCCARD1 | SYSCON2_PCCARD2;
-+ clps_writel(v, SYSCON2);
-+ v = clps_readl(SYSCON1) | SYSCON1_EXCKEN;
-+ clps_writel(v, SYSCON1);
-+
-+ for (nr = 0; nr < NR_CLPS6700; nr++) {
-+ err = clps6700_init_skt(nr);
-+ if (err)
-+ goto free;
-+ }
-+
-+ err = register_ss_entry(nr, &clps6700_operations);
-+ if (err)
-+ goto free;
-+
-+ return 0;
-+
-+free:
-+ clps6700_free_resources();
-+ /*
-+ * An error occurred. Unmap and free all CLPS6700
-+ */
-+ return err;
-+}
-+
-+static void __exit clps6700_exit(void)
-+{
-+ unregister_ss_entry(&clps6700_operations);
-+ clps6700_free_resources();
-+}
-+
-+module_init(clps6700_init);
-+module_exit(clps6700_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/clps6700.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,85 @@
-+#define PCISR 0x0000 /* PC Card Interrupt Status Register */
-+#define PCIMR 0x0400 /* PC Card Interrupt Mask Register */
-+#define PCICR 0x0800 /* PC Card Interrupt Clear Register */
-+#define PCIOSR 0x0c00 /* PC Card Interrupt Output Select Regsiter */
-+#define PCIRR1 0x1000 /* PC Card Interrupt Reserved Register 1 */
-+#define PCIRR2 0x1400 /* PC Card Interrupt Reserved Register 2 */
-+#define PCIRR3 0x1800 /* PC Card Interrupt Reserved Register 3 */
-+#define PCIILR 0x1c00 /* PC Card Interrupt Input Level Register */
-+#define SICR 0x2000 /* System Interface Configuration Register */
-+#define CICR 0x2400 /* Card Interface Configuration Register */
-+#define PMR 0x2800 /* Power Management Register */
-+#define CPCR 0x2c00 /* Card Power Control Register */
-+#define CITR0A 0x3000 /* Card Interface Timing Register 0A */
-+#define CITR0B 0x3400 /* Card Interface Timing Register 0B */
-+#define CITR1A 0x3800 /* Card Interface Timing Register 1A */
-+#define CITR1B 0x3c00 /* Card Interface Timing Register 1B */
-+#define DMACR 0x4000 /* DMA Control Register */
-+#define DIR 0x4400 /* Device Information Register */
-+
-+#define CLPS6700_ATTRIB_BASE 0x00000000
-+#define CLPS6700_IO_BASE 0x04000000
-+#define CLPS6700_MEM_BASE 0x08000000
-+#define CLPS6700_REG_BASE 0x0c000000
-+#define CLPS6700_REG_SIZE 0x00005000
-+
-+
-+#define PMR_AUTOIDLE (1 << 0) /* auto idle mode */
-+#define PMR_FORCEIDLE (1 << 1) /* force idle mode */
-+#define PMR_PDCS (1 << 2) /* Power down card on standby */
-+#define PMR_PDCR (1 << 3) /* Power down card on removal */
-+#define PMR_DCAR (1 << 4) /* Disable card access on removal */
-+#define PMR_CPE (1 << 5) /* Card power enable */
-+#define PMR_MCPE (1 << 6) /* Monitor card power enable */
-+#define PMR_PDREQLSEL (1 << 7) /* If set, PDREQL is a GPIO pin */
-+#define PMR_DISSTBY (1 << 8) /* Disable standby */
-+#define PMR_ACCSTBY (1 << 9) /* Complete card accesses before standby*/
-+#define PMR_CDUNPROT (0 << 10) /* Card detect inputs unprotected */
-+#define PMR_CDPROT (1 << 10) /* Card detect inputs protected */
-+#define PMR_CDWEAK (2 << 10) /* Weak pullup except in standby */
-+#define PMR_CDWEAKAL (3 << 10) /* Weak pullup */
-+
-+#define CPCR_PON(x) ((x)&7) /* PCTL[2:0] value when PMR_CPE = 1 */
-+#define CPCR_POFF(x) (((x)&7)<<3) /* PCTL[2:0] value when PMR_CPE = 0 */
-+#define CPCR_PDIR(x) (((x)&7)<<6) /* PCTL[2:0] direction */
-+#define CPCR_CON(x) (((x)&1)<<9) /* GPIO value when PMR_CPE = 1 */
-+#define CPCR_COFF(x) (((x)&1)<<10) /* GPIO value when PMR_CPE = 0 */
-+#define CPCR_CDIR(x) (((x)&1)<<11) /* GPIO direction (PMR_PDREQLSEL = 1) */
-+#define CPCR_VS(x) (((x)&3)<<12) /* VS[2:1] output value */
-+#define CPCR_VSDIR(x) (((x)&3)<<14) /* VS[2:1] direction */
-+
-+#define PCTL0 (1 << 0)
-+#define PCTL1 (1 << 1)
-+#define PCTL2 (1 << 2)
-+
-+#define CICR_ASRTMR1 (1 << 0) /* Timer 1 select for attribute read */
-+#define CICR_ASWTMR1 (1 << 1) /* Timer 1 select for attribute write */
-+#define CICR_IOSRTMR1 (1 << 2) /* Timer 1 select for IO read */
-+#define CICR_IOSWTMR1 (1 << 3) /* Timer 1 select for IO write */
-+#define CICR_MEMSRTMR1 (1 << 4) /* Timer 1 select for memory read */
-+#define CICR_MEMSWTMR1 (1 << 5) /* Timer 1 select for memory write */
-+#define CICR_AUTOIOSZ (1 << 6) /* Auto size I/O accesses */
-+#define CICR_CAW (1 << 7) /* Card access width */
-+#define CICR_IOMODE (1 << 8) /* IO mode select */
-+#define CICR_ENABLE (1 << 10) /* Card enable */
-+#define CICR_RESETOE (1 << 11) /* Card reset output enable */
-+#define CICR_RESET (1 << 12) /* Card reset */
-+
-+
-+#define RD_FAIL (1 << 14)
-+#define WR_FAIL (1 << 13)
-+#define IDLE (1 << 12)
-+
-+#define FFOTHLD (1 << 11)
-+#define PCM_RDYL (1 << 10)
-+#define PCM_WP (1 << 9)
-+#define PCTL (1 << 8)
-+
-+#define PDREQ_L (1 << 6)
-+#define PCM_VS2 (1 << 5)
-+#define PCM_VS1 (1 << 4)
-+
-+#define PCM_CD2 (1 << 3)
-+#define PCM_CD1 (1 << 2)
-+#define PCM_BVD2 (1 << 1)
-+#define PCM_BVD1 (1 << 0)
---- linux-2.4.25/drivers/pcmcia/cs.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/cs.c 2004-03-31 17:15:09.000000000 +0200
-@@ -3,7 +3,7 @@
- Kernel Card Services -- core services
-
- cs.c 1.271 2000/10/02 20:27:49
--
-+
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #include <linux/module.h>
-@@ -92,7 +92,7 @@
- MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
- MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE
- "\n options:" OPTIONS);
--MODULE_LICENSE("Dual MPL/GPL");
-+MODULE_LICENSE("Dual MPL/GPL");
-
- #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
-@@ -123,7 +123,7 @@
- static const char *version =
- "cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
- #endif
--
-+
- /*====================================================================*/
-
- socket_state_t dead_socket = {
-@@ -299,7 +299,7 @@
-
- Low-level PC Card interface drivers need to register with Card
- Services using these calls.
--
-+
- ======================================================================*/
-
- static int setup_socket(socket_info_t *);
-@@ -331,7 +331,7 @@
- s->use_bus_pm = use_bus_pm;
- s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
- spin_lock_init(&s->lock);
--
-+
- for (i = 0; i < sockets; i++)
- if (socket_table[i] == NULL) break;
- socket_table[i] = s;
-@@ -365,7 +365,7 @@
- for (ns = 0; ns < nsock; ns++) {
- pcmcia_register_socket (ns, ss_entry, 0);
- }
--
-+
- return 0;
- } /* register_ss_entry */
-
-@@ -457,7 +457,7 @@
- static void shutdown_socket(socket_info_t *s)
- {
- client_t **c;
--
-+
- DEBUG(1, "cs: shutdown_socket(%p)\n", s);
-
- /* Blank out the socket state */
-@@ -561,7 +561,7 @@
- have several causes: card insertion, a call to reset_socket, or
- recovery from a suspend/resume cycle. Unreset_socket() sends
- a CS event that matches the cause of the reset.
--
-+
- ======================================================================*/
-
- static void reset_socket(socket_info_t *s)
-@@ -616,7 +616,7 @@
- s->state &= ~SOCKET_SETUP_PENDING;
- } else {
- send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
-- if (s->reset_handle) {
-+ if (s->reset_handle) {
- s->reset_handle->event_callback_args.info = NULL;
- EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
- CS_EVENT_PRI_LOW);
-@@ -631,7 +631,7 @@
- valid clients. Parse_events() interprets the event bits from
- a card status change report. Do_shutdown() handles the high
- priority stuff associated with a card removal.
--
-+
- ======================================================================*/
-
- static int send_event(socket_info_t *s, event_t event, int priority)
-@@ -641,7 +641,7 @@
- DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
- s->sock, event, priority);
- ret = 0;
-- for (; client; client = client->next) {
-+ for (; client; client = client->next) {
- if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
- continue;
- if (client->EventMask & event) {
-@@ -675,10 +675,17 @@
- static void parse_events(void *info, u_int events)
- {
- socket_info_t *s = info;
-+
- if (events & SS_DETECT) {
- int status;
-
- get_socket_status(s, &status);
-+
-+ /*
-+ * If our socket state indicates that a card is present and
-+ * either the socket has not been suspended (for some reason)
-+ * or the card has been removed, shut down the socket first.
-+ */
- if ((s->state & SOCKET_PRESENT) &&
- (!(s->state & SOCKET_SUSPEND) ||
- !(status & SS_DETECT)))
-@@ -716,7 +723,7 @@
-
- This does not comply with the latest PC Card spec for handling
- power management events.
--
-+
- ======================================================================*/
-
- void pcmcia_suspend_socket (socket_info_t *s)
-@@ -773,7 +780,7 @@
- /*======================================================================
-
- Special stuff for managing IO windows, because they are scarce.
--
-+
- ======================================================================*/
-
- static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
-@@ -862,7 +869,7 @@
- Access_configuration_register() reads and writes configuration
- registers in attribute memory. Memory window 0 is reserved for
- this and the tuple reading services.
--
-+
- ======================================================================*/
-
- int pcmcia_access_configuration_register(client_handle_t handle,
-@@ -872,7 +879,7 @@
- config_t *c;
- int addr;
- u_char val;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -890,7 +897,7 @@
- return CS_CONFIGURATION_LOCKED;
-
- addr = (c->ConfigBase + reg->Offset) >> 1;
--
-+
- switch (reg->Action) {
- case CS_READ:
- read_cis_mem(s, 1, addr, 1, &val);
-@@ -913,7 +920,7 @@
- It is normally called by Driver Services after it has identified
- a newly inserted card. An instance of that driver will then be
- eligible to register as a client of this socket.
--
-+
- ======================================================================*/
-
- int pcmcia_bind_device(bind_req_t *req)
-@@ -949,23 +956,23 @@
- region. It is normally called by Driver Services after it has
- identified a memory device type. An instance of the corresponding
- driver will then be able to register to control this region.
--
-+
- ======================================================================*/
-
- int pcmcia_bind_mtd(mtd_bind_t *req)
- {
- socket_info_t *s;
- memory_handle_t region;
--
-+
- if (CHECK_SOCKET(req->Socket))
- return CS_BAD_SOCKET;
- s = SOCKET(req);
--
-+
- if (req->Attributes & REGION_TYPE_AM)
- region = s->a_region;
- else
- region = s->c_region;
--
-+
- while (region) {
- if (region->info.CardOffset == req->CardOffset) break;
- region = region->info.next;
-@@ -973,7 +980,7 @@
- if (!region || (region->mtd != NULL))
- return CS_BAD_OFFSET;
- strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
--
-+
- DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
- req->Attributes, req->CardOffset, (char *)req->dev_info);
- return CS_SUCCESS;
-@@ -988,7 +995,7 @@
- memory_handle_t region;
- u_long flags;
- int i, sn;
--
-+
- DEBUG(1, "cs: deregister_client(%p)\n", handle);
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-@@ -1007,7 +1014,7 @@
- for (region = s->c_region; region; region = region->info.next)
- if (region->mtd == handle) region->mtd = NULL;
- }
--
-+
- sn = handle->Socket; s = socket_table[sn];
-
- if ((handle->state & CLIENT_STALE) ||
-@@ -1032,7 +1039,7 @@
-
- if (--s->real_clients == 0)
- register_callback(s, NULL, NULL);
--
-+
- return CS_SUCCESS;
- } /* deregister_client */
-
-@@ -1043,7 +1050,7 @@
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1055,7 +1062,7 @@
- return CS_BAD_ARGS;
- } else
- config->Function = handle->Function;
--
-+
- #ifdef CONFIG_CARDBUS
- if (s->state & SOCKET_CARDBUS) {
- u_char fn = config->Function;
-@@ -1076,16 +1083,16 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- c = (s->config != NULL) ? &s->config[config->Function] : NULL;
--
-+
- if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
- config->Attributes = 0;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- return CS_SUCCESS;
- }
--
-+
- /* !!! This is a hack !!! */
- memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
- config->Attributes |= CONF_VALID_CLIENT;
-@@ -1099,14 +1106,14 @@
- config->NumPorts2 = c->io.NumPorts2;
- config->Attributes2 = c->io.Attributes2;
- config->IOAddrLines = c->io.IOAddrLines;
--
-+
- return CS_SUCCESS;
- } /* get_configuration_info */
-
- /*======================================================================
-
- Return information about this version of Card Services.
--
-+
- ======================================================================*/
-
- int pcmcia_get_card_services_info(servinfo_t *info)
-@@ -1124,7 +1131,7 @@
-
- Note that get_first_client() *does* recognize the Socket field
- in the request structure.
--
-+
- ======================================================================*/
-
- int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
-@@ -1239,7 +1246,7 @@
-
- Get the current socket state bits. We don't support the latched
- SocketState yet: I haven't seen any point for it.
--
-+
- ======================================================================*/
-
- int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
-@@ -1247,7 +1254,7 @@
- socket_info_t *s;
- config_t *c;
- int val;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1263,7 +1270,7 @@
- return CS_NO_CARD;
- if (s->state & SOCKET_SETUP_PENDING)
- status->CardState |= CS_EVENT_CARD_INSERTION;
--
-+
- /* Get info from the PRR, if necessary */
- if (handle->Function == BIND_FN_ALL) {
- if (status->Function && (status->Function >= s->functions))
-@@ -1309,7 +1316,7 @@
- /*======================================================================
-
- Change the card address of an already open memory window.
--
-+
- ======================================================================*/
-
- int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
-@@ -1338,7 +1345,7 @@
- /*======================================================================
-
- Modify a locked socket configuration
--
-+
- ======================================================================*/
-
- int pcmcia_modify_configuration(client_handle_t handle,
-@@ -1346,7 +1353,7 @@
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle); c = CONFIG(handle);
-@@ -1354,7 +1361,7 @@
- return CS_NO_CARD;
- if (!(c->state & CONFIG_LOCKED))
- return CS_CONFIGURATION_LOCKED;
--
-+
- if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
- if (mod->Attributes & CONF_ENABLE_IRQ) {
- c->Attributes |= CONF_ENABLE_IRQ;
-@@ -1406,7 +1413,7 @@
- win->ctl.flags |= MAP_USE_WAIT;
- win->ctl.speed = req->AccessSpeed;
- set_mem_map(win->sock, &win->ctl);
--
-+
- return CS_SUCCESS;
- } /* modify_window */
-
-@@ -1416,7 +1423,7 @@
- caller with a socket. The driver must have already been bound
- to a socket with bind_device() -- in fact, bind_device()
- allocates the client structure that will be used.
--
-+
- ======================================================================*/
-
- int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
-@@ -1424,7 +1431,7 @@
- client_t *client;
- socket_info_t *s;
- socket_t ns;
--
-+
- /* Look for unbound client with matching dev_info */
- client = NULL;
- for (ns = 0; ns < sockets; ns++) {
-@@ -1464,7 +1471,7 @@
-
- if (s->state & SOCKET_CARDBUS)
- client->state |= CLIENT_CARDBUS;
--
-+
- if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
- (client->Function != BIND_FN_ALL)) {
- cistpl_longlink_mfc_t mfc;
-@@ -1479,7 +1486,7 @@
- return CS_OUT_OF_RESOURCE;
- memset(s->config, 0, sizeof(config_t) * s->functions);
- }
--
-+
- DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",
- client, client->Socket, client->dev_info);
- if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
-@@ -1501,13 +1508,13 @@
- pccard_io_map io = { 0, 0, 0, 0, 1 };
- socket_info_t *s;
- int i;
--
-+
- if (CHECK_HANDLE(handle) ||
- !(handle->state & CLIENT_CONFIG_LOCKED))
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_CONFIG_LOCKED;
- s = SOCKET(handle);
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- cb_disable(s);
-@@ -1515,7 +1522,7 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (--(s->lock_count) == 0) {
-@@ -1536,7 +1543,7 @@
- }
- c->state &= ~CONFIG_LOCKED;
- }
--
-+
- return CS_SUCCESS;
- } /* release_configuration */
-
-@@ -1547,25 +1554,25 @@
- the actual socket configuration, so if the client is "stale", we
- don't bother checking the port ranges against the current socket
- values.
--
-+
- ======================================================================*/
-
- int pcmcia_release_io(client_handle_t handle, io_req_t *req)
- {
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_IO_REQ;
- s = SOCKET(handle);
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- cb_release(s);
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (c->state & CONFIG_LOCKED)
-@@ -1581,7 +1588,7 @@
- release_io_space(s, req->BasePort1, req->NumPorts1);
- if (req->NumPorts2)
- release_io_space(s, req->BasePort2, req->NumPorts2);
--
-+
- return CS_SUCCESS;
- } /* release_io */
-
-@@ -1594,7 +1601,7 @@
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_IRQ_REQ;
- s = SOCKET(handle);
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (c->state & CONFIG_LOCKED)
-@@ -1608,16 +1615,16 @@
- s->irq.AssignedIRQ = 0;
- }
- }
--
-+
- if (req->Attributes & IRQ_HANDLE_PRESENT) {
- bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
- }
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (req->AssignedIRQ != s->cap.pci_irq)
- undo_irq(req->Attributes, req->AssignedIRQ);
- #endif
--
-+
- return CS_SUCCESS;
- } /* cs_release_irq */
-
-@@ -1626,7 +1633,7 @@
- int pcmcia_release_window(window_handle_t win)
- {
- socket_info_t *s;
--
-+
- if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
- s = win->sock;
-@@ -1640,11 +1647,11 @@
-
- /* Release system memory */
- if(!(s->cap.features & SS_CAP_STATIC_MAP))
-- release_mem_region(win->base, win->size);
-+ release_mem_resource(win->base, win->size);
- win->handle->state &= ~CLIENT_WIN_REQ(win->index);
-
- win->magic = 0;
--
-+
- return CS_SUCCESS;
- } /* release_window */
-
-@@ -1658,13 +1665,13 @@
- socket_info_t *s;
- config_t *c;
- pccard_io_map iomap;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
- if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- if (!(req->IntType & INT_CARDBUS))
-@@ -1677,7 +1684,7 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (req->IntType & INT_CARDBUS)
- return CS_UNSUPPORTED_MODE;
- c = CONFIG(handle);
-@@ -1692,9 +1699,9 @@
- s->socket.Vpp = req->Vpp1;
- if (set_socket(s, &s->socket))
- return CS_BAD_VPP;
--
-+
- c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
--
-+
- /* Pick memory or I/O card, DMA mode, interrupt */
- c->IntType = req->IntType;
- c->Attributes = req->Attributes;
-@@ -1712,7 +1719,7 @@
- s->socket.io_irq = 0;
- set_socket(s, &s->socket);
- s->lock_count++;
--
-+
- /* Set up CIS configuration registers */
- base = c->ConfigBase = req->ConfigBase;
- c->Present = c->CardValues = req->Present;
-@@ -1757,7 +1764,7 @@
- u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
- write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
- }
--
-+
- /* Configure I/O windows */
- if (c->state & CONFIG_IO_REQ) {
- iomap.speed = io_speed;
-@@ -1779,24 +1786,24 @@
- s->io[i].Config++;
- }
- }
--
-+
- c->state |= CONFIG_LOCKED;
- handle->state |= CLIENT_CONFIG_LOCKED;
- return CS_SUCCESS;
- } /* request_configuration */
-
- /*======================================================================
--
-+
- Request_io() reserves ranges of port addresses for a socket.
- I have not implemented range sharing or alias addressing.
--
-+
- ======================================================================*/
-
- int pcmcia_request_io(client_handle_t handle, io_req_t *req)
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1855,7 +1862,7 @@
- hooked, we don't guarantee that an irq will still be available
- when the configuration is locked. Now that I think about it,
- there might be a way to fix this using a dummy handler.
--
-+
- ======================================================================*/
-
- int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
-@@ -1863,7 +1870,7 @@
- socket_info_t *s;
- config_t *c;
- int ret = CS_IN_USE, irq = 0;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1875,7 +1882,7 @@
- if (c->state & CONFIG_IRQ_REQ)
- return CS_IN_USE;
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (s->irq.AssignedIRQ != 0) {
- /* If the interrupt is already assigned, it must match */
- irq = s->irq.AssignedIRQ;
-@@ -1909,7 +1916,7 @@
-
- if (req->Attributes & IRQ_HANDLE_PRESENT) {
- if (bus_request_irq(s->cap.bus, irq, req->Handler,
-- ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
-+ ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
- (s->functions > 1) ||
- (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
- handle->dev_info, req->Instance))
-@@ -1919,7 +1926,7 @@
- c->irq.Attributes = req->Attributes;
- s->irq.AssignedIRQ = req->AssignedIRQ = irq;
- s->irq.Config++;
--
-+
- c->state |= CONFIG_IRQ_REQ;
- handle->state |= CLIENT_IRQ_REQ;
- return CS_SUCCESS;
-@@ -1938,7 +1945,7 @@
- window_t *win;
- u_long align;
- int w;
--
-+
- if (CHECK_HANDLE(*handle))
- return CS_BAD_HANDLE;
- s = SOCKET(*handle);
-@@ -2005,7 +2012,7 @@
- /* Return window handle */
- req->Base = win->ctl.sys_start;
- *wh = win;
--
-+
- return CS_SUCCESS;
- } /* request_window */
-
-@@ -2014,14 +2021,14 @@
- I'm not sure which "reset" function this is supposed to use,
- but for now, it uses the low-level interface's reset, not the
- CIS register.
--
-+
- ======================================================================*/
-
- int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
- {
- int i, ret;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2049,14 +2056,14 @@
-
- These shut down or wake up a socket. They are sort of user
- initiated versions of the APM suspend and resume actions.
--
-+
- ======================================================================*/
-
- int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
- {
- int i;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2077,7 +2084,7 @@
- {
- int i;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2095,7 +2102,7 @@
- /*======================================================================
-
- These handle user requests to eject or insert a card.
--
-+
- ======================================================================*/
-
- int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
-@@ -2103,7 +2110,7 @@
- int i, ret;
- socket_info_t *s;
- u_long flags;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2119,9 +2126,9 @@
- spin_lock_irqsave(&s->lock, flags);
- do_shutdown(s);
- spin_unlock_irqrestore(&s->lock, flags);
--
-+
- return CS_SUCCESS;
--
-+
- } /* eject_card */
-
- int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
-@@ -2129,7 +2136,7 @@
- int i, status;
- socket_info_t *s;
- u_long flags;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2157,7 +2164,7 @@
-
- Maybe this should send a CS_EVENT_CARD_INSERTION event if we
- haven't sent one to this client yet?
--
-+
- ======================================================================*/
-
- int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
-@@ -2189,7 +2196,7 @@
- printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", handle->dev_info);
--
-+
- for (i = 0; i < SERVICE_COUNT; i++)
- if (service_table[i].key == err->func) break;
- if (i < SERVICE_COUNT)
-@@ -2347,13 +2354,13 @@
- default:
- return CS_UNSUPPORTED_FUNCTION; break;
- }
--
-+
- } /* CardServices */
-
- /*======================================================================
-
- OS-specific module glue goes here
--
-+
- ======================================================================*/
- /* in alpha order */
- EXPORT_SYMBOL(pcmcia_access_configuration_register);
-@@ -2450,4 +2457,3 @@
- module_exit(exit_pcmcia_cs);
-
- /*====================================================================*/
--
---- linux-2.4.25/drivers/pcmcia/ds.c~2.4.25-vrs2.patch 2001-11-12 18:39:01.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/ds.c 2004-03-31 17:15:09.000000000 +0200
-@@ -55,6 +55,7 @@
- #include <pcmcia/bulkmem.h>
- #include <pcmcia/cistpl.h>
- #include <pcmcia/ds.h>
-+#include <linux/devfs_fs_kernel.h>
-
- /*====================================================================*/
-
-@@ -880,6 +881,8 @@
- EXPORT_SYMBOL(register_pccard_driver);
- EXPORT_SYMBOL(unregister_pccard_driver);
-
-+static devfs_handle_t devfs_handle;
-+
- /*====================================================================*/
-
- int __init init_pcmcia_ds(void)
-@@ -957,8 +960,13 @@
- if (i == -EBUSY)
- printk(KERN_NOTICE "unable to find a free device # for "
- "Driver Services\n");
-- else
-+ else {
- major_dev = i;
-+ devfs_handle = devfs_register(NULL, "pcmcia", DEVFS_FL_DEFAULT,
-+ major_dev, 0,
-+ S_IFCHR | S_IRUSR | S_IWUSR,
-+ &ds_fops, NULL);
-+ }
-
- #ifdef CONFIG_PROC_FS
- if (proc_pccard)
-@@ -983,7 +991,9 @@
- remove_proc_entry("drivers", proc_pccard);
- #endif
- if (major_dev != -1)
-- unregister_chrdev(major_dev, "pcmcia");
-+ devfs_unregister_chrdev(major_dev, "pcmcia");
-+ devfs_unregister(devfs_handle);
-+
- for (i = 0; i < sockets; i++)
- pcmcia_deregister_client(socket_table[i].handle);
- sockets = 0;
---- linux-2.4.25/drivers/pcmcia/i82365.c~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/i82365.c 2004-03-31 17:15:09.000000000 +0200
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #include <linux/module.h>
-@@ -65,6 +65,15 @@
- #include "ricoh.h"
- #include "o2micro.h"
-
-+#ifdef CONFIG_ARCH_EBSA110
-+#define I365_MASK (1 << 6)
-+#define SOCKIRQ2REG(sock,irq) ((irq) ? ((sock) ? 3 : 4) : 0)
-+#define REG2SOCKIRQ(sock,reg) (6)
-+#else
-+#define SOCKIRQ2REG(sock,irq) (irq)
-+#define REG2SOCKIRQ(sock,reg) (reg)
-+#endif
-+
- #ifdef PCMCIA_DEBUG
- static int pc_debug = PCMCIA_DEBUG;
- MODULE_PARM(pc_debug, "i");
-@@ -173,13 +182,15 @@
- } socket_info_t;
-
- /* Where we keep track of our sockets... */
--static int sockets = 0;
--static socket_info_t socket[8] = {
-- { 0, }, /* ... */
--};
-+static int sockets /* = 0 */;
-+static socket_info_t socket[8] /* = {
-+ { 0, },
-+} */;
-
- /* Default ISA interrupt mask */
-+#ifndef I365_MASK
- #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
-+#endif
-
- static int grab_irq;
- static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
-@@ -303,7 +314,7 @@
-
- The VIA controllers also use these routines, as they are mostly
- Cirrus lookalikes, without the timing registers.
--
-+
- ======================================================================*/
-
- #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
-@@ -389,7 +400,7 @@
- Code to save and restore global state information for Vadem VG468
- and VG469 controllers, and to set and report global configuration
- options.
--
-+
- ======================================================================*/
-
- static void vg46x_get_state(u_short s)
-@@ -411,7 +422,7 @@
- static u_int __init vg46x_set_opts(u_short s, char *buf)
- {
- vg46x_state_t *p = &socket[s].state.vg46x;
--
-+
- flip(p->ctl, VG468_CTL_ASYNC, async_clock);
- flip(p->ema, VG469_MODE_CABLE, cable_mode);
- if (p->ctl & VG468_CTL_ASYNC)
-@@ -436,7 +447,7 @@
- /*======================================================================
-
- Generic routines to get and set controller options
--
-+
- ======================================================================*/
-
- static void get_bridge_state(u_short s)
-@@ -489,7 +500,7 @@
- /*======================================================================
-
- Interrupt testing code, for ISA and PCI interrupts
--
-+
- ======================================================================*/
-
- static volatile u_int irq_hits;
-@@ -517,7 +528,7 @@
- }
-
- /* Generate one interrupt */
-- i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
-+ i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (SOCKIRQ2REG(sock, irq) << 4));
- i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
- udelay(1000);
-
-@@ -526,7 +537,7 @@
- /* mask all interrupts */
- i365_set(sock, I365_CSCINT, 0);
- DEBUG(2, " hits = %d\n", irq_hits);
--
-+
- return (irq_hits != 1);
- }
-
-@@ -540,7 +551,7 @@
- /* Don't probe level-triggered interrupts -- reserved for PCI */
- mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
- #endif
--
-+
- if (do_scan) {
- set_bridge_state(sock);
- i365_set(sock, I365_CSCINT, 0);
-@@ -551,7 +562,7 @@
- if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
- mask1 ^= (1 << i);
- }
--
-+
- printk(KERN_INFO " ISA irqs (");
- if (mask1) {
- printk("scanned");
-@@ -565,12 +576,12 @@
- if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
- }
- printk(") = ");
--
-+
- for (i = 0; i < 16; i++)
- if (mask1 & (1<<i))
- printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
- if (mask1 == 0) printk("none!");
--
-+
- return mask1;
- }
-
-@@ -598,14 +609,14 @@
- /* Use the next free entry in the socket table */
- socket[sockets].ioaddr = port;
- socket[sockets].psock = sock;
--
-+
- /* Wake up a sleepy Cirrus controller */
- if (wakeup) {
- i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
- /* Pause at least 50 ms */
- mdelay(50);
- }
--
-+
- if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
- return -1;
- switch (val) {
-@@ -618,7 +629,7 @@
- case 0x88: case 0x89: case 0x8a:
- type = IS_IBM; break;
- }
--
-+
- /* Check for Vadem VG-468 chips */
- outb(0x0e, port);
- outb(0x37, port);
-@@ -633,7 +644,7 @@
- val = i365_get(sockets, RF5C_CHIP_ID);
- if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
- type = IS_RF5Cx96;
--
-+
- /* Check for Cirrus CL-PD67xx chips */
- i365_set(sockets, PD67_CHIP_INFO, 0);
- val = i365_get(sockets, PD67_CHIP_INFO);
-@@ -655,14 +666,14 @@
- bound to a (non PC Card) Linux driver. We leave these alone.
-
- We make an exception for cards that seem to be serial devices.
--
-+
- ======================================================================*/
-
- static int __init is_alive(u_short sock)
- {
- u_char stat;
- u_short start, stop;
--
-+
- stat = i365_get(sock, I365_STATUS);
- start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
- stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
-@@ -697,7 +708,7 @@
-
- base = sockets-ns;
- if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
--
-+
- if (base == 0) printk("\n");
- printk(KERN_INFO " %s", pcic[type].name);
- printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
-@@ -713,7 +724,7 @@
- mask &= I365_MASK & set_bridge_opts(base, ns);
- /* Scan for ISA interrupts */
- mask = isa_scan(base, mask);
--
-+
- /* Poll if only two interrupts available */
- if (!poll_interval) {
- u_int tmp = (mask & 0xff20);
-@@ -735,15 +746,15 @@
- printk(" status change on irq %d\n", cs_irq);
- }
- }
--
-+
- if (!isa_irq) {
- if (poll_interval == 0)
- poll_interval = HZ;
- printk(" polling interval = %d ms\n",
- poll_interval * 1000 / HZ);
--
-+
- }
--
-+
- /* Update socket interrupt information, capabilities */
- for (i = 0; i < ns; i++) {
- t[i].cap.features |= SS_CAP_PCCARD;
-@@ -866,12 +877,12 @@
- events = pending_events[i];
- pending_events[i] = 0;
- spin_unlock_irq(&pending_event_lock);
-- /*
-- SS_DETECT events need a small delay here. The reason for this is that
-+ /*
-+ SS_DETECT events need a small delay here. The reason for this is that
- the "is there a card" electronics need time to see the card after the
-- "we have a card coming in" electronics have seen it.
-+ "we have a card coming in" electronics have seen it.
- */
-- if (events & SS_DETECT)
-+ if (events & SS_DETECT)
- mdelay(4);
- if (socket[i].handler)
- socket[i].handler(socket[i].info, events);
-@@ -890,7 +901,7 @@
- int i, j, csc;
- u_int events, active;
- u_long flags = 0;
--
-+
- DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
-
- for (j = 0; j < 20; j++) {
-@@ -906,20 +917,20 @@
- continue;
- }
- events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
--
--
-+
-+
- /* Several sockets will send multiple "new card detected"
-- events in rapid succession. However, the rest of the pcmcia expects
-+ events in rapid succession. However, the rest of the pcmcia expects
- only one such event. We just ignore these events by having a
- timeout */
-
- if (events) {
-- if ((jiffies - last_detect_jiffies)<(HZ/20))
-+ if ((jiffies - last_detect_jiffies)<(HZ/20))
- events = 0;
- last_detect_jiffies = jiffies;
--
-+
- }
--
-+
- if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
- events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
- else {
-@@ -980,11 +991,11 @@
- static int i365_get_status(u_short sock, u_int *value)
- {
- u_int status;
--
-+
- status = i365_get(sock, I365_STATUS);
- *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
- ? SS_DETECT : 0;
--
-+
- if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
- *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
- else {
-@@ -1005,7 +1016,7 @@
- *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
- }
- }
--
-+
- DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
- return 0;
- } /* i365_get_status */
-@@ -1016,7 +1027,7 @@
- {
- socket_info_t *t = &socket[sock];
- u_char reg, vcc, vpp;
--
-+
- reg = i365_get(sock, I365_POWER);
- state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
- state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-@@ -1057,14 +1068,14 @@
- reg = i365_get(sock, I365_INTCTL);
- state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
- if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-- state->io_irq = reg & I365_IRQ_MASK;
--
-+ state->io_irq = REG2SOCKIRQ(sock, reg & I365_IRQ_MASK);
-+
- /* speaker control */
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
- state->flags |= SS_SPKR_ENA;
- }
--
-+
- /* Card status change mask */
- reg = i365_get(sock, I365_CSCINT);
- state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
-@@ -1075,7 +1086,7 @@
- state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
- state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
- }
--
-+
- DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-@@ -1088,21 +1099,21 @@
- {
- socket_info_t *t = &socket[sock];
- u_char reg;
--
-+
- DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
--
-+
- /* First set global controller options */
- set_bridge_state(sock);
--
-+
- /* IO card, RESET flag, IO interrupt */
- reg = t->intr;
-- reg |= state->io_irq;
-+ reg |= SOCKIRQ2REG(sock, state->io_irq);
- reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
- reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
- i365_set(sock, I365_INTCTL, reg);
--
-+
- reg = I365_PWR_NORESET;
- if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
- if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
-@@ -1165,7 +1176,7 @@
- default: return -EINVAL;
- }
- }
--
-+
- if (reg != i365_get(sock, I365_POWER))
- i365_set(sock, I365_POWER, reg);
-
-@@ -1175,9 +1186,9 @@
- i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
- state->flags & SS_SPKR_ENA);
- }
--
-+
- /* Card status change interrupt mask */
-- reg = t->cs_irq << 4;
-+ reg = SOCKIRQ2REG(sock, t->cs_irq) << 4;
- if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
- if (state->flags & SS_IOCARD) {
- if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
-@@ -1188,7 +1199,7 @@
- }
- i365_set(sock, I365_CSCINT, reg);
- i365_get(sock, I365_CSC);
--
-+
- return 0;
- } /* i365_set_socket */
-
-@@ -1197,7 +1208,7 @@
- static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
- {
- u_char map, ioctl, addr;
--
-+
- map = io->map;
- if (map > 1) return -EINVAL;
- io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
-@@ -1220,7 +1231,7 @@
- static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
- {
- u_char map, ioctl;
--
-+
- DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
- io->speed, io->start, io->stop);
-@@ -1250,30 +1261,30 @@
- {
- u_short base, i;
- u_char map, addr;
--
-+
- map = mem->map;
- if (map > 4) return -EINVAL;
- addr = i365_get(sock, I365_ADDRWIN);
- mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
- base = I365_MEM(map);
--
-+
- i = i365_get_pair(sock, base+I365_W_START);
- mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
- mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
- mem->sys_start = ((u_long)(i & 0x0fff) << 12);
--
-+
- i = i365_get_pair(sock, base+I365_W_STOP);
- mem->speed = (i & I365_MEM_WS0) ? 1 : 0;
- mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
- mem->speed = to_ns(mem->speed);
- mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
--
-+
- i = i365_get_pair(sock, base+I365_W_OFF);
- mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
- mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
- mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
- mem->card_start &= 0x3ffffff;
--
-+
- DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
- "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
- mem->sys_start, mem->sys_stop, mem->card_start);
-@@ -1281,12 +1292,12 @@
- } /* i365_get_mem_map */
-
- /*====================================================================*/
--
-+
- static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
- {
- u_short base, i;
- u_char map;
--
-+
- DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
- "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
- mem->sys_start, mem->sys_stop, mem->card_start);
-@@ -1297,17 +1308,17 @@
- return -EINVAL;
- if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
- return -EINVAL;
--
-+
- /* Turn off the window before changing anything */
- if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
- i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
--
-+
- base = I365_MEM(map);
- i = (mem->sys_start >> 12) & 0x0fff;
- if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
- if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
- i365_set_pair(sock, base+I365_W_START, i);
--
-+
- i = (mem->sys_stop >> 12) & 0x0fff;
- switch (to_cycles(mem->speed)) {
- case 0: break;
-@@ -1316,12 +1327,12 @@
- default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
- }
- i365_set_pair(sock, base+I365_W_STOP, i);
--
-+
- i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
- if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
- if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
- i365_set_pair(sock, base+I365_W_OFF, i);
--
-+
- /* Turn on the window if necessary */
- if (mem->flags & MAP_ACTIVE)
- i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
-@@ -1332,7 +1343,7 @@
-
- Routines for accessing socket information and register dumps via
- /proc/bus/pccard/...
--
-+
- ======================================================================*/
-
- #ifdef CONFIG_PROC_FS
-@@ -1353,7 +1364,7 @@
- u_short sock = (socket_info_t *)data - socket;
- char *p = buf;
- int i, top;
--
-+
- u_long flags = 0;
- ISA_LOCK(sock, flags);
- top = 0x40;
-@@ -1399,7 +1410,7 @@
-
- /*====================================================================*/
-
--/* this is horribly ugly... proper locking needs to be done here at
-+/* this is horribly ugly... proper locking needs to be done here at
- * some time... */
- #define LOCKED(x) do { \
- int retval; \
-@@ -1532,7 +1543,7 @@
- /* Set up interrupt handler(s) */
- if (grab_irq != 0)
- request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
--
-+
- if (register_ss_entry(sockets, &pcic_operations) != 0)
- printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
-
-@@ -1544,9 +1555,9 @@
- poll_timer.expires = jiffies + poll_interval;
- add_timer(&poll_timer);
- }
--
-+
- return 0;
--
-+
- } /* init_i82365 */
-
- static void __exit exit_i82365(void)
---- linux-2.4.25/drivers/pcmcia/rsrc_mgr.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/rsrc_mgr.c 2004-03-31 17:15:09.000000000 +0200
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #define __NO_VERSION__
-@@ -55,6 +55,10 @@
- #include <pcmcia/cistpl.h>
- #include "cs_internal.h"
-
-+#ifndef ISAMEM_PHYS
-+#define ISAMEM_PHYS 0
-+#endif
-+
- /*====================================================================*/
-
- /* Parameters that can be set with 'insmod' */
-@@ -62,7 +66,7 @@
- #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
- INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
- INT_MODULE_PARM(mem_limit, 0x10000);
- #endif
-@@ -85,7 +89,7 @@
- /* IO port resource database */
- static resource_map_t io_db = { 0, 0, &io_db };
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- typedef struct irq_info_t {
- u_int Attributes;
-@@ -133,6 +137,7 @@
- static inline int check_mem_resource(unsigned long b, unsigned long n,
- struct pci_dev *dev)
- {
-+ b += ISAMEM_PHYS;
- return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
- }
-
-@@ -169,10 +174,15 @@
- static int request_mem_resource(unsigned long b, unsigned long n,
- char *name, struct pci_dev *dev)
- {
-- struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
-- struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
-+ struct resource *res;
-+ struct resource *pr;
- int err = -ENOMEM;
-
-+ b += ISAMEM_PHYS;
-+
-+ res = make_resource(b, n, IORESOURCE_MEM, name);
-+ pr = resource_parent(b, n, IORESOURCE_MEM, dev);
-+
- if (res) {
- err = request_resource(pr, res);
- if (err)
-@@ -181,10 +191,16 @@
- return err;
- }
-
-+void release_mem_resource(unsigned long b, unsigned long n)
-+{
-+ b += ISAMEM_PHYS;
-+ release_mem_region(b, n);
-+}
-+
- /*======================================================================
-
- These manage the internal databases of available resources.
--
-+
- ======================================================================*/
-
- static int add_interval(resource_map_t *map, u_long base, u_long num)
-@@ -248,25 +264,25 @@
-
- These routines examine a region of IO or memory addresses to
- determine what ranges might be genuinely available.
--
-+
- ======================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- static void do_io_probe(ioaddr_t base, ioaddr_t num)
- {
--
-+
- ioaddr_t i, j, bad, any;
- u_char *b, hole, most;
--
-+
- printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
- base, base+num-1);
--
-+
- /* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
- if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
- return;
-- }
-+ }
- memset(b, 0, 256);
- for (i = base, most = 0; i < base+num; i += 8) {
- if (check_io_resource(i, 8, NULL))
-@@ -308,7 +324,7 @@
- printk(" %#04x-%#04x", bad, i-1);
- }
- }
--
-+
- printk(any ? "\n" : " clean.\n");
- }
- #endif
-@@ -318,7 +334,7 @@
- The memory probe. If the memory list includes a 64K-aligned block
- below 1MB, we probe in 64K chunks, and as soon as we accumulate at
- least mem_limit free space, we quit.
--
-+
- ======================================================================*/
-
- static int do_mem_probe(u_long base, u_long num,
-@@ -332,7 +348,7 @@
- bad = fail = 0;
- step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
- for (i = j = base; i < base+num; i = j + step) {
-- if (!fail) {
-+ if (!fail) {
- for (j = i; j < base+num; j += step)
- if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
- is_valid(j))
-@@ -356,7 +372,7 @@
- return (num - bad);
- }
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- static u_long inv_probe(int (*is_valid)(u_long),
- int (*do_cksum)(u_long),
-@@ -383,7 +399,7 @@
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- static int hi = 0, lo = 0;
- u_long b, i, ok = 0;
--
-+
- if (!probe_mem) return;
- /* We do up to four passes through the list */
- if (!force_low) {
-@@ -414,14 +430,14 @@
- }
- }
-
--#else /* CONFIG_ISA */
-+#else /* CONFIG_PCMCIA_PROBE */
-
- void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
- int force_low, socket_info_t *s)
- {
- resource_map_t *m, *n;
- static int done = 0;
--
-+
- if (!probe_mem || done++)
- return;
-
-@@ -432,7 +448,7 @@
- }
- }
-
--#endif /* CONFIG_ISA */
-+#endif /* CONFIG_PCMCIA_PROBE */
-
- /*======================================================================
-
-@@ -444,7 +460,7 @@
- should be a power of two, greater than or equal to 'num'. A value
- of 0 means that all bits of *base are significant. *base should
- also be strictly less than 'align'.
--
-+
- ======================================================================*/
-
- int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
-@@ -452,7 +468,7 @@
- {
- ioaddr_t try;
- resource_map_t *m;
--
-+
- for (m = io_db.next; m != &io_db; m = m->next) {
- try = (m->base & ~(align-1)) + *base;
- for (try = (try >= m->base) ? try : try+align;
-@@ -500,10 +516,10 @@
- This checks to see if an interrupt is available, with support
- for interrupt sharing. We don't support reserving interrupts
- yet. If the interrupt is available, we allocate it.
--
-+
- ======================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- static void fake_irq(int i, void *d, struct pt_regs *r) { }
- static inline int check_irq(int irq)
-@@ -570,7 +586,7 @@
-
- /*====================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- void undo_irq(u_int Attributes, int irq)
- {
-@@ -600,7 +616,7 @@
-
- The various adjust_* calls form the external interface to the
- resource database.
--
-+
- ======================================================================*/
-
- static int adjust_memory(adjust_t *adj)
-@@ -632,7 +648,7 @@
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- }
--
-+
- return ret;
- }
-
-@@ -641,7 +657,7 @@
- static int adjust_io(adjust_t *adj)
- {
- int base, num;
--
-+
- base = adj->resource.io.BasePort;
- num = adj->resource.io.NumPorts;
- if ((base < 0) || (base > 0xffff))
-@@ -653,7 +669,7 @@
- case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0)
- return CS_IN_USE;
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (probe_io)
- do_io_probe(base, num);
- #endif
-@@ -673,15 +689,15 @@
-
- static int adjust_irq(adjust_t *adj)
- {
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- int irq;
- irq_info_t *info;
--
-+
- irq = adj->resource.irq.IRQ;
- if ((irq < 0) || (irq > 15))
- return CS_BAD_IRQ;
- info = &irq_table[irq];
--
-+
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (info->Attributes & RES_REMOVED)
-@@ -716,7 +732,7 @@
- {
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
--
-+
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- return adjust_memory(adj);
-@@ -736,7 +752,7 @@
- void release_resource_db(void)
- {
- resource_map_t *p, *q;
--
-+
- for (p = mem_db.next; p != &mem_db; p = q) {
- q = p->next;
- kfree(p);
---- linux-2.4.25/drivers/pcmcia/sa1100.h~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100.h 2004-03-31 17:15:09.000000000 +0200
-@@ -204,7 +204,9 @@
- extern struct pcmcia_low_level flexanet_pcmcia_ops;
- extern struct pcmcia_low_level simpad_pcmcia_ops;
- extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
-+extern struct pcmcia_low_level adsagc_pcmcia_ops;
- extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
-+extern struct pcmcia_low_level adsbitsyplus_pcmcia_ops;
- extern struct pcmcia_low_level stork_pcmcia_ops;
- extern struct pcmcia_low_level badge4_pcmcia_ops;
-
---- linux-2.4.25/drivers/pcmcia/sa1100_adsbitsy.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_adsbitsy.c 2004-03-31 17:15:09.000000000 +0200
-@@ -11,28 +11,156 @@
- */
- #include <linux/kernel.h>
- #include <linux/sched.h>
-+#include <linux/ioport.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-+#include <asm/irq.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-
-+int adsbitsy_smc91111_present(void);
-+
-+#ifndef CONFIG_SMC91111
-+#define adsbitsy_smc91111_present() 0
-+#endif
-+
-+static struct irqs {
-+ int irq;
-+ const char *str;
-+} irqs[] = {
-+ { S0_CD_VALID, "SA1111 PCMCIA card detect" },
-+ { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
-+ { S1_CD_VALID, "SA1111 CF card detect" },
-+ { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
-+};
-+
- static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
- {
-- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
-- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+ int ret=0;
-+ int nirq = 0;
-+ int slots = 0;
-+ int i;
-
-- /* Disable Power 3.3V/5V for PCMCIA/CF */
-- PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
-+ /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
-+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
-
-- /* Why? */
-- MECR = 0x09430943;
-+ /* Disable Power 3.3V/5V for PCMCIA */
-+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
-
-- return sa1111_pcmcia_init(init);
-+ if (!request_mem_region(_PCCR, 512, "PCMCIA"))
-+ return -1;
-+
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
-+
-+ nirq = 2;
-+ slots = 1;
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ /* If the SMC91111 is used CF cannot be used */
-+ /* Set GPIO_A<3:2> to be outputs for CF power controller: */
-+ PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
-+
-+ /* Disable Power 3.3V/5V for CF */
-+ PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+ nirq = 4;
-+ slots = 2;
-+ }
-+
-+ for (i = ret = 0; i < nirq; i++) {
-+ ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (ret)
-+ break;
-+ }
-+
-+ if (i < nirq) {
-+ printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
-+ irqs[i].irq, ret);
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ release_mem_region(_PCCR, 16);
-+ }
-+
-+ return ret ? -1 : slots;
- }
-
--static int
--adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
-+static int adsbitsy_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state)
-+{
-+ unsigned long status;
-+
-+ if (adsbitsy_smc91111_present()) {
-+ if(state->size<1) return -1;
-+ }
-+ else
-+ if(state->size<2) return -1;
-+
-+ memset(state->state, 0,
-+ (state->size)*sizeof(struct pcmcia_state));
-+
-+ status = PCSR;
-+
-+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
-+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
-+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
-+ state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
-+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
-+ state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
-+ state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
-+
-+ if (state->size > 1) {
-+ if (adsbitsy_smc91111_present()) {
-+ // If there is SMC91111 on ADS Bitsy connector board
-+ // it returns not detect/ready/...
-+ state->state[1].detect = 0;
-+ state->state[1].ready = 0;
-+ state->state[1].bvd1 = 0;
-+ state->state[1].bvd2 = 0;
-+ state->state[1].wrprot = 0;
-+ state->state[1].vs_3v = 0;
-+ state->state[1].vs_Xv = 0;
-+ }
-+ else {
-+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
-+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
-+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
-+ state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
-+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
-+ state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
-+ state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
-+ }
-+ }
-+ return 1;
-+}
-+
-+static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
- {
- unsigned int pa_dwr_mask, pa_dwr_set;
- int ret;
-@@ -54,10 +182,11 @@
-
- switch (conf->vcc) {
- default:
-- case 0: pa_dwr_set = 0; break;
-+ case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
- case 33: pa_dwr_set = GPIO_GPIO2; break;
- case 50: pa_dwr_set = GPIO_GPIO3; break;
- }
-+ break;
-
- default:
- return -1;
-@@ -83,8 +212,8 @@
-
- struct pcmcia_low_level adsbitsy_pcmcia_ops = {
- init: adsbitsy_pcmcia_init,
-- shutdown: sa1111_pcmcia_shutdown,
-- socket_state: sa1111_pcmcia_socket_state,
-+ shutdown: adsbitsy_pcmcia_shutdown,
-+ socket_state: adsbitsy_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: adsbitsy_pcmcia_configure_socket,
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_adsbitsyplus.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,236 @@
-+/*
-+ * drivers/pcmcia/sa1100_adsbitsyplus.c
-+ *
-+ * PCMCIA implementation routines for ADS Bitsy Plus
-+ *
-+ * Created Feb 7, 2003 by Robert Whaley <rwhaley@applieddata.net>
-+ *
-+ * This file comes from sa1100_adsbitsy.c of Woojung Huh <whuh@applieddata.net>
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-+#include <asm/irq.h>
-+
-+#include "sa1100_generic.h"
-+#include "sa1111_generic.h"
-+
-+int adsbitsy_smc91111_present(void);
-+
-+#ifndef CONFIG_SMC91111
-+#define adsbitsy_smc91111_present() 0
-+#endif
-+
-+static struct irqs {
-+ int irq;
-+ const char *str;
-+} irqs[] = {
-+ { S0_CD_VALID, "SA1111 PCMCIA card detect" },
-+ { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
-+ { S1_CD_VALID, "SA1111 CF card detect" },
-+ { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
-+};
-+
-+#define sock0_3_3_reverse_logic() ((ADS_CPLD_IO2 & ADS_IO2_CPLD_REV_MASK) >= ADS_IO2_CPLD_REV_5_MAGIC)
-+
-+static int adsbitsyplus_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int ret=0;
-+ int nirq = 0;
-+ int slots = 0;
-+ int i;
-+
-+ /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
-+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
-+
-+ /* Disable Power 3.3V/5V for PCMCIA */
-+ if (sock0_3_3_reverse_logic())
-+ PA_DWR = (PA_DWR & ~GPIO_GPIO0) | GPIO_GPIO1;
-+ else
-+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
-+
-+ if (!request_mem_region(_PCCR, 512, "PCMCIA"))
-+ return -1;
-+
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
-+
-+ nirq = 2;
-+ slots = 1;
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ /* If the SMC91111 is used CF cannot be used */
-+ /* Set GPIO_A<3:2> to be outputs for CF power controller: */
-+ PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
-+
-+ /* Disable Power 3.3V/5V for CF */
-+ PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+ nirq = 4;
-+ slots = 2;
-+ }
-+
-+ for (i = ret = 0; i < nirq; i++) {
-+ ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (ret)
-+ break;
-+ }
-+
-+ if (i < nirq) {
-+ printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
-+ irqs[i].irq, ret);
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ release_mem_region(_PCCR, 16);
-+ }
-+
-+ return ret ? -1 : slots;
-+}
-+
-+static int adsbitsyplus_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int adsbitsyplus_pcmcia_socket_state(struct pcmcia_state_array *state)
-+{
-+ unsigned long status;
-+
-+ if (adsbitsy_smc91111_present()) {
-+ if(state->size<1) return -1;
-+ }
-+ else
-+ if(state->size<2) return -1;
-+
-+ memset(state->state, 0,
-+ (state->size)*sizeof(struct pcmcia_state));
-+
-+ status = PCSR;
-+
-+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
-+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
-+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
-+ state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
-+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
-+ state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
-+ state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
-+
-+ if (state->size > 1) {
-+ if (adsbitsy_smc91111_present()) {
-+ // If there is SMC91111 on ADS Bitsy connector board
-+ // it returns not detect/ready/...
-+ state->state[1].detect = 0;
-+ state->state[1].ready = 0;
-+ state->state[1].bvd1 = 0;
-+ state->state[1].bvd2 = 0;
-+ state->state[1].wrprot = 0;
-+ state->state[1].vs_3v = 0;
-+ state->state[1].vs_Xv = 0;
-+ }
-+ else {
-+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
-+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
-+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
-+ state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
-+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
-+ state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
-+ state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
-+ }
-+ }
-+ return 1;
-+}
-+
-+static int adsbitsyplus_pcmcia_configure_socket(const struct pcmcia_configure *conf)
-+{
-+ unsigned int pa_dwr_mask, pa_dwr_set;
-+ int ret;
-+
-+ switch (conf->sock) {
-+ case 0:
-+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
-+
-+ if (sock0_3_3_reverse_logic()) {
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO1; break;
-+ case 33: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
-+ case 50: pa_dwr_set = 0; break;
-+ }
-+ } else {
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
-+ case 33: pa_dwr_set = GPIO_GPIO1; break;
-+ case 50: pa_dwr_set = GPIO_GPIO0; break;
-+ }
-+ }
-+ break;
-+
-+ case 1:
-+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
-+ case 33: pa_dwr_set = GPIO_GPIO2; break;
-+ case 50: pa_dwr_set = GPIO_GPIO3; break;
-+ }
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
-+ printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
-+ __FUNCTION__, conf->vpp);
-+ return -1;
-+ }
-+
-+ ret = sa1111_pcmcia_configure_socket(conf);
-+ if (ret == 0) {
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
-+ local_irq_restore(flags);
-+ }
-+
-+ return ret;
-+}
-+
-+struct pcmcia_low_level adsbitsyplus_pcmcia_ops = {
-+ init: adsbitsyplus_pcmcia_init,
-+ shutdown: adsbitsyplus_pcmcia_shutdown,
-+ socket_state: adsbitsyplus_pcmcia_socket_state,
-+ get_irq_info: sa1111_pcmcia_get_irq_info,
-+ configure_socket: adsbitsyplus_pcmcia_configure_socket,
-+
-+ socket_init: sa1111_pcmcia_socket_init,
-+ socket_suspend: sa1111_pcmcia_socket_suspend,
-+};
-+
---- linux-2.4.25/drivers/pcmcia/sa1100_freebird.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_freebird.c 2004-03-31 17:15:09.000000000 +0200
-@@ -67,9 +67,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels = LINKUP_PRS;
- //printk("LINKUP_PRS=%x \n",levels);
-
---- linux-2.4.25/drivers/pcmcia/sa1100_generic.c~2.4.25-vrs2.patch 2003-06-13 16:51:35.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_generic.c 2004-03-31 17:15:09.000000000 +0200
-@@ -992,10 +992,18 @@
- if(machine_is_graphicsmaster())
- pcmcia_low_level = &graphicsmaster_pcmcia_ops;
- #endif
-+#ifdef CONFIG_SA1100_ADSAGC
-+ if(machine_is_adsagc())
-+ pcmcia_low_level = &graphicsmaster_pcmcia_ops;
-+#endif
- #ifdef CONFIG_SA1100_ADSBITSY
- if(machine_is_adsbitsy())
- pcmcia_low_level = &adsbitsy_pcmcia_ops;
- #endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if(machine_is_adsbitsyplus())
-+ pcmcia_low_level = &adsbitsyplus_pcmcia_ops;
-+#endif
- #ifdef CONFIG_SA1100_STORK
- if(machine_is_stork())
- pcmcia_low_level = &stork_pcmcia_ops;
-@@ -1067,7 +1075,7 @@
- * We initialize the MECR to default values here, because we are
- * not guaranteed to see a SetIOMap operation at runtime.
- */
-- mecr = 0;
-+ mecr = MECR;
-
- clock = cpufreq_get(0);
-
---- linux-2.4.25/drivers/pcmcia/sa1100_graphicsclient.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_graphicsclient.c 2004-03-31 17:15:09.000000000 +0200
-@@ -3,6 +3,8 @@
- *
- * PCMCIA implementation routines for Graphics Client Plus
- *
-+ * Nov/14/01 Woojung
-+ * Set MECR at initializing time
- * 9/12/01 Woojung
- * Turn power OFF at startup
- * 1/31/2001 Woojung Huh
-@@ -19,11 +21,6 @@
- #include <asm/irq.h>
- #include "sa1100_generic.h"
-
--#error This is broken!
--
--#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
--#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
--
- static volatile unsigned long *PCMCIA_Status =
- ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS));
-
-@@ -46,20 +43,23 @@
- *PCMCIA_Power &= ~0x03;
-
- /* Register interrupts */
-- irq = S0_CD_IRQ;
-+ irq = IRQ_GRAPHICSCLIENT_S0_CD;
- res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
- if (res < 0) {
-- printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
-+ printk(KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq);
- return -1;
- }
-
-+ // Nov/14/01 WH
-+ MECR = 0x00000943;
-+
- return 1; // 1 PCMCIA Slot
- }
-
- static int gcplus_pcmcia_shutdown(void)
- {
- /* disable IRQs */
-- free_irq( S0_CD_IRQ, NULL);
-+ free_irq( IRQ_GRAPHICSCLIENT_S0_CD, NULL);
-
- /* Shutdown PCMCIA power */
- mdelay(2); // 2msec
-@@ -74,9 +74,6 @@
-
- if(state_array->size<1) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=*PCMCIA_Status;
-
- state_array->state[0].detect=(levels & ADS_CS_ST_A_CD)?1:0;
-@@ -96,7 +93,7 @@
- return -1;
-
- if (info->sock == 0)
-- info->irq = S0_STS_IRQ;
-+ info->irq = IRQ_GRAPHICSCLIENT_S0_STS;
-
- return 0;
- }
-@@ -143,6 +140,11 @@
-
- restore_flags(flags);
-
-+ if (configure->irq)
-+ enable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
-+ else
-+ disable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
-+
- return 0;
- }
-
---- linux-2.4.25/drivers/pcmcia/sa1100_graphicsmaster.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_graphicsmaster.c 2004-03-31 17:15:09.000000000 +0200
-@@ -12,13 +12,13 @@
- #include <linux/sched.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-
- static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
- {
-- int return_val=0;
-
- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-@@ -26,9 +26,6 @@
- /* Disable Power 3.3V/5V for PCMCIA/CF */
- PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
-
-- /* why? */
-- MECR = 0x09430943;
--
- return sa1111_pcmcia_init(init);
- }
-
-@@ -59,6 +56,10 @@
- case 33: pa_dwr_set = GPIO_GPIO3; break;
- case 50: pa_dwr_set = GPIO_GPIO2; break;
- }
-+ break;
-+
-+ default:
-+ return -1;
- }
-
- if (conf->vpp != conf->vcc && conf->vpp != 0) {
---- linux-2.4.25/drivers/pcmcia/sa1100_h3600.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_h3600.c 2004-03-31 17:15:09.000000000 +0200
-@@ -29,6 +29,9 @@
- set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_IRQ0 | GPIO_H3600_PCMCIA_IRQ1,
- GPIO_FALLING_EDGE);
-
-+ set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1,
-+ GPIO_NO_EDGES);
-+
- /*
- * Register interrupts
- */
---- linux-2.4.25/drivers/pcmcia/sa1100_jornada720.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_jornada720.c 2004-03-31 17:15:09.000000000 +0200
-@@ -8,6 +8,7 @@
- #include <linux/sched.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-@@ -88,7 +89,7 @@
-
- local_irq_save(flags);
- PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
-- locla_irq_restore(flags);
-+ local_irq_restore(flags);
- }
-
- return ret;
---- linux-2.4.25/drivers/pcmcia/sa1100_pangolin.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_pangolin.c 2004-03-31 17:15:09.000000000 +0200
-@@ -53,9 +53,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
- #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
- state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
---- linux-2.4.25/drivers/pcmcia/sa1100_shannon.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_shannon.c 2004-03-31 17:15:09.000000000 +0200
-@@ -53,9 +53,6 @@
- {
- unsigned long levels;
-
-- memset(state_array->state, 0,
-- state_array->size * sizeof(struct pcmcia_state));
--
- levels = GPLR;
-
- state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
---- linux-2.4.25/drivers/pcmcia/sa1100_simpad.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_simpad.c 2004-03-31 17:15:09.000000000 +0200
-@@ -63,9 +63,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
-
- state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
---- linux-2.4.25/drivers/pcmcia/sa1100_stork.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/pcmcia/sa1100_stork.c 2004-03-31 17:15:09.000000000 +0200
-@@ -79,9 +79,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
-
- if (debug > 1)
---- linux-2.4.25/drivers/pcmcia/sa1100_yopy.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/pcmcia/sa1100_yopy.c 2004-03-31 17:15:09.000000000 +0200
-@@ -73,9 +73,6 @@
- if (state_array->size != 1)
- return -1;
-
-- memset(state_array->state, 0,
-- state_array->size * sizeof(struct pcmcia_state));
--
- levels = GPLR;
-
- state_array->state[0].detect = (levels & GPIO_CF_CD) ? 0 : 1;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pld/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,28 @@
-+#
-+# Makefile for the kernel pld device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definitions are now inherited from the
-+# parent makes..
-+#
-+# $Id: $
-+#
-+
-+O_TARGET := pld.o
-+
-+export-objs := pld_hotswap.o
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_PLD) += pld_epxa.o
-+obj-$(CONFIG_PLD_HOTSWAP) += pld_hotswap.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastdep:
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pld/pld_epxa.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,375 @@
-+
-+/*
-+ * drivers/char/epxapld.c
-+ *
-+ * Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/arch/excalibur.h>
-+#include <asm/arch/hardware.h>
-+#define PLD_CONF00_TYPE (volatile unsigned int *)
-+#define MODE_CTRL00_TYPE (volatile unsigned int *)
-+//#define DEBUG(x) x
-+#define DEBUG(x)
-+
-+#include <asm/arch/mode_ctrl00.h>
-+#include <asm/arch/pld_conf00.h>
-+#ifdef CONFIG_PLD_HOTSWAP
-+#include <linux/pld/pld_hotswap.h>
-+#endif
-+#include <linux/pld/pld_epxa.h>
-+
-+/*
-+ * Macros
-+ */
-+
-+
-+#define PLD_BASE (IO_ADDRESS(EXC_PLD_CONFIG00_BASE))
-+#define CLOCK_DIV_RATIO ((1 + EXC_AHB2_CLK_FREQUENCY/32000000) & CONFIG_CONTROL_CLOCK_RATIO_MSK)
-+/*
-+ * STRUCTURES
-+ */
-+
-+
-+struct pld_sbihdr{
-+ unsigned int fpos;
-+ unsigned int temp;
-+};
-+
-+static DECLARE_MUTEX(pld_sem);
-+
-+
-+static void lock_pld (void)
-+{
-+ /* Lock the pld i/f */
-+ unsigned int tmp;
-+
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ tmp |= CONFIG_CONTROL_LK_MSK;
-+
-+ writel(tmp,CONFIG_CONTROL(PLD_BASE));
-+}
-+
-+static void unlock_excalibur_pld (void)
-+{
-+ /* Unlock the pld i/f */
-+
-+ if (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK ){
-+ writel(CONFIG_UNLOCK_MAGIC, CONFIG_UNLOCK(PLD_BASE));
-+ while (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK);
-+ }
-+}
-+
-+
-+static int place_pld_into_configure_mode (void)
-+{
-+ unsigned int tmp;
-+
-+
-+ if( readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK ){
-+ /*
-+ * Already being configured!!!
-+ */
-+ printk(KERN_WARNING "pld0: Device already being configured!\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Set up the config clock */
-+
-+ writel(CLOCK_DIV_RATIO,CONFIG_CONTROL_CLOCK(PLD_BASE));
-+ while(readl(CONFIG_CONTROL_CLOCK(PLD_BASE))
-+ !=CLOCK_DIV_RATIO);
-+ /* Tell the device we wish to configure it */
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ tmp |= CONFIG_CONTROL_CO_MSK;
-+ writel(tmp,CONFIG_CONTROL(PLD_BASE));
-+
-+
-+ /*
-+ * Wait for the busy bit to clear then check for errors.
-+ */
-+
-+ while((tmp=readl(CONFIG_CONTROL(PLD_BASE))&CONFIG_CONTROL_B_MSK ));
-+
-+ if ( tmp & CONFIG_CONTROL_E_MSK ){
-+ if ( tmp & CONFIG_CONTROL_ES_0_MSK ){
-+ /* Already being programmed via JTAG */
-+ printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
-+ return -EBUSY;
-+
-+ }
-+ if ( tmp & CONFIG_CONTROL_ES_1_MSK ){
-+ /* No config clock configured */
-+ printk(KERN_ERR "pld0:No config clock!\n");
-+ BUG();
-+ return -EBUSY;
-+ }
-+ if ( tmp & CONFIG_CONTROL_ES_2_MSK ){
-+ /* Already being programmed via External device */
-+ printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
-+ return -EBUSY;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int write_pld_data_word(unsigned int config_data)
-+{
-+ unsigned int tmp;
-+
-+ do{
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ }
-+ while ( ( tmp & CONFIG_CONTROL_B_MSK ) &&
-+ !( tmp & CONFIG_CONTROL_E_MSK ));
-+
-+ if ( tmp & CONFIG_CONTROL_E_MSK ){
-+ printk("pld0: Error writing pld data, CONFIG_CONTROL=%#x\n",tmp);
-+
-+ return -EILSEQ;
-+ }
-+
-+ writel(config_data,CONFIG_CONTROL_DATA(PLD_BASE));
-+ return 0;
-+
-+}
-+
-+
-+static int wait_for_device_to_configure (void)
-+{
-+ int i=0x10000;
-+
-+ while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
-+
-+ /*
-+ * Wait for the config bit (CO) to go low, indicating that everything
-+ * is Ok. If it doesn't, assume that is screwed up somehow and
-+ * clear the CO bit to abort the configuration.
-+ */
-+
-+ while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
-+
-+ while (i&&(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK)){
-+ i--;
-+ }
-+
-+ if (!i){
-+ writel(0,CONFIG_CONTROL(PLD_BASE));
-+ printk(KERN_WARNING "pld0: Invalid PLD config data\n");
-+ return -EILSEQ;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+static int pld_open(struct inode* inode, struct file *filep)
-+{
-+
-+ struct pld_sbihdr* sbihdr;
-+
-+ /* Check the device minor number */
-+ if(minor(inode->i_rdev)){
-+ DEBUG(printk("pld0: minor=%d",minor(inode->i_rdev));)
-+ return -ENODEV;
-+ }
-+
-+ /* Create our private data and link it to the file structure */
-+ sbihdr=kmalloc(sizeof(struct pld_sbihdr),GFP_KERNEL);
-+
-+ if(!sbihdr)
-+ return -ENOMEM;
-+
-+ filep->private_data=sbihdr;
-+
-+ sbihdr->fpos=0;
-+ sbihdr->temp=0;
-+ return 0;
-+}
-+
-+static int pld_release(struct inode* inode, struct file *filep){
-+ int ret_code;
-+
-+ kfree(filep->private_data);
-+ ret_code=wait_for_device_to_configure();
-+ lock_pld();
-+ return ret_code;
-+}
-+
-+static ssize_t pld_write(struct file* filep, const char* data, size_t count, loff_t* ppos){
-+
-+ struct pld_sbihdr* sbihdr=filep->private_data;
-+ int bytes_left=count;
-+ int result;
-+ DEBUG(int i=0);
-+
-+
-+ /* Can't seek (pwrite) on pld. */
-+ if (ppos != &filep->f_pos)
-+ return -ESPIPE;
-+
-+
-+ /* Check access to the whole are in one go */
-+ if(!access_ok(VERIFY_READ,(const void*)data, count)){
-+ return -EFAULT;
-+ }
-+
-+ /*
-+ * We now lock against writes.
-+ */
-+ if (down_interruptible(&pld_sem))
-+ return -ERESTARTSYS;
-+
-+ if(!sbihdr->fpos){
-+ /*
-+ * unlock the pld and place in configure mode
-+ */
-+ unlock_excalibur_pld();
-+ result=place_pld_into_configure_mode();
-+ if(result)
-+ return result;
-+ }
-+ DEBUG(printk("data= %#x count=%#x 0ffset=%#x\n",*data, count, *ppos));
-+
-+ while(bytes_left){
-+ char tmp;
-+ __get_user(tmp,data);
-+ /* read our header ! */
-+ sbihdr->temp|=tmp << (8*(sbihdr->fpos&3));
-+ if((sbihdr->fpos&3)==3){
-+ if(write_pld_data_word(sbihdr->temp))
-+ {
-+ DEBUG(printk("pos=%d\n",sbihdr->fpos);)
-+ return -EILSEQ;
-+ }
-+ DEBUG(if(i<10){)
-+ DEBUG(printk("fpos2 :%#x data=%#x\n",sbihdr->fpos,sbihdr->temp));
-+ DEBUG(i++);
-+ DEBUG(});
-+ sbihdr->temp=0;
-+ DEBUG(words_written++);
-+ }
-+ sbihdr->fpos++;
-+ data++;
-+ bytes_left--;
-+ }
-+
-+ up(&pld_sem);
-+ return (count);
-+}
-+
-+int pld_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
-+{
-+
-+ switch(cmd){
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+ case PLD_IOC_ADD_PLD_DEV:
-+ {
-+ struct pldhs_dev_desc desc;
-+ struct pldhs_dev_info info;
-+ char *name;
-+ void *data;
-+ int result=0;
-+
-+ result=copy_from_user(&desc,(const void*)arg,sizeof(struct pldhs_dev_desc));
-+ if(result)
-+ return -EFAULT;
-+ result=copy_from_user(&info,(const void*)desc.info,sizeof(struct pldhs_dev_info));
-+ if(result)
-+ return -EFAULT;
-+ name=kmalloc(info.nsize,GFP_KERNEL);
-+ if(!name)
-+ return -ENOMEM;
-+
-+ result=copy_from_user(name,(const void*)desc.name,info.nsize);
-+ if(result){
-+ result=-EFAULT;
-+ goto ioctl_out;
-+ }
-+
-+ data=kmalloc(info.pssize,GFP_KERNEL);
-+ if(!data){
-+ result=-ENOMEM;
-+ goto ioctl_out;
-+ }
-+
-+ result=copy_from_user(data,(const void*)desc.data,info.pssize);
-+ if(result){
-+ result=-EFAULT;
-+ goto ioctl_out1;
-+ }
-+ result=pldhs_add_device(&info,name,data);
-+
-+ ioctl_out1:
-+ kfree(data);
-+ ioctl_out:
-+ kfree(name);
-+ return result;
-+
-+ }
-+
-+ case PLD_IOC_REMOVE_PLD_DEVS:
-+ pldhs_remove_devices();
-+ return 0;
-+
-+ case PLD_IOC_SET_INT_MODE:
-+ if(cmd==3){
-+ printk(KERN_INFO "Interrupt mode set to 3 (Six individual interrupts)\n");
-+ return 0;
-+ }else{
-+ printk(KERN_INFO "There is no interrupt handler available for this mode (%d). You will need to add one\n to implement whatever scheme you require\n");
-+ return -EACCES;
-+ }
-+#endif
-+ default:
-+ return -ENOTTY;
-+ }
-+}
-+
-+
-+static struct file_operations pld_fops={
-+ write: pld_write,
-+ ioctl: pld_ioctl,
-+ open: pld_open,
-+ release: pld_release
-+};
-+
-+static int __init pld_init(void){
-+ int major;
-+ major=register_chrdev(0,"pld",&pld_fops);
-+ printk(KERN_INFO "Using PLD major num=%d\n",major);
-+ if (major<0){
-+ return major;
-+ }
-+ return 0;
-+}
-+
-+__initcall(pld_init);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/pld/pld_hotswap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,188 @@
-+/*
-+ * linux/drivers/pld/pld_hotswap.c
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ *
-+ * Copyright 2001 Altera Corporation (cdavies@altera.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+
-+/*
-+ * pld_hotswap ops contains the basic operation required for adding
-+ * and removing devices from the system.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/pagemap.h>
-+#include <linux/slab.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <linux/kmod.h>
-+#include <linux/proc_fs.h>
-+#include <linux/list.h>
-+#include <asm/uaccess.h>
-+#include <linux/pld/pld_hotswap.h>
-+
-+
-+static struct pld_hotswap_ops pldhs_driver_list={
-+ list: LIST_HEAD_INIT(pldhs_driver_list.list),
-+ name: "",
-+};
-+
-+static spinlock_t list_lock=SPIN_LOCK_UNLOCKED;
-+
-+
-+
-+static struct pld_hotswap_ops * pldhs_find_driver(char* name)
-+{
-+ struct pld_hotswap_ops * ptr;
-+ struct list_head *list_pos;
-+
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(!strcmp(name, ptr->name)){
-+ spin_unlock(&list_lock);
-+ return ptr;
-+
-+ }
-+ }
-+ spin_unlock(&list_lock);
-+ return 0;
-+}
-+
-+
-+
-+int pldhs_register_driver(struct pld_hotswap_ops *drv)
-+{
-+
-+ /* Check that the device is not already on the list
-+ * if so, do nothing */
-+ if(pldhs_find_driver(drv->name)){
-+ return 0;
-+ }
-+
-+ printk(KERN_INFO "PLD: Registering hotswap driver %s\n",drv->name);
-+ /* Add this at the start of the list */
-+ spin_lock(&list_lock);
-+ list_add((struct list_head*)drv,&pldhs_driver_list.list);
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+int pldhs_unregister_driver(char *name)
-+{
-+ struct pld_hotswap_ops *ptr;
-+
-+ ptr=pldhs_find_driver(name);
-+ if(!ptr){
-+ return -ENODEV;
-+ }
-+
-+ printk(KERN_INFO "PLD: Unregistering hotswap driver%s\n",name);
-+ spin_lock(&list_lock);
-+ list_del((struct list_head*)ptr);
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data)
-+{
-+ struct pld_hotswap_ops * ptr;
-+
-+ ptr=pldhs_find_driver(drv_name);
-+
-+ if(!ptr){
-+ /* try requesting this module*/
-+ request_module(drv_name);
-+ /* is the driver there now? */
-+ ptr=pldhs_find_driver(drv_name);
-+ if(!ptr){
-+ printk("pld hotswap: Failed to load a driver for %s\n",drv_name);
-+ return -ENODEV;
-+ }
-+ }
-+
-+ if(!ptr->add_device){
-+ printk(KERN_WARNING "pldhs: no add_device() function for driver %s\n",drv_name);
-+ return 0;
-+ }
-+
-+ return ptr->add_device(dev_info,dev_ps_data);
-+}
-+
-+int pldhs_remove_devices(void)
-+{
-+ struct list_head *list_pos;
-+ struct pld_hotswap_ops * ptr;
-+
-+
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(ptr->remove_devices)
-+ ptr->remove_devices();
-+
-+ }
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+int pldhs_read_proc(char* buf,char** start,off_t offset,int count,int *eof,void *data){
-+
-+
-+ struct list_head *list_pos;
-+ struct pld_hotswap_ops * ptr;
-+ int i,len=0;
-+
-+ *start=buf;
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(ptr->proc_read){
-+ i=ptr->proc_read(buf,start,offset,count,eof,data);
-+ count-=i;
-+ len+=i;
-+ *start+=i;
-+ }
-+ }
-+ spin_unlock(&list_lock);
-+
-+ *start=NULL;
-+ *eof=1;
-+ return len;
-+}
-+
-+void __init pldhs_init(void){
-+ create_proc_read_entry("pld",0,NULL,pldhs_read_proc,NULL);
-+}
-+
-+__initcall(pldhs_init);
-+#endif
-+
-+EXPORT_SYMBOL(pldhs_register_driver);
-+EXPORT_SYMBOL(pldhs_unregister_driver);
---- linux-2.4.25/drivers/scsi/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/scsi/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -21,7 +21,7 @@
-
- O_TARGET := scsidrv.o
-
--export-objs := scsi_syms.o 53c700.o
-+export-objs := scsi_syms.o 53c700.o scsi_error.o
- mod-subdirs := pcmcia ../acorn/scsi
-
-
---- linux-2.4.25/drivers/scsi/scsi.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/scsi.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1334,14 +1334,10 @@
- */
- int scsi_retry_command(Scsi_Cmnd * SCpnt)
- {
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ /*
-+ * Restore the SCSI command state.
-+ */
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Zero the sense information from the last time we tried
---- linux-2.4.25/drivers/scsi/scsi.h~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/scsi.h 2004-03-31 17:15:09.000000000 +0200
-@@ -465,6 +465,7 @@
- int sectors);
- extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
- extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
-+extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
- extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
- extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
- int block_sectors);
-@@ -588,6 +589,7 @@
- unsigned changed:1; /* Data invalid due to media change */
- unsigned busy:1; /* Used to prevent races */
- unsigned lockable:1; /* Able to prevent media removal */
-+ unsigned locked:1; /* Media removal disabled */
- unsigned borken:1; /* Tell the Seagate driver to be
- * painfully slow on this device */
- unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
---- linux-2.4.25/drivers/scsi/scsi_dma.c~2.4.25-vrs2.patch 2002-02-25 20:38:04.000000000 +0100
-+++ linux-2.4.25/drivers/scsi/scsi_dma.c 2004-03-31 17:15:09.000000000 +0200
-@@ -30,6 +30,15 @@
- typedef unsigned char FreeSectorBitmap;
- #elif SECTORS_PER_PAGE <= 32
- typedef unsigned int FreeSectorBitmap;
-+#elif SECTORS_PER_PAGE <= 64
-+#if 0
-+typedef unsigned long long FreeSectorBitmap;
-+#else
-+typedef struct {
-+ unsigned long l,h;
-+} FreeSectorBitmap;
-+#define LARGE_MALLOC
-+#endif
- #else
- #error You lose.
- #endif
-@@ -69,6 +78,7 @@
- * to allocate more memory in order to be able to write the
- * data to disk, you would wedge the system.
- */
-+#ifndef LARGE_MALLOC
- void *scsi_malloc(unsigned int len)
- {
- unsigned int nbits, mask;
-@@ -167,6 +177,97 @@
- panic("scsi_free:Bad offset");
- }
-
-+#else
-+
-+void *scsi_malloc(unsigned int len)
-+{
-+ unsigned int nbits;
-+ unsigned long maskl, maskh, flags;
-+ FreeSectorBitmap *fsb;
-+ int i;
-+
-+ if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
-+ return NULL;
-+
-+ save_flags_cli (flags);
-+ nbits = len >> 9;
-+ if (nbits < 32) {
-+ maskl = (1 << nbits) - 1;
-+ maskh = 0;
-+ } else {
-+ maskl = (unsigned long)-1;
-+ maskh = (1 << (nbits - 32)) - 1;
-+ }
-+
-+ fsb = dma_malloc_freelist;
-+
-+ for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) {
-+ unsigned long mml, mmh;
-+ int j;
-+ mml = maskl;
-+ mmh = maskh;
-+ j = 0;
-+ do {
-+ if ((fsb->l & mml) == 0 && (fsb->h & mmh) == 0) {
-+ fsb->h |= mmh;
-+ fsb->l |= mml;
-+ restore_flags (flags);
-+ scsi_dma_free_sectors -= nbits;
-+#ifdef DEBUG
-+ printk("SMalloc: %d %p\n",len, dma_malloc_pages[i] + (j << 9));
-+#endif
-+ return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
-+ }
-+ mmh = (mmh << 1) | (mml >> 31);
-+ mml <<= 1;
-+ j++;
-+ } while (!(mmh & (1 << 31)));
-+ fsb ++;
-+ }
-+ return NULL; /* Nope. No more */
-+}
-+
-+int scsi_free(void *obj, unsigned int len)
-+{
-+ unsigned int page, sector, nbits;
-+ unsigned long maskl, maskh, flags;
-+
-+#ifdef DEBUG
-+ printk("scsi_free %p %d\n",obj, len);
-+#endif
-+
-+ for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
-+ unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
-+ if ((unsigned long) obj >= page_addr &&
-+ (unsigned long) obj < page_addr + PAGE_SIZE) {
-+ sector = (((unsigned long) obj) - page_addr) >> 9;
-+ nbits = len >> 9;
-+ if (nbits < 32) {
-+ maskl = (1 << nbits) - 1;
-+ maskh = 0;
-+ } else {
-+ maskl = (unsigned long)-1;
-+ maskh = (1 << (nbits - 32)) - 1;
-+ }
-+ if ((sector + nbits) > SECTORS_PER_PAGE)
-+ panic ("scsi_free:Bad memory alignment");
-+ maskh = (maskh << sector) | (maskl >> (32 - sector));
-+ maskl = maskl << sector;
-+ save_flags_cli(flags);
-+ if (((dma_malloc_freelist[page].l & maskl) != maskl) ||
-+ ((dma_malloc_freelist[page].h & maskh) != maskh))
-+ panic("scsi_free:Trying to free unused memory");
-+ scsi_dma_free_sectors += nbits;
-+ dma_malloc_freelist[page].l &= ~maskl;
-+ dma_malloc_freelist[page].h &= ~maskh;
-+ restore_flags(flags);
-+ return 0;
-+ }
-+ }
-+ panic("scsi_free:Bad offset");
-+}
-+#endif
-+
-
- /*
- * Function: scsi_resize_dma_pool
---- linux-2.4.25/drivers/scsi/scsi_error.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
-+++ linux-2.4.25/drivers/scsi/scsi_error.c 2004-03-31 17:15:09.000000000 +0200
-@@ -35,6 +35,8 @@
- #include "hosts.h"
- #include "constants.h"
-
-+#include <scsi/scsi_ioctl.h> /* grr */
-+
- /*
- * We must always allow SHUTDOWN_SIGS. Even if we are not a module,
- * the host drivers that we are using may be loaded as modules, and
-@@ -49,6 +51,13 @@
- */
- #define SHUTDOWN_SIGS (sigmask(SIGHUP))
-
-+/*
-+ * The number of times we retry a REQUEST SENSE and TEST UNIT READY
-+ * respectively. This is arbitary.
-+ */
-+#define SENSE_RETRIES 5
-+#define TUR_RETRIES 5
-+
- #ifdef DEBUG
- #define SENSE_TIMEOUT SCSI_TIMEOUT
- #define ABORT_TIMEOUT SCSI_TIMEOUT
-@@ -385,16 +394,12 @@
- */
- STATIC int scsi_eh_retry_command(Scsi_Cmnd * SCpnt)
- {
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ int tries = 0;
-
-- scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
-+ do {
-+ scsi_setup_cmd_retry(SCpnt);
-+ scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SCpnt->allowed);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -421,16 +426,10 @@
- static unsigned char generic_sense[6] =
- {REQUEST_SENSE, 0, 0, 0, 255, 0};
- unsigned char scsi_result0[256], *scsi_result = NULL;
-- int saved_result;
-+ int saved_result, tries;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
-- memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
-- sizeof(generic_sense));
--
-- if (SCpnt->device->scsi_level <= SCSI_2)
-- SCpnt->cmnd[1] = SCpnt->lun << 5;
--
- scsi_result = (!SCpnt->host->hostt->unchecked_isa_dma)
- ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
-
-@@ -438,24 +437,41 @@
- printk("cannot allocate scsi_result in scsi_request_sense.\n");
- return FAILED;
- }
-- /*
-- * Zero the sense buffer. Some host adapters automatically always request
-- * sense, so it is not a good idea that SCpnt->request_buffer and
-- * SCpnt->sense_buffer point to the same address (DB).
-- * 0 is not a valid sense code.
-- */
-- memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-- memset((void *) scsi_result, 0, 256);
-
- saved_result = SCpnt->result;
-- SCpnt->request_buffer = scsi_result;
-- SCpnt->request_bufflen = 256;
-- SCpnt->use_sg = 0;
-- SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-- SCpnt->sc_data_direction = SCSI_DATA_READ;
-- SCpnt->underflow = 0;
-
-- scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ tries = 0;
-+ do {
-+ memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
-+ sizeof(generic_sense));
-+
-+ if (SCpnt->device->scsi_level <= SCSI_2)
-+ SCpnt->cmnd[1] = SCpnt->lun << 5;
-+
-+ /*
-+ * Zero the sense buffer. Some host adapters automatically
-+ * always request sense, so it is not a good idea that
-+ * SCpnt->request_buffer and SCpnt->sense_buffer point to
-+ * the same address (DB). 0 is not a valid sense code.
-+ */
-+ memset((void *) SCpnt->sense_buffer, 0,
-+ sizeof(SCpnt->sense_buffer));
-+ memset((void *) scsi_result, 0, 256);
-+
-+ SCpnt->request_buffer = scsi_result;
-+ SCpnt->request_bufflen = 256;
-+ SCpnt->use_sg = 0;
-+ SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-+ SCpnt->sc_data_direction = SCSI_DATA_READ;
-+ SCpnt->underflow = 0;
-+
-+ scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ /*
-+ * If the SCSI device responded with "logical unit
-+ * is in process of becoming ready", we need to
-+ * retry this command.
-+ */
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SENSE_RETRIES);
-
- /* Last chance to have valid sense data */
- if (!scsi_sense_valid(SCpnt))
-@@ -470,15 +486,8 @@
- * When we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (DB)
- */
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
- SCpnt->result = saved_result;
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -496,40 +505,42 @@
- {
- static unsigned char tur_command[6] =
- {TEST_UNIT_READY, 0, 0, 0, 0, 0};
-+ int tries = 0;
-
-- memcpy((void *) SCpnt->cmnd, (void *) tur_command,
-- sizeof(tur_command));
-+ do {
-+ memcpy((void *) SCpnt->cmnd, (void *) tur_command,
-+ sizeof(tur_command));
-
-- if (SCpnt->device->scsi_level <= SCSI_2)
-- SCpnt->cmnd[1] = SCpnt->lun << 5;
-+ if (SCpnt->device->scsi_level <= SCSI_2)
-+ SCpnt->cmnd[1] = SCpnt->lun << 5;
-
-- /*
-- * Zero the sense buffer. The SCSI spec mandates that any
-- * untransferred sense data should be interpreted as being zero.
-- */
-- memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-+ /*
-+ * Zero the sense buffer. The SCSI spec mandates that any
-+ * untransferred sense data should be interpreted as being zero.
-+ */
-+ memset((void *) SCpnt->sense_buffer, 0,
-+ sizeof(SCpnt->sense_buffer));
-
-- SCpnt->request_buffer = NULL;
-- SCpnt->request_bufflen = 0;
-- SCpnt->use_sg = 0;
-- SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-- SCpnt->underflow = 0;
-- SCpnt->sc_data_direction = SCSI_DATA_NONE;
-+ SCpnt->request_buffer = NULL;
-+ SCpnt->request_bufflen = 0;
-+ SCpnt->use_sg = 0;
-+ SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-+ SCpnt->underflow = 0;
-+ SCpnt->sc_data_direction = SCSI_DATA_NONE;
-
-- scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ /*
-+ * If the SCSI device responded with "logical unit
-+ * is in process of becoming ready", we need to
-+ * retry this command.
-+ */
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < TUR_RETRIES);
-
- /*
- * When we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (DB)
- */
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -589,7 +600,6 @@
-
- host = SCpnt->host;
-
-- retry:
- /*
- * We will use a queued command if possible, otherwise we will emulate the
- * queuing and calling of completion function ourselves.
-@@ -672,14 +682,13 @@
- SCSI_LOG_ERROR_RECOVERY(3,
- printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", ret));
- switch (ret) {
-- case SUCCESS:
-- SCpnt->eh_state = SUCCESS;
-- break;
-- case NEEDS_RETRY:
-- goto retry;
-- case FAILED:
- default:
-- SCpnt->eh_state = FAILED;
-+ ret = FAILED;
-+ /*FALLTHROUGH*/
-+ case FAILED:
-+ case NEEDS_RETRY:
-+ case SUCCESS:
-+ SCpnt->eh_state = ret;
- break;
- }
- } else {
-@@ -1220,6 +1229,82 @@
-
-
- /*
-+ * Function: scsi_eh_lock_done
-+ *
-+ * Purpose: free the command and request structures associated
-+ * with the error handlers door lock request
-+ *
-+ * Arguments: SCpnt - the SCSI command block for the door lock request.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: We completed the asynchronous door lock request, and
-+ * it has either locked the door or failed. We must free
-+ * the command structures associated with this request.
-+ */
-+static void scsi_eh_lock_done(struct scsi_cmnd *SCpnt)
-+{
-+ struct scsi_request *SRpnt = SCpnt->sc_request;
-+
-+ SCpnt->sc_request = NULL;
-+ SRpnt->sr_command = NULL;
-+
-+ scsi_release_command(SCpnt);
-+ scsi_release_request(SRpnt);
-+}
-+
-+
-+/*
-+ * Function: scsi_eh_lock_door
-+ *
-+ * Purpose: Prevent medium removal for the specified device
-+ *
-+ * Arguments: dev - SCSI device to prevent medium removal
-+ *
-+ * Locking: We must be called from process context;
-+ * scsi_allocate_request() may sleep.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request
-+ * on the head of the devices request queue, and continue.
-+ *
-+ * Bugs: scsi_allocate_request() may sleep waiting for existing
-+ * requests to be processed. However, since we haven't
-+ * kicked off any request processing for this host, this
-+ * may deadlock.
-+ *
-+ * If scsi_allocate_request() fails for what ever reason,
-+ * we completely forget to lock the door.
-+ */
-+STATIC void scsi_eh_lock_door(struct scsi_device *dev)
-+{
-+ struct scsi_request *SRpnt = scsi_allocate_request(dev);
-+
-+ if (SRpnt == NULL) {
-+ /* what now? */
-+ return;
-+ }
-+
-+ SRpnt->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-+ SRpnt->sr_cmnd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
-+ SRpnt->sr_cmnd[2] = 0;
-+ SRpnt->sr_cmnd[3] = 0;
-+ SRpnt->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
-+ SRpnt->sr_cmnd[5] = 0;
-+ SRpnt->sr_data_direction = SCSI_DATA_NONE;
-+ SRpnt->sr_bufflen = 0;
-+ SRpnt->sr_buffer = NULL;
-+ SRpnt->sr_allowed = 5;
-+ SRpnt->sr_done = scsi_eh_lock_done;
-+ SRpnt->sr_timeout_per_command = 10 * HZ;
-+ SRpnt->sr_cmd_len = COMMAND_SIZE(SRpnt->sr_cmnd[0]);
-+
-+ scsi_insert_special_req(SRpnt, 1);
-+}
-+
-+
-+/*
- * Function: scsi_restart_operations
- *
- * Purpose: Restart IO operations to the specified host.
-@@ -1241,6 +1326,15 @@
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
-+ * If the door was locked, we need to insert a door lock request
-+ * onto the head of the SCSI request queue for the device. There
-+ * is no point trying to lock the door of an off-line device.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ if (SDpnt->online && SDpnt->locked)
-+ scsi_eh_lock_door(SDpnt);
-+
-+ /*
- * Next free up anything directly waiting upon the host. This will be
- * requests for character device operations, and also for ioctls to queued
- * block devices.
-@@ -1260,8 +1354,7 @@
- request_queue_t *q;
- if ((host->can_queue > 0 && (host->host_busy >= host->can_queue))
- || (host->host_blocked)
-- || (host->host_self_blocked)
-- || (SDpnt->device_blocked)) {
-+ || (host->host_self_blocked)) {
- break;
- }
- q = &SDpnt->request_queue;
-@@ -1271,136 +1364,202 @@
- }
-
- /*
-- * Function: scsi_unjam_host
-+ * Function: scsi_eh_find_failed_command
- *
-- * Purpose: Attempt to fix a host which has a command that failed for
-- * some reason.
-+ * Purpose: Find a failed Scsi_Cmnd structure on a device.
- *
-- * Arguments: host - host that needs unjamming.
-- *
-- * Returns: Nothing
-+ * Arguments: SDpnt - Scsi_Device structure
- *
-- * Notes: When we come in here, we *know* that all commands on the
-- * bus have either completed, failed or timed out. We also
-- * know that no further commands are being sent to the host,
-- * so things are relatively quiet and we have freedom to
-- * fiddle with things as we wish.
-+ * Returns: Pointer to Scsi_Cmnd structure, or NULL on failure
-+ */
-+STATIC Scsi_Cmnd *scsi_eh_find_failed_command(Scsi_Device *SDpnt)
-+{
-+ Scsi_Cmnd *SCpnt;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
-+ if (SCpnt->state == SCSI_STATE_FAILED ||
-+ SCpnt->state == SCSI_STATE_TIMEOUT)
-+ return SCpnt;
-+
-+ return NULL;
-+}
-+
-+
-+/*
-+ * Function: scsi_eh_test_and_retry
- *
-- * Additional note: This is only the *default* implementation. It is possible
-- * for individual drivers to supply their own version of this
-- * function, and if the maintainer wishes to do this, it is
-- * strongly suggested that this function be taken as a template
-- * and modified. This function was designed to correctly handle
-- * problems for about 95% of the different cases out there, and
-- * it should always provide at least a reasonable amount of error
-- * recovery.
-+ * Purpose: Try to retry a failed command.
- *
-- * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
-- * have scsi_finish_command() called for it. We do all of
-- * the retry stuff here, so when we restart the host after we
-- * return it should have an empty queue.
-+ * Arguments: SCpnt - scsi command structure
-+ * done - list of commands that have been successfully
-+ * completed.
-+ *
-+ * Returns: SUCCESS or FAILED
-+ *
-+ * Note: If the TEST UNIT READY command successfully executes,
-+ * but returns some form of "device not ready", we wait
-+ * a while, and retry 3 times. The device could be still
-+ * re-initialising.
- */
--STATIC int scsi_unjam_host(struct Scsi_Host *host)
-+STATIC int scsi_eh_test_and_retry(Scsi_Cmnd *SCpnt, Scsi_Cmnd **done)
- {
-- int devices_failed;
-- int numfailed;
-- int ourrtn;
-- int rtn = FALSE;
-- int result;
-- Scsi_Cmnd *SCloop;
-- Scsi_Cmnd *SCpnt;
-- Scsi_Device *SDpnt;
-- Scsi_Device *SDloop;
-- Scsi_Cmnd *SCdone;
-- int timed_out;
-+ int rtn, tries = 3;
-
-- ASSERT_LOCK(&io_request_lock, 0);
-+ do {
-+ rtn = scsi_test_unit_ready(SCpnt);
-+ if (rtn != SUCCESS)
-+ return rtn;
-
-- SCdone = NULL;
-+ if (scsi_unit_is_ready(SCpnt))
-+ break;
-+
-+ if (tries-- == 0)
-+ return FAILED;
-+
-+ scsi_sleep(5 * HZ);
-+ } while (1);
-+
-+ rtn = scsi_eh_retry_command(SCpnt);
-+ if (rtn == SUCCESS) {
-+ SCpnt->host->host_failed--;
-+ scsi_eh_finish_command(done, SCpnt);
-+ }
-+
-+ return rtn;
-+}
-
-- /*
-- * First, protect against any sort of race condition. If any of the outstanding
-- * commands are in states that indicate that we are not yet blocked (i.e. we are
-- * not in a quiet state) then we got woken up in error. If we ever end up here,
-- * we need to re-examine some of the assumptions.
-- */
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state == SCSI_STATE_FAILED
-- || SCpnt->state == SCSI_STATE_TIMEOUT
-- || SCpnt->state == SCSI_STATE_INITIALIZING
-- || SCpnt->state == SCSI_STATE_UNUSED) {
-- continue;
-- }
-- /*
-- * Rats. Something is still floating around out there. This could
-- * be the result of the fact that the upper level drivers are still frobbing
-- * commands that might have succeeded. There are two outcomes. One is that
-- * the command block will eventually be freed, and the other one is that
-- * the command will be queued and will be finished along the way.
-- */
-- SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
-
- /*
-- * panic("SCSI Error handler woken too early\n");
-+ * Function: scsi_eh_restart_device
- *
-- * This is no longer a problem, since now the code cares only about
-- * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
-- * Other states are useful only to release active commands when devices are
-- * set offline. If (host->host_active == host->host_busy) we can safely assume
-- * that there are no commands in state other then TIMEOUT od FAILED. (DB)
-+ * Purpose: Retry all failed or timed out commands for a device
- *
-- * FIXME:
-- * It is not easy to release correctly commands according to their state when
-- * devices are set offline, when the state is neither TIMEOUT nor FAILED.
-- * When a device is set offline, we can have some command with
-- * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
-- * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
-- * (DB, 17 May 1998)
-+ * Arguments: SDpnt - SCSI device to retry
-+ * done - list of commands that have been successfully
-+ * completed.
-+ *
-+ * Returns: SUCCESS or failure code
- */
-+STATIC int scsi_eh_restart_device(Scsi_Device *SDpnt, Scsi_Cmnd **done)
-+{
-+ Scsi_Cmnd *SCpnt, *SCnext;
-+ int rtn = SUCCESS;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
-+ SCnext = SCpnt->next;
-+
-+ if (SCpnt->state == SCSI_STATE_FAILED ||
-+ SCpnt->state == SCSI_STATE_TIMEOUT) {
-+ rtn = scsi_eh_test_and_retry(SCpnt, done);
-+ if (rtn != SUCCESS)
-+ break;
-+ }
-+ }
-+
-+ return rtn;
-+}
-+
-+/*
-+ * Function: scsi_eh_set_device_offline
-+ *
-+ * Purpose: set a device off line
-+ *
-+ * Arguments: SDpnt - SCSI device to take off line
-+ * done - list of commands that have been successfully
-+ * completed.
-+ * reason - text string describing why the device is off-line
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: In addition, we complete each failed or timed out command
-+ * attached to this device.
-+ */
-+STATIC void scsi_eh_set_device_offline(Scsi_Device *SDpnt, Scsi_Cmnd **done,
-+ const char *reason)
-+{
-+ Scsi_Cmnd *SCpnt, *SCnext;
-+
-+ printk(KERN_ERR "scsi: device set offline - %s: "
-+ "host %d channel %d id %d lun %d\n",
-+ reason, SDpnt->host->host_no, SDpnt->channel,
-+ SDpnt->id, SDpnt->lun);
-+
-+ SDpnt->online = FALSE;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
-+ SCnext = SCpnt->next;
-+
-+ switch (SCpnt->state) {
-+ case SCSI_STATE_TIMEOUT:
-+ SCpnt->result |= DRIVER_TIMEOUT;
-+ /*FALLTHROUGH*/
-+
-+ case SCSI_STATE_FAILED:
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("Finishing command for device %d %x\n",
-+ SDpnt->id, SCpnt->result));
-+
-+ SDpnt->host->host_failed--;
-+ scsi_eh_finish_command(done, SCpnt);
-+ break;
-+
-+ default:
-+ break;
- }
- }
-+}
-+
-+static void scsi_unjam_request_sense(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ int rtn;
-+ int result;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Device *SDpnt;
-
- /*
- * Next, see if we need to request sense information. if so,
- * then get it now, so we have a better idea of what to do.
-- * FIXME(eric) this has the unfortunate side effect that if a host
-- * adapter does not automatically request sense information, that we end
-- * up shutting it down before we request it. All hosts should be doing this
-- * anyways, so for now all I have to say is tough noogies if you end up in here.
-- * On second thought, this is probably a good idea. We *really* want to give
-- * authors an incentive to automatically request this.
-+ * FIXME(eric) this has the unfortunate side effect that if a
-+ * host adapter does not automatically request sense information,
-+ * that we end up shutting it down before we request it. All
-+ * hosts should be doing this anyways, so for now all I have
-+ * to say is tough noogies if you end up in here. On second
-+ * thought, this is probably a good idea. We *really* want
-+ * to give authors an incentive to automatically request this.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt)) {
-+ if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt))
- continue;
-- }
-- SCSI_LOG_ERROR_RECOVERY(2, printk("scsi_unjam_host: Requesting sense for %d\n",
-- SCpnt->target));
-+
-+ SCSI_LOG_ERROR_RECOVERY(2,
-+ printk("scsi_unjam_host: Requesting sense for %d\n",
-+ SCpnt->target));
- rtn = scsi_request_sense(SCpnt);
-- if (rtn != SUCCESS) {
-+ if (rtn != SUCCESS)
- continue;
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("Sense requested for %p - result %x\n",
-- SCpnt, SCpnt->result));
-+
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("Sense requested for %p - result %x\n",
-+ SCpnt, SCpnt->result));
- SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", SCpnt));
-
- result = scsi_decide_disposition(SCpnt);
-
- /*
-- * If the result was normal, then just pass it along to the
-- * upper level.
-+ * If the result was normal, then just pass
-+ * it along to the upper level.
- */
- if (result == SUCCESS) {
- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCpnt);
-+ scsi_eh_finish_command(done, SCpnt);
- }
-- if (result != NEEDS_RETRY) {
-+ if (result != NEEDS_RETRY)
- continue;
-- }
-+
- /*
- * We only come in here if we want to retry a
- * command. The test to see whether the command
-@@ -1410,20 +1569,29 @@
- */
- SCpnt->state = NEEDS_RETRY;
- rtn = scsi_eh_retry_command(SCpnt);
-- if (rtn != SUCCESS) {
-+ if (rtn != SUCCESS)
- continue;
-- }
-+
- /*
- * We eventually hand this one back to the top level.
- */
- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCpnt);
-+ scsi_eh_finish_command(done, SCpnt);
- }
- }
-+}
-+
-+static void scsi_unjam_count(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int devices_failed;
-+ int numfailed;
-+ int timed_out;
-
- /*
-- * Go through the list of commands and figure out where we stand and how bad things
-- * really are.
-+ * Go through the list of commands and figure out where we
-+ * stand and how bad things really are.
- */
- numfailed = 0;
- timed_out = 0;
-@@ -1433,359 +1601,478 @@
-
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
- if (SCpnt->state == SCSI_STATE_FAILED) {
-- SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d failed\n",
-- SCpnt->target));
-+ SCSI_LOG_ERROR_RECOVERY(5,
-+ printk("Command to ID %d failed\n",
-+ SCpnt->target));
- numfailed++;
- device_error++;
- }
- if (SCpnt->state == SCSI_STATE_TIMEOUT) {
-- SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d timedout\n",
-- SCpnt->target));
-+ SCSI_LOG_ERROR_RECOVERY(5,
-+ printk("Command to ID %d timedout\n",
-+ SCpnt->target));
- timed_out++;
- device_error++;
- }
- }
-- if (device_error > 0) {
-+ if (device_error > 0)
- devices_failed++;
-- }
- }
-
-- SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d+%d commands on %d devices require eh work\n",
-- numfailed, timed_out, devices_failed));
-+ SCSI_LOG_ERROR_RECOVERY(2,
-+ printk("Total of %d+%d commands on %d devices require eh work\n",
-+ numfailed, timed_out, devices_failed));
-+}
-+
-+static void scsi_unjam_abort(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn;
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * Next, try and see whether or not it makes sense to try and abort
-- * the running command. This only works out to be the case if we have
-- * one command that has timed out. If the command simply failed, it
-- * makes no sense to try and abort the command, since as far as the
-- * host adapter is concerned, it isn't running.
-+ * Next, try and see whether or not it makes sense to try and
-+ * abort the running command. This only works out to be the
-+ * case if we have one command that has timed out. If the
-+ * command simply failed, it makes no sense to try and abort
-+ * the command, since as far as the host adapter is concerned,
-+ * it isn't running.
- */
-
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state != SCSI_STATE_TIMEOUT) {
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-+ if (SCpnt->state != SCSI_STATE_TIMEOUT)
- continue;
-- }
-- rtn = scsi_try_to_abort_command(SCloop, ABORT_TIMEOUT);
-- if (rtn == SUCCESS) {
-- rtn = scsi_test_unit_ready(SCloop);
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
--
-- if (rtn == SUCCESS) {
-- SCloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-+ rtn = scsi_try_to_abort_command(SCpnt, ABORT_TIMEOUT);
-+ if (rtn == SUCCESS)
-+ scsi_eh_test_and_retry(SCpnt, done);
- }
- }
-+}
-+
-+static void scsi_unjam_device_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn;
-
-- /*
-- * If we have corrected all of the problems, then we are done.
-- */
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
- * Either the abort wasn't appropriate, or it didn't succeed.
-- * Now try a bus device reset. Still, look to see whether we have
-- * multiple devices that are jammed or not - if we have multiple devices,
-- * it makes no sense to try BUS_DEVICE_RESET - we really would need
-- * to try a BUS_RESET instead.
-+ * Now try a bus device reset. Still, look to see whether we
-+ * have multiple devices that are jammed or not - if we have
-+ * multiple devices, it makes no sense to try BUS_DEVICE_RESET
-+ * - we really would need to try a BUS_RESET instead.
- *
-- * Does this make sense - should we try BDR on each device individually?
-- * Yes, definitely.
-+ * Does this make sense - should we try BDR on each device
-+ * individually? Yes, definitely.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state == SCSI_STATE_FAILED
-- || SCloop->state == SCSI_STATE_TIMEOUT) {
-- break;
-- }
-- }
--
-- if (SCloop == NULL) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt == NULL)
- continue;
-- }
-+
- /*
-- * OK, we have a device that is having problems. Try and send
-- * a bus device reset to it.
-- *
-- * FIXME(eric) - make sure we handle the case where multiple
-- * commands to the same device have failed. They all must
-- * get properly restarted.
-+ * OK, we have a device that is having problems.
-+ * Try and send a bus device reset to it.
- */
-- rtn = scsi_try_bus_device_reset(SCloop, RESET_TIMEOUT);
-+ rtn = scsi_try_bus_device_reset(SCpnt, RESET_TIMEOUT);
-
-- if (rtn == SUCCESS) {
-- rtn = scsi_test_unit_ready(SCloop);
-+ /*
-+ * A successful bus device reset causes all commands
-+ * currently executing on the device to terminate.
-+ * We expect the HBA driver to "forget" all commands
-+ * associated with this device.
-+ *
-+ * Retry each failed or timed out command currently
-+ * outstanding for this device.
-+ *
-+ * If any command fails, bail out. We will try a
-+ * bus reset instead.
-+ */
-+ if (rtn == SUCCESS)
-+ scsi_eh_restart_device(SDpnt, done);
-+ }
-+}
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+static void scsi_unjam_bus_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn, channel, max_channel = 0;
-
-- if (rtn == SUCCESS) {
-- SCloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-- }
-+ /*
-+ * If we ended up here, we have serious problems. The only thing
-+ * left to try is a full bus reset. If someone has grabbed the
-+ * bus and isn't letting go, then perhaps this will help.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try hard bus reset\n"));
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * If we ended up here, we have serious problems. The only thing left
-- * to try is a full bus reset. If someone has grabbed the bus and isn't
-- * letting go, then perhaps this will help.
-+ * Find the maximum channel number for this host.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard bus reset\n"));
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ if (SDpnt->channel > max_channel)
-+ max_channel = SDpnt->channel;
-
-- /*
-- * We really want to loop over the various channels, and do this on
-- * a channel by channel basis. We should also check to see if any
-- * of the failed commands are on soft_reset devices, and if so, skip
-- * the reset.
-+ /*
-+ * Loop over each channel, and see if it any device on
-+ * each channel has failed.
- */
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- next_device:
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED
-- && SCpnt->state != SCSI_STATE_TIMEOUT) {
-+ for (channel = 0; channel <= max_channel; channel++) {
-+ Scsi_Cmnd *failed_command;
-+ int soft_reset;
-+
-+ try_again:
-+ failed_command = NULL;
-+ soft_reset = 0;
-+
-+ /*
-+ * Loop over each device on this channel locating any
-+ * failed command. We need a Scsi_Cmnd structure to
-+ * call the bus reset function.
-+ *
-+ * We also need to check if any of the failed commands
-+ * are on soft_reset devices, and if so, skip the reset.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ if (SDpnt->channel != channel)
- continue;
-- }
-- /*
-- * We have a failed command. Make sure there are no other failed
-- * commands on the same channel that are timed out and implement a
-- * soft reset.
-- */
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->channel != SCpnt->channel) {
-- continue;
-- }
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- if (SDloop->soft_reset && SCloop->state == SCSI_STATE_TIMEOUT) {
-- /*
-- * If this device uses the soft reset option, and this
-- * is one of the devices acting up, then our only
-- * option is to wait a bit, since the command is
-- * supposedly still running.
-- *
-- * FIXME(eric) - right now we will just end up falling
-- * through to the 'take device offline' case.
-- *
-- * FIXME(eric) - It is possible that the command completed
-- * *after* the error recovery procedure started, and if this
-- * is the case, we are worrying about nothing here.
-- */
-
-- scsi_sleep(1 * HZ);
-- goto next_device;
-- }
-- }
-- }
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt)
-+ failed_command = SCpnt;
-
- /*
-- * We now know that we are able to perform a reset for the
-- * bus that SCpnt points to. There are no soft-reset devices
-- * with outstanding timed out commands.
-+ * If this device has timed out or failed commands,
-+ * and uses the soft_reset option.
- */
-- rtn = scsi_try_bus_reset(SCpnt);
-- if (rtn == SUCCESS) {
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->channel != SCpnt->channel) {
-- continue;
-- }
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- rtn = scsi_test_unit_ready(SCloop);
-+ if (SCpnt && SDpnt->soft_reset)
-+ soft_reset = 1;
-+ }
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+ /*
-+ * If this channel hasn't failed, we
-+ * don't need to reset it.
-+ */
-+ if (!failed_command)
-+ continue;
-
-- if (rtn == SUCCESS) {
-- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- /*
-- * If the bus reset worked, but we are still unable to
-- * talk to the device, take it offline.
-- * FIXME(eric) - is this really the correct thing to do?
-- */
-- if (rtn != SUCCESS) {
-- printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after bus reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-+ /*
-+ * If this device uses the soft reset option, and this
-+ * is one of the devices acting up, then our only
-+ * option is to wait a bit, since the command is
-+ * supposedly still running.
-+ *
-+ * FIXME(eric) - right now we will just end up falling
-+ * through to the 'take device offline' case.
-+ *
-+ * FIXME(eric) - It is possible that the command completed
-+ * *after* the error recovery procedure started, and if
-+ * this is the case, we are worrying about nothing here.
-+ *
-+ * FIXME(rmk) - This should be bounded; we shouldn't wait
-+ * for an infinite amount of time for any device.
-+ */
-+ if (soft_reset) {
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: unable to try bus "
-+ "reset for host %d channel %d\n",
-+ host->host_no, channel));
-+ scsi_sleep(1 * HZ);
-+ goto try_again;
-+ }
-
-- SDloop->online = FALSE;
-- SDloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-+ /*
-+ * We now know that we are able to perform a reset for the
-+ * bus that SCpnt points to. There are no soft-reset devices
-+ * with outstanding timed out commands.
-+ */
-+ rtn = scsi_try_bus_reset(failed_command);
-+
-+ /*
-+ * If we failed to reset the bus, move on to the next bus.
-+ */
-+ if (rtn != SUCCESS)
-+ continue;
-+
-+ /*
-+ * We succeeded. Retry each failed command.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ if (SDpnt->channel != channel)
-+ continue;
-+
-+ rtn = scsi_eh_restart_device(SDpnt, done);
-+
-+ if (rtn != SUCCESS) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+
-+ /*
-+ * This device failed again. Since a bus
-+ * reset freed it up, chances are we've
-+ * hit the same problem, so try the same
-+ * solution. We also need to ensure that
-+ * the SCSI bus is in the BUS FREE state
-+ * so we can try to talk to other devices.
-+ */
-+ scsi_try_bus_reset(SCpnt);
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "not ready or command retry "
-+ "failed after bus reset");
- }
- }
- }
-+}
-+
-+static void scsi_unjam_host_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Cmnd *failed_command = NULL;
-+ int rtn, soft_reset;
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * If we ended up here, we have serious problems. The only thing left
-- * to try is a full host reset - perhaps the firmware on the device
-- * crashed, or something like that.
-+ * If we ended up here, we have serious problems. The only thing
-+ * left to try is a full host reset - perhaps the firmware on the
-+ * device crashed, or something like that.
- *
-- * It is assumed that a succesful host reset will cause *all* information
-- * about the command to be flushed from both the host adapter *and* the
-- * device.
-+ * It is assumed that a succesful host reset will cause *all*
-+ * information about the command to be flushed from both the host
-+ * adapter *and* the device.
- *
-- * FIXME(eric) - it isn't clear that devices that implement the soft reset
-- * option can ever be cleared except via cycling the power. The problem is
-- * that sending the host reset command will cause the host to forget
-- * about the pending command, but the device won't forget. For now, we
-- * skip the host reset option if any of the failed devices are configured
-- * to use the soft reset option.
-+ * FIXME(eric) - it isn't clear that devices that implement the
-+ * soft reset option can ever be cleared except via cycling the
-+ * power. The problem is that sending the host reset command will
-+ * cause the host to forget about the pending command, but the
-+ * device won't forget. For now, we skip the host reset option
-+ * if any of the failed devices are configured to use the soft
-+ * reset option.
- */
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try host reset\n"));
-+
-+ try_again:
-+ failed_command = NULL;
-+ soft_reset = 0;
-+
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- next_device2:
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED
-- && SCpnt->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- if (SDpnt->soft_reset && SCpnt->state == SCSI_STATE_TIMEOUT) {
-- /*
-- * If this device uses the soft reset option, and this
-- * is one of the devices acting up, then our only
-- * option is to wait a bit, since the command is
-- * supposedly still running.
-- *
-- * FIXME(eric) - right now we will just end up falling
-- * through to the 'take device offline' case.
-- */
-- SCSI_LOG_ERROR_RECOVERY(3,
-- printk("scsi_unjam_host: Unable to try hard host reset\n"));
-+ /*
-+ * Locate any failed commands for this device.
-+ */
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt)
-+ failed_command = SCpnt;
-
-- /*
-- * Due to the spinlock, we will never get out of this
-- * loop without a proper wait. (DB)
-- */
-- scsi_sleep(1 * HZ);
-+ /*
-+ * If this device has timed out or failed commands,
-+ * and uses the soft_reset option.
-+ */
-+ if (SCpnt && SDpnt->soft_reset)
-+ soft_reset = 1;
-+ }
-
-- goto next_device2;
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard host reset\n"));
-+ /*
-+ * If this device uses the soft reset option, and this
-+ * is one of the devices acting up, then our only
-+ * option is to wait a bit, since the command is
-+ * supposedly still running.
-+ *
-+ * FIXME(eric) - right now we will just end up falling
-+ * through to the 'take device offline' case.
-+ *
-+ * FIXME(rmk) - This should be bounded; we shouldn't wait
-+ * for an infinite amount of time for any device.
-+ */
-+ if (soft_reset) {
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: unable to try "
-+ "hard host reset\n"));
-
- /*
-- * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
-+ * Due to the spinlock, we will never get out of this
-+ * loop without a proper wait. (DB)
- */
-- rtn = scsi_try_host_reset(SCpnt);
-- if (rtn == SUCCESS) {
-- /*
-- * FIXME(eric) we assume that all commands are flushed from the
-- * controller. We should get a DID_RESET for all of the commands
-- * that were pending. We should ignore these so that we can
-- * guarantee that we are in a consistent state.
-- *
-- * I believe this to be the case right now, but this needs to be
-- * tested.
-- */
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- rtn = scsi_test_unit_ready(SCloop);
--
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+ scsi_sleep(1 * HZ);
-
-- if (rtn == SUCCESS) {
-- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- if (rtn != SUCCESS) {
-- printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after host reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-- SDloop->online = FALSE;
-- SDloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-- }
-- }
-+ goto try_again;
- }
-
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try hard host reset\n"));
-+
- /*
-- * If we solved all of the problems, then let's rev up the engines again.
-- */
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
-- /*
-- * If the HOST RESET failed, then for now we assume that the entire host
-- * adapter is too hosed to be of any use. For our purposes, however, it is
-- * easier to simply take the devices offline that correspond to commands
-- * that failed.
-+ * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
- */
-- SCSI_LOG_ERROR_RECOVERY(1, printk("scsi_unjam_host: Take device offline\n"));
-+ rtn = scsi_try_host_reset(failed_command);
-+ if (rtn == SUCCESS) {
-+ /*
-+ * FIXME(eric) we assume that all commands are flushed from
-+ * the controller. We should get a DID_RESET for all of the
-+ * commands that were pending. We should ignore these so
-+ * that we can guarantee that we are in a consistent state.
-+ *
-+ * I believe this to be the case right now, but this needs
-+ * to be tested.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ rtn = scsi_eh_restart_device(SDpnt, done);
-
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == SCSI_STATE_TIMEOUT) {
-- SDloop = SCloop->device;
-- if (SDloop->online == TRUE) {
-- printk(KERN_INFO "scsi: device set offline - command error recover failed: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-- SDloop->online = FALSE;
-- }
-+ if (rtn != SUCCESS) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-
- /*
-- * This should pass the failure up to the top level driver, and
-- * it will have to try and do something intelligent with it.
-+ * This device failed again. Since a host
-+ * reset freed it up, chances are we've
-+ * hit the same problem, so try the same
-+ * solution. We also need to ensure that
-+ * the SCSI bus is in the BUS FREE state
-+ * so we can try to talk to other devices.
- */
-- SCloop->host->host_failed--;
--
-- if (SCloop->state == SCSI_STATE_TIMEOUT) {
-- SCloop->result |= (DRIVER_TIMEOUT << 24);
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command for device %d %x\n",
-- SDloop->id, SCloop->result));
--
-- scsi_eh_finish_command(&SCdone, SCloop);
-+ scsi_try_host_reset(SCpnt);
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "not ready or command retry "
-+ "failed after host reset");
- }
- }
- }
-+}
-
-- if (host->host_failed != 0) {
-+static void scsi_unjam_failure(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+
-+ /*
-+ * If the HOST RESET failed, then for now we assume that the
-+ * entire host adapter is too hosed to be of any use. For our
-+ * purposes, however, it is easier to simply take the devices
-+ * offline that correspond to commands that failed.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(1,
-+ printk("scsi_unjam_host: Take device offline\n"));
-+
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "command error recover failed");
-+
-+ if (host->host_failed != 0)
- panic("scsi_unjam_host: Miscount of number of failed commands.\n");
-- }
-+
- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Returning\n"));
-+}
-
-- ourrtn = FALSE;
-+static void (*unjam_method[])(struct Scsi_Host *, Scsi_Cmnd **) = {
-+ scsi_unjam_request_sense,
-+ scsi_unjam_count,
-+ scsi_unjam_abort,
-+ scsi_unjam_device_reset,
-+ scsi_unjam_bus_reset,
-+ scsi_unjam_host_reset,
-+ scsi_unjam_failure,
-+};
-
-- leave:
-+/*
-+ * Function: scsi_unjam_host
-+ *
-+ * Purpose: Attempt to fix a host which has a command that failed for
-+ * some reason.
-+ *
-+ * Arguments: host - host that needs unjamming.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: When we come in here, we *know* that all commands on the
-+ * bus have either completed, failed or timed out. We also
-+ * know that no further commands are being sent to the host,
-+ * so things are relatively quiet and we have freedom to
-+ * fiddle with things as we wish.
-+ *
-+ * Additional note: This is only the *default* implementation. It is possible
-+ * for individual drivers to supply their own version of this
-+ * function, and if the maintainer wishes to do this, it is
-+ * strongly suggested that this function be taken as a template
-+ * and modified. This function was designed to correctly handle
-+ * problems for about 95% of the different cases out there, and
-+ * it should always provide at least a reasonable amount of error
-+ * recovery.
-+ *
-+ * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
-+ * have scsi_finish_command() called for it. We do all of
-+ * the retry stuff here, so when we restart the host after we
-+ * return it should have an empty queue.
-+ */
-+STATIC int scsi_unjam_host(struct Scsi_Host *host)
-+{
-+ Scsi_Cmnd *SCdone = NULL;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Device *SDpnt;
-+ int ourrtn = FALSE;
-+ int i;
-+
-+ ASSERT_LOCK(&io_request_lock, 0);
-+
-+ /*
-+ * First, protect against any sort of race condition. If any of the outstanding
-+ * commands are in states that indicate that we are not yet blocked (i.e. we are
-+ * not in a quiet state) then we got woken up in error. If we ever end up here,
-+ * we need to re-examine some of the assumptions.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-+ if (SCpnt->state == SCSI_STATE_FAILED
-+ || SCpnt->state == SCSI_STATE_TIMEOUT
-+ || SCpnt->state == SCSI_STATE_INITIALIZING
-+ || SCpnt->state == SCSI_STATE_UNUSED) {
-+ continue;
-+ }
-+ /*
-+ * Rats. Something is still floating around out there. This could
-+ * be the result of the fact that the upper level drivers are still frobbing
-+ * commands that might have succeeded. There are two outcomes. One is that
-+ * the command block will eventually be freed, and the other one is that
-+ * the command will be queued and will be finished along the way.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
-+
-+/*
-+ * panic("SCSI Error handler woken too early\n");
-+ *
-+ * This is no longer a problem, since now the code cares only about
-+ * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
-+ * Other states are useful only to release active commands when devices are
-+ * set offline. If (host->host_active == host->host_busy) we can safely assume
-+ * that there are no commands in state other then TIMEOUT od FAILED. (DB)
-+ *
-+ * FIXME:
-+ * It is not easy to release correctly commands according to their state when
-+ * devices are set offline, when the state is neither TIMEOUT nor FAILED.
-+ * When a device is set offline, we can have some command with
-+ * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
-+ * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
-+ * (DB, 17 May 1998)
-+ */
-+ }
-+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(unjam_method); i++) {
-+ unjam_method[i](host, &SCdone);
-+
-+ /*
-+ * If we solved all of the problems, then
-+ * let's rev up the engines again.
-+ */
-+ if (host->host_failed == 0) {
-+ ourrtn = TRUE;
-+ break;
-+ }
-+ }
-
- /*
- * We should have a list of commands that we 'finished' during the course of
-@@ -2025,3 +2312,17 @@
- * tab-width: 8
- * End:
- */
-+
-+EXPORT_SYMBOL(scsi_eh_times_out);
-+EXPORT_SYMBOL(scsi_eh_retry_command);
-+EXPORT_SYMBOL(scsi_request_sense);
-+EXPORT_SYMBOL(scsi_test_unit_ready);
-+EXPORT_SYMBOL(scsi_unit_is_ready);
-+EXPORT_SYMBOL(scsi_eh_finish_command);
-+EXPORT_SYMBOL(scsi_try_to_abort_command);
-+EXPORT_SYMBOL(scsi_try_bus_device_reset);
-+EXPORT_SYMBOL(scsi_try_bus_reset);
-+EXPORT_SYMBOL(scsi_try_host_reset);
-+EXPORT_SYMBOL(scsi_sense_valid);
-+EXPORT_SYMBOL(scsi_done);
-+EXPORT_SYMBOL(scsi_decide_disposition);
---- linux-2.4.25/drivers/scsi/scsi_ioctl.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/scsi_ioctl.c 2004-03-31 17:15:09.000000000 +0200
-@@ -153,6 +153,29 @@
- return result;
- }
-
-+int scsi_set_medium_removal(Scsi_Device *dev, char state)
-+{
-+ char scsi_cmd[MAX_COMMAND_SIZE];
-+ int ret;
-+
-+ if (!dev->removable || !dev->lockable)
-+ return 0;
-+
-+ scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-+ scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
-+ scsi_cmd[2] = 0;
-+ scsi_cmd[3] = 0;
-+ scsi_cmd[4] = state;
-+ scsi_cmd[5] = 0;
-+
-+ ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-+
-+ if (ret == 0)
-+ dev->locked = state == SCSI_REMOVAL_PREVENT;
-+
-+ return ret;
-+}
-+
- /*
- * This interface is depreciated - users should use the scsi generic (sg)
- * interface instead, as this is a more flexible approach to performing
-@@ -450,24 +473,9 @@
- return scsi_ioctl_send_command((Scsi_Device *) dev,
- (Scsi_Ioctl_Command *) arg);
- case SCSI_IOCTL_DOORLOCK:
-- if (!dev->removable || !dev->lockable)
-- return 0;
-- scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-- scsi_cmd[1] = cmd_byte1;
-- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-- scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
-- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-- IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-- break;
-+ return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT);
- case SCSI_IOCTL_DOORUNLOCK:
-- if (!dev->removable || !dev->lockable)
-- return 0;
-- scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-- scsi_cmd[1] = cmd_byte1;
-- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-- scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
-- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-- IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-+ return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
- case SCSI_IOCTL_TEST_UNIT_READY:
- scsi_cmd[0] = TEST_UNIT_READY;
- scsi_cmd[1] = cmd_byte1;
---- linux-2.4.25/drivers/scsi/scsi_lib.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/scsi_lib.c 2004-03-31 17:15:09.000000000 +0200
-@@ -208,6 +208,30 @@
- }
-
- /*
-+ * Function: scsi_setup_cmd_retry()
-+ *
-+ * Purpose: Restore the command state for a retry
-+ *
-+ * Arguments: SCpnt - command to be restored
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: Immediately prior to retrying a command, we need
-+ * to restore certain fields that we saved above.
-+ */
-+void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt)
-+{
-+ memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-+ sizeof(SCpnt->data_cmnd));
-+ SCpnt->request_buffer = SCpnt->buffer;
-+ SCpnt->request_bufflen = SCpnt->bufflen;
-+ SCpnt->use_sg = SCpnt->old_use_sg;
-+ SCpnt->cmd_len = SCpnt->old_cmd_len;
-+ SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-+ SCpnt->underflow = SCpnt->old_underflow;
-+}
-+
-+/*
- * Function: scsi_queue_next_request()
- *
- * Purpose: Handle post-processing of completed commands.
-@@ -723,7 +747,7 @@
- printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
- SCpnt->host->host_no, (int) SCpnt->channel,
- (int) SCpnt->target, (int) SCpnt->lun);
-- print_command(SCpnt->cmnd);
-+ print_command(SCpnt->data_cmnd);
- print_sense("sd", SCpnt);
- SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
- return;
-@@ -898,8 +922,17 @@
- * space. Technically the error handling thread should be
- * doing this crap, but the error handler isn't used by
- * most hosts.
-+ *
-+ * (rmk)
-+ * Trying to lock the door can cause deadlocks. We therefore
-+ * only use this for old hosts; our door locking is now done
-+ * by the error handler in scsi_restart_operations for new
-+ * eh hosts.
-+ *
-+ * Note that we don't clear was_reset here; this is used by
-+ * st.c, and either one or other has to die.
- */
-- if (SDpnt->was_reset) {
-+ if (SHpnt->hostt->use_new_eh_code == 0 && SDpnt->was_reset) {
- /*
- * We need to relock the door, but we might
- * be in an interrupt handler. Only do this
-@@ -910,7 +943,7 @@
- * this work.
- */
- SDpnt->was_reset = 0;
-- if (SDpnt->removable && !in_interrupt()) {
-+ if (SDpnt->removable && SDpnt->locked && !in_interrupt()) {
- spin_unlock_irq(&io_request_lock);
- scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
- spin_lock_irq(&io_request_lock);
---- linux-2.4.25/drivers/scsi/scsi_syms.c~2.4.25-vrs2.patch 2002-08-03 02:39:44.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/scsi_syms.c 2004-03-31 17:15:09.000000000 +0200
-@@ -103,3 +103,6 @@
- extern int scsi_delete_timer(Scsi_Cmnd *);
- EXPORT_SYMBOL(scsi_add_timer);
- EXPORT_SYMBOL(scsi_delete_timer);
-+
-+extern int scsi_set_medium_removal(Scsi_Device *dev, char state);
-+EXPORT_SYMBOL(scsi_set_medium_removal);
---- linux-2.4.25/drivers/scsi/sd.c~2.4.25-vrs2.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/scsi/sd.c 2004-03-31 17:15:09.000000000 +0200
-@@ -399,6 +399,7 @@
- this_count = 0xffff;
-
- SCpnt->cmnd[0] += READ_10 - READ_6;
-+ SCpnt->cmnd[1] |= 1 << 3; /* Set FUA --rmk */
- SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
- SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
- SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
-@@ -524,7 +525,7 @@
- if (SDev->removable)
- if (SDev->access_count==1)
- if (scsi_block_when_processing_errors(SDev))
-- scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
-+ scsi_set_medium_removal(SDev, SCSI_REMOVAL_PREVENT);
-
-
- return 0;
-@@ -553,7 +554,7 @@
- if (SDev->removable) {
- if (!SDev->access_count)
- if (scsi_block_when_processing_errors(SDev))
-- scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);
-+ scsi_set_medium_removal(SDev, SCSI_REMOVAL_ALLOW);
- }
- if (SDev->host->hostt->module)
- __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
---- linux-2.4.25/drivers/scsi/sr_ioctl.c~2.4.25-vrs2.patch 2002-11-29 00:53:14.000000000 +0100
-+++ linux-2.4.25/drivers/scsi/sr_ioctl.c 2004-03-31 17:15:09.000000000 +0200
-@@ -214,9 +214,8 @@
-
- int sr_lock_door(struct cdrom_device_info *cdi, int lock)
- {
-- return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
-- lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
-- 0);
-+ return scsi_set_medium_removal(scsi_CDs[MINOR(cdi->dev)].device,
-+ lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
- }
-
- int sr_drive_status(struct cdrom_device_info *cdi, int slot)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/21285.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,600 @@
-+/*
-+ * linux/drivers/char/serial_21285.c
-+ *
-+ * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
-+ *
-+ * Based on drivers/char/serial.c
-+ *
-+ * $Id: 21285.c,v 1.4.2.1 2002/10/24 09:53:23 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/serial.h>
-+#include <linux/major.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware/dec21285.h>
-+#include <asm/hardware.h>
-+
-+#define BAUD_BASE (mem_fclk_21285/64)
-+
-+#define SERIAL_21285_NAME "ttyFB"
-+#define SERIAL_21285_MAJOR 204
-+#define SERIAL_21285_MINOR 4
-+
-+#define SERIAL_21285_AUXNAME "cuafb"
-+#define SERIAL_21285_AUXMAJOR 205
-+#define SERIAL_21285_AUXMINOR 4
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+#include <asm/mach-types.h>
-+/*
-+ * Compatability with a mistake made a long time ago.
-+ * Note - the use of "ttyI", "/dev/ttyS0" and major/minor 5,64
-+ * is HIGHLY DEPRECIATED, and will be removed in the 2.5
-+ * kernel series.
-+ * -- rmk 15/04/2000
-+ */
-+#define SERIAL_21285_OLD_NAME "ttyI"
-+#define SERIAL_21285_OLD_MAJOR TTY_MAJOR
-+#define SERIAL_21285_OLD_MINOR 64
-+
-+static struct tty_driver rs285_old_driver;
-+#endif
-+
-+static struct tty_driver rs285_driver, callout_driver;
-+static int rs285_refcount;
-+static struct tty_struct *rs285_table[1];
-+
-+static struct termios *rs285_termios[1];
-+static struct termios *rs285_termios_locked[1];
-+
-+static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
-+static struct tty_struct *rs285_tty;
-+static DECLARE_MUTEX(rs285_sem);
-+static int rs285_use_count;
-+static unsigned long rs285_irq_enabled;
-+
-+#define TX_IRQ_BIT (0)
-+#define RX_IRQ_BIT (1)
-+
-+static void rs285_stop_tx(void)
-+{
-+ if (test_and_clear_bit(TX_IRQ_BIT, &rs285_irq_enabled))
-+ disable_irq(IRQ_CONTX);
-+}
-+
-+static void rs285_start_tx(void)
-+{
-+ if (!test_and_set_bit(TX_IRQ_BIT, &rs285_irq_enabled))
-+ enable_irq(IRQ_CONTX);
-+}
-+
-+static void rs285_stop_rx(void)
-+{
-+ if (test_and_clear_bit(RX_IRQ_BIT, &rs285_irq_enabled))
-+ disable_irq(IRQ_CONRX);
-+}
-+
-+static void rs285_start_rx(void)
-+{
-+ if (!test_and_set_bit(RX_IRQ_BIT, &rs285_irq_enabled))
-+ enable_irq(IRQ_CONRX);
-+}
-+
-+static int rs285_write_room(struct tty_struct *tty)
-+{
-+ return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
-+}
-+
-+static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ if (!rs285_tty) {
-+ rs285_stop_rx();
-+ return;
-+ }
-+ while (!(*CSR_UARTFLG & 0x10)) {
-+ int ch, flag;
-+ ch = *CSR_UARTDR;
-+ flag = *CSR_RXSTAT;
-+ if (flag & 4)
-+ tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
-+ if (flag & 2)
-+ flag = TTY_PARITY;
-+ else if (flag & 1)
-+ flag = TTY_FRAME;
-+ tty_insert_flip_char(rs285_tty, ch, flag);
-+ }
-+ tty_flip_buffer_push(rs285_tty);
-+}
-+
-+static void rs285_send_xchar(struct tty_struct *tty, char ch)
-+{
-+ x_char = ch;
-+ rs285_start_tx();
-+}
-+
-+static void rs285_throttle(struct tty_struct *tty)
-+{
-+ if (I_IXOFF(tty))
-+ rs285_send_xchar(tty, STOP_CHAR(tty));
-+}
-+
-+static void rs285_unthrottle(struct tty_struct *tty)
-+{
-+ if (I_IXOFF(tty)) {
-+ if (x_char)
-+ x_char = 0;
-+ else
-+ rs285_send_xchar(tty, START_CHAR(tty));
-+ }
-+}
-+
-+static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ while (!(*CSR_UARTFLG & 0x20)) {
-+ if (x_char) {
-+ *CSR_UARTDR = x_char;
-+ x_char = 0;
-+ continue;
-+ }
-+ if (putp == getp) {
-+ rs285_stop_tx();
-+ break;
-+ }
-+ *CSR_UARTDR = *getp;
-+ if (++getp >= wbuf + sizeof(wbuf))
-+ getp = wbuf;
-+ }
-+ if (rs285_tty)
-+ wake_up_interruptible(&rs285_tty->write_wait);
-+}
-+
-+static inline int rs285_xmit(int ch)
-+{
-+ if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
-+ return 0;
-+ *putp = ch;
-+ if (++putp >= wbuf + sizeof(wbuf))
-+ putp = wbuf;
-+ rs285_start_tx();
-+ return 1;
-+}
-+
-+static int rs285_write(struct tty_struct *tty, int from_user,
-+ const u_char * buf, int count)
-+{
-+ int i;
-+
-+ if (from_user && verify_area(VERIFY_READ, buf, count))
-+ return -EINVAL;
-+
-+ for (i = 0; i < count; i++) {
-+ char ch;
-+ if (from_user)
-+ __get_user(ch, buf + i);
-+ else
-+ ch = buf[i];
-+ if (!rs285_xmit(ch))
-+ break;
-+ }
-+ return i;
-+}
-+
-+static void rs285_put_char(struct tty_struct *tty, u_char ch)
-+{
-+ rs285_xmit(ch);
-+}
-+
-+static int rs285_chars_in_buffer(struct tty_struct *tty)
-+{
-+ return sizeof(wbuf) - rs285_write_room(tty);
-+}
-+
-+static void rs285_flush_buffer(struct tty_struct *tty)
-+{
-+ rs285_stop_tx();
-+ putp = getp = wbuf;
-+ if (x_char)
-+ rs285_start_tx();
-+}
-+
-+static inline void rs285_set_cflag(int cflag)
-+{
-+ int h_lcr, baud, quot;
-+
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ h_lcr = 0x10;
-+ break;
-+ case CS6:
-+ h_lcr = 0x30;
-+ break;
-+ case CS7:
-+ h_lcr = 0x50;
-+ break;
-+ default: /* CS8 */
-+ h_lcr = 0x70;
-+ break;
-+
-+ }
-+ if (cflag & CSTOPB)
-+ h_lcr |= 0x08;
-+ if (cflag & PARENB)
-+ h_lcr |= 0x02;
-+ if (!(cflag & PARODD))
-+ h_lcr |= 0x04;
-+
-+ switch (cflag & CBAUD) {
-+ case B200: baud = 200; break;
-+ case B300: baud = 300; break;
-+ case B1200: baud = 1200; break;
-+ case B1800: baud = 1800; break;
-+ case B2400: baud = 2400; break;
-+ case B4800: baud = 4800; break;
-+ default:
-+ case B9600: baud = 9600; break;
-+ case B19200: baud = 19200; break;
-+ case B38400: baud = 38400; break;
-+ case B57600: baud = 57600; break;
-+ case B115200: baud = 115200; break;
-+ }
-+
-+ /*
-+ * The documented expression for selecting the divisor is:
-+ * BAUD_BASE / baud - 1
-+ * However, typically BAUD_BASE is not divisible by baud, so
-+ * we want to select the divisor that gives us the minimum
-+ * error. Therefore, we want:
-+ * int(BAUD_BASE / baud - 0.5) ->
-+ * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
-+ * int((BAUD_BASE - (baud >> 1)) / baud)
-+ */
-+ quot = (BAUD_BASE - (baud >> 1)) / baud;
-+
-+ *CSR_UARTCON = 0;
-+ *CSR_L_UBRLCR = quot & 0xff;
-+ *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
-+ *CSR_H_UBRLCR = h_lcr;
-+ *CSR_UARTCON = 1;
-+}
-+
-+static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
-+{
-+ if (old && tty->termios->c_cflag == old->c_cflag)
-+ return;
-+ rs285_set_cflag(tty->termios->c_cflag);
-+}
-+
-+
-+static void rs285_stop(struct tty_struct *tty)
-+{
-+ rs285_stop_tx();
-+}
-+
-+static void rs285_start(struct tty_struct *tty)
-+{
-+ rs285_start_tx();
-+}
-+
-+static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
-+{
-+ int orig_jiffies = jiffies;
-+ while (*CSR_UARTFLG & 8) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ if (signal_pending(current))
-+ break;
-+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING);
-+}
-+
-+static int rs285_open(struct tty_struct *tty, struct file *filp)
-+{
-+ int line, ret;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ line = MINOR(tty->device) - tty->driver.minor_start;
-+ if (line)
-+ return -ENODEV;
-+
-+ ret = down_interruptible(&rs285_sem);
-+ if (ret)
-+ return ret;
-+
-+ tty->driver_data = NULL;
-+ rs285_tty = tty;
-+
-+ if (rs285_use_count == 0) {
-+ rs285_irq_enabled = 3;
-+ ret = request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL);
-+ if (ret == 0) {
-+ ret = request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285",
-+ NULL);
-+ if (ret)
-+ free_irq(IRQ_CONRX, NULL);
-+ }
-+ }
-+
-+ if (ret == 0)
-+ rs285_use_count++;
-+
-+ up(&rs285_sem);
-+
-+ return ret;
-+}
-+
-+static void rs285_close(struct tty_struct *tty, struct file *filp)
-+{
-+ down(&rs285_sem);
-+ if (!--rs285_use_count) {
-+ rs285_wait_until_sent(tty, 0);
-+ rs285_stop_rx();
-+ rs285_stop_tx();
-+ rs285_tty = NULL;
-+ free_irq(IRQ_CONTX, NULL);
-+ free_irq(IRQ_CONRX, NULL);
-+ }
-+ up(&rs285_sem);
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static int __init rs285_init(void)
-+{
-+ int baud = B9600;
-+
-+ if (machine_is_personal_server())
-+ baud = B57600;
-+
-+ rs285_driver.magic = TTY_DRIVER_MAGIC;
-+ rs285_driver.driver_name = "serial_21285";
-+ rs285_driver.name = SERIAL_21285_NAME;
-+ rs285_driver.major = SERIAL_21285_MAJOR;
-+ rs285_driver.minor_start = SERIAL_21285_MINOR;
-+ rs285_driver.num = 1;
-+ rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
-+ rs285_driver.subtype = SERIAL_TYPE_NORMAL;
-+ rs285_driver.init_termios = tty_std_termios;
-+ rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
-+ rs285_driver.flags = TTY_DRIVER_REAL_RAW;
-+ rs285_driver.refcount = &rs285_refcount;
-+ rs285_driver.table = rs285_table;
-+ rs285_driver.termios = rs285_termios;
-+ rs285_driver.termios_locked = rs285_termios_locked;
-+
-+ rs285_driver.open = rs285_open;
-+ rs285_driver.close = rs285_close;
-+ rs285_driver.write = rs285_write;
-+ rs285_driver.put_char = rs285_put_char;
-+ rs285_driver.write_room = rs285_write_room;
-+ rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
-+ rs285_driver.flush_buffer = rs285_flush_buffer;
-+ rs285_driver.throttle = rs285_throttle;
-+ rs285_driver.unthrottle = rs285_unthrottle;
-+ rs285_driver.send_xchar = rs285_send_xchar;
-+ rs285_driver.set_termios = rs285_set_termios;
-+ rs285_driver.stop = rs285_stop;
-+ rs285_driver.start = rs285_start;
-+ rs285_driver.wait_until_sent = rs285_wait_until_sent;
-+
-+ callout_driver = rs285_driver;
-+ callout_driver.name = SERIAL_21285_AUXNAME;
-+ callout_driver.major = SERIAL_21285_AUXMAJOR;
-+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder()) {
-+ rs285_old_driver = rs285_driver;
-+ rs285_old_driver.name = SERIAL_21285_OLD_NAME;
-+ rs285_old_driver.major = SERIAL_21285_OLD_MAJOR;
-+ rs285_old_driver.minor_start = SERIAL_21285_OLD_MINOR;
-+
-+ if (tty_register_driver(&rs285_old_driver))
-+ printk(KERN_ERR "Couldn't register old 21285 serial driver\n");
-+ }
-+#endif
-+
-+ if (tty_register_driver(&rs285_driver))
-+ printk(KERN_ERR "Couldn't register 21285 serial driver\n");
-+ if (tty_register_driver(&callout_driver))
-+ printk(KERN_ERR "Couldn't register 21285 callout driver\n");
-+
-+ return 0;
-+}
-+
-+static void __exit rs285_fini(void)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ save_flags(flags);
-+ cli();
-+ ret = tty_unregister_driver(&callout_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister 21285 callout driver "
-+ "(%d)\n", ret);
-+ ret = tty_unregister_driver(&rs285_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
-+ ret);
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder()) {
-+ ret = tty_unregister_driver(&rs285_old_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister old 21285 "
-+ "driver (%d)\n", ret);
-+ }
-+#endif
-+ free_irq(IRQ_CONTX, NULL);
-+ free_irq(IRQ_CONRX, NULL);
-+ restore_flags(flags);
-+}
-+
-+module_init(rs285_init);
-+module_exit(rs285_fini);
-+
-+#ifdef CONFIG_SERIAL_21285_CONSOLE
-+/************** console driver *****************/
-+
-+static void rs285_console_write(struct console *co, const char *s, u_int count)
-+{
-+ int i;
-+
-+ rs285_stop_tx();
-+ for (i = 0; i < count; i++) {
-+ while (*CSR_UARTFLG & 0x20);
-+ *CSR_UARTDR = s[i];
-+ if (s[i] == '\n') {
-+ while (*CSR_UARTFLG & 0x20);
-+ *CSR_UARTDR = '\r';
-+ }
-+ }
-+ rs285_start_tx();
-+}
-+
-+static kdev_t rs285_console_device(struct console *c)
-+{
-+ return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
-+}
-+
-+static int __init rs285_console_setup(struct console *co, char *options)
-+{
-+ int baud = 9600;
-+ int bits = 8;
-+ int parity = 'n';
-+ int cflag = CREAD | HUPCL | CLOCAL;
-+
-+ if (machine_is_personal_server())
-+ baud = 57600;
-+
-+ if (options) {
-+ char *s = options;
-+ baud = simple_strtoul(options, NULL, 10);
-+ while (*s >= '0' && *s <= '9')
-+ s++;
-+ if (*s)
-+ parity = *s++;
-+ if (*s)
-+ bits = *s - '0';
-+ }
-+
-+ /*
-+ * Now construct a cflag setting.
-+ */
-+ switch (baud) {
-+ case 1200:
-+ cflag |= B1200;
-+ break;
-+ case 2400:
-+ cflag |= B2400;
-+ break;
-+ case 4800:
-+ cflag |= B4800;
-+ break;
-+ case 9600:
-+ cflag |= B9600;
-+ break;
-+ case 19200:
-+ cflag |= B19200;
-+ break;
-+ case 38400:
-+ cflag |= B38400;
-+ break;
-+ case 57600:
-+ cflag |= B57600;
-+ break;
-+ case 115200:
-+ cflag |= B115200;
-+ break;
-+ default:
-+ cflag |= B9600;
-+ break;
-+ }
-+ switch (bits) {
-+ case 7:
-+ cflag |= CS7;
-+ break;
-+ default:
-+ cflag |= CS8;
-+ break;
-+ }
-+ switch (parity) {
-+ case 'o':
-+ case 'O':
-+ cflag |= PARODD;
-+ break;
-+ case 'e':
-+ case 'E':
-+ cflag |= PARENB;
-+ break;
-+ }
-+ co->cflag = cflag;
-+ rs285_set_cflag(cflag);
-+ rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
-+ if (options)
-+ rs285_console_write(NULL, options, strlen(options));
-+ else
-+ rs285_console_write(NULL, "no options", 10);
-+ rs285_console_write(NULL, "\n", 1);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+static struct console rs285_old_cons =
-+{
-+ SERIAL_21285_OLD_NAME,
-+ rs285_console_write,
-+ NULL,
-+ rs285_console_device,
-+ NULL,
-+ rs285_console_setup,
-+ CON_PRINTBUFFER,
-+ -1,
-+ 0,
-+ NULL
-+};
-+#endif
-+
-+static struct console rs285_cons =
-+{
-+ name: SERIAL_21285_NAME,
-+ write: rs285_console_write,
-+ device: rs285_console_device,
-+ setup: rs285_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+void __init rs285_console_init(void)
-+{
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder())
-+ register_console(&rs285_old_cons);
-+#endif
-+ register_console(&rs285_cons);
-+}
-+
-+#endif /* CONFIG_SERIAL_21285_CONSOLE */
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/8250.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,2170 @@
-+/*
-+ * linux/drivers/serial/8250.c
-+ *
-+ * Driver for 8250/16550-type serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * $Id: 8250.c,v 1.14.2.8 2002/10/24 14:31:31 rmk Exp $
-+ *
-+ * A note about mapbase / membase
-+ *
-+ * mapbase is the physical address of the IO port. Currently, we don't
-+ * support this very well, and it may well be dropped from this driver
-+ * in future. As such, mapbase should be NULL.
-+ *
-+ * membase is an 'ioremapped' cookie. This is compatible with the old
-+ * serial.c driver, and is currently the preferred form.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/serial_reg.h>
-+#include <linux/serialP.h>
-+#include <linux/delay.h>
-+#include <linux/serial_core.h>
-+#include <linux/kmod.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#include "8250.h"
-+
-+/*
-+ * Configuration:
-+ * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option
-+ * is unsafe when used on edge-triggered interrupts.
-+ */
-+unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
-+
-+/*
-+ * Debugging.
-+ */
-+#if 0
-+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-+#else
-+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-+#endif
-+
-+#if 0
-+#define DEBUG_INTR(fmt...) printk(fmt)
-+#else
-+#define DEBUG_INTR(fmt...) do { } while (0)
-+#endif
-+
-+#define PASS_LIMIT 256
-+
-+/*
-+ * We default to IRQ0 for the "no irq" hack. Some
-+ * machine types want others as well - they're free
-+ * to redefine this in their header file.
-+ */
-+#define is_real_interrupt(irq) ((irq) != 0)
-+
-+/*
-+ * This converts from our new CONFIG_ symbols to the symbols
-+ * that asm/serial.h expects. You _NEED_ to comment out the
-+ * linux/config.h include contained inside asm/serial.h for
-+ * this to work.
-+ */
-+#undef CONFIG_SERIAL_MANY_PORTS
-+#undef CONFIG_SERIAL_DETECT_IRQ
-+#undef CONFIG_SERIAL_MULTIPORT
-+#undef CONFIG_HUB6
-+
-+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-+#define CONFIG_SERIAL_DETECT_IRQ 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_MULTIPORT
-+#define CONFIG_SERIAL_MULTIPORT 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+#define CONFIG_HUB6 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-+#define CONFIG_SERIAL_MANY_PORTS 1
-+#endif
-+
-+#include <asm/serial.h>
-+
-+static struct old_serial_port old_serial_port[] = {
-+ SERIAL_PORT_DFNS /* defined in asm/serial.h */
-+};
-+
-+#define UART_NR ARRAY_SIZE(old_serial_port)
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *serial8250_table[UART_NR];
-+static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+
-+#define PORT_RSA_MAX 4
-+static int probe_rsa[PORT_RSA_MAX];
-+static int force_rsa[PORT_RSA_MAX];
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
-+struct uart_8250_port {
-+ struct uart_port port;
-+ struct timer_list timer; /* "no irq" timer */
-+ struct list_head list; /* ports on this IRQ */
-+ unsigned int capabilities; /* port capabilities */
-+ unsigned char acr;
-+ unsigned char ier;
-+ unsigned short rev;
-+ unsigned char lcr;
-+ unsigned char mcr;
-+ unsigned char mcr_mask; /* mask of user bits */
-+ unsigned char mcr_force; /* mask of forced bits */
-+ unsigned char efr;
-+ unsigned int lsr_break_flag;
-+
-+ /*
-+ * We provide a per-port pm hook.
-+ */
-+ void (*pm)(struct uart_port *port,
-+ unsigned int state, unsigned int old);
-+};
-+
-+struct irq_info {
-+ spinlock_t lock;
-+ struct list_head *head;
-+};
-+
-+static struct irq_info irq_lists[NR_IRQS];
-+
-+/*
-+ * Here we define the default xmit fifo size used for each type of UART.
-+ */
-+static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
-+ { "unknown", 1, 0 },
-+ { "8250", 1, 0 },
-+ { "16450", 1, 0 },
-+ { "16550", 1, 0 },
-+ { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "Cirrus", 1, 0 },
-+ { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
-+ { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "Startech", 1, 0 },
-+ { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
-+};
-+
-+static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
-+{
-+ offset <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+ case SERIAL_IO_HUB6:
-+ outb(up->port.hub6 - 1 + offset, up->port.iobase);
-+ return inb(up->port.iobase + 1);
-+#endif
-+
-+ case SERIAL_IO_MEM:
-+ return readb(up->port.membase + offset);
-+
-+ default:
-+ return inb(up->port.iobase + offset);
-+ }
-+}
-+
-+static _INLINE_ void
-+serial_out(struct uart_8250_port *up, int offset, int value)
-+{
-+ offset <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+ case SERIAL_IO_HUB6:
-+ outb(up->port.hub6 - 1 + offset, up->port.iobase);
-+ outb(value, up->port.iobase + 1);
-+ break;
-+#endif
-+
-+ case SERIAL_IO_MEM:
-+ writeb(value, up->port.membase + offset);
-+ break;
-+
-+ default:
-+ outb(value, up->port.iobase + offset);
-+ }
-+}
-+
-+/*
-+ * We used to support using pause I/O for certain machines. We
-+ * haven't supported this for a while, but just in case it's badly
-+ * needed for certain old 386 machines, I've left these #define's
-+ * in....
-+ */
-+#define serial_inp(up, offset) serial_in(up, offset)
-+#define serial_outp(up, offset, value) serial_out(up, offset, value)
-+
-+
-+/*
-+ * For the 16C950
-+ */
-+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-+{
-+ serial_out(up, UART_SCR, offset);
-+ serial_out(up, UART_ICR, value);
-+}
-+
-+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-+{
-+ unsigned int value;
-+
-+ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
-+ serial_out(up, UART_SCR, offset);
-+ value = serial_in(up, UART_ICR);
-+ serial_icr_write(up, UART_ACR, up->acr);
-+
-+ return value;
-+}
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+/*
-+ * Attempts to turn on the RSA FIFO. Returns zero on failure.
-+ * We set the port uart clock rate if we succeed.
-+ */
-+static int __enable_rsa(struct uart_8250_port *up)
-+{
-+ unsigned char mode;
-+ int result;
-+
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = mode & UART_RSA_MSR_FIFO;
-+
-+ if (!result) {
-+ serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = mode & UART_RSA_MSR_FIFO;
-+ }
-+
-+ if (result)
-+ up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-+
-+ return result;
-+}
-+
-+static void enable_rsa(struct uart_8250_port *up)
-+{
-+ if (up->port.type == PORT_RSA) {
-+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
-+ spin_lock_irq(&up->port.lock);
-+ __enable_rsa(up);
-+ spin_unlock_irq(&up->port.lock);
-+ }
-+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
-+ serial_outp(up, UART_RSA_FRR, 0);
-+ }
-+}
-+
-+/*
-+ * Attempts to turn off the RSA FIFO. Returns zero on failure.
-+ * It is unknown why interrupts were disabled in here. However,
-+ * the caller is expected to preserve this behaviour by grabbing
-+ * the spinlock before calling this function.
-+ */
-+static void disable_rsa(struct uart_8250_port *up)
-+{
-+ unsigned char mode;
-+ int result;
-+
-+ if (up->port.type == PORT_RSA &&
-+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
-+ spin_lock_irq(&up->port.lock);
-+
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = !(mode & UART_RSA_MSR_FIFO);
-+
-+ if (!result) {
-+ serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = !(mode & UART_RSA_MSR_FIFO);
-+ }
-+
-+ if (result)
-+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
-+ spin_unlock_irq(&up->port.lock);
-+ }
-+}
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
-+/*
-+ * This is a quickie test to see how big the FIFO is.
-+ * It doesn't work at all the time, more's the pity.
-+ */
-+static int size_fifo(struct uart_8250_port *up)
-+{
-+ unsigned char old_fcr, old_mcr, old_dll, old_dlm;
-+ int count;
-+
-+ old_fcr = serial_inp(up, UART_FCR);
-+ old_mcr = serial_inp(up, UART_MCR);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_MCR, UART_MCR_LOOP);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ old_dll = serial_inp(up, UART_DLL);
-+ old_dlm = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, 0x01);
-+ serial_outp(up, UART_DLM, 0x00);
-+ serial_outp(up, UART_LCR, 0x03);
-+ for (count = 0; count < 256; count++)
-+ serial_outp(up, UART_TX, count);
-+ mdelay(20);/* FIXME - schedule_timeout */
-+ for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
-+ (count < 256); count++)
-+ serial_inp(up, UART_RX);
-+ serial_outp(up, UART_FCR, old_fcr);
-+ serial_outp(up, UART_MCR, old_mcr);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ serial_outp(up, UART_DLL, old_dll);
-+ serial_outp(up, UART_DLM, old_dlm);
-+
-+ return count;
-+}
-+
-+/*
-+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
-+ * When this function is called we know it is at least a StarTech
-+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
-+ * its clones. (We treat the broken original StarTech 16650 V1 as a
-+ * 16550, and why not? Startech doesn't seem to even acknowledge its
-+ * existence.)
-+ *
-+ * What evil have men's minds wrought...
-+ */
-+static void autoconfig_has_efr(struct uart_8250_port *up)
-+{
-+ unsigned char id1, id2, id3, rev, saved_dll, saved_dlm;
-+
-+ /*
-+ * First we check to see if it's an Oxford Semiconductor UART.
-+ *
-+ * If we have to do this here because some non-National
-+ * Semiconductor clone chips lock up if you try writing to the
-+ * LSR register (which serial_icr_read does)
-+ */
-+
-+ /*
-+ * Check for Oxford Semiconductor 16C950.
-+ *
-+ * EFR [4] must be set else this test fails.
-+ *
-+ * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
-+ * claims that it's needed for 952 dual UART's (which are not
-+ * recommended for new designs).
-+ */
-+ up->acr = 0;
-+ serial_out(up, UART_LCR, 0xBF);
-+ serial_out(up, UART_EFR, 0x10);
-+ serial_out(up, UART_LCR, 0x00);
-+ id1 = serial_icr_read(up, UART_ID1);
-+ id2 = serial_icr_read(up, UART_ID2);
-+ id3 = serial_icr_read(up, UART_ID3);
-+ rev = serial_icr_read(up, UART_REV);
-+
-+ DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-+
-+ if (id1 == 0x16 && id2 == 0xC9 &&
-+ (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
-+ up->port.type = PORT_16C950;
-+ up->rev = rev | (id3 << 8);
-+ return;
-+ }
-+
-+ /*
-+ * We check for a XR16C850 by setting DLL and DLM to 0, and then
-+ * reading back DLL and DLM. The chip type depends on the DLM
-+ * value read back:
-+ * 0x10 - XR16C850 and the DLL contains the chip revision.
-+ * 0x12 - XR16C2850.
-+ * 0x14 - XR16C854.
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ saved_dll = serial_inp(up, UART_DLL);
-+ saved_dlm = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, 0);
-+ serial_outp(up, UART_DLM, 0);
-+ id2 = serial_inp(up, UART_DLL);
-+ id1 = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, saved_dll);
-+ serial_outp(up, UART_DLM, saved_dlm);
-+
-+ DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
-+
-+ if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
-+ if (id1 == 0x10)
-+ up->rev = id2;
-+ up->port.type = PORT_16850;
-+ return;
-+ }
-+
-+ /*
-+ * It wasn't an XR16C850.
-+ *
-+ * We distinguish between the '654 and the '650 by counting
-+ * how many bytes are in the FIFO. I'm using this for now,
-+ * since that's the technique that was sent to me in the
-+ * serial driver update, but I'm not convinced this works.
-+ * I've had problems doing this in the past. -TYT
-+ */
-+ if (size_fifo(up) == 64)
-+ up->port.type = PORT_16654;
-+ else
-+ up->port.type = PORT_16650V2;
-+}
-+
-+/*
-+ * We detected a chip without a FIFO. Only two fall into
-+ * this category - the original 8250 and the 16450. The
-+ * 16450 has a scratch register (accessible with LCR=0)
-+ */
-+static void autoconfig_8250(struct uart_8250_port *up)
-+{
-+ unsigned char scratch, status1, status2;
-+
-+ up->port.type = PORT_8250;
-+
-+ scratch = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, 0xa5);
-+ status1 = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, 0x5a);
-+ status2 = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, scratch);
-+
-+ if (status1 == 0xa5 && status2 == 0x5a)
-+ up->port.type = PORT_16450;
-+}
-+
-+/*
-+ * We know that the chip has FIFOs. Does it have an EFR? The
-+ * EFR is located in the same register position as the IIR and
-+ * we know the top two bits of the IIR are currently set. The
-+ * EFR should contain zero. Try to read the EFR.
-+ */
-+static void autoconfig_16550a(struct uart_8250_port *up)
-+{
-+ unsigned char status1, status2;
-+
-+ up->port.type = PORT_16550A;
-+
-+ /*
-+ * Check for presence of the EFR when DLAB is set.
-+ * Only ST16C650V1 UARTs pass this test.
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ if (serial_in(up, UART_EFR) == 0) {
-+ DEBUG_AUTOCONF("EFRv1 ");
-+ up->port.type = PORT_16650;
-+ return;
-+ }
-+
-+ /*
-+ * Maybe it requires 0xbf to be written to the LCR.
-+ * (other ST16C650V2 UARTs, TI16C752A, etc)
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ if (serial_in(up, UART_EFR) == 0) {
-+ DEBUG_AUTOCONF("EFRv2 ");
-+ autoconfig_has_efr(up);
-+ return;
-+ }
-+
-+ /*
-+ * Check for a National Semiconductor SuperIO chip.
-+ * Attempt to switch to bank 2, read the value of the LOOP bit
-+ * from EXCR1. Switch back to bank 0, change it in MCR. Then
-+ * switch back to bank 2, read it from EXCR1 again and check
-+ * it's changed. If so, set baud_base in EXCR2 to 921600.
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ status1 = serial_in(up, UART_MCR);
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status2 = serial_in(up, 0x02); /* EXCR1 */
-+
-+ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status2 = serial_in(up, 0x02); /* EXCR1 */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_MCR, status1);
-+
-+ if ((status2 ^ status1) & UART_MCR_LOOP) {
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status1 = serial_in(up, 0x04); /* EXCR1 */
-+ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-+ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
-+ serial_outp(up, 0x04, status1);
-+ serial_outp(up, UART_LCR, 0);
-+
-+ up->port.type = PORT_NS16550A;
-+ up->port.uartclk = 921600*16;
-+ return;
-+ }
-+ }
-+
-+ /*
-+ * No EFR. Try to detect a TI16750, which only sets bit 5 of
-+ * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
-+ * Try setting it with and without DLAB set. Cheap clones
-+ * set bit 5 without DLAB set.
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-+ status1 = serial_in(up, UART_IIR) >> 5;
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-+ status2 = serial_in(up, UART_IIR) >> 5;
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+
-+ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-+
-+ if (status1 == 6 && status2 == 7) {
-+ up->port.type = PORT_16750;
-+ return;
-+ }
-+}
-+
-+/*
-+ * This routine is called by rs_init() to initialize a specific serial
-+ * port. It determines what type of UART chip this serial port is
-+ * using: 8250, 16450, 16550, 16550A. The important question is
-+ * whether or not this UART is a 16550A or not, since this will
-+ * determine whether or not we can use its FIFO features or not.
-+ */
-+static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-+{
-+ unsigned char status1, scratch, scratch2, scratch3;
-+ unsigned char save_lcr, save_mcr;
-+ unsigned long flags;
-+
-+ if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
-+ return;
-+
-+ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
-+ up->port.line, up->port.iobase, up->port.membase);
-+
-+ /*
-+ * We really do need global IRQs disabled here - we're going to
-+ * be frobbing the chips IRQ enable register to see if it exists.
-+ */
-+ spin_lock_irqsave(&up->port.lock, flags);
-+
-+ if (!(up->port.flags & UPF_BUGGY_UART)) {
-+ /*
-+ * Do a simple existence test first; if we fail this,
-+ * there's no point trying anything else.
-+ *
-+ * 0x80 is used as a nonsense port to prevent against
-+ * false positives due to ISA bus float. The
-+ * assumption is that 0x80 is a non-existent port;
-+ * which should be safe since include/asm/io.h also
-+ * makes this assumption.
-+ *
-+ * Note: this is safe as long as MCR bit 4 is clear
-+ * and the device is in "PC" mode.
-+ */
-+ scratch = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, 0);
-+#ifdef __i386__
-+ outb(0xff, 0x080);
-+#endif
-+ scratch2 = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, 0x0F);
-+#ifdef __i386__
-+ outb(0, 0x080);
-+#endif
-+ scratch3 = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, scratch);
-+ if (scratch2 != 0 || scratch3 != 0x0F) {
-+ /*
-+ * We failed; there's nothing here
-+ */
-+ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-+ scratch2, scratch3);
-+ goto out;
-+ }
-+ }
-+
-+ save_mcr = serial_in(up, UART_MCR);
-+ save_lcr = serial_in(up, UART_LCR);
-+
-+ /*
-+ * Check to see if a UART is really there. Certain broken
-+ * internal modems based on the Rockwell chipset fail this
-+ * test, because they apparently don't implement the loopback
-+ * test mode. So this test is skipped on the COM 1 through
-+ * COM 4 ports. This *should* be safe, since no board
-+ * manufacturer would be stupid enough to design a board
-+ * that conflicts with COM 1-4 --- we hope!
-+ */
-+ if (!(up->port.flags & UPF_SKIP_TEST)) {
-+ serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
-+ status1 = serial_inp(up, UART_MSR) & 0xF0;
-+ serial_outp(up, UART_MCR, save_mcr);
-+ if (status1 != 0x90) {
-+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-+ status1);
-+ goto out;
-+ }
-+ }
-+
-+ /*
-+ * We're pretty sure there's a port here. Lets find out what
-+ * type of port it is. The IIR top two bits allows us to find
-+ * out if its 8250 or 16450, 16550, 16550A or later. This
-+ * determines what we test for next.
-+ *
-+ * We also initialise the EFR (if any) to zero for later. The
-+ * EFR occupies the same register location as the FCR and IIR.
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ serial_outp(up, UART_LCR, 0);
-+
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ scratch = serial_in(up, UART_IIR) >> 6;
-+
-+ DEBUG_AUTOCONF("iir=%d ", scratch);
-+
-+ switch (scratch) {
-+ case 0:
-+ autoconfig_8250(up);
-+ break;
-+ case 1:
-+ up->port.type = PORT_UNKNOWN;
-+ break;
-+ case 2:
-+ up->port.type = PORT_16550;
-+ break;
-+ case 3:
-+ autoconfig_16550a(up);
-+ break;
-+ }
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+ /*
-+ * Only probe for RSA ports if we got the region.
-+ */
-+ if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
-+ int i;
-+
-+ for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
-+ if (!probe_rsa[i] && !force_rsa[i])
-+ break;
-+ if (((probe_rsa[i] != up->port.iobase) ||
-+ check_region(up->port.iobase + UART_RSA_BASE, 16)) &&
-+ (force_rsa[i] != up->port.iobase))
-+ continue;
-+ if (__enable_rsa(up)) {
-+ up->port.type = PORT_RSA;
-+ break;
-+ }
-+ }
-+ }
-+#endif
-+ serial_outp(up, UART_LCR, save_lcr);
-+
-+ up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-+ up->capabilities = uart_config[up->port.type].flags;
-+
-+ if (up->port.type == PORT_UNKNOWN)
-+ goto out;
-+
-+ /*
-+ * Reset the UART.
-+ */
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ if (up->port.type == PORT_RSA)
-+ serial_outp(up, UART_RSA_FRR, 0);
-+#endif
-+ serial_outp(up, UART_MCR, save_mcr);
-+ serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR |
-+ UART_FCR_CLEAR_XMIT));
-+ serial_outp(up, UART_FCR, 0);
-+ (void)serial_in(up, UART_RX);
-+ serial_outp(up, UART_IER, 0);
-+
-+ out:
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ if (up->port.iobase && up->port.type == PORT_RSA) {
-+ release_region(up->port.iobase, 8);
-+ request_region(up->port.iobase + UART_RSA_BASE, 16,
-+ "serial_rsa");
-+ }
-+#endif
-+ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-+}
-+
-+static void autoconfig_irq(struct uart_8250_port *up)
-+{
-+ unsigned char save_mcr, save_ier;
-+ unsigned char save_ICP = 0;
-+ unsigned int ICP = 0;
-+ unsigned long irqs;
-+ int irq;
-+
-+ if (up->port.flags & UPF_FOURPORT) {
-+ ICP = (up->port.iobase & 0xfe0) | 0x1f;
-+ save_ICP = inb_p(ICP);
-+ outb_p(0x80, ICP);
-+ (void) inb_p(ICP);
-+ }
-+
-+ /* forget possible initially masked and pending IRQ */
-+ probe_irq_off(probe_irq_on());
-+ save_mcr = serial_inp(up, UART_MCR);
-+ save_ier = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-+
-+ irqs = probe_irq_on();
-+ serial_outp(up, UART_MCR, 0);
-+ udelay (10);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ serial_outp(up, UART_MCR,
-+ UART_MCR_DTR | UART_MCR_RTS);
-+ } else {
-+ serial_outp(up, UART_MCR,
-+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-+ }
-+ serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
-+ (void)serial_inp(up, UART_LSR);
-+ (void)serial_inp(up, UART_RX);
-+ (void)serial_inp(up, UART_IIR);
-+ (void)serial_inp(up, UART_MSR);
-+ serial_outp(up, UART_TX, 0xFF);
-+ udelay (20);
-+ irq = probe_irq_off(irqs);
-+
-+ serial_outp(up, UART_MCR, save_mcr);
-+ serial_outp(up, UART_IER, save_ier);
-+
-+ if (up->port.flags & UPF_FOURPORT)
-+ outb_p(save_ICP, ICP);
-+
-+ up->port.irq = (irq > 0) ? irq : 0;
-+}
-+
-+static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ if (up->ier & UART_IER_THRI) {
-+ up->ier &= ~UART_IER_THRI;
-+ serial_out(up, UART_IER, up->ier);
-+ }
-+ if (up->port.type == PORT_16C950 && tty_stop) {
-+ up->acr |= UART_ACR_TXDIS;
-+ serial_icr_write(up, UART_ACR, up->acr);
-+ }
-+}
-+
-+static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ if (!(up->ier & UART_IER_THRI)) {
-+ up->ier |= UART_IER_THRI;
-+ serial_out(up, UART_IER, up->ier);
-+ }
-+ /*
-+ * We only do this from uart_start
-+ */
-+ if (tty_start && up->port.type == PORT_16C950) {
-+ up->acr &= ~UART_ACR_TXDIS;
-+ serial_icr_write(up, UART_ACR, up->acr);
-+ }
-+}
-+
-+static void serial8250_stop_rx(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ up->ier &= ~UART_IER_RLSI;
-+ up->port.read_status_mask &= ~UART_LSR_DR;
-+ serial_out(up, UART_IER, up->ier);
-+}
-+
-+static void serial8250_enable_ms(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ up->ier |= UART_IER_MSI;
-+ serial_out(up, UART_IER, up->ier);
-+}
-+
-+static _INLINE_ void
-+receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
-+{
-+ struct tty_struct *tty = up->port.info->tty;
-+ unsigned char ch;
-+ int max_count = 256;
-+
-+ do {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ /*
-+ * FIXME: Deadlock can happen here if we're a
-+ * low-latency port. We're holding the per-port
-+ * spinlock, and we call flush_to_ldisc->
-+ * n_tty_receive_buf->n_tty_receive_char->
-+ * opost->uart_put_char.
-+ */
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ return; // if TTY_DONT_FLIP is set
-+ }
-+ ch = serial_inp(up, UART_RX);
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ up->port.icount.rx++;
-+
-+ if (*status & (UART_LSR_BI | UART_LSR_PE |
-+ UART_LSR_FE | UART_LSR_OE)) {
-+ /*
-+ * For statistics only
-+ */
-+ if (*status & UART_LSR_BI) {
-+ *status &= ~(UART_LSR_FE | UART_LSR_PE);
-+ up->port.icount.brk++;
-+ /*
-+ * We do the SysRQ and SAK checking
-+ * here because otherwise the break
-+ * may get masked by ignore_status_mask
-+ * or read_status_mask.
-+ */
-+ if (uart_handle_break(&up->port))
-+ goto ignore_char;
-+ } else if (*status & UART_LSR_PE)
-+ up->port.icount.parity++;
-+ else if (*status & UART_LSR_FE)
-+ up->port.icount.frame++;
-+ if (*status & UART_LSR_OE)
-+ up->port.icount.overrun++;
-+
-+ /*
-+ * Mask off conditions which should be ingored.
-+ */
-+ *status &= up->port.read_status_mask;
-+
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+ if (up->port.line == up->port.cons->index) {
-+ /* Recover the break flag from console xmit */
-+ *status |= up->lsr_break_flag;
-+ up->lsr_break_flag = 0;
-+ }
-+#endif
-+ if (*status & UART_LSR_BI) {
-+ DEBUG_INTR("handling break....");
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ } else if (*status & UART_LSR_PE)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (*status & UART_LSR_FE)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+ if (uart_handle_sysrq_char(&up->port, ch, regs))
-+ goto ignore_char;
-+ if ((*status & up->port.ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((*status & UART_LSR_OE) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character.
-+ */
-+ *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ *status = serial_inp(up, UART_LSR);
-+ } while ((*status & UART_LSR_DR) && (max_count-- > 0));
-+ tty_flip_buffer_push(tty);
-+}
-+
-+static _INLINE_ void transmit_chars(struct uart_8250_port *up)
-+{
-+ struct circ_buf *xmit = &up->port.info->xmit;
-+ int count;
-+
-+ if (up->port.x_char) {
-+ serial_outp(up, UART_TX, up->port.x_char);
-+ up->port.icount.tx++;
-+ up->port.x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-+ serial8250_stop_tx(&up->port, 0);
-+ return;
-+ }
-+
-+ count = up->port.fifosize;
-+ do {
-+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ up->port.icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&up->port);
-+
-+ DEBUG_INTR("THRE...");
-+
-+ if (uart_circ_empty(xmit))
-+ serial8250_stop_tx(&up->port, 0);
-+}
-+
-+static _INLINE_ void check_modem_status(struct uart_8250_port *up)
-+{
-+ int status;
-+
-+ status = serial_in(up, UART_MSR);
-+
-+ if ((status & UART_MSR_ANY_DELTA) == 0)
-+ return;
-+
-+ if (status & UART_MSR_TERI)
-+ up->port.icount.rng++;
-+ if (status & UART_MSR_DDSR)
-+ up->port.icount.dsr++;
-+ if (status & UART_MSR_DDCD)
-+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-+ if (status & UART_MSR_DCTS)
-+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-+
-+ wake_up_interruptible(&up->port.info->delta_msr_wait);
-+}
-+
-+/*
-+ * This handles the interrupt from one port.
-+ */
-+static inline void
-+serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
-+{
-+ unsigned int status = serial_inp(up, UART_LSR);
-+
-+ DEBUG_INTR("status = %x...", status);
-+
-+ if (status & UART_LSR_DR)
-+ receive_chars(up, &status, regs);
-+ check_modem_status(up);
-+ if (status & UART_LSR_THRE)
-+ transmit_chars(up);
-+}
-+
-+/*
-+ * This is the serial driver's interrupt routine.
-+ *
-+ * Arjan thinks the old way was overly complex, so it got simplified.
-+ * Alan disagrees, saying that need the complexity to handle the weird
-+ * nature of ISA shared interrupts. (This is a special exception.)
-+ *
-+ * In order to handle ISA shared interrupts properly, we need to check
-+ * that all ports have been serviced, and therefore the ISA interrupt
-+ * line has been de-asserted.
-+ *
-+ * This means we need to loop through all ports. checking that they
-+ * don't have an interrupt pending.
-+ */
-+static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct irq_info *i = dev_id;
-+ struct list_head *l, *end = NULL;
-+ int pass_counter = 0;
-+
-+ DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-+
-+ spin_lock(&i->lock);
-+
-+ l = i->head;
-+ do {
-+ struct uart_8250_port *up;
-+ unsigned int iir;
-+
-+ up = list_entry(l, struct uart_8250_port, list);
-+
-+ iir = serial_in(up, UART_IIR);
-+ if (!(iir & UART_IIR_NO_INT)) {
-+ spin_lock(&up->port.lock);
-+ serial8250_handle_port(up, regs);
-+ spin_unlock(&up->port.lock);
-+
-+ end = NULL;
-+ } else if (end == NULL)
-+ end = l;
-+
-+ l = l->next;
-+
-+ if (l == i->head && pass_counter++ > PASS_LIMIT) {
-+ /* If we hit this, we're dead. */
-+ printk(KERN_ERR "serial8250: too much work for "
-+ "irq%d\n", irq);
-+ break;
-+ }
-+ } while (l != end);
-+
-+ spin_unlock(&i->lock);
-+
-+ DEBUG_INTR("end.\n");
-+}
-+
-+/*
-+ * To support ISA shared interrupts, we need to have one interrupt
-+ * handler that ensures that the IRQ line has been deasserted
-+ * before returning. Failing to do this will result in the IRQ
-+ * line being stuck active, and, since ISA irqs are edge triggered,
-+ * no more IRQs will be seen.
-+ */
-+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-+{
-+ spin_lock_irq(&i->lock);
-+
-+ if (!list_empty(i->head)) {
-+ if (i->head == &up->list)
-+ i->head = i->head->next;
-+ list_del(&up->list);
-+ } else {
-+ BUG_ON(i->head != &up->list);
-+ i->head = NULL;
-+ }
-+
-+ spin_unlock_irq(&i->lock);
-+}
-+
-+static int serial_link_irq_chain(struct uart_8250_port *up)
-+{
-+ struct irq_info *i = irq_lists + up->port.irq;
-+ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
-+
-+ spin_lock_irq(&i->lock);
-+
-+ if (i->head) {
-+ list_add(&up->list, i->head);
-+ spin_unlock_irq(&i->lock);
-+
-+ ret = 0;
-+ } else {
-+ INIT_LIST_HEAD(&up->list);
-+ i->head = &up->list;
-+ spin_unlock_irq(&i->lock);
-+
-+ ret = request_irq(up->port.irq, serial8250_interrupt,
-+ irq_flags, "serial", i);
-+ if (ret < 0)
-+ serial_do_unlink(i, up);
-+ }
-+
-+ return ret;
-+}
-+
-+static void serial_unlink_irq_chain(struct uart_8250_port *up)
-+{
-+ struct irq_info *i = irq_lists + up->port.irq;
-+
-+ BUG_ON(i->head == NULL);
-+
-+ if (list_empty(i->head))
-+ free_irq(up->port.irq, i);
-+
-+ serial_do_unlink(i, up);
-+}
-+
-+/*
-+ * This function is used to handle ports that do not have an
-+ * interrupt. This doesn't work very well for 16450's, but gives
-+ * barely passable results for a 16550A. (Although at the expense
-+ * of much CPU overhead).
-+ */
-+static void serial8250_timeout(unsigned long data)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)data;
-+ unsigned int timeout;
-+ unsigned int iir;
-+
-+ iir = serial_in(up, UART_IIR);
-+ if (!(iir & UART_IIR_NO_INT)) {
-+ spin_lock(&up->port.lock);
-+ serial8250_handle_port(up, NULL);
-+ spin_unlock(&up->port.lock);
-+ }
-+
-+ timeout = up->port.timeout;
-+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-+ mod_timer(&up->timer, jiffies + timeout);
-+}
-+
-+static unsigned int serial8250_tx_empty(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ return ret;
-+}
-+
-+static unsigned int serial8250_get_mctrl(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned char status;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ status = serial_in(up, UART_MSR);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ ret = 0;
-+ if (status & UART_MSR_DCD)
-+ ret |= TIOCM_CAR;
-+ if (status & UART_MSR_RI)
-+ ret |= TIOCM_RNG;
-+ if (status & UART_MSR_DSR)
-+ ret |= TIOCM_DSR;
-+ if (status & UART_MSR_CTS)
-+ ret |= TIOCM_CTS;
-+ return ret;
-+}
-+
-+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned char mcr = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ mcr |= UART_MCR_RTS;
-+ if (mctrl & TIOCM_DTR)
-+ mcr |= UART_MCR_DTR;
-+ if (mctrl & TIOCM_OUT1)
-+ mcr |= UART_MCR_OUT1;
-+ if (mctrl & TIOCM_OUT2)
-+ mcr |= UART_MCR_OUT2;
-+ if (mctrl & TIOCM_LOOP)
-+ mcr |= UART_MCR_LOOP;
-+
-+ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-+
-+ serial_out(up, UART_MCR, mcr);
-+}
-+
-+static void serial8250_break_ctl(struct uart_port *port, int break_state)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (break_state == -1)
-+ up->lcr |= UART_LCR_SBC;
-+ else
-+ up->lcr &= ~UART_LCR_SBC;
-+ serial_out(up, UART_LCR, up->lcr);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+static int serial8250_startup(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned char lsr, iir;
-+ int retval;
-+
-+ up->capabilities = uart_config[up->port.type].flags;
-+ up->mcr = 0;
-+ up->efr = 0;
-+ up->ier = 0;
-+
-+ if (up->port.type == PORT_16C950) {
-+ /* Wake up and initialize UART */
-+ up->acr = 0;
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_IER, 0);
-+ serial_outp(up, UART_LCR, 0);
-+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ /*
-+ * If this is an RSA port, see if we can kick it up to the
-+ * higher speed clock.
-+ */
-+ enable_rsa(up);
-+#endif
-+
-+ /*
-+ * Clear the FIFO buffers and disable them.
-+ * (they will be reeanbled in change_speed())
-+ */
-+ if (up->capabilities & UART_CLEAR_FIFO) {
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_FCR, 0);
-+ }
-+
-+ /*
-+ * Clear the interrupt registers.
-+ */
-+ (void) serial_inp(up, UART_LSR);
-+ (void) serial_inp(up, UART_RX);
-+ (void) serial_inp(up, UART_IIR);
-+ (void) serial_inp(up, UART_MSR);
-+
-+ /*
-+ * At this point, there's no way the LSR could still be 0xff;
-+ * if it is, then bail out, because there's likely no UART
-+ * here.
-+ */
-+ if (!(up->port.flags & UPF_BUGGY_UART) &&
-+ (serial_inp(up, UART_LSR) == 0xff)) {
-+ printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
-+ return -ENODEV;
-+ }
-+
-+ /*
-+ * If the "interrupt" for this port doesn't correspond with any
-+ * hardware interrupt, we use a timer-based system. The original
-+ * driver used to do this with IRQ0.
-+ */
-+ if (!is_real_interrupt(up->port.irq)) {
-+ unsigned int timeout = up->port.timeout;
-+
-+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-+
-+ up->timer.data = (unsigned long)up;
-+ mod_timer(&up->timer, jiffies + timeout);
-+ } else {
-+ retval = serial_link_irq_chain(up);
-+ if (retval)
-+ return retval;
-+ }
-+
-+ /*
-+ * Now, initialize the UART
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ if (!is_real_interrupt(up->port.irq))
-+ up->port.mctrl |= TIOCM_OUT1;
-+ } else
-+ /*
-+ * Most PC uarts need OUT2 raised to enable interrupts.
-+ */
-+ if (is_real_interrupt(up->port.irq))
-+ up->port.mctrl |= TIOCM_OUT2;
-+
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+
-+ /*
-+ * Do a quick test to see if we receive an
-+ * interrupt when we enable the TX irq.
-+ */
-+ serial_outp(up, UART_IER, UART_IER_THRI);
-+ lsr = serial_in(up, UART_LSR);
-+ iir = serial_in(up, UART_IIR);
-+ serial_outp(up, UART_IER, 0);
-+
-+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
-+ up->capabilities |= UART_BAD_TX_ENABLE;
-+ printk("ttyS%d - enabling bad tx status workarounds\n",
-+ port->line);
-+ }
-+
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ /*
-+ * Finally, enable interrupts. Note: Modem status interrupts
-+ * are set via change_speed(), which will be occuring imminently
-+ * anyway, so we don't enable them here.
-+ */
-+ up->ier = UART_IER_RLSI | UART_IER_RDI;
-+ serial_outp(up, UART_IER, up->ier);
-+
-+ if (up->port.flags & UPF_FOURPORT) {
-+ unsigned int icp;
-+ /*
-+ * Enable interrupts on the AST Fourport board
-+ */
-+ icp = (up->port.iobase & 0xfe0) | 0x01f;
-+ outb_p(0x80, icp);
-+ (void) inb_p(icp);
-+ }
-+
-+ /*
-+ * And clear the interrupt registers again for luck.
-+ */
-+ (void) serial_inp(up, UART_LSR);
-+ (void) serial_inp(up, UART_RX);
-+ (void) serial_inp(up, UART_IIR);
-+ (void) serial_inp(up, UART_MSR);
-+
-+ return 0;
-+}
-+
-+static void serial8250_shutdown(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+
-+ /*
-+ * Disable interrupts from this port
-+ */
-+ up->ier = 0;
-+ serial_outp(up, UART_IER, 0);
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ /* reset interrupts on the AST Fourport board */
-+ inb((up->port.iobase & 0xfe0) | 0x1f);
-+ up->port.mctrl |= TIOCM_OUT1;
-+ } else
-+ up->port.mctrl &= ~TIOCM_OUT2;
-+
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ /*
-+ * Disable break condition and FIFOs
-+ */
-+ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR |
-+ UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_FCR, 0);
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ /*
-+ * Reset the RSA board back to 115kbps compat mode.
-+ */
-+ disable_rsa(up);
-+#endif
-+
-+ /*
-+ * Read data port to reset things, and then unlink from
-+ * the IRQ chain.
-+ */
-+ (void) serial_in(up, UART_RX);
-+
-+ if (!is_real_interrupt(up->port.irq))
-+ del_timer_sync(&up->timer);
-+ else
-+ serial_unlink_irq_chain(up);
-+}
-+
-+static void serial8250_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned char cval, fcr = 0;
-+ unsigned long flags;
-+
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ cval = 0x00;
-+ break;
-+ case CS6:
-+ cval = 0x01;
-+ break;
-+ case CS7:
-+ cval = 0x02;
-+ break;
-+ default:
-+ case CS8:
-+ cval = 0x03;
-+ break;
-+ }
-+
-+ if (cflag & CSTOPB)
-+ cval |= 0x04;
-+ if (cflag & PARENB)
-+ cval |= UART_LCR_PARITY;
-+ if (!(cflag & PARODD))
-+ cval |= UART_LCR_EPAR;
-+#ifdef CMSPAR
-+ if (cflag & CMSPAR)
-+ cval |= UART_LCR_SPAR;
-+#endif
-+
-+ /*
-+ * Work around a bug in the Oxford Semiconductor 952 rev B
-+ * chip which causes it to seriously miscalculate baud rates
-+ * when DLL is 0.
-+ */
-+ if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
-+ up->rev == 0x5201)
-+ quot ++;
-+
-+ if (up->capabilities & UART_USE_FIFO) {
-+ if ((up->port.uartclk / quot) < (2400 * 16))
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ else if (up->port.type == PORT_RSA)
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
-+#endif
-+ else
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-+ }
-+ if (up->port.type == PORT_16750)
-+ fcr |= UART_FCR7_64BYTE;
-+
-+ /*
-+ * Ok, we're now changing the port state. Do it with
-+ * interrupts disabled.
-+ */
-+ spin_lock_irqsave(&up->port.lock, flags);
-+
-+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-+ if (iflag & IGNPAR)
-+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+ if (iflag & (BRKINT | PARMRK))
-+ up->port.read_status_mask |= UART_LSR_BI;
-+
-+ /*
-+ * Characteres to ignore
-+ */
-+ up->port.ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-+ if (iflag & IGNBRK) {
-+ up->port.ignore_status_mask |= UART_LSR_BI;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ up->port.ignore_status_mask |= UART_LSR_OE;
-+ }
-+
-+ /*
-+ * ignore all characters if CREAD is not set
-+ */
-+ if ((cflag & CREAD) == 0)
-+ up->port.ignore_status_mask |= UART_LSR_DR;
-+
-+ /*
-+ * CTS flow control flag and modem status interrupts
-+ */
-+ up->ier &= ~UART_IER_MSI;
-+ if (UART_ENABLE_MS(&up->port, cflag))
-+ up->ier |= UART_IER_MSI;
-+
-+ serial_out(up, UART_IER, up->ier);
-+
-+ if (up->capabilities & UART_MCRAFE) {
-+ /*
-+ * TI16C750 hardware flow control
-+ */
-+ up->mcr &= ~UART_MCR_AFE;
-+ if (cflag & CRTSCTS)
-+ up->mcr |= UART_MCR_AFE;
-+ }
-+ if (up->capabilities & UART_EFRAFE) {
-+ /*
-+ * TI16C752/Startech hardware flow control
-+ * FIXME:
-+ * - TI16C752 requires control thresholds
-+ * to be set for auto-RTS.
-+ * - We only enable auto-CTS here.
-+ * Note: ST16C654 does not allow MCR bit 1
-+ * to override RTS when UART_EFR_RTS is set.
-+ */
-+ up->efr &= ~UART_EFR_CTS;
-+ if (cflag & CRTSCTS)
-+ up->efr |= UART_EFR_CTS;
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, up->efr);
-+ }
-+
-+ if (up->capabilities & UART_NATSEMI) {
-+ /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
-+ serial_outp(up, UART_LCR, 0xe0);
-+ } else {
-+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-+ }
-+ serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
-+ serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
-+ if (up->port.type == PORT_16750)
-+ serial_outp(up, UART_FCR, fcr); /* set fcr */
-+ serial_outp(up, UART_LCR, cval); /* reset DLAB */
-+ up->lcr = cval; /* Save LCR */
-+ if (up->port.type != PORT_16750) {
-+ if (fcr & UART_FCR_ENABLE_FIFO) {
-+ /* emulated UARTs (Lucent Venus 167x) need two steps */
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ }
-+ serial_outp(up, UART_FCR, fcr); /* set fcr */
-+ }
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+static void
-+serial8250_pm(struct uart_port *port, unsigned int state,
-+ unsigned int oldstate)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ if (state) {
-+ /* sleep */
-+ if (up->capabilities & UART_STARTECH) {
-+ /* Arrange to enter sleep mode */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_IER, UART_IERX_SLEEP);
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+ if (up->port.type == PORT_16750) {
-+ /* Arrange to enter sleep mode */
-+ serial_outp(up, UART_IER, UART_IERX_SLEEP);
-+ }
-+ } else {
-+ /* wake */
-+ if (up->capabilities & UART_STARTECH) {
-+ /* Wake up UART */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ /*
-+ * Turn off LCR == 0xBF so we actually set the IER
-+ * register on the XR16C850
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_IER, 0);
-+ /*
-+ * Now reset LCR so we can turn off the ECB bit
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ /*
-+ * For a XR16C850, we need to set the trigger levels
-+ */
-+ if (up->port.type == PORT_16850) {
-+ unsigned char fctr;
-+
-+ fctr = serial_inp(up, UART_FCTR) &
-+ ~(UART_FCTR_RX | UART_FCTR_TX);
-+ serial_outp(up, UART_FCTR, fctr |
-+ UART_FCTR_TRGD |
-+ UART_FCTR_RX);
-+ serial_outp(up, UART_TRG, UART_TRG_96);
-+ serial_outp(up, UART_FCTR, fctr |
-+ UART_FCTR_TRGD |
-+ UART_FCTR_TX);
-+ serial_outp(up, UART_TRG, UART_TRG_96);
-+ }
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+
-+ if (up->port.type == PORT_16750) {
-+ /* Wake up UART */
-+ serial_outp(up, UART_IER, 0);
-+ }
-+ }
-+}
-+
-+/*
-+ * Resource handling. This is complicated by the fact that resources
-+ * depend on the port type. Maybe we should be claiming the standard
-+ * 8250 ports, and then trying to get other resources as necessary?
-+ */
-+static int
-+serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
-+{
-+ unsigned int size = 8 << up->port.regshift;
-+ int ret = 0;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ *res = request_mem_region(up->port.mapbase, size, "serial");
-+ if (!*res)
-+ ret = -EBUSY;
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ *res = request_region(up->port.iobase, size, "serial");
-+ if (!*res)
-+ ret = -EBUSY;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int
-+serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res)
-+{
-+ unsigned int size = 8 << up->port.regshift;
-+ unsigned long start;
-+ int ret = 0;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ start = up->port.mapbase;
-+ start += UART_RSA_BASE << up->port.regshift;
-+ *res = request_mem_region(start, size, "serial-rsa");
-+ if (!*res)
-+ ret = -EBUSY;
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ start = up->port.iobase;
-+ start += UART_RSA_BASE << up->port.regshift;
-+ *res = request_region(start, size, "serial-rsa");
-+ if (!*res)
-+ ret = -EBUSY;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static void serial8250_release_port(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long start, offset = 0, size = 0;
-+
-+ if (up->port.type == PORT_RSA) {
-+ offset = UART_RSA_BASE << up->port.regshift;
-+ size = 8;
-+ }
-+
-+ size <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ /*
-+ * Unmap the area.
-+ */
-+ if (up->port.flags & UPF_IOREMAP) {
-+ iounmap(up->port.membase);
-+ up->port.membase = NULL;
-+ }
-+
-+ start = up->port.mapbase;
-+
-+ if (size)
-+ release_mem_region(start + offset, size);
-+ release_mem_region(start, 8 << up->port.regshift);
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ start = up->port.iobase;
-+
-+ if (size)
-+ release_region(start + offset, size);
-+ release_region(start + offset, 8 << up->port.regshift);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+}
-+
-+static int serial8250_request_port(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ struct resource *res = NULL, *res_rsa = NULL;
-+ int ret = 0;
-+
-+ if (up->port.flags & UPF_RESOURCES) {
-+ if (up->port.type == PORT_RSA) {
-+ ret = serial8250_request_rsa_resource(up, &res_rsa);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ ret = serial8250_request_std_resource(up, &res);
-+ }
-+
-+ /*
-+ * If we have a mapbase, then request that as well.
-+ */
-+ if (ret == 0 && up->port.flags & UPF_IOREMAP) {
-+ int size = res->end - res->start + 1;
-+
-+ up->port.membase = ioremap(up->port.mapbase, size);
-+ if (!up->port.membase)
-+ ret = -ENOMEM;
-+ }
-+
-+ if (ret < 0) {
-+ if (res_rsa)
-+ release_resource(res_rsa);
-+ if (res)
-+ release_resource(res);
-+ }
-+ return ret;
-+}
-+
-+static void serial8250_config_port(struct uart_port *port, int flags)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ struct resource *res_std = NULL, *res_rsa = NULL;
-+ int probeflags = PROBE_ANY;
-+ int ret;
-+
-+#ifdef CONFIG_MCA
-+ /*
-+ * Don't probe for MCA ports on non-MCA machines.
-+ */
-+ if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
-+ return;
-+#endif
-+
-+ /*
-+ * Find the region that we can probe for. This in turn
-+ * tells us whether we can probe for the type of port.
-+ */
-+ if (up->port.flags & UPF_RESOURCES) {
-+ ret = serial8250_request_std_resource(up, &res_std);
-+ if (ret < 0)
-+ return;
-+
-+ ret = serial8250_request_rsa_resource(up, &res_rsa);
-+ if (ret < 0)
-+ probeflags &= ~PROBE_RSA;
-+ } else {
-+ probeflags &= ~PROBE_RSA;
-+ }
-+
-+ if (flags & UART_CONFIG_TYPE)
-+ autoconfig(up, probeflags);
-+ if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-+ autoconfig_irq(up);
-+
-+ /*
-+ * If the port wasn't an RSA port, release the resource.
-+ */
-+ if (up->port.type != PORT_RSA && res_rsa)
-+ release_resource(res_rsa);
-+
-+ if (up->port.type == PORT_UNKNOWN && res_std)
-+ release_resource(res_std);
-+}
-+
-+static int
-+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ if (ser->irq >= NR_IRQS || ser->irq < 0 ||
-+ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-+ ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
-+ ser->type == PORT_STARTECH)
-+ return -EINVAL;
-+ return 0;
-+}
-+
-+static const char *
-+serial8250_type(struct uart_port *port)
-+{
-+ int type = port->type;
-+
-+ if (type >= ARRAY_SIZE(uart_config))
-+ type = 0;
-+ return uart_config[type].name;
-+}
-+
-+static struct uart_ops serial8250_pops = {
-+ .tx_empty = serial8250_tx_empty,
-+ .set_mctrl = serial8250_set_mctrl,
-+ .get_mctrl = serial8250_get_mctrl,
-+ .stop_tx = serial8250_stop_tx,
-+ .start_tx = serial8250_start_tx,
-+ .stop_rx = serial8250_stop_rx,
-+ .enable_ms = serial8250_enable_ms,
-+ .break_ctl = serial8250_break_ctl,
-+ .startup = serial8250_startup,
-+ .shutdown = serial8250_shutdown,
-+ .change_speed = serial8250_change_speed,
-+ .pm = serial8250_pm,
-+ .type = serial8250_type,
-+ .release_port = serial8250_release_port,
-+ .request_port = serial8250_request_port,
-+ .config_port = serial8250_config_port,
-+ .verify_port = serial8250_verify_port,
-+};
-+
-+static struct uart_8250_port serial8250_ports[UART_NR];
-+
-+static void __init serial8250_isa_init_ports(void)
-+{
-+ struct uart_8250_port *up;
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
-+ i++, up++) {
-+ up->port.iobase = old_serial_port[i].port;
-+ up->port.irq = irq_cannonicalize(old_serial_port[i].irq);
-+ up->port.uartclk = old_serial_port[i].baud_base * 16;
-+ up->port.flags = old_serial_port[i].flags |
-+ UPF_RESOURCES;
-+ up->port.hub6 = old_serial_port[i].hub6;
-+ up->port.membase = old_serial_port[i].iomem_base;
-+ up->port.iotype = old_serial_port[i].io_type;
-+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
-+ up->port.ops = &serial8250_pops;
-+
-+ if (up->port.iotype == UPIO_MEM && up->port.mapbase)
-+ up->port.flags |= UPF_IOREMAP;
-+
-+ if (share_irqs)
-+ up->port.flags |= UPF_SHARE_IRQ;
-+ }
-+}
-+
-+static void __init serial8250_register_ports(struct uart_driver *drv)
-+{
-+ int i;
-+
-+ serial8250_isa_init_ports();
-+
-+ for (i = 0; i < UART_NR; i++) {
-+ struct uart_8250_port *up = &serial8250_ports[i];
-+
-+ up->port.line = i;
-+ up->port.ops = &serial8250_pops;
-+ init_timer(&up->timer);
-+ up->timer.function = serial8250_timeout;
-+
-+ /*
-+ * ALPHA_KLUDGE_MCR needs to be killed.
-+ */
-+ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
-+ up->mcr_force = ALPHA_KLUDGE_MCR;
-+
-+ uart_add_one_port(drv, &up->port);
-+ }
-+}
-+
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+
-+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-+
-+/*
-+ * Wait for transmitter & holding register to empty
-+ */
-+static inline void wait_for_xmitr(struct uart_8250_port *up)
-+{
-+ unsigned int status, tmout = 10000;
-+
-+ /* Wait up to 10ms for the character(s) to be sent. */
-+ do {
-+ status = serial_in(up, UART_LSR);
-+
-+ if (status & UART_LSR_BI)
-+ up->lsr_break_flag = UART_LSR_BI;
-+
-+ if (--tmout == 0)
-+ break;
-+ udelay(1);
-+ } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-+
-+ /* Wait up to 1s for flow control if necessary */
-+ if (up->port.flags & UPF_CONS_FLOW) {
-+ tmout = 1000000;
-+ while (--tmout &&
-+ ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-+ udelay(1);
-+ }
-+}
-+
-+/*
-+ * Print a string to the serial port trying not to disturb
-+ * any possible real use of the port...
-+ *
-+ * The console_lock must be held when we get here.
-+ */
-+static void
-+serial8250_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct uart_8250_port *up = &serial8250_ports[co->index];
-+ unsigned int ier;
-+ int i;
-+
-+ /*
-+ * First save the UER then disable the interrupts
-+ */
-+ ier = serial_in(up, UART_IER);
-+ serial_out(up, UART_IER, 0);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++, s++) {
-+ wait_for_xmitr(up);
-+
-+ /*
-+ * Send the character out.
-+ * If a LF, also do CR...
-+ */
-+ serial_out(up, UART_TX, *s);
-+ if (*s == 10) {
-+ wait_for_xmitr(up);
-+ serial_out(up, UART_TX, 13);
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the IER
-+ */
-+ wait_for_xmitr(up);
-+ serial_out(up, UART_IER, ier);
-+}
-+
-+static kdev_t serial8250_console_device(struct console *co)
-+{
-+ return MKDEV(TTY_MAJOR, 64 + co->index);
-+}
-+
-+static int __init serial8250_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 9600;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index >= UART_NR)
-+ co->index = 0;
-+ port = &serial8250_ports[co->index].port;
-+
-+ /*
-+ * Temporary fix.
-+ */
-+ spin_lock_init(&port->lock);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console serial8250_console = {
-+ .name = "ttyS",
-+ .write = serial8250_console_write,
-+ .device = serial8250_console_device,
-+ .setup = serial8250_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init serial8250_console_init(void)
-+{
-+ serial8250_isa_init_ports();
-+ register_console(&serial8250_console);
-+}
-+
-+#define SERIAL8250_CONSOLE &serial8250_console
-+#else
-+#define SERIAL8250_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver serial8250_reg = {
-+ .owner = THIS_MODULE,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "tts/%d",
-+ .callout_name = "cua/%d",
-+#else
-+ .normal_name = "ttyS",
-+ .callout_name = "cua",
-+#endif
-+ .normal_major = TTY_MAJOR,
-+ .callout_major = TTYAUX_MAJOR,
-+ .normal_driver = &normal,
-+ .callout_driver = &callout,
-+ .table = serial8250_table,
-+ .termios = serial8250_termios,
-+ .termios_locked = serial8250_termios_locked,
-+ .minor = 64,
-+ .nr = UART_NR,
-+ .cons = SERIAL8250_CONSOLE,
-+};
-+
-+/*
-+ * register_serial and unregister_serial allows for 16x50 serial ports to be
-+ * configured at run-time, to support PCMCIA modems.
-+ */
-+
-+static int __register_serial(struct serial_struct *req, int line)
-+{
-+ struct uart_port port;
-+
-+ port.iobase = req->port;
-+ port.membase = req->iomem_base;
-+ port.irq = req->irq;
-+ port.uartclk = req->baud_base * 16;
-+ port.fifosize = req->xmit_fifo_size;
-+ port.regshift = req->iomem_reg_shift;
-+ port.iotype = req->io_type;
-+ port.flags = req->flags | UPF_BOOT_AUTOCONF;
-+ port.mapbase = req->iomap_base;
-+ port.line = line;
-+
-+ if (share_irqs)
-+ port.flags |= UPF_SHARE_IRQ;
-+
-+ if (HIGH_BITS_OFFSET)
-+ port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-+
-+ /*
-+ * If a clock rate wasn't specified by the low level
-+ * driver, then default to the standard clock rate.
-+ */
-+ if (port.uartclk == 0)
-+ port.uartclk = BASE_BAUD * 16;
-+
-+ return uart_register_port(&serial8250_reg, &port);
-+}
-+
-+/**
-+ * register_serial - configure a 16x50 serial port at runtime
-+ * @req: request structure
-+ *
-+ * Configure the serial port specified by the request. If the
-+ * port exists and is in use an error is returned. If the port
-+ * is not currently in the table it is added.
-+ *
-+ * The port is then probed and if necessary the IRQ is autodetected
-+ * If this fails an error is returned.
-+ *
-+ * On success the port is ready to use and the line number is returned.
-+ */
-+int register_serial(struct serial_struct *req)
-+{
-+ return __register_serial(req, -1);
-+}
-+
-+/**
-+ * unregister_serial - remove a 16x50 serial port at runtime
-+ * @line: serial line number
-+ *
-+ * Remove one serial port. This may be called from interrupt
-+ * context.
-+ */
-+void unregister_serial(int line)
-+{
-+ uart_unregister_port(&serial8250_reg, line);
-+}
-+
-+/*
-+ * This is for ISAPNP only.
-+ */
-+void serial8250_get_irq_map(unsigned int *map)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++) {
-+ if (serial8250_ports[i].port.type != PORT_UNKNOWN &&
-+ serial8250_ports[i].port.irq < 16)
-+ *map |= 1 << serial8250_ports[i].port.irq;
-+ }
-+}
-+
-+static int __init serial8250_init(void)
-+{
-+ int ret, i;
-+
-+ for (i = 0; i < NR_IRQS; i++)
-+ spin_lock_init(&irq_lists[i].lock);
-+
-+ ret = uart_register_driver(&serial8250_reg);
-+ if (ret >= 0)
-+ serial8250_register_ports(&serial8250_reg);
-+
-+ return ret;
-+}
-+
-+static void __exit serial8250_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
-+
-+ uart_unregister_driver(&serial8250_reg);
-+}
-+
-+module_init(serial8250_init);
-+module_exit(serial8250_exit);
-+
-+EXPORT_SYMBOL(register_serial);
-+EXPORT_SYMBOL(unregister_serial);
-+EXPORT_SYMBOL(serial8250_get_irq_map);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-+
-+MODULE_PARM(share_irqs, "i");
-+MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
-+ " (unsafe)");
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
-+MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
-+MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
-+MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/8250.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,88 @@
-+/*
-+ * linux/drivers/serial/8250.h
-+ *
-+ * Driver for 8250/16550-type serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * $Id: 8250.h,v 1.1.1.1.2.1 2002/10/24 09:53:24 rmk Exp $
-+ */
-+
-+#include <linux/config.h>
-+
-+struct serial8250_probe {
-+ struct module *owner;
-+ int (*pci_init_one)(struct pci_dev *dev);
-+ void (*pci_remove_one)(struct pci_dev *dev);
-+ void (*pnp_init)(void);
-+};
-+
-+int serial8250_register_probe(struct serial8250_probe *probe);
-+void serial8250_unregister_probe(struct serial8250_probe *probe);
-+void serial8250_get_irq_map(unsigned int *map);
-+
-+struct old_serial_port {
-+ unsigned int uart;
-+ unsigned int baud_base;
-+ unsigned int port;
-+ unsigned int irq;
-+ unsigned int flags;
-+ unsigned char hub6;
-+ unsigned char io_type;
-+ unsigned char *iomem_base;
-+ unsigned short iomem_reg_shift;
-+};
-+
-+struct serial8250_config {
-+ const char *name;
-+ unsigned int dfl_xmit_fifo_size;
-+ unsigned int flags;
-+};
-+
-+#define UART_CLEAR_FIFO 0x01
-+#define UART_USE_FIFO 0x02
-+#define UART_STARTECH 0x04
-+#define UART_NATSEMI 0x08
-+#define UART_MCRAFE 0x10 /* TI16C750-style auto-flow */
-+#define UART_EFRAFE 0x20 /* TI16C752/startech auto-flow */
-+
-+#define UART_BAD_TX_ENABLE 0x80000000
-+
-+#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-+#define SERIAL_INLINE
-+#endif
-+
-+#ifdef SERIAL_INLINE
-+#define _INLINE_ inline
-+#else
-+#define _INLINE_
-+#endif
-+
-+#define PROBE_RSA (1 << 0)
-+#define PROBE_ANY (~0)
-+
-+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-+
-+#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-+#define SERIAL8250_SHARE_IRQS 1
-+#else
-+#define SERIAL8250_SHARE_IRQS 0
-+#endif
-+
-+#if defined(__alpha__) && !defined(CONFIG_PCI)
-+/*
-+ * Digital did something really horribly wrong with the OUT1 and OUT2
-+ * lines on at least some ALPHA's. The failure mode is that if either
-+ * is cleared, the machine locks up with endless interrupts.
-+ */
-+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
-+#else
-+#define ALPHA_KLUDGE_MCR 0
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/8250_pci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,1080 @@
-+/*
-+ * linux/drivers/char/serial_8250_pci.c
-+ *
-+ * Probe module for 8250/16550-type PCI serial ports.
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * $Id: 8250_pci.c,v 1.8.2.1 2002/10/24 09:53:24 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/sched.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/serial.h>
-+
-+/* 2.4.6 compatibility cruft ;( */
-+#define pci_board __pci_board
-+#include <linux/serialP.h>
-+#undef pci_board
-+
-+#include <asm/bitops.h>
-+#include <asm/byteorder.h>
-+#include <asm/serial.h>
-+
-+#include "8250.h"
-+
-+#ifndef IS_PCI_REGION_IOPORT
-+#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
-+ IORESOURCE_IO)
-+#endif
-+#ifndef IS_PCI_REGION_IOMEM
-+#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
-+ IORESOURCE_MEM)
-+#endif
-+#ifndef PCI_IRQ_RESOURCE
-+#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
-+#endif
-+
-+#ifndef pci_get_subvendor
-+#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
-+#define pci_get_subdevice(dev) ((dev)->subsystem_device)
-+#endif
-+
-+struct serial_private {
-+ unsigned int nr;
-+ struct pci_board *board;
-+ int line[0];
-+};
-+
-+struct pci_board {
-+ int flags;
-+ int num_ports;
-+ int base_baud;
-+ int uart_offset;
-+ int reg_shift;
-+ int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
-+ int enable);
-+ int first_uart_offset;
-+};
-+
-+static int
-+get_pci_port(struct pci_dev *dev, struct pci_board *board,
-+ struct serial_struct *req, int idx)
-+{
-+ unsigned long port;
-+ int base_idx;
-+ int max_port;
-+ int offset;
-+
-+ base_idx = SPCI_FL_GET_BASE(board->flags);
-+ if (board->flags & SPCI_FL_BASE_TABLE)
-+ base_idx += idx;
-+
-+ if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-+ max_port = pci_resource_len(dev, base_idx) / 8;
-+ if (idx >= max_port)
-+ return 1;
-+ }
-+
-+ offset = board->first_uart_offset;
-+
-+ /* Timedia/SUNIX uses a mixture of BARs and offsets */
-+ /* Ugh, this is ugly as all hell --- TYT */
-+ if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
-+ switch(idx) {
-+ case 0: base_idx=0;
-+ break;
-+ case 1: base_idx=0; offset=8;
-+ break;
-+ case 2: base_idx=1;
-+ break;
-+ case 3: base_idx=1; offset=8;
-+ break;
-+ case 4: /* BAR 2*/
-+ case 5: /* BAR 3 */
-+ case 6: /* BAR 4*/
-+ case 7: base_idx=idx-2; /* BAR 5*/
-+ }
-+
-+ /* Some Titan cards are also a little weird */
-+ if (dev->vendor == PCI_VENDOR_ID_TITAN &&
-+ (dev->device == PCI_DEVICE_ID_TITAN_400L ||
-+ dev->device == PCI_DEVICE_ID_TITAN_800L)) {
-+ switch (idx) {
-+ case 0: base_idx = 1;
-+ break;
-+ case 1: base_idx = 2;
-+ break;
-+ default:
-+ base_idx = 4;
-+ offset = 8 * (idx - 2);
-+ }
-+ }
-+
-+ port = pci_resource_start(dev, base_idx) + offset;
-+
-+ if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-+ port += idx * (board->uart_offset ? board->uart_offset : 8);
-+
-+ if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
-+ req->port = port;
-+ if (HIGH_BITS_OFFSET)
-+ req->port_high = port >> HIGH_BITS_OFFSET;
-+ else
-+ req->port_high = 0;
-+ return 0;
-+ }
-+ req->io_type = SERIAL_IO_MEM;
-+ req->iomem_base = ioremap(port, board->uart_offset);
-+ req->iomem_reg_shift = board->reg_shift;
-+ req->port = 0;
-+ return 0;
-+}
-+
-+static _INLINE_ int get_pci_irq(struct pci_dev *dev,
-+ struct pci_board *board,
-+ int idx)
-+{
-+ int base_idx;
-+
-+ if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
-+ return dev->irq;
-+
-+ base_idx = SPCI_FL_GET_IRQBASE(board->flags);
-+ if (board->flags & SPCI_FL_IRQ_TABLE)
-+ base_idx += idx;
-+
-+ return PCI_IRQ_RESOURCE(dev, base_idx);
-+}
-+
-+/*
-+ * Some PCI serial cards using the PLX 9050 PCI interface chip require
-+ * that the card interrupt be explicitly enabled or disabled. This
-+ * seems to be mainly needed on card using the PLX which also use I/O
-+ * mapped memory.
-+ */
-+static int __devinit
-+pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u8 data, *p, irq_config;
-+ int pci_config;
-+
-+ irq_config = 0x41;
-+ pci_config = PCI_COMMAND_MEMORY;
-+ if (dev->vendor == PCI_VENDOR_ID_PANACOM)
-+ irq_config = 0x43;
-+ if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
-+ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
-+ /*
-+ * As the megawolf cards have the int pins active
-+ * high, and have 2 UART chips, both ints must be
-+ * enabled on the 9050. Also, the UARTS are set in
-+ * 16450 mode by default, so we have to enable the
-+ * 16C950 'enhanced' mode so that we can use the deep
-+ * FIFOs
-+ */
-+ irq_config = 0x5b;
-+ pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
-+ }
-+
-+ pci_read_config_byte(dev, PCI_COMMAND, &data);
-+
-+ if (enable)
-+ pci_write_config_byte(dev, PCI_COMMAND,
-+ data | pci_config);
-+
-+ /* enable/disable interrupts */
-+ p = ioremap(pci_resource_start(dev, 0), 0x80);
-+ writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
-+ iounmap(p);
-+
-+ if (!enable)
-+ pci_write_config_byte(dev, PCI_COMMAND,
-+ data & ~pci_config);
-+ return 0;
-+}
-+
-+
-+/*
-+ * SIIG serial cards have an PCI interface chip which also controls
-+ * the UART clocking frequency. Each UART can be clocked independently
-+ * (except cards equiped with 4 UARTs) and initial clocking settings
-+ * are stored in the EEPROM chip. It can cause problems because this
-+ * version of serial driver doesn't support differently clocked UART's
-+ * on single PCI card. To prevent this, initialization functions set
-+ * high frequency clocking for all UART's on given card. It is safe (I
-+ * hope) because it doesn't touch EEPROM settings to prevent conflicts
-+ * with other OSes (like M$ DOS).
-+ *
-+ * SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
-+ *
-+ * There is two family of SIIG serial cards with different PCI
-+ * interface chip and different configuration methods:
-+ * - 10x cards have control registers in IO and/or memory space;
-+ * - 20x cards have control registers in standard PCI configuration space.
-+ */
-+
-+#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
-+#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
-+
-+static int __devinit
-+pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u16 data, *p;
-+
-+ if (!enable) return 0;
-+
-+ p = ioremap(pci_resource_start(dev, 0), 0x80);
-+
-+ switch (dev->device & 0xfff8) {
-+ case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
-+ data = 0xffdf;
-+ break;
-+ case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
-+ data = 0xf7ff;
-+ break;
-+ default: /* 1S1P, 4S */
-+ data = 0xfffb;
-+ break;
-+ }
-+
-+ writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
-+ iounmap(p);
-+ return 0;
-+}
-+
-+#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
-+#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
-+
-+static int __devinit
-+pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u8 data;
-+
-+ if (!enable) return 0;
-+
-+ /* Change clock frequency for the first UART. */
-+ pci_read_config_byte(dev, 0x6f, &data);
-+ pci_write_config_byte(dev, 0x6f, data & 0xef);
-+
-+ /* If this card has 2 UART, we have to do the same with second UART. */
-+ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
-+ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
-+ pci_read_config_byte(dev, 0x73, &data);
-+ pci_write_config_byte(dev, 0x73, data & 0xef);
-+ }
-+ return 0;
-+}
-+
-+/* Added for EKF Intel i960 serial boards */
-+static int __devinit
-+pci_inteli960ni_fn(struct pci_dev *dev,
-+ struct pci_board *board,
-+ int enable)
-+{
-+ unsigned long oldval;
-+
-+ if (!(pci_get_subdevice(dev) & 0x1000))
-+ return(-1);
-+
-+ if (!enable) /* is there something to deinit? */
-+ return(0);
-+
-+ /* is firmware started? */
-+ pci_read_config_dword(dev, 0x44, (void*) &oldval);
-+ if (oldval == 0x00001000L) { /* RESET value */
-+ printk(KERN_DEBUG "Local i960 firmware missing");
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Timedia has an explosion of boards, and to avoid the PCI table from
-+ * growing *huge*, we use this function to collapse some 70 entries
-+ * in the PCI table into one, for sanity's and compactness's sake.
-+ */
-+static unsigned short timedia_single_port[] = {
-+ 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
-+static unsigned short timedia_dual_port[] = {
-+ 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
-+ 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
-+ 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
-+ 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
-+ 0xD079, 0 };
-+static unsigned short timedia_quad_port[] = {
-+ 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
-+ 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
-+ 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
-+ 0xB157, 0 };
-+static unsigned short timedia_eight_port[] = {
-+ 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
-+ 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
-+static struct timedia_struct {
-+ int num;
-+ unsigned short *ids;
-+} timedia_data[] = {
-+ { 1, timedia_single_port },
-+ { 2, timedia_dual_port },
-+ { 4, timedia_quad_port },
-+ { 8, timedia_eight_port },
-+ { 0, 0 }
-+};
-+
-+static int __devinit
-+pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ int i, j;
-+ unsigned short *ids;
-+
-+ if (!enable)
-+ return 0;
-+
-+ for (i=0; timedia_data[i].num; i++) {
-+ ids = timedia_data[i].ids;
-+ for (j=0; ids[j]; j++) {
-+ if (pci_get_subdevice(dev) == ids[j]) {
-+ board->num_ports = timedia_data[i].num;
-+ return 0;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int __devinit
-+pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ __set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ/10);
-+ return 0;
-+}
-+
-+/*
-+ * This is the configuration table for all of the PCI serial boards
-+ * which we support. It is directly indexed by the pci_board_num_t enum
-+ * value, which is encoded in the pci_device_id PCI probe table's
-+ * driver_data member.
-+ */
-+enum pci_board_num_t {
-+ pbn_b0_1_115200,
-+ pbn_default = 0,
-+
-+ pbn_b0_2_115200,
-+ pbn_b0_4_115200,
-+
-+ pbn_b0_1_921600,
-+ pbn_b0_2_921600,
-+ pbn_b0_4_921600,
-+
-+ pbn_b0_bt_1_115200,
-+ pbn_b0_bt_2_115200,
-+ pbn_b0_bt_1_460800,
-+ pbn_b0_bt_2_460800,
-+
-+ pbn_b1_1_115200,
-+ pbn_b1_2_115200,
-+ pbn_b1_4_115200,
-+ pbn_b1_8_115200,
-+
-+ pbn_b1_2_921600,
-+ pbn_b1_4_921600,
-+ pbn_b1_8_921600,
-+
-+ pbn_b1_2_1382400,
-+ pbn_b1_4_1382400,
-+ pbn_b1_8_1382400,
-+
-+ pbn_b2_8_115200,
-+ pbn_b2_4_460800,
-+ pbn_b2_8_460800,
-+ pbn_b2_16_460800,
-+ pbn_b2_4_921600,
-+ pbn_b2_8_921600,
-+
-+ pbn_b2_bt_1_115200,
-+ pbn_b2_bt_2_115200,
-+ pbn_b2_bt_4_115200,
-+ pbn_b2_bt_2_921600,
-+
-+ pbn_panacom,
-+ pbn_panacom2,
-+ pbn_panacom4,
-+ pbn_plx_romulus,
-+ pbn_oxsemi,
-+ pbn_timedia,
-+ pbn_intel_i960,
-+ pbn_sgi_ioc3,
-+#ifdef CONFIG_DDB5074
-+ pbn_nec_nile4,
-+#endif
-+#if 0
-+ pbn_dci_pccom8,
-+#endif
-+ pbn_xircom_combo,
-+
-+ pbn_siig10x_0,
-+ pbn_siig10x_1,
-+ pbn_siig10x_2,
-+ pbn_siig10x_4,
-+ pbn_siig20x_0,
-+ pbn_siig20x_2,
-+ pbn_siig20x_4,
-+
-+ pbn_computone_4,
-+ pbn_computone_6,
-+ pbn_computone_8,
-+};
-+
-+static struct pci_board pci_boards[] __devinitdata = {
-+ /*
-+ * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-+ * Offset to get to next UART's registers,
-+ * Register shift to use for memory-mapped I/O,
-+ * Initialization function, first UART offset
-+ */
-+
-+ /* Generic serial board, pbn_b0_1_115200, pbn_default */
-+ { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
-+ pbn_default */
-+
-+ { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
-+ { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
-+
-+ { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
-+ { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
-+ { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
-+
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
-+
-+ { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
-+ { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
-+ { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
-+ { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
-+
-+ { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
-+ { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
-+ { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
-+
-+ { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
-+ { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
-+ { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
-+
-+ { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
-+ { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
-+ { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
-+ { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
-+ { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
-+ { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
-+
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
-+
-+ { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
-+ 0x20, 2, pci_plx9050_fn, 0x03 },
-+ /* This board uses the size of PCI Base region 0 to
-+ * signal now many ports are available */
-+ { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
-+ { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
-+ 0, 0, pci_timedia_fn },
-+ /* EKF addition for i960 Boards form EKF with serial port */
-+ { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
-+ 8<<2, 2, pci_inteli960ni_fn, 0x10000},
-+ { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
-+ 1, 458333, 0, 0, 0, 0x20178 },
-+#ifdef CONFIG_DDB5074
-+ /*
-+ * NEC Vrc-5074 (Nile 4) builtin UART.
-+ * Conditionally compiled in since this is a motherboard device.
-+ */
-+ { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
-+ 64, 3, NULL, 0x300 },
-+#endif
-+#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */
-+ { SPCI_FL_BASE3, 8, 115200, 8 },
-+#endif
-+ { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
-+ 0, 0, pci_xircom_fn },
-+
-+ { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
-+ 0, 0, pci_siig20x_fn },
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
-+ 0, 0, pci_siig20x_fn },
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
-+ 0, 0, pci_siig20x_fn },
-+
-+ { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
-+ 0x40, 2, NULL, 0x200 },
-+ { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
-+ 0x40, 2, NULL, 0x200 },
-+ { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
-+ 0x40, 2, NULL, 0x200 },
-+};
-+
-+/*
-+ * Given a complete unknown PCI device, try to use some heuristics to
-+ * guess what the configuration might be, based on the pitiful PCI
-+ * serial specs. Returns 0 on success, 1 on failure.
-+ */
-+static int __devinit serial_pci_guess_board(struct pci_dev *dev,
-+ struct pci_board *board)
-+{
-+ int num_iomem = 0, num_port = 0, first_port = -1;
-+ int i;
-+
-+ /*
-+ * If it is not a communications device or the programming
-+ * interface is greater than 6, give up.
-+ *
-+ * (Should we try to make guesses for multiport serial devices
-+ * later?)
-+ */
-+ if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
-+ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
-+ (dev->class & 0xff) > 6)
-+ return 1;
-+
-+ for (i=0; i < 6; i++) {
-+ if (IS_PCI_REGION_IOPORT(dev, i)) {
-+ num_port++;
-+ if (first_port == -1)
-+ first_port = i;
-+ }
-+ if (IS_PCI_REGION_IOMEM(dev, i))
-+ num_iomem++;
-+ }
-+
-+ /*
-+ * If there is 1 or 0 iomem regions, and exactly one port, use
-+ * it.
-+ */
-+ if (num_iomem <= 1 && num_port == 1) {
-+ board->flags = first_port;
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+/*
-+ * return -1 to refuse
-+ */
-+static int pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-+{
-+ struct serial_private *priv;
-+ struct pci_board *board, tmp;
-+ struct serial_struct serial_req;
-+ int base_baud, rc, k;
-+
-+ board = &pci_boards[ent->driver_data];
-+
-+ rc = pci_enable_device(dev);
-+ if (rc)
-+ return rc;
-+
-+ if (ent->driver_data == pbn_default &&
-+ serial_pci_guess_board(dev, board))
-+ return -ENODEV;
-+ else if (serial_pci_guess_board(dev, &tmp) == 0) {
-+ printk(KERN_INFO "Redundant entry in serial pci_table. "
-+ "Please send the output of\n"
-+ "lspci -vv, this message (%d,%d,%d,%d)\n"
-+ "and the manufacturer and name of "
-+ "serial board or modem board\n"
-+ "to serial-pci-info@lists.sourceforge.net.\n",
-+ dev->vendor, dev->device,
-+ pci_get_subvendor(dev), pci_get_subdevice(dev));
-+ }
-+
-+
-+ priv = kmalloc(sizeof(struct serial_private) +
-+ sizeof(unsigned int) * board->num_ports,
-+ GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ /*
-+ * Run the initialization function, if any
-+ */
-+ if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) {
-+ kfree(priv);
-+ return -ENODEV;
-+ }
-+
-+ base_baud = board->base_baud;
-+ if (!base_baud)
-+ base_baud = BASE_BAUD;
-+ memset(&serial_req, 0, sizeof(serial_req));
-+ for (k=0; k < board->num_ports; k++) {
-+ serial_req.irq = get_pci_irq(dev, board, k);
-+ if (get_pci_port(dev, board, &serial_req, k))
-+ break;
-+#ifdef SERIAL_DEBUG_PCI
-+ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
-+ serial_req.port, serial_req.irq, serial_req.io_type);
-+#endif
-+ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-+ serial_req.baud_base = base_baud;
-+ priv->line[k] = register_serial(&serial_req);
-+ if (priv->line[k] < 0)
-+ break;
-+ }
-+
-+ priv->board = board;
-+ priv->nr = k;
-+
-+ pci_set_drvdata(dev, priv);
-+
-+ return 0;
-+}
-+
-+static void pci_remove_one(struct pci_dev *dev)
-+{
-+ struct serial_private *priv = pci_get_drvdata(dev);
-+ int i;
-+
-+ pci_set_drvdata(dev, NULL);
-+
-+ for (i = 0; i < priv->nr; i++)
-+ unregister_serial(priv->line[i]);
-+
-+ priv->board->init_fn(dev, priv->board, 0);
-+
-+ kfree(priv);
-+}
-+
-+static struct pci_device_id serial_pci_tbl[] __devinitdata = {
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-+ pbn_b1_8_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-+ pbn_b1_4_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-+ pbn_b1_2_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-+ pbn_b1_8_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-+ pbn_b1_4_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-+ pbn_b1_2_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
-+ pbn_b1_4_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
-+ pbn_b1_4_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
-+ pbn_b1_2_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
-+ pbn_b1_4_921600 },
-+
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_1_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_4_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_4_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_8_115200 },
-+
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_921600 },
-+ /* VScom SPCOM800, from sl@s.pl */
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_8_921600 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_4_921600 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_KEYSPAN,
-+ PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
-+ pbn_panacom },
-+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_panacom4 },
-+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_panacom2 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
-+ pbn_b2_4_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
-+ pbn_b2_8_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
-+ pbn_b2_16_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
-+ pbn_b2_16_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-+ PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
-+ pbn_b2_4_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-+ PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
-+ pbn_b2_8_460800 },
-+ /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
-+ /* (Exoray@isys.ca) */
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
-+ 0x10b5, 0x106a, 0, 0,
-+ pbn_plx_romulus },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_4_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_2_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_8_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_8_115200 },
-+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
-+ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_115200 },
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_2_115200 },
-+
-+ /* Digitan DS560-558, from jimd@esoft.com */
-+ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_1_115200 },
-+
-+ /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
-+ { PCI_VENDOR_ID_USR, 0x1008,
-+ PCI_ANY_ID, PCI_ANY_ID, },
-+
-+ /* Titan Electronic cards */
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_1_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_2_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE1, 1, 921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-+ /* The 400L and 800L have a custom hack in get_pci_port */
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE_TABLE, 4, 921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE_TABLE, 8, 921600 },
-+
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+
-+ /* Computone devices submitted by Doug McNash dmcnash@computone.com */
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
-+ 0, 0, pbn_computone_4 },
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
-+ 0, 0, pbn_computone_8 },
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
-+ 0, 0, pbn_computone_6 },
-+
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
-+ { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
-+ PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
-+
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_1_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_1_460800 },
-+
-+ /* RAStel 2 port modem, gerg@moreton.com.au */
-+ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+
-+ /* EKF addition for i960 Boards form EKF with serial port */
-+ { PCI_VENDOR_ID_INTEL, 0x1960,
-+ 0xE4BF, PCI_ANY_ID, 0, 0,
-+ pbn_intel_i960 },
-+
-+ /* Xircom Cardbus/Ethernet combos */
-+ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_xircom_combo },
-+
-+ /*
-+ * Untested PCI modems, sent in from various folks...
-+ */
-+
-+ /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
-+ { PCI_VENDOR_ID_ROCKWELL, 0x1004,
-+ 0x1048, 0x1500, 0, 0,
-+ pbn_b1_1_115200 },
-+
-+ { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-+ 0xFF00, 0, 0, 0,
-+ pbn_sgi_ioc3 },
-+
-+#ifdef CONFIG_DDB5074
-+ /*
-+ * NEC Vrc-5074 (Nile 4) builtin UART.
-+ * Conditionally compiled in since this is a motherboard device.
-+ */
-+ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_nec_nile4 },
-+#endif
-+
-+#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */
-+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_dci_pccom8 },
-+#endif
-+
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, },
-+ { 0, }
-+};
-+
-+static struct pci_driver serial_pci_driver = {
-+ name: "serial",
-+ probe: pci_init_one,
-+ remove: pci_remove_one,
-+ id_table: serial_pci_tbl,
-+};
-+
-+static int __init serial8250_pci_init(void)
-+{
-+ return pci_module_init(&serial_pci_driver);
-+}
-+
-+static void __exit serial8250_pci_exit(void)
-+{
-+ pci_unregister_driver(&serial_pci_driver);
-+}
-+
-+module_init(serial8250_pci_init);
-+module_exit(serial8250_pci_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-+MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/8250_pnp.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,553 @@
-+/*
-+ * linux/drivers/char/serial_8250_pnp.c
-+ *
-+ * Probe module for 8250/16550-type ISAPNP serial ports.
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * $Id: 8250_pnp.c,v 1.3.2.1 2002/10/24 09:53:25 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/isapnp.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/serial.h>
-+#include <linux/serialP.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/byteorder.h>
-+#include <asm/serial.h>
-+
-+#include "8250.h"
-+
-+static struct serial_state rs_table[] = { };
-+#define NR_PORTS 0
-+
-+struct pnpbios_device_id
-+{
-+ char id[8];
-+ unsigned long driver_data;
-+};
-+
-+static const struct pnpbios_device_id pnp_dev_table[] = {
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "AAC000F", 0 },
-+ /* Anchor Datacomm BV */
-+ /* SXPro 144 External Data Fax Modem Plug & Play */
-+ { "ADC0001", 0 },
-+ /* SXPro 288 External Data Fax Modem Plug & Play */
-+ { "ADC0002", 0 },
-+ /* Rockwell 56K ACF II Fax+Data+Voice Modem */
-+ { "AKY1021", SPCI_FL_NO_SHIRQ },
-+ /* AZT3005 PnP SOUND DEVICE */
-+ { "AZT4001", 0 },
-+ /* Best Data Products Inc. Smart One 336F PnP Modem */
-+ { "BDP3336", 0 },
-+ /* Boca Research */
-+ /* Boca Complete Ofc Communicator 14.4 Data-FAX */
-+ { "BRI0A49", 0 },
-+ /* Boca Research 33,600 ACF Modem */
-+ { "BRI1400", 0 },
-+ /* Boca 33.6 Kbps Internal FD34FSVD */
-+ { "BRI3400", 0 },
-+ /* Boca 33.6 Kbps Internal FD34FSVD */
-+ { "BRI0A49", 0 },
-+ /* Best Data Products Inc. Smart One 336F PnP Modem */
-+ { "BDP3336", 0 },
-+ /* Computer Peripherals Inc */
-+ /* EuroViVa CommCenter-33.6 SP PnP */
-+ { "CPI4050", 0 },
-+ /* Creative Labs */
-+ /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
-+ { "CTL3001", 0 },
-+ /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
-+ { "CTL3011", 0 },
-+ /* Creative */
-+ /* Creative Modem Blaster Flash56 DI5601-1 */
-+ { "DMB1032", 0 },
-+ /* Creative Modem Blaster V.90 DI5660 */
-+ { "DMB2001", 0 },
-+ /* FUJITSU */
-+ /* Fujitsu 33600 PnP-I2 R Plug & Play */
-+ { "FUJ0202", 0 },
-+ /* Fujitsu FMV-FX431 Plug & Play */
-+ { "FUJ0205", 0 },
-+ /* Fujitsu 33600 PnP-I4 R Plug & Play */
-+ { "FUJ0206", 0 },
-+ /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
-+ { "FUJ0209", 0 },
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "GVC000F", 0 },
-+ /* Hayes */
-+ /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
-+ { "HAY0001", 0 },
-+ /* Hayes Optima 336 V.34 + FAX + Voice PnP */
-+ { "HAY000C", 0 },
-+ /* Hayes Optima 336B V.34 + FAX + Voice PnP */
-+ { "HAY000D", 0 },
-+ /* Hayes Accura 56K Ext Fax Modem PnP */
-+ { "HAY5670", 0 },
-+ /* Hayes Accura 56K Ext Fax Modem PnP */
-+ { "HAY5674", 0 },
-+ /* Hayes Accura 56K Fax Modem PnP */
-+ { "HAY5675", 0 },
-+ /* Hayes 288, V.34 + FAX */
-+ { "HAYF000", 0 },
-+ /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
-+ { "HAYF001", 0 },
-+ /* IBM */
-+ /* IBM Thinkpad 701 Internal Modem Voice */
-+ { "IBM0033", 0 },
-+ /* Intertex */
-+ /* Intertex 28k8 33k6 Voice EXT PnP */
-+ { "IXDC801", 0 },
-+ /* Intertex 33k6 56k Voice EXT PnP */
-+ { "IXDC901", 0 },
-+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
-+ { "IXDD801", 0 },
-+ /* Intertex 33k6 56k Voice SP EXT PnP */
-+ { "IXDD901", 0 },
-+ /* Intertex 28k8 33k6 Voice SP INT PnP */
-+ { "IXDF401", 0 },
-+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
-+ { "IXDF801", 0 },
-+ /* Intertex 33k6 56k Voice SP EXT PnP */
-+ { "IXDF901", 0 },
-+ /* Kortex International */
-+ /* KORTEX 28800 Externe PnP */
-+ { "KOR4522", 0 },
-+ /* KXPro 33.6 Vocal ASVD PnP */
-+ { "KORF661", 0 },
-+ /* Lasat */
-+ /* LASAT Internet 33600 PnP */
-+ { "LAS4040", 0 },
-+ /* Lasat Safire 560 PnP */
-+ { "LAS4540", 0 },
-+ /* Lasat Safire 336 PnP */
-+ { "LAS5440", 0 },
-+ /* Microcom, Inc. */
-+ /* Microcom TravelPorte FAST V.34 Plug & Play */
-+ { "MNP0281", 0 },
-+ /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
-+ { "MNP0336", 0 },
-+ /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
-+ { "MNP0339", 0 },
-+ /* Microcom DeskPorte 28.8P Plug & Play */
-+ { "MNP0342", 0 },
-+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-+ { "MNP0500", 0 },
-+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-+ { "MNP0501", 0 },
-+ /* Microcom DeskPorte 28.8S Internal Plug & Play */
-+ { "MNP0502", 0 },
-+ /* Motorola */
-+ /* Motorola BitSURFR Plug & Play */
-+ { "MOT1105", 0 },
-+ /* Motorola TA210 Plug & Play */
-+ { "MOT1111", 0 },
-+ /* Motorola HMTA 200 (ISDN) Plug & Play */
-+ { "MOT1114", 0 },
-+ /* Motorola BitSURFR Plug & Play */
-+ { "MOT1115", 0 },
-+ /* Motorola Lifestyle 28.8 Internal */
-+ { "MOT1190", 0 },
-+ /* Motorola V.3400 Plug & Play */
-+ { "MOT1501", 0 },
-+ /* Motorola Lifestyle 28.8 V.34 Plug & Play */
-+ { "MOT1502", 0 },
-+ /* Motorola Power 28.8 V.34 Plug & Play */
-+ { "MOT1505", 0 },
-+ /* Motorola ModemSURFR External 28.8 Plug & Play */
-+ { "MOT1509", 0 },
-+ /* Motorola Premier 33.6 Desktop Plug & Play */
-+ { "MOT150A", 0 },
-+ /* Motorola VoiceSURFR 56K External PnP */
-+ { "MOT150F", 0 },
-+ /* Motorola ModemSURFR 56K External PnP */
-+ { "MOT1510", 0 },
-+ /* Motorola ModemSURFR 56K Internal PnP */
-+ { "MOT1550", 0 },
-+ /* Motorola ModemSURFR Internal 28.8 Plug & Play */
-+ { "MOT1560", 0 },
-+ /* Motorola Premier 33.6 Internal Plug & Play */
-+ { "MOT1580", 0 },
-+ /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
-+ { "MOT15B0", 0 },
-+ /* Motorola VoiceSURFR 56K Internal PnP */
-+ { "MOT15F0", 0 },
-+ /* Com 1 */
-+ /* Deskline K56 Phone System PnP */
-+ { "MVX00A1", 0 },
-+ /* PC Rider K56 Phone System PnP */
-+ { "MVX00F2", 0 },
-+ /* Pace 56 Voice Internal Plug & Play Modem */
-+ { "PMC2430", 0 },
-+ /* Generic */
-+ /* Generic standard PC COM port */
-+ { "PNP0500", 0 },
-+ /* Generic 16550A-compatible COM port */
-+ { "PNP0501", 0 },
-+ /* Compaq 14400 Modem */
-+ { "PNPC000", 0 },
-+ /* Compaq 2400/9600 Modem */
-+ { "PNPC001", 0 },
-+ /* Dial-Up Networking Serial Cable between 2 PCs */
-+ { "PNPC031", 0 },
-+ /* Dial-Up Networking Parallel Cable between 2 PCs */
-+ { "PNPC032", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC100", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC101", 0 },
-+ /* Standard 28800 bps Modem*/
-+ { "PNPC102", 0 },
-+ /* Standard Modem*/
-+ { "PNPC103", 0 },
-+ /* Standard 9600 bps Modem*/
-+ { "PNPC104", 0 },
-+ /* Standard 14400 bps Modem*/
-+ { "PNPC105", 0 },
-+ /* Standard 28800 bps Modem*/
-+ { "PNPC106", 0 },
-+ /* Standard Modem */
-+ { "PNPC107", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC108", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC109", 0 },
-+ /* Standard 28800 bps Modem */
-+ { "PNPC10A", 0 },
-+ /* Standard Modem */
-+ { "PNPC10B", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC10C", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC10D", 0 },
-+ /* Standard 28800 bps Modem */
-+ { "PNPC10E", 0 },
-+ /* Standard Modem */
-+ { "PNPC10F", 0 },
-+ /* Standard PCMCIA Card Modem */
-+ { "PNP2000", 0 },
-+ /* Rockwell */
-+ /* Modular Technology */
-+ /* Rockwell 33.6 DPF Internal PnP */
-+ /* Modular Technology 33.6 Internal PnP */
-+ { "ROK0030", 0 },
-+ /* Kortex International */
-+ /* KORTEX 14400 Externe PnP */
-+ { "ROK0100", 0 },
-+ /* Viking Components, Inc */
-+ /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
-+ { "ROK4920", 0 },
-+ /* Rockwell */
-+ /* British Telecom */
-+ /* Modular Technology */
-+ /* Rockwell 33.6 DPF External PnP */
-+ /* BT Prologue 33.6 External PnP */
-+ /* Modular Technology 33.6 External PnP */
-+ { "RSS00A0", 0 },
-+ /* Viking 56K FAX INT */
-+ { "RSS0262", 0 },
-+ /* SupraExpress 28.8 Data/Fax PnP modem */
-+ { "SUP1310", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1421", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1590", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1760", 0 },
-+ /* Phoebe Micro */
-+ /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
-+ { "TEX0011", 0 },
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "UAC000F", 0 },
-+ /* 3Com Corp. */
-+ /* Gateway Telepath IIvi 33.6 */
-+ { "USR0000", 0 },
-+ /* Sportster Vi 14.4 PnP FAX Voicemail */
-+ { "USR0004", 0 },
-+ /* U.S. Robotics 33.6K Voice INT PnP */
-+ { "USR0006", 0 },
-+ /* U.S. Robotics 33.6K Voice EXT PnP */
-+ { "USR0007", 0 },
-+ /* U.S. Robotics 33.6K Voice INT PnP */
-+ { "USR2002", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR2070", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP */
-+ { "USR2080", 0 },
-+ /* U.S. Robotics 56K FAX INT */
-+ { "USR3031", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR3070", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP */
-+ { "USR3080", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR3090", 0 },
-+ /* U.S. Robotics 56K Message */
-+ { "USR9100", 0 },
-+ /* U.S. Robotics 56K FAX EXT PnP*/
-+ { "USR9160", 0 },
-+ /* U.S. Robotics 56K FAX INT PnP*/
-+ { "USR9170", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP*/
-+ { "USR9180", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP*/
-+ { "USR9190", 0 },
-+ { "", 0 }
-+};
-+
-+static void inline avoid_irq_share(struct pci_dev *dev)
-+{
-+ int i, map = 0x1FF8;
-+ struct serial_state *state = rs_table;
-+ struct isapnp_irq *irq;
-+ struct isapnp_resources *res = dev->sysdata;
-+
-+ for (i = 0; i < NR_PORTS; i++) {
-+ if (state->type != PORT_UNKNOWN)
-+ clear_bit(state->irq, &map);
-+ state++;
-+ }
-+
-+ for ( ; res; res = res->alt)
-+ for(irq = res->irq; irq; irq = irq->next)
-+ irq->map = map;
-+}
-+
-+static char *modem_names[] __devinitdata = {
-+ "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
-+ "56K", "56k", "K56", "33.6", "28.8", "14.4",
-+ "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
-+ "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
-+};
-+
-+static int __devinit check_name(char *name)
-+{
-+ char **tmp;
-+
-+ for (tmp = modem_names; *tmp; tmp++)
-+ if (strstr(name, *tmp))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static int inline check_compatible_id(struct pci_dev *dev)
-+{
-+ int i;
-+ for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
-+ if ((dev->vendor_compatible[i] ==
-+ ISAPNP_VENDOR('P', 'N', 'P')) &&
-+ (swab16(dev->device_compatible[i]) >= 0xc000) &&
-+ (swab16(dev->device_compatible[i]) <= 0xdfff))
-+ return 0;
-+ return 1;
-+}
-+
-+/*
-+ * Given a complete unknown ISA PnP device, try to use some heuristics to
-+ * detect modems. Currently use such heuristic set:
-+ * - dev->name or dev->bus->name must contain "modem" substring;
-+ * - device must have only one IO region (8 byte long) with base adress
-+ * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
-+ *
-+ * Such detection looks very ugly, but can detect at least some of numerous
-+ * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
-+ * table.
-+ */
-+static int serial_pnp_guess_board(struct pci_dev *dev, int *flags)
-+{
-+ struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
-+ struct isapnp_resources *resa;
-+
-+ if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
-+ !(check_compatible_id(dev)))
-+ return -ENODEV;
-+
-+ if (!res || res->next)
-+ return -ENODEV;
-+
-+ for (resa = res->alt; resa; resa = resa->alt) {
-+ struct isapnp_port *port;
-+ for (port = res->port; port; port = port->next)
-+ if ((port->size == 8) &&
-+ ((port->min == 0x2f8) ||
-+ (port->min == 0x3f8) ||
-+ (port->min == 0x2e8) ||
-+ (port->min == 0x3e8)))
-+ return 0;
-+ }
-+
-+ return -ENODEV;
-+}
-+
-+static int
-+pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent,
-+ char *slot_name)
-+{
-+ struct serial_struct serial_req;
-+ int ret, line, flags = ent ? ent->driver_data : 0;
-+
-+ if (!ent) {
-+ ret = serial_pnp_guess_board(dev, &flags);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (dev->prepare(dev) < 0) {
-+ printk("serial: PNP device '%s' prepare failed\n",
-+ slot_name);
-+ return -ENODEV;
-+ }
-+
-+ if (dev->active)
-+ return -ENODEV;
-+
-+ if (flags & SPCI_FL_NO_SHIRQ)
-+ avoid_irq_share(dev);
-+
-+ if (dev->activate(dev) < 0) {
-+ printk("serial: PNP device '%s' activate failed\n",
-+ slot_name);
-+ return -ENODEV;
-+ }
-+
-+ memset(&serial_req, 0, sizeof(serial_req));
-+ serial_req.irq = dev->irq_resource[0].start;
-+ serial_req.port = pci_resource_start(dev, 0);
-+ if (HIGH_BITS_OFFSET)
-+ serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET;
-+
-+#ifdef SERIAL_DEBUG_PCI
-+ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
-+ serial_req.port, serial_req.irq, serial_req.io_type);
-+#endif
-+
-+ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-+ serial_req.baud_base = 115200;
-+ line = register_serial(&serial_req);
-+
-+ if (line >= 0) {
-+ pci_set_drvdata(dev, (void *)(line + 1));
-+
-+ /*
-+ * Public health warning: remove this once the 2.5
-+ * pnpbios_module_init() stuff is incorporated.
-+ */
-+ dev->driver = (void *)pnp_dev_table;
-+ } else
-+ dev->deactivate(dev);
-+
-+ return line >= 0 ? 0 : -ENODEV;
-+}
-+
-+static void pnp_remove_one(struct pci_dev *dev)
-+{
-+ int line = (int)pci_get_drvdata(dev);
-+
-+ if (line) {
-+ pci_set_drvdata(dev, NULL);
-+
-+ unregister_serial(line - 1);
-+
-+ dev->deactivate(dev);
-+ }
-+}
-+
-+static char hex[] = "0123456789ABCDEF";
-+
-+/*
-+ * This function should vanish when 2.5 comes around and
-+ * we have pnpbios_module_init()
-+ */
-+static void pnp_init(void)
-+{
-+ const struct pnpbios_device_id *id;
-+ struct pci_dev *dev = NULL;
-+
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Entered probe_serial_pnp()\n");
-+#endif
-+
-+ isapnp_for_each_dev(dev) {
-+ char slot_name[8];
-+ u32 pnpid;
-+
-+ if (dev->active)
-+ continue;
-+
-+ pnpid = dev->vendor << 16 | dev->device;
-+ pnpid = cpu_to_le32(pnpid);
-+
-+#define HEX(id,a) hex[((id)>>a) & 15]
-+#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-+ slot_name[0] = CHAR(pnpid, 26);
-+ slot_name[1] = CHAR(pnpid, 21);
-+ slot_name[2] = CHAR(pnpid, 16);
-+ slot_name[3] = HEX(pnpid, 12);
-+ slot_name[4] = HEX(pnpid, 8);
-+ slot_name[5] = HEX(pnpid, 4);
-+ slot_name[6] = HEX(pnpid, 0);
-+ slot_name[7] = '\0';
-+
-+ for (id = pnp_dev_table; id->id[0]; id++)
-+ if (memcmp(id->id, slot_name, 7) == 0)
-+ break;
-+
-+ if (id->id[0])
-+ pnp_init_one(dev, id, slot_name);
-+ else
-+ pnp_init_one(dev, NULL, slot_name);
-+ }
-+
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Leaving probe_serial_pnp() (probe finished)\n");
-+#endif
-+}
-+
-+static int __init serial8250_pnp_init(void)
-+{
-+ if (!isapnp_present()) {
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Leaving probe_serial_pnp() (no isapnp)\n");
-+#endif
-+ return -ENODEV;
-+ }
-+ pnp_init();
-+ return 0;
-+}
-+
-+static void __exit serial8250_pnp_exit(void)
-+{
-+ struct pci_dev *dev = NULL;
-+
-+ isapnp_for_each_dev(dev) {
-+ if (dev->driver != (void *)pnp_dev_table)
-+ continue;
-+ pnp_remove_one(dev);
-+ }
-+}
-+
-+module_init(serial8250_pnp_init);
-+module_exit(serial8250_pnp_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
-+MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,91 @@
-+#
-+# Serial device configuration
-+#
-+# $Id: Config.in,v 1.4 2001/10/12 15:46:58 rmk Exp $
-+#
-+mainmenu_option next_comment
-+comment 'Serial drivers'
-+
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ # I don't have this in my tree yet.
-+ dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN
-+ dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN
-+ if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then
-+ int ' Default Anakin serial baudrate' CONFIG_ANAKIN_DEFAULT_BAUDRATE 9600
-+ fi
-+
-+ dep_tristate 'ARM AMBA serial port support' CONFIG_SERIAL_AMBA $CONFIG_ARCH_INTEGRATOR
-+ dep_bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE $CONFIG_SERIAL_AMBA
-+ if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then
-+ define_bool CONFIG_SERIAL_INTEGRATOR y
-+ fi
-+
-+ dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X
-+ dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X
-+
-+ dep_bool 'DC21285 serial port support' CONFIG_SERIAL_21285 $CONFIG_FOOTBRIDGE
-+ dep_bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD $CONFIG_SERIAL_21285 $CONFIG_OBSOLETE
-+ dep_bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE $CONFIG_SERIAL_21285
-+
-+ dep_bool 'Excalibur serial port (uart00) support' CONFIG_SERIAL_UART00 $CONFIG_ARCH_CAMELOT
-+ dep_bool ' Support for console on Excalibur serial port' CONFIG_SERIAL_UART00_CONSOLE $CONFIG_SERIAL_UART00
-+
-+
-+ dep_bool 'SA1100 serial port support' CONFIG_SERIAL_SA1100 $CONFIG_ARCH_SA1100
-+ dep_bool ' Console on SA1100 serial port' CONFIG_SERIAL_SA1100_CONSOLE $CONFIG_SERIAL_SA1100
-+ if [ "$CONFIG_SERIAL_SA1100" = "y" ]; then
-+ int ' Default SA1100 serial baudrate' CONFIG_SA1100_DEFAULT_BAUDRATE 9600
-+ fi
-+
-+ dep_tristate 'ARM Omaha serial port support' CONFIG_SERIAL_OMAHA $CONFIG_ARCH_OMAHA
-+ dep_bool ' Support for console on Omaha serial port' CONFIG_SERIAL_OMAHA_CONSOLE $CONFIG_SERIAL_OMAHA
-+
-+ dep_tristate 'AT91RM9200 serial port support' CONFIG_SERIAL_AT91 $CONFIG_ARCH_AT91RM9200
-+ dep_bool ' Console on AT91RM9200 serial port' CONFIG_SERIAL_AT91_CONSOLE $CONFIG_SERIAL_AT91
-+
-+fi
-+#
-+# The new 8250/16550 serial drivers
-+dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
-+dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
-+
-+dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250
-+dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support for sharing serial interrupts' CONFIG_SERIAL_8250_SHARE_IRQ $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_8250_DETECT_IRQ $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support special multiport boards' CONFIG_SERIAL_8250_MULTIPORT $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support Bell Technologies HUB6 card' CONFIG_SERIAL_8250_HUB6 $CONFIG_SERIAL_8250_EXTENDED
-+
-+if [ "$CONFIG_SERIAL_AMBA" = "y" -o \
-+ "$CONFIG_SERIAL_CLPS711X" = "y" -o \
-+ "$CONFIG_SERIAL_SA1100" = "y" -o \
-+ "$CONFIG_SERIAL_ANAKIN" = "y" -o \
-+ "$CONFIG_SERIAL_UART00" = "y" -o \
-+ "$CONFIG_SERIAL_8250" = "y" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "y" -o \
-+ "$CONFIG_SERIAL_AT91" = "y" ]; then
-+ define_bool CONFIG_SERIAL_CORE y
-+else
-+ if [ "$CONFIG_SERIAL_AMBA" = "m" -o \
-+ "$CONFIG_SERIAL_CLPS711X" = "m" -o \
-+ "$CONFIG_SERIAL_SA1100" = "m" -o \
-+ "$CONFIG_SERIAL_ANAKIN" = "m" -o \
-+ "$CONFIG_SERIAL_UART00" = "m" -o \
-+ "$CONFIG_SERIAL_8250" = "m" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "m" -o \
-+ "$CONFIG_SERIAL_AT91" = "m" ]; then
-+ define_bool CONFIG_SERIAL_CORE m
-+ fi
-+fi
-+if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_UART00_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_8250_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "y" -o \
-+ "$CONFIG_SERIAL_AT91_CONSOLE" = "y" ]; then
-+ define_bool CONFIG_SERIAL_CORE_CONSOLE y
-+fi
-+
-+endmenu
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,39 @@
-+#
-+# Makefile for the kernel serial device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definitions are now inherited from the
-+# parent makes..
-+#
-+# $Id: Makefile,v 1.2 2001/10/12 15:46:58 rmk Exp $
-+#
-+
-+O_TARGET := serial.o
-+
-+export-objs := core.o 8250.o
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+serial-8250-y :=
-+serial-8250-$(CONFIG_PCI) += 8250_pci.o
-+serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o
-+obj-$(CONFIG_SERIAL_CORE) += core.o
-+obj-$(CONFIG_SERIAL_21285) += 21285.o
-+obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
-+obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
-+obj-$(CONFIG_SERIAL_AMBA) += amba.o
-+obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-+obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
-+obj-$(CONFIG_SERIAL_UART00) += uart00.o
-+obj-$(CONFIG_SERIAL_OMAHA) += omaha.o
-+obj-$(CONFIG_SERIAL_AT91US3) += at91us3.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastdep:
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/amba.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,770 @@
-+/*
-+ * linux/drivers/char/serial_amba.c
-+ *
-+ * Driver for AMBA serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: amba.c,v 1.9.2.2 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ * This is a generic driver for ARM AMBA-type serial ports. They
-+ * have a lot of 16550-like features, but are not register compatable.
-+ * Note that although they do have CTS, DCD and DSR inputs, they do
-+ * not have an RI input, nor do they have DTR or RTS outputs. If
-+ * required, these have to be supplied via some other means (eg, GPIO)
-+ * and hooked into this driver.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/serial_amba.h>
-+
-+#define UART_NR 2
-+
-+#define SERIAL_AMBA_MAJOR 204
-+#define SERIAL_AMBA_MINOR 16
-+#define SERIAL_AMBA_NR UART_NR
-+
-+#define CALLOUT_AMBA_NAME "cuaam"
-+#define CALLOUT_AMBA_MAJOR 205
-+#define CALLOUT_AMBA_MINOR 16
-+#define CALLOUT_AMBA_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *amba_table[UART_NR];
-+static struct termios *amba_termios[UART_NR], *amba_termios_locked[UART_NR];
-+#ifdef SUPPORT_SYSRQ
-+static struct console amba_console;
-+#endif
-+
-+#define AMBA_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the AMBA UARTs
-+ */
-+#define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR)
-+#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR)
-+#define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR)
-+#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR)
-+#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR)
-+#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR)
-+#define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR)
-+#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR)
-+#define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L)
-+#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L)
-+#define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M)
-+#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M)
-+#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H)
-+#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H)
-+#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
-+#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
-+#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
-+
-+#define UART_DUMMY_RSR_RX 256
-+#define UART_PORT_SIZE 64
-+
-+/*
-+ * On the Integrator platform, the port RTS and DTR are provided by
-+ * bits in the following SC_CTRLS register bits:
-+ * RTS DTR
-+ * UART0 7 6
-+ * UART1 5 4
-+ */
-+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
-+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
-+
-+/*
-+ * We wrap our port structure around the generic uart_port.
-+ */
-+struct uart_amba_port {
-+ struct uart_port port;
-+ unsigned int dtr_mask;
-+ unsigned int rts_mask;
-+ unsigned int old_status;
-+};
-+
-+static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr &= ~AMBA_UARTCR_TIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr |= AMBA_UARTCR_TIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_stop_rx(struct uart_port *port)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_enable_ms(struct uart_port *port)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr |= AMBA_UARTCR_MSIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void
-+#ifdef SUPPORT_SYSRQ
-+ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+#else
-+ambauart_rx_chars(struct uart_port *port)
-+#endif
-+{
-+ struct tty_struct *tty = port->info->tty;
-+ unsigned int status, ch, rsr, max_count = 256;
-+
-+ status = UART_GET_FR(port);
-+ while (UART_RX_DATA(status) && max_count--) {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-+ return;
-+ }
-+ }
-+
-+ ch = UART_GET_CHAR(port);
-+
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ port->icount.rx++;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
-+ if (rsr & AMBA_UARTRSR_ANY) {
-+ if (rsr & AMBA_UARTRSR_BE) {
-+ rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
-+ port->icount.brk++;
-+ if (uart_handle_break(port))
-+ goto ignore_char;
-+ } else if (rsr & AMBA_UARTRSR_PE)
-+ port->icount.parity++;
-+ else if (rsr & AMBA_UARTRSR_FE)
-+ port->icount.frame++;
-+ if (rsr & AMBA_UARTRSR_OE)
-+ port->icount.overrun++;
-+
-+ rsr &= port->read_status_mask;
-+
-+ if (rsr & AMBA_UARTRSR_BE)
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ else if (rsr & AMBA_UARTRSR_PE)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (rsr & AMBA_UARTRSR_FE)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ if ((rsr & port->ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((rsr & AMBA_UARTRSR_OE) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character
-+ */
-+ *tty->flip.char_buf_ptr++ = 0;
-+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ status = UART_GET_FR(port);
-+ }
-+ tty_flip_buffer_push(tty);
-+ return;
-+}
-+
-+static void ambauart_tx_chars(struct uart_port *port)
-+{
-+ struct circ_buf *xmit = &port->info->xmit;
-+ int count;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ ambauart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ ambauart_stop_tx(port, 0);
-+}
-+
-+static void ambauart_modem_status(struct uart_port *port)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ unsigned int status, delta;
-+
-+ UART_PUT_ICR(&uap->port, 0);
-+
-+ status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
-+
-+ delta = status ^ uap->old_status;
-+ uap->old_status = status;
-+
-+ if (!delta)
-+ return;
-+
-+ if (delta & AMBA_UARTFR_DCD)
-+ uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD);
-+
-+ if (delta & AMBA_UARTFR_DSR)
-+ uap->port.icount.dsr++;
-+
-+ if (delta & AMBA_UARTFR_CTS)
-+ uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS);
-+
-+ wake_up_interruptible(&uap->port.info->delta_msr_wait);
-+}
-+
-+static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ do {
-+ if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
-+#ifdef SUPPORT_SYSRQ
-+ ambauart_rx_chars(port, regs);
-+#else
-+ ambauart_rx_chars(port);
-+#endif
-+ if (status & AMBA_UARTIIR_TIS)
-+ ambauart_tx_chars(port);
-+ if (status & AMBA_UARTIIR_MIS)
-+ ambauart_modem_status(port);
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
-+ AMBA_UARTIIR_TIS));
-+}
-+
-+static unsigned int ambauart_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int ambauart_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ status = UART_GET_FR(port);
-+ if (status & AMBA_UARTFR_DCD)
-+ result |= TIOCM_CAR;
-+ if (status & AMBA_UARTFR_DSR)
-+ result |= TIOCM_DSR;
-+ if (status & AMBA_UARTFR_CTS)
-+ result |= TIOCM_CTS;
-+
-+ return result;
-+}
-+
-+static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ unsigned int ctrls = 0, ctrlc = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ ctrlc |= uap->rts_mask;
-+ else
-+ ctrls |= uap->rts_mask;
-+
-+ if (mctrl & TIOCM_DTR)
-+ ctrlc |= uap->dtr_mask;
-+ else
-+ ctrls |= uap->dtr_mask;
-+
-+ __raw_writel(ctrls, SC_CTRLS);
-+ __raw_writel(ctrlc, SC_CTRLC);
-+}
-+
-+static void ambauart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned long flags;
-+ unsigned int lcr_h;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ lcr_h = UART_GET_LCRH(port);
-+ if (break_state == -1)
-+ lcr_h |= AMBA_UARTLCR_H_BRK;
-+ else
-+ lcr_h &= ~AMBA_UARTLCR_H_BRK;
-+ UART_PUT_LCRH(port, lcr_h);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static int ambauart_startup(struct uart_port *port)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, ambauart_int, 0, "amba", port);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
-+
-+ /*
-+ * Finally, enable interrupts
-+ */
-+ UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE |
-+ AMBA_UARTCR_RTIE);
-+
-+ return 0;
-+}
-+
-+static void ambauart_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ UART_PUT_CR(port, 0);
-+
-+ /* disable break condition and fifos */
-+ UART_PUT_LCRH(port, UART_GET_LCRH(port) &
-+ ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
-+}
-+
-+static void ambauart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ unsigned int lcr_h, old_cr;
-+ unsigned long flags;
-+
-+#if DEBUG
-+ printk("ambauart_set_cflag(0x%x) called\n", cflag);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_5;
-+ break;
-+ case CS6:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_6;
-+ break;
-+ case CS7:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_7;
-+ break;
-+ default: // CS8
-+ lcr_h = AMBA_UARTLCR_H_WLEN_8;
-+ break;
-+ }
-+ if (cflag & CSTOPB)
-+ lcr_h |= AMBA_UARTLCR_H_STP2;
-+ if (cflag & PARENB) {
-+ lcr_h |= AMBA_UARTLCR_H_PEN;
-+ if (!(cflag & PARODD))
-+ lcr_h |= AMBA_UARTLCR_H_EPS;
-+ }
-+ if (port->fifosize > 1)
-+ lcr_h |= AMBA_UARTLCR_H_FEN;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+
-+ port->read_status_mask = AMBA_UARTRSR_OE;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= AMBA_UARTRSR_BE;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= AMBA_UARTRSR_BE;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AMBA_UARTRSR_OE;
-+ }
-+
-+ /*
-+ * Ignore all characters if CREAD is not set.
-+ */
-+ if ((cflag & CREAD) == 0)
-+ port->ignore_status_mask |= UART_DUMMY_RSR_RX;
-+
-+ old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
-+
-+ if (UART_ENABLE_MS(port, cflag))
-+ old_cr |= AMBA_UARTCR_MSIE;
-+
-+ UART_PUT_CR(port, 0);
-+
-+ /* Set baud rate */
-+ quot -= 1;
-+ UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
-+ UART_PUT_LCRL(port, (quot & 0xff));
-+
-+ /*
-+ * ----------v----------v----------v----------v-----
-+ * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
-+ * ----------^----------^----------^----------^-----
-+ */
-+ UART_PUT_LCRH(port, lcr_h);
-+ UART_PUT_CR(port, old_cr);
-+
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static const char *ambauart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_AMBA ? "AMBA" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void ambauart_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int ambauart_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba")
-+ != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void ambauart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_AMBA;
-+ ambauart_request_port(port);
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops amba_pops = {
-+ .tx_empty = ambauart_tx_empty,
-+ .set_mctrl = ambauart_set_mctrl,
-+ .get_mctrl = ambauart_get_mctrl,
-+ .stop_tx = ambauart_stop_tx,
-+ .start_tx = ambauart_start_tx,
-+ .stop_rx = ambauart_stop_rx,
-+ .enable_ms = ambauart_enable_ms,
-+ .break_ctl = ambauart_break_ctl,
-+ .startup = ambauart_startup,
-+ .shutdown = ambauart_shutdown,
-+ .change_speed = ambauart_change_speed,
-+ .type = ambauart_type,
-+ .release_port = ambauart_release_port,
-+ .request_port = ambauart_request_port,
-+ .config_port = ambauart_config_port,
-+ .verify_port = ambauart_verify_port,
-+};
-+
-+static struct uart_amba_port amba_ports[UART_NR] = {
-+ {
-+ .port = {
-+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
-+ .mapbase = INTEGRATOR_UART0_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UARTINT0,
-+ .uartclk = 14745600,
-+ .fifosize = 16,
-+ .ops = &amba_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ .line = 0,
-+ },
-+ .dtr_mask = 1 << 5,
-+ .rts_mask = 1 << 4,
-+ },
-+ {
-+ .port = {
-+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
-+ .mapbase = INTEGRATOR_UART1_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UARTINT1,
-+ .uartclk = 14745600,
-+ .fifosize = 16,
-+ .ops = &amba_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ .line = 1,
-+ },
-+ .dtr_mask = 1 << 7,
-+ .rts_mask = 1 << 6,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-+
-+static void ambauart_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct uart_port *port = &amba_ports[co->index].port;
-+ unsigned int status, old_cr;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+ old_cr = UART_GET_CR(port);
-+ UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the TCR
-+ */
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (status & AMBA_UARTFR_BUSY);
-+ UART_PUT_CR(port, old_cr);
-+}
-+
-+static kdev_t ambauart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index);
-+}
-+
-+static void __init
-+ambauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) {
-+ unsigned int lcr_h, quot;
-+ lcr_h = UART_GET_LCRH(port);
-+
-+ *parity = 'n';
-+ if (lcr_h & AMBA_UARTLCR_H_PEN) {
-+ if (lcr_h & AMBA_UARTLCR_H_EPS)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7)
-+ *bits = 7;
-+ else
-+ *bits = 8;
-+
-+ quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
-+ *baud = port->uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init ambauart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index >= UART_NR)
-+ co->index = 0;
-+ port = &amba_ports[co->index].port;
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ ambauart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console amba_console = {
-+ .name = "ttyAM",
-+ .write = ambauart_console_write,
-+ .device = ambauart_console_device,
-+ .setup = ambauart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init ambauart_console_init(void)
-+{
-+ register_console(&amba_console);
-+}
-+
-+#define AMBA_CONSOLE &amba_console
-+#else
-+#define AMBA_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver amba_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_AMBA_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttyAM%d",
-+ .callout_name = "cuaam%d",
-+#else
-+ .normal_name = "ttyAM",
-+ .callout_name = "cuaam",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_AMBA_MAJOR,
-+ .callout_driver = &callout,
-+ .table = amba_table,
-+ .termios = amba_termios,
-+ .termios_locked = amba_termios_locked,
-+ .minor = SERIAL_AMBA_MINOR,
-+ .nr = UART_NR,
-+ .cons = AMBA_CONSOLE,
-+};
-+
-+static int __init ambauart_init(void)
-+{
-+ int ret;
-+
-+ ret = uart_register_driver(&amba_reg);
-+ if (ret == 0) {
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_add_one_port(&amba_reg, &amba_ports[i].port);
-+ }
-+ return ret;
-+}
-+
-+static void __exit ambauart_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&amba_reg, &amba_ports[i].port);
-+
-+ uart_unregister_driver(&amba_reg);
-+}
-+
-+module_init(ambauart_init);
-+module_exit(ambauart_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("ARM AMBA serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/anakin.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,545 @@
-+/*
-+ * linux/drivers/char/serial_anakin.c
-+ *
-+ * Based on driver for AMBA serial ports, by ARM Limited,
-+ * Deep Blue Solutions Ltd., Linus Torvalds and Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * Copyright (C) 2001 Blue Mug, Inc. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 20-Apr-2001 TTC Created
-+ * 05-May-2001 W/TTC Updated for serial_core.c
-+ * 27-Jun-2001 jonm Minor changes; add mctrl support, switch to
-+ * SA_INTERRUPT. Works reliably now. No longer requires
-+ * changes to the serial_core API.
-+ *
-+ * $Id: anakin.c,v 1.5.2.2 2002/10/24 09:53:25 rmk Exp $
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/arch/serial_reg.h>
-+
-+#define UART_NR 5
-+
-+#define SERIAL_ANAKIN_NAME "ttyAN"
-+#define SERIAL_ANAKIN_MAJOR 204
-+#define SERIAL_ANAKIN_MINOR 32
-+
-+#define CALLOUT_ANAKIN_NAME "cuaan"
-+#define CALLOUT_ANAKIN_MAJOR 205
-+#define CALLOUT_ANAKIN_MINOR 32
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *anakin_table[UART_NR];
-+static struct termios *anakin_termios[UART_NR], *anakin_termios_locked[UART_NR];
-+static struct uart_state anakin_state[UART_NR];
-+static u_int txenable[NR_IRQS]; /* Software interrupt register */
-+
-+static inline unsigned int
-+anakin_in(struct uart_port *port, u_int offset)
-+{
-+ return __raw_readl(port->base + offset);
-+}
-+
-+static inline void
-+anakin_out(struct uart_port *port, u_int offset, unsigned int value)
-+{
-+ __raw_writel(value, port->base + offset);
-+}
-+
-+static void
-+anakin_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ txenable[port->irq] = 0;
-+}
-+
-+static inline void
-+anakin_transmit_buffer(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x14, info->xmit.buf[info->xmit.tail]);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE-1);
-+ info->state->icount.tx++;
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ anakin_stop_tx(port, 0);
-+}
-+
-+static inline void
-+anakin_transmit_x_char(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+
-+ anakin_out(port, 0x14, info->x_char);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+ info->state->icount.tx++;
-+ info->x_char = 0;
-+}
-+
-+static void
-+anakin_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
-+{
-+ unsigned int flags;
-+
-+ save_flags_cli(flags);
-+
-+ // is it this... or below: if (nonempty
-+ if (!txenable[port->irq]) {
-+ txenable[port->irq] = TXENABLE;
-+
-+ if ((anakin_in(port, 0x10) & TXEMPTY) && nonempty) {
-+ anakin_transmit_buffer((struct uart_info*)port->unused);
-+ }
-+ }
-+
-+ restore_flags(flags);
-+}
-+
-+static void
-+anakin_stop_rx(struct uart_port *port)
-+{
-+ unsigned long flags;
-+
-+ save_flags_cli(flags);
-+ while (anakin_in(port, 0x10) & RXRELEASE)
-+ anakin_in(port, 0x14);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX);
-+ restore_flags(flags);
-+}
-+
-+static void
-+anakin_enable_ms(struct uart_port *port)
-+{
-+}
-+
-+static inline void
-+anakin_rx_chars(struct uart_info *info)
-+{
-+ unsigned int ch;
-+ struct tty_struct *tty = info->tty;
-+
-+ if (!(anakin_in(info->port, 0x10) & RXRELEASE))
-+ return;
-+
-+ ch = anakin_in(info->port, 0x14) & 0xff;
-+
-+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ *tty->flip.char_buf_ptr++ = ch;
-+ *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-+ info->state->icount.rx++;
-+ tty->flip.count++;
-+ }
-+ tty_flip_buffer_push(tty);
-+}
-+
-+static inline void
-+anakin_overrun_chars(struct uart_info *info)
-+{
-+ unsigned int ch;
-+
-+ ch = anakin_in(info->port, 0x14);
-+ info->state->icount.overrun++;
-+}
-+
-+static inline void
-+anakin_tx_chars(struct uart_info *info)
-+{
-+ if (info->x_char) {
-+ anakin_transmit_x_char(info);
-+ return;
-+ }
-+
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ anakin_stop_tx(info->port, 0);
-+ return;
-+ }
-+
-+ anakin_transmit_buffer(info);
-+
-+ if (CIRC_CNT(info->xmit.head,
-+ info->xmit.tail,
-+ UART_XMIT_SIZE) < WAKEUP_CHARS)
-+ uart_event(info, EVT_WRITE_WAKEUP);
-+}
-+
-+static void
-+anakin_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status;
-+ struct uart_info *info = dev_id;
-+
-+ status = anakin_in(info->port, 0x1c);
-+
-+ if (status & RX)
-+ anakin_rx_chars(info);
-+
-+ if (status & OVERRUN)
-+ anakin_overrun_chars(info);
-+
-+ if (txenable[info->port->irq] && (status & TX))
-+ anakin_tx_chars(info);
-+}
-+
-+static u_int
-+anakin_tx_empty(struct uart_port *port)
-+{
-+ return anakin_in(port, 0x10) & TXEMPTY ? TIOCSER_TEMT : 0;
-+}
-+
-+static u_int
-+anakin_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int status = 0;
-+
-+ status |= (anakin_in(port, 0x10) & CTS ? TIOCM_CTS : 0);
-+ status |= (anakin_in(port, 0x18) & DCD ? TIOCM_CAR : 0);
-+ status |= (anakin_in(port, 0x18) & DTR ? TIOCM_DTR : 0);
-+ status |= (anakin_in(port, 0x18) & RTS ? TIOCM_RTS : 0);
-+
-+ return status;
-+}
-+
-+static void
-+anakin_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned int status;
-+
-+ status = anakin_in(port, 0x18);
-+
-+ if (mctrl & TIOCM_RTS)
-+ status |= RTS;
-+ else
-+ status &= ~RTS;
-+
-+ if (mctrl & TIOCM_CAR)
-+ status |= DCD;
-+ else
-+ status &= ~DCD;
-+
-+ anakin_out(port, 0x18, status);
-+}
-+
-+static void
-+anakin_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned int status;
-+
-+ status = anakin_in(port, 0x20);
-+
-+ if (break_state == -1)
-+ status |= SETBREAK;
-+ else
-+ status &= ~SETBREAK;
-+
-+ anakin_out(port, 0x20, status);
-+}
-+
-+static int
-+anakin_startup(struct uart_port *port, struct uart_info *info)
-+{
-+ int retval;
-+ unsigned int read,write;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, anakin_int, SA_INTERRUPT, "serial_anakin", info);
-+ if (retval)
-+ return retval;
-+
-+ port->ops->set_mctrl(port, info->mctrl);
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ port->old_status = 0;
-+
-+ /*
-+ * Finally, disable IRQ and softIRQs for first byte)
-+ */
-+ txenable[port->irq] = 0;
-+ read = anakin_in(port, 0x18);
-+ write = (read & ~(RTS | DTR | BLOCKRX)) | IRQENABLE;
-+ anakin_out(port, 0x18, write);
-+
-+ /* Store the uart_info pointer so we can reference it in
-+ * anakin_start_tx() */
-+ port->unused = (u_int)info;
-+
-+ return 0;
-+}
-+
-+static void
-+anakin_shutdown(struct uart_port *port, struct uart_info *info)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, info);
-+
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) & ~IRQENABLE);
-+}
-+
-+static void
-+anakin_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ unsigned int flags;
-+
-+ save_flags_cli(flags);
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x10, (anakin_in(port, 0x10) & ~PRESCALER)
-+ | (quot << 3));
-+
-+ //parity always set to none
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) & ~PARITY);
-+ restore_flags(flags);
-+}
-+
-+static const char *anakin_type(struct port *port)
-+{
-+ return port->type == PORT_ANAKIN ? "ANAKIN" : NULL;
-+}
-+
-+static struct uart_ops anakin_pops = {
-+ tx_empty: anakin_tx_empty,
-+ set_mctrl: anakin_set_mctrl,
-+ get_mctrl: anakin_get_mctrl,
-+ stop_tx: anakin_stop_tx,
-+ start_tx: anakin_start_tx,
-+ stop_rx: anakin_stop_rx,
-+ enable_ms: anakin_enable_ms,
-+ break_ctl: anakin_break_ctl,
-+ startup: anakin_startup,
-+ shutdown: anakin_shutdown,
-+ change_speed: anakin_change_speed,
-+ type: anakin_type,
-+};
-+
-+static struct uart_port anakin_ports[UART_NR] = {
-+ {
-+ base: IO_BASE + UART0,
-+ irq: IRQ_UART0,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART1,
-+ irq: IRQ_UART1,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART2,
-+ irq: IRQ_UART2,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART3,
-+ irq: IRQ_UART3,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART4,
-+ irq: IRQ_UART4,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+};
-+
-+
-+#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-+
-+static void
-+anakin_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = anakin_ports + co->index;
-+ unsigned int flags, status, i;
-+
-+ /*
-+ * First save the status then disable the interrupts
-+ */
-+ save_flags_cli(flags);
-+ status = anakin_in(port, 0x18);
-+ anakin_out(port, 0x18, status & ~IRQENABLE);
-+ restore_flags(flags);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++, s++) {
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+
-+ /*
-+ * Send the character out.
-+ * If a LF, also do CR...
-+ */
-+ anakin_out(port, 0x14, *s);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+
-+ if (*s == 10) {
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x14, 13);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18)
-+ | SENDREQUEST);
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the interrupts
-+ */
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+
-+ if (status & IRQENABLE)
-+ save_flags_cli(flags);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE);
-+ restore_flags(flags);
-+}
-+
-+static kdev_t
-+anakin_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR + co->index);
-+}
-+
-+/*
-+ * Read the current UART setup.
-+ */
-+static void __init
-+anakin_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ int paritycode;
-+
-+ *baud = GETBAUD (anakin_in(port, 0x10) & PRESCALER);
-+ paritycode = GETPARITY(anakin_in(port, 0x18) & PARITY);
-+ switch (paritycode) {
-+ case NONEPARITY: *parity = 'n'; break;
-+ case ODDPARITY: *parity = 'o'; break;
-+ case EVENPARITY: *parity = 'e'; break;
-+ }
-+ *bits = 8;
-+}
-+
-+static int __init
-+anakin_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = CONFIG_ANAKIN_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(anakin_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits);
-+ else
-+ anakin_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits);
-+}
-+
-+static struct console anakin_console = {
-+ name: SERIAL_ANAKIN_NAME,
-+ write: anakin_console_write,
-+ device: anakin_console_device,
-+ setup: anakin_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+void __init
-+anakin_console_init(void)
-+{
-+ register_console(&anakin_console);
-+}
-+
-+#define ANAKIN_CONSOLE &anakin_console
-+#else
-+#define ANAKIN_CONSOLE NULL
-+#endif
-+
-+static struct uart_register anakin_reg = {
-+ normal_major: SERIAL_ANAKIN_MAJOR,
-+ normal_name: SERIAL_ANAKIN_NAME,
-+ normal_driver: &normal,
-+ callout_major: CALLOUT_ANAKIN_MAJOR,
-+ callout_name: CALLOUT_ANAKIN_NAME,
-+ callout_driver: &callout,
-+ table: anakin_table,
-+ termios: anakin_termios,
-+ termios_locked: anakin_termios_locked,
-+ minor: SERIAL_ANAKIN_MINOR,
-+ nr: UART_NR,
-+ state: anakin_state,
-+ port: anakin_ports,
-+ cons: ANAKIN_CONSOLE,
-+};
-+
-+static int __init
-+anakin_init(void)
-+{
-+ return uart_register_port(&anakin_reg);
-+}
-+
-+__initcall(anakin_init);
-+
-+MODULE_DESCRIPTION("Anakin serial driver");
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_SUPPORTED_DEVICE("ttyAN");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/clps711x.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,635 @@
-+/*
-+ * linux/drivers/char/serial_clps711x.c
-+ *
-+ * Driver for CLPS711x serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: clps711x.c,v 1.12.2.2 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/clps7111.h>
-+
-+#define UART_NR 2
-+
-+#define SERIAL_CLPS711X_NAME "ttyAM"
-+#define SERIAL_CLPS711X_MAJOR 204
-+#define SERIAL_CLPS711X_MINOR 16
-+#define SERIAL_CLPS711X_NR UART_NR
-+
-+#define CALLOUT_CLPS711X_NAME "cuaam"
-+#define CALLOUT_CLPS711X_MAJOR 205
-+#define CALLOUT_CLPS711X_MINOR 16
-+#define CALLOUT_CLPS711X_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *clps711x_table[UART_NR];
-+static struct termios *clps711x_termios[UART_NR], *clps711x_termios_locked[UART_NR];
-+
-+/*
-+ * We use the relevant SYSCON register as a base address for these ports.
-+ */
-+#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
-+#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
-+#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
-+#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
-+
-+#define TX_IRQ(port) ((port)->irq)
-+#define RX_IRQ(port) ((port)->irq + 1)
-+
-+#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-+
-+#define tx_enabled(port) ((port)->unused[0])
-+
-+static void
-+clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ if (tx_enabled(port)) {
-+ disable_irq(TX_IRQ(port));
-+ tx_enabled(port) = 0;
-+ }
-+}
-+
-+static void
-+clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ if (!tx_enabled(port)) {
-+ enable_irq(TX_IRQ(port));
-+ tx_enabled(port) = 1;
-+ }
-+}
-+
-+static void clps711xuart_stop_rx(struct uart_port *port)
-+{
-+ disable_irq(RX_IRQ(port));
-+}
-+
-+static void clps711xuart_enable_ms(struct uart_port *port)
-+{
-+}
-+
-+static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ struct tty_struct *tty = port->info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = clps_readl(SYSFLG(port));
-+ while (!(status & SYSFLG_URXFE)) {
-+ ch = clps_readl(UARTDR(port));
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ port->icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (ch & UART_ANY_ERR)
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = clps_readl(SYSFLG(port));
-+ }
-+ out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+ handle_error:
-+ if (ch & UARTDR_PARERR)
-+ port->icount.parity++;
-+ else if (ch & UARTDR_FRMERR)
-+ port->icount.frame++;
-+ if (ch & UARTDR_OVERR)
-+ port->icount.overrun++;
-+
-+ if (ch & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+ ch &= port->read_status_mask;
-+
-+ if (ch & UARTDR_PARERR)
-+ flg = TTY_PARITY;
-+ else if (ch & UARTDR_FRMERR)
-+ flg = TTY_FRAME;
-+
-+ if (ch & UARTDR_OVERR) {
-+ /*
-+ * CHECK: does overrun affect the current character?
-+ * ASSUMPTION: it does not.
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ struct circ_buf *xmit = &port->info->xmit;
-+ int count;
-+
-+ if (port->x_char) {
-+ clps_writel(port->x_char, UARTDR(port));
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ clps711xuart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ clps_writel(xmit->buf[xmit->tail], UARTDR(port));
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ clps711xuart_stop_tx(port, 0);
-+}
-+
-+static unsigned int clps711xuart_tx_empty(struct uart_port *port)
-+{
-+ unsigned int status = clps_readl(SYSFLG(port));
-+ return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int port_addr;
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ port_addr = SYSFLG(port);
-+ if (port_addr == SYSFLG1) {
-+ status = clps_readl(SYSFLG1);
-+ if (status & SYSFLG1_DCD)
-+ result |= TIOCM_CAR;
-+ if (status & SYSFLG1_DSR)
-+ result |= TIOCM_DSR;
-+ if (status & SYSFLG1_CTS)
-+ result |= TIOCM_CTS;
-+ }
-+
-+ return result;
-+}
-+
-+static void
-+clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
-+{
-+}
-+
-+static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned long flags;
-+ unsigned int ubrlcr;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ ubrlcr = clps_readl(UBRLCR(port));
-+ if (break_state == -1)
-+ ubrlcr |= UBRLCR_BREAK;
-+ else
-+ ubrlcr &= ~UBRLCR_BREAK;
-+ clps_writel(ubrlcr, UBRLCR(port));
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static int clps711xuart_startup(struct uart_port *port)
-+{
-+ unsigned int syscon;
-+ int retval;
-+
-+ tx_enabled(port) = 1;
-+
-+ /*
-+ * Allocate the IRQs
-+ */
-+ retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
-+ "clps711xuart_tx", port);
-+ if (retval)
-+ return retval;
-+
-+ retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
-+ "clps711xuart_rx", port);
-+ if (retval) {
-+ free_irq(TX_IRQ(port), port);
-+ return retval;
-+ }
-+
-+ /*
-+ * enable the port
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ syscon |= SYSCON_UARTEN;
-+ clps_writel(syscon, SYSCON(port));
-+
-+ return 0;
-+}
-+
-+static void clps711xuart_shutdown(struct uart_port *port)
-+{
-+ unsigned int ubrlcr, syscon;
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(TX_IRQ(port), port); /* TX interrupt */
-+ free_irq(RX_IRQ(port), port); /* RX interrupt */
-+
-+ /*
-+ * disable the port
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ syscon &= ~SYSCON_UARTEN;
-+ clps_writel(syscon, SYSCON(port));
-+
-+ /*
-+ * disable break condition and fifos
-+ */
-+ ubrlcr = clps_readl(UBRLCR(port));
-+ ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
-+ clps_writel(ubrlcr, UBRLCR(port));
-+}
-+
-+static void clps711xuart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ unsigned int ubrlcr;
-+ unsigned long flags;
-+
-+#if DEBUG
-+ printk("clps711xuart_change_speed(cflag=0x%x, iflag=0x%x, quot=%d) called\n",
-+ cflag, iflag, quot);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ ubrlcr = UBRLCR_WRDLEN5;
-+ break;
-+ case CS6:
-+ ubrlcr = UBRLCR_WRDLEN6;
-+ break;
-+ case CS7:
-+ ubrlcr = UBRLCR_WRDLEN7;
-+ break;
-+ default: // CS8
-+ ubrlcr = UBRLCR_WRDLEN8;
-+ break;
-+ }
-+ if (cflag & CSTOPB)
-+ ubrlcr |= UBRLCR_XSTOP;
-+ if (cflag & PARENB) {
-+ ubrlcr |= UBRLCR_PRTEN;
-+ if (!(cflag & PARODD))
-+ ubrlcr |= UBRLCR_EVENPRT;
-+ }
-+ if (port->fifosize > 1)
-+ ubrlcr |= UBRLCR_FIFOEN;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+
-+ port->read_status_mask = UARTDR_OVERR;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
-+ if (iflag & IGNBRK) {
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns to (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UARTDR_OVERR;
-+ }
-+
-+ quot -= 1;
-+
-+ clps_writel(ubrlcr | quot, UBRLCR(port));
-+
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static const char *clps711xuart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void clps711xuart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE)
-+ port->type = PORT_CLPS711X;
-+}
-+
-+static void clps711xuart_release_port(struct uart_port *port)
-+{
-+}
-+
-+static int clps711xuart_request_port(struct uart_port *port)
-+{
-+ return 0;
-+}
-+
-+static struct uart_ops clps711x_pops = {
-+ .tx_empty = clps711xuart_tx_empty,
-+ .set_mctrl = clps711xuart_set_mctrl_null,
-+ .get_mctrl = clps711xuart_get_mctrl,
-+ .stop_tx = clps711xuart_stop_tx,
-+ .start_tx = clps711xuart_start_tx,
-+ .stop_rx = clps711xuart_stop_rx,
-+ .enable_ms = clps711xuart_enable_ms,
-+ .break_ctl = clps711xuart_break_ctl,
-+ .startup = clps711xuart_startup,
-+ .shutdown = clps711xuart_shutdown,
-+ .change_speed = clps711xuart_change_speed,
-+ .type = clps711xuart_type,
-+ .config_port = clps711xuart_config_port,
-+ .release_port = clps711xuart_release_port,
-+ .request_port = clps711xuart_request_port,
-+};
-+
-+static struct uart_port clps711x_ports[UART_NR] = {
-+ {
-+ .iobase = SYSCON1,
-+ .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
-+ .uartclk = 3686400,
-+ .fifosize = 16,
-+ .ops = &clps711x_pops,
-+ .line = 0,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ },
-+ {
-+ .iobase = SYSCON2,
-+ .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
-+ .uartclk = 3686400,
-+ .fifosize = 16,
-+ .ops = &clps711x_pops,
-+ .line = 1,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-+/*
-+ * Print a string to the serial port trying not to disturb
-+ * any possible real use of the port...
-+ *
-+ * The console_lock must be held when we get here.
-+ *
-+ * Note that this is called with interrupts already disabled
-+ */
-+static void
-+clps711xuart_console_write(struct console *co, const char *s,
-+ unsigned int count)
-+{
-+ struct uart_port *port = clps711x_ports + co->index;
-+ unsigned int status, syscon;
-+ int i;
-+
-+ /*
-+ * Ensure that the port is enabled.
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UTXFF);
-+ clps_writel(s[i], UARTDR(port));
-+ if (s[i] == '\n') {
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UTXFF);
-+ clps_writel('\r', UARTDR(port));
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the uart state.
-+ */
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UBUSY);
-+
-+ clps_writel(syscon, SYSCON(port));
-+}
-+
-+static kdev_t clps711xuart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index);
-+}
-+
-+static void __init
-+clps711xuart_console_get_options(struct uart_port *port, int *baud,
-+ int *parity, int *bits)
-+{
-+ if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
-+ unsigned int ubrlcr, quot;
-+
-+ ubrlcr = clps_readl(UBRLCR(port));
-+
-+ *parity = 'n';
-+ if (ubrlcr & UBRLCR_PRTEN) {
-+ if (ubrlcr & UBRLCR_EVENPRT)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
-+ *bits = 7;
-+ else
-+ *bits = 8;
-+
-+ quot = ubrlcr & UBRLCR_BAUD_MASK;
-+ *baud = port->uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init clps711xuart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(clps711x_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ clps711xuart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console clps711x_console = {
-+ .name = SERIAL_CLPS711X_NAME,
-+ .write = clps711xuart_console_write,
-+ .device = clps711xuart_console_device,
-+ .setup = clps711xuart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init clps711xuart_console_init(void)
-+{
-+ register_console(&clps711x_console);
-+}
-+
-+#define CLPS711X_CONSOLE &clps711x_console
-+#else
-+#define CLPS711X_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver clps711x_reg = {
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = SERIAL_CLPS711X_NAME,
-+ .callout_name = CALLOUT_CLPS711X_NAME,
-+#else
-+ .normal_name = SERIAL_CLPS711X_NAME,
-+ .callout_name = CALLOUT_CLPS711X_NAME,
-+#endif
-+
-+ .normal_major = SERIAL_CLPS711X_MAJOR,
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_CLPS711X_MAJOR,
-+ .callout_driver = &callout,
-+
-+ .table = clps711x_table,
-+ .termios = clps711x_termios,
-+ .termios_locked = clps711x_termios_locked,
-+
-+ .minor = SERIAL_CLPS711X_MINOR,
-+ .nr = UART_NR,
-+
-+ .cons = CLPS711X_CONSOLE,
-+};
-+
-+static int __init clps711xuart_init(void)
-+{
-+ int ret, i;
-+
-+ printk(KERN_INFO "Serial: CLPS711x driver\n");
-+
-+ ret = uart_register_driver(&clps711x_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
-+
-+ return 0;
-+}
-+
-+static void __exit clps711xuart_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
-+
-+ uart_unregister_driver(&clps711x_reg);
-+}
-+
-+module_init(clps711xuart_init);
-+module_exit(clps711xuart_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("CLPS-711x generic serial driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,2584 @@
-+/*
-+ * linux/drivers/serial/core.c
-+ *
-+ * Driver core for serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: core.c,v 1.20.2.5 2002/03/13 15:22:26 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/tty.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/pm.h>
-+#include <linux/serial_core.h>
-+#include <linux/smp_lock.h>
-+
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK(x...) printk(x)
-+#else
-+#define DPRINTK(x...) do { } while (0)
-+#endif
-+
-+#ifndef CONFIG_PM
-+#define pm_access(pm) do { } while (0)
-+#define pm_unregister(pm) do { } while (0)
-+#endif
-+
-+/*
-+ * This is used to lock changes in serial line configuration.
-+ */
-+static DECLARE_MUTEX(port_sem);
-+
-+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-+
-+#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
-+
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
-+#else
-+#define uart_console(port) (0)
-+#endif
-+
-+static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
-+static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
-+static void uart_change_pm(struct uart_state *state, int pm_state);
-+
-+/*
-+ * This routine is used by the interrupt handler to schedule processing in
-+ * the software interrupt portion of the driver.
-+ */
-+void uart_write_wakeup(struct uart_port *port)
-+{
-+ struct uart_info *info = port->info;
-+ tasklet_schedule(&info->tlet);
-+}
-+
-+static void uart_stop(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->stop_tx(port, 1);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void __uart_start(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
-+ !tty->stopped && !tty->hw_stopped)
-+ port->ops->start_tx(port, 1);
-+}
-+
-+static void uart_start(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ pm_access(state->pm);
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ __uart_start(tty);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void uart_tasklet_action(unsigned long data)
-+{
-+ struct uart_state *state = (struct uart_state *)data;
-+ struct tty_struct *tty;
-+
-+ tty = state->info->tty;
-+ if (tty) {
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-+ tty->ldisc.write_wakeup)
-+ tty->ldisc.write_wakeup(tty);
-+ wake_up_interruptible(&tty->write_wait);
-+ }
-+}
-+
-+static inline void
-+uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
-+{
-+ unsigned long flags;
-+ unsigned int old;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ old = port->mctrl;
-+ port->mctrl = (old & ~clear) | set;
-+ if (old != port->mctrl)
-+ port->ops->set_mctrl(port, port->mctrl);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0)
-+#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear)
-+
-+static inline unsigned int uart_get_altspeed(struct uart_port *port)
-+{
-+ unsigned int flags = port->flags & UPF_SPD_MASK;
-+ unsigned int altbaud = 0;
-+
-+ if (flags == ASYNC_SPD_HI)
-+ altbaud = 57600;
-+ if (flags == ASYNC_SPD_VHI)
-+ altbaud = 115200;
-+ if (flags == ASYNC_SPD_SHI)
-+ altbaud = 230400;
-+ if (flags == ASYNC_SPD_WARP)
-+ altbaud = 460800;
-+
-+ return altbaud;
-+}
-+
-+/*
-+ * Startup the port. This will be called once per open. All calls
-+ * will be serialised by the per-port semaphore.
-+ */
-+static int uart_startup(struct uart_state *state, int init_hw)
-+{
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+ unsigned long page;
-+ int retval = 0;
-+
-+ if (info->flags & UIF_INITIALIZED)
-+ return 0;
-+
-+ /*
-+ * Set the TTY IO error marker - we will only clear this
-+ * once we have successfully opened the port. Also set
-+ * up the tty->alt_speed kludge
-+ */
-+ if (info->tty)
-+ set_bit(TTY_IO_ERROR, &info->tty->flags);
-+
-+ if (port->type == PORT_UNKNOWN)
-+ return 0;
-+
-+ /*
-+ * Initialise and allocate the transmit and temporary
-+ * buffer.
-+ */
-+ if (!info->xmit.buf) {
-+ page = get_zeroed_page(GFP_KERNEL);
-+ if (!page)
-+ return -ENOMEM;
-+
-+ info->xmit.buf = (unsigned char *) page;
-+ info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE;
-+ init_MUTEX(&info->tmpbuf_sem);
-+ uart_circ_clear(&info->xmit);
-+ }
-+
-+ port->mctrl = 0;
-+
-+ retval = port->ops->startup(port);
-+ if (retval == 0) {
-+ if (init_hw) {
-+ /*
-+ * Initialise the hardware port settings.
-+ */
-+ uart_change_speed(state, NULL);
-+
-+ /*
-+ * Setup the RTS and DTR signals once the
-+ * port is open and ready to respond.
-+ */
-+ if (info->tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-+ }
-+
-+ info->flags |= UIF_INITIALIZED;
-+
-+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
-+ }
-+
-+ if (retval && capable(CAP_SYS_ADMIN))
-+ retval = 0;
-+
-+ return retval;
-+}
-+
-+/*
-+ * This routine will shutdown a serial port; interrupts are disabled, and
-+ * DTR is dropped if the hangup on close termio flag is on. Calls to
-+ * uart_shutdown are serialised by the per-port semaphore.
-+ */
-+static void uart_shutdown(struct uart_state *state)
-+{
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+
-+ if (!(info->flags & UIF_INITIALIZED))
-+ return;
-+
-+ /*
-+ * Turn off DTR and RTS early.
-+ */
-+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-+ uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-+
-+ /*
-+ * clear delta_msr_wait queue to avoid mem leaks: we may free
-+ * the irq here so the queue might never be woken up. Note
-+ * that we won't end up waiting on delta_msr_wait again since
-+ * any outstanding file descriptors should be pointing at
-+ * hung_up_tty_fops now.
-+ */
-+ wake_up_interruptible(&info->delta_msr_wait);
-+
-+ /*
-+ * Free the IRQ and disable the port.
-+ */
-+ port->ops->shutdown(port);
-+
-+ /*
-+ * Free the transmit buffer page.
-+ */
-+ if (info->xmit.buf) {
-+ free_page((unsigned long)info->xmit.buf);
-+ info->xmit.buf = NULL;
-+ info->tmpbuf = NULL;
-+ }
-+
-+ /*
-+ * kill off our tasklet
-+ */
-+ tasklet_kill(&info->tlet);
-+ if (info->tty)
-+ set_bit(TTY_IO_ERROR, &info->tty->flags);
-+
-+ info->flags &= ~UIF_INITIALIZED;
-+}
-+
-+/**
-+ * uart_update_timeout - update per-port FIFO timeout.
-+ * @port: uart_port structure describing the port.
-+ * @cflag: termios cflag value
-+ * @quot: uart clock divisor quotient
-+ *
-+ * Set the port FIFO timeout value. The @cflag value should
-+ * reflect the actual hardware settings.
-+ */
-+void
-+uart_update_timeout(struct uart_port *port, unsigned int cflag,
-+ unsigned int baud)
-+{
-+ unsigned int bits;
-+
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ bits = 7;
-+ break;
-+ case CS6:
-+ bits = 8;
-+ break;
-+ case CS7:
-+ bits = 9;
-+ break;
-+ default:
-+ bits = 10;
-+ break; // CS8
-+ }
-+
-+ if (cflag & CSTOPB)
-+ bits++;
-+ if (cflag & PARENB)
-+ bits++;
-+
-+ /*
-+ * The total number of bits to be transmitted in the fifo.
-+ */
-+ bits = bits * port->fifosize;
-+
-+ /*
-+ * Figure the timeout to send the above number of bits.
-+ * Add .02 seconds of slop
-+ */
-+ port->timeout = (HZ * bits) / baud + HZ/50;
-+}
-+
-+EXPORT_SYMBOL(uart_update_timeout);
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+ u_int quot;
-+
-+ /* Special case: B0 rate */
-+ if (!baud)
-+ baud = 9600;
-+
-+ /* Old HI/VHI/custom speed handling */
-+ if (baud == 38400 &&
-+ ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-+ quot = port->custom_divisor;
-+ else
-+ quot = port->uartclk / (16 * baud);
-+
-+ return quot;
-+}
-+
-+static void
-+uart_change_speed(struct uart_state *state, struct termios *old_termios)
-+{
-+ struct tty_struct *tty = state->info->tty;
-+ struct uart_port *port = state->port;
-+ struct termios *termios;
-+ unsigned int quot, baud, cflag, try;
-+
-+ /*
-+ * If we have no tty, termios, or the port does not exist,
-+ * then we can't set the parameters for this port.
-+ */
-+ if (!tty || !tty->termios || port->type == PORT_UNKNOWN)
-+ return;
-+
-+ termios = tty->termios;
-+
-+ cflag = termios->c_cflag;
-+
-+ for (try = 0; try < 2; try ++) {
-+ /* Determine divisor based on baud rate */
-+ baud = tty_get_baud_rate(tty);
-+ quot = uart_calculate_quot(port, baud);
-+ if (quot)
-+ break;
-+
-+ /*
-+ * Oops, the quotient was zero. Try again with
-+ * the old baud rate if possible.
-+ */
-+ termios->c_cflag &= ~CBAUD;
-+ if (old_termios) {
-+ termios->c_cflag |=
-+ (old_termios->c_cflag & CBAUD);
-+ old_termios = NULL;
-+ continue;
-+ }
-+
-+ /*
-+ * As a last resort, if the quotient is zero,
-+ * default to 9600 bps
-+ */
-+ termios->c_cflag |= B9600;
-+ }
-+
-+ uart_update_timeout(port, cflag, port->uartclk / (16 * quot));
-+
-+ if (termios->c_cflag & CRTSCTS)
-+ state->info->flags |= UIF_CTS_FLOW;
-+ else
-+ state->info->flags &= ~UIF_CTS_FLOW;
-+ if (termios->c_cflag & CLOCAL)
-+ state->info->flags &= ~UIF_CHECK_CD;
-+ else
-+ state->info->flags |= UIF_CHECK_CD;
-+
-+ /*
-+ * Set up parity check flag
-+ */
-+ pm_access(state->pm);
-+
-+ port->ops->change_speed(port, cflag, termios->c_iflag, quot);
-+}
-+
-+static inline void
-+__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
-+{
-+ unsigned long flags;
-+
-+ if (!circ->buf)
-+ return;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ if (uart_circ_chars_free(circ) != 0) {
-+ circ->buf[circ->head] = c;
-+ circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
-+ }
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static inline int
-+__uart_user_write(struct uart_port *port, struct circ_buf *circ,
-+ const unsigned char *buf, int count)
-+{
-+ unsigned long flags;
-+ int c, ret = 0;
-+
-+ if (down_interruptible(&port->info->tmpbuf_sem))
-+ return -EINTR;
-+
-+ while (1) {
-+ int c1;
-+ c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+
-+ c -= copy_from_user(port->info->tmpbuf, buf, c);
-+ if (!c) {
-+ if (!ret)
-+ ret = -EFAULT;
-+ break;
-+ }
-+ spin_lock_irqsave(&port->lock, flags);
-+ c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (c1 < c)
-+ c = c1;
-+ memcpy(circ->buf + circ->head, port->info->tmpbuf, c);
-+ circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ buf += c;
-+ count -= c;
-+ ret += c;
-+ }
-+ up(&port->info->tmpbuf_sem);
-+
-+ return ret;
-+}
-+
-+static inline int
-+__uart_kern_write(struct uart_port *port, struct circ_buf *circ,
-+ const unsigned char *buf, int count)
-+{
-+ unsigned long flags;
-+ int c, ret = 0;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ while (1) {
-+ c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+ memcpy(circ->buf + circ->head, buf, c);
-+ circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-+ buf += c;
-+ count -= c;
-+ ret += c;
-+ }
-+ spin_unlock_irqrestore(&port->lock, flags);
-+
-+ return ret;
-+}
-+
-+static void uart_put_char(struct tty_struct *tty, unsigned char ch)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ __uart_put_char(state->port, &state->info->xmit, ch);
-+}
-+
-+static void uart_flush_chars(struct tty_struct *tty)
-+{
-+ uart_start(tty);
-+}
-+
-+static int
-+uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf,
-+ int count)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ int ret;
-+
-+ if (!state->info->xmit.buf)
-+ return 0;
-+
-+ if (from_user)
-+ ret = __uart_user_write(state->port, &state->info->xmit, buf, count);
-+ else
-+ ret = __uart_kern_write(state->port, &state->info->xmit, buf, count);
-+
-+ uart_start(tty);
-+ return ret;
-+}
-+
-+static int uart_write_room(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ return uart_circ_chars_free(&state->info->xmit);
-+}
-+
-+static int uart_chars_in_buffer(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ return uart_circ_chars_pending(&state->info->xmit);
-+}
-+
-+static void uart_flush_buffer(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ DPRINTK("uart_flush_buffer(%d) called\n",
-+ MINOR(tty->device) - tty->driver.minor_start);
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ uart_circ_clear(&state->info->xmit);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ wake_up_interruptible(&tty->write_wait);
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-+ tty->ldisc.write_wakeup)
-+ (tty->ldisc.write_wakeup)(tty);
-+}
-+
-+/*
-+ * This function is used to send a high-priority XON/XOFF character to
-+ * the device
-+ */
-+static void uart_send_xchar(struct tty_struct *tty, char ch)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ if (port->ops->send_xchar)
-+ port->ops->send_xchar(port, ch);
-+ else {
-+ port->x_char = ch;
-+ if (ch) {
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->start_tx(port, 0);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ }
-+ }
-+}
-+
-+static void uart_throttle(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ if (I_IXOFF(tty))
-+ uart_send_xchar(tty, STOP_CHAR(tty));
-+
-+ if (tty->termios->c_cflag & CRTSCTS)
-+ uart_clear_mctrl(state->port, TIOCM_RTS);
-+}
-+
-+static void uart_unthrottle(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ if (I_IXOFF(tty)) {
-+ if (port->x_char)
-+ port->x_char = 0;
-+ else
-+ uart_send_xchar(tty, START_CHAR(tty));
-+ }
-+
-+ if (tty->termios->c_cflag & CRTSCTS)
-+ uart_set_mctrl(port, TIOCM_RTS);
-+}
-+
-+static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo)
-+{
-+ struct uart_port *port = state->port;
-+ struct serial_struct tmp;
-+
-+ memset(&tmp, 0, sizeof(tmp));
-+ tmp.type = port->type;
-+ tmp.line = port->line;
-+ tmp.port = port->iobase;
-+ if (HIGH_BITS_OFFSET)
-+ tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
-+ tmp.irq = port->irq;
-+ tmp.flags = port->flags;
-+ tmp.xmit_fifo_size = port->fifosize;
-+ tmp.baud_base = port->uartclk / 16;
-+ tmp.close_delay = state->close_delay;
-+ tmp.closing_wait = state->closing_wait;
-+ tmp.custom_divisor = port->custom_divisor;
-+ tmp.hub6 = port->hub6;
-+ tmp.io_type = port->iotype;
-+ tmp.iomem_reg_shift = port->regshift;
-+ tmp.iomem_base = (void *)port->mapbase;
-+
-+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-+ return -EFAULT;
-+ return 0;
-+}
-+
-+static int
-+uart_set_info(struct uart_state *state, struct serial_struct *newinfo)
-+{
-+ struct serial_struct new_serial;
-+ struct uart_port *port = state->port;
-+ unsigned long new_port;
-+ unsigned int change_irq, change_port, old_flags;
-+ unsigned int old_custom_divisor;
-+ int retval = 0;
-+
-+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-+ return -EFAULT;
-+
-+ new_port = new_serial.port;
-+ if (HIGH_BITS_OFFSET)
-+ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-+
-+ new_serial.irq = irq_cannonicalize(new_serial.irq);
-+
-+ /*
-+ * This semaphore protects state->count. It is also
-+ * very useful to prevent opens. Also, take the
-+ * port configuration semaphore to make sure that a
-+ * module insertion/removal doesn't change anything
-+ * under us.
-+ */
-+ down(&state->sem);
-+
-+ change_irq = new_serial.irq != port->irq;
-+
-+ /*
-+ * Since changing the 'type' of the port changes its resource
-+ * allocations, we should treat type changes the same as
-+ * IO port changes.
-+ */
-+ change_port = new_port != port->iobase ||
-+ (unsigned long)new_serial.iomem_base != port->mapbase ||
-+ new_serial.hub6 != port->hub6 ||
-+ new_serial.io_type != port->iotype ||
-+ new_serial.iomem_reg_shift != port->regshift ||
-+ new_serial.type != port->type;
-+
-+ old_flags = port->flags;
-+ old_custom_divisor = port->custom_divisor;
-+
-+ if (!capable(CAP_SYS_ADMIN)) {
-+ retval = -EPERM;
-+ if (change_irq || change_port ||
-+ (new_serial.baud_base != port->uartclk / 16) ||
-+ (new_serial.close_delay != state->close_delay) ||
-+ (new_serial.closing_wait != state->closing_wait) ||
-+ (new_serial.xmit_fifo_size != port->fifosize) ||
-+ (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
-+ goto exit;
-+ port->flags = ((port->flags & ~UPF_USR_MASK) |
-+ (new_serial.flags & UPF_USR_MASK));
-+ port->custom_divisor = new_serial.custom_divisor;
-+ goto check_and_exit;
-+ }
-+
-+ /*
-+ * Ask the low level driver to verify the settings.
-+ */
-+ if (port->ops->verify_port)
-+ retval = port->ops->verify_port(port, &new_serial);
-+
-+ if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-+ (new_serial.baud_base < 9600))
-+ retval = -EINVAL;
-+
-+ if (retval)
-+ goto exit;
-+
-+ if (change_port || change_irq) {
-+ retval = -EBUSY;
-+
-+ /*
-+ * Make sure that we are the sole user of this port.
-+ */
-+ if (uart_users(state) > 1)
-+ goto exit;
-+
-+ /*
-+ * We need to shutdown the serial port at the old
-+ * port/type/irq combination.
-+ */
-+ uart_shutdown(state);
-+ }
-+
-+ if (change_port) {
-+ unsigned long old_iobase, old_mapbase;
-+ unsigned int old_type, old_iotype, old_hub6, old_shift;
-+
-+ old_iobase = port->iobase;
-+ old_mapbase = port->mapbase;
-+ old_type = port->type;
-+ old_hub6 = port->hub6;
-+ old_iotype = port->iotype;
-+ old_shift = port->regshift;
-+
-+ /*
-+ * Free and release old regions
-+ */
-+ if (old_type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ port->iobase = new_port;
-+ port->type = new_serial.type;
-+ port->hub6 = new_serial.hub6;
-+ port->iotype = new_serial.io_type;
-+ port->regshift = new_serial.iomem_reg_shift;
-+ port->mapbase = (unsigned long)new_serial.iomem_base;
-+
-+ /*
-+ * Claim and map the new regions
-+ */
-+ if (port->type != PORT_UNKNOWN) {
-+ retval = port->ops->request_port(port);
-+ } else {
-+ /* Always success - Jean II */
-+ retval = 0;
-+ }
-+
-+ /*
-+ * If we fail to request resources for the
-+ * new port, try to restore the old settings.
-+ */
-+ if (retval && old_type != PORT_UNKNOWN) {
-+ port->iobase = old_iobase;
-+ port->type = old_type;
-+ port->hub6 = old_hub6;
-+ port->iotype = old_iotype;
-+ port->regshift = old_shift;
-+ port->mapbase = old_mapbase;
-+ retval = port->ops->request_port(port);
-+ /*
-+ * If we failed to restore the old settings,
-+ * we fail like this.
-+ */
-+ if (retval)
-+ port->type = PORT_UNKNOWN;
-+
-+ /*
-+ * We failed anyway.
-+ */
-+ retval = -EBUSY;
-+ }
-+ }
-+
-+ port->irq = new_serial.irq;
-+ port->uartclk = new_serial.baud_base * 16;
-+ port->flags = (port->flags & ~UPF_CHANGE_MASK) |
-+ (new_serial.flags & UPF_CHANGE_MASK);
-+ port->custom_divisor = new_serial.custom_divisor;
-+ state->close_delay = new_serial.close_delay * HZ / 100;
-+ state->closing_wait = new_serial.closing_wait * HZ / 100;
-+ port->fifosize = new_serial.xmit_fifo_size;
-+ if (state->info->tty)
-+ state->info->tty->low_latency =
-+ (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-+
-+ check_and_exit:
-+ retval = 0;
-+ if (port->type == PORT_UNKNOWN)
-+ goto exit;
-+ if (state->info->flags & UIF_INITIALIZED) {
-+ if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
-+ old_custom_divisor != port->custom_divisor) {
-+ state->info->tty->alt_speed = uart_get_altspeed(port);
-+ uart_change_speed(state, NULL);
-+ }
-+ } else
-+ retval = uart_startup(state, 1);
-+ exit:
-+ up(&state->sem);
-+ return retval;
-+}
-+
-+
-+/*
-+ * uart_get_lsr_info - get line status register info.
-+ * Note: uart_ioctl protects us against hangups.
-+ */
-+static int uart_get_lsr_info(struct uart_state *state, unsigned int *value)
-+{
-+ struct uart_port *port = state->port;
-+ unsigned int result;
-+
-+ result = port->ops->tx_empty(port);
-+
-+ /*
-+ * If we're about to load something into the transmit
-+ * register, we'll pretend the transmitter isn't empty to
-+ * avoid a race condition (depending on when the transmit
-+ * interrupt happens).
-+ */
-+ if (port->x_char ||
-+ ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
-+ !state->info->tty->stopped && !state->info->tty->hw_stopped))
-+ result &= ~TIOCSER_TEMT;
-+
-+ return put_user(result, value);
-+}
-+
-+static int uart_tiocmget(struct tty_struct *tty, struct file *file)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ int result = -EIO;
-+
-+ down(&state->sem);
-+ if ((!file || !tty_hung_up_p(file)) &&
-+ !(tty->flags & (1 << TTY_IO_ERROR))) {
-+ result = port->mctrl;
-+ result |= port->ops->get_mctrl(port);
-+ }
-+ up(&state->sem);
-+
-+ return result;
-+}
-+
-+static int
-+uart_tiocmset(struct tty_struct *tty, struct file *file,
-+ unsigned int set, unsigned int clear)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ int ret = -EIO;
-+
-+ down(&state->sem);
-+ if ((!file || !tty_hung_up_p(file)) &&
-+ !(tty->flags & (1 << TTY_IO_ERROR))) {
-+ uart_update_mctrl(port, set, clear);
-+ ret = 0;
-+ }
-+ up(&state->sem);
-+ return ret;
-+}
-+
-+static void uart_break_ctl(struct tty_struct *tty, int break_state)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ down(&state->sem);
-+
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->break_ctl(port, break_state);
-+
-+ up(&state->sem);
-+}
-+
-+static int uart_do_autoconfig(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+ int flags, ret;
-+
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ /*
-+ * Take the per-port semaphore. This prevents count from
-+ * changing, and hence any extra opens of the port while
-+ * we're auto-configuring.
-+ */
-+ if (down_interruptible(&state->sem))
-+ return -ERESTARTSYS;
-+
-+ ret = -EBUSY;
-+ if (uart_users(state) == 1) {
-+ uart_shutdown(state);
-+
-+ /*
-+ * If we already have a port type configured,
-+ * we must release its resources.
-+ */
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ flags = UART_CONFIG_TYPE;
-+ if (port->flags & UPF_AUTO_IRQ)
-+ flags |= UART_CONFIG_IRQ;
-+
-+ /*
-+ * This will claim the ports resources if
-+ * a port is found.
-+ */
-+ port->ops->config_port(port, flags);
-+
-+ ret = uart_startup(state, 1);
-+ }
-+ up(&state->sem);
-+ return ret;
-+}
-+
-+/*
-+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-+ * - mask passed in arg for lines of interest
-+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-+ * Caller should use TIOCGICOUNT to see which one it was
-+ */
-+static int
-+uart_wait_modem_status(struct uart_state *state, unsigned long arg)
-+{
-+ struct uart_port *port = state->port;
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct uart_icount cprev, cnow;
-+ int ret;
-+
-+ /*
-+ * note the counters on entry
-+ */
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cprev, &port->icount, sizeof(struct uart_icount));
-+
-+ /*
-+ * Force modem status interrupts on
-+ */
-+ port->ops->enable_ms(port);
-+ spin_unlock_irq(&port->lock);
-+
-+ add_wait_queue(&state->info->delta_msr_wait, &wait);
-+ for (;;) {
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
-+ spin_unlock_irq(&port->lock);
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-+ ret = 0;
-+ break;
-+ }
-+
-+ schedule();
-+
-+ /* see if a signal did it */
-+ if (signal_pending(current)) {
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-+
-+ cprev = cnow;
-+ }
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&state->info->delta_msr_wait, &wait);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-+ * Return: write counters to the user passed counter struct
-+ * NB: both 1->0 and 0->1 transitions are counted except for
-+ * RI where only 0->1 is counted.
-+ */
-+static int
-+uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt)
-+{
-+ struct serial_icounter_struct icount;
-+ struct uart_icount cnow;
-+ struct uart_port *port = state->port;
-+
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
-+ spin_unlock_irq(&port->lock);
-+
-+ icount.cts = cnow.cts;
-+ icount.dsr = cnow.dsr;
-+ icount.rng = cnow.rng;
-+ icount.dcd = cnow.dcd;
-+ icount.rx = cnow.rx;
-+ icount.tx = cnow.tx;
-+ icount.frame = cnow.frame;
-+ icount.overrun = cnow.overrun;
-+ icount.parity = cnow.parity;
-+ icount.brk = cnow.brk;
-+ icount.buf_overrun = cnow.buf_overrun;
-+
-+ return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
-+}
-+
-+/*
-+ * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here.
-+ */
-+static int
-+uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ int ret = -ENOIOCTLCMD;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ /*
-+ * These ioctls don't rely on the hardware to be present.
-+ */
-+ switch (cmd) {
-+ case TIOCGSERIAL:
-+ ret = uart_get_info(state, (struct serial_struct *)arg);
-+ break;
-+
-+ case TIOCSSERIAL:
-+ ret = uart_set_info(state, (struct serial_struct *)arg);
-+ break;
-+
-+ case TIOCSERCONFIG:
-+ ret = uart_do_autoconfig(state);
-+ break;
-+
-+ case TIOCSERGWILD: /* obsolete */
-+ case TIOCSERSWILD: /* obsolete */
-+ ret = 0;
-+ break;
-+ }
-+
-+ if (ret != -ENOIOCTLCMD)
-+ goto out;
-+
-+ if (tty->flags & (1 << TTY_IO_ERROR)) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * The following should only be used when hardware is present.
-+ */
-+ switch (cmd) {
-+ case TIOCMIWAIT:
-+ ret = uart_wait_modem_status(state, arg);
-+ break;
-+
-+ case TIOCGICOUNT:
-+ ret = uart_get_count(state, (struct serial_icounter_struct *)arg);
-+ break;
-+
-+ case TIOCMGET:
-+ {
-+ int val;
-+ val = uart_tiocmget(tty, filp);
-+ if (val >= 0) {
-+ ret = put_user(val, (int *)arg);
-+ } else {
-+ ret = val;
-+ }
-+ }
-+ break;
-+
-+ case TIOCMBIS:
-+ case TIOCMBIC:
-+ case TIOCMSET:
-+ {
-+ int val, set = 0, clear = 0;
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ break;
-+
-+ switch (cmd) {
-+ case TIOCMBIS:
-+ set = val;
-+ break;
-+ case TIOCMBIC:
-+ clear = val;
-+ break;
-+ case TIOCMSET:
-+ set = val;
-+ clear = ~val;
-+ break;
-+ }
-+
-+ set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
-+ clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
-+
-+ ret = uart_tiocmset(tty, filp, set, clear);
-+ }
-+ break;
-+ }
-+
-+ if (ret != -ENOIOCTLCMD)
-+ goto out;
-+
-+ down(&state->sem);
-+
-+ if (tty_hung_up_p(filp)) {
-+ ret = -EIO;
-+ goto out_up;
-+ }
-+
-+ /*
-+ * All these rely on hardware being present and need to be
-+ * protected against the tty being hung up.
-+ */
-+ switch (cmd) {
-+ case TIOCSERGETLSR: /* Get line status register */
-+ ret = uart_get_lsr_info(state, (unsigned int *)arg);
-+ break;
-+
-+ default: {
-+ struct uart_port *port = state->port;
-+ if (port->ops->ioctl)
-+ ret = port->ops->ioctl(port, cmd, arg);
-+ break;
-+ }
-+ }
-+ out_up:
-+ up(&state->sem);
-+ out:
-+ return ret;
-+}
-+
-+static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ unsigned long flags;
-+ unsigned int cflag = tty->termios->c_cflag;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ /*
-+ * These are the bits that are used to setup various
-+ * flags in the low level driver.
-+ */
-+#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-+
-+ if ((cflag ^ old_termios->c_cflag) == 0 &&
-+ RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
-+ return;
-+
-+ uart_change_speed(state, old_termios);
-+
-+ /* Handle transition to B0 status */
-+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-+ uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
-+
-+ /* Handle transition away from B0 status */
-+ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-+ unsigned int mask = TIOCM_DTR;
-+ if (!(cflag & CRTSCTS) ||
-+ !test_bit(TTY_THROTTLED, &tty->flags))
-+ mask |= TIOCM_RTS;
-+ uart_set_mctrl(state->port, mask);
-+ }
-+
-+ /* Handle turning off CRTSCTS */
-+ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-+ spin_lock_irqsave(&state->port->lock, flags);
-+ tty->hw_stopped = 0;
-+ __uart_start(tty);
-+ spin_unlock_irqrestore(&state->port->lock, flags);
-+ }
-+
-+#if 0
-+ /*
-+ * No need to wake up processes in open wait, since they
-+ * sample the CLOCAL flag once, and don't recheck it.
-+ * XXX It's not clear whether the current behavior is correct
-+ * or not. Hence, this may change.....
-+ */
-+ if (!(old_termios->c_cflag & CLOCAL) &&
-+ (tty->termios->c_cflag & CLOCAL))
-+ wake_up_interruptible(&state->info->open_wait);
-+#endif
-+}
-+
-+/*
-+ * In 2.4.5, calls to this will be serialized via the BKL in
-+ * linux/drivers/char/tty_io.c:tty_release()
-+ * linux/drivers/char/tty_io.c:do_tty_handup()
-+ */
-+static void uart_close(struct tty_struct *tty, struct file *filp)
-+{
-+ struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ if (!state || !state->port)
-+ return;
-+
-+ port = state->port;
-+
-+ DPRINTK("uart_close(%d) called\n", port->line);
-+
-+ down(&state->sem);
-+
-+ if (tty_hung_up_p(filp))
-+ goto done;
-+
-+ if ((tty->count == 1) && (state->count != 1)) {
-+ /*
-+ * Uh, oh. tty->count is 1, which means that the tty
-+ * structure will be freed. state->count should always
-+ * be one in these conditions. If it's greater than
-+ * one, we've got real problems, since it means the
-+ * serial port won't be shutdown.
-+ */
-+ printk("uart_close: bad serial port count; tty->count is 1, "
-+ "state->count is %d\n", state->count);
-+ state->count = 1;
-+ }
-+ if (--state->count < 0) {
-+ printk("rs_close: bad serial port count for %s%d: %d\n",
-+ tty->driver.name, port->line, state->count);
-+ state->count = 0;
-+ }
-+ if (state->count)
-+ goto done;
-+
-+ /*
-+ * Save the termios structure, since this port may have
-+ * separate termios for callout and dialin.
-+ */
-+ if (state->info->flags & UIF_NORMAL_ACTIVE)
-+ state->normal_termios = *tty->termios;
-+ if (state->info->flags & UIF_CALLOUT_ACTIVE)
-+ state->callout_termios = *tty->termios;
-+
-+ /*
-+ * Now we wait for the transmit buffer to clear; and we notify
-+ * the line discipline to only process XON/XOFF characters by
-+ * setting tty->closing.
-+ */
-+ tty->closing = 1;
-+
-+ if (state->closing_wait != USF_CLOSING_WAIT_NONE)
-+ tty_wait_until_sent(tty, state->closing_wait);
-+
-+ /*
-+ * At this point, we stop accepting input. To do this, we
-+ * disable the receive line status interrupts.
-+ */
-+ if (state->info->flags & UIF_INITIALIZED) {
-+ unsigned long flags;
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->stop_rx(port);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ /*
-+ * Before we drop DTR, make sure the UART transmitter
-+ * has completely drained; this is especially
-+ * important if there is a transmit FIFO!
-+ */
-+ uart_wait_until_sent(tty, port->timeout);
-+ }
-+
-+ uart_shutdown(state);
-+ uart_flush_buffer(tty);
-+ if (tty->ldisc.flush_buffer)
-+ tty->ldisc.flush_buffer(tty);
-+ tty->closing = 0;
-+ state->info->tty = NULL;
-+
-+ if (state->info->blocked_open) {
-+ if (state->close_delay) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(state->close_delay);
-+ set_current_state(TASK_RUNNING);
-+ }
-+ } else if (!uart_console(port)) {
-+ uart_change_pm(state, 3);
-+ }
-+
-+ /*
-+ * Wake up anyone trying to open this port.
-+ */
-+ state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
-+ wake_up_interruptible(&state->info->open_wait);
-+
-+ done:
-+ up(&state->sem);
-+ if (drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+}
-+
-+static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long char_time, expire;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ if (port->type == PORT_UNKNOWN || port->fifosize == 0)
-+ return;
-+
-+ /*
-+ * Set the check interval to be 1/5 of the estimated time to
-+ * send a single character, and make it at least 1. The check
-+ * interval should also be less than the timeout.
-+ *
-+ * Note: we have to use pretty tight timings here to satisfy
-+ * the NIST-PCTS.
-+ */
-+ char_time = (port->timeout - HZ/50) / port->fifosize;
-+ char_time = char_time / 5;
-+ if (char_time == 0)
-+ char_time = 1;
-+ if (timeout && timeout < char_time)
-+ char_time = timeout;
-+
-+ /*
-+ * If the transmitter hasn't cleared in twice the approximate
-+ * amount of time to send the entire FIFO, it probably won't
-+ * ever clear. This assumes the UART isn't doing flow
-+ * control, which is currently the case. Hence, if it ever
-+ * takes longer than port->timeout, this is probably due to a
-+ * UART bug of some kind. So, we clamp the timeout parameter at
-+ * 2*port->timeout.
-+ */
-+ if (timeout == 0 || timeout > 2 * port->timeout)
-+ timeout = 2 * port->timeout;
-+
-+ expire = jiffies + timeout;
-+
-+ DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
-+ port->line, jiffies, expire);
-+
-+ /*
-+ * Check whether the transmitter is empty every 'char_time'.
-+ * 'timeout' / 'expire' give us the maximum amount of time
-+ * we wait.
-+ */
-+ while (!port->ops->tx_empty(port)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(char_time);
-+ if (signal_pending(current))
-+ break;
-+ if (time_after(jiffies, expire))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING); /* might not be needed */
-+}
-+
-+/*
-+ * This is called with the BKL held in
-+ * linux/drivers/char/tty_io.c:do_tty_hangup()
-+ * We're called from the eventd thread, so we can sleep for
-+ * a _short_ time only.
-+ */
-+static void uart_hangup(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ BUG_ON(!kernel_locked());
-+ DPRINTK("uart_hangup(%d)\n", state->port->line);
-+
-+ down(&state->sem);
-+ if (state->info && state->info->flags & (UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE)) {
-+ uart_flush_buffer(tty);
-+ uart_shutdown(state);
-+ state->count = 0;
-+ state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
-+ state->info->tty = NULL;
-+ wake_up_interruptible(&state->info->open_wait);
-+ wake_up_interruptible(&state->info->delta_msr_wait);
-+ }
-+ up(&state->sem);
-+}
-+
-+/*
-+ * Copy across the serial console cflag setting into the termios settings
-+ * for the initial open of the port. This allows continuity between the
-+ * kernel settings, and the settings init adopts when it opens the port
-+ * for the first time.
-+ */
-+static void uart_update_termios(struct uart_state *state)
-+{
-+ struct tty_struct *tty = state->info->tty;
-+ struct uart_port *port = state->port;
-+
-+ if (uart_console(port) && port->cons->cflag) {
-+ tty->termios->c_cflag = port->cons->cflag;
-+ port->cons->cflag = 0;
-+ }
-+
-+ /*
-+ * If the device failed to grab its irq resources,
-+ * or some other error occurred, don't try to talk
-+ * to the port hardware.
-+ */
-+ if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-+ /*
-+ * Make termios settings take effect.
-+ */
-+ uart_change_speed(state, NULL);
-+
-+ /*
-+ * And finally enable the RTS and DTR signals.
-+ */
-+ if (tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-+ }
-+}
-+
-+/*
-+ * Block the open until the port is ready. We must be called with
-+ * the per-port semaphore held.
-+ */
-+static int
-+uart_block_til_ready(struct file *filp, struct uart_state *state)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+ struct termios *termios;
-+
-+ /*
-+ * If this is a callout device, then just make sure the normal
-+ * device isn't being used.
-+ */
-+ if (info->tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-+ if (info->flags & UIF_NORMAL_ACTIVE)
-+ return -EBUSY;
-+ if ((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (info->flags & ASYNC_SESSION_LOCKOUT) &&
-+ (info->session != current->session))
-+ return -EBUSY;
-+ if ((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (info->flags & ASYNC_PGRP_LOCKOUT) &&
-+ (info->pgrp != current->pgrp))
-+ return -EBUSY;
-+ info->flags |= UIF_CALLOUT_ACTIVE;
-+ return 0;
-+ }
-+
-+ if (info->flags & UIF_CALLOUT_ACTIVE) {
-+ termios = &state->normal_termios;
-+ } else {
-+ termios = state->info->tty->termios;
-+ }
-+
-+ info->blocked_open++;
-+ state->count--;
-+
-+ add_wait_queue(&info->open_wait, &wait);
-+ while (1) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ /*
-+ * If we have been hung up, tell userspace/restart open.
-+ */
-+ if (tty_hung_up_p(filp) || info->tty == NULL)
-+ break;
-+
-+ /*
-+ * If the port has been closed, tell userspace/restart open.
-+ */
-+ if (!(info->flags & UIF_INITIALIZED))
-+ break;
-+
-+ /*
-+ * If non-blocking mode is set, or CLOCAL mode is set,
-+ * we don't want to wait for the modem status lines to
-+ * indicate that the port is ready.
-+ *
-+ * Also, if the port is not enabled/configured, we want
-+ * to allow the open to succeed here. Note that we will
-+ * have set TTY_IO_ERROR for a non-existant port.
-+ */
-+ if ((filp->f_flags & O_NONBLOCK) ||
-+ (termios->c_cflag & CLOCAL) ||
-+ (info->tty->flags & (1 << TTY_IO_ERROR))) {
-+ break;
-+ }
-+
-+ if (!(info->flags & UIF_CALLOUT_ACTIVE)) {
-+ /*
-+ * Set DTR to allow modem to know we're waiting. Do
-+ * not set RTS here - we want to make sure we catch
-+ * the data from the modem.
-+ */
-+ if (info->tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_DTR);
-+
-+ /*
-+ * and wait for the carrier to indicate that the
-+ * modem is ready for us.
-+ */
-+ if (port->ops->get_mctrl(port) & TIOCM_CAR)
-+ break;
-+ }
-+
-+ up(&state->sem);
-+ schedule();
-+ down(&state->sem);
-+
-+ if (signal_pending(current))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&info->open_wait, &wait);
-+
-+ state->count++;
-+ info->blocked_open--;
-+
-+ info->flags |= UIF_NORMAL_ACTIVE;
-+
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+
-+ if (!info->tty || tty_hung_up_p(filp))
-+ return -EAGAIN;
-+
-+ return 0;
-+}
-+
-+static struct uart_state *uart_get(struct uart_driver *drv, int line)
-+{
-+ struct uart_state *state;
-+
-+ down(&port_sem);
-+ state = drv->state + line;
-+ if (down_interruptible(&state->sem)) {
-+ state = ERR_PTR(-ERESTARTSYS);
-+ goto out;
-+ }
-+
-+ state->count++;
-+ if (!state->port) {
-+ state->count--;
-+ up(&state->sem);
-+ state = ERR_PTR(-ENXIO);
-+ goto out;
-+ }
-+
-+ if (!state->info) {
-+ state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
-+ if (state->info) {
-+ memset(state->info, 0, sizeof(struct uart_info));
-+ init_waitqueue_head(&state->info->open_wait);
-+ init_waitqueue_head(&state->info->delta_msr_wait);
-+
-+ /*
-+ * Link the info into the other structures.
-+ */
-+ state->port->info = state->info;
-+
-+ tasklet_init(&state->info->tlet, uart_tasklet_action,
-+ (unsigned long)state);
-+ } else {
-+ state->count--;
-+ up(&state->sem);
-+ state = ERR_PTR(-ENOMEM);
-+ }
-+ }
-+
-+ out:
-+ up(&port_sem);
-+ return state;
-+}
-+
-+/*
-+ * In 2.4.5, calls to uart_open are serialised by the BKL in
-+ * linux/fs/devices.c:chrdev_open()
-+ * Note that if this fails, then uart_close() _will_ be called.
-+ */
-+static int uart_open(struct tty_struct *tty, struct file *filp)
-+{
-+ struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-+ struct uart_state *state;
-+ int retval, line = MINOR(tty->device) - tty->driver.minor_start;
-+
-+ BUG_ON(!kernel_locked());
-+ DPRINTK("uart_open(%d) called\n", line);
-+
-+ /*
-+ * tty->driver->num won't change, so we won't fail here with
-+ * tty->driver_data set to something non-NULL (and therefore
-+ * we won't get caught by uart_close()).
-+ */
-+ retval = -ENODEV;
-+ if (line >= tty->driver.num)
-+ goto fail;
-+
-+ if (!try_inc_mod_count(drv->owner))
-+ goto fail;
-+
-+ /*
-+ * We take the semaphore inside uart_get to guarantee that we won't
-+ * be re-entered while allocating the info structure, or while we
-+ * request any IRQs that the driver may need. This also has the nice
-+ * side-effect that it delays the action of uart_hangup, so we can
-+ * guarantee that info->tty will always contain something reasonable.
-+ */
-+ state = uart_get(drv, line);
-+ if (IS_ERR(state)) {
-+ retval = PTR_ERR(state);
-+ if (!tty->driver_data)
-+ goto out;
-+ else
-+ goto fail;
-+ }
-+
-+ /*
-+ * Once we set tty->driver_data here, we are guaranteed that
-+ * uart_close() will decrement the driver module use count.
-+ * Any failures from here onwards should not touch the count.
-+ */
-+ tty->driver_data = state;
-+ tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-+ tty->alt_speed = uart_get_altspeed(state->port);
-+ state->info->tty = tty;
-+
-+ /*
-+ * If the port is in the middle of closing, bail out now.
-+ */
-+ if (tty_hung_up_p(filp)) {
-+ retval = -EAGAIN;
-+ state->count--;
-+ up(&state->sem);
-+ goto fail;
-+ }
-+
-+ /*
-+ * Make sure the device is in D0 state.
-+ */
-+ if (state->count == 1)
-+ uart_change_pm(state, 0);
-+
-+ /*
-+ * Start up the serial port.
-+ */
-+ retval = uart_startup(state, 0);
-+
-+ /*
-+ * If we succeeded, wait until the port is ready.
-+ */
-+ if (retval == 0)
-+ retval = uart_block_til_ready(filp, state);
-+
-+ /*
-+ * If this is the first open to succeed, adjust things to suit.
-+ */
-+ if (retval == 0 && state->count == 1) {
-+ if (state->port->flags & UPF_SPLIT_TERMIOS) {
-+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-+ *tty->termios = state->normal_termios;
-+ else
-+ *tty->termios = state->callout_termios;
-+ }
-+
-+ uart_update_termios(state);
-+
-+ state->info->session = current->session;
-+ state->info->pgrp = current->pgrp;
-+ }
-+ up(&state->sem);
-+
-+ return 0;
-+
-+ out:
-+ if (drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+ fail:
-+ return retval;
-+}
-+
-+static const char *uart_type(struct uart_port *port)
-+{
-+ const char *str = NULL;
-+
-+ if (port->ops->type)
-+ str = port->ops->type(port);
-+
-+ if (!str)
-+ str = "unknown";
-+
-+ return str;
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+
-+static int uart_line_info(char *buf, struct uart_driver *drv, int i)
-+{
-+ struct uart_state *state = drv->state + i;
-+ struct uart_port *port = state->port;
-+ char stat_buf[32];
-+ unsigned int status;
-+ int ret;
-+
-+ if (!port)
-+ return 0;
-+
-+ ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d",
-+ port->line, uart_type(port),
-+ port->iobase, port->irq);
-+
-+ if (port->type == PORT_UNKNOWN) {
-+ strcat(buf, "\n");
-+ return ret + 1;
-+ }
-+
-+ status = port->ops->get_mctrl(port);
-+
-+ ret += sprintf(buf + ret, " tx:%d rx:%d",
-+ port->icount.tx, port->icount.rx);
-+ if (port->icount.frame)
-+ ret += sprintf(buf + ret, " fe:%d",
-+ port->icount.frame);
-+ if (port->icount.parity)
-+ ret += sprintf(buf + ret, " pe:%d",
-+ port->icount.parity);
-+ if (port->icount.brk)
-+ ret += sprintf(buf + ret, " brk:%d",
-+ port->icount.brk);
-+ if (port->icount.overrun)
-+ ret += sprintf(buf + ret, " oe:%d",
-+ port->icount.overrun);
-+
-+#define INFOBIT(bit,str) \
-+ if (port->mctrl & (bit)) \
-+ strcat(stat_buf, (str))
-+#define STATBIT(bit,str) \
-+ if (status & (bit)) \
-+ strcat(stat_buf, (str))
-+
-+ stat_buf[0] = '\0';
-+ stat_buf[1] = '\0';
-+ INFOBIT(TIOCM_RTS, "|RTS");
-+ STATBIT(TIOCM_CTS, "|CTS");
-+ INFOBIT(TIOCM_DTR, "|DTR");
-+ STATBIT(TIOCM_DSR, "|DSR");
-+ STATBIT(TIOCM_CAR, "|CD");
-+ STATBIT(TIOCM_RNG, "|RI");
-+ if (stat_buf[0])
-+ stat_buf[0] = ' ';
-+ strcat(stat_buf, "\n");
-+
-+ ret += sprintf(buf + ret, stat_buf);
-+ return ret;
-+}
-+
-+static int uart_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ struct tty_driver *ttydrv = data;
-+ struct uart_driver *drv = ttydrv->driver_state;
-+ int i, len = 0, l;
-+ off_t begin = 0;
-+
-+ len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
-+ "", "", "");
-+ for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) {
-+ l = uart_line_info(page + len, drv, i);
-+ len += l;
-+ if (len + begin > off + count)
-+ goto done;
-+ if (len + begin < off) {
-+ begin += len;
-+ len = 0;
-+ }
-+ }
-+ *eof = 1;
-+ done:
-+ if (off >= len + begin)
-+ return 0;
-+ *start = page + (off - begin);
-+ return (count < begin + len - off) ? count : (begin + len - off);
-+}
-+#endif
-+
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+/*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+struct uart_port * __init
-+uart_get_console(struct uart_port *ports, int nr, struct console *co)
-+{
-+ int idx = co->index;
-+
-+ if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
-+ ports[idx].membase == NULL))
-+ for (idx = 0; idx < nr; idx++)
-+ if (ports[idx].iobase != 0 ||
-+ ports[idx].membase != NULL)
-+ break;
-+
-+ co->index = idx;
-+
-+ return ports + idx;
-+}
-+
-+/**
-+ * uart_parse_options - Parse serial port baud/parity/bits/flow contro.
-+ * @options: pointer to option string
-+ * @baud: pointer to an 'int' variable for the baud rate.
-+ * @parity: pointer to an 'int' variable for the parity.
-+ * @bits: pointer to an 'int' variable for the number of data bits.
-+ * @flow: pointer to an 'int' variable for the flow control character.
-+ *
-+ * uart_parse_options decodes a string containing the serial console
-+ * options. The format of the string is <baud><parity><bits><flow>,
-+ * eg: 115200n8r
-+ */
-+void __init
-+uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
-+{
-+ char *s = options;
-+
-+ *baud = simple_strtoul(s, NULL, 10);
-+ while (*s >= '0' && *s <= '9')
-+ s++;
-+ if (*s)
-+ *parity = *s++;
-+ if (*s)
-+ *bits = *s++ - '0';
-+ if (*s)
-+ *flow = *s;
-+}
-+
-+struct baud_rates {
-+ unsigned int rate;
-+ unsigned int cflag;
-+};
-+
-+static struct baud_rates baud_rates[] = {
-+ { 921600, B921600 },
-+ { 460800, B460800 },
-+ { 230400, B230400 },
-+ { 115200, B115200 },
-+ { 57600, B57600 },
-+ { 38400, B38400 },
-+ { 19200, B19200 },
-+ { 9600, B9600 },
-+ { 4800, B4800 },
-+ { 2400, B2400 },
-+ { 1200, B1200 },
-+ { 0, B38400 }
-+};
-+
-+/**
-+ * uart_set_options - setup the serial console parameters
-+ * @port: pointer to the serial ports uart_port structure
-+ * @co: console pointer
-+ * @baud: baud rate
-+ * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
-+ * @bits: number of data bits
-+ * @flow: flow control character - 'r' (rts)
-+ */
-+int __init
-+uart_set_options(struct uart_port *port, struct console *co,
-+ int baud, int parity, int bits, int flow)
-+{
-+ struct termios termios;
-+ unsigned int quot;
-+ int i;
-+
-+ memset(&termios, 0, sizeof(struct termios));
-+
-+ termios.c_cflag = CREAD | HUPCL | CLOCAL;
-+
-+ /*
-+ * Construct a cflag setting.
-+ */
-+ for (i = 0; baud_rates[i].rate; i++)
-+ if (baud_rates[i].rate <= baud)
-+ break;
-+
-+ termios.c_cflag |= baud_rates[i].cflag;
-+ baud = baud_rates[i].rate;
-+ if (baud == 0)
-+ baud = 38400;
-+
-+ if (bits == 7)
-+ termios.c_cflag |= CS7;
-+ else
-+ termios.c_cflag |= CS8;
-+
-+ switch (parity) {
-+ case 'o': case 'O':
-+ termios.c_cflag |= PARODD;
-+ /*fall through*/
-+ case 'e': case 'E':
-+ termios.c_cflag |= PARENB;
-+ break;
-+ }
-+
-+ if (flow == 'r')
-+ termios.c_cflag |= CRTSCTS;
-+
-+ quot = (port->uartclk / (16 * baud));
-+ port->ops->change_speed(port, termios.c_cflag, 0, quot);
-+ co->cflag = termios.c_cflag;
-+
-+ return 0;
-+}
-+
-+extern void ambauart_console_init(void);
-+extern void anakin_console_init(void);
-+extern void clps711xuart_console_init(void);
-+extern void sa1100_rs_console_init(void);
-+extern void serial8250_console_init(void);
-+extern void at91_console_init(void);
-+
-+/*
-+ * Central "initialise all serial consoles" container. Needs to be killed.
-+ */
-+void __init uart_console_init(void)
-+{
-+#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-+ ambauart_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-+ anakin_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-+ clps711xuart_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-+ sa1100_rs_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_AT91_CONSOLE
-+ at91_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+ serial8250_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_UART00_CONSOLE
-+ uart00_console_init();
-+#endif
-+}
-+#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-+
-+static void uart_change_pm(struct uart_state *state, int pm_state)
-+{
-+ struct uart_port *port = state->port;
-+ if (port->ops->pm)
-+ port->ops->pm(port, pm_state, 0);
-+}
-+
-+#ifdef CONFIG_PM
-+int uart_suspend_port(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+
-+ down(&state->sem);
-+ if (port) {
-+ /*
-+ * Disable the console device before suspending.
-+ */
-+ if (uart_console(port))
-+ port->cons->flags &= ~CON_ENABLED;
-+
-+ if (state->info && state->info->flags & UIF_INITIALIZED) {
-+ struct uart_ops *ops = port->ops;
-+
-+ spin_lock_irq(&port->lock);
-+ ops->stop_tx(port, 0);
-+ ops->set_mctrl(port, 0);
-+ ops->stop_rx(port);
-+ spin_unlock_irq(&port->lock);
-+
-+ /*
-+ * Wait for the transmitter to empty.
-+ */
-+ while (!ops->tx_empty(port)) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(10*HZ/1000);
-+ }
-+ set_current_state(TASK_RUNNING);
-+
-+ ops->shutdown(port);
-+ }
-+
-+ uart_change_pm(state, 3);
-+ }
-+
-+ up(&state->sem);
-+
-+ return 0;
-+}
-+
-+int uart_resume_port(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+
-+ down(&state->sem);
-+ if (port) {
-+ uart_change_pm(state, 0);
-+
-+ /*
-+ * Re-enable the console device after suspending.
-+ */
-+ if (uart_console(port)) {
-+ uart_change_speed(state, NULL);
-+ port->cons->flags |= CON_ENABLED;
-+ }
-+
-+ if (state->info && state->info->flags & UIF_INITIALIZED) {
-+ struct uart_ops *ops = port->ops;
-+
-+ ops->set_mctrl(port, 0);
-+ ops->startup(port);
-+ uart_change_speed(state, NULL);
-+ spin_lock_irq(&port->lock);
-+ ops->set_mctrl(port, port->mctrl);
-+ ops->start_tx(port, 0);
-+ spin_unlock_irq(&port->lock);
-+ }
-+ }
-+
-+ up(&state->sem);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Wakeup support.
-+ */
-+static int uart_pm_set_wakeup(struct uart_state *state, int data)
-+{
-+ int err = 0;
-+
-+ if (state->port->ops->set_wake)
-+ err = state->port->ops->set_wake(state->port, data);
-+
-+ return err;
-+}
-+
-+static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct uart_state *state = dev->data;
-+ int err = 0;
-+
-+ if (state->port && state->port->type == PORT_UNKNOWN)
-+ return 0;
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ err = uart_suspend_port(state);
-+ break;
-+
-+ case PM_RESUME:
-+ err = uart_resume_port(state);
-+ break;
-+
-+ case PM_SET_WAKEUP:
-+ err = uart_pm_set_wakeup(state, (int)data);
-+ break;
-+ }
-+ return err;
-+}
-+#endif
-+
-+static inline void
-+uart_report_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ printk("%s%d at ", drv->normal_name, port->line);
-+ switch (port->iotype) {
-+ case UPIO_PORT:
-+ printk("I/O 0x%x", port->iobase);
-+ break;
-+ case UPIO_HUB6:
-+ printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
-+ break;
-+ case UPIO_MEM:
-+ printk("MMIO 0x%lx", port->mapbase);
-+ break;
-+ }
-+ printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
-+}
-+
-+static void
-+uart_configure_port(struct uart_driver *drv, struct uart_state *state,
-+ struct uart_port *port)
-+{
-+ unsigned int flags;
-+
-+ /*
-+ * If there isn't a port here, don't do anything further.
-+ */
-+ if (!port->iobase && !port->mapbase && !port->membase)
-+ return;
-+
-+ /*
-+ * Now do the auto configuration stuff. Note that config_port
-+ * is expected to claim the resources and map the port for us.
-+ */
-+ flags = UART_CONFIG_TYPE;
-+ if (port->flags & UPF_AUTO_IRQ)
-+ flags |= UART_CONFIG_IRQ;
-+ if (port->flags & UPF_BOOT_AUTOCONF) {
-+ port->type = PORT_UNKNOWN;
-+ port->ops->config_port(port, flags);
-+ }
-+
-+ if (port->type != PORT_UNKNOWN) {
-+ unsigned long flags;
-+
-+ uart_report_port(drv, port);
-+
-+ /*
-+ * Ensure that the modem control lines are de-activated.
-+ * We probably don't need a spinlock around this, but
-+ */
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->set_mctrl(port, 0);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+
-+ /*
-+ * Power down all ports by default, except the
-+ * console if we have one.
-+ */
-+ if (!uart_console(port))
-+ uart_change_pm(state, 3);
-+ }
-+}
-+
-+/*
-+ * This reverses the effects of uart_configure_port, hanging up the
-+ * port before removal.
-+ */
-+static void
-+uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+ struct uart_info *info = state->info;
-+
-+ if (info && info->tty)
-+ tty_vhangup(info->tty);
-+
-+ down(&state->sem);
-+
-+ state->info = NULL;
-+
-+ /*
-+ * Free the port IO and memory resources, if any.
-+ */
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ /*
-+ * Indicate that there isn't a port here anymore.
-+ */
-+ port->type = PORT_UNKNOWN;
-+
-+ /*
-+ * Kill the tasklet, and free resources.
-+ */
-+ if (info) {
-+ tasklet_kill(&info->tlet);
-+ kfree(info);
-+ }
-+
-+ up(&state->sem);
-+}
-+
-+/**
-+ * uart_register_driver - register a driver with the uart core layer
-+ * @drv: low level driver structure
-+ *
-+ * Register a uart driver with the core driver. We in turn register
-+ * with the tty layer, and initialise the core driver per-port state.
-+ *
-+ * We have a proc file in /proc/tty/driver which is named after the
-+ * normal driver.
-+ *
-+ * drv->port should be NULL, and the per-port structures should be
-+ * registered using uart_add_one_port after this call has succeeded.
-+ */
-+int uart_register_driver(struct uart_driver *drv)
-+{
-+ struct tty_driver *normal, *callout;
-+ int i, retval;
-+
-+ BUG_ON(drv->state);
-+
-+ /*
-+ * Maybe we should be using a slab cache for this, especially if
-+ * we have a large number of ports to handle. Note that we also
-+ * allocate space for an integer for reference counting.
-+ */
-+ drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +
-+ sizeof(int), GFP_KERNEL);
-+ retval = -ENOMEM;
-+ if (!drv->state)
-+ goto out;
-+
-+ memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
-+ sizeof(int));
-+
-+ normal = drv->normal_driver;
-+ callout = drv->callout_driver;
-+
-+ normal->magic = TTY_DRIVER_MAGIC;
-+ normal->driver_name = drv->normal_name;
-+ normal->name = drv->normal_name;
-+ normal->major = drv->normal_major;
-+ normal->minor_start = drv->minor;
-+ normal->num = drv->nr;
-+ normal->type = TTY_DRIVER_TYPE_SERIAL;
-+ normal->subtype = SERIAL_TYPE_NORMAL;
-+ normal->init_termios = tty_std_termios;
-+ normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-+ normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-+ normal->refcount = (int *)(drv->state + drv->nr);
-+ normal->table = drv->table;
-+ normal->termios = drv->termios;
-+ normal->termios_locked = drv->termios_locked;
-+ normal->driver_state = drv;
-+
-+ normal->open = uart_open;
-+ normal->close = uart_close;
-+ normal->write = uart_write;
-+ normal->put_char = uart_put_char;
-+ normal->flush_chars = uart_flush_chars;
-+ normal->write_room = uart_write_room;
-+ normal->chars_in_buffer = uart_chars_in_buffer;
-+ normal->flush_buffer = uart_flush_buffer;
-+ normal->ioctl = uart_ioctl;
-+ normal->throttle = uart_throttle;
-+ normal->unthrottle = uart_unthrottle;
-+ normal->send_xchar = uart_send_xchar;
-+ normal->set_termios = uart_set_termios;
-+ normal->stop = uart_stop;
-+ normal->start = uart_start;
-+ normal->hangup = uart_hangup;
-+ normal->break_ctl = uart_break_ctl;
-+ normal->wait_until_sent = uart_wait_until_sent;
-+#ifdef CONFIG_PROC_FS
-+ normal->read_proc = uart_read_proc;
-+#endif
-+
-+ /*
-+ * The callout device is just like the normal device except for
-+ * the major number and the subtype code.
-+ */
-+ *callout = *normal;
-+ callout->name = drv->callout_name;
-+ callout->major = drv->callout_major;
-+ callout->subtype = SERIAL_TYPE_CALLOUT;
-+ callout->read_proc = NULL;
-+ callout->proc_entry = NULL;
-+
-+ /*
-+ * Initialise the UART state(s).
-+ */
-+ for (i = 0; i < drv->nr; i++) {
-+ struct uart_state *state = drv->state + i;
-+
-+ state->callout_termios = callout->init_termios;
-+ state->normal_termios = normal->init_termios;
-+ state->close_delay = 5 * HZ / 10;
-+ state->closing_wait = 30 * HZ;
-+
-+ init_MUTEX(&state->sem);
-+ }
-+
-+ retval = tty_register_driver(normal);
-+ if (retval)
-+ goto out;
-+
-+ retval = tty_register_driver(callout);
-+ if (retval)
-+ tty_unregister_driver(normal);
-+
-+ out:
-+ if (retval < 0) {
-+ kfree(drv->state);
-+ }
-+ return retval;
-+}
-+
-+/**
-+ * uart_unregister_driver - remove a driver from the uart core layer
-+ * @drv: low level driver structure
-+ *
-+ * Remove all references to a driver from the core driver. The low
-+ * level driver must have removed all its ports via the
-+ * uart_remove_one_port() if it registered them with uart_add_one_port().
-+ * (ie, drv->port == NULL)
-+ */
-+void uart_unregister_driver(struct uart_driver *drv)
-+{
-+ tty_unregister_driver(drv->normal_driver);
-+ tty_unregister_driver(drv->callout_driver);
-+
-+ kfree(drv->state);
-+ drv->state = NULL;
-+}
-+
-+/**
-+ * uart_add_one_port - attach a driver-defined port structure
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure to use for this port.
-+ *
-+ * This allows the driver to register its own uart_port structure
-+ * with the core driver. The main purpose is to allow the low
-+ * level uart drivers to expand uart_port, rather than having yet
-+ * more levels of structures.
-+ */
-+int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state;
-+ int ret = 0;
-+
-+ BUG_ON(in_interrupt());
-+
-+ if (port->line >= drv->nr)
-+ return -EINVAL;
-+
-+ state = drv->state + port->line;
-+
-+ down(&port_sem);
-+ if (state->port) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ state->port = port;
-+
-+ spin_lock_init(&port->lock);
-+ port->cons = drv->cons;
-+ port->info = state->info;
-+
-+ uart_configure_port(drv, state, port);
-+
-+ /*
-+ * Register the port whether it's detected or not. This allows
-+ * setserial to be used to alter this ports parameters.
-+ */
-+ tty_register_devfs(drv->normal_driver, 0, drv->minor + port->line);
-+ tty_register_devfs(drv->callout_driver, 0, drv->minor + port->line);
-+
-+#ifdef CONFIG_PM
-+ port->cons = drv->cons;
-+ state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
-+ if (state->pm)
-+ state->pm->data = state;
-+#endif
-+
-+ out:
-+ up(&port_sem);
-+
-+ return ret;
-+}
-+
-+/**
-+ * uart_remove_one_port - detach a driver defined port structure
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure for this port
-+ *
-+ * This unhooks (and hangs up) the specified port structure from the
-+ * core driver. No further calls will be made to the low-level code
-+ * for this port.
-+ */
-+int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state = drv->state + port->line;
-+
-+ BUG_ON(in_interrupt());
-+
-+ if (state->port != port)
-+ printk(KERN_ALERT "Removing wrong port: %p != %p\n",
-+ state->port, port);
-+
-+ down(&port_sem);
-+
-+ pm_unregister(state->pm);
-+
-+ /*
-+ * Remove the devices from devfs
-+ */
-+ tty_unregister_devfs(drv->normal_driver, drv->minor + port->line);
-+ tty_unregister_devfs(drv->callout_driver, drv->minor + port->line);
-+
-+ uart_unconfigure_port(drv, state);
-+ state->port = NULL;
-+ up(&port_sem);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Are the two ports equivalent?
-+ */
-+static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
-+{
-+ if (port1->iotype != port2->iotype)
-+ return 0;
-+
-+ switch (port1->iotype) {
-+ case UPIO_PORT:
-+ return (port1->iobase == port2->iobase);
-+ case UPIO_HUB6:
-+ return (port1->iobase == port2->iobase) &&
-+ (port1->hub6 == port2->hub6);
-+ case UPIO_MEM:
-+ return (port1->membase == port2->membase);
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Try to find an unused uart_state slot for a port.
-+ */
-+static struct uart_state *
-+uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
-+{
-+ int i;
-+
-+ /*
-+ * First, find a port entry which matches. Note: if we do
-+ * find a matching entry, and it has a non-zero use count,
-+ * then we can't register the port.
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (uart_match_port(drv->state[i].port, port))
-+ return &drv->state[i];
-+
-+ /*
-+ * We didn't find a matching entry, so look for the first
-+ * free entry. We look for one which hasn't been previously
-+ * used (indicated by zero iobase).
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (drv->state[i].port->type == PORT_UNKNOWN &&
-+ drv->state[i].port->iobase == 0 &&
-+ drv->state[i].count == 0)
-+ return &drv->state[i];
-+
-+ /*
-+ * That also failed. Last resort is to find any currently
-+ * entry which doesn't have a real port associated with it.
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (drv->state[i].port->type == PORT_UNKNOWN &&
-+ drv->state[i].count == 0)
-+ return &drv->state[i];
-+
-+ return NULL;
-+}
-+
-+/**
-+ * uart_register_port: register uart settings with a port
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure describing the port
-+ *
-+ * Register UART settings with the specified low level driver. Detect
-+ * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
-+ * IRQ if UPF_AUTO_IRQ is set.
-+ *
-+ * We try to pick the same port for the same IO base address, so that
-+ * when a modem is plugged in, unplugged and plugged back in, it gets
-+ * allocated the same port.
-+ *
-+ * Returns negative error, or positive line number.
-+ */
-+int uart_register_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state;
-+ int ret;
-+
-+ down(&port_sem);
-+
-+ state = uart_find_match_or_unused(drv, port);
-+
-+ if (state) {
-+ /*
-+ * Ok, we've found a line that we can use.
-+ *
-+ * If we find a port that matches this one, and it appears
-+ * to be in-use (even if it doesn't have a type) we shouldn't
-+ * alter it underneath itself - the port may be open and
-+ * trying to do useful work.
-+ */
-+ if (uart_users(state) != 0) {
-+ ret = -EBUSY;
-+ goto out;
-+ }
-+
-+ /*
-+ * If the port is already initialised, don't touch it.
-+ */
-+ if (state->port->type == PORT_UNKNOWN) {
-+ state->port->iobase = port->iobase;
-+ state->port->membase = port->membase;
-+ state->port->irq = port->irq;
-+ state->port->uartclk = port->uartclk;
-+ state->port->fifosize = port->fifosize;
-+ state->port->regshift = port->regshift;
-+ state->port->iotype = port->iotype;
-+ state->port->flags = port->flags;
-+ state->port->line = state - drv->state;
-+ state->port->mapbase = port->mapbase;
-+
-+ uart_configure_port(drv, state, state->port);
-+ }
-+
-+ ret = state->port->line;
-+ } else
-+ ret = -ENOSPC;
-+ out:
-+ up(&port_sem);
-+ return ret;
-+}
-+
-+/**
-+ * uart_unregister_port - de-allocate a port
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @line: line index previously returned from uart_register_port()
-+ *
-+ * Hang up the specified line associated with the low level driver,
-+ * and mark the port as unused.
-+ */
-+void uart_unregister_port(struct uart_driver *drv, int line)
-+{
-+ struct uart_state *state;
-+
-+ if (line < 0 || line >= drv->nr) {
-+ printk(KERN_ERR "Attempt to unregister %s%d\n",
-+ drv->normal_name, line);
-+ return;
-+ }
-+
-+ state = drv->state + line;
-+
-+ down(&port_sem);
-+ uart_unconfigure_port(drv, state);
-+ up(&port_sem);
-+}
-+
-+EXPORT_SYMBOL(uart_write_wakeup);
-+EXPORT_SYMBOL(uart_register_driver);
-+EXPORT_SYMBOL(uart_unregister_driver);
-+EXPORT_SYMBOL(uart_register_port);
-+EXPORT_SYMBOL(uart_unregister_port);
-+EXPORT_SYMBOL(uart_add_one_port);
-+EXPORT_SYMBOL(uart_remove_one_port);
-+
-+MODULE_DESCRIPTION("Serial driver core");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/omaha.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,584 @@
-+/*
-+ * linux/drivers/char/omaha.c
-+ *
-+ * Driver for Omaha serial port
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999-2002 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: serial_amba.c,v 1.4 2001/07/17 20:34:27 rmk Exp $
-+ *
-+ * This is a generic driver for ARM AMBA-type serial ports. They
-+ * have a lot of 16550-like features, but are not register compatable.
-+ * Note that although they do have CTS, DCD and DSR inputs, they do
-+ * not have an RI input, nor do they have DTR or RTS outputs. If
-+ * required, these have to be supplied via some other means (eg, GPIO)
-+ * and hooked into this driver.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#if defined(CONFIG_SERIAL_OMAHA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/serial_omaha.h>
-+
-+#define UART_NR 1
-+
-+#define SERIAL_OMAHA_MAJOR 204
-+#define SERIAL_OMAHA_MINOR 32
-+#define SERIAL_OMAHA_NR UART_NR
-+
-+#define CALLOUT_OMAHA_NAME "cuaom"
-+#define CALLOUT_OMAHA_MAJOR 205
-+#define CALLOUT_OMAHA_MINOR 32
-+#define CALLOUT_OMAHA_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *omaha_table[UART_NR];
-+static struct termios *omaha_termios[UART_NR], *omaha_termios_locked[UART_NR];
-+#ifdef SUPPORT_SYSRQ
-+static struct console omaha_console;
-+#endif
-+
-+#define OMAHA_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the Omaha UARTs
-+ */
-+
-+#define UART_GET_FR(p) readb((p)->membase + OMAHA_UTRSTAT)
-+#define UART_GET_CHAR(p) readb((p)->membase + OMAHA_URXH)
-+#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + OMAHA_UTXH)
-+#define UART_GET_RSR(p) readb((p)->membase + OMAHA_UERSTAT)
-+#define UART_FIFO_STATUS(p) (readl((p)->membase + OMAHA_UFSTAT))
-+#define UART_RX_DATA(s) (((s) & OMAHA_RXFF_CNT) != 0)
-+#define UART_TX_DATA(s) (!((s) & OMAHA_TXFF))
-+#define UART_TX_READY(s) (((s) & OMAHA_UTX_EMPTY))
-+#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & OMAHA_UTXEMPTY) != 0)
-+
-+#define UART_DUMMY_RSR_RX 256
-+#define UART_PORT_SIZE 64
-+
-+#define RX_IRQ(port) ((port)->irq)
-+#define TX_IRQ(port) ((port)->irq + 5)
-+
-+/*
-+ * Our private driver data mappings.
-+ */
-+#define drv_old_status driver_priv
-+
-+static void omahauart_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ disable_irq(TX_IRQ(port));
-+}
-+
-+static void omahauart_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
-+{
-+ if (nonempty)
-+ enable_irq(TX_IRQ(port));
-+}
-+
-+static void omahauart_stop_rx(struct uart_port *port)
-+{
-+ disable_irq(RX_IRQ(port));
-+}
-+
-+static void omahauart_enable_ms(struct uart_port *port)
-+{
-+ // Do nothing...
-+}
-+
-+static void
-+#ifdef SUPPORT_SYSRQ
-+omahauart_rx_chars(struct uart_info *info, struct pt_regs *regs)
-+#else
-+omahauart_rx_chars(struct uart_info *info)
-+#endif
-+{
-+ struct tty_struct *tty = info->tty;
-+ volatile unsigned int status, data, ch, rsr, max_count = 256;
-+ struct uart_port *port = info->port;
-+
-+ status = UART_FIFO_STATUS(port);
-+ while (UART_RX_DATA(status) && max_count--) {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-+ return;
-+ }
-+ }
-+
-+ ch = UART_GET_CHAR(port);
-+
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ port->icount.rx++;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
-+ if (rsr & 0xf) {
-+ if (rsr & OMAHA_UART_BREAK) {
-+ rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY);
-+ port->icount.brk++;
-+ if (uart_handle_break(info, &omaha_console))
-+ goto ignore_char;
-+ } else if (rsr & OMAHA_UART_PARITY)
-+ port->icount.parity++;
-+ else if (rsr & OMAHA_UART_FRAME)
-+ port->icount.frame++;
-+ if (rsr & OMAHA_UART_OVERRUN)
-+ port->icount.overrun++;
-+
-+ rsr &= port->read_status_mask;
-+
-+ if (rsr & OMAHA_UART_BREAK)
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ else if (rsr & OMAHA_UART_PARITY)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (rsr & OMAHA_UART_FRAME)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+
-+ if (uart_handle_sysrq_char(info, ch, regs))
-+ goto ignore_char;
-+
-+ if ((rsr & port->ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((rsr & OMAHA_UART_OVERRUN) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character
-+ */
-+ *tty->flip.char_buf_ptr++ = 0;
-+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ status = UART_FIFO_STATUS(port);
-+ }
-+ tty_flip_buffer_push(tty);
-+ return;
-+}
-+
-+static void omahauart_tx_chars(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+ volatile unsigned int status;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ omahauart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ status = UART_FIFO_STATUS(info->port);
-+
-+ // FIll FIFO as far as possible
-+ while(UART_TX_DATA(UART_FIFO_STATUS(info->port)))
-+ {
-+ UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (info->xmit.head == info->xmit.tail)
-+ break;
-+ }
-+
-+ if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
-+ WAKEUP_CHARS)
-+ uart_event(info, EVT_WRITE_WAKEUP);
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ omahauart_stop_tx(info->port, 0);
-+}
-+
-+static void omahauart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_info *info = dev_id;
-+ volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ do {
-+ // TX if FIFO not full
-+ if (UART_TX_DATA(status))
-+ omahauart_tx_chars(info);
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ } while (UART_TX_DATA(status));
-+}
-+
-+static void omahauart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_info *info = dev_id;
-+ volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ do {
-+ if (UART_RX_DATA(status))
-+#ifdef SUPPORT_SYSRQ
-+ omahauart_rx_chars(info, regs);
-+#else
-+ omahauart_rx_chars(info);
-+#endif
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ } while (UART_RX_DATA(status));
-+}
-+
-+static u_int omahauart_tx_empty(struct uart_port *port)
-+{
-+ return UART_FIFO_STATUS(port) ? 0 : TIOCSER_TEMT;
-+}
-+
-+static int omahauart_get_mctrl(struct uart_port *port)
-+{
-+ // Report no errors.
-+
-+ return 0;
-+}
-+
-+static void omahauart_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ // Do nothing.
-+}
-+
-+static void omahauart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ // Do nothing.
-+}
-+
-+static int omahauart_startup(struct uart_port *port, struct uart_info *info)
-+{
-+ unsigned int tmp;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQs
-+ */
-+ retval = request_irq(TX_IRQ(port), omahauart_int_tx, 0, "omaha_uart_tx", info);
-+ if (retval)
-+ return retval;
-+
-+ retval = request_irq(RX_IRQ(port), omahauart_int_rx, 0, "omaha_uart_rx", info);
-+
-+ if (retval)
-+ {
-+ free_irq(TX_IRQ(port), info);
-+ return retval;
-+ }
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ info->drv_old_status = 0;
-+
-+ // Clear all errors
-+ writel(0, port->membase + OMAHA_UERSTAT);
-+
-+ // Enable FIFO, 16-byte watermark, also do reset (auto-clearing)
-+ writel(0xF7, port->membase + OMAHA_UFCON);
-+
-+ // Level driven TX/RX ints, with rx timeout enabled
-+ tmp = readl(port->membase + OMAHA_UCON);
-+ tmp |= 0x280; // rx is pulse driven...
-+ writel(tmp, port->membase + OMAHA_UCON);
-+
-+ return 0;
-+}
-+
-+static void omahauart_shutdown(struct uart_port *port, struct uart_info *info)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(TX_IRQ(port), info); /* TX interrupt */
-+ free_irq(RX_IRQ(port), info); /* RX interrupt */
-+
-+}
-+
-+static void omahauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ // Do nothing.
-+}
-+
-+static const char *omahauart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_OMAHA ? "OMAHA" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void omahauart_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int omahauart_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_omaha")
-+ != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void omahauart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_OMAHA;
-+ omahauart_request_port(port);
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int omahauart_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_OMAHA)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops omaha_pops = {
-+ .tx_empty = omahauart_tx_empty,
-+ .set_mctrl = omahauart_set_mctrl,
-+ .get_mctrl = omahauart_get_mctrl,
-+ .stop_tx = omahauart_stop_tx,
-+ .start_tx = omahauart_start_tx,
-+ .stop_rx = omahauart_stop_rx,
-+ .enable_ms = omahauart_enable_ms,
-+ .break_ctl = omahauart_break_ctl,
-+ .startup = omahauart_startup,
-+ .shutdown = omahauart_shutdown,
-+ .change_speed = omahauart_change_speed,
-+ .type = omahauart_type,
-+ .release_port = omahauart_release_port,
-+ .request_port = omahauart_request_port,
-+ .config_port = omahauart_config_port,
-+ .verify_port = omahauart_verify_port,
-+};
-+
-+static struct uart_port omaha_ports[UART_NR] = {
-+ {
-+ .membase = (void *)IO_ADDRESS(OMAHA_UART0_BASE),
-+ .mapbase = OMAHA_UART0_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = OMAHA_INT_URXD0,
-+ .uartclk = 10000000,
-+ .fifosize = 8,
-+ .unused = { 4, 5 }, /*Udriver_priv: PORT_CTRLS(5, 4), */
-+ .ops = &omaha_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_OMAHA_CONSOLE
-+static void omahauart_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = omaha_ports + co->index;
-+ unsigned int status;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the TCR
-+ */
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+}
-+
-+static kdev_t omahauart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_OMAHA_MAJOR, SERIAL_OMAHA_MINOR + co->index);
-+}
-+
-+static int omahauart_console_wait_key(struct console *co)
-+{
-+ struct uart_port *port = omaha_ports + co->index;
-+ unsigned int status;
-+
-+ do {
-+ status = UART_FIFO_STATUS(port);
-+ } while (!UART_RX_DATA(status));
-+ return UART_GET_CHAR(port);
-+}
-+
-+static void __init
-+omahauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ // Do nothing.
-+}
-+
-+static int __init omahauart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(omaha_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ omahauart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console omaha_console = {
-+ .write = omahauart_console_write,
-+ .device = omahauart_console_device,
-+ .wait_key = omahauart_console_wait_key,
-+ .setup = omahauart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init omahauart_console_init(void)
-+{
-+ register_console(&omaha_console);
-+}
-+
-+#define OMAHA_CONSOLE &omaha_console
-+#else
-+#define OMAHA_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver omaha_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_OMAHA_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttyOM%d",
-+ .callout_name = "cuaom%d",
-+#else
-+ .normal_name = "ttyOM",
-+ .callout_name = "cuaom",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_OMAHA_MAJOR,
-+ .callout_driver = &callout,
-+ .table = omaha_table,
-+ .termios = omaha_termios,
-+ .termios_locked = omaha_termios_locked,
-+ .minor = SERIAL_OMAHA_MINOR,
-+ .nr = UART_NR,
-+ .port = omaha_ports,
-+ .cons = OMAHA_CONSOLE,
-+};
-+
-+static int __init omahauart_init(void)
-+{
-+ return uart_register_driver(&omaha_reg);
-+}
-+
-+static void __exit omahauart_exit(void)
-+{
-+ uart_unregister_driver(&omaha_reg);
-+}
-+
-+module_init(omahauart_init);
-+module_exit(omahauart_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/sa1100.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,904 @@
-+/*
-+ * linux/drivers/char/serial_sa1100.c
-+ *
-+ * Driver for SA11x0 serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: sa1100.c,v 1.14.2.4 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/mach/serial_sa1100.h>
-+
-+#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+/* We've been assigned a range on the "Low-density serial ports" major */
-+#define SERIAL_SA1100_MAJOR 204
-+#define CALLOUT_SA1100_MAJOR 205
-+#define MINOR_START 5
-+
-+#define NR_PORTS 3
-+
-+#define SA1100_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Convert from ignore_status_mask or read_status_mask to UTSR[01]
-+ */
-+#define SM_TO_UTSR0(x) ((x) & 0xff)
-+#define SM_TO_UTSR1(x) ((x) >> 8)
-+#define UTSR0_TO_SM(x) ((x))
-+#define UTSR1_TO_SM(x) ((x) << 8)
-+
-+#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
-+#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
-+#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
-+#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
-+#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
-+#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
-+#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
-+
-+#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
-+#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
-+#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
-+#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
-+#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
-+#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
-+#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
-+
-+/*
-+ * This is the size of our serial port register set.
-+ */
-+#define UART_PORT_SIZE 0x24
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *sa1100_table[NR_PORTS];
-+static struct termios *sa1100_termios[NR_PORTS], *sa1100_termios_locked[NR_PORTS];
-+static int (*sa1100_open)(struct uart_port *);
-+static void (*sa1100_close)(struct uart_port *);
-+#ifdef SUPPORT_SYSRQ
-+static struct console sa1100_console;
-+#endif
-+
-+/*
-+ * This determines how often we check the modem status signals
-+ * for any change. They generally aren't connected to an IRQ
-+ * so we have to poll them. We also check immediately before
-+ * filling the TX fifo incase CTS has been dropped.
-+ */
-+#define MCTRL_TIMEOUT (250*HZ/1000)
-+
-+struct sa1100_port {
-+ struct uart_port port;
-+ struct timer_list timer;
-+ unsigned int old_status;
-+};
-+
-+/*
-+ * Handle any change of modem status signal since we were last called.
-+ */
-+static void sa1100_mctrl_check(struct sa1100_port *sport)
-+{
-+ unsigned int status, changed;
-+
-+ status = sport->port.ops->get_mctrl(&sport->port);
-+ changed = status ^ sport->old_status;
-+
-+ if (changed == 0)
-+ return;
-+
-+ sport->old_status = status;
-+
-+ if (changed & TIOCM_RI)
-+ sport->port.icount.rng++;
-+ if (changed & TIOCM_DSR)
-+ sport->port.icount.dsr++;
-+ if (changed & TIOCM_CAR)
-+ uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
-+ if (changed & TIOCM_CTS)
-+ uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-+
-+ wake_up_interruptible(&sport->port.info->delta_msr_wait);
-+}
-+
-+/*
-+ * This is our per-port timeout handler, for checking the
-+ * modem status signals.
-+ */
-+static void sa1100_timeout(unsigned long data)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)data;
-+ unsigned long flags;
-+
-+ if (sport->port.info) {
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ sa1100_mctrl_check(sport);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+
-+ mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
-+ }
-+}
-+
-+/*
-+ * interrupts disabled on entry
-+ */
-+static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ u32 utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
-+ sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
-+}
-+
-+/*
-+ * interrupts may not be disabled on entry
-+ */
-+static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ u32 utcr3;
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ utcr3 = UART_GET_UTCR3(sport);
-+ sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
-+ UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+/*
-+ * Interrupts enabled
-+ */
-+static void sa1100_stop_rx(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ u32 utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
-+}
-+
-+/*
-+ * Set the modem control timer to fire immediately.
-+ */
-+static void sa1100_enable_ms(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ mod_timer(&sport->timer, jiffies);
-+}
-+
-+static void
-+sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
-+{
-+ struct tty_struct *tty = sport->port.info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
-+ UTSR0_TO_SM(UART_GET_UTSR0(sport));
-+ while (status & UTSR1_TO_SM(UTSR1_RNE)) {
-+ ch = UART_GET_CHAR(sport);
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ sport->port.icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(&sport->port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
-+ UTSR0_TO_SM(UART_GET_UTSR0(sport));
-+ }
-+ out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+ handle_error:
-+ if (status & UTSR1_TO_SM(UTSR1_PRE))
-+ sport->port.icount.parity++;
-+ else if (status & UTSR1_TO_SM(UTSR1_FRE))
-+ sport->port.icount.frame++;
-+ if (status & UTSR1_TO_SM(UTSR1_ROR))
-+ sport->port.icount.overrun++;
-+
-+ if (status & sport->port.ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+
-+ status &= sport->port.read_status_mask;
-+
-+ if (status & UTSR1_TO_SM(UTSR1_PRE))
-+ flg = TTY_PARITY;
-+ else if (status & UTSR1_TO_SM(UTSR1_FRE))
-+ flg = TTY_FRAME;
-+
-+ if (status & UTSR1_TO_SM(UTSR1_ROR)) {
-+ /*
-+ * overrun does *not* affect the character
-+ * we read from the FIFO
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ sport->port.sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void sa1100_tx_chars(struct sa1100_port *sport)
-+{
-+ struct circ_buf *xmit = &sport->port.info->xmit;
-+
-+ if (sport->port.x_char) {
-+ UART_PUT_CHAR(sport, sport->port.x_char);
-+ sport->port.icount.tx++;
-+ sport->port.x_char = 0;
-+ return;
-+ }
-+
-+ /*
-+ * Check the modem control lines before
-+ * transmitting anything.
-+ */
-+ sa1100_mctrl_check(sport);
-+
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-+ sa1100_stop_tx(&sport->port, 0);
-+ return;
-+ }
-+
-+ /*
-+ * Tried using FIFO (not checking TNF) for fifo fill:
-+ * still had the '4 bytes repeated' problem.
-+ */
-+ while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
-+ UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ sport->port.icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ }
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&sport->port);
-+
-+ if (uart_circ_empty(xmit))
-+ sa1100_stop_tx(&sport->port, 0);
-+}
-+
-+static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct sa1100_port *sport = dev_id;
-+ unsigned int status, pass_counter = 0;
-+
-+ spin_lock(&sport->port.lock);
-+ status = UART_GET_UTSR0(sport);
-+ status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
-+ do {
-+ if (status & (UTSR0_RFS | UTSR0_RID)) {
-+ /* Clear the receiver idle bit, if set */
-+ if (status & UTSR0_RID)
-+ UART_PUT_UTSR0(sport, UTSR0_RID);
-+ sa1100_rx_chars(sport, regs);
-+ }
-+
-+ /* Clear the relevant break bits */
-+ if (status & (UTSR0_RBB | UTSR0_REB))
-+ UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
-+
-+ if (status & UTSR0_RBB)
-+ sport->port.icount.brk++;
-+
-+ if (status & UTSR0_REB)
-+ uart_handle_break(&sport->port);
-+
-+ if (status & UTSR0_TFS)
-+ sa1100_tx_chars(sport);
-+ if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
-+ break;
-+ status = UART_GET_UTSR0(sport);
-+ status &= SM_TO_UTSR0(sport->port.read_status_mask) |
-+ ~UTSR0_TFS;
-+ } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
-+ spin_unlock(&sport->port.lock);
-+}
-+
-+/*
-+ * Return TIOCSER_TEMT when transmitter is not busy.
-+ */
-+static unsigned int sa1100_tx_empty(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int sa1100_get_mctrl(struct uart_port *port)
-+{
-+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-+}
-+
-+static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+}
-+
-+/*
-+ * Interrupts always disabled.
-+ */
-+static void sa1100_break_ctl(struct uart_port *port, int break_state)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ unsigned int utcr3;
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ utcr3 = UART_GET_UTCR3(sport);
-+ if (break_state == -1)
-+ utcr3 |= UTCR3_BRK;
-+ else
-+ utcr3 &= ~UTCR3_BRK;
-+ UART_PUT_UTCR3(sport, utcr3);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+static int sa1100_startup(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(sport->port.irq, sa1100_int, 0,
-+ "sa11x0-uart", sport);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * If there is a specific "open" function
-+ * (to register control line interrupts)
-+ */
-+ if (sa1100_open) {
-+ retval = sa1100_open(port);
-+ if (retval) {
-+ free_irq(sport->port.irq, sport);
-+ return retval;
-+ }
-+ }
-+
-+ /*
-+ * Finally, clear and enable interrupts
-+ */
-+ UART_PUT_UTSR0(sport, -1);
-+ UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
-+
-+ return 0;
-+}
-+
-+static void sa1100_shutdown(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ /*
-+ * Stop our timer.
-+ */
-+ del_timer_sync(&sport->timer);
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(sport->port.irq, sport);
-+
-+ /*
-+ * If there is a specific "close" function (to unregister
-+ * control line interrupts)
-+ */
-+ if (sa1100_close)
-+ sa1100_close(port);
-+
-+ /*
-+ * Disable all interrupts, port and break condition.
-+ */
-+ UART_PUT_UTCR3(sport, 0);
-+}
-+
-+static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ unsigned int utcr0, old_utcr3;
-+
-+ if ((cflag & CSIZE) == CS8)
-+ utcr0 = UTCR0_DSS;
-+ else
-+ utcr0 = 0;
-+
-+ if (cflag & CSTOPB)
-+ utcr0 |= UTCR0_SBS;
-+ if (cflag & PARENB) {
-+ utcr0 |= UTCR0_PE;
-+ if (!(cflag & PARODD))
-+ utcr0 |= UTCR0_OES;
-+ }
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+
-+ sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
-+ sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
-+ if (iflag & INPCK)
-+ sport->port.read_status_mask |=
-+ UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-+ if (iflag & (BRKINT | PARMRK))
-+ sport->port.read_status_mask |=
-+ UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ sport->port.ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ sport->port.ignore_status_mask |=
-+ UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-+ if (iflag & IGNBRK) {
-+ sport->port.ignore_status_mask |=
-+ UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ sport->port.ignore_status_mask |=
-+ UTSR1_TO_SM(UTSR1_ROR);
-+ }
-+
-+ del_timer_sync(&sport->timer);
-+
-+ /*
-+ * disable interrupts and drain transmitter
-+ */
-+ old_utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
-+
-+ while (UART_GET_UTSR1(sport) & UTSR1_TBY)
-+ barrier();
-+
-+ /* then, disable everything */
-+ UART_PUT_UTCR3(sport, 0);
-+
-+ /* set the parity, stop bits and data size */
-+ UART_PUT_UTCR0(sport, utcr0);
-+
-+ /* set the baud rate */
-+ quot -= 1;
-+ UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
-+ UART_PUT_UTCR2(sport, (quot & 0xff));
-+
-+ UART_PUT_UTSR0(sport, -1);
-+
-+ UART_PUT_UTCR3(sport, old_utcr3);
-+
-+ if (UART_ENABLE_MS(&sport->port, cflag))
-+ sa1100_enable_ms(&sport->port);
-+
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+static const char *sa1100_type(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'.
-+ */
-+static void sa1100_release_port(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'.
-+ */
-+static int sa1100_request_port(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
-+ "sa11x0-uart") != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void sa1100_config_port(struct uart_port *port, int flags)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ if (flags & UART_CONFIG_TYPE &&
-+ sa1100_request_port(&sport->port) == 0)
-+ sport->port.type = PORT_SA1100;
-+}
-+
-+/*
-+ * Verify the new serial_struct (for TIOCSSERIAL).
-+ * The only change we allow are to the flags and type, and
-+ * even then only between PORT_SA1100 and PORT_UNKNOWN
-+ */
-+static int sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ int ret = 0;
-+
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
-+ ret = -EINVAL;
-+ if (sport->port.irq != ser->irq)
-+ ret = -EINVAL;
-+ if (ser->io_type != SERIAL_IO_MEM)
-+ ret = -EINVAL;
-+ if (sport->port.uartclk / 16 != ser->baud_base)
-+ ret = -EINVAL;
-+ if ((void *)sport->port.mapbase != ser->iomem_base)
-+ ret = -EINVAL;
-+ if (sport->port.iobase != ser->port)
-+ ret = -EINVAL;
-+ if (ser->hub6 != 0)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops sa1100_pops = {
-+ .tx_empty = sa1100_tx_empty,
-+ .set_mctrl = sa1100_set_mctrl,
-+ .get_mctrl = sa1100_get_mctrl,
-+ .stop_tx = sa1100_stop_tx,
-+ .start_tx = sa1100_start_tx,
-+ .stop_rx = sa1100_stop_rx,
-+ .enable_ms = sa1100_enable_ms,
-+ .break_ctl = sa1100_break_ctl,
-+ .startup = sa1100_startup,
-+ .shutdown = sa1100_shutdown,
-+ .change_speed = sa1100_change_speed,
-+ .type = sa1100_type,
-+ .release_port = sa1100_release_port,
-+ .request_port = sa1100_request_port,
-+ .config_port = sa1100_config_port,
-+ .verify_port = sa1100_verify_port,
-+};
-+
-+static struct sa1100_port sa1100_ports[NR_PORTS];
-+
-+/*
-+ * Setup the SA1100 serial ports. Note that we don't include the IrDA
-+ * port here since we have our own SIR/FIR driver (see drivers/net/irda)
-+ *
-+ * Note also that we support "console=ttySAx" where "x" is either 0 or 1.
-+ * Which serial port this ends up being depends on the machine you're
-+ * running this kernel on. I'm not convinced that this is a good idea,
-+ * but that's the way it traditionally works.
-+ *
-+ * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
-+ * used here.
-+ */
-+static void __init sa1100_init_ports(void)
-+{
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0; i < NR_PORTS; i++) {
-+ sa1100_ports[i].port.uartclk = 3686400;
-+ sa1100_ports[i].port.ops = &sa1100_pops;
-+ sa1100_ports[i].port.fifosize = 8;
-+ sa1100_ports[i].port.line = i;
-+ sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
-+ init_timer(&sa1100_ports[i].timer);
-+ sa1100_ports[i].timer.function = sa1100_timeout;
-+ sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
-+ }
-+
-+ /*
-+ * make transmit lines outputs, so that when the port
-+ * is closed, the output is in the MARK state.
-+ */
-+ PPDR |= PPC_TXD1 | PPC_TXD3;
-+ PPSR |= PPC_TXD1 | PPC_TXD3;
-+}
-+
-+void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
-+{
-+ if (fns->enable_ms)
-+ sa1100_pops.enable_ms = fns->enable_ms;
-+ if (fns->get_mctrl)
-+ sa1100_pops.get_mctrl = fns->get_mctrl;
-+ if (fns->set_mctrl)
-+ sa1100_pops.set_mctrl = fns->set_mctrl;
-+ sa1100_open = fns->open;
-+ sa1100_close = fns->close;
-+ sa1100_pops.pm = fns->pm;
-+ sa1100_pops.set_wake = fns->set_wake;
-+}
-+
-+void __init sa1100_register_uart(int idx, int port)
-+{
-+ if (idx >= NR_PORTS) {
-+ printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
-+ return;
-+ }
-+
-+ switch (port) {
-+ case 1:
-+ sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser1UART;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ case 2:
-+ sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ case 3:
-+ sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser3UART;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
-+ }
-+}
-+
-+
-+#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-+
-+/*
-+ * Interrupts are disabled on entering
-+ */
-+static void
-+sa1100_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct sa1100_port *sport = &sa1100_ports[co->index];
-+ unsigned int old_utcr3, status, i;
-+
-+ /*
-+ * First, save UTCR3 and then disable interrupts
-+ */
-+ old_utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
-+ UTCR3_TXE);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (!(status & UTSR1_TNF));
-+ UART_PUT_CHAR(sport, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (!(status & UTSR1_TNF));
-+ UART_PUT_CHAR(sport, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore UTCR3
-+ */
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (status & UTSR1_TBY);
-+ UART_PUT_UTCR3(sport, old_utcr3);
-+}
-+
-+static kdev_t sa1100_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_SA1100_MAJOR, MINOR_START + co->index);
-+}
-+
-+/*
-+ * If the port was already initialised (eg, by a boot loader), try to determine
-+ * the current setup.
-+ */
-+static void __init
-+sa1100_console_get_options(struct sa1100_port *sport, int *baud,
-+ int *parity, int *bits)
-+{
-+ unsigned int utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
-+ if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
-+ /* ok, the port was enabled */
-+ unsigned int utcr0, quot;
-+
-+ utcr0 = UART_GET_UTCR0(sport);
-+
-+ *parity = 'n';
-+ if (utcr0 & UTCR0_PE) {
-+ if (utcr0 & UTCR0_OES)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if (utcr0 & UTCR0_DSS)
-+ *bits = 8;
-+ else
-+ *bits = 7;
-+
-+ quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
-+ quot &= 0xfff;
-+ *baud = sport->port.uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init
-+sa1100_console_setup(struct console *co, char *options)
-+{
-+ struct sa1100_port *sport;
-+ int baud = CONFIG_SA1100_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index == -1 || co->index >= NR_PORTS)
-+ co->index = 0;
-+ sport = &sa1100_ports[co->index];
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ sa1100_console_get_options(sport, &baud, &parity, &bits);
-+
-+ return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console sa1100_console = {
-+ .name = "ttySA",
-+ .write = sa1100_console_write,
-+ .device = sa1100_console_device,
-+ .setup = sa1100_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init sa1100_rs_console_init(void)
-+{
-+ sa1100_init_ports();
-+ register_console(&sa1100_console);
-+}
-+
-+#define SA1100_CONSOLE &sa1100_console
-+#else
-+#define SA1100_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver sa1100_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_SA1100_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttySA%d",
-+ .callout_name = "cusa%d",
-+#else
-+ .normal_name = "ttySA",
-+ .callout_name = "cusa",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_SA1100_MAJOR,
-+ .callout_driver = &callout,
-+ .table = sa1100_table,
-+ .termios = sa1100_termios,
-+ .termios_locked = sa1100_termios_locked,
-+ .minor = MINOR_START,
-+ .nr = NR_PORTS,
-+ .cons = SA1100_CONSOLE,
-+};
-+
-+static int __init sa1100_serial_init(void)
-+{
-+ int i, ret;
-+
-+ sa1100_init_ports();
-+
-+ ret = uart_register_driver(&sa1100_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < NR_PORTS; i++)
-+ uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
-+
-+ return 0;
-+}
-+
-+static void __exit sa1100_serial_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_PORTS; i++)
-+ uart_remove_one_port(&sa1100_reg, &sa1100_ports[i].port);
-+
-+ uart_unregister_driver(&sa1100_reg);
-+}
-+
-+module_init(sa1100_serial_init);
-+module_exit(sa1100_serial_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("SA1100 generic serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/serial/uart00.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,903 @@
-+/*
-+ * linux/drivers/serial/uart00.c
-+ *
-+ * Driver for UART00 serial ports
-+ *
-+ * Based on drivers/char/serial_amba.c, by ARM Limited &
-+ * Deep Blue Solutions Ltd.
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: uart00.c,v 1.3.2.5 2002/10/24 09:53:26 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/pld/pld_hotswap.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+#include <asm/sizes.h>
-+
-+#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+#include <asm/arch/excalibur.h>
-+#define UART00_TYPE (volatile unsigned int*)
-+#include <asm/arch/uart00.h>
-+#include <asm/arch/int_ctrl00.h>
-+
-+#undef DEBUG
-+#define UART_NR 2
-+
-+#define SERIAL_UART00_NAME "ttyUA"
-+#define SERIAL_UART00_MAJOR 204
-+#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
-+#define SERIAL_UART00_NR UART_NR
-+#define UART_PORT_SIZE 0x50
-+
-+#define CALLOUT_UART00_NAME "cuaua"
-+#define CALLOUT_UART00_MAJOR 205
-+#define CALLOUT_UART00_MINOR 16 /* Temporary - will change in future */
-+#define CALLOUT_UART00_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *uart00_table[UART_NR];
-+static struct termios *uart00_termios[UART_NR], *uart00_termios_locked[UART_NR];
-+static struct console uart00_console;
-+static struct uart_driver uart00_reg;
-+
-+
-+#define UART00_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the UART00 UARTs
-+ */
-+#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
-+#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
-+#define UART_GET_IES(p) inl(UART_IES((p)->membase))
-+#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
-+#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
-+#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
-+#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
-+#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
-+#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
-+#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
-+#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
-+#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
-+#define UART_GET_MC(p) inl(UART_MC((p)->membase))
-+#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
-+#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
-+#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
-+#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
-+#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
-+#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
-+#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
-+#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
-+//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
-+
-+static void uart00_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+
-+ UART_PUT_IEC(port, UART_IEC_TIE_MSK);
-+}
-+
-+static void uart00_stop_rx(struct uart_port *port)
-+{
-+
-+ UART_PUT_IEC(port, UART_IEC_RE_MSK);
-+}
-+
-+static void uart00_enable_ms(struct uart_port *port)
-+{
-+
-+ UART_PUT_IES(port, UART_IES_ME_MSK);
-+}
-+
-+static void
-+uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+ unsigned int status, ch, rds, flg, ignored = 0;
-+
-+
-+ status = UART_GET_RSR(port);
-+ while (UART_RX_DATA(status)) {
-+
-+ /*
-+ * We need to read rds before reading the
-+ * character from the fifo
-+ */
-+ rds = UART_GET_RDS(port);
-+ ch = UART_GET_CHAR(port);
-+ port->icount.rx++;
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|UART_RDS_PE_MSK))
-+ goto handle_error;
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UART_GET_RSR(port);
-+ }
-+out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+handle_error:
-+ if (rds & UART_RDS_BI_MSK) {
-+ status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
-+ port->icount.brk++;
-+
-+#ifdef SUPPORT_SYSRQ
-+ if (uart_handle_break(port))
-+ goto ignore_char;
-+#endif
-+ } else if (rds & UART_RDS_PE_MSK)
-+ port->icount.parity++;
-+ else if (rds & UART_RDS_FE_MSK)
-+ port->icount.frame++;
-+ if (rds & UART_RDS_OE_MSK)
-+ port->icount.overrun++;
-+
-+ if (rds & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+ rds &= port->read_status_mask;
-+
-+ if (rds & UART_RDS_BI_MSK)
-+ flg = TTY_BREAK;
-+ else if (rds & UART_RDS_PE_MSK)
-+ flg = TTY_PARITY;
-+ else if (rds & UART_RDS_FE_MSK)
-+ flg = TTY_FRAME;
-+
-+ if (rds & UART_RDS_OE_MSK) {
-+ /*
-+ * CHECK: does overrun affect the current character?
-+ * ASSUMPTION: it does not.
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void uart00_tx_chars(struct uart_port *port)
-+{
-+ int count;
-+ struct uart_info *info = port->info;
-+
-+ if (port->x_char) {
-+ while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+
-+ return;
-+ }
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ uart00_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
-+ UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (info->xmit.head == info->xmit.tail)
-+ break;
-+ } while (--count > 0);
-+
-+ if (CIRC_CNT(info->xmit.head,
-+ info->xmit.tail,
-+ UART_XMIT_SIZE) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ uart00_stop_tx(port, 0);
-+}
-+
-+static void uart00_start_tx(struct uart_port *port, u_int from_tty)
-+{
-+ UART_PUT_IES(port,UART_IES_TIE_MSK );
-+ uart00_tx_chars(port);
-+}
-+
-+static void uart00_modem_status(struct uart_port *port)
-+{
-+ unsigned int status;
-+ struct uart_icount *icount = &port->icount;
-+ struct uart_info *info = port->info;
-+
-+ status = UART_GET_MSR(port);
-+
-+ if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
-+ UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))
-+ return;
-+
-+ if (status & UART_MSR_DDCD_MSK) {
-+ icount->dcd++;
-+#ifdef CONFIG_HARD_PPS
-+ if ((port->flags & ASYNC_HARDPPS_CD) &&
-+ (status & UART_MSR_DCD_MSK))
-+ hardpps();
-+#endif
-+ if (info->flags & ASYNC_CHECK_CD) {
-+ if (status & UART_MSR_DCD_MSK)
-+ wake_up_interruptible(&info->open_wait);
-+ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-+ (port->flags & ASYNC_CALLOUT_NOHUP))) {
-+ if (info->tty)
-+ tty_hangup(info->tty);
-+ }
-+ }
-+ }
-+
-+ if (status & UART_MSR_DDSR_MSK)
-+ icount->dsr++;
-+
-+ if (status & UART_MSR_DCTS_MSK) {
-+ icount->cts++;
-+
-+ if (info->flags & ASYNC_CTS_FLOW) {
-+ status &= UART_MSR_CTS_MSK;
-+
-+ if (info->tty->hw_stopped) {
-+ if (status) {
-+ info->tty->hw_stopped = 0;
-+ port->ops->start_tx(port, 0);
-+ uart_write_wakeup(port);
-+ }
-+ } else {
-+ if (!status) {
-+ info->tty->hw_stopped = 1;
-+ port->ops->stop_tx(port, 0);
-+ }
-+ }
-+ }
-+ }
-+ wake_up_interruptible(&info->delta_msr_wait);
-+
-+}
-+
-+static void uart00_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pass_counter = 0;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ do {
-+
-+ if (status & UART_ISR_RI_MSK)
-+ uart00_rx_chars(port, regs);
-+ if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
-+ uart00_tx_chars(port);
-+ if (status & UART_ISR_MI_MSK)
-+ uart00_modem_status(port);
-+ if (pass_counter++ > UART00_ISR_PASS_LIMIT)
-+ break;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ } while (status);
-+}
-+
-+static u_int uart00_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
-+}
-+
-+static u_int uart00_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ status = UART_GET_MSR(port);
-+ if (status & UART_MSR_DCD_MSK)
-+ result |= TIOCM_CAR;
-+ if (status & UART_MSR_DSR_MSK)
-+ result |= TIOCM_DSR;
-+ if (status & UART_MSR_CTS_MSK)
-+ result |= TIOCM_CTS;
-+ if (status & UART_MCR_RI_MSK)
-+ result |= TIOCM_RNG;
-+
-+ return result;
-+}
-+
-+static void uart00_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned char mcr = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ mcr |= UART_MCR_RTS_MSK;
-+ if (mctrl & TIOCM_DTR)
-+ mcr |= UART_MCR_DTR_MSK;
-+ if (mctrl & TIOCM_LOOP)
-+ mcr |= UART_MCR_LB_MSK;
-+
-+ UART_PUT_MCR(port, mcr);
-+}
-+
-+static void uart00_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned int mcr;
-+
-+ mcr = UART_GET_MCR(port);
-+ if (break_state == -1)
-+ mcr |= UART_MCR_BR_MSK;
-+ else
-+ mcr &= ~UART_MCR_BR_MSK;
-+ UART_PUT_MCR(port, mcr);
-+}
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+ u_int quot;
-+
-+ /* Special case: B0 rate */
-+ if (!baud)
-+ baud = 9600;
-+
-+ quot = (port->uartclk / (16 * baud)-1) ;
-+
-+ return quot;
-+}
-+static void uart00_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ u_int uart_mc=0, old_ies;
-+ unsigned long flags;
-+
-+#ifdef DEBUG
-+ printk("uart00_set_cflag(0x%x) called\n", cflag);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5: uart_mc = UART_MC_CLS_CHARLEN_5; break;
-+ case CS6: uart_mc = UART_MC_CLS_CHARLEN_6; break;
-+ case CS7: uart_mc = UART_MC_CLS_CHARLEN_7; break;
-+ default: uart_mc = UART_MC_CLS_CHARLEN_8; break; // CS8
-+ }
-+ if (cflag & CSTOPB)
-+ uart_mc|= UART_MC_ST_TWO;
-+ if (cflag & PARENB) {
-+ uart_mc |= UART_MC_PE_MSK;
-+ if (!(cflag & PARODD))
-+ uart_mc |= UART_MC_EP_MSK;
-+ }
-+
-+ port->read_status_mask = UART_RDS_OE_MSK;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= UART_RDS_BI_MSK;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= UART_RDS_BI_MSK;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns to (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UART_RDS_OE_MSK;
-+ }
-+
-+ /* first, disable everything */
-+ save_flags(flags); cli();
-+ old_ies = UART_GET_IES(port);
-+
-+ if ((port->flags & ASYNC_HARDPPS_CD) ||
-+ (cflag & CRTSCTS) || !(cflag & CLOCAL))
-+ old_ies |= UART_IES_ME_MSK;
-+
-+
-+ /* Set baud rate */
-+ UART_PUT_DIV_LO(port, (quot & 0xff));
-+ UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-+
-+
-+ UART_PUT_MC(port, uart_mc);
-+ UART_PUT_IES(port, old_ies);
-+
-+ restore_flags(flags);
-+}
-+
-+static int uart00_startup(struct uart_port *port)
-+{
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, uart00_int, 0, "uart00", port);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * Finally, enable interrupts. Use the TII interrupt to minimise
-+ * the number of interrupts generated. If higher performance is
-+ * needed, consider using the TI interrupt with a suitable FIFO
-+ * threshold
-+ */
-+ UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
-+
-+ return 0;
-+}
-+
-+static void uart00_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ UART_PUT_IEC(port, 0xff);
-+
-+ /* disable break condition and fifos */
-+ UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+}
-+
-+static const char *uart00_type(struct uart_port *port)
-+{
-+ return port->type == PORT_UART00 ? "Altera UART00" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void uart00_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+ if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){
-+ iounmap(port->membase);
-+ }
-+#endif
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int uart00_request_port(struct uart_port *port)
-+{
-+ int result;
-+
-+ result = request_mem_region(port->mapbase, UART_PORT_SIZE,
-+ "serial_uart00") != NULL ? 0 : -EBUSY;
-+ if (result)
-+ return result;
-+
-+ port->membase = ioremap(port->mapbase, SZ_4K);
-+ if (!port->membase) {
-+ printk(KERN_ERR "serial00: cannot map io memory\n");
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+ }
-+
-+ return port->membase ? 0 : -ENOMEM;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void uart00_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ if (uart00_request_port(port) == 0)
-+ port->type = PORT_UART00;
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops uart00_pops = {
-+ tx_empty: uart00_tx_empty,
-+ set_mctrl: uart00_set_mctrl,
-+ get_mctrl: uart00_get_mctrl,
-+ stop_tx: uart00_stop_tx,
-+ start_tx: uart00_start_tx,
-+ stop_rx: uart00_stop_rx,
-+ enable_ms: uart00_enable_ms,
-+ break_ctl: uart00_break_ctl,
-+ startup: uart00_startup,
-+ shutdown: uart00_shutdown,
-+ change_speed: uart00_change_speed,
-+ type: uart00_type,
-+ release_port: uart00_release_port,
-+ request_port: uart00_request_port,
-+ config_port: uart00_config_port,
-+ verify_port: uart00_verify_port,
-+};
-+
-+static struct uart_port uart00_ports[UART_NR] = {
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+{
-+ .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
-+ .mapbase = EXC_UART00_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UART,
-+ .uartclk = EXC_AHB2_CLK_FREQUENCY,
-+ .fifosize = 16,
-+ .ops = &uart00_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+}
-+#endif
-+};
-+
-+#ifdef CONFIG_SERIAL_UART00_CONSOLE
-+static void uart00_console_write(struct console *co, const char *s, unsigned count)
-+{
-+#ifdef CONFIG_ARCH_CAMELOT
-+ struct uart_port *port = &uart00_ports[0];
-+ unsigned int status, old_ies;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+ old_ies = UART_GET_IES(port);
-+ UART_PUT_IEC(port,0xff);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the IES
-+ */
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (status & UART_TSR_TX_LEVEL_MSK);
-+ UART_PUT_IES(port, old_ies);
-+#endif
-+}
-+
-+static kdev_t uart00_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);
-+}
-+
-+static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ u_int uart_mc, quot;
-+ uart_mc= UART_GET_MC(port);
-+
-+ *parity = 'n';
-+ if (uart_mc & UART_MC_PE_MSK) {
-+ if (uart_mc & UART_MC_EP_MSK)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ switch (uart_mc & UART_MC_CLS_MSK){
-+
-+ case UART_MC_CLS_CHARLEN_5:
-+ *bits = 5;
-+ break;
-+ case UART_MC_CLS_CHARLEN_6:
-+ *bits = 6;
-+ break;
-+ case UART_MC_CLS_CHARLEN_7:
-+ *bits = 7;
-+ break;
-+ case UART_MC_CLS_CHARLEN_8:
-+ *bits = 8;
-+ break;
-+ }
-+ quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
-+ *baud = port->uartclk / (16 *quot );
-+}
-+
-+static int __init uart00_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow= 'n';
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = &uart00_ports[0];
-+ co->index = 0;
-+#else
-+ return -ENODEV;
-+#endif
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ uart00_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console uart00_console = {
-+ .name = SERIAL_UART00_NAME,
-+ .write = uart00_console_write,
-+ .device = uart00_console_device,
-+ .setup = uart00_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = 0,
-+};
-+
-+void __init uart00_console_init(void)
-+{
-+ register_console(&uart00_console);
-+}
-+
-+#define UART00_CONSOLE &uart00_console
-+#else
-+#define UART00_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver uart00_reg = {
-+ .owner = NULL,
-+ .normal_major = SERIAL_UART00_MAJOR,
-+ .normal_name = SERIAL_UART00_NAME,
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_UART00_MAJOR,
-+ .callout_name = CALLOUT_UART00_NAME,
-+ .callout_driver = &callout,
-+ .table = uart00_table,
-+ .termios = uart00_termios,
-+ .termios_locked = uart00_termios_locked,
-+ .minor = SERIAL_UART00_MINOR,
-+ .nr = UART_NR,
-+ .state = NULL,
-+ .cons = UART00_CONSOLE,
-+};
-+
-+struct dev_port_entry{
-+ struct uart_port *port;
-+};
-+
-+static struct dev_port_entry dev_port_map[UART_NR];
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+/*
-+ * Keep a mapping of dev_info addresses -> port lines to use when
-+ * removing ports dev==NULL indicates unused entry
-+ */
-+
-+struct uart00_ps_data{
-+ unsigned int clk;
-+ unsigned int fifosize;
-+};
-+
-+int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
-+{
-+ struct uart00_ps_data* dev_ps=dev_ps_data;
-+ struct uart_port * port;
-+ int i,result;
-+
-+ i=0;
-+ while(dev_port_map[i].port)
-+ i++;
-+
-+ if(i==UART_NR){
-+ printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
-+ return 0;
-+ }
-+
-+ port=&uart00_ports[i];
-+
-+ printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
-+ port->membase=0;
-+ port->mapbase=dev_info->base_addr;
-+ port->iotype=SERIAL_IO_MEM;
-+ port->irq=dev_info->irq;
-+ port->uartclk=dev_ps->clk;
-+ port->fifosize=dev_ps->fifosize;
-+ port->ops=&uart00_pops;
-+ port->line=i;
-+ port->flags=ASYNC_BOOT_AUTOCONF;
-+
-+ result=uart_register_port(&uart00_reg, port);
-+ if(result<0){
-+ printk("uart_register_port returned %d\n",result);
-+ return result;
-+ }
-+ dev_port_map[i].port=port;
-+ printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,i);
-+ return 0;
-+
-+}
-+
-+int uart00_remove_devices(void)
-+{
-+ int i,result;
-+
-+
-+ result=0;
-+ for(i=1;i<UART_NR;i++){
-+ if(dev_port_map[i].port){
-+ uart_unregister_port(&uart00_reg,i);
-+ dev_port_map[i].port=NULL;
-+ }
-+ }
-+ return 0;
-+
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+
-+
-+int uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){
-+
-+ int i,len=0;
-+ struct uart_port *port;
-+ int limit = count - 80;
-+ char ps_data[80];
-+ if(*start)
-+ buf=*start;
-+ for(i=0;(i<UART_NR)&&(len<limit);i++){
-+ if(dev_port_map[i].port){
-+ port=dev_port_map[i].port;
-+ sprintf(ps_data,"clk, %dHz, fifo size, %dbytes",
-+ port->uartclk,port->fifosize);
-+ len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i,
-+ port->mapbase,port->irq,ps_data);
-+
-+ }
-+ }
-+ *eof=1;
-+ return len;
-+}
-+
-+
-+
-+#endif
-+struct pld_hotswap_ops uart00_pldhs_ops={
-+ .name = "uart00",
-+ .add_device = uart00_add_device,
-+ .remove_devices = uart00_remove_devices,
-+ .proc_read = uart00_proc_read
-+};
-+
-+#endif
-+
-+static int __init uart00_init(void)
-+{
-+ int ret;
-+ int i;
-+
-+ ret = uart_register_driver(&uart00_reg);
-+ if (ret) {
-+ printk(KERN_ERR "uart00: Couldn't register driver\n");
-+ return ret;
-+ }
-+
-+ unregister_console(&uart00_console);
-+
-+ for(i=0;i<UART_NR;i++){
-+ uart00_ports[i].ops=&uart00_pops;
-+ }
-+
-+ printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+ pldhs_register_driver(&uart00_pldhs_ops);
-+#endif
-+ for (i=0; i<UART_NR; i++)
-+ uart_add_one_port(&uart00_reg,&uart00_ports[i]);
-+
-+ uart00_console.flags = 0;
-+ register_console(&uart00_console);
-+#ifdef CONFIG_ARCH_CAMELOT
-+ dev_port_map[0].port=uart00_ports;
-+#endif
-+ return ret;
-+}
-+
-+
-+__initcall(uart00_init);
-+
-+
---- linux-2.4.25/drivers/sound/.version~2.4.25-vrs2.patch
-+++ linux-2.4.25/drivers/sound/.version
--3.8s
--0x030804
---- linux-2.4.25/drivers/sound/Config.in~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/sound/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -131,6 +131,17 @@
- dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI
- dep_mbool ' VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX
-
-+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ dep_tristate ' StrongARM-11x0 Sound Drivers' CONFIG_SOUND_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_SOUND
-+ dep_tristate ' UDA1341 Stereo Codec' CONFIG_SOUND_UDA1341 $CONFIG_L3 $CONFIG_SOUND_SA1100 $CONFIG_SOUND
-+ dep_tristate ' Assabet audio support' CONFIG_SOUND_ASSABET_UDA1341 $CONFIG_SA1100_ASSABET $CONFIG_SOUND_UDA1341
-+ dep_tristate ' Compaq iPAQ audio support' CONFIG_SOUND_H3600_UDA1341 $CONFIG_SA1100_H3600 $CONFIG_SOUND_UDA1341
-+ dep_tristate ' Pangolin audio support' CONFIG_SOUND_PANGOLIN_UDA1341 $CONFIG_SA1100_PANGOLIN $CONFIG_SOUND_UDA1341
-+ dep_tristate ' SA1111 audio support' CONFIG_SOUND_SA1111_UDA1341 $CONFIG_SA1111 $CONFIG_SOUND_UDA1341
-+ dep_tristate ' SA1111 AC97 Sound' CONFIG_SOUND_SA1111_AC97 $CONFIG_SA1111 $CONFIG_SOUND_SA1100
-+ dep_tristate ' Generic DAC on the SA11x0 SSP port' CONFIG_SOUND_SA1100SSP $CONFIG_SOUND_SA1100
-+fi
-+
- dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
-
- if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
-@@ -220,14 +231,14 @@
- bool ' Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
- fi
- fi
-+
-+fi
-
-- if [ "$CONFIG_ARM" = "y" ]; then
-- if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
-- dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
-- fi
-- dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" -o "$CONFIG_ARCH_RISCSTATION" ]; then
-+ dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
- fi
--
-+ dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
- fi
-
- dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
---- linux-2.4.25/drivers/sound/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/sound/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,8 @@
- export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
- msnd.o opl3.o sb_common.o sequencer_syms.o \
- sound_core.o sound_syms.o uart401.o \
-- nm256_audio.o ac97.o ac97_codec.o aci.o
-+ nm256_audio.o ac97.o ac97_codec.o aci.o \
-+ sa1100-audio.o
-
- # Each configuration option enables a list of files.
-
-@@ -76,6 +77,14 @@
- obj-$(CONFIG_SOUND_FORTE) += forte.o ac97_codec.o
- obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
- obj-$(CONFIG_SOUND_HARMONY) += harmony.o
-+obj-$(CONFIG_SOUND_SA1100) += sa1100-audio.o
-+obj-$(CONFIG_SOUND_UDA1341) += uda1341.o
-+obj-$(CONFIG_SOUND_ASSABET_UDA1341) += assabet-uda1341.o
-+obj-$(CONFIG_SOUND_PANGOLIN_UDA1341) += pangolin-uda1341.o
-+obj-$(CONFIG_SOUND_H3600_UDA1341) += h3600-uda1341.o
-+obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
-+obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
-+obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
- obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
- obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
- obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
-@@ -105,7 +114,6 @@
- obj-y += dmasound/dmasound.o
- endif
-
--
- # Declare multi-part drivers.
-
- list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/assabet-uda1341.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,404 @@
-+/*
-+ * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Assabet/UDA1341 support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
-+ *
-+ * 2001-08-03 Russell King Fix left/right channel swap.
-+ * Attempt to reduce power consumption when idle.
-+ *
-+ * 2001-09-23 Russell King Remove old L3 bus driver.
-+ *
-+ * Please note that fiddling too much with MDREFR results in oopses, so we don't
-+ * touch MDREFR unnecessarily, which means we don't touch it on close.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/cpufreq.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/arch/assabet.h>
-+
-+#include "sa1100-audio.h"
-+
-+/*
-+ * Define this to fix the power drain on early Assabets
-+ */
-+#define FIX_POWER_DRAIN
-+
-+/*
-+ * Debugging?
-+ */
-+#undef DEBUG
-+
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+/*
-+ * Mixer (UDA1341) interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations assabet_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+/*
-+ * FIXME: what about SFRM going high when SSP is disabled?
-+ */
-+static void assabet_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ u_int clk_ref, clk_div;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * Our clock source is derived from the CPLD on which we don't have
-+ * much control unfortunately. This was intended for a fixed 48000 Hz
-+ * samplerate assuming a core clock of 221.2 MHz. The CPLD appears
-+ * to divide the memory clock so there is a ratio of 4608 between
-+ * the core clock and the resulting samplerate (obtained by
-+ * measurements, the CPLD equations should confirm that).
-+ *
-+ * Still we can play with the SA1110's clock divisor for the SSP port
-+ * to get half the samplerate as well.
-+ *
-+ * Apparently the clock sent to the SA1110 for the SSP port is further
-+ * more divided from the clock sent to the UDA1341 (some people tried
-+ * to be too clever in their design, or simply failed to read the
-+ * SA1110 manual). If it was the same clock we would have been able
-+ * to support a third samplerate with the UDA1341's 384FS mode.
-+ *
-+ * At least it would have been a minimum acceptable solution to be
-+ * able to set the CPLD divisor by software. The iPAQ design is
-+ * certainly a better example to follow for a new design.
-+ */
-+ clk_ref = cpufreq_get(0) * 1000 / 4608;
-+ if (val > clk_ref*4/7) {
-+ audio_samplerate = clk_ref;
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(2);
-+ } else {
-+ audio_samplerate = clk_ref/2;
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(4);
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+}
-+
-+/*
-+ * Initialise the Assabet audio driver.
-+ *
-+ * Note that we have to be careful with the order that we do things here;
-+ * there is a D-type flip flop which is clocked from the SFRM line which
-+ * indicates whether the same is for the left or right channel to the
-+ * UDA1341.
-+ *
-+ * When you disable the SSP (by clearing SSCR0_SSE) it appears that the
-+ * SFRM signal can float high. When you re-enable the SSP, you clock the
-+ * flip flop once, and end up swapping the left and right channels.
-+ *
-+ * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known
-+ * state, but this line resets other devices as well!
-+ *
-+ * In addition to the above, it appears that powering down the UDA1341 on
-+ * early Assabets leaves the UDA_WS actively driving a logic '1' into the
-+ * chip, wasting power! (you can tell this by D11 being half-on). We
-+ * attempt to correct this by kicking the flip flop on init/open/close.
-+ * We should probably do this on PM resume as well.
-+ *
-+ * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST
-+ * is important).
-+ */
-+static void assabet_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+ unsigned int mdrefr;
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ * Enable the power for the UDA1341 before driving any signals.
-+ * We leave the audio amp (LM4880) disabled for now.
-+ */
-+ ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);
-+
-+#ifdef FIX_POWER_DRAIN
-+ GPSR = GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+#endif
-+
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);
-+
-+ /*
-+ * Setup the SSP uart.
-+ */
-+ PPAR |= PPAR_SPR;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK;
-+ GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
-+ GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ /*
-+ * Only give SFRM to the SSP after it has been enabled.
-+ */
-+ GAFR |= GPIO_SSP_SFRM;
-+
-+ /*
-+ * The assabet board uses the SDRAM clock as the source clock for
-+ * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
-+ * At 206MHz we need to run the audio clock (SDRAM bank 2)
-+ * at half speed. This clock will scale with core frequency so
-+ * the audio sample rate will also scale. The CPLD on Assabet
-+ * will need to be programmed to match the core frequency.
-+ */
-+ mdrefr = MDREFR;
-+ if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
-+ MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
-+ mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
-+ mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
-+ MDREFR = mdrefr;
-+ (void) MDREFR;
-+ }
-+ local_irq_restore(flags);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ mdelay(1);
-+
-+ l3_open(&uda1341);
-+
-+ assabet_set_samplerate(audio_samplerate);
-+
-+ /* Enable the audio power */
-+ ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF);
-+}
-+
-+/*
-+ * Shutdown the Assabet audio driver.
-+ *
-+ * We have to be careful about the SFRM line here for the same reasons
-+ * described in the initialisation comments above. This basically means
-+ * that we must hand the SSP pins back to the GPIO module before disabling
-+ * the SSP.
-+ *
-+ * In addition, to reduce power drain, we toggle the SFRM line once so
-+ * that the UDA_WS line is at logic 0.
-+ *
-+ * We can't clear ASSABET_BCR_CODEC_RST without knowing if the UCB1300 or
-+ * ADV7171 driver is still active. If it is, then we still need to play
-+ * games, so we might as well leave ASSABET_BCR_CODEC_RST set.
-+ */
-+static void assabet_audio_shutdown(void *dummy)
-+{
-+ ASSABET_BCR_set(ASSABET_BCR_STEREO_LB | ASSABET_BCR_QMUTE |
-+ ASSABET_BCR_SPK_OFF);
-+
-+ l3_close(&uda1341);
-+
-+ GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
-+ Ser4SSCR0 = 0;
-+
-+#ifdef FIX_POWER_DRAIN
-+ GPSR = GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+#endif
-+
-+ /* disable the audio power */
-+ ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
-+}
-+
-+static int assabet_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ assabet_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do signed 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Assabet UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "Assabet UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: assabet_audio_init,
-+ hw_shutdown: assabet_audio_shutdown,
-+ client_ioctl: assabet_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int assabet_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations assabet_audio_fops = {
-+ open: assabet_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init assabet_uda1341_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_assabet())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1);
-+
-+#ifdef FIX_POWER_DRAIN
-+ {
-+ unsigned long flags;
-+ local_irq_save(flags);
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ GPSR = GPIO_SSP_SFRM;
-+ GPDR |= GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+ local_irq_restore(flags);
-+ }
-+#endif
-+
-+ printk(KERN_INFO "Sound: Assabet UDA1341: dsp id %d mixer id %d\n",
-+ audio_dev_id, mixer_dev_id);
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit assabet_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(assabet_uda1341_init);
-+module_exit(assabet_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/h3600-uda1341.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,352 @@
-+/*
-+ * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release.
-+ *
-+ * 2000-07-?? George France Bitsy support.
-+ *
-+ * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+//#include <asm/arch/h3600_hal.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "Bitsy_UDA1341"
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations h3600_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+/*
-+ * Stop-gap solution until rest of hh.org HAL stuff is merged.
-+ */
-+#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
-+#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
-+static void h3600_set_audio_clock(long val)
-+{
-+ switch (val) {
-+ case 24000: case 32000: case 48000: /* 00: 12.288 MHz */
-+ GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */
-+ GPSR = GPIO_H3600_CLK_SET0;
-+ GPCR = GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 8000: case 10666: case 16000: /* 10: 4.096 MHz */
-+ GPCR = GPIO_H3600_CLK_SET0;
-+ GPSR = GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */
-+ GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-+ break;
-+ }
-+}
-+
-+static void h3600_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ int clk_div = 0;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * We have the following clock sources:
-+ * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
-+ * Those can be divided either by 256, 384 or 512.
-+ * This makes up 12 combinations for the following samplerates...
-+ */
-+ if (val >= 48000)
-+ val = 48000;
-+ else if (val >= 44100)
-+ val = 44100;
-+ else if (val >= 32000)
-+ val = 32000;
-+ else if (val >= 29400)
-+ val = 29400;
-+ else if (val >= 24000)
-+ val = 24000;
-+ else if (val >= 22050)
-+ val = 22050;
-+ else if (val >= 21970)
-+ val = 21970;
-+ else if (val >= 16000)
-+ val = 16000;
-+ else if (val >= 14647)
-+ val = 14647;
-+ else if (val >= 10985)
-+ val = 10985;
-+ else if (val >= 10666)
-+ val = 10666;
-+ else
-+ val = 8000;
-+
-+ /* Set the external clock generator */
-+ h3600_set_audio_clock(val);
-+
-+ /* Select the clock divisor */
-+ switch (val) {
-+ case 8000:
-+ case 10985:
-+ case 22050:
-+ case 24000:
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(16);
-+ break;
-+ case 16000:
-+ case 21970:
-+ case 44100:
-+ case 48000:
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(8);
-+ break;
-+ case 10666:
-+ case 14647:
-+ case 29400:
-+ case 32000:
-+ cfg.fs = 384;
-+ clk_div = SSCR0_SerClkDiv(12);
-+ break;
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+ audio_samplerate = val;
-+}
-+
-+static void h3600_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+
-+ /* Setup the uarts */
-+ local_irq_save(flags);
-+ GAFR |= (GPIO_SSP_CLK);
-+ GPDR &= ~(GPIO_SSP_CLK);
-+ Ser4SSCR0 = 0;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ /* Enable the audio power */
-+
-+ clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
-+ set_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+ local_irq_restore(flags);
-+
-+ /* external clock configuration */
-+ h3600_set_samplerate(audio_samplerate);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ mdelay(1);
-+
-+ /* make the left and right channels unswapped (flip the WS latch ) */
-+ Ser4SSDR = 0;
-+
-+ /* Initialize the UDA1341 internal state */
-+ l3_open(&uda1341);
-+
-+ clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+}
-+
-+static void h3600_audio_shutdown(void *dummy)
-+{
-+ /* disable the audio power and all signals leading to the audio chip */
-+ l3_close(&uda1341);
-+ Ser4SSCR0 = 0;
-+ clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ clr_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
-+ clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+}
-+
-+static int h3600_audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ h3600_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: h3600_audio_init,
-+ hw_shutdown: h3600_audio_shutdown,
-+ client_ioctl: h3600_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int h3600_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations h3600_audio_fops = {
-+ open: h3600_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init h3600_uda1341_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_h3xxx())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&h3600_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&h3600_mixer_fops, -1);
-+
-+ printk( KERN_INFO "iPAQ audio support initialized\n" );
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit h3600_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(h3600_uda1341_init);
-+module_exit(h3600_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre, George France");
-+MODULE_DESCRIPTION("Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/pangolin-uda1341.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,322 @@
-+/*
-+ * Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Pangolin/UDA1341 support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
-+ *
-+ * 2001-08-06 Richard Fan Pangolin Support
-+ *
-+ * 2001-09-23 Russell King Update inline with Assabet driver
-+ * Remove old L3 bus driver
-+ *
-+ * Note: this should probably be merged with the Assabet audio driver,
-+ * and become the "SDRAM-clock driven" SA1100 audio driver.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+/*
-+ * Debugging?
-+ */
-+#undef DEBUG
-+
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+#define QmutePin GPIO_GPIO(4)
-+#define SpeakerOffPin GPIO_GPIO(5)
-+
-+/*
-+ * Mixer (UDA1341) interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations pangolin_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+static void pangolin_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ int clk_div;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * Our clock source is derived from the CPLD on which we don't have
-+ * much control unfortunately. This was intended for a fixed 44100Hz
-+ * samplerate assuming a core clock of 206 MHz. Still we can play
-+ * with the SA1110's clock divisor for the SSP port to get a 22050Hz
-+ * samplerate.
-+ *
-+ * Apparently the clock sent to the SA1110 for the SSP port is
-+ * divided from the clock sent to the UDA1341 (some people tried to
-+ * be too clever in their design, or simply failed to read the SA1110
-+ * manual). If it was the same source we would have been able to
-+ * support a third samplerate.
-+ *
-+ * At least it would have been a minimum acceptable solution to be
-+ * able to set the CPLD divisor by software. The iPAQ design is
-+ * certainly a better example to follow for a new design.
-+ */
-+ if (val >= 44100) {
-+ audio_samplerate = 44100;
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(2);
-+ } else {
-+ audio_samplerate = 22050;
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(4);
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+}
-+
-+static void pangolin_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+ unsigned int mdrefr;
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ * Setup the SSP uart.
-+ */
-+ PPAR |= PPAR_SPR;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK |
-+ GPIO_SSP_SFRM;
-+ GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
-+ GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ GAFR &= ~(SpeakerOffPin | QmutePin);
-+ GPDR |= (SpeakerOffPin | QmutePin);
-+ GPCR = SpeakerOffPin;
-+
-+ /*
-+ * The assabet board uses the SDRAM clock as the source clock for
-+ * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
-+ * At 206MHz we need to run the audio clock (SDRAM bank 2)
-+ * at half speed. This clock will scale with core frequency so
-+ * the audio sample rate will also scale. The CPLD on Assabet
-+ * will need to be programmed to match the core frequency.
-+ */
-+ mdrefr = MDREFR;
-+ if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
-+ MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
-+ mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
-+ mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
-+ MDREFR = mdrefr;
-+ (void) MDREFR;
-+ }
-+ local_irq_restore(flags);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ mdelay(100);
-+
-+ l3_open(&uda1341);
-+
-+ pangolin_set_samplerate(audio_samplerate);
-+
-+ GPCR = QmutePin;
-+}
-+
-+static void pangolin_audio_shutdown(void *dummy)
-+{
-+ GPSR = QmutePin;
-+
-+ l3_close(&uda1341);
-+
-+ Ser4SSCR0 = 0;
-+ MDREFR &= ~(MDREFR_K2DB2 | MDREFR_K2RUN);
-+}
-+
-+static int pangolin_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ pangolin_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do signed 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Pangolin UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "Pangolin UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: pangolin_audio_init,
-+ hw_shutdown: pangolin_audio_shutdown,
-+ client_ioctl: pangolin_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int pangolin_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations pangolin_audio_fops = {
-+ open: pangolin_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init pangolin_uda1341_init(void)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ if (!machine_is_pangolin())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&pangolin_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&pangolin_mixer_fops, -1);
-+
-+ local_irq_save(flags);
-+ GAFR &= ~(SpeakerOffPin | QmutePin);
-+ GPDR |= (SpeakerOffPin | QmutePin);
-+ local_irq_restore(flags);
-+
-+ printk(KERN_INFO "Pangolin UDA1341 audio driver initialized\n");
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit pangolin_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(pangolin_uda1341_init);
-+module_exit(pangolin_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1100-audio.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,976 @@
-+/*
-+ * Common audio handling for the SA11x0 processor
-+ *
-+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ *
-+ * This module handles the generic buffering/DMA/mmap audio interface for
-+ * codecs connected to the SA1100 chip. All features depending on specific
-+ * hardware implementations like supported audio formats or samplerates are
-+ * relegated to separate specific modules.
-+ *
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2000-06-10 Erik Bunce Add initial poll support.
-+ *
-+ * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the
-+ * generic SA1100 DMA interface.
-+ *
-+ * 2000-11-30 Nicolas Pitre - Validation of opened instances;
-+ * - Power handling at open/release time instead
-+ * of driver load/unload;
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-22 Nicolas Pitre - added mmap() and realtime support
-+ * - corrected many details to better comply
-+ * with the OSS API
-+ *
-+ * 2001-10-19 Nicolas Pitre - brought DMA registration processing
-+ * into this module for better ressource
-+ * management. This also fixes a bug
-+ * with the suspend/resume logic.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/poll.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+/* #define DEBUG 1 */
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "sa1100-audio"
-+#define AUDIO_NBFRAGS_DEFAULT 8
-+#define AUDIO_FRAGSIZE_DEFAULT 8192
-+
-+#define NEXT_BUF(_s_,_b_) { \
-+ (_s_)->_b_##_idx++; \
-+ (_s_)->_b_##_idx %= (_s_)->nbfrags; \
-+ (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; }
-+
-+#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
-+
-+/*
-+ * This function frees all buffers
-+ */
-+
-+static void audio_clear_buf(audio_stream_t * s)
-+{
-+ DPRINTK("audio_clear_buf\n");
-+
-+ /* ensure DMA won't run anymore */
-+ s->active = 0;
-+ s->stopped = 0;
-+ sa1100_dma_flush_all(s->dma_ch);
-+
-+ if (s->buffers) {
-+ int frag;
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ if (!s->buffers[frag].master)
-+ continue;
-+ consistent_free(s->buffers[frag].start,
-+ s->buffers[frag].master,
-+ s->buffers[frag].dma_addr);
-+ }
-+ kfree(s->buffers);
-+ s->buffers = NULL;
-+ }
-+
-+ s->buf_idx = 0;
-+ s->buf = NULL;
-+}
-+
-+
-+/*
-+ * This function allocates the buffer structure array and buffer data space
-+ * according to the current number of fragments and fragment size.
-+ */
-+
-+static int audio_setup_buf(audio_stream_t * s)
-+{
-+ int frag;
-+ int dmasize = 0;
-+ char *dmabuf = NULL;
-+ dma_addr_t dmaphys = 0;
-+
-+ if (s->buffers)
-+ return -EBUSY;
-+
-+ s->buffers = (audio_buf_t *)
-+ kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
-+ if (!s->buffers)
-+ goto err;
-+ memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
-+
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+
-+ /*
-+ * Let's allocate non-cached memory for DMA buffers.
-+ * We try to allocate all memory at once.
-+ * If this fails (a common reason is memory fragmentation),
-+ * then we allocate more smaller buffers.
-+ */
-+ if (!dmasize) {
-+ dmasize = (s->nbfrags - frag) * s->fragsize;
-+ do {
-+ dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
-+ dmasize,
-+ &dmaphys);
-+ if (!dmabuf)
-+ dmasize -= s->fragsize;
-+ } while (!dmabuf && dmasize);
-+ if (!dmabuf)
-+ goto err;
-+ b->master = dmasize;
-+ memzero(dmabuf, dmasize);
-+ }
-+
-+ b->start = dmabuf;
-+ b->dma_addr = dmaphys;
-+ b->stream = s;
-+ sema_init(&b->sem, 1);
-+ DPRINTK("buf %d: start %p dma %p\n", frag, b->start,
-+ b->dma_addr);
-+
-+ dmabuf += s->fragsize;
-+ dmaphys += s->fragsize;
-+ dmasize -= s->fragsize;
-+ }
-+
-+ s->buf_idx = 0;
-+ s->buf = &s->buffers[0];
-+ s->bytecount = 0;
-+ s->getptrCount = 0;
-+ s->fragcount = 0;
-+
-+ return 0;
-+
-+err:
-+ printk(AUDIO_NAME ": unable to allocate audio memory\n ");
-+ audio_clear_buf(s);
-+ return -ENOMEM;
-+}
-+
-+
-+/*
-+ * This function yanks all buffers from the DMA code's control and
-+ * resets them ready to be used again.
-+ */
-+
-+static void audio_reset_buf(audio_stream_t * s)
-+{
-+ int frag;
-+
-+ s->active = 0;
-+ s->stopped = 0;
-+ sa1100_dma_flush_all(s->dma_ch);
-+ if (s->buffers) {
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+ b->size = 0;
-+ sema_init(&b->sem, 1);
-+ }
-+ }
-+ s->bytecount = 0;
-+ s->getptrCount = 0;
-+ s->fragcount = 0;
-+}
-+
-+
-+/*
-+ * DMA callback functions
-+ */
-+
-+static void audio_dmaout_done_callback(void *buf_id, int size)
-+{
-+ audio_buf_t *b = (audio_buf_t *) buf_id;
-+ audio_stream_t *s = b->stream;
-+
-+ /* Accounting */
-+ s->bytecount += size;
-+ s->fragcount++;
-+
-+ /* Recycle buffer */
-+ if (s->mapped)
-+ sa1100_dma_queue_buffer(s->dma_ch, buf_id,
-+ b->dma_addr, s->fragsize);
-+ else
-+ up(&b->sem);
-+
-+ /* And any process polling on write. */
-+ wake_up(&s->wq);
-+}
-+
-+static void audio_dmain_done_callback(void *buf_id, int size)
-+{
-+ audio_buf_t *b = (audio_buf_t *) buf_id;
-+ audio_stream_t *s = b->stream;
-+
-+ /* Accounting */
-+ s->bytecount += size;
-+ s->fragcount++;
-+
-+ /* Recycle buffer */
-+ if (s->mapped) {
-+ sa1100_dma_queue_buffer(s->dma_ch, buf_id,
-+ b->dma_addr, s->fragsize);
-+ } else {
-+ b->size = size;
-+ up(&b->sem);
-+ }
-+
-+ /* And any process polling on write. */
-+ wake_up(&s->wq);
-+}
-+
-+static int audio_sync(struct file *file)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ audio_buf_t *b;
-+
-+ DPRINTK("audio_sync\n");
-+
-+ if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
-+ return 0;
-+
-+ /*
-+ * Send current buffer if it contains data. Be sure to send
-+ * a full sample count.
-+ */
-+ b = s->buf;
-+ if (b->size &= ~3) {
-+ down(&b->sem);
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, b->size);
-+ b->size = 0;
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ /*
-+ * Let's wait for the last buffer we sent i.e. the one before the
-+ * current buf_idx. When we acquire the semaphore, this means either:
-+ * - DMA on the buffer completed or
-+ * - the buffer was already free thus nothing else to sync.
-+ */
-+ b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags);
-+ if (down_interruptible(&b->sem))
-+ return -EINTR;
-+ up(&b->sem);
-+ return 0;
-+}
-+
-+
-+static int audio_write(struct file *file, const char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ const char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ int chunksize, ret = 0;
-+
-+ DPRINTK("audio_write: count=%d\n", count);
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = s->buf;
-+
-+ /* Wait for a buffer to become free */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&b->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&b->sem))
-+ break;
-+ }
-+
-+ /* Feed the current buffer */
-+ chunksize = s->fragsize - b->size;
-+ if (chunksize > count)
-+ chunksize = count;
-+ DPRINTK("write %d to %d\n", chunksize, s->buf_idx);
-+ if (copy_from_user(b->start + b->size, buffer, chunksize)) {
-+ up(&b->sem);
-+ return -EFAULT;
-+ }
-+ b->size += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->size < s->fragsize) {
-+ up(&b->sem);
-+ break;
-+ }
-+
-+ /* Send current buffer to dma */
-+ s->active = 1;
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, b->size);
-+ b->size = 0; /* indicate that the buffer has been sent */
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ DPRINTK("audio_write: return=%d\n", ret);
-+ return ret;
-+}
-+
-+
-+static inline void audio_check_tx_spin(audio_state_t *state)
-+{
-+ /*
-+ * With some codecs like the Philips UDA1341 we must ensure
-+ * there is an output stream at any time while recording since
-+ * this is how the UDA1341 gets its clock from the SA1100.
-+ * So while there is no playback data to send, the output DMA
-+ * will spin with all zeroes. We use the cache flush special
-+ * area for that.
-+ */
-+ if (state->need_tx_for_rx && !state->tx_spinning) {
-+ sa1100_dma_set_spin(state->output_stream->dma_ch,
-+ (dma_addr_t)FLUSH_BASE_PHYS, 2048);
-+ state->tx_spinning = 1;
-+ }
-+}
-+
-+
-+static void audio_prime_dma(audio_stream_t *s)
-+{
-+ int i;
-+
-+ s->active = 1;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *b = s->buf;
-+ down(&b->sem);
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, s->fragsize);
-+ NEXT_BUF(s, buf);
-+ }
-+}
-+
-+
-+static int audio_read(struct file *file, char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->input_stream;
-+ int chunksize, ret = 0;
-+
-+ DPRINTK("audio_read: count=%d\n", count);
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+
-+ if (!s->active) {
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ audio_check_tx_spin(state);
-+ audio_prime_dma(s);
-+ }
-+
-+ while (count > 0) {
-+ audio_buf_t *b = s->buf;
-+
-+ /* Wait for a buffer to become full */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&b->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&b->sem))
-+ break;
-+ }
-+
-+ /* Grab data from the current buffer */
-+ chunksize = b->size;
-+ if (chunksize > count)
-+ chunksize = count;
-+ DPRINTK("read %d from %d\n", chunksize, s->buf_idx);
-+ if (copy_to_user(buffer,
-+ b->start + s->fragsize - b->size,
-+ chunksize)) {
-+ up(&b->sem);
-+ return -EFAULT;
-+ }
-+ b->size -= chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->size > 0) {
-+ up(&b->sem);
-+ break;
-+ }
-+
-+ /* Make current buffer available for DMA again */
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, s->fragsize);
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ DPRINTK("audio_read: return=%d\n", ret);
-+ return ret;
-+}
-+
-+
-+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s;
-+ unsigned long size, vma_addr;
-+ int i, ret;
-+
-+ if (vma->vm_pgoff != 0)
-+ return -EINVAL;
-+
-+ if (vma->vm_flags & VM_WRITE) {
-+ if (!state->wr_ref)
-+ return -EINVAL;;
-+ s = state->output_stream;
-+ } else if (vma->vm_flags & VM_READ) {
-+ if (!state->rd_ref)
-+ return -EINVAL;
-+ s = state->input_stream;
-+ } else return -EINVAL;
-+
-+ if (s->mapped)
-+ return -EINVAL;
-+ size = vma->vm_end - vma->vm_start;
-+ if (size != s->fragsize * s->nbfrags)
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ vma_addr = vma->vm_start;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *buf = &s->buffers[i];
-+ if (!buf->master)
-+ continue;
-+ ret = remap_page_range(vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);
-+ if (ret)
-+ return ret;
-+ vma_addr += buf->master;
-+ }
-+ s->mapped = 1;
-+
-+ return 0;
-+}
-+
-+
-+static unsigned int audio_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ unsigned int mask = 0;
-+ int i;
-+
-+ DPRINTK("audio_poll(): mode=%s%s\n",
-+ (file->f_mode & FMODE_READ) ? "r" : "",
-+ (file->f_mode & FMODE_WRITE) ? "w" : "");
-+
-+ if (file->f_mode & FMODE_READ) {
-+ /* Start audio input if not already active */
-+ if (!is->active) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ audio_check_tx_spin(state);
-+ audio_prime_dma(is);
-+ }
-+ poll_wait(file, &is->wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ poll_wait(file, &os->wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_READ) {
-+ if (is->mapped) {
-+/* if the buffer is mapped assume we care that there are more bytes available than
-+ when we last asked using SNDCTL_DSP_GETxPTR */
-+ if (is->bytecount != is->getptrCount)
-+ mask |= POLLIN | POLLRDNORM;
-+ } else {
-+ for (i = 0; i < is->nbfrags; i++) {
-+ if (atomic_read(&is->buffers[i].sem.count) > 0) {
-+ mask |= POLLIN | POLLRDNORM;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (os->mapped) {
-+ if (os->bytecount != os->getptrCount)
-+ mask |= POLLOUT | POLLWRNORM;
-+ } else {
-+ for (i = 0; i < os->nbfrags; i++) {
-+ if (atomic_read(&os->buffers[i].sem.count) > 0) {
-+ mask |= POLLOUT | POLLWRNORM;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+ DPRINTK("audio_poll() returned mask of %s%s\n",
-+ (mask & POLLIN) ? "r" : "",
-+ (mask & POLLOUT) ? "w" : "");
-+
-+ return mask;
-+}
-+
-+
-+static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+
-+static int audio_set_fragments(audio_stream_t *s, int val)
-+{
-+ if (s->active)
-+ return -EBUSY;
-+ if (s->buffers)
-+ audio_clear_buf(s);
-+ s->nbfrags = (val >> 16) & 0x7FFF;
-+ val &= 0xffff;
-+ if (val < 4)
-+ val = 4;
-+ if (val > 15)
-+ val = 15;
-+ s->fragsize = 1 << val;
-+ if (s->nbfrags < 2)
-+ s->nbfrags = 2;
-+ if (s->nbfrags * s->fragsize > 128 * 1024)
-+ s->nbfrags = 128 * 1024 / s->fragsize;
-+ if (audio_setup_buf(s))
-+ return -ENOMEM;
-+ return val|(s->nbfrags << 16);
-+}
-+
-+static int audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *os = state->output_stream;
-+ audio_stream_t *is = state->input_stream;
-+ long val;
-+
-+ /* dispatch based on command */
-+ switch (cmd) {
-+ case OSS_GETVERSION:
-+ return put_user(SOUND_VERSION, (int *)arg);
-+
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ if (file->f_mode & FMODE_WRITE)
-+ return put_user(os->fragsize, (int *)arg);
-+ else
-+ return put_user(is->fragsize, (int *)arg);
-+
-+ case SNDCTL_DSP_GETCAPS:
-+ val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
-+ if (is && os)
-+ val |= DSP_CAP_DUPLEX;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if (get_user(val, (long *) arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ int ret = audio_set_fragments(is, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ int ret = audio_set_fragments(os, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_SYNC:
-+ return audio_sync(file);
-+
-+ case SNDCTL_DSP_SETDUPLEX:
-+ return 0;
-+
-+ case SNDCTL_DSP_POST:
-+ return 0;
-+
-+ case SNDCTL_DSP_GETTRIGGER:
-+ val = 0;
-+ if (file->f_mode & FMODE_READ && is->active && !is->stopped)
-+ val |= PCM_ENABLE_INPUT;
-+ if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
-+ val |= PCM_ENABLE_OUTPUT;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETTRIGGER:
-+ if (get_user(val, (int *)arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ if (val & PCM_ENABLE_INPUT) {
-+ if (!is->active) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ audio_prime_dma(is);
-+ }
-+ audio_check_tx_spin(state);
-+ if (is->stopped) {
-+ is->stopped = 0;
-+ sa1100_dma_resume(is->dma_ch);
-+ }
-+ } else {
-+ sa1100_dma_stop(is->dma_ch);
-+ is->stopped = 1;
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (val & PCM_ENABLE_OUTPUT) {
-+ if (!os->active) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ if (os->mapped)
-+ audio_prime_dma(os);
-+ }
-+ if (os->stopped) {
-+ os->stopped = 0;
-+ sa1100_dma_resume(os->dma_ch);
-+ }
-+ } else {
-+ sa1100_dma_stop(os->dma_ch);
-+ os->stopped = 1;
-+ }
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_GETOPTR:
-+ case SNDCTL_DSP_GETIPTR:
-+ {
-+ count_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
-+ audio_buf_t *b;
-+ dma_addr_t ptr;
-+ int bytecount, offset, flags;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (s->active) {
-+ save_flags_cli(flags);
-+ if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
-+ offset = ptr - b->dma_addr;
-+ inf.ptr = (b - s->buffers) * s->fragsize + offset;
-+ } else offset = 0;
-+ bytecount = s->bytecount + offset;
-+ s->getptrCount = s->bytecount; /* so poll can tell if it changes */
-+ inf.blocks = s->fragcount;
-+ s->fragcount = 0;
-+ restore_flags(flags);
-+ if (bytecount < 0)
-+ bytecount = 0;
-+ inf.bytes = bytecount;
-+ }
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETOSPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ int i;
-+
-+ if (!(file->f_mode & FMODE_WRITE))
-+ return -EINVAL;
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ for (i = 0; i < os->nbfrags; i++) {
-+ if (atomic_read(&os->buffers[i].sem.count) > 0) {
-+ if (os->buffers[i].size == 0)
-+ inf.fragments++;
-+ inf.bytes += os->fragsize - os->buffers[i].size;
-+ }
-+ }
-+ inf.fragstotal = os->nbfrags;
-+ inf.fragsize = os->fragsize;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETISPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ int i;
-+
-+ if (!(file->f_mode & FMODE_READ))
-+ return -EINVAL;
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ for (i = 0; i < is->nbfrags; i++) {
-+ if (atomic_read(&is->buffers[i].sem.count) > 0) {
-+ if (is->buffers[i].size == is->fragsize)
-+ inf.fragments++;
-+ inf.bytes += is->buffers[i].size;
-+ }
-+ }
-+ inf.fragstotal = is->nbfrags;
-+ inf.fragsize = is->fragsize;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_NONBLOCK:
-+ file->f_flags |= O_NONBLOCK;
-+ return 0;
-+
-+ case SNDCTL_DSP_RESET:
-+ if (file->f_mode & FMODE_READ) {
-+ if (state->tx_spinning) {
-+ sa1100_dma_set_spin(os->dma_ch, 0, 0);
-+ state->tx_spinning = 0;
-+ }
-+ audio_reset_buf(is);
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_reset_buf(os);
-+ }
-+ return 0;
-+
-+ default:
-+ /*
-+ * Let the client of this module handle the
-+ * non generic ioctls
-+ */
-+ return state->client_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int audio_release(struct inode *inode, struct file *file)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ DPRINTK("audio_release\n");
-+
-+ down(&state->sem);
-+
-+ if (file->f_mode & FMODE_READ) {
-+ if (state->tx_spinning) {
-+ sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0);
-+ state->tx_spinning = 0;
-+ }
-+ audio_clear_buf(state->input_stream);
-+ if (!state->skip_dma_init) {
-+ sa1100_free_dma(state->input_stream->dma_ch);
-+ if (state->need_tx_for_rx && !state->wr_ref)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ }
-+ state->rd_ref = 0;
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_sync(file);
-+ audio_clear_buf(state->output_stream);
-+ if (!state->skip_dma_init)
-+ if (!state->need_tx_for_rx || !state->rd_ref)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ state->wr_ref = 0;
-+ }
-+
-+ if (!AUDIO_ACTIVE(state)) {
-+ if (state->hw_shutdown)
-+ state->hw_shutdown(state->data);
-+#ifdef CONFIG_PM
-+ pm_unregister(state->pm_dev);
-+#endif
-+ }
-+
-+ up(&state->sem);
-+ return 0;
-+}
-+
-+
-+#ifdef CONFIG_PM
-+
-+static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ audio_state_t *state = (audio_state_t *)pm_dev->data;
-+
-+ switch (req) {
-+ case PM_SUSPEND: /* enter D1-D3 */
-+ if (state->output_stream)
-+ sa1100_dma_sleep(state->output_stream->dma_ch);
-+ if (state->input_stream)
-+ sa1100_dma_sleep(state->input_stream->dma_ch);
-+ if (AUDIO_ACTIVE(state) && state->hw_shutdown)
-+ state->hw_shutdown(state->data);
-+ break;
-+ case PM_RESUME: /* enter D0 */
-+ if (AUDIO_ACTIVE(state) && state->hw_init)
-+ state->hw_init(state->data);
-+ if (state->input_stream)
-+ sa1100_dma_wakeup(state->input_stream->dma_ch);
-+ if (state->output_stream)
-+ sa1100_dma_wakeup(state->output_stream->dma_ch);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+#endif
-+
-+
-+int sa1100_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state)
-+{
-+ int err, need_tx_dma;
-+
-+ DPRINTK("audio_open\n");
-+
-+ down(&state->sem);
-+
-+ /* access control */
-+ err = -ENODEV;
-+ if ((file->f_mode & FMODE_WRITE) && !state->output_stream)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && !state->input_stream)
-+ goto out;
-+ err = -EBUSY;
-+ if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && state->rd_ref)
-+ goto out;
-+ err = -EINVAL;
-+ if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)
-+ goto out;
-+
-+ /* request DMA channels */
-+ if (state->skip_dma_init)
-+ goto skip_dma;
-+ need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
-+ ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
-+ if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
-+ need_tx_dma = 0;
-+ if (need_tx_dma) {
-+ err = sa1100_request_dma(&state->output_stream->dma_ch,
-+ state->output_id,
-+ state->output_dma);
-+ if (err)
-+ goto out;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ err = sa1100_request_dma(&state->input_stream->dma_ch,
-+ state->input_id,
-+ state->input_dma);
-+ if (err) {
-+ if (need_tx_dma)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ goto out;
-+ }
-+ }
-+skip_dma:
-+
-+ /* now complete initialisation */
-+ if (!AUDIO_ACTIVE(state)) {
-+ if (state->hw_init)
-+ state->hw_init(state->data);
-+#ifdef CONFIG_PM
-+ state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);
-+ if (state->pm_dev)
-+ state->pm_dev->data = state;
-+#endif
-+ }
-+
-+ if ((file->f_mode & FMODE_WRITE)) {
-+ state->wr_ref = 1;
-+ audio_clear_buf(state->output_stream);
-+ state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ state->output_stream->mapped = 0;
-+ sa1100_dma_set_callback(state->output_stream->dma_ch,
-+ audio_dmaout_done_callback);
-+ init_waitqueue_head(&state->output_stream->wq);
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ state->rd_ref = 1;
-+ audio_clear_buf(state->input_stream);
-+ state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ state->input_stream->mapped = 0;
-+ sa1100_dma_set_callback(state->input_stream->dma_ch,
-+ audio_dmain_done_callback);
-+ init_waitqueue_head(&state->input_stream->wq);
-+ }
-+
-+ file->private_data = state;
-+ file->f_op->release = audio_release;
-+ file->f_op->write = audio_write;
-+ file->f_op->read = audio_read;
-+ file->f_op->mmap = audio_mmap;
-+ file->f_op->poll = audio_poll;
-+ file->f_op->ioctl = audio_ioctl;
-+ file->f_op->llseek = audio_llseek;
-+ err = 0;
-+
-+out:
-+ up(&state->sem);
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(sa1100_audio_attach);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Common audio handling for the SA11x0 processor");
-+MODULE_LICENSE("GPL");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1100-audio.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,68 @@
-+/*
-+ * Common audio handling for the SA11x0
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+
-+/*
-+ * Buffer Management
-+ */
-+
-+typedef struct {
-+ int size; /* buffer size */
-+ char *start; /* points to actual buffer */
-+ dma_addr_t dma_addr; /* physical buffer address */
-+ struct semaphore sem; /* down before touching the buffer */
-+ int master; /* owner for buffer allocation, contain size when true */
-+ struct audio_stream_s *stream; /* owning stream */
-+} audio_buf_t;
-+
-+typedef struct audio_stream_s {
-+ audio_buf_t *buffers; /* pointer to audio buffer structures */
-+ audio_buf_t *buf; /* current buffer used by read/write */
-+ u_int buf_idx; /* index for the pointer above... */
-+ u_int fragsize; /* fragment i.e. buffer size */
-+ u_int nbfrags; /* nbr of fragments i.e. buffers */
-+ int bytecount; /* nbr of processed bytes */
-+ int getptrCount; /* value of bytecount last time anyone asked via GETxPTR */
-+ int fragcount; /* nbr of fragment transitions */
-+ dmach_t dma_ch; /* DMA channel ID */
-+ wait_queue_head_t wq; /* for poll */
-+ int mapped:1; /* mmap()'ed buffers */
-+ int active:1; /* actually in progress */
-+ int stopped:1; /* might be active but stopped */
-+} audio_stream_t;
-+
-+/*
-+ * State structure for one instance
-+ */
-+
-+typedef struct {
-+ audio_stream_t *output_stream;
-+ audio_stream_t *input_stream;
-+ dma_device_t output_dma;
-+ dma_device_t input_dma;
-+ char *output_id;
-+ char *input_id;
-+ int rd_ref:1; /* open reference for recording */
-+ int wr_ref:1; /* open reference for playback */
-+ int need_tx_for_rx:1; /* if data must be sent while receiving */
-+ int tx_spinning:1; /* tx spinning active */
-+ int skip_dma_init:1; /* hack for the SA1111 */
-+ void *data;
-+ void (*hw_init)(void *);
-+ void (*hw_shutdown)(void *);
-+ int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
-+ struct pm_dev *pm_dev;
-+ struct semaphore sem; /* to protect against races in attach() */
-+} audio_state_t;
-+
-+/*
-+ * Functions exported by this module
-+ */
-+extern int sa1100_audio_attach( struct inode *inode, struct file *file,
-+ audio_state_t *state);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1100ssp.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,182 @@
-+/*
-+ * Glue audio driver for a simple DAC on the SA1100's SSP port
-+ *
-+ * Copyright (c) 2001 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-06-04 Nicolas Pitre Initial release.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "SA1100 SSP audio"
-+
-+#define AUDIO_FMT AFMT_S16_LE
-+#define AUDIO_CHANNELS 2
-+
-+static int sample_rate = 44100;
-+
-+
-+static void ssp_audio_init(void)
-+{
-+ if (machine_is_lart()) {
-+ unsigned long flags;
-+ local_irq_save(flags);
-+
-+ /* LART has the SSP port rewired to GPIO 10-13, 19 */
-+ /* alternate functions for the GPIOs */
-+ GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK |
-+ GPIO_SSP_SFRM | GPIO_SSP_CLK );
-+
-+ /* Set the direction: 10, 12, 13 output; 11, 19 input */
-+ GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM );
-+ GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK );
-+
-+ /* enable SSP pin swap */
-+ PPAR |= PPAR_SPR;
-+
-+ local_irq_restore(flags);
-+ }
-+
-+ /* turn on the SSP */
-+ Ser4SSCR0 = 0;
-+ Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) |
-+ SSCR0_SSE);
-+ Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk);
-+}
-+
-+static void ssp_audio_shutdown(void)
-+{
-+ Ser4SSCR0 = 0;
-+}
-+
-+static int ssp_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* Simple standard DACs are stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* Simple standard DACs are stereo only */
-+ return put_user(AUDIO_CHANNELS, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ case SOUND_PCM_READ_RATE:
-+ /* We assume the clock doesn't change */
-+ return put_user(sample_rate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* Simple standard DACs are 16-bit only */
-+ return put_user(AUDIO_FMT, (long *) arg);
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Generic SSP sound",
-+ hw_init: ssp_audio_init,
-+ hw_shutdown: ssp_audio_shutdown,
-+ client_ioctl: ssp_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int ssp_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations ssp_audio_fops = {
-+ open: ssp_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+static int audio_dev_id;
-+
-+static int __init sa1100ssp_audio_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_lart()) {
-+ printk(KERN_ERR AUDIO_NAME ": no support for this SA-1100 design!\n");
-+ /* look at ssp_audio_init() for specific initialisations */
-+ return -ENODEV;
-+ }
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&ssp_audio_fops, -1);
-+
-+ printk( KERN_INFO AUDIO_NAME " initialized\n" );
-+ return 0;
-+}
-+
-+static void __exit sa1100ssp_audio_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+}
-+
-+module_init(sa1100ssp_audio_init);
-+module_exit(sa1100ssp_audio_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for a simple DAC on the SA1100's SSP port");
-+
-+MODULE_PARM(sample_rate, "i");
-+MODULE_PARM_DESC(sample_rate, "Sample rate of the audio DAC, default is 44100");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1111-ac97.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,518 @@
-+/*
-+ * Glue audio driver for the CS4205 and CS4201 AC'97 codecs.
-+ * largely based on the framework provided by sa1111-uda1341.c.
-+ *
-+ * Copyright (c) 2002 Bertrik Sikken (bertrik.sikken@technolution.nl)
-+ * Copyright (c) 2002 Robert Whaley (rwhaley@applieddata.net)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This driver makes use of the ac97_codec module (for mixer registers)
-+ * and the sa1100-audio module (for DMA).
-+ *
-+ * History:
-+ *
-+ * 2002-04-04 Initial version.
-+ * 2002-04-10 Updated mtd_audio_init to improve choppy sound
-+ * and hanging sound issue.
-+ * 2002-05-16 Updated for ADS Bitsy+ Robert Whaley
-+ * 2002-06-28 Cleanup and added retry for read register timeouts
-+ * 2002-08-14 Updated for ADS AGC Robert Whaley
-+ * 2002-12-26 Cleanup, remove CONFIG_PM (it's handled by sa1100-audio.c)
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/proc_fs.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ac97_codec.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/dma.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "sa1100-audio.h"
-+
-+/* SAC FIFO depth, low nibble is transmit fifo, high nibble is receive FIFO */
-+#define SAC_FIFO_DEPTH 0x77
-+
-+// #define DEBUG
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+/*
-+ Our codec data
-+*/
-+static struct ac97_codec ac97codec;
-+static int audio_dev_id, mixer_dev_id;
-+static audio_stream_t output_stream, input_stream;
-+
-+/* proc info */
-+
-+struct proc_dir_entry *ac97_ps;
-+
-+static int sa1111_ac97_set_adc_rate(long rate);
-+static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val);
-+static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg);
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M') {
-+ return -EINVAL;
-+ }
-+
-+ /* pass the ioctl to the ac97 mixer */
-+ return ac97codec.mixer_ioctl(&ac97codec, cmd, arg);
-+}
-+
-+
-+static struct file_operations sa1111_ac97_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+static void sa1111_ac97_power_off(void *dummy)
-+{
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ /* turn off audio and audio amp */
-+ ADS_CPLD_PCON |= (ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
-+
-+ /* make GPIO11 high impeadence */
-+ GPDR &= ~GPIO_GPIO11;
-+
-+ /* disable SACR0 so we can make these pins high impeadence */
-+ SACR0 &= ~SACR0_ENB;
-+
-+ /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
-+ PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSAGC
-+ /* turn off audio and audio amp */
-+ ADS_CR1 &= ~(ADS_CR1_CODEC | ADS_CR1_AMP);
-+
-+ /* disable SACR0 so we can make these pins high impeadence */
-+ SACR0 &= ~SACR0_ENB;
-+
-+ /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
-+ PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+
-+#endif
-+}
-+
-+
-+static void sa1111_ac97_power_on(void *dummy)
-+{
-+ int ret, i;
-+
-+ /* disable L3 */
-+ SACR1 = 0;
-+
-+ SKPCR |= (SKPCR_ACCLKEN); /* enable ac97 clock */
-+ udelay(50);
-+
-+ /* BIT_CLK is input to SA1111, DMA thresholds 9 (both dirs) */
-+ SACR0 |= SACR0_BCKD | (SAC_FIFO_DEPTH << 8);
-+
-+ /* reset SAC registers */
-+ SACR0 &= ~SACR0_RST;
-+ udelay(50);
-+ SACR0 |= SACR0_RST;
-+ udelay(50);
-+ SACR0 &= ~SACR0_RST;
-+
-+ /* setup SA1111 to use AC'97 */
-+ SBI_SKCR |= SKCR_SELAC; /* select ac97 */
-+ udelay(50);
-+
-+ /* issue a cold AC97 reset */
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+
-+ /* initialize reset line */
-+ GAFR &= ~GPIO_GPIO11;
-+ GPDR |= GPIO_GPIO11;
-+ GPSR = GPIO_GPIO11;
-+
-+ /* turn on audio and audio amp */
-+ ADS_CPLD_PCON &= ~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
-+ mdelay(5);
-+
-+ /* reset by lowering the reset pin momentarily */
-+ DPRINTK("reseting codec via GPIO11\n");
-+ GPCR = GPIO_GPIO11;
-+ udelay(5);
-+ GPSR = GPIO_GPIO11;
-+ udelay(10);
-+
-+#endif
-+#ifdef CONFIG_SA1100_ADSAGC
-+
-+ /* turn on audio and audio amp */
-+ DPRINTK("before turning on power. ADS_CR1: %x\n", ADS_CR1);
-+ ADS_CR1 |= (ADS_CR1_AMP | ADS_CR1_CODEC);
-+ DPRINTK("after turnning on power. ADS_CR1: %x\n", ADS_CR1);
-+ mdelay(5);
-+
-+ /* reset by lowering the reset pin momentarily */
-+ DPRINTK("reseting codec via CPLD\n");
-+ ADS_CR1 |= ADS_CR1_AUDIO_RST;
-+ DPRINTK("after reset1. ADS_CR1: %x\n", ADS_CR1);
-+ udelay(5);
-+ ADS_CR1 &= ~ADS_CR1_AUDIO_RST;
-+ DPRINTK("after reset2. ADS_CR1: %x\n", ADS_CR1);
-+ udelay(10);
-+
-+#endif
-+ SACR2 = 0;
-+ udelay(50);
-+
-+ DPRINTK("before SW reset: SACR2: %x\n", SACR2);
-+ SACR2 = SACR2_RESET;
-+ DPRINTK("after SW reset: SACR2: %x\n", SACR2);
-+ udelay(50);
-+
-+ /* set AC97 slot 3 and 4 (PCM out) to valid */
-+ SACR2 = (SACR2_RESET | SACR2_TS3V | SACR2_TS4V);
-+
-+ /* enable SAC */
-+ SACR0 |= SACR0_ENB;
-+
-+ i = 100;
-+ while (!(SASR1 & SASR1_CRDY)) {
-+ if (!i--) {
-+ printk("Didn't get CRDY. SASR1=%x SKID=%x\n", SASR1, SBI_SKID);
-+ break;
-+ }
-+ udelay(50);
-+ }
-+
-+ if (!(ret = ac97_probe_codec(&ac97codec))) {
-+ printk("ac97_probe_codec failed (%d)\n", ret);
-+ return;
-+ }
-+
-+ /* mic ADC on, disable VRA, disable VRM */
-+ sa1111_ac97_write_reg(&ac97codec, AC97_EXTENDED_STATUS, 0x0200);
-+}
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+
-+static int sa1111_ac97_audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ DPRINTK("sa1111_ac97_audio_ioctl\n");
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret) {
-+ return ret;
-+ }
-+ /* the cs42xx is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the cs42xx is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+#define SA1100_AC97_IOCTL_EXTRAS
-+
-+#ifdef SA1100_AC97_IOCTL_EXTRAS
-+
-+#define SNDCTL_DSP_AC97_CMD _SIOWR('P', 99, int)
-+#define SNDCTL_DSP_INPUT_SPEED _SIOWR('P', 98, int)
-+#define SOUND_PCM_READ_INPUT_RATE _SIOWR('P', 97, int)
-+
-+ case SNDCTL_DSP_AC97_CMD:
-+
-+ ret = get_user(val, (long *) arg);
-+ if (ret) {
-+ break;
-+ }
-+ sa1111_ac97_write_reg(&ac97codec, (u8) ((val & 0xff000000) >> 24), (u16) (val & 0xffff));
-+ return 0;
-+
-+
-+ case SNDCTL_DSP_INPUT_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ // acc code here to set the speed
-+ if (ret) {
-+ break;
-+ }
-+ // note that this only changes the ADC rate, not the
-+ // rate of the DAC.
-+ ret = sa1111_ac97_set_adc_rate(val);
-+ if (ret)
-+ break;
-+ return put_user(val, (long *) arg);
-+
-+ case SOUND_PCM_READ_INPUT_RATE:
-+
-+ return put_user((long) sa1111_ac97_read_reg(&ac97codec, 0x32), (long *) arg);
-+
-+
-+#endif
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) {
-+ break;
-+ }
-+
-+ case SOUND_PCM_READ_RATE:
-+ /* only 48 kHz playback is supported by the SA1111 */
-+ return put_user(48000L, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ input_stream: &input_stream,
-+ skip_dma_init: 1, /* done locally */
-+ hw_init: sa1111_ac97_power_on,
-+ hw_shutdown: sa1111_ac97_power_off,
-+ client_ioctl: sa1111_ac97_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+
-+static int sa1111_ac97_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations sa1111_ac97_audio_fops = {
-+ open: sa1111_ac97_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val)
-+{
-+ int i;
-+
-+ /* reset status bits */
-+ SASCR = SASCR_DTS;
-+
-+ /* write command and data registers */
-+ ACCAR = reg << 12;
-+ ACCDR = val << 4;
-+
-+ /* wait for data to be transmitted */
-+ i = 0;
-+ while ((SASR1 & SASR1_CADT) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("sa1111_ac97_write_reg failed (data not transmitted. SASR1: %x)\n", SASR1);
-+ break;
-+ }
-+ }
-+
-+ DPRINTK("<%03d> sa1111_ac97_write_reg, [%02X]=%04X\n", i, reg, val);
-+}
-+
-+
-+static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg)
-+{
-+ u16 val;
-+ int i;
-+ int retry = 10;
-+
-+ do {
-+ /* reset status bits */
-+ SASCR = SASCR_RDD | SASCR_STO;
-+
-+ /* write command register */
-+ ACCAR = (reg | 0x80) << 12;
-+ ACCDR = 0;
-+
-+ /* wait for SADR bit in SASR1 */
-+ i = 0;
-+ while ((SASR1 & SASR1_SADR) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("<---> sa1111_ac97_read_reg failed\n");
-+ retry--;
-+ break;
-+ }
-+ if ((SASR1 & SASR1_RSTO) != 0) {
-+ DPRINTK("sa1111_ac97_read_reg *timeout*\n");
-+ retry--;
-+ break;
-+ }
-+ }
-+
-+ } while ((SASR1 & SASR1_SADR) == 0 && retry > 0);
-+
-+ val = ACSDR >> 4;
-+
-+ DPRINTK("<%03d> sa1111_ac97_read_reg, [%02X]=%04X\n", i, reg, val);
-+ return val;
-+}
-+
-+
-+/* wait for codec ready */
-+static void sa1111_ac97_ready(struct ac97_codec *dev)
-+{
-+ int i;
-+ u16 val;
-+
-+ i = 0;
-+ while ((SASR1 & SASR1_CRDY) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("sa1111_ac97_ready failed\n");
-+ return;
-+ }
-+ }
-+ DPRINTK("codec_ready bit took %d cycles\n", i);
-+
-+ /* Wait for analog parts of codec to initialise */
-+ i = 0;
-+ do {
-+ val = sa1111_ac97_read_reg(&ac97codec, AC97_POWER_CONTROL);
-+ if (++i > 100) {
-+ break;
-+ }
-+ mdelay(10);
-+ } while ((val & 0xF) != 0xF || val == 0xFFFF);
-+
-+ /* the cs42xx typically takes 150 ms to initialise */
-+
-+ DPRINTK("analog init took %d cycles\n", i);
-+}
-+
-+
-+static int __init sa1111_ac97_init(void)
-+{
-+ int ret;
-+
-+ // SBI_SKCR |= SKCR_RCLKEN;
-+
-+ DPRINTK("sa1111_ac97_init\n");
-+
-+ /* install the ac97 mixer module */
-+ ac97codec.codec_read = sa1111_ac97_read_reg;
-+ ac97codec.codec_write = sa1111_ac97_write_reg;
-+ ac97codec.codec_wait = sa1111_ac97_ready;
-+
-+ /* Acquire and initialize DMA */
-+ ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
-+ SA1111_SAC_XMT_CHANNEL);
-+ if (ret < 0) {
-+ printk("DMA request for SAC output failed\n");
-+ return ret;
-+ }
-+
-+ ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
-+ SA1111_SAC_RCV_CHANNEL);
-+ if (ret < 0) {
-+ printk("DMA request for SAC input failed\n");
-+ sa1100_free_dma(output_stream.dma_ch);
-+ return ret;
-+ }
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&sa1111_ac97_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&sa1111_ac97_mixer_fops, -1);
-+
-+
-+ /* setup proc entry */
-+ ac97_ps = create_proc_read_entry ("driver/sa1111-ac97", 0, NULL,
-+ ac97_read_proc, &ac97codec);
-+
-+ return 0;
-+}
-+
-+
-+static void __exit sa1111_ac97_exit(void)
-+{
-+ SKPCR &= ~SKPCR_ACCLKEN; /* disable ac97 clock */
-+ SBI_SKCR &= ~SKCR_SELAC; /* deselect ac97 */
-+
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ sa1100_free_dma(output_stream.dma_ch);
-+ sa1100_free_dma(input_stream.dma_ch);
-+}
-+
-+static int sa1111_ac97_set_adc_rate(long rate)
-+{
-+
-+ // note this only changes the rate of the ADC, the DAC is fixed at 48K.
-+ // this is due to limitations of the SA1111 chip
-+
-+ u16 code = rate;
-+
-+ switch (rate) {
-+ case 8000:
-+ case 11025:
-+ case 16000:
-+ case 22050:
-+ case 32000:
-+ case 44100:
-+ case 48000:
-+ break;
-+ default:
-+ return -1;
-+ }
-+ sa1111_ac97_write_reg(&ac97codec, 0x2A, 0x0001);
-+ sa1111_ac97_write_reg(&ac97codec, 0x32, code);
-+ return 0;
-+}
-+
-+module_init(sa1111_ac97_init);
-+module_exit(sa1111_ac97_exit);
-+
-+MODULE_AUTHOR("Bertrik Sikken, Technolution B.V., Netherlands");
-+MODULE_DESCRIPTION("Glue audio driver for AC'97 codec");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/sa1111-uda1341.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,282 @@
-+/*
-+ * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2000-09-04 John Dorsey SA-1111 Serial Audio Controller support
-+ * was initially added to the sa1100-uda1341.c
-+ * driver.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-09-23 Russell King Remove old L3 bus driver.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ioport.h>
-+#include <linux/pm.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "sa1100-audio.h"
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+/*
-+ * Definitions
-+ */
-+
-+#define AUDIO_RATE_DEFAULT 22050
-+
-+#define AUDIO_CLK_BASE 561600
-+
-+
-+
-+/*
-+ * Mixer interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations uda1341_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+static int audio_clk_div = (AUDIO_CLK_BASE + AUDIO_RATE_DEFAULT/2)/AUDIO_RATE_DEFAULT;
-+
-+static void sa1111_audio_init(void *dummy)
-+{
-+#ifdef CONFIG_ASSABET_NEPONSET
-+ if (machine_is_assabet()) {
-+ /* Select I2S audio (instead of AC-Link) */
-+ AUD_CTL = AUD_SEL_1341;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_JORNADA720
-+ if (machine_is_jornada720()) {
-+ /* LDD4 is speaker, LDD3 is microphone */
-+ PPSR &= ~(PPC_LDD3 | PPC_LDD4);
-+ PPDR |= PPC_LDD3 | PPC_LDD4;
-+ PPSR |= PPC_LDD4; /* enable speaker */
-+ PPSR |= PPC_LDD3; /* enable microphone */
-+ }
-+#endif
-+
-+ SBI_SKCR &= ~SKCR_SELAC;
-+
-+ /* Enable the I2S clock and L3 bus clock: */
-+ SKPCR |= (SKPCR_I2SCLKEN | SKPCR_L3CLKEN);
-+
-+ /* Activate and reset the Serial Audio Controller */
-+ SACR0 |= (SACR0_ENB | SACR0_RST);
-+ mdelay(5);
-+ SACR0 &= ~SACR0_RST;
-+
-+ /* For I2S, BIT_CLK is supplied internally. The "SA-1111
-+ * Specification Update" mentions that the BCKD bit should
-+ * be interpreted as "0 = output". Default clock divider
-+ * is 22.05kHz.
-+ *
-+ * Select I2S, L3 bus. "Recording" and "Replaying"
-+ * (receive and transmit) are enabled.
-+ */
-+ SACR1 = SACR1_L3EN;
-+ SKAUD = audio_clk_div - 1;
-+
-+ /* Initialize the UDA1341 internal state */
-+ l3_open(&uda1341);
-+}
-+
-+static void sa1111_audio_shutdown(void *dummy)
-+{
-+ l3_close(&uda1341);
-+ SACR0 &= ~SACR0_ENB;
-+}
-+
-+static int sa1111_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ if (val < 8000) val = 8000;
-+ if (val > 48000) val = 48000;
-+ audio_clk_div = (AUDIO_CLK_BASE + val/2)/val;
-+ SKAUD = audio_clk_div - 1;
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(AUDIO_CLK_BASE/audio_clk_div, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (as per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ input_stream: &input_stream,
-+ skip_dma_init: 1, /* done locally */
-+ hw_init: sa1111_audio_init,
-+ hw_shutdown: sa1111_audio_shutdown,
-+ client_ioctl: sa1111_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int sa1111_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations sa1111_audio_fops = {
-+ open: sa1111_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init sa1111_uda1341_init(void)
-+{
-+ struct uda1341_cfg cfg;
-+ int ret;
-+
-+ if ( !( (machine_is_assabet() && machine_has_neponset()) ||
-+ machine_is_jornada720() ||
-+ machine_is_badge4() ))
-+ return -ENODEV;
-+
-+ if (!request_mem_region(_SACR0, 512, "sound"))
-+ return -EBUSY;
-+
-+ ret = l3_attach_client(&uda1341, "l3-sa1111", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* Acquire and initialize DMA */
-+ ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
-+ SA1111_SAC_XMT_CHANNEL);
-+ if (ret < 0)
-+ goto release_l3;
-+
-+ ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
-+ SA1111_SAC_RCV_CHANNEL);
-+ if (ret < 0)
-+ goto release_dma;
-+
-+ cfg.fs = 256;
-+ cfg.format = FMT_I2S;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&sa1111_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1);
-+
-+ printk(KERN_INFO "Sound: SA1111 UDA1341: dsp id %d mixer id %d\n",
-+ audio_dev_id, mixer_dev_id);
-+ return 0;
-+
-+release_dma:
-+ sa1100_free_dma(output_stream.dma_ch);
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ release_mem_region(_SACR0, 512);
-+ return ret;
-+}
-+
-+static void __exit sa1111_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ sa1100_free_dma(output_stream.dma_ch);
-+ sa1100_free_dma(input_stream.dma_ch);
-+ l3_detach_client(&uda1341);
-+
-+ release_mem_region(_SACR0, 512);
-+}
-+
-+module_init(sa1111_uda1341_init);
-+module_exit(sa1111_uda1341_exit);
-+
-+MODULE_AUTHOR("John Dorsey, Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/sound/uda1341.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,511 @@
-+/*
-+ * Philips UDA1341 mixer device driver
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2000-08-19 Erik Bunce More inline w/ OSS API and UDA1341 docs
-+ * including fixed AGC and audio source handling
-+ *
-+ * 2000-11-30 Nicolas Pitre - More mixer functionalities.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-08-13 Russell King Re-written as part of the L3 interface
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/ioctl.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define DEF_VOLUME 65
-+
-+/*
-+ * UDA1341 L3 address and command types
-+ */
-+#define UDA1341_L3ADDR 5
-+#define UDA1341_DATA0 (UDA1341_L3ADDR << 2 | 0)
-+#define UDA1341_DATA1 (UDA1341_L3ADDR << 2 | 1)
-+#define UDA1341_STATUS (UDA1341_L3ADDR << 2 | 2)
-+
-+struct uda1341_regs {
-+ unsigned char stat0;
-+#define STAT0 0x00
-+#define STAT0_RST (1 << 6)
-+#define STAT0_SC_MASK (3 << 4)
-+#define STAT0_SC_512FS (0 << 4)
-+#define STAT0_SC_384FS (1 << 4)
-+#define STAT0_SC_256FS (2 << 4)
-+#define STAT0_IF_MASK (7 << 1)
-+#define STAT0_IF_I2S (0 << 1)
-+#define STAT0_IF_LSB16 (1 << 1)
-+#define STAT0_IF_LSB18 (2 << 1)
-+#define STAT0_IF_LSB20 (3 << 1)
-+#define STAT0_IF_MSB (4 << 1)
-+#define STAT0_IF_LSB16MSB (5 << 1)
-+#define STAT0_IF_LSB18MSB (6 << 1)
-+#define STAT0_IF_LSB20MSB (7 << 1)
-+#define STAT0_DC_FILTER (1 << 0)
-+
-+ unsigned char stat1;
-+#define STAT1 0x80
-+#define STAT1_DAC_GAIN (1 << 6) /* gain of DAC */
-+#define STAT1_ADC_GAIN (1 << 5) /* gain of ADC */
-+#define STAT1_ADC_POL (1 << 4) /* polarity of ADC */
-+#define STAT1_DAC_POL (1 << 3) /* polarity of DAC */
-+#define STAT1_DBL_SPD (1 << 2) /* double speed playback */
-+#define STAT1_ADC_ON (1 << 1) /* ADC powered */
-+#define STAT1_DAC_ON (1 << 0) /* DAC powered */
-+
-+ unsigned char data0_0;
-+#define DATA0 0x00
-+#define DATA0_VOLUME_MASK 0x3f
-+#define DATA0_VOLUME(x) (x)
-+
-+ unsigned char data0_1;
-+#define DATA1 0x40
-+#define DATA1_BASS(x) ((x) << 2)
-+#define DATA1_BASS_MASK (15 << 2)
-+#define DATA1_TREBLE(x) ((x))
-+#define DATA1_TREBLE_MASK (3)
-+
-+ unsigned char data0_2;
-+#define DATA2 0x80
-+#define DATA2_PEAKAFTER (1 << 5)
-+#define DATA2_DEEMP_NONE (0 << 3)
-+#define DATA2_DEEMP_32KHz (1 << 3)
-+#define DATA2_DEEMP_44KHz (2 << 3)
-+#define DATA2_DEEMP_48KHz (3 << 3)
-+#define DATA2_MUTE (1 << 2)
-+#define DATA2_FILTER_FLAT (0 << 0)
-+#define DATA2_FILTER_MIN (1 << 0)
-+#define DATA2_FILTER_MAX (3 << 0)
-+
-+#define EXTADDR(n) (0xc0 | (n))
-+#define EXTDATA(d) (0xe0 | (d))
-+
-+ unsigned char ext0;
-+#define EXT0 0
-+#define EXT0_CH1_GAIN(x) (x)
-+
-+ unsigned char ext1;
-+#define EXT1 1
-+#define EXT1_CH2_GAIN(x) (x)
-+
-+ unsigned char ext2;
-+#define EXT2 2
-+#define EXT2_MIC_GAIN_MASK (7 << 2)
-+#define EXT2_MIC_GAIN(x) ((x) << 2)
-+#define EXT2_MIXMODE_DOUBLEDIFF (0)
-+#define EXT2_MIXMODE_CH1 (1)
-+#define EXT2_MIXMODE_CH2 (2)
-+#define EXT2_MIXMODE_MIX (3)
-+
-+ unsigned char ext4;
-+#define EXT4 4
-+#define EXT4_AGC_ENABLE (1 << 4)
-+#define EXT4_INPUT_GAIN_MASK (3)
-+#define EXT4_INPUT_GAIN(x) ((x) & 3)
-+
-+ unsigned char ext5;
-+#define EXT5 5
-+#define EXT5_INPUT_GAIN(x) ((x) >> 2)
-+
-+ unsigned char ext6;
-+#define EXT6 6
-+#define EXT6_AGC_CONSTANT_MASK (7 << 2)
-+#define EXT6_AGC_CONSTANT(x) ((x) << 2)
-+#define EXT6_AGC_LEVEL_MASK (3)
-+#define EXT6_AGC_LEVEL(x) (x)
-+};
-+
-+#define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
-+#define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
-+
-+struct uda1341 {
-+ struct uda1341_regs regs;
-+ int active;
-+ unsigned short volume;
-+ unsigned short bass;
-+ unsigned short treble;
-+ unsigned short line;
-+ unsigned short mic;
-+ int mod_cnt;
-+};
-+
-+#define ADD_FIELD(reg,field) \
-+ *p++ = reg | uda->regs.field
-+
-+#define ADD_EXTFIELD(reg,field) \
-+ *p++ = EXTADDR(reg); \
-+ *p++ = EXTDATA(uda->regs.field);
-+
-+static void uda1341_sync(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ char buf[24], *p = buf;
-+
-+ ADD_FIELD(STAT0, stat0);
-+ ADD_FIELD(STAT1, stat1);
-+
-+ if (p != buf)
-+ l3_write(clnt, UDA1341_STATUS, buf, p - buf);
-+
-+ p = buf;
-+ ADD_FIELD(DATA0, data0_0);
-+ ADD_FIELD(DATA1, data0_1);
-+ ADD_FIELD(DATA2, data0_2);
-+ ADD_EXTFIELD(EXT0, ext0);
-+ ADD_EXTFIELD(EXT1, ext1);
-+ ADD_EXTFIELD(EXT2, ext2);
-+ ADD_EXTFIELD(EXT4, ext4);
-+ ADD_EXTFIELD(EXT5, ext5);
-+ ADD_EXTFIELD(EXT6, ext6);
-+
-+ if (p != buf)
-+ l3_write(clnt, UDA1341_DATA0, buf, p - buf);
-+}
-+
-+static void uda1341_cmd_init(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ char buf[2];
-+
-+ uda->active = 1;
-+
-+ buf[0] = uda->regs.stat0 | STAT0_RST;
-+ buf[1] = uda->regs.stat0;
-+
-+ l3_write(clnt, UDA1341_STATUS, buf, 2);
-+
-+ /* resend all parameters */
-+ uda1341_sync(clnt);
-+}
-+
-+static int uda1341_configure(struct l3_client *clnt, struct uda1341_cfg *conf)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ int ret = 0;
-+
-+ uda->regs.stat0 &= ~(STAT0_SC_MASK | STAT0_IF_MASK);
-+
-+ switch (conf->fs) {
-+ case 512: uda->regs.stat0 |= STAT0_SC_512FS; break;
-+ case 384: uda->regs.stat0 |= STAT0_SC_384FS; break;
-+ case 256: uda->regs.stat0 |= STAT0_SC_256FS; break;
-+ default: ret = -EINVAL; break;
-+ }
-+
-+ switch (conf->format) {
-+ case FMT_I2S: uda->regs.stat0 |= STAT0_IF_I2S; break;
-+ case FMT_LSB16: uda->regs.stat0 |= STAT0_IF_LSB16; break;
-+ case FMT_LSB18: uda->regs.stat0 |= STAT0_IF_LSB18; break;
-+ case FMT_LSB20: uda->regs.stat0 |= STAT0_IF_LSB20; break;
-+ case FMT_MSB: uda->regs.stat0 |= STAT0_IF_MSB; break;
-+ case FMT_LSB16MSB: uda->regs.stat0 |= STAT0_IF_LSB16MSB; break;
-+ case FMT_LSB18MSB: uda->regs.stat0 |= STAT0_IF_LSB18MSB; break;
-+ case FMT_LSB20MSB: uda->regs.stat0 |= STAT0_IF_LSB20MSB; break;
-+ }
-+
-+ if (ret == 0 && uda->active) {
-+ char buf = uda->regs.stat0 | STAT0;
-+ l3_write(clnt, UDA1341_STATUS, &buf, 1);
-+ }
-+ return ret;
-+}
-+
-+static int uda1341_update_direct(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain *v = arg;
-+ char newreg;
-+ int val;
-+
-+ switch (cmd) {
-+ case L3_SET_VOLUME: /* set volume. val = 0 to 100 => 62 to 1 */
-+ uda->regs.data0_0 = DATA0_VOLUME(62 - ((v->left * 61) / 100));
-+ newreg = uda->regs.data0_0 | DATA0;
-+ break;
-+
-+ case L3_SET_BASS: /* set bass. val = 50 to 100 => 0 to 12 */
-+ val = v->left - 50;
-+ if (val < 0)
-+ val = 0;
-+ uda->regs.data0_1 &= ~DATA1_BASS_MASK;
-+ uda->regs.data0_1 |= DATA1_BASS((val * 12) / 50);
-+ newreg = uda->regs.data0_1 | DATA1;
-+ break;
-+
-+ case L3_SET_TREBLE: /* set treble. val = 50 to 100 => 0 to 3 */
-+ val = v->left - 50;
-+ if (val < 0)
-+ val = 0;
-+ uda->regs.data0_1 &= ~DATA1_TREBLE_MASK;
-+ uda->regs.data0_1 |= DATA1_TREBLE((val * 3) / 50);
-+ newreg = uda->regs.data0_1 | DATA1;
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ if (uda->active)
-+ l3_write(clnt, UDA1341_DATA0, &newreg, 1);
-+ return 0;
-+}
-+
-+static int uda1341_update_indirect(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain *gain = arg;
-+ struct l3_agc *agc = arg;
-+ char buf[8], *p = buf;
-+ int val, ret = 0;
-+
-+ switch (cmd) {
-+ case L3_SET_GAIN:
-+ val = 31 - (gain->left * 31 / 100);
-+ switch (gain->channel) {
-+ case 1:
-+ uda->regs.ext0 = EXT0_CH1_GAIN(val);
-+ ADD_EXTFIELD(EXT0, ext0);
-+ break;
-+
-+ case 2:
-+ uda->regs.ext1 = EXT1_CH2_GAIN(val);
-+ ADD_EXTFIELD(EXT1, ext1);
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ }
-+ break;
-+
-+ case L3_INPUT_AGC:
-+ if (agc->channel == 2) {
-+ if (agc->enable)
-+ uda->regs.ext4 |= EXT4_AGC_ENABLE;
-+ else
-+ uda->regs.ext4 &= ~EXT4_AGC_ENABLE;
-+#if 0
-+ agc->level
-+ agc->attack
-+ agc->decay
-+#endif
-+ ADD_EXTFIELD(EXT4, ext4);
-+ } else
-+ ret = -EINVAL;
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ if (ret == 0 && uda->active)
-+ l3_write(clnt, UDA1341_DATA0, buf, p - buf);
-+
-+ return ret;
-+}
-+
-+static int uda1341_mixer_ioctl(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain gain;
-+ int val, nr = _IOC_NR(cmd), ret = 0;
-+
-+ if (cmd == SOUND_MIXER_INFO) {
-+ struct mixer_info mi;
-+
-+ strncpy(mi.id, "UDA1341", sizeof(mi.id));
-+ strncpy(mi.name, "Philips UDA1341", sizeof(mi.name));
-+ mi.modify_counter = uda->mod_cnt;
-+ return copy_to_user(arg, &mi, sizeof(mi));
-+ }
-+
-+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ goto out;
-+
-+ gain.left = val & 255;
-+ gain.right = val >> 8;
-+ gain.channel = 0;
-+
-+ switch (nr) {
-+ case SOUND_MIXER_VOLUME:
-+ uda->volume = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_VOLUME, &gain);
-+ break;
-+
-+ case SOUND_MIXER_BASS:
-+ uda->bass = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_BASS, &gain);
-+ break;
-+
-+ case SOUND_MIXER_TREBLE:
-+ uda->treble = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_TREBLE, &gain);
-+ break;
-+
-+ case SOUND_MIXER_LINE:
-+ uda->line = val;
-+ gain.channel = 1;
-+ uda->mod_cnt++;
-+ uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ uda->mic = val;
-+ gain.channel = 2;
-+ uda->mod_cnt++;
-+ uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
-+ break;
-+
-+ case SOUND_MIXER_RECSRC:
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ }
-+ }
-+
-+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
-+ int nr = _IOC_NR(cmd);
-+ ret = 0;
-+
-+ switch (nr) {
-+ case SOUND_MIXER_VOLUME: val = uda->volume; break;
-+ case SOUND_MIXER_BASS: val = uda->bass; break;
-+ case SOUND_MIXER_TREBLE: val = uda->treble; break;
-+ case SOUND_MIXER_LINE: val = uda->line; break;
-+ case SOUND_MIXER_MIC: val = uda->mic; break;
-+ case SOUND_MIXER_RECSRC: val = REC_MASK; break;
-+ case SOUND_MIXER_RECMASK: val = REC_MASK; break;
-+ case SOUND_MIXER_DEVMASK: val = DEV_MASK; break;
-+ case SOUND_MIXER_CAPS: val = 0; break;
-+ case SOUND_MIXER_STEREODEVS: val = 0; break;
-+ default: val = 0; ret = -EINVAL; break;
-+ }
-+
-+ if (ret == 0)
-+ ret = put_user(val, (int *)arg);
-+ }
-+out:
-+ return ret;
-+}
-+
-+static int uda1341_attach(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda;
-+
-+ uda = kmalloc(sizeof(*uda), GFP_KERNEL);
-+ if (!uda)
-+ return -ENOMEM;
-+
-+ memset(uda, 0, sizeof(*uda));
-+
-+ uda->volume = DEF_VOLUME | DEF_VOLUME << 8;
-+ uda->bass = 50 | 50 << 8;
-+ uda->treble = 50 | 50 << 8;
-+ uda->line = 88 | 88 << 8;
-+ uda->mic = 88 | 88 << 8;
-+
-+ uda->regs.stat0 = STAT0_SC_256FS | STAT0_IF_LSB16;
-+ uda->regs.stat1 = STAT1_DAC_GAIN | STAT1_ADC_GAIN |
-+ STAT1_ADC_ON | STAT1_DAC_ON;
-+ uda->regs.data0_0 = DATA0_VOLUME(62 - ((DEF_VOLUME * 61) / 100));
-+ uda->regs.data0_1 = DATA1_BASS(0) | DATA1_TREBLE(0);
-+ uda->regs.data0_2 = DATA2_PEAKAFTER | DATA2_DEEMP_NONE |
-+ DATA2_FILTER_MAX;
-+ uda->regs.ext0 = EXT0_CH1_GAIN(4);
-+ uda->regs.ext1 = EXT1_CH2_GAIN(4);
-+ uda->regs.ext2 = EXT2_MIXMODE_MIX | EXT2_MIC_GAIN(4);
-+ uda->regs.ext4 = EXT4_AGC_ENABLE | EXT4_INPUT_GAIN(0);
-+ uda->regs.ext5 = EXT5_INPUT_GAIN(0);
-+ uda->regs.ext6 = EXT6_AGC_CONSTANT(3) | EXT6_AGC_LEVEL(0);
-+
-+ clnt->driver_data = uda;
-+
-+ return 0;
-+}
-+
-+static void uda1341_detach(struct l3_client *clnt)
-+{
-+ kfree(clnt->driver_data);
-+}
-+
-+static int
-+uda1341_command(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ int ret = -EINVAL;
-+
-+ if (_IOC_TYPE(cmd) == 'M')
-+ ret = uda1341_mixer_ioctl(clnt, cmd, arg);
-+ else if (cmd == L3_UDA1341_CONFIGURE)
-+ ret = uda1341_configure(clnt, arg);
-+
-+ return ret;
-+}
-+
-+static int uda1341_open(struct l3_client *clnt)
-+{
-+ uda1341_cmd_init(clnt);
-+ return 0;
-+}
-+
-+static void uda1341_close(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ uda->active = 0;
-+}
-+
-+static struct l3_ops uda1341_ops = {
-+ open: uda1341_open,
-+ command: uda1341_command,
-+ close: uda1341_close,
-+};
-+
-+static struct l3_driver uda1341 = {
-+ name: UDA1341_NAME,
-+ attach_client: uda1341_attach,
-+ detach_client: uda1341_detach,
-+ ops: &uda1341_ops,
-+ owner: THIS_MODULE,
-+};
-+
-+static int __init uda1341_init(void)
-+{
-+ return l3_add_driver(&uda1341);
-+}
-+
-+static void __exit uda1341_exit(void)
-+{
-+ l3_del_driver(&uda1341);
-+}
-+
-+module_init(uda1341_init);
-+module_exit(uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Philips UDA1341 CODEC driver");
---- linux-2.4.25/drivers/sound/vidc.c~2.4.25-vrs2.patch 2001-10-11 18:43:30.000000000 +0200
-+++ linux-2.4.25/drivers/sound/vidc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -40,6 +40,7 @@
- #endif
-
- #define VIDC_SOUND_CLOCK (250000)
-+#define VIDC_SOUND_CLOCK_EXT (176400)
-
- /*
- * When using SERIAL SOUND mode (external DAC), the number of physical
-@@ -192,28 +193,43 @@
- return vidc_audio_format;
- }
-
-+#define my_abs(i) ((i)<0 ? -(i) : (i))
-+
- static int vidc_audio_set_speed(int dev, int rate)
- {
- if (rate) {
-- unsigned int hwctrl, hwrate;
-+ unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
- unsigned int newsize, new2size;
-
-- /*
-- * If we have selected 44.1kHz, use the DAC clock.
-- */
-- if (0 && rate == 44100) {
-- hwctrl = 0x00000002;
-+ hwctrl = 0x00000003;
-+
-+ /* Using internal clock */
-+ hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
-+ if (hwrate < 3)
- hwrate = 3;
-- } else {
-- hwctrl = 0x00000003;
-+ if (hwrate > 255)
-+ hwrate = 255;
-
-- hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
-- if (hwrate < 3)
-- hwrate = 3;
-- if (hwrate > 255)
-- hwrate = 255;
-+ /* Using exernal clock */
-+ hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
-+ if (hwrate_ext < 3)
-+ hwrate_ext = 3;
-+ if (hwrate_ext > 255)
-+ hwrate_ext = 255;
-
-- rate = VIDC_SOUND_CLOCK / hwrate;
-+ rate_int = VIDC_SOUND_CLOCK / hwrate;
-+ rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
-+
-+ /* Chose between external and internal clock */
-+ if (my_abs(rate_ext-rate) < my_abs(rate_int-rate)) {
-+ /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
-+ hwrate=hwrate_ext;
-+ hwctrl=0x00000002;
-+ rate=rate_ext;
-+ } else {
-+ /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
-+ hwctrl=0x00000003;
-+ rate=rate_int;
- }
-
- vidc_writel(0xb0000000 | (hwrate - 2));
-@@ -225,13 +241,14 @@
- if (newsize > 4096)
- newsize = 4096;
- for (new2size = 128; new2size < newsize; new2size <<= 1);
-- if (new2size - newsize > newsize - (new2size >> 1))
-- new2size >>= 1;
-+ if (new2size - newsize > newsize - (new2size >> 1))
-+ new2size >>= 1;
- if (new2size > 4096) {
- printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
- newsize, new2size);
- new2size = 4096;
- }
-+ /*printk("VIDC: dma size %d\n", new2size);*/
- dma_bufsize = new2size;
- vidc_audio_rate = rate;
- }
---- linux-2.4.25/drivers/sound/waveartist.c~2.4.25-vrs2.patch 2001-10-25 22:53:52.000000000 +0200
-+++ linux-2.4.25/drivers/sound/waveartist.c 2004-03-31 17:15:09.000000000 +0200
-@@ -247,17 +247,15 @@
- printk("\n");
- }
-
-- if (inb(io_base + STATR) & CMD_RF) {
-- int old_data;
--
-- /* flush the port
-- */
-+ /*
-+ * flush any stale command data from the port.
-+ */
-+ while (inb(io_base + STATR) & CMD_RF) {
-+ unsigned int old_data;
-
- old_data = inw(io_base + CMDR);
--
-- if (debug_flg & DEBUG_CMD)
-- printk("flushed %04X...", old_data);
--
-+ printk("waveartist: flushing stale command data: 0x%04x pc=%p\n",
-+ old_data, __builtin_return_address(0));
- udelay(10);
- }
-
-@@ -287,16 +285,19 @@
- resp[i] = inw(io_base + CMDR);
- }
-
-- if (debug_flg & DEBUG_CMD) {
-- if (!timed_out) {
-- printk("waveartist_cmd: resp=");
-+ if (debug_flg & DEBUG_CMD && !timed_out) {
-+ printk("waveartist_cmd: resp=");
-
-- for (i = 0; i < nr_resp; i++)
-- printk("%04X ", resp[i]);
-+ for (i = 0; i < nr_resp; i++)
-+ printk("%04X ", resp[i]);
-+ printk("\n");
-+ }
-
-- printk("\n");
-- } else
-- printk("waveartist_cmd: timed out\n");
-+ if (timed_out) {
-+ printk(KERN_ERR "waveartist_cmd: command timed out:");
-+ for (i = 0; i < nr_cmd; i++)
-+ printk(" %04x", cmd[i]);
-+ printk("\n");
- }
-
- return timed_out ? 1 : 0;
-@@ -495,7 +496,6 @@
- audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- count == devc->xfer_count) {
-- devc->audio_mode |= PCM_ENABLE_INPUT;
- return; /*
- * Auto DMA mode on. No need to react
- */
-@@ -571,9 +571,6 @@
- wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
- unsigned int speed, bits;
-
-- if (devc->audio_mode)
-- return 0;
--
- speed = waveartist_get_speed(portc);
- bits = waveartist_get_bits(portc);
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,11 @@
-+
-+mainmenu_option next_comment
-+comment 'Synchronous Serial Interface'
-+tristate 'Synchronous Serial Interface Support' CONFIG_SSI
-+
-+comment 'SSI Bus Drivers'
-+dep_tristate ' CLPS711X SSI support' CONFIG_SSI_CLPS711X $CONFIG_SSI $CONFIG_ARCH_CLPS711X
-+
-+comment 'SSI Device Drivers'
-+dep_tristate ' JUNO keyboard support' CONFIG_SSI_JUNO $CONFIG_SSI
-+endmenu
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,50 @@
-+#
-+# Makefile for the SSI drivers
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definition is now inherited from the
-+# parent makefile.
-+#
-+
-+O_TARGET := ssi.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+export-objs :=
-+list-multi :=
-+
-+obj-$(CONFIG_SSI) += ssi_core.o
-+obj-$(CONFIG_SSI_CLPS711X) += clps711x_ssi1.o
-+obj-y += juno.o
-+
-+# Extract lists of the multi-part drivers.
-+# The 'int-*' lists are intermediate files used to build the multi's.
-+
-+multi-y := $(filter $(list-multi), $(obj-y))
-+multi-m := $(filter $(list-multi), $(obj-m))
-+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-+
-+# Files that are both resident and modular; remove from modular.
-+
-+obj-m := $(filter-out $(obj-y), $(obj-m))
-+int-m := $(filter-out $(int-y), $(int-m))
-+
-+# Take multi-part drivers out of obj-y and put components in.
-+
-+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
-+
-+# Translate to Rules.make lists.
-+
-+O_OBJS := $(filter-out $(export-objs), $(obj-y))
-+OX_OBJS := $(filter $(export-objs), $(obj-y))
-+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/README 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,86 @@
-+ Synchronous Serial Interface bus driver
-+ ---------------------------------------
-+
-+ EEEEE X X PPPP EEEEE RRRR IIIII M M EEEEE N N TTTTT AAA L
-+ E X X P P E R R I MM MM E NN N T A A L
-+ EEEE X PPPP EEEE RRRR I M M M EEEE N N N T AAAAA L
-+ E X X P E R R I M M E N NN T A A L
-+ EEEEE X X P EEEEE R R IIIII M M EEEEE N N T A A LLLLL
-+
-+This directory holds the SSI bus drivers. Basically, a SSI bus consists
-+of the following signals:
-+
-+ stxd Transmit data
-+ srxd Receive data
-+ sclk Clock
-+ sfrm Frame
-+ Chip selects (1 - n)
-+
-+There may be more than one device on a SSI bus, and each device can
-+have different timing requirements. There are several frame formats:
-+
-+1. Texas Instruments Synchronous Serial Frame format
-+
-+ sclk ____~_~_~_~_~_~_~_~____
-+ sfrm ____~~_________________
-+ stxd ------bn..........b0---
-+ srxd ------bn..........b0---
-+
-+ - data latched in on the falling edge of the clock
-+ - data shifted out on the rising edge of the clock
-+
-+2. Motorola SPI frame format
-+
-+ sclk ______~_~_~_~_~_~_~____
-+ sfrm ~~~~________________~~~
-+ stxd -----bn..........b0----
-+ srxd ----.bn..........b0----
-+
-+ - data latched in on the rising edge of the clock
-+ - data shifted out on the falling edge of the clock, or falling edge
-+ of sfrm
-+
-+3. National Microwire format
-+
-+ sclk ______~_~_~_~_~_~_~_~_~_~_~_~_~_____
-+ sfrm ~~~~_____________________________~~~
-+ stxd -----bn......b0---------------------
-+ srxd -----------------bn..........b0.----
-+
-+ - data latched in on the rising edge of the clock
-+ - data shifted out on the falling edge of the clock
-+ - half duplex, one clock between transmission and reception
-+
-+Types of devices
-+----------------
-+
-+The following types of devices can be found on a SSP bus:
-+
-+ Sound chips
-+ Keyboard devices
-+ Touch screen devices
-+
-+Keyboard
-+--------
-+
-+TX:
-+0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
-+1. select device
-+2. keyboard responds asserting key_atn
-+3. wait 0.1ms to 5ms
-+4. transmit data byte
-+5. wait >= 150us
-+6. repeat step 4 until all data sent
-+7. deselect device
-+8. keyboard responds de-asserting key_atn
-+9. wait >= 120us
-+
-+RX:
-+0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
-+1. keyboard asserts key_atn
-+2. select device after 0.1ms < 5ms
-+3. read data byte
-+4. wait 150us
-+5. if key_atn still asserted, goto 3
-+6. deselect device
-+7. wait >= 120us
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/clps711x_ssi1.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,237 @@
-+/*
-+ * linux/drivers/ssi/clps711x_ssi1.c
-+ *
-+ * SSI bus driver for the CLPS711x SSI1 bus. We support EP7212
-+ * extensions as well.
-+ *
-+ * Frame sizes can be between 4 and 24 bits.
-+ * Config sizes can be between 4 and 16 bits.
-+ */
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/mach-types.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#include <asm/hardware/ep7212.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+#define EP7212
-+
-+/*
-+ * Port E on the P720T is used for the SPI bus chip selects
-+ * 0 - Keyboard
-+ * 1 - Touch screen
-+ * 2 - CS4224 ADC/DAC
-+ * 7 - idle
-+ */
-+
-+#if 0
-+/*
-+ * we place in the transmit buffer:
-+ * <control>
-+ * received data (binary):
-+ * 0xxxxxxxxxxxx000
-+ * where 'x' is the value
-+ */
-+struct ssi_dev ads7846_dev = {
-+ name: "ADS7846",
-+ id: 1,
-+ proto: SSI_SPI,
-+ cfglen: 8,
-+ framelen: 24,
-+ clkpol: 0,
-+ clkfreq: 2500000,
-+};
-+
-+/*
-+ * we place in the transmit buffer:
-+ * write: <20> <map> <data>...
-+ * received data discarded
-+ */
-+struct ssi_dev cs4224_dev = {
-+ name: "CS4224",
-+ id: 2,
-+ proto: SSI_SPI,
-+ cfglen: 8,
-+ framelen: 8,
-+ clkpol: 0,
-+ clkfreq: 6000000,
-+};
-+#endif
-+
-+/*
-+ * Supplement with whatever method your board requires
-+ */
-+static void ssi1_select_id(int id)
-+{
-+ if (machine_is_p720t()) {
-+ clps_writel(7, PEDDR);
-+ clps_writel(id, PEDR);
-+ }
-+}
-+
-+/*
-+ * Select the specified device. The upper layers will have already
-+ * checked that the bus transmit queue is idle. We need to make sure
-+ * that the interface itself is idle.
-+ */
-+static int ssi1_select(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ u_int id = dev ? dev->id : 7;
-+ u_int val;
-+
-+ /*
-+ * Make sure that the interface is idle
-+ */
-+ do {
-+ val = clps_readl(SYSFLG1);
-+ } while (val & SYSFLG1_SSIBUSY);
-+
-+ ssi1_select_id(7);
-+
-+ if (dev) {
-+ /*
-+ * Select clock frequency. This is very rough,
-+ * and assumes that we're operating in PLL mode.
-+ */
-+ val = clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK;
-+// if (dev->clkfreq <= 16000) /* <16kHz */
-+// val |= SYSCON1_ADCKSEL(0);
-+// else if (dev->clkfreq < 64000) /* <64kHz */
-+// val |= SYSCON1_ADCKSEL(1);
-+// else if (dev->clkfreq < 128000) /* <128kHz */
-+ val |= SYSCON1_ADCKSEL(2);
-+// else /* >= 128kHz */
-+// val |= SYSCON1_ADCKSEL(3);
-+ clps_writel(val, SYSCON1);
-+
-+ bus->cfglen = dev->cfglen;
-+ bus->framelen = dev->framelen;
-+ bus->clkpol = dev->clkpol;
-+ bus->proto = dev->proto;
-+
-+#ifdef EP7212
-+ /*
-+ * Set the clock edge according to the device.
-+ * (set clkpol if the device reads data on the
-+ * falling edge of the clock signal).
-+ */
-+ val = ep_readl(SYSCON3) & ~SYSCON3_ADCCKNSEN;
-+ if (bus->clkpol && dev->proto != SSI_USAR)
-+ val |= SYSCON3_ADCCKNSEN;
-+ ep_writel(val, SYSCON3);
-+#endif
-+
-+ /*
-+ * Select the device
-+ */
-+ ssi1_select_id(id);
-+
-+#ifdef EP7212
-+ /*
-+ * If we are doing USAR, wait 30us, then set
-+ * the clock line low.
-+ */
-+ if (dev->proto == SSI_USAR) {
-+ udelay(150);
-+
-+ val |= SYSCON3_ADCCKNSEN;
-+ ep_writel(val, SYSCON3);
-+ }
-+#endif
-+ }
-+
-+ return 0;
-+}
-+
-+static void ssi1_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct ssi_bus *bus = (struct ssi_bus *)dev_id;
-+
-+ /*
-+ * Read the data word and queue it.
-+ */
-+ ssi_core_rcv(bus, clps_readl(SYNCIO));
-+}
-+
-+/*
-+ * Enable transmission and/or of some bytes
-+ */
-+static int ssi1_trans(struct ssi_bus *bus, u_int data)
-+{
-+ u_int syncio;
-+
-+#ifdef EP7212
-+ data <<= 32 - bus->cfglen;
-+ syncio = bus->cfglen | bus->framelen << 7 | data;
-+#else
-+ syncio = data | bus->framelen << 8;
-+#endif
-+
-+ clps_writel(syncio, SYNCIO);
-+ clps_writel(syncio | SYNCIO_TXFRMEN, SYNCIO);
-+ return 0;
-+}
-+
-+/*
-+ * Initialise the SSI bus.
-+ */
-+static int ssi1_bus_init(struct ssi_bus *bus)
-+{
-+ int retval, val;
-+
-+ retval = request_irq(IRQ_SSEOTI, ssi1_int, 0, "ssi1", bus);
-+ if (retval)
-+ return retval;
-+
-+#ifdef EP7212
-+ /*
-+ * EP7212 only! Set the configuration command length.
-+ * On the CLPS711x chips, it is fixed at 8 bits.
-+ */
-+ val = ep_readl(SYSCON3);
-+ val |= SYSCON3_ADCCON;
-+ ep_writel(val, SYSCON3);
-+#endif
-+
-+ ssi1_select(bus, NULL);
-+
-+ PLD_SPI |= PLD_SPI_EN;
-+
-+ return 0;
-+}
-+
-+static void ssi1_bus_exit(struct ssi_bus *bus)
-+{
-+ ssi1_select(bus, NULL);
-+
-+ PLD_SPI &= ~PLD_SPI_EN;
-+
-+ free_irq(IRQ_SSEOTI, bus);
-+}
-+
-+struct ssi_bus clps711x_ssi1_bus = {
-+ name: "clps711x_ssi1",
-+ init: ssi1_bus_init,
-+ exit: ssi1_bus_exit,
-+ select: ssi1_select,
-+ trans: ssi1_trans,
-+};
-+
-+static int __init clps711x_ssi1_init(void)
-+{
-+ return ssi_register_bus(&clps711x_ssi1_bus);
-+}
-+
-+static void __exit clps711x_ssi1_exit(void)
-+{
-+ ssi_unregister_bus(&clps711x_ssi1_bus);
-+}
-+
-+module_init(clps711x_ssi1_init);
-+module_exit(clps711x_ssi1_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/juno.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,131 @@
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#include <asm/arch/syspld.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+extern struct ssi_bus clps711x_ssi1_bus;
-+
-+static u_int recvbuf[16];
-+static volatile u_int ptr, rxed;
-+
-+static inline void juno_enable_irq(void)
-+{
-+ enable_irq(IRQ_EINT1);
-+}
-+
-+static inline void juno_disable_irq(void)
-+{
-+ disable_irq(IRQ_EINT1);
-+}
-+
-+static void juno_rcv(struct ssi_dev *dev, u_int data)
-+{
-+ if (ptr < 16) {
-+ recvbuf[ptr] = data;
-+ ptr++;
-+ } else
-+ printk("juno_rcv: %04x\n", data);
-+ rxed = 1;
-+}
-+
-+static void juno_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct ssi_dev *dev = dev_id;
-+
-+ printk("juno_irq\n");
-+
-+ ssi_select_device(dev->bus, dev);
-+
-+ ptr = 0;
-+ do {
-+ rxed = 0;
-+ ssi_transmit_data(dev, 0xff);
-+ while (rxed == 0);
-+ udelay(150);
-+ } while (PLD_INT & PLD_INT_KBD_ATN);
-+
-+ ssi_select_device(dev->bus, NULL);
-+
-+ { int i;
-+ printk("juno_rcv: ");
-+ for (i = 0; i < ptr; i++)
-+ printk("%04x ", recvbuf[i]);
-+ printk("\n");
-+ }
-+}
-+
-+static void juno_command(struct ssi_dev *dev, int cmd, int data)
-+{
-+ ssi_transmit_data(dev, cmd);
-+ mdelay(1);
-+ ssi_transmit_data(dev, data);
-+ mdelay(1);
-+ ssi_transmit_data(dev, 0xa0 ^ 0xc0);
-+ mdelay(1);
-+}
-+
-+static int juno_dev_init(struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+ PLD_KBD |= PLD_KBD_EN;
-+ ptr = 16;
-+
-+ mdelay(20);
-+
-+ retval = request_irq(IRQ_EINT1, juno_irq, 0, dev->name, dev);
-+ if (retval)
-+ return retval;
-+
-+ juno_disable_irq();
-+
-+ if (ssi_select_device(dev->bus, dev) != 0) {
-+ printk("juno: ssi_select_dev failed\n");
-+ return -EBUSY;
-+ }
-+
-+ mdelay(1);
-+
-+ juno_command(dev, 0x80, 0x20);
-+
-+ ssi_select_device(dev->bus, NULL);
-+
-+ juno_enable_irq();
-+
-+ return 0;
-+}
-+
-+static struct ssi_dev juno_dev = {
-+ name: "Juno",
-+ id: 0,
-+ proto: SSI_USAR,
-+ cfglen: 8,
-+ framelen: 8,
-+ clkpol: 1,
-+ clkfreq: 250000,
-+ rcv: juno_rcv,
-+ init: juno_dev_init,
-+};
-+
-+static int __init juno_init(void)
-+{
-+ return ssi_register_device(&clps711x_ssi1_bus, &juno_dev);
-+}
-+
-+static void __exit juno_exit(void)
-+{
-+ ssi_unregister_device(&juno_dev);
-+}
-+
-+module_init(juno_init);
-+module_exit(juno_exit);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/ssi_bus.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,21 @@
-+#include <linux/circ_buf.h>
-+
-+struct ssi_dev;
-+
-+struct ssi_bus {
-+ u_char cfglen;
-+ u_char framelen;
-+ u_char clkpol;
-+ u_char proto;
-+ struct ssi_dev *dev; /* current device */
-+ int (*select)(struct ssi_bus *, struct ssi_dev *);
-+ int (*trans)(struct ssi_bus *, u_int data);
-+ int (*init)(struct ssi_bus *);
-+ void (*exit)(struct ssi_bus *);
-+ char *name;
-+ u_int devices;
-+};
-+
-+extern int ssi_core_rcv(struct ssi_bus *bus, u_int data);
-+extern int ssi_register_bus(struct ssi_bus *bus);
-+extern int ssi_unregister_bus(struct ssi_bus *bus);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/ssi_core.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,175 @@
-+/*
-+ * linux/drivers/ssi/ssi_core.c
-+ *
-+ * This file provides a common framework to allow multiple SSI devices
-+ * to work together on a single SSI bus.
-+ *
-+ * You can use this in two ways:
-+ * 1. select the device, queue up data, flush the data to the device,
-+ * (optionally) purge the received data, deselect the device.
-+ * 2. select the device, queue up one data word, flush to the device
-+ * read data word, queue up next data word, flush to the device...
-+ * deselect the device.
-+ */
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/malloc.h>
-+#include <linux/init.h>
-+
-+#include <asm/errno.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+#define DEBUG
-+
-+/**
-+ * ssi_core_rcv - pass received SSI data to the device
-+ * @bus: the bus that the data was received from
-+ * @data: the data word that was received
-+ *
-+ * This function is intended to be called by SSI bus device
-+ * drivers to pass received data to the device driver.
-+ */
-+int ssi_core_rcv(struct ssi_bus *bus, u_int data)
-+{
-+ struct ssi_dev *dev = bus->dev;
-+
-+ if (dev && dev->rcv)
-+ dev->rcv(dev, data);
-+
-+ return 0;
-+}
-+
-+/**
-+ * ssi_transmit_data - queue SSI data for later transmission
-+ * @dev: device requesting data to be transmitted
-+ * @data: data word to be transmitted.
-+ *
-+ * Queue one data word of SSI data for later transmission.
-+ */
-+int ssi_transmit_data(struct ssi_dev *dev, u_int data)
-+{
-+ struct ssi_bus *bus = dev->bus;
-+
-+ /*
-+ * Make sure that we currently own the bus
-+ */
-+ if (bus->dev != dev)
-+ BUG();
-+
-+ bus->trans(bus, data);
-+ return 0;
-+}
-+
-+/**
-+ * ssi_select_device - select a SSI device for later transactions
-+ * @dev: device to be selected
-+ */
-+int ssi_select_device(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+#ifdef DEBUG
-+ printk("SSI: selecting device %s on bus %s\n",
-+ dev ? dev->name : "<none>", bus->name);
-+#endif
-+
-+ /*
-+ * Select the device if it wasn't already selected.
-+ */
-+ retval = 0;
-+ if (bus->dev != dev) {
-+ retval = bus->select(bus, dev);
-+ bus->dev = dev;
-+ }
-+
-+ return retval;
-+}
-+
-+/**
-+ * ssi_register_device - register a SSI device with a SSI bus
-+ * @bus: bus
-+ * @dev: SSI device
-+ */
-+int ssi_register_device(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+ dev->bus = bus;
-+ bus->devices++;
-+ retval = dev->init(dev);
-+ if (retval != 0) {
-+ dev->bus = NULL;
-+ bus->devices--;
-+ } else {
-+#ifdef DEBUG
-+ printk("SSI: registered new device %s on bus %s\n", dev->name, bus->name);
-+#endif
-+ }
-+ return retval;
-+}
-+
-+/**
-+ * ssi_unregister_device - unregister a SSI device from a SSI bus
-+ * @dev: SSI device
-+ */
-+int ssi_unregister_device(struct ssi_dev *dev)
-+{
-+ struct ssi_bus *bus = dev->bus;
-+
-+ if (bus->dev == dev)
-+ bus->dev = NULL;
-+
-+ dev->bus = NULL;
-+ bus->devices--;
-+#ifdef DEBUG
-+ printk("SSI: unregistered device %s on bus %s\n", dev->name, bus->name);
-+#endif
-+ return 0;
-+}
-+
-+/**
-+ * ssi_register_bus - register a SSI bus driver
-+ * @bus: bus
-+ */
-+int ssi_register_bus(struct ssi_bus *bus)
-+{
-+ int retval;
-+
-+ retval = bus->init(bus);
-+ if (retval == 0) {
-+ bus->devices = 0;
-+#ifdef DEBUG
-+ printk("SSI: registered new bus %s\n", bus->name);
-+#endif
-+ }
-+
-+ return retval;
-+}
-+
-+/**
-+ * ssi_unregister_bus - unregister a SSI bus driver
-+ * @bus: bus
-+ */
-+int ssi_unregister_bus(struct ssi_bus *bus)
-+{
-+ int retval = -EBUSY;
-+ if (bus->devices == 0) {
-+ retval = 0;
-+ }
-+ return retval;
-+}
-+
-+static int __init ssi_init(void)
-+{
-+ return 0;
-+}
-+
-+static void __exit ssi_exit(void)
-+{
-+}
-+
-+module_init(ssi_init);
-+module_exit(ssi_exit);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/ssi/ssi_dev.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,21 @@
-+struct ssi_bus;
-+
-+#define SSI_SPI 1
-+#define SSI_MICROWIRE 2
-+#define SSI_TISSF 3
-+#define SSI_USAR 4
-+
-+struct ssi_dev {
-+ char *name;
-+ u_int id;
-+ u_int clkfreq;
-+ u_char cfglen;
-+ u_char framelen;
-+ u_char clkpol;
-+ u_char proto;
-+ void (*rcv)(struct ssi_dev *, u_int);
-+ int (*init)(struct ssi_dev *);
-+ struct ssi_bus *bus;
-+};
-+
-+
---- linux-2.4.25/drivers/usb/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/usb/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -4,7 +4,13 @@
- mainmenu_option next_comment
- comment 'USB support'
-
--dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
-+# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
-+if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'Support for USB' CONFIG_USB
-+else
-+ define_bool CONFIG_USB n
-+fi
-+
- if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
- bool ' USB verbose debug messages' CONFIG_USB_DEBUG
-
---- linux-2.4.25/drivers/usb/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/usb/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -74,6 +74,14 @@
-
- subdir-$(CONFIG_USB_OHCI) += host
- ifeq ($(CONFIG_USB_OHCI),y)
-+ obj-y += host/usb-ohci.o host/usb-ohci-pci.o
-+endif
-+subdir-$(CONFIG_USB_OHCI_SA1111)+= host
-+ifeq ($(CONFIG_USB_OHCI),y)
-+ obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o
-+endif
-+subdir-$(CONFIG_USB_OHCI_AT91) += host
-+ifeq ($(CONFIG_USB_OHCI_AT91),y)
- obj-y += host/usb-ohci.o
- endif
-
-@@ -85,8 +93,6 @@
- obj-$(CONFIG_USB_KBD) += usbkbd.o
- obj-$(CONFIG_USB_AIPTEK) += aiptek.o
- obj-$(CONFIG_USB_WACOM) += wacom.o
--obj-$(CONFIG_USB_KBTAB) += kbtab.o
--obj-$(CONFIG_USB_POWERMATE) += powermate.o
-
- obj-$(CONFIG_USB_SCANNER) += scanner.o
- obj-$(CONFIG_USB_ACM) += acm.o
---- linux-2.4.25/drivers/usb/hcd.c~2.4.25-vrs2.patch 2003-06-13 16:51:36.000000000 +0200
-+++ linux-2.4.25/drivers/usb/hcd.c 2004-03-31 17:15:09.000000000 +0200
-@@ -96,7 +96,7 @@
- /* used when updating hcd data */
- static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
-
--static struct usb_operations hcd_operations;
-+/*static*/ struct usb_operations hcd_operations;
-
- /*-------------------------------------------------------------------------*/
-
-@@ -1203,13 +1203,21 @@
- // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
- if (usb_pipecontrol (urb->pipe))
- urb->setup_dma = pci_map_single (
-+#ifdef CONFIG_PCI
- hcd->pdev,
-+#else
-+ NULL,
-+#endif
- urb->setup_packet,
- sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
- if (urb->transfer_buffer_length != 0)
- urb->transfer_dma = pci_map_single (
-+#ifdef CONFIG_PCI
- hcd->pdev,
-+#else
-+ NULL,
-+#endif
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
-@@ -1422,7 +1430,7 @@
- return 0;
- }
-
--static struct usb_operations hcd_operations = {
-+/*static*/ struct usb_operations hcd_operations = {
- allocate: hcd_alloc_dev,
- get_frame_number: hcd_get_frame_number,
- submit_urb: hcd_submit_urb,
-@@ -1432,7 +1440,7 @@
-
- /*-------------------------------------------------------------------------*/
-
--static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
-+/*static*/ void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
- {
- struct usb_hcd *hcd = __hcd;
- int start = hcd->state;
-@@ -1481,11 +1489,23 @@
-
- // NOTE: 2.5 does this if !URB_NO_DMA_MAP transfer flag
- if (usb_pipecontrol (urb->pipe))
-- pci_unmap_single (hcd->pdev, urb->setup_dma,
-+ pci_unmap_single (
-+#ifdef CONFIG_PCI
-+ hcd->pdev,
-+#else
-+ NULL,
-+#endif
-+ urb->setup_dma,
- sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
- if (urb->transfer_buffer_length != 0)
-- pci_unmap_single (hcd->pdev, urb->transfer_dma,
-+ pci_unmap_single (
-+#ifdef CONFIG_PCI
-+ hcd->pdev,
-+#else
-+ NULL,
-+#endif
-+ urb->transfer_dma,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
- ? PCI_DMA_FROMDEVICE
---- linux-2.4.25/drivers/usb/host/Config.in~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/usb/host/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -12,8 +12,13 @@
- define_bool CONFIG_USB_UHCI_ALT n
- fi
- dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
-+dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
- if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then
- # Cypress embedded USB controller on StrongARM or on x86 in PC/104
- dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
- dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL
- fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ dep_tristate ' AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB
-+fi
-+
---- linux-2.4.25/drivers/usb/host/Makefile~2.4.25-vrs2.patch 2003-11-28 19:26:20.000000000 +0100
-+++ linux-2.4.25/drivers/usb/host/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -8,9 +8,11 @@
- obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
- obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
- obj-$(CONFIG_USB_UHCI) += usb-uhci.o
--obj-$(CONFIG_USB_OHCI) += usb-ohci.o
-+obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o
- obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o
- obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
-+obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o
-+obj-$(CONFIG_USB_OHCI_AT91) += usb-ohci.o
-
- # Extract lists of the multi-part drivers.
- # The 'int-*' lists are the intermediate files used to build the multi's.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/usb/host/usb-ohci-pci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,436 @@
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h> /* for in_interrupt() */
-+#undef DEBUG
-+#include <linux/usb.h>
-+
-+#include "usb-ohci.h"
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+#include <asm/machdep.h>
-+#include <asm/pmac_feature.h>
-+#include <asm/pci-bridge.h>
-+#ifndef CONFIG_PM
-+#define CONFIG_PM
-+#endif
-+#endif
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* Increment the module usage count, start the control thread and
-+ * return success. */
-+
-+static struct pci_driver ohci_pci_driver;
-+extern spinlock_t usb_ed_lock;
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
-+ const char *name, const char *slot_name);
-+extern void hc_remove_ohci(ohci_t *ohci);
-+
-+static int __devinit
-+hc_found_ohci (struct pci_dev *dev, int irq,
-+ void *mem_base, const struct pci_device_id *id)
-+{
-+ unsigned long flags = id->driver_data;
-+
-+ printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
-+
-+ /* Check for NSC87560. We have to look at the bridge (fn1) to identify
-+ the USB (fn2). This quirk might apply to more or even all NSC stuff
-+ I don't know.. */
-+
-+ if(dev->vendor == PCI_VENDOR_ID_NS)
-+ {
-+ struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
-+ if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
-+ flags |= OHCI_QUIRK_SUCKYIO;
-+
-+ }
-+
-+ if (flags & OHCI_QUIRK_SUCKYIO)
-+ printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
-+ if (flags & OHCI_QUIRK_AMD756)
-+ printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
-+
-+ return hc_add_ohci(dev, irq, mem_base, flags,
-+ ohci_pci_driver.name, dev->slot_name);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+#ifdef CONFIG_PM
-+
-+/* controller died; cleanup debris, then restart */
-+/* must not be called from interrupt context */
-+
-+static void hc_restart (ohci_t *ohci)
-+{
-+ int temp;
-+ int i;
-+
-+ if (ohci->pci_latency)
-+ pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
-+
-+ ohci->disabled = 1;
-+ ohci->sleeping = 0;
-+ if (ohci->bus->root_hub)
-+ usb_disconnect (&ohci->bus->root_hub);
-+
-+ /* empty the interrupt branches */
-+ for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-+ for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
-+
-+ /* no EDs to remove */
-+ ohci->ed_rm_list [0] = NULL;
-+ ohci->ed_rm_list [1] = NULL;
-+
-+ /* empty control and bulk lists */
-+ ohci->ed_isotail = NULL;
-+ ohci->ed_controltail = NULL;
-+ ohci->ed_bulktail = NULL;
-+
-+ if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-+ err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
-+ } else
-+ dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
-+}
-+
-+#endif /* CONFIG_PM */
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* configured so that an OHCI device is always provided */
-+/* always called with process context; sleeping is OK */
-+
-+static int __devinit
-+ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-+{
-+ unsigned long mem_resource, mem_len;
-+ void *mem_base;
-+ int status;
-+
-+ if (pci_enable_device(dev) < 0)
-+ return -ENODEV;
-+
-+ if (!dev->irq) {
-+ err("found OHCI device with no IRQ assigned. check BIOS settings!");
-+ pci_disable_device (dev);
-+ return -ENODEV;
-+ }
-+
-+ /* we read its hardware registers as memory */
-+ mem_resource = pci_resource_start(dev, 0);
-+ mem_len = pci_resource_len(dev, 0);
-+ if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-+ dbg ("controller already in use");
-+ pci_disable_device (dev);
-+ return -EBUSY;
-+ }
-+
-+ mem_base = ioremap_nocache (mem_resource, mem_len);
-+ if (!mem_base) {
-+ err("Error mapping OHCI memory");
-+ release_mem_region (mem_resource, mem_len);
-+ pci_disable_device (dev);
-+ return -EFAULT;
-+ }
-+
-+ /* controller writes into our memory */
-+ pci_set_master (dev);
-+
-+ status = hc_found_ohci (dev, dev->irq, mem_base, id);
-+ if (status < 0) {
-+ iounmap (mem_base);
-+ release_mem_region (mem_resource, mem_len);
-+ pci_disable_device (dev);
-+ }
-+ return status;
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* may be called from interrupt context [interface spec] */
-+/* may be called without controller present */
-+/* may be called with controller, bus, and devices active */
-+
-+static void __devexit
-+ohci_pci_remove (struct pci_dev *dev)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+
-+ dbg ("remove %s controller usb-%s%s%s",
-+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-+ dev->slot_name,
-+ ohci->disabled ? " (disabled)" : "",
-+ in_interrupt () ? " in interrupt" : ""
-+ );
-+
-+ hc_remove_ohci(ohci);
-+
-+ release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-+ pci_disable_device (dev);
-+}
-+
-+
-+#ifdef CONFIG_PM
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int
-+ohci_pci_suspend (struct pci_dev *dev, u32 state)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+ unsigned long flags;
-+ u16 cmd;
-+
-+ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-+ dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-+ return -EIO;
-+ }
-+
-+ /* act as if usb suspend can always be used */
-+ info ("USB suspend: usb-%s", dev->slot_name);
-+ ohci->sleeping = 1;
-+
-+ /* First stop processing */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-+ (void) readl (&ohci->regs->intrstatus);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+
-+ /* Wait a frame or two */
-+ mdelay(1);
-+ if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-+ mdelay (1);
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+ if (_machine == _MACH_Pmac)
-+ disable_irq (ohci->irq);
-+ /* else, 2.4 assumes shared irqs -- don't disable */
-+#endif
-+ /* Enable remote wakeup */
-+ writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
-+
-+ /* Suspend chip and let things settle down a bit */
-+ ohci->hc_control = OHCI_USB_SUSPEND;
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (500); /* No schedule here ! */
-+ switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-+ case OHCI_USB_RESET:
-+ dbg("Bus in reset phase ???");
-+ break;
-+ case OHCI_USB_RESUME:
-+ dbg("Bus in resume phase ???");
-+ break;
-+ case OHCI_USB_OPER:
-+ dbg("Bus in operational phase ???");
-+ break;
-+ case OHCI_USB_SUSPEND:
-+ dbg("Bus suspended");
-+ break;
-+ }
-+ /* In some rare situations, Apple's OHCI have happily trashed
-+ * memory during sleep. We disable it's bus master bit during
-+ * suspend
-+ */
-+ pci_read_config_word (dev, PCI_COMMAND, &cmd);
-+ cmd &= ~PCI_COMMAND_MASTER;
-+ pci_write_config_word (dev, PCI_COMMAND, cmd);
-+#ifdef CONFIG_PMAC_PBOOK
-+ {
-+ struct device_node *of_node;
-+
-+ /* Disable USB PAD & cell clock */
-+ of_node = pci_device_to_OF_node (ohci->ohci_dev);
-+ if (of_node)
-+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-+ }
-+#endif
-+ return 0;
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int
-+ohci_pci_resume (struct pci_dev *dev)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+ int temp;
-+ unsigned long flags;
-+
-+ /* guard against multiple resumes */
-+ atomic_inc (&ohci->resume_count);
-+ if (atomic_read (&ohci->resume_count) != 1) {
-+ err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-+ atomic_dec (&ohci->resume_count);
-+ return 0;
-+ }
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+ {
-+ struct device_node *of_node;
-+
-+ /* Re-enable USB PAD & cell clock */
-+ of_node = pci_device_to_OF_node (ohci->ohci_dev);
-+ if (of_node)
-+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-+ }
-+#endif
-+
-+ /* did we suspend, or were we powered off? */
-+ ohci->hc_control = readl (&ohci->regs->control);
-+ temp = ohci->hc_control & OHCI_CTRL_HCFS;
-+
-+#ifdef DEBUG
-+ /* the registers may look crazy here */
-+ ohci_dump_status (ohci);
-+#endif
-+
-+ /* Re-enable bus mastering */
-+ pci_set_master(ohci->ohci_dev);
-+
-+ switch (temp) {
-+
-+ case OHCI_USB_RESET: // lost power
-+ info ("USB restart: usb-%s", dev->slot_name);
-+ hc_restart (ohci);
-+ break;
-+
-+ case OHCI_USB_SUSPEND: // host wakeup
-+ case OHCI_USB_RESUME: // remote wakeup
-+ info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
-+ (temp == OHCI_USB_SUSPEND)
-+ ? "host" : "remote");
-+ ohci->hc_control = OHCI_USB_RESUME;
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (20); /* no schedule here ! */
-+ /* Some controllers (lucent) need a longer delay here */
-+ mdelay (15);
-+ temp = readl (&ohci->regs->control);
-+ temp = ohci->hc_control & OHCI_CTRL_HCFS;
-+ if (temp != OHCI_USB_RESUME) {
-+ err ("controller usb-%s won't resume", dev->slot_name);
-+ ohci->disabled = 1;
-+ return -EIO;
-+ }
-+
-+ /* Some chips likes being resumed first */
-+ writel (OHCI_USB_OPER, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (3);
-+
-+ /* Then re-enable operations */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ ohci->disabled = 0;
-+ ohci->sleeping = 0;
-+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-+ if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-+ if (ohci->ed_controltail)
-+ ohci->hc_control |= OHCI_CTRL_CLE;
-+ if (ohci->ed_bulktail)
-+ ohci->hc_control |= OHCI_CTRL_BLE;
-+ }
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-+ /* Check for a pending done list */
-+ writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
-+ (void) readl (&ohci->regs->intrdisable);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+#ifdef CONFIG_PMAC_PBOOK
-+ if (_machine == _MACH_Pmac)
-+ enable_irq (ohci->irq);
-+#endif
-+ if (ohci->hcca->done_head)
-+ dl_done_list (ohci, dl_reverse_done_list (ohci));
-+ writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
-+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-+ break;
-+
-+ default:
-+ warn ("odd PCI resume for usb-%s", dev->slot_name);
-+ }
-+
-+ /* controller is operational, extra resumes are harmless */
-+ atomic_dec (&ohci->resume_count);
-+
-+ return 0;
-+}
-+
-+#endif /* CONFIG_PM */
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
-+
-+ /*
-+ * AMD-756 [Viper] USB has a serious erratum when used with
-+ * lowspeed devices like mice.
-+ */
-+ vendor: 0x1022,
-+ device: 0x740c,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+
-+ driver_data: OHCI_QUIRK_AMD756,
-+
-+} , {
-+
-+ /* handle any USB OHCI controller */
-+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-+ class_mask: ~0,
-+
-+ /* no matter who makes it */
-+ vendor: PCI_ANY_ID,
-+ device: PCI_ANY_ID,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+
-+ }, { /* end: all zeroes */ }
-+};
-+
-+MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
-+
-+static struct pci_driver ohci_pci_driver = {
-+ name: "usb-ohci",
-+ id_table: &ohci_pci_ids [0],
-+
-+ probe: ohci_pci_probe,
-+ remove: __devexit_p(ohci_pci_remove),
-+
-+#ifdef CONFIG_PM
-+ suspend: ohci_pci_suspend,
-+ resume: ohci_pci_resume,
-+#endif /* PM */
-+};
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int __init ohci_hcd_init (void)
-+{
-+ return pci_module_init (&ohci_pci_driver);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static void __exit ohci_hcd_cleanup (void)
-+{
-+ pci_unregister_driver (&ohci_pci_driver);
-+}
-+
-+module_init (ohci_hcd_init);
-+module_exit (ohci_hcd_cleanup);
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/usb/host/usb-ohci-sa1111.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,118 @@
-+/*
-+ * linux/drivers/usb/usb-ohci-sa1111.c
-+ *
-+ * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
-+ * original OHCI driver modifications, and reworked into a cleaner form
-+ * by Russell King <rmk@arm.linux.org.uk>.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/usb.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/pci.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/arch/badge4.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "usb-ohci.h"
-+
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
-+ const char *name, const char *slot_name);
-+extern void hc_remove_ohci(ohci_t *ohci);
-+
-+static ohci_t *sa1111_ohci;
-+
-+static void __init sa1111_ohci_configure(void)
-+{
-+ unsigned int usb_rst = 0;
-+
-+ if (machine_is_xp860() ||
-+ machine_has_neponset() ||
-+ machine_is_accelent_sa() ||
-+ machine_is_pfs168() ||
-+ machine_is_badge4())
-+ usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
-+
-+ /*
-+ * Configure the power sense and control lines. Place the USB
-+ * host controller in reset.
-+ */
-+ USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
-+
-+ /*
-+ * Now, carefully enable the USB clock, and take
-+ * the USB host controller out of reset.
-+ */
-+ SKPCR |= SKPCR_UCLKEN;
-+ udelay(11);
-+ USB_RESET = usb_rst;
-+}
-+
-+static int __init sa1111_ohci_init(void)
-+{
-+ int ret;
-+
-+ /*
-+ * Request memory resources.
-+ */
-+// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci"))
-+// return -EBUSY;
-+
-+ sa1111_ohci_configure();
-+
-+ /*
-+ * Initialise the generic OHCI driver.
-+ */
-+ ret = hc_add_ohci(SA1111_FAKE_PCIDEV, NIRQHCIM,
-+ (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci,
-+ "usb-ohci", "sa1111");
-+
-+// if (ret)
-+// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
-+
-+#ifdef CONFIG_SA1100_BADGE4
-+ if (machine_is_badge4() && (!ret)) {
-+ /* found the controller, so now power the bus */
-+ badge4_set_5V(BADGE4_5V_USB, 1);
-+ }
-+#endif
-+
-+ return ret;
-+}
-+
-+static void __exit sa1111_ohci_exit(void)
-+{
-+ hc_remove_ohci(sa1111_ohci);
-+
-+ /*
-+ * Put the USB host controller into reset.
-+ */
-+ USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
-+
-+ /*
-+ * Stop the USB clock.
-+ */
-+ SKPCR &= ~SKPCR_UCLKEN;
-+
-+ /*
-+ * Release memory resources.
-+ */
-+// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
-+
-+#ifdef CONFIG_SA1100_BADGE4
-+ if (machine_is_badge4()) {
-+ badge4_set_5V(BADGE4_5V_USB, 0);
-+ }
-+#endif
-+}
-+
-+module_init(sa1111_ohci_init);
-+module_exit(sa1111_ohci_exit);
---- linux-2.4.25/drivers/usb/host/usb-ohci.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/usb/host/usb-ohci.c 2004-03-31 17:15:09.000000000 +0200
-@@ -12,7 +12,6 @@
- *
- * History:
- *
-- * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX <thchou@ali>)
- * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
- * load failure (Matthew Frederickson)
- * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and
-@@ -81,16 +80,6 @@
-
- #include "../hcd.h"
-
--#ifdef CONFIG_PMAC_PBOOK
--#include <asm/machdep.h>
--#include <asm/pmac_feature.h>
--#include <asm/pci-bridge.h>
--#ifndef CONFIG_PM
--#define CONFIG_PM
--#endif
--#endif
--
--
- /*
- * Version Information
- */
-@@ -98,14 +87,10 @@
- #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
- #define DRIVER_DESC "USB OHCI Host Controller Driver"
-
--/* For initializing controller (mask in an HCFS mode too) */
--#define OHCI_CONTROL_INIT \
-- (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
--
- #define OHCI_UNLINK_TIMEOUT (HZ / 10)
-
- static LIST_HEAD (ohci_hcd_list);
--static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-+spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-
-
- /*-------------------------------------------------------------------------*/
-@@ -443,7 +428,7 @@
-
- static void ohci_dump (ohci_t *controller, int verbose)
- {
-- dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
-+ dbg ("OHCI controller usb-%s state", controller->slot_name);
-
- // dumps some of the state we know about
- ohci_dump_status (controller);
-@@ -557,7 +542,7 @@
- int i, size = 0;
- unsigned long flags;
- int bustime = 0;
-- int mem_flags = GFP_ATOMIC;
-+ int mem_flags = ALLOC_FLAGS;
-
- if (!urb->dev || !urb->dev->bus)
- return -ENODEV;
-@@ -702,6 +687,9 @@
- if (urb->timeout) {
- struct list_head *entry;
-
-+ // FIXME: usb-uhci uses relative timeouts (like this),
-+ // while uhci uses absolute ones (probably better).
-+ // Pick one solution and change the affected drivers.
- urb->timeout += jiffies;
-
- list_for_each (entry, &ohci->timeout_list) {
-@@ -715,7 +703,6 @@
-
- /* drive timeouts by SF (messy, but works) */
- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- #endif
-
-@@ -790,10 +777,8 @@
-
- /* wait until all TDs are deleted */
- set_current_state(TASK_UNINTERRUPTIBLE);
-- while (timeout && (urb->status == USB_ST_URB_PENDING)) {
-+ while (timeout && (urb->status == USB_ST_URB_PENDING))
- timeout = schedule_timeout (timeout);
-- set_current_state(TASK_UNINTERRUPTIBLE);
-- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue (&unlink_wakeup, &wait);
- if (urb->status == USB_ST_URB_PENDING) {
-@@ -864,7 +849,7 @@
- if (ed->state == ED_OPER) {
- /* driver on that interface didn't unlink an urb */
- dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
-- ohci->ohci_dev->slot_name, usb_dev->devnum, i);
-+ ohci->slot_name, usb_dev->devnum, i);
- ep_unlink (ohci, ed);
- }
- ep_rm_ed (usb_dev, ed);
-@@ -909,7 +894,7 @@
- } else {
- /* likely some interface's driver has a refcount bug */
- err ("bus %s devnum %d deletion in interrupt",
-- ohci->ohci_dev->slot_name, usb_dev->devnum);
-+ ohci->slot_name, usb_dev->devnum);
- BUG ();
- }
- }
-@@ -1294,7 +1279,6 @@
- /* enable SOF interrupt */
- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- }
-
-@@ -1316,7 +1300,11 @@
- err("internal OHCI error: TD index > length");
- return;
- }
--
-+#ifdef CONFIG_SA1111
-+ if (data & (1 << 20))
-+ panic("td_fill: A20 = 1: %08x\n", data);
-+#endif
-+
- /* use this td as the next dummy */
- td_pt = urb_priv->td [index];
- td_pt->hwNextTD = 0;
-@@ -1415,7 +1403,6 @@
- if (!ohci->sleeping) {
- wmb();
- writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- break;
-
-@@ -1444,7 +1431,6 @@
- if (!ohci->sleeping) {
- wmb();
- writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- break;
-
-@@ -1826,7 +1812,7 @@
- num_ports = roothub_a (ohci) & RH_A_NDP;
- if (num_ports > MAX_ROOT_PORTS) {
- err ("bogus NDP=%d for OHCI usb-%s", num_ports,
-- ohci->ohci_dev->slot_name);
-+ ohci->slot_name);
- err ("rereads as NDP=%d",
- readl (&ohci->regs->roothub.a) & RH_A_NDP);
- /* retry later; "should not happen" */
-@@ -2174,16 +2160,12 @@
- writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
-
- dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
-- ohci->ohci_dev->slot_name,
-+ ohci->slot_name,
- readl (&ohci->regs->control));
-
- /* Reset USB (needed by some controllers) */
- writel (0, &ohci->regs->control);
--
-- /* Force a state change from USBRESET to USBOPERATIONAL for ALi */
-- (void) readl (&ohci->regs->control); /* PCI posting */
-- writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control);
--
-+
- /* HC Reset requires max 10 ms delay */
- writel (OHCI_HCR, &ohci->regs->cmdstatus);
- while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
-@@ -2252,8 +2234,6 @@
- writel (RH_HS_LPSC, &ohci->regs->roothub.status);
- #endif /* OHCI_USE_NPS */
-
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
--
- // POTPGT delay is bits 24-31, in 2 ms units.
- mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
-
-@@ -2332,14 +2312,14 @@
- /* interrupt for some other device? */
- } else if ((ints &= readl (&regs->intrenable)) == 0) {
- return;
-- }
-+ }
-
- // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
-
- if (ints & OHCI_INTR_UE) {
- ohci->disabled++;
- err ("OHCI Unrecoverable Error, controller usb-%s disabled",
-- ohci->ohci_dev->slot_name);
-+ ohci->slot_name);
- // e.g. due to PCI Master/Target Abort
-
- #ifdef DEBUG
-@@ -2355,30 +2335,24 @@
-
- if (ints & OHCI_INTR_WDH) {
- writel (OHCI_INTR_WDH, &regs->intrdisable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- dl_done_list (ohci, dl_reverse_done_list (ohci));
- writel (OHCI_INTR_WDH, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- }
-
- if (ints & OHCI_INTR_SO) {
- dbg("USB Schedule overrun");
- writel (OHCI_INTR_SO, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- }
-
- // FIXME: this assumes SOF (1/ms) interrupts don't get lost...
- if (ints & OHCI_INTR_SF) {
- unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
- writel (OHCI_INTR_SF, &regs->intrdisable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- if (ohci->ed_rm_list[!frame] != NULL) {
- dl_del_list (ohci, !frame);
- }
-- if (ohci->ed_rm_list[frame] != NULL) {
-+ if (ohci->ed_rm_list[frame] != NULL)
- writel (OHCI_INTR_SF, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
-- }
- }
-
- if (!list_empty (&ohci->timeout_list)) {
-@@ -2392,7 +2366,6 @@
-
- writel (ints, &regs->intrstatus);
- writel (OHCI_INTR_MIE, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- }
-
- /*-------------------------------------------------------------------------*/
-@@ -2423,7 +2396,9 @@
- ohci->regs = mem_base;
-
- ohci->ohci_dev = dev;
-+#ifdef CONFIG_PCI
- pci_set_drvdata(dev, ohci);
-+#endif
-
- INIT_LIST_HEAD (&ohci->ohci_hcd_list);
- list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
-@@ -2451,7 +2426,7 @@
-
- static void hc_release_ohci (ohci_t * ohci)
- {
-- dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
-+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
-
- /* disconnect all devices */
- if (ohci->bus->root_hub)
-@@ -2464,7 +2439,9 @@
- free_irq (ohci->irq, ohci);
- ohci->irq = -1;
- }
-- pci_set_drvdata(ohci->ohci_dev, NULL);
-+#ifdef CONFIG_PCI
-+ pci_set_drvdata(ohci->ohci_dev, 0);
-+#endif
- if (ohci->bus) {
- if (ohci->bus->busnum != -1)
- usb_deregister_bus (ohci->bus);
-@@ -2487,17 +2464,15 @@
-
- /*-------------------------------------------------------------------------*/
-
--/* Increment the module usage count, start the control thread and
-- * return success. */
--
--static struct pci_driver ohci_pci_driver;
--
--static int __devinit
--hc_found_ohci (struct pci_dev *dev, int irq,
-- void *mem_base, const struct pci_device_id *id)
-+/*
-+ * Host bus independent add one OHCI host controller.
-+ */
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags,
-+ const char *name, const char *slot_name)
- {
-- ohci_t * ohci;
- char buf[8], *bufp = buf;
-+ ohci_t * ohci;
- int ret;
-
- #ifndef __sparc__
-@@ -2507,34 +2482,17 @@
- #endif
- printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
- (unsigned long) mem_base, bufp);
-- printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
--
-+
- ohci = hc_alloc_ohci (dev, mem_base);
- if (!ohci) {
- return -ENOMEM;
- }
-+ ohci->slot_name = slot_name;
- if ((ret = ohci_mem_init (ohci)) < 0) {
- hc_release_ohci (ohci);
- return ret;
- }
-- ohci->flags = id->driver_data;
--
-- /* Check for NSC87560. We have to look at the bridge (fn1) to identify
-- the USB (fn2). This quirk might apply to more or even all NSC stuff
-- I don't know.. */
--
-- if(dev->vendor == PCI_VENDOR_ID_NS)
-- {
-- struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
-- if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
-- ohci->flags |= OHCI_QUIRK_SUCKYIO;
--
-- }
--
-- if (ohci->flags & OHCI_QUIRK_SUCKYIO)
-- printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
-- if (ohci->flags & OHCI_QUIRK_AMD756)
-- printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
-+ ohci->flags = flags;
-
- if (hc_reset (ohci) < 0) {
- hc_release_ohci (ohci);
-@@ -2543,13 +2501,11 @@
-
- /* FIXME this is a second HC reset; why?? */
- writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- wait_ms (10);
-
- usb_register_bus (ohci->bus);
-
-- if (request_irq (irq, hc_interrupt, SA_SHIRQ,
-- ohci_pci_driver.name, ohci) != 0) {
-+ if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) {
- err ("request interrupt %s failed", bufp);
- hc_release_ohci (ohci);
- return -EBUSY;
-@@ -2557,7 +2513,7 @@
- ohci->irq = irq;
-
- if (hc_start (ohci) < 0) {
-- err ("can't start usb-%s", dev->slot_name);
-+ err ("can't start usb-%s", ohci->slot_name);
- hc_release_ohci (ohci);
- return -EBUSY;
- }
-@@ -2568,114 +2524,11 @@
- return 0;
- }
-
--/*-------------------------------------------------------------------------*/
--
--#ifdef CONFIG_PM
--
--/* controller died; cleanup debris, then restart */
--/* must not be called from interrupt context */
--
--static void hc_restart (ohci_t *ohci)
--{
-- int temp;
-- int i;
--
-- if (ohci->pci_latency)
-- pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
--
-- ohci->disabled = 1;
-- ohci->sleeping = 0;
-- if (ohci->bus->root_hub)
-- usb_disconnect (&ohci->bus->root_hub);
--
-- /* empty the interrupt branches */
-- for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-- for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
--
-- /* no EDs to remove */
-- ohci->ed_rm_list [0] = NULL;
-- ohci->ed_rm_list [1] = NULL;
--
-- /* empty control and bulk lists */
-- ohci->ed_isotail = NULL;
-- ohci->ed_controltail = NULL;
-- ohci->ed_bulktail = NULL;
--
-- if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-- err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
-- } else
-- dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
--}
--
--#endif /* CONFIG_PM */
--
--/*-------------------------------------------------------------------------*/
--
--/* configured so that an OHCI device is always provided */
--/* always called with process context; sleeping is OK */
--
--static int __devinit
--ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
--{
-- unsigned long mem_resource, mem_len;
-- void *mem_base;
-- int status;
--
-- if (pci_enable_device(dev) < 0)
-- return -ENODEV;
--
-- if (!dev->irq) {
-- err("found OHCI device with no IRQ assigned. check BIOS settings!");
-- pci_disable_device (dev);
-- return -ENODEV;
-- }
--
-- /* we read its hardware registers as memory */
-- mem_resource = pci_resource_start(dev, 0);
-- mem_len = pci_resource_len(dev, 0);
-- if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-- dbg ("controller already in use");
-- pci_disable_device (dev);
-- return -EBUSY;
-- }
--
-- mem_base = ioremap_nocache (mem_resource, mem_len);
-- if (!mem_base) {
-- err("Error mapping OHCI memory");
-- release_mem_region (mem_resource, mem_len);
-- pci_disable_device (dev);
-- return -EFAULT;
-- }
--
-- /* controller writes into our memory */
-- pci_set_master (dev);
--
-- status = hc_found_ohci (dev, dev->irq, mem_base, id);
-- if (status < 0) {
-- iounmap (mem_base);
-- release_mem_region (mem_resource, mem_len);
-- pci_disable_device (dev);
-- }
-- return status;
--}
--
--/*-------------------------------------------------------------------------*/
--
--/* may be called from interrupt context [interface spec] */
--/* may be called without controller present */
--/* may be called with controller, bus, and devices active */
--
--static void __devexit
--ohci_pci_remove (struct pci_dev *dev)
-+/*
-+ * Host bus independent remove one OHCI host controller.
-+ */
-+void __devexit hc_remove_ohci(ohci_t *ohci)
- {
-- ohci_t *ohci = pci_get_drvdata(dev);
--
-- dbg ("remove %s controller usb-%s%s%s",
-- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-- dev->slot_name,
-- ohci->disabled ? " (disabled)" : "",
-- in_interrupt () ? " in interrupt" : ""
-- );
- #ifdef DEBUG
- ohci_dump (ohci, 1);
- #endif
-@@ -2692,270 +2545,8 @@
- &ohci->regs->control);
-
- hc_release_ohci (ohci);
--
-- release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-- pci_disable_device (dev);
- }
-
--
--#ifdef CONFIG_PM
--
--/*-------------------------------------------------------------------------*/
--
--static int
--ohci_pci_suspend (struct pci_dev *dev, u32 state)
--{
-- ohci_t *ohci = pci_get_drvdata(dev);
-- unsigned long flags;
-- u16 cmd;
--
-- if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-- dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-- return -EIO;
-- }
--
-- /* act as if usb suspend can always be used */
-- info ("USB suspend: usb-%s", dev->slot_name);
-- ohci->sleeping = 1;
--
-- /* First stop processing */
-- spin_lock_irqsave (&usb_ed_lock, flags);
-- ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-- writel (ohci->hc_control, &ohci->regs->control);
-- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-- (void) readl (&ohci->regs->intrstatus);
-- spin_unlock_irqrestore (&usb_ed_lock, flags);
--
-- /* Wait a frame or two */
-- mdelay(1);
-- if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-- mdelay (1);
--
--#ifdef CONFIG_PMAC_PBOOK
-- if (_machine == _MACH_Pmac)
-- disable_irq (ohci->irq);
-- /* else, 2.4 assumes shared irqs -- don't disable */
--#endif
-- /* Enable remote wakeup */
-- writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
--
-- /* Suspend chip and let things settle down a bit */
-- ohci->hc_control = OHCI_USB_SUSPEND;
-- writel (ohci->hc_control, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (500); /* No schedule here ! */
-- switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-- case OHCI_USB_RESET:
-- dbg("Bus in reset phase ???");
-- break;
-- case OHCI_USB_RESUME:
-- dbg("Bus in resume phase ???");
-- break;
-- case OHCI_USB_OPER:
-- dbg("Bus in operational phase ???");
-- break;
-- case OHCI_USB_SUSPEND:
-- dbg("Bus suspended");
-- break;
-- }
-- /* In some rare situations, Apple's OHCI have happily trashed
-- * memory during sleep. We disable it's bus master bit during
-- * suspend
-- */
-- pci_read_config_word (dev, PCI_COMMAND, &cmd);
-- cmd &= ~PCI_COMMAND_MASTER;
-- pci_write_config_word (dev, PCI_COMMAND, cmd);
--#ifdef CONFIG_PMAC_PBOOK
-- {
-- struct device_node *of_node;
--
-- /* Disable USB PAD & cell clock */
-- of_node = pci_device_to_OF_node (ohci->ohci_dev);
-- if (of_node)
-- pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-- }
--#endif
-- return 0;
--}
--
--/*-------------------------------------------------------------------------*/
--
--static int
--ohci_pci_resume (struct pci_dev *dev)
--{
-- ohci_t *ohci = pci_get_drvdata(dev);
-- int temp;
-- unsigned long flags;
--
-- /* guard against multiple resumes */
-- atomic_inc (&ohci->resume_count);
-- if (atomic_read (&ohci->resume_count) != 1) {
-- err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-- atomic_dec (&ohci->resume_count);
-- return 0;
-- }
--
--#ifdef CONFIG_PMAC_PBOOK
-- {
-- struct device_node *of_node;
--
-- /* Re-enable USB PAD & cell clock */
-- of_node = pci_device_to_OF_node (ohci->ohci_dev);
-- if (of_node)
-- pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-- }
--#endif
--
-- /* did we suspend, or were we powered off? */
-- ohci->hc_control = readl (&ohci->regs->control);
-- temp = ohci->hc_control & OHCI_CTRL_HCFS;
--
--#ifdef DEBUG
-- /* the registers may look crazy here */
-- ohci_dump_status (ohci);
--#endif
--
-- /* Re-enable bus mastering */
-- pci_set_master(ohci->ohci_dev);
--
-- switch (temp) {
--
-- case OHCI_USB_RESET: // lost power
-- info ("USB restart: usb-%s", dev->slot_name);
-- hc_restart (ohci);
-- break;
--
-- case OHCI_USB_SUSPEND: // host wakeup
-- case OHCI_USB_RESUME: // remote wakeup
-- info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
-- (temp == OHCI_USB_SUSPEND)
-- ? "host" : "remote");
-- ohci->hc_control = OHCI_USB_RESUME;
-- writel (ohci->hc_control, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (20); /* no schedule here ! */
-- /* Some controllers (lucent) need a longer delay here */
-- mdelay (15);
-- temp = readl (&ohci->regs->control);
-- temp = ohci->hc_control & OHCI_CTRL_HCFS;
-- if (temp != OHCI_USB_RESUME) {
-- err ("controller usb-%s won't resume", dev->slot_name);
-- ohci->disabled = 1;
-- return -EIO;
-- }
--
-- /* Some chips likes being resumed first */
-- writel (OHCI_USB_OPER, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (3);
--
-- /* Then re-enable operations */
-- spin_lock_irqsave (&usb_ed_lock, flags);
-- ohci->disabled = 0;
-- ohci->sleeping = 0;
-- ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-- if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-- if (ohci->ed_controltail)
-- ohci->hc_control |= OHCI_CTRL_CLE;
-- if (ohci->ed_bulktail)
-- ohci->hc_control |= OHCI_CTRL_BLE;
-- }
-- writel (ohci->hc_control, &ohci->regs->control);
-- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- /* Check for a pending done list */
-- writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
-- (void) readl (&ohci->regs->intrdisable);
-- spin_unlock_irqrestore (&usb_ed_lock, flags);
--#ifdef CONFIG_PMAC_PBOOK
-- if (_machine == _MACH_Pmac)
-- enable_irq (ohci->irq);
--#endif
-- if (ohci->hcca->done_head)
-- dl_done_list (ohci, dl_reverse_done_list (ohci));
-- writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
-- writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-- writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-- break;
--
-- default:
-- warn ("odd PCI resume for usb-%s", dev->slot_name);
-- }
--
-- /* controller is operational, extra resumes are harmless */
-- atomic_dec (&ohci->resume_count);
--
-- return 0;
--}
--
--#endif /* CONFIG_PM */
--
--
--/*-------------------------------------------------------------------------*/
--
--static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
--
-- /*
-- * AMD-756 [Viper] USB has a serious erratum when used with
-- * lowspeed devices like mice.
-- */
-- vendor: 0x1022,
-- device: 0x740c,
-- subvendor: PCI_ANY_ID,
-- subdevice: PCI_ANY_ID,
--
-- driver_data: OHCI_QUIRK_AMD756,
--
--} , {
--
-- /* handle any USB OHCI controller */
-- class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-- class_mask: ~0,
--
-- /* no matter who makes it */
-- vendor: PCI_ANY_ID,
-- device: PCI_ANY_ID,
-- subvendor: PCI_ANY_ID,
-- subdevice: PCI_ANY_ID,
--
-- }, { /* end: all zeroes */ }
--};
--
--MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
--
--static struct pci_driver ohci_pci_driver = {
-- name: "usb-ohci",
-- id_table: &ohci_pci_ids [0],
--
-- probe: ohci_pci_probe,
-- remove: __devexit_p(ohci_pci_remove),
--
--#ifdef CONFIG_PM
-- suspend: ohci_pci_suspend,
-- resume: ohci_pci_resume,
--#endif /* PM */
--};
--
--
--/*-------------------------------------------------------------------------*/
--
--static int __init ohci_hcd_init (void)
--{
-- return pci_module_init (&ohci_pci_driver);
--}
--
--/*-------------------------------------------------------------------------*/
--
--static void __exit ohci_hcd_cleanup (void)
--{
-- pci_unregister_driver (&ohci_pci_driver);
--}
--
--module_init (ohci_hcd_init);
--module_exit (ohci_hcd_cleanup);
--
--
- MODULE_AUTHOR( DRIVER_AUTHOR );
- MODULE_DESCRIPTION( DRIVER_DESC );
- MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/usb/host/usb-ohci.h~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/usb/host/usb-ohci.h 2004-03-31 17:15:09.000000000 +0200
-@@ -386,6 +386,7 @@
- struct ohci_regs * regs; /* OHCI controller's memory */
- struct list_head ohci_hcd_list; /* list of all ohci_hcd */
-
-+ struct ohci * next; // chain of ohci device contexts
- struct list_head timeout_list;
- // struct list_head urb_list; // list of all pending urbs
- // spinlock_t urb_list_lock; // lock to keep consistency
-@@ -403,6 +404,7 @@
-
- /* PCI device handle, settings, ... */
- struct pci_dev *ohci_dev;
-+ const char *slot_name;
- u8 pci_latency;
- struct pci_pool *td_cache;
- struct pci_pool *dev_cache;
-@@ -448,7 +450,7 @@
- #endif
-
- #ifndef CONFIG_PCI
--# error "usb-ohci currently requires PCI-based controllers"
-+//# error "usb-ohci currently requires PCI-based controllers"
- /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
- #endif
-
-@@ -641,3 +643,6 @@
- pci_pool_free (hc->dev_cache, dev, dev->dma);
- }
-
-+/* For initializing controller (mask in an HCFS mode too) */
-+#define OHCI_CONTROL_INIT \
-+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
---- linux-2.4.25/drivers/video/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/video/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -30,13 +30,28 @@
- tristate ' Permedia3 support (EXPERIMENTAL)' CONFIG_FB_PM3
- fi
- fi
-- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-- bool ' Acorn VIDC support' CONFIG_FB_ACORN
-- fi
-- dep_tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
-- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- bool ' SA-1100 LCD support' CONFIG_FB_SA1100
-+ if [ "$CONFIG_ARM" = "y" ]; then
-+ if [ "$CONFIG_ARCH_ACORN" -o "$CONFIG_ARCH_RISCSTATION" ]; then
-+ bool ' Acorn VIDC support' CONFIG_FB_ACORN
-+ else
-+ define_bool CONFIG_FB_ACORN n
-+ fi
-+ dep_bool ' Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
-+ dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
-+ dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
-+ dep_bool ' MX1ADS LCD support' CONFIG_FB_DBMX1 $CONFIG_ARCH_MX1ADS
-+ if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
-+ choice 'CerfBoard LCD Display Size' \
-+ "3.8_Color CONFIG_CERF_LCD_38_A \
-+ 3.8_Mono CONFIG_CERF_LCD_38_B \
-+ 5.7 CONFIG_CERF_LCD_57_A \
-+ 7.2 CONFIG_CERF_LCD_72_A" 5.7
-+ fi
-+ if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
-+ bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
-+ fi
- fi
-+ dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
- if [ "$CONFIG_APOLLO" = "y" ]; then
- define_bool CONFIG_FB_APOLLO y
- fi
-@@ -265,7 +280,7 @@
- "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \
- "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
- "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
-- "$CONFIG_FB_TX3912" = "y" ]; then
-+ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" ]; then
- define_tristate CONFIG_FBCON_MFB y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \
-@@ -273,19 +288,20 @@
- "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \
- "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
- "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
-- "$CONFIG_FB_TX3912" = "m" ]; then
-+ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
- define_tristate CONFIG_FBCON_MFB m
- fi
- fi
- if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
- "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
-- "$CONFIG_FB_TX3912" = "y" ]; then
-+ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB2 y
- define_tristate CONFIG_FBCON_CFB4 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
- "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
-- "$CONFIG_FB_TX3912" = "m" ]; then
-+ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
- define_tristate CONFIG_FBCON_CFB2 m
- define_tristate CONFIG_FBCON_CFB4 m
- fi
-@@ -312,7 +328,8 @@
- "$CONFIG_FB_TX3912" = "y" -o \
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
- "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
-- "$CONFIG_FB_INTEL" = "y" ]; then
-+ "$CONFIG_FB_INTEL" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB8 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
-@@ -354,7 +371,9 @@
- "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
- "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
-- "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" ]; then
-+ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
-+ "$CONFIG_FB_ANAKIN" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB16 y
- else
- if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
-@@ -509,6 +528,9 @@
- if [ "$CONFIG_AMIGA" = "y" ]; then
- define_bool CONFIG_FONT_PEARL_8x8 y
- fi
-+ if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
-+ define_bool CONFIG_FONT_ACORN_8x8 y
-+ fi
- if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
- define_bool CONFIG_FONT_ACORN_8x8 y
- fi
---- linux-2.4.25/drivers/video/Makefile~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/video/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -55,6 +55,7 @@
- obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
- obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
- obj-$(CONFIG_FB_CT65550) += chipsfb.o
-+obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
- obj-$(CONFIG_FB_CYBER) += cyberfb.o
- obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
- obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
-@@ -68,7 +69,7 @@
- obj-$(CONFIG_FB_TRIDENT) += tridentfb.o fbgen.o
- obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
- obj-$(CONFIG_FB_TGA) += tgafb.o fbgen.o
--obj-$(CONFIG_FB_VESA) += vesafb.o
-+obj-$(CONFIG_FB_VESA) += vesafb.o
- obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
- obj-$(CONFIG_FB_VIRGE) += virgefb.o
- obj-$(CONFIG_FB_G364) += g364fb.o
-@@ -126,14 +127,16 @@
-
- obj-$(CONFIG_FB_SUN3) += sun3fb.o
- obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
--obj-$(CONFIG_FB_HGA) += hgafb.o
-+obj-$(CONFIG_FB_HGA) += hgafb.o
- obj-$(CONFIG_FB_SA1100) += sa1100fb.o
--obj-$(CONFIG_FB_VIRTUAL) += vfb.o
-+obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
-+obj-$(CONFIG_FB_VIRTUAL) += vfb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
- obj-$(CONFIG_FB_E1355) += epson1355fb.o fbgen.o
- obj-$(CONFIG_FB_E1356) += epson1356fb.o
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
-+obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
-
- # Generic Low Level Drivers
-
-@@ -169,4 +172,3 @@
- -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
-
- promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h
--
---- linux-2.4.25/drivers/video/acornfb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/drivers/video/acornfb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -752,11 +752,12 @@
- }
- #endif
- #ifdef FBCON_HAS_CFB16
-- if (bpp == 16 && regno < 16) {
-+ if (bpp == 16) {
- int i;
-
-- current_par.cmap.cfb16[regno] =
-- regno | regno << 5 | regno << 10;
-+ if (regno < 16)
-+ current_par.cmap.cfb16[regno] =
-+ regno | regno << 5 | regno << 10;
-
- pal.p = 0;
- vidc_writel(0x10000000);
-@@ -1215,7 +1216,7 @@
- p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
- p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
- }
-- acornfb_palette_write(i, current_par.palette[i]);
-+ acornfb_palette_write(i, p);
- }
- } else
- #endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/anakinfb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,221 @@
-+/*
-+ * linux/drivers/video/anakinfb.c
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 23-Apr-2001 TTC Created
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/string.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+
-+#include <asm/io.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-cfb16.h>
-+
-+static u16 colreg[16];
-+static int currcon = 0;
-+static struct fb_info fb_info;
-+static struct display display;
-+
-+static int
-+anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-+ u_int *transp, struct fb_info *info)
-+{
-+ if (regno > 15)
-+ return 1;
-+
-+ *red = colreg[regno] & 0xf800;
-+ *green = colreg[regno] & 0x7e0 << 5;
-+ *blue = colreg[regno] & 0x1f << 11;
-+ *transp = 0;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ if (regno > 15)
-+ return 1;
-+
-+ colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
-+ (blue & 0xf800 >> 11);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, "AnakinFB");
-+ fix->smem_start = VGA_START;
-+ fix->smem_len = VGA_SIZE;
-+ fix->type = FB_TYPE_PACKED_PIXELS;
-+ fix->type_aux = 0;
-+ fix->visual = FB_VISUAL_TRUECOLOR;
-+ fix->xpanstep = 0;
-+ fix->ypanstep = 0;
-+ fix->ywrapstep = 0;
-+ fix->line_length = 400 * 2;
-+ fix->accel = FB_ACCEL_NONE;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ memset(var, 0, sizeof(struct fb_var_screeninfo));
-+ var->xres = 400;
-+ var->yres = 234;
-+ var->xres_virtual = 400;
-+ var->yres_virtual = 234;
-+ var->xoffset = 0;
-+ var->yoffset = 0;
-+ var->bits_per_pixel = 16;
-+ var->grayscale = 0;
-+ 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;
-+ var->nonstd = 0;
-+ var->activate = FB_ACTIVATE_NOW;
-+ var->height = -1;
-+ var->width = -1;
-+ var->pixclock = 0;
-+ var->left_margin = 0;
-+ var->right_margin = 0;
-+ var->upper_margin = 0;
-+ var->lower_margin = 0;
-+ var->hsync_len = 0;
-+ var->vsync_len = 0;
-+ var->sync = 0;
-+ var->vmode = FB_VMODE_NONINTERLACED;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+static int
-+anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ if (con == currcon)
-+ return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
-+ else if (fb_display[con].cmap.len)
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err;
-+
-+ if (!fb_display[con].cmap.len) {
-+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
-+ return err;
-+ }
-+ if (con == currcon)
-+ return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
-+ else
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_switch_con(int con, struct fb_info *info)
-+{
-+ currcon = con;
-+ return 0;
-+
-+}
-+
-+static int
-+anakinfb_updatevar(int con, struct fb_info *info)
-+{
-+ return 0;
-+}
-+
-+static void
-+anakinfb_blank(int blank, struct fb_info *info)
-+{
-+ /*
-+ * TODO: use I2C to blank/unblank the screen
-+ */
-+}
-+
-+static struct fb_ops anakinfb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: anakinfb_get_fix,
-+ fb_get_var: anakinfb_get_var,
-+ fb_set_var: anakinfb_set_var,
-+ fb_get_cmap: anakinfb_get_cmap,
-+ fb_set_cmap: anakinfb_set_cmap,
-+};
-+
-+int __init
-+anakinfb_init(void)
-+{
-+ memset(&fb_info, 0, sizeof(struct fb_info));
-+ strcpy(fb_info.modename, "AnakinFB");
-+ fb_info.node = -1;
-+ fb_info.flags = FBINFO_FLAG_DEFAULT;
-+ fb_info.fbops = &anakinfb_ops;
-+ fb_info.disp = &display;
-+ strcpy(fb_info.fontname, "VGA8x16");
-+ fb_info.changevar = NULL;
-+ fb_info.switch_con = &anakinfb_switch_con;
-+ fb_info.updatevar = &anakinfb_updatevar;
-+ fb_info.blank = &anakinfb_blank;
-+
-+ memset(&display, 0, sizeof(struct display));
-+ anakinfb_get_var(&display.var, 0, &fb_info);
-+ display.screen_base = ioremap(VGA_START, VGA_SIZE);
-+ display.visual = FB_VISUAL_TRUECOLOR;
-+ display.type = FB_TYPE_PACKED_PIXELS;
-+ display.type_aux = 0;
-+ display.ypanstep = 0;
-+ display.ywrapstep = 0;
-+ display.line_length = 400 * 2;
-+ display.can_soft_blank = 1;
-+ display.inverse = 0;
-+
-+#ifdef FBCON_HAS_CFB16
-+ display.dispsw = &fbcon_cfb16;
-+ display.dispsw_data = colreg;
-+#else
-+ display.dispsw = &fbcon_dummy;
-+#endif
-+
-+ if (register_framebuffer(&fb_info) < 0)
-+ return -EINVAL;
-+
-+ MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_DESCRIPTION("Anakin framebuffer driver");
-+MODULE_SUPPORTED_DEVICE("fb");
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/clps711xfb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,677 @@
-+/*
-+ * linux/drivers/video/clps711xfb.c
-+ *
-+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Framebuffer driver for the CLPS7111 and EP7212 processors.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/delay.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb2.h>
-+#include <video/fbcon-mfb.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+
-+#include <asm/hardware/clps7111.h>
-+#include <asm/arch/syspld.h>
-+
-+static struct clps7111fb_info {
-+ struct fb_info fb;
-+ int currcon;
-+} *cfb;
-+
-+#define CMAP_MAX_SIZE 16
-+
-+/* The /proc entry for the backlight. */
-+static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
-+
-+static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+static int clps7111fb_proc_backlight_write(struct file *file,
-+ const char *buffer, unsigned long count, void *data);
-+
-+/*
-+ * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
-+ * This determines how many clocks + 1 of CL1 before the M signal toggles.
-+ * The number of lines on the display must not be divisible by this number.
-+ */
-+static unsigned int lcd_ac_prescale = 13;
-+
-+/*
-+ * Set a single color register. Return != 0 for invalid regno.
-+ */
-+static int
-+clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ unsigned int level, mask, shift, pal;
-+
-+ if (regno >= (1 << info->var.bits_per_pixel))
-+ return 1;
-+
-+ /* gray = 0.30*R + 0.58*G + 0.11*B */
-+ level = (red * 77 + green * 151 + blue * 28) >> 20;
-+
-+ /*
-+ * On an LCD, a high value is dark, while a low value is light.
-+ * So we invert the level.
-+ *
-+ * This isn't true on all machines, so we only do it on EDB7211.
-+ * --rmk
-+ */
-+ if (machine_is_edb7211() || machine_is_guidea07()) {
-+ level = 15 - level;
-+ }
-+
-+ shift = 4 * (regno & 7);
-+ level <<= shift;
-+ mask = 15 << shift;
-+ level &= mask;
-+
-+ regno = regno < 8 ? PALLSW : PALMSW;
-+
-+ pal = clps_readl(regno);
-+ pal = (pal & ~mask) | level;
-+ clps_writel(pal, regno);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Set the colormap
-+ */
-+static int
-+clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
-+ struct fb_cmap *dcmap = &fb_display[con].cmap;
-+ int err = 0;
-+
-+ /* no colormap allocated? */
-+ if (!dcmap->len)
-+ err = fb_alloc_cmap(dcmap, CMAP_MAX_SIZE, 0);
-+
-+ if (!err && con == cfb->currcon) {
-+ err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
-+ dcmap = &cfb->fb.cmap;
-+ }
-+
-+ if (!err)
-+ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
-+
-+ return err;
-+}
-+
-+/*
-+ * Set the User Defined Part of the Display
-+ */
-+static int
-+clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct display *display;
-+ unsigned int lcdcon, syscon, pixclock;
-+ int chgvar = 0;
-+
-+ if (var->activate & FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
-+ return -EINVAL;
-+
-+ if (cfb->fb.var.xres != var->xres)
-+ chgvar = 1;
-+ if (cfb->fb.var.yres != var->yres)
-+ chgvar = 1;
-+ if (cfb->fb.var.xres_virtual != var->xres_virtual)
-+ chgvar = 1;
-+ if (cfb->fb.var.yres_virtual != var->yres_virtual)
-+ chgvar = 1;
-+ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
-+ chgvar = 1;
-+
-+ if (con < 0) {
-+ display = cfb->fb.disp;
-+ chgvar = 0;
-+ } else {
-+ display = fb_display + con;
-+ }
-+
-+ var->transp.msb_right = 0;
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.msb_right = 0;
-+ var->red.offset = 0;
-+ var->red.length = var->bits_per_pixel;
-+ var->green = var->red;
-+ var->blue = var->red;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_MFB
-+ case 1:
-+ cfb->fb.fix.visual = FB_VISUAL_MONO01;
-+ display->dispsw = &fbcon_mfb;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB2
-+ case 2:
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->dispsw = &fbcon_cfb2;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->dispsw = &fbcon_cfb4;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ display->next_line = var->xres_virtual * var->bits_per_pixel / 8;
-+
-+ cfb->fb.fix.line_length = display->next_line;
-+
-+ display->screen_base = cfb->fb.screen_base;
-+ display->line_length = cfb->fb.fix.line_length;
-+ display->visual = cfb->fb.fix.visual;
-+ display->type = cfb->fb.fix.type;
-+ display->type_aux = cfb->fb.fix.type_aux;
-+ display->ypanstep = cfb->fb.fix.ypanstep;
-+ display->ywrapstep = cfb->fb.fix.ywrapstep;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ cfb->fb.var = *var;
-+ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
-+
-+ /*
-+ * Update the old var. The fbcon drivers still use this.
-+ * Once they are using cfb->fb.var, this can be dropped.
-+ * --rmk
-+ */
-+ display->var = cfb->fb.var;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ if (var->activate & FB_ACTIVATE_ALL)
-+ cfb->fb.disp->var = cfb->fb.var;
-+
-+ if (chgvar && info && cfb->fb.changevar)
-+ cfb->fb.changevar(con);
-+
-+ lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
-+ lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
-+ lcdcon |= lcd_ac_prescale << 25;
-+
-+ /*
-+ * Calculate pixel prescale value from the pixclock. This is:
-+ * 36.864MHz / pixclock_mhz - 1.
-+ * However, pixclock is in picoseconds, so this ends up being:
-+ * 36864000 * pixclock_ps / 10^12 - 1
-+ * and this will overflow the 32-bit math. We perform this as
-+ * (9 * 4096000 == 36864000):
-+ * pixclock_ps * 9 * (4096000 / 10^12) - 1
-+ */
-+ pixclock = 9 * info->var.pixclock / 244140 - 1;
-+ lcdcon |= pixclock << 19;
-+
-+ if (info->var.bits_per_pixel == 4)
-+ lcdcon |= LCDCON_GSMD;
-+ if (info->var.bits_per_pixel >= 2)
-+ lcdcon |= LCDCON_GSEN;
-+
-+ /*
-+ * LCDCON must only be changed while the LCD is disabled
-+ */
-+ syscon = clps_readl(SYSCON1);
-+ clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
-+ clps_writel(lcdcon, LCDCON);
-+ clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
-+
-+ fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Get the currently displayed virtual consoles colormap.
-+ */
-+static int
-+gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+/*
-+ * Get the currently displayed virtual consoles fixed part of the display.
-+ */
-+static int
-+gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ *fix = info->fix;
-+ return 0;
-+}
-+
-+/*
-+ * Get the current user defined part of the display.
-+ */
-+static int
-+gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ *var = info->var;
-+ return 0;
-+}
-+
-+static struct fb_ops clps7111fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_set_var: clps7111fb_set_var,
-+ fb_set_cmap: clps7111fb_set_cmap,
-+ fb_get_fix: gen_get_fix,
-+ fb_get_var: gen_get_var,
-+ fb_get_cmap: gen_get_cmap,
-+};
-+
-+static int clps7111fb_switch(int con, struct fb_info *info)
-+{
-+ struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
-+ struct display *disp;
-+ struct fb_cmap *cmap;
-+
-+ if (cfb->currcon >= 0) {
-+ disp = fb_display + cfb->currcon;
-+
-+ /*
-+ * Save the old colormap and video mode.
-+ */
-+ disp->var = cfb->fb.var;
-+ if (disp->cmap.len)
-+ fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
-+ }
-+
-+ cfb->currcon = con;
-+ disp = fb_display + con;
-+
-+ /*
-+ * Install the new colormap and change the video mode. By default,
-+ * fbcon sets all the colormaps and video modes to the default
-+ * values at bootup.
-+ */
-+ if (disp->cmap.len)
-+ cmap = &disp->cmap;
-+ else
-+ cmap = fb_default_cmap(CMAP_MAX_SIZE);
-+
-+ fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
-+
-+ cfb->fb.var = disp->var;
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
-+
-+ return 0;
-+}
-+
-+static int clps7111fb_updatevar(int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+static void clps7111fb_blank(int blank, struct fb_info *info)
-+{
-+ if (blank) {
-+ if (machine_is_edb7211()) {
-+ /* Turn off the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
-+
-+ /* Power off the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
-+
-+ /* Delay for a little while (half a second). */
-+ udelay(100);
-+
-+ /* Power off the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
-+
-+ /* Power off the LCD controller. */
-+ clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
-+ SYSCON1);
-+ }
-+ } else {
-+ if (machine_is_edb7211()) {
-+ /* Power up the LCD controller. */
-+ clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
-+ SYSCON1);
-+
-+ /* Power up the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-+
-+ /* Delay for a little while. */
-+ udelay(100);
-+
-+ /* Power up the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
-+ PDDR);
-+
-+ /* Turn on the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-+ }
-+ }
-+}
-+
-+static int
-+clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ /* We need at least two characters, one for the digit, and one for
-+ * the terminating NULL. */
-+ if (count < 2)
-+ return -EINVAL;
-+
-+ if (machine_is_edb7211()) {
-+ return sprintf(page, "%d\n",
-+ (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ unsigned char char_value;
-+ int value;
-+
-+ if (count < 1) {
-+ return -EINVAL;
-+ }
-+
-+ if (copy_from_user(&char_value, buffer, 1))
-+ return -EFAULT;
-+
-+ value = char_value - '0';
-+
-+ if (machine_is_edb7211()) {
-+ unsigned char port_d;
-+
-+ port_d = clps_readb(PDDR);
-+
-+ if (value) {
-+ port_d |= EDB_PD3_LCDBL;
-+ } else {
-+ port_d &= ~EDB_PD3_LCDBL;
-+ }
-+
-+ clps_writeb(port_d, PDDR);
-+ }
-+
-+ return count;
-+}
-+
-+static void __init clps711x_guess_lcd_params(struct fb_info *info)
-+{
-+ unsigned int lcdcon, syscon, size;
-+ unsigned long phys_base = PHYS_OFFSET;
-+ void *virt_base = (void *)PAGE_OFFSET;
-+
-+ info->var.xres_virtual = 640;
-+ info->var.yres_virtual = 240;
-+ info->var.bits_per_pixel = 4;
-+ info->var.activate = FB_ACTIVATE_NOW;
-+ info->var.height = -1;
-+ info->var.width = -1;
-+ info->var.pixclock = 93006; /* 10.752MHz pixel clock */
-+
-+ /*
-+ * If the LCD controller is already running, decode the values
-+ * in LCDCON to xres/yres/bpp/pixclock/acprescale
-+ */
-+ syscon = clps_readl(SYSCON1);
-+ if (syscon & SYSCON1_LCDEN) {
-+ lcdcon = clps_readl(LCDCON);
-+
-+ /*
-+ * Decode GSMD and GSEN bits to bits per pixel
-+ * (in cs89712 docs, GSEN is GSMD1, GSMD is GSMD2)
-+ */
-+ switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
-+ case LCDCON_GSMD | LCDCON_GSEN:
-+ info->var.bits_per_pixel = 4;
-+ break;
-+
-+ case LCDCON_GSEN:
-+ info->var.bits_per_pixel = 2;
-+ break;
-+
-+ default:
-+ info->var.bits_per_pixel = 1;
-+ break;
-+ }
-+
-+ /*
-+ * Decode xres/yres
-+ */
-+ info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
-+ info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
-+ (info->var.xres_virtual *
-+ info->var.bits_per_pixel);
-+
-+ /*
-+ * Calculate pixclock
-+ */
-+ info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
-+
-+ /*
-+ * Grab AC prescale
-+ */
-+ lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
-+ }
-+
-+ info->var.xres = info->var.xres_virtual;
-+ info->var.yres = info->var.yres_virtual;
-+ info->var.grayscale = info->var.bits_per_pixel > 1;
-+
-+ size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
-+
-+ /*
-+ * Might be worth checking to see if we can use the on-board
-+ * RAM if size here...
-+ * CLPS7110 - no on-board SRAM
-+ * EP7212 - 38400 bytes
-+ */
-+ if (size <= 38400) {
-+ printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
-+ }
-+
-+ if ((syscon & SYSCON1_LCDEN) == 0) {
-+ /*
-+ * The display isn't running. Ensure that
-+ * the display memory is empty.
-+ */
-+ memset(virt_base, 0, size);
-+ }
-+
-+ info->screen_base = virt_base;
-+ info->fix.smem_start = phys_base;
-+ info->fix.smem_len = PAGE_ALIGN(size);
-+ info->fix.type = FB_TYPE_PACKED_PIXELS;
-+}
-+
-+/* this function initializes the LCD registers as required by the Guide A07
-+*/
-+int __init clps711xfb_guidea07_init(void)
-+{
-+ unsigned long videomem, videosize;
-+ unsigned int lcdcon, syscon;
-+
-+ //LCDCON must only be changed while the LCD is disabled
-+ syscon = clps_readl(SYSCON1);
-+ clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
-+
-+ printk(KERN_INFO "CLPS711xFB: setting up cs89712 SRAM as QVGA video framebuffer\n");
-+ clps_writel(0x6, FBADDR); //internal SRAM location
-+ videomem = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
-+ if (!videomem) {
-+ printk("ioremap failed!\n");
-+ kfree(cfb);
-+ return -EIO;
-+ }
-+
-+ videosize = (320*240 * 4 / 8); //ie. 38400 or 0x9600
-+ memset((void *)videomem, 0, videosize); //clear the vid memory
-+
-+ cfb->fb.screen_base = (void *)videomem;
-+ cfb->fb.fix.smem_start = SRAM_START; //must be physical address
-+ cfb->fb.fix.smem_len = videosize;
-+
-+ cfb->fb.var.grayscale = 1;
-+ cfb->fb.var.bits_per_pixel = 4;
-+ cfb->fb.var.xres_virtual = 320;
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ // change to 4bpp mode
-+ lcdcon = clps_readl(LCDCON);
-+ lcdcon |= LCDCON_GSMD | LCDCON_GSEN; //4bpp
-+ //lcdcon |= 5 << 19; //pixel prescale value (pixclock)
-+ //lcdcon |= 13 << 25; //AC prescale value
-+ clps_writel(lcdcon, LCDCON);
-+
-+ //reenable LCD
-+ clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
-+
-+ return 0;
-+}
-+
-+int __init clps711xfb_init(void)
-+{
-+ int err = -ENOMEM;
-+
-+ cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
-+ if (!cfb)
-+ goto out;
-+
-+ memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
-+ strcpy(cfb->fb.fix.id, "clps7111");
-+
-+ cfb->currcon = -1;
-+ cfb->fb.screen_base = (void *)PAGE_OFFSET;
-+ cfb->fb.fix.smem_start = PAGE_OFFSET;
-+ cfb->fb.fix.smem_len = 0x14000;
-+ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
-+
-+ cfb->fb.fbops = &clps7111fb_ops;
-+ cfb->fb.changevar = NULL;
-+ cfb->fb.switch_con = clps7111fb_switch;
-+ cfb->fb.updatevar = clps7111fb_updatevar;
-+ cfb->fb.blank = clps7111fb_blank;
-+ cfb->fb.flags = FBINFO_FLAG_DEFAULT;
-+ cfb->fb.disp = (struct display *)(cfb + 1);
-+
-+ clps711x_guess_lcd_params(&cfb->fb);
-+
-+ if (machine_is_guidea07()) {
-+ clps711xfb_guidea07_init();
-+ }
-+
-+ if (machine_is_fortunet()) {
-+ cfb->fb.fix.smem_len = 0x20000;
-+ }
-+
-+ fb_alloc_cmap(&cfb->fb.cmap, CMAP_MAX_SIZE, 0);
-+
-+ /* Register the /proc entries. */
-+ clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
-+ &proc_root);
-+ if (clps7111fb_backlight_proc_entry == NULL) {
-+ printk("Couldn't create the /proc entry for the backlight.\n");
-+ return -EINVAL;
-+ }
-+
-+ clps7111fb_backlight_proc_entry->read_proc =
-+ &clps7111fb_proc_backlight_read;
-+ clps7111fb_backlight_proc_entry->write_proc =
-+ &clps7111fb_proc_backlight_write;
-+
-+ /*
-+ * Power up the LCD
-+ */
-+ if (machine_is_p720t()) {
-+ PLD_LCDEN = PLD_LCDEN_EN;
-+ PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-+ }
-+
-+ if (machine_is_edb7211()) {
-+ /* Power up the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-+
-+ /* Delay for a little while. */
-+ udelay(100);
-+
-+ /* Power up the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
-+
-+ /* Turn on the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-+ }
-+
-+ clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+ err = register_framebuffer(&cfb->fb);
-+
-+out: return err;
-+}
-+
-+static void __exit clps711xfb_exit(void)
-+{
-+ unregister_framebuffer(&cfb->fb);
-+ kfree(cfb);
-+
-+ /*
-+ * Power down the LCD
-+ */
-+ if (machine_is_p720t()) {
-+ PLD_LCDEN = 0;
-+ PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-+ }
-+}
-+
-+#ifdef MODULE
-+module_init(clps711xfb_init);
-+#endif
-+module_exit(clps711xfb_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("CLPS711x framebuffer driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/video/cyber2000fb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/drivers/video/cyber2000fb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1,7 +1,7 @@
- /*
- * linux/drivers/video/cyber2000fb.c
- *
-- * Copyright (C) 1998-2000 Russell King
-+ * Copyright (C) 1998-2002 Russell King
- *
- * MIPS and 50xx clock support
- * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
-@@ -13,22 +13,28 @@
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-- * Intergraphics CyberPro 2000, 2010 and 5000 frame buffer device
-+ * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
- *
- * Based on cyberfb.c.
- *
-- * Note that we now use the new fbcon fix, var and cmap scheme. We do still
-- * have to check which console is the currently displayed one however, since
-- * especially for the colourmap stuff. Once fbcon has been fully migrated,
-- * we can kill the last 5 references to cfb->currcon.
-+ * Note that we now use the new fbcon fix, var and cmap scheme. We do
-+ * still have to check which console is the currently displayed one
-+ * however, especially for the colourmap stuff.
- *
-- * We also use the new hotplug PCI subsystem. I'm not sure if there are any
-- * such cards, but I'm erring on the side of caution. We don't want to go
-- * pop just because someone does have one.
-+ * We also use the new hotplug PCI subsystem. I'm not sure if there
-+ * are any such cards, but I'm erring on the side of caution. We don't
-+ * want to go pop just because someone does have one.
- *
-- * Note that this doesn't work fully in the case of multiple CyberPro cards
-- * with grabbers. We currently can only attach to the first CyberPro card
-- * found.
-+ * Note that this doesn't work fully in the case of multiple CyberPro
-+ * cards with grabbers. We currently can only attach to the first
-+ * CyberPro card found.
-+ *
-+ * When we're in truecolour mode, we power down the LUT RAM as a power
-+ * saving feature. Also, when we enter any of the powersaving modes
-+ * (except soft blanking) we power down the RAMDACs. This saves about
-+ * 1W, which is roughly 8% of the power consumption of a NetWinder
-+ * (which, incidentally, is about the same saving as a 2.5in hard disk
-+ * entering standby mode.)
- */
- #include <linux/config.h>
- #include <linux/module.h>
-@@ -55,20 +61,16 @@
- #include <video/fbcon-cfb24.h>
- #include <video/fbcon-cfb32.h>
-
--/*
-- * Define this if you don't want RGB565, but RGB555 for 16bpp displays.
-- */
--/*#define CFB16_IS_CFB15*/
--
- #include "cyber2000fb.h"
-
- struct cfb_info {
- struct fb_info fb;
- struct display_switch *dispsw;
-+ struct display *display;
- struct pci_dev *dev;
- unsigned char *region;
- unsigned char *regs;
-- signed int currcon;
-+ u_int id;
- int func_use_count;
- u_long ref_ps;
-
-@@ -81,10 +83,16 @@
- u8 red, green, blue;
- } palette[NR_PALETTE];
-
-+ u_char mem_ctl0;
- u_char mem_ctl1;
- u_char mem_ctl2;
- u_char mclk_mult;
- u_char mclk_div;
-+ /*
-+ * RAMDAC control register is both of these or'ed together
-+ */
-+ u_char ramdac_ctrl;
-+ u_char ramdac_powerdown;
- };
-
- static char default_font_storage[40];
-@@ -144,7 +152,7 @@
- {
- int count = 100000;
-
-- while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
-+ while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
- if (!count--) {
- debug_printf("accel_wait timed out\n");
- cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
-@@ -154,24 +162,23 @@
- }
- }
-
--static void cyber2000_accel_setup(struct display *p)
-+static void cyber2000_accel_setup(struct display *display)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
-- cfb->dispsw->setup(p);
-+ cfb->dispsw->setup(display);
- }
-
- static void
--cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
-+cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
- int height, int width)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-- struct fb_var_screeninfo *var = &p->fb_info->var;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-+ struct fb_var_screeninfo *var = &display->var;
- u_long src, dst;
-- u_int fh, fw;
-- int cmd = CO_CMD_L_PATTERN_FGCOL;
-+ u_int fh, fw, cmd = CO_CMD_L_PATTERN_FGCOL;
-
-- fw = fontwidth(p);
-+ fw = fontwidth(display);
- sx *= fw;
- dx *= fw;
- width *= fw;
-@@ -183,7 +190,7 @@
- cmd |= CO_CMD_L_INC_LEFT;
- }
-
-- fh = fontheight(p);
-+ fh = fontheight(display);
- sy *= fh;
- dy *= fh;
- height *= fh;
-@@ -199,227 +206,265 @@
- dst = dx + dy * var->xres_virtual;
-
- cyber2000_accel_wait(cfb);
-- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
-- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
-+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
-+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
-
-- if (var->bits_per_pixel != 24) {
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
-- } else {
-- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
-- cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-- cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
-+ if (var->bits_per_pixel == 24) {
-+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-+ dst *= 3;
-+ src *= 3;
- }
-
-- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
-- cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
-- cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
-+ cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
-+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
-+ cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
-+ cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
- }
-
- static void
--cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-- int height, int width)
-+cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
-+ int sx, int height, int width)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-- struct fb_var_screeninfo *var = &p->fb_info->var;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-+ struct fb_var_screeninfo *var = &display->var;
- u_long dst;
- u_int fw, fh;
-- u32 bgx = attr_bgcol_ec(p, conp);
-+ u32 bgx = attr_bgcol_ec(display, conp);
-
-- fw = fontwidth(p);
-- fh = fontheight(p);
-+ fw = fontwidth(display);
-+ fh = fontheight(display);
-
- dst = sx * fw + sy * var->xres_virtual * fh;
- width = width * fw - 1;
- height = height * fh - 1;
-
- cyber2000_accel_wait(cfb);
-- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
-- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
-- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
--
-- switch (var->bits_per_pixel) {
-- case 15:
-- case 16:
-- bgx = ((u16 *)p->dispsw_data)[bgx];
-- case 8:
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- break;
-+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
-+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
-
-- case 24:
-- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
-+ if (var->bits_per_pixel == 24) {
- cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-- bgx = ((u32 *)p->dispsw_data)[bgx];
-- break;
--
-- case 32:
-- bgx = ((u32 *)p->dispsw_data)[bgx];
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- break;
-+ dst *= 3;
- }
-
-- cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
-+ if (var->bits_per_pixel == 16)
-+ bgx = ((u16 *)display->dispsw_data)[bgx];
-+ else if (var->bits_per_pixel >= 24)
-+ bgx = ((u32 *)display->dispsw_data)[bgx];
-+
-+ cyber2000fb_writel(bgx, CO_REG_FGCOLOUR, cfb);
-+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
- cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
-- cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
-+ cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
- }
-
- static void
--cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
-+cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
- int yy, int xx)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->putc(conp, p, c, yy, xx);
-+ cfb->dispsw->putc(conp, display, c, yy, xx);
- }
-
- static void
--cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
-+cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
- const unsigned short *s, int count, int yy, int xx)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->putcs(conp, p, s, count, yy, xx);
-+ cfb->dispsw->putcs(conp, display, s, count, yy, xx);
- }
-
--static void cyber2000_accel_revc(struct display *p, int xx, int yy)
-+static void cyber2000_accel_revc(struct display *display, int xx, int yy)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->revc(p, xx, yy);
-+ cfb->dispsw->revc(display, xx, yy);
- }
-
- static void
--cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
-+cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
- int bottom_only)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
-- cfb->dispsw->clear_margins(conp, p, bottom_only);
-+ cfb->dispsw->clear_margins(conp, display, bottom_only);
- }
-
- static struct display_switch fbcon_cyber_accel = {
-- setup: cyber2000_accel_setup,
-- bmove: cyber2000_accel_bmove,
-- clear: cyber2000_accel_clear,
-- putc: cyber2000_accel_putc,
-- putcs: cyber2000_accel_putcs,
-- revc: cyber2000_accel_revc,
-- clear_margins: cyber2000_accel_clear_margins,
-- fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
-+ .setup = cyber2000_accel_setup,
-+ .bmove = cyber2000_accel_bmove,
-+ .clear = cyber2000_accel_clear,
-+ .putc = cyber2000_accel_putc,
-+ .putcs = cyber2000_accel_putcs,
-+ .revc = cyber2000_accel_revc,
-+ .clear_margins = cyber2000_accel_clear_margins,
-+ .fontwidthmask = FONTWIDTH(8)|FONTWIDTH(16)
- };
-
-+static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
-+{
-+ u_int mask = (1 << bf->length) - 1;
-+
-+ return (val >> (16 - bf->length) & mask) << bf->offset;
-+}
-+
- /*
- * Set a single color register. Return != 0 for invalid regno.
- */
- static int
--cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-- u_int transp, struct fb_info *info)
-+cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-+ struct fb_var_screeninfo *var = &cfb->display->var;
-+ u32 pseudo_val;
-+ int ret = 1;
-
-- u_int alpha = transp ^ 0xFFFF;
--
-- if (regno >= NR_PALETTE)
-+ switch (cfb->fb.fix.visual) {
-+ default:
- return 1;
-
-- red >>= 8;
-- green >>= 8;
-- blue >>= 8;
-- alpha >>= 8;
-+#ifdef FBCON_HAS_CFB8
-+ /*
-+ * Pseudocolour:
-+ * 8 8
-+ * pixel --/--+--/--> red lut --> red dac
-+ * | 8
-+ * +--/--> green lut --> green dac
-+ * | 8
-+ * +--/--> blue lut --> blue dac
-+ */
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ if (regno >= NR_PALETTE)
-+ return 1;
-
-- cfb->palette[regno].red = red;
-- cfb->palette[regno].green = green;
-- cfb->palette[regno].blue = blue;
-+ red >>= 8;
-+ green >>= 8;
-+ blue >>= 8;
-+
-+ cfb->palette[regno].red = red;
-+ cfb->palette[regno].green = green;
-+ cfb->palette[regno].blue = blue;
-
-- switch (cfb->fb.var.bits_per_pixel) {
--#ifdef FBCON_HAS_CFB8
-- case 8:
- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-+ cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
-- break;
-+ cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ return 0;
- #endif
-
--#ifdef FBCON_HAS_CFB16
-- case 16:
--#ifndef CFB16_IS_CFB15
-- if (regno < 64) {
-- /* write green */
-+ /*
-+ * Direct colour:
-+ * n rl
-+ * pixel --/--+--/--> red lut --> red dac
-+ * | gl
-+ * +--/--> green lut --> green dac
-+ * | bl
-+ * +--/--> blue lut --> blue dac
-+ * n = bpp, rl = red length, gl = green length, bl = blue length
-+ */
-+ case FB_VISUAL_DIRECTCOLOR:
-+ red >>= 8;
-+ green >>= 8;
-+ blue >>= 8;
-+
-+ if (var->green.length == 6 && regno < 64) {
-+ cfb->palette[regno << 2].green = green;
-+
-+ /*
-+ * The 6 bits of the green component are applied
-+ * to the high 6 bits of the LUT.
-+ */
- cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
-+
-+ green = cfb->palette[regno << 3].green;
-+
-+ ret = 0;
- }
-
-- if (regno < 32) {
-- /* write red,blue */
-+ if (var->green.length >= 5 && regno < 32) {
-+ cfb->palette[regno << 3].red = red;
-+ cfb->palette[regno << 3].green = green;
-+ cfb->palette[regno << 3].blue = blue;
-+
-+ /*
-+ * The 5 bits of each colour component are
-+ * applied to the high 5 bits of the LUT.
-+ */
- cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
-+ cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ ret = 0;
- }
-
-- if (regno < 16)
-- ((u16 *)cfb->fb.pseudo_palette)[regno] =
-- ((red << 8) & 0xf800) |
-- ((green << 3) & 0x07e0) |
-- ((blue >> 3));
-- break;
--#endif
-+ if (var->green.length == 4 && regno < 16) {
-+ cfb->palette[regno << 4].red = red;
-+ cfb->palette[regno << 4].green = green;
-+ cfb->palette[regno << 4].blue = blue;
-
-- case 15:
-- if (regno < 32) {
-- cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
-+ /*
-+ * The 5 bits of each colour component are
-+ * applied to the high 5 bits of the LUT.
-+ */
-+ cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ ret = 0;
- }
-- if (regno < 16)
-- ((u16 *)cfb->fb.pseudo_palette)[regno] =
-- ((red << 7) & 0x7c00) |
-- ((green << 2) & 0x03e0) |
-- ((blue >> 3));
-- break;
--
--#endif
--
--#ifdef FBCON_HAS_CFB24
-- case 24:
-- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
-
-- if (regno < 16)
-- ((u32 *)cfb->fb.pseudo_palette)[regno] =
-- (red << 16) | (green << 8) | blue;
-+ /*
-+ * Since this is only used for the first 16 colours, we
-+ * don't have to care about overflowing for regno >= 32
-+ */
-+ pseudo_val = regno << var->red.offset |
-+ regno << var->green.offset |
-+ regno << var->blue.offset;
- break;
--#endif
-
--#ifdef FBCON_HAS_CFB32
-- case 32:
-- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
--
-- if (regno < 16)
-- ((u32 *)cfb->fb.pseudo_palette)[regno] =
-- (alpha << 24) | (red << 16) | (green << 8) | blue;
-+ /*
-+ * True colour:
-+ * n rl
-+ * pixel --/--+--/--> red dac
-+ * | gl
-+ * +--/--> green dac
-+ * | bl
-+ * +--/--> blue dac
-+ * n = bpp, rl = red length, gl = green length, bl = blue length
-+ */
-+ case FB_VISUAL_TRUECOLOR:
-+ pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
-+ pseudo_val |= convert_bitfield(red, &var->red);
-+ pseudo_val |= convert_bitfield(green, &var->green);
-+ pseudo_val |= convert_bitfield(blue, &var->blue);
- break;
--#endif
-+ }
-
-- default:
-- return 1;
-+ /*
-+ * Now set our pseudo palette for the CFB16/24/32 drivers.
-+ */
-+ if (regno < 16) {
-+ if (var->bits_per_pixel == 16)
-+ ((u16 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
-+ else
-+ ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
-+ ret = 0;
- }
-
-- return 0;
-+ return ret;
- }
-
- struct par_info {
-@@ -428,8 +473,8 @@
- */
- u_char clock_mult;
- u_char clock_div;
-- u_char visualid;
-- u_char pixformat;
-+ u_char extseqmisc;
-+ u_char co_pixfmt;
- u_char crtc_ofl;
- u_char crtc[19];
- u_int width;
-@@ -439,8 +484,7 @@
- /*
- * Other
- */
-- u_char palette_ctrl;
-- u_int vmode;
-+ u_char ramdac;
- };
-
- static const u_char crtc_idx[] = {
-@@ -449,6 +493,18 @@
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
- };
-
-+static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
-+{
-+ unsigned int i;
-+ unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
-+
-+ cyber2000fb_writeb(0x56, 0x3ce, cfb);
-+ i = cyber2000fb_readb(0x3cf, cfb);
-+ cyber2000fb_writeb(i | 4, 0x3cf, cfb);
-+ cyber2000fb_writeb(val, 0x3c6, cfb);
-+ cyber2000fb_writeb(i, 0x3cf, cfb);
-+}
-+
- static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
- {
- u_int i;
-@@ -480,7 +536,7 @@
- for (i = 0x0a; i < 0x10; i++)
- cyber2000_crtcw(i, 0, cfb);
-
-- cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
-+ cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
- cyber2000_grphw(0x00, 0x00, cfb);
- cyber2000_grphw(0x01, 0x00, cfb);
- cyber2000_grphw(0x02, 0x00, cfb);
-@@ -501,30 +557,17 @@
- cyber2000_attrw(0x13, 0x00, cfb);
- cyber2000_attrw(0x14, 0x00, cfb);
-
-- /* woody: set the interlaced bit... */
-- /* FIXME: what about doublescan? */
-- cyber2000fb_writeb(0x11, 0x3ce, cfb);
-- i = cyber2000fb_readb(0x3cf, cfb);
-- if (hw->vmode == FB_VMODE_INTERLACED)
-- i |= 0x20;
-- else
-- i &= ~0x20;
-- cyber2000fb_writeb(i, 0x3cf, cfb);
--
- /* PLL registers */
-- cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
-- cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
-- cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
-- cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
-+ cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
-+ cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
-+ cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
-+ cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
- cyber2000_grphw(0x90, 0x01, cfb);
- cyber2000_grphw(0xb9, 0x80, cfb);
- cyber2000_grphw(0xb9, 0x00, cfb);
-
-- cyber2000fb_writeb(0x56, 0x3ce, cfb);
-- i = cyber2000fb_readb(0x3cf, cfb);
-- cyber2000fb_writeb(i | 4, 0x3cf, cfb);
-- cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
-- cyber2000fb_writeb(i, 0x3cf, cfb);
-+ cfb->ramdac_ctrl = hw->ramdac;
-+ cyber2000fb_write_ramdac_ctrl(cfb);
-
- cyber2000fb_writeb(0x20, 0x3c0, cfb);
- cyber2000fb_writeb(0xff, 0x3c6, cfb);
-@@ -532,31 +575,32 @@
- cyber2000_grphw(0x14, hw->fetch, cfb);
- cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
- ((hw->pitch >> 4) & 0x30), cfb);
-- cyber2000_grphw(0x77, hw->visualid, cfb);
-+ cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
-
-- /* make sure we stay in linear mode */
-- cyber2000_grphw(0x33, 0x0d, cfb);
-+// cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
-+// EXT_BIU_MISC_COP_ENABLE |
-+// EXT_BIU_MISC_COP_BFC, cfb);
-
- /*
- * Set up accelerator registers
- */
- cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
- cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
-- cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
-+ cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
- }
-
- static inline int
- cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
- {
-- u_int base;
--
-- base = var->yoffset * var->xres_virtual + var->xoffset;
-+ u_int base = var->yoffset * var->xres_virtual + var->xoffset;
-
-- /* have to be careful, because bits_per_pixel might be 15
-- in this version of the driver -- dok@directfb.org 2002/06/13 */
-- base *= (var->bits_per_pixel + 7) >> 3;
-+ base *= var->bits_per_pixel;
-
-- base >>= 2;
-+ /*
-+ * Convert to bytes and shift two extra bits because DAC
-+ * can only start on 4 byte aligned data.
-+ */
-+ base >>= 5;
-
- if (base >= 1 << 20)
- return -EINVAL;
-@@ -576,27 +620,20 @@
- struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-- struct fb_cmap *dcmap = &fb_display[con].cmap;
-+ struct display *display = fb_display + con;
-+ struct fb_cmap *dcmap = &display->cmap;
- int err = 0;
-
- /* no colormap allocated? */
-- if (!dcmap->len) {
-- int size;
--
-- if (cfb->fb.var.bits_per_pixel == 16)
-- size = 32;
-- else
-- size = 256;
--
-- err = fb_alloc_cmap(dcmap, size, 0);
-- }
-+ if (!dcmap->len)
-+ err = fb_alloc_cmap(dcmap, 256, 0);
-
- /*
- * we should be able to remove this test once fbcon has been
- * "improved" --rmk
- */
-- if (!err && con == cfb->currcon) {
-- err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
-+ if (!err && display == cfb->display) {
-+ err = fb_set_cmap(cmap, kspc, cyber2000fb_setcolreg, &cfb->fb);
- dcmap = &cfb->fb.cmap;
- }
-
-@@ -672,8 +709,9 @@
- hw->crtc[16] = Vblankend;
- hw->crtc[18] = 0xff;
-
-- /* overflow - graphics reg 0x11 */
-- /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
-+ /*
-+ * overflow - graphics reg 0x11
-+ * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
- * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
- */
- hw->crtc_ofl =
-@@ -681,7 +719,12 @@
- BIT(Vdispend, 10, 0x01, 1) |
- BIT(Vsyncstart, 10, 0x01, 2) |
- BIT(Vblankstart,10, 0x01, 3) |
-- 1 << 4;
-+ EXT_CRT_VRTOFL_LINECOMP10;
-+
-+ /* woody: set the interlaced bit... */
-+ /* FIXME: what about doublescan? */
-+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-+ hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
-
- return 0;
- }
-@@ -787,7 +830,7 @@
- vco = ref_ps * best_div1 / best_mult;
- if ((ref_ps == 40690) && (vco < 5556))
- /* Set VFSEL when VCO > 180MHz (5.556 ps). */
-- hw->clock_div |= DCLK_DIV_VFSEL;
-+ hw->clock_div |= EXT_DCLK_DIV_VFSEL;
-
- return 0;
- }
-@@ -801,58 +844,131 @@
- cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
- struct par_info *hw)
- {
-+ unsigned int mem;
- int err;
-
- hw->width = var->xres_virtual;
-- hw->palette_ctrl = 0x06;
-- hw->vmode = var->vmode;
-+ hw->ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
-+
-+ var->transp.msb_right = 0;
-+ var->red.msb_right = 0;
-+ var->green.msb_right = 0;
-+ var->blue.msb_right = 0;
-
- switch (var->bits_per_pixel) {
- #ifdef FBCON_HAS_CFB8
- case 8: /* PSEUDOCOLOUR, 256 */
-- hw->pixformat = PIXFORMAT_8BPP;
-- hw->visualid = VISUALID_256;
-+ hw->co_pixfmt = CO_PIXFMT_8BPP;
- hw->pitch = hw->width >> 3;
-+ hw->extseqmisc = EXT_SEQ_MISC_8;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 0;
-+ var->red.length = 8;
-+ var->green.offset = 0;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
-- case 16:/* DIRECTCOLOUR, 64k */
--#ifndef CFB16_IS_CFB15
-- hw->pixformat = PIXFORMAT_16BPP;
-- hw->visualid = VISUALID_64K;
-- hw->pitch = hw->width >> 2;
-- hw->palette_ctrl |= 0x10;
-- break;
--#endif
-- case 15:/* DIRECTCOLOUR, 32k */
-- hw->pixformat = PIXFORMAT_16BPP;
-- hw->visualid = VISUALID_32K;
-+ case 16:/* DIRECTCOLOUR, 64k or 32k */
-+ hw->co_pixfmt = CO_PIXFMT_16BPP;
- hw->pitch = hw->width >> 2;
-- hw->palette_ctrl |= 0x10;
-- break;
-
-+ switch (var->green.length) {
-+ case 6: /* RGB565, 64k */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 11;
-+ var->red.length = 5;
-+ var->green.offset = 5;
-+ var->green.length = 6;
-+ var->blue.offset = 0;
-+ var->blue.length = 5;
-+ break;
-+
-+ default:
-+ case 5: /* RGB555, 32k */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 10;
-+ var->red.length = 5;
-+ var->green.offset = 5;
-+ var->green.length = 5;
-+ var->blue.offset = 0;
-+ var->blue.length = 5;
-+ break;
-+
-+ case 4: /* RGB444, 4k + transparency? */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB444;
-+
-+ var->transp.offset = 12;
-+ var->transp.length = 4;
-+ var->red.offset = 8;
-+ var->red.length = 4;
-+ var->green.offset = 4;
-+ var->green.length = 4;
-+ var->blue.offset = 0;
-+ var->blue.length = 4;
-+ break;
-+ }
-+ break;
- #endif
- #ifdef FBCON_HAS_CFB24
- case 24:/* TRUECOLOUR, 16m */
-- hw->pixformat = PIXFORMAT_24BPP;
-- hw->visualid = VISUALID_16M;
-+ hw->co_pixfmt = CO_PIXFMT_24BPP;
- hw->width *= 3;
- hw->pitch = hw->width >> 3;
-- hw->palette_ctrl |= 0x10;
-+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:/* TRUECOLOUR, 16m */
-- hw->pixformat = PIXFORMAT_32BPP;
-- hw->visualid = VISUALID_16M_32;
-+ hw->co_pixfmt = CO_PIXFMT_32BPP;
- hw->pitch = hw->width >> 1;
-- hw->palette_ctrl |= 0x10;
-+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ hw->extseqmisc = EXT_SEQ_MISC_32;
-+
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- default:
- return -EINVAL;
- }
-
-+ mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
-+ if (mem > cfb->fb.fix.smem_len)
-+ var->yres_virtual = cfb->fb.fix.smem_len * 8 /
-+ (var->bits_per_pixel * var->xres_virtual);
-+
-+ if (var->yres > var->yres_virtual)
-+ var->yres = var->yres_virtual;
-+ if (var->xres > var->xres_virtual)
-+ var->xres = var->xres_virtual;
-+
- err = cyber2000fb_decode_clock(hw, cfb, var);
- if (err)
- return err;
-@@ -880,7 +996,7 @@
- struct cfb_info *cfb = (struct cfb_info *)info;
- struct display *display;
- struct par_info hw;
-- int err, chgvar = 0;
-+ int err, chgvar;
-
- /*
- * CONUPDATE and SMOOTH_XPAN are equal. However,
-@@ -888,11 +1004,11 @@
- */
- if (var->vmode & FB_VMODE_CONUPDATE) {
- var->vmode |= FB_VMODE_YWRAP;
-- var->xoffset = cfb->fb.var.xoffset;
-- var->yoffset = cfb->fb.var.yoffset;
-+ var->xoffset = cfb->display->var.xoffset;
-+ var->yoffset = cfb->display->var.yoffset;
- }
-
-- err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
-+ err = cyber2000fb_decode_var(var, cfb, &hw);
- if (err)
- return err;
-
-@@ -902,105 +1018,61 @@
- if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
- return -EINVAL;
-
-- if (cfb->fb.var.xres != var->xres)
-- chgvar = 1;
-- if (cfb->fb.var.yres != var->yres)
-- chgvar = 1;
-- if (cfb->fb.var.xres_virtual != var->xres_virtual)
-- chgvar = 1;
-- if (cfb->fb.var.yres_virtual != var->yres_virtual)
-- chgvar = 1;
-- if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
-- chgvar = 1;
--
- if (con < 0) {
- display = cfb->fb.disp;
-- chgvar = 0;
- } else {
- display = fb_display + con;
- }
-
-- var->red.msb_right = 0;
-- var->green.msb_right = 0;
-- var->blue.msb_right = 0;
-+ chgvar = cfb->fb.var.xres != var->xres ||
-+ cfb->fb.var.yres != var->yres ||
-+ cfb->fb.var.xres_virtual != var->xres_virtual ||
-+ cfb->fb.var.yres_virtual != var->yres_virtual ||
-+ cfb->fb.var.bits_per_pixel != var->bits_per_pixel;
-+
-+ if (memcmp(&cfb->fb.var.red, &var->red, sizeof(var->red)) ||
-+ memcmp(&cfb->fb.var.green, &var->green, sizeof(var->green)) ||
-+ memcmp(&cfb->fb.var.blue, &var->blue, sizeof(var->blue)))
-+ chgvar = 1;
-+
-+ if (con < 0)
-+ chgvar = 0;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ err = var->activate;
-+ var->activate = FB_ACTIVATE_NOW;
-+ if (err & FB_ACTIVATE_ALL)
-+ cfb->fb.disp->var = *var;
-+
-+ cfb->fb.var = *var;
-+ cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
- switch (var->bits_per_pixel) {
- #ifdef FBCON_HAS_CFB8
- case 8: /* PSEUDOCOLOUR, 256 */
-- var->red.offset = 0;
-- var->red.length = 8;
-- var->green.offset = 0;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
- cfb->dispsw = &fbcon_cfb8;
- display->dispsw_data = NULL;
-- display->next_line = var->xres_virtual;
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
-- case 16:/* DIRECTCOLOUR, 64k */
--#ifndef CFB16_IS_CFB15
-- var->red.offset = 11;
-- var->red.length = 5;
-- var->green.offset = 5;
-- var->green.length = 6;
-- var->blue.offset = 0;
-- var->blue.length = 5;
--
-- cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ case 16:/* DIRECTCOLOUR */
- cfb->dispsw = &fbcon_cfb16;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 2;
-- break;
--#endif
-- case 15:/* DIRECTCOLOUR, 32k */
-- var->bits_per_pixel = 15;
-- var->red.offset = 10;
-- var->red.length = 5;
-- var->green.offset = 5;
-- var->green.length = 5;
-- var->blue.offset = 0;
-- var->blue.length = 5;
--
-- cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-- cfb->dispsw = &fbcon_cfb16;
-- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 2;
- break;
- #endif
- #ifdef FBCON_HAS_CFB24
- case 24:/* TRUECOLOUR, 16m */
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
- cfb->dispsw = &fbcon_cfb24;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 3;
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:/* TRUECOLOUR, 16m */
-- var->transp.offset = 24;
-- var->transp.length = 8;
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
- cfb->dispsw = &fbcon_cfb32;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 4;
- break;
- #endif
- default:/* in theory this should never happen */
-@@ -1010,15 +1082,27 @@
- break;
- }
-
-+ /*
-+ * 8bpp displays are always pseudo colour.
-+ * 16bpp and above are direct colour or true colour, depending
-+ * on whether the RAMDAC palettes are bypassed. (Direct colour
-+ * has palettes, true colour does not.)
-+ */
-+ if (var->bits_per_pixel == 8)
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else if (hw.ramdac & RAMDAC_BYPASS)
-+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-+ else
-+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+
- if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)
- display->dispsw = &fbcon_cyber_accel;
- else
- display->dispsw = cfb->dispsw;
-
-- cfb->fb.fix.line_length = display->next_line;
--
- display->screen_base = cfb->fb.screen_base;
- display->line_length = cfb->fb.fix.line_length;
-+ display->next_line = cfb->fb.fix.line_length;
- display->visual = cfb->fb.fix.visual;
- display->type = cfb->fb.fix.type;
- display->type_aux = cfb->fb.fix.type_aux;
-@@ -1026,31 +1110,15 @@
- display->ywrapstep = cfb->fb.fix.ywrapstep;
- display->can_soft_blank = 1;
- display->inverse = 0;
-+ display->var = *var;
-
-- cfb->fb.var = *var;
-- cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
--
-- /*
-- * Update the old var. The fbcon drivers still use this.
-- * Once they are using cfb->fb.var, this can be dropped.
-- * --rmk
-- */
-- display->var = cfb->fb.var;
--
-- /*
-- * If we are setting all the virtual consoles, also set the
-- * defaults used to create new consoles.
-- */
-- if (var->activate & FB_ACTIVATE_ALL)
-- cfb->fb.disp->var = cfb->fb.var;
-+ cyber2000fb_set_timing(cfb, &hw);
-+ cyber2000fb_update_start(cfb, var);
-+ fb_set_cmap(&cfb->fb.cmap, 1, cyber2000fb_setcolreg, &cfb->fb);
-
-- if (chgvar && info && cfb->fb.changevar)
-+ if (chgvar && cfb->fb.changevar)
- cfb->fb.changevar(con);
-
-- cyber2000fb_update_start(cfb, var);
-- cyber2000fb_set_timing(cfb, &hw);
-- fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb);
--
- return 0;
- }
-
-@@ -1072,18 +1140,18 @@
-
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
-- if (y_bottom > cfb->fb.var.yres_virtual)
-+ if (y_bottom > cfb->display->var.yres_virtual)
- return -EINVAL;
-
- if (cyber2000fb_update_start(cfb, var))
- return -EINVAL;
-
-- cfb->fb.var.xoffset = var->xoffset;
-- cfb->fb.var.yoffset = var->yoffset;
-+ cfb->display->var.xoffset = var->xoffset;
-+ cfb->display->var.yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP) {
-- cfb->fb.var.vmode |= FB_VMODE_YWRAP;
-+ cfb->display->var.vmode |= FB_VMODE_YWRAP;
- } else {
-- cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
-+ cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
- }
-
- return 0;
-@@ -1106,22 +1174,18 @@
- static int cyber2000fb_switch(int con, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-- struct display *disp;
-+ struct display *display = cfb->display;
- struct fb_cmap *cmap;
-
-- if (cfb->currcon >= 0) {
-- disp = fb_display + cfb->currcon;
--
-+ if (display) {
- /*
- * Save the old colormap and video mode.
- */
-- disp->var = cfb->fb.var;
-- if (disp->cmap.len)
-- fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
-+ if (display->cmap.len)
-+ fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
- }
-
-- cfb->currcon = con;
-- disp = fb_display + con;
-+ cfb->display = display = fb_display + con;
-
- /*
- * Install the new colormap and change the video mode. By default,
-@@ -1132,73 +1196,88 @@
- * depth of the new video mode. For now, we leave it at its
- * default 256 entry.
- */
-- if (disp->cmap.len)
-- cmap = &disp->cmap;
-+ if (display->cmap.len)
-+ cmap = &display->cmap;
- else
-- cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
-+ cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
-
- fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
-
-- cfb->fb.var = disp->var;
-- cfb->fb.var.activate = FB_ACTIVATE_NOW;
--
-- cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
-+ display->var.activate = FB_ACTIVATE_NOW;
-+ cyber2000fb_set_var(&display->var, con, &cfb->fb);
-
- return 0;
- }
-
- /*
- * (Un)Blank the display.
-+ *
-+ * Blank the screen if blank_mode != 0, else unblank. If
-+ * blank == NULL then the caller blanks by setting the CLUT
-+ * (Color Look Up Table) to all black. Return 0 if blanking
-+ * succeeded, != 0 if un-/blanking failed due to e.g. a
-+ * video mode which doesn't support it. Implements VESA
-+ * suspend and powerdown modes on hardware that supports
-+ * disabling hsync/vsync:
-+ * blank_mode == 2: suspend vsync
-+ * blank_mode == 3: suspend hsync
-+ * blank_mode == 4: powerdown
-+ *
-+ * wms...Enable VESA DMPS compatible powerdown mode
-+ * run "setterm -powersave powerdown" to take advantage
- */
- static void cyber2000fb_blank(int blank, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-+ unsigned int sync = 0;
- int i;
-
-- /*
-- * Blank the screen if blank_mode != 0, else unblank. If
-- * blank == NULL then the caller blanks by setting the CLUT
-- * (Color Look Up Table) to all black. Return 0 if blanking
-- * succeeded, != 0 if un-/blanking failed due to e.g. a
-- * video mode which doesn't support it. Implements VESA
-- * suspend and powerdown modes on hardware that supports
-- * disabling hsync/vsync:
-- * blank_mode == 2: suspend vsync
-- * blank_mode == 3: suspend hsync
-- * blank_mode == 4: powerdown
-- *
-- * wms...Enable VESA DMPS compatible powerdown mode
-- * run "setterm -powersave powerdown" to take advantage
-- */
--
- switch (blank) {
- case 4: /* powerdown - both sync lines down */
-- cyber2000_grphw(0x16, 0x05, cfb);
-+ sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
- break;
- case 3: /* hsync off */
-- cyber2000_grphw(0x16, 0x01, cfb);
-+ sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
- break;
- case 2: /* vsync off */
-- cyber2000_grphw(0x16, 0x04, cfb);
-- break;
-+ sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
-+ break;
- case 1: /* soft blank */
-- cyber2000_grphw(0x16, 0x00, cfb);
-+ default: /* unblank */
-+ break;
-+ }
-+
-+ cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
-+
-+ if (blank <= 1) {
-+ /* turn on ramdacs */
-+ cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ cyber2000fb_write_ramdac_ctrl(cfb);
-+ }
-+
-+ /*
-+ * Soft blank/unblank the display.
-+ */
-+ if (blank) { /* soft blank */
- for (i = 0; i < NR_PALETTE; i++) {
- cyber2000fb_writeb(i, 0x3c8, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- }
-- break;
-- default: /* unblank */
-- cyber2000_grphw(0x16, 0x00, cfb);
-+ } else { /* unblank */
- for (i = 0; i < NR_PALETTE; i++) {
- cyber2000fb_writeb(i, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
- }
-- break;
-+ }
-+
-+ if (blank >= 2) {
-+ /* turn off ramdacs */
-+ cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
-+ cyber2000fb_write_ramdac_ctrl(cfb);
- }
- }
-
-@@ -1233,51 +1312,61 @@
- }
-
- static struct fb_ops cyber2000fb_ops = {
-- owner: THIS_MODULE,
-- fb_set_var: cyber2000fb_set_var,
-- fb_set_cmap: cyber2000fb_set_cmap,
-- fb_pan_display: cyber2000fb_pan_display,
-- fb_get_fix: gen_get_fix,
-- fb_get_var: gen_get_var,
-- fb_get_cmap: gen_get_cmap,
-+ .owner = THIS_MODULE,
-+ .fb_set_var = cyber2000fb_set_var,
-+ .fb_set_cmap = cyber2000fb_set_cmap,
-+ .fb_pan_display = cyber2000fb_pan_display,
-+ .fb_get_fix = gen_get_fix,
-+ .fb_get_var = gen_get_var,
-+ .fb_get_cmap = gen_get_cmap,
- };
-
- /*
-+ * This is the only "static" reference to the internal data structures
-+ * of this driver. It is here solely at the moment to support the other
-+ * CyberPro modules external to this driver.
-+ */
-+static struct cfb_info *int_cfb_info;
-+
-+/*
- * Enable access to the extended registers
- */
--static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
-+void cyber2000fb_enable_extregs(struct cfb_info *cfb)
- {
- cfb->func_use_count += 1;
-
- if (cfb->func_use_count == 1) {
- int old;
-
-- old = cyber2000_grphr(FUNC_CTL, cfb);
-- cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
-+ old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-+ old |= EXT_FUNC_CTL_EXTREGENBL;
-+ cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
- }
- }
-
- /*
- * Disable access to the extended registers
- */
--static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
-+void cyber2000fb_disable_extregs(struct cfb_info *cfb)
- {
- if (cfb->func_use_count == 1) {
- int old;
-
-- old = cyber2000_grphr(FUNC_CTL, cfb);
-- cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
-+ old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-+ old &= ~EXT_FUNC_CTL_EXTREGENBL;
-+ cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
- }
-
-- cfb->func_use_count -= 1;
-+ if (cfb->func_use_count == 0)
-+ printk(KERN_ERR "disable_extregs: count = 0\n");
-+ else
-+ cfb->func_use_count -= 1;
- }
-
--/*
-- * This is the only "static" reference to the internal data structures
-- * of this driver. It is here solely at the moment to support the other
-- * CyberPro modules external to this driver.
-- */
--static struct cfb_info *int_cfb_info;
-+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
-+{
-+ memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
-+}
-
- /*
- * Attach a capture/tv driver to the core CyberX0X0 driver.
-@@ -1311,164 +1400,102 @@
-
- EXPORT_SYMBOL(cyber2000fb_attach);
- EXPORT_SYMBOL(cyber2000fb_detach);
-+EXPORT_SYMBOL(cyber2000fb_enable_extregs);
-+EXPORT_SYMBOL(cyber2000fb_disable_extregs);
-+EXPORT_SYMBOL(cyber2000fb_get_fb_var);
-
- /*
- * These parameters give
- * 640x480, hsync 31.5kHz, vsync 60Hz
- */
- static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
-- refresh: 60,
-- xres: 640,
-- yres: 480,
-- pixclock: 39722,
-- left_margin: 56,
-- right_margin: 16,
-- upper_margin: 34,
-- lower_margin: 9,
-- hsync_len: 88,
-- vsync_len: 2,
-- sync: FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-- vmode: FB_VMODE_NONINTERLACED
-+ .refresh = 60,
-+ .xres = 640,
-+ .yres = 480,
-+ .pixclock = 39722,
-+ .left_margin = 56,
-+ .right_margin = 16,
-+ .upper_margin = 34,
-+ .lower_margin = 9,
-+ .hsync_len = 88,
-+ .vsync_len = 2,
-+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+ .vmode = FB_VMODE_NONINTERLACED
- };
-
-+/* static register programming for all chips */
- static char igs_regs[] __devinitdata = {
-- 0x12, 0x00, 0x13, 0x00,
-- 0x16, 0x00,
-- 0x31, 0x00, 0x32, 0x00,
-- 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
-- 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
-- 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
-- 0x70, 0x0b, 0x73, 0x30,
-- 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8
-+ EXT_CRT_IRQ, 0,
-+ EXT_CRT_TEST, 0,
-+ EXT_SYNC_CTL, 0,
-+ EXT_SEG_WRITE_PTR, 0,
-+ EXT_SEG_READ_PTR, 0,
-+ EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
-+ EXT_BIU_MISC_COP_ENABLE |
-+ EXT_BIU_MISC_COP_BFC,
-+ EXT_FUNC_CTL, 0,
-+ CURS_H_START, 0,
-+ CURS_H_START + 1, 0,
-+ CURS_H_PRESET, 0,
-+ CURS_V_START, 0,
-+ CURS_V_START + 1, 0,
-+ CURS_V_PRESET, 0,
-+ CURS_CTL, 0,
-+ EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
-+ EXT_OVERSCAN_RED, 0,
-+ EXT_OVERSCAN_GREEN, 0,
-+ EXT_OVERSCAN_BLUE, 0,
-+};
-+
-+/* specific register setting for the 2000 series */
-+static char igs_2000_regs[] __devinitdata = {
-+ /* some of these are questionable when we have a BIOS */
-+ EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
-+ EXT_MEM_CTL0_RAS_1 |
-+ EXT_MEM_CTL0_MULTCAS,
-+ EXT_HIDDEN_CTL1, 0x30,
-+ EXT_FIFO_CTL, 0x0b,
-+ EXT_FIFO_CTL + 1, 0x17,
-+ 0x76, 0x00,
-+ EXT_HIDDEN_CTL4, 0xc8
- };
-
- /*
-- * We need to wake up the CyberPro, and make sure its in linear memory
-- * mode. Unfortunately, this is specific to the platform and card that
-- * we are running on.
-- *
-- * On x86 and ARM, should we be initialising the CyberPro first via the
-- * IO registers, and then the MMIO registers to catch all cases? Can we
-- * end up in the situation where the chip is in MMIO mode, but not awake
-- * on an x86 system?
-- *
-- * Note that on the NetWinder, the firmware automatically detects the
-- * type, width and size, and leaves this in extended registers 0x71 and
-- * 0x72 for us.
-+ * Initialise the CyberPro hardware.
- */
--static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
-+static void cyberpro_init_hw(struct cfb_info *cfb)
- {
- int i;
-
-- /*
-- * Wake up the CyberPro.
-- */
--#ifdef __sparc__
--#ifdef __sparc_v9__
--#error "You loose, consult DaveM."
--#else
-- /*
-- * SPARC does not have an "outb" instruction, so we generate
-- * I/O cycles storing into a reserved memory space at
-- * physical address 0x3000000
-- */
-- {
-- unsigned char *iop;
--
-- iop = ioremap(0x3000000, 0x5000);
-- if (iop == NULL) {
-- prom_printf("iga5000: cannot map I/O\n");
-- return -ENOMEM;
-- }
--
-- writeb(0x18, iop + 0x46e8);
-- writeb(0x01, iop + 0x102);
-- writeb(0x08, iop + 0x46e8);
-- writeb(0x33, iop + 0x3ce);
-- writeb(0x01, iop + 0x3cf);
--
-- iounmap((void *)iop);
-- }
--#endif
--
-- if (at_boot) {
-- /*
-- * Use mclk from BIOS. Only read this if we're
-- * initialising this card for the first time.
-- * FIXME: what about hotplug?
-- */
-- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-- cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
-- }
--#endif
--#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
-- /*
-- * x86 and MIPS are simple, we just do regular
-- * outb's instead of cyber2000fb_writeb.
-- */
-- outb(0x18, 0x46e8);
-- outb(0x01, 0x102);
-- outb(0x08, 0x46e8);
-- outb(0x33, 0x3ce);
-- outb(0x01, 0x3cf);
--
-- if (at_boot) {
-- /*
-- * Use mclk from BIOS. Only read this if we're
-- * initialising this card for the first time.
-- * FIXME: what about hotplug?
-- */
-- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-- cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
-- }
--#endif
--#ifdef __arm__
-- cyber2000fb_writeb(0x18, 0x46e8, cfb);
-- cyber2000fb_writeb(0x01, 0x102, cfb);
-- cyber2000fb_writeb(0x08, 0x46e8, cfb);
-- cyber2000fb_writeb(0x33, 0x3ce, cfb);
-- cyber2000fb_writeb(0x01, 0x3cf, cfb);
--
-- /*
-- * MCLK on the NetWinder and the Shark is fixed at 75MHz
-- */
-- cfb->mclk_mult = 0xdb;
-- cfb->mclk_div = 0x54;
--#endif
--
-- /*
-- * Initialise the CyberPro
-- */
- for (i = 0; i < sizeof(igs_regs); i += 2)
- cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
-
-- if (at_boot) {
-+ if (cfb->id == ID_CYBERPRO_5000) {
- /*
-- * get the video RAM size and width from the VGA register.
-- * This should have been already initialised by the BIOS,
-- * but if it's garbage, claim default 1MB VRAM (woody)
-+ * On the CyberPro5XXXX, ensure that we're using the correct
-+ * PLL (5XXX's may be programmed to use an additional set of
-+ * PLLs.)
- */
-- cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
-- cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
-+ unsigned char val;
-+ cyber2000fb_writeb(0xba, 0x3ce, cfb);
-+ val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
-+ cyber2000fb_writeb(val, 0x3cf, cfb);
-+ cyber2000fb_ops.fb_pan_display = NULL; /* FIXME: panning broken */
- } else {
- /*
-- * Reprogram the MEM_CTL1 and MEM_CTL2 registers
-+ * Other supported chips (2000 series) appear to need
-+ * these registers programming
- */
-- cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
-- cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
-+ for (i = 0; i < sizeof(igs_2000_regs); i += 2)
-+ cyber2000_grphw(igs_2000_regs[i],
-+ igs_2000_regs[i+1],
-+ cfb);
- }
-
-- /*
-- * Ensure thatwe are using the correct PLL.
-- * (CyberPro 5000's may be programmed to use
-- * an additional set of PLLs.
-- */
-- cyber2000fb_writeb(0xba, 0x3ce, cfb);
-- cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
- }
-
- static struct cfb_info * __devinit
--cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
-+cyberpro_alloc_fb_info(unsigned int id, char *name)
- {
- struct cfb_info *cfb;
-
-@@ -1480,10 +1507,9 @@
-
- memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
-
-- cfb->currcon = -1;
-- cfb->dev = dev;
-+ cfb->id = id;
-
-- if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
-+ if (id == ID_CYBERPRO_5000)
- cfb->ref_ps = 40690; // 24.576 MHz
- else
- cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
-@@ -1492,7 +1518,7 @@
- cfb->divisors[1] = 2;
- cfb->divisors[2] = 4;
-
-- if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
-+ if (id == ID_CYBERPRO_2000)
- cfb->divisors[3] = 8;
- else
- cfb->divisors[3] = 6;
-@@ -1504,7 +1530,24 @@
- cfb->fb.fix.xpanstep = 0;
- cfb->fb.fix.ypanstep = 1;
- cfb->fb.fix.ywrapstep = 0;
-- cfb->fb.fix.accel = id->driver_data;
-+
-+ switch (id) {
-+ case ID_IGA_1682:
-+ cfb->fb.fix.accel = 0;
-+ break;
-+
-+ case ID_CYBERPRO_2000:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
-+ break;
-+
-+ case ID_CYBERPRO_2010:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
-+ break;
-+
-+ case ID_CYBERPRO_5000:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
-+ break;
-+ }
-
- cfb->fb.var.nonstd = 0;
- cfb->fb.var.activate = FB_ACTIVATE_NOW;
-@@ -1569,55 +1612,46 @@
- return 0;
- }
-
--static int __devinit
--cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
-+/*
-+ * The CyberPro chips can be placed on many different bus types.
-+ * This probe function is common to all bus types. The bus-specific
-+ * probe function is expected to have:
-+ * - enabled access to the linear memory region
-+ * - memory mapped access to the registers
-+ * - initialised mem_ctl1 and mem_ctl2 appropriately.
-+ */
-+static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
- {
-- struct cfb_info *cfb;
-- u_int h_sync, v_sync;
- u_long smem_size;
-- char name[16];
-+ u_int h_sync, v_sync;
- int err;
-
-- sprintf(name, "CyberPro%4X", id->device);
--
-- err = pci_enable_device(dev);
-- if (err)
-- return err;
--
-- err = pci_request_regions(dev, name);
-- if (err)
-- return err;
--
-- err = -ENOMEM;
-- cfb = cyberpro_alloc_fb_info(dev, id, name);
-- if (!cfb)
-- goto failed_release;
--
-- cfb->region = ioremap(pci_resource_start(dev, 0),
-- pci_resource_len(dev, 0));
-- if (!cfb->region)
-- goto failed_ioremap;
--
-- cfb->regs = cfb->region + MMIO_OFFSET;
-+ cyberpro_init_hw(cfb);
-
-- cyberpro_init_hw(cfb, 1);
-+ /*
-+ * Get the video RAM size and width from the VGA register.
-+ * This should have been already initialised by the BIOS,
-+ * but if it's garbage, claim default 1MB VRAM (woody)
-+ */
-+ cfb->mem_ctl0 = cyber2000_grphr(EXT_MEM_CTL0, cfb);
-+ cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
-+ cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
-
-+ /*
-+ * Determine the size of the memory.
-+ */
- switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
- case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
- case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
-+ case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
- default: smem_size = 0x00100000; break;
- }
-
-- /*
-- * Hmm, we _need_ a portable way of finding the address for
-- * the remap stuff, both for mmio and for smem.
-- */
-- cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-- cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-- cfb->fb.fix.mmio_len = MMIO_SIZE;
- cfb->fb.fix.smem_len = smem_size;
-+ cfb->fb.fix.mmio_len = MMIO_SIZE;
- cfb->fb.screen_base = cfb->region;
-
-+ err = -EINVAL;
- if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
- &cyber2000fb_default_mode, 8)) {
- printk("%s: no valid mode found\n", cfb->fb.fix.id);
-@@ -1644,13 +1678,181 @@
- v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
- cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
-
-- printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-+ printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
- cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
- cfb->fb.var.xres, cfb->fb.var.yres,
- h_sync / 1000, h_sync % 1000, v_sync);
-
- err = register_framebuffer(&cfb->fb);
-- if (err < 0)
-+
-+failed:
-+ return err;
-+}
-+
-+static void cyberpro_common_resume(struct cfb_info *cfb)
-+{
-+ cyberpro_init_hw(cfb);
-+
-+ /*
-+ * Reprogram the MEM_CTL0, 1 and 2 registers
-+ */
-+ cyber2000_grphw(EXT_MEM_CTL0, cfb->mem_ctl0, cfb);
-+ cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
-+ cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
-+
-+ /*
-+ * Restore the old video mode and the palette.
-+ * We also need to tell fbcon to redraw the console.
-+ */
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+ cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+}
-+
-+
-+
-+
-+/*
-+ * PCI specific support.
-+ */
-+
-+/*
-+ * We need to wake up the CyberPro, and make sure its in linear memory
-+ * mode. Unfortunately, this is specific to the platform and card that
-+ * we are running on.
-+ *
-+ * On x86 and ARM, should we be initialising the CyberPro first via the
-+ * IO registers, and then the MMIO registers to catch all cases? Can we
-+ * end up in the situation where the chip is in MMIO mode, but not awake
-+ * on an x86 system?
-+ */
-+static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
-+{
-+ unsigned char val;
-+
-+#if defined(__sparc_v9__)
-+#error "You loose, consult DaveM."
-+#elif defined(__sparc__)
-+ /*
-+ * SPARC does not have an "outb" instruction, so we generate
-+ * I/O cycles storing into a reserved memory space at
-+ * physical address 0x3000000
-+ */
-+ unsigned char *iop;
-+
-+ iop = ioremap(0x3000000, 0x5000);
-+ if (iop == NULL) {
-+ prom_printf("iga5000: cannot map I/O\n");
-+ return -ENOMEM;
-+ }
-+
-+ writeb(0x18, iop + 0x46e8);
-+ writeb(0x01, iop + 0x102);
-+ writeb(0x08, iop + 0x46e8);
-+ writeb(EXT_BIU_MISC, iop + 0x3ce);
-+ writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
-+
-+ iounmap((void *)iop);
-+#elif defined(CONFIG_ARCH_SHARK)
-+ /*
-+ * Shark probably needs to do it this way rather than use the
-+ * IO method below. Since the CyberPro on the Shark isn't a
-+ * PCI device, we probably want to move this to a bus-specific
-+ * probe function. Do we even need to do this?
-+ */
-+ cyber2000fb_writeb(0x18, 0x46e8, cfb);
-+ cyber2000fb_writeb(0x01, 0x102, cfb);
-+ cyber2000fb_writeb(0x08, 0x46e8, cfb);
-+ cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
-+ cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
-+#else
-+ /*
-+ * Most other machine types are "normal", so
-+ * we use the standard IO-based wakeup.
-+ */
-+ outb(0x18, 0x46e8);
-+ outb(0x01, 0x102);
-+ outb(0x08, 0x46e8);
-+ outb(EXT_BIU_MISC, 0x3ce);
-+ outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
-+#endif
-+
-+ /*
-+ * Allow the CyberPro to accept PCI burst accesses
-+ */
-+ val = cyber2000_grphr(EXT_BUS_CTL, cfb);
-+ if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
-+ printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
-+
-+ val |= EXT_BUS_CTL_PCIBURST_WRITE;
-+
-+ if (cfb->id == ID_CYBERPRO_5000)
-+ val |= EXT_BUS_CTL_PCIBURST_READ;
-+
-+ cyber2000_grphw(EXT_BUS_CTL, val, cfb);
-+ }
-+
-+ return 0;
-+}
-+
-+static int __devinit
-+cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-+{
-+ struct cfb_info *cfb;
-+ char name[16];
-+ int err;
-+
-+ sprintf(name, "CyberPro%4X", id->device);
-+
-+ err = pci_enable_device(dev);
-+ if (err)
-+ return err;
-+
-+ err = pci_request_regions(dev, name);
-+ if (err)
-+ return err;
-+
-+ err = -ENOMEM;
-+ cfb = cyberpro_alloc_fb_info(id->driver_data, name);
-+ if (!cfb)
-+ goto failed_release;
-+
-+ cfb->dev = dev;
-+ cfb->region = ioremap(pci_resource_start(dev, 0),
-+ pci_resource_len(dev, 0));
-+ if (!cfb->region)
-+ goto failed_ioremap;
-+
-+ cfb->regs = cfb->region + MMIO_OFFSET;
-+ cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-+ cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-+
-+ /*
-+ * Bring up the hardware. This is expected to enable access
-+ * to the linear memory region, and allow access to the memory
-+ * mapped registers. Also, mem_ctl1 and mem_ctl2 must be
-+ * initialised.
-+ */
-+ err = cyberpro_pci_enable_mmio(cfb);
-+ if (err)
-+ goto failed;
-+
-+ /*
-+ * Use MCLK from BIOS. FIXME: what about hotplug?
-+ */
-+ cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
-+ cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
-+#ifdef __arm__
-+ if (machine_is_netwinder() || machine_is_shark()) {
-+ /*
-+ * MCLK on the NetWinder and the Shark is fixed at 75MHz
-+ */
-+ cfb->mclk_mult = 0xdb;
-+ cfb->mclk_div = 0x54;
-+ }
-+#endif
-+
-+ err = cyberpro_common_probe(cfb);
-+ if (err)
- goto failed;
-
- /*
-@@ -1672,7 +1874,7 @@
- return err;
- }
-
--static void __devexit cyberpro_remove(struct pci_dev *dev)
-+static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
- {
- struct cfb_info *cfb = pci_get_drvdata(dev);
-
-@@ -1701,7 +1903,7 @@
- }
- }
-
--static int cyberpro_suspend(struct pci_dev *dev, u32 state)
-+static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
- {
- return 0;
- }
-@@ -1709,41 +1911,44 @@
- /*
- * Re-initialise the CyberPro hardware
- */
--static int cyberpro_resume(struct pci_dev *dev)
-+static int cyberpro_pci_resume(struct pci_dev *dev)
- {
- struct cfb_info *cfb = pci_get_drvdata(dev);
-
- if (cfb) {
-- cyberpro_init_hw(cfb, 0);
--
-- /*
-- * Restore the old video mode and the palette.
-- * We also need to tell fbcon to redraw the console.
-- */
-- cfb->fb.var.activate = FB_ACTIVATE_NOW;
-- cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+ cyberpro_pci_enable_mmio(cfb);
-+ cyberpro_common_resume(cfb);
- }
-
- return 0;
- }
-
- static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
-+// Not yet
-+// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
-+// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
- { 0, }
- };
-
-+MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
-+
-+#ifndef __devexit_p
-+#define __devexit_p(x) (x)
-+#endif
-+
- static struct pci_driver cyberpro_driver = {
-- name: "CyberPro",
-- probe: cyberpro_probe,
-- remove: __devexit_p(cyberpro_remove),
-- suspend: cyberpro_suspend,
-- resume: cyberpro_resume,
-- id_table: cyberpro_pci_table
-+ .name = "CyberPro",
-+ .probe = cyberpro_pci_probe,
-+ .remove = __devexit_p(cyberpro_pci_remove),
-+ .suspend = cyberpro_pci_suspend,
-+ .resume = cyberpro_pci_resume,
-+ .id_table = cyberpro_pci_table
- };
-
- /*
-@@ -1768,5 +1973,4 @@
-
- MODULE_AUTHOR("Russell King");
- MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
--MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
- MODULE_LICENSE("GPL");
---- linux-2.4.25/drivers/video/cyber2000fb.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/drivers/video/cyber2000fb.h 2004-03-31 17:15:09.000000000 +0200
-@@ -36,24 +36,55 @@
- #define debug_printf(x...) do { } while (0)
- #endif
-
--#define PIXFORMAT_8BPP 0
--#define PIXFORMAT_16BPP 1
--#define PIXFORMAT_24BPP 2
--#define PIXFORMAT_32BPP 3
-+#define RAMDAC_RAMPWRDN 0x01
-+#define RAMDAC_DAC8BIT 0x02
-+#define RAMDAC_VREFEN 0x04
-+#define RAMDAC_BYPASS 0x10
-+#define RAMDAC_DACPWRDN 0x40
-
--#define VISUALID_256 1
--#define VISUALID_64K 2
--#define VISUALID_16M_32 3
--#define VISUALID_16M 4
--#define VISUALID_32K 6
-+#define EXT_CRT_VRTOFL 0x11
-+#define EXT_CRT_VRTOFL_LINECOMP10 0x10
-+#define EXT_CRT_VRTOFL_INTERLACE 0x20
-
--#define FUNC_CTL 0x3c
--#define FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
-+#define EXT_CRT_IRQ 0x12
-+#define EXT_CRT_IRQ_ENABLE 0x01
-+#define EXT_CRT_IRQ_ACT_HIGH 0x04
-
--#define BIU_BM_CONTROL 0x3e
--#define BIU_BM_CONTROL_ENABLE 0x01 /* enable bus-master */
--#define BIU_BM_CONTROL_BURST 0x02 /* enable burst */
--#define BIU_BM_CONTROL_BACK2BACK 0x04 /* enable back to back */
-+#define EXT_CRT_TEST 0x13
-+
-+#define EXT_SYNC_CTL 0x16
-+#define EXT_SYNC_CTL_HS_NORMAL 0x00
-+#define EXT_SYNC_CTL_HS_0 0x01
-+#define EXT_SYNC_CTL_HS_1 0x02
-+#define EXT_SYNC_CTL_HS_HSVS 0x03
-+#define EXT_SYNC_CTL_VS_NORMAL 0x00
-+#define EXT_SYNC_CTL_VS_0 0x04
-+#define EXT_SYNC_CTL_VS_1 0x08
-+#define EXT_SYNC_CTL_VS_COMP 0x0c
-+
-+#define EXT_BUS_CTL 0x30
-+#define EXT_BUS_CTL_LIN_1MB 0x00
-+#define EXT_BUS_CTL_LIN_2MB 0x01
-+#define EXT_BUS_CTL_LIN_4MB 0x02
-+#define EXT_BUS_CTL_ZEROWAIT 0x04
-+#define EXT_BUS_CTL_PCIBURST_WRITE 0x20
-+#define EXT_BUS_CTL_PCIBURST_READ 0x80 /* CyberPro 5000 only */
-+
-+#define EXT_SEG_WRITE_PTR 0x31
-+#define EXT_SEG_READ_PTR 0x32
-+#define EXT_BIU_MISC 0x33
-+#define EXT_BIU_MISC_LIN_ENABLE 0x01
-+#define EXT_BIU_MISC_COP_ENABLE 0x04
-+#define EXT_BIU_MISC_COP_BFC 0x08
-+
-+#define EXT_FUNC_CTL 0x3c
-+#define EXT_FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
-+
-+#define PCI_BM_CTL 0x3e
-+#define PCI_BM_CTL_ENABLE 0x01 /* enable bus-master */
-+#define PCI_BM_CTL_BURST 0x02 /* enable burst */
-+#define PCI_BM_CTL_BACK2BACK 0x04 /* enable back to back */
-+#define PCI_BM_CTL_DUMMY 0x08 /* insert dummy cycle */
-
- #define X_V2_VID_MEM_START 0x40
- #define X_V2_VID_SRC_WIDTH 0x43
-@@ -87,6 +118,19 @@
-
- #define K_CAP_X2_CTL1 0x49
-
-+#define CURS_H_START 0x50
-+#define CURS_H_PRESET 0x52
-+#define CURS_V_START 0x53
-+#define CURS_V_PRESET 0x55
-+#define CURS_CTL 0x56
-+
-+#define EXT_ATTRIB_CTL 0x57
-+#define EXT_ATTRIB_CTL_EXT 0x01
-+
-+#define EXT_OVERSCAN_RED 0x58
-+#define EXT_OVERSCAN_GREEN 0x59
-+#define EXT_OVERSCAN_BLUE 0x5a
-+
- #define CAP_X_START 0x60
- #define CAP_X_END 0x62
- #define CAP_Y_START 0x64
-@@ -96,46 +140,112 @@
- #define CAP_DDA_Y_INIT 0x6c
- #define CAP_DDA_Y_INC 0x6e
-
--#define MEM_CTL1 0x71
-+#define EXT_MEM_CTL0 0x70
-+#define EXT_MEM_CTL0_7CLK 0x01
-+#define EXT_MEM_CTL0_RAS_1 0x02
-+#define EXT_MEM_CTL0_RAS2CAS_1 0x04
-+#define EXT_MEM_CTL0_MULTCAS 0x08
-+#define EXT_MEM_CTL0_ASYM 0x10
-+#define EXT_MEM_CTL0_CAS1ON 0x20
-+#define EXT_MEM_CTL0_FIFOFLUSH 0x40
-+#define EXT_MEM_CTL0_SEQRESET 0x80
-
--#define MEM_CTL2 0x72
-+#define EXT_MEM_CTL1 0x71
-+#define EXT_MEM_CTL1_PAR 0x00
-+#define EXT_MEM_CTL1_SERPAR 0x01
-+#define EXT_MEM_CTL1_SER 0x03
-+#define EXT_MEM_CTL1_SYNC 0x04
-+#define EXT_MEM_CTL1_VRAM 0x08
-+#define EXT_MEM_CTL1_4K_REFRESH 0x10
-+#define EXT_MEM_CTL1_256Kx4 0x00
-+#define EXT_MEM_CTL1_512Kx8 0x40
-+#define EXT_MEM_CTL1_1Mx16 0x60
-+
-+#define EXT_MEM_CTL2 0x72
-+#define MEM_CTL2_SIZE_1MB 0x00
- #define MEM_CTL2_SIZE_2MB 0x01
- #define MEM_CTL2_SIZE_4MB 0x02
- #define MEM_CTL2_SIZE_MASK 0x03
- #define MEM_CTL2_64BIT 0x04
-
-+#define EXT_HIDDEN_CTL1 0x73
-+
- #define EXT_FIFO_CTL 0x74
-
-+#define EXT_SEQ_MISC 0x77
-+#define EXT_SEQ_MISC_8 0x01
-+#define EXT_SEQ_MISC_16_RGB565 0x02
-+#define EXT_SEQ_MISC_32 0x03
-+#define EXT_SEQ_MISC_24_RGB888 0x04
-+#define EXT_SEQ_MISC_16_RGB555 0x06
-+#define EXT_SEQ_MISC_8_RGB332 0x09
-+#define EXT_SEQ_MISC_16_RGB444 0x0a
-+
-+#define EXT_HIDDEN_CTL4 0x7a
-+
-+#define CURS_MEM_START 0x7e /* bits 23..12 */
-+
- #define CAP_PIP_X_START 0x80
- #define CAP_PIP_X_END 0x82
- #define CAP_PIP_Y_START 0x84
- #define CAP_PIP_Y_END 0x86
-
--#define CAP_NEW_CTL1 0x88
-+#define EXT_CAP_CTL1 0x88
-
--#define CAP_NEW_CTL2 0x89
-+#define EXT_CAP_CTL2 0x89
-+#define EXT_CAP_CTL2_ODDFRAMEIRQ 0x01
-+#define EXT_CAP_CTL2_ANYFRAMEIRQ 0x02
-
- #define BM_CTRL0 0x9c
- #define BM_CTRL1 0x9d
-
--#define CAP_MODE1 0xa4
--#define CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
--#define CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
--#define CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
--#define CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
--#define CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
--#define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
--#define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
-+#define EXT_CAP_MODE1 0xa4
-+#define EXT_CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
-+#define EXT_CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
-+#define EXT_CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
-+#define EXT_CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
-+#define EXT_CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
-+#define EXT_CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
-+#define EXT_CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
-
--#define DCLK_MULT 0xb0
--#define DCLK_DIV 0xb1
--#define DCLK_DIV_VFSEL 0x20
--#define MCLK_MULT 0xb2
--#define MCLK_DIV 0xb3
-+#define EXT_CAP_MODE2 0xa5
-+#define EXT_CAP_MODE2_CCIRINVOE 0x01
-+#define EXT_CAP_MODE2_CCIRINVVGT 0x02
-+#define EXT_CAP_MODE2_CCIRINVHGT 0x04
-+#define EXT_CAP_MODE2_CCIRINVDG 0x08
-+#define EXT_CAP_MODE2_DATEND 0x10
-+#define EXT_CAP_MODE2_CCIRDGH 0x20
-+#define EXT_CAP_MODE2_FIXSONY 0x40
-+#define EXT_CAP_MODE2_SYNCFREEZE 0x80
-
--#define CAP_MODE2 0xa5
-+#define EXT_TV_CTL 0xae
-
--#define Y_TV_CTL 0xae
-+#define EXT_DCLK_MULT 0xb0
-+#define EXT_DCLK_DIV 0xb1
-+#define EXT_DCLK_DIV_VFSEL 0x20
-+#define EXT_MCLK_MULT 0xb2
-+#define EXT_MCLK_DIV 0xb3
-+
-+#define EXT_LATCH1 0xb5
-+#define EXT_LATCH1_VAFC_EN 0x01 /* enable VAFC */
-+
-+#define EXT_FEATURE 0xb7
-+#define EXT_FEATURE_BUS_MASK 0x07 /* host bus mask */
-+#define EXT_FEATURE_BUS_PCI 0x00
-+#define EXT_FEATURE_BUS_VL_STD 0x04
-+#define EXT_FEATURE_BUS_VL_LINEAR 0x05
-+#define EXT_FEATURE_1682 0x20 /* IGS 1682 compatibility */
-+
-+#define EXT_LATCH2 0xb6
-+#define EXT_LATCH2_I2C_CLKEN 0x10
-+#define EXT_LATCH2_I2C_CLK 0x20
-+#define EXT_LATCH2_I2C_DATEN 0x40
-+#define EXT_LATCH2_I2C_DAT 0x80
-+
-+#define EXT_XT_CTL 0xbe
-+#define EXT_XT_CAP16 0x04
-+#define EXT_XT_LINEARFB 0x08
-+#define EXT_XT_PAL 0x10
-
- #define EXT_MEM_START 0xc0 /* ext start address 21 bits */
- #define HOR_PHASE_SHIFT 0xc2 /* high 3 bits */
-@@ -160,25 +270,37 @@
- #define EXT_VID_FMT_RGB565 0x02
- #define EXT_VID_FMT_RGB888_24 0x03
- #define EXT_VID_FMT_RGB888_32 0x04
-+#define EXT_VID_FMT_RGB8 0x05
-+#define EXT_VID_FMT_RGB4444 0x06
-+#define EXT_VID_FMT_RGB8T 0x07
- #define EXT_VID_FMT_DUP_PIX_ZOON 0x08 /* duplicate pixel zoom */
- #define EXT_VID_FMT_MOD_3RD_PIX 0x20 /* modify 3rd duplicated pixel */
- #define EXT_VID_FMT_DBL_H_PIX 0x40 /* double horiz pixels */
--#define EXT_VID_FMT_UV128 0x80 /* UV data offset by 128 */
-+#define EXT_VID_FMT_YUV128 0x80 /* YUV data offset by 128 */
-
- #define EXT_VID_DISP_CTL1 0xdc
- #define EXT_VID_DISP_CTL1_INTRAM 0x01 /* video pixels go to internal RAM */
- #define EXT_VID_DISP_CTL1_IGNORE_CCOMP 0x02 /* ignore colour compare registers */
- #define EXT_VID_DISP_CTL1_NOCLIP 0x04 /* do not clip to 16235,16240 */
- #define EXT_VID_DISP_CTL1_UV_AVG 0x08 /* U/V data is averaged */
--#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 */
--#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* vertical interpolation off */
-+#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 (if YUV128 set) */
-+#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* disable vertical interpolation */
- #define EXT_VID_DISP_CTL1_FULL_WIN 0x40 /* video out window full */
- #define EXT_VID_DISP_CTL1_ENABLE_WINDOW 0x80 /* enable video window */
-
- #define EXT_VID_FIFO_CTL1 0xdd
-+#define EXT_VID_FIFO_CTL1_OE_HIGH 0x02
-+#define EXT_VID_FIFO_CTL1_INTERLEAVE 0x04 /* enable interleaved memory read */
-+
-+#define EXT_ROM_UCB4GH 0xe5
-+#define EXT_ROM_UCB4GH_FREEZE 0x02 /* capture frozen */
-+#define EXT_ROM_UCB4GH_ODDFRAME 0x04 /* 1 = odd frame captured */
-+#define EXT_ROM_UCB4GH_1HL 0x08 /* first horizonal line after VGT falling edge */
-+#define EXT_ROM_UCB4GH_ODD 0x10 /* odd frame indicator */
-+#define EXT_ROM_UCB4GH_INTSTAT 0x20 /* video interrupt */
-
- #define VFAC_CTL1 0xe8
--#define VFAC_CTL1_CAPTURE 0x01 /* capture enable */
-+#define VFAC_CTL1_CAPTURE 0x01 /* capture enable (only when VSYNC high)*/
- #define VFAC_CTL1_VFAC_ENABLE 0x02 /* vfac enable */
- #define VFAC_CTL1_FREEZE_CAPTURE 0x04 /* freeze capture */
- #define VFAC_CTL1_FREEZE_CAPTURE_SYNC 0x08 /* sync freeze capture */
-@@ -197,6 +319,13 @@
- #define VFAC_CTL2_INVERT_OVSYNC 0x80 /* invert other vsync input */
-
- #define VFAC_CTL3 0xea
-+#define VFAC_CTL3_CAP_LARGE_FIFO 0x01 /* large capture fifo */
-+#define VFAC_CTL3_CAP_INTERLACE 0x02 /* capture odd and even fields */
-+#define VFAC_CTL3_CAP_HOLD_4NS 0x00 /* hold capture data for 4ns */
-+#define VFAC_CTL3_CAP_HOLD_2NS 0x04 /* hold capture data for 2ns */
-+#define VFAC_CTL3_CAP_HOLD_6NS 0x08 /* hold capture data for 6ns */
-+#define VFAC_CTL3_CAP_HOLD_0NS 0x0c /* hold capture data for 0ns */
-+#define VFAC_CTL3_CHROMAKEY 0x20 /* capture data will be chromakeyed */
- #define VFAC_CTL3_CAP_IRQ 0x40 /* enable capture interrupt */
-
- #define CAP_MEM_START 0xeb /* 18 bits */
-@@ -235,26 +364,98 @@
- #define BM_COUNT 0xbc090 /* read-only */
-
- /*
-- * Graphics Co-processor
-+ * TV registers
- */
--#define CO_CMD_L_PATTERN_FGCOL 0x8000
--#define CO_CMD_L_INC_LEFT 0x0004
--#define CO_CMD_L_INC_UP 0x0002
--
--#define CO_CMD_H_SRC_PIXMAP 0x2000
--#define CO_CMD_H_BLITTER 0x0800
-+#define TV_VBLANK_EVEN_START 0xbe43c
-+#define TV_VBLANK_EVEN_END 0xbe440
-+#define TV_VBLANK_ODD_START 0xbe444
-+#define TV_VBLANK_ODD_END 0xbe448
-+#define TV_SYNC_YGAIN 0xbe44c
-+#define TV_UV_GAIN 0xbe450
-+#define TV_PED_UVDET 0xbe454
-+#define TV_UV_BURST_AMP 0xbe458
-+#define TV_HSYNC_START 0xbe45c
-+#define TV_HSYNC_END 0xbe460
-+#define TV_Y_DELAY1 0xbe464
-+#define TV_Y_DELAY2 0xbe468
-+#define TV_UV_DELAY1 0xbe46c
-+#define TV_BURST_START 0xbe470
-+#define TV_BURST_END 0xbe474
-+#define TV_HBLANK_START 0xbe478
-+#define TV_HBLANK_END 0xbe47c
-+#define TV_PED_EVEN_START 0xbe480
-+#define TV_PED_EVEN_END 0xbe484
-+#define TV_PED_ODD_START 0xbe488
-+#define TV_PED_ODD_END 0xbe48c
-+#define TV_VSYNC_EVEN_START 0xbe490
-+#define TV_VSYNC_EVEN_END 0xbe494
-+#define TV_VSYNC_ODD_START 0xbe498
-+#define TV_VSYNC_ODD_END 0xbe49c
-+#define TV_SCFL 0xbe4a0
-+#define TV_SCFH 0xbe4a4
-+#define TV_SCP 0xbe4a8
-+#define TV_DELAYBYPASS 0xbe4b4
-+#define TV_EQL_END 0xbe4bc
-+#define TV_SERR_START 0xbe4c0
-+#define TV_SERR_END 0xbe4c4
-+#define TV_CTL 0xbe4dc /* reflects a previous register- MVFCLR, MVPCLR etc P241*/
-+#define TV_VSYNC_VGA_HS 0xbe4e8
-+#define TV_FLICK_XMIN 0xbe514
-+#define TV_FLICK_XMAX 0xbe518
-+#define TV_FLICK_YMIN 0xbe51c
-+#define TV_FLICK_YMAX 0xbe520
-
-+/*
-+ * Graphics Co-processor
-+ */
- #define CO_REG_CONTROL 0xbf011
-+#define CO_CTRL_BUSY 0x80
-+#define CO_CTRL_CMDFULL 0x04
-+#define CO_CTRL_FIFOEMPTY 0x02
-+#define CO_CTRL_READY 0x01
-+
- #define CO_REG_SRC_WIDTH 0xbf018
--#define CO_REG_PIX_FORMAT 0xbf01c
--#define CO_REG_FORE_MIX 0xbf048
--#define CO_REG_FOREGROUND 0xbf058
--#define CO_REG_WIDTH 0xbf060
--#define CO_REG_HEIGHT 0xbf062
-+#define CO_REG_PIXFMT 0xbf01c
-+#define CO_PIXFMT_32BPP 0x03
-+#define CO_PIXFMT_24BPP 0x02
-+#define CO_PIXFMT_16BPP 0x01
-+#define CO_PIXFMT_8BPP 0x00
-+
-+#define CO_REG_FGMIX 0xbf048
-+#define CO_FG_MIX_ZERO 0x00
-+#define CO_FG_MIX_SRC_AND_DST 0x01
-+#define CO_FG_MIX_SRC_AND_NDST 0x02
-+#define CO_FG_MIX_SRC 0x03
-+#define CO_FG_MIX_NSRC_AND_DST 0x04
-+#define CO_FG_MIX_DST 0x05
-+#define CO_FG_MIX_SRC_XOR_DST 0x06
-+#define CO_FG_MIX_SRC_OR_DST 0x07
-+#define CO_FG_MIX_NSRC_AND_NDST 0x08
-+#define CO_FG_MIX_SRC_XOR_NDST 0x09
-+#define CO_FG_MIX_NDST 0x0a
-+#define CO_FG_MIX_SRC_OR_NDST 0x0b
-+#define CO_FG_MIX_NSRC 0x0c
-+#define CO_FG_MIX_NSRC_OR_DST 0x0d
-+#define CO_FG_MIX_NSRC_OR_NDST 0x0e
-+#define CO_FG_MIX_ONES 0x0f
-+
-+#define CO_REG_FGCOLOUR 0xbf058
-+#define CO_REG_BGCOLOUR 0xbf05c
-+#define CO_REG_PIXWIDTH 0xbf060
-+#define CO_REG_PIXHEIGHT 0xbf062
- #define CO_REG_X_PHASE 0xbf078
- #define CO_REG_CMD_L 0xbf07c
-+#define CO_CMD_L_PATTERN_FGCOL 0x8000
-+#define CO_CMD_L_INC_LEFT 0x0004
-+#define CO_CMD_L_INC_UP 0x0002
-+
- #define CO_REG_CMD_H 0xbf07e
--#define CO_REG_SRC_PTR 0xbf170
-+#define CO_CMD_H_BGSRCMAP 0x8000 /* otherwise bg colour */
-+#define CO_CMD_H_FGSRCMAP 0x2000 /* otherwise fg colour */
-+#define CO_CMD_H_BLITTER 0x0800
-+
-+#define CO_REG_SRC1_PTR 0xbf170
-+#define CO_REG_SRC2_PTR 0xbf174
- #define CO_REG_DEST_PTR 0xbf178
- #define CO_REG_DEST_WIDTH 0xbf218
-
-@@ -269,6 +470,7 @@
- char *fb;
- char dev_name[32];
- unsigned int fb_size;
-+ unsigned int chip_id;
-
- /*
- * The following is a pointer to be passed into the
-@@ -288,10 +490,19 @@
- void (*disable_extregs)(struct cfb_info *);
- };
-
-+#define ID_IGA_1682 0
-+#define ID_CYBERPRO_2000 1
-+#define ID_CYBERPRO_2010 2
-+#define ID_CYBERPRO_5000 3
-+
-+struct fb_var_screeninfo;
-+
- /*
- * Note! Writing to the Cyber20x0 registers from an interrupt
- * routine is definitely a bad idea atm.
- */
- int cyber2000fb_attach(struct cyberpro_info *info, int idx);
- void cyber2000fb_detach(int idx);
--
-+void cyber2000fb_enable_extregs(struct cfb_info *cfb);
-+void cyber2000fb_disable_extregs(struct cfb_info *cfb);
-+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/dbmx1fb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,2002 @@
-+/******************************************************************************
-+ Copyright (C) 2002 Motorola GSG-China
-+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License
-+ as published by the Free Software Foundation; either version 2
-+ of the License, or (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+*******************************************************************************/
-+/*****************************************************************************
-+ * File Name: dbmx1fb.c
-+ *
-+ * Progammers: Chen Ning, Zhang Juan
-+ *
-+ * Date of Creations: 10 DEC,2001
-+ *
-+ * Synopsis:
-+ *
-+ * Descirption: DB-MX1 LCD controller Linux frame buffer driver
-+ * This file is subject to the terms and conditions of the
-+ * GNU General Public License. See the file COPYING in the main
-+ * directory of this archive for more details.
-+ *
-+ * Modification History:
-+ * 10 DEC, 2001, initialization version, frame work for frame buffer driver
-+ *
-+*******************************************************************************/
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/tty.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/fb.h>
-+#include <linux/delay.h>
-+#include <linux/wrapper.h>
-+#include <linux/selection.h>
-+#include <linux/console.h>
-+#include <linux/kd.h>
-+#include <linux/vt_kern.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+#include <asm/proc/pgtable.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-mfb.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb8.h>
-+#include <video/fbcon-cfb16.h>
-+
-+#include "asm/arch/hardware.h"
-+#include "asm/arch/platform.h"
-+#include "asm/arch/memory.h"
-+
-+#include "dbmx1fb.h"
-+
-+#undef SUP_TTY0
-+
-+#define LCD_PM
-+#ifdef LCD_PM
-+#include <linux/pm.h>
-+struct pm_dev *pm;
-+#endif
-+
-+// PLAM - make sure fbmem.c also has this defined for full screen frame
-+// buffer support in SDRAM
-+#define FULL_SCREEN
-+
-+#undef HARDWARE_CURSOR
-+// #undef HARDWARE_CURSOR
-+#undef DEBUG
-+
-+
-+/********************************************************************************/
-+#ifdef DEBUG
-+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-+#define FUNC_START DPRINTK(KERN_ERR"start\n");
-+#define FUNC_END DPRINTK(KERN_ERR"end\n");
-+#else
-+# define DPRINTK(fmt, args...)
-+#define FUNC_START
-+#define FUNC_END
-+#endif
-+
-+#define _IO_ADDRESS(r) ((r)+0xf0000000)
-+unsigned int READREG(unsigned int r)
-+{
-+ volatile unsigned int * reg;
-+ reg = (volatile unsigned int*) _IO_ADDRESS(r);
-+ return *reg;
-+}
-+void WRITEREG(unsigned int r, unsigned int val)
-+{
-+ volatile unsigned int *reg;
-+ reg = (volatile unsigned int*) _IO_ADDRESS(r);
-+ *reg = val;
-+ return;
-+}
-+
-+#define FONT_DATA ((unsigned char *)font->data)
-+struct fbcon_font_desc *font;
-+
-+/* Local LCD controller parameters */
-+struct dbmx1fb_par{
-+ u_char *screen_start_address; /* Screen Start Address */
-+ u_char *v_screen_start_address;/* Virtul Screen Start Address */
-+ unsigned long screen_memory_size; /* screen memory size */
-+ unsigned int palette_size;
-+ unsigned int max_xres;
-+ unsigned int max_yres;
-+ unsigned int xres;
-+ unsigned int yres;
-+ unsigned int xres_virtual;
-+ unsigned int yres_virtual;
-+ unsigned int max_bpp;
-+ unsigned int bits_per_pixel;
-+ unsigned int currcon;
-+ unsigned int visual;
-+ unsigned int TFT :1;
-+ unsigned int color :1 ;
-+ unsigned int sharp :1 ;
-+
-+ unsigned short cfb16[16];
-+};
-+
-+#ifdef HARDWARE_CURSOR
-+/* hardware cursor parameters */
-+struct dbmx1fb_cursor{
-+ // int enable;
-+ int startx;
-+ int starty;
-+ int blinkenable;
-+ int blink_rate;
-+ int width;
-+ int height;
-+ int color[3];
-+ int state;
-+};
-+
-+/* Frame buffer of LCD information */
-+struct dbmx1fb_info{
-+ struct display_switch dispsw;
-+ struct dbmx1fb_cursor cursor;
-+};
-+#endif // HARDWARE_CURSOR
-+
-+static u_char* p_framebuffer_memory_address;
-+static u_char* v_framebuffer_memory_address;
-+
-+/* Fake monspecs to fill in fbinfo structure */
-+static struct fb_monspecs monspecs __initdata = {
-+ 30000, 70000, 50, 65, 0 /* Generic */
-+};
-+
-+/* color map initial */
-+static unsigned short __attribute__((unused)) color4map[16] = {
-+ 0x0000, 0x000f, 0x00f0, 0x0f2a, 0x0f00, 0x0f0f, 0x0f88, 0x0ccc,
-+ 0x0888, 0x00ff, 0x00f8, 0x0f44, 0x0fa6, 0x0f22, 0x0ff0, 0x0fff
-+};
-+
-+static unsigned short gray4map[16] = {
-+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
-+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f
-+};
-+
-+static struct display global_disp; /* Initial (default) Display Settings */
-+static struct fb_info fb_info;
-+static struct fb_var_screeninfo init_var = {};
-+static struct dbmx1fb_par current_par={ };
-+
-+/* Frame buffer device API */
-+static int dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_get_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info);
-+
-+/* Interface to the low level driver */
-+static int dbmx1fb_switch(int con, struct fb_info *info);
-+static void dbmx1fb_blank(int blank, struct fb_info *info);
-+static int dbmx1fb_updatevar(int con, struct fb_info *info);
-+
-+/* Internal routines */
-+static int _reserve_fb_memory(void);
-+static void _install_cmap(int con, struct fb_info *info);
-+static void _enable_lcd_controller(void);
-+static void _disable_lcd_controller(void);
-+static int _encode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par);
-+static int _decode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par);
-+
-+/* initialization routines */
-+static void __init _init_lcd_system(void);
-+static int __init _init_lcd(void);
-+static void __init _init_fbinfo(void);
-+static int __init _reserve_fb_memory(void);
-+
-+/* frame buffer ops */
-+static struct fb_ops dbmx1fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: dbmx1fb_get_fix,
-+ fb_get_var: dbmx1fb_get_var,
-+ fb_set_var: dbmx1fb_set_var,
-+ fb_get_cmap: dbmx1fb_get_cmap,
-+ fb_set_cmap: dbmx1fb_set_cmap,
-+};
-+
-+#ifdef HARDWARE_CURSOR
-+/* Hardware Cursor */
-+static void dbmx1fb_cursor(struct display *p, int mode, int x, int y);
-+static int dbmx1fb_set_font(struct display *d, int width, int height);
-+static UINT8 cursor_color_map[] = {0xf8};
-+static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state);
-+static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb);
-+static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink);
-+
-+struct display_switch dbmx1fb_cfb4 = {
-+ setup: fbcon_cfb4_setup,
-+ bmove: fbcon_cfb4_bmove,
-+ clear: fbcon_cfb4_clear,
-+ putc: fbcon_cfb4_putc,
-+ putcs: fbcon_cfb4_putcs,
-+ revc: fbcon_cfb4_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+
-+struct display_switch dbmx1fb_cfb8 = {
-+ setup: fbcon_cfb8_setup,
-+ bmove: fbcon_cfb8_bmove,
-+ clear: fbcon_cfb8_clear,
-+ putc: fbcon_cfb8_putc,
-+ putcs: fbcon_cfb8_putcs,
-+ revc: fbcon_cfb8_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+
-+struct display_switch dbmx1fb_cfb16 = {
-+ setup: fbcon_cfb16_setup,
-+ bmove: fbcon_cfb16_bmove,
-+ clear: fbcon_cfb16_clear,
-+ putc: fbcon_cfb16_putc,
-+ putcs: fbcon_cfb16_putcs,
-+ revc: fbcon_cfb16_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+#endif // HARDWARE_CURSOR
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_getcolreg()
-+ *
-+ * Input: regno : Color register ID
-+ * red : Color map red[]
-+ * green : Color map green[]
-+ * blue : Color map blue[]
-+ * transparent : Flag
-+ * info : Fb_info database
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Transfer to fb_xxx_cmap handlers as parameters to
-+ * control color registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+#define RED 0xf00
-+#define GREEN 0xf0
-+#define BLUE 0x0f
-+static int dbmx1fb_getcolreg(u_int regno, u_int *red, u_int *green,
-+ u_int *blue, u_int *trans, struct fb_info *info)
-+{
-+ unsigned int val;
-+
-+ FUNC_START;
-+
-+ if(regno >= current_par.palette_size)
-+ return 1;
-+
-+ val = READREG(DBMX1_LCD_MAPRAM+regno);
-+
-+ if((current_par.bits_per_pixel == 4)&&(!current_par.color))
-+ {
-+ *red = *green = *blue = (val & BLUE) << 4;//TODO:
-+ *trans = 0;
-+ }
-+ else
-+ {
-+ *red = (val & RED) << 4;
-+ *green = (val & GREEN) << 8;
-+ *blue = (val & BLUE) << 12;
-+ *trans = 0;
-+ }
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_setcolreg()
-+ *
-+ * Input: regno : Color register ID
-+ * red : Color map red[]
-+ * green : Color map green[]
-+ * blue : Color map blue[]
-+ * transparent : Flag
-+ * info : Fb_info database
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Transfer to fb_xxx_cmap handlers as parameters to
-+ * control color registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+ *****************************************************************************/
-+static int
-+dbmx1fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ unsigned int val=0;
-+ FUNC_START
-+ if(regno >= current_par.palette_size)
-+ return 1;
-+
-+ if((current_par.bits_per_pixel == 4)&&(!current_par.color))
-+ val = (blue & 0x00f) << 12;//TODO:
-+ else
-+ {
-+ val = (blue >> 12 ) & BLUE;
-+ val |= (green >> 8) & GREEN;
-+ val |= (red >> 4) & RED;
-+ }
-+
-+ if (regno < 16) {
-+ current_par.cfb16[regno] =
-+ regno | regno << 5 | regno << 10;
-+}
-+
-+ WRITEREG(DBMX1_LCD_MAPRAM+regno, val);
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_cmap()
-+ *
-+ * Input: cmap : Ouput data pointer
-+ * kspc : Kernel space flag
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Data is copied from hardware or local or system DISPAY,
-+ * and copied to cmap.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err = 0;
-+
-+ FUNC_START;
-+ DPRINTK("current_par.visual=%d\n", current_par.visual);
-+ if (con == current_par.currcon)
-+ err = fb_get_cmap(cmap, kspc, dbmx1fb_getcolreg, info);
-+ else if (fb_display[con].cmap.len)
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ fb_copy_cmap(fb_default_cmap(current_par.palette_size),
-+ cmap, kspc ? 0 : 2);
-+ FUNC_END;
-+ return err;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_cmap()
-+ *
-+ * Input: cmap : Ouput data pointer
-+ * kspc : Kernel space flag
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Copy data from cmap and copy to DISPLAY. If DISPLAy has no cmap,
-+ * allocate memory for it. If DISPLAY is current console and visible,
-+ * then hardware color map shall be set.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ int err = 0;
-+
-+ FUNC_START;
-+ DPRINTK("current_par.visual=%d\n", current_par.visual);
-+ if (!fb_display[con].cmap.len)
-+ err = fb_alloc_cmap(&fb_display[con].cmap,
-+ current_par.palette_size, 0);
-+
-+ if (!err) {
-+ if (con == current_par.currcon)
-+ err = fb_set_cmap(cmap, kspc, dbmx1fb_setcolreg,
-+ info);
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ }
-+ FUNC_END;
-+ return err;
-+}
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_var()
-+ *
-+ * Input: var : Iuput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: _encode_var()
-+ *
-+ * Description: Get color map from current, or global display[console]
-+ * used by ioctl
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ if (con == -1) {
-+ _encode_var(var, &current_par);
-+ } else
-+ *var = fb_display[con].var;
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_updatevar()
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Fill in display switch with LCD information,
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int dbmx1fb_updatevar(int con, struct fb_info *info)
-+{
-+ DPRINTK("entered\n");
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_dispsw()
-+ *
-+ * Input: display : Iuput data pointer
-+ * dbmx1fb_info : Frame buffer of LCD information
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Fill in display switch with LCD information,
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void dbmx1fb_set_dispsw(struct display *disp
-+#ifdef HARDWARE_CURSOR
-+ ,struct dbmx1fb_info *info
-+#endif
-+ )
-+{
-+ FUNC_START;
-+ switch (disp->var.bits_per_pixel) {
-+#ifdef HARDWARE_CURSOR
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ info->dispsw = dbmx1fb_cfb4;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ info->dispsw = dbmx1fb_cfb8;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ info->dispsw = dbmx1fb_cfb16;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = current_par.cfb16;
-+ break;
-+#endif
-+#else //!HARDWARE_CURSOR
-+ /* first step disable the hardware cursor */
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ disp->dispsw = &fbcon_cfb4;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ disp->dispsw = &fbcon_cfb8;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ disp->dispsw = &fbcon_cfb16;
-+ disp->dispsw_data = current_par.cfb16;
-+ break;
-+#endif
-+
-+#endif // HARDWARE_CURSOR
-+ default:
-+ disp->dispsw = &fbcon_dummy;
-+ disp->dispsw_data = NULL;
-+ }
-+#ifdef HARDWARE_CURSOR
-+ if (&info->cursor)
-+ {
-+ info->dispsw.cursor = dbmx1fb_cursor;
-+ info->dispsw.set_font = dbmx1fb_set_font;
-+ }
-+#endif // HARDWARE_CURSOR
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_var()
-+ *
-+ * Input: var : Iuput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: dbmx1fb_decode_var()
-+ * dbmx1fb_encode_var()
-+ * dbmx1fb_set_dispsw()
-+ *
-+ * Description: set current_par by var, also set display data, specially the console
-+ * related fileops, then enable the lcd controller, and set cmap to
-+ * hardware.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ struct display *display;
-+ int err, chgvar = 0;
-+ struct dbmx1fb_par par;
-+
-+ FUNC_START;
-+ if (con >= 0)
-+ display = &fb_display[con]; /* Display settings for console */
-+ else
-+ display = &global_disp; /* Default display settings */
-+
-+ /* Decode var contents into a par structure, adjusting any */
-+ /* out of range values. */
-+ if ((err = _decode_var(var, &par))){
-+ DPRINTK("decode var error!");
-+ return err;
-+ }
-+
-+ // Store adjusted par values into var structure
-+ _encode_var(var, &par);
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
-+ ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
-+ return -EINVAL;
-+
-+ if (con >= 0) {
-+ if ((display->var.xres != var->xres) ||
-+ (display->var.yres != var->yres) ||
-+ (display->var.xres_virtual != var->xres_virtual) ||
-+ (display->var.yres_virtual != var->yres_virtual) ||
-+ (display->var.sync != var->sync) ||
-+ (display->var.bits_per_pixel != var->bits_per_pixel) ||
-+ (memcmp(&display->var.red, &var->red, sizeof(var->red))) ||
-+ (memcmp(&display->var.green, &var->green, sizeof(var->green)
-+ )) ||
-+ (memcmp(&display->var.blue, &var->blue, sizeof(var->blue))))
-+ chgvar = 1;
-+ }
-+
-+ display->var = *var;
-+ display->screen_base = par.v_screen_start_address;
-+ display->visual = par.visual;
-+ display->type = FB_TYPE_PACKED_PIXELS;
-+ display->type_aux = 0;
-+ display->ypanstep = 0;
-+ display->ywrapstep = 0;
-+ display->line_length =
-+ display->next_line = (var->xres * 16) / 8;
-+
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ dbmx1fb_set_dispsw(display
-+#ifdef HARDWARE_CURSOR
-+ , (struct dbmx1fb_info *)info
-+#endif // HARDWARE_CURSOR
-+ );
-+
-+ /* If the console has changed and the console has defined */
-+ /* a changevar function, call that function. */
-+ if (chgvar && info && info->changevar)
-+ info->changevar(con); // TODO:
-+
-+ /* If the current console is selected and it's not truecolor,
-+ * update the palette
-+ */
-+ if ((con == current_par.currcon) &&
-+ (current_par.visual != FB_VISUAL_TRUECOLOR)) {
-+ struct fb_cmap *cmap;
-+
-+ current_par = par; // TODO ?
-+ if (display->cmap.len)
-+ cmap = &display->cmap;
-+ else
-+ cmap = fb_default_cmap(current_par.palette_size);
-+
-+ fb_set_cmap(cmap, 1, dbmx1fb_setcolreg, info);
-+ }
-+
-+ /* If the current console is selected, activate the new var. */
-+ if (con == current_par.currcon){
-+ init_var = *var; // TODO:gcc support structure copy?
-+ _enable_lcd_controller();
-+ }
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_fix()
-+ *
-+ * Input: fix : Ouput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: get fix from display data, current_par data
-+ * used by ioctl
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ struct display *display;
-+
-+ FUNC_START;
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, DBMX1_NAME);
-+
-+ if (con >= 0)
-+ {
-+ DPRINTK("Using console specific display for con=%d\n",con);
-+ display = &fb_display[con]; /* Display settings for console */
-+ }
-+ else
-+ display = &global_disp; /* Default display settings */
-+
-+ fix->smem_start = (unsigned long)current_par.screen_start_address;
-+ fix->smem_len = current_par.screen_memory_size;
-+//printk("dbmx1fb_get_fix, pointer fix: 0x%08x, smem_len: 0x%08x\n",fix,fix->smem_len);
-+ fix->type = display->type;
-+ fix->type_aux = display->type_aux;
-+ fix->xpanstep = 0;
-+ fix->ypanstep = display->ypanstep;
-+ fix->ywrapstep = display->ywrapstep;
-+ fix->visual = display->visual;
-+ fix->line_length = display->line_length;
-+ fix->accel = FB_ACCEL_NONE;
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_inter_handler()
-+ *
-+ * Input:
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Interrupt handler
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void dbmx1fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int intsr;
-+ FUNC_START;
-+ intsr = READREG(DBMX1_LCD_INTSR); // read to clear status
-+ printk(KERN_ERR"lcd interrupt!\n");
-+ FUNC_END;
-+ // handle
-+}
-+
-+#ifdef LCD_PM
-+#define PM_OPT " [pm]"
-+#define LCD_PMST_RESUME 0
-+#define LCD_PMST_SUSPEND 1
-+static unsigned int lcd_pm_status = LCD_PMST_RESUME;
-+
-+void lcd_pm_resume(void)
-+{
-+ if(lcd_pm_status == LCD_PMST_RESUME)
-+ return;
-+ WRITEREG(0x21c21c, 0x10000); // light on
-+ WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00a9008a);
-+ lcd_pm_status = LCD_PMST_RESUME;
-+// printk(KERN_ERR"lcd resumed\n");
-+}
-+
-+void lcd_pm_suspend(void)
-+{
-+ unsigned val;
-+ if(lcd_pm_status == LCD_PMST_SUSPEND)
-+ return;
-+ val = READREG(0x20502c);
-+ val |= 0x8000;
-+ WRITEREG(0x20502c, val);
-+ //To produce enough dealy time before trun off the LCDC.
-+ for(val=0;val<=600000;val++);
-+ val = READREG(0x21c21c);
-+ val &= ~0x10000;
-+ WRITEREG(0x21c21c, val); // light off
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ lcd_pm_status = LCD_PMST_SUSPEND;
-+// printk(KERN_ERR"lcd suspended\n");
-+}
-+
-+int lcd_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ switch(rqst){
-+ case PM_RESUME:
-+ lcd_pm_resume();
-+ break;
-+ case PM_SUSPEND:
-+ lcd_pm_suspend();
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+#endif // LCD_PM
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_init()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: _init_fbinfo()
-+ * disable_irq()
-+ * enable_irq()
-+ * _init_lcd()
-+ * dbmx1fb_init_cursor()
-+ *
-+ * Description: initialization module, all of init routine's entry point
-+ * initialize fb_info, init_var, current_par
-+ * and setup interrupt, memory, lcd controller
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+int __init dbmx1fb_init(void)
-+{
-+ int ret;
-+#ifdef HARDWARE_CURSOR
-+ struct dbmx1fb_info *info;
-+#endif // HARDWARE_CURSOR
-+
-+ _init_lcd_system();
-+
-+ _init_fbinfo();
-+
-+ if ((ret = _reserve_fb_memory()) != 0){
-+ printk(KERN_ERR"failed for reserved DBMX frame buffer memory\n");
-+ return ret;
-+ }
-+
-+#if 0
-+ if (request_irq(IRQ_LCD,
-+ dbmx1fb_inter_handler,
-+ SA_INTERRUPT,
-+ DEV_NAME,
-+ NULL) != 0) {
-+ printk(KERN_ERR "dbmx1fb: failed in request_irq\n");
-+ return -EBUSY;
-+ }
-+
-+ disable_irq(IRQ_LCD);
-+#endif
-+ if (dbmx1fb_set_var(&init_var, -1, &fb_info))
-+ ; //current_par.allow_modeset = 0;
-+
-+ _init_lcd();
-+ _enable_lcd_controller();
-+
-+#ifdef HARDWARE_CURSOR
-+ info = kmalloc(sizeof(struct dbmx1fb_info), GFP_KERNEL);
-+ if(info == NULL){
-+ printk(KERN_ERR"can not kmalloc dbmx1fb_info memory\n");
-+ return -1;
-+ }
-+
-+ memset(info,0,sizeof(struct dbmx1fb_info));
-+
-+ info->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-+ info->cursor.blinkenable = 0;
-+ info->cursor.state = LCD_CURSOR_OFF;
-+ WRITEREG(DBMX1_LCD_LCXYP,0x90010001);
-+ WRITEREG(DBMX1_LCD_CURBLKCR,0x1F1F0000);
-+ WRITEREG(DBMX1_LCD_LCHCC,0x0000F800);
-+
-+ DPRINTK(KERN_ERR"LCXYP = %x\n",READREG(DBMX1_LCD_LCXYP));
-+ DPRINTK(KERN_ERR"CURBLICR = %x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ DPRINTK(KERN_ERR"LCHCC = %x\n",READREG(DBMX1_LCD_LCHCC));
-+
-+ //dbmx1fb_set_cursor(info);
-+ //info->cursor = dbmx1fb_init_cursor(info);
-+#endif // HARDWARE_CURSOR
-+
-+ register_framebuffer(&fb_info);
-+
-+#ifdef LCD_PM
-+ pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, lcd_pm_handler);
-+ printk("register LCD power management successfully.\n");
-+#endif
-+#if 0
-+ enable_irq(IRQ_LCD); // TODO:
-+#endif
-+ /* This driver cannot be unloaded at the moment */
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_setup()
-+ *
-+ * Input: info : VOID
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: basically, this routine used to parse command line parameters, which
-+ * is initialization parameters for lcd controller, such as freq, xres,
-+ * yres, and so on
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+int __init dbmx1fb_setup(char *options)
-+{
-+ FUNC_START;
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_fbinfo()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: while 16bpp is used to store a 12 bits pixels packet, but
-+ * it is not a really 16bpp system. maybe in-compatiable with
-+ * other system or GUI.There are some field in var which specify
-+ * the red/green/blue offset in a 16bit word, just little endian is
-+ * concerned
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void __init _init_fbinfo(void)
-+{
-+// Thomas Wong add this for debugging
-+// *((unsigned char *)0xF5000008) = '&';
-+
-+ FUNC_START;
-+ strcpy(fb_info.modename, DBMX1_NAME);
-+ strcpy(fb_info.fontname, "Acorn8x8");
-+
-+ fb_info.node = -1;
-+ fb_info.flags = FBINFO_FLAG_DEFAULT; // Low-level driver is not a module
-+ fb_info.fbops = &dbmx1fb_ops;
-+ fb_info.monspecs = monspecs;
-+ fb_info.disp = &global_disp;
-+ fb_info.changevar = NULL;
-+ fb_info.switch_con = dbmx1fb_switch;
-+ fb_info.updatevar = dbmx1fb_updatevar;
-+ fb_info.blank = dbmx1fb_blank;
-+
-+/*
-+ * * setup initial parameters
-+ * */
-+ memset(&init_var, 0, sizeof(init_var));
-+
-+ init_var.transp.length = 0;
-+ init_var.nonstd = 0;
-+ init_var.activate = FB_ACTIVATE_NOW;
-+ init_var.xoffset = 0;
-+ init_var.yoffset = 0;
-+ init_var.height = -1;
-+ init_var.width = -1;
-+ init_var.vmode = FB_VMODE_NONINTERLACED;
-+
-+ if (1) {
-+ current_par.max_xres = LCD_MAXX;
-+ current_par.max_yres = LCD_MAXY;
-+ current_par.max_bpp = LCD_MAX_BPP; // 12
-+ init_var.red.length = 5; // 5;
-+ init_var.green.length = 6; // 6;
-+ init_var.blue.length = 5; // 5;
-+#ifdef __LITTLE_ENDIAN
-+ init_var.red.offset = 11;
-+ init_var.green.offset = 5;
-+ init_var.blue.offset = 0;
-+#endif //__LITTLE_ENDIAN
-+ init_var.grayscale = 16; // i suppose, TODO
-+ init_var.sync = 0;
-+ init_var.pixclock = 171521; // TODO
-+ }
-+
-+ current_par.screen_start_address = NULL;
-+ current_par.v_screen_start_address = NULL;
-+ current_par.screen_memory_size = MAX_PIXEL_MEM_SIZE;
-+// Thomas Wong add this for debugging
-+//printk("_init_fbinfo, pointer to current_par: 0x%08x, screen_memory_size: 0x%08x\n", &current_par,current_par.screen_memory_size);
-+ current_par.currcon = -1; // TODO
-+
-+ init_var.xres = current_par.max_xres;
-+ init_var.yres = current_par.max_yres;
-+ init_var.xres_virtual = init_var.xres;
-+ init_var.yres_virtual = init_var.yres;
-+ init_var.bits_per_pixel = current_par.max_bpp;
-+
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_blank()
-+ *
-+ * Input: blank : Blank flag
-+ * info : Frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: _enable_lcd_controller()
-+ * _disable_lcd_controller()
-+ *
-+ * Description: blank the screen, if blank, disable lcd controller, while if no blank
-+ * set cmap and enable lcd controller
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void
-+dbmx1fb_blank(int blank, struct fb_info *info)
-+{
-+#ifdef SUP_TTY0
-+ int i;
-+
-+ FUNC_START;
-+ DPRINTK("blank=%d info->modename=%s\n", blank, info->modename);
-+ if (blank) {
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR)
-+ for (i = 0; i < current_par.palette_size; i++)
-+ ; // TODO
-+//printk("Disable LCD\n");
-+ _disable_lcd_controller();
-+ }
-+ else {
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR)
-+ dbmx1fb_set_cmap(&fb_display[current_par.currcon].cmap,
-+ 1,
-+ current_par.currcon, info);
-+//printk("Enable LCD\n");
-+ _enable_lcd_controller();
-+ }
-+ FUNC_END;
-+#endif //SUP_TTY0
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_switch()
-+ *
-+ * Input: info : Frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: Switch to another console
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int dbmx1fb_switch(int con, struct fb_info *info)
-+{
-+ FUNC_START;
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR) {
-+ struct fb_cmap *cmap;
-+ if (current_par.currcon >= 0) {
-+ // Get the colormap for the selected console
-+ cmap = &fb_display[current_par.currcon].cmap;
-+
-+ if (cmap->len)
-+ fb_get_cmap(cmap, 1, dbmx1fb_getcolreg, info);
-+ }
-+ }
-+
-+ current_par.currcon = con;
-+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
-+ dbmx1fb_set_var(&fb_display[con].var, con, info);
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _encode_par()
-+ *
-+ * Input: var : Input var data
-+ * par : LCD controller parameters
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: use current_par to set a var structure
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int _encode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par)
-+{
-+ // Don't know if really want to zero var on entry.
-+ // Look at set_var to see. If so, may need to add extra params to par
-+
-+ // memset(var, 0, sizeof(struct fb_var_screeninfo));
-+
-+ var->xres = par->xres;
-+ var->yres = par->yres;
-+ var->xres_virtual = par->xres_virtual;
-+ var->yres_virtual = par->yres_virtual;
-+
-+ var->bits_per_pixel = par->bits_per_pixel;
-+
-+ DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-+ switch(var->bits_per_pixel) {
-+ case 2:
-+ case 4:
-+ case 8:
-+ var->red.length = 4;
-+ var->green = var->red;
-+ var->blue = var->red;
-+ var->transp.length = 0;
-+ break;
-+ case 12: // This case should differ for Active/Passive mode
-+ case 16:
-+ if (1) {
-+ var->red.length = 4;
-+ var->blue.length = 4;
-+ var->green.length = 4;
-+ var->transp.length = 0;
-+#ifdef __LITTLE_ENDIAN
-+ var->red.offset = 8;
-+ var->green.offset = 4;
-+ var->blue.offset = 0;
-+ var->transp.offset = 0;
-+#endif // __LITTLE_ENDIAN
-+ }
-+ else
-+ {
-+ var->red.length = 5;
-+ var->blue.length = 5;
-+ var->green.length = 6;
-+ var->transp.length = 0;
-+ var->red.offset = 11;
-+ var->green.offset = 5;
-+ var->blue.offset = 0;
-+ var->transp.offset = 0;
-+ }
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _decode_var
-+ *
-+ * Input: var : Input var data
-+ * par : LCD controller parameters
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Get the video params out of 'var'. If a value doesn't fit,
-+ * round it up,if it's too big, return -EINVAL.
-+ *
-+ * Cautions: Round up in the following order: bits_per_pixel, xres,
-+ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
-+ * bitfields, horizontal timing, vertical timing.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int _decode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par)
-+{
-+ *par = current_par;
-+
-+ if ((par->xres = var->xres) < MIN_XRES)
-+ par->xres = MIN_XRES;
-+ if ((par->yres = var->yres) < MIN_YRES)
-+ par->yres = MIN_YRES;
-+ if (par->xres > current_par.max_xres)
-+ par->xres = current_par.max_xres;
-+ if (par->yres > current_par.max_yres)
-+ par->yres = current_par.max_yres;
-+ par->xres_virtual =
-+ var->xres_virtual < par->xres ? par->xres : var->xres_virtual;
-+ par->yres_virtual =
-+ var->yres_virtual < par->yres ? par->yres : var->yres_virtual;
-+ par->bits_per_pixel = var->bits_per_pixel;
-+
-+ switch (par->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ par->visual = FB_VISUAL_PSEUDOCOLOR;
-+ par->palette_size = 16;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ par->visual = FB_VISUAL_PSEUDOCOLOR;
-+ par->palette_size = 256;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12: // RGB 444
-+ case 16: /* RGB 565 */
-+ par->visual = FB_VISUAL_TRUECOLOR;
-+ par->palette_size = 0;
-+ break;
-+#endif
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ par->screen_start_address =(u_char*)(
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+ par->v_screen_start_address =(u_char*)(
-+ (u_long)v_framebuffer_memory_address+PAGE_SIZE);
-+
-+// Thomas Wong - try to change start address here (map to SRAM, instead of SDRAM)
-+#ifndef FULL_SCREEN
-+ par->screen_start_address =(u_char*)(0x00300000);
-+ par->v_screen_start_address =(u_char*)(0xF0300000);
-+#endif
-+
-+// par->screen_start_address =(u_char*)(0x0BE00000);
-+// par->v_screen_start_address =(u_char*)(0xFBE00000);
-+
-+// par->screen_start_address =(u_char*)(0x12000000);
-+// par->v_screen_start_address =(u_char*)(0xF2000000);
-+
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: _reserve_fb_memory()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: get data out of var structure and set related LCD controller registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int __init _reserve_fb_memory(void)
-+{
-+ u_int required_pages;
-+ u_int extra_pages;
-+ u_int order;
-+ struct page *page;
-+ char *allocated_region;
-+
-+ DPRINTK("frame buffer memory size = %x\n", (unsigned int)ALLOCATED_FB_MEM_SIZE);
-+ if (v_framebuffer_memory_address != NULL)
-+ return -EINVAL;
-+
-+ /* Find order required to allocate enough memory for framebuffer */
-+ required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT;
-+ for (order = 0 ; required_pages >> order ; order++) {;}
-+ extra_pages = (1 << order) - required_pages;
-+
-+ if ((allocated_region =
-+ (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL){
-+
-+ DPRINTK("can not allocated memory\n");
-+ return -ENOMEM;
-+ }
-+
-+
-+ v_framebuffer_memory_address = (u_char *)allocated_region +
-+ (extra_pages << PAGE_SHIFT);
-+ p_framebuffer_memory_address = (u_char *)__virt_to_phys(
-+ (u_long)v_framebuffer_memory_address);
-+#if 0
-+ printk(KERN_ERR"Frame buffer __get_free_pages vd:= %x, pd= %x",
-+ (unsigned int)v_framebuffer_memory_address,
-+ (unsigned int)p_framebuffer_memory_address);
-+#endif
-+ /* Free all pages that we don't need but were given to us because */
-+ /* __get_free_pages() works on powers of 2. */
-+ for (;extra_pages;extra_pages--)
-+ free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
-+
-+ /* Set reserved flag for fb memory to allow it to be remapped into */
-+ /* user space by the common fbmem driver using remap_page_range(). */
-+ for(page = virt_to_page(v_framebuffer_memory_address);
-+ page < virt_to_page(v_framebuffer_memory_address
-+ + ALLOCATED_FB_MEM_SIZE);
-+ page++)
-+ mem_map_reserve(page);
-+#if 0
-+ /* Remap the fb memory to a non-buffered, non-cached region */
-+ v_framebuffer_memory_address = (u_char *)__ioremap(
-+ (u_long)p_framebuffer_memory_address,
-+ ALLOCATED_FB_MEM_SIZE,
-+ L_PTE_PRESENT |
-+ L_PTE_YOUNG |
-+ L_PTE_DIRTY |
-+ L_PTE_WRITE);
-+#endif
-+ current_par.screen_start_address =(u_char*)(
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+ current_par.v_screen_start_address =(u_char*)(
-+ (u_long)v_framebuffer_memory_address+PAGE_SIZE);
-+
-+ DPRINTK("physical screen start addres: %x\n",
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+
-+#ifndef FULL_SCREEN
-+// Thomas Wong - we'll try to change the screen start address here
-+// printk("\n\rMap LCD screen to SDRAM.\n\r");
-+
-+ printk("\n\rMap LCD screen to embedded SRAM.\n\r");
-+ current_par.screen_start_address =(u_char*)(0x00300000);
-+ current_par.v_screen_start_address =(u_char*)(0xF0300000);
-+#endif
-+
-+// printk("\n\rMap LCD screen to SDRAM 0xFBE00000.\n\r");
-+// current_par.screen_start_address =(u_char*)(0x0BE00000);
-+// current_par.v_screen_start_address =(u_char*)(0xFBE00000);
-+
-+// printk("\n\rMap LCD screen to SRAM 0x12000000.\n\r");
-+// current_par.screen_start_address =(u_char*)(0x12000000);
-+// current_par.v_screen_start_address =(u_char*)(0xF2000000);
-+
-+ return (v_framebuffer_memory_address == NULL ? -EINVAL : 0);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _enable_lcd_controller()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: enable Lcd controller, setup registers,
-+ * base on current_par value
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _enable_lcd_controller(void)
-+{
-+ unsigned int val;
-+#if 0
-+ int i;
-+ val =0;
-+
-+ FUNC_START;
-+ _decode_var(&init_var, &current_par);
-+
-+ val = current_par.xres/16;
-+ val <<= 20;
-+ val += current_par.yres;
-+ WRITEREG(DBMX1_LCD_XYMAX, val);
-+
-+ val=0;
-+ val=current_par.xres_virtual /2;
-+ WRITEREG(DBMX1_LCD_VPW, val);
-+
-+ switch(current_par.bits_per_pixel ){
-+ case 4: // for gray only
-+ for(i=0; i<16; i++){
-+ WRITEREG(DBMX1_LCD_MAPRAM+i, gray4map[i]);
-+ }
-+ WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_4); // no interrupt
-+ WRITEREG(DBMX1_LCD_REFMCR, REFMCR_VAL_4);
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_4);
-+ WRITEREG(DBMX1_LCD_PWMR, PWMR_VAL);
-+ break;
-+ case 12:
-+ case 16:
-+ WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
-+
-+ break;
-+ }
-+#else
-+ val = READREG(0x21c21c);
-+ val |= 0x0010000;
-+ WRITEREG(0x21c21c, val);
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x8200);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
-+
-+ // Thomas Wong - we want 0x8A not 0x200
-+// WRITEREG(DBMX1_LCD_PWMR, 0x200);
-+// PLAM -- for rev2 (endian bit)
-+// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00A9008A);
-+// end PLAM
-+#endif
-+
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _disable_lcd_controller()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: just disable the LCD controller
-+ * disable lcd interrupt. others, i have no ideas
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _disable_lcd_controller(void)
-+{
-+ unsigned int val;
-+ val = READREG(0x21c21c);
-+ val &= ~0x0010000;
-+ WRITEREG(0x21c21c, val);
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x8200);
-+// WRITEREG(DBMX1_LCD_REFMCR, DISABLELCD_VAL);
-+ WRITEREG(0x205034, 0x0);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _install_cmap
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: set color map to hardware
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _install_cmap(int con, struct fb_info *info)
-+{
-+ if (con != current_par.currcon)
-+ return ;
-+ if (fb_display[con].cmap.len)
-+ fb_set_cmap(&fb_display[con].cmap, 1, dbmx1fb_setcolreg, info);
-+ else
-+ fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-+ 1,
-+ dbmx1fb_setcolreg,
-+ info);
-+ return ;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_lcd_system
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: initialize the gpio port C and port D with DMA enable
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void __init _init_lcd_system(void)
-+{
-+unsigned int val;
-+
-+/* Thomas Wong - we don't need DMA here
-+ // dma reset & enable
-+ val = READREG(0x209000);
-+ val |= 0x02;
-+ WRITEREG(0x209000, val);
-+ val = READREG(0x209000);
-+ val |= 0x01;
-+ WRITEREG(0x209000, val);
-+*/
-+ // gpio
-+ //clear port D for LCD signal
-+ WRITEREG(0x21c320, 0x0);
-+ WRITEREG(0x21c338, 0x0);
-+
-+ val = READREG(0x21c220);
-+ val |= 0x10000;
-+ WRITEREG(0x21c220, val);
-+ val = READREG(0x21c208);
-+ val |= 0x03;
-+ WRITEREG(0x21c208, val);
-+ val = READREG(0x21c200);
-+ val |= 0x10000;
-+ WRITEREG(0x21c200, val);
-+ val = READREG(0x21c238);
-+ val |= 0x10000;
-+ WRITEREG(0x21c238, val);
-+ val = READREG(0x21c21c);
-+ val |= 0x10000;
-+ WRITEREG(0x21c21c, val);
-+
-+}
-+
-+static void set_pclk(unsigned int fmhz)
-+{
-+ unsigned int div= 96/fmhz;
-+ unsigned int reg;
-+ reg = READREG(0x21b020);
-+ reg &= ~0xf0;
-+ WRITEREG(0x21b020, reg);
-+ reg |= ((div-1)<<4) &0xf0;
-+ WRITEREG(0x21b020, reg);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_lcd
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: _decode_var()
-+ *
-+ * Description: initialize the LCD controller, use current_par for 12bpp
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int __init _init_lcd()
-+{
-+
-+ unsigned int val, rate;
-+ int i;
-+ unsigned char * pscr;
-+ //unsigned long pclk,temp,PCLKDIV2;
-+ //unsigned long MFI,MFN,PD,MFD,tempReg,MCUPLLCLK;
-+
-+
-+ _decode_var(&init_var, &current_par);
-+
-+ // gpio begin
-+ val = READREG(0x21c21c);
-+ val &= ~0x00010000;
-+ WRITEREG(0x21c21c, val);
-+ DPRINTK(KERN_ERR"DR=%x\n", READREG(0x21c21c));
-+
-+ // LCD regs
-+ DPRINTK(KERN_ERR"write SSA by %x\n",
-+ (unsigned int)current_par.screen_start_address);
-+ WRITEREG(DBMX1_LCD_SSA, (unsigned int)current_par.screen_start_address);
-+ DPRINTK(KERN_ERR"SSA=%x\n", READREG(DBMX1_LCD_SSA));
-+
-+ val =0;
-+ val = current_par.xres/16;
-+ val = val<<20;
-+ val += current_par.yres;
-+ DPRINTK(KERN_ERR"par.x=%x, y=%x\n",
-+ current_par.xres,
-+ current_par.yres);
-+ WRITEREG(DBMX1_LCD_XYMAX, val);
-+ DPRINTK(KERN_ERR"XYMAX=%x\n", READREG(DBMX1_LCD_XYMAX));
-+
-+ val=0;
-+ val=current_par.xres_virtual/2;
-+ WRITEREG(DBMX1_LCD_VPW, val);
-+ DPRINTK(KERN_ERR"VPW=%x\n", READREG(DBMX1_LCD_VPW));
-+
-+ set_pclk(4);
-+
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PANELCFG=%x\n",
-+ READREG(DBMX1_LCD_PANELCFG));
-+
-+ WRITEREG(DBMX1_LCD_HCFG, 0x04000f06);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_HCFG=%x\n",
-+ READREG(DBMX1_LCD_HCFG));
-+
-+ WRITEREG(DBMX1_LCD_VCFG, 0x04000907);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_VCFG=%x\n",
-+ READREG(DBMX1_LCD_VCFG));
-+
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
-+ READREG(DBMX1_LCD_REFMCR));
-+
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_DMACR=%x\n",
-+ READREG(DBMX1_LCD_DMACR));
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
-+ READREG(DBMX1_LCD_PWMR));
-+
-+ // Thomas Wong - we don't want to turn it on here
-+ /*
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002)
-+ DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
-+ READREG(DBMX1_LCD_REFMCR));
-+ */
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
-+ READREG(DBMX1_LCD_PWMR));
-+
-+ // Thomas Wong
-+ WRITEREG(0x21B020, 0x000B005B);
-+// PLAM -- for rev2 (new register and endian bits)
-+ WRITEREG(DBMX1_LCD_PANELCFG, 0xF8008B42); // little endian
-+// WRITEREG(DBMX1_LCD_PANELCFG, 0xF8048B42); // big endian
-+ WRITEREG(DBMX1_LCD_LGPMR, 0x00090300);
-+// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
-+ WRITEREG (DBMX1_LCD_PWMR, 0x009A008A);
-+// end PLAM
-+
-+// PLAM -- for rev2 (new DMACR setting)
-+// WRITEREG(DBMX1_LCD_DMACR, 0x800C0002);
-+ WRITEREG(DBMX1_LCD_DMACR, 0x00040008);
-+//end PLAM
-+
-+
-+#define DMACR_VAL_12 0x800C0002
-+
-+
-+// WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_12);
-+// DPRINTK(KERN_ERR"DBMX1_LCD_INTCR=%x\n",
-+// READREG(DBMX1_LCD_INTCR));
-+
-+ // warm up LCD
-+ for(i=0;i<10000000;i++) ;
-+
-+ // gpio end
-+ val = READREG(0x21c21c);
-+ val |= 0x00010000;
-+ WRITEREG(0x21c21c, val);
-+ DPRINTK(KERN_ERR"DR=%x\n",
-+ READREG(0x21c21c));
-+#if 0
-+ // clear screen
-+ pscr = current_par.v_screen_start_address;
-+ for(i=0; i< (current_par.screen_memory_size - 2*PAGE_SIZE); i++){
-+ *pscr++ = 0xff;
-+ }
-+#endif
-+ DPRINTK(KERN_ERR"_init_lcd end \n");
-+
-+ return 0;
-+}
-+
-+#ifdef HARDWARE_CURSOR
-+
-+/*
-+ * Hardware cursor support
-+ */
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_color()
-+ *
-+ * Input: fb : frame buffer database
-+ * red : red component level in the cursor
-+ * green : green component level in the cursor
-+ * blue : blue component level in the cursor
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set color of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_color(struct dbmx1fb_info *fb, UINT8 *red, UINT8 *green, UINT8 *blue)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 color;
-+
-+ FUNC_START;
-+ c->color[0] = *red;
-+ c->color[1] = *green;
-+ c->color[2] = *blue;
-+ color = (UINT32)*red;
-+ color |= (UINT32)(*green>>5);
-+ color |= (UINT32)(*blue>>11);
-+
-+ WRITEREG(DBMX1_LCD_LCHCC, color);
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor()
-+ *
-+ * Input: fb : frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Load information of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 temp,tempReg,x,y;
-+
-+ FUNC_START;
-+ //DPRINTK(KERN_ERR"BLINK_RATE=%x\n",c->blink_rate);
-+// DPRINTK(KERN_ERR"width=%x\n",c->width);
-+// DPRINTK(KERN_ERR"height=%x\n",c->height);
-+
-+ x = c->startx << 16;
-+ if (c->state == LCD_CURSOR_ON)
-+ x |= CURSOR_ON_MASK;
-+
-+#ifdef FBCON_HAS_CFB4
-+ else if(c->state == LCD_CURSOR_REVERSED)
-+ x |= CURSOR_REVERSED_MASK;
-+ else if(c->state == LCD_CURSOR_ON_WHITE)
-+ x |= CURSOR_WHITE_MASK;
-+#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
-+ else if(c->state == LCD_CURSOR_INVERT_BGD)
-+ x |= CURSOR_INVERT_MASK;
-+ else if(c->state == LCD_CURSOR_AND_BGD)
-+ x |= CURSOR_AND_BGD_MASK;
-+ else if(c->state == LCD_CURSOR_OR_BGD)
-+ x |= CURSOR_OR_BGD_MASK;
-+ else if(c->state == LCD_CURSOR_XOR_BGD)
-+ x |= CURSOR_XOR_BGD_MASK;
-+#endif
-+ else
-+ x = c->startx;
-+
-+ y = c->starty;
-+
-+ temp = (UINT32)x | (UINT32)y;
-+ WRITEREG(DBMX1_LCD_LCXYP, temp);
-+ //DPRINTK(KERN_ERR"lcxyp=%x\n",READREG(DBMX1_LCD_LCXYP));
-+
-+ temp = (UINT32)((c->width<<8) | (c->height));
-+ tempReg = (UINT32)((temp<<16) | c->blink_rate);
-+
-+ WRITEREG(DBMX1_LCD_CURBLKCR, tempReg);
-+
-+ //c->blink_rate = 10;
-+ if (c->blinkenable)
-+ dbmx1fb_set_cursor_blink(fb,c->blink_rate);
-+ DPRINTK(KERN_ERR"CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_blink()
-+ *
-+ * Input: fb : frame buffer database
-+ * blink : input blink frequency of cursor
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set blink frequency of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ unsigned long temp,tempReg;
-+ unsigned long PCD, XMAX, YMAX, PCLKDIV2;
-+ unsigned long tempMicroPeriod;
-+
-+ FUNC_START;
-+ DPRINTK(KERN_ERR"dbmx1fb_set_cursor_blink\n");
-+
-+ if(!c){
-+ DPRINTK(KERN_ERR"dangerouts, for c == null\n");
-+ }
-+ c->blink_rate = blink;
-+
-+ tempReg = READREG(DBMX1_LCD_XYMAX);
-+ XMAX = (tempReg & XMAX_MASK) >> 20;
-+ YMAX = tempReg & YMAX_MASK;
-+ //XMAX = 240;
-+ //YMAX = 320;
-+ tempReg = READREG(PCDR);
-+ PCLKDIV2 = (tempReg & PCLKDIV2_MASK) >> 4;
-+ tempReg = READREG(DBMX1_LCD_PANELCFG);
-+ PCD = tempReg & PCD_MASK;
-+
-+ temp = (PCLKDIV2 + 1);
-+
-+ if (!blink)
-+ {
-+ /* disable the blinking cursor function when frequency is 0 */
-+ tempReg = READREG(DBMX1_LCD_CURBLKCR);
-+ tempReg &= CURSORBLINK_DIS_MASK;
-+ WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
-+ }
-+ else
-+ {
-+
-+ tempMicroPeriod = temp * XMAX * YMAX * (PCD + 1);
-+ temp = 96*10000000/(blink * tempMicroPeriod);
-+ tempReg = READREG(DBMX1_LCD_CURBLKCR);
-+ tempReg |= CURSORBLINK_EN_MASK;
-+ tempReg |= temp;
-+ WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
-+ DPRINTK(KERN_ERR"Inter_CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ }
-+
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_state()
-+ *
-+ * Input: fb : frame buffer database
-+ * state : The status of the cursor to be set. e.g.
-+ * LCD_CURSOR_OFF
-+ * LCD_CURSOR_ON
-+ * LCD_CURSOR_REVERSED
-+ * LCD_CURSOR_ON_WHITE
-+ * LCD_CURSOR_OR_BGD
-+ * LCD_CURSOR_XOR_BGD
-+ * LCD_CURSOR_AND_BGD
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set state of cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 temp;
-+
-+ FUNC_START;
-+ c->state = state;
-+ temp = READREG(DBMX1_LCD_LCXYP);
-+ temp &= CURSOR_OFF_MASK;
-+
-+ if (state == LCD_CURSOR_OFF)
-+ temp = temp;
-+ else if (state == LCD_CURSOR_ON)
-+ temp |= CURSOR_ON_MASK;
-+#ifdef FBCON_HAS_CFB4
-+ else if (state == LCD_CURSOR_REVERSED)
-+ temp |= CURSOR_REVERSED_MASK;
-+ else if (state == LCD_CURSOR_ON_WHITE)
-+ temp |= CURSOR_WHITE_MASK;
-+#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
-+ else if(state == LCD_CURSOR_INVERT_BGD)
-+ temp |= CURSOR_INVERT_MASK;
-+ else if (state == LCD_CURSOR_OR_BGD)
-+ temp |= CURSOR_OR_BGD_MASK;
-+ else if (state == LCD_CURSOR_XOR_BGD)
-+ temp |= CURSOR_XOR_BGD_MASK;
-+ else if (state == LCD_CURSOR_AND_BGD)
-+ temp |= CURSOR_AND_BGD_MASK;
-+#endif
-+ WRITEREG(DBMX1_LCD_LCXYP,temp);
-+ DPRINTK(KERN_ERR"LCDXYP=%x\n",READREG(DBMX1_LCD_LCXYP));
-+ FUNC_END;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_cursor()
-+ *
-+ * Input: fb : frame buffer database
-+ *
-+ * Value Returned: cursor : The structure of hardware cursor
-+ *
-+ * Functions Called: dbmx1fb_set_cursor()
-+ * dbmx1fb_set_cursor_state()
-+ *
-+ * Description: The entry for display switch to operate hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_cursor(struct display *p, int mode, int x, int y)
-+{
-+ struct dbmx1fb_info *fb = (struct dbmx1fb_info *)p->fb_info;
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ FUNC_START;
-+ if (c==0) return;
-+
-+
-+ x *= fontwidth(p);
-+ y *= fontheight(p);
-+
-+ c->startx = x;
-+ c->starty = y;
-+
-+ switch (mode) {
-+ case CM_ERASE:
-+ dbmx1fb_set_cursor_state(fb,LCD_CURSOR_OFF);
-+ break;
-+
-+ case CM_DRAW:
-+ case CM_MOVE:
-+ c->state = LCD_CURSOR_ON;
-+ dbmx1fb_set_cursor(fb);
-+ dbmx1fb_set_cursor_state(fb, c->state);
-+ break;
-+ }
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_font()
-+ *
-+ * Input: display : console datebase
-+ * width : The new width of cursor to be set.
-+ * height : The new height of cursor position to be set
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: dbmx1fb_set_cursor()
-+ * dbmx1fb_set_cursor_color()
-+ *
-+ * Description: Set font for cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static int dbmx1fb_set_font(struct display *d, int width, int height)
-+{
-+ struct dbmx1fb_info *fb=(struct dbmx1fb_info *)d->fb_info;
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ FUNC_START;
-+ if(!d){
-+ printk(KERN_ERR"dbmx1fb_set_font d=null\n");
-+ return -1;
-+ }
-+
-+ if (c) {
-+ if (!width || !height) {
-+ width = 16;
-+ height = 16;
-+ }
-+
-+ c->width = width;
-+ c->height = height;
-+
-+ DPRINTK(KERN_ERR"set cursor\n");
-+ dbmx1fb_set_cursor(fb);
-+ DPRINTK(KERN_ERR"set color cursor\n");
-+ dbmx1fb_set_cursor_color(fb, cursor_color_map,
-+ cursor_color_map, cursor_color_map);
-+ }else{
-+ DPRINTK(KERN_ERR"set cursor failed, cursor == null\n");
-+ }
-+
-+ FUNC_END;
-+ return 1;
-+}
-+#endif // HARDWARE_CURSOR
-+/* end of file */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/drivers/video/dbmx1fb.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,213 @@
-+/****************************************************************************
-+ *
-+ * Copyright (C) 2001, Chen Ning All Rights Reserved
-+ *
-+ * File Name: dbmx1fb.h
-+ *
-+ * Progammers: Chen Ning, Zhang Juan
-+ *
-+ * Date of Creations: 10 DEC,2001
-+ *
-+ * Synopsis:
-+ *
-+ * Descirption:
-+ *
-+ * Modification History:
-+ * 10 DEC, 2001, initialization version, frame work for frame buffer driver
-+ *
-+*******************************************************************************/
-+
-+#ifndef LCDFB_H
-+#define LCDFB_H
-+#include "asm/arch/hardware.h"
-+#include "asm/arch/platform.h"
-+
-+typedef signed char BOOLEAN;
-+typedef unsigned char UINT8; /* Unsigned 8 bit quantity */
-+typedef signed char SINT8; /* Signed 8 bit quantity */
-+typedef unsigned short UINT16; /* Unsigned 16 bit quantity */
-+typedef signed short SINT16; /* Signed 16 bit quantity */
-+typedef unsigned long UINT32; /* Unsigned 32 bit quantity */
-+typedef signed long SINT32; /* Signed 32 bit quantity */
-+
-+typedef volatile BOOLEAN VBOOLEAN;
-+typedef volatile UINT8 VUINT8; /* Unsigned 8 bit quantity */
-+typedef volatile SINT8 VSINT8; /* Signed 8 bit quantity */
-+typedef volatile UINT16 VUINT16; /* Unsigned 16 bit quantity */
-+typedef volatile SINT16 VSINT16; /* Signed 16 bit quantity */
-+typedef volatile UINT32 VUINT32; /* Unsigned 32 bit quantity */
-+typedef volatile SINT32 VSINT32; /* Signed 32 bit quantity */
-+
-+#define LCDBASE 0x00205000
-+#define LCD_REGIONSIZE 0xc00
-+
-+#define DBMX1_LCD_SSA 0x00205000
-+#define DBMX1_LCD_XYMAX 0x00205004
-+#define DBMX1_LCD_VPW 0x00205008
-+#define DBMX1_LCD_LCXYP 0x0020500c
-+#define DBMX1_LCD_CURBLKCR 0x00205010
-+#define DBMX1_LCD_LCHCC 0x00205014
-+#define DBMX1_LCD_PANELCFG 0x00205018
-+#define DBMX1_LCD_HCFG 0x0020501c
-+#define DBMX1_LCD_VCFG 0x00205020
-+#define DBMX1_LCD_POS 0x00205024
-+#define DBMX1_LCD_LGPMR 0x00205028
-+#define DBMX1_LCD_PWMR 0x0020502c
-+#define DBMX1_LCD_DMACR 0x00205030
-+#define DBMX1_LCD_REFMCR 0x00205034
-+#define DBMX1_LCD_INTCR 0x00205038
-+#define DBMX1_LCD_INTSR 0x00205040
-+#define DBMX1_LCD_MAPRAM 0x00205800
-+
-+#define MPCTL0 0x0021B004
-+#define PCDR 0X0021B020
-+
-+#define SSA DBMX1_LCD_SSA
-+#define XYMAX DBMX1_LCD_XYMAX
-+#define VPW DBMX1_LCD_VPW
-+#define LCXYP DBMX1_LCD_LCXYP
-+#define CURBLKCR DBMX1_LCD_CURBLKCR
-+#define LCHCC DBMX1_LCD_LCHCC
-+#define PANELCFG DBMX1_LCD_PANELCFG
-+#define VCFG DBMX1_LCD_VCFG
-+#define HCFG DBMX1_LCD_HCFG
-+#define POS DBMX1_LCD_POS
-+#define LGPMR DBMX1_LCD_LGPMR
-+#define PWMR DBMX1_LCD_PWMR
-+#define DMACR DBMX1_LCD_DMACR
-+#define REFMCR DBMX1_LCD_REFMCR
-+#define INTCR DBMX1_LCD_INTCR
-+#define INTSR DBMX1_LCD_INTSR
-+#define MAPRAM DBMX1_LCD_MAPRAM
-+// default value
-+#define SHARP_TFT_240x320
-+
-+#ifdef SHARP_TFT_240x320
-+#define PANELCFG_VAL_12 0xf8008b48
-+#define HCFG_VAL_12 0x04000f06
-+#define VCFG_VAL_12 0x04000907
-+#define PWMR_VAL 0x0000008a
-+#define LCD_MAXX 240
-+#define LCD_MAXY 320
-+#else //SHARP_TFT_240x320
-+
-+#define PANELCFG_VAL_12 0xf8088c6b
-+#define HCFG_VAL_12 0x04000f06
-+#define VCFG_VAL_12 0x04010c03
-+#define PWMR_VAL 0x00000200
-+#define LCD_MAXX 320
-+#define LCD_MAXY 240
-+#endif // SHARP_TFT_240x320
-+
-+#define PANELCFG_VAL_4 0x20008c09
-+#define PANELCFG_VAL_4C 0x60008c09
-+
-+#define HCFG_VAL_4 0x04000f07
-+
-+#define VCFG_VAL_4 0x04010c03
-+
-+
-+#define REFMCR_VAL_4 0x00000003
-+#define REFMCR_VAL_12 0x00000003
-+#define DISABLELCD_VAL 0x00000000
-+
-+#define DMACR_VAL_4 0x800c0003 // 12 & 3 TRIGGER
-+#define DMACR_VAL_12 0x00020008
-+
-+#define INTCR_VAL_4 0x00000000
-+#define INTCR_VAL_12 0x00000000
-+
-+#define INTSR_UDRERR 0x00000008
-+#define INTSR_ERRRESP 0x00000004
-+#define INTSR_EOF 0x00000002
-+#define INTSR_BOF 0x00000001
-+
-+#define MIN_XRES 64
-+#define MIN_YRES 64
-+
-+#define LCD_MAX_BPP 16
-+
-+#if 0
-+#define READREG(r) \
-+ inl(IO_ADDRESS(r))
-+
-+#define WRITEREG(r, val) \
-+ outl(val, IO_ADDRESS(r))
-+#else
-+#endif // 0
-+
-+#define MAX_PALETTE_NUM_ENTRIES 256
-+#define MAX_PIXEL_MEM_SIZE \
-+ ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8)
-+#define MAX_FRAMEBUFFER_MEM_SIZE \
-+ (MAX_PIXEL_MEM_SIZE + 32)
-+#define ALLOCATED_FB_MEM_SIZE \
-+ (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2))
-+
-+ // TODO:
-+#define FBCON_HAS_CFB4
-+#define FBCON_HAS_CFB8
-+#define FBCON_HAS_CFB16
-+
-+#define IRQ_LCD 12 // TODO: which irq?
-+#define DBMX1_NAME "DBMX1FB"
-+#define DEV_NAME DBMX1_NAME
-+#define MAX_PALETTE_NUM_ENTRIES 256
-+#define DEFAULT_CURSOR_BLINK_RATE (20)
-+#define CURSOR_DRAW_DELAY (2)
-+/*cursor status*/
-+#define LCD_CURSOR_OFF 0
-+#define LCD_CURSOR_ON 1
-+
-+#ifdef FBCON_HAS_CFB4
-+ #define LCD_CURSOR_REVERSED 2
-+ #define LCD_CURSOR_ON_WHITE 3
-+#elif defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16)
-+ #define LCD_CURSOR_INVERT_BGD 2
-+ #define LCD_CURSOR_AND_BGD 3
-+ #define LCD_CURSOR_OR_BGD 4
-+ #define LCD_CURSOR_XOR_BGD 5
-+#endif //FBCON_HAS_CFB4
-+
-+/* MASK use for caculating MCDUPLLCLK */
-+#define MFI_MASK 0x00003C00
-+#define MFN_MASK 0x000003FF
-+#define PD_MASK 0x3C000000
-+#define MFD_MASK 0x03FF0000
-+#define PCLKDIV2_MASK 0x000000F0
-+#define PCD_MASK 0x0000003F
-+#define XMAX_MASK 0xF3F00000
-+#define YMAX_MASK 0x000001FF
-+#define HWAIT1_MASK 0x0000FF00
-+#define HWAIT2_MASK 0x000000FF
-+#define HWIDTH_MASK 0xFC000000
-+#define PASSDIV_MASK 0x00FF0000
-+#define VWAIT1_MASK 0x0000FF00
-+#define VWAIT2_MASK 0x000000FF
-+#define VWIDTH_MASK 0xFC000000
-+#define CURSORBLINK_DIS_MASK 0x80000000
-+
-+#define DISPLAY_MODE_MASK 0x80000000
-+
-+#define MCU_FREQUENCE 32768
-+#define COLOR_MASK 0x40000000
-+
-+/* MASK use for indicating the cursor status */
-+#define CURSOR_ON_MASK 0x40000000
-+#define CURSOR_OFF_MASK 0x0FFFFFFF
-+#define MAX_CURSOR_WIDTH 31
-+#define MAX_CURSOR_HEIGHT 31
-+#define CURSORBLINK_EN_MASK 0x80000000
-+
-+#ifdef FBCON_HAS_CFB4
-+#define CURSOR_REVERSED_MASK 0x80000000
-+#define CURSOR_WHITE_MASK 0xC0000000
-+#else
-+#define CURSOR_INVERT_MASK 0x80000000
-+#define CURSOR_AND_BGD_MASK 0xC0000000
-+#define CURSOR_OR_BGD_MASK 0x50000000
-+#define CURSOR_XOR_BGD_MASK 0x90000000
-+#endif // FBCON_HAS_CFB4
-+
-+#endif //LCDFB_H
-+
---- linux-2.4.25/drivers/video/fbmem.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/drivers/video/fbmem.c 2004-03-31 17:15:09.000000000 +0200
-@@ -61,7 +61,9 @@
- extern int pm2fb_setup(char*);
- extern int pm3fb_init(void);
- extern int pm3fb_setup(char*);
-+extern int clps711xfb_init(void);
- extern int cyber2000fb_init(void);
-+extern int cyber2000fb_setup(char*);
- extern int retz3fb_init(void);
- extern int retz3fb_setup(char*);
- extern int clgenfb_init(void);
-@@ -145,6 +147,8 @@
- extern int sstfb_setup(char*);
- extern int it8181fb_init(void);
- extern int it8181fb_setup(char*);
-+extern int anakinfb_init(void);
-+extern int dbmx1fb_init(void);
-
- static struct {
- const char *name;
-@@ -170,11 +174,14 @@
- #ifdef CONFIG_FB_AMIGA
- { "amifb", amifb_init, amifb_setup },
- #endif
-+#ifdef CONFIG_FB_CLPS711X
-+ { "clps711xfb", clps711xfb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_CYBER
- { "cyber", cyberfb_init, cyberfb_setup },
- #endif
- #ifdef CONFIG_FB_CYBER2000
-- { "cyber2000", cyber2000fb_init, NULL },
-+ { "cyber2000", cyber2000fb_init, cyber2000fb_setup },
- #endif
- #ifdef CONFIG_FB_PM2
- { "pm2fb", pm2fb_init, pm2fb_setup },
-@@ -226,10 +233,10 @@
- #endif
- #ifdef CONFIG_FB_S3TRIO
- { "s3trio", s3triofb_init, NULL },
--#endif
-+#endif
- #ifdef CONFIG_FB_FM2
- { "fm2fb", fm2fb_init, fm2fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_SIS
- { "sisfb", sisfb_init, sisfb_setup },
- #endif
-@@ -242,7 +249,7 @@
-
- /*
- * Generic drivers that are used as fallbacks
-- *
-+ *
- * These depend on resource management and must be initialized
- * _after_ all other frame buffer devices that use resource
- * management!
-@@ -253,7 +260,7 @@
- #endif
- #ifdef CONFIG_FB_VESA
- { "vesa", vesafb_init, vesafb_setup },
--#endif
-+#endif
-
- /*
- * Chipset specific drivers that don't use resource management (yet)
-@@ -276,7 +283,7 @@
- #endif
- #ifdef CONFIG_FB_HGA
- { "hga", hgafb_init, hgafb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_IGA
- { "igafb", igafb_init, igafb_setup },
- #endif
-@@ -291,7 +298,7 @@
- #endif
- #ifdef CONFIG_FB_HP300
- { "hpfb", hpfb_init, NULL },
--#endif
-+#endif
- #ifdef CONFIG_FB_G364
- { "g364", g364fb_init, NULL },
- #endif
-@@ -307,6 +314,9 @@
- #ifdef CONFIG_FB_TX3912
- { "tx3912", tx3912fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_ANAKIN
-+ { "anakinfb", anakinfb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_E1355
- { "e1355fb", e1355fb_init, e1355fb_setup },
- #endif
-@@ -330,10 +340,13 @@
- #endif
- #ifdef CONFIG_FB_AU1100
- { "au1100fb", au1100fb_init, au1100fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_IT8181
- { "it8181fb", it8181fb_init, it8181fb_setup },
- #endif
-+#ifdef CONFIG_FB_DBMX1
-+ { "dbmx1fb", dbmx1fb_init, NULL },
-+#endif
-
-
- /*
-@@ -342,7 +355,7 @@
-
- #ifdef CONFIG_FB_VGA16
- { "vga16", vga16fb_init, vga16fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_STI
- { "stifb", stifb_init, stifb_setup },
- #endif
-@@ -371,7 +384,7 @@
-
- struct fb_info *registered_fb[FB_MAX];
- int num_registered_fb;
--extern int fbcon_softback_size;
-+extern int fbcon_softback_size;
-
- static int first_fb_vc;
- static int last_fb_vc = MAX_NR_CONSOLES-1;
-@@ -480,7 +493,7 @@
- }
- #endif /* CONFIG_KMOD */
-
--static int
-+static int
- fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
- {
-@@ -492,7 +505,7 @@
- struct fb_fix_screeninfo fix;
- struct fb_con2fbmap con2fb;
- int i;
--
-+
- if (! fb)
- return -ENODEV;
- switch (cmd) {
-@@ -576,7 +589,7 @@
- }
- }
-
--static int
-+static int
- fb_mmap(struct file *file, struct vm_area_struct * vma)
- {
- int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
-@@ -667,11 +680,11 @@
- #elif defined(__sh__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
- #elif defined(__hppa__)
-- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
- #elif defined(__ia64__)
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- #elif defined(__hppa__)
-- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
- #else
- #warning What do we have to do here??
- #endif
-@@ -724,7 +737,7 @@
- return res;
- }
-
--static int
-+static int
- fb_release(struct inode *inode, struct file *file)
- {
- int fbidx = GET_FB_IDX(inode->i_rdev);
-@@ -856,7 +869,7 @@
- *
- */
-
--void __init
-+void __init
- fbmem_init(void)
- {
- int i;
-@@ -904,7 +917,7 @@
-
- if (!options || !*options)
- return 0;
--
-+
- if (!strncmp(options, "scrollback:", 11)) {
- options += 11;
- if (*options) {
-@@ -930,7 +943,7 @@
- }
- return 0;
- }
--
-+
- if (!strncmp(options, "vc:", 3)) {
- options += 3;
- if (*options)
---- linux-2.4.25/drivers/video/font_acorn_8x8.c~2.4.25-vrs2.patch 1998-09-30 05:56:33.000000000 +0200
-+++ linux-2.4.25/drivers/video/font_acorn_8x8.c 2004-03-31 17:15:09.000000000 +0200
-@@ -11,33 +11,33 @@
- /* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */
- /* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */
- /* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */
--/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 06 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 07 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 08 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 09 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */
- /* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */
--/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 12 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 13 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 14 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 15 */ 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x06, 0x3c, 0x00,
-+/* 16 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 17 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 18 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 19 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */
- /* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */
--/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
-+/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
- /* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */
- /* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */
- /* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */
-@@ -132,55 +132,55 @@
- /* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */
- /* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */
- /* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */
--/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
--/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
-+/* 80 */ 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x30, 0x60,
-+/* 81 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 82 */ 0x0c, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 83 */ 0x18, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 84 */ 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 85 */ 0x30, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 86 */ 0x3c, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 87 */ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x60,
-+/* 88 */ 0x3c, 0x66, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 89 */ 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 8A */ 0x30, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 8B */ 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8C */ 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8D */ 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8E */ 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
-+/* 8F */ 0x18, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
-+/* 90 */ 0x0c, 0x18, 0x7e, 0x60, 0x7c, 0x60, 0x7e, 0x00,
-+/* 91 */ 0x00, 0x00, 0x3f, 0x0d, 0x3f, 0x6c, 0x3f, 0x00,
-+/* 92 */ 0x3f, 0x66, 0x66, 0x7f, 0x66, 0x66, 0x67, 0x00,
-+/* 93 */ 0x3c, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 94 */ 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 95 */ 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 96 */ 0x3c, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 97 */ 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 98 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c,
-+/* 99 */ 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
-+/* 9A */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
-+/* 9B */ 0x08, 0x3e, 0x6b, 0x68, 0x6b, 0x3e, 0x08, 0x00,
-+/* 9C */ 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00,
-+/* 9D */ 0x66, 0x3c, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
-+/* 9E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 9F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* A0 */ 0x0c, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* A1 */ 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* A2 */ 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* A3 */ 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* A4 */ 0x36, 0x6c, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x00,
-+/* A5 */ 0x36, 0x6c, 0x00, 0x66, 0x76, 0x6e, 0x66, 0x00,
-+/* A6 */ 0x1c, 0x06, 0x1e, 0x36, 0x1e, 0x00, 0x3e, 0x00,
-+/* A7 */ 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00,
-+/* A8 */ 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3c, 0x00,
-+/* A9 */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* AA */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* AB */ 0x40, 0xc0, 0x40, 0x4f, 0x41, 0x0f, 0x08, 0x0f,
-+/* AC */ 0x40, 0xc0, 0x40, 0x48, 0x48, 0x0a, 0x0f, 0x02,
-+/* AD */ 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
-+/* AE */ 0x00, 0x33, 0x66, 0xcc, 0xcc, 0x66, 0x33, 0x00,
-+/* AF */ 0x00, 0xcc, 0x66, 0x33, 0x33, 0x66, 0xcc, 0x00,
- /* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
- /* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
- /* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
-@@ -229,37 +229,37 @@
- /* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- /* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- /* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
--/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E1 */ 0x3c, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x6c, 0xc0,
-+/* E2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E6 */ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x60,
-+/* E7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E8 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EA */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* ED */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EF */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F1 */ 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
-+/* F2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F6 */ 0x00, 0x18, 0x00, 0xff, 0x00, 0x18, 0x00, 0x00,
-+/* F7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F8 */ 0x3c, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* F9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FA */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
-+/* FB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FD */ 0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00,
-+/* FE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
---- linux-2.4.25/drivers/video/pm3fb.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/drivers/video/pm3fb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -5,7 +5,6 @@
- * Based on code written by:
- * Sven Luther, <luther@dpt-info.u-strasbg.fr>
- * Alan Hourihane, <alanh@fairlite.demon.co.uk>
-- * Russel King, <rmk@arm.linux.org.uk>
- * Based on linux/drivers/video/skeletonfb.c:
- * Copyright (C) 1997 Geert Uytterhoeven
- * Based on linux/driver/video/pm2fb.c:
-@@ -16,13 +15,9 @@
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
-- * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
-+ * $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $
- *
- * CHANGELOG:
-- * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
-- * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
-- * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
-- * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
- * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
- * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
- * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
-@@ -53,8 +48,8 @@
- */
-
- #include <linux/config.h>
--#include <linux/module.h>
- #include <linux/version.h>
-+#include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -80,7 +75,6 @@
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
--
- #ifdef CONFIG_FB_OF
- #include <asm/prom.h>
- #endif
-@@ -128,7 +122,6 @@
- unsigned long refresh;
- unsigned long powerdown;
- };
--typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
- #define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
- #define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
-
-@@ -191,21 +184,13 @@
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}}, {
- "1024x768-74-32", {
-- 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-- 806, 1024, 0, 32,
-- PM3VideoControl_ENABLE |
-- PM3VideoControl_HSYNC_ACTIVE_HIGH
-- |
-- PM3VideoControl_VSYNC_ACTIVE_HIGH
-- | PM3VideoControl_PIXELSIZE_32BIT}},
--/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
-- {
-- "SGI1600SW", {
-- 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
-- 1056, 1600, 0, 8,
-- PM3VideoControl_ENABLE|
-- PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
-- PM3VideoControl_PIXELSIZE_32BIT}},
-+ 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-+ 806, 1024, 0, 32,
-+ PM3VideoControl_ENABLE |
-+ PM3VideoControl_HSYNC_ACTIVE_HIGH
-+ |
-+ PM3VideoControl_VSYNC_ACTIVE_HIGH
-+ | PM3VideoControl_PIXELSIZE_32BIT}},
- /* ##### auto-generated mode, by fbtimings2pm3 */
- /* Generated mode : "640x480-60" */
- {
-@@ -554,11 +539,9 @@
- short noaccel[PM3_MAX_BOARD];
- char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
- short depth[PM3_MAX_BOARD];
--short flatpanel[PM3_MAX_BOARD];
- static struct display disp[PM3_MAX_BOARD];
- static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
- short printtimings = 0;
--short forcesize[PM3_MAX_BOARD];
-
- /* ********************* */
- /* ***** prototype ***** */
-@@ -566,8 +549,7 @@
- /* card-specific */
- static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
- /* permedia3-specific */
--static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
--static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
-+static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
- static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
- static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r);
-@@ -683,7 +665,7 @@
- NULL, NULL
- };
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- struct fbgen_hwswitch pm3fb_switch = {
- pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
- pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, pm3fb_setcolreg,
-@@ -696,7 +678,7 @@
- fbgen_get_fix, fbgen_get_var, fbgen_set_var,
- fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, pm3fb_ioctl, NULL, NULL
- };
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- #ifdef PM3FB_USE_ACCEL
- #ifdef FBCON_HAS_CFB32
- static struct display_switch pm3fb_cfb32 = {
-@@ -727,75 +709,52 @@
- #endif /* FBCON_HAS_CFB8 */
- #endif /* PM3FB_USE_ACCEL */
-
--/* ****************************** */
--/* ***** card-specific data ***** */
--/* ****************************** */
--struct pm3fb_card_timings {
-- unsigned long memsize; /* 0 for last value (i.e. default) */
-- struct pm3fb_timings memt;
--};
--
--static struct pm3fb_card_timings t_FormacProFormance3[] = {
-- { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
-- { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
--};
--
--static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
-- { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
-- { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
--};
--
--static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
-- { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
-- { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
--};
--
-+/* ********************************** */
-+/* ***** card-specific function ***** */
-+/* ********************************** */
- static struct {
- char cardname[32]; /* recognized card name */
- u16 subvendor; /* subvendor of the card */
- u16 subdevice; /* subdevice of the card */
- u8 func; /* function of the card to which the extra init apply */
- void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
-- struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
-+ struct pm3fb_timings memt; /* default timing for the board WARNING : might be *card* - specific */
- } cardbase[] = {
-- { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
-- { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
-- t_AppianJeronimo2000
-- },
-+ { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, PM3FB_UNKNOWN_TIMINGS },
- { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
-- t_AppianJeronimo2000
-+ {0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} /* also in pm3fb_j2000_setup */
- },
- { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
-- t_FormacProFormance3
-+ { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} /* from the 16Mb ProFormance 3 */
- },
-- { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
-+ { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
- { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
-- t_3DLabsOxygenVX1
-+ { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000 }
- },
-- { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
-- { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
-- { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
-- { "\0", 0x0, 0x0, 0, NULL, NULL }
-+ { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "\0", 0x0, 0x0, 0, NULL, PM3FB_UNKNOWN_TIMINGS }
- };
-
--/* ********************************** */
--/* ***** card-specific function ***** */
--/* ********************************** */
- static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
- { /* the appian j2000 require more initialization of the second head */
- /* l_fb_info must point to the _second_ head of the J2000 */
-
- DTRACE;
--
-- l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
-+
-+ /* Memory timings for the Appian J2000 board. also in cardbase */
-+ l_fb_info->memt.caps = 0x02e311B8;
-+ l_fb_info->memt.timings = 0x07424905;
-+ l_fb_info->memt.control = 0x0c000003;
-+ l_fb_info->memt.refresh = 0x00000061;
-+ l_fb_info->memt.powerdown = 0x00000000;
-
- pm3fb_write_memory_timings(l_fb_info);
- }
-
--/* *************************************** */
--/* ***** permedia3-specific function ***** */
--/* *************************************** */
--static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
-+static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
- {
- l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
- l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
-@@ -810,35 +769,20 @@
- (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
- {
- printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
-- return(pm3fb_try_memory_timings(l_fb_info));
-- }
-- return(pm3fb_timing_ok);
--}
--
--static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
--{
-- if (cardbase[l_fb_info->board_type].c_memt)
-- {
-- int i = 0, done = 0;
-- while (!done)
-+ if ((cardbase[l_fb_info->board_type].memt.caps != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.timings != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.control != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.refresh != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.powerdown != PM3FB_UNKNOWN_TIMING_VALUE))
- {
-- if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
-- || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
-- { /* will use the 0-sized timings by default */
-- done = 1;
-- l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
-- printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
-- l_fb_info->board_num,
-- cardbase[l_fb_info->board_type].cardname,
-- cardbase[l_fb_info->board_type].c_memt[i].memsize);
-- pm3fb_write_memory_timings(l_fb_info);
-- return(pm3fb_timing_retry);
-- }
-- i++;
-+ l_fb_info->memt = cardbase[l_fb_info->board_type].memt;
-+ printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s)\n", l_fb_info->board_num, cardbase[l_fb_info->board_type].cardname);
-+ pm3fb_write_memory_timings(l_fb_info);
- }
-- } else
-- return(pm3fb_timing_problem);
-- return(pm3fb_timing_ok);
-+ else
-+ return(1);
-+ }
-+ return(0);
- }
-
- static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
-@@ -873,6 +817,10 @@
- PM3RD_SClkControl_ENABLE);
- }
-
-+/* *************************************** */
-+/* ***** permedia3-specific function ***** */
-+/* *************************************** */
-+
- static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r)
- {
-@@ -1067,7 +1015,6 @@
- /* write the mode to registers */
- static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
- {
-- char tempsync = 0x00, tempmisc = 0x00;
- DTRACE;
-
- PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
-@@ -1197,26 +1144,22 @@
- /*
- PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
- */
-- if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
-- PM3VideoControl_HSYNC_ACTIVE_HIGH)
-- tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-- if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
-- PM3VideoControl_VSYNC_ACTIVE_HIGH)
-- tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
--
-- PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
-- DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
--
-- if (flatpanel[l_fb_info->board_num])
- {
-- PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
-- PM3_WAIT(2);
-- PM3_WRITE_REG(PM3VSConfiguration, 0x06);
-- PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
-- tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
-+ char tempsync = 0x00;
-+
-+ if ((l_fb_info->current_par->
-+ video & PM3VideoControl_HSYNC_MASK) ==
-+ PM3VideoControl_HSYNC_ACTIVE_HIGH)
-+ tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-+ if ((l_fb_info->current_par->
-+ video & PM3VideoControl_VSYNC_MASK) ==
-+ PM3VideoControl_VSYNC_ACTIVE_HIGH)
-+ tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
-+
-+ PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
-+ DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
- }
-- else
-- PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
-+ PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
-
- switch (l_fb_info->current_par->depth) {
- case 8:
-@@ -1225,7 +1168,8 @@
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
- PM3RD_ColorFormat_CI8_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-- tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 12:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1234,8 +1178,9 @@
- PM3RD_ColorFormat_4444_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 15:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1244,8 +1189,9 @@
- PM3RD_ColorFormat_5551_FRONT_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 16:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1254,8 +1200,9 @@
- PM3RD_ColorFormat_565_FRONT_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 32:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1263,12 +1210,12 @@
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
- PM3RD_ColorFormat_8888_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- }
-- PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
--
-+
- PM3_SHOW_CUR_MODE;
- }
-
-@@ -1390,9 +1337,8 @@
-
- static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
- {
-- unsigned long memsize = 0, tempBypass, i, temp1, temp2;
-+ unsigned long memsize, tempBypass, i, temp1, temp2;
- u16 subvendor, subdevice;
-- pm3fb_timing_result ptr;
-
- DTRACE;
-
-@@ -1438,7 +1384,7 @@
-
- /* card-specific setup is done, we preserve the final
- memory timing for future reference */
-- if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
-+ if (pm3fb_preserve_memory_timings(l_fb_info)) { /* memory timings were wrong ! oops.... */
- return(0);
- }
-
-@@ -1464,12 +1410,12 @@
- temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
- #endif
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
- temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- /* Let's check for wrapover, write will fail at 16MB boundary */
- if (temp1 == (i * 0x00345678))
- memsize = i;
-@@ -1512,7 +1458,7 @@
- ((i - 32) * 1048576)));
- #endif
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
-@@ -1521,7 +1467,7 @@
- temp2 =
- fb_readl((l_fb_info->v_fb +
- ((i - 32) * 1048576)));
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
- memsize = i;
- else
-@@ -1538,21 +1484,8 @@
-
- DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
-
-- if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
-- {
-- printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
-- memsize = 1048576 * forcesize[l_fb_info->board_num];
-- }
--
- l_fb_info->fb_size = memsize;
--
-- if (ptr == pm3fb_timing_retry)
-- {
-- printk(KERN_WARNING "pm3fb: retrying memory timings check");
-- if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
-- return(0);
-- }
--
-+
- return (memsize);
- }
-
-@@ -1571,7 +1504,7 @@
- writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
- #endif
- #endif
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
- #endif
- }
-@@ -1600,7 +1533,7 @@
- disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
- l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
- l_fb_info->gen.info.changevar = NULL;
-- l_fb_info->gen.info.node = B_FREE;
-+ l_fb_info->gen.info.node = -1;
- l_fb_info->gen.info.fbops = &pm3fb_ops;
- l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
- if (fontn[l_fb_info->board_num][0])
-@@ -1765,7 +1698,6 @@
- }
-
- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(PM3FBWriteMode,
- PM3FBWriteMode_WriteEnable |
- PM3FBWriteMode_OpaqueSpan |
-@@ -1786,7 +1718,9 @@
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
- else
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
--
-+
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
-+
- switch (l_fb_info->current_par->depth) {
- case 8:
- PM3_SLOW_WRITE_REG(PM3DitherMode,
-@@ -1842,10 +1776,7 @@
- height = height * fontheight(p);
- c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
-- /* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
-- we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */
-- if ((l_fb_info->current_par->width > 1600) ||
-- (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
-+ if (l_fb_info->current_par->width > 1600) {
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
-@@ -1867,7 +1798,7 @@
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
-- } else {
-+ } else { /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) we can use 16bpp operations */
- PM3_WAIT(8);
-
- PM3_WRITE_REG(PM3FBBlockColor, c);
-@@ -1992,10 +1923,7 @@
-
- PM3_WAIT(4);
-
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
-@@ -2006,23 +1934,14 @@
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(width)) |
-- (PM3Render2D_Height(height)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(width)) |
-- (PM3Render2D_Height(height)));
--
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(width)) |
-+ (PM3Render2D_Height(height)));
-+
- pm3fb_wait_pm3(l_fb_info);
- }
-
-@@ -2048,69 +1967,45 @@
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
--
-+
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-+
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset
- (p->var.xoffset +
- sx)) | (PM3RectanglePosition_YOffset(p->
- var.
- yoffset)));
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(p->var.xres - sx)) |
-- (PM3Render2D_Height(p->var.yres)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(p->var.xres - sx)) |
-- (PM3Render2D_Height(p->var.yres)));
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(p->var.xres - sx)) |
-+ (PM3Render2D_Height(p->var.yres)));
- }
--
-+
- /* bottom margin left -> right */
- PM3_WAIT(4);
--
-+
- PM3_WRITE_REG(PM3Config2D,
-- PM3Config2D_UseConstantSource |
-- PM3Config2D_ForegroundROPEnable |
-- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
-- PM3Config2D_FBWriteEnable);
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
--
--
-+ PM3Config2D_UseConstantSource |
-+ PM3Config2D_ForegroundROPEnable |
-+ (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
-+ PM3Config2D_FBWriteEnable);
-+
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-+
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(p->var.xoffset)) |
- (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(p->var.xres)) |
-- (PM3Render2D_Height(p->var.yres - sy)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(p->var.xres)) |
-- (PM3Render2D_Height(p->var.yres - sy)));
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(p->var.xres)) |
-+ (PM3Render2D_Height(p->var.yres - sy)));
-
- pm3fb_wait_pm3(l_fb_info);
- }
-@@ -2288,7 +2183,7 @@
- int c, int yy, int xx)
- {
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-+ u8 *cdat, asx = 0, asy = 0, o_x, o_y;
- u32 fgx, bgx, ldat;
- int sx, sy, i;
-
-@@ -2398,7 +2293,7 @@
- int xx)
- {
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-+ u8 *cdat, asx = 0, asy = 0, o_x, o_y;
- u32 fgx, bgx, ldat;
- int sx, sy, i, j;
- u16 sc;
-@@ -2516,12 +2411,7 @@
- yy = yy * fontheight(p);
-
- if (l_fb_info->current_par->depth == 8)
-- {
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
-- else
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
-- }
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
-
- PM3_WAIT(3);
-
-@@ -2547,12 +2437,7 @@
- pm3fb_wait_pm3(l_fb_info);
-
- if (l_fb_info->current_par->depth == 8)
-- {
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
-- else
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
-- }
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
- }
-
- #endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-@@ -2640,25 +2525,12 @@
- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
- if (!(depth_supported(bd))) {
-- printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
-- bds, board_num);
-+ DPRINTK(1, "Invalid depth: %s\n", bds);
- return;
- }
- depth[board_num] = bd;
- }
-
--static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
--{
-- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
--
-- if (bd > 64) {
-- printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
-- bds, board_num);
-- return;
-- }
-- forcesize[board_num] = bd;
--}
--
- static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
- {
- char *next;
-@@ -2752,12 +2624,6 @@
- pm3fb_bootdepth_setup(options, bn);
- } else if (!strncmp(options, "printtimings", 12)) {
- printtimings = 1;
-- } else if (!strncmp(options, "flatpanel:", 10)) {
-- options = pm3fb_boardnum_setup(options + 10, &bn);
-- flatpanel[bn] = 1;
-- } else if (!strncmp(options, "forcesize:", 10)) {
-- options = pm3fb_boardnum_setup(options + 10, &bn);
-- pm3fb_forcesize_setup(options, bn);
- }
- options = next;
- }
-@@ -3495,7 +3361,7 @@
- pci_resource_start(l_fb_info->dev, 1);
- l_fb_info->v_fb = (unsigned char *) -1;
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* full resource management, new in linux-2.4.x */
-+#ifdef KERNEL_2_4 /* full resource management, new in linux-2.4.x */
- if (!request_mem_region
- ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
- "pm3fb")) {
-@@ -3512,10 +3378,8 @@
- l_fb_info->board_num);
- continue;
- }
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-- if (forcesize[l_fb_info->board_num])
-- l_fb_info->fb_size = forcesize[l_fb_info->board_num];
--
-+#endif /* KERNEL_2_4 */
-+
- l_fb_info->fb_size =
- pm3fb_size_memory(l_fb_info);
-
-@@ -3611,7 +3475,7 @@
- /* ***** standard FB API init functions ***** */
- /* ****************************************** */
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- int __init pm3fb_setup(char *options)
- #endif
- #ifdef KERNEL_2_2
-@@ -3627,12 +3491,12 @@
- PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
- g_options[PM3_OPTIONS_SIZE - 1] = 0;
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- return (0);
- #endif
- }
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- int __init pm3fb_init(void)
- #endif
- #ifdef KERNEL_2_2
-@@ -3641,7 +3505,7 @@
- {
- DTRACE;
-
-- DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
-+ DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $");
-
- pm3fb_real_setup(g_options);
-
-@@ -3650,7 +3514,7 @@
- if (!fb_info[0].dev) { /* not even one board ??? */
- DPRINTK(1, "No PCI Permedia3 board detected\n");
- }
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- return (0);
- #endif
- }
-@@ -3753,9 +3617,7 @@
- MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
- MODULE_PARM_DESC(depth,"boot-time depth");
- MODULE_PARM(printtimings, "h");
--MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
--MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
--MODULE_PARM_DESC(forcesize, "force specified memory size");
-+MODULE_PARM_DESC(printtimings, "print the memory timngs of the card(s)");
- /*
- MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
- MODULE_GENERIC_TABLE(gtype,name)
-@@ -3829,14 +3691,14 @@
- if (l_fb_info->vIOBase !=
- (unsigned char *) -1) {
- pm3fb_unmapIO(l_fb_info);
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- release_mem_region(l_fb_info->p_fb,
- l_fb_info->
- fb_size);
- release_mem_region(l_fb_info->
- pIOBase,
- PM3_REGS_SIZE);
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- }
- unregister_framebuffer(&l_fb_info->gen.
- info);
---- linux-2.4.25/drivers/video/pm3fb.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.25/drivers/video/pm3fb.h 2004-03-31 17:15:09.000000000 +0200
-@@ -8,7 +8,7 @@
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
-- * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
-+ * $Header: /home/pm3fb/pm3fb/pm3fb.h,v 1.30 2001/08/22 09:13:46 dolbeau Exp $
- *
- */
-
-@@ -92,7 +92,6 @@
- #define PM3MemBypassWriteMask 0x1008
- #define PM3MemScratch 0x1010
- #define PM3LocalMemCaps 0x1018
-- #define PM3LocalMemCaps_NoWriteMask (1 << 28)
- #define PM3LocalMemTimings 0x1020
- #define PM3LocalMemControl 0x1028
- #define PM3LocalMemRefresh 0x1030
-@@ -1121,10 +1120,6 @@
-
- /* kernel -specific definitions */
- /* what kernel is this ? */
--#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
--#define KERNEL_2_5
--#endif
--
- #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
- #define KERNEL_2_4
- #endif
-@@ -1138,8 +1133,8 @@
- #endif
- #endif
-
--#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
--#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
-+#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4))
-+#error "Only kernel 2.2.x and kernel 2.4.y might work"
- #endif
-
- /* not sure if/why it's needed. doesn't work without on my PowerMac... */
-@@ -1147,11 +1142,6 @@
- #define MUST_BYTESWAP
- #endif
-
--/* for compatibility between 2.5, 2.4 and 2.2 */
--#ifndef B_FREE
--#define B_FREE -1
--#endif
--
- /* permedia3 -specific definitions */
- #define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
- #define PICOS2KHZ(a) (1000000000UL/(a))
-@@ -1219,10 +1209,10 @@
- #define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
- #endif /* MUST_BYTESWAP */
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
-+#ifdef KERNEL_2_4 /* native-endian access */
- #define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
- #define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
-
-
- #define depth2bpp(d) ((d + 7L) & ~7L)
---- linux-2.4.25/drivers/video/sa1100fb.c~2.4.25-vrs2.patch 2001-11-14 23:52:20.000000000 +0100
-+++ linux-2.4.25/drivers/video/sa1100fb.c 2004-03-31 17:15:09.000000000 +0200
-@@ -23,11 +23,11 @@
- * Thank you.
- *
- * Known problems:
-- * - With the Neponset plugged into an Assabet, LCD powerdown
-- * doesn't work (LCD stays powered up). Therefore we shouldn't
-- * blank the screen.
-- * - We don't limit the CPU clock rate nor the mode selection
-- * according to the available SDRAM bandwidth.
-+ * - With the Neponset plugged into an Assabet, LCD powerdown
-+ * doesn't work (LCD stays powered up). Therefore we shouldn't
-+ * blank the screen.
-+ * - We don't limit the CPU clock rate nor the mode selection
-+ * according to the available SDRAM bandwidth.
- *
- * Other notes:
- * - Linear grayscale palettes and the kernel.
-@@ -41,6 +41,17 @@
- * David Neuer. It's around 8 lines of C code, plus another 4 to
- * detect if we are using grayscale.
- *
-+ * - The following must never be specified in a panel definition:
-+ * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
-+ *
-+ * - The following should be specified:
-+ * either LCCR0_Color or LCCR0_Mono
-+ * either LCCR0_Sngl or LCCR0_Dual
-+ * either LCCR0_Act or LCCR0_Pas
-+ * either LCCR3_OutEnH or LCCD3_OutEnL
-+ * either LCCR3_PixRsEdg or LCCR3_PixFlEdg
-+ * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
-+ *
- * Code Status:
- * 1999/04/01:
- * - Driver appears to be working for Brutus 320x200x8bpp mode. Other
-@@ -147,6 +158,10 @@
- *
- * 2001/10/12: <rmk@arm.linux.org.uk>
- * - Add patch 681/1 and clean up stork definitions.
-+ *
-+ * 2002/02/21: <abraham@2d3d.co.za>
-+ * - Added support for ICP LCD-Kit01 on Frodo.
-+ * - Added support for backlight via CPLDs on Frodo.
- */
-
- #include <linux/config.h>
-@@ -169,6 +184,7 @@
- #include <asm/mach-types.h>
- #include <asm/uaccess.h>
- #include <asm/arch/assabet.h>
-+#include <asm/arch/shannon.h>
-
- #include <video/fbcon.h>
- #include <video/fbcon-mfb.h>
-@@ -177,11 +193,6 @@
- #include <video/fbcon-cfb16.h>
-
- /*
-- * enable this if your panel appears to have broken
-- */
--#undef CHECK_COMPAT
--
--/*
- * debugging?
- */
- #define DEBUG 0
-@@ -197,243 +208,6 @@
- void (*sa1100fb_blank_helper)(int blank);
- EXPORT_SYMBOL(sa1100fb_blank_helper);
-
--
--#ifdef CHECK_COMPAT
--static void
--sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
-- struct fb_var_screeninfo *var, u_int pcd)
--{
-- struct sa1100fb_lcd_reg shadow;
-- int different = 0;
--
-- /*
-- * These machines are good machines!
-- */
-- if (machine_is_assabet() || machine_is_h3600())
-- return;
--
-- /*
-- * The following ones are bad, bad, bad.
-- * Please make yours good!
-- */
-- if (machine_is_pangolin()) {
-- DPRINTK("Configuring Pangolin LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
-- LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
-- LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
-- LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
-- LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
--
-- DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
-- pcd, LCCR3_PixClkDiv(pcd));
-- }
-- if (machine_is_freebird()) {
-- DPRINTK("Configuring Freebird LCD\n");
--#if 1
-- shadow.lccr0 = 0x00000038;
-- shadow.lccr1 = 0x010108e0;
-- shadow.lccr2 = 0x0000053f;
-- shadow.lccr3 = 0x00000c20;
--#else
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
-- LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_DMADel(0);
-- /* Check ,Chester */
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
-- LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
-- /* Check ,Chester */
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
-- /* Check ,Chester */
-- shadow.lccr3 =
-- LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-- LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
--#endif
-- }
-- if (machine_is_brutus()) {
-- DPRINTK("Configuring Brutus LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
-- LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-- shadow.lccr3 =
-- LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-- LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
-- }
-- if (machine_is_huw_webpanel()) {
-- DPRINTK("Configuring HuW LCD\n");
-- shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
-- shadow.lccr1 = LCCR1_DisWdth(var->xres) +
-- LCCR1_HorSnchWdth(3) +
-- LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-- shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
-- shadow.lccr3 = 8 + LCCR3_OutEnH +
-- LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
-- }
-- if (machine_is_lart()) {
-- DPRINTK("Configuring LART LCD\n");
--#if defined LART_GREY_LCD
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
-- LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
--#endif
--#if defined LART_COLOR_LCD
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
-- LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
-- LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
-- LCCR3_PixFlEdg;
--#endif
--#if defined LART_VIDEO_OUT
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
-- LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
-- shadow.lccr2 =
-- LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
-- LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
-- LCCR3_PixFlEdg + LCCR3_OutEnL;
--#endif
-- }
-- if (machine_is_graphicsclient()) {
-- DPRINTK("Configuring GraphicsClient LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
-- LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
-- LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-- }
-- if (machine_is_omnimeter()) {
-- DPRINTK("Configuring OMNI LCD\n");
-- shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
-- shadow.lccr1 =
-- LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
-- LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
-- shadow.lccr2 = LCCR2_DisHght(var->yres);
-- shadow.lccr3 =
-- LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
--//jca (GetPCD(25) << LCD3_V_PCD);
-- }
-- if (machine_is_xp860()) {
-- DPRINTK("Configuring XP860 LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) +
-- LCCR1_HorSnchWdth(var->hsync_len) +
-- LCCR1_BegLnDel(var->left_margin) +
-- LCCR1_EndLnDel(var->right_margin);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) +
-- LCCR2_VrtSnchWdth(var->vsync_len) +
-- LCCR2_BegFrmDel(var->upper_margin) +
-- LCCR2_EndFrmDel(var->lower_margin);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-- }
--
-- /*
-- * Ok, since we're calculating these values, we want to know
-- * if the calculation is correct. If you see any of these
-- * messages _PLEASE_ report the incident to me for diagnosis,
-- * including details about what was happening when the
-- * messages appeared. --rmk, 30 March 2001
-- */
-- if (shadow.lccr0 != new_regs->lccr0) {
-- printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr1, new_regs->lccr1);
-- different = 1;
-- }
-- if (shadow.lccr1 != new_regs->lccr1) {
-- printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr1, new_regs->lccr1);
-- different = 1;
-- }
-- if (shadow.lccr2 != new_regs->lccr2) {
-- printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr2, new_regs->lccr2);
-- different = 1;
-- }
-- if (shadow.lccr3 != new_regs->lccr3) {
-- printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr3, new_regs->lccr3);
-- different = 1;
-- }
-- if (different) {
-- printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
-- var->xres, var->hsync_len,
-- var->left_margin, var->right_margin);
-- printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
-- var->yres, var->vsync_len,
-- var->upper_margin, var->lower_margin);
--
-- printk(KERN_ERR "Please report this to Russell King "
-- "<rmk@arm.linux.org.uk>\n");
-- }
--
-- DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
-- DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
-- DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
-- DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
--}
--#else
--#define sa1100fb_check_shadow(regs,var,pcd)
--#endif
--
--
--
- /*
- * IMHO this looks wrong. In 8BPP, length should be 8.
- */
-@@ -488,42 +262,56 @@
- #endif
- #endif
-
--#ifdef CONFIG_SA1100_H3600
--static struct sa1100fb_mach_info h3600_info __initdata = {
--#ifdef CONFIG_IPAQ_H3100
-- pixclock: 407766, bpp: 4,
-+#ifdef CONFIG_SA1100_H3XXX
-+static struct sa1100fb_mach_info h3800_info __initdata = {
-+ pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
-
-- hsync_len: 26, vsync_len: 41,
-- left_margin: 4, upper_margin: 0,
-- right_margin: 4, lower_margin: 0,
-+ hsync_len: 3, vsync_len: 3,
-+ left_margin: 12, upper_margin: 10,
-+ right_margin: 17, lower_margin: 1,
-
-- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-- cmap_greyscale: 1, cmap_static: 1,
-- cmap_inverse: 1,
-+ sync: 0, cmap_static: 1,
-
-- lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
--#else
-- pixclock: 174757, bpp: 16,
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
-+};
-+
-+static struct sa1100fb_mach_info h3600_info __initdata = {
-+ pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
-
- hsync_len: 3, vsync_len: 3,
- left_margin: 12, upper_margin: 10,
- right_margin: 17, lower_margin: 1,
-
-- sync: 0,
-+ sync: 0, cmap_static: 1,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
--#endif
-+ lccr3: LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
- };
-
- static struct sa1100fb_rgb h3600_rgb_16 = {
- red: { offset: 12, length: 4, },
- green: { offset: 7, length: 4, },
- blue: { offset: 1, length: 4, },
-- transp: { offset: 0, length: 0, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct sa1100fb_mach_info h3100_info __initdata = {
-+ pixclock: 406977, bpp: 4,
-+ xres: 320, yres: 240,
-+
-+ hsync_len: 26, vsync_len: 41,
-+ left_margin: 4, upper_margin: 0,
-+ right_margin: 4, lower_margin: 0,
-+
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+ cmap_greyscale: 1,
-+ cmap_inverse: 1,
-+
-+ lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
- };
- #endif
-
-@@ -618,6 +406,58 @@
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
- static struct sa1100fb_mach_info graphicsclient_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+static struct sa1100fb_mach_info graphicsmaster_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSBITSY
-+static struct sa1100fb_mach_info adsbitsy_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+static struct sa1100fb_mach_info adsbitsyplus_info __initdata = {
-+// for LQ64D343
- pixclock: 53500, bpp: 8,
- xres: 640, yres: 480,
-
-@@ -699,7 +539,6 @@
- lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
- };
- #endif
--
- #ifdef LART_KIT01_LCD
- static struct sa1100fb_mach_info lart_kit01_info __initdata =
- {
-@@ -707,7 +546,7 @@
- xres: 640, yres: 480,
-
- hsync_len: 64, vsync_len: 3,
-- left_margin: 122, upper_margin: 45,
-+ left_margin: 122, upper_margin: 45,
- right_margin: 10, lower_margin: 10,
-
- sync: 0,
-@@ -717,6 +556,40 @@
- };
- #endif
-
-+#ifdef CONFIG_SA1100_FRODO
-+static struct sa1100fb_mach_info frodo_kit01_info __initdata =
-+{
-+ /* best would be 41731 (25.8mhz), but we can only do 14.743mhz at 191.7mhz clock speed */
-+ pixclock: 73030, bpp: 16,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 32, vsync_len: 19,
-+ left_margin: 120, upper_margin: 33,
-+ right_margin: 17, lower_margin: 12,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_SHANNON
-+static struct sa1100fb_mach_info shannon_info __initdata = {
-+ pixclock: 152500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 4, vsync_len: 3,
-+ left_margin: 2, upper_margin: 0,
-+ right_margin: 1, lower_margin: 0,
-+
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+
-+ lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
-+ lccr3: LCCR3_ACBsDiv(512),
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_OMNIMETER
- static struct sa1100fb_mach_info omnimeter_info __initdata = {
- pixclock: 0, bpp: 4,
-@@ -752,7 +625,24 @@
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPUTER
-+static struct sa1100fb_mach_info simputer_info __initdata = {
-+ pixclock: 70000, bpp: 4,
-+ xres: 320, yres: 240,
-+
-+ hsync_len: 9, vsync_len: 2,
-+ left_margin: 9, upper_margin: 0,
-+ right_margin: 2, lower_margin: 0,
-+
-+ cmap_greyscale: 1,
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
-+
-+ lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(202),
- };
- #endif
-
-@@ -828,7 +718,6 @@
- #endif
-
-
--
- static struct sa1100fb_mach_info * __init
- sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
- {
-@@ -849,11 +738,17 @@
- #endif
- }
- #endif
--#ifdef CONFIG_SA1100_H3600
-+#ifdef CONFIG_SA1100_H3XXX
- if (machine_is_h3600()) {
- inf = &h3600_info;
- fbi->rgb[RGB_16] = &h3600_rgb_16;
- }
-+ if (machine_is_h3100()) {
-+ inf = &h3100_info;
-+ }
-+ if (machine_is_h3800()) {
-+ inf = &h3800_info;
-+ }
- #endif
- #ifdef CONFIG_SA1100_BRUTUS
- if (machine_is_brutus()) {
-@@ -876,6 +771,22 @@
- inf = &graphicsclient_info;
- }
- #endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ inf = &graphicsmaster_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSY
-+ if (machine_is_adsbitsy()) {
-+ inf = &adsbitsy_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ inf = &adsbitsyplus_info;
-+ }
-+ }
-+#endif
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- if (machine_is_huw_webpanel()) {
- inf = &huw_webpanel_info;
-@@ -897,6 +808,21 @@
- #endif
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo()) {
-+ inf = &frodo_kit01_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_SHANNON
-+ if (machine_is_shannon()) {
-+ inf = &shannon_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ inf = &simputer_info;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_OMNIMETER
- if (machine_is_omnimeter()) {
- inf = &omnimeter_info;
-@@ -1556,7 +1482,8 @@
- unsigned int pcd;
-
- if (pixclock) {
-- pcd = get_cclk_frequency() * pixclock;
-+ pcd = cpufreq_get(0) / 100;
-+ pcd *= pixclock;
- pcd /= 10000000;
- pcd += 1; /* make up for integer math truncations */
- } else {
-@@ -1580,6 +1507,7 @@
- return pcd;
- }
-
-+
- /*
- * sa1100fb_activate_var():
- * Configures LCD Controller based on entries in var parameter. Settings are
-@@ -1659,8 +1587,6 @@
- if (pcd)
- new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
-
-- sa1100fb_check_shadow(&new_regs, var, pcd);
--
- DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
- DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
- DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-@@ -1733,6 +1659,10 @@
- if (machine_is_omnimeter())
- LEDBacklightOn();
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
-+#endif
- }
-
- /*
-@@ -1755,6 +1685,10 @@
- if (machine_is_omnimeter())
- LEDBacklightOff();
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
-+#endif
- }
-
- static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
-@@ -1773,20 +1707,25 @@
- if (machine_is_omnimeter())
- LCDPowerOn();
- #endif
--#ifdef CONFIG_SA1100_H3600
-- if (machine_is_h3600()) {
-- set_h3600_egpio(EGPIO_H3600_LCD_ON |
-- EGPIO_H3600_LCD_PCI |
-- EGPIO_H3600_LCD_5V_ON |
-- EGPIO_H3600_LVDD_ON);
-- }
--#endif
-+ if (machine_is_h3xxx())
-+ set_h3600_egpio( IPAQ_EGPIO_LCD_ON ); /* Turn on power to the LCD */
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 1);
- storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ sa1100fb_backlight_on(fbi);
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ ADS_CPLD_PCON &= ~ADS_PCON_PANEL_ON;
-+ ADS_CPLD_SUPPC |= ADS_SUPPC_VEE_ON;
-+ }
-+#endif
-+
- }
-
- static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
-@@ -1802,20 +1741,24 @@
- if (machine_is_huw_webpanel())
- BCR_set(BCR_TFT_NPWR);
- #endif
--#ifdef CONFIG_SA1100_H3600
-- if (machine_is_h3600()) {
-- clr_h3600_egpio(EGPIO_H3600_LCD_ON |
-- EGPIO_H3600_LCD_PCI |
-- EGPIO_H3600_LCD_5V_ON |
-- EGPIO_H3600_LVDD_ON);
-- }
--#endif
-+ if (machine_is_h3xxx())
-+ clr_h3600_egpio( IPAQ_EGPIO_LCD_ON );
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 0);
- storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ sa1100fb_backlight_off(fbi);
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ ADS_CPLD_PCON |= ADS_PCON_PANEL_ON;
-+ ADS_CPLD_SUPPC &= ~ADS_SUPPC_VEE_ON;
-+ }
-+#endif
- }
-
- static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
-@@ -1911,15 +1854,29 @@
- LCCR0 |= LCCR0_LEN;
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
--#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- // From ADS doc again...same as disable
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
-- GPSR |= GPIO_GPIO24;
-+ GPDR |= GPIO_GPIO24;
-+ GPSR = GPIO_GPIO24;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ // From ADS doc again...same as disable
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(20 * HZ / 1000);
-+ GPDR |= GPIO_GPIO24;
-+ GPSR = GPIO_GPIO24;
- }
- #endif
-
-+ if (machine_is_shannon()) {
-+ GPDR |= SHANNON_GPIO_DISP_EN;
-+ GPSR |= SHANNON_GPIO_DISP_EN;
-+ }
-+
- DPRINTK("DBAR1 = %p\n", DBAR1);
- DPRINTK("DBAR2 = %p\n", DBAR2);
- DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
-@@ -1935,7 +1892,6 @@
- DPRINTK("Disabling LCD controller\n");
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
--#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- /*
- * From ADS internal document:
-@@ -1944,6 +1900,22 @@
- *
- * We'll wait 20msec.
- */
-+ GPDR |= GPIO_GPIO24;
-+ GPCR |= GPIO_GPIO24;
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(20 * HZ / 1000);
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ /*
-+ * From ADS internal document:
-+ * GPIO24 should be LOW at least 10msec prior to disabling
-+ * the LCD interface.
-+ *
-+ * We'll wait 20msec.
-+ */
-+ GPDR |= GPIO_GPIO24;
- GPCR |= GPIO_GPIO24;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
-@@ -1958,12 +1930,15 @@
- }
- #endif
-
-+ if (machine_is_shannon()) {
-+ GPCR |= SHANNON_GPIO_DISP_EN;
-+ }
-+
- add_wait_queue(&fbi->ctrlr_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- LCSR = 0xffffffff; /* Clear LCD Status Register */
- LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
-- enable_irq(IRQ_LCD); /* Enable LCD IRQ */
- LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */
-
- schedule_timeout(20 * HZ / 1000);
-@@ -2006,12 +1981,13 @@
- * Disable controller for clock change. If the
- * controller is already disabled, then do nothing.
- */
-- if (old_state != C_DISABLE) {
-+ if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
- fbi->state = state;
- sa1100fb_disable_controller(fbi);
- }
- break;
-
-+ case C_DISABLE_PM:
- case C_DISABLE:
- /*
- * Disable controller
-@@ -2050,6 +2026,16 @@
- }
- break;
-
-+ case C_ENABLE_PM:
-+ /*
-+ * Re-enable the controller after PM. This is not
-+ * perfect - think about the case where we were doing
-+ * a clock change, and we suspended half-way through.
-+ */
-+ if (old_state != C_DISABLE_PM)
-+ break;
-+ /* fall through */
-+
- case C_ENABLE:
- /*
- * Power up the LCD screen, enable controller, and
-@@ -2162,10 +2148,10 @@
-
- if (state == 0) {
- /* Enter D0. */
-- set_ctrlr_state(fbi, C_ENABLE);
-+ set_ctrlr_state(fbi, C_ENABLE_PM);
- } else {
- /* Enter D1-D3. Disable the LCD controller. */
-- set_ctrlr_state(fbi, C_DISABLE);
-+ set_ctrlr_state(fbi, C_DISABLE_PM);
- }
- }
- DPRINTK("done\n");
-@@ -2304,7 +2290,7 @@
- goto failed;
-
- ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
-- fbi->fb.fix.id, fbi);
-+ "LCD", fbi);
- if (ret) {
- printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
- goto failed;
---- linux-2.4.25/drivers/video/sa1100fb.h~2.4.25-vrs2.patch 2001-10-25 22:53:52.000000000 +0200
-+++ linux-2.4.25/drivers/video/sa1100fb.h 2004-03-31 17:15:09.000000000 +0200
-@@ -127,6 +127,8 @@
- #define C_DISABLE_CLKCHANGE (2)
- #define C_ENABLE_CLKCHANGE (3)
- #define C_REENABLE (4)
-+#define C_DISABLE_PM (5)
-+#define C_ENABLE_PM (6)
-
- #define SA1100_NAME "SA1100"
-
---- linux-2.4.25/fs/adfs/dir.c~2.4.25-vrs2.patch 2000-09-19 00:14:06.000000000 +0200
-+++ linux-2.4.25/fs/adfs/dir.c 2004-03-31 17:15:09.000000000 +0200
-@@ -23,7 +23,7 @@
- /*
- * For future. This should probably be per-directory.
- */
--static rwlock_t adfs_dir_lock;
-+static rwlock_t adfs_dir_lock = RW_LOCK_UNLOCKED;
-
- static int
- adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
---- linux-2.4.25/fs/adfs/map.c~2.4.25-vrs2.patch 2001-10-25 22:53:53.000000000 +0200
-+++ linux-2.4.25/fs/adfs/map.c 2004-03-31 17:15:09.000000000 +0200
-@@ -13,24 +13,27 @@
- #include <linux/adfs_fs.h>
- #include <linux/spinlock.h>
-
-+#include <asm/unaligned.h>
-+
- #include "adfs.h"
-
- /*
- * For the future...
- */
--static rwlock_t adfs_map_lock;
-+static rwlock_t adfs_map_lock = RW_LOCK_UNLOCKED;
-
-+/*
-+ * This is fun. We need to load up to 19 bits from the map at an
-+ * arbitary bit alignment. (We're limited to 19 bits by F+ version
-+ * 2).
-+ */
- #define GET_FRAG_ID(_map,_start,_idmask) \
- ({ \
-- unsigned long _v2, _frag; \
-- unsigned int _tmp; \
-- _tmp = _start >> 5; \
-- _frag = le32_to_cpu(_map[_tmp]); \
-- _v2 = le32_to_cpu(_map[_tmp + 1]); \
-- _tmp = start & 31; \
-- _frag = (_frag >> _tmp) | (_v2 << (32 - _tmp)); \
-+ unsigned char *_m = _map + (_start >> 3); \
-+ u32 _frag = get_unaligned((u32 *)_m); \
-+ _frag >>= (_start & 7); \
- _frag & _idmask; \
-- })
-+ })
-
- /*
- * return the map bit offset of the fragment frag_id in
-@@ -44,14 +47,13 @@
- const unsigned int frag_id, unsigned int *offset)
- {
- const unsigned int mapsize = dm->dm_endbit;
-- const unsigned int idmask = (1 << idlen) - 1;
-- unsigned long *map = ((unsigned long *)dm->dm_bh->b_data) + 1;
-+ const u32 idmask = (1 << idlen) - 1;
-+ unsigned char *map = dm->dm_bh->b_data + 4;
- unsigned int start = dm->dm_startbit;
- unsigned int mapptr;
-+ u32 frag;
-
- do {
-- unsigned long frag;
--
- frag = GET_FRAG_ID(map, start, idmask);
- mapptr = start + idlen;
-
-@@ -59,15 +61,17 @@
- * find end of fragment
- */
- {
-- unsigned long v2;
-+ u32 v, *_map = (u32 *)map;
-
-- while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
-+ v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
-+ while (v == 0) {
- mapptr = (mapptr & ~31) + 32;
- if (mapptr >= mapsize)
- goto error;
-+ v = le32_to_cpu(_map[mapptr >> 5]);
- }
-
-- mapptr += 1 + ffz(~v2);
-+ mapptr += 1 + ffz(~v);
- }
-
- if (frag == frag_id)
-@@ -75,8 +79,11 @@
- again:
- start = mapptr;
- } while (mapptr < mapsize);
-+ return -1;
-
- error:
-+ printk(KERN_ERR "adfs: oversized fragment 0x%x at 0x%x-0x%x\n",
-+ frag, start, mapptr);
- return -1;
-
- found:
-@@ -102,10 +109,10 @@
- const unsigned int mapsize = dm->dm_endbit + 32;
- const unsigned int idlen = asb->s_idlen;
- const unsigned int frag_idlen = idlen <= 15 ? idlen : 15;
-- const unsigned int idmask = (1 << frag_idlen) - 1;
-- unsigned long *map = (unsigned long *)dm->dm_bh->b_data;
-+ const u32 idmask = (1 << frag_idlen) - 1;
-+ unsigned char *map = dm->dm_bh->b_data;
- unsigned int start = 8, mapptr;
-- unsigned long frag;
-+ u32 frag;
- unsigned long total = 0;
-
- /*
-@@ -133,15 +140,17 @@
- * find end of fragment
- */
- {
-- unsigned long v2;
-+ u32 v, *_map = (u32 *)map;
-
-- while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
-+ v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
-+ while (v == 0) {
- mapptr = (mapptr & ~31) + 32;
- if (mapptr >= mapsize)
- goto error;
-+ v = le32_to_cpu(_map[mapptr >> 5]);
- }
-
-- mapptr += 1 + ffz(~v2);
-+ mapptr += 1 + ffz(~v);
- }
-
- total += mapptr - start;
---- linux-2.4.25/fs/adfs/super.c~2.4.25-vrs2.patch 2002-02-25 20:38:07.000000000 +0100
-+++ linux-2.4.25/fs/adfs/super.c 2004-03-31 17:15:09.000000000 +0200
-@@ -386,6 +386,14 @@
- sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits);
- sb->u.adfs_sb.s_version = dr->format_version;
- sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize;
-+
-+ printk(KERN_DEBUG "ADFS: idlen %d map bit size %d sector size %d\n",
-+ dr->idlen, 1 << dr->log2bpmb, 1 << dr->log2secsize);
-+ printk(KERN_DEBUG "ADFS: map size %d map2blk %d version %d share size %d\n",
-+ sb->u.adfs_sb.s_map_size,
-+ sb->u.adfs_sb.s_map2blk,
-+ sb->u.adfs_sb.s_version,
-+ 1 << sb->u.adfs_sb.s_log2sharesize);
-
- sb->u.adfs_sb.s_map = adfs_read_map(sb, dr);
- if (!sb->u.adfs_sb.s_map)
-@@ -393,6 +401,8 @@
-
- brelse(bh);
-
-+ printk(KERN_DEBUG "ADFS: ids per zone %d\n", sb->u.adfs_sb.s_ids_per_zone);
-+
- /*
- * set up enough so that we can read an inode
- */
---- linux-2.4.25/fs/binfmt_aout.c~2.4.25-vrs2.patch 2001-11-03 02:39:20.000000000 +0100
-+++ linux-2.4.25/fs/binfmt_aout.c 2004-03-31 17:15:09.000000000 +0200
-@@ -422,7 +422,11 @@
- start_thread(regs, ex.a_entry, current->mm->start_stack);
- if (current->ptrace & PT_PTRACED)
- send_sig(SIGTRAP, current, 0);
-+#ifndef __arm__
- return 0;
-+#else
-+ return regs->ARM_r0;
-+#endif
- }
-
- static int load_aout_library(struct file *file)
-@@ -452,8 +456,11 @@
-
- /* For QMAGIC, the starting address is 0x20 into the page. We mask
- this off to get the starting address for the page */
--
-- start_addr = ex.a_entry & 0xfffff000;
-+#ifndef __arm__
-+ start_addr = ex.a_entry & 0xfffff000;
-+#else
-+ start_addr = ex.a_entry & 0xffff8000;
-+#endif
-
- if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
- static unsigned long error_time;
---- linux-2.4.25/fs/binfmt_elf.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/fs/binfmt_elf.c 2004-03-31 17:15:09.000000000 +0200
-@@ -635,7 +635,6 @@
- }
-
- current->mm->start_stack = bprm->p;
--
- /* Now we do a little grungy work by mmaping the ELF image into
- the correct location in memory. At this point, we assume that
- the image should be loaded at fixed address, not at a variable
---- linux-2.4.25/fs/exec.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/fs/exec.c 2004-03-31 17:15:09.000000000 +0200
-@@ -315,6 +315,7 @@
- spin_unlock(&tsk->mm->page_table_lock);
-
- /* no need for flush_tlb */
-+ memc_update_addr(tsk->mm, *pte, address);
- return;
- out:
- spin_unlock(&tsk->mm->page_table_lock);
---- linux-2.4.25/fs/jffs/inode-v23.c~2.4.25-vrs2.patch 2001-10-05 00:14:35.000000000 +0200
-+++ linux-2.4.25/fs/jffs/inode-v23.c 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
-+ * $Id: inode-v23.c,v 1.72 2002/01/31 11:42:57 cdavies Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -48,6 +48,7 @@
- #include <linux/stat.h>
- #include <linux/blkdev.h>
- #include <linux/quotaops.h>
-+#include <linux/compatmac.h>
- #include <asm/semaphore.h>
- #include <asm/byteorder.h>
- #include <asm/uaccess.h>
-@@ -58,6 +59,11 @@
- #include "jffs_proc.h"
- #endif
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
-+#define minor(x) MINOR(x)
-+#define major(x) MAJOR(x)
-+#endif
-+
- static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-
- static struct super_operations jffs_ops;
-@@ -81,7 +87,7 @@
- D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
- kdevname(dev)));
-
-- if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
-+ if (major(dev) != MTD_BLOCK_MAJOR) {
- printk(KERN_WARNING "JFFS: Trying to mount a "
- "non-mtd device.\n");
- return 0;
-@@ -358,7 +364,7 @@
- inode->i_nlink = raw_inode->nlink;
- inode->i_uid = raw_inode->uid;
- inode->i_gid = raw_inode->gid;
-- inode->i_rdev = 0;
-+ inode->i_rdev = NODEV;
- inode->i_size = raw_inode->dsize;
- inode->i_atime = raw_inode->atime;
- inode->i_mtime = raw_inode->mtime;
---- linux-2.4.25/fs/jffs/intrep.c~2.4.25-vrs2.patch 2003-06-13 16:51:37.000000000 +0200
-+++ linux-2.4.25/fs/jffs/intrep.c 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
-+ * $Id: intrep.c,v 1.104 2002/03/05 14:07:39 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -772,6 +772,9 @@
- __u32 free_chunk_size1;
- __u32 free_chunk_size2;
-
-+ __u32 largest_hole = 0;
-+ __u32 hole_end_offset = 0;
-+ __u32 head_offset;
-
- #define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
- int num_free_space = 0; /* Flag err if more than TWO
-@@ -884,6 +887,21 @@
- (unsigned int) start,
- (unsigned int)(test_start - start)));
-
-+ D1(printk("Reducing start to 0x%x from 0x%x\n",
-+ test_start, start));
-+ if (largest_hole < test_start - start){
-+
-+ D3(printk("was hole = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ if (fmc->head) {
-+ largest_hole = test_start - start;
-+ hole_end_offset = test_start;
-+ }
-+ }
-+
-+ D3(printk("now = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+
- /* below, space from "start" to "pos" will be marked dirty. */
- start = test_start;
-
-@@ -956,6 +974,19 @@
- num_free_space++;
- D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start, (unsigned int) (pos - start)));
-+
-+ if (largest_hole < pos - start) {
-+
-+ D3(printk("was hole = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ if (fmc->head){
-+ largest_hole = pos - start;
-+ hole_end_offset = pos;
-+ }
-+
-+ D3(printk("now = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ }
- }else{
- num_free_spc_not_accp++;
- D1(printk("Free space (#%i) found but *Not* accepted: Starting "
-@@ -968,7 +999,7 @@
- (unsigned int) start, (unsigned int) (pos - start)));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
-- }
-+ }
-
- }
- if(num_free_space > NUMFREEALLOWED){
-@@ -1002,9 +1033,11 @@
- to scan for the magic pattern. */
- D1(printk("*************** Dirty flash memory or "
- "bad inode: "
-- "hexdump(pos = 0x%lx, len = 128):\n",
-- (long)pos));
-- D1(jffs_hexdump(fmc->mtd, pos, 128));
-+ "hexdump(pos = 0x%lx, len = %d):\n",
-+ (long)pos,
-+ end - pos > 128 ? 128 : end - pos));
-+ D1(jffs_hexdump(fmc->mtd, pos,
-+ end - pos > 128 ? 128 : end - pos));
-
- for (pos += 4; pos < end; pos += 4) {
- switch (flash_read_u32(fmc->mtd, pos)) {
-@@ -1197,12 +1230,6 @@
-
- return -ENOMEM;
- }
-- if ((err = jffs_insert_node(c, 0, &raw_inode,
-- name, node)) < 0) {
-- printk("JFFS: Failed to handle raw inode. "
-- "(err = %d)\n", err);
-- break;
-- }
- if (raw_inode.rename) {
- struct jffs_delete_list *dl
- = (struct jffs_delete_list *)
-@@ -1226,6 +1253,12 @@
- c->delete_list = dl;
- node->data_size = 0;
- }
-+ if ((err = jffs_insert_node(c, 0, &raw_inode,
-+ name, node)) < 0) {
-+ printk("JFFS: Failed to handle raw inode. "
-+ "(err = %d)\n", err);
-+ break;
-+ }
- D3(jffs_print_node(node));
- node = 0; /* Don't free the node! */
- }
-@@ -1242,7 +1275,19 @@
- jffs_free_node(node);
- DJM(no_jffs_node--);
- }
-- jffs_build_end(fmc);
-+ if (fmc->head && fmc->tail_extra &&
-+ fmc->head->offset + fmc->flash_size -
-+ fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole) {
-+ head_offset = fmc->head->offset;
-+ }
-+ else {
-+ head_offset = hole_end_offset;
-+ }
-+
-+ if (jffs_build_end(fmc, head_offset) < 0) {
-+ D(printk("jffs_build_end() failed\n"));
-+ return -ENOMEM;
-+ }
-
- /* Free read buffer */
- kfree (read_buf);
---- linux-2.4.25/fs/jffs/jffs_fm.c~2.4.25-vrs2.patch 2001-10-05 00:13:18.000000000 +0200
-+++ linux-2.4.25/fs/jffs/jffs_fm.c 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
-+ * $Id: jffs_fm.c,v 1.29 2002/01/22 09:48:16 cdavies Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -20,8 +20,14 @@
- #include <linux/slab.h>
- #include <linux/blkdev.h>
- #include <linux/jffs.h>
-+#include <linux/compatmac.h>
- #include "jffs_fm.h"
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
-+#define minor(x) MINOR(x)
-+#define major(x) MAJOR(x)
-+#endif
-+
- #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
- static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
- #endif
-@@ -46,7 +52,7 @@
- }
- DJM(no_jffs_fmcontrol++);
-
-- mtd = get_mtd_device(NULL, MINOR(dev));
-+ mtd = get_mtd_device(NULL, minor(dev));
-
- if (!mtd) {
- kfree(fmc);
-@@ -89,8 +95,8 @@
-
- /* When the flash memory scan has completed, this function should be called
- before use of the control structure. */
--void
--jffs_build_end(struct jffs_fmcontrol *fmc)
-+int
-+jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset)
- {
- D3(printk("jffs_build_end()\n"));
-
-@@ -99,13 +105,100 @@
- fmc->tail = fmc->tail_extra;
- }
- else if (fmc->head_extra) {
-- fmc->tail_extra->next = fmc->head;
-- fmc->head->prev = fmc->tail_extra;
-- fmc->head = fmc->head_extra;
-+ struct jffs_fm *fm, *cur;
-+
-+ if (head_offset == fmc->head->offset){
-+ fmc->tail->next = fmc->head_extra;
-+ fmc->head_extra->prev = fmc->tail;
-+ fmc->tail = fmc->tail_extra;
-+ }
-+ else {
-+ fmc->tail_extra->next = fmc->head;
-+ fmc->head->prev = fmc->tail_extra;
-+ fmc->head = fmc->head_extra;
-+ while (fmc->head->offset != head_offset){
-+ fmc->tail->next = fmc->head;
-+ fmc->head = fmc->head->next;
-+ fmc->head->prev = 0;
-+ fmc->tail->next->prev = fmc->tail;
-+ fmc->tail = fmc->tail->next;
-+ fmc->tail->next = 0;
-+ }
-+ }
-+ /* Make sure the only free space we have is between tail and head.
-+ */
-+ for (cur = fmc->head; cur && cur != fmc->tail;) {
-+ if (cur->offset + cur->size < cur->next->offset) {
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = cur->next->offset - cur->offset - cur->size;
-+ fm->offset = cur->offset + cur->size;
-+ fm->nodes = 0;
-+ fm->next = cur->next;
-+ fm->prev = cur;
-+ cur->next->prev = fm;
-+ cur->next = fm;
-+ cur = fm->next;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ else if (cur->offset > cur->next->offset) {
-+ if (cur->offset + cur->size < fmc->flash_size){
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))){
-+
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = fmc->flash_size -
-+ cur->offset - cur->size;
-+ fm->nodes = 0;
-+ fm->offset = cur->offset + cur->size;
-+ fm->next = cur->next;
-+ fm->prev = cur;
-+ cur->next->prev = fm;
-+ cur->next = fm;
-+ cur = fm->next;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ else {
-+ cur = cur->next;
-+ }
-+ if (cur->offset > 0) {
-+
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = cur->offset;
-+ fm->nodes = 0;
-+ fm->offset = 0;
-+ fm->next = cur;
-+ fm->prev = cur->prev;
-+ cur->prev->next = fm;
-+ cur->prev = fm;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ }
-+ else if (cur->offset + cur->size != cur->next->offset) {
-+ printk("jffs_build_end(): Internal error.\n");
-+ return -EINVAL;
-+ }
-+ else {
-+ cur = cur->next;
-+ }
-+ }
- }
- fmc->head_extra = 0; /* These two instructions should be omitted. */
- fmc->tail_extra = 0;
- D3(jffs_print_fmcontrol(fmc));
-+ return 0;
- }
-
-
---- linux-2.4.25/fs/jffs/jffs_fm.h~2.4.25-vrs2.patch 2001-10-05 00:13:18.000000000 +0200
-+++ linux-2.4.25/fs/jffs/jffs_fm.h 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
-+ * $Id: jffs_fm.h,v 1.14 2001/12/10 17:37:12 asanochkin Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -123,7 +123,7 @@
-
-
- struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, kdev_t dev);
--void jffs_build_end(struct jffs_fmcontrol *fmc);
-+int jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset);
- void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
-
- int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
---- linux-2.4.25/fs/partitions/Config.in~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.25/fs/partitions/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -6,6 +6,7 @@
- bool ' Acorn partition support' CONFIG_ACORN_PARTITION
- if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
- # bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
-+ bool ' EESOX partition support' CONFIG_ACORN_PARTITION_EESOX
- bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
- bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
- bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
-@@ -52,6 +53,7 @@
- define_bool CONFIG_ACORN_PARTITION y
- define_bool CONFIG_ACORN_PARTITION_ADFS y
- # define_bool CONFIG_ACORN_PARTITION_CUMANA y
-+ define_bool CONFIG_ACORN_PARTITION_EESOX y
- define_bool CONFIG_ACORN_PARTITION_ICS y
- define_bool CONFIG_ACORN_PARTITION_POWERTEC y
- define_bool CONFIG_ACORN_PARTITION_RISCIX y
---- linux-2.4.25/fs/partitions/acorn.c~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/fs/partitions/acorn.c 2004-03-31 17:15:09.000000000 +0200
-@@ -7,7 +7,10 @@
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-- * Scan ADFS partitions on hard disk drives.
-+ * Scan ADFS partitions on hard disk drives. Unfortunately, there
-+ * isn't a standard for partitioning drives on Acorn machines, so
-+ * every single manufacturer of SCSI and IDE cards created their own
-+ * method.
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
-@@ -18,10 +21,18 @@
- #include <linux/genhd.h>
- #include <linux/fs.h>
- #include <linux/pagemap.h>
-+#include <linux/adfs_fs.h>
-
- #include "check.h"
- #include "acorn.h"
-
-+/*
-+ * Partition types. (Oh for reusability)
-+ */
-+#define PARTITION_RISCIX_MFM 1
-+#define PARTITION_RISCIX_SCSI 2
-+#define PARTITION_LINUX 9
-+
- static void
- adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
- {
-@@ -61,6 +72,21 @@
- }
-
- #ifdef CONFIG_ACORN_PARTITION_RISCIX
-+
-+struct riscix_part {
-+ __u32 start;
-+ __u32 length;
-+ __u32 one;
-+ char name[16];
-+};
-+
-+struct riscix_record {
-+ __u32 magic;
-+#define RISCIX_MAGIC (0x4a657320)
-+ __u32 date;
-+ struct riscix_part part[8];
-+};
-+
- static int
- riscix_partition(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sect, int minor, unsigned long nr_sects)
-@@ -102,6 +128,15 @@
- }
- #endif
-
-+#define LINUX_NATIVE_MAGIC 0xdeafa1de
-+#define LINUX_SWAP_MAGIC 0xdeafab1e
-+
-+struct linux_part {
-+ __u32 magic;
-+ __u32 start_sect;
-+ __u32 nr_sects;
-+};
-+
- static int
- linux_partition(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sect, int minor, unsigned long nr_sects)
-@@ -136,7 +171,7 @@
- }
-
- #ifdef CONFIG_ACORN_PARTITION_CUMANA
--static int
-+int
- adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-@@ -147,7 +182,7 @@
- int first = 1;
-
- /*
-- * Try Cumana style partitions - sector 3 contains ADFS boot block
-+ * Try Cumana style partitions - sector 6 contains ADFS boot block
- * with pointer to next 'drive'.
- *
- * There are unknowns in this code - is the 'cylinder number' of the
-@@ -163,13 +198,13 @@
- struct adfs_discrecord *dr;
- unsigned int nr_sects;
-
-- if (!(minor & mask))
-- break;
--
- data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
- if (!data)
- return -1;
-
-+ if (!(minor & mask))
-+ break;
-+
- dr = adfs_partition(hd, name, data, first_sector, minor++);
- if (!dr)
- break;
-@@ -229,7 +264,7 @@
- * hda1 = ADFS partition on first drive.
- * hda2 = non-ADFS partition.
- */
--static int
-+int
- adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-@@ -282,11 +317,18 @@
- break;
- }
- }
-+ printk("\n");
- return 1;
- }
- #endif
-
- #ifdef CONFIG_ACORN_PARTITION_ICS
-+
-+struct ics_part {
-+ __u32 start;
-+ __s32 size;
-+};
-+
- static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
- {
- Sector sect;
-@@ -303,6 +345,22 @@
- }
-
- /*
-+ * Check for a valid ICS partition using the checksum.
-+ */
-+static inline int valid_ics_sector(const unsigned char *data)
-+{
-+ unsigned long sum;
-+ int i;
-+
-+ for (i = 0, sum = 0x50617274; i < 508; i++)
-+ sum += data[i];
-+
-+ sum -= le32_to_cpu(*(__u32 *)(&data[508]));
-+
-+ return sum == 0;
-+}
-+
-+/*
- * Purpose: allocate ICS partitions.
- * Params : hd - pointer to gendisk structure to store partition info.
- * dev - device number to access.
-@@ -314,15 +372,14 @@
- * hda2 = ADFS partition 1 on first drive.
- * ..etc..
- */
--static int
-+int
- adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-+ const unsigned char *data;
-+ const struct ics_part *p;
-+ unsigned int mask = (1 << hd->minor_shift) - 1;
- Sector sect;
-- unsigned char *data;
-- unsigned long sum;
-- unsigned int i, mask = (1 << hd->minor_shift) - 1;
-- struct ics_part *p;
-
- /*
- * Try ICS style partitions - sector 0 contains partition info.
-@@ -331,21 +388,14 @@
- if (!data)
- return -1;
-
-- /*
-- * check for a valid checksum
-- */
-- for (i = 0, sum = 0x50617274; i < 508; i++)
-- sum += data[i];
--
-- sum -= le32_to_cpu(*(__u32 *)(&data[508]));
-- if (sum) {
-- put_dev_sector(sect);
-- return 0; /* not ICS partition table */
-+ if (!valid_ics_sector(data)) {
-+ put_dev_sector(sect);
-+ return 0;
- }
-
- printk(" [ICS]");
-
-- for (p = (struct ics_part *)data; p->size; p++) {
-+ for (p = (const struct ics_part *)data; p->size; p++) {
- unsigned long start;
- long size;
-
-@@ -355,12 +405,19 @@
- start = le32_to_cpu(p->start);
- size = le32_to_cpu(p->size);
-
-+ /*
-+ * Negative sizes tell the RISC OS ICS driver to ignore
-+ * this partition - in effect it says that this does not
-+ * contain an ADFS filesystem.
-+ */
- if (size < 0) {
- size = -size;
-
- /*
-- * We use the first sector to identify what type
-- * this partition is...
-+ * Our own extension - We use the first sector
-+ * of the partition to identify what type this
-+ * partition is. We must not make this visible
-+ * to the filesystem.
- */
- if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
- start += 1;
-@@ -375,10 +432,32 @@
- }
-
- put_dev_sector(sect);
-+ printk("\n");
- return 1;
- }
- #endif
-
-+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-+struct ptec_part {
-+ __u32 unused1;
-+ __u32 unused2;
-+ __u32 start;
-+ __u32 size;
-+ __u32 unused5;
-+ char type[8];
-+};
-+
-+static inline int valid_ptec_sector(const unsigned char *data)
-+{
-+ unsigned char checksum = 0x2a;
-+ int i;
-+
-+ for (i = 0; i < 511; i++)
-+ checksum += data[i];
-+
-+ return checksum == data[511];
-+}
-+
- /*
- * Purpose: allocate ICS partitions.
- * Params : hd - pointer to gendisk structure to store partition info.
-@@ -391,32 +470,27 @@
- * hda2 = ADFS partition 1 on first drive.
- * ..etc..
- */
--#ifdef CONFIG_ACORN_PARTITION_POWERTEC
--static int
-+int
- adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
- Sector sect;
-- unsigned char *data;
-- struct ptec_partition *p;
-- unsigned char checksum;
-+ const unsigned char *data;
-+ const struct ptec_part *p;
- int i;
-
- data = read_dev_sector(bdev, 0, &sect);
- if (!data)
- return -1;
-
-- for (checksum = 0x2a, i = 0; i < 511; i++)
-- checksum += data[i];
--
-- if (checksum != data[511]) {
-+ if (!valid_ptec_sector(data)) {
- put_dev_sector(sect);
- return 0;
- }
-
- printk(" [POWERTEC]");
-
-- for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
-+ for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
- unsigned long start;
- unsigned long size;
-
-@@ -430,49 +504,82 @@
- }
-
- put_dev_sector(sect);
-+ printk("\n");
- return 1;
- }
- #endif
-
--static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
--#ifdef CONFIG_ACORN_PARTITION_ICS
-- adfspart_check_ICS,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-- adfspart_check_POWERTEC,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_CUMANA
-- adfspart_check_CUMANA,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_ADFS
-- adfspart_check_ADFS,
--#endif
-- NULL
-+#ifdef CONFIG_ACORN_PARTITION_EESOX
-+struct eesox_part {
-+ char magic[6];
-+ char name[10];
-+ u32 start;
-+ u32 unused6;
-+ u32 unused7;
-+ u32 unused8;
- };
-+
- /*
-- * Purpose: initialise all the partitions on an ADFS drive.
-- * These may be other ADFS partitions or a Linux/RiscBSD/RISCiX
-- * partition.
-+ * Guess who created this format?
-+ */
-+static const char eesox_name[] = {
-+ 'N', 'e', 'i', 'l', ' ',
-+ 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
-+};
-+
-+/*
-+ * EESOX SCSI partition format.
- *
-- * Params : hd - pointer to gendisk structure
-- * dev - device number to access
-- * first_sect - first available sector on the disk.
-- * first_minor - first available minor on this device.
-+ * This is a goddamned awful partition format. We don't seem to store
-+ * the size of the partition in this table, only the start addresses.
- *
-- * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
-+ * There are two possibilities where the size comes from:
-+ * 1. The individual ADFS boot block entries that are placed on the disk.
-+ * 2. The start address of the next entry.
- */
--int acorn_partition(struct gendisk *hd, struct block_device *bdev,
-- unsigned long first_sect, int first_minor)
-+int
-+adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor)
- {
-+ Sector sect;
-+ const unsigned char *data;
-+ unsigned char buffer[256];
-+ struct eesox_part *p;
-+ u32 start = first_sector;
- int i;
-
-- for (i = 0; partfn[i]; i++) {
-- int r = partfn[i](hd, bdev, first_sect, first_minor);
-- if (r) {
-- if (r > 0)
-- printk("\n");
-- return r;
-- }
-+ data = read_dev_sector(bdev, 7, &sect);
-+ if (!data)
-+ return -1;
-+
-+ /*
-+ * "Decrypt" the partition table. God knows why...
-+ */
-+ for (i = 0; i < 256; i++)
-+ buffer[i] = data[i] ^ eesox_name[i & 15];
-+
-+ put_dev_sector(sect);
-+
-+ for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
-+ u32 next;
-+
-+ if (memcmp(p->magic, "Eesox", 6))
-+ break;
-+
-+ next = le32_to_cpu(p->start) + first_sector;
-+ if (i)
-+ add_gd_partition(hd, minor++, start, next - start);
-+ start = next;
- }
-- return 0;
-+
-+ if (i != 0) {
-+ unsigned long size;
-+
-+ size = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects;
-+ add_gd_partition(hd, minor++, start, size - start);
-+ printk("\n");
-+ }
-+
-+ return i ? 1 : 0;
- }
-+#endif
---- linux-2.4.25/fs/partitions/acorn.h~2.4.25-vrs2.patch 2001-11-22 20:48:07.000000000 +0100
-+++ linux-2.4.25/fs/partitions/acorn.h 2004-03-31 17:15:09.000000000 +0200
-@@ -1,55 +1,28 @@
- /*
-- * fs/partitions/acorn.h
-+ * linux/fs/partitions/acorn.h
- *
-- * Copyright (C) 1996-1998 Russell King
-- */
--#include <linux/adfs_fs.h>
--
--/*
-- * Partition types. (Oh for reusability)
-+ * Copyright (C) 1996-2001 Russell King.
-+ *
-+ * I _hate_ this partitioning mess - why can't we have one defined
-+ * format, and everyone stick to it?
- */
--#define PARTITION_RISCIX_MFM 1
--#define PARTITION_RISCIX_SCSI 2
--#define PARTITION_LINUX 9
--
--struct riscix_part {
-- __u32 start;
-- __u32 length;
-- __u32 one;
-- char name[16];
--};
-
--struct riscix_record {
-- __u32 magic;
--#define RISCIX_MAGIC (0x4a657320)
-- __u32 date;
-- struct riscix_part part[8];
--};
--
--#define LINUX_NATIVE_MAGIC 0xdeafa1de
--#define LINUX_SWAP_MAGIC 0xdeafab1e
--
--struct linux_part {
-- __u32 magic;
-- __u32 start_sect;
-- __u32 nr_sects;
--};
-+int
-+adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--struct ics_part {
-- __u32 start;
-- __s32 size;
--};
-+int
-+adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--struct ptec_partition {
-- __u32 unused1;
-- __u32 unused2;
-- __u32 start;
-- __u32 size;
-- __u32 unused5;
-- char type[8];
--};
--
-+int
-+adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--int acorn_partition(struct gendisk *hd, struct block_device *bdev,
-- unsigned long first_sect, int first_minor);
-+int
-+adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
-+int
-+adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
---- linux-2.4.25/fs/partitions/check.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/fs/partitions/check.c 2004-03-31 17:15:09.000000000 +0200
-@@ -40,8 +40,30 @@
- int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
-
- static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
--#ifdef CONFIG_ACORN_PARTITION
-- acorn_partition,
-+ /*
-+ * Probe partition formats with tables at disk address 0
-+ * that also have an ADFS boot block at 0xdc0.
-+ */
-+#ifdef CONFIG_ACORN_PARTITION_ICS
-+ adfspart_check_ICS,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-+ adfspart_check_POWERTEC,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_EESOX
-+ adfspart_check_EESOX,
-+#endif
-+
-+ /*
-+ * Now move on to formats that only have partition info at
-+ * disk address 0xdc0. These should come before MSDOS
-+ * partition tables.
-+ */
-+#ifdef CONFIG_ACORN_PARTITION_CUMANA
-+ adfspart_check_CUMANA,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_ADFS
-+ adfspart_check_ADFS,
- #endif
- #ifdef CONFIG_SGI_PARTITION
- sgi_partition,
-@@ -79,13 +101,25 @@
- NULL
- };
-
-+static char *raid_name (struct gendisk *hd, unsigned int unit, unsigned int part,
-+ int major_base, char *buf)
-+{
-+ int ctlr = hd->major - major_base;
-+ if (part == 0)
-+ sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, unit);
-+ else
-+ sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, unit,
-+ part);
-+ return buf;
-+}
-+
- /*
- * This is ucking fugly but its probably the best thing for 2.4.x
- * Take it as a clear reminder that: 1) we should put the device name
- * generation in the object kdev_t points to in 2.5.
- * and 2) ioctls better work on half-opened devices.
- */
--
-+
- #ifdef CONFIG_ARCH_S390
- int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
- int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
-@@ -104,10 +138,11 @@
- char *disk_name (struct gendisk *hd, int minor, char *buf)
- {
- const char *maj = hd->major_name;
-- unsigned int unit = (minor >> hd->minor_shift);
-- unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
-+ unsigned int unit = minor >> hd->minor_shift;
-+ unsigned int part = minor & (( 1 << hd->minor_shift) - 1);
-+ char *p;
-
-- if ((unit < hd->nr_real) && hd->part[minor].de) {
-+ if (unit < hd->nr_real && hd->part[minor].de) {
- int pos;
-
- pos = devfs_generate_path (hd->part[minor].de, buf, 64);
-@@ -153,51 +188,32 @@
- }
- if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
- unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
-- if (unit+'a' > 'z') {
-- unit -= 26;
-- sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
-- if (part)
-- sprintf(buf + 4, "%d", part);
-- return buf;
-- }
- }
- if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
-- int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
-- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-- return buf;
-- }
-+ return raid_name(hd, unit, part, COMPAQ_SMART2_MAJOR, buf);
-+ }
- if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
-- int ctlr = hd->major - COMPAQ_CISS_MAJOR;
-- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-- return buf;
-+ return raid_name(hd, unit, part, COMPAQ_CISS_MAJOR, buf);
- }
- if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
-- int ctlr = hd->major - DAC960_MAJOR;
-+ return raid_name(hd, unit, part, DAC960_MAJOR, buf);
-+ }
-+ if (hd->major == ATARAID_MAJOR) {
-+ int disk = minor >> hd->minor_shift;
-+ int part = minor & (( 1 << hd->minor_shift) - 1);
- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-+ sprintf(buf, "%s/d%d", maj, disk);
- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-+ sprintf(buf, "%s/d%dp%d", maj, disk, part);
- return buf;
- }
-- if (hd->major == ATARAID_MAJOR) {
-- int disk = minor >> hd->minor_shift;
-- int part = minor & (( 1 << hd->minor_shift) - 1);
-- if (part == 0)
-- sprintf(buf, "%s/d%d", maj, disk);
-- else
-- sprintf(buf, "%s/d%dp%d", maj, disk, part);
-- return buf;
-- }
-- if (part)
-- sprintf(buf, "%s%c%d", maj, unit+'a', part);
-+ p = buf;
-+ if (unit <= 26)
-+ p += sprintf(buf, "%s%c", maj, 'a' + unit);
- else
-- sprintf(buf, "%s%c", maj, unit+'a');
-+ p += sprintf(buf, "%s%c%c", maj, 'a' + unit / 26, 'a' + unit % 26);
-+ if (part)
-+ sprintf(p, "%d", part);
- return buf;
- }
-
-@@ -207,7 +223,7 @@
- void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
- {
- #ifndef CONFIG_DEVFS_FS
-- char buf[40];
-+ char buf[MAX_DISKNAME_LEN];
- #endif
-
- hd->part[minor].start_sect = start;
-@@ -229,7 +245,7 @@
- static int first_time = 1;
- unsigned long first_sector;
- struct block_device *bdev;
-- char buf[64];
-+ char buf[MAX_DISKNAME_LEN];
- int i;
-
- if (first_time)
---- linux-2.4.25/fs/proc/array.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/fs/proc/array.c 2004-03-31 17:15:09.000000000 +0200
-@@ -362,15 +362,15 @@
- task->cmin_flt,
- task->maj_flt,
- task->cmaj_flt,
-- task->times.tms_utime,
-- task->times.tms_stime,
-- task->times.tms_cutime,
-- task->times.tms_cstime,
-+ hz_to_std(task->times.tms_utime),
-+ hz_to_std(task->times.tms_stime),
-+ hz_to_std(task->times.tms_cutime),
-+ hz_to_std(task->times.tms_cstime),
- priority,
- nice,
- 0UL /* removed */,
- task->it_real_value,
-- task->start_time,
-+ hz_to_std(task->start_time),
- vsize,
- mm ? mm->rss : 0, /* you might want to shift this left 3 */
- task->rlim[RLIMIT_RSS].rlim_cur,
-@@ -417,6 +417,7 @@
- end = PMD_SIZE;
- do {
- pte_t page = *pte;
-+ unsigned long pfn;
- struct page *ptpage;
-
- address += PAGE_SIZE;
-@@ -426,8 +427,11 @@
- ++*total;
- if (!pte_present(page))
- continue;
-- ptpage = pte_page(page);
-- if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
-+ pfn = pte_pfn(page);
-+ if (!pfn_valid(pfn))
-+ continue;
-+ ptpage = pfn_to_page(pfn);
-+ if (PageReserved(ptpage))
- continue;
- ++*pages;
- if (pte_dirty(page))
-@@ -609,14 +613,14 @@
-
- len = sprintf(buffer,
- "cpu %lu %lu\n",
-- task->times.tms_utime,
-- task->times.tms_stime);
-+ hz_to_std(task->times.tms_utime),
-+ hz_to_std(task->times.tms_stime));
-
- for (i = 0 ; i < smp_num_cpus; i++)
- len += sprintf(buffer + len, "cpu%d %lu %lu\n",
- i,
-- task->per_cpu_utime[cpu_logical_map(i)],
-- task->per_cpu_stime[cpu_logical_map(i)]);
-+ hz_to_std(task->per_cpu_utime[cpu_logical_map(i)]),
-+ hz_to_std(task->per_cpu_stime[cpu_logical_map(i)]));
-
- return len;
- }
---- linux-2.4.25/fs/proc/proc_misc.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/fs/proc/proc_misc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -308,16 +308,16 @@
- {
- int i, len = 0;
- extern unsigned long total_forks;
-- unsigned long jif = jiffies;
-+ unsigned long jif = hz_to_std(jiffies);
- unsigned int sum = 0, user = 0, nice = 0, system = 0;
- int major, disk;
-
- for (i = 0 ; i < smp_num_cpus; i++) {
- int cpu = cpu_logical_map(i), j;
-
-- user += kstat.per_cpu_user[cpu];
-- nice += kstat.per_cpu_nice[cpu];
-- system += kstat.per_cpu_system[cpu];
-+ user += hz_to_std(kstat.per_cpu_user[cpu]);
-+ nice += hz_to_std(kstat.per_cpu_nice[cpu]);
-+ system += hz_to_std(kstat.per_cpu_system[cpu]);
- #if !defined(CONFIG_ARCH_S390)
- for (j = 0 ; j < NR_IRQS ; j++)
- sum += kstat.irqs[cpu][j];
-@@ -331,10 +331,10 @@
- proc_sprintf(page, &off, &len,
- "cpu%d %u %u %u %lu\n",
- i,
-- kstat.per_cpu_user[cpu_logical_map(i)],
-- kstat.per_cpu_nice[cpu_logical_map(i)],
-- kstat.per_cpu_system[cpu_logical_map(i)],
-- jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
-+ hz_to_std(kstat.per_cpu_user[cpu_logical_map(i)]),
-+ hz_to_std(kstat.per_cpu_nice[cpu_logical_map(i)]),
-+ hz_to_std(kstat.per_cpu_system[cpu_logical_map(i)]),
-+ jif - hz_to_std( kstat.per_cpu_user[cpu_logical_map(i)] \
- + kstat.per_cpu_nice[cpu_logical_map(i)] \
- + kstat.per_cpu_system[cpu_logical_map(i)]));
- proc_sprintf(page, &off, &len,
-@@ -440,12 +440,14 @@
- return proc_calc_metrics(page, start, off, count, eof, len);
- }
-
-+#ifdef CONFIG_GENERIC_ISA_DMA
- static int dma_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- int len = get_dma_list(page);
- return proc_calc_metrics(page, start, off, count, eof, len);
- }
-+#endif
-
- static int cmdline_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-@@ -613,7 +615,9 @@
- {"interrupts", interrupts_read_proc},
- #endif
- {"filesystems", filesystems_read_proc},
-+#ifdef CONFIG_GENERIC_ISA_DMA
- {"dma", dma_read_proc},
-+#endif
- {"cmdline", cmdline_read_proc},
- #ifdef CONFIG_SGI_DS1286
- {"rtc", ds1286_read_proc},
---- linux-2.4.25/fs/stat.c~2.4.25-vrs2.patch 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.25/fs/stat.c 2004-03-31 17:15:09.000000000 +0200
-@@ -26,7 +26,9 @@
- }
-
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
-@@ -38,7 +40,7 @@
- struct __old_kernel_stat tmp;
-
- memset(&tmp, 0, sizeof(struct __old_kernel_stat));
--
-+
- if (warncount > 0) {
- warncount--;
- printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
-@@ -58,7 +60,7 @@
- #if BITS_PER_LONG == 32
- if (inode->i_size > MAX_NON_LFS)
- return -EOVERFLOW;
--#endif
-+#endif
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
-@@ -84,7 +86,7 @@
- #if BITS_PER_LONG == 32
- if (inode->i_size > MAX_NON_LFS)
- return -EOVERFLOW;
--#endif
-+#endif
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
-@@ -129,7 +131,9 @@
- }
-
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
- /*
- * For backward compatibility? Maybe this should be moved
- * into arch/i386 instead?
-@@ -165,7 +169,9 @@
- return error;
- }
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
-@@ -203,7 +209,9 @@
- return error;
- }
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
---- linux-2.4.25/include/asm-alpha/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/asm-alpha/ide.h 2004-03-31 17:15:09.000000000 +0200
-@@ -19,35 +19,15 @@
- #define MAX_HWIFS 4
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- switch (base) {
-- case 0x1f0: return 14;
-- case 0x170: return 15;
-- case 0x1e8: return 11;
-- case 0x168: return 10;
-- default:
-- return 0;
-- }
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- switch (index) {
-- case 0: return 0x1f0;
-- case 1: return 0x170;
-- case 2: return 0x1e8;
-- case 3: return 0x168;
-- default:
-- return 0;
-- }
--}
-+#define ide_default_io_base(i) ((ide_ioreg_t)0)
-+#define ide_default_irq(b) (0)
-
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
- ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(hw, 0, sizeof(*hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -55,7 +35,7 @@
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
-- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-+ hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
- }
- if (irq != NULL)
- *irq = 0;
-@@ -70,13 +50,19 @@
- {
- #ifndef CONFIG_BLK_DEV_IDEPCI
- hw_regs_t hw;
-- int index;
-
-- for (index = 0; index < MAX_HWIFS; index++) {
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
-+ ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
-+ hw.irq = 14;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
-+ hw.irq = 15;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
-+ hw.irq = 11;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
-+ hw.irq = 10;
-+ ide_register_hw(&hw, NULL);
- #endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
---- linux-2.4.25/include/asm-alpha/param.h~2.4.25-vrs2.patch 2000-11-08 08:37:31.000000000 +0100
-+++ linux-2.4.25/include/asm-alpha/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -13,6 +13,9 @@
- # else
- # define HZ 1200
- # endif
-+#ifdef __KERNEL__
-+# define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,127 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 / MCI definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_MCI_H
-+#define AT91RM9200_MCI_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Multimedia Card Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_MCI {
-+ AT91_REG MCI_CR; // MCI Control Register
-+ AT91_REG MCI_MR; // MCI Mode Register
-+ AT91_REG MCI_DTOR; // MCI Data Timeout Register
-+ AT91_REG MCI_SDCR; // MCI SD Card Register
-+ AT91_REG MCI_ARGR; // MCI Argument Register
-+ AT91_REG MCI_CMDR; // MCI Command Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG MCI_RSPR[4]; // MCI Response Register
-+ AT91_REG MCI_RDR; // MCI Receive Data Register
-+ AT91_REG MCI_TDR; // MCI Transmit Data Register
-+ AT91_REG Reserved1[2]; //
-+ AT91_REG MCI_SR; // MCI Status Register
-+ AT91_REG MCI_IER; // MCI Interrupt Enable Register
-+ AT91_REG MCI_IDR; // MCI Interrupt Disable Register
-+ AT91_REG MCI_IMR; // MCI Interrupt Mask Register
-+ AT91_REG Reserved2[44]; //
-+ AT91_REG MCI_RPR; // Receive Pointer Register
-+ AT91_REG MCI_RCR; // Receive Counter Register
-+ AT91_REG MCI_TPR; // Transmit Pointer Register
-+ AT91_REG MCI_TCR; // Transmit Counter Register
-+ AT91_REG MCI_RNPR; // Receive Next Pointer Register
-+ AT91_REG MCI_RNCR; // Receive Next Counter Register
-+ AT91_REG MCI_TNPR; // Transmit Next Pointer Register
-+ AT91_REG MCI_TNCR; // Transmit Next Counter Register
-+ AT91_REG MCI_PTCR; // PDC Transfer Control Register
-+ AT91_REG MCI_PTSR; // PDC Transfer Status Register
-+} AT91S_MCI, *AT91PS_MCI;
-+
-+#endif
-+
-+// -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register --------
-+#define AT91C_MCI_MCIEN ((unsigned int) 0x1 << 0) // (MCI) Multimedia Interface Enable
-+#define AT91C_MCI_MCIDIS ((unsigned int) 0x1 << 1) // (MCI) Multimedia Interface Disable
-+#define AT91C_MCI_PWSEN ((unsigned int) 0x1 << 2) // (MCI) Power Save Mode Enable
-+#define AT91C_MCI_PWSDIS ((unsigned int) 0x1 << 3) // (MCI) Power Save Mode Disable
-+// -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register --------
-+#define AT91C_MCI_CLKDIV ((unsigned int) 0x1 << 0) // (MCI) Clock Divider
-+#define AT91C_MCI_PWSDIV ((unsigned int) 0x1 << 8) // (MCI) Power Saving Divider
-+#define AT91C_MCI_PDCPADV ((unsigned int) 0x1 << 14) // (MCI) PDC Padding Value
-+#define AT91C_MCI_PDCMODE ((unsigned int) 0x1 << 15) // (MCI) PDC Oriented Mode
-+#define AT91C_MCI_BLKLEN ((unsigned int) 0x1 << 18) // (MCI) Data Block Length
-+// -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register --------
-+#define AT91C_MCI_DTOCYC ((unsigned int) 0x1 << 0) // (MCI) Data Timeout Cycle Number
-+#define AT91C_MCI_DTOMUL ((unsigned int) 0x7 << 4) // (MCI) Data Timeout Multiplier
-+#define AT91C_MCI_DTOMUL_1 ((unsigned int) 0x0 << 4) // (MCI) DTOCYC x 1
-+#define AT91C_MCI_DTOMUL_16 ((unsigned int) 0x1 << 4) // (MCI) DTOCYC x 16
-+#define AT91C_MCI_DTOMUL_128 ((unsigned int) 0x2 << 4) // (MCI) DTOCYC x 128
-+#define AT91C_MCI_DTOMUL_256 ((unsigned int) 0x3 << 4) // (MCI) DTOCYC x 256
-+#define AT91C_MCI_DTOMUL_1024 ((unsigned int) 0x4 << 4) // (MCI) DTOCYC x 1024
-+#define AT91C_MCI_DTOMUL_4096 ((unsigned int) 0x5 << 4) // (MCI) DTOCYC x 4096
-+#define AT91C_MCI_DTOMUL_65536 ((unsigned int) 0x6 << 4) // (MCI) DTOCYC x 65536
-+#define AT91C_MCI_DTOMUL_1048576 ((unsigned int) 0x7 << 4) // (MCI) DTOCYC x 1048576
-+// -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register --------
-+#define AT91C_MCI_SCDSEL ((unsigned int) 0x1 << 0) // (MCI) SD Card Selector
-+#define AT91C_MCI_SCDBUS ((unsigned int) 0x1 << 7) // (MCI) SD Card Bus Width
-+// -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register --------
-+#define AT91C_MCI_CMDNB ((unsigned int) 0x1F << 0) // (MCI) Command Number
-+#define AT91C_MCI_RSPTYP ((unsigned int) 0x3 << 6) // (MCI) Response Type
-+#define AT91C_MCI_RSPTYP_NO ((unsigned int) 0x0 << 6) // (MCI) No response
-+#define AT91C_MCI_RSPTYP_48 ((unsigned int) 0x1 << 6) // (MCI) 48-bit response
-+#define AT91C_MCI_RSPTYP_136 ((unsigned int) 0x2 << 6) // (MCI) 136-bit response
-+#define AT91C_MCI_SPCMD ((unsigned int) 0x7 << 8) // (MCI) Special CMD
-+#define AT91C_MCI_SPCMD_NONE ((unsigned int) 0x0 << 8) // (MCI) Not a special CMD
-+#define AT91C_MCI_SPCMD_INIT ((unsigned int) 0x1 << 8) // (MCI) Initialization CMD
-+#define AT91C_MCI_SPCMD_SYNC ((unsigned int) 0x2 << 8) // (MCI) Synchronized CMD
-+#define AT91C_MCI_SPCMD_IT_CMD ((unsigned int) 0x4 << 8) // (MCI) Interrupt command
-+#define AT91C_MCI_SPCMD_IT_REP ((unsigned int) 0x5 << 8) // (MCI) Interrupt response
-+#define AT91C_MCI_OPDCMD ((unsigned int) 0x1 << 11) // (MCI) Open Drain Command
-+#define AT91C_MCI_MAXLAT ((unsigned int) 0x1 << 12) // (MCI) Maximum Latency for Command to respond
-+#define AT91C_MCI_TRCMD ((unsigned int) 0x3 << 16) // (MCI) Transfer CMD
-+#define AT91C_MCI_TRCMD_NO ((unsigned int) 0x0 << 16) // (MCI) No transfer
-+#define AT91C_MCI_TRCMD_START ((unsigned int) 0x1 << 16) // (MCI) Start transfer
-+#define AT91C_MCI_TRCMD_STOP ((unsigned int) 0x2 << 16) // (MCI) Stop transfer
-+#define AT91C_MCI_TRDIR ((unsigned int) 0x1 << 18) // (MCI) Transfer Direction
-+#define AT91C_MCI_TRTYP ((unsigned int) 0x3 << 19) // (MCI) Transfer Type
-+#define AT91C_MCI_TRTYP_BLOCK ((unsigned int) 0x0 << 19) // (MCI) Block Transfer type
-+#define AT91C_MCI_TRTYP_MULTIPLE ((unsigned int) 0x1 << 19) // (MCI) Multiple Block transfer type
-+#define AT91C_MCI_TRTYP_STREAM ((unsigned int) 0x2 << 19) // (MCI) Stream transfer type
-+// -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------
-+#define AT91C_MCI_CMDRDY ((unsigned int) 0x1 << 0) // (MCI) Command Ready flag
-+#define AT91C_MCI_RXRDY ((unsigned int) 0x1 << 1) // (MCI) RX Ready flag
-+#define AT91C_MCI_TXRDY ((unsigned int) 0x1 << 2) // (MCI) TX Ready flag
-+#define AT91C_MCI_BLKE ((unsigned int) 0x1 << 3) // (MCI) Data Block Transfer Ended flag
-+#define AT91C_MCI_DTIP ((unsigned int) 0x1 << 4) // (MCI) Data Transfer in Progress flag
-+#define AT91C_MCI_NOTBUSY ((unsigned int) 0x1 << 5) // (MCI) Data Line Not Busy flag
-+#define AT91C_MCI_ENDRX ((unsigned int) 0x1 << 6) // (MCI) End of RX Buffer flag
-+#define AT91C_MCI_ENDTX ((unsigned int) 0x1 << 7) // (MCI) End of TX Buffer flag
-+#define AT91C_MCI_RXBUFF ((unsigned int) 0x1 << 14) // (MCI) RX Buffer Full flag
-+#define AT91C_MCI_TXBUFE ((unsigned int) 0x1 << 15) // (MCI) TX Buffer Empty flag
-+#define AT91C_MCI_RINDE ((unsigned int) 0x1 << 16) // (MCI) Response Index Error flag
-+#define AT91C_MCI_RDIRE ((unsigned int) 0x1 << 17) // (MCI) Response Direction Error flag
-+#define AT91C_MCI_RCRCE ((unsigned int) 0x1 << 18) // (MCI) Response CRC Error flag
-+#define AT91C_MCI_RENDE ((unsigned int) 0x1 << 19) // (MCI) Response End Bit Error flag
-+#define AT91C_MCI_RTOE ((unsigned int) 0x1 << 20) // (MCI) Response Time-out Error flag
-+#define AT91C_MCI_DCRCE ((unsigned int) 0x1 << 21) // (MCI) data CRC Error flag
-+#define AT91C_MCI_DTOE ((unsigned int) 0x1 << 22) // (MCI) Data timeout Error flag
-+#define AT91C_MCI_OVRE ((unsigned int) 0x1 << 30) // (MCI) Overrun flag
-+#define AT91C_MCI_UNRE ((unsigned int) 0x1 << 31) // (MCI) Underrun flag
-+// -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register --------
-+// -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register --------
-+// -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register --------
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,129 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 / SSC definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_SSC_H
-+#define AT91RM9200_SSC_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Synchronous Serial Controller Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_SSC {
-+ AT91_REG SSC_CR; // Control Register
-+ AT91_REG SSC_CMR; // Clock Mode Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG SSC_RCMR; // Receive Clock ModeRegister
-+ AT91_REG SSC_RFMR; // Receive Frame Mode Register
-+ AT91_REG SSC_TCMR; // Transmit Clock Mode Register
-+ AT91_REG SSC_TFMR; // Transmit Frame Mode Register
-+ AT91_REG SSC_RHR; // Receive Holding Register
-+ AT91_REG SSC_THR; // Transmit Holding Register
-+ AT91_REG Reserved1[2]; //
-+ AT91_REG SSC_RSHR; // Receive Sync Holding Register
-+ AT91_REG SSC_TSHR; // Transmit Sync Holding Register
-+ AT91_REG SSC_RC0R; // Receive Compare 0 Register
-+ AT91_REG SSC_RC1R; // Receive Compare 1 Register
-+ AT91_REG SSC_SR; // Status Register
-+ AT91_REG SSC_IER; // Interrupt Enable Register
-+ AT91_REG SSC_IDR; // Interrupt Disable Register
-+ AT91_REG SSC_IMR; // Interrupt Mask Register
-+ AT91_REG Reserved2[44]; //
-+ AT91_REG SSC_RPR; // Receive Pointer Register
-+ AT91_REG SSC_RCR; // Receive Counter Register
-+ AT91_REG SSC_TPR; // Transmit Pointer Register
-+ AT91_REG SSC_TCR; // Transmit Counter Register
-+ AT91_REG SSC_RNPR; // Receive Next Pointer Register
-+ AT91_REG SSC_RNCR; // Receive Next Counter Register
-+ AT91_REG SSC_TNPR; // Transmit Next Pointer Register
-+ AT91_REG SSC_TNCR; // Transmit Next Counter Register
-+ AT91_REG SSC_PTCR; // PDC Transfer Control Register
-+ AT91_REG SSC_PTSR; // PDC Transfer Status Register
-+} AT91S_SSC, *AT91PS_SSC;
-+
-+#endif
-+
-+// -------- SSC_CR : (SSC Offset: 0x0) SSC Control Register --------
-+#define AT91C_SSC_RXEN ( 0x1 << 0) // (SSC) Receive Enable
-+#define AT91C_SSC_RXDIS ( 0x1 << 1) // (SSC) Receive Disable
-+#define AT91C_SSC_TXEN ( 0x1 << 8) // (SSC) Transmit Enable
-+#define AT91C_SSC_TXDIS ( 0x1 << 9) // (SSC) Transmit Disable
-+#define AT91C_SSC_SWRST ( 0x1 << 15) // (SSC) Software Reset
-+// -------- SSC_RCMR : (SSC Offset: 0x10) SSC Receive Clock Mode Register --------
-+#define AT91C_SSC_CKS ( 0x3 << 0) // (SSC) Receive/Transmit Clock Selection
-+#define AT91C_SSC_CKS_DIV ( 0x0) // (SSC) Divided Clock
-+#define AT91C_SSC_CKS_TK ( 0x1) // (SSC) TK Clock signal
-+#define AT91C_SSC_CKS_RK ( 0x2) // (SSC) RK pin
-+#define AT91C_SSC_CKO ( 0x7 << 2) // (SSC) Receive/Transmit Clock Output Mode Selection
-+#define AT91C_SSC_CKO_NONE ( 0x0 << 2) // (SSC) Receive/Transmit Clock Output Mode: None RK pin: Input-only
-+#define AT91C_SSC_CKO_CONTINOUS ( 0x1 << 2) // (SSC) Continuous Receive/Transmit Clock RK pin: Output
-+#define AT91C_SSC_CKO_DATA_TX ( 0x2 << 2) // (SSC) Receive/Transmit Clock only during data transfers RK pin: Output
-+#define AT91C_SSC_CKI ( 0x1 << 5) // (SSC) Receive/Transmit Clock Inversion
-+#define AT91C_SSC_CKG ( 0x3 << 6) // (SSC) Receive/Transmit Clock Gating Selection
-+#define AT91C_SSC_CKG_NONE ( 0x0 << 6) // (SSC) Receive/Transmit Clock Gating: None, continuous clock
-+#define AT91C_SSC_CKG_LOW ( 0x1 << 6) // (SSC) Receive/Transmit Clock enabled only if RF Low
-+#define AT91C_SSC_CKG_HIGH ( 0x2 << 6) // (SSC) Receive/Transmit Clock enabled only if RF High
-+#define AT91C_SSC_START ( 0xF << 8) // (SSC) Receive/Transmit Start Selection
-+#define AT91C_SSC_START_CONTINOUS ( 0x0 << 8) // (SSC) Continuous, as soon as the receiver is enabled, and immediately after the end of transfer of the previous data.
-+#define AT91C_SSC_START_TX ( 0x1 << 8) // (SSC) Transmit/Receive start
-+#define AT91C_SSC_START_LOW_RF ( 0x2 << 8) // (SSC) Detection of a low level on RF input
-+#define AT91C_SSC_START_HIGH_RF ( 0x3 << 8) // (SSC) Detection of a high level on RF input
-+#define AT91C_SSC_START_FALL_RF ( 0x4 << 8) // (SSC) Detection of a falling edge on RF input
-+#define AT91C_SSC_START_RISE_RF ( 0x5 << 8) // (SSC) Detection of a rising edge on RF input
-+#define AT91C_SSC_START_LEVEL_RF ( 0x6 << 8) // (SSC) Detection of any level change on RF input
-+#define AT91C_SSC_START_EDGE_RF ( 0x7 << 8) // (SSC) Detection of any edge on RF input
-+#define AT91C_SSC_START_0 ( 0x8 << 8) // (SSC) Compare 0
-+#define AT91C_SSC_STOP ( 0x1 << 12) // (SSC) Receive Stop Selection
-+#define AT91C_SSC_STTOUT ( 0x1 << 15) // (SSC) Receive/Transmit Start Output Selection
-+#define AT91C_SSC_STTDLY ( 0xFF << 16) // (SSC) Receive/Transmit Start Delay
-+#define AT91C_SSC_PERIOD ( 0xFF << 24) // (SSC) Receive/Transmit Period Divider Selection
-+// -------- SSC_RFMR : (SSC Offset: 0x14) SSC Receive Frame Mode Register --------
-+#define AT91C_SSC_DATLEN ( 0x1F << 0) // (SSC) Data Length
-+#define AT91C_SSC_LOOP ( 0x1 << 5) // (SSC) Loop Mode
-+#define AT91C_SSC_MSBF ( 0x1 << 7) // (SSC) Most Significant Bit First
-+#define AT91C_SSC_DATNB ( 0xF << 8) // (SSC) Data Number per Frame
-+#define AT91C_SSC_FSLEN ( 0xF << 16) // (SSC) Receive/Transmit Frame Sync length
-+#define AT91C_SSC_FSOS ( 0x7 << 20) // (SSC) Receive/Transmit Frame Sync Output Selection
-+#define AT91C_SSC_FSOS_NONE ( 0x0 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: None RK pin Input-only
-+#define AT91C_SSC_FSOS_NEGATIVE ( 0x1 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Negative Pulse
-+#define AT91C_SSC_FSOS_POSITIVE ( 0x2 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Positive Pulse
-+#define AT91C_SSC_FSOS_LOW ( 0x3 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver Low during data transfer
-+#define AT91C_SSC_FSOS_HIGH ( 0x4 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver High during data transfer
-+#define AT91C_SSC_FSOS_TOGGLE ( 0x5 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Toggling at each start of data transfer
-+#define AT91C_SSC_FSEDGE ( 0x1 << 24) // (SSC) Frame Sync Edge Detection
-+// -------- SSC_TCMR : (SSC Offset: 0x18) SSC Transmit Clock Mode Register --------
-+// -------- SSC_TFMR : (SSC Offset: 0x1c) SSC Transmit Frame Mode Register --------
-+#define AT91C_SSC_DATDEF ( 0x1 << 5) // (SSC) Data Default Value
-+#define AT91C_SSC_FSDEN ( 0x1 << 23) // (SSC) Frame Sync Data Enable
-+// -------- SSC_SR : (SSC Offset: 0x40) SSC Status Register --------
-+#define AT91C_SSC_TXRDY ( 0x1 << 0) // (SSC) Transmit Ready
-+#define AT91C_SSC_TXEMPTY ( 0x1 << 1) // (SSC) Transmit Empty
-+#define AT91C_SSC_ENDTX ( 0x1 << 2) // (SSC) End Of Transmission
-+#define AT91C_SSC_TXBUFE ( 0x1 << 3) // (SSC) Transmit Buffer Empty
-+#define AT91C_SSC_RXRDY ( 0x1 << 4) // (SSC) Receive Ready
-+#define AT91C_SSC_OVRUN ( 0x1 << 5) // (SSC) Receive Overrun
-+#define AT91C_SSC_ENDRX ( 0x1 << 6) // (SSC) End of Reception
-+#define AT91C_SSC_RXBUFF ( 0x1 << 7) // (SSC) Receive Buffer Full
-+#define AT91C_SSC_CP0 ( 0x1 << 8) // (SSC) Compare 0
-+#define AT91C_SSC_CP1 ( 0x1 << 9) // (SSC) Compare 1
-+#define AT91C_SSC_TXSYN ( 0x1 << 10) // (SSC) Transmit Sync
-+#define AT91C_SSC_RXSYN ( 0x1 << 11) // (SSC) Receive Sync
-+#define AT91C_SSC_TXENA ( 0x1 << 16) // (SSC) Transmit Enable
-+#define AT91C_SSC_RXENA ( 0x1 << 17) // (SSC) Receive Enable
-+// -------- SSC_IER : (SSC Offset: 0x44) SSC Interrupt Enable Register --------
-+// -------- SSC_IDR : (SSC Offset: 0x48) SSC Interrupt Disable Register --------
-+// -------- SSC_IMR : (SSC Offset: 0x4c) SSC Interrupt Mask Register --------
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,165 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_TC_H
-+#define AT91RM9200_TC_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Timer Counter Channel Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_TC {
-+ AT91_REG TC_CCR; // Channel Control Register
-+ AT91_REG TC_CMR; // Channel Mode Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG TC_CV; // Counter Value
-+ AT91_REG TC_RA; // Register A
-+ AT91_REG TC_RB; // Register B
-+ AT91_REG TC_RC; // Register C
-+ AT91_REG TC_SR; // Status Register
-+ AT91_REG TC_IER; // Interrupt Enable Register
-+ AT91_REG TC_IDR; // Interrupt Disable Register
-+ AT91_REG TC_IMR; // Interrupt Mask Register
-+} AT91S_TC, *AT91PS_TC;
-+
-+typedef struct _AT91S_TCB {
-+ AT91S_TC TCB_TC0; // TC Channel 0
-+ AT91_REG Reserved0[4]; //
-+ AT91S_TC TCB_TC1; // TC Channel 1
-+ AT91_REG Reserved1[4]; //
-+ AT91S_TC TCB_TC2; // TC Channel 2
-+ AT91_REG Reserved2[4]; //
-+ AT91_REG TCB_BCR; // TC Block Control Register
-+ AT91_REG TCB_BMR; // TC Block Mode Register
-+} AT91S_TCB, *AT91PS_TCB;
-+
-+#endif
-+
-+// -------- TC_CCR : (TC Offset: 0x0) TC Channel Control Register --------
-+#define AT91C_TC_CLKEN ( 0x1 << 0) // (TC) Counter Clock Enable Command
-+#define AT91C_TC_CLKDIS ( 0x1 << 1) // (TC) Counter Clock Disable Command
-+#define AT91C_TC_SWTRG ( 0x1 << 2) // (TC) Software Trigger Command
-+// -------- TC_CMR : (TC Offset: 0x4) TC Channel Mode Register: Capture Mode / Waveform Mode --------
-+#define AT91C_TC_TCCLKS ( 0x7 << 0) // (TC) Clock Selection
-+#define AT91C_TC_TIMER_DIV1_CLOCK ( 0x0 << 0) // (TC) MCK/2
-+#define AT91C_TC_TIMER_DIV2_CLOCK ( 0x1 << 0) // (TC) MCK/8
-+#define AT91C_TC_TIMER_DIV3_CLOCK ( 0x2 << 0) // (TC) MCK/32
-+#define AT91C_TC_TIMER_DIV4_CLOCK ( 0x3 << 0) // (TC) MCK/128
-+#define AT91C_TC_TIMER_DIV5_CLOCK ( 0x4 << 0) // (TC) MCK/256 = SLOW CLOCK
-+#define AT91C_TC_TIMER_XC0 ( 0x5 << 0) // (TC) XC0
-+#define AT91C_TC_TIMER_XC1 ( 0x6 << 0) // (TC) XC1
-+#define AT91C_TC_TIMER_XC2 ( 0x7 << 0) // (TC) XC2
-+#define AT91C_TC_CLKI ( 0x1 << 3) // (TC) Clock Invert
-+#define AT91C_TC_BURST ( 0x3 << 4) // (TC) Burst Signal Selection
-+#define AT91C_TC_CPCSTOP ( 0x1 << 6) // (TC) Counter Clock Stopped with RC Compare
-+#define AT91C_TC_CPCDIS ( 0x1 << 7) // (TC) Counter Clock Disable with RC Compare
-+#define AT91C_TC_EEVTEDG ( 0x3 << 8) // (TC) External Event Edge Selection
-+#define AT91C_TC_EEVTEDG_NONE ( 0x0 << 8) // (TC) Edge: None
-+#define AT91C_TC_EEVTEDG_RISING ( 0x1 << 8) // (TC) Edge: rising edge
-+#define AT91C_TC_EEVTEDG_FALLING ( 0x2 << 8) // (TC) Edge: falling edge
-+#define AT91C_TC_EEVTEDG_BOTH ( 0x3 << 8) // (TC) Edge: each edge
-+#define AT91C_TC_EEVT ( 0x3 << 10) // (TC) External Event Selection
-+#define AT91C_TC_EEVT_NONE ( 0x0 << 10) // (TC) Signal selected as external event: TIOB TIOB direction: input
-+#define AT91C_TC_EEVT_RISING ( 0x1 << 10) // (TC) Signal selected as external event: XC0 TIOB direction: output
-+#define AT91C_TC_EEVT_FALLING ( 0x2 << 10) // (TC) Signal selected as external event: XC1 TIOB direction: output
-+#define AT91C_TC_EEVT_BOTH ( 0x3 << 10) // (TC) Signal selected as external event: XC2 TIOB direction: output
-+#define AT91C_TC_ENETRG ( 0x1 << 12) // (TC) External Event Trigger enable
-+#define AT91C_TC_WAVESEL ( 0x3 << 13) // (TC) Waveform Selection
-+#define AT91C_TC_WAVESEL_UP ( 0x0 << 13) // (TC) UP mode without atomatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UP_AUTO ( 0x1 << 13) // (TC) UP mode with automatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UPDOWN ( 0x2 << 13) // (TC) UPDOWN mode without automatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UPDOWN_AUTO ( 0x3 << 13) // (TC) UPDOWN mode with automatic trigger on RC Compare
-+#define AT91C_TC_CPCTRG ( 0x1 << 14) // (TC) RC Compare Trigger Enable
-+#define AT91C_TC_WAVE ( 0x1 << 15) // (TC)
-+#define AT91C_TC_ACPA ( 0x3 << 16) // (TC) RA Compare Effect on TIOA
-+#define AT91C_TC_ACPA_NONE ( 0x0 << 16) // (TC) Effect: none
-+#define AT91C_TC_ACPA_SET ( 0x1 << 16) // (TC) Effect: set
-+#define AT91C_TC_ACPA_CLEAR ( 0x2 << 16) // (TC) Effect: clear
-+#define AT91C_TC_ACPA_TOGGLE ( 0x3 << 16) // (TC) Effect: toggle
-+#define AT91C_TC_ACPC ( 0x3 << 18) // (TC) RC Compare Effect on TIOA
-+#define AT91C_TC_ACPC_NONE ( 0x0 << 18) // (TC) Effect: none
-+#define AT91C_TC_ACPC_SET ( 0x1 << 18) // (TC) Effect: set
-+#define AT91C_TC_ACPC_CLEAR ( 0x2 << 18) // (TC) Effect: clear
-+#define AT91C_TC_ACPC_TOGGLE ( 0x3 << 18) // (TC) Effect: toggle
-+#define AT91C_TC_AEEVT ( 0x3 << 20) // (TC) External Event Effect on TIOA
-+#define AT91C_TC_AEEVT_NONE ( 0x0 << 20) // (TC) Effect: none
-+#define AT91C_TC_AEEVT_SET ( 0x1 << 20) // (TC) Effect: set
-+#define AT91C_TC_AEEVT_CLEAR ( 0x2 << 20) // (TC) Effect: clear
-+#define AT91C_TC_AEEVT_TOGGLE ( 0x3 << 20) // (TC) Effect: toggle
-+#define AT91C_TC_ASWTRG ( 0x3 << 22) // (TC) Software Trigger Effect on TIOA
-+#define AT91C_TC_ASWTRG_NONE ( 0x0 << 22) // (TC) Effect: none
-+#define AT91C_TC_ASWTRG_SET ( 0x1 << 22) // (TC) Effect: set
-+#define AT91C_TC_ASWTRG_CLEAR ( 0x2 << 22) // (TC) Effect: clear
-+#define AT91C_TC_ASWTRG_TOGGLE ( 0x3 << 22) // (TC) Effect: toggle
-+#define AT91C_TC_BCPB ( 0x3 << 24) // (TC) RB Compare Effect on TIOB
-+#define AT91C_TC_BCPB_NONE ( 0x0 << 24) // (TC) Effect: none
-+#define AT91C_TC_BCPB_SET ( 0x1 << 24) // (TC) Effect: set
-+#define AT91C_TC_BCPB_CLEAR ( 0x2 << 24) // (TC) Effect: clear
-+#define AT91C_TC_BCPB_TOGGLE ( 0x3 << 24) // (TC) Effect: toggle
-+#define AT91C_TC_BCPC ( 0x3 << 26) // (TC) RC Compare Effect on TIOB
-+#define AT91C_TC_BCPC_NONE ( 0x0 << 26) // (TC) Effect: none
-+#define AT91C_TC_BCPC_SET ( 0x1 << 26) // (TC) Effect: set
-+#define AT91C_TC_BCPC_CLEAR ( 0x2 << 26) // (TC) Effect: clear
-+#define AT91C_TC_BCPC_TOGGLE ( 0x3 << 26) // (TC) Effect: toggle
-+#define AT91C_TC_BEEVT ( 0x3 << 28) // (TC) External Event Effect on TIOB
-+#define AT91C_TC_BEEVT_NONE ( 0x0 << 28) // (TC) Effect: none
-+#define AT91C_TC_BEEVT_SET ( 0x1 << 28) // (TC) Effect: set
-+#define AT91C_TC_BEEVT_CLEAR ( 0x2 << 28) // (TC) Effect: clear
-+#define AT91C_TC_BEEVT_TOGGLE ( 0x3 << 28) // (TC) Effect: toggle
-+#define AT91C_TC_BSWTRG ( 0x3 << 30) // (TC) Software Trigger Effect on TIOB
-+#define AT91C_TC_BSWTRG_NONE ( 0x0 << 30) // (TC) Effect: none
-+#define AT91C_TC_BSWTRG_SET ( 0x1 << 30) // (TC) Effect: set
-+#define AT91C_TC_BSWTRG_CLEAR ( 0x2 << 30) // (TC) Effect: clear
-+#define AT91C_TC_BSWTRG_TOGGLE ( 0x3 << 30) // (TC) Effect: toggle
-+// -------- TC_SR : (TC Offset: 0x20) TC Channel Status Register --------
-+#define AT91C_TC_COVFS ( 0x1 << 0) // (TC) Counter Overflow
-+#define AT91C_TC_LOVRS ( 0x1 << 1) // (TC) Load Overrun
-+#define AT91C_TC_CPAS ( 0x1 << 2) // (TC) RA Compare
-+#define AT91C_TC_CPBS ( 0x1 << 3) // (TC) RB Compare
-+#define AT91C_TC_CPCS ( 0x1 << 4) // (TC) RC Compare
-+#define AT91C_TC_LDRAS ( 0x1 << 5) // (TC) RA Loading
-+#define AT91C_TC_LDRBS ( 0x1 << 6) // (TC) RB Loading
-+#define AT91C_TC_ETRCS ( 0x1 << 7) // (TC) External Trigger
-+#define AT91C_TC_ETRGS ( 0x1 << 16) // (TC) Clock Enabling
-+#define AT91C_TC_MTIOA ( 0x1 << 17) // (TC) TIOA Mirror
-+#define AT91C_TC_MTIOB ( 0x1 << 18) // (TC) TIOA Mirror
-+// -------- TC_IER : (TC Offset: 0x24) TC Channel Interrupt Enable Register --------
-+// -------- TC_IDR : (TC Offset: 0x28) TC Channel Interrupt Disable Register --------
-+// -------- TC_IMR : (TC Offset: 0x2c) TC Channel Interrupt Mask Register --------
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Timer Counter Interface
-+// *****************************************************************************
-+// -------- TCB_BCR : (TCB Offset: 0xc0) TC Block Control Register --------
-+#define AT91C_TCB_SYNC ( 0x1 << 0) // (TCB) Synchro Command
-+// -------- TCB_BMR : (TCB Offset: 0xc4) TC Block Mode Register --------
-+#define AT91C_TCB_TC0XC0S ( 0x1 << 0) // (TCB) External Clock Signal 0 Selection
-+#define AT91C_TCB_TC0XC0S_TCLK0 ( 0x0) // (TCB) TCLK0 connected to XC0
-+#define AT91C_TCB_TC0XC0S_NONE ( 0x1) // (TCB) None signal connected to XC0
-+#define AT91C_TCB_TC0XC0S_TIOA1 ( 0x2) // (TCB) TIOA1 connected to XC0
-+#define AT91C_TCB_TC0XC0S_TIOA2 ( 0x3) // (TCB) TIOA2 connected to XC0
-+#define AT91C_TCB_TC1XC1S ( 0x1 << 2) // (TCB) External Clock Signal 1 Selection
-+#define AT91C_TCB_TC1XC1S_TCLK1 ( 0x0 << 2) // (TCB) TCLK1 connected to XC1
-+#define AT91C_TCB_TC1XC1S_NONE ( 0x1 << 2) // (TCB) None signal connected to XC1
-+#define AT91C_TCB_TC1XC1S_TIOA0 ( 0x2 << 2) // (TCB) TIOA0 connected to XC1
-+#define AT91C_TCB_TC1XC1S_TIOA2 ( 0x3 << 2) // (TCB) TIOA2 connected to XC1
-+#define AT91C_TCB_TC2XC2S ( 0x1 << 4) // (TCB) External Clock Signal 2 Selection
-+#define AT91C_TCB_TC2XC2S_TCLK2 ( 0x0 << 4) // (TCB) TCLK2 connected to XC2
-+#define AT91C_TCB_TC2XC2S_NONE ( 0x1 << 4) // (TCB) None signal connected to XC2
-+#define AT91C_TCB_TC2XC2S_TIOA0 ( 0x2 << 4) // (TCB) TIOA0 connected to XC2
-+#define AT91C_TCB_TC2XC2S_TIOA2 ( 0x3 << 4) // (TCB) TIOA2 connected to XC2
-+
-+#endif
---- linux-2.4.25/include/asm-arm/arch-at91rm9200/at91rm9200dk.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/at91rm9200dk.h 2004-03-31 17:15:09.000000000 +0200
-@@ -68,6 +68,7 @@
- #define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
- #define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
-
-+#define AT91C_CONSOLE_DEFAULT_BAUDRATE 115200 /* default serial console baud-rate */
-
- /*
- * Serial port configuration.
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/csb337.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,82 @@
-+/*
-+ * linux/include/asm-arm/arch-at91rm9200/csb337.h
-+ *
-+ * Copyright (c) 2003 Christopher Bahns & David Knickerbocker
-+ * Polaroid Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef __ASM_ARCH_HARDWARE_CSB337_H
-+#define __ASM_ARCH_HARDWARE_CSB337_H
-+
-+
-+/* AT91RM92000 clocks on CSB337 */
-+#define AT91C_MAIN_CLOCK 184320000
-+#define AT91C_MASTER_CLOCK 46080000 /* peripheral clock (AT91C_MAIN_CLOCK / 4) */
-+#define AT91C_SLOW_CLOCK 32768 /* slow clock */
-+
-+
-+/* FLASH */
-+#define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
-+
-+/* SDRAM */
-+#define AT91_SDRAM_BASE 0x20000000 // NCS1: SDRAM physical base address
-+
-+/* SmartMedia */
-+#define AT91_SMARTMEDIA_BASE 0x40000000 // NCS3: Smartmedia physical base address
-+
-+/* Multi-Master Memory controller */
-+#define AT91_UHP_BASE 0x00300000 // USB Host controller
-+
-+
-+/* Peripheral interrupt configuration */
-+#define AT91_SMR_FIQ (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (FIQ)
-+#define AT91_SMR_SYS (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // System Peripheral
-+#define AT91_SMR_PIOA (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller A
-+#define AT91_SMR_PIOB (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller B
-+#define AT91_SMR_PIOC (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller C
-+#define AT91_SMR_PIOD (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller D
-+#define AT91_SMR_US0 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 0
-+#define AT91_SMR_US1 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 1
-+#define AT91_SMR_US2 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 2
-+#define AT91_SMR_US3 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 3
-+#define AT91_SMR_MCI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Multimedia Card Interface
-+#define AT91_SMR_UDP (AT91C_AIC_PRIOR_4 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Device Port
-+#define AT91_SMR_TWI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Two-Wire Interface
-+#define AT91_SMR_SPI (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Peripheral Interface
-+#define AT91_SMR_SSC0 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 0
-+#define AT91_SMR_SSC1 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 1
-+#define AT91_SMR_SSC2 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 2
-+#define AT91_SMR_TC0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 0
-+#define AT91_SMR_TC1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 1
-+#define AT91_SMR_TC2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 2
-+#define AT91_SMR_TC3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 3
-+#define AT91_SMR_TC4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 4
-+#define AT91_SMR_TC5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 5
-+#define AT91_SMR_UHP (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Host port
-+#define AT91_SMR_EMAC (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Ethernet MAC
-+#define AT91_SMR_IRQ0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ0)
-+#define AT91_SMR_IRQ1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ1)
-+#define AT91_SMR_IRQ2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ2)
-+#define AT91_SMR_IRQ3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ3)
-+#define AT91_SMR_IRQ4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ4)
-+#define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
-+#define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
-+
-+
-+#define AT91C_CONSOLE_DEFAULT_BAUDRATE 38400
-+
-+/*
-+ * Serial port configuration.
-+ * 0 .. 3 = USART0 .. USART3
-+ * 4 = DBGU
-+ */
-+#define AT91C_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
-+#define AT91C_CONSOLE 0 /* ttyS0 */
-+
-+#endif
---- linux-2.4.25/include/asm-arm/arch-at91rm9200/hardware.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/hardware.h 2004-03-31 17:15:09.000000000 +0200
-@@ -82,5 +82,8 @@
- #include <asm/arch/at91rm9200dk.h>
- #endif
-
-+#ifdef CONFIG_MACH_CSB337
-+#include <asm/arch/csb337.h>
-+#endif
-
- #endif
---- linux-2.4.25/include/asm-arm/arch-at91rm9200/pio.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/pio.h 2004-03-31 17:15:09.000000000 +0200
-@@ -66,6 +66,18 @@
- }
-
- /*
-+ * Configure interrupt from Ethernet PHY.
-+ */
-+static inline void AT91_CfgPIO_EMAC_PHY(void) {
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_PIOC; /* enable peripheral clock */
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_ODR = AT91C_PIO_PC2;
-+#else
-+ AT91_SYS->PIOC_ODR = AT91C_PIO_PC4;
-+#endif
-+}
-+
-+/*
- * Enable the Two-Wire interface.
- */
- static inline void AT91_CfgPIO_TWI(void) {
---- linux-2.4.25/include/asm-arm/arch-at91rm9200/time.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-at91rm9200/time.h 2004-03-31 17:15:09.000000000 +0200
-@@ -27,6 +27,21 @@
- extern unsigned long (*gettimeoffset)(void);
-
- /*
-+ * The ST_CRTR is updated asynchronously to the master clock. It is therefore
-+ * necessary to read it twice (with the same value) to ensure accuracy.
-+ */
-+static inline unsigned long read_CRTR(void) {
-+ unsigned long x1, x2;
-+
-+ do {
-+ x1 = AT91_SYS->ST_CRTR;
-+ x2 = AT91_SYS->ST_CRTR;
-+ } while (x1 != x2);
-+
-+ return x1;
-+}
-+
-+/*
- * Returns number of microseconds since last timer interrupt. Note that interrupts
- * will have been disabled by do_gettimeofday()
- * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
-@@ -36,7 +51,7 @@
- {
- unsigned long elapsed;
-
-- elapsed = (AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
-+ elapsed = (read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
-
- return (unsigned long)(elapsed * tick) / LATCH;
- }
-@@ -52,7 +67,7 @@
-
- AT91_SYS->ST_RTAR = (AT91_SYS->ST_RTAR + LATCH) & AT91C_ST_ALMV;
-
-- } while (((AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
-+ } while (((read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
-
- do_profile(regs);
- }
---- linux-2.4.25/include/asm-arm/arch-clps711x/system.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-clps711x/system.h 2004-03-31 17:15:09.000000000 +0200
-@@ -28,8 +28,8 @@
- {
- clps_writel(1, HALT);
- __asm__ __volatile__(
-- "mov r0, r0
-- mov r0, r0");
-+ "mov r0, r0\n\t"
-+ "mov r0, r0");
- }
-
- static inline void arch_reset(char mode)
---- linux-2.4.25/include/asm-arm/arch-integrator/uncompress.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-integrator/uncompress.h 2004-03-31 17:15:09.000000000 +0200
-@@ -18,6 +18,8 @@
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-+#include <asm/hardware/serial_amba.h>
-+
- #define AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
- #define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
- #define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
-@@ -30,21 +32,25 @@
- */
- static void puts(const char *s)
- {
-+ /* Do nothing if the UART is not enabled. */
-+ if (!(AMBA_UART_CR & AMBA_UARTCR_UARTEN))
-+ return;
-+
- while (*s) {
-- while (AMBA_UART_FR & (1 << 5))
-+ while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
- barrier();
-
- AMBA_UART_DR = *s;
-
- if (*s == '\n') {
-- while (AMBA_UART_FR & (1 << 5))
-+ while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
- barrier();
-
- AMBA_UART_DR = '\r';
- }
- s++;
- }
-- while (AMBA_UART_FR & (1 << 3));
-+ while (AMBA_UART_FR & AMBA_UARTFR_BUSY);
- }
-
- /*
---- linux-2.4.25/include/asm-arm/arch-riscstation/system.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-riscstation/system.h 2004-03-31 17:15:09.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- * linux/include/asm-arm/arch-rpc/system.h
-+ * linux/include/asm-arm/arch-riscstation/system.h
- *
- * Copyright (C) 1996-1999 Russell King.
- *
-@@ -18,7 +18,7 @@
-
- static inline void arch_reset(char mode)
- {
-- iomd_writeb(0, IOMD_ROMCR0);
-+ iomd_writeb(0x40, IOMD_ROMCR0);
-
- /*
- * Jump into the ROM
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-clock.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,76 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-clock.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 clock register definitions
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_CLOCK_H
-+#define ASMARM_ARCH_S3C2410_CLOCK_H
-+
-+#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
-+
-+#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
-+
-+#define S3C2410_LOCKTIME S3C2410_CLKREG(0x00)
-+#define S3C2410_MPLLCON S3C2410_CLKREG(0x04)
-+#define S3C2410_UPLLCON S3C2410_CLKREG(0x08)
-+#define S3C2410_CLKCON S3C2410_CLKREG(0x0C)
-+#define S3C2410_CLKSLOW S3C2410_CLKREG(0x10)
-+#define S3C2410_CLKDIVN S3C2410_CLKREG(0x14)
-+
-+#define S3C2410_PLLCON_MDIVSHIFT 12
-+#define S3C2410_PLLCON_PDIVSHIFT 4
-+#define S3C2410_PLLCON_SDIVSHIFT 0
-+#define S3C2410_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1)
-+#define S3C2410_PLLCON_PDIVMASK ((1<<5)-1)
-+#define S3C2410_PLLCON_SDIVMASK 3
-+
-+/* DCLKCON register addresses in gpio.h */
-+
-+#define S3C2410_DCLKCON_DCLK0EN (1<<0)
-+#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
-+#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
-+#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
-+#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
-+
-+#define S3C2410_DCLKCON_DCLK1EN (1<<16)
-+#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
-+#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
-+#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
-+
-+#define S3C2410_CLKDIVN_PDIVN (1<<0)
-+#define S3C2410_CLKDIVN_HDIVN (1<<1)
-+
-+static inline unsigned int
-+s3c2410_get_pll(int pllval, int baseclk)
-+{
-+ int mdiv, pdiv, sdiv;
-+
-+ mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT;
-+ pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT;
-+ sdiv = pllval >> S3C2410_PLLCON_SDIVSHIFT;
-+
-+ mdiv &= S3C2410_PLLCON_MDIVMASK;
-+ pdiv &= S3C2410_PLLCON_PDIVMASK;
-+ sdiv &= S3C2410_PLLCON_SDIVMASK;
-+
-+ return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
-+}
-+
-+#endif /* ASMARM_ARCH_S3C2410_CLOCK_H */
-+
-+
-+
-+
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-gpio.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,602 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 GPIO register definitions
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ * 23-06-2003 BJD Updated GSTATUS registers
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_GPIO_H
-+#define ASMARM_ARCH_S3C2410_GPIO_H
-+
-+/* configure GPIO ports A..G */
-+
-+#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
-+
-+/* port A - 22bits, zero in bit X makes pin X output
-+ * 1 makes port special function, this is default
-+*/
-+#define S3C2410_GPACON S3C2410_GPIOREG(0x00)
-+#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)
-+
-+/* 0x08 and 0x0c are reserved */
-+
-+/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
-+ * 00 = input, 01 = output, 10=special function, 11=reserved
-+ * bit 0,1 = pin 0, 2,3= pin 1...
-+ *
-+ * CPBUP = pull up resistor control, 1=disabled, 0=enabled
-+*/
-+
-+#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
-+#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
-+#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
-+
-+/* no i/o pin in port b can have value 3! */
-+
-+#define S3C2410_GPB0_INP (0x00 << 0)
-+#define S3C2410_GPB0_OUTP (0x01 << 0)
-+#define S3C2410_GPB0_TOUT0 (0x02 << 0)
-+
-+#define S3C2410_GPB1_INP (0x00 << 2)
-+#define S3C2410_GPB1_OUTP (0x01 << 2)
-+#define S3C2410_GPB1_TOUT1 (0x02 << 2)
-+
-+#define S3C2410_GPB2_INP (0x00 << 4)
-+#define S3C2410_GPB2_OUTP (0x01 << 4)
-+#define S3C2410_GPB2_TOUT2 (0x02 << 4)
-+
-+#define S3C2410_GPB3_INP (0x00 << 6)
-+#define S3C2410_GPB3_OUTP (0x01 << 6)
-+#define S3C2410_GPB3_TOUT3 (0x02 << 6)
-+
-+#define S3C2410_GPB4_INP (0x00 << 8)
-+#define S3C2410_GPB4_OUTP (0x01 << 8)
-+#define S3C2410_GPB4_TCLK0 (0x02 << 8)
-+#define S3C2410_GPB4_MASK (0x03 << 8)
-+
-+#define S3C2410_GPB5_INP (0x00 << 10)
-+#define S3C2410_GPB5_OUTP (0x01 << 10)
-+#define S3C2410_GPB5_nXBACK (0x02 << 10)
-+
-+#define S3C2410_GPB6_INP (0x00 << 12)
-+#define S3C2410_GPB6_OUTP (0x01 << 12)
-+#define S3C2410_GPB6_nXBREQ (0x02 << 12)
-+
-+#define S3C2410_GPB7_INP (0x00 << 14)
-+#define S3C2410_GPB7_OUTP (0x01 << 14)
-+#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
-+
-+#define S3C2410_GPB8_INP (0x00 << 16)
-+#define S3C2410_GPB8_OUTP (0x01 << 16)
-+#define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
-+
-+#define S3C2410_GPB9_INP (0x00 << 18)
-+#define S3C2410_GPB9_OUTP (0x01 << 18)
-+#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
-+
-+#define S3C2410_GPB10_INP (0x00 << 18)
-+#define S3C2410_GPB10_OUTP (0x01 << 18)
-+#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
-+
-+/* Port C consits of 16 GPIO/Special function
-+ *
-+ * almost identical setup to port b, but the special functions are mostly
-+ * to do with the video system's sync/etc.
-+*/
-+
-+#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)
-+#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)
-+#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)
-+
-+#define S3C2410_GPC0_INP (0x00 << 0)
-+#define S3C2410_GPC0_OUTP (0x01 << 0)
-+#define S3C2410_GPC0_LEND (0x02 << 0)
-+
-+#define S3C2410_GPC1_INP (0x00 << 2)
-+#define S3C2410_GPC1_OUTP (0x01 << 2)
-+#define S3C2410_GPC1_VCLK (0x02 << 2)
-+
-+#define S3C2410_GPC2_INP (0x00 << 4)
-+#define S3C2410_GPC2_OUTP (0x01 << 4)
-+#define S3C2410_GPC2_VLINE (0x02 << 4)
-+
-+#define S3C2410_GPC3_INP (0x00 << 6)
-+#define S3C2410_GPC3_OUTP (0x01 << 6)
-+#define S3C2410_GPC3_VFRAME (0x02 << 6)
-+
-+#define S3C2410_GPC4_INP (0x00 << 8)
-+#define S3C2410_GPC4_OUTP (0x01 << 8)
-+#define S3C2410_GPC4_VM (0x02 << 8)
-+
-+#define S3C2410_GPC5_INP (0x00 << 10)
-+#define S3C2410_GPC5_OUTP (0x01 << 10)
-+#define S3C2410_GPC5_LCDVF0 (0x02 << 10)
-+
-+#define S3C2410_GPC6_INP (0x00 << 12)
-+#define S3C2410_GPC6_OUTP (0x01 << 12)
-+#define S3C2410_GPC6_LCDVF1 (0x02 << 12)
-+
-+#define S3C2410_GPC7_INP (0x00 << 14)
-+#define S3C2410_GPC7_OUTP (0x01 << 14)
-+#define S3C2410_GPC7_LCDVF2 (0x02 << 14)
-+
-+#define S3C2410_GPC8_INP (0x00 << 16)
-+#define S3C2410_GPC8_OUTP (0x01 << 16)
-+#define S3C2410_GPC8_VD0 (0x02 << 16)
-+
-+#define S3C2410_GPC9_INP (0x00 << 18)
-+#define S3C2410_GPC9_OUTP (0x01 << 18)
-+#define S3C2410_GPC9_VD1 (0x02 << 18)
-+
-+#define S3C2410_GPC10_INP (0x00 << 20)
-+#define S3C2410_GPC10_OUTP (0x01 << 20)
-+#define S3C2410_GPC10_VD2 (0x02 << 20)
-+
-+#define S3C2410_GPC11_INP (0x00 << 22)
-+#define S3C2410_GPC11_OUTP (0x01 << 22)
-+#define S3C2410_GPC11_VD3 (0x02 << 22)
-+
-+#define S3C2410_GPC12_INP (0x00 << 24)
-+#define S3C2410_GPC12_OUTP (0x01 << 24)
-+#define S3C2410_GPC12_VD4 (0x02 << 24)
-+
-+#define S3C2410_GPC13_INP (0x00 << 26)
-+#define S3C2410_GPC13_OUTP (0x01 << 26)
-+#define S3C2410_GPC13_VD5 (0x02 << 26)
-+
-+#define S3C2410_GPC14_INP (0x00 << 28)
-+#define S3C2410_GPC14_OUTP (0x01 << 28)
-+#define S3C2410_GPC14_VD6 (0x02 << 28)
-+
-+#define S3C2410_GPC15_INP (0x00 << 30)
-+#define S3C2410_GPC15_OUTP (0x01 << 30)
-+#define S3C2410_GPC15_VD7 (0x02 << 30)
-+
-+/* Port D consists of 16 GPIO/Special function
-+ *
-+ * almost identical setup to port b, but the special functions are mostly
-+ * to do with the video system's data.
-+*/
-+
-+#define S3C2410_GPDCON S3C2410_GPIOREG(0x30)
-+#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)
-+#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)
-+
-+#define S3C2410_GPD0_INP (0x00 << 0)
-+#define S3C2410_GPD0_OUTP (0x01 << 0)
-+#define S3C2410_GPD0_VD8 (0x02 << 0)
-+
-+#define S3C2410_GPD1_INP (0x00 << 2)
-+#define S3C2410_GPD1_OUTP (0x01 << 2)
-+#define S3C2410_GPD1_VD9 (0x02 << 2)
-+
-+#define S3C2410_GPD2_INP (0x00 << 4)
-+#define S3C2410_GPD2_OUTP (0x01 << 4)
-+#define S3C2410_GPD2_VD10 (0x02 << 4)
-+
-+#define S3C2410_GPD3_INP (0x00 << 6)
-+#define S3C2410_GPD3_OUTP (0x01 << 6)
-+#define S3C2410_GPD3_VD11 (0x02 << 6)
-+
-+#define S3C2410_GPD4_INP (0x00 << 8)
-+#define S3C2410_GPD4_OUTP (0x01 << 8)
-+#define S3C2410_GPD4_VD12 (0x02 << 8)
-+
-+#define S3C2410_GPD5_INP (0x00 << 10)
-+#define S3C2410_GPD5_OUTP (0x01 << 10)
-+#define S3C2410_GPD5_VD13 (0x02 << 10)
-+
-+#define S3C2410_GPD6_INP (0x00 << 12)
-+#define S3C2410_GPD6_OUTP (0x01 << 12)
-+#define S3C2410_GPD6_VD14 (0x02 << 12)
-+
-+#define S3C2410_GPD7_INP (0x00 << 14)
-+#define S3C2410_GPD7_OUTP (0x01 << 14)
-+#define S3C2410_GPD7_VD15 (0x02 << 14)
-+
-+#define S3C2410_GPD8_INP (0x00 << 16)
-+#define S3C2410_GPD8_OUTP (0x01 << 16)
-+#define S3C2410_GPD8_VD16 (0x02 << 16)
-+
-+#define S3C2410_GPD9_INP (0x00 << 18)
-+#define S3C2410_GPD9_OUTP (0x01 << 18)
-+#define S3C2410_GPD9_VD17 (0x02 << 18)
-+
-+#define S3C2410_GPD10_INP (0x00 << 20)
-+#define S3C2410_GPD10_OUTP (0x01 << 20)
-+#define S3C2410_GPD10_VD18 (0x02 << 20)
-+
-+#define S3C2410_GPD11_INP (0x00 << 22)
-+#define S3C2410_GPD11_OUTP (0x01 << 22)
-+#define S3C2410_GPD11_VD19 (0x02 << 22)
-+
-+#define S3C2410_GPD12_INP (0x00 << 24)
-+#define S3C2410_GPD12_OUTP (0x01 << 24)
-+#define S3C2410_GPD12_VD20 (0x02 << 24)
-+
-+#define S3C2410_GPD13_INP (0x00 << 26)
-+#define S3C2410_GPD13_OUTP (0x01 << 26)
-+#define S3C2410_GPD13_VD21 (0x02 << 26)
-+
-+#define S3C2410_GPD14_INP (0x00 << 28)
-+#define S3C2410_GPD14_OUTP (0x01 << 28)
-+#define S3C2410_GPD14_VD22 (0x02 << 28)
-+
-+#define S3C2410_GPD15_INP (0x00 << 30)
-+#define S3C2410_GPD15_OUTP (0x01 << 30)
-+#define S3C2410_GPD15_VD23 (0x02 << 30)
-+
-+/* Port E consists of 16 GPIO/Special function
-+ *
-+ * again, the same as port B, but dealing with I2S, SDI, and
-+ * more miscellaneous functions
-+*/
-+
-+#define S3C2410_GPECON S3C2410_GPIOREG(0x40)
-+#define S3C2410_GPEDAT S3C2410_GPIOREG(0x44)
-+#define S3C2410_GPEUP S3C2410_GPIOREG(0x48)
-+
-+#define S3C2410_GPE0_INP (0x00 << 0)
-+#define S3C2410_GPE0_OUTP (0x01 << 0)
-+#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
-+#define S3C2410_GPE0_MASK (0x03 << 0)
-+
-+#define S3C2410_GPE1_INP (0x00 << 2)
-+#define S3C2410_GPE1_OUTP (0x01 << 2)
-+#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
-+#define S3C2410_GPE1_MASK (0x03 << 2)
-+
-+#define S3C2410_GPE2_INP (0x00 << 4)
-+#define S3C2410_GPE2_OUTP (0x01 << 4)
-+#define S3C2410_GPE2_CDCLK (0x02 << 4)
-+
-+#define S3C2410_GPE3_INP (0x00 << 6)
-+#define S3C2410_GPE3_OUTP (0x01 << 6)
-+#define S3C2410_GPE3_I2SSDI (0x02 << 6)
-+#define S3C2410_GPE3_MASK (0x03 << 6)
-+
-+#define S3C2410_GPE4_INP (0x00 << 8)
-+#define S3C2410_GPE4_OUTP (0x01 << 8)
-+#define S3C2410_GPE4_I2SSDO (0x02 << 8)
-+#define S3C2410_GPE4_MASK (0x03 << 8)
-+
-+#define S3C2410_GPE5_INP (0x00 << 10)
-+#define S3C2410_GPE5_OUTP (0x01 << 10)
-+#define S3C2410_GPE5_SDCLK (0x02 << 10)
-+
-+#define S3C2410_GPE6_INP (0x00 << 12)
-+#define S3C2410_GPE6_OUTP (0x01 << 12)
-+#define S3C2410_GPE6_SDCLK (0x02 << 12)
-+
-+#define S3C2410_GPE7_INP (0x00 << 14)
-+#define S3C2410_GPE7_OUTP (0x01 << 14)
-+#define S3C2410_GPE7_SDCMD (0x02 << 14)
-+
-+#define S3C2410_GPE8_INP (0x00 << 16)
-+#define S3C2410_GPE8_OUTP (0x01 << 16)
-+#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
-+
-+#define S3C2410_GPE9_INP (0x00 << 18)
-+#define S3C2410_GPE9_OUTP (0x01 << 18)
-+#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
-+
-+#define S3C2410_GPE10_INP (0x00 << 20)
-+#define S3C2410_GPE10_OUTP (0x01 << 20)
-+#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
-+
-+#define S3C2410_GPE11_INP (0x00 << 22)
-+#define S3C2410_GPE11_OUTP (0x01 << 22)
-+#define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
-+
-+#define S3C2410_GPE12_INP (0x00 << 24)
-+#define S3C2410_GPE12_OUTP (0x01 << 24)
-+#define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
-+
-+#define S3C2410_GPE13_INP (0x00 << 26)
-+#define S3C2410_GPE13_OUTP (0x01 << 26)
-+#define S3C2410_GPE13_SPICLK0 (0x02 << 26)
-+
-+#define S3C2410_GPE14_INP (0x00 << 28)
-+#define S3C2410_GPE14_OUTP (0x01 << 28)
-+#define S3C2410_GPE14_IICSCL (0x02 << 28)
-+#define S3C2410_GPE14_MASK (0x03 << 28)
-+
-+#define S3C2410_GPE15_INP (0x00 << 30)
-+#define S3C2410_GPE15_OUTP (0x01 << 30)
-+#define S3C2410_GPE15_IICSDA (0x02 << 30)
-+#define S3C2410_GPE15_MASK (0x03 << 30)
-+
-+#define S3C2410_GPE_PUPDIS(x) (1<<(x))
-+
-+/* Port F consists of 8 GPIO/Special function
-+ *
-+ * GPIO / interrupt inputs
-+ *
-+ * GPFCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 undefined
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)
-+#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
-+#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)
-+
-+
-+#define S3C2410_GPF0_INP (0x00 << 0)
-+#define S3C2410_GPF0_OUTP (0x01 << 0)
-+#define S3C2410_GPF0_EINT0 (0x02 << 0)
-+
-+#define S3C2410_GPF1_INP (0x00 << 2)
-+#define S3C2410_GPF1_OUTP (0x01 << 2)
-+#define S3C2410_GPF1_EINT1 (0x02 << 2)
-+
-+#define S3C2410_GPF2_INP (0x00 << 4)
-+#define S3C2410_GPF2_OUTP (0x01 << 4)
-+#define S3C2410_GPF2_EINT2 (0x02 << 4)
-+
-+#define S3C2410_GPF3_INP (0x00 << 6)
-+#define S3C2410_GPF3_OUTP (0x01 << 6)
-+#define S3C2410_GPF3_EINT3 (0x02 << 6)
-+
-+#define S3C2410_GPF4_INP (0x00 << 8)
-+#define S3C2410_GPF4_OUTP (0x01 << 8)
-+#define S3C2410_GPF4_EINT4 (0x02 << 8)
-+
-+#define S3C2410_GPF5_INP (0x00 << 10)
-+#define S3C2410_GPF5_OUTP (0x01 << 10)
-+#define S3C2410_GPF5_EINT5 (0x02 << 10)
-+
-+#define S3C2410_GPF6_INP (0x00 << 12)
-+#define S3C2410_GPF6_OUTP (0x01 << 12)
-+#define S3C2410_GPF6_EINT6 (0x02 << 12)
-+
-+#define S3C2410_GPF7_INP (0x00 << 14)
-+#define S3C2410_GPF7_OUTP (0x01 << 14)
-+#define S3C2410_GPF7_EINT7 (0x02 << 14)
-+
-+/* Port G consists of 8 GPIO/IRQ/Special function
-+ *
-+ * GPGCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPGCON S3C2410_GPIOREG(0x60)
-+#define S3C2410_GPGDAT S3C2410_GPIOREG(0x64)
-+#define S3C2410_GPGUP S3C2410_GPIOREG(0x68)
-+
-+#define S3C2410_GPG0_INP (0x00 << 0)
-+#define S3C2410_GPG0_OUTP (0x01 << 0)
-+#define S3C2410_GPG0_EINT8 (0x02 << 0)
-+
-+#define S3C2410_GPG1_INP (0x00 << 2)
-+#define S3C2410_GPG1_OUTP (0x01 << 2)
-+#define S3C2410_GPG1_EINT9 (0x02 << 2)
-+
-+#define S3C2410_GPG2_INP (0x00 << 4)
-+#define S3C2410_GPG2_OUTP (0x01 << 4)
-+#define S3C2410_GPG2_EINT10 (0x02 << 4)
-+
-+#define S3C2410_GPG3_INP (0x00 << 6)
-+#define S3C2410_GPG3_OUTP (0x01 << 6)
-+#define S3C2410_GPG3_EINT11 (0x02 << 6)
-+
-+#define S3C2410_GPG4_INP (0x00 << 8)
-+#define S3C2410_GPG4_OUTP (0x01 << 8)
-+#define S3C2410_GPG4_EINT12 (0x02 << 8)
-+#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
-+
-+#define S3C2410_GPG5_INP (0x00 << 10)
-+#define S3C2410_GPG5_OUTP (0x01 << 10)
-+#define S3C2410_GPG5_EINT13 (0x02 << 10)
-+#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
-+
-+#define S3C2410_GPG6_INP (0x00 << 12)
-+#define S3C2410_GPG6_OUTP (0x01 << 12)
-+#define S3C2410_GPG6_EINT14 (0x02 << 12)
-+#define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
-+
-+#define S3C2410_GPG7_INP (0x00 << 14)
-+#define S3C2410_GPG7_OUTP (0x01 << 14)
-+#define S3C2410_GPG7_EINT15 (0x02 << 14)
-+#define S3C2410_GPG7_SPICLK1 (0x03 << 14)
-+
-+#define S3C2410_GPG8_INP (0x00 << 16)
-+#define S3C2410_GPG8_OUTP (0x01 << 16)
-+#define S3C2410_GPG8_EINT16 (0x02 << 16)
-+
-+#define S3C2410_GPG9_INP (0x00 << 18)
-+#define S3C2410_GPG9_OUTP (0x01 << 18)
-+#define S3C2410_GPG9_EINT17 (0x02 << 18)
-+
-+#define S3C2410_GPG10_INP (0x00 << 20)
-+#define S3C2410_GPG10_OUTP (0x01 << 20)
-+#define S3C2410_GPG10_EINT18 (0x02 << 20)
-+
-+#define S3C2410_GPG11_INP (0x00 << 22)
-+#define S3C2410_GPG11_OUTP (0x01 << 22)
-+#define S3C2410_GPG11_EINT19 (0x02 << 22)
-+#define S3C2410_GPG11_TCLK1 (0x03 << 22)
-+
-+#define S3C2410_GPG12_INP (0x00 << 24)
-+#define S3C2410_GPG12_OUTP (0x01 << 24)
-+#define S3C2410_GPG12_EINT18 (0x02 << 24)
-+#define S3C2410_GPG12_XMON (0x03 << 24)
-+
-+#define S3C2410_GPG13_INP (0x00 << 26)
-+#define S3C2410_GPG13_OUTP (0x01 << 26)
-+#define S3C2410_GPG13_EINT18 (0x02 << 26)
-+#define S3C2410_GPG13_nXPON (0x03 << 26)
-+
-+#define S3C2410_GPG14_INP (0x00 << 28)
-+#define S3C2410_GPG14_OUTP (0x01 << 28)
-+#define S3C2410_GPG14_EINT18 (0x02 << 28)
-+#define S3C2410_GPG14_YMON (0x03 << 28)
-+
-+#define S3C2410_GPG15_INP (0x00 << 30)
-+#define S3C2410_GPG15_OUTP (0x01 << 30)
-+#define S3C2410_GPG15_EINT18 (0x02 << 30)
-+#define S3C2410_GPG15_nYPON (0x03 << 30)
-+
-+
-+#define S3C2410_GPG_PUPDIS(x) (1<<(x))
-+
-+/* Port H consists of11 GPIO/serial/Misc pins
-+ *
-+ * GPGCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPHCON S3C2410_GPIOREG(0x70)
-+#define S3C2410_GPHDAT S3C2410_GPIOREG(0x74)
-+#define S3C2410_GPHUP S3C2410_GPIOREG(0x78)
-+
-+#define S3C2410_GPH0_INP (0x00 << 0)
-+#define S3C2410_GPH0_OUTP (0x01 << 0)
-+#define S3C2410_GPH0_nCTS0 (0x02 << 0)
-+
-+#define S3C2410_GPH1_INP (0x00 << 2)
-+#define S3C2410_GPH1_OUTP (0x01 << 2)
-+#define S3C2410_GPH1_nRTS0 (0x02 << 2)
-+
-+#define S3C2410_GPH2_INP (0x00 << 4)
-+#define S3C2410_GPH2_OUTP (0x01 << 4)
-+#define S3C2410_GPH2_TXD0 (0x02 << 4)
-+
-+#define S3C2410_GPH3_INP (0x00 << 6)
-+#define S3C2410_GPH3_OUTP (0x01 << 6)
-+#define S3C2410_GPH3_RXD0 (0x02 << 6)
-+
-+#define S3C2410_GPH4_INP (0x00 << 8)
-+#define S3C2410_GPH4_OUTP (0x01 << 8)
-+#define S3C2410_GPH4_TXD1 (0x02 << 8)
-+
-+#define S3C2410_GPH5_INP (0x00 << 10)
-+#define S3C2410_GPH5_OUTP (0x01 << 10)
-+#define S3C2410_GPH5_RXD1 (0x02 << 10)
-+
-+#define S3C2410_GPH6_INP (0x00 << 12)
-+#define S3C2410_GPH6_OUTP (0x01 << 12)
-+#define S3C2410_GPH6_TXD2 (0x02 << 12)
-+#define S3C2410_GPH6_nRTS1 (0x03 << 12)
-+
-+#define S3C2410_GPH7_INP (0x00 << 14)
-+#define S3C2410_GPH7_OUTP (0x01 << 14)
-+#define S3C2410_GPH7_RXD2 (0x02 << 14)
-+#define S3C2410_GPH7_nCTS1 (0x03 << 14)
-+
-+#define S3C2410_GPH8_INP (0x00 << 16)
-+#define S3C2410_GPH8_OUTP (0x01 << 16)
-+#define S3C2410_GPH8_UCLK (0x02 << 16)
-+
-+#define S3C2410_GPH9_INP (0x00 << 18)
-+#define S3C2410_GPH9_OUTP (0x01 << 18)
-+#define S3C2410_GPH9_CLKOUT0 (0x02 << 18)
-+
-+#define S3C2410_GPH10_INP (0x00 << 20)
-+#define S3C2410_GPH10_OUTP (0x01 << 20)
-+#define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
-+
-+/* miscellaneous control */
-+
-+#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
-+#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
-+
-+/* see clock.h for dclk definitions */
-+
-+/* pullup control on databus */
-+#define S3C2410_MISCCR_SPUCR_HEN (0)
-+#define S3C2410_MISCCR_SPUCR_HDIS (1<<0)
-+#define S3C2410_MISCCR_SPUCR_LEN (0)
-+#define S3C2410_MISCCR_SPUCR_LDIS (1<<1)
-+
-+#define S3C2410_MISCCR_USBDEV (0)
-+#define S3C2410_MISCCR_USBHOST (1<<3)
-+
-+#define S3C2410_MISCCR_CLK0_MPLL (0<<4)
-+#define S3C2410_MISCCR_CLK0_UPLL (1<<4)
-+#define S3C2410_MISCCR_CLK0_FCLK (2<<4)
-+#define S3C2410_MISCCR_CLK0_HCLK (3<<4)
-+#define S3C2410_MISCCR_CLK0_PCLK (4<<4)
-+#define S3C2410_MISCCR_CLK0_DCLK0 (5<<4)
-+
-+#define S3C2410_MISCCR_CLK1_MPLL (0<<8)
-+#define S3C2410_MISCCR_CLK1_UPLL (1<<8)
-+#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
-+#define S3C2410_MISCCR_CLK1_HCLK (3<<8)
-+#define S3C2410_MISCCR_CLK1_PCLK (4<<8)
-+#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
-+
-+#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
-+#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
-+
-+#define S3C2410_MISCCR_nRSTCON (1<<16)
-+
-+/* external interrupt control... */
-+/* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
-+ * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
-+ * S3C2410_EXTINT2 -> irq sense control for EINT16..EINT23
-+ *
-+ * note S3C2410_EXTINT2 has filtering options for EINT16..EINT23
-+ *
-+ * Samsung datasheet p9-25
-+*/
-+
-+#define S3C2410_EXTINT0 S3C2410_GPIOREG(0x88)
-+#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
-+#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
-+
-+/* values for S3C2410_EXTINT0/1/2 */
-+#define S3C2410_EXTINT_LOWLEV (0x00)
-+#define S3C2410_EXTINT_HILEV (0x01)
-+#define S3C2410_EXTINT_FALLEDGE (0x02)
-+#define S3C2410_EXTINT_RISEEDGE (0x04)
-+#define S3C2410_EXTINT_BOTHEDGE (0x06)
-+
-+/* interrupt filtering conrrol for EINT16..EINT23 */
-+#define S3C2410_EINFLT0 S3C2410_GPIOREG(0x94)
-+#define S3C2410_EINFLT1 S3C2410_GPIOREG(0x98)
-+#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
-+#define S3C2410_EINFLT3 S3C2410_GPIOREG(0xA0)
-+
-+/* mask: 0=enable, 1=disable
-+ * 1 bit EINT, 4=EINT4, 23=EINT23
-+ * EINT0,1,2,3 are not handled here.
-+*/
-+#define S3C2410_EINTMASK S3C2410_GPIOREG(0xA4)
-+#define S3C2410_EINTPEND S3C2410_GPIOREG(0xA8)
-+
-+/* GSTATUS have miscellaneous information in them
-+ *
-+ */
-+
-+#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
-+#define S3C2410_GSTATUS1 S3C2410_GPIOREG(0x0B0)
-+#define S3C2410_GSTATUS2 S3C2410_GPIOREG(0x0B4)
-+#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
-+#define S3C2410_GSTATUS4 S3C2410_GPIOREG(0x0BC)
-+
-+#define S3C2410_GSTATUS0_nWAIT (1<<3)
-+#define S3C2410_GSTATUS0_NCON (1<<2)
-+#define S3C2410_GSTATUS0_RnB (1<<1)
-+#define S3C2410_GSTATUS0_nBATTFLT (1<<0)
-+
-+#define S3C2410_GSTATUS2_WTRESET (1<<2)
-+#define S3C2410_GSTATUs2_OFFRESET (1<<1)
-+#define S3C2410_GSTATUS2_PONRESET (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_GPIO_H */
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-iis.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,61 @@
-+/* linux/include/asm/hardware/s3c2410/iis.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 IIS register definition
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ * 26-06-2003 BJD Finished off definitions for register addresses
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_IIS_H
-+#define ASMARM_ARCH_S3C2410_IIS_H
-+
-+#define S3C2410_IISCON (S3C2410_VA_IIS + 0x00)
-+
-+#define S3C2410_IISCON_LRINDEX (1<<8)
-+#define S3C2410_IISCON_TXFIFORDY (1<<7)
-+#define S3C2410_IISCON_RXFIFORDY (1<<6)
-+#define S3C2410_IISCON_TXDMAEN (1<<5)
-+#define S3C2410_IISCON_RXDMAEN (1<<4)
-+#define S3C2410_IISCON_TXIDLE (1<<3)
-+#define S3C2410_IISCON_RXIDLE (1<<2)
-+#define S3C2410_IISCON_IISEN (1<<0)
-+
-+#define S3C2410_IISMOD (S3C2410_VA_IIS + 0x04)
-+
-+#define S3C2410_IISMOD_SLAVE (1<<8)
-+#define S3C2410_IISMOD_NOXFER (0<<6)
-+#define S3C2410_IISMOD_RXMODE (1<<6)
-+#define S3C2410_IISMOD_TXMODE (2<<6)
-+#define S3C2410_IISMOD_TXRXMODE (3<<6)
-+#define S3C2410_IISMOD_LR_LLOW (0<<5)
-+#define S3C2410_IISMOD_LR_RLOW (1<<5)
-+#define S3C2410_IISMOD_IIS (0<<4)
-+#define S3C2410_IISMOD_MSB (1<<4)
-+#define S3C2410_IISMOD_8BIT (0<<3)
-+#define S3C2410_IISMOD_16BIT (1<<3)
-+#define S3C2410_IISMOD_256FS (0<<1)
-+#define S3C2410_IISMOD_384FS (1<<1)
-+#define S3C2410_IISMOD_16FS (0<<0)
-+#define S3C2410_IISMOD_32FS (1<<0)
-+#define S3C2410_IISMOD_48FS (2<<0)
-+
-+#define S3C2410_IISPSR (S3C2410_VA_IIS + 0x08)
-+
-+#define S3C2410_IISFCON (S3C2410_VA_IIS + 0x0c)
-+
-+#define S3C2410_IISFCON_TXDMA (1<<15)
-+#define S3C2410_IISFCON_RXDMA (1<<14)
-+#define S3C2410_IISFCON_TXENABLE (1<<13)
-+#define S3C2410_IISFCON_RXENABLE (1<<12)
-+
-+#define S3C2410_IISFIFO (S3C2410_VA_IIS + 0x10)
-+
-+#endif /* ASMARM_ARCH_S3C2410_IIS_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-irq.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,34 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-irq.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_IRQ_H
-+#define ASMARM_ARCH_S3C2410_IRQ_H
-+
-+/* interrupt controller */
-+
-+#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
-+#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
-+
-+#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
-+#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
-+#define S3C2410_INTMSK S3C2410_IRQREG(0x008)
-+#define S3C2410_PRIORITY S3C2410_IRQREG(0x00C)
-+#define S3C2410_INTPND S3C2410_IRQREG(0x010)
-+#define S3C2410_INTOFFSET S3C2410_IRQREG(0x014)
-+#define S3C2410_SUBSRCPND S3C2410_IRQREG(0x018)
-+#define S3C2410_INTSUBMSK S3C2410_IRQREG(0x01C)
-+
-+#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
-+#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
-+
-+#endif /* ASMARM_ARCH_S3C2410_IRQ_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-lcd.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,107 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ *
-+ * Changelog:
-+ * 12-06-2003 BJD Created file
-+ * 26-06-2003 BJD Updated LCDCON register definitions
-+*/
-+
-+#ifndef ASMARM_ARCH_S3C2410_LCD_H
-+#define ASMARM_ARCH_S3C2410_LCD_H
-+
-+#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
-+
-+/* LCD control registers */
-+#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
-+#define S3C2410_LCDCON2 S3C2410_LCDREG(0x04)
-+#define S3C2410_LCDCON3 S3C2410_LCDREG(0x08)
-+#define S3C2410_LCDCON4 S3C2410_LCDREG(0x0C)
-+#define S3C2410_LCDCON5 S3C2410_LCDREG(0x10)
-+
-+#define S3C2410_LCDCON1_CLKVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON1_MMODE (1<<7)
-+#define S3C2410_LCDCON1_DSCAN4 (0<<5)
-+#define S3C2410_LCDCON1_STN4 (1<<5)
-+#define S3C2410_LCDCON1_STN8 (2<<5)
-+#define S3C2410_LCDCON1_TFT (3<<5)
-+
-+#define S3C2410_LCDCON1_STN1BPP (0<<1)
-+#define S3C2410_LCDCON1_STN2GREY (1<<1)
-+#define S3C2410_LCDCON1_STN4GREY (2<<1)
-+#define S3C2410_LCDCON1_STN8BPP (3<<1)
-+#define S3C2410_LCDCON1_STN12BPP (4<<1)
-+
-+#define S3C2410_LCDCON1_TFT1BPP (8<<1)
-+#define S3C2410_LCDCON1_TFT2BPP (9<<1)
-+#define S3C2410_LCDCON1_TFT4BPP (10<<1)
-+#define S3C2410_LCDCON1_TFT8BPP (11<<1)
-+#define S3C2410_LCDCON1_TFT16BPP (12<<1)
-+#define S3C2410_LCDCON1_TFT24BPP (13<<1)
-+
-+#define S3C2410_LCDCON1_ENVDI (1)
-+
-+#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
-+#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
-+#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
-+#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
-+
-+#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
-+#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
-+#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
-+#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
-+
-+#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
-+#define S3C2410_LCDCON4_WLH(x) ((x) << 0)
-+
-+#define S3C2410_LCDCON5_BPP24BL (1<<12)
-+#define S3C2410_LCDCON5_FRM565 (1<<11)
-+#define S3C2410_LCDCON5_INVVCLK (1<<10)
-+#define S3C2410_LCDCON5_INVVLINE (1<<9)
-+#define S3C2410_LCDCON5_INVVFRAME (1<<8)
-+#define S3C2410_LCDCON5_INVVD (1<<7)
-+#define S3C2410_LCDCON5_INVVSYNC (1<<8)
-+#define S3C2410_LCDCON5_INVHSYNC (1<<9)
-+#define S3C2410_LCDCON5_INVVDEN (1<<6)
-+#define S3C2410_LCDCON5_INVPWREN (1<<5)
-+#define S3C2410_LCDCON5_INVLEND (1<<4)
-+#define S3C2410_LCDCON5_PWREN (1<<3)
-+#define S3C2410_LCDCON5_ENLEND (1<<2)
-+#define S3C2410_LCDCON5_BSWP (1<<1)
-+#define S3C2410_LCDCON5_HWSWP (1<<0)
-+
-+/* framebuffer start addressed */
-+#define S3C2410_LCDSADDR1 S3C2410_LCDREG(0x14)
-+#define S3C2410_LCDSADDR2 S3C2410_LCDREG(0x18)
-+#define S3C2410_LCDSADDR3 S3C2410_LCDREG(0x1C)
-+
-+/* colour lookup and miscellaneous controls */
-+
-+#define S3C2410_REDLUT S3C2410_LCDREG(0x20)
-+#define S3C2410_GREENLUT S3C2410_LCDREG(0x24)
-+#define S3C2410_BLUELUT S3C2410_LCDREG(0x28)
-+
-+#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
-+#define S3C2410_TPAL S3C2410_LCDREG(0x50)
-+
-+/* interrupt info */
-+#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
-+#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
-+#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
-+#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)
-+
-+#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))
-+
-+#endif /* ASMARM_ARCH_S3C2410_LCD_H */
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-rtc.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,61 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Timer configuration
-+ *
-+ * Changelog:
-+ * 05-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_RTC_H
-+#define ASMARM_ARCH_S3C2410_RTC_H
-+
-+#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
-+
-+#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
-+#define S3C2410_RTCCON_RTCEN (1<<0)
-+#define S3C2410_RTCCON_CLKRST (1<<3)
-+
-+#define S3C2410_TICNT S3C2410_RTCREG(0x44)
-+#define S3C2410_TICNT_ENABLE (1<<7)
-+
-+#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
-+#define S3C2410_RTCALM_ALMEN (1<<6)
-+#define S3C2410_RTCALM_YEAREN (1<<5)
-+#define S3C2410_RTCALM_MONEN (1<<4)
-+#define S3C2410_RTCALM_DAYEN (1<<3)
-+#define S3C2410_RTCALM_HOUREN (1<<2)
-+#define S3C2410_RTCALM_MINEN (1<<1)
-+#define S3C2410_RTCALM_SECEN (1<<0)
-+
-+#define S3C2410_RTCALM_ALL \
-+ S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
-+ S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
-+ S3C2410_RTCALM_SECEN
-+
-+
-+#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
-+#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
-+#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
-+
-+#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
-+#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
-+#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
-+
-+#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
-+
-+#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
-+#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
-+#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
-+#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
-+#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
-+#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
-+#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
-+
-+#endif /* ASMARM_ARCH_S3C2410_RTC_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-serial.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,98 @@
-+/*
-+ * linux/include/asm-arm/arch-s3c2410/S3C2410-serial.h
-+ *
-+ * Internal header file for Samsung S3C2410 serial ports (UART0-2)
-+ *
-+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
-+ *
-+ * Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
-+ *
-+ * Adapted from:
-+ *
-+ * Internal header file for MX1ADS serial ports (UART1 & 2)
-+ *
-+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_SERIAL_H
-+#define ASMARM_ARCH_S3C2410_SERIAL_H
-+
-+#define S3C2410_UARTRXH0_OFF (0x24)
-+#define S3C2410_UARTTXH0_OFF (0x20)
-+#define S3C2410_UARTLCON_OFF (0x00)
-+#define S3C2410_UARTCON_OFF (0x04)
-+#define S3C2410_UARTFCON_OFF (0x08)
-+#define S3C2410_UARTMCON_OFF (0x0C)
-+#define S3C2410_UARTBRDIV_OFF (0x28)
-+#define S3C2410_UARTTRSTAT_OFF (0x10)
-+#define S3C2410_UARTERSTAT_OFF (0x14)
-+#define S3C2410_UARTFSTAT_OFF (0x18)
-+#define S3C2410_UARTMSTAT_OFF (0x1C)
-+
-+
-+#define S3C2410_UART1_OFF (0x4000)
-+#define S3C2410_UART2_OFF (0x8000)
-+
-+#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
-+
-+#define S3C2410_LCON_CS5 (0x0)
-+#define S3C2410_LCON_CS6 (0x1)
-+#define S3C2410_LCON_CS7 (0x2)
-+#define S3C2410_LCON_CS8 (0x3)
-+
-+#define S3C2410_LCON_PNONE (0x0)
-+#define S3C2410_LCON_PEVEN ((0x5)<<3)
-+#define S3C2410_LCON_PODD ((0x4)<<3)
-+
-+#define S3C2410_UMCON_AFC (0x10)
-+#define S3C2410_UMCON_RTS (0x1)
-+
-+#define S3C2410_UMSTAT_CTS (0x1)
-+
-+#define S3C2410_UCON_SBREAK (1<<4)
-+
-+#define S3C2410_UCON_TXILEVEL (1<<9)
-+#define S3C2410_UCON_RXILEVEL (1<<8)
-+#define S3C2410_UCON_TXIRQMODE (1<<2)
-+#define S3C2410_UCON_RXIRQMODE (1<<0)
-+#define S3C2410_UCON_RXFIFO_TOI (1<<7)
-+
-+#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL \
-+ | S3C2410_UCON_TXIRQMODE | S3C2410_UCON_RXIRQMODE \
-+ | S3C2410_UCON_RXFIFO_TOI)
-+
-+#define S3C2410_UFCON_FIFOMODE (1<<0)
-+#define S3C2410_UFCON_TXTRIG0 (0<<6)
-+#define S3C2410_UFCON_RXTRIG8 (1<<4)
-+#define S3C2410_UFCON_RXTRIG12 (2<<4)
-+
-+#define S3C2410_UFCON_RESETBOTH (3<<1)
-+
-+#define S3C2410_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | S3C2410_UFCON_TXTRIG0 \
-+ | S3C2410_UFCON_RXTRIG8 )
-+
-+#define S3C2410_UFSTAT_TXFULL (1<<9)
-+#define S3C2410_UFSTAT_RXFULL (1<<8)
-+#define S3C2410_UFSTAT_TXMASK (15<<4)
-+#define S3C2410_UFSTAT_TXSHIFT (4)
-+#define S3C2410_UFSTAT_RXMASK (15<<0)
-+#define S3C2410_UFSTAT_RXSHIFT (0)
-+
-+#define S3C2410_UTRSTAT_TXFE (1<<1)
-+#define S3C2410_UTRSTAT_RXDR (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_SERIAL_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-timer.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,81 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-timer.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Timer configuration
-+ *
-+ * Changelog:
-+ * 05-06-2003 BJD Created file
-+ * 26-06-2003 BJD Added more timer definitions to mux / control
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_TIMER_H
-+#define ASMARM_ARCH_S3C2410_TIMER_H
-+
-+#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
-+#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
-+
-+#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
-+#define S3C2410_TCFG1 S3C2410_TIMERREG(0x04)
-+#define S3C2410_TCON S3C2410_TIMERREG(0x08)
-+
-+
-+#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
-+#define S3C2410_TCFG1_MUX4_MASK (15<<16)
-+
-+#define S3C2410_TCFG1_MUX3_TCLK1 (4<<12)
-+#define S3C2410_TCFG1_MUX3_MASK (15<<12)
-+
-+#define S3C2410_TCFG1_MUX2_TCLK1 (4<<8)
-+#define S3C2410_TCFG1_MUX2_MASK (15<<8)
-+
-+#define S3C2410_TCFG1_MUX1_TCLK0 (4<<4)
-+#define S3C2410_TCFG1_MUX1_MASK (15<<4)
-+
-+#define S3C2410_TCFG1_MUX0_TCLK0 (4<<0)
-+#define S3C2410_TCFG1_MUX0_MASK (15<<0)
-+
-+/* for each timer, we have an count buffer, an compare buffer and an
-+ * observation buffer
-+ */
-+
-+/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
-+
-+#define S3C2410_TCNTB(tmr) S3C2410_TIMERREG2(tmr, 0x00)
-+#define S3C2410_TCMPB(tmr) S3C2410_TIMERREG2(tmr, 0x04)
-+#define S3C2410_TCNTO(tmr) S3C2410_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
-+
-+#define S3C2410_TCON_T4RELOAD (1<<22)
-+#define S3C2410_TCON_T4MANUALUPD (1<<21)
-+#define S3C2410_TCON_T4START (1<<20)
-+
-+#define S3C2410_TCON_T3RELOAD (1<<19)
-+#define S3C2410_TCON_T3INVERT (1<<18)
-+#define S3C2410_TCON_T3MANUALUPD (1<<17)
-+#define S3C2410_TCON_T3START (1<<16)
-+
-+#define S3C2410_TCON_T2RELOAD (1<<15)
-+#define S3C2410_TCON_T2INVERT (1<<14)
-+#define S3C2410_TCON_T2MANUALUPD (1<<13)
-+#define S3C2410_TCON_T2START (1<<12)
-+
-+#define S3C2410_TCON_T1RELOAD (1<<11)
-+#define S3C2410_TCON_T1INVERT (1<<10)
-+#define S3C2410_TCON_T1MANUALUPD (1<<9)
-+#define S3C2410_TCON_T1START (1<<8)
-+
-+#define S3C2410_TCON_T0DEADZONE (1<<4)
-+#define S3C2410_TCON_T0RELOAD (1<<3)
-+#define S3C2410_TCON_T0INVERT (1<<2)
-+#define S3C2410_TCON_T0MANUALUPD (1<<1)
-+#define S3C2410_TCON_T0START (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_TIMER_H */
-+
-+
-+
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,40 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Watchdog timer control
-+ *
-+ * Changelog:
-+ * 21-06-2003 BJD Created file
-+*/
-+
-+#ifndef ASMARM_ARCH_S3C2410_WATCHDOG_H
-+#define ASMARM_ARCH_S3C2410_WATCHDOG_H
-+
-+#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
-+
-+#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
-+#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
-+#define S3C2410_WTCNT S3C2410_WDOGREG(0x08)
-+
-+/* the watchdog can either generate a reset pulse, or an interrupt. */
-+
-+#define S3C2410_WTCON_RSTEN (0x01)
-+#define S3C2410_WTCON_INTEN (1<<2)
-+#define S3C2410_WTCON_ENABLE (1<<5)
-+
-+#define S3C2410_WTCON_DIV16 (0<<3)
-+#define S3C2410_WTCON_DIV32 (1<<3)
-+#define S3C2410_WTCON_DIV64 (2<<3)
-+#define S3C2410_WTCON_DIV128 (3<<3)
-+
-+#define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
-+
-+#endif /* ASMARM_ARCH_S3C2410_WATCHDOG_H */
-+
-+
---- linux-2.4.25/include/asm-arm/bugs.h~2.4.25-vrs2.patch 2000-09-19 00:15:23.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/bugs.h 2004-03-31 17:15:09.000000000 +0200
-@@ -10,8 +10,17 @@
- #ifndef __ASM_BUGS_H
- #define __ASM_BUGS_H
-
-+#include <linux/config.h>
- #include <asm/proc-fns.h>
-
--#define check_bugs() cpu_check_bugs()
-+extern void check_writebuffer_bugs(void);
-+
-+static inline void check_bugs(void)
-+{
-+#ifdef CONFIG_CPU_32
-+ check_writebuffer_bugs();
-+#endif
-+ cpu_check_bugs();
-+}
-
- #endif
---- linux-2.4.25/include/asm-arm/div64.h~2.4.25-vrs2.patch 2000-01-13 22:30:31.000000000 +0100
-+++ linux-2.4.25/include/asm-arm/div64.h 2004-03-31 17:15:09.000000000 +0200
-@@ -4,9 +4,13 @@
- /* We're not 64-bit, but... */
- #define do_div(n,base) \
- ({ \
-- int __res; \
-- __res = ((unsigned long)n) % (unsigned int)base; \
-- n = ((unsigned long)n) / (unsigned int)base; \
-+ register int __res asm("r2") = base; \
-+ register unsigned long long __n asm("r0") = n; \
-+ asm("bl do_div64" \
-+ : "=r" (__n), "=r" (__res) \
-+ : "0" (__n), "1" (__res) \
-+ : "r3", "ip", "lr", "cc"); \
-+ n = __n; \
- __res; \
- })
-
---- linux-2.4.25/include/asm-arm/elf.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/include/asm-arm/elf.h 2004-03-31 17:15:09.000000000 +0200
-@@ -45,8 +45,8 @@
-
- #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
--/* When the program starts, a1 contains a pointer to a function to be
-- registered with atexit, as per the SVR4 ABI. A value of 0 means we
-+/* When the program starts, a1 contains a pointer to a function to be
-+ registered with atexit, as per the SVR4 ABI. A value of 0 means we
- have no such handler. */
- #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
-
---- linux-2.4.25/include/asm-arm/mach/dma.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/mach/dma.h 2004-03-31 17:15:09.000000000 +0200
-@@ -41,6 +41,7 @@
- unsigned int dma_base; /* Controller base address */
- int dma_irq; /* Controller IRQ */
- struct scatterlist cur_sg; /* Current controller buffer */
-+ unsigned int state; /* RiscPC DMA status */
-
- struct dma_ops *d_ops;
- };
---- linux-2.4.25/include/asm-arm/mach/serial_at91rm9200.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/mach/serial_at91rm9200.h 2004-03-31 17:15:09.000000000 +0200
-@@ -10,7 +10,6 @@
- #include <linux/config.h>
-
- struct uart_port;
--struct uart_info;
-
- /*
- * This is a temporary structure for registering these
-@@ -22,11 +21,11 @@
- void (*enable_ms)(struct uart_port *);
- void (*pm)(struct uart_port *, u_int, u_int);
- int (*set_wake)(struct uart_port *, u_int);
-- int (*open)(struct uart_port *, struct uart_info *);
-- void (*close)(struct uart_port *, struct uart_info *);
-+ int (*open)(struct uart_port *);
-+ void (*close)(struct uart_port *);
- };
-
--#if defined(CONFIG_SERIAL_AT91RM9200)
-+#if defined(CONFIG_SERIAL_AT91)
- void at91rm9200_register_uart_fns(struct at91rm9200_port_fns *fns);
- void at91rm9200_register_uart(int idx, int port);
- #else
---- linux-2.4.25/include/asm-arm/proc-armv/processor.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-armv/processor.h 2004-03-31 17:15:09.000000000 +0200
-@@ -54,7 +54,9 @@
- regs->ARM_cpsr = USR_MODE; \
- else \
- regs->ARM_cpsr = USR26_MODE; \
-- regs->ARM_pc = pc; /* pc */ \
-+ if (elf_hwcap & HWCAP_THUMB && pc & 1) \
-+ regs->ARM_cpsr |= PSR_T_BIT; \
-+ regs->ARM_pc = pc & ~1; /* pc */ \
- regs->ARM_sp = sp; /* sp */ \
- regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
- regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
---- linux-2.4.25/include/asm-arm/proc-armv/ptrace.h~2.4.25-vrs2.patch 2000-11-28 02:07:59.000000000 +0100
-+++ linux-2.4.25/include/asm-arm/proc-armv/ptrace.h 2004-03-31 17:15:09.000000000 +0200
-@@ -33,6 +33,16 @@
- #define CC_N_BIT (1 << 31)
- #define PCMASK 0
-
-+/* 2.5 versions */
-+#define PSR_T_BIT 0x00000020
-+#define PSR_F_BIT 0x00000040
-+#define PSR_I_BIT 0x00000080
-+#define PSR_J_BIT 0x01000000
-+#define PSR_V_BIT 0x10000000
-+#define PSR_C_BIT 0x20000000
-+#define PSR_Z_BIT 0x40000000
-+#define PSR_N_BIT 0x80000000
-+
- #ifndef __ASSEMBLY__
-
- /* this struct defines the way the registers are stored on the
---- linux-2.4.25/include/asm-arm/proc-armv/uaccess.h~2.4.25-vrs2.patch 2001-10-25 22:53:55.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-armv/uaccess.h 2004-03-31 17:15:09.000000000 +0200
-@@ -12,12 +12,11 @@
- * Note that this is actually 0x1,0000,0000
- */
- #define KERNEL_DS 0x00000000
--#define USER_DS PAGE_OFFSET
-+#define USER_DS TASK_SIZE
-
- static inline void set_fs (mm_segment_t fs)
- {
- current->addr_limit = fs;
--
- modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
- }
-
-@@ -38,7 +37,7 @@
- : "cc"); \
- (flag == 0); })
-
--#define __put_user_asm_byte(x,addr,err) \
-+#define __put_user_asm_byte(x,__pu_addr,err) \
- __asm__ __volatile__( \
- "1: strbt %1,[%2],#0\n" \
- "2:\n" \
-@@ -51,18 +50,18 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err) \
-- : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err) \
-+ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
-+ : "cc")
-
--#define __put_user_asm_half(x,addr,err) \
-+#define __put_user_asm_half(x,__pu_addr,err) \
- ({ \
- unsigned long __temp = (unsigned long)(x); \
-- unsigned long __ptr = (unsigned long)(addr); \
-- __put_user_asm_byte(__temp, __ptr, err); \
-- __put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
-+ __put_user_asm_byte(__temp, __pu_addr, err); \
-+ __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
- })
-
--#define __put_user_asm_word(x,addr,err) \
-+#define __put_user_asm_word(x,__pu_addr,err) \
- __asm__ __volatile__( \
- "1: strt %1,[%2],#0\n" \
- "2:\n" \
-@@ -75,8 +74,28 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err) \
-- : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err) \
-+ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
-+ : "cc")
-+
-+#define __put_user_asm_dword(x,__pu_addr,err) \
-+ __asm__ __volatile__( \
-+ "1: strt %R2, [%1], #4\n" \
-+ "2: strt %Q2, [%1], #0\n" \
-+ "3:\n" \
-+ " .section .fixup,\"ax\"\n" \
-+ " .align 2\n" \
-+ "4: mov %0, %3\n" \
-+ " b 3b\n" \
-+ " .previous\n" \
-+ " .section __ex_table,\"a\"\n" \
-+ " .align 3\n" \
-+ " .long 1b, 4b\n" \
-+ " .long 2b, 4b\n" \
-+ " .previous" \
-+ : "+r" (err), "+r" (__pu_addr) \
-+ : "r" (x), "i" (-EFAULT) \
-+ : "cc")
-
- #define __get_user_asm_byte(x,addr,err) \
- __asm__ __volatile__( \
-@@ -92,18 +111,18 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err), "=&r" (x) \
-- : "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err), "=&r" (x) \
-+ : "r" (addr), "i" (-EFAULT) \
-+ : "cc")
-
--#define __get_user_asm_half(x,addr,err) \
-+#define __get_user_asm_half(x,__gu_addr,err) \
- ({ \
-- unsigned long __b1, __b2, __ptr = (unsigned long)addr; \
-- __get_user_asm_byte(__b1, __ptr, err); \
-- __get_user_asm_byte(__b2, __ptr + 1, err); \
-+ unsigned long __b1, __b2; \
-+ __get_user_asm_byte(__b1, __gu_addr, err); \
-+ __get_user_asm_byte(__b2, __gu_addr + 1, err); \
- (x) = __b1 | (__b2 << 8); \
- })
-
--
- #define __get_user_asm_word(x,addr,err) \
- __asm__ __volatile__( \
- "1: ldrt %1,[%2],#0\n" \
-@@ -118,8 +137,9 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err), "=&r" (x) \
-- : "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err), "=&r" (x) \
-+ : "r" (addr), "i" (-EFAULT) \
-+ : "cc")
-
- extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
- #define __do_copy_from_user(to,from,n) \
---- linux-2.4.25/include/asm-arm/proc-fns.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/proc-fns.h 2004-03-31 17:15:09.000000000 +0200
-@@ -76,6 +76,30 @@
- # define CPU_NAME arm926
- # endif
- # endif
-+# ifdef CONFIG_CPU_ARM1020
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1020
-+# endif
-+# endif
-+# ifdef CONFIG_CPU_ARM1020E
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1020E
-+# endif
-+# endif
-+# ifdef CONFIG_CPU_ARM1022
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1022
-+# endif
-+# endif
- # ifdef CONFIG_CPU_ARM1026
- # ifdef CPU_NAME
- # undef MULTI_CPU
---- linux-2.4.25/include/asm-arm/processor.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/processor.h 2004-03-31 17:15:09.000000000 +0200
-@@ -43,6 +43,7 @@
- #include <asm/atomic.h>
- #include <asm/ptrace.h>
- #include <asm/arch/memory.h>
-+#include <asm/elf.h>
- #include <asm/proc/processor.h>
- #include <asm/types.h>
-
---- linux-2.4.25/include/asm-arm/system.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/system.h 2004-03-31 17:15:09.000000000 +0200
-@@ -29,6 +29,10 @@
-
- void die_if_kernel(const char *str, struct pt_regs *regs, int err);
-
-+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-+ struct pt_regs *),
-+ int sig, const char *name);
-+
- #include <asm/proc-fns.h>
-
- #define xchg(ptr,x) \
-@@ -89,6 +93,14 @@
- #define sti() local_irq_enable()
- #define clf() __clf()
- #define stf() __stf()
-+
-+#define irqs_disabled() \
-+({ \
-+ unsigned long flags; \
-+ local_save_flags(flags); \
-+ flags & PSR_I_BIT; \
-+})
-+
- #define save_flags(x) local_save_flags(x)
- #define restore_flags(x) local_irq_restore(x)
- #define save_flags_cli(x) local_irq_save(x)
---- linux-2.4.25/include/asm-arm/termios.h~2.4.25-vrs2.patch 2001-06-12 04:15:27.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/termios.h 2004-03-31 17:15:09.000000000 +0200
-@@ -47,6 +47,8 @@
- #define TIOCM_OUT2 0x4000
- #define TIOCM_LOOP 0x8000
-
-+#define TIOCM_MODEM_BITS TIOCM_OUT2 /* IRDA support */
-+
- /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
- /* line disciplines */
---- linux-2.4.25/include/asm-arm/uaccess.h~2.4.25-vrs2.patch 2001-10-25 22:53:55.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/uaccess.h 2004-03-31 17:15:09.000000000 +0200
-@@ -74,14 +74,14 @@
- __asm__ __volatile__ ("bl __get_user_" #__s \
- : "=&r" (__e), "=r" (__r1) \
- : "0" (__p) \
-- : __i)
-+ : __i, "cc")
-
- #define get_user(x,p) \
- ({ \
- const register typeof(*(p)) *__p asm("r0") = (p); \
- register typeof(*(p)) __r1 asm("r1"); \
- register int __e asm("r0"); \
-- switch (sizeof(*(p))) { \
-+ switch (sizeof(*(__p))) { \
- case 1: \
- __get_user_x(__r1, __p, __e, 1, "lr"); \
- break; \
-@@ -100,8 +100,31 @@
- __e; \
- })
-
--#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
--#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-+#define __get_user(x,ptr) \
-+({ \
-+ long __gu_err = 0; \
-+ __get_user_err((x),(ptr),__gu_err); \
-+ __gu_err; \
-+})
-+
-+#define __get_user_error(x,ptr,err) \
-+({ \
-+ __get_user_err((x),(ptr),err); \
-+ (void) 0; \
-+})
-+
-+#define __get_user_err(x,ptr,err) \
-+do { \
-+ unsigned long __gu_addr = (unsigned long)(ptr); \
-+ unsigned long __gu_val; \
-+ switch (sizeof(*(ptr))) { \
-+ case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
-+ case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
-+ case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
-+ default: (__gu_val) = __get_user_bad(); \
-+ } \
-+ (x) = (__typeof__(*(ptr)))__gu_val; \
-+} while (0)
-
- extern int __put_user_1(void *, unsigned int);
- extern int __put_user_2(void *, unsigned int);
-@@ -113,22 +136,22 @@
- __asm__ __volatile__ ("bl __put_user_" #__s \
- : "=&r" (__e) \
- : "0" (__p), "r" (__r1) \
-- : __i)
-+ : __i, "cc")
-
- #define put_user(x,p) \
- ({ \
- const register typeof(*(p)) __r1 asm("r1") = (x); \
- const register typeof(*(p)) *__p asm("r0") = (p); \
- register int __e asm("r0"); \
-- switch (sizeof(*(p))) { \
-+ switch (sizeof(*(__p))) { \
- case 1: \
-- __put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 1, "ip", "lr"); \
- break; \
- case 2: \
-- __put_user_x(__r1, __p, __e, 2, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 2, "ip", "lr"); \
- break; \
- case 4: \
-- __put_user_x(__r1, __p, __e, 4, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 4, "ip", "lr"); \
- break; \
- case 8: \
- __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \
-@@ -138,8 +161,31 @@
- __e; \
- })
-
--#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
--#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-+#define __put_user(x,ptr) \
-+({ \
-+ long __pu_err = 0; \
-+ __put_user_err((x),(ptr),__pu_err); \
-+ __pu_err; \
-+})
-+
-+#define __put_user_error(x,ptr,err) \
-+({ \
-+ __put_user_err((x),(ptr),err); \
-+ (void) 0; \
-+})
-+
-+#define __put_user_err(x,ptr,err) \
-+do { \
-+ unsigned long __pu_addr = (unsigned long)(ptr); \
-+ __typeof__(*(ptr)) __pu_val = (x); \
-+ switch (sizeof(*(ptr))) { \
-+ case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
-+ case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
-+ case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
-+ case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
-+ default: __put_user_bad(); \
-+ } \
-+} while (0)
-
- static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
- {
-@@ -209,82 +255,4 @@
- return res;
- }
-
--/*
-- * These are the work horses of the get/put_user functions
-- */
--#if 0
--#define __get_user_check(x,ptr,size) \
--({ \
-- long __gu_err = -EFAULT, __gu_val = 0; \
-- const __typeof__(*(ptr)) *__gu_addr = (ptr); \
-- if (access_ok(VERIFY_READ,__gu_addr,size)) { \
-- __gu_err = 0; \
-- __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
-- } \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- __gu_err; \
--})
--#endif
--
--#define __get_user_nocheck(x,ptr,size) \
--({ \
-- long __gu_err = 0, __gu_val; \
-- __get_user_size(__gu_val,(ptr),(size),__gu_err); \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- __gu_err; \
--})
--
--#define __get_user_nocheck_error(x,ptr,size,err) \
--({ \
-- long __gu_val; \
-- __get_user_size(__gu_val,(ptr),(size),(err)); \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- (void) 0; \
--})
--
--#define __put_user_check(x,ptr,size) \
--({ \
-- long __pu_err = -EFAULT; \
-- __typeof__(*(ptr)) *__pu_addr = (ptr); \
-- if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \
-- __pu_err = 0; \
-- __put_user_size((x),__pu_addr,(size),__pu_err); \
-- } \
-- __pu_err; \
--})
--
--#define __put_user_nocheck(x,ptr,size) \
--({ \
-- long __pu_err = 0; \
-- __typeof__(*(ptr)) *__pu_addr = (ptr); \
-- __put_user_size((x),__pu_addr,(size),__pu_err); \
-- __pu_err; \
--})
--
--#define __put_user_nocheck_error(x,ptr,size,err) \
--({ \
-- __put_user_size((x),(ptr),(size),err); \
-- (void) 0; \
--})
--
--#define __get_user_size(x,ptr,size,retval) \
--do { \
-- switch (size) { \
-- case 1: __get_user_asm_byte(x,ptr,retval); break; \
-- case 2: __get_user_asm_half(x,ptr,retval); break; \
-- case 4: __get_user_asm_word(x,ptr,retval); break; \
-- default: (x) = __get_user_bad(); \
-- } \
--} while (0)
--
--#define __put_user_size(x,ptr,size,retval) \
--do { \
-- switch (size) { \
-- case 1: __put_user_asm_byte(x,ptr,retval); break; \
-- case 2: __put_user_asm_half(x,ptr,retval); break; \
-- case 4: __put_user_asm_word(x,ptr,retval); break; \
-- default: __put_user_bad(); \
-- } \
--} while (0)
--
- #endif /* _ASMARM_UACCESS_H */
---- linux-2.4.25/include/asm-arm/unistd.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-arm/unistd.h 2004-03-31 17:15:09.000000000 +0200
-@@ -31,7 +31,7 @@
- #define __NR_write (__NR_SYSCALL_BASE+ 4)
- #define __NR_open (__NR_SYSCALL_BASE+ 5)
- #define __NR_close (__NR_SYSCALL_BASE+ 6)
--#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
-+ /* 7 was sys_waitpid */
- #define __NR_creat (__NR_SYSCALL_BASE+ 8)
- #define __NR_link (__NR_SYSCALL_BASE+ 9)
- #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
-@@ -41,8 +41,8 @@
- #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
- #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
- #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
--#define __NR_break (__NR_SYSCALL_BASE+ 17)
--
-+ /* 17 was sys_break */
-+ /* 18 was sys_stat */
- #define __NR_lseek (__NR_SYSCALL_BASE+ 19)
- #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
- #define __NR_mount (__NR_SYSCALL_BASE+ 21)
-@@ -52,14 +52,14 @@
- #define __NR_stime (__NR_SYSCALL_BASE+ 25)
- #define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
- #define __NR_alarm (__NR_SYSCALL_BASE+ 27)
--
-+ /* 28 was sys_fstat */
- #define __NR_pause (__NR_SYSCALL_BASE+ 29)
- #define __NR_utime (__NR_SYSCALL_BASE+ 30)
--#define __NR_stty (__NR_SYSCALL_BASE+ 31)
--#define __NR_gtty (__NR_SYSCALL_BASE+ 32)
-+ /* 31 was sys_stty */
-+ /* 32 was sys_gtty */
- #define __NR_access (__NR_SYSCALL_BASE+ 33)
- #define __NR_nice (__NR_SYSCALL_BASE+ 34)
--#define __NR_ftime (__NR_SYSCALL_BASE+ 35)
-+ /* 35 was sys_ftime */
- #define __NR_sync (__NR_SYSCALL_BASE+ 36)
- #define __NR_kill (__NR_SYSCALL_BASE+ 37)
- #define __NR_rename (__NR_SYSCALL_BASE+ 38)
-@@ -68,22 +68,23 @@
- #define __NR_dup (__NR_SYSCALL_BASE+ 41)
- #define __NR_pipe (__NR_SYSCALL_BASE+ 42)
- #define __NR_times (__NR_SYSCALL_BASE+ 43)
--#define __NR_prof (__NR_SYSCALL_BASE+ 44)
-+ /* 44 was sys_prof */
- #define __NR_brk (__NR_SYSCALL_BASE+ 45)
- #define __NR_setgid (__NR_SYSCALL_BASE+ 46)
- #define __NR_getgid (__NR_SYSCALL_BASE+ 47)
--#define __NR_signal (__NR_SYSCALL_BASE+ 48)
-+ /* 48 was sys_signal */
- #define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
- #define __NR_getegid (__NR_SYSCALL_BASE+ 50)
- #define __NR_acct (__NR_SYSCALL_BASE+ 51)
- #define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
--#define __NR_lock (__NR_SYSCALL_BASE+ 53)
-+ /* 53 was sys_lock */
- #define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
- #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
--#define __NR_mpx (__NR_SYSCALL_BASE+ 56)
-+ /* 56 was sys_mpx */
- #define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
- #define __NR_ulimit (__NR_SYSCALL_BASE+ 58)
--
-+ /* 58 was sys_ulimit */
-+ /* 59 was sys_olduname */
- #define __NR_umask (__NR_SYSCALL_BASE+ 60)
- #define __NR_chroot (__NR_SYSCALL_BASE+ 61)
- #define __NR_ustat (__NR_SYSCALL_BASE+ 62)
-@@ -92,8 +93,8 @@
- #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
- #define __NR_setsid (__NR_SYSCALL_BASE+ 66)
- #define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
--#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68)
--#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69)
-+ /* 68 was sys_sgetmask */
-+ /* 69 was sys_ssetmask */
- #define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
- #define __NR_setregid (__NR_SYSCALL_BASE+ 71)
- #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
-@@ -108,7 +109,7 @@
- #define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
- #define __NR_select (__NR_SYSCALL_BASE+ 82)
- #define __NR_symlink (__NR_SYSCALL_BASE+ 83)
--
-+ /* 84 was sys_lstat */
- #define __NR_readlink (__NR_SYSCALL_BASE+ 85)
- #define __NR_uselib (__NR_SYSCALL_BASE+ 86)
- #define __NR_swapon (__NR_SYSCALL_BASE+ 87)
-@@ -122,10 +123,10 @@
- #define __NR_fchown (__NR_SYSCALL_BASE+ 95)
- #define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
- #define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
--#define __NR_profil (__NR_SYSCALL_BASE+ 98)
-+ /* 98 was sys_profil */
- #define __NR_statfs (__NR_SYSCALL_BASE+ 99)
- #define __NR_fstatfs (__NR_SYSCALL_BASE+100)
--#define __NR_ioperm (__NR_SYSCALL_BASE+101)
-+ /* 101 was sys_ioperm */
- #define __NR_socketcall (__NR_SYSCALL_BASE+102)
- #define __NR_syslog (__NR_SYSCALL_BASE+103)
- #define __NR_setitimer (__NR_SYSCALL_BASE+104)
-@@ -133,10 +134,10 @@
- #define __NR_stat (__NR_SYSCALL_BASE+106)
- #define __NR_lstat (__NR_SYSCALL_BASE+107)
- #define __NR_fstat (__NR_SYSCALL_BASE+108)
--
--
-+ /* 109 was sys_uname */
-+ /* 110 was sys_iopl */
- #define __NR_vhangup (__NR_SYSCALL_BASE+111)
--#define __NR_idle (__NR_SYSCALL_BASE+112)
-+ /* 112 was sys_idle */
- #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
- #define __NR_wait4 (__NR_SYSCALL_BASE+114)
- #define __NR_swapoff (__NR_SYSCALL_BASE+115)
-@@ -147,7 +148,7 @@
- #define __NR_clone (__NR_SYSCALL_BASE+120)
- #define __NR_setdomainname (__NR_SYSCALL_BASE+121)
- #define __NR_uname (__NR_SYSCALL_BASE+122)
--#define __NR_modify_ldt (__NR_SYSCALL_BASE+123)
-+ /* 123 was sys_modify_ldt */
- #define __NR_adjtimex (__NR_SYSCALL_BASE+124)
- #define __NR_mprotect (__NR_SYSCALL_BASE+125)
- #define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
-@@ -161,7 +162,7 @@
- #define __NR_bdflush (__NR_SYSCALL_BASE+134)
- #define __NR_sysfs (__NR_SYSCALL_BASE+135)
- #define __NR_personality (__NR_SYSCALL_BASE+136)
--#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */
-+ /* 137 was sys_afs_syscall */
- #define __NR_setfsuid (__NR_SYSCALL_BASE+138)
- #define __NR_setfsgid (__NR_SYSCALL_BASE+139)
- #define __NR__llseek (__NR_SYSCALL_BASE+140)
-@@ -190,7 +191,7 @@
- #define __NR_mremap (__NR_SYSCALL_BASE+163)
- #define __NR_setresuid (__NR_SYSCALL_BASE+164)
- #define __NR_getresuid (__NR_SYSCALL_BASE+165)
--#define __NR_vm86 (__NR_SYSCALL_BASE+166)
-+ /* 166 was sys_vm86 */
- #define __NR_query_module (__NR_SYSCALL_BASE+167)
- #define __NR_poll (__NR_SYSCALL_BASE+168)
- #define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
---- linux-2.4.25/include/asm-i386/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/asm-i386/ide.h 2004-03-31 17:15:09.000000000 +0200
-@@ -23,39 +23,15 @@
- # endif
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- switch (base) {
-- case 0x1f0: return 14;
-- case 0x170: return 15;
-- case 0x1e8: return 11;
-- case 0x168: return 10;
-- case 0x1e0: return 8;
-- case 0x160: return 12;
-- default:
-- return 0;
-- }
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- switch (index) {
-- case 0: return 0x1f0;
-- case 1: return 0x170;
-- case 2: return 0x1e8;
-- case 3: return 0x168;
-- case 4: return 0x1e0;
-- case 5: return 0x160;
-- default:
-- return 0;
-- }
--}
-+#define ide_default_io_base(i) ((ide_ioreg_t)0)
-+#define ide_default_irq(b) (0)
-
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
- ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(hw, 0, sizeof(*hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -63,7 +39,7 @@
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
-- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-+ hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
- }
- if (irq != NULL)
- *irq = 0;
-@@ -74,14 +50,25 @@
- {
- #ifndef CONFIG_BLK_DEV_IDEPCI
- hw_regs_t hw;
-- int index;
-
-- for(index = 0; index < MAX_HWIFS; index++) {
-- memset(&hw, 0, sizeof hw);
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
-+ ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
-+ hw.irq = 14;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
-+ hw.irq = 15;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
-+ hw.irq = 11;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
-+ hw.irq = 10;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e0, 0x3e6, NULL);
-+ hw.irq = 8;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x160, 0x366, NULL);
-+ hw.irq = 12;
-+ ide_register_hw(&hw, NULL);
- #endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
---- linux-2.4.25/include/asm-i386/param.h~2.4.25-vrs2.patch 2000-10-27 20:04:43.000000000 +0200
-+++ linux-2.4.25/include/asm-i386/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -3,6 +3,16 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#if HZ == 100
-+/* X86 is defined to provide userspace with a world where HZ=100
-+ We have to do this, (x*const)/const2 isnt optimised out because its not
-+ a null operation as it might overflow.. */
-+#define hz_to_std(a) (a)
-+#else
-+#define hz_to_std(a) ((a)*(100/HZ)+((a)*(100%HZ))/HZ)
-+#endif
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.25/include/asm-i386/pgtable.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.25/include/asm-i386/pgtable.h 2004-03-31 17:15:09.000000000 +0200
-@@ -361,7 +361,6 @@
- #endif /* !__ASSEMBLY__ */
-
- /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
--#define PageSkip(page) (0)
- #define kern_addr_valid(addr) (1)
-
- #define io_remap_page_range remap_page_range
---- linux-2.4.25/include/asm-ia64/param.h~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/include/asm-ia64/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -8,6 +8,10 @@
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
-+
- #define EXEC_PAGESIZE 65536
-
- #ifndef NGROUPS
---- linux-2.4.25/include/asm-m68k/param.h~2.4.25-vrs2.patch 2001-01-04 22:00:55.000000000 +0100
-+++ linux-2.4.25/include/asm-m68k/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192
---- linux-2.4.25/include/asm-mips/ide.h~2.4.25-vrs2.patch 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.25/include/asm-mips/ide.h 2004-03-31 17:15:09.000000000 +0200
-@@ -27,7 +27,7 @@
- int (*ide_default_irq)(ide_ioreg_t base);
- ide_ioreg_t (*ide_default_io_base)(int index);
- void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port,
-- ide_ioreg_t ctrl_port, int *irq);
-+ ide_ioreg_t ctrl_port, int *irq);
- };
-
- extern struct ide_ops *ide_ops;
---- linux-2.4.25/include/asm-ppc/param.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/asm-ppc/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.25/include/asm-s390/param.h~2.4.25-vrs2.patch 2001-02-13 23:13:44.000000000 +0100
-+++ linux-2.4.25/include/asm-s390/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -11,6 +11,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.25/include/asm-sh/param.h~2.4.25-vrs2.patch 2001-01-04 22:19:13.000000000 +0100
-+++ linux-2.4.25/include/asm-sh/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.25/include/asm-sparc/param.h~2.4.25-vrs2.patch 2000-10-30 23:34:12.000000000 +0100
-+++ linux-2.4.25/include/asm-sparc/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -4,6 +4,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
---- linux-2.4.25/include/asm-sparc64/ide.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/asm-sparc64/ide.h 2004-03-31 17:15:09.000000000 +0200
-@@ -25,21 +25,12 @@
- # endif
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- return 0;
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- return 0;
--}
--
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
-- ide_ioreg_t reg = data_port;
-+ ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(&hw, 0, sizeof(hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -60,16 +51,6 @@
- */
- static __inline__ void ide_init_default_hwifs(void)
- {
--#ifndef CONFIG_BLK_DEV_IDEPCI
-- hw_regs_t hw;
-- int index;
--
-- for (index = 0; index < MAX_HWIFS; index++) {
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
--#endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
- #undef SUPPORT_SLOW_DATA_PORTS
---- linux-2.4.25/include/asm-sparc64/param.h~2.4.25-vrs2.patch 2000-10-30 23:34:12.000000000 +0100
-+++ linux-2.4.25/include/asm-sparc64/param.h 2004-03-31 17:15:09.000000000 +0200
-@@ -4,6 +4,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
---- linux-2.4.25/include/linux/console_struct.h~2.4.25-vrs2.patch 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.25/include/linux/console_struct.h 2004-03-31 17:15:09.000000000 +0200
-@@ -7,6 +7,8 @@
- * Fields marked with [#] must be set by the low-level driver.
- * Fields marked with [!] can be changed by the low-level driver
- * to achieve effects such as fast scrolling by changing the origin.
-+ *
-+ * 11/07/1998 RMK Changed vc_state to be a function pointer
- */
-
- #ifndef _LINUX_CONSOLE_STRUCT_H_
-@@ -34,7 +36,11 @@
- unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
- unsigned int vc_x, vc_y; /* Cursor position */
- unsigned int vc_top, vc_bottom; /* Scrolling region */
-+#ifdef CONSOLE_WIP
-+ int (*vc_state)(int currcons, struct tty_struct *tty, unsigned int c);
-+#else
- unsigned int vc_state; /* Escape sequence parser state */
-+#endif
- unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
- unsigned long vc_origin; /* [!] Start of real screen */
- unsigned long vc_scr_end; /* [!] End of real screen */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/cpufreq.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,94 @@
-+/*
-+ * linux/include/linux/cpufreq.h
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * $Id: cpufreq.h,v 1.5.2.1 2002/05/03 13:26:27 rmk Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef _LINUX_CPUFREQ_H
-+#define _LINUX_CPUFREQ_H
-+
-+#include <linux/config.h>
-+#include <linux/notifier.h>
-+
-+#ifndef CONFIG_SMP
-+#define cpufreq_current(cpu) ((void)(cpu), __cpufreq_cur)
-+#define cpufreq_max(cpu) ((void)(cpu), __cpufreq_max)
-+#define cpufreq_min(cpu) ((void)(cpu), __cpufreq_min)
-+#else
-+/*
-+ * Should be something like:
-+ *
-+ * typedef struct {
-+ * u_int current;
-+ * u_int max;
-+ * u_int min;
-+ * } __cacheline_aligned cpufreq_info_t;
-+ *
-+ * static cpufreq_info_t cpufreq_info;
-+ *
-+ * #define cpufreq_current(cpu) (cpufreq_info[cpu].current)
-+ * #define cpufreq_max(cpu) (cpufreq_info[cpu].max)
-+ * #define cpufreq_min(cpu) (cpufreq_info[cpu].min)
-+ *
-+ * Maybe we should find some other per-cpu structure to
-+ * bury this in?
-+ */
-+#error fill in SMP version
-+#endif
-+
-+struct cpufreq_info {
-+ unsigned int old_freq;
-+ unsigned int new_freq;
-+};
-+
-+/*
-+ * The max and min frequency rates that the registered device
-+ * can tolerate. Never set any element this structure directly -
-+ * always use cpu_updateminmax.
-+ */
-+struct cpufreq_minmax {
-+ unsigned int min_freq;
-+ unsigned int max_freq;
-+ unsigned int cur_freq;
-+ unsigned int new_freq;
-+};
-+
-+static inline
-+void cpufreq_updateminmax(void *arg, unsigned int min, unsigned int max)
-+{
-+ struct cpufreq_minmax *minmax = arg;
-+
-+ if (minmax->min_freq < min)
-+ minmax->min_freq = min;
-+ if (minmax->max_freq > max)
-+ minmax->max_freq = max;
-+}
-+
-+#define CPUFREQ_MINMAX (0)
-+#define CPUFREQ_PRECHANGE (1)
-+#define CPUFREQ_POSTCHANGE (2)
-+
-+int cpufreq_register_notifier(struct notifier_block *nb);
-+int cpufreq_unregister_notifier(struct notifier_block *nb);
-+
-+int cpufreq_setmax(void);
-+int cpufreq_restore(void);
-+int cpufreq_set(unsigned int khz);
-+unsigned int cpufreq_get(int cpu);
-+
-+/*
-+ * These two functions are only available at init time.
-+ */
-+void cpufreq_init(unsigned int khz,
-+ unsigned int min_freq,
-+ unsigned int max_freq);
-+
-+void cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
-+ void (*setspeed)(unsigned int));
-+
-+#endif
---- linux-2.4.25/include/linux/i2c-id.h~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/include/linux/i2c-id.h 2004-03-31 17:15:09.000000000 +0200
-@@ -20,16 +20,16 @@
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* ------------------------------------------------------------------------- */
-
--/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
-+/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
-
- #ifndef I2C_ID_H
- #define I2C_ID_H
- /*
- * This file is part of the i2c-bus package and contains the identifier
- * values for drivers, adapters and other folk populating these serial
-- * worlds.
-+ * worlds.
- *
-- * These will change often (i.e. additions) , therefore this has been
-+ * These will change often (i.e. additions) , therefore this has been
- * separated from the functional interface definitions of the i2c api.
- *
- */
-@@ -38,10 +38,10 @@
- * ---- Driver types -----------------------------------------------------
- * device id name + number function description, i2c address(es)
- *
-- * Range 1000-1999 range is defined in sensors/sensors.h
-- * Range 0x100 - 0x1ff is for V4L2 Common Components
-+ * Range 1000-1999 range is defined in sensors/sensors.h
-+ * Range 0x100 - 0x1ff is for V4L2 Common Components
- * Range 0xf000 - 0xffff is reserved for local experimentation, and should
-- * never be used in official drivers
-+ * never be used in official drivers
- */
-
- #define I2C_DRIVERID_MSP3400 1
-@@ -90,7 +90,12 @@
- #define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
- #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
- #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
-+#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
-+#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */
- #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */
-+#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */
-+#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
-+#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
- #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
- #define I2C_DRIVERID_SAA7191 57 /* video decoder */
- #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
-@@ -102,8 +107,10 @@
-
- #define I2C_DRIVERID_I2CDEV 900
- #define I2C_DRIVERID_I2CPROC 901
-+#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
-+#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
-
--/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
-+/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
- These were originally in sensors.h in the lm_sensors package */
- #define I2C_DRIVERID_LM78 1002
- #define I2C_DRIVERID_LM75 1003
-@@ -131,6 +138,12 @@
- #define I2C_DRIVERID_ADM1024 1025
- #define I2C_DRIVERID_IT87 1026
- #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
-+#define I2C_DRIVERID_FSCPOS 1028
-+#define I2C_DRIVERID_FSCSCY 1029
-+#define I2C_DRIVERID_PCF8591 1030
-+#define I2C_DRIVERID_SMSC47M1 1031
-+#define I2C_DRIVERID_VT1211 1032
-+#define I2C_DRIVERID_LM92 1033
-
- /*
- * ---- Adapter types ----------------------------------------------------
-@@ -147,7 +160,8 @@
- #define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
- #define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
- #define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
--
-+#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
-+#define I2C_ALGO_SAA7134 0x090000
- #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
-
- #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
-@@ -156,13 +170,15 @@
-
- #define I2C_ALGO_SGI 0x130000 /* SGI algorithm */
-
-+#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
-+
- #define I2C_ALGO_EXP 0x800000 /* experimental */
-
- #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
- #define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
-
- #define I2C_HW_ADAPS 0x10000 /* # adapter types */
--#define I2C_HW_MASK 0xffff
-+#define I2C_HW_MASK 0xffff
-
-
- /* hw specific modules that are defined per algorithm layer
-@@ -182,9 +198,13 @@
- #define I2C_HW_B_I810 0x0a /* Intel I810 */
- #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
- #define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
-+#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
- #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
- #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
- #define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
-+#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
-+#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface */
-+#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
-
- /* --- PCF 8584 based algorithms */
- #define I2C_HW_P_LP 0x00 /* Parallel port interface */
-@@ -197,6 +217,12 @@
- /* --- MPC8xx PowerPC adapters */
- #define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
-
-+/* --- ITE based algorithms */
-+#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
-+
-+/* --- PowerPC on-chip adapters */
-+#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
-+
- /* --- Broadcom SiByte adapters */
- #define I2C_HW_SIBYTE 0x00
-
---- linux-2.4.25/include/linux/ide.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/include/linux/ide.h 2004-03-31 17:15:09.000000000 +0200
-@@ -287,7 +287,9 @@
- * Check for an interrupt and acknowledge the interrupt status
- */
- struct hwif_s;
-+struct ide_drive_s;
- typedef int (ide_ack_intr_t)(struct hwif_s *);
-+typedef void (ide_xfer_data_t)(struct ide_drive_s *, void *, unsigned int);
-
- #ifndef NO_DMA
- #define NO_DMA 255
-@@ -311,10 +313,14 @@
- typedef struct hw_regs_s {
- ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
- int irq; /* our irq number */
-- int dma; /* our dma entry */
-+ int dma; /* our dma number */
- ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
-+ ide_xfer_data_t *ide_output_data; /* write data to i/face */
-+ ide_xfer_data_t *ide_input_data; /* read data from i/face */
-+ ide_xfer_data_t *atapi_output_bytes; /* write bytes to i/face */
-+ ide_xfer_data_t *atapi_input_bytes; /* read bytes from i/face */
- void *priv; /* interface specific data */
-- hwif_chipset_t chipset;
-+ hwif_chipset_t chipset;
- sata_ioreg_t sata_scr[SATA_NR_PORTS];
- sata_ioreg_t sata_misc[SATA_NR_PORTS];
- } hw_regs_t;
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/l3/algo-bit.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,39 @@
-+/*
-+ * linux/include/linux/l3/algo-bit.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * L3 Bus bit-banging algorithm. Derived from i2c-algo-bit.h by
-+ * Simon G. Vogl.
-+ */
-+#ifndef L3_ALGO_BIT_H
-+#define L3_ALGO_BIT_H 1
-+
-+#include <linux/l3/l3.h>
-+
-+struct l3_algo_bit_data {
-+ void (*setdat) (void *data, int state);
-+ void (*setclk) (void *data, int state);
-+ void (*setmode)(void *data, int state);
-+ void (*setdir) (void *data, int in); /* set data direction */
-+ int (*getdat) (void *data);
-+
-+ void *data;
-+
-+ /* bus timings (us) */
-+ int data_hold;
-+ int data_setup;
-+ int clock_high;
-+ int mode_hold;
-+ int mode_setup;
-+ int mode;
-+};
-+
-+int l3_bit_add_bus(struct l3_adapter *);
-+int l3_bit_del_bus(struct l3_adapter *);
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/l3/l3.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,208 @@
-+/*
-+ * linux/include/linux/l3/l3.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * Derived from i2c.h by Simon G. Vogl
-+ */
-+#ifndef L3_H
-+#define L3_H
-+
-+struct l3_msg {
-+ unsigned char addr; /* slave address */
-+ unsigned char flags;
-+#define L3_M_RD 0x01
-+#define L3_M_NOADDR 0x02
-+ unsigned short len; /* msg length */
-+ unsigned char *buf; /* pointer to msg data */
-+};
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+#include <linux/list.h>
-+
-+struct l3_client;
-+
-+struct l3_ops {
-+ int (*open)(struct l3_client *);
-+ int (*command)(struct l3_client *, int cmd, void *arg);
-+ void (*close)(struct l3_client *);
-+};
-+
-+/*
-+ * A driver is capable of handling one or more physical devices present on
-+ * L3 adapters. This information is used to inform the driver of adapter
-+ * events.
-+ */
-+struct l3_driver {
-+ /*
-+ * This name is used to uniquely identify the driver.
-+ * It should be the same as the module name.
-+ */
-+ char name[32];
-+
-+ /*
-+ * Notifies the driver that a new client wishes to use its
-+ * services. Note that the module use count will be increased
-+ * prior to this function being called. In addition, the
-+ * clients driver and adapter fields will have been setup.
-+ */
-+ int (*attach_client)(struct l3_client *);
-+
-+ /*
-+ * Notifies the driver that the client has finished with its
-+ * services, and any memory that it allocated for this client
-+ * should be cleaned up. In addition the chip should be
-+ * shut down.
-+ */
-+ void (*detach_client)(struct l3_client *);
-+
-+ /*
-+ * Possible operations on the driver.
-+ */
-+ struct l3_ops *ops;
-+
-+ /*
-+ * Module structure, if any.
-+ */
-+ struct module *owner;
-+
-+ /*
-+ * drivers list
-+ */
-+ struct list_head drivers;
-+};
-+
-+struct l3_adapter;
-+
-+struct l3_algorithm {
-+ /* textual description */
-+ char name[32];
-+
-+ /* perform bus transactions */
-+ int (*xfer)(struct l3_adapter *, struct l3_msg msgs[], int num);
-+};
-+
-+struct semaphore;
-+
-+/*
-+ * l3_adapter is the structure used to identify a physical L3 bus along
-+ * with the access algorithms necessary to access it.
-+ */
-+struct l3_adapter {
-+ /*
-+ * This name is used to uniquely identify the adapter.
-+ * It should be the same as the module name.
-+ */
-+ char name[32];
-+
-+ /*
-+ * the algorithm to access the bus
-+ */
-+ struct l3_algorithm *algo;
-+
-+ /*
-+ * Algorithm specific data
-+ */
-+ void *algo_data;
-+
-+ /*
-+ * This may be NULL, or should point to the module struct
-+ */
-+ struct module *owner;
-+
-+ /*
-+ * private data for the adapter
-+ */
-+ void *data;
-+
-+ /*
-+ * Our lock. Unlike the i2c layer, we allow this to be used for
-+ * other stuff, like the i2c layer lock. Some people implement
-+ * i2c stuff using the same signals as the l3 bus.
-+ */
-+ struct semaphore *lock;
-+
-+ /*
-+ * List of attached clients.
-+ */
-+ struct list_head clients;
-+
-+ /*
-+ * List of all adapters.
-+ */
-+ struct list_head adapters;
-+};
-+
-+/*
-+ * l3_client identifies a single device (i.e. chip) that is connected to an
-+ * L3 bus. The behaviour is defined by the routines of the driver. This
-+ * function is mainly used for lookup & other admin. functions.
-+ */
-+struct l3_client {
-+ struct l3_adapter *adapter; /* the adapter we sit on */
-+ struct l3_driver *driver; /* and our access routines */
-+ void *driver_data; /* private driver data */
-+ struct list_head __adap;
-+};
-+
-+
-+extern int l3_add_adapter(struct l3_adapter *);
-+extern int l3_del_adapter(struct l3_adapter *);
-+
-+extern int l3_add_driver(struct l3_driver *);
-+extern int l3_del_driver(struct l3_driver *);
-+
-+extern int l3_attach_client(struct l3_client *, const char *, const char *);
-+extern int l3_detach_client(struct l3_client *);
-+
-+extern int l3_transfer(struct l3_adapter *, struct l3_msg msgs[], int);
-+extern int l3_write(struct l3_client *, int, const char *, int);
-+extern int l3_read(struct l3_client *, int, char *, int);
-+
-+/**
-+ * l3_command - send a command to a L3 device driver
-+ * @client: registered client structure
-+ * @cmd: device driver command
-+ * @arg: device driver arguments
-+ *
-+ * Ask the L3 device driver to perform some function. Further information
-+ * should be sought from the device driver in question.
-+ *
-+ * Returns negative error code on failure.
-+ */
-+static inline int l3_command(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ int ret = -EINVAL;
-+
-+ if (ops && ops->command)
-+ ret = ops->command(clnt, cmd, arg);
-+
-+ return ret;
-+}
-+
-+static inline int l3_open(struct l3_client *clnt)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ int ret = 0;
-+
-+ if (ops && ops->open)
-+ ret = ops->open(clnt);
-+ return ret;
-+}
-+
-+static inline void l3_close(struct l3_client *clnt)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ if (ops && ops->close)
-+ ops->close(clnt);
-+}
-+#endif
-+
-+#endif /* L3_H */
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/l3/uda1341.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,50 @@
-+/*
-+ * linux/include/linux/l3/uda1341.h
-+ *
-+ * Philips UDA1341 mixer device driver
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#define UDA1341_NAME "uda1341"
-+
-+struct uda1341_cfg {
-+ unsigned int fs:16;
-+ unsigned int format:3;
-+};
-+
-+#define FMT_I2S 0
-+#define FMT_LSB16 1
-+#define FMT_LSB18 2
-+#define FMT_LSB20 3
-+#define FMT_MSB 4
-+#define FMT_LSB16MSB 5
-+#define FMT_LSB18MSB 6
-+#define FMT_LSB20MSB 7
-+
-+#define L3_UDA1341_CONFIGURE 0x13410001
-+
-+struct l3_gain {
-+ unsigned int left:8;
-+ unsigned int right:8;
-+ unsigned int unused:8;
-+ unsigned int channel:8;
-+};
-+
-+#define L3_SET_VOLUME 0x13410002
-+#define L3_SET_TREBLE 0x13410003
-+#define L3_SET_BASS 0x13410004
-+#define L3_SET_GAIN 0x13410005
-+
-+struct l3_agc {
-+ unsigned int level:8;
-+ unsigned int enable:1;
-+ unsigned int attack:7;
-+ unsigned int decay:8;
-+ unsigned int channel:8;
-+};
-+
-+#define L3_INPUT_AGC 0x13410006
---- linux-2.4.25/include/linux/mm.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/include/linux/mm.h 2004-03-31 17:15:09.000000000 +0200
-@@ -685,6 +685,12 @@
-
- extern struct page * vmalloc_to_page(void *addr);
-
-+#ifndef __arm__
-+#define memc_update_addr(x,y,z)
-+#define memc_update_mm(x)
-+#define memc_clear(x,y)
-+#endif
-+
- #endif /* __KERNEL__ */
-
- #endif
---- linux-2.4.25/include/linux/pci.h~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/include/linux/pci.h 2004-03-31 17:15:09.000000000 +0200
-@@ -410,6 +410,7 @@
-
- char name[90]; /* device name */
- char slot_name[8]; /* slot name */
-+ u32 saved_state[16]; /* for saving the config space before suspend */
- int active; /* ISAPnP: device is active */
- int ro; /* ISAPnP: read only */
- unsigned short regs; /* ISAPnP: supported registers */
-@@ -496,6 +497,8 @@
-
- struct pbus_set_ranges_data
- {
-+ int found_vga:1;
-+ int prefetch_valid:1;
- unsigned long io_start, io_end;
- unsigned long mem_start, mem_end;
- unsigned long prefetch_start, prefetch_end;
-@@ -637,6 +640,8 @@
- int pci_restore_state(struct pci_dev *dev, u32 *buffer);
- int pci_set_power_state(struct pci_dev *dev, int state);
- int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
-+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state);
-+int pci_generic_resume_restore(struct pci_dev *pdev);
-
- /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
-
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/pld/pld_epxa.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,35 @@
-+#ifndef __LINUX_EPXAPLD_H
-+#define __LINUX_EPXAPLD_H
-+
-+/*
-+ * linux/drivers/char/pld/epxapld.h
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+#define PLD_IOC_MAGIC 'p'
-+#if !defined(KERNEL) || defined(CONFIG_PLD_HOTSWAP)
-+#define PLD_IOC_ADD_PLD_DEV _IOW(PLD_IOC_MAGIC, 0xa0, struct pldhs_dev_desc)
-+#define PLD_IOC_REMOVE_PLD_DEVS _IO(PLD_IOC_MAGIC, 0xa1)
-+#define PLD_IOC_SET_INT_MODE _IOW(PLD_IOC_MAGIC, 0xa2, int)
-+#endif
-+
-+#endif
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/pld/pld_hotswap.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,87 @@
-+#ifndef __LINUX_PLD_HOTSWAP_H
-+#define __LINUX_PLD_HOTSWAP_H
-+/*
-+ * linux/drivers/char/pld/pld_hotswap.h
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+
-+/*
-+ * The pld_hotswap ops contain the basic operation required for adding
-+ * and removing devices from the system.
-+ */
-+
-+struct pldhs_dev_info{
-+ unsigned int size;
-+ unsigned short vendor_id;
-+ unsigned short product_id;
-+ unsigned char fsize;
-+ unsigned char nsize;
-+ unsigned short pssize;
-+ unsigned short cmdsize;
-+ unsigned char irq;
-+ unsigned char version;
-+ unsigned int base_addr;
-+ unsigned int reg_size;
-+};
-+
-+struct pldhs_dev_desc{
-+ struct pldhs_dev_info* info;
-+ char* name;
-+ void* data;
-+};
-+
-+#include <linux/pld/pld_epxa.h>
-+
-+
-+#ifdef __KERNEL__
-+struct pld_hotswap_ops{
-+ struct list_head list;
-+ char* name;
-+ int (*add_device)(struct pldhs_dev_info *dev_info, void* dev_ps_data);
-+ int (*remove_devices)(void);
-+ int (*proc_read)(char* buf,char** start,off_t offset,int count,int *eof,void *data);
-+};
-+
-+/*
-+ * These functions are called by the device drivers to register functions
-+ * which should be called when devices are added and removed
-+ */
-+extern int pldhs_register_driver(struct pld_hotswap_ops *drv);
-+extern int pldhs_unregister_driver(char *driver);
-+
-+/*
-+ * These functions are called by the pld loader to add and remove
-+ * device instances from the system. The call the functions regsistered
-+ * the the particular deriver for this purpose
-+ */
-+extern int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data);
-+extern int pldhs_remove_devices(void);
-+
-+/* Macro for formatting data to appear in the proc/pld file */
-+#define PLDHS_READ_PROC_DATA(buf,name,index,base,irq,ps_string) \
-+ sprintf(buf,":%s:%d Base Address, %#lx, IRQ, %d#\n%s\n",\
-+ name,index,base,irq,ps_string)
-+
-+#endif
-+
-+#endif
---- linux-2.4.25/include/linux/serial.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/include/linux/serial.h 2004-03-31 17:15:09.000000000 +0200
-@@ -48,7 +48,7 @@
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned int port_high;
-- int reserved[1];
-+ unsigned long iomap_base; /* cookie passed into ioremap */
- };
-
- /*
---- linux-2.4.25/include/linux/serialP.h~2.4.25-vrs2.patch 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.25/include/linux/serialP.h 2004-03-31 17:15:09.000000000 +0200
-@@ -157,8 +157,8 @@
- struct pci_dev *dev;
- };
-
--extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
--extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-+//extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-+//extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-
- #ifndef PCI_ANY_ID
- #define PCI_ANY_ID (~0)
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/include/linux/serial_core.h 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,441 @@
-+/*
-+ * linux/drivers/char/serial_core.h
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: serial_core.h,v 1.9.2.3 2001/11/26 22:32:45 rmk Exp $
-+ */
-+
-+/*
-+ * The type definitions. These are from Ted Ts'o's serial.h
-+ */
-+#define PORT_UNKNOWN 0
-+#define PORT_8250 1
-+#define PORT_16450 2
-+#define PORT_16550 3
-+#define PORT_16550A 4
-+#define PORT_CIRRUS 5
-+#define PORT_16650 6
-+#define PORT_16650V2 7
-+#define PORT_16750 8
-+#define PORT_STARTECH 9
-+#define PORT_16C950 10
-+#define PORT_16654 11
-+#define PORT_16850 12
-+#define PORT_RSA 13
-+#define PORT_NS16550A 14
-+#define PORT_MAX_8250 14 /* max port ID */
-+
-+/*
-+ * ARM specific type numbers. These are not currently guaranteed
-+ * to be implemented, and will change in the future. These are
-+ * separate so any additions to the old serial.c that occur before
-+ * we are merged can be easily merged here.
-+ */
-+#define PORT_AMBA 32
-+#define PORT_CLPS711X 33
-+#define PORT_SA1100 34
-+#define PORT_UART00 35
-+#define PORT_21285 37
-+
-+/* Sparc type numbers. */
-+#define PORT_SUNZILOG 38
-+#define PORT_SUNSAB 39
-+
-+/* NEC v850. */
-+#define PORT_NB85E_UART 40
-+
-+/* NEC PC-9800 */
-+#define PORT_8251_PC98 41
-+#define PORT_19K_PC98 42
-+#define PORT_FIFO_PC98 43
-+#define PORT_VFAST_PC98 44
-+#define PORT_PC9861 45
-+#define PORT_PC9801_101 46
-+
-+/* DZ */
-+#define PORT_DZ 47
-+
-+#define PORT_OMAHA 48
-+#define PORT_AT91RM9200 49
-+
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/config.h>
-+#include <linux/interrupt.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/spinlock.h>
-+
-+struct uart_port;
-+struct uart_info;
-+struct serial_struct;
-+
-+/*
-+ * This structure describes all the operations that can be
-+ * done on the physical hardware.
-+ */
-+struct uart_ops {
-+ unsigned int (*tx_empty)(struct uart_port *);
-+ void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
-+ unsigned int (*get_mctrl)(struct uart_port *);
-+ void (*stop_tx)(struct uart_port *, unsigned int tty_stop);
-+ void (*start_tx)(struct uart_port *, unsigned int tty_start);
-+ void (*send_xchar)(struct uart_port *, char ch);
-+ void (*stop_rx)(struct uart_port *);
-+ void (*enable_ms)(struct uart_port *);
-+ void (*break_ctl)(struct uart_port *, int ctl);
-+ int (*startup)(struct uart_port *);
-+ void (*shutdown)(struct uart_port *);
-+ void (*change_speed)(struct uart_port *, unsigned int cflag, unsigned int iflag, unsigned int quot);
-+ void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate);
-+ int (*set_wake)(struct uart_port *, unsigned int state);
-+
-+ /*
-+ * Return a string describing the type of the port
-+ */
-+ const char *(*type)(struct uart_port *);
-+
-+ /*
-+ * Release IO and memory resources used by the port.
-+ * This includes iounmap if necessary.
-+ */
-+ void (*release_port)(struct uart_port *);
-+
-+ /*
-+ * Request IO and memory resources used by the port.
-+ * This includes iomapping the port if necessary.
-+ */
-+ int (*request_port)(struct uart_port *);
-+ void (*config_port)(struct uart_port *, int);
-+ int (*verify_port)(struct uart_port *, struct serial_struct *);
-+ int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
-+};
-+
-+#define UART_CONFIG_TYPE (1 << 0)
-+#define UART_CONFIG_IRQ (1 << 1)
-+
-+struct uart_icount {
-+ __u32 cts;
-+ __u32 dsr;
-+ __u32 rng;
-+ __u32 dcd;
-+ __u32 rx;
-+ __u32 tx;
-+ __u32 frame;
-+ __u32 overrun;
-+ __u32 parity;
-+ __u32 brk;
-+ __u32 buf_overrun;
-+};
-+
-+struct uart_port {
-+ spinlock_t lock; /* port lock */
-+ unsigned int iobase; /* in/out[bwl] */
-+ char *membase; /* read/write[bwl] */
-+ unsigned char fifosize; /* tx fifo size */
-+ unsigned char x_char; /* xon/xoff char */
-+ unsigned char regshift; /* reg offset shift */
-+ unsigned char iotype; /* io access style */
-+
-+#define UPIO_PORT (0)
-+#define UPIO_HUB6 (1)
-+#define UPIO_MEM (2)
-+
-+ unsigned int read_status_mask; /* driver specific */
-+ unsigned int ignore_status_mask; /* driver specific */
-+
-+ struct uart_info *info; /* pointer to parent info */
-+ struct uart_icount icount; /* statistics */
-+
-+ struct console *cons; /* struct console, if any */
-+ unsigned long sysrq; /* sysrq timeout */
-+
-+ unsigned int flags;
-+
-+#define UPF_HUP_NOTIFY ASYNC_HUP_NOTIFY
-+#define UPF_FOURPORT ASYNC_FOURPORT
-+#define UPF_SAK ASYNC_SAK
-+#define UPF_SPLIT_TERMIOS ASYNC_SPLIT_TERMIOS
-+#define UPF_SPD_MASK (0x1030)
-+#define UPF_SPD_HI (0x0010)
-+#define UPF_SPD_VHI (0x0020)
-+#define UPF_SPD_CUST (0x0030)
-+#define UPF_SPD_SHI (0x1000)
-+#define UPF_SPD_WARP (0x1010)
-+#define UPF_SKIP_TEST ASYNC_SKIP_TEST
-+#define UPF_AUTO_IRQ ASYNC_AUTO_IRQ
-+#define UPF_SESSION_LOCKOUT ASYNC_SESSION_LOCKOUT
-+#define UPF_PGRP_LOCKOUT ASYNCPGRP_LOCKOUT
-+#define UPF_CALLOUT_NOHUP ASYNC_CALLOUT_NOHUP
-+#define UPF_HARDPPS_CD ASYNC_HARDPPS_CD
-+ /* 12 */
-+#define UPF_LOW_LATENCY ASYNC_LOW_LATENCY
-+#define UPF_BUGGY_UART ASYNC_BUGGY_UART
-+#define UPF_AUTOPROBE ASYNC_AUTOPROBE
-+#define UPF_MAGIC_MULTIPLIER (1 << 16)
-+#define UPF_BOOT_ONLYMCA ASYNC_BOOT_ONLYMCA
-+#define UPF_CONS_FLOW ASYNC_CONS_FLOW
-+#define UPF_SHARE_IRQ ASYNC_SHARE_IRQ
-+#define UPF_BOOT_AUTOCONF ASYNC_BOOT_AUTOCONF
-+#define UPF_RESOURCES (1 << 30)
-+#define UPF_IOREMAP (1 << 31)
-+
-+#define UPF_CHANGE_MASK (0x17fff)
-+#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY)
-+
-+ unsigned int mctrl; /* current modem ctrl settings */
-+ unsigned int timeout; /* character-based timeout */
-+ unsigned int type; /* port type */
-+ struct uart_ops *ops;
-+ unsigned int uartclk; /* base uart clock */
-+ unsigned int custom_divisor;
-+ unsigned int irq; /* irq number */
-+ unsigned int line; /* port index */
-+ unsigned long mapbase; /* for ioremap */
-+ unsigned char hub6; /* this should be in the 8250 driver */
-+ unsigned char unused[7];
-+};
-+
-+/*
-+ * This is the state information which is persistent across opens.
-+ * The low level driver must not to touch any elements contained
-+ * within.
-+ */
-+struct uart_state {
-+ unsigned int close_delay;
-+ unsigned int closing_wait;
-+
-+#define USF_CLOSING_WAIT_INF (0)
-+#define USF_CLOSING_WAIT_NONE (65535)
-+
-+ struct termios normal_termios;
-+ struct termios callout_termios;
-+
-+ int count;
-+ struct uart_info *info;
-+ struct uart_port *port;
-+
-+ struct semaphore sem;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+};
-+
-+#define UART_XMIT_SIZE 1024
-+/*
-+ * This is the state information which is only valid when the port
-+ * is open; it may be freed by the core driver once the device has
-+ * been closed. Either the low level driver or the core can modify
-+ * stuff here.
-+ */
-+struct uart_info {
-+ struct tty_struct *tty;
-+ struct circ_buf xmit;
-+ unsigned int flags;
-+
-+/*
-+ * These are the flags that specific to info->flags, and reflect our
-+ * internal state. They can not be accessed via port->flags. Low
-+ * level drivers must not change these, but may query them instead.
-+ */
-+#define UIF_CHECK_CD ASYNC_CHECK_CD
-+#define UIF_CTS_FLOW ASYNC_CTS_FLOW
-+#define UIF_CALLOUT_ACTIVE ASYNC_CALLOUT_ACTIVE
-+#define UIF_NORMAL_ACTIVE ASYNC_NORMAL_ACTIVE
-+#define UIF_INITIALIZED ASYNC_INITIALIZED
-+
-+ unsigned char *tmpbuf;
-+ struct semaphore tmpbuf_sem;
-+
-+ unsigned int driver_priv;
-+ int blocked_open;
-+ pid_t session;
-+ pid_t pgrp;
-+
-+ struct tasklet_struct tlet;
-+
-+ wait_queue_head_t open_wait;
-+ wait_queue_head_t delta_msr_wait;
-+};
-+
-+/* number of characters left in xmit buffer before we ask for more */
-+#define WAKEUP_CHARS 256
-+
-+struct module;
-+struct tty_driver;
-+
-+struct uart_driver {
-+ struct module *owner;
-+ int normal_major;
-+ const char *normal_name;
-+ struct tty_driver *normal_driver;
-+ int callout_major;
-+ const char *callout_name;
-+ struct tty_driver *callout_driver;
-+ struct tty_struct **table;
-+ struct termios **termios;
-+ struct termios **termios_locked;
-+ int minor;
-+ int nr;
-+ struct console *cons;
-+
-+ /*
-+ * these are private; the low level driver should not
-+ * touch these; they should be initialised to NULL
-+ */
-+ struct uart_state *state;
-+};
-+
-+void uart_write_wakeup(struct uart_port *port);
-+struct uart_port *uart_get_console(struct uart_port *ports, int nr,
-+ struct console *c);
-+void uart_parse_options(char *options, int *baud, int *parity, int *bits,
-+ int *flow);
-+int uart_set_options(struct uart_port *port, struct console *co, int baud,
-+ int parity, int bits, int flow);
-+
-+/*
-+ * Port/driver registration/removal
-+ */
-+int uart_register_driver(struct uart_driver *uart);
-+void uart_unregister_driver(struct uart_driver *uart);
-+void uart_unregister_port(struct uart_driver *reg, int line);
-+int uart_register_port(struct uart_driver *reg, struct uart_port *port);
-+int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
-+int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
-+
-+#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
-+#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
-+
-+#define uart_circ_chars_pending(circ) \
-+ (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-+
-+#define uart_circ_chars_free(circ) \
-+ (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-+
-+#define uart_tx_stopped(port) \
-+ ((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
-+
-+/*
-+ * The following are helper functions for the low level drivers.
-+ */
-+#ifdef SUPPORT_SYSRQ
-+static inline int
-+uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
-+ struct pt_regs *regs)
-+{
-+ if (port->sysrq) {
-+ if (ch && time_before(jiffies, port->sysrq)) {
-+ handle_sysrq(ch, regs, NULL, NULL);
-+ port->sysrq = 0;
-+ return 1;
-+ }
-+ port->sysrq = 0;
-+ }
-+ return 0;
-+}
-+#else
-+#define uart_handle_sysrq_char(port,ch,regs) (0)
-+#endif
-+
-+/*
-+ * We do the SysRQ and SAK checking like this...
-+ */
-+static inline int uart_handle_break(struct uart_port *port)
-+{
-+ struct uart_info *info = port->info;
-+#ifdef SUPPORT_SYSRQ
-+ if (port->cons && port->cons->index == port->line) {
-+ if (!port->sysrq) {
-+ port->sysrq = jiffies + HZ*5;
-+ return 1;
-+ }
-+ port->sysrq = 0;
-+ }
-+#endif
-+ if (port->flags & UPF_SAK)
-+ do_SAK(info->tty);
-+ return 0;
-+}
-+
-+/**
-+ * uart_handle_dcd_change - handle a change of carrier detect state
-+ * @port: uart_port structure for the open port
-+ * @status: new carrier detect status, nonzero if active
-+ */
-+static inline void
-+uart_handle_dcd_change(struct uart_port *port, unsigned int status)
-+{
-+ struct uart_info *info = port->info;
-+
-+ port->icount.dcd++;
-+
-+#ifdef CONFIG_HARD_PPS
-+ if ((port->flags & UPF_HARDPPS_CD) && status)
-+ hardpps();
-+#endif
-+
-+ if (info->flags & UIF_CHECK_CD) {
-+ if (status)
-+ wake_up_interruptible(&info->open_wait);
-+ else if (!((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (port->flags & UPF_CALLOUT_NOHUP))) {
-+ if (info->tty)
-+ tty_hangup(info->tty);
-+ }
-+ }
-+}
-+
-+/**
-+ * uart_handle_cts_change - handle a change of clear-to-send state
-+ * @port: uart_port structure for the open port
-+ * @status: new clear to send status, nonzero if active
-+ */
-+static inline void
-+uart_handle_cts_change(struct uart_port *port, unsigned int status)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+
-+ port->icount.cts++;
-+
-+ if (info->flags & UIF_CTS_FLOW) {
-+ if (tty->hw_stopped) {
-+ if (status) {
-+ tty->hw_stopped = 0;
-+ port->ops->start_tx(port, 0);
-+ uart_write_wakeup(port);
-+ }
-+ } else {
-+ if (!status) {
-+ tty->hw_stopped = 1;
-+ port->ops->stop_tx(port, 0);
-+ }
-+ }
-+ }
-+}
-+
-+/*
-+ * UART_ENABLE_MS - determine if port should enable modem status irqs
-+ */
-+#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
-+ (cflag) & CRTSCTS || \
-+ !((cflag) & CLOCAL))
-+
-+#endif
---- linux-2.4.25/include/linux/serial_reg.h~2.4.25-vrs2.patch 2001-05-02 01:05:00.000000000 +0200
-+++ linux-2.4.25/include/linux/serial_reg.h 2004-03-31 17:15:09.000000000 +0200
-@@ -121,6 +121,7 @@
- /*
- * These are the definitions for the Modem Control Register
- */
-+#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
- #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
- #define UART_MCR_OUT2 0x08 /* Out2 complement */
- #define UART_MCR_OUT1 0x04 /* Out1 complement */
---- linux-2.4.25/include/linux/zlib.h~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.25/include/linux/zlib.h 2004-03-31 17:15:09.000000000 +0200
-@@ -31,7 +31,7 @@
- #ifndef _ZLIB_H
- #define _ZLIB_H
-
--#include <linux/zconf.h>
-+#include "zconf.h"
-
- #ifdef __cplusplus
- extern "C" {
---- linux-2.4.25/init/do_mounts.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/init/do_mounts.c 2004-03-31 17:15:09.000000000 +0200
-@@ -888,7 +888,7 @@
- */
- void prepare_namespace(void)
- {
-- int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
-+ int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
- #ifdef CONFIG_ALL_PPC
- extern void arch_discover_root(void);
- arch_discover_root();
-@@ -951,6 +951,7 @@
- static unsigned inptr; /* index of next byte to be processed in inbuf */
- static unsigned outcnt; /* bytes in output buffer */
- static int exit_code;
-+static int unzip_error;
- static long bytes_out;
- static int crd_infd, crd_outfd;
-
-@@ -998,13 +999,17 @@
- /* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
-+ * Returning -1 does not guarantee that gunzip() will ever return.
- */
- static int __init fill_inbuf(void)
- {
- if (exit_code) return -1;
-
- insize = read(crd_infd, inbuf, INBUFSIZ);
-- if (insize == 0) return -1;
-+ if (insize == 0) {
-+ error("RAMDISK: ran out of compressed data\n");
-+ return -1;
-+ }
-
- inptr = 1;
-
-@@ -1018,10 +1023,15 @@
- static void __init flush_window(void)
- {
- ulg c = crc; /* temporary variable */
-- unsigned n;
-+ unsigned n, written;
- uch *in, ch;
-
-- write(crd_outfd, window, outcnt);
-+ written = write(crd_outfd, window, outcnt);
-+ if (written != outcnt && unzip_error == 0) {
-+ printk(KERN_ERR "RAMDISK: incomplete write (%d != %d), "
-+ "only wrote %ld\n", written, outcnt, bytes_out);
-+ unzip_error = 1;
-+ }
- in = window;
- for (n = 0; n < outcnt; n++) {
- ch = *in++;
-@@ -1036,6 +1046,7 @@
- {
- printk(KERN_ERR "%s", x);
- exit_code = 1;
-+ unzip_error = 1;
- }
-
- static int __init crd_load(int in_fd, int out_fd)
-@@ -1064,6 +1075,8 @@
- }
- makecrc();
- result = gunzip();
-+ if (unzip_error)
-+ result = 1;
- kfree(inbuf);
- kfree(window);
- return result;
---- linux-2.4.25/kernel/Makefile~2.4.25-vrs2.patch 2001-09-17 06:22:40.000000000 +0200
-+++ linux-2.4.25/kernel/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -9,16 +9,19 @@
-
- O_TARGET := kernel.o
-
--export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
-+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
-+ printk.o fork.o cpufreq.o
-
--obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
-+obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
- module.o exit.o itimer.o info.o time.o softirq.o resource.o \
- sysctl.o acct.o capability.o ptrace.o timer.o user.o \
- signal.o sys.o kmod.o context.o
-
-+obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += ksyms.o
- obj-$(CONFIG_PM) += pm.o
-+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/kernel/cpufreq.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,536 @@
-+/*
-+ * linux/kernel/cpufreq.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * $Id: cpufreq.c,v 1.17.2.2 2002/05/03 13:26:27 rmk Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * CPU speed changing core functionality. We provide the following
-+ * services to the system:
-+ * - notifier lists to inform other code of the freq change both
-+ * before and after the freq change.
-+ * - the ability to change the freq speed
-+ *
-+ * ** You'll need to add CTL_CPU = 10 to include/linux/sysctl.h if
-+ * it's not already present.
-+ *
-+ * When this appears in the kernel, the sysctl enums will move to
-+ * include/linux/sysctl.h
-+ */
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/fs.h>
-+#include <linux/sysctl.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+#include <linux/interrupt.h> /* requires system.h */
-+
-+/*
-+ * This list is for kernel code that needs to handle
-+ * changes to devices when the CPU clock speed changes.
-+ */
-+static struct notifier_block *cpufreq_notifier_list;
-+static DECLARE_MUTEX_LOCKED(cpufreq_sem);
-+static unsigned long cpufreq_ref_loops;
-+static unsigned int cpufreq_ref_freq;
-+static int cpufreq_initialised;
-+static unsigned int (*cpufreq_validatespeed)(unsigned int);
-+static void (*cpufreq_setspeed)(unsigned int);
-+
-+#ifndef CONFIG_SMP
-+static unsigned int __cpufreq_max;
-+static unsigned int __cpufreq_min;
-+static unsigned int __cpufreq_cur;
-+#endif
-+
-+static unsigned long scale(unsigned long ref, u_int div, u_int mult)
-+{
-+ unsigned long new_jiffy_l, new_jiffy_h;
-+
-+ /*
-+ * Recalculate loops_per_jiffy. We do it this way to
-+ * avoid math overflow on 32-bit machines. Maybe we
-+ * should make this architecture dependent? If you have
-+ * a better way of doing this, please replace!
-+ *
-+ * new = old * mult / div
-+ */
-+ new_jiffy_h = ref / div;
-+ new_jiffy_l = (ref % div) / 100;
-+ new_jiffy_h *= mult;
-+ new_jiffy_l = new_jiffy_l * mult / div;
-+
-+ return new_jiffy_h + new_jiffy_l * 100;
-+}
-+
-+/*
-+ * cpufreq_max command line parameter. Use:
-+ * cpufreq=59000-221000
-+ * to set the CPU frequency to 59 to 221MHz.
-+ */
-+static int __init cpufreq_setup(char *str)
-+{
-+ unsigned int min, max;
-+ int i;
-+
-+ min = 0;
-+ max = simple_strtoul(str, &str, 0);
-+ if (*str == '-') {
-+ min = max;
-+ max = simple_strtoul(str + 1, NULL, 0);
-+ }
-+
-+ for (i = 0; i < smp_num_cpus; i++) {
-+ cpufreq_max(i) = max;
-+ cpufreq_min(i) = min;
-+ }
-+
-+ return 1;
-+}
-+
-+__setup("cpufreq=", cpufreq_setup);
-+
-+/**
-+ * cpufreq_register_notifier - register a driver with cpufreq
-+ * @nb: notifier function to register
-+ *
-+ * Add a driver to the list of drivers that which to be notified about
-+ * CPU clock rate changes. The driver will be called three times on
-+ * clock change.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_register.
-+ */
-+int cpufreq_register_notifier(struct notifier_block *nb)
-+{
-+ int ret;
-+
-+ down(&cpufreq_sem);
-+ ret = notifier_chain_register(&cpufreq_notifier_list, nb);
-+ up(&cpufreq_sem);
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL(cpufreq_register_notifier);
-+
-+/**
-+ * cpufreq_unregister_notifier - unregister a driver with cpufreq
-+ * @nb: notifier block to be unregistered
-+ *
-+ * Remove a driver from the CPU frequency notifier lists.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_unregister.
-+ */
-+int cpufreq_unregister_notifier(struct notifier_block *nb)
-+{
-+ int ret;
-+
-+ down(&cpufreq_sem);
-+ ret = notifier_chain_unregister(&cpufreq_notifier_list, nb);
-+ up(&cpufreq_sem);
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL(cpufreq_unregister_notifier);
-+
-+/*
-+ * This notifier alters the system "loops_per_jiffy" for the clock
-+ * speed change. We ignore CPUFREQ_MINMAX here.
-+ */
-+static void adjust_jiffies(unsigned long val, struct cpufreq_info *ci)
-+{
-+ if ((val == CPUFREQ_PRECHANGE && ci->old_freq < ci->new_freq) ||
-+ (val == CPUFREQ_POSTCHANGE && ci->old_freq > ci->new_freq))
-+ loops_per_jiffy = scale(cpufreq_ref_loops, cpufreq_ref_freq,
-+ ci->new_freq);
-+}
-+
-+#ifdef CONFIG_PM
-+/**
-+ * cpufreq_restore - restore the CPU clock frequency after resume
-+ *
-+ * Restore the CPU clock frequency so that our idea of the current
-+ * frequency reflects the actual hardware.
-+ */
-+int cpufreq_restore(void)
-+{
-+ unsigned long old_cpus;
-+ int cpu = smp_processor_id();
-+ int ret;
-+
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_restore() called before initialisation!");
-+ if (in_interrupt())
-+ panic("cpufreq_restore() called from interrupt context!");
-+
-+ /*
-+ * Bind to the current CPU.
-+ */
-+ old_cpus = current->cpus_allowed;
-+ current->cpus_allowed = 1UL << cpu_logical_map(cpu);
-+
-+ down(&cpufreq_sem);
-+
-+ ret = -ENXIO;
-+ if (cpufreq_setspeed) {
-+ cpufreq_setspeed(cpufreq_current(cpu));
-+ ret = 0;
-+ }
-+
-+ up(&cpufreq_sem);
-+
-+ current->cpus_allowed = old_cpus;
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_restore);
-+#endif
-+
-+/**
-+ * cpu_setfreq - change the CPU clock frequency.
-+ * @freq: frequency (in kHz) at which we should run.
-+ *
-+ * Set the CPU clock frequency, informing all registered users of
-+ * the change. We bound the frequency according to the cpufreq_max
-+ * command line parameter, and the parameters the registered users
-+ * will allow.
-+ *
-+ * This function must be called from process context, and on the
-+ * cpu that we wish to change the frequency of.
-+ *
-+ * We return 0 if successful. (we are currently always successful).
-+ */
-+int cpufreq_set(unsigned int freq)
-+{
-+ unsigned long old_cpus;
-+ struct cpufreq_info clkinfo;
-+ struct cpufreq_minmax minmax;
-+ int cpu = smp_processor_id();
-+ int ret;
-+
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_set() called before initialisation!");
-+ if (in_interrupt())
-+ panic("cpufreq_set() called from interrupt context!");
-+
-+ /*
-+ * Bind to the current CPU.
-+ */
-+ old_cpus = current->cpus_allowed;
-+ current->cpus_allowed = 1UL << cpu_logical_map(cpu);
-+
-+ down(&cpufreq_sem);
-+ ret = -ENXIO;
-+ if (!cpufreq_setspeed || !cpufreq_validatespeed)
-+ goto out;
-+
-+ /*
-+ * Don't allow the CPU to be clocked over the limit.
-+ */
-+ minmax.min_freq = cpufreq_min(cpu);
-+ minmax.max_freq = cpufreq_max(cpu);
-+ minmax.cur_freq = cpufreq_current(cpu);
-+ minmax.new_freq = freq;
-+
-+ /*
-+ * Find out what the registered devices will currently tolerate,
-+ * and limit the requested clock rate to these values. Drivers
-+ * must not rely on the 'new_freq' value - it is only a guide.
-+ */
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_MINMAX, &minmax);
-+ if (freq < minmax.min_freq)
-+ freq = minmax.min_freq;
-+ if (freq > minmax.max_freq)
-+ freq = minmax.max_freq;
-+
-+ /*
-+ * Ask the CPU specific code to validate the speed. If the speed
-+ * is not acceptable, make it acceptable. Current policy is to
-+ * round the frequency down to the value the processor actually
-+ * supports.
-+ */
-+ freq = cpufreq_validatespeed(freq);
-+
-+ if (cpufreq_current(cpu) != freq) {
-+ clkinfo.old_freq = cpufreq_current(cpu);
-+ clkinfo.new_freq = freq;
-+
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_PRECHANGE,
-+ &clkinfo);
-+
-+ adjust_jiffies(CPUFREQ_PRECHANGE, &clkinfo);
-+
-+ /*
-+ * Actually set the CPU frequency.
-+ */
-+ cpufreq_setspeed(freq);
-+ cpufreq_current(cpu) = freq;
-+ adjust_jiffies(CPUFREQ_POSTCHANGE, &clkinfo);
-+
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_POSTCHANGE,
-+ &clkinfo);
-+ }
-+
-+ ret = 0;
-+
-+ out:
-+ up(&cpufreq_sem);
-+
-+ current->cpus_allowed = old_cpus;
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_set);
-+
-+/**
-+ * cpufreq_setmax - set the CPU to maximum frequency
-+ *
-+ * Sets the CPU this function is executed on to maximum frequency.
-+ */
-+int cpufreq_setmax(void)
-+{
-+ return cpufreq_set(cpufreq_max(smp_processor_id()));
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_setmax);
-+
-+/**
-+ * cpufreq_get - return the current CPU clock frequency in 1kHz
-+ * @cpu: cpu number to obtain frequency for
-+ *
-+ * Returns the specified CPUs frequency in kHz.
-+ */
-+unsigned int cpufreq_get(int cpu)
-+{
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_get() called before initialisation!");
-+ return cpufreq_current(cpu);
-+}
-+
-+EXPORT_SYMBOL(cpufreq_get);
-+
-+#ifdef CONFIG_SYSCTL
-+
-+static int
-+cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ char buf[16], *p;
-+ int cpu = 0, len, left = *lenp;
-+
-+ if (!left || (filp->f_pos && !write)) {
-+ *lenp = 0;
-+ return 0;
-+ }
-+
-+ if (write) {
-+ unsigned int freq;
-+
-+ len = left;
-+ if (left > sizeof(buf))
-+ left = sizeof(buf);
-+ if (copy_from_user(buf, buffer, left))
-+ return -EFAULT;
-+ buf[sizeof(buf) - 1] = '\0';
-+
-+ freq = simple_strtoul(buf, &p, 0);
-+ cpufreq_set(freq);
-+ } else {
-+ len = sprintf(buf, "%d\n", cpufreq_get(cpu));
-+ if (len > left)
-+ len = left;
-+ if (copy_to_user(buffer, buf, len))
-+ return -EFAULT;
-+ }
-+
-+ *lenp = len;
-+ filp->f_pos += len;
-+ return 0;
-+}
-+
-+static int
-+cpufreq_sysctl(ctl_table *table, int *name, int nlen,
-+ void *oldval, size_t *oldlenp,
-+ void *newval, size_t newlen, void **context)
-+{
-+ int cpu = 0;
-+
-+ if (oldval && oldlenp) {
-+ size_t oldlen;
-+
-+ if (get_user(oldlen, oldlenp))
-+ return -EFAULT;
-+
-+ if (oldlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
-+ put_user(sizeof(unsigned int), oldlenp))
-+ return -EFAULT;
-+ }
-+ if (newval && newlen) {
-+ unsigned int freq;
-+
-+ if (newlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (get_user(freq, (unsigned int *)newval))
-+ return -EFAULT;
-+
-+ cpufreq_set(freq);
-+ }
-+ return 1;
-+}
-+
-+enum {
-+ CPU_NR_FREQ_MAX = 1,
-+ CPU_NR_FREQ_MIN = 2,
-+ CPU_NR_FREQ = 3
-+};
-+
-+static ctl_table ctl_cpu_vars[4] = {
-+ {
-+ ctl_name: CPU_NR_FREQ_MAX,
-+ procname: "speed-max",
-+ data: &cpufreq_max(0),
-+ maxlen: sizeof(cpufreq_max(0)),
-+ mode: 0444,
-+ proc_handler: proc_dointvec,
-+ },
-+ {
-+ ctl_name: CPU_NR_FREQ_MIN,
-+ procname: "speed-min",
-+ data: &cpufreq_min(0),
-+ maxlen: sizeof(cpufreq_min(0)),
-+ mode: 0444,
-+ proc_handler: proc_dointvec,
-+ },
-+ {
-+ ctl_name: CPU_NR_FREQ,
-+ procname: "speed",
-+ mode: 0644,
-+ proc_handler: cpufreq_procctl,
-+ strategy: cpufreq_sysctl,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+enum {
-+ CPU_NR = 1,
-+};
-+
-+static ctl_table ctl_cpu_nr[2] = {
-+ {
-+ ctl_name: CPU_NR,
-+ procname: "0",
-+ mode: 0555,
-+ child: ctl_cpu_vars,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+static ctl_table ctl_cpu[2] = {
-+ {
-+ ctl_name: CTL_CPU,
-+ procname: "cpu",
-+ mode: 0555,
-+ child: ctl_cpu_nr,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+static inline void cpufreq_sysctl_init(void)
-+{
-+ register_sysctl_table(ctl_cpu, 0);
-+}
-+
-+#else
-+#define cpufreq_sysctl_init()
-+#endif
-+
-+/**
-+ * cpufreq_setfunctions - Set CPU clock functions
-+ * @validate: pointer to validation function
-+ * @setspeed: pointer to setspeed function
-+ */
-+void
-+cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
-+ void (*setspeed)(unsigned int))
-+{
-+ down(&cpufreq_sem);
-+ cpufreq_validatespeed = validate;
-+ cpufreq_setspeed = setspeed;
-+ up(&cpufreq_sem);
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_setfunctions);
-+
-+/**
-+ * cpufreq_init - Initialise the cpufreq core
-+ * @freq: current CPU clock speed.
-+ * @min_freq: minimum CPU clock speed.
-+ * @max_freq: maximum CPU clock speed.
-+ *
-+ * Initialise the cpufreq core. If the cpufreq_max command line
-+ * parameter has not been specified, we set the maximum clock rate
-+ * to the current CPU clock rate.
-+ */
-+void cpufreq_init(unsigned int freq,
-+ unsigned int min_freq,
-+ unsigned int max_freq)
-+{
-+ /*
-+ * If the user doesn't tell us their maximum frequency,
-+ * or if it is invalid, use the values determined
-+ * by the cpufreq-arch-specific initialization functions.
-+ * The validatespeed code is responsible for limiting
-+ * this further.
-+ */
-+ if (max_freq && ((cpufreq_max(0) == 0) || (cpufreq_max(0) > max_freq)))
-+ cpufreq_max(0) = max_freq;
-+ if (min_freq && ((cpufreq_min(0) == 0) || (cpufreq_min(0) < min_freq)))
-+ cpufreq_min(0) = min_freq;
-+
-+ if (cpufreq_max(0) == 0)
-+ cpufreq_max(0) = freq;
-+
-+ printk(KERN_INFO "CPU clock: %d.%03d MHz (%d.%03d-%d.%03d MHz)\n",
-+ freq / 1000, freq % 1000,
-+ cpufreq_min(0) / 1000, cpufreq_min(0) % 1000,
-+ cpufreq_max(0) / 1000, cpufreq_max(0) % 1000);
-+
-+ cpufreq_ref_loops = loops_per_jiffy;
-+ cpufreq_ref_freq = freq;
-+ cpufreq_current(smp_processor_id()) = freq;
-+
-+ cpufreq_initialised = 1;
-+ up(&cpufreq_sem);
-+
-+ cpufreq_sysctl_init();
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_init);
---- linux-2.4.25/kernel/exit.c~2.4.25-vrs2.patch 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.25/kernel/exit.c 2004-03-31 17:15:09.000000000 +0200
-@@ -587,7 +587,7 @@
- return retval;
- }
-
--#if !defined(__alpha__) && !defined(__ia64__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
-
- /*
- * sys_waitpid() remains for compatibility. waitpid() should be
---- linux-2.4.25/kernel/fork.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/kernel/fork.c 2004-03-31 17:15:09.000000000 +0200
-@@ -75,7 +75,11 @@
- * value: the thread structures can take up at most half
- * of memory.
- */
-+#if THREAD_SIZE > PAGE_SIZE
- max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
-+#else
-+ max_threads = (mempages * PAGE_SIZE) / (8 * THREAD_SIZE);
-+#endif
-
- init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
- init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
-@@ -220,6 +224,7 @@
-
- fail_nomem:
- flush_tlb_mm(current->mm);
-+ memc_update_mm(mm);
- return retval;
- }
-
---- linux-2.4.25/kernel/ksyms.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/kernel/ksyms.c 2004-03-31 17:15:09.000000000 +0200
-@@ -345,6 +345,7 @@
-
- /* tty routines */
- EXPORT_SYMBOL(tty_hangup);
-+EXPORT_SYMBOL(tty_vhangup);
- EXPORT_SYMBOL(tty_wait_until_sent);
- EXPORT_SYMBOL(tty_check_change);
- EXPORT_SYMBOL(tty_hung_up_p);
-@@ -439,9 +440,11 @@
- EXPORT_SYMBOL(kiobuf_wait_for_io);
-
- /* dma handling */
-+#ifdef CONFIG_GENERIC_ISA_DMA
- EXPORT_SYMBOL(request_dma);
- EXPORT_SYMBOL(free_dma);
- EXPORT_SYMBOL(dma_spin_lock);
-+#endif
- #ifdef HAVE_DISABLE_HLT
- EXPORT_SYMBOL(disable_hlt);
- EXPORT_SYMBOL(enable_hlt);
---- linux-2.4.25/kernel/signal.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/kernel/signal.c 2004-03-31 17:15:09.000000000 +0200
-@@ -778,8 +778,8 @@
- info.si_uid = tsk->uid;
-
- /* FIXME: find out whether or not this is supposed to be c*time. */
-- info.si_utime = tsk->times.tms_utime;
-- info.si_stime = tsk->times.tms_stime;
-+ info.si_utime = hz_to_std(tsk->times.tms_utime);
-+ info.si_stime = hz_to_std(tsk->times.tms_stime);
-
- status = tsk->exit_code & 0x7f;
- why = SI_KERNEL; /* shouldn't happen */
-@@ -1277,7 +1277,7 @@
- #endif /* __sparc__ */
- #endif
-
--#if !defined(__alpha__) && !defined(__ia64__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
- /*
- * For backwards compatibility. Functionality superseded by sigprocmask.
- */
-@@ -1305,7 +1305,8 @@
- }
- #endif /* !defined(__alpha__) */
-
--#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \
-+ !defined(__arm__)
- /*
- * For backwards compatibility. Functionality superseded by sigaction.
- */
-@@ -1322,4 +1323,4 @@
-
- return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
- }
--#endif /* !alpha && !__ia64__ && !defined(__mips__) */
-+#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */
---- linux-2.4.25/kernel/sys.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/kernel/sys.c 2004-03-31 17:15:09.000000000 +0200
-@@ -801,16 +801,23 @@
-
- asmlinkage long sys_times(struct tms * tbuf)
- {
-+ struct tms temp;
-+
- /*
- * In the SMP world we might just be unlucky and have one of
- * the times increment as we use it. Since the value is an
- * atomically safe type this is just fine. Conceptually its
- * as if the syscall took an instant longer to occur.
- */
-- if (tbuf)
-- if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
-+ if (tbuf) {
-+ temp.tms_utime = hz_to_std(current->times.tms_utime);
-+ temp.tms_stime = hz_to_std(current->times.tms_stime);
-+ temp.tms_cutime = hz_to_std(current->times.tms_cutime);
-+ temp.tms_cstime = hz_to_std(current->times.tms_cstime);
-+ if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
- return -EFAULT;
-- return jiffies;
-+ }
-+ return hz_to_std(jiffies);
- }
-
- /*
---- linux-2.4.25/lib/string.c~2.4.25-vrs2.patch 2002-08-03 02:39:46.000000000 +0200
-+++ linux-2.4.25/lib/string.c 2004-03-31 17:15:09.000000000 +0200
-@@ -188,10 +188,10 @@
- */
- char * strchr(const char * s, int c)
- {
-- for(; *s != (char) c; ++s)
-- if (*s == '\0')
-- return NULL;
-- return (char *) s;
-+ for(; *s != '\0'; ++s)
-+ if (*s == (char) c)
-+ return (char *) s;
-+ return NULL;
- }
- #endif
-
---- linux-2.4.25/mm/Makefile~2.4.25-vrs2.patch 2002-08-03 02:39:46.000000000 +0200
-+++ linux-2.4.25/mm/Makefile 2004-03-31 17:15:09.000000000 +0200
-@@ -18,4 +18,5 @@
-
- obj-$(CONFIG_HIGHMEM) += highmem.o
-
-+obj-y += debug.o
- include $(TOPDIR)/Rules.make
---- /dev/null 2003-09-23 19:59:22.000000000 +0200
-+++ linux-2.4.25/mm/debug.c 2004-03-31 17:15:09.000000000 +0200
-@@ -0,0 +1,159 @@
-+/*
-+ * linux/mm/debug.c
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Dump out page information on SysRQ-G, and provide show_page_info()
-+ *
-+ * You are advised to use a serial console with this patch - it
-+ * saturates a 38400baud link for 1 minute on a 32MB machine.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/pagemap.h>
-+#include <linux/sysrq.h>
-+#include <linux/init.h>
-+
-+/*
-+ * We print out the following information for each page in the system:
-+ * address: use count, age, mapping, [RSsr] rD [acd]
-+ *
-+ * The flags are:
-+ * R - reserved
-+ * S - in swapcache
-+ * s - slab page
-+ *
-+ * r - referenced
-+ * D - dirty
-+ *
-+ * a - active page
-+ */
-+static void page_detail(struct page *page)
-+{
-+ if (!page)
-+ return;
-+
-+ printk("%p: %2d %p [%c%c%c] %c%c [%c]\n",
-+ page_address(page),
-+ page_count(page),
-+ page->mapping,
-+
-+ PageReserved(page) ? 'R' : '-',
-+ PageSwapCache(page) ? 'S' : '-',
-+ PageSlab(page) ? 's' : '-',
-+
-+ PageReferenced(page) ? 'r' : '-',
-+ PageDirty(page) ? 'D' : '-',
-+
-+ PageActive(page) ? 'a' : '-');
-+}
-+
-+/*
-+ * This version collects statistics
-+ */
-+static int anon_pages, slab_pages, resvd_pages, unused_pages;
-+
-+static void page_statistics(struct page *page)
-+{
-+ if (page) {
-+ if (PageReserved(page))
-+ resvd_pages++;
-+ else if (PageSlab(page))
-+ slab_pages++;
-+ else if (!page_count(page))
-+ unused_pages ++;
-+ else if (!page->mapping)
-+ anon_pages ++;
-+ return;
-+ }
-+
-+ printk(" anon: %d, slab: %d, reserved: %d, free: %d\n",
-+ anon_pages, slab_pages, resvd_pages, unused_pages);
-+}
-+
-+static void show_zone_info(zone_t *zone, void (*fn)(struct page *))
-+{
-+ int i;
-+
-+ printk(" total %ld, free %ld\n",
-+ zone->size, zone->free_pages);
-+
-+ anon_pages = 0;
-+ slab_pages = 0;
-+ resvd_pages = 0;
-+ unused_pages = 0;
-+
-+ for (i = 0; i < zone->size; i++) {
-+ struct page *page = zone->zone_mem_map + i;
-+
-+ fn(page);
-+ }
-+
-+ fn(NULL);
-+}
-+
-+static void show_node_info(pg_data_t *pg, void (*fn)(struct page *))
-+{
-+ int type;
-+
-+ for (type = 0; type < MAX_NR_ZONES; type++) {
-+ zone_t *zone = pg->node_zones + type;
-+
-+ if (zone->size == 0)
-+ continue;
-+
-+ printk("----- Zone %d ------\n", type);
-+
-+ show_zone_info(zone, fn);
-+ }
-+}
-+
-+static void __show_page_info(void (*fn)(struct page *))
-+{
-+ pg_data_t *pg;
-+ int pgdat = 0;
-+
-+ for (pg = pgdat_list; pg; pg = pg->node_next) {
-+
-+ printk("===== Node %d =====\n", pgdat++);
-+
-+ show_node_info(pg, fn);
-+ }
-+}
-+
-+void show_page_info(void)
-+{
-+ __show_page_info(page_detail);
-+}
-+
-+static void
-+show_pg_info(int key, struct pt_regs *regs, struct kbd_struct *kd,
-+ struct tty_struct *tty)
-+{
-+ void (*fn)(struct page *);
-+ show_mem();
-+ if (key == 'g')
-+ fn = page_detail;
-+ else
-+ fn = page_statistics;
-+ __show_page_info(fn);
-+}
-+
-+static struct sysrq_key_op page_info_op = {
-+ handler: show_pg_info,
-+ help_msg: "paGeinfo",
-+ action_msg: "Page Info",
-+};
-+
-+static int __init debug_mm_init(void)
-+{
-+ register_sysrq_key('g', &page_info_op);
-+ register_sysrq_key('h', &page_info_op);
-+ return 0;
-+}
-+
-+__initcall(debug_mm_init);
---- linux-2.4.25/mm/filemap.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/mm/filemap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -2210,10 +2210,14 @@
- pte_t pte = *ptep;
-
- if (pte_present(pte)) {
-- struct page *page = pte_page(pte);
-- if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
-- flush_tlb_page(vma, address);
-- set_page_dirty(page);
-+ unsigned long pfn = pte_pfn(pte);
-+
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
-+ flush_tlb_page(vma, address);
-+ set_page_dirty(page);
-+ }
- }
- }
- return 0;
---- linux-2.4.25/mm/memory.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/mm/memory.c 2004-03-31 17:15:09.000000000 +0200
-@@ -77,8 +77,13 @@
- */
- void __free_pte(pte_t pte)
- {
-- struct page *page = pte_page(pte);
-- if ((!VALID_PAGE(page)) || PageReserved(page))
-+ unsigned long pfn = pte_pfn(pte);
-+ struct page *page;
-+
-+ if (!pfn_valid(pfn))
-+ return;
-+ page = pfn_to_page(pfn);
-+ if (PageReserved(page))
- return;
- if (pte_dirty(pte))
- set_page_dirty(page);
-@@ -232,6 +237,7 @@
- do {
- pte_t pte = *src_pte;
- struct page *ptepage;
-+ unsigned long pfn;
-
- /* copy_one_pte */
-
-@@ -241,9 +247,11 @@
- swap_duplicate(pte_to_swp_entry(pte));
- goto cont_copy_pte_range;
- }
-- ptepage = pte_page(pte);
-- if ((!VALID_PAGE(ptepage)) ||
-- PageReserved(ptepage))
-+ pfn = pte_pfn(pte);
-+ if (!pfn_valid(pfn))
-+ goto cont_copy_pte_range;
-+ ptepage = pfn_to_page(pfn);
-+ if (PageReserved(ptepage))
- goto cont_copy_pte_range;
-
- /* If it's a COW mapping, write protect it both in the parent and the child */
-@@ -314,9 +322,13 @@
- if (pte_none(pte))
- continue;
- if (pte_present(pte)) {
-- struct page *page = pte_page(pte);
-- if (VALID_PAGE(page) && !PageReserved(page))
-- freed ++;
-+ unsigned long pfn = pte_pfn(pte);
-+
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page))
-+ freed ++;
-+ }
- /* This will eventually call __free_pte on the pte. */
- tlb_remove_page(tlb, ptep, address + offset);
- } else {
-@@ -354,17 +366,37 @@
- return freed;
- }
-
-+void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long address, unsigned long end)
-+{
-+ int freed = 0;
-+ pgd_t * dir;
-+
-+ if (address >= end)
-+ BUG();
-+ dir = pgd_offset(mm, address);
-+ do {
-+ freed += zap_pmd_range(tlb, dir, address, end - address);
-+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
-+ dir++;
-+ } while (address && (address < end));
-+
-+ /*
-+ * Update rss for the mm_struct (not necessarily current->mm)
-+ * Notice that rss is an unsigned long.
-+ */
-+ if (mm->rss > freed)
-+ mm->rss -= freed;
-+ else
-+ mm->rss = 0;
-+}
-+
- /*
- * remove user pages in a given range.
- */
- void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
- {
-- mmu_gather_t *tlb;
-- pgd_t * dir;
- unsigned long start = address, end = address + size;
-- int freed = 0;
--
-- dir = pgd_offset(mm, address);
-+ mmu_gather_t *tlb;
-
- /*
- * This is a long-lived spinlock. That's fine.
-@@ -377,25 +409,10 @@
- BUG();
- spin_lock(&mm->page_table_lock);
- flush_cache_range(mm, address, end);
-- tlb = tlb_gather_mmu(mm);
-
-- do {
-- freed += zap_pmd_range(tlb, dir, address, end - address);
-- address = (address + PGDIR_SIZE) & PGDIR_MASK;
-- dir++;
-- } while (address && (address < end));
--
-- /* this will flush any remaining tlb entries */
-+ tlb = tlb_gather_mmu(mm);
-+ unmap_page_range(tlb, mm, address, end);
- tlb_finish_mmu(tlb, start, end);
--
-- /*
-- * Update rss for the mm_struct (not necessarily current->mm)
-- * Notice that rss is an unsigned long.
-- */
-- if (mm->rss > freed)
-- mm->rss -= freed;
-- else
-- mm->rss = 0;
- spin_unlock(&mm->page_table_lock);
- }
-
-@@ -407,6 +424,7 @@
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *ptep, pte;
-+ unsigned long pfn;
-
- pgd = pgd_offset(mm, address);
- if (pgd_none(*pgd) || pgd_bad(*pgd))
-@@ -423,8 +441,11 @@
- pte = *ptep;
- if (pte_present(pte)) {
- if (!write ||
-- (pte_write(pte) && pte_dirty(pte)))
-- return pte_page(pte);
-+ (pte_write(pte) && pte_dirty(pte))) {
-+ pfn = pte_pfn(pte);
-+ if (pfn_valid(pfn))
-+ return pfn_to_page(pfn);
-+ }
- }
-
- out:
-@@ -439,7 +460,8 @@
-
- static inline struct page * get_page_map(struct page *page)
- {
-- if (!VALID_PAGE(page))
-+ unsigned long pfn = page_to_pfn(page);
-+ if (!pfn_valid(pfn))
- return 0;
- return page;
- }
-@@ -826,22 +848,22 @@
- unsigned long 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 {
-- struct page *page;
- pte_t oldpage;
- oldpage = ptep_get_and_clear(pte);
-
-- page = virt_to_page(__va(phys_addr));
-- if ((!VALID_PAGE(page)) || PageReserved(page))
-- set_pte(pte, mk_pte_phys(phys_addr, prot));
-+ if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
-+ set_pte(pte, pfn_pte(pfn, prot));
- forget_pte(oldpage);
- address += PAGE_SIZE;
-- phys_addr += PAGE_SIZE;
-+ pfn++;
- pte++;
- } while (address && (address < end));
- }
-@@ -949,10 +971,11 @@
- unsigned long address, pte_t *page_table, pte_t pte)
- {
- struct page *old_page, *new_page;
-+ unsigned long pfn = pte_pfn(pte);
-
-- old_page = pte_page(pte);
-- if (!VALID_PAGE(old_page))
-+ if (!pfn_valid(pfn))
- goto bad_wp_page;
-+ old_page = pte_page(pte);
-
- if (!TryLockPage(old_page)) {
- int reuse = can_share_swap_page(old_page);
-@@ -996,7 +1019,7 @@
-
- bad_wp_page:
- spin_unlock(&mm->page_table_lock);
-- printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
-+ printk("do_wp_page: bogus page at address %08lx\n", address);
- return -1;
- no_mem:
- page_cache_release(old_page);
---- linux-2.4.25/mm/mmap.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/mm/mmap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -18,6 +18,9 @@
-
- #include <asm/uaccess.h>
- #include <asm/pgalloc.h>
-+#include <asm/tlb.h>
-+
-+extern void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
-
- /*
- * WARNING: the debugging will use recursive algorithms so never enable this
-@@ -915,6 +918,8 @@
- * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
- */
- start_index = pgd_index(first);
-+ if (start_index < FIRST_USER_PGD_NR)
-+ start_index = FIRST_USER_PGD_NR;
- end_index = pgd_index(last);
- if (end_index > start_index) {
- clear_page_tables(mm, start_index, end_index - start_index);
-@@ -1046,7 +1051,6 @@
- len = PAGE_ALIGN(len);
- if (!len)
- return addr;
--
- if ((addr + len) > TASK_SIZE || (addr + len) < addr)
- return -EINVAL;
-
-@@ -1135,45 +1139,58 @@
- /* Release all mmaps. */
- void exit_mmap(struct mm_struct * mm)
- {
-+ mmu_gather_t *tlb;
- struct vm_area_struct * mpnt;
-
- release_segments(mm);
- spin_lock(&mm->page_table_lock);
-+
-+ tlb = tlb_gather_mmu(mm);
-+
-+ flush_cache_mm(mm);
-+ mpnt = mm->mmap;
-+ while (mpnt) {
-+ unsigned long start = mpnt->vm_start;
-+ unsigned long end = mpnt->vm_end;
-+
-+ mm->map_count--;
-+ remove_shared_vm_struct(mpnt);
-+ unmap_page_range(tlb, mm, start, end);
-+ mpnt = mpnt->vm_next;
-+ }
-+
-+ /* This is just debugging */
-+ if (mm->map_count)
-+ BUG();
-+
-+ tlb_finish_mmu(tlb, 0, TASK_SIZE);
-+
- mpnt = mm->mmap;
- mm->mmap = mm->mmap_cache = NULL;
- mm->mm_rb = RB_ROOT;
- mm->rss = 0;
-- spin_unlock(&mm->page_table_lock);
- mm->total_vm = 0;
- mm->locked_vm = 0;
-
-- flush_cache_mm(mm);
-+ spin_unlock(&mm->page_table_lock);
-+
-+ clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
-+
-+ /*
-+ * Walk the list again, actually closing and freeing it
-+ * without holding any MM locks.
-+ */
- while (mpnt) {
- struct vm_area_struct * next = mpnt->vm_next;
-- unsigned long start = mpnt->vm_start;
-- unsigned long end = mpnt->vm_end;
-- unsigned long size = end - start;
--
- if (mpnt->vm_ops) {
- if (mpnt->vm_ops->close)
- mpnt->vm_ops->close(mpnt);
- }
-- mm->map_count--;
-- remove_shared_vm_struct(mpnt);
-- zap_page_range(mm, start, size);
- if (mpnt->vm_file)
- fput(mpnt->vm_file);
- kmem_cache_free(vm_area_cachep, mpnt);
- mpnt = next;
- }
--
-- /* This is just debugging */
-- if (mm->map_count)
-- BUG();
--
-- clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
--
-- flush_tlb_mm(mm);
- }
-
- /* Insert vm structure into process list sorted by address
---- linux-2.4.25/mm/slab.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/mm/slab.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1391,7 +1391,7 @@
- #if DEBUG
- # define CHECK_NR(pg) \
- do { \
-- if (!VALID_PAGE(pg)) { \
-+ if (!virt_addr_valid(pg)) { \
- printk(KERN_ERR "kfree: out of range ptr %lxh.\n", \
- (unsigned long)objp); \
- BUG(); \
-@@ -1950,12 +1950,12 @@
- name = cachep->name;
- {
- char tmp;
-- mm_segment_t old_fs;
-+ mm_segment_t old_fs;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- if (__get_user(tmp, name))
- name = "broken";
-- set_fs(old_fs);
-+ set_fs (old_fs);
- }
-
- seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
---- linux-2.4.25/mm/vmalloc.c~2.4.25-vrs2.patch 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.25/mm/vmalloc.c 2004-03-31 17:15:09.000000000 +0200
-@@ -44,8 +44,13 @@
- if (pte_none(page))
- continue;
- if (pte_present(page)) {
-- struct page *ptpage = pte_page(page);
-- if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))
-+ unsigned long pfn = pte_pfn(page);
-+ struct page *ptpage;
-+
-+ if (!pfn_valid(pfn))
-+ continue;
-+ ptpage = pfn_to_page(pfn);
-+ if (!PageReserved(ptpage))
- __free_page(ptpage);
- continue;
- }
---- linux-2.4.25/mm/vmscan.c~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/mm/vmscan.c 2004-03-31 17:15:09.000000000 +0200
-@@ -121,6 +121,7 @@
- drop_pte:
- mm->rss--;
- UnlockPage(page);
-+ memc_clear(vma->vm_mm, page);
- {
- int freeable = page_count(page) - !!page->buffers <= 2;
- page_cache_release(page);
-@@ -206,13 +207,16 @@
-
- do {
- if (pte_present(*pte)) {
-- struct page *page = pte_page(*pte);
-+ unsigned long pfn = pte_pfn(*pte);
-
-- if (VALID_PAGE(page) && !PageReserved(page)) {
-- count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
-- if (!count) {
-- address += PAGE_SIZE;
-- break;
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page)) {
-+ count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
-+ if (!count) {
-+ address += PAGE_SIZE;
-+ break;
-+ }
- }
- }
- }
---- linux-2.4.25/net/irda/af_irda.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/net/irda/af_irda.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1176,7 +1176,7 @@
- #endif /* CONFIG_IRDA_ULTRA */
- kfree(self);
- MOD_DEC_USE_COUNT;
--
-+
- return;
- }
-
-@@ -2571,19 +2571,15 @@
- sock_register(&irda_family_ops);
-
- irda_packet_type.type = htons(ETH_P_IRDA);
-- dev_add_pack(&irda_packet_type);
-+ dev_add_pack(&irda_packet_type);
-
- register_netdevice_notifier(&irda_dev_notifier);
--
- irda_init();
- #ifdef MODULE
-- irda_device_init(); /* Called by init/main.c when non-modular */
-+ irda_device_init(); /* Called by init/main.c when non-modular */
- #endif
- return 0;
- }
--#ifdef MODULE
--module_init(irda_proto_init); /* If non-module, called from init/main.c */
--#endif
-
- /*
- * Function irda_proto_cleanup (void)
-@@ -2591,25 +2587,27 @@
- * Remove IrDA protocol layer
- *
- */
--#ifdef MODULE
--void irda_proto_cleanup(void)
-+static void __exit irda_proto_cleanup(void)
- {
- irda_packet_type.type = htons(ETH_P_IRDA);
-- dev_remove_pack(&irda_packet_type);
-+ dev_remove_pack(&irda_packet_type);
-+
-+ unregister_netdevice_notifier(&irda_dev_notifier);
-
-- unregister_netdevice_notifier(&irda_dev_notifier);
--
- sock_unregister(PF_IRDA);
-+
- irda_cleanup();
--
-- return;
- }
-+
-+#ifdef MODULE
-+module_init(irda_proto_init);
- module_exit(irda_proto_cleanup);
--
-+
- MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
--MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
-+MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
- MODULE_LICENSE("GPL");
- #ifdef CONFIG_IRDA_DEBUG
- MODULE_PARM(irda_debug, "1l");
- #endif
--#endif /* MODULE */
-+#endif
-+
---- linux-2.4.25/net/irda/iriap.c~2.4.25-vrs2.patch 2002-11-29 00:53:16.000000000 +0100
-+++ linux-2.4.25/net/irda/iriap.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1004,18 +1004,20 @@
-
- switch (attrib->value->type) {
- case IAS_INTEGER:
-- len += sprintf(buf+len, "%d\n",
-+ len += sprintf(buf+len, "%d",
- attrib->value->t.integer);
- break;
- case IAS_STRING:
-- len += sprintf(buf+len, "\"%s\"\n",
-+ len += sprintf(buf+len, "\"%s\"",
- attrib->value->t.string);
- break;
- case IAS_OCT_SEQ:
-- len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
-+ len += sprintf(buf+len,
-+ "octet sequence (%d bytes)",
-+ attrib->value->len);
- break;
- case IAS_MISSING:
-- len += sprintf(buf+len, "missing\n");
-+ len += sprintf(buf+len, "missing");
- break;
- default:
- IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
-@@ -1027,6 +1029,7 @@
- hashbin_get_next(obj->attribs);
- }
- obj = (struct ias_object *) hashbin_get_next(objects);
-+ len += sprintf(buf+len, "\n");
- }
- restore_flags(flags);
-
---- linux-2.4.25/net/irda/irlan/irlan_common.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/net/irda/irlan/irlan_common.c 2004-03-31 17:15:09.000000000 +0200
-@@ -317,6 +317,9 @@
-
- del_timer(&self->watchdog_timer);
-
-+ /* since irlan_do_*_event gobble the skb, we must get it once -- rmk */
-+ skb_get(skb);
-+
- /* If you want to pass the skb to *both* state machines, you will
- * need to skb_clone() it, so that you don't free it twice.
- * As the state machines don't need it, git rid of it here...
---- linux-2.4.25/net/irda/irlap_event.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/net/irda/irlap_event.c 2004-03-31 17:15:09.000000000 +0200
-@@ -532,7 +532,7 @@
- #endif /* CONFIG_IRDA_ULTRA */
- case RECV_TEST_CMD:
- /* Remove test frame header */
-- skb_pull(skb, sizeof(struct test_frame));
-+ skb_pull(skb, 10 /*sizeof(struct test_frame)*/);
-
- /*
- * Send response. This skb will not be sent out again, and
-@@ -740,7 +740,7 @@
-
- switch (event) {
- case CONNECT_RESPONSE:
-- skb_pull(skb, sizeof(struct snrm_frame));
-+ skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
-
- ASSERT(self->netdev != NULL, return -1;);
-
-@@ -870,7 +870,7 @@
-
- ASSERT(self->netdev != NULL, return -1;);
-
-- skb_pull(skb, sizeof(struct snrm_frame));
-+ skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
-
- irlap_qos_negotiate(self, skb);
-
-@@ -902,7 +902,7 @@
- /* Negotiate connection parameters */
- ASSERT(skb->len > 10, return -1;);
-
-- skb_pull(skb, sizeof(struct ua_frame));
-+ skb_pull(skb, 10 /*sizeof(struct ua_frame)*/);
-
- ASSERT(self->netdev != NULL, return -1;);
-
---- linux-2.4.25/net/irda/irlap_frame.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/net/irda/irlap_frame.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1,5 +1,5 @@
- /*********************************************************************
-- *
-+ *
- * Filename: irlap_frame.c
- * Version: 1.0
- * Description: Build and transmit IrLAP frames
-@@ -8,18 +8,18 @@
- * Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Wed Jan 5 08:59:04 2000
- * Modified by: Dag Brattli <dagb@cs.uit.no>
-- *
-- * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
-+ *
-+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
- * All Rights Reserved.
- * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.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
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Neither Dag Brattli nor University of Tromsø admit liability nor
-- * provide warranty for any of this software. This material is
-+ * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-@@ -29,11 +29,12 @@
- #include <linux/if_ether.h>
- #include <linux/netdevice.h>
- #include <linux/irda.h>
--
-+
- #include <net/pkt_sched.h>
- #include <net/sock.h>
--
-+
- #include <asm/byteorder.h>
-+#include <asm/unaligned.h>
-
- #include <net/irda/irda.h>
- #include <net/irda/irda_device.h>
-@@ -46,18 +47,18 @@
- /*
- * Function irlap_insert_info (self, skb)
- *
-- * Insert minimum turnaround time and speed information into the skb. We
-+ * Insert minimum turnaround time and speed information into the skb. We
- * need to do this since it's per packet relevant information. Safe to
- * have this function inlined since it's only called from one place
- */
--static inline void irlap_insert_info(struct irlap_cb *self,
-+static inline void irlap_insert_info(struct irlap_cb *self,
- struct sk_buff *skb)
- {
- struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
-
-- /*
-+ /*
- * Insert MTT (min. turn time) and speed into skb, so that the
-- * device driver knows which settings to use
-+ * device driver knows which settings to use
- */
- cb->magic = LAP_MAGIC;
- cb->mtt = self->mtt_required;
-@@ -65,15 +66,15 @@
-
- /* Reset */
- self->mtt_required = 0;
--
-- /*
-- * Delay equals negotiated BOFs count, plus the number of BOFs to
-- * force the negotiated minimum turnaround time
-+
-+ /*
-+ * Delay equals negotiated BOFs count, plus the number of BOFs to
-+ * force the negotiated minimum turnaround time
- */
- cb->xbofs = self->bofs_count;
- cb->next_xbofs = self->next_bofs;
- cb->xbofs_delay = self->xbofs_delay;
--
-+
- /* Reset XBOF's delay (used only for getting min turn time) */
- self->xbofs_delay = 0;
- /* Put the correct xbofs value for the next packet */
-@@ -104,7 +105,7 @@
- *
- * Transmits a connect SNRM command frame
- */
--void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
-+void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
- {
- struct sk_buff *skb;
- struct snrm_frame *frame;
-@@ -118,7 +119,7 @@
- if (!skb)
- return;
-
-- frame = (struct snrm_frame *) skb_put(skb, 2);
-+ frame = (struct snrm_frame *) skb_put(skb, 2);
-
- /* Insert connection address field */
- if (qos)
-@@ -128,17 +129,17 @@
-
- /* Insert control field */
- frame->control = SNRM_CMD | PF_BIT;
--
-+
- /*
-- * If we are establishing a connection then insert QoS paramerters
-+ * If we are establishing a connection then insert QoS paramerters
- */
- if (qos) {
- skb_put(skb, 9); /* 21 left */
-- frame->saddr = cpu_to_le32(self->saddr);
-- frame->daddr = cpu_to_le32(self->daddr);
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
-
- frame->ncaddr = self->caddr;
--
-+
- ret = irlap_insert_qos_negotiation_params(self, skb);
- if (ret < 0) {
- dev_kfree_skb(skb);
-@@ -154,13 +155,13 @@
- * Received SNRM (Set Normal Response Mode) command frame
- *
- */
--static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct snrm_frame *frame;
-
- frame = (struct snrm_frame *) skb->data;
--
-+
- if (skb->len >= sizeof(struct snrm_frame)) {
- /* Copy the new connection address ignoring the C/R bit */
- info->caddr = frame->ncaddr & 0xFE;
-@@ -170,11 +171,11 @@
- IRDA_DEBUG(3, "%s(), invalid connection address!\n", __FUNCTION__);
- return;
- }
--
-+
- /* Copy peer device address */
-- info->daddr = le32_to_cpu(frame->saddr);
-- info->saddr = le32_to_cpu(frame->daddr);
--
-+ info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
-+
- /* Only accept if addressed directly to us */
- if (info->saddr != self->saddr) {
- IRDA_DEBUG(2, "%s(), not addressed to us!\n", __FUNCTION__);
-@@ -198,9 +199,9 @@
- struct sk_buff *skb;
- struct ua_frame *frame;
- int ret;
--
-+
- IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
-
-@@ -212,13 +213,13 @@
- return;
-
- frame = (struct ua_frame *) skb_put(skb, 10);
--
-+
- /* Build UA response */
- frame->caddr = self->caddr;
- frame->control = UA_RSP | PF_BIT;
-
-- frame->saddr = cpu_to_le32(self->saddr);
-- frame->daddr = cpu_to_le32(self->daddr);
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
-
- /* Should we send QoS negotiation parameters? */
- if (qos) {
-@@ -243,7 +244,7 @@
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
-
-@@ -252,7 +253,7 @@
- return;
-
- frame = skb_put( skb, 2);
--
-+
- if (self->state == LAP_NDM)
- frame[0] = CBROADCAST;
- else
-@@ -260,7 +261,7 @@
-
- frame[1] = DM_RSP | PF_BIT;
-
-- irlap_queue_xmit(self, skb);
-+ irlap_queue_xmit(self, skb);
- }
-
- /*
-@@ -269,11 +270,11 @@
- * Send disconnect (DISC) frame
- *
- */
--void irlap_send_disc_frame(struct irlap_cb *self)
-+void irlap_send_disc_frame(struct irlap_cb *self)
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
-
- ASSERT(self != NULL, return;);
-@@ -284,7 +285,7 @@
- return;
-
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr | CMD_FRAME;
- frame[1] = DISC_CMD | PF_BIT;
-
-@@ -295,17 +296,17 @@
- * Function irlap_send_discovery_xid_frame (S, s, command)
- *
- * Build and transmit a XID (eXchange station IDentifier) discovery
-- * frame.
-+ * frame.
- */
--void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
-- __u8 command, discovery_t *discovery)
-+void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
-+ __u8 command, discovery_t *discovery)
- {
- struct sk_buff *skb = NULL;
- struct xid_frame *frame;
-- __u32 bcast = BROADCAST;
-+ __u32 bcast = BROADCAST, daddr;
- __u8 *info;
-
-- IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
-+ IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
- command);
-
- ASSERT(self != NULL, return;);
-@@ -328,13 +329,14 @@
- }
- frame->ident = XID_FORMAT;
-
-- frame->saddr = cpu_to_le32(self->saddr);
--
- if (command)
-- frame->daddr = cpu_to_le32(bcast);
-+ daddr = bcast;
- else
-- frame->daddr = cpu_to_le32(discovery->daddr);
--
-+ daddr = discovery->daddr;
-+
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(daddr), &frame->daddr);
-+
- switch (S) {
- case 1:
- frame->flags = 0x00;
-@@ -353,10 +355,10 @@
- break;
- }
-
-- frame->slotnr = s;
-+ frame->slotnr = s;
- frame->version = 0x00;
-
-- /*
-+ /*
- * Provide info for final slot only in commands, and for all
- * responses. Send the second byte of the hint only if the
- * EXTENSION bit is set in the first byte.
-@@ -365,7 +367,7 @@
- int len;
-
- if (discovery->hints.byte[0] & HINT_EXTENSION) {
-- info = skb_put(skb, 2);
-+ info = skb_put(skb, 2);
- info[0] = discovery->hints.byte[0];
- info[1] = discovery->hints.byte[1];
- } else {
-@@ -378,7 +380,7 @@
- len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
- info = skb_put(skb, len);
- memcpy(info, discovery->nickname, len);
-- }
-+ }
- irlap_queue_xmit(self, skb);
- }
-
-@@ -388,9 +390,9 @@
- * Received a XID discovery response
- *
- */
--static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct xid_frame *xid;
- discovery_t *discovery = NULL;
-@@ -404,8 +406,8 @@
-
- xid = (struct xid_frame *) skb->data;
-
-- info->daddr = le32_to_cpu(xid->saddr);
-- info->saddr = le32_to_cpu(xid->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
-
- /* Make sure frame is addressed to us */
- if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-@@ -439,11 +441,11 @@
- discovery->charset = discovery_info[1];
- text = (char *) &discovery_info[2];
- }
-- /*
-- * Terminate info string, should be safe since this is where the
-+ /*
-+ * Terminate info string, should be safe since this is where the
- * FCS bytes resides.
- */
-- skb->data[skb->len] = '\0';
-+ skb->data[skb->len] = '\0';
- strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
- discovery->name_len = strlen(discovery->nickname);
-
-@@ -458,9 +460,9 @@
- * Received a XID discovery command
- *
- */
--static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct xid_frame *xid;
- discovery_t *discovery = NULL;
-@@ -469,8 +471,8 @@
-
- xid = (struct xid_frame *) skb->data;
-
-- info->daddr = le32_to_cpu(xid->saddr);
-- info->saddr = le32_to_cpu(xid->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
-
- /* Make sure frame is addressed to us */
- if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-@@ -497,11 +499,11 @@
- return;
- }
- info->s = xid->slotnr;
--
-+
- discovery_info = skb_pull(skb, sizeof(struct xid_frame));
-
-- /*
-- * Check if last frame
-+ /*
-+ * Check if last frame
- */
- if (info->s == 0xff) {
- /* Check if things are sane at this point... */
-@@ -518,7 +520,7 @@
- WARNING("%s(), unable to malloc!\n", __FUNCTION__);
- return;
- }
--
-+
- discovery->daddr = info->daddr;
- discovery->saddr = self->saddr;
- discovery->timestamp = jiffies;
-@@ -533,11 +535,11 @@
- discovery->charset = discovery_info[1];
- text = (char *) &discovery_info[2];
- }
-- /*
-- * Terminate string, should be safe since this is where the
-+ /*
-+ * Terminate string, should be safe since this is where the
- * FCS bytes resides.
- */
-- skb->data[skb->len] = '\0';
-+ skb->data[skb->len] = '\0';
- strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
- discovery->name_len = strlen(discovery->nickname);
-
-@@ -554,7 +556,7 @@
- * Build and transmit RR (Receive Ready) frame. Notice that it is currently
- * only possible to send RR frames with the poll bit set.
- */
--void irlap_send_rr_frame(struct irlap_cb *self, int command)
-+void irlap_send_rr_frame(struct irlap_cb *self, int command)
- {
- struct sk_buff *skb;
- __u8 *frame;
-@@ -562,9 +564,9 @@
- skb = dev_alloc_skb(16);
- if (!skb)
- return;
--
-+
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[0] |= (command) ? CMD_FRAME : 0;
-
-@@ -576,7 +578,7 @@
- /*
- * Function irlap_send_rd_frame (self)
- *
-- * Request disconnect. Used by a secondary station to request the
-+ * Request disconnect. Used by a secondary station to request the
- * disconnection of the link.
- */
- void irlap_send_rd_frame(struct irlap_cb *self)
-@@ -587,9 +589,9 @@
- skb = dev_alloc_skb(16);
- if (!skb)
- return;
--
-+
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[1] = RD_RSP | PF_BIT;
-
-@@ -603,8 +605,8 @@
- * making it inline since its called only from one single place
- * (irlap_driver_rcv).
- */
--static inline void irlap_recv_rr_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-+static inline void irlap_recv_rr_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5;
-@@ -620,7 +622,7 @@
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-
-@@ -629,7 +631,7 @@
- return;
-
- frame = skb_put( skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[0] |= (command) ? CMD_FRAME : 0;
-
-@@ -639,7 +641,7 @@
-
- frame[2] = 0;
-
-- IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
-+ IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
-
- irlap_queue_xmit(self, skb);
- }
-@@ -650,8 +652,8 @@
- * Received RNR (Receive Not Ready) frame from peer station
- *
- */
--static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info, int command)
-+static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5;
-
-@@ -663,13 +665,13 @@
- irlap_do_event(self, RECV_RNR_RSP, skb, info);
- }
-
--static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
-
- info->nr = skb->data[1] >> 5;
--
-+
- /* Check if this is a command or a response frame */
- if (command)
- irlap_do_event(self, RECV_REJ_CMD, skb, info);
-@@ -677,13 +679,13 @@
- irlap_do_event(self, RECV_REJ_RSP, skb, info);
- }
-
--static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
-
- info->nr = skb->data[1] >> 5;
--
-+
- /* Check if this is a command or a response frame */
- if (command)
- irlap_do_event(self, RECV_SREJ_CMD, skb, info);
-@@ -691,7 +693,7 @@
- irlap_do_event(self, RECV_SREJ_RSP, skb, info);
- }
-
--static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
-@@ -709,9 +711,9 @@
- * Received UA (Unnumbered Acknowledgement) frame
- *
- */
--static inline void irlap_recv_ua_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static inline void irlap_recv_ua_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- irlap_do_event(self, RECV_UA_RSP, skb, info);
- }
-@@ -728,25 +730,25 @@
-
- if (skb->data[1] == I_FRAME) {
-
-- /*
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- /* Copy buffer */
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
- }
--
-- /*
-- * Insert frame in store, in case of retransmissions
-+
-+ /*
-+ * Insert frame in store, in case of retransmissions
- */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- self->vs = (self->vs + 1) % 8;
-- self->ack_required = FALSE;
-+ self->ack_required = FALSE;
- self->window -= 1;
-
- irlap_send_i_frame( self, tx_skb, CMD_FRAME);
-@@ -761,40 +763,40 @@
- *
- * Send I(nformation) frame as primary with poll bit set
- */
--void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
-+void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
- {
- struct sk_buff *tx_skb;
-
- /* Stop P timer */
- del_timer(&self->poll_timer);
--
-+
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
--
-- /*
-+
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- /* Copy buffer */
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
- }
--
-- /*
-- * Insert frame in store, in case of retransmissions
-+
-+ /*
-+ * Insert frame in store, in case of retransmissions
- */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-- /*
-+
-+ /*
- * Set poll bit if necessary. We do this to the copied
- * skb, since retransmitted need to set or clear the poll
-- * bit depending on when they are sent.
-+ * bit depending on when they are sent.
- */
- tx_skb->data[1] |= PF_BIT;
--
-+
- self->vs = (self->vs + 1) % 8;
- self->ack_required = FALSE;
-
-@@ -827,8 +829,8 @@
- * Send I(nformation) frame as secondary with final bit set
- *
- */
--void irlap_send_data_secondary_final(struct irlap_cb *self,
-- struct sk_buff *skb)
-+void irlap_send_data_secondary_final(struct irlap_cb *self,
-+ struct sk_buff *skb)
- {
- struct sk_buff *tx_skb = NULL;
-
-@@ -839,26 +841,26 @@
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
-
-- /*
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
-- }
-+ }
-
- /* Insert frame in store */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- tx_skb->data[1] |= PF_BIT;
--
-- self->vs = (self->vs + 1) % 8;
-+
-+ self->vs = (self->vs + 1) % 8;
- self->ack_required = FALSE;
--
-- irlap_send_i_frame(self, tx_skb, RSP_FRAME);
-+
-+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
- } else {
- if (self->ack_required) {
- irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
-@@ -885,32 +887,32 @@
- * Send I(nformation) frame as secondary without final bit set
- *
- */
--void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
-+void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
- {
- struct sk_buff *tx_skb = NULL;
-
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
--
-- /*
-+
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
-- }
--
-+ }
-+
- /* Insert frame in store */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- self->vs = (self->vs + 1) % 8;
-- self->ack_required = FALSE;
-+ self->ack_required = FALSE;
- self->window -= 1;
-
-- irlap_send_i_frame(self, tx_skb, RSP_FRAME);
-+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
- } else {
- irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
- self->window -= 1;
-@@ -920,8 +922,8 @@
- /*
- * Function irlap_resend_rejected_frames (nr)
- *
-- * Resend frames which has not been acknowledged. Should be safe to
-- * traverse the list without locking it since this function will only be
-+ * Resend frames which has not been acknowledged. Should be safe to
-+ * traverse the list without locking it since this function will only be
- * called from interrupt context (BH)
- */
- void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
-@@ -943,8 +945,8 @@
- while (skb != NULL) {
- irlap_wait_min_turn_around(self, &self->qos_tx);
-
-- /* We copy the skb to be retransmitted since we will have to
-- * modify it. Cloning will confuse packet sniffers
-+ /* We copy the skb to be retransmitted since we will have to
-+ * modify it. Cloning will confuse packet sniffers
- */
- /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
- tx_skb = skb_copy(skb, GFP_ATOMIC);
-@@ -959,17 +961,17 @@
- /* Clear old Nr field + poll bit */
- tx_skb->data[1] &= 0x0f;
-
-- /*
-+ /*
- * Set poll bit on the last frame retransmitted
- */
- if (count-- == 1)
- tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
- else
- tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
--
-+
- irlap_send_i_frame(self, tx_skb, command);
-
-- /*
-+ /*
- * If our skb is the last buffer in the list, then
- * we are finished, if not, move to the next sk-buffer
- */
-@@ -979,23 +981,23 @@
- skb = skb->next;
- }
- #if 0 /* Not yet */
-- /*
-+ /*
- * We can now fill the window with additinal data frames
- */
- while (skb_queue_len( &self->txq) > 0) {
--
-+
- IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
-- if ((skb_queue_len( &self->txq) > 0) &&
-+ if ((skb_queue_len( &self->txq) > 0) &&
- (self->window > 0)) {
-- skb = skb_dequeue( &self->txq);
-+ skb = skb_dequeue( &self->txq);
- ASSERT(skb != NULL, return;);
-
- /*
-- * If send window > 1 then send frame with pf
-+ * If send window > 1 then send frame with pf
- * bit cleared
-- */
-- if ((self->window > 1) &&
-- skb_queue_len(&self->txq) > 0)
-+ */
-+ if ((self->window > 1) &&
-+ skb_queue_len(&self->txq) > 0)
- {
- irlap_send_data_primary(self, skb);
- } else {
-@@ -1023,14 +1025,14 @@
- if (skb != NULL) {
- irlap_wait_min_turn_around(self, &self->qos_tx);
-
-- /* We copy the skb to be retransmitted since we will have to
-- * modify it. Cloning will confuse packet sniffers
-+ /* We copy the skb to be retransmitted since we will have to
-+ * modify it. Cloning will confuse packet sniffers
- */
- /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
- tx_skb = skb_copy(skb, GFP_ATOMIC);
- if (!tx_skb) {
- IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
-- return;
-+ return;
- }
- /* Unlink tx_skb from list */
- tx_skb->next = tx_skb->prev = NULL;
-@@ -1041,7 +1043,7 @@
-
- /* Set poll/final bit */
- tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
--
-+
- irlap_send_i_frame(self, tx_skb, command);
- }
- }
-@@ -1052,15 +1054,15 @@
- * Contruct and transmit an Unnumbered Information (UI) frame
- *
- */
--void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
-+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
- __u8 caddr, int command)
- {
- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
--
-+
- /* Insert connection address */
- skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
-
-@@ -1072,13 +1074,13 @@
- *
- * Contruct and transmit Information (I) frame
- */
--void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
-- int command)
-+void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ int command)
- {
- /* Insert connection address */
- skb->data[0] = self->caddr;
- skb->data[0] |= (command) ? CMD_FRAME : 0;
--
-+
- /* Insert next to receive (Vr) */
- skb->data[1] |= (self->vr << 5); /* insert nr */
-
-@@ -1091,9 +1093,9 @@
- * Receive and parse an I (Information) frame, no harm in making it inline
- * since it's called only from one single place (irlap_driver_rcv).
- */
--static inline void irlap_recv_i_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info, int command)
-+static inline void irlap_recv_i_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5; /* Next to receive */
- info->pf = skb->data[1] & PF_BIT; /* Final bit */
-@@ -1112,7 +1114,7 @@
- * Receive and parse an Unnumbered Information (UI) frame
- *
- */
--static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info)
- {
- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
-@@ -1128,19 +1130,19 @@
- * Received Frame Reject response.
- *
- */
--static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- __u8 *frame;
- int w, x, y, z;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
--
-+
- frame = skb->data;
-
- info->nr = frame[2] >> 5; /* Next to receive */
-@@ -1151,11 +1153,11 @@
- x = frame[3] & 0x02;
- y = frame[3] & 0x04;
- z = frame[3] & 0x08;
--
-+
- if (w) {
- IRDA_DEBUG(0, "Rejected control field is undefined or not "
- "implemented.\n");
-- }
-+ }
- if (x) {
- IRDA_DEBUG(0, "Rejected control field was invalid because it "
- "contained a non permitted I field.\n");
-@@ -1178,7 +1180,7 @@
- * Send a test frame response
- *
- */
--void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
-+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
- struct sk_buff *cmd)
- {
- struct sk_buff *skb;
-@@ -1191,7 +1193,7 @@
-
- /* Broadcast frames must include saddr and daddr fields */
- if (caddr == CBROADCAST) {
-- frame = (struct test_frame *)
-+ frame = (struct test_frame *)
- skb_put(skb, sizeof(struct test_frame));
-
- /* Insert the swapped addresses */
-@@ -1218,28 +1220,28 @@
- * Receive a test frame
- *
- */
--static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- struct test_frame *frame;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
--
-+
- frame = (struct test_frame *) skb->data;
--
-+
- /* Broadcast frames must carry saddr and daddr fields */
- if (info->caddr == CBROADCAST) {
- if (skb->len < sizeof(struct test_frame)) {
- IRDA_DEBUG(0, "%s() test frame to short!\n", __FUNCTION__);
- return;
- }
--
-+
- /* Read and swap addresses */
-- info->daddr = le32_to_cpu(frame->saddr);
-- info->saddr = le32_to_cpu(frame->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
-
- /* Make sure frame is addressed to us */
-- if ((info->saddr != self->saddr) &&
-+ if ((info->saddr != self->saddr) &&
- (info->saddr != BROADCAST)) {
- return;
- }
-@@ -1254,18 +1256,18 @@
- /*
- * Function irlap_driver_rcv (skb, netdev, ptype)
- *
-- * Called when a frame is received. Dispatches the right receive function
-+ * Called when a frame is received. Dispatches the right receive function
- * for processing of the frame.
- *
- */
--int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
-+int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype)
- {
- struct irlap_info info;
- struct irlap_cb *self;
- int command;
- __u8 control;
--
-+
- /* FIXME: should we get our own field? */
- self = (struct irlap_cb *) dev->atalk_ptr;
-
-@@ -1281,10 +1283,10 @@
- dev_kfree_skb(skb);
- return -1;
- }
--
-+
- command = skb->data[0] & CMD_FRAME;
- info.caddr = skb->data[0] & CBROADCAST;
--
-+
- info.pf = skb->data[1] & PF_BIT;
- info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
-
-@@ -1295,7 +1297,7 @@
- IRDA_DEBUG(0, "%s(), wrong connection address!\n", __FUNCTION__);
- goto out;
- }
-- /*
-+ /*
- * Optimize for the common case and check if the frame is an
- * I(nformation) frame. Only I-frames have bit 0 set to 0
- */
-@@ -1304,11 +1306,11 @@
- goto out;
- }
- /*
-- * We now check is the frame is an S(upervisory) frame. Only
-+ * We now check is the frame is an S(upervisory) frame. Only
- * S-frames have bit 0 set to 1 and bit 1 set to 0
- */
- if (~control & 0x02) {
-- /*
-+ /*
- * Received S(upervisory) frame, check which frame type it is
- * only the first nibble is of interest
- */
-@@ -1332,8 +1334,8 @@
- }
- goto out;
- }
-- /*
-- * This must be a C(ontrol) frame
-+ /*
-+ * This must be a C(ontrol) frame
- */
- switch (control) {
- case XID_RSP:
-@@ -1369,6 +1371,6 @@
- break;
- }
- out:
-- dev_kfree_skb(skb);
-+ dev_kfree_skb(skb);
- return 0;
- }
---- linux-2.4.25/net/irda/irttp.c~2.4.25-vrs2.patch 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.25/net/irda/irttp.c 2004-03-31 17:15:09.000000000 +0200
-@@ -1665,8 +1665,8 @@
- }
- self->rx_sdu_size = 0;
- }
--
-- /*
-+
-+ /*
- * It's not trivial to keep track of how many credits are available
- * by incrementing at each packet, because delivery may fail
- * (irttp_do_data_indication() may requeue the frame) and because
-@@ -1676,7 +1676,7 @@
- * to send remote_credit.
- * No need to spinlock, write is atomic and self correcting...
- * Jean II
-- */
-+ */
- self->avail_credit = (self->initial_credit -
- (self->remote_credit +
- skb_queue_len(&self->rx_queue) +
---- linux-2.4.25/net/sched/Config.in~2.4.25-vrs2.patch 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.25/net/sched/Config.in 2004-03-31 17:15:09.000000000 +0200
-@@ -3,9 +3,9 @@
- #
- tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ
- tristate ' HTB packet scheduler' CONFIG_NET_SCH_HTB
--tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
-+dep_tristate ' CSZ packet scheduler (experimental)' CONFIG_NET_SCH_CSZ $CONFIG_EXPERIMENTAL
- #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
--tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
-+tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
- if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
- dep_tristate ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
- fi
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/defconfig-simpad b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/defconfig-simpad
deleted file mode 100644
index da3037f465..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/defconfig-simpad
+++ /dev/null
@@ -1,1281 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_ANAKIN is not set
-# CONFIG_ARCH_ARCA5K is not set
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_OMAHA is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_MX1ADS is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_RISCSTATION is not set
-CONFIG_ARCH_SA1100=y
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_AT91RM9200 is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
-
-#
-# SA11x0 Implementations
-#
-# CONFIG_SA1100_ACCELENT is not set
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSAGC is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_ADSBITSYPLUS is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CEP is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_H3600_SLEEVE is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_FRODO is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_BADGE4 is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-CONFIG_SA1100_SIMPAD=y
-# CONFIG_SA1100_SIMPUTER is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-CONFIG_SA1100_USB_CHAR=m
-# CONFIG_SA1100_SSP is not set
-
-#
-# AT91RM9200 Implementations
-#
-# CONFIG_ARCH_AT91RM9200DK is not set
-# CONFIG_MACH_CSB337 is not set
-
-#
-# Intel PXA250/210 Implementations
-#
-# CONFIG_ARCH_LUBBOCK is not set
-# CONFIG_ARCH_PXA_IDP is not set
-# CONFIG_ARCH_PXA_CERF is not set
-# CONFIG_ARCH_TRIZEPS2 is not set
-# CONFIG_PXA_USB is not set
-# CONFIG_PXA_USB_NETLINK is not set
-# CONFIG_PXA_USB_CHAR is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_GUIDEA07 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_PLD is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_ARM1020E is not set
-# CONFIG_CPU_ARM1022 is not set
-# CONFIG_CPU_ARM1026 is not set
-# CONFIG_CPU_SA110 is not set
-CONFIG_CPU_SA1100=y
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-
-#
-# Processor Features
-#
-CONFIG_DISCONTIGMEM=y
-
-#
-# General setup
-#
-# CONFIG_PCI is not set
-CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CPU_FREQ=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_CLPS6700 is not set
-CONFIG_PCMCIA_SA1100=y
-# CONFIG_PCMCIA_PXA is not set
-
-#
-# MMC device drivers
-#
-# CONFIG_MMC is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-
-#
-# At least one math emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_PM=y
-CONFIG_APM=y
-CONFIG_SIMPAD_PM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mtdparts=sa1100:512k(boot),1m(kernel),14848k(root),-(home) console=ttySA root=1f02 noinitrd jffs2_orphaned_inodes=delete rootfstype=jffs2 mem=32M"
-CONFIG_LEDS=y
-# CONFIG_LEDS_TIMER is not set
-# CONFIG_LEDS_CPU is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CONCAT=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-CONFIG_MTD_CFI_B2=y
-# CONFIG_MTD_CFI_B4 is not set
-# CONFIG_MTD_CFI_B8 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_NORA is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
-CONFIG_MTD_SA1100=y
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-# CONFIG_MTD_FORTUNET is not set
-# CONFIG_MTD_EPXA is not set
-# CONFIG_MTD_AUTCPU12 is not set
-# CONFIG_MTD_EDB7312 is not set
-# CONFIG_MTD_IMPA7 is not set
-# CONFIG_MTD_CEIVA is not set
-# CONFIG_MTD_PCI is not set
-# CONFIG_MTD_PCMCIA is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_MMC=m
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_CISS_MONITOR_THREAD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_STATS is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-# CONFIG_NET_IPGRE_BROADCAST is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_ARPD=y
-CONFIG_INET_ECN=y
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_SUBTREES=y
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_MOBILITY=m
-CONFIG_IPV6_MOBILITY_MN=m
-CONFIG_IPV6_MOBILITY_HA=m
-CONFIG_IPV6_MOBILITY_DEBUG=y
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-# CONFIG_KHTTPD is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=m
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-CONFIG_VLAN_8021Q=m
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_IPSEC=y
-
-#
-# IPSec options (Openswan)
-#
-CONFIG_IPSEC_IPIP=y
-CONFIG_IPSEC_AH=y
-CONFIG_IPSEC_AUTH_HMAC_MD5=y
-CONFIG_IPSEC_AUTH_HMAC_SHA1=y
-CONFIG_IPSEC_ESP=y
-CONFIG_IPSEC_ENC_3DES=y
-CONFIG_IPSEC_ENC_AES=y
-CONFIG_IPSEC_ALG=y
-CONFIG_IPSEC_ALG_AES=y
-# CONFIG_IPSEC_ALG_CRYPTOAPI is not set
-CONFIG_IPSEC_IPCOMP=y
-CONFIG_IPSEC_DEBUG=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
-# CONFIG_ARM_CIRRUS is not set
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_TULIP is not set
-# CONFIG_DM9102 is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_SUNDANCE_MMIO is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-CONFIG_NET_POCKET=y
-# CONFIG_DE600 is not set
-# CONFIG_DE620 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_STRIP is not set
-# CONFIG_WAVELAN is not set
-# CONFIG_ARLAN is not set
-# CONFIG_AIRONET4500 is not set
-# CONFIG_AIRONET4500_NONCS is not set
-# CONFIG_AIRONET4500_PROC is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-
-#
-# Wireless Pcmcia cards support
-#
-# CONFIG_PCMCIA_HERMES is not set
-# CONFIG_AIRO_CS is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_NET_PCMCIA_RADIO=y
-# CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_AIRONET4500_CS is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_TOSHIBA_OLD is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VLSI_FIR is not set
-# CONFIG_VIA_IRCC_FIR is not set
-CONFIG_SA1100_FIR=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-# CONFIG_BLK_DEV_ATARAID_SII is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_KEYBDEV=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-CONFIG_INPUT_EVDEV=m
-CONFIG_INPUT_UINPUT=y
-# CONFIG_INPUT_MX1TS is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_ANAKIN is not set
-# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-# CONFIG_SERIAL_OMAHA is not set
-# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-# CONFIG_SERIAL_AT91 is not set
-# CONFIG_SERIAL_AT91_CONSOLE is not set
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-
-#
-# Other L3 adapters
-#
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_NS558 is not set
-# CONFIG_INPUT_LIGHTNING is not set
-# CONFIG_INPUT_PCIGAME is not set
-# CONFIG_INPUT_CS461X is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_INPUT_SERIO is not set
-# CONFIG_INPUT_SERPORT is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_ANALOG is not set
-# CONFIG_INPUT_A3D is not set
-# CONFIG_INPUT_ADI is not set
-# CONFIG_INPUT_COBRA is not set
-# CONFIG_INPUT_GF2K is not set
-# CONFIG_INPUT_GRIP is not set
-# CONFIG_INPUT_INTERACT is not set
-# CONFIG_INPUT_TMDC is not set
-# CONFIG_INPUT_SIDEWINDER is not set
-# CONFIG_INPUT_IFORCE_USB is not set
-# CONFIG_INPUT_IFORCE_232 is not set
-# CONFIG_INPUT_WARRIOR is not set
-# CONFIG_INPUT_MAGELLAN is not set
-# CONFIG_INPUT_SPACEORB is not set
-# CONFIG_INPUT_SPACEBALL is not set
-# CONFIG_INPUT_STINGER is not set
-# CONFIG_INPUT_DB9 is not set
-# CONFIG_INPUT_GAMECON is not set
-# CONFIG_INPUT_TURBOGRAFX is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_IPMI_PANIC_EVENT is not set
-# CONFIG_IPMI_DEVICE_INTERFACE is not set
-# CONFIG_IPMI_KCS is not set
-# CONFIG_IPMI_WATCHDOG is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_SCx200 is not set
-# CONFIG_SCx200_GPIO is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_SA1100_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-
-#
-# Direct Rendering Manager (XFree86 DRI support)
-#
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-# CONFIG_SYNCLINK_CS is not set
-CONFIG_TDA8007=m
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=m
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=y
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_CRAMFS=m
-# CONFIG_CRAMFS_LINEAR is not set
-# CONFIG_CRAMFS_LINEAR_XIP is not set
-# CONFIG_ROOT_CRAMFS_LINEAR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_TRACE is not set
-# CONFIG_XFS_DEBUG is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_SMB_UNIX=y
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=y
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=y
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_ANAKIN is not set
-# CONFIG_FB_CLPS711X is not set
-# CONFIG_FB_SA1100 is not set
-# CONFIG_FB_DBMX1 is not set
-# CONFIG_FB_PXA is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_MQ200=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-# CONFIG_FBCON_CFB24 is not set
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-CONFIG_SOUND_SA1100=y
-# CONFIG_SOUND_UDA1341 is not set
-# CONFIG_SOUND_ASSABET_UDA1341 is not set
-# CONFIG_SOUND_H3600_UDA1341 is not set
-# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-# CONFIG_SOUND_SA1111_UDA1341 is not set
-# CONFIG_SOUND_SA1111_AC97 is not set
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_VIDC is not set
-# CONFIG_SOUND_WAVEARTIST is not set
-# CONFIG_SOUND_PXA_AC97 is not set
-# CONFIG_SOUND_TVMIXER is not set
-# CONFIG_SOUND_AD1980 is not set
-# CONFIG_SOUND_WM97XX is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-CONFIG_MCP_UCB1200=y
-CONFIG_MCP_UCB1200_AUDIO=y
-CONFIG_MCP_UCB1200_TS=y
-# CONFIG_MCP_UCB1400_TS is not set
-
-#
-# Console Switches
-#
-CONFIG_SWITCHES=y
-CONFIG_SWITCHES_SA1100=y
-CONFIG_SWITCHES_UCB1X00=y
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Support for USB gadgets
-#
-CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_NET2280=y
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_CONTROLLER is not set
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-
-#
-# Bluetooth device drivers
-#
-# CONFIG_BLUEZ_HCIUSB is not set
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-# CONFIG_BLUEZ_HCIBFUSB is not set
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Kernel hacking
-#
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_NO_PGT_CACHE is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-# CONFIG_FW_LOADER is not set
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mppe-20040216.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mppe-20040216.patch
deleted file mode 100644
index 4393e2ea83..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/mppe-20040216.patch
+++ /dev/null
@@ -1,1225 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.25/drivers/net/Config.in~mppe-20040216
-+++ linux-2.4.25/drivers/net/Config.in
-@@ -327,6 +327,7 @@
- dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
- dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
- dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
-+ dep_tristate ' PPP MPPE compression (encryption)' CONFIG_PPP_MPPE $CONFIG_PPP
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
- fi
---- /dev/null
-+++ linux-2.4.25/drivers/net/arcfour.c
-@@ -0,0 +1,75 @@
-+/*
-+ * arcfour.c
-+ * by Frank Cusack <frank@google.com>
-+ * 100% public domain
-+ *
-+ * Implemented from the description in _Applied Cryptography_, 2nd ed.
-+ *
-+ * ** Distribution ** of this software is unlimited and unrestricted.
-+ *
-+ * ** Use ** of this software is almost certainly legal; however, refer
-+ * to <http://theory.lcs.mit.edu/~rivest/faq.html>.
-+ */
-+
-+#include "arcfour.h"
-+#if defined(__linux__)
-+#include <linux/string.h>
-+#endif
-+
-+#define swap(a, b) \
-+{ \
-+ unsigned char t = b; \
-+ b = a; \
-+ a = t; \
-+}
-+
-+/*
-+ * Initialize arcfour from a key.
-+ */
-+void
-+arcfour_setkey(arcfour_context *context, const unsigned char *key,
-+ unsigned keylen)
-+{
-+ unsigned i, j;
-+ unsigned char K[256];
-+
-+ context->i = context->j = 0;
-+
-+ for (i = 0; i < 256; i++) {
-+ context->S[i] = i;
-+ K[i] = key[i % keylen];
-+ }
-+
-+ j = 0;
-+ for (i = 0; i < 256; i++) {
-+ j = (j + context->S[i] + K[i]) % 256;
-+ swap(context->S[i], context->S[j]);
-+ }
-+
-+ memset(K, 0, sizeof(K));
-+}
-+
-+/*
-+ * plaintext -> ciphertext (or vice versa)
-+ */
-+void
-+arcfour_encrypt(arcfour_context *context, const unsigned char *in, unsigned len,
-+ unsigned char *out)
-+{
-+ unsigned i = context->i;
-+ unsigned j = context->j;
-+ unsigned char *S = context->S;
-+ unsigned char K;
-+
-+ while (len--) {
-+ i = (i + 1) % 256;
-+ j = (j + S[i]) % 256;
-+ swap(S[i], S[j]);
-+ K = S[(S[i] + S[j]) % 256];
-+ *out++ = *in++ ^ K;
-+ }
-+
-+ context->i = i;
-+ context->j = j;
-+}
-+
---- /dev/null
-+++ linux-2.4.25/drivers/net/arcfour.h
-@@ -0,0 +1,17 @@
-+/* arcfour.h */
-+
-+#ifndef _ARCFOUR_H
-+#define _ARCFOUR_H
-+
-+typedef struct {
-+ unsigned i;
-+ unsigned j;
-+ unsigned char S[256];
-+} arcfour_context;
-+
-+extern void arcfour_setkey(arcfour_context *, const unsigned char *, unsigned);
-+extern void arcfour_encrypt(arcfour_context *, const unsigned char *, unsigned,
-+ unsigned char *);
-+#define arcfour_decrypt arcfour_encrypt
-+
-+#endif /* _ARCFOUR_H */
---- linux-2.4.25/drivers/net/ppp_generic.c~mppe-20040216
-+++ linux-2.4.25/drivers/net/ppp_generic.c
-@@ -102,6 +102,7 @@
- spinlock_t rlock; /* lock for receive side 58 */
- spinlock_t wlock; /* lock for transmit side 5c */
- int mru; /* max receive unit 60 */
-+ int mru_alloc; /* MAX(1500,MRU) for dev_alloc_skb() */
- unsigned int flags; /* control bits 64 */
- unsigned int xstate; /* transmit state bits 68 */
- unsigned int rstate; /* receive state bits 6c */
-@@ -129,6 +130,7 @@
- struct sock_fprog pass_filter; /* filter for packets to pass */
- struct sock_fprog active_filter;/* filter for pkts to reset idle */
- #endif /* CONFIG_PPP_FILTER */
-+ int xpad; /* ECP or CCP (MPPE) transmit padding */
- };
-
- /*
-@@ -552,7 +554,9 @@
- case PPPIOCSMRU:
- if (get_user(val, (int *) arg))
- break;
-- ppp->mru = val;
-+ ppp->mru_alloc = ppp->mru = val;
-+ if (ppp->mru_alloc < PPP_MRU)
-+ ppp->mru_alloc = PPP_MRU; /* increase for broken peers */
- err = 0;
- break;
-
-@@ -1031,8 +1035,8 @@
- /* try to do packet compression */
- if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
- && proto != PPP_LCP && proto != PPP_CCP) {
-- new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len,
-- GFP_ATOMIC);
-+ new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len
-+ + ppp->xpad, GFP_ATOMIC);
- if (new_skb == 0) {
- printk(KERN_ERR "PPP: no memory (comp pkt)\n");
- goto drop;
-@@ -1044,15 +1048,28 @@
- /* compressor still expects A/C bytes in hdr */
- len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2,
- new_skb->data, skb->len + 2,
-- ppp->dev->mtu + PPP_HDRLEN);
-+ ppp->dev->mtu + ppp->xpad
-+ + PPP_HDRLEN);
- if (len > 0 && (ppp->flags & SC_CCP_UP)) {
- kfree_skb(skb);
- skb = new_skb;
- skb_put(skb, len);
- skb_pull(skb, 2); /* pull off A/C bytes */
-- } else {
-+ } else if (len == 0) {
- /* didn't compress, or CCP not up yet */
- kfree_skb(new_skb);
-+ } else {
-+ /*
-+ * (len < 0)
-+ * MPPE requires that we do not send unencrypted
-+ * frames. The compressor will return -1 if we
-+ * should drop the frame. We cannot simply test
-+ * the compress_proto because MPPE and MPPC share
-+ * the same number.
-+ */
-+ printk(KERN_ERR "ppp: compressor dropped pkt\n");
-+ kfree_skb(new_skb);
-+ goto drop;
- }
- }
-
-@@ -1540,14 +1557,15 @@
- int len;
-
- if (proto == PPP_COMP) {
-- ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
-+ ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN);
- if (ns == 0) {
- printk(KERN_ERR "ppp_decompress_frame: no memory\n");
- goto err;
- }
- /* the decompressor still expects the A/C bytes in the hdr */
- len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
-- skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN);
-+ skb->len + 2, ns->data,
-+ ppp->mru_alloc + PPP_HDRLEN);
- if (len < 0) {
- /* Pass the compressed frame to pppd as an
- error indication. */
-@@ -1982,6 +2000,20 @@
- ocomp->comp_free(ostate);
- err = 0;
- }
-+ if (ccp_option[0] == CI_MPPE)
-+ /*
-+ * pppd (userland) has reduced the MTU by MPPE_PAD,
-+ * to accomodate "compressor" growth. We must
-+ * increase the space allocated for compressor
-+ * output in ppp_send_frame() accordingly. Note
-+ * that from a purist's view, it may be more correct
-+ * to require multilink and fragment large packets,
-+ * but that seems inefficient compared to this
-+ * little trick.
-+ */
-+ ppp->xpad = MPPE_PAD;
-+ else
-+ ppp->xpad = 0;
-
- } else {
- state = cp->decomp_alloc(ccp_option, data.length);
-@@ -2253,6 +2285,7 @@
- /* Initialize the new ppp unit */
- ppp->file.index = unit;
- ppp->mru = PPP_MRU;
-+ ppp->mru_alloc = PPP_MRU;
- init_ppp_file(&ppp->file, INTERFACE);
- ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
- for (i = 0; i < NUM_NP; ++i)
---- /dev/null
-+++ linux-2.4.25/drivers/net/ppp_mppe_compress.c
-@@ -0,0 +1,643 @@
-+/*
-+ * ==FILEVERSION 20020521==
-+ *
-+ * ppp_mppe_compress.c - interface MPPE to the PPP code.
-+ * This version is for use with Linux kernel 2.2.19+ and 2.4.x.
-+ *
-+ * By Frank Cusack <frank@google.com>.
-+ * Copyright (c) 2002 Google, Inc.
-+ * All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and distribute this software and its
-+ * documentation is hereby granted, provided that the above copyright
-+ * notice appears in all copies. This software is provided without any
-+ * warranty, express or implied.
-+ *
-+ * Changelog:
-+ * 2/15/04 - TS: added #include <version.h> and testing for Kernel
-+ * version before using
-+ * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are
-+ * depreciated in 2.6
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+
-+#include <linux/ppp_defs.h>
-+#include <linux/ppp-comp.h>
-+
-+#include "arcfour.h"
-+#include "sha1.h"
-+
-+/*
-+ * State for an MPPE (de)compressor.
-+ */
-+typedef struct ppp_mppe_state {
-+ unsigned char master_key[MPPE_MAX_KEY_LEN];
-+ unsigned char session_key[MPPE_MAX_KEY_LEN];
-+ arcfour_context arcfour_context; /* encryption state */
-+ unsigned keylen; /* key length in bytes */
-+ /* NB: 128-bit == 16, 40-bit == 8! */
-+ /* If we want to support 56-bit, */
-+ /* the unit has to change to bits */
-+ unsigned char bits; /* MPPE control bits */
-+ unsigned ccount; /* 12-bit coherency count (seqno) */
-+ unsigned stateful; /* stateful mode flag */
-+ int discard; /* stateful mode packet loss flag */
-+ int sanity_errors; /* take down LCP if too many */
-+ int unit;
-+ int debug;
-+ struct compstat stats;
-+} ppp_mppe_state;
-+
-+/* ppp_mppe_state.bits definitions */
-+#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */
-+#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */
-+#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */
-+#define MPPE_BIT_D 0x10 /* This is an encrypted frame */
-+
-+#define MPPE_BIT_FLUSHED MPPE_BIT_A
-+#define MPPE_BIT_ENCRYPTED MPPE_BIT_D
-+
-+#define MPPE_BITS(p) ((p)[4] & 0xf0)
-+#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5])
-+#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */
-+
-+#define MPPE_OVHD 2 /* MPPE overhead/packet */
-+#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */
-+
-+static void GetNewKeyFromSHA __P((unsigned char *StartKey,
-+ unsigned char *SessionKey,
-+ unsigned SessionKeyLength,
-+ unsigned char *InterimKey));
-+static void mppe_rekey __P((ppp_mppe_state *state, int));
-+static void *mppe_alloc __P((unsigned char *options, int optlen));
-+static void mppe_free __P((void *state));
-+static int mppe_init __P((void *state, unsigned char *options,
-+ int optlen, int unit, int debug, const char *));
-+static int mppe_comp_init __P((void *state, unsigned char *options,
-+ int optlen,
-+ int unit, int hdrlen, int debug));
-+static int mppe_decomp_init __P((void *state, unsigned char *options,
-+ int optlen, int unit,
-+ int hdrlen, int mru, int debug));
-+static int mppe_compress __P((void *state, unsigned char *ibuf,
-+ unsigned char *obuf,
-+ int isize, int osize));
-+static void mppe_incomp __P((void *state, unsigned char *ibuf, int icnt));
-+static int mppe_decompress __P((void *state, unsigned char *ibuf,
-+ int isize, unsigned char *obuf,int osize));
-+static void mppe_comp_reset __P((void *state));
-+static void mppe_decomp_reset __P((void *state));
-+static void mppe_comp_stats __P((void *state, struct compstat *stats));
-+
-+
-+/*
-+ * Key Derivation, from RFC 3078, RFC 3079.
-+ * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
-+ */
-+static void
-+GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey,
-+ unsigned SessionKeyLength, unsigned char *InterimKey)
-+{
-+ SHA1_CTX Context;
-+ unsigned char Digest[SHA1_SIGNATURE_SIZE];
-+
-+ unsigned char SHApad1[40] =
-+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-+ unsigned char SHApad2[40] =
-+ { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
-+
-+ /* assert(SessionKeyLength <= SHA1_SIGNATURE_SIZE); */
-+
-+ SHA1_Init(&Context);
-+ SHA1_Update(&Context, MasterKey, SessionKeyLength);
-+ SHA1_Update(&Context, SHApad1, sizeof(SHApad1));
-+ SHA1_Update(&Context, SessionKey, SessionKeyLength);
-+ SHA1_Update(&Context, SHApad2, sizeof(SHApad2));
-+ SHA1_Final(Digest, &Context);
-+
-+ memcpy(InterimKey, Digest, SessionKeyLength);
-+}
-+
-+/*
-+ * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3.
-+ * Well, not what's written there, but rather what they meant.
-+ */
-+static void
-+mppe_rekey(ppp_mppe_state *state, int initial_key)
-+{
-+ unsigned char InterimKey[MPPE_MAX_KEY_LEN];
-+
-+ GetNewKeyFromSHA(state->master_key, state->session_key,
-+ state->keylen, InterimKey);
-+ if (!initial_key) {
-+ arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen);
-+ arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen,
-+ state->session_key);
-+ } else {
-+ memcpy(state->session_key, InterimKey, state->keylen);
-+ }
-+ if (state->keylen == 8) {
-+ /* See RFC 3078 */
-+ state->session_key[0] = 0xd1;
-+ state->session_key[1] = 0x26;
-+ state->session_key[2] = 0x9e;
-+ }
-+ arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen);
-+}
-+
-+
-+/*
-+ * Allocate space for a (de)compressor.
-+ */
-+static void *
-+mppe_alloc(unsigned char *options, int optlen)
-+{
-+ ppp_mppe_state *state;
-+
-+ if (optlen != CILEN_MPPE + sizeof(state->master_key)
-+ || options[0] != CI_MPPE
-+ || options[1] != CILEN_MPPE)
-+ return NULL;
-+
-+ state = (ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
-+ if (state == NULL)
-+ return NULL;
-+
-+/*
-+ Added to avoid module warnings about MOD_INC
-+ being depreciated in 2.6.x
-+*/
-+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) )
-+ try_module_get(THIS_MODULE);
-+#else
-+ MOD_INC_USE_COUNT;
-+#endif
-+ memset(state, 0, sizeof(*state));
-+
-+ /* Save keys. */
-+ memcpy(state->master_key, &options[CILEN_MPPE], sizeof(state->master_key));
-+ memcpy(state->session_key, state->master_key, sizeof(state->master_key));
-+ /*
-+ * We defer initial key generation until mppe_init(), as mppe_alloc()
-+ * is called frequently during negotiation.
-+ */
-+
-+ return (void *) state;
-+}
-+
-+/*
-+ * Deallocate space for a (de)compressor.
-+ */
-+static void
-+mppe_free(void *arg)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ if (state) {
-+ kfree(state);
-+/*
-+ Added to avoid module warnings about MOD_DEC_USE_COUNT
-+ being depreciated in 2.6.x
-+*/
-+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) )
-+ module_put(THIS_MODULE);
-+#else
-+ MOD_DEC_USE_COUNT;
-+#endif
-+ }
-+}
-+
-+
-+/*
-+ * Initialize (de)compressor state.
-+ */
-+static int
-+mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug,
-+ const char *debugstr)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ unsigned char mppe_opts;
-+
-+ if (optlen != CILEN_MPPE
-+ || options[0] != CI_MPPE
-+ || options[1] != CILEN_MPPE)
-+ return 0;
-+
-+ MPPE_CI_TO_OPTS(&options[2], mppe_opts);
-+ if (mppe_opts & MPPE_OPT_128)
-+ state->keylen = 16;
-+ else if (mppe_opts & MPPE_OPT_40)
-+ state->keylen = 8;
-+ else {
-+ printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, unit);
-+ return 0;
-+ }
-+ if (mppe_opts & MPPE_OPT_STATEFUL)
-+ state->stateful = 1;
-+
-+ /* Generate the initial session key. */
-+ mppe_rekey(state, 1);
-+
-+ if (debug) {
-+ int i;
-+ char mkey[sizeof(state->master_key) * 2 + 1];
-+ char skey[sizeof(state->session_key) * 2 + 1];
-+
-+ printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr,
-+ unit, (state->keylen == 16)? 128: 40,
-+ (state->stateful)? "stateful": "stateless");
-+
-+ for (i = 0; i < sizeof(state->master_key); i++)
-+ sprintf(mkey + i * 2, "%.2x", state->master_key[i]);
-+ for (i = 0; i < sizeof(state->session_key); i++)
-+ sprintf(skey + i * 2, "%.2x", state->session_key[i]);
-+ printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n",
-+ debugstr, unit, mkey, skey);
-+ }
-+
-+ /*
-+ * Initialize the coherency count. The initial value is not specified
-+ * in RFC 3078, but we can make a reasonable assumption that it will
-+ * start at 0. Setting it to the max here makes the comp/decomp code
-+ * do the right thing (determined through experiment).
-+ */
-+ state->ccount = MPPE_CCOUNT_SPACE - 1;
-+
-+ /*
-+ * Note that even though we have initialized the key table, we don't
-+ * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1.
-+ */
-+ state->bits = MPPE_BIT_ENCRYPTED;
-+
-+ state->unit = unit;
-+ state->debug = debug;
-+
-+ return 1;
-+}
-+
-+
-+
-+static int
-+mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit,
-+ int hdrlen, int debug)
-+{
-+ /* ARGSUSED */
-+ return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init");
-+}
-+
-+/*
-+ * We received a CCP Reset-Request (actually, we are sending a Reset-Ack),
-+ * tell the compressor to rekey. Note that we MUST NOT rekey for
-+ * every CCP Reset-Request; we only rekey on the next xmit packet.
-+ * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost.
-+ * So, rekeying for every CCP Reset-Request is broken as the peer will not
-+ * know how many times we've rekeyed. (If we rekey and THEN get another
-+ * CCP Reset-Request, we must rekey again.)
-+ */
-+static void
-+mppe_comp_reset(void *arg)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ state->bits |= MPPE_BIT_FLUSHED;
-+}
-+
-+/*
-+ * Compress (encrypt) a packet.
-+ * It's strange to call this a compressor, since the output is always
-+ * MPPE_OVHD + 2 bytes larger than the input.
-+ */
-+int
-+mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
-+ int isize, int osize)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ int proto;
-+
-+ /*
-+ * Check that the protocol is in the range we handle.
-+ */
-+ proto = PPP_PROTOCOL(ibuf);
-+ if (proto < 0x0021 || proto > 0x00fa)
-+ return 0;
-+
-+ /* Make sure we have enough room to generate an encrypted packet. */
-+ if (osize < isize + MPPE_OVHD + 2) {
-+ /* Drop the packet if we should encrypt it, but can't. */
-+ printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "
-+ "(have: %d need: %d)\n", state->unit,
-+ osize, osize + MPPE_OVHD + 2);
-+ return -1;
-+ }
-+
-+ osize = isize + MPPE_OVHD + 2;
-+
-+ /*
-+ * Copy over the PPP header and set control bits.
-+ */
-+ obuf[0] = PPP_ADDRESS(ibuf);
-+ obuf[1] = PPP_CONTROL(ibuf);
-+ obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */
-+ obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */
-+ obuf += PPP_HDRLEN;
-+
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ if (state->debug >= 7)
-+ printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
-+ state->ccount);
-+ obuf[0] = state->ccount >> 8;
-+ obuf[1] = state->ccount & 0xff;
-+
-+ if (!state->stateful || /* stateless mode */
-+ ((state->ccount & 0xff) == 0xff) || /* "flag" packet */
-+ (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */
-+ /* We must rekey */
-+ if (state->debug && state->stateful)
-+ printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", state->unit);
-+ mppe_rekey(state, 0);
-+ state->bits |= MPPE_BIT_FLUSHED;
-+ }
-+ obuf[0] |= state->bits;
-+ state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */
-+
-+ obuf += MPPE_OVHD;
-+ ibuf += 2; /* skip to proto field */
-+ isize -= 2;
-+
-+ /* Encrypt packet */
-+ arcfour_encrypt(&state->arcfour_context, ibuf, isize, obuf);
-+
-+ state->stats.unc_bytes += isize;
-+ state->stats.unc_packets++;
-+ state->stats.comp_bytes += osize;
-+ state->stats.comp_packets++;
-+
-+ return osize;
-+}
-+
-+/*
-+ * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going
-+ * to look bad ... and the longer the link is up the worse it will get.
-+ */
-+static void
-+mppe_comp_stats(void *arg, struct compstat *stats)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ *stats = state->stats;
-+}
-+
-+
-+static int
-+mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit,
-+ int hdrlen, int mru, int debug)
-+{
-+ /* ARGSUSED */
-+ return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init");
-+}
-+
-+/*
-+ * We received a CCP Reset-Ack. Just ignore it.
-+ */
-+static void
-+mppe_decomp_reset(void *arg)
-+{
-+ /* ARGSUSED */
-+ return;
-+}
-+
-+/*
-+ * Decompress (decrypt) an MPPE packet.
-+ */
-+int
-+mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
-+ int osize)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ unsigned ccount;
-+ int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
-+ int sanity = 0;
-+
-+ if (isize <= PPP_HDRLEN + MPPE_OVHD) {
-+ if (state->debug)
-+ printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n",
-+ state->unit, isize);
-+ return DECOMP_ERROR;
-+ }
-+
-+ /* Make sure we have enough room to decrypt the packet. */
-+ if (osize < isize - MPPE_OVHD - 2) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "
-+ "(have: %d need: %d)\n", state->unit,
-+ osize, isize - MPPE_OVHD - 2);
-+ return DECOMP_ERROR;
-+ }
-+ osize = isize - MPPE_OVHD - 2;
-+
-+ ccount = MPPE_CCOUNT(ibuf);
-+ if (state->debug >= 7)
-+ printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", state->unit,
-+ ccount);
-+
-+ /* sanity checks -- terminate with extreme prejudice */
-+ if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
-+ state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+ if (!state->stateful && !flushed) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
-+ "stateless mode!\n", state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+ if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
-+ "flag packet!\n", state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+
-+ if (sanity) {
-+ if (state->sanity_errors < SANITY_MAX)
-+ return DECOMP_ERROR;
-+ else
-+ /*
-+ * Take LCP down if the peer is sending too many bogons.
-+ * We don't want to do this for a single or just a few
-+ * instances since it could just be due to packet corruption.
-+ */
-+ return DECOMP_FATALERROR;
-+ }
-+
-+ /*
-+ * Check the coherency count.
-+ */
-+
-+ if (!state->stateful) {
-+ /* RFC 3078, sec 8.1. Rekey for every packet. */
-+ while (state->ccount != ccount) {
-+ mppe_rekey(state, 0);
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ }
-+ } else {
-+ /* RFC 3078, sec 8.2. */
-+ if (!state->discard) {
-+ /* normal state */
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ if (ccount != state->ccount) {
-+ /*
-+ * (ccount > state->ccount)
-+ * Packet loss detected, enter the discard state.
-+ * Signal the peer to rekey (by sending a CCP Reset-Request).
-+ */
-+ state->discard = 1;
-+ return DECOMP_ERROR;
-+ }
-+ } else {
-+ /* discard state */
-+ if (!flushed) {
-+ /* ccp.c will be silent (no additional CCP Reset-Requests). */
-+ return DECOMP_ERROR;
-+ } else {
-+ /* Rekey for every missed "flag" packet. */
-+ while ((ccount & ~0xff) != (state->ccount & ~0xff)) {
-+ mppe_rekey(state, 0);
-+ state->ccount = (state->ccount + 256) % MPPE_CCOUNT_SPACE;
-+ }
-+
-+ /* reset */
-+ state->discard = 0;
-+ state->ccount = ccount;
-+ /*
-+ * Another problem with RFC 3078 here. It implies that the
-+ * peer need not send a Reset-Ack packet. But RFC 1962
-+ * requires it. Hopefully, M$ does send a Reset-Ack; even
-+ * though it isn't required for MPPE synchronization, it is
-+ * required to reset CCP state.
-+ */
-+ }
-+ }
-+ if (flushed)
-+ mppe_rekey(state, 0);
-+ }
-+
-+ /*
-+ * Fill in the first part of the PPP header. The protocol field
-+ * comes from the decrypted data.
-+ */
-+ obuf[0] = PPP_ADDRESS(ibuf); /* +1 */
-+ obuf[1] = PPP_CONTROL(ibuf); /* +1 */
-+ obuf += 2;
-+ ibuf += PPP_HDRLEN + MPPE_OVHD;
-+ isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */
-+ /* net osize: isize-4 */
-+
-+ /* And finally, decrypt the packet. */
-+ arcfour_decrypt(&state->arcfour_context, ibuf, isize, obuf);
-+
-+ state->stats.unc_bytes += osize;
-+ state->stats.unc_packets++;
-+ state->stats.comp_bytes += isize;
-+ state->stats.comp_packets++;
-+
-+ /* good packet credit */
-+ state->sanity_errors >>= 1;
-+
-+ return osize;
-+}
-+
-+/*
-+ * Incompressible data has arrived (this should never happen!).
-+ * We should probably drop the link if the protocol is in the range
-+ * of what should be encrypted. At the least, we should drop this
-+ * packet. (How to do this?)
-+ */
-+static void
-+mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ if (state->debug &&
-+ (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))
-+ printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! "
-+ "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));
-+
-+ state->stats.inc_bytes += icnt;
-+ state->stats.inc_packets++;
-+ state->stats.unc_bytes += icnt;
-+ state->stats.unc_packets++;
-+}
-+
-+/*************************************************************
-+ * Module interface table
-+ *************************************************************/
-+
-+/* These are in ppp.c (2.2.x) or ppp_generic.c (2.4.x) */
-+extern int ppp_register_compressor (struct compressor *cp);
-+extern void ppp_unregister_compressor (struct compressor *cp);
-+
-+/*
-+ * Procedures exported to if_ppp.c.
-+ */
-+struct compressor ppp_mppe = {
-+ CI_MPPE, /* compress_proto */
-+ mppe_alloc, /* comp_alloc */
-+ mppe_free, /* comp_free */
-+ mppe_comp_init, /* comp_init */
-+ mppe_comp_reset, /* comp_reset */
-+ mppe_compress, /* compress */
-+ mppe_comp_stats, /* comp_stat */
-+ mppe_alloc, /* decomp_alloc */
-+ mppe_free, /* decomp_free */
-+ mppe_decomp_init, /* decomp_init */
-+ mppe_decomp_reset, /* decomp_reset */
-+ mppe_decompress, /* decompress */
-+ mppe_incomp, /* incomp */
-+ mppe_comp_stats, /* decomp_stat */
-+};
-+
-+/* 2.2 compatibility defines */
-+#ifndef __init
-+#define __init
-+#endif
-+#ifndef __exit
-+#define __exit
-+#endif
-+#ifndef MODULE_LICENSE
-+#define MODULE_LICENSE(license)
-+#endif
-+
-+int __init
-+ppp_mppe_init(void)
-+{
-+ int answer = ppp_register_compressor(&ppp_mppe);
-+
-+ if (answer == 0)
-+ printk(KERN_INFO "PPP MPPE Compression module registered\n");
-+ return answer;
-+}
-+
-+void __exit
-+ppp_mppe_cleanup(void)
-+{
-+ ppp_unregister_compressor(&ppp_mppe);
-+}
-+
-+module_init(ppp_mppe_init);
-+module_exit(ppp_mppe_cleanup);
-+MODULE_LICENSE("BSD without advertisement clause");
---- /dev/null
-+++ linux-2.4.25/drivers/net/sha1.c
-@@ -0,0 +1,185 @@
-+/*
-+ * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
-+ *
-+ * SHA-1 in C
-+ * By Steve Reid <steve@edmweb.com>
-+ * 100% Public Domain
-+ *
-+ * Test Vectors (from FIPS PUB 180-1)
-+ * "abc"
-+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-+ * A million repetitions of "a"
-+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-+ */
-+
-+/* #define SHA1HANDSOFF * Copies data before messing with it. */
-+
-+#if defined(__linux__)
-+#include <asm/byteorder.h>
-+#include <linux/string.h>
-+#elif defined(__solaris__)
-+#include <sys/isa_defs.h>
-+#include <sys/ddi.h>
-+#include <sys/sunddi.h>
-+#define memcpy(d, s, c) bcopy(s, d, c)
-+#define memset(d, b, c) bzero(d, c)
-+#endif
-+
-+#include "sha1.h"
-+
-+static void SHA1_Transform(unsigned long[5], const unsigned char[64]);
-+
-+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-+
-+/* blk0() and blk() perform the initial expand. */
-+/* I got the idea of expanding during the round function from SSLeay */
-+#if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)
-+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-+ |(rol(block->l[i],8)&0x00FF00FF))
-+#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)
-+#define blk0(i) block->l[i]
-+#else
-+#error Endianness not defined
-+#endif
-+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-+ ^block->l[(i+2)&15]^block->l[i&15],1))
-+
-+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-+
-+
-+/* Hash a single 512-bit block. This is the core of the algorithm. */
-+
-+static void
-+SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
-+{
-+ unsigned long a, b, c, d, e;
-+ typedef union {
-+ unsigned char c[64];
-+ unsigned long l[16];
-+ } CHAR64LONG16;
-+ CHAR64LONG16 *block;
-+
-+#ifdef SHA1HANDSOFF
-+ static unsigned char workspace[64];
-+ block = (CHAR64LONG16 *) workspace;
-+ memcpy(block, buffer, 64);
-+#else
-+ block = (CHAR64LONG16 *) buffer;
-+#endif
-+ /* Copy context->state[] to working vars */
-+ a = state[0];
-+ b = state[1];
-+ c = state[2];
-+ d = state[3];
-+ e = state[4];
-+ /* 4 rounds of 20 operations each. Loop unrolled. */
-+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-+ /* Add the working vars back into context.state[] */
-+ state[0] += a;
-+ state[1] += b;
-+ state[2] += c;
-+ state[3] += d;
-+ state[4] += e;
-+ /* Wipe variables */
-+ a = b = c = d = e = 0;
-+}
-+
-+
-+/* SHA1Init - Initialize new context */
-+
-+void
-+SHA1_Init(SHA1_CTX *context)
-+{
-+ /* SHA1 initialization constants */
-+ context->state[0] = 0x67452301;
-+ context->state[1] = 0xEFCDAB89;
-+ context->state[2] = 0x98BADCFE;
-+ context->state[3] = 0x10325476;
-+ context->state[4] = 0xC3D2E1F0;
-+ context->count[0] = context->count[1] = 0;
-+}
-+
-+
-+/* Run your data through this. */
-+
-+void
-+SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
-+{
-+ unsigned int i, j;
-+
-+ j = (context->count[0] >> 3) & 63;
-+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-+ context->count[1] += (len >> 29);
-+ if ((j + len) > 63) {
-+ memcpy(&context->buffer[j], data, (i = 64-j));
-+ SHA1_Transform(context->state, context->buffer);
-+ for ( ; i + 63 < len; i += 64) {
-+ SHA1_Transform(context->state, &data[i]);
-+ }
-+ j = 0;
-+ }
-+ else
-+ i = 0;
-+
-+ memcpy(&context->buffer[j], &data[i], len - i);
-+}
-+
-+
-+/* Add padding and return the message digest. */
-+
-+void
-+SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
-+{
-+ unsigned long i, j;
-+ unsigned char finalcount[8];
-+
-+ for (i = 0; i < 8; i++) {
-+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
-+ }
-+ SHA1_Update(context, (unsigned char *) "\200", 1);
-+ while ((context->count[0] & 504) != 448) {
-+ SHA1_Update(context, (unsigned char *) "\0", 1);
-+ }
-+ SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
-+ for (i = 0; i < 20; i++) {
-+ digest[i] = (unsigned char)
-+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-+ }
-+ /* Wipe variables */
-+ i = j = 0;
-+ memset(context->buffer, 0, 64);
-+ memset(context->state, 0, 20);
-+ memset(context->count, 0, 8);
-+ memset(&finalcount, 0, 8);
-+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
-+ SHA1Transform(context->state, context->buffer);
-+#endif
-+}
-+
---- /dev/null
-+++ linux-2.4.25/drivers/net/sha1.h
-@@ -0,0 +1,18 @@
-+/* sha1.h */
-+
-+#ifndef _SHA1_H
-+#define _SHA1_H
-+
-+typedef struct {
-+ unsigned long state[5];
-+ unsigned long count[2];
-+ unsigned char buffer[64];
-+} SHA1_CTX;
-+
-+#define SHA1_SIGNATURE_SIZE 20
-+
-+extern void SHA1_Init(SHA1_CTX *);
-+extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
-+extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *);
-+
-+#endif /* _SHA1_H */
---- linux-2.4.25/include/linux/ppp-comp.h~mppe-20040216
-+++ linux-2.4.25/include/linux/ppp-comp.h
-@@ -187,6 +187,100 @@
- #define DEFLATE_CHK_SEQUENCE 0
-
- /*
-+ * Definitions for MPPE.
-+ */
-+
-+#define CI_MPPE 18 /* config option for MPPE */
-+#define CILEN_MPPE 6 /* length of config option */
-+
-+#define MPPE_PAD 4 /* MPPE growth per frame */
-+#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */
-+
-+/* option bits for ccp_options.mppe */
-+#define MPPE_OPT_40 0x01 /* 40 bit */
-+#define MPPE_OPT_128 0x02 /* 128 bit */
-+#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */
-+/* unsupported opts */
-+#define MPPE_OPT_56 0x08 /* 56 bit */
-+#define MPPE_OPT_MPPC 0x10 /* MPPC compression */
-+#define MPPE_OPT_D 0x20 /* Unknown */
-+#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
-+#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */
-+
-+/*
-+ * This is not nice ... the alternative is a bitfield struct though.
-+ * And unfortunately, we cannot share the same bits for the option
-+ * names above since C and H are the same bit. We could do a u_int32
-+ * but then we have to do a htonl() all the time and/or we still need
-+ * to know which octet is which.
-+ */
-+#define MPPE_C_BIT 0x01 /* MPPC */
-+#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */
-+#define MPPE_L_BIT 0x20 /* 40-bit */
-+#define MPPE_S_BIT 0x40 /* 128-bit */
-+#define MPPE_M_BIT 0x80 /* 56-bit, not supported */
-+#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */
-+
-+/* Does not include H bit; used for least significant octet only. */
-+#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
-+
-+/* Build a CI from mppe opts (see RFC 3078) */
-+#define MPPE_OPTS_TO_CI(opts, ci) \
-+ do { \
-+ u_char *ptr = ci; /* u_char[4] */ \
-+ \
-+ /* H bit */ \
-+ if (opts & MPPE_OPT_STATEFUL) \
-+ *ptr++ = 0x0; \
-+ else \
-+ *ptr++ = MPPE_H_BIT; \
-+ *ptr++ = 0; \
-+ *ptr++ = 0; \
-+ \
-+ /* S,L bits */ \
-+ *ptr = 0; \
-+ if (opts & MPPE_OPT_128) \
-+ *ptr |= MPPE_S_BIT; \
-+ if (opts & MPPE_OPT_40) \
-+ *ptr |= MPPE_L_BIT; \
-+ /* M,D,C bits not supported */ \
-+ } while (/* CONSTCOND */ 0)
-+
-+/* The reverse of the above */
-+#define MPPE_CI_TO_OPTS(ci, opts) \
-+ do { \
-+ u_char *ptr = ci; /* u_char[4] */ \
-+ \
-+ opts = 0; \
-+ \
-+ /* H bit */ \
-+ if (!(ptr[0] & MPPE_H_BIT)) \
-+ opts |= MPPE_OPT_STATEFUL; \
-+ \
-+ /* S,L bits */ \
-+ if (ptr[3] & MPPE_S_BIT) \
-+ opts |= MPPE_OPT_128; \
-+ if (ptr[3] & MPPE_L_BIT) \
-+ opts |= MPPE_OPT_40; \
-+ \
-+ /* M,D,C bits */ \
-+ if (ptr[3] & MPPE_M_BIT) \
-+ opts |= MPPE_OPT_56; \
-+ if (ptr[3] & MPPE_D_BIT) \
-+ opts |= MPPE_OPT_D; \
-+ if (ptr[3] & MPPE_C_BIT) \
-+ opts |= MPPE_OPT_MPPC; \
-+ \
-+ /* Other bits */ \
-+ if (ptr[0] & ~MPPE_H_BIT) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ if (ptr[1] || ptr[2]) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ if (ptr[3] & ~MPPE_ALL_BITS) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ } while (/* CONSTCOND */ 0)
-+
-+/*
- * Definitions for other, as yet unsupported, compression methods.
- */
-
---- linux-2.4.25/drivers/net/Makefile~mppe-20040216
-+++ linux-2.4.25/drivers/net/Makefile
-@@ -18,8 +18,9 @@
- export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \
- ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
- net_init.o mii.o
--list-multi := rcpci.o
-+list-multi := rcpci.o ppp_mppe.o
- rcpci-objs := rcpci45.o rclanmtl.o
-+ppp_mppe-objs := ppp_mppe_compress.o sha1.o arcfour.o
-
- ifeq ($(CONFIG_TULIP),y)
- obj-y += tulip/tulip.o
-@@ -163,6 +164,14 @@
- obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
- obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
-
-+ifeq ($(CONFIG_PPP_MPPE),y)
-+ obj-y += $(ppp_mppe-objs)
-+else
-+ ifeq ($(CONFIG_PPP_MPPE),m)
-+ obj-m += ppp_mppe.o
-+ endif
-+endif
-+
- obj-$(CONFIG_SLIP) += slip.o
- ifeq ($(CONFIG_SLIP_COMPRESSED),y)
- obj-$(CONFIG_SLIP) += slhc.o
-@@ -269,3 +278,7 @@
-
- rcpci.o: $(rcpci-objs)
- $(LD) -r -o $@ $(rcpci-objs)
-+
-+ppp_mppe.o: $(ppp_mppe-objs)
-+ $(LD) -r -o $@ $(ppp_mppe-objs)
-+
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/scrolling-area.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/scrolling-area.patch
deleted file mode 100644
index c4f7758b3c..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/scrolling-area.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#
-# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher
-#
-
---- linux-2.4.25/drivers/video/fbcon.c~scrolling-area.patch 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.25/drivers/video/fbcon.c 2004-03-31 17:15:13.000000000 +0200
-@@ -110,8 +110,8 @@
- # define DPRINTK(fmt, args...)
- #endif
-
--#define LOGO_H 80
--#define LOGO_W 80
-+#define LOGO_H 400
-+#define LOGO_W 800
- #define LOGO_LINE (LOGO_W/8)
-
- struct display fb_display[MAX_NR_CONSOLES];
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff
deleted file mode 100644
index 8b66c04276..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-apm.diff
+++ /dev/null
@@ -1,801 +0,0 @@
---- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/arch/arm/mach-sa1100/pm-common.c 1970-01-01 01:00:00.000000000 +0100
-+++ arch/arm/mach-sa1100/pm-common.c 2004-07-04 14:56:34.000000000 +0200
-@@ -0,0 +1,268 @@
-+/*
-+ * SA1100 Power Management Routines
-+ *
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-02-06: Cliff Brake Initial code
-+ *
-+ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
-+ * Chester Kuo <chester@linux.org.tw>
-+ * Save more value for the resume function! Support
-+ * Bitsy/Assabet/Freebird board
-+ *
-+ * 2001-08-29: Nicolas Pitre <nico@cam.org>
-+ * Cleaned up, pushed platform dependent stuff
-+ * in the platform specific files.
-+ *
-+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
-+ * Storage is local on the stack now.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+#include <asm/uaccess.h>
-+
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch-sa1100/h3600_asic.h>
-+#endif
-+
-+#define __KERNEL_SYSCALLS__
-+#include <linux/unistd.h>
-+
-+/*
-+ * Debug macros
-+ */
-+#undef DEBUG
-+
-+
-+
-+static char pm_helper_path[128] = "/sbin/pm_helper";
-+extern int exec_usermodehelper(char *path, char **argv, char **envp);
-+int debug_pm = 0;
-+static int pm_helper_veto = 0;
-+
-+static int
-+run_sbin_pm_helper( pm_request_t action )
-+{
-+ int i;
-+ char *argv[3], *envp[8];
-+
-+ if (!pm_helper_path[0])
-+ return 2;
-+
-+ if ( action != PM_SUSPEND && action != PM_RESUME )
-+ return 1;
-+
-+ /* Be root */
-+ current->uid = current->gid = 0;
-+
-+ i = 0;
-+ argv[i++] = pm_helper_path;
-+ argv[i++] = (action == PM_RESUME ? "resume" : "suspend");
-+ argv[i] = 0;
-+
-+ i = 0;
-+ /* minimal command environment */
-+ envp[i++] = "HOME=/";
-+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+ envp[i] = 0;
-+
-+ /* other stuff we want to pass to /sbin/pm_helper */
-+ return exec_usermodehelper (argv [0], argv, envp);
-+}
-+
-+/*
-+ * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend.
-+ */
-+int (*pm_suggest_suspend_hook)(int state);
-+EXPORT_SYMBOL(pm_suggest_suspend_hook);
-+
-+/*
-+ * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume
-+ */
-+int pm_use_sbin_pm_helper = 1;
-+EXPORT_SYMBOL(pm_use_sbin_pm_helper);
-+
-+/*
-+ * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend.
-+ * If it returns a true value, then pm_suspend is not called.
-+ * Use this to hook in apmd, for now.
-+ */
-+int (*pm_sysctl_suspend_hook)(int state);
-+EXPORT_SYMBOL(pm_sysctl_suspend_hook);
-+
-+int pm_suspend(void);
-+
-+int pm_suggest_suspend(void)
-+{
-+ int retval;
-+
-+ if (pm_suggest_suspend_hook) {
-+ if (pm_suggest_suspend_hook(PM_SUSPEND))
-+ return 0;
-+ }
-+
-+ if (pm_use_sbin_pm_helper) {
-+ pid_t pid;
-+ int res;
-+ int status = 0;
-+ unsigned int old_fs;
-+
-+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 );
-+ if ( pid < 0 )
-+ return pid;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid);
-+
-+ old_fs = get_fs ();
-+ set_fs (get_ds ());
-+ res = waitpid(pid, &status, __WCLONE);
-+ set_fs (old_fs);
-+
-+ if ( pid != res ) {
-+ if (debug_pm)
-+ printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status );
-+
-+ return -1;
-+ }
-+
-+ /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/
-+ if (( status & 0xff7f ) != 0 ) {
-+ if (pm_helper_veto) {
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8);
-+ return -1;
-+ } else {
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8);
-+ }
-+ }
-+ }
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ );
-+
-+ if (pm_sysctl_suspend_hook) {
-+ if (pm_sysctl_suspend_hook(PM_SUSPEND))
-+ return 0;
-+ }
-+
-+ retval = pm_suspend();
-+ if (retval) {
-+ if (debug_pm)
-+ printk(KERN_CRIT "pm_suspend returned %d\n", retval);
-+ return retval;
-+ }
-+
-+ if (pm_use_sbin_pm_helper) {
-+ pid_t pid;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__);
-+
-+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 );
-+ if ( pid < 0 )
-+ return pid;
-+
-+ if ( pid != waitpid ( pid, NULL, __WCLONE ))
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(pm_suggest_suspend);
-+
-+
-+/*
-+ * Send us to sleep.
-+ */
-+int pm_suspend(void)
-+{
-+ int retval;
-+
-+ retval = pm_send_all(PM_SUSPEND, (void *)3);
-+ if ( retval )
-+ return retval;
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ retval = h3600_power_management(PM_SUSPEND);
-+ if (retval) {
-+ pm_send_all(PM_RESUME, (void *)0);
-+ return retval;
-+ }
-+#endif
-+
-+ retval = pm_do_suspend();
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ /* Allow the power management routines to override resuming */
-+ while ( h3600_power_management(PM_RESUME) )
-+ retval = pm_do_suspend();
-+#endif
-+
-+ pm_send_all(PM_RESUME, (void *)0);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(pm_suspend);
-+
-+#ifdef CONFIG_SYSCTL
-+/*
-+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
-+ * linux/sysctl.h.
-+ *
-+ * This means our interface here won't survive long - it needs a new
-+ * interface. Quick hack to get this working - use sysctl id 9999.
-+ */
-+#warning ACPI broke the kernel, this interface needs to be fixed up.
-+#define CTL_ACPI 9999
-+#define ACPI_S1_SLP_TYP 19
-+
-+static struct ctl_table pm_table[] =
-+{
-+/* {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_suspend},*/
-+ {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring},
-+ {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec},
-+ {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec},
-+ {0}
-+};
-+
-+static struct ctl_table pm_dir_table[] =
-+{
-+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-+ {0}
-+};
-+
-+/*
-+ * Initialize power interface
-+ */
-+static int __init pm_init(void)
-+{
-+ register_sysctl_table(pm_dir_table, 1);
-+ return 0;
-+}
-+
-+__initcall(pm_init);
-+
-+#endif
-+
---- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/arch/arm/mach-sa1100/apm.c 2004-07-01 21:10:30.000000000 +0200
-+++ arch/arm/mach-sa1100/apm.c 2004-07-04 14:53:38.000000000 +0200
-@@ -32,9 +32,7 @@
-
- #include <asm/system.h>
- #include <asm/hardware.h>
--#if FIXME
- #include <asm/arch-sa1100/pm.h>
--#endif
-
- #ifdef CONFIG_IPAQ_HANDHELD
- #include <asm/arch-sa1100/h3600_hal.h>
-@@ -92,6 +91,8 @@
- int magic;
- struct apm_user * next;
- int suser: 1;
-+ int writer: 1;
-+ int reader: 1;
- int suspend_wait: 1;
- int suspend_result;
- int suspends_pending;
-@@ -111,7 +112,7 @@
- /*
- * Local variables
- */
--//static int suspends_pending;
-+static int suspends_pending;
- //static int standbys_pending;
- //static int ignore_normal_resume;
-
-@@ -129,8 +130,6 @@
- #else
- static int power_off = 1;
- #endif
--static int exit_kapmd;
--static int kapmd_running;
-
- static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
- static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-@@ -190,6 +189,42 @@
- return as->events[as->event_tail];
- }
-
-+static void queue_event(apm_event_t event, struct apm_user *sender)
-+{
-+ struct apm_user * as;
-+
-+ if (user_list == NULL)
-+ return;
-+ for (as = user_list; as != NULL; as = as->next) {
-+ if ((as == sender) || (!as->reader))
-+ continue;
-+ as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-+ if (as->event_head == as->event_tail) {
-+ static int notified;
-+
-+ if (notified++ == 0)
-+ printk(KERN_ERR "apm: an event queue overflowed\n");
-+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-+ }
-+ as->events[as->event_head] = event;
-+ if ((!as->suser) || (!as->writer))
-+ continue;
-+ switch (event) {
-+ case APM_SYS_SUSPEND:
-+ case APM_USER_SUSPEND:
-+ as->suspends_pending++;
-+ suspends_pending++;
-+ break;
-+
-+ case APM_SYS_STANDBY:
-+ case APM_USER_STANDBY:
-+ as->standbys_pending++;
-+ break;
-+ }
-+ }
-+ wake_up_interruptible(&apm_waitqueue);
-+}
-+
- static int check_apm_user(struct apm_user *as, const char *func)
- {
- if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-@@ -228,7 +263,6 @@
- i = count;
- while ((i >= sizeof(event)) && !queue_empty(as)) {
- event = get_queued_event(as);
-- printk(" do_read: event=%d\n", event);
- if (copy_to_user(buf, &event, sizeof(event))) {
- if (i < count)
- break;
-@@ -280,9 +314,17 @@
- return -EPERM;
- switch (cmd) {
- case APM_IOC_SUSPEND:
--#if FIXME
-- pm_suggest_suspend();
--#endif
-+ if (as->suspends_read > 0) {
-+ as->suspends_read--;
-+ as->suspends_pending--;
-+ suspends_pending--;
-+ } else {
-+ queue_event(APM_USER_SUSPEND, as);
-+ }
-+
-+ if (suspends_pending <= 0)
-+ wake_up(&apm_suspend_waitqueue);
-+
- break;
- default:
- return -EINVAL;
-@@ -299,6 +341,20 @@
- return 0;
- filp->private_data = NULL;
- lock_kernel();
-+ if (user_list == as)
-+ user_list = as->next;
-+ else {
-+ struct apm_user * as1;
-+
-+ for (as1 = user_list;
-+ (as1 != NULL) && (as1->next != as);
-+ as1 = as1->next)
-+ ;
-+ if (as1 == NULL)
-+ printk(KERN_ERR "apm: filp not in user list\n");
-+ else
-+ as1->next = as->next;
-+ }
- unlock_kernel();
- kfree(as);
- return 0;
-@@ -326,6 +382,8 @@
- * privileged operation -- cevans
- */
- as->suser = capable(CAP_SYS_ADMIN);
-+ as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-+ as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
- as->next = user_list;
- user_list = as;
- filp->private_data = as;
-@@ -409,34 +467,6 @@
- return p - buf;
- }
-
--#ifndef MODULE
--static int __init apm_setup(char *str)
--{
-- int invert;
--
-- while ((str != NULL) && (*str != '\0')) {
-- if (strncmp(str, "off", 3) == 0)
-- apm_disabled = 1;
-- if (strncmp(str, "on", 2) == 0)
-- apm_disabled = 0;
-- invert = (strncmp(str, "no-", 3) == 0);
-- if (invert)
-- str += 3;
-- if (strncmp(str, "debug", 5) == 0)
-- debug = !invert;
-- if ((strncmp(str, "power-off", 9) == 0) ||
-- (strncmp(str, "power_off", 9) == 0))
-- power_off = !invert;
-- str = strchr(str, ',');
-- if (str != NULL)
-- str += strspn(str, ", \t");
-- }
-- return 1;
--}
--
--__setup("apm=", apm_setup);
--#endif
--
- static struct file_operations apm_bios_fops = {
- owner: THIS_MODULE,
- read: do_read,
-@@ -454,6 +484,50 @@
-
- #define APM_INIT_ERROR_RETURN return -1
-
-+static pid_t apmd_pid;
-+static DECLARE_COMPLETION(apmd_exited);
-+
-+static int apm(void *unused)
-+{
-+ unsigned short bx;
-+ unsigned short cx;
-+ unsigned short dx;
-+ int error;
-+ char * power_stat;
-+ char * bat_stat;
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct apm_user au, *as;
-+
-+ lock_kernel();
-+
-+ daemonize();
-+
-+ strcpy(current->comm, "kapmd");
-+
-+ as = &au;
-+ as->magic = APM_BIOS_MAGIC;
-+ as->event_tail = as->event_head = 0;
-+ as->suspends_pending = as->standbys_pending = 0;
-+ as->suspends_read = as->standbys_read = 0;
-+ as->suser = 1;
-+ as->writer = 1;
-+ as->reader = 0;
-+
-+ for (;;) {
-+ interruptible_sleep_on(&apm_suspend_waitqueue);
-+ if (signal_pending (current))
-+ break;
-+
-+ pm_suggest_suspend();
-+
-+ queue_event(APM_NORMAL_RESUME, as);
-+ }
-+
-+ unlock_kernel();
-+
-+ complete_and_exit(&apmd_exited, 0);
-+}
-+
- /*
- * Just start the APM thread. We do NOT want to do APM BIOS
- * calls from anything but the APM thread, if for no other reason
-@@ -492,6 +564,8 @@
-
- misc_register(&apm_device);
-
-+ apmd_pid = kernel_thread(apm, NULL, 0);
-+
- return 0;
- }
-
-@@ -499,11 +573,10 @@
- {
- misc_deregister(&apm_device);
- remove_proc_entry("apm", NULL);
-+ kill_proc (apmd_pid, SIGTERM, 1);
-+ wait_for_completion(&apmd_exited);
- if (power_off)
- pm_power_off = NULL;
-- exit_kapmd = 1;
-- while (kapmd_running)
-- schedule();
- pm_active = 0;
- }
-
-@@ -512,6 +585,7 @@
-
- MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
- MODULE_DESCRIPTION("A minimal emulation of APM");
-+MODULE_LICENSE("GPL");
- MODULE_PARM(debug, "i");
- MODULE_PARM_DESC(debug, "Enable debug mode");
- MODULE_PARM(power_off, "i");
-diff -bBaruN /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/include/asm-arm/arch-sa1100/pm.h include/asm-arm/arch/pm.h
---- /mnt/bdisk/openembedded/oetmp/base/opensimpad-2.4.25-vrs2-pxa1-jpm1-r5/linux-2.4.25/include/asm-arm/arch-sa1100/pm.h 1970-01-01 01:00:00.000000000 +0100
-+++ include/asm-arm/arch-sa1100/pm.h 2004-07-04 16:47:18.000000000 +0200
-@@ -0,0 +1,20 @@
-+/*
-+ *
-+ * Declarations for ARM Linux Power Management
-+ *
-+ * Copyright 2002 Compaq Computer Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Author: Jamey Hicks.
-+ *
-+ */
-+
-+
-+extern int (*pm_suggest_suspend_hook)(int state);
-+extern int (*pm_sysctl_suspend_hook)(int state);
-+extern int pm_use_sbin_pm_helper;
-+extern int pm_suspend(void);
-+extern int pm_suggest_suspend(void); /* triggers /sbin/pm_helper or queueing event to apmd */
---- /mnt/bdisk/openembedded/oetmp/work/opensimpad-64+0-2.4.25-vrs2-pxa1-jpm1-r6/linux-2.4.25/arch/arm/mach-sa1100/Makefile 2004-07-04 19:39:48.000000000 +0200
-+++ arch/arm/mach-sa1100/Makefile 2004-07-04 17:11:35.000000000 +0200
-@@ -19,7 +19,7 @@
- flexanet.o freebird.o frodo.o generic.o h3600.o \
- huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \
- system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \
-- simpad.o
-+ simpad.o pm-sa1100.o
-
- # These aren't present yet, and prevents a plain -ac kernel building.
- # hwtimer.o
-@@ -105,7 +105,7 @@
- obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
-
- # Miscelaneous functions
--obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_PM) += pm-sa1100.o sleep.o
- obj-$(CONFIG_APM) += apm.o
-
- # SIMpad specific
---- /mnt/bdisk/openembedded/oetmp/work/opensimpad-64+0-2.4.25-vrs2-pxa1-jpm1-r6/linux-2.4.25/arch/arm/mach-sa1100/pm-sa1100.c 1970-01-01 01:00:00.000000000 +0100
-+++ arch/arm/mach-sa1100/pm-sa1100.c 2004-07-04 17:11:11.000000000 +0200
-@@ -0,0 +1,225 @@
-+/*
-+ * SA1100 Power Management Routines
-+ *
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-02-06: Cliff Brake Initial code
-+ *
-+ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
-+ * Chester Kuo <chester@linux.org.tw>
-+ * Save more value for the resume function! Support
-+ * Bitsy/Assabet/Freebird board
-+ *
-+ * 2001-08-29: Nicolas Pitre <nico@cam.org>
-+ * Cleaned up, pushed platform dependent stuff
-+ * in the platform specific files.
-+ *
-+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
-+ * Storage is local on the stack now.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch/h3600_asic.h>
-+#endif
-+
-+#define __KERNEL_SYSCALLS__
-+#include <linux/unistd.h>
-+
-+extern void sa1100_cpu_suspend(void);
-+extern void sa1100_cpu_resume(void);
-+extern int debug_pm;
-+
-+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
-+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-+
-+/*
-+ * List of global SA11x0 peripheral registers to preserve.
-+ * More ones like CP and general purpose register values are preserved
-+ * with the stack location in sleep.S.
-+ */
-+enum { SLEEP_SAVE_START = 0,
-+
-+ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
-+ SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
-+
-+ SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
-+ SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
-+
-+ SLEEP_SAVE_ICMR,
-+#ifdef CONFIG_SA1100_SIMPAD
-+ SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
-+#endif
-+ SLEEP_SAVE_Ser1SDCR0,
-+
-+ SLEEP_SAVE_PWER,
-+ SLEEP_SAVE_MSC1, SLEEP_SAVE_MSC2,
-+
-+ SLEEP_SAVE_SIZE
-+};
-+
-+
-+int pm_do_suspend(void)
-+{
-+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+
-+ cli();
-+
-+ leds_event(led_stop);
-+
-+ /* preserve current time */
-+ RCNR = xtime.tv_sec;
-+
-+ /* save vital registers */
-+ SAVE(OSCR);
-+ SAVE(OSMR0);
-+ SAVE(OSMR1);
-+ SAVE(OSMR2);
-+ SAVE(OSMR3);
-+ SAVE(OIER);
-+
-+ SAVE(GPDR);
-+ SAVE(GRER);
-+ SAVE(GFER);
-+ SAVE(GAFR);
-+
-+ SAVE(PPDR);
-+ SAVE(PPSR);
-+ SAVE(PPAR);
-+ SAVE(PSDR);
-+
-+ SAVE(Ser1SDCR0);
-+
-+ SAVE(ICMR);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ SAVE(MECR);
-+#endif
-+ SAVE(PWER);
-+ SAVE(MSC1);
-+ SAVE(MSC2);
-+
-+ /* ... maybe a global variable initialized by arch code to set this? */
-+ GRER &= PWER;
-+ GFER &= PWER;
-+ // Ugly, but I need the AC inserted event
-+ // In the future, we're going to care about DCD and USB interrupts as well
-+ if ( machine_is_h3800()) {
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ GFER = GPIO_H3800_AC_IN;
-+#endif
-+ } else {
-+ GFER = 0;
-+ if (machine_is_jornada56x()) {
-+ /* jca */
-+ GFER = PWER;
-+ ICMR |= PWER;
-+ }
-+ }
-+ GEDR = GEDR;
-+
-+ /* Clear previous reset status */
-+ RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
-+
-+ /* set resume return address */
-+ PSPR = virt_to_phys(sa1100_cpu_resume);
-+
-+ /* go zzz */
-+ sa1100_cpu_suspend();
-+
-+ /* ensure not to come back here if it wasn't intended */
-+ PSPR = 0;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "*** made it back from resume\n");
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ if ( machine_is_ipaq()) {
-+ ipaq_model_ops.gedr = GEDR;
-+ ipaq_model_ops.icpr = ICPR;
-+ }
-+#endif
-+
-+ /* restore registers */
-+ RESTORE(GPDR);
-+ RESTORE(GRER);
-+ RESTORE(GFER);
-+ RESTORE(GAFR);
-+
-+ /* clear any edge detect bit */
-+ GEDR = GEDR;
-+
-+ RESTORE(PPDR);
-+ RESTORE(PPSR);
-+ RESTORE(PPAR);
-+ RESTORE(PSDR);
-+
-+ RESTORE(Ser1SDCR0);
-+
-+ PSSR = PSSR_PH;
-+
-+ RESTORE(OSMR0);
-+ RESTORE(OSMR1);
-+ RESTORE(OSMR2);
-+ RESTORE(OSMR3);
-+ RESTORE(OSCR);
-+ RESTORE(OIER);
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+/* OSMR0 may have fired before we went to sleep, but after interrupts
-+ were shut off. Set OSMR0 to something plausible */
-+ OSMR0 = OSCR + LATCH;
-+#endif
-+ ICLR = 0;
-+ ICCR = 1;
-+ RESTORE(ICMR);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ RESTORE(MECR);
-+#endif
-+ RESTORE(PWER);
-+ RESTORE(MSC1);
-+ RESTORE(MSC2);
-+ /* restore current time */
-+ xtime.tv_sec = RCNR;
-+
-+ leds_event(led_start);
-+
-+ sti();
-+
-+ if (debug_pm)
-+ printk("interrupts are enabled\n");
-+
-+ /*
-+ * Restore the CPU frequency settings.
-+ */
-+#ifdef CONFIG_CPU_FREQ
-+ cpufreq_restore();
-+#endif
-+ return 0;
-+}
-+
-+unsigned long sleep_phys_sp(void *sp)
-+{
-+ return virt_to_phys(sp);
-+}
-+
-+#include "pm-common.c"
diff --git a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-pm-updates.patch b/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-pm-updates.patch
deleted file mode 100644
index 938c34c67a..0000000000
--- a/recipes/linux/opensimpad-2.4.25-vrs2-pxa1-jpm1/simpad-pm-updates.patch
+++ /dev/null
@@ -1,47 +0,0 @@
---- arch/arm/mach-sa1100/pm-sa1100.c 2004-07-14 01:21:38.000000000 +0200
-+++ /home/fuchs/Projekte/simpad/kernel/linux-2.4.25/arch/arm/mach-sa1100/pm-sa1100.c 2004-07-22 00:41:57.000000000 +0200
-@@ -69,6 +69,7 @@
- SLEEP_SAVE_ICMR,
- #ifdef CONFIG_SA1100_SIMPAD
- SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
-+ SLEEP_SAVE_Ser4MCCR0, SLEEP_SAVE_Ser4MCSR, SLEEP_SAVE_Ser4MCCR1, /* touchscreen */
- #endif
- SLEEP_SAVE_Ser1SDCR0,
-
-@@ -82,7 +83,7 @@
- int pm_do_suspend(void)
- {
- unsigned long sleep_save[SLEEP_SAVE_SIZE];
--
-+
- cli();
-
- leds_event(led_stop);
-@@ -113,10 +114,13 @@
- SAVE(ICMR);
- #ifdef CONFIG_SA1100_SIMPAD
- SAVE(MECR);
--#endif
-- SAVE(PWER);
-- SAVE(MSC1);
-- SAVE(MSC2);
-+ SAVE(Ser4MCCR0);
-+ SAVE(Ser4MCSR);
-+ SAVE(Ser4MCCR1);
-+#endif
-+ SAVE(PWER);
-+ SAVE(MSC1);
-+ SAVE(MSC2);
-
- /* ... maybe a global variable initialized by arch code to set this? */
- GRER &= PWER;
-@@ -194,6 +198,9 @@
- RESTORE(ICMR);
- #ifdef CONFIG_SA1100_SIMPAD
- RESTORE(MECR);
-+ RESTORE(Ser4MCCR0);
-+ RESTORE(Ser4MCSR);
-+ RESTORE(Ser4MCCR1);
- #endif
- RESTORE(PWER);
- RESTORE(MSC1);
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-mh1.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-mh1.patch
deleted file mode 100644
index f5379f0077..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-mh1.patch
+++ /dev/null
@@ -1,1134 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/arch/sparc64/kernel/ioctl32.c~patch-2.4.27-mh1
-+++ linux-2.4.27/arch/sparc64/kernel/ioctl32.c
-@@ -4322,6 +4322,11 @@
- #define CMTPGETCONNLIST _IOR('C', 210, int)
- #define CMTPGETCONNINFO _IOR('C', 211, int)
-
-+#define HIDPCONNADD _IOW('H', 200, int)
-+#define HIDPCONNDEL _IOW('H', 201, int)
-+#define HIDPGETCONNLIST _IOR('H', 210, int)
-+#define HIDPGETCONNINFO _IOR('H', 211, int)
-+
- struct ioctl_trans {
- unsigned int cmd;
- unsigned int handler;
-@@ -5050,6 +5055,10 @@
- COMPATIBLE_IOCTL(CMTPCONNDEL)
- COMPATIBLE_IOCTL(CMTPGETCONNLIST)
- COMPATIBLE_IOCTL(CMTPGETCONNINFO)
-+COMPATIBLE_IOCTL(HIDPCONNADD)
-+COMPATIBLE_IOCTL(HIDPCONNDEL)
-+COMPATIBLE_IOCTL(HIDPGETCONNLIST)
-+COMPATIBLE_IOCTL(HIDPGETCONNINFO)
- /* Scanner */
- COMPATIBLE_IOCTL(SCANNER_IOCTL_VENDOR)
- COMPATIBLE_IOCTL(SCANNER_IOCTL_PRODUCT)
---- linux-2.4.27/CREDITS~patch-2.4.27-mh1
-+++ linux-2.4.27/CREDITS
-@@ -1348,6 +1348,7 @@
- D: Maintainer of the Linux Bluetooth Subsystem
- D: Author and maintainer of the various Bluetooth HCI drivers
- D: Author and maintainer of the CAPI message transport protocol driver
-+D: Author and maintainer of the Bluetooth HID protocol driver
- D: Various other Bluetooth related patches, cleanups and fixes
- S: Germany
-
---- linux-2.4.27/Documentation/Configure.help~patch-2.4.27-mh1
-+++ linux-2.4.27/Documentation/Configure.help
-@@ -23313,6 +23313,7 @@
- RFCOMM Module (RFCOMM Protocol)
- BNEP Module (Bluetooth Network Encapsulation Protocol)
- CMTP Module (CAPI Message Transport Protocol)
-+ HIDP Module (Human Interface Device Protocol)
-
- Say Y here to compile Bluetooth support into the kernel or say M to
- compile it as module (bluez.o).
-@@ -23378,6 +23379,15 @@
- Say Y here to compile CMTP support into the kernel or say M to
- compile it as module (cmtp.o).
-
-+HIDP protocol support
-+CONFIG_BLUEZ_HIDP
-+ HIDP (Human Interface Device Protocol) is a transport layer
-+ for HID reports. HIDP is required for the Bluetooth Human
-+ Interface Device Profile.
-+
-+ Say Y here to compile HIDP support into the kernel or say M to
-+ compile it as module (hidp.o).
-+
- HCI UART driver
- CONFIG_BLUEZ_HCIUART
- Bluetooth HCI UART driver.
---- linux-2.4.27/MAINTAINERS~patch-2.4.27-mh1
-+++ linux-2.4.27/MAINTAINERS
-@@ -359,6 +359,11 @@
- M: marcel@holtmann.org
- S: Maintained
-
-+BLUETOOTH HIDP LAYER
-+P: Marcel Holtmann
-+M: marcel@holtmann.org
-+S: Maintained
-+
- BLUETOOTH HCI UART DRIVER
- P: Marcel Holtmann
- M: marcel@holtmann.org
---- linux-2.4.27/net/bluetooth/Config.in~patch-2.4.27-mh1
-+++ linux-2.4.27/net/bluetooth/Config.in
-@@ -14,6 +14,7 @@
- source net/bluetooth/rfcomm/Config.in
- source net/bluetooth/bnep/Config.in
- source net/bluetooth/cmtp/Config.in
-+ source net/bluetooth/hidp/Config.in
- source drivers/bluetooth/Config.in
- fi
-
---- /dev/null
-+++ linux-2.4.27/net/bluetooth/hidp/Config.in
-@@ -0,0 +1,5 @@
-+#
-+# Bluetooth HIDP layer configuration
-+#
-+
-+dep_tristate 'HIDP protocol support' CONFIG_BLUEZ_HIDP $CONFIG_INPUT $CONFIG_BLUEZ_L2CAP
---- /dev/null
-+++ linux-2.4.27/net/bluetooth/hidp/core.c
-@@ -0,0 +1,655 @@
-+/*
-+ HIDP implementation for Linux Bluetooth stack (BlueZ).
-+ Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License version 2 as
-+ published by the Free Software Foundation;
-+
-+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
-+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+
-+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
-+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
-+ SOFTWARE IS DISCLAIMED.
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/major.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/poll.h>
-+#include <linux/fcntl.h>
-+#include <linux/skbuff.h>
-+#include <linux/socket.h>
-+#include <linux/ioctl.h>
-+#include <linux/file.h>
-+#include <linux/init.h>
-+#include <net/sock.h>
-+
-+#include <linux/input.h>
-+
-+#include <net/bluetooth/bluetooth.h>
-+#include <net/bluetooth/l2cap.h>
-+
-+#include "hidp.h"
-+
-+#ifndef CONFIG_BT_HIDP_DEBUG
-+#undef BT_DBG
-+#define BT_DBG(D...)
-+#endif
-+
-+#define VERSION "1.0"
-+
-+static DECLARE_RWSEM(hidp_session_sem);
-+static LIST_HEAD(hidp_session_list);
-+
-+static unsigned char hidp_keycode[256] = {
-+ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
-+ 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
-+ 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
-+ 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
-+ 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
-+ 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
-+ 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
-+ 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
-+ 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
-+ 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+ 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
-+ 150,158,159,128,136,177,178,176,142,152,173,140
-+};
-+
-+static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
-+{
-+ struct hidp_session *session;
-+ struct list_head *p;
-+
-+ BT_DBG("");
-+
-+ list_for_each(p, &hidp_session_list) {
-+ session = list_entry(p, struct hidp_session, list);
-+ if (!bacmp(bdaddr, &session->bdaddr))
-+ return session;
-+ }
-+ return NULL;
-+}
-+
-+static void __hidp_link_session(struct hidp_session *session)
-+{
-+ MOD_INC_USE_COUNT;
-+ list_add(&session->list, &hidp_session_list);
-+}
-+
-+static void __hidp_unlink_session(struct hidp_session *session)
-+{
-+ list_del(&session->list);
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
-+{
-+ bacpy(&ci->bdaddr, &session->bdaddr);
-+
-+ ci->flags = session->flags;
-+ ci->state = session->state;
-+
-+ ci->vendor = 0x0000;
-+ ci->product = 0x0000;
-+ ci->version = 0x0000;
-+ memset(ci->name, 0, 128);
-+
-+ if (session->input) {
-+ ci->vendor = session->input->idvendor;
-+ ci->product = session->input->idproduct;
-+ ci->version = session->input->idversion;
-+ if (session->input->name)
-+ strncpy(ci->name, session->input->name, 128);
-+ else
-+ strncpy(ci->name, "HID Boot Device", 128);
-+ }
-+}
-+
-+static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-+{
-+ struct hidp_session *session = dev->private;
-+ struct sk_buff *skb;
-+ unsigned char newleds;
-+
-+ BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
-+
-+ if (type != EV_LED)
-+ return -1;
-+
-+ newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
-+ (!!test_bit(LED_COMPOSE, dev->led) << 3) |
-+ (!!test_bit(LED_SCROLLL, dev->led) << 2) |
-+ (!!test_bit(LED_CAPSL, dev->led) << 1) |
-+ (!!test_bit(LED_NUML, dev->led));
-+
-+ if (session->leds == newleds)
-+ return 0;
-+
-+ session->leds = newleds;
-+
-+ if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
-+ BT_ERR("Can't allocate memory for new frame");
-+ return -ENOMEM;
-+ }
-+
-+ *skb_put(skb, 1) = 0xa2;
-+ *skb_put(skb, 1) = 0x01;
-+ *skb_put(skb, 1) = newleds;
-+
-+ skb_queue_tail(&session->intr_transmit, skb);
-+
-+ hidp_schedule(session);
-+
-+ return 0;
-+}
-+
-+static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
-+{
-+ struct input_dev *dev = session->input;
-+ unsigned char *keys = session->keys;
-+ unsigned char *udata = skb->data + 1;
-+ signed char *sdata = skb->data + 1;
-+ int i, size = skb->len - 1;
-+
-+ switch (skb->data[0]) {
-+ case 0x01: /* Keyboard report */
-+ for (i = 0; i < 8; i++)
-+ input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
-+
-+ for (i = 2; i < 8; i++) {
-+ if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
-+ if (hidp_keycode[keys[i]])
-+ input_report_key(dev, hidp_keycode[keys[i]], 0);
-+ else
-+ BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
-+ }
-+
-+ if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
-+ if (hidp_keycode[udata[i]])
-+ input_report_key(dev, hidp_keycode[udata[i]], 1);
-+ else
-+ BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
-+ }
-+ }
-+
-+ memcpy(keys, udata, 8);
-+ break;
-+
-+ case 0x02: /* Mouse report */
-+ input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
-+ input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
-+ input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
-+ input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
-+ input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
-+
-+ input_report_rel(dev, REL_X, sdata[1]);
-+ input_report_rel(dev, REL_Y, sdata[2]);
-+
-+ if (size > 3)
-+ input_report_rel(dev, REL_WHEEL, sdata[3]);
-+ break;
-+ }
-+
-+ input_event(dev, EV_RST, 0, 0);
-+}
-+
-+static void hidp_idle_timeout(unsigned long arg)
-+{
-+ struct hidp_session *session = (struct hidp_session *) arg;
-+
-+ atomic_inc(&session->terminate);
-+ hidp_schedule(session);
-+}
-+
-+static inline void hidp_set_timer(struct hidp_session *session)
-+{
-+ if (session->idle_to > 0)
-+ mod_timer(&session->timer, jiffies + HZ * session->idle_to);
-+}
-+
-+static inline void hidp_del_timer(struct hidp_session *session)
-+{
-+ if (session->idle_to > 0)
-+ del_timer(&session->timer);
-+}
-+
-+static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
-+{
-+ struct sk_buff *skb;
-+
-+ BT_DBG("session %p", session);
-+
-+ if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
-+ BT_ERR("Can't allocate memory for message");
-+ return;
-+ }
-+
-+ *skb_put(skb, 1) = hdr;
-+
-+ skb_queue_tail(&session->ctrl_transmit, skb);
-+
-+ hidp_schedule(session);
-+}
-+
-+static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
-+{
-+ __u8 hdr;
-+
-+ BT_DBG("session %p skb %p len %d", session, skb, skb->len);
-+
-+ hdr = skb->data[0];
-+ skb_pull(skb, 1);
-+
-+ if (hdr == 0xa1) {
-+ hidp_set_timer(session);
-+
-+ if (session->input)
-+ hidp_input_report(session, skb);
-+ } else {
-+ BT_DBG("Unsupported protocol header 0x%02x", hdr);
-+ }
-+
-+ kfree_skb(skb);
-+ return 0;
-+}
-+
-+static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
-+{
-+ struct iovec iv = { data, len };
-+ struct msghdr msg;
-+
-+ BT_DBG("sock %p data %p len %d", sock, data, len);
-+
-+ if (!len)
-+ return 0;
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.msg_iovlen = 1;
-+ msg.msg_iov = &iv;
-+
-+ return sock_sendmsg(sock, &msg, len);
-+}
-+
-+static int hidp_process_transmit(struct hidp_session *session)
-+{
-+ struct sk_buff *skb;
-+
-+ BT_DBG("session %p", session);
-+
-+ while ((skb = skb_dequeue(&session->ctrl_transmit))) {
-+ if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
-+ skb_queue_head(&session->ctrl_transmit, skb);
-+ break;
-+ }
-+
-+ hidp_set_timer(session);
-+ kfree_skb(skb);
-+ }
-+
-+ while ((skb = skb_dequeue(&session->intr_transmit))) {
-+ if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
-+ skb_queue_head(&session->intr_transmit, skb);
-+ break;
-+ }
-+
-+ hidp_set_timer(session);
-+ kfree_skb(skb);
-+ }
-+
-+ return skb_queue_len(&session->ctrl_transmit) +
-+ skb_queue_len(&session->intr_transmit);
-+}
-+
-+static int hidp_session(void *arg)
-+{
-+ struct hidp_session *session = arg;
-+ struct sock *ctrl_sk = session->ctrl_sock->sk;
-+ struct sock *intr_sk = session->intr_sock->sk;
-+ struct sk_buff *skb;
-+ int vendor = 0x0000, product = 0x0000;
-+ wait_queue_t ctrl_wait, intr_wait;
-+ unsigned long timeo = HZ;
-+
-+ BT_DBG("session %p", session);
-+
-+ if (session->input) {
-+ vendor = session->input->idvendor;
-+ product = session->input->idproduct;
-+ }
-+
-+ daemonize(); reparent_to_init();
-+
-+ sprintf(current->comm, "khidpd_%04x%04x", vendor, product);
-+
-+ sigfillset(&current->blocked);
-+ flush_signals(current);
-+
-+ current->nice = -15;
-+
-+ set_fs(KERNEL_DS);
-+
-+ init_waitqueue_entry(&ctrl_wait, current);
-+ init_waitqueue_entry(&intr_wait, current);
-+ add_wait_queue(ctrl_sk->sleep, &ctrl_wait);
-+ add_wait_queue(intr_sk->sleep, &intr_wait);
-+ while (!atomic_read(&session->terminate)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ if (ctrl_sk->state != BT_CONNECTED || intr_sk->state != BT_CONNECTED)
-+ break;
-+
-+ while ((skb = skb_dequeue(&ctrl_sk->receive_queue))) {
-+ skb_orphan(skb);
-+ hidp_recv_frame(session, skb);
-+ }
-+
-+ while ((skb = skb_dequeue(&intr_sk->receive_queue))) {
-+ skb_orphan(skb);
-+ hidp_recv_frame(session, skb);
-+ }
-+
-+ hidp_process_transmit(session);
-+
-+ schedule();
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(intr_sk->sleep, &intr_wait);
-+ remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
-+
-+ down_write(&hidp_session_sem);
-+
-+ hidp_del_timer(session);
-+
-+ if (intr_sk->state != BT_CONNECTED) {
-+ init_waitqueue_entry(&ctrl_wait, current);
-+ add_wait_queue(ctrl_sk->sleep, &ctrl_wait);
-+ while (timeo && ctrl_sk->state != BT_CLOSED) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ timeo = schedule_timeout(timeo);
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
-+ timeo = HZ;
-+ }
-+
-+ fput(session->ctrl_sock->file);
-+
-+ init_waitqueue_entry(&intr_wait, current);
-+ add_wait_queue(intr_sk->sleep, &intr_wait);
-+ while (timeo && intr_sk->state != BT_CLOSED) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ timeo = schedule_timeout(timeo);
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(intr_sk->sleep, &intr_wait);
-+
-+ fput(session->intr_sock->file);
-+
-+ __hidp_unlink_session(session);
-+
-+ if (session->input) {
-+ input_unregister_device(session->input);
-+ kfree(session->input);
-+ }
-+
-+ up_write(&hidp_session_sem);
-+
-+ kfree(session);
-+ return 0;
-+}
-+
-+static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
-+{
-+ struct input_dev *input = session->input;
-+ int i;
-+
-+ input->private = session;
-+
-+ input->idbus = BUS_BLUETOOTH;
-+ input->idvendor = req->vendor;
-+ input->idproduct = req->product;
-+ input->idversion = req->version;
-+
-+ if (req->subclass & 0x40) {
-+ set_bit(EV_KEY, input->evbit);
-+ set_bit(EV_LED, input->evbit);
-+ set_bit(EV_REP, input->evbit);
-+
-+ set_bit(LED_NUML, input->ledbit);
-+ set_bit(LED_CAPSL, input->ledbit);
-+ set_bit(LED_SCROLLL, input->ledbit);
-+ set_bit(LED_COMPOSE, input->ledbit);
-+ set_bit(LED_KANA, input->ledbit);
-+
-+ for (i = 0; i < sizeof(hidp_keycode); i++)
-+ set_bit(hidp_keycode[i], input->keybit);
-+ clear_bit(0, input->keybit);
-+ }
-+
-+ if (req->subclass & 0x80) {
-+ input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-+ input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-+ input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-+ input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-+ input->relbit[0] |= BIT(REL_WHEEL);
-+ }
-+
-+ input->event = hidp_input_event;
-+
-+ input_register_device(input);
-+}
-+
-+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
-+{
-+ struct hidp_session *session, *s;
-+ int err;
-+
-+ BT_DBG("");
-+
-+ if (bacmp(&bluez_pi(ctrl_sock->sk)->src, &bluez_pi(intr_sock->sk)->src) ||
-+ bacmp(&bluez_pi(ctrl_sock->sk)->dst, &bluez_pi(intr_sock->sk)->dst))
-+ return -ENOTUNIQ;
-+
-+ session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
-+ if (!session)
-+ return -ENOMEM;
-+ memset(session, 0, sizeof(struct hidp_session));
-+
-+ session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
-+ if (!session->input) {
-+ kfree(session);
-+ return -ENOMEM;
-+ }
-+ memset(session->input, 0, sizeof(struct input_dev));
-+
-+ down_write(&hidp_session_sem);
-+
-+ s = __hidp_get_session(&bluez_pi(ctrl_sock->sk)->dst);
-+ if (s && s->state == BT_CONNECTED) {
-+ err = -EEXIST;
-+ goto failed;
-+ }
-+
-+ bacpy(&session->bdaddr, &bluez_pi(ctrl_sock->sk)->dst);
-+
-+ session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
-+ session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
-+
-+ BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
-+
-+ session->ctrl_sock = ctrl_sock;
-+ session->intr_sock = intr_sock;
-+ session->state = BT_CONNECTED;
-+
-+ init_timer(&session->timer);
-+
-+ session->timer.function = hidp_idle_timeout;
-+ session->timer.data = (unsigned long) session;
-+
-+ skb_queue_head_init(&session->ctrl_transmit);
-+ skb_queue_head_init(&session->intr_transmit);
-+
-+ session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
-+ session->idle_to = req->idle_to;
-+
-+ if (session->input)
-+ hidp_setup_input(session, req);
-+
-+ __hidp_link_session(session);
-+
-+ hidp_set_timer(session);
-+
-+ err = kernel_thread(hidp_session, session, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-+ if (err < 0)
-+ goto unlink;
-+
-+ if (session->input) {
-+ hidp_send_message(session, 0x70);
-+ session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
-+
-+ session->leds = 0xff;
-+ hidp_input_event(session->input, EV_LED, 0, 0);
-+ }
-+
-+ up_write(&hidp_session_sem);
-+ return 0;
-+
-+unlink:
-+ hidp_del_timer(session);
-+
-+ __hidp_unlink_session(session);
-+
-+ if (session->input)
-+ input_unregister_device(session->input);
-+
-+failed:
-+ up_write(&hidp_session_sem);
-+
-+ if (session->input)
-+ kfree(session->input);
-+
-+ kfree(session);
-+ return err;
-+}
-+
-+int hidp_del_connection(struct hidp_conndel_req *req)
-+{
-+ struct hidp_session *session;
-+ int err = 0;
-+
-+ BT_DBG("");
-+
-+ down_read(&hidp_session_sem);
-+
-+ session = __hidp_get_session(&req->bdaddr);
-+ if (session) {
-+ if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
-+ hidp_send_message(session, 0x15);
-+ } else {
-+ /* Flush the transmit queues */
-+ skb_queue_purge(&session->ctrl_transmit);
-+ skb_queue_purge(&session->intr_transmit);
-+
-+ /* Kill session thread */
-+ atomic_inc(&session->terminate);
-+ hidp_schedule(session);
-+ }
-+ } else
-+ err = -ENOENT;
-+
-+ up_read(&hidp_session_sem);
-+ return err;
-+}
-+
-+int hidp_get_connlist(struct hidp_connlist_req *req)
-+{
-+ struct list_head *p;
-+ int err = 0, n = 0;
-+
-+ BT_DBG("");
-+
-+ down_read(&hidp_session_sem);
-+
-+ list_for_each(p, &hidp_session_list) {
-+ struct hidp_session *session;
-+ struct hidp_conninfo ci;
-+
-+ session = list_entry(p, struct hidp_session, list);
-+
-+ __hidp_copy_session(session, &ci);
-+
-+ if (copy_to_user(req->ci, &ci, sizeof(ci))) {
-+ err = -EFAULT;
-+ break;
-+ }
-+
-+ if (++n >= req->cnum)
-+ break;
-+
-+ req->ci++;
-+ }
-+ req->cnum = n;
-+
-+ up_read(&hidp_session_sem);
-+ return err;
-+}
-+
-+int hidp_get_conninfo(struct hidp_conninfo *ci)
-+{
-+ struct hidp_session *session;
-+ int err = 0;
-+
-+ down_read(&hidp_session_sem);
-+
-+ session = __hidp_get_session(&ci->bdaddr);
-+ if (session)
-+ __hidp_copy_session(session, ci);
-+ else
-+ err = -ENOENT;
-+
-+ up_read(&hidp_session_sem);
-+ return err;
-+}
-+
-+static int __init hidp_init(void)
-+{
-+ l2cap_load();
-+
-+ hidp_init_sockets();
-+
-+ BT_INFO("BlueZ HIDP ver %s", VERSION);
-+ BT_INFO("Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>");
-+
-+ return 0;
-+}
-+
-+static void __exit hidp_exit(void)
-+{
-+ hidp_cleanup_sockets();
-+}
-+
-+module_init(hidp_init);
-+module_exit(hidp_exit);
-+
-+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
-+MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/net/bluetooth/hidp/hidp.h
-@@ -0,0 +1,122 @@
-+/*
-+ HIDP implementation for Linux Bluetooth stack (BlueZ).
-+ Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License version 2 as
-+ published by the Free Software Foundation;
-+
-+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
-+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+
-+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
-+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
-+ SOFTWARE IS DISCLAIMED.
-+*/
-+
-+#ifndef __HIDP_H
-+#define __HIDP_H
-+
-+#include <linux/types.h>
-+#include <net/bluetooth/bluetooth.h>
-+
-+/* HIDP ioctl defines */
-+#define HIDPCONNADD _IOW('H', 200, int)
-+#define HIDPCONNDEL _IOW('H', 201, int)
-+#define HIDPGETCONNLIST _IOR('H', 210, int)
-+#define HIDPGETCONNINFO _IOR('H', 211, int)
-+
-+#define HIDP_VIRTUAL_CABLE_UNPLUG 0
-+#define HIDP_BOOT_PROTOCOL_MODE 1
-+#define HIDP_BLUETOOTH_VENDOR_ID 9
-+
-+struct hidp_connadd_req {
-+ int ctrl_sock; // Connected control socket
-+ int intr_sock; // Connteted interrupt socket
-+ __u16 parser;
-+ __u16 rd_size;
-+ __u8 *rd_data;
-+ __u8 country;
-+ __u8 subclass;
-+ __u16 vendor;
-+ __u16 product;
-+ __u16 version;
-+ __u32 flags;
-+ __u32 idle_to;
-+ char name[128];
-+};
-+
-+struct hidp_conndel_req {
-+ bdaddr_t bdaddr;
-+ __u32 flags;
-+};
-+
-+struct hidp_conninfo {
-+ bdaddr_t bdaddr;
-+ __u32 flags;
-+ __u16 state;
-+ __u16 vendor;
-+ __u16 product;
-+ __u16 version;
-+ char name[128];
-+};
-+
-+struct hidp_connlist_req {
-+ __u32 cnum;
-+ struct hidp_conninfo *ci;
-+};
-+
-+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
-+int hidp_del_connection(struct hidp_conndel_req *req);
-+int hidp_get_connlist(struct hidp_connlist_req *req);
-+int hidp_get_conninfo(struct hidp_conninfo *ci);
-+
-+/* HIDP session defines */
-+struct hidp_session {
-+ struct list_head list;
-+
-+ struct socket *ctrl_sock;
-+ struct socket *intr_sock;
-+
-+ bdaddr_t bdaddr;
-+
-+ unsigned long state;
-+ unsigned long flags;
-+ unsigned long idle_to;
-+
-+ uint ctrl_mtu;
-+ uint intr_mtu;
-+
-+ atomic_t terminate;
-+
-+ unsigned char keys[8];
-+ unsigned char leds;
-+
-+ struct input_dev *input;
-+
-+ struct timer_list timer;
-+
-+ struct sk_buff_head ctrl_transmit;
-+ struct sk_buff_head intr_transmit;
-+};
-+
-+static inline void hidp_schedule(struct hidp_session *session)
-+{
-+ struct sock *ctrl_sk = session->ctrl_sock->sk;
-+ struct sock *intr_sk = session->intr_sock->sk;
-+
-+ wake_up_interruptible(ctrl_sk->sleep);
-+ wake_up_interruptible(intr_sk->sleep);
-+}
-+
-+/* HIDP init defines */
-+extern int __init hidp_init_sockets(void);
-+extern void __exit hidp_cleanup_sockets(void);
-+
-+#endif /* __HIDP_H */
---- /dev/null
-+++ linux-2.4.27/net/bluetooth/hidp/Makefile
-@@ -0,0 +1,10 @@
-+#
-+# Makefile for the Linux Bluetooth HIDP layer
-+#
-+
-+O_TARGET := hidp.o
-+
-+obj-y := core.o sock.o
-+obj-m += $(O_TARGET)
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/net/bluetooth/hidp/sock.c
-@@ -0,0 +1,212 @@
-+/*
-+ HIDP implementation for Linux Bluetooth stack (BlueZ).
-+ Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License version 2 as
-+ published by the Free Software Foundation;
-+
-+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-+ CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
-+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+
-+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
-+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
-+ SOFTWARE IS DISCLAIMED.
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/major.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/poll.h>
-+#include <linux/fcntl.h>
-+#include <linux/skbuff.h>
-+#include <linux/socket.h>
-+#include <linux/ioctl.h>
-+#include <linux/file.h>
-+#include <linux/init.h>
-+#include <net/sock.h>
-+
-+#include "hidp.h"
-+
-+#ifndef CONFIG_BT_HIDP_DEBUG
-+#undef BT_DBG
-+#define BT_DBG(D...)
-+#endif
-+
-+static int hidp_sock_release(struct socket *sock)
-+{
-+ struct sock *sk = sock->sk;
-+
-+ BT_DBG("sock %p sk %p", sock, sk);
-+
-+ if (!sk)
-+ return 0;
-+
-+ sock_orphan(sk);
-+ sock_put(sk);
-+
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-+{
-+ struct hidp_connadd_req ca;
-+ struct hidp_conndel_req cd;
-+ struct hidp_connlist_req cl;
-+ struct hidp_conninfo ci;
-+ struct socket *csock;
-+ struct socket *isock;
-+ int err;
-+
-+ BT_DBG("cmd %x arg %lx", cmd, arg);
-+
-+ switch (cmd) {
-+ case HIDPCONNADD:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EACCES;
-+
-+ if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
-+ return -EFAULT;
-+
-+ csock = sockfd_lookup(ca.ctrl_sock, &err);
-+ if (!csock)
-+ return err;
-+
-+ isock = sockfd_lookup(ca.intr_sock, &err);
-+ if (!isock) {
-+ fput(csock->file);
-+ return err;
-+ }
-+
-+ if (csock->sk->state != BT_CONNECTED || isock->sk->state != BT_CONNECTED) {
-+ fput(csock->file);
-+ fput(isock->file);
-+ return -EBADFD;
-+ }
-+
-+ err = hidp_add_connection(&ca, csock, isock);
-+ if (!err) {
-+ if (copy_to_user((void *) arg, &ca, sizeof(ca)))
-+ err = -EFAULT;
-+ } else {
-+ fput(csock->file);
-+ fput(isock->file);
-+ }
-+
-+ return err;
-+
-+ case HIDPCONNDEL:
-+ if (!capable(CAP_NET_ADMIN))
-+ return -EACCES;
-+
-+ if (copy_from_user(&cd, (void *) arg, sizeof(cd)))
-+ return -EFAULT;
-+
-+ return hidp_del_connection(&cd);
-+
-+ case HIDPGETCONNLIST:
-+ if (copy_from_user(&cl, (void *) arg, sizeof(cl)))
-+ return -EFAULT;
-+
-+ if (cl.cnum <= 0)
-+ return -EINVAL;
-+
-+ err = hidp_get_connlist(&cl);
-+ if (!err && copy_to_user((void *) arg, &cl, sizeof(cl)))
-+ return -EFAULT;
-+
-+ return err;
-+
-+ case HIDPGETCONNINFO:
-+ if (copy_from_user(&ci, (void *) arg, sizeof(ci)))
-+ return -EFAULT;
-+
-+ err = hidp_get_conninfo(&ci);
-+ if (!err && copy_to_user((void *) arg, &ci, sizeof(ci)))
-+ return -EFAULT;
-+
-+ return err;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+static struct proto_ops hidp_sock_ops = {
-+ family: PF_BLUETOOTH,
-+ release: hidp_sock_release,
-+ ioctl: hidp_sock_ioctl,
-+ bind: sock_no_bind,
-+ getname: sock_no_getname,
-+ sendmsg: sock_no_sendmsg,
-+ recvmsg: sock_no_recvmsg,
-+ poll: sock_no_poll,
-+ listen: sock_no_listen,
-+ shutdown: sock_no_shutdown,
-+ setsockopt: sock_no_setsockopt,
-+ getsockopt: sock_no_getsockopt,
-+ connect: sock_no_connect,
-+ socketpair: sock_no_socketpair,
-+ accept: sock_no_accept,
-+ mmap: sock_no_mmap
-+};
-+
-+static int hidp_sock_create(struct socket *sock, int protocol)
-+{
-+ struct sock *sk;
-+
-+ BT_DBG("sock %p", sock);
-+
-+ if (sock->type != SOCK_RAW)
-+ return -ESOCKTNOSUPPORT;
-+
-+ sock->ops = &hidp_sock_ops;
-+
-+ if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1)))
-+ return -ENOMEM;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ sock->state = SS_UNCONNECTED;
-+ sock_init_data(sock, sk);
-+
-+ sk->destruct = NULL;
-+ sk->protocol = protocol;
-+
-+ return 0;
-+}
-+
-+static struct net_proto_family hidp_sock_family_ops = {
-+ family: PF_BLUETOOTH,
-+ create: hidp_sock_create
-+};
-+
-+int __init hidp_init_sockets(void)
-+{
-+ int err;
-+
-+ if ((err = bluez_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops)))
-+ BT_ERR("Can't register HIDP socket layer (%d)", err);
-+
-+ return err;
-+}
-+
-+void __exit hidp_cleanup_sockets(void)
-+{
-+ int err;
-+
-+ if ((err = bluez_sock_unregister(BTPROTO_HIDP)))
-+ BT_ERR("Can't unregister HIDP socket layer (%d)", err);
-+}
---- linux-2.4.27/net/bluetooth/Makefile~patch-2.4.27-mh1
-+++ linux-2.4.27/net/bluetooth/Makefile
-@@ -16,6 +16,7 @@
- subdir-$(CONFIG_BLUEZ_RFCOMM) += rfcomm
- subdir-$(CONFIG_BLUEZ_BNEP) += bnep
- subdir-$(CONFIG_BLUEZ_CMTP) += cmtp
-+subdir-$(CONFIG_BLUEZ_HIDP) += hidp
-
- ifeq ($(CONFIG_BLUEZ_RFCOMM),y)
- obj-y += rfcomm/rfcomm.o
-@@ -25,6 +26,14 @@
- obj-y += bnep/bnep.o
- endif
-
-+ifeq ($(CONFIG_BLUEZ_CMTP),y)
-+obj-y += cmtp/cmtp.o
-+endif
-+
-+ifeq ($(CONFIG_BLUEZ_HIDP),y)
-+obj-y += hidp/hidp.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-
- bluez.o: $(bluez-objs)
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1-jpm1.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1-jpm1.patch
deleted file mode 100644
index bf4633979b..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1-jpm1.patch
+++ /dev/null
@@ -1,8760 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/Makefile~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/Makefile
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 27
--EXTRAVERSION =-vrs1-pxa1
-+EXTRAVERSION =-vrs1-pxa1-jpm1
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
---- linux-2.4.27/arch/arm/mach-sa1100/Makefile~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/mach-sa1100/Makefile
-@@ -18,7 +18,8 @@
- export-objs := assabet.o consus.o badge4.o dma-sa1100.o dma-sa1111.o \
- flexanet.o freebird.o frodo.o generic.o h3600.o \
- huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \
-- system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o
-+ system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \
-+ simpad.o
-
- # These aren't present yet, and prevents a plain -ac kernel building.
- # hwtimer.o
-@@ -30,7 +31,6 @@
- ifeq ($(CONFIG_CPU_FREQ),y)
- obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_CEP) += cpu-sa1110.o
--obj-$(CONFIG_SA1100_CONSUS) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o
- obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
-@@ -52,7 +52,6 @@
- obj-$(CONFIG_SA1100_BRUTUS) += brutus.o
- obj-$(CONFIG_SA1100_CEP) += cep.o
- obj-$(CONFIG_SA1100_CERF) += cerf.o
--obj-$(CONFIG_SA1100_CONSUS) += consus.o
- obj-$(CONFIG_SA1100_EMPEG) += empeg.o
- obj-$(CONFIG_SA1100_FLEXANET) += flexanet.o
- obj-$(CONFIG_SA1100_FREEBIRD) += freebird.o
-@@ -87,7 +86,6 @@
- leds-$(CONFIG_SA1100_ASSABET) += leds-assabet.o
- leds-$(CONFIG_SA1100_BRUTUS) += leds-brutus.o
- leds-$(CONFIG_SA1100_CERF) += leds-cerf.o
--leds-$(CONFIG_SA1100_CONSUS) += leds-consus.o
- leds-$(CONFIG_SA1100_FLEXANET) += leds-flexanet.o
- leds-$(CONFIG_SA1100_FRODO) += leds-frodo.o
- leds-$(CONFIG_SA1100_GRAPHICSCLIENT) += leds-graphicsclient.o
-@@ -108,7 +106,12 @@
-
- # Miscelaneous functions
- obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_APM) += apm.o
-
-+# SIMpad specific
-+export-objs += simpad_pm.o
-+obj-$(CONFIG_SIMPAD_PM) += simpad_pm.o
-+
- obj-$(CONFIG_SA1100_SSP) += ssp.o
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.27/drivers/video/fbmem.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/video/fbmem.c
-@@ -109,6 +109,7 @@
- extern int chips_init(void);
- extern int g364fb_init(void);
- extern int sa1100fb_init(void);
-+extern int mq200fb_init(void);
- extern int pxafb_init(void);
- extern int fm2fb_init(void);
- extern int fm2fb_setup(char*);
-@@ -306,6 +307,9 @@
- #ifdef CONFIG_FB_SA1100
- { "sa1100", sa1100fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_MQ200
-+ { "mq200fb", mq200fb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_PXA
- { "pxa", pxafb_init, NULL },
- #endif
---- linux-2.4.27/arch/arm/config.in~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/config.in
-@@ -128,6 +128,9 @@
- dep_bool ' Shannon' CONFIG_SA1100_SHANNON $CONFIG_ARCH_SA1100
- dep_bool ' Sherman' CONFIG_SA1100_SHERMAN $CONFIG_ARCH_SA1100
- dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100
-+if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then
-+ bool ' T-Sinus PAD' CONFIG_SA1100_SIMPAD_SINUSPAD
-+fi
- dep_bool ' Simputer' CONFIG_SA1100_SIMPUTER $CONFIG_ARCH_SA1100
- dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100
- dep_bool ' Victor' CONFIG_SA1100_VICTOR $CONFIG_ARCH_SA1100
-@@ -587,6 +590,10 @@
- tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
- tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
- dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
-+dep_tristate 'Advanced power management emulation support' CONFIG_APM $CONFIG_PM
-+if [ "$CONFIG_APM" != "n" ]; then
-+ bool ' SIMpad power management' CONFIG_SIMPAD_PM
-+fi
- dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
- string 'Default kernel command string' CONFIG_CMDLINE ""
-
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/simpad
-@@ -0,0 +1,967 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+CONFIG_ARCH_SA1100=y
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+CONFIG_SA1100_SIMPAD=y
-+# CONFIG_SA1100_SIMPAD_SINUSPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+CONFIG_SA1100_USB=m
-+CONFIG_SA1100_USB_NETLINK=m
-+CONFIG_SA1100_USB_CHAR=m
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+CONFIG_CPU_SA1100=y
-+# CONFIG_CPU_32v3 is not set
-+CONFIG_CPU_32v4=y
-+CONFIG_DISCONTIGMEM=y
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+CONFIG_ISA=y
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+CONFIG_PCMCIA_PROBE=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+CONFIG_PCMCIA_SA1100=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+CONFIG_BINFMT_MISC=m
-+CONFIG_PM=y
-+CONFIG_APM=y
-+CONFIG_SIMPAD_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="mtdparts=sa1100:512k(boot),1m(kernel),-(root) console=ttySA root=1f02 noinitrd mem=64M"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+CONFIG_MTD_JEDECPROBE=y
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+CONFIG_MTD_CFI_B2=y
-+# CONFIG_MTD_CFI_B4 is not set
-+# CONFIG_MTD_CFI_B8 is not set
-+CONFIG_MTD_CFI_I1=y
-+# CONFIG_MTD_CFI_I2 is not set
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+CONFIG_MTD_ROM=y
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+CONFIG_MTD_SA1100=y
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+CONFIG_MTD_MTDRAM=y
-+CONFIG_MTDRAM_TOTAL_SIZE=32768
-+CONFIG_MTDRAM_ERASE_SIZE=1
-+CONFIG_MTDRAM_ABS_POS=C2000000
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+CONFIG_PACKET_MMAP=y
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+CONFIG_DUMMY=y
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_AT1700 is not set
-+# CONFIG_DEPCA is not set
-+# CONFIG_HP100 is not set
-+# CONFIG_NET_ISA is not set
-+CONFIG_NET_PCI=y
-+# CONFIG_PCNET32 is not set
-+# CONFIG_ADAPTEC_STARFIRE is not set
-+# CONFIG_AC3200 is not set
-+# CONFIG_APRICOT is not set
-+# CONFIG_CS89x0 is not set
-+# CONFIG_TULIP is not set
-+# CONFIG_TC35815 is not set
-+# CONFIG_DM9102 is not set
-+# CONFIG_EEPRO100 is not set
-+# CONFIG_LNE390 is not set
-+# CONFIG_FEALNX is not set
-+# CONFIG_NATSEMI is not set
-+# CONFIG_NE2K_PCI is not set
-+# CONFIG_NE3210 is not set
-+# CONFIG_ES3210 is not set
-+# CONFIG_8139CP is not set
-+# CONFIG_8139TOO is not set
-+# CONFIG_8139TOO_PIO is not set
-+# CONFIG_8139TOO_TUNE_TWISTER is not set
-+# CONFIG_8139TOO_8129 is not set
-+# CONFIG_8139_NEW_RX_RESET is not set
-+# CONFIG_SIS900 is not set
-+# CONFIG_EPIC100 is not set
-+# CONFIG_SUNDANCE is not set
-+# CONFIG_VIA_RHINE is not set
-+# CONFIG_VIA_RHINE_MMIO is not set
-+# CONFIG_WINBOND_840 is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+# CONFIG_WAVELAN is not set
-+# CONFIG_ARLAN is not set
-+# CONFIG_AIRONET4500 is not set
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+CONFIG_AIRO=m
-+# CONFIG_HERMES is not set
-+# CONFIG_PCMCIA_HERMES is not set
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=m
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+# CONFIG_PCMCIA_RAYCS is not set
-+# CONFIG_PCMCIA_NETWAVE is not set
-+CONFIG_PCMCIA_WAVELAN=m
-+# CONFIG_AIRONET4500_CS is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=m
-+CONFIG_IRLAN=m
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=m
-+# CONFIG_IRDA_ULTRA is not set
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+# CONFIG_IRDA_DEBUG is not set
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=m
-+CONFIG_IRPORT_SIR=m
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+CONFIG_SA1100_FIR=m
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=m
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=m
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=m
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=m
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+CONFIG_SERIAL_SA1100=y
-+CONFIG_SERIAL_SA1100_CONSOLE=y
-+CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_AT91US3 is not set
-+# CONFIG_SERIAL_AT91US3_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=32
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_SA1100_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=m
-+CONFIG_TDA8007=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+CONFIG_REISERFS_FS=m
-+# CONFIG_REISERFS_CHECK is not set
-+CONFIG_REISERFS_PROC_INFO=y
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=m
-+CONFIG_JBD=m
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+CONFIG_JFFS_FS=m
-+CONFIG_JFFS_FS_VERBOSE=0
-+CONFIG_JFFS_PROC_FS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+CONFIG_CRAMFS=m
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+CONFIG_DEVFS_DEBUG=y
-+# CONFIG_DEVPTS_FS is not set
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=m
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+CONFIG_SMB_FS=m
-+# CONFIG_SMB_NLS_DEFAULT is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+CONFIG_ZLIB_FS_INFLATE=m
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+CONFIG_SMB_NLS=y
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=y
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=y
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+CONFIG_NLS_ISO8859_15=y
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+# CONFIG_FB_CYBER2000 is not set
-+CONFIG_FB_MQ200=y
-+# CONFIG_FB_VIRTUAL is not set
-+CONFIG_FBCON_ADVANCED=y
-+# CONFIG_FBCON_MFB is not set
-+# CONFIG_FBCON_CFB2 is not set
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_CFB24 is not set
-+# CONFIG_FBCON_CFB32 is not set
-+# CONFIG_FBCON_AFB is not set
-+# CONFIG_FBCON_ILBM is not set
-+# CONFIG_FBCON_IPLAN2P2 is not set
-+# CONFIG_FBCON_IPLAN2P4 is not set
-+# CONFIG_FBCON_IPLAN2P8 is not set
-+# CONFIG_FBCON_MAC is not set
-+# CONFIG_FBCON_VGA_PLANES is not set
-+# CONFIG_FBCON_VGA is not set
-+# CONFIG_FBCON_HGA is not set
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+CONFIG_FBCON_FONTS=y
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_SUN12x22 is not set
-+# CONFIG_FONT_6x11 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+# CONFIG_FONT_ACORN_8x8 is not set
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+CONFIG_SOUND_SA1100=y
-+# CONFIG_SOUND_UDA1341 is not set
-+# CONFIG_SOUND_ASSABET_UDA1341 is not set
-+# CONFIG_SOUND_H3600_UDA1341 is not set
-+# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-+# CONFIG_SOUND_SA1111_UDA1341 is not set
-+# CONFIG_SOUND_SA1111_AC97 is not set
-+# CONFIG_SOUND_SA1100SSP is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_VIDC is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+CONFIG_MCP=y
-+CONFIG_MCP_SA1100=y
-+CONFIG_MCP_UCB1200=y
-+CONFIG_MCP_UCB1200_AUDIO=y
-+CONFIG_MCP_UCB1200_TS=y
-+
-+#
-+# Console Switches
-+#
-+CONFIG_SWITCHES=y
-+CONFIG_SWITCHES_SA1100=y
-+CONFIG_SWITCHES_UCB1X00=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+# CONFIG_DEBUG_KERNEL is not set
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
-+# CONFIG_DEBUG_ERRORS is not set
-+# CONFIG_DEBUG_LL is not set
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- linux-2.4.27/arch/arm/kernel/head-armv.S~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/kernel/head-armv.S
-@@ -93,6 +93,8 @@
- .section ".text.init",#alloc,#execinstr
- .type stext, #function
- ENTRY(stext)
-+ mov r1, #87
-+ mov r0, #0
- mov r12, r0
- /*
- * NOTE! Any code which is placed here should be done for one of
---- linux-2.4.27/arch/arm/kernel/irq.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/kernel/irq.c
-@@ -82,9 +82,9 @@
-
- spin_lock_irqsave(&irq_controller_lock, flags);
- if (!desc->disable_depth++) {
--#ifndef CONFIG_CPU_SA1100
-+// #ifndef CONFIG_CPU_SA1100
- desc->mask(irq);
--#endif
-+// #endif
- }
- spin_unlock_irqrestore(&irq_controller_lock, flags);
- }
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/apm.c
-@@ -0,0 +1,520 @@
-+/*
-+ * bios-less APM driver for ARM Linux
-+ * Jamey Hicks <jamey@crl.dec.com>
-+ * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
-+ *
-+ * APM 1.2 Reference:
-+ * Intel Corporation, Microsoft Corporation. Advanced Power Management
-+ * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
-+ *
-+ * [This document is available from Microsoft at:
-+ * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/poll.h>
-+#include <linux/types.h>
-+#include <linux/stddef.h>
-+#include <linux/timer.h>
-+#include <linux/fcntl.h>
-+#include <linux/slab.h>
-+#include <linux/stat.h>
-+#include <linux/proc_fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/apm_bios.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/pm.h>
-+#include <linux/kernel.h>
-+#include <linux/smp_lock.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#if FIXME
-+#include <asm/arch-sa1100/pm.h>
-+#endif
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch-sa1100/h3600_hal.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch-sa1100/simpad_pm.h>
-+#endif
-+
-+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-+extern int (*console_blank_hook)(int);
-+#endif
-+
-+struct apm_bios_info apm_bios_info = {
-+ /* this driver simulates APM version 1.2 */
-+ version: 0x102,
-+ flags: APM_32_BIT_SUPPORT
-+};
-+
-+/*
-+ * The apm_bios device is one of the misc char devices.
-+ * This is its minor number.
-+ */
-+#define APM_MINOR_DEV 134
-+
-+/*
-+ * See Documentation/Config.help for the configuration options.
-+ *
-+ * Various options can be changed at boot time as follows:
-+ * (We allow underscores for compatibility with the modules code)
-+ * apm=on/off enable/disable APM
-+ * [no-]debug log some debugging messages
-+ * [no-]power[-_]off power off on shutdown
-+ */
-+
-+/*
-+ * Need to poll the APM BIOS every second
-+ */
-+#define APM_CHECK_TIMEOUT (HZ)
-+
-+/*
-+ * Ignore suspend events for this amount of time after a resume
-+ */
-+#define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
-+
-+/*
-+ * Maximum number of events stored
-+ */
-+#define APM_MAX_EVENTS 20
-+
-+/*
-+ * The per-file APM data
-+ */
-+struct apm_user {
-+ int magic;
-+ struct apm_user * next;
-+ int suser: 1;
-+ int suspend_wait: 1;
-+ int suspend_result;
-+ int suspends_pending;
-+ int standbys_pending;
-+ int suspends_read;
-+ int standbys_read;
-+ int event_head;
-+ int event_tail;
-+ apm_event_t events[APM_MAX_EVENTS];
-+};
-+
-+/*
-+ * The magic number in apm_user
-+ */
-+#define APM_BIOS_MAGIC 0x4101
-+
-+/*
-+ * Local variables
-+ */
-+//static int suspends_pending;
-+//static int standbys_pending;
-+//static int ignore_normal_resume;
-+
-+#ifdef CONFIG_APM_RTC_IS_GMT
-+# define clock_cmos_diff 0
-+# define got_clock_diff 1
-+#else
-+//static long clock_cmos_diff;
-+//static int got_clock_diff;
-+#endif
-+static int debug;
-+static int apm_disabled;
-+#ifdef CONFIG_SMP
-+static int power_off;
-+#else
-+static int power_off = 1;
-+#endif
-+static int exit_kapmd;
-+static int kapmd_running;
-+
-+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-+static struct apm_user * user_list = NULL;
-+
-+static char driver_version[] = "1.13"; /* no spaces */
-+
-+typedef struct lookup_t {
-+ int key;
-+ char * msg;
-+} lookup_t;
-+
-+static const lookup_t error_table[] = {
-+/* N/A { APM_SUCCESS, "Operation succeeded" }, */
-+ { APM_DISABLED, "Power management disabled" },
-+ { APM_CONNECTED, "Real mode interface already connected" },
-+ { APM_NOT_CONNECTED, "Interface not connected" },
-+ { APM_16_CONNECTED, "16 bit interface already connected" },
-+/* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */
-+ { APM_32_CONNECTED, "32 bit interface already connected" },
-+ { APM_32_UNSUPPORTED, "32 bit interface not supported" },
-+ { APM_BAD_DEVICE, "Unrecognized device ID" },
-+ { APM_BAD_PARAM, "Parameter out of range" },
-+ { APM_NOT_ENGAGED, "Interface not engaged" },
-+ { APM_BAD_FUNCTION, "Function not supported" },
-+ { APM_RESUME_DISABLED, "Resume timer disabled" },
-+ { APM_BAD_STATE, "Unable to enter requested state" },
-+/* N/A { APM_NO_EVENTS, "No events pending" }, */
-+ { APM_NO_ERROR, "BIOS did not set a return code" },
-+ { APM_NOT_PRESENT, "No APM present" }
-+};
-+#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
-+
-+static int apm_get_power_status(u_char *ac_line_status,
-+ u_char *battery_status,
-+ u_char *battery_flag,
-+ u_char *battery_percentage,
-+ u_short *battery_life)
-+{
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ h3600_apm_get_power_status(ac_line_status, battery_status, battery_flag, battery_percentage, battery_life);
-+#endif
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_apm_get_power_status(ac_line_status, battery_status, battery_flag, battery_percentage, battery_life);
-+#endif
-+ return APM_SUCCESS;
-+}
-+
-+static int queue_empty(struct apm_user *as)
-+{
-+ return as->event_head == as->event_tail;
-+}
-+
-+static apm_event_t get_queued_event(struct apm_user *as)
-+{
-+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-+ return as->events[as->event_tail];
-+}
-+
-+static int check_apm_user(struct apm_user *as, const char *func)
-+{
-+ if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-+ printk(KERN_ERR "apm: %s passed bad filp\n", func);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
-+{
-+ struct apm_user * as;
-+ int i;
-+ apm_event_t event;
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ as = fp->private_data;
-+ if (check_apm_user(as, "read"))
-+ return -EIO;
-+ if (count < sizeof(apm_event_t))
-+ return -EINVAL;
-+ if (queue_empty(as)) {
-+ if (fp->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ add_wait_queue(&apm_waitqueue, &wait);
-+ printk("do_read: waiting\n");
-+repeat:
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (queue_empty(as) && !signal_pending(current)) {
-+ schedule();
-+ goto repeat;
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&apm_waitqueue, &wait);
-+ }
-+ i = count;
-+ while ((i >= sizeof(event)) && !queue_empty(as)) {
-+ event = get_queued_event(as);
-+ printk(" do_read: event=%d\n", event);
-+ if (copy_to_user(buf, &event, sizeof(event))) {
-+ if (i < count)
-+ break;
-+ return -EFAULT;
-+ }
-+ switch (event) {
-+ case APM_SYS_SUSPEND:
-+ case APM_USER_SUSPEND:
-+ as->suspends_read++;
-+ break;
-+
-+ case APM_SYS_STANDBY:
-+ case APM_USER_STANDBY:
-+ as->standbys_read++;
-+ break;
-+ }
-+ buf += sizeof(event);
-+ i -= sizeof(event);
-+ }
-+ if (i < count)
-+ return count - i;
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+ return 0;
-+}
-+
-+static unsigned int do_poll(struct file *fp, poll_table * wait)
-+{
-+ struct apm_user * as;
-+
-+ as = fp->private_data;
-+ if (check_apm_user(as, "poll"))
-+ return 0;
-+ poll_wait(fp, &apm_waitqueue, wait);
-+ if (!queue_empty(as))
-+ return POLLIN | POLLRDNORM;
-+ return 0;
-+}
-+
-+static int do_ioctl(struct inode * inode, struct file *filp,
-+ u_int cmd, u_long arg)
-+{
-+ struct apm_user * as;
-+
-+ as = filp->private_data;
-+ if (check_apm_user(as, "ioctl"))
-+ return -EIO;
-+ if (!as->suser)
-+ return -EPERM;
-+ switch (cmd) {
-+ case APM_IOC_SUSPEND:
-+#if FIXME
-+ pm_suggest_suspend();
-+#endif
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+static int do_release(struct inode * inode, struct file * filp)
-+{
-+ struct apm_user * as;
-+
-+ as = filp->private_data;
-+ if (check_apm_user(as, "release"))
-+ return 0;
-+ filp->private_data = NULL;
-+ lock_kernel();
-+ unlock_kernel();
-+ kfree(as);
-+ return 0;
-+}
-+
-+static int do_open(struct inode * inode, struct file * filp)
-+{
-+ struct apm_user * as;
-+
-+ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
-+ if (as == NULL) {
-+ printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-+ sizeof(*as));
-+ return -ENOMEM;
-+ }
-+ as->magic = APM_BIOS_MAGIC;
-+ as->event_tail = as->event_head = 0;
-+ as->suspends_pending = as->standbys_pending = 0;
-+ as->suspends_read = as->standbys_read = 0;
-+ /*
-+ * XXX - this is a tiny bit broken, when we consider BSD
-+ * process accounting. If the device is opened by root, we
-+ * instantly flag that we used superuser privs. Who knows,
-+ * we might close the device immediately without doing a
-+ * privileged operation -- cevans
-+ */
-+ as->suser = capable(CAP_SYS_ADMIN);
-+ as->next = user_list;
-+ user_list = as;
-+ filp->private_data = as;
-+ return 0;
-+}
-+
-+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
-+{
-+ char * p;
-+ unsigned short dx;
-+ unsigned short error;
-+ unsigned char ac_line_status = 0xff;
-+ unsigned char battery_status = 0xff;
-+ unsigned char battery_flag = 0xff;
-+ unsigned char percentage = 0xff;
-+ int time_units = -1;
-+ char *units = "?";
-+
-+ p = buf;
-+
-+ if ((smp_num_cpus == 1) &&
-+ !(error = apm_get_power_status(&ac_line_status,
-+ &battery_status, &battery_flag, &percentage, &dx))) {
-+ if (apm_bios_info.version > 0x100) {
-+ if (dx != 0xffff) {
-+ units = (dx & 0x8000) ? "min" : "sec";
-+ time_units = dx & 0x7fff;
-+ }
-+ }
-+ }
-+ /* Arguments, with symbols from linux/apm_bios.h. Information is
-+ from the Get Power Status (0x0a) call unless otherwise noted.
-+
-+ 0) Linux driver version (this will change if format changes)
-+ 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
-+ 2) APM flags from APM Installation Check (0x00):
-+ bit 0: APM_16_BIT_SUPPORT
-+ bit 1: APM_32_BIT_SUPPORT
-+ bit 2: APM_IDLE_SLOWS_CLOCK
-+ bit 3: APM_BIOS_DISABLED
-+ bit 4: APM_BIOS_DISENGAGED
-+ 3) AC line status
-+ 0x00: Off-line
-+ 0x01: On-line
-+ 0x02: On backup power (BIOS >= 1.1 only)
-+ 0xff: Unknown
-+ 4) Battery status
-+ 0x00: High
-+ 0x01: Low
-+ 0x02: Critical
-+ 0x03: Charging
-+ 0x04: Selected battery not present (BIOS >= 1.2 only)
-+ 0xff: Unknown
-+ 5) Battery flag
-+ bit 0: High
-+ bit 1: Low
-+ bit 2: Critical
-+ bit 3: Charging
-+ bit 7: No system battery
-+ 0xff: Unknown
-+ 6) Remaining battery life (percentage of charge):
-+ 0-100: valid
-+ -1: Unknown
-+ 7) Remaining battery life (time units):
-+ Number of remaining minutes or seconds
-+ -1: Unknown
-+ 8) min = minutes; sec = seconds */
-+
-+ p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-+ driver_version,
-+ (apm_bios_info.version >> 8) & 0xff,
-+ apm_bios_info.version & 0xff,
-+ apm_bios_info.flags,
-+ ac_line_status,
-+ battery_status,
-+ battery_flag,
-+ percentage,
-+ time_units,
-+ units);
-+
-+ return p - buf;
-+}
-+
-+#ifndef MODULE
-+static int __init apm_setup(char *str)
-+{
-+ int invert;
-+
-+ while ((str != NULL) && (*str != '\0')) {
-+ if (strncmp(str, "off", 3) == 0)
-+ apm_disabled = 1;
-+ if (strncmp(str, "on", 2) == 0)
-+ apm_disabled = 0;
-+ invert = (strncmp(str, "no-", 3) == 0);
-+ if (invert)
-+ str += 3;
-+ if (strncmp(str, "debug", 5) == 0)
-+ debug = !invert;
-+ if ((strncmp(str, "power-off", 9) == 0) ||
-+ (strncmp(str, "power_off", 9) == 0))
-+ power_off = !invert;
-+ str = strchr(str, ',');
-+ if (str != NULL)
-+ str += strspn(str, ", \t");
-+ }
-+ return 1;
-+}
-+
-+__setup("apm=", apm_setup);
-+#endif
-+
-+static struct file_operations apm_bios_fops = {
-+ owner: THIS_MODULE,
-+ read: do_read,
-+ poll: do_poll,
-+ ioctl: do_ioctl,
-+ open: do_open,
-+ release: do_release,
-+};
-+
-+static struct miscdevice apm_device = {
-+ APM_MINOR_DEV,
-+ "apm_bios",
-+ &apm_bios_fops
-+};
-+
-+#define APM_INIT_ERROR_RETURN return -1
-+
-+/*
-+ * Just start the APM thread. We do NOT want to do APM BIOS
-+ * calls from anything but the APM thread, if for no other reason
-+ * than the fact that we don't trust the APM BIOS. This way,
-+ * most common APM BIOS problems that lead to protection errors
-+ * etc will have at least some level of being contained...
-+ *
-+ * In short, if something bad happens, at least we have a choice
-+ * of just killing the apm thread..
-+ */
-+static int __init apm_init(void)
-+{
-+ if (apm_bios_info.version == 0) {
-+ printk(KERN_INFO "apm: BIOS not found.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+ printk(KERN_INFO
-+ "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
-+ ((apm_bios_info.version >> 8) & 0xff),
-+ (apm_bios_info.version & 0xff),
-+ apm_bios_info.flags,
-+ driver_version);
-+
-+ if (apm_disabled) {
-+ printk(KERN_NOTICE "apm: disabled on user request.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+
-+ if (PM_IS_ACTIVE()) {
-+ printk(KERN_NOTICE "apm: overridden by ACPI.\n");
-+ APM_INIT_ERROR_RETURN;
-+ }
-+ pm_active = 1;
-+
-+ create_proc_info_entry("apm", 0, NULL, apm_get_info);
-+
-+ misc_register(&apm_device);
-+
-+ return 0;
-+}
-+
-+static void __exit apm_exit(void)
-+{
-+ misc_deregister(&apm_device);
-+ remove_proc_entry("apm", NULL);
-+ if (power_off)
-+ pm_power_off = NULL;
-+ exit_kapmd = 1;
-+ while (kapmd_running)
-+ schedule();
-+ pm_active = 0;
-+}
-+
-+module_init(apm_init);
-+module_exit(apm_exit);
-+
-+MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
-+MODULE_DESCRIPTION("A minimal emulation of APM");
-+MODULE_PARM(debug, "i");
-+MODULE_PARM_DESC(debug, "Enable debug mode");
-+MODULE_PARM(power_off, "i");
-+MODULE_PARM_DESC(power_off, "Enable power off");
-+
-+EXPORT_NO_SYMBOLS;
---- linux-2.4.27/arch/arm/mach-sa1100/leds.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/mach-sa1100/leds.c
-@@ -45,6 +45,8 @@
- leds_event = pfs168_leds_event;
- if (machine_is_pt_system3())
- leds_event = system3_leds_event;
-+ if (machine_is_simpad())
-+ leds_event = simpad_leds_event;
-
- leds_event(led_start);
- return 0;
---- linux-2.4.27/arch/arm/mach-sa1100/leds.h~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/mach-sa1100/leds.h
-@@ -12,4 +12,6 @@
- extern void hackkit_leds_event(led_event_t evt);
- extern void lart_leds_event(led_event_t evt);
- extern void pfs168_leds_event(led_event_t evt);
-+extern void simpad_leds_event(led_event_t evt);
- extern void system3_leds_event(led_event_t evt);
-+
---- linux-2.4.27/arch/arm/mach-sa1100/pm.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/mach-sa1100/pm.c
-@@ -63,6 +63,7 @@
- SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
-
- SLEEP_SAVE_ICMR,
-+ SLEEP_SAVE_MECR,
- SLEEP_SAVE_Ser1SDCR0,
-
- SLEEP_SAVE_SIZE
-@@ -109,6 +110,8 @@
-
- SAVE(ICMR);
-
-+ SAVE(MECR);
-+
- /* ... maybe a global variable initialized by arch code to set this? */
- GRER = PWER;
- GFER = 0;
-@@ -163,6 +166,8 @@
- ICCR = 1;
- RESTORE(ICMR);
-
-+ RESTORE(MECR);
-+
- /* restore current time */
- xtime.tv_sec = RCNR + delta;
-
---- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c
-@@ -10,6 +10,7 @@
- #include <linux/tty.h>
- #include <linux/proc_fs.h>
- #include <linux/string.h>
-+#include <linux/pm.h>
-
- #include <asm/hardware.h>
- #include <asm/setup.h>
-@@ -28,6 +29,11 @@
- return cs3_shadow;
- }
-
-+void set_cs3(long value)
-+{
-+ *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
-+}
-+
- void set_cs3_bit(int value)
- {
- cs3_shadow |= value;
-@@ -40,31 +46,62 @@
- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
- }
-
-+EXPORT_SYMBOL(set_cs3_bit);
-+EXPORT_SYMBOL(clear_cs3_bit);
-+
-+static void simpad_power_off(void)
-+{
-+ cli();
-+ set_cs3(0x800); /* only SD_MEDIAQ */
-+
-+ /* disable internal oscillator, float CS lines */
-+ PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
-+ /* enable wake-up on GPIO0 (Assabet...) */
-+ PWER = GFER = GRER = 1;
-+ /*
-+ * set scratchpad to zero, just in case it is used as a
-+ * restart address by the bootloader.
-+ */
-+ PSPR = 0;
-+ PGSR = 0;
-+ /* enter sleep mode */
-+ PMCR = PMCR_SF;
-+ while(1);
-+}
-+
-+static int __init simpad_init(void)
-+{
-+ pm_power_off = simpad_power_off;
-+ return 0;
-+}
-+
-+__initcall(simpad_init);
-+
- static void __init
- fixup_simpad(struct machine_desc *desc, struct param_struct *params,
- char **cmdline, struct meminfo *mi)
- {
--#ifdef CONFIG_SA1100_SIMPAD_DRAM_64MB /* DRAM */
-- SET_BANK( 0, 0xc0000000, 64*1024*1024 );
--#else
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
- SET_BANK( 0, 0xc0000000, 32*1024*1024 );
-+#else
-+ SET_BANK( 0, 0xc0000000, 64*1024*1024 );
- #endif
- mi->nr_banks = 1;
-- ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+
- setup_ramdisk( 1, 0, 0, 8192 );
- setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
- }
-
--
- static struct map_desc simpad_io_desc[] __initdata = {
-- /* virtual physical length domain r w c b */
-- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 },
-- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
-- { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
-+ /* virtual physical length domain r w c b */
-+ { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },
-+ { 0xe9000000, 0x08000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 },
-+ { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CS3, write only */
-+ { 0xf2000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CS4, tda8007 */
-+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
- LAST_DESC
- };
-
--
- static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
- {
- if (port->mapbase == (u_int)&Ser1UTCR0) {
-@@ -81,20 +118,32 @@
-
- static void __init simpad_map_io(void)
- {
-- sa1100_map_io();
-- iotable_init(simpad_io_desc);
-+ sa1100_map_io();
-+ iotable_init(simpad_io_desc);
-
-- PSPR = 0xc0008000;
-- GPDR &= ~GPIO_GPIO0;
-- cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-- ENABLE_5V | RESET_SIMCARD);
-- *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
-+ set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-+ ENABLE_5V | nRESET_SIMCARD);
-
-- //It is only possible to register 3 UART in serial_sa1100.c
-- sa1100_register_uart(0, 3);
-- sa1100_register_uart(1, 1);
-+ //It is only possible to register 3 UART in serial_sa1100.c
-+ sa1100_register_uart(0, 3);
-+ sa1100_register_uart(1, 1);
-
-- set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
-+ GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
-+ GPDR |= GPIO_UART_TXD;
-+ GPDR &= ~GPIO_UART_RXD;
-+ PPAR |= PPAR_UPR;
-+
-+ set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
-+ set_GPIO_IRQ_edge(GPIO_POWER_BUTTON, GPIO_FALLING_EDGE);
-+
-+ /*
-+ * Set up registers for sleep mode.
-+ */
-+
-+ PWER = PWER_GPIO0;
-+ PGSR = 0x818;
-+ PCFR = 0;
-+ PSDR = 0;
- }
-
- #ifdef CONFIG_PROC_FS
-@@ -140,7 +189,17 @@
-
- return len;
- }
--
-+
-+static int proc_cs3_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ unsigned long newRegValue;
-+ char *endp;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ set_cs3( newRegValue );
-+ return (count+endp-buffer);
-+}
-
- static struct proc_dir_entry *proc_cs3;
-
-@@ -148,7 +207,10 @@
- {
- proc_cs3 = create_proc_entry("cs3", 0, 0);
- if (proc_cs3)
-+ {
- proc_cs3->read_proc = proc_cs3_read;
-+ proc_cs3->write_proc = (void*)proc_cs3_write;
-+ }
- return 0;
- }
-
-@@ -165,6 +227,7 @@
- MACHINE_START(SIMPAD, "Simpad")
- MAINTAINER("Juergen Messerer")
- BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-+ BOOT_PARAMS(0xc0000100)
- FIXUP(fixup_simpad)
- MAPIO(simpad_map_io)
- INITIRQ(sa1100_init_irq)
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/simpad_pm.c
-@@ -0,0 +1,147 @@
-+/*
-+* Powermanagement layer for SIMPad.
-+*
-+* Copyright 2003 Peter Pregler
-+* Copyright 2000,2001 Compaq Computer Corporation.
-+*
-+* Use consistent with the GNU GPL is permitted,
-+* provided that this copyright notice is
-+* preserved in its entirety in all copies and derived works.
-+*
-+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-+* FITNESS FOR ANY PARTICULAR PURPOSE.
-+*
-+* Author: Peter Pregler (based on work for ipaq by Andrew Christian)
-+* May, 2003
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/poll.h>
-+#include <asm/uaccess.h> /* get_user,copy_to_user */
-+#include <linux/string.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/console.h>
-+#include <linux/devfs_fs_kernel.h>
-+
-+#include <linux/tqueue.h>
-+#include <linux/sched.h>
-+#include <linux/pm.h>
-+#include <linux/proc_fs.h>
-+#include <linux/apm_bios.h>
-+#include <linux/kmod.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/arch-sa1100/simpad_pm.h>
-+
-+MODULE_AUTHOR("Peter Pregler");
-+MODULE_DESCRIPTION("Power manamgement abstraction layer for the SIMpad");
-+
-+/****************************************************************************/
-+/* Functions exported for use by the kernel and kernel modules */
-+/****************************************************************************/
-+
-+int simpad_apm_get_power_status(u_char *ac_line_status,
-+ u_char *battery_status,
-+ u_char *battery_flag,
-+ u_char *battery_percentage,
-+ u_short *battery_life)
-+{
-+ struct simpad_battery bstat;
-+ unsigned char ac = APM_AC_UNKNOWN;
-+ unsigned char level = APM_BATTERY_STATUS_UNKNOWN;
-+ int status, result;
-+
-+ result = simpad_get_battery(&bstat);
-+ if (result) {
-+ printk("%s: unable to access battery information: result=%d\n", __FUNCTION__, result);
-+ return 0;
-+ }
-+
-+ switch (bstat.ac_status) {
-+ case SIMPAD_AC_STATUS_AC_OFFLINE:
-+ ac = APM_AC_OFFLINE;
-+ break;
-+ case SIMPAD_AC_STATUS_AC_ONLINE:
-+ ac = APM_AC_ONLINE;
-+ break;
-+ case SIMPAD_AC_STATUS_AC_BACKUP:
-+ ac = APM_AC_BACKUP;
-+ break;
-+ }
-+
-+ if (ac_line_status != NULL)
-+ *ac_line_status = ac;
-+
-+ status = bstat.status;
-+ if (status & (SIMPAD_BATT_STATUS_CHARGING | SIMPAD_BATT_STATUS_CHARGE_MAIN))
-+ level = APM_BATTERY_STATUS_CHARGING;
-+ else if (status & (SIMPAD_BATT_STATUS_HIGH | SIMPAD_BATT_STATUS_FULL))
-+ level = APM_BATTERY_STATUS_HIGH;
-+ else if (status & SIMPAD_BATT_STATUS_LOW)
-+ level = APM_BATTERY_STATUS_LOW;
-+ else if (status & SIMPAD_BATT_STATUS_CRITICAL)
-+ level = APM_BATTERY_STATUS_CRITICAL;
-+
-+ if (battery_status != NULL)
-+ *battery_status = level;
-+
-+ if (battery_percentage != NULL)
-+ *battery_percentage = bstat.percentage;
-+
-+ /* we have a dumb battery - so we know nothing */
-+ if (battery_life != NULL) {
-+ *battery_life = APM_BATTERY_LIFE_UNKNOWN;
-+ }
-+
-+#if 0
-+ printk("apm_get_power: ac: %02x / bs: %02x / bf: %02x / perc: %02x / life: %d\n",
-+ *ac_line_status, *battery_status, *battery_flag,
-+ *battery_percentage, *battery_life );
-+#endif
-+ return 1;
-+}
-+
-+EXPORT_SYMBOL(simpad_apm_get_power_status);
-+
-+
-+/***********************************************************************************/
-+/* Initialization */
-+/***********************************************************************************/
-+
-+#ifdef CONFIG_FB_MQ200
-+extern void (*mq200_blank_helper)(int blank);
-+#endif
-+
-+int __init simpad_hal_init_module(void)
-+{
-+ int i;
-+ printk(KERN_INFO "SIMpad Registering HAL abstraction layer\n");
-+
-+ /* Request the appropriate underlying module to provide services */
-+
-+#ifdef CONFIG_FB_SA1100
-+ sa1100fb_blank_helper = simpad_hal_backlight_helper;
-+#endif
-+
-+ return 0;
-+}
-+
-+void simpad_hal_cleanup_module(void)
-+{
-+ int i;
-+ printk(KERN_INFO "SIMpad shutting down HAL abstraction layer\n");
-+
-+#ifdef CONFIG_FB_SA1100
-+ sa1100fb_blank_helper = NULL;
-+#endif
-+}
-+
-+module_init(simpad_hal_init_module);
-+module_exit(simpad_hal_cleanup_module);
---- linux-2.4.27/drivers/char/Config.in~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/char/Config.in
-@@ -424,4 +424,7 @@
- tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO
- fi
-
-+if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then
-+ tristate 'Smartcardreader(TDA8007) support' CONFIG_TDA8007
-+fi
- endmenu
---- linux-2.4.27/drivers/char/Makefile~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/char/Makefile
-@@ -376,6 +376,8 @@
- obj-y += ipmi/ipmi.o
- endif
-
-+obj-$(CONFIG_TDA8007) += tda8007.o
-+
- include $(TOPDIR)/Rules.make
-
- fastdep:
---- /dev/null
-+++ linux-2.4.27/drivers/char/tda8007.c
-@@ -0,0 +1,514 @@
-+/*
-+ * linux/drivers/char/tda8007.c
-+ *
-+ * Copyright (C) 2001 juergen.messerer@freesurf.ch, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * The TDA8007B driver provides basic services for handling IO,
-+ * interrupts, and accessing registers.
-+ */
-+
-+#include <linux/delay.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/simpad.h>
-+#include <asm/uaccess.h>
-+
-+#include "tda8007b.h"
-+
-+#define TDA8007_DIRNAME "driver/tda8007"
-+#define REG_DIRNAME "registers"
-+
-+extern void clear_cs3_bit(int value);
-+
-+static struct proc_dir_entry *regdir;
-+static struct proc_dir_entry *tda8007dir;
-+
-+static ssize_t proc_tda8007_read(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos);
-+static ssize_t proc_tda8007_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos);
-+
-+static struct file_operations proc_reg_operations = {
-+ read: proc_tda8007_read,
-+ write: proc_tda8007_write
-+};
-+
-+static int __init tda8007_init();
-+
-+/* ------------------------------------------------------------------------- */
-+void tda8007_reg_write(int reg, int val)
-+{
-+ printk("Address:%x \n", CS4_BASE+reg);
-+ printk("Value:%x \n", val);
-+ TDA_REG_WRITE(reg,val);
-+}
-+/* ------------------------------------------------------------------------- */
-+int tda8007_reg_read(int reg)
-+{
-+ printk("Address:%x \n", CS4_BASE+reg);
-+ return(TDA_REG_READ(reg)&0xff);
-+}
-+/* ------------------------------------------------------------------------- */
-+int tdaregs[16];
-+/* ------------------------------------------------------------------------- */
-+static void tda8007_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ printk("\n****tda8007_irq****\n");
-+}
-+/* ------------------------------------------------------------------------- */
-+static int tda_card_present( uint cardport )
-+{
-+ int val=0;
-+
-+ switch( cardport )
-+ {
-+ case CARD_PORT1:
-+ if( tda8007_reg_read(TDA_MSR) & TDA_MSR_PR1 )
-+ val = 1;
-+ break;
-+ case CARD_PORT2:
-+ if( tda8007_reg_read(TDA_MSR) & TDA_MSR_PR2 )
-+ val = 1;
-+ break;
-+ default:
-+ val =0;
-+ break;
-+ }
-+
-+ return val;
-+}
-+/* ------------------------------------------------------------------------- */
-+void tda_inituart(void)
-+{
-+ int hsr_reg, fcr_reg;
-+
-+ printk("Init TDA8007 Uart\n");
-+ hsr_reg = tda8007_reg_read(TDA_HSR);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ tda8007_reg_write(TDA_CSR, 0x00);
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_SC1); /* select Card 1 */
-+
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC1);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ tda8007_reg_write(TDA_PDR, TDA_PDR_VAL); /* Rat v. jandu 8.9.2000 */
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR2_DIV);
-+
-+ tda8007_reg_write(TDA_CCR, 0x40|TDA_CCR_AC1); /*1=XTAL/2 2=XTAL/4 3=XTAL/8 */
-+ tda8007_reg_write(TDA_GTR, TDA_GTR_GT1);
-+
-+ fcr_reg = tda8007_reg_read(TDA_FCR);
-+ tda8007_reg_write(TDA_FCR, (fcr_reg & 0xf0) | TDA_FCR_FL1);
-+
-+ tda8007_reg_write(TDA_FCR, TDA_FCR_FL2|TDA_FCR_FL1|TDA_FCR_FL0);
-+ tda8007_reg_write(TDA_UCR1, TDA_UCR_SS|TDA_UCR_CONV);
-+ tda8007_reg_write(TDA_PCR, 0x00);
-+
-+ while( tda8007_reg_read(TDA_USR) & TDA_USR_TBE_RBF )
-+ {
-+ hsr_reg = tda8007_reg_read(TDA_URR);
-+ udelay(5);
-+ }
-+}
-+/* ------------------------------------------------------------------------- */
-+void start_tda8007_sync(int volt)
-+{
-+ int i=0,j=0;
-+ if( tda_card_present( CARD_PORT1 ) )
-+ {
-+ printk("Card Present ");
-+ tda8007_reg_write(TDA_TOR1, TDA_TOR1_TOL2|TDA_TOR1_TOL3);
-+ tda8007_reg_write(TDA_TOR2, TDA_TOR2_TOL16|TDA_TOR2_TOL15|
-+ TDA_TOR2_TOL13|TDA_TOR2_TOL12|
-+ TDA_TOR2_TOL11);
-+ tda8007_reg_write(TDA_TOR3, 0x00);
-+ tda8007_reg_write(TDA_TOC, TDA_TOC_MODE2);
-+ tda_inituart();
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX ASYNC MODE
-+
-+ if( volt == 3 )
-+ volt = TDA_PCR_3V_5V;
-+ else
-+ volt = 0x00;
-+
-+ tda8007_reg_write(TDA_PCR, 0x00|volt); // Set /Reset,3V
-+ udelay(1000);
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_START|volt); // /Reset,3V,Start
-+ udelay(2000);
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_RSTIN|TDA_PCR_START|volt); // Set Reset High
-+ i=0;
-+ while( 1 )// !serstat()
-+ {
-+ if( ((msr[i]=tda8007_reg_read(TDA_MSR)) & TDA_MSR_FE) == 0 )
-+ {
-+ hsr[i]=tda8007_reg_read(TDA_HSR);
-+ usr[i]=tda8007_reg_read(TDA_USR);
-+ csr[i]=tda8007_reg_read(TDA_CSR);
-+ urr[i]=tda8007_reg_read(TDA_URR);
-+ i++;
-+ }
-+ if( i == 1 )
-+ {
-+ /* Reset SS */
-+ tda8007_reg_write(TDA_UCR1,
-+ tda8007_reg_read(TDA_UCR1) & ~TDA_UCR_SS);
-+ /* Set Autoconv high */
-+ tda8007_reg_write(TDA_UCR2,
-+ tda8007_reg_read(TDA_UCR2) | TDA_UCR_nAUTOCONV);
-+ }
-+
-+ if( i >= BUFFSIZE )
-+ {
-+ printk("Buffer Overflow");
-+ break;
-+ }
-+ // tda8007_reg_write(TDA_FCR, TDA_FCR_PEC0|TDA_FCR_FL0);
-+ }
-+ hsr[i]=tda8007_reg_read(TDA_HSR);
-+ msr[i]=tda8007_reg_read(TDA_MSR);
-+ csr[i]=tda8007_reg_read(TDA_CSR);
-+ urr[i]=tda8007_reg_read(TDA_URR);
-+ i++;
-+ //serin();
-+ if( i==1 )
-+ printk("No Characters received\n");
-+ else
-+ for(j=0;j<i-1; j++)
-+ printk("Buffer[%3d]=USR(0x%02x) HSR(0x%02x) MSR(0x%02x) CSR(0x%02x) URR(0x%02x=%c)\n",
-+ j,usr[j],hsr[j],msr[j],csr[j],urr[j],pascii(urr[j]));
-+
-+ printk("Now USR(0x%02x) HSR(0x%02x) MSR(0x%02x) CSR(0x%02x) URR(0x%02x=%c)\n",
-+ usr[j],hsr[j],msr[j],csr[j],urr[j],pascii(urr[j]));
-+
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_RSTIN|volt); // remove start
-+ udelay(2000);
-+ tda8007_reg_write(TDA_PCR, 0x00|volt); // remove Reset
-+
-+ }
-+ else
-+ {
-+ tda8007_reg_write(TDA_PCR, TDA_PCR_3V_5V);
-+ }
-+
-+}
-+/* -------------------------------------------------------------------------*/
-+int test_tda8007(void)
-+{
-+ int c, i,j, reg,end=0;
-+
-+ printk("\nTDA8007 TEST:");
-+
-+ for( i=0; i < 0x10; i++ )
-+ printk("\nTDA8007 Reg %2d = 0x%02x ", i, tda8007_reg_read(i)&0xff);
-+
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tdaregs[i]=tda8007_reg_read(i) & 0xff;
-+ }
-+ do
-+ {
-+ printk("\nTDA8007 IRQ=%s Command:",
-+ (GPLR&(1<<10) ? "HIGH":"LOW"));
-+
-+ //c=serin();
-+ //serout(c);
-+ printk("\n");
-+
-+ switch (c )
-+ {
-+
-+ case 'c':
-+ printk("\nReg?:");
-+ //reg=gethex(serin,serout);
-+ printk("\nVal?:");
-+ //i=gethex(serin,serout);
-+ tda8007_reg_write(reg,i);
-+ j=tda8007_reg_read(reg);
-+ printk("Reg 0x%02x (0x%02x) now 0x%02x\n", reg, i, j);
-+ break;
-+
-+ case 'i':
-+ printk("\nInit\n");
-+ tda8007_init();
-+
-+ case 'p':
-+ for( i=0; i < 0x10; i++ )
-+ printk("\nTDA8007 Reg %2d = 0x%02x ", i,
-+ tda8007_reg_read(i)&0xff);
-+ break;
-+ case 'e':
-+ end=1;
-+ break;
-+
-+ case 'r':
-+ while( 1 ) // serstat() == 0
-+ {
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tdaregs[i]=tda8007_reg_read(i) & 0xff;
-+ }
-+ }
-+ //serin();
-+ break;
-+
-+ case 'S':
-+ start_tda8007_sync(5);
-+ break;
-+ case 's':
-+ start_tda8007_sync(3);
-+ break;
-+ case 'w':
-+ while( 1 )//serstat() == 0
-+ {
-+ for( i=0 ;i < 0x10; i++ )
-+ {
-+ tda8007_reg_write(i,0x10-i);
-+ }
-+ }
-+ //serin();
-+ break;
-+
-+ default :
-+ //serout(0x07);
-+ break;
-+ }
-+
-+ }while( end == 0 );
-+ return(0);
-+}
-+/*-------------------------------------------------------------------------*/
-+static int tda8007_ioctl(struct inode *ino, struct file *filp,
-+ uint cmd, ulong arg)
-+{
-+ unsigned int val, gain;
-+ int ret = 0;
-+
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ switch (_IOC_NR(cmd))
-+ {
-+ case TDA_INFO:
-+ break;
-+
-+ case TDA_INIT:
-+ break;
-+
-+ case TDA_SET:
-+ break;
-+
-+ case TDA_CARD_PRESENT:
-+ break;
-+
-+ case TDA_CARD_VOLT:
-+ break;
-+
-+ default:
-+ val = 0;
-+ ret = -EINVAL;
-+ break;
-+ }
-+ return ret;
-+}
-+/* ------------------------------------------------------------------------- */
-+static ssize_t proc_tda8007_read( struct file *file, char *buf, size_t nbytes,
-+ loff_t *ppos)
-+{
-+ char outputbuf[80];
-+ int count = 0;
-+ int i = 0;
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ tda8007_reg_entry_t* current_reg = NULL;
-+
-+ if ((*ppos) > 0) /* Assume reading completed in previous read*/
-+ return 0;
-+
-+ for (i=0; i<NUM_OF_TDA8007_REG_ENTRY; i++)
-+ {
-+ if (tda8007_regs[i].low_ino==i_ino)
-+ {
-+ if( tda8007_regs[i].mode == 2 ) /* write only */
-+ {
-+ printk("%s\n", tda8007_regs[i].description);
-+ printk("Read operation is on this register not possible!\n");
-+ return -EINVAL;
-+ }
-+ current_reg = &tda8007_regs[i];
-+
-+ break;
-+ }
-+ }
-+
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ printk("%s\n", current_reg->description);
-+ count += sprintf(outputbuf, "%s: 0x%x\n", current_reg->name,
-+ tda8007_reg_read( current_reg->addr ));
-+ /* count = sprintf(outputbuf, "value: 0x%x\n",
-+ tda8007_reg_read( current_reg->addr ));*/
-+
-+ *ppos+=count;
-+
-+ if (count>nbytes) /* Assume output can be read at one time */
-+ return -EINVAL;
-+
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+
-+ return count;
-+}
-+/* ------------------------------------------------------------------------- */
-+static ssize_t proc_tda8007_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ int i;
-+ unsigned long newRegValue;
-+ char *endp;
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ tda8007_reg_entry_t* current_reg=NULL;
-+
-+ for (i=0; i<NUM_OF_TDA8007_REG_ENTRY; i++)
-+ {
-+ if (tda8007_regs[i].low_ino==i_ino)
-+ {
-+ if( tda8007_regs[i].mode == 1 ) /* read only */
-+ {
-+ printk("%s\n", tda8007_regs[i].description);
-+ printk("Write operation is on this register not possible!\n");
-+ return -EINVAL;
-+ }
-+ current_reg = &tda8007_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ tda8007_reg_write( current_reg->addr, newRegValue);
-+ return (count+endp-buffer);
-+}
-+/* ------------------------------------------------------------------------- */
-+static int __init tda8007_init()
-+{
-+ int i, hsr_reg, res;
-+ int ret = -ENODEV;
-+ struct proc_dir_entry *entry;
-+ int tda8007_major = 60;
-+
-+ res = register_chrdev( tda8007_major, "tda8007", NULL );
-+
-+ if(res < 0){
-+ printk(KERN_WARNING "tda8007: can't get major%d\n", tda8007_major);
-+ return res;
-+ }
-+
-+ if( tda8007_major == 0 )
-+ tda8007_major = res;
-+
-+ set_GPIO_IRQ_edge(GPIO_SMART_CARD, GPIO_RISING_EDGE);
-+
-+ ret = request_irq( IRQ_GPIO_SMART_CARD, tda8007_irq,
-+ SA_INTERRUPT, "SMARTCARD_CD", NULL );
-+ if (ret) {
-+ printk(KERN_ERR "tda8007: unable to grab irq%d: %d\n",
-+ IRQ_GPIO_SMART_CARD, ret);
-+ return ret;
-+ }
-+
-+ printk("\nInit TDA8007 IRQ=%s\n",
-+ (GPLR&(1<<10) ? "HIGH":"LOW"));
-+
-+// clear_cs3_bit(RESET_SIMCARD);
-+
-+
-+#ifdef CONFIG_PROC_FS
-+ /* Create two dir entries for the TDA8007 */
-+ tda8007dir = proc_mkdir("tda8007"/*TDA8007_DIRNAME*/, NULL);
-+ if (tda8007dir == NULL) {
-+ printk(KERN_ERR "tda80007: can't create /proc/" TDA8007_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ regdir = proc_mkdir(REG_DIRNAME, tda8007dir);
-+ if (regdir == NULL) {
-+ printk(KERN_ERR "tda8007: can't create /proc/" TDA8007_DIRNAME "/" REG_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ for(i=0;i<NUM_OF_TDA8007_REG_ENTRY;i++) {
-+ entry = create_proc_entry(tda8007_regs[i].name,
-+ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH,
-+ regdir);
-+ if(entry) {
-+ tda8007_regs[i].low_ino = entry->low_ino;
-+ entry->proc_fops = &proc_reg_operations;
-+ }
-+ else {
-+ printk( KERN_ERR
-+ "tda8007: can't create /proc/" REG_DIRNAME
-+ "/%s\n", tda8007_regs[i].name);
-+ return(-ENOMEM);
-+ }
-+ }
-+
-+#endif // CONFIG_PROC_FS
-+
-+
-+ tda8007_reg_write(TDA_CSR, 0);
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU);
-+ for( i=0; i < 16; i++ )
-+ tda8007_reg_write(i,0);
-+
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC2);
-+ tda8007_reg_write(TDA_PCR, 0); /* START=0 */
-+ tda8007_reg_write(TDA_CSR, TDA_CSR_nRIU|TDA_CSR_SC1);
-+ tda8007_reg_write(TDA_PCR, 0); /* START=0 */
-+ tda8007_reg_write(TDA_TOC, 0);
-+ tda8007_reg_write(TDA_FCR, TDA_FCR_FL2|TDA_FCR_FL1|TDA_FCR_FL0);
-+
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX DIS_CLK
-+ tda8007_reg_write(TDA_UCR2, TDA_UCR_DISAUX|TDA_UCR2_DIV); // DIS_AUX CLK SYNC-MODE
-+ hsr_reg = tda8007_reg_read(TDA_HSR);
-+
-+ tda8007_reg_write(TDA_CCR, TDA_CCR_AC1|TDA_CCR_AC0); /* XTAL/8 */
-+
-+ return 0;
-+}
-+/* ------------------------------------------------------------------------- */
-+static void __exit tda8007_exit(void)
-+{
-+ int i;
-+
-+ free_irq(IRQ_GPIO_SMART_CARD, NULL);
-+ /* kfree(my_ucb);*/
-+
-+ if (regdir)
-+ {
-+ for(i=0;i<NUM_OF_TDA8007_REG_ENTRY;i++) {
-+ remove_proc_entry( tda8007_regs[i].name, regdir);
-+ }
-+ }
-+}
-+/* ------------------------------------------------------------------------- */
-+module_init(tda8007_init);
-+module_exit(tda8007_exit);
-+
-+MODULE_AUTHOR("Juergen Messerer <juergen.messerer@freesurf.ch>");
-+MODULE_DESCRIPTION("TDA8007 driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/char/tda8007b.h
-@@ -0,0 +1,312 @@
-+/*
-+ * Double multiprotocol IC car interface (Philips SmartCard reader)
-+ *
-+ * linux/drivers/char/tda8007b.h
-+ *
-+ * Copyright (C) 2002 juergen.messerer@freesurf.ch, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef TDA8007B_H
-+#define TDA8007B_H
-+
-+#define CS4BUSTYPE unsigned volatile long
-+#define CS4_BASE 0xf2000000
-+
-+#define CARD_PORT1 1
-+#define CARD_PORT2 2
-+#define CARD_PORT3 3
-+
-+#define TDA_REG_READ(reg) *(CS4BUSTYPE *)(CS4_BASE+reg)
-+#define TDA_REG_WRITE(reg,val) *(CS4BUSTYPE *)(CS4_BASE+reg)=val
-+
-+#define TDA_MULTIPLEXED_MODE 0
-+
-+#define TDA_UCR2_DIV 0
-+#define TDA_PDR_VAL 12
-+
-+#define pascii(i) ((i>=' ' && i < 0x7f) ? (i):'.')
-+
-+#define BUFFSIZE 128
-+
-+#define TDA_READ 1
-+#define TDA_WRITE 2
-+
-+#define TDA_INFO 1
-+#define TDA_INIT 2
-+#define TDA_SET 3
-+#define TDA_CARD_PRESENT 4
-+#define TDA_CARD_VOLT 5
-+
-+int hsr[BUFFSIZE];
-+int msr[BUFFSIZE];
-+int csr[BUFFSIZE];
-+int urr[BUFFSIZE];
-+int usr[BUFFSIZE];
-+
-+/*************************** Control Register ********************************/
-+
-+/*
-+ * Card select register (read/write)
-+ * all significant bits are cleared execept SC1 which is set (xxxx'0001)
-+ */
-+#define TDA_CSR 0x00
-+#define TDA_CSR_SC1 (1 << 0)
-+#define TDA_CSR_SC2 (1 << 1)
-+#define TDA_CSR_SC3 (1 << 2)
-+#define TDA_CSR_nRIU (1 << 3)
-+
-+/*
-+ * Clock configuration register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_CCR 0x01
-+#define TDA_CCR_AC0 (1 << 0)
-+#define TDA_CCR_AC1 (1 << 1)
-+#define TDA_CCR_AC2 (1 << 2)
-+#define TDA_CCR_SC (1 << 3)
-+#define TDA_CCR_CST (1 << 4)
-+#define TDA_CCR_SHL (1 << 5)
-+
-+/*
-+ * Programmable divider register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_PDR 0x02
-+#define TDA_PDR_PD0 (1 << 0)
-+#define TDA_PDR_PD1 (1 << 1)
-+#define TDA_PDR_PD2 (1 << 2)
-+#define TDA_PDR_PD3 (1 << 3)
-+#define TDA_PDR_PD4 (1 << 4)
-+#define TDA_PDR_PD5 (1 << 5)
-+#define TDA_PDR_PD6 (1 << 6)
-+#define TDA_PDR_PD7 (1 << 7)
-+
-+/*
-+ * UART configuration register 2(read/write)
-+ * all relevant bits are cleared after reset (x000'0000)
-+ */
-+#define TDA_UCR2 0x03
-+#define TDA_UCR_PSC (1 << 0)
-+#define TDA_UCR_CKU (1 << 1)
-+#define TDA_UCR_nAUTOCONV (1 << 2)
-+#define TDA_UCR_SAN (1 << 3)
-+#define TDA_UCR_PDWN (1 << 4)
-+#define TDA_UCR_DISAUX (1 << 5)
-+#define TDA_UCR_DISTBE_RBF (1 << 6)
-+
-+/*
-+ * Guard time register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_GTR 0x05
-+#define TDA_GTR_GT0 (1 << 0)
-+#define TDA_GTR_GT1 (1 << 1)
-+#define TDA_GTR_GT2 (1 << 2)
-+#define TDA_GTR_GT3 (1 << 3)
-+#define TDA_GTR_GT4 (1 << 4)
-+#define TDA_GTR_GT5 (1 << 5)
-+#define TDA_GTR_GT6 (1 << 6)
-+#define TDA_GTR_GT7 (1 << 7)
-+
-+/*
-+ * UART configuration register 1(read/write)
-+ * all relevant bits are cleared after reset (x000'0000)
-+ */
-+#define TDA_UCR1 0x06
-+#define TDA_UCR_CONV (1 << 0)
-+#define TDA_UCR_SS (1 << 1)
-+#define TDA_UCR_LCT (1 << 2)
-+#define TDA_UCR_T_R (1 << 3)
-+#define TDA_UCR_PROT (1 << 4)
-+#define TDA_UCR_FC (1 << 5)
-+#define TDA_UCR_FIP (1 << 6)
-+
-+/*
-+ * Power control register (read/write)
-+ * all relevant bits are cleared after reset (xx11'0000)
-+ */
-+#define TDA_PCR 0x07
-+#define TDA_PCR_START (1 << 0)
-+#define TDA_PCR_3V_5V (1 << 1)
-+#define TDA_PCR_RSTIN (1 << 2)
-+#define TDA_PCR_1V8 (1 << 3)
-+#define TDA_PCR_C4 (1 << 4)
-+#define TDA_PCR_C8 (1 << 5)
-+
-+/*
-+ * Time-out configuration register (read/write)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOC 0x08
-+#define TDA_TOC_STOP_ALL 0x00
-+#define TDA_TOC_MODE1 0x61
-+#define TDA_TOC_MODE2 0x65
-+#define TDA_TOC_MODE3 0x68
-+#define TDA_TOC_MODE4 0x7c
-+#define TDA_TOC_MODE5 0xe5
-+
-+/*
-+ * Time-out register 1(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR1 0x09
-+#define TDA_TOR1_TOL0 (1 << 0)
-+#define TDA_TOR1_TOL1 (1 << 1)
-+#define TDA_TOR1_TOL2 (1 << 2)
-+#define TDA_TOR1_TOL3 (1 << 3)
-+#define TDA_TOR1_TOL4 (1 << 4)
-+#define TDA_TOR1_TOL5 (1 << 5)
-+#define TDA_TOR1_TOL6 (1 << 6)
-+#define TDA_TOR1_TOL7 (1 << 7)
-+
-+/*
-+ * Time-out register 2(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR2 0x0a
-+#define TDA_TOR2_TOL10 (1 << 0)
-+#define TDA_TOR2_TOL11 (1 << 1)
-+#define TDA_TOR2_TOL12 (1 << 2)
-+#define TDA_TOR2_TOL13 (1 << 3)
-+#define TDA_TOR2_TOL14 (1 << 4)
-+#define TDA_TOR2_TOL15 (1 << 5)
-+#define TDA_TOR2_TOL16 (1 << 6)
-+#define TDA_TOR2_TOL17 (1 << 7)
-+
-+/*
-+ * Time-out register 3(write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_TOR3 0x0b
-+#define TDA_TOR3_TOL16 (1 << 0)
-+#define TDA_TOR3_TOL17 (1 << 1)
-+#define TDA_TOR3_TOL18 (1 << 2)
-+#define TDA_TOR3_TOL19 (1 << 3)
-+#define TDA_TOR3_TOL20 (1 << 4)
-+#define TDA_TOR3_TOL21 (1 << 5)
-+#define TDA_TOR3_TOL22 (1 << 6)
-+#define TDA_TOR3_TOL23 (1 << 7)
-+
-+/*
-+ * Mixed status register (read only)
-+ * bits TBE, RBF and BGT are cleared, bit FE is set after reset (x10x'xxx0)
-+ */
-+#define TDA_MSR 0x0c
-+#define TDA_MSR_TBE_RBF (1 << 0)
-+#define TDA_MSR_INTAUX (1 << 1)
-+#define TDA_MSR_PR1 (1 << 2)
-+#define TDA_MSR_PR2 (1 << 3)
-+#define TDA_MSR_BGT (1 << 5)
-+#define TDA_MSR_FE (1 << 6)
-+
-+/*
-+ * FIFO control register (write only)
-+ * all relevant bits are cleared after reset (x000'x000)
-+ */
-+#define TDA_FCR 0x0c
-+#define TDA_FCR_FL0 (1 << 0)
-+#define TDA_FCR_FL1 (1 << 1)
-+#define TDA_FCR_FL2 (1 << 2)
-+#define TDA_FCR_PEC0 (1 << 4)
-+#define TDA_FCR_PEC1 (1 << 5)
-+#define TDA_FCR_PEC2 (1 << 6)
-+
-+/*
-+ * UART transmit register (write only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_UTR 0x0d
-+#define TDA_UTR_UT0 (1 << 0)
-+#define TDA_UTR_UT1 (1 << 1)
-+#define TDA_UTR_UT2 (1 << 2)
-+#define TDA_UTR_UT3 (1 << 3)
-+#define TDA_UTR_UT4 (1 << 4)
-+#define TDA_UTR_UT5 (1 << 5)
-+#define TDA_UTR_UT6 (1 << 6)
-+#define TDA_UTR_UT7 (1 << 7)
-+
-+/*
-+ * UART receive register (read only)
-+ * all bits are cleared (0000'0000)
-+ */
-+#define TDA_URR 0x0d
-+#define TDA_URR_UR0 (1 << 0)
-+#define TDA_URR_UR1 (1 << 1)
-+#define TDA_URR_UR2 (1 << 2)
-+#define TDA_URR_UR3 (1 << 3)
-+#define TDA_URR_UR4 (1 << 4)
-+#define TDA_URR_UR5 (1 << 5)
-+#define TDA_URR_UR6 (1 << 6)
-+#define TDA_URR_UR7 (1 << 7)
-+
-+/*
-+ * UART status register (read only)
-+ * all bits are cleared (0x00'0000)
-+ */
-+#define TDA_USR 0x0e
-+#define TDA_USR_TBE_RBF (1 << 0)
-+#define TDA_USR_FER (1 << 1)
-+#define TDA_USR_OVR (1 << 2)
-+#define TDA_USR_PE (1 << 3)
-+#define TDA_USR_EA (1 << 4)
-+#define TDA_USR_TO1 (1 << 5)
-+#define TDA_USR_TO3 (1 << 7)
-+
-+/*
-+ * Hardware status register (read only)
-+ * all significant bits are cleared, except SUPL (x001'0000)
-+ */
-+#define TDA_HSR 0x0f
-+#define TDA_HSR_PTL (1 << 0)
-+#define TDA_HSR_INTAUXL (1 << 1)
-+#define TDA_HSR_PRL1 (1 << 2)
-+#define TDA_HSR_PRL2 (1 << 3)
-+#define TDA_HSR_SUPL (1 << 4)
-+#define TDA_HSR_PRTL1 (1 << 5)
-+#define TDA_HSR_PRTL2 (1 << 6)
-+
-+typedef struct tda8007_reg_entry {
-+ u32 addr;
-+ char* name;
-+ char* description;
-+ u8 mode;
-+ unsigned short low_ino;
-+} tda8007_reg_entry_t;
-+
-+
-+/*
-+ * Read : 1
-+ * Write : 2
-+ * Read/Write : 3
-+ */
-+
-+static tda8007_reg_entry_t tda8007_regs[] =
-+{
-+ {TDA_CSR, "TDA_CSR", "Card select register (read/write)", 3},
-+ {TDA_CCR, "TDA_CCR", "Clock configuration register (read/write)", 3},
-+ {TDA_PDR, "TDA_PDR", "Programmable divider register (read/write)", 3},
-+ {TDA_UCR2, "TDA_UCR2", "UART configuration register 2(read/write)", 3},
-+ {TDA_GTR, "TDA_GTR", "Guard time register (read/write)", 3},
-+ {TDA_UCR1, "TDA_UCR1", "UART configuration register 1(read/write)", 3},
-+ {TDA_PCR, "TDA_PCR", "Power control register (read/write)", 3},
-+ {TDA_TOC, "TDA_TOC", "Time-out configuration register (read/write)", 3},
-+ {TDA_MSR, "TDA_MSR", "Mixed status register (read only)", 1},
-+ {TDA_URR, "TDA_URR", "UART receive register (read only)", 1},
-+ {TDA_USR, "TDA_USR", "UART status register (read only)", 1},
-+ {TDA_HSR, "TDA_HSR", "Hardware status register (read only)", 1},
-+ {TDA_TOR1, "TDA_TOR1", "Time-out register 1(write only)", 2},
-+ {TDA_TOR2, "TDA_TOR2", "Time-out register 2(write only)", 2},
-+ {TDA_TOR3, "TDA_TOR3", "Time-out register 3(write only)", 2},
-+ {TDA_FCR, "TDA_FCR", "FIFO control register (write only)", 2},
-+ {TDA_UTR, "TDA_UTR", "UART transmit register (write only)", 2}
-+};
-+#define NUM_OF_TDA8007_REG_ENTRY (sizeof(tda8007_regs)/sizeof(tda8007_reg_entry_t))
-+/*
-+struct tda8007 {
-+
-+};
-+*/
-+#endif /* TDA8007B_H */
---- linux-2.4.27/drivers/misc/Config.in~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/misc/Config.in
-@@ -16,3 +16,15 @@
- dep_tristate ' UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND
-
- endmenu
-+mainmenu_option next_comment
-+comment 'Console Switches'
-+
-+tristate 'Console Switch Support' CONFIG_SWITCHES
-+if [ "$CONFIG_SWITCHES" != "n" ]; then
-+ dep_bool ' SA-1100 switches' CONFIG_SWITCHES_SA1100 $CONFIG_ARCH_SA1100
-+ if [ "$CONFIG_MCP_UCB1200" != "n" ]; then
-+ bool ' UCB1x00 switches' CONFIG_SWITCHES_UCB1X00
-+ fi
-+fi
-+
-+endmenu
---- linux-2.4.27/drivers/misc/Makefile~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/misc/Makefile
-@@ -21,6 +21,24 @@
- obj-$(CONFIG_MCP_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o
- obj-$(CONFIG_PXA_CERF_PDA) += cerf_ucb1400gpio.o
-
-+ifeq ($(CONFIG_SA1100_ASSABET),y)
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
-+endif
-+
-+ifeq ($(CONFIG_SA1100_SIMPAD),y)
-+export-objs += ucb1x00-simpad.o
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-simpad.o
-+endif
-+
-+obj-$(CONFIG_SWITCHES) += switches.o
-+
-+switches-objs-y += switches-core.o
-+switches-objs-$(CONFIG_SWITCHES_SA1100) += switches-sa1100.o
-+switches-objs-$(CONFIG_SWITCHES_UCB1X00) += switches-ucb1x00.o
-+
- include $(TOPDIR)/Rules.make
-
-+switches.o: $(switches-objs-y)
-+ $(LD) $(LD_RFLAG) -r -o $@ $(switches-objs-y)
-+
- fastdep:
---- /dev/null
-+++ linux-2.4.27/drivers/misc/switches-core.c
-@@ -0,0 +1,226 @@
-+/*
-+ * linux/drivers/misc/switches-core.c
-+ *
-+ * Copyright (C) 2000-2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 5 October 2000 - created.
-+ *
-+ * 25 October 2000 - userland file interface added.
-+ *
-+ * 13 January 2001 - added support for Spot.
-+ *
-+ * 11 September 2001 - UCB1200 driver framework support added.
-+ *
-+ * 19 December 2001 - separated out SA-1100 and UCB1x00 code.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/poll.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/wait.h>
-+
-+#include <asm/uaccess.h>
-+
-+#include "switches.h"
-+
-+
-+MODULE_AUTHOR("John Dorsey");
-+MODULE_DESCRIPTION("Console switch support");
-+MODULE_LICENSE("GPL");
-+
-+
-+struct switches_action {
-+ struct list_head list;
-+ switches_mask_t mask;
-+};
-+
-+
-+static int switches_users = 0;
-+
-+static spinlock_t switches_lock = SPIN_LOCK_UNLOCKED;
-+
-+DECLARE_WAIT_QUEUE_HEAD(switches_wait);
-+LIST_HEAD(switches_event_queue);
-+
-+
-+static ssize_t switches_read(struct file *file, char *buffer,
-+ size_t count, loff_t *pos)
-+{
-+ unsigned long flags;
-+ struct list_head *event;
-+ struct switches_action *action;
-+
-+ if (count < sizeof(struct switches_mask_t))
-+ return -EINVAL;
-+
-+ while (list_empty(&switches_event_queue)) {
-+
-+ if (file->f_flags & O_NDELAY)
-+ return -EAGAIN;
-+
-+ interruptible_sleep_on(&switches_wait);
-+
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+
-+ }
-+
-+ if (verify_area(VERIFY_WRITE, buffer, sizeof(struct switches_mask_t)))
-+ return -EFAULT;
-+
-+ spin_lock_irqsave(&switches_lock, flags);
-+
-+ event = switches_event_queue.next;
-+ action = list_entry(event, struct switches_action, list);
-+ copy_to_user(buffer, &(action->mask), sizeof(struct switches_mask_t));
-+ list_del(event);
-+ kfree(action);
-+
-+ spin_unlock_irqrestore(&switches_lock, flags);
-+
-+ return sizeof(struct switches_mask_t);
-+
-+}
-+
-+static ssize_t switches_write(struct file *file, const char *buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ return -EINVAL;
-+}
-+
-+static unsigned int switches_poll(struct file *file, poll_table *wait)
-+{
-+
-+ poll_wait(file, &switches_wait, wait);
-+
-+ if (!list_empty(&switches_event_queue))
-+ return POLLIN | POLLRDNORM;
-+
-+ return 0;
-+
-+}
-+
-+static int switches_open(struct inode *inode, struct file *file)
-+{
-+
-+ if (switches_users > 0)
-+ return -EBUSY;
-+
-+ MOD_INC_USE_COUNT;
-+ ++switches_users;
-+ return 0;
-+
-+}
-+
-+static int switches_release(struct inode *inode, struct file *file)
-+{
-+
-+ --switches_users;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+
-+}
-+
-+static struct file_operations switches_ops = {
-+ read: switches_read,
-+ write: switches_write,
-+ poll: switches_poll,
-+ open: switches_open,
-+ release: switches_release
-+};
-+
-+static struct miscdevice switches_misc = {
-+ MISC_DYNAMIC_MINOR, SWITCHES_NAME, &switches_ops
-+};
-+
-+int switches_event(switches_mask_t *mask)
-+{
-+ struct switches_action *action;
-+
-+ if ((switches_users > 0) && (SWITCHES_COUNT(mask) > 0)) {
-+
-+ if ((action = (struct switches_action *)
-+ kmalloc(sizeof(struct switches_action),
-+ GFP_ATOMIC)) == NULL) {
-+ printk(KERN_ERR "%s: unable to allocate action "
-+ "descriptor\n", SWITCHES_NAME);
-+ return -1;
-+ }
-+
-+ action->mask = *mask;
-+
-+ spin_lock(&switches_lock);
-+ list_add_tail(&action->list, &switches_event_queue);
-+ spin_unlock(&switches_lock);
-+
-+ wake_up_interruptible(&switches_wait);
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static int __init switches_init(void)
-+{
-+
-+#ifdef CONFIG_SWITCHES_SA1100
-+ if (switches_sa1100_init() < 0) {
-+ printk(KERN_ERR "%s: unable to initialize SA-1100 switches\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+#endif
-+
-+#ifdef CONFIG_SWITCHES_UCB1X00
-+ if (switches_ucb1x00_init() < 0) {
-+ printk(KERN_ERR "%s: unable to initialize UCB1x00 switches\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+#endif
-+
-+ if (misc_register(&switches_misc) < 0) {
-+ printk(KERN_ERR "%s: unable to register misc device\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ printk("Console switches initialized\n");
-+
-+ return 0;
-+
-+}
-+
-+static void __exit switches_exit(void)
-+{
-+
-+#ifdef CONFIG_SWITCHES_SA1100
-+ switches_sa1100_exit();
-+#endif
-+
-+#ifdef CONFIG_SWITCHES_UCB1X00
-+ switches_ucb1x00_exit();
-+#endif
-+
-+ if (misc_deregister(&switches_misc) < 0)
-+ printk(KERN_ERR "%s: unable to deregister misc device\n",
-+ SWITCHES_NAME);
-+
-+}
-+
-+module_init(switches_init);
-+module_exit(switches_exit);
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/misc/switches-sa1100.c
-@@ -0,0 +1,311 @@
-+/*
-+ * linux/drivers/misc/switches-sa1100.c
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created from sa1100_switches.c.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+#include <asm/arch/assabet.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch/simpad.h>
-+#endif
-+
-+#include "switches.h"
-+
-+
-+static void switches_sa1100_handler(int irq, void *dev_id,
-+ struct pt_regs *regs);
-+
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+
-+/* Assabet
-+ * ^^^^^^^
-+ * We have two general-purpose switches, S1 and S2, available via GPIO
-+ * on Assabet. This code sets bits in the range [1, 2] in the mask that
-+ * we return to userland.
-+ */
-+
-+static int assabet_switches_sa1100_init(void)
-+{
-+
-+ if (machine_has_neponset())
-+ NCR_0 |= NCR_GP01_OFF;
-+
-+ set_irq_type(IRQ_GPIO0, IRQT_BOTHEDGE);
-+ set_irq_type(IRQ_GPIO1, IRQT_BOTHEDGE);
-+
-+ if (request_irq(IRQ_GPIO0, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 0\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ if (request_irq(IRQ_GPIO1, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for GPIO 1\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void assabet_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO1, NULL);
-+ free_irq(IRQ_GPIO0, NULL);
-+
-+}
-+
-+static void assabet_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO0: s = 0; break;
-+
-+ case IRQ_GPIO1: s = 1; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_ASSABET */
-+
-+
-+#ifdef CONFIG_SA1100_SPOT
-+
-+/* Spot
-+ * ^^^^
-+ * Spot (R2, R3) has a single general-purpose switch (S1), which is
-+ * also the power-on switch. We set bit [1] in the mask we return to
-+ * userland.
-+ */
-+
-+static int spot_switches_sa1100_init(void)
-+{
-+
-+ set_GPIO_IRQ_edge(GPIO_SW1, GPIO_BOTH_EDGES);
-+
-+ if (request_irq(IRQ_GPIO_SW1, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for SW1\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void spot_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO_SW1, NULL);
-+
-+}
-+
-+static void spot_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO_SW1: s = 0; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_SPOT */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+/* SIMpad
-+ * ^^^^
-+ * SIMpad has a single general-purpose switch (S0), which is
-+ * also the power-on switch. We set bit [1] in the mask we return to
-+ * userland.
-+ */
-+
-+static int simpad_switches_sa1100_init(void)
-+{
-+
-+ set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_BOTH_EDGES);
-+
-+ if (request_irq(IRQ_GPIO0, switches_sa1100_handler, SA_INTERRUPT,
-+ SWITCHES_NAME, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to register IRQ for SW0\n",
-+ SWITCHES_NAME);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void simpad_switches_sa1100_shutdown(void)
-+{
-+
-+ free_irq(IRQ_GPIO0, NULL);
-+
-+}
-+
-+static void simpad_switches_sa1100_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int s, last, this;
-+ static unsigned int states = 0;
-+
-+ switch (irq) {
-+
-+ case IRQ_GPIO0: s = 0; break;
-+
-+ default: return;
-+
-+ }
-+
-+ last = ((states & (1 << s)) != 0);
-+ this = ((GPLR & GPIO_GPIO(s)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ SWITCHES_SET(mask, s + 1, this);
-+
-+ states = this ? (states | (1 << s)) : (states & ~(1 << s));
-+
-+}
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+
-+
-+/* switches_sa1100_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * This routine is a generalized handler for SA-1100 switches
-+ * which manages action descriptors and calls a board-specific
-+ * service routine. This routine is appropriate for GPIO switches
-+ * or other primary interrupt sources, and can be registered as a
-+ * first-class IRQ handler using request_irq().
-+ */
-+static void switches_sa1100_handler(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ switches_mask_t mask;
-+
-+ SWITCHES_ZERO(&mask);
-+
-+ /* Porting note: call a board-specific switch interrupt handler
-+ * here. The handler can assume that sufficient storage for
-+ * `mask' has been allocated, and that the corresponding
-+ * switches_mask_t structure has been zeroed.
-+ */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_sa1100_handler(irq, &mask);
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ spot_switches_sa1100_handler(irq, &mask);
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_sa1100_handler(irq, &mask);
-+#endif
-+ }
-+
-+ switches_event(&mask);
-+
-+}
-+
-+int __init switches_sa1100_init(void)
-+{
-+
-+ /* Porting note: call a board-specific init routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ if (assabet_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ if (spot_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (simpad_switches_sa1100_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+
-+ return 0;
-+
-+}
-+
-+void __exit switches_sa1100_exit(void)
-+{
-+
-+ /* Porting note: call a board-specific shutdown routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_sa1100_shutdown();
-+#endif
-+ } else if (machine_is_spot()) {
-+#ifdef CONFIG_SA1100_SPOT
-+ spot_switches_sa1100_shutdown();
-+#endif
-+ } else if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_sa1100_shutdown();
-+#endif
-+ }
-+
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/misc/switches-ucb1x00.c
-@@ -0,0 +1,331 @@
-+/*
-+ * linux/drivers/misc/switches-ucb1x00.c
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created from sa1100_switches.c.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+#include <asm/arch/assabet.h>
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+#include <asm/arch/simpad.h>
-+#endif
-+
-+#include "switches.h"
-+#include "ucb1x00.h"
-+
-+
-+static struct ucb1x00 *ucb1x00;
-+
-+static void switches_ucb1x00_handler(int irq, void *devid);
-+
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+
-+/* Assabet
-+ * ^^^^^^^
-+ * Six switches are routed to GPIO pins on the UCB1300: S3 -- S8.
-+ * This code sets bits in the range [3, 8] in the mask that we
-+ * return to userland. Note that we transpose signals SW7 and SW8;
-+ * see assabet_switches_ucb1x00_handler().
-+ */
-+
-+static int assabet_switches_ucb1x00_init(void)
-+{
-+ int i;
-+
-+ /* Note that ucb1x00_init() must complete before this point: */
-+
-+ if ((ucb1x00 = ucb1x00_get()) == NULL) {
-+ printk(KERN_ERR "%s: UCB1300 driver not ready; switches "
-+ "3 -- 8 will not be available\n",
-+ SWITCHES_NAME);
-+ return 0;
-+ }
-+
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5, 0);
-+
-+ for (i = 0; i < 6; ++i) {
-+
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ if (ucb1x00_hook_irq(ucb1x00, i,
-+ switches_ucb1x00_handler, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to hook IRQ for "
-+ "UCB1300 IO_%d\n", SWITCHES_NAME, i);
-+ return -EBUSY;
-+ }
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void assabet_switches_ucb1x00_shutdown(void)
-+{
-+ int i;
-+
-+ for (i = 5; i >= 0; --i) {
-+
-+ ucb1x00_disable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ /* Only error conditions are ENOENT and EINVAL; silently
-+ * ignore:
-+ */
-+ ucb1x00_free_irq(ucb1x00, i, NULL);
-+
-+ }
-+
-+}
-+
-+static void assabet_switches_ucb1x00_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int last, this;
-+ static unsigned int states = 0;
-+
-+ last = ((states & (1 << irq)) != 0);
-+ this = ((ucb1x00_io_read(ucb1x00) & (1 << irq)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ /* Intel StrongARM SA-1110 Development Board
-+ * Schematics Figure 5, Sheet 5 of 12
-+ *
-+ * See switches S8 and S7. Notice their
-+ * relationship to signals SW7 and SW8. Hmmm.
-+ */
-+
-+ switch (irq) {
-+
-+ case 4:
-+
-+ SWITCHES_SET(mask, 8, this);
-+ break;
-+
-+ case 5:
-+
-+ SWITCHES_SET(mask, 7, this);
-+ break;
-+
-+ default:
-+
-+ SWITCHES_SET(mask, irq + 3, this);
-+
-+ }
-+
-+ states = this ? (states | (1 << irq)) : (states & ~(1 << irq));
-+
-+}
-+#endif /* CONFIG_SA1100_ASSABET */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+/* SIMpad
-+ * ^^^^^^
-+ * Six switches are routed to GPIO pins on the UCB1300: S3 -- S8.
-+ * This code sets bits in the range [3, 8] in the mask that we
-+ * return to userland.
-+ */
-+
-+static int simpad_switches_ucb1x00_init(void)
-+{
-+ int i;
-+
-+ /* Note that ucb1x00_init() must complete before this point: */
-+
-+ if ((ucb1x00 = ucb1x00_get()) == NULL) {
-+ printk(KERN_ERR "%s: UCB1300 driver not ready; switches "
-+ "3 -- 8 will not be available\n",
-+ SWITCHES_NAME);
-+ return 0;
-+ }
-+
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5,
-+ UCB_IO_8 | UCB_IO_9);
-+
-+ ucb1x00_disable(ucb1x00);
-+
-+ for (i = 0; i < 6; ++i) {
-+
-+ if (ucb1x00_hook_irq(ucb1x00, i,
-+ switches_ucb1x00_handler, NULL) < 0) {
-+ printk(KERN_ERR "%s: unable to hook IRQ for "
-+ "UCB1300 IO_%d\n", SWITCHES_NAME, i);
-+ return -EBUSY;
-+ }
-+
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+ }
-+
-+ return 0;
-+
-+}
-+
-+int simpad_switches_ucb1x00_reinit(void)
-+{
-+ int i;
-+ ucb1x00_enable(ucb1x00);
-+
-+ ucb1x00_io_set_dir(ucb1x00,
-+ UCB_IO_0 | UCB_IO_1 | UCB_IO_2 |
-+ UCB_IO_3 | UCB_IO_4 | UCB_IO_5,
-+ UCB_IO_8 | UCB_IO_9);
-+
-+ ucb1x00_disable(ucb1x00);
-+
-+ for (i = 0; i < 6; ++i)
-+ ucb1x00_enable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ return 0;
-+}
-+
-+static void simpad_switches_ucb1x00_shutdown(void)
-+{
-+ int i;
-+
-+ for (i = 5; i >= 0; --i) {
-+
-+ ucb1x00_disable_irq(ucb1x00, i, UCB_RISING | UCB_FALLING);
-+
-+ /* Only error conditions are ENOENT and EINVAL; silently
-+ * ignore:
-+ */
-+ ucb1x00_free_irq(ucb1x00, i, NULL);
-+
-+ }
-+
-+}
-+
-+static void simpad_switches_ucb1x00_handler(int irq, switches_mask_t *mask)
-+{
-+ unsigned int last, this;
-+ static unsigned int states = 0;
-+
-+ last = ((states & (1 << irq)) != 0);
-+ this = ((~ucb1x00_io_read(ucb1x00) & (1 << irq)) != 0);
-+
-+ if (last == this) /* debounce */
-+ return;
-+
-+ switch (irq) {
-+
-+ case 4:
-+
-+
-+
-+ case 5:
-+
-+
-+
-+ default:
-+
-+ SWITCHES_SET(mask, irq + 3, this);
-+
-+ }
-+
-+ states = this ? (states | (1 << irq)) : (states & ~(1 << irq));
-+
-+}
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+
-+/* switches_ucb1x00_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * This routine is a generalized handler for UCB1x00 GPIO switches
-+ * which calls a board-specific service routine and passes an event
-+ * mask to the core event handler. This routine is appropriate for
-+ * systems which use the ucb1x00 framework, and can be registered
-+ * using ucb1x00_hook_irq().
-+ */
-+static void switches_ucb1x00_handler(int irq, void *devid)
-+{
-+ switches_mask_t mask;
-+
-+ SWITCHES_ZERO(&mask);
-+
-+ /* Porting note: call a board-specific UCB1x00 switch handler here.
-+ * The handler can assume that sufficient storage for `mask' has
-+ * been allocated, and that the corresponding switches_mask_t
-+ * structure has been zeroed.
-+ */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_ucb1x00_handler(irq, &mask);
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_handler(irq, &mask);
-+#endif
-+ }
-+
-+ switches_event(&mask);
-+
-+}
-+
-+int __init switches_ucb1x00_init(void)
-+{
-+
-+ /* Porting note: call a board-specific init routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ if (assabet_switches_ucb1x00_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (simpad_switches_ucb1x00_init() < 0)
-+ return -EIO;
-+#endif
-+ }
-+
-+ return 0;
-+
-+}
-+
-+void __exit switches_ucb1x00_exit(void)
-+{
-+
-+ /* Porting note: call a board-specific shutdown routine here. */
-+
-+ if (machine_is_assabet()) {
-+#ifdef CONFIG_SA1100_ASSABET
-+ assabet_switches_ucb1x00_shutdown();
-+#endif
-+ }
-+ if (machine_is_simpad()) {
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_shutdown();
-+#endif
-+ }
-+
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/misc/switches.h
-@@ -0,0 +1,28 @@
-+/*
-+ * linux/drivers/misc/switches.h
-+ *
-+ * Copyright (C) 2001 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 19 December 2001 - created.
-+ */
-+
-+#if !defined(_SWITCHES_H)
-+# define _SWITCHES_H
-+
-+#include <linux/switches.h>
-+
-+#define SWITCHES_NAME "switches"
-+
-+extern int switches_event(switches_mask_t *mask);
-+
-+extern int switches_sa1100_init(void);
-+extern void switches_sa1100_exit(void);
-+
-+extern int switches_ucb1x00_init(void);
-+extern void switches_ucb1x00_exit(void);
-+
-+#endif /* !defined(_SWITCHES_H) */
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00-assabet.c
-@@ -0,0 +1,114 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-assabet.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * We handle the machine-specific bits of the UCB1x00 driver here.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+
-+#include "ucb1x00.h"
-+
-+static struct proc_dir_entry *dir;
-+static struct ucb1x00 *ucb;
-+
-+static int ucb1x00_assabet_read_vbatt(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb1x00_assabet_read_vcharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb1x00_assabet_read_batt_temp(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD2, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int (*fn)(struct ucb1x00 *) = data;
-+ int v, len;
-+
-+ v = fn(ucb);
-+
-+ p += sprintf(p, "%d\n", v);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init ucb1x00_assabet_init(void)
-+{
-+ struct proc_dir_entry *res;
-+
-+ ucb = ucb1x00_get();
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ dir = proc_mkdir("ucb1x00", NULL);
-+ if (!dir)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vbatt", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_vbatt);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vcharger", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_vcharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("batt_temp", S_IRUGO, dir, ucb_read, ucb1x00_assabet_read_batt_temp);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_assabet_exit(void)
-+{
-+ remove_proc_entry("vbatt", dir);
-+ remove_proc_entry("vcharger", dir);
-+ remove_proc_entry("batt_temp", dir);
-+}
-+
-+module_init(ucb1x00_assabet_init);
-+module_exit(ucb1x00_assabet_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/misc/ucb1x00-audio.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/misc/ucb1x00-audio.c
-@@ -283,7 +283,7 @@
- {
- struct ucb1x00_audio *ucba;
-
-- ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
-+ ucba = kmalloc(sizeof(*ucba), GFP_ATOMIC);
- if (ucba) {
- memset(ucba, 0, sizeof(*ucba));
-
---- linux-2.4.27/drivers/misc/ucb1x00-core.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/misc/ucb1x00-core.c
-@@ -215,6 +215,9 @@
- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
- ucb1x00_disable(ucb);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ simpad_switches_ucb1x00_reinit();
-+#endif
- }
-
- return 0;
-@@ -561,8 +564,10 @@
- default_irq = IRQ_GPIO_UCB1300_IRQ;
- #endif
- #ifdef CONFIG_SA1100_SIMPAD
-- if (machine_is_simpad())
-+ if (machine_is_simpad()) {
- default_irq = IRQ_GPIO_UCB1300_IRQ;
-+ irq_gpio_pin = GPIO_UCB1300_IRQ;
-+ }
- #endif
- #ifdef CONFIG_SA1100_SIMPUTER
- if (machine_is_simputer()) {
-@@ -660,7 +665,7 @@
- if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)
- id = UCB_ID_1400_BUGGY;
-
-- my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
-+ my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_ATOMIC);
- ret = -ENOMEM;
- if (!my_ucb)
- goto out;
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00-simpad.c
-@@ -0,0 +1,241 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-simpad.c
-+ *
-+ * Modified by Juergen Messerer for SIMpad
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * We handle the machine-specific bits of the UCB1x00 driver here.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/dma.h>
-+
-+#include <asm/arch-sa1100/simpad_pm.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Conversion from AD -> mV
-+ * 7.5V = 1023 7.3313mV/Digit
-+ *
-+ * 400 Units == 9.7V
-+ * a = ADC value
-+ * 21 = ADC error
-+ * 12600 = Divident to get 2*7.3242
-+ * 860 = Divider to get 2*7.3242
-+ * 170 = Voltagedrop over
-+ */
-+#define CALIBRATE_BATTERY(a) ((((a + 21)*12600)/860) + 170)
-+
-+/*
-+ * We have two types of batteries a small and a large one
-+ * To get the right value we to distinguish between those two
-+ * 450 Units == 15 V
-+ */
-+#ifdef SMALL_BATTERY
-+#define CALIBRATE_SUPPLY(a) (((a) * 1500) / 51)
-+#define MIN_SUPPLY 8500 /* Less then 8.5V means no powersupply */
-+#else
-+#define CALIBRATE_SUPPLY(a) (((a) * 1500) / 45)
-+//#define MIN_SUPPLY 14000 /* Less then 14V means no powersupply */
-+#define MIN_SUPPLY 12000 /* Less then 12V means no powersupply */
-+#endif
-+
-+/*
-+ * Charging Current
-+ * if value is >= 50 then charging is on
-+ */
-+#define CALIBRATE_CHARGING(a) (((a)* 1000)/(152/4)))
-+//#define CHARGING_LED_LEVEL 50
-+
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+#define CHARGING_LED_LEVEL 12
-+#define CHARGING_MAX_LEVEL 120
-+#define BATT_FULL 8100
-+#define BATT_LOW 7300
-+#define BATT_CRITICAL 6700
-+#define BATT_EMPTY 6400
-+
-+
-+#else // CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+#define CHARGING_LED_LEVEL 28
-+#define CHARGING_MAX_LEVEL 265
-+#define BATT_FULL 8300
-+#define BATT_LOW 7400
-+#define BATT_CRITICAL 6800
-+#define BATT_EMPTY 6500
-+
-+#endif // CONFIG_SA1100_SIMPAD_SINUSPAD
-+
-+
-+static struct proc_dir_entry *dir;
-+static struct ucb1x00 *ucb;
-+
-+static int ucb1x00_simpad_read_vbatt(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return CALIBRATE_BATTERY(val);
-+}
-+
-+static int ucb1x00_simpad_read_vcharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD2, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return CALIBRATE_SUPPLY(val);
-+}
-+
-+static int ucb1x00_simpad_read_icharger(struct ucb1x00 *ucb)
-+{
-+ int val;
-+ ucb1x00_adc_enable(ucb);
-+ val = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD3, UCB_NOSYNC);
-+ ucb1x00_adc_disable(ucb);
-+
-+ return val;
-+}
-+
-+static int ucb_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int (*fn)(struct ucb1x00 *) = data;
-+ int v, len;
-+
-+ v = fn(ucb);
-+
-+ p += sprintf(p, "%d\n", v);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+/****************************************************************************/
-+/* Functions exported for use by the kernel and kernel modules */
-+/****************************************************************************/
-+
-+int simpad_get_battery(struct simpad_battery *bstat)
-+{
-+ int icharger, vcharger, vbatt;
-+
-+ if ( ucb ) {
-+ icharger = ucb1x00_simpad_read_icharger( ucb );
-+ vcharger = ucb1x00_simpad_read_vcharger( ucb );
-+ vbatt = ucb1x00_simpad_read_vbatt( ucb );
-+ } else {
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_UNKNOWN;
-+ bstat->status = SIMPAD_BATT_STATUS_UNKNOWN;
-+ bstat->percentage = 0x64; /* lets say 100% */
-+ bstat->life = 360; /* lets say a long time */
-+ return 0;
-+ }
-+
-+ /* AC status */
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_OFFLINE;
-+ if ( vcharger>MIN_SUPPLY ) {
-+ bstat->ac_status = SIMPAD_AC_STATUS_AC_ONLINE;
-+ }
-+
-+ /* charging */
-+ bstat->status = 0x0;
-+ if ( icharger > CHARGING_LED_LEVEL ) {
-+ bstat->status = SIMPAD_BATT_STATUS_CHARGING;
-+ }
-+
-+ if ( vbatt > BATT_LOW )
-+ bstat->status |= SIMPAD_BATT_STATUS_HIGH;
-+ else if ( vbatt < BATT_CRITICAL )
-+ bstat->status |= SIMPAD_BATT_STATUS_CRITICAL;
-+ else
-+ bstat->status |= SIMPAD_BATT_STATUS_LOW;
-+
-+ if (bstat->status & SIMPAD_BATT_STATUS_CHARGING) {
-+ if (icharger > CHARGING_MAX_LEVEL) icharger = CHARGING_MAX_LEVEL;
-+ if (icharger < CHARGING_LED_LEVEL) icharger = CHARGING_LED_LEVEL;
-+ bstat->percentage = 100 - 100 * (icharger - CHARGING_LED_LEVEL) /
-+ (CHARGING_MAX_LEVEL - CHARGING_LED_LEVEL);
-+ } else {
-+ if (vbatt > BATT_FULL) vbatt = BATT_FULL;
-+ if (vbatt < BATT_EMPTY) vbatt = BATT_EMPTY;
-+ bstat->percentage = 100 * (vbatt - BATT_EMPTY) / (BATT_FULL - BATT_EMPTY);
-+ }
-+
-+ /* let's assume: full load is 7h */
-+ /* bstat->life = 420*bstat->percentage/100; */
-+ bstat->life = 0;
-+
-+#if 0
-+ printk("get_battery: ac: %02x / ch: %02x / perc: %02x / life: %d\n",
-+ bstat->ac_status, bstat->status,
-+ bstat->percentage, bstat->life );
-+#endif
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(simpad_get_battery);
-+
-+/****************************************************************************/
-+/* sample proc interface */
-+/****************************************************************************/
-+static int __init ucb1x00_simpad_init(void)
-+{
-+ struct proc_dir_entry *res;
-+
-+ ucb = ucb1x00_get();
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ dir = proc_mkdir("ucb1x00", NULL);
-+ if (!dir)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vbatt", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_vbatt);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("vcharger", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_vcharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_read_entry("icharger", S_IRUGO, dir, ucb_read, ucb1x00_simpad_read_icharger);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_simpad_exit(void)
-+{
-+ remove_proc_entry("vbatt", dir);
-+ remove_proc_entry("vcharger", dir);
-+ remove_proc_entry("icharger", dir);
-+}
-+
-+module_init(ucb1x00_simpad_init);
-+module_exit(ucb1x00_simpad_exit);
-+
-+MODULE_AUTHOR("Juergen Messerer <juergen.messerer@freesurf.ch>");
-+MODULE_DESCRIPTION("SIMpad noddy testing only example ADC driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/misc/ucb1x00-ts.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/misc/ucb1x00-ts.c
-@@ -356,7 +356,7 @@
- UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-
-- udelay(55);
-+ udelay(250); /*former 55*/
-
- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
- }
-@@ -379,7 +379,7 @@
- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
- UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-
-- udelay(55);
-+ udelay(250); /*former 55*/
-
- return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
- }
---- linux-2.4.27/drivers/mtd/Config.in~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/mtd/Config.in
-@@ -11,6 +11,9 @@
- if [ "$CONFIG_MTD_DEBUG" = "y" ]; then
- int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0
- fi
-+ if [ "$CONFIG_CRAMFS" = "y" ]; then
-+ bool ' Cramfs root partition' CONFIG_ROOT_CRAMFS
-+ fi
- dep_tristate ' MTD partitioning support' CONFIG_MTD_PARTITIONS $CONFIG_MTD
- dep_tristate ' MTD concatenating support' CONFIG_MTD_CONCAT $CONFIG_MTD
- dep_tristate ' RedBoot partition table parsing' CONFIG_MTD_REDBOOT_PARTS $CONFIG_MTD_PARTITIONS
---- linux-2.4.27/drivers/mtd/maps/sa1100-flash.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/mtd/maps/sa1100-flash.c
-@@ -767,40 +767,38 @@
- #endif
-
- #ifdef CONFIG_SA1100_SIMPAD
--#define SIMPAD_FLASH_SIZE 0x02000000
--static struct mtd_partition simpad_partitions[] = {
-- {
-- name: "SIMpad boot firmware",
-- size: 0x00080000,
-- offset: 0,
-- mask_flags: MTD_WRITEABLE, /* force read-only */
-- }, {
-- name: "SIMpad kernel",
-- size: 0x00100000,
-- offset: 0x00080000,
-- }, {
--#ifdef CONFIG_JFFS2_FS
-- name: "SIMpad root jffs2",
-- size: MTDPART_SIZ_FULL,
-- offset: 0x00180000,
-+
-+#ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
-+#define SIMPAD_FLASH_SIZE 0x01000000
- #else
-- name: "SIMpad initrd",
-- size: 0x00300000,
-- offset: 0x00180000,
-- }, {
-- name: "SIMpad root cramfs",
-- size: 0x00300000,
-- offset: 0x00480000,
-- }, {
-- name: "SIMpad usr cramfs",
-- size: 0x005c0000,
-- offset: 0x00780000,
-- }, {
-- name: "SIMpad usr local",
-- size: MTDPART_SIZ_FULL,
-- offset: 0x00d40000,
-+#define SIMPAD_FLASH_SIZE 0x02000000
- #endif
-- }
-+
-+static struct mtd_partition simpad_partitions[] = {
-+ {
-+ name: "SIMpad boot firmware",
-+ offset: 0,
-+ size: 0x00080000,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "SIMpad kernel",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00100000
-+ },{
-+#ifdef CONFIG_ROOT_CRAMFS
-+ name: "SIMpad root cramfs",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00D80000
-+ },{
-+ name: "SIMpad local jffs",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL
-+#else
-+ name: "SIMpad root jffs2",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL
-+#endif /* CONFIG_CRAM_FS */
-+ }
- };
- #endif /* CONFIG_SA1100_SIMPAD */
-
---- linux-2.4.27/drivers/pcmcia/sa1100_simpad.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_simpad.c
-@@ -9,20 +9,18 @@
-
- #include <asm/hardware.h>
- #include <asm/irq.h>
-+#include <asm/arch/simpad.h>
-+
- #include "sa1100_generic.h"
--
-+
- extern long get_cs3_shadow(void);
--extern void set_cs3_bit(int value);
-+extern void set_cs3_bit(int value);
- extern void clear_cs3_bit(int value);
-
-
- static int simpad_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
-
-- set_cs3_bit(PCMCIA_RESET);
-- clear_cs3_bit(PCMCIA_BUFF_DIS);
-- clear_cs3_bit(PCMCIA_RESET);
--
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
-
- /* Set transition detect */
-@@ -63,6 +61,9 @@
-
- if(state_array->size<2) return -1;
-
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-+
- levels=GPLR;
-
- state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
-@@ -100,13 +101,15 @@
- static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
- *configure)
- {
-- unsigned long value, flags;
-+ static int irq_disabled = 0;
-
-- if(configure->sock>1) return -1;
-+ if(configure->sock>1)
-+ return -1;
-
-- if(configure->sock==0) return 0;
-+ if(configure->sock==0)
-+ return 0;
-
-- save_flags_cli(flags);
-+ //local_irq_save(flags);
-
- /* Murphy: see table of MIC2562a-1 */
-
-@@ -116,8 +119,8 @@
- break;
-
- case 33:
-- clear_cs3_bit(VCC_3V_EN|EN0);
-- set_cs3_bit(VCC_5V_EN|EN1);
-+ clear_cs3_bit(VCC_3V_EN|EN1);
-+ set_cs3_bit(VCC_5V_EN|EN0);
- break;
-
- case 50:
-@@ -129,26 +132,50 @@
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
-- restore_flags(flags);
-+ //restore_flags(flags);
- return -1;
- }
-
-- /* Silently ignore Vpp, output enable, speaker enable. */
-+ if(configure->reset)
-+ set_cs3_bit(PCMCIA_RESET);
-+ else
-+ clear_cs3_bit(PCMCIA_RESET);
-+
-+ if(configure->output)
-+ clear_cs3_bit(PCMCIA_BUFF_DIS);
-+ else
-+ set_cs3_bit(PCMCIA_BUFF_DIS);
-
-- restore_flags(flags);
-+ if(configure->irq) {
-+ enable_irq(IRQ_GPIO_CF_IRQ);
-+ irq_disabled = 0;
-+ }
-+ else {
-+ if (!irq_disabled) {
-+ disable_irq(IRQ_GPIO_CF_IRQ);
-+ irq_disabled = 1;
-+ }
-+ }
-+
-+ //local_irq_restore(flags);
-
- return 0;
- }
-
- static int simpad_pcmcia_socket_init(int sock)
- {
-- set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_BOTH_EDGES);
-+ if(sock == 1)
-+ set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_BOTH_EDGES);
- return 0;
- }
-
- static int simpad_pcmcia_socket_suspend(int sock)
- {
-- set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_NO_EDGES);
-+ if(sock == 1)
-+ {
-+ set_GPIO_IRQ_edge(GPIO_CF_CD, GPIO_NO_EDGES);
-+ set_cs3_bit(PCMCIA_RESET);
-+ }
- return 0;
- }
-
---- linux-2.4.27/drivers/video/Config.in~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/video/Config.in
-@@ -61,6 +61,10 @@
- fi
- fi
- dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
-+ if [ "$CONFIG_SA1100_SIMPAD" = "y" -o \
-+ "$CONFIGG_SA1100_GDS2200" = "y" ]; then
-+ bool ' MQ200 VGA support' CONFIG_FB_MQ200
-+ fi
- if [ "$CONFIG_APOLLO" = "y" ]; then
- define_bool CONFIG_FB_APOLLO y
- fi
---- linux-2.4.27/drivers/video/Makefile~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/drivers/video/Makefile
-@@ -141,6 +141,7 @@
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
- obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
-+obj-$(CONFIG_FB_MQ200) += mq200fb.o
-
- # Generic Low Level Drivers
-
---- /dev/null
-+++ linux-2.4.27/drivers/video/mq200fb.c
-@@ -0,0 +1,1963 @@
-+/* MQ200 console frame buffer driver---mq200fb.c
-+ *
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ */
-+
-+#include <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/vmalloc.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/interrupt.h>
-+#include <linux/proc_fs.h> /* all the /proc functions */
-+#include <linux/ioport.h>
-+#include <asm/uaccess.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <asm/io.h>
-+
-+#include <linux/console.h>
-+
-+#include <video/fbcon.h>
-+#ifdef CONFIG_FBCON_MFB
-+#include <video/fbcon-mfb.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB2
-+#include <video/fbcon-cfb2.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB4
-+#include <video/fbcon-cfb4.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB8
-+#include <video/fbcon-cfb8.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+#include <video/fbcon-cfb16.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+#include <video/fbcon-cfb24.h>
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+#include <video/fbcon-cfb32.h>
-+#endif
-+
-+#include <video/MQ200/mq2hw.h>
-+#include <video/MQ200/mqdata.h>
-+#include <video/MQ200/mqplat.h>
-+
-+/* GPIO handling */
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+
-+#ifdef TEST
-+#undef PDEBUG /* Safety */
-+
-+#define PDEBUG(fmt, args...) printk(KERN_EMERG fmt, ##args)
-+#else
-+#define PDEBUG(fmt, args...)
-+#endif
-+
-+#define MQ200_DIRNAME "driver/mq200"
-+#define REG_DIRNAME "registers"
-+
-+void enable_cursor(void *pMQMMIO);
-+
-+static ssize_t proc_read_reg(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos);
-+static ssize_t proc_write_reg(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos);
-+
-+static struct file_operations proc_reg_operations = {
-+ read: proc_read_reg,
-+ write: proc_write_reg
-+};
-+
-+typedef struct sa1110_reg_entry {
-+ u32 phyaddr;
-+ char* name;
-+ char* description;
-+ unsigned short low_ino;
-+} sa1110_reg_entry_t;
-+
-+#define CMAPSIZE 32
-+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-+
-+#define mq200_p2v( x ) \
-+ (((x) - 0x4b800000) + 0xf2800000)
-+
-+/* The following is copied from mq2hw.c for initialization of MQ200 */
-+/* PLL1 data */
-+#define PLL1_83MHZ 0x0EF2082A
-+#define DEF_MIU2_83MHZ 0x4143E086
-+#define PLL1_50MHZ 0x0B200A2A
-+#define DEF_MIU2_50MHZ 0x40C30086
-+
-+/* Miscellaneous default data */
-+#define DEF_D1 0x05000271
-+#define DEF_D2 0x00000271
-+#define DEF_MIU3 0x6D6AABFF
-+#define DEF_MIU4 0x00000001
-+#define DEF_MIU5 0x0000010D
-+
-+#ifdef CONFIG_SA1100_GDS2200
-+#define DEF_GPO_CONTROL 0x00020054
-+#else
-+#define DEF_GPO_CONTROL 0x00000000
-+#endif
-+
-+#define DEF_GPIO_CONTROL 0x00000000
-+#define DEF_PWM_CONTROL 0x00A16c44
-+#define PWMOFFMASK 0xFF0FFF0F
-+
-+struct fb_info_mq200 {
-+ struct fb_info fb_info;
-+ struct fb_fix_screeninfo fix;
-+ struct fb_var_screeninfo var;
-+ struct display disp;
-+ struct {
-+ __u8 red, green, blue;
-+ } palette[256];
-+ struct fb_info_mq200 *next;
-+ unsigned int mqMmioAddrVirt;
-+ unsigned int mqFbAddrVirt;
-+ unsigned int mqMmioAddrPhys;
-+ unsigned int mqFbAddrPhys;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+};
-+
-+u32 mqflag;
-+u32 mqMmioAddr, mqFbAddr;
-+
-+/* Interface need to console.c. The following variable are defined in
-+ drivers/char/console.c */
-+
-+extern unsigned char color_table[];
-+extern int default_red[];
-+extern int default_grn[];
-+extern int default_blu[];
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+ extern void set_cs3_bit(int value);
-+ extern void clear_cs3_bit(int value);
-+ DISPLAY_CONFIG dc = {800, 600, 16, 60, 1600, 0x00130004};
-+#else
-+ DISPLAY_CONFIG dc = {800, 600, 32, 60, 3200, 0x0023000f};
-+#endif
-+
-+static int currcon = 0;
-+static char mq200fb_name[16] = "MQ200FB";
-+
-+static struct fb_var_screeninfo mq200fb_default = {
-+ /* 800x600, 32 bpp */
-+ 800, 600, 800, 600, 0, 0, 32, 0,
-+ {0, 8, 0}, {8, 8, 0}, {16, 8, 0}, {24, 8, 0},
-+ 0, 0, -1, -1, 0, MQ200_FB_SIZE, 64, 64, 32, 32, 64, 2,
-+ 0, FB_VMODE_NONINTERLACED
-+};
-+static union {
-+ u16 cfb16[CMAPSIZE];
-+ u32 cfb24[CMAPSIZE];
-+ u32 cfb32[CMAPSIZE];
-+} fbcon_cmap;
-+
-+static struct proc_dir_entry *regdir;
-+static struct proc_dir_entry *mq200dir;
-+static struct proc_dir_entry *driverdir;
-+
-+/* Functions used to initialize MQ200 chip */
-+void setmqmode(PDISPLAY_CONFIG, void *);
-+void setup_cursor(void *);
-+void onoffdisplay(int, void *);
-+unsigned long getbppbits(int);
-+PDISPLAY_TIMING getgcparam(int, int, int);
-+void setpal(int, unsigned long, void *);
-+void setupfp(int, void *);
-+void setuphfbuffer(int, unsigned long, void *);
-+void setupgc(int, int, int, int, int, void *);
-+void setupgcmem(PDISPLAY_CONFIG, unsigned long, void *);
-+long idmqchip(void *pMQMMIO);
-+void turnoffMQ200(void * pMQMMIO);
-+
-+/* Interface used by the world */
-+int mq200fb_setup(char*);
-+static int mq200fb_open(struct fb_info *info, int user);
-+static int mq200fb_release (struct fb_info *info, int user);
-+static int mq200fb_get_fix(struct fb_fix_screeninfo *fix, int con, \
-+ struct fb_info *info);
-+static int mq200fb_get_var(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_set_var(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_pan_display(struct fb_var_screeninfo *var, int con, \
-+ struct fb_info *info);
-+static int mq200fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, \
-+ struct fb_info *info);
-+static int mq200fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, \
-+ struct fb_info *info);
-+static int mq200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-+ u_long arg, int con, struct fb_info *info);
-+
-+/* Interface to the low level console driver */
-+int mq200fb_init(void);
-+static int mq200fbcon_switch(int con, struct fb_info *info);
-+static int mq200fbcon_updatevar(int con, struct fb_info *info);
-+static void mq200fbcon_blank(int blank, struct fb_info *info);
-+
-+/* int sa1100fb_map_video_memory(void * pmem int memsize); */
-+
-+/*
-+ *Internal routines
-+ */
-+
-+static u_long get_line_length(int xres_virtual, int bpp);
-+static void mq200fb_encode_fix(struct fb_fix_screeninfo *fix,
-+ struct fb_var_screeninfo *var);
-+static void set_color_bitfields(struct fb_var_screeninfo *var);
-+static int mq200fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-+ u_int *transp, struct fb_info *info);
-+static int mq200fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info);
-+static void do_install_cmap(int con, struct fb_info *info);
-+
-+#ifdef CONFIG_PM
-+static int mq200fb_pm_callback(struct pm_dev *, pm_request_t, void *);
-+#endif
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+static void mq200_backlight(void *, int);
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+static void writeBrightness(void *, int);
-+#endif
-+
-+static struct fb_ops mq200fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: mq200fb_get_fix,
-+ fb_get_var: mq200fb_get_var,
-+ fb_set_var: mq200fb_set_var,
-+ fb_get_cmap: mq200fb_get_cmap,
-+ fb_set_cmap: mq200fb_set_cmap,
-+ fb_pan_display: mq200fb_pan_display,
-+ fb_ioctl: mq200fb_ioctl,
-+};
-+
-+typedef struct mq200_reg_entry {
-+ u32 phyaddr;
-+ char* name;
-+ char* description;
-+ unsigned short low_ino;
-+} mq200_reg_entry_t;
-+
-+static mq200_reg_entry_t mq200_regs[] =
-+{
-+ { 0x4be00000, "PM_MISC", "MQ200 PM_MISC" },
-+ { 0x4be00004, "D1_STATE", "MQ200 D1_STATE" },
-+ { 0x4be00008, "D2_STATE", "MQ200 D2_STATE" },
-+ { 0x4be00018, "PLL2_CONTROL", "MQ200 PLL2_CONTROL" },
-+ { 0x4be0001c, "PLL3_CONTROL", "MQ200 PLL3_CONTROL" },
-+ { 0x4be02000, "CPU_CONTROL", "MQ200 CPU_CONTROL" },
-+ { 0x4be02004, "DRAW_STATUS", "MQ200 DRAW_STATUS" },
-+ { 0x4be04000, "MIU_CONTROL1", "MQ200 MIU_CONTROL1" },
-+ { 0x4be04004, "MIU_CONTROL2", "MQ200 MIU_CONTROL2" },
-+ { 0x4be04008, "MIU_CONTROL3", "MQ200 MIU_CONTROL3" },
-+ { 0x4be0400c, "MIU_CONTROL4", "MQ200 MIU_CONTROL4" },
-+ { 0x4be04010, "MIU_CONTROL5", "MQ200 MIU_CONTROL5" },
-+ { 0x4be0a000, "GC1_CONTROL", "MQ200 GC1_CONTROL" },
-+ { 0x4be0a004, "GC1_CRT_CONTROL", "MQ200 GC1_CRT_CONTROL" },
-+ { 0x4be0a008, "HD1_CONTROL", "MQ200 HD1_CONTROL" },
-+ { 0x4be0a00c, "VD1_CONTROL", "MQ200 VD1_CONTROL" },
-+ { 0x4be0a010, "HS1_CONTROL", "MQ200 HS1_CONTROL" },
-+ { 0x4be0a014, "VS1_CONTROL", "MQ200 VS1_CONTROL" },
-+ { 0x4be0a020, "HW1_CONTROL", "MQ200 HW1_CONTROL" },
-+ { 0x4be0a024, "VW1_CONTROL", "MQ200 VW1_CONTROL" },
-+ { 0x4be0a040, "HW_CURSOR1_POS", "MQ200 HW_CURSOR1_POS" },
-+ { 0x4be0a044, "HW_CURSOR1_ADDR", "MQ200 HW_CURSOR1_ADDR" },
-+ { 0x4be0e000, "FP_CONTROL", "MQ200 FP_CONTROL" },
-+ { 0x4be0e004, "FP_PIN_CONTROL", "MQ200 FP_PIN_CONTROL" },
-+ { 0x4be0e008, "FP_GPO_CONTROL", "MQ200 FP_GPO_CONTROL" },
-+ { 0x4be0e00c, "FP_GPIO_CONTROL", "MQ200 FP_GPIO_CONTROL" },
-+ { 0x4be0e010, "STN_CONTROL", "MQ200 STN_CONTROL" },
-+ { 0x4be0e014, "DSTN_FB_CONTROL", "MQ200 DSTN_FB_CONTROL" },
-+ { 0x4be0e03c, "PWM_CONTROL", "MQ200 PWM_CONTROL" },
-+ { 0x4be14000, "DC_0", "MQ200 DC_1" },
-+ { 0x4be14004, "DC_1", "MQ200 DC_2" },
-+ { 0x4be14008, "DC_SW_0", "MQ200 DC_SW_0" },
-+ { 0x4be1400c, "DC_SW_1", "MQ200 DC_SW_1" },
-+ { 0x4be16040, "PMR", "MQ200 PMR" },
-+ { 0x4be16044, "PMCSR", "MQ200 PMCSR" }
-+};
-+
-+#define NUM_OF_MQ200_REG_ENTRY (sizeof(mq200_regs)/sizeof(mq200_reg_entry_t))
-+
-+static int mq200fb_open(struct fb_info *info, int user)
-+{
-+ /*
-+ * Nothing, only a usage count for the moment
-+ */
-+ MOD_INC_USE_COUNT;
-+ return(0);
-+
-+}
-+
-+/* Release console */
-+static int mq200fb_release (struct fb_info *info, int user)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+ turnoffMQ200((void *) p->mqMmioAddrVirt);
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+/* Get the Fixed Part of the Display */
-+static int mq200fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_get_fix.\n", __LINE__);
-+
-+ *fix = p->fix;
-+ return 0;
-+
-+}
-+
-+
-+ /*
-+ * Get the User Defined Part of the Display
-+ */
-+
-+static int mq200fb_get_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_get_var.\n", __LINE__);
-+
-+ *var = p->var;
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Set the User Defined Part of the Display
-+ */
-+
-+static int mq200fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct fb_info_mq200 * p = (struct fb_info_mq200 *) info;
-+ int err, activate = var->activate;
-+ int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
-+ u_long line_length;
-+
-+ struct display *display;
-+
-+ PDEBUG("mq200fb: %i---in mq200fb_set_var.\n", __LINE__);
-+
-+ if (con >= 0)
-+ display = &fb_display[con];
-+ else
-+ display = &(p->disp); /* used during initialization */
-+
-+ /*
-+ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-+ * as FB_VMODE_SMOOTH_XPAN is only used internally
-+ */
-+
-+ if (var->vmode & FB_VMODE_CONUPDATE) {
-+ var->vmode |= FB_VMODE_YWRAP;
-+ var->xoffset = display->var.xoffset;
-+ var->yoffset = display->var.yoffset;
-+ }
-+
-+ /*
-+ * Memory limit
-+ */
-+ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-+ if (line_length*var->yres_virtual > MQ200_FB_SIZE)
-+ return -ENOMEM;
-+
-+ set_color_bitfields(var);
-+
-+ if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-+ oldxres = display->var.xres;
-+ oldyres = display->var.yres;
-+ oldvxres = display->var.xres_virtual;
-+ oldvyres = display->var.yres_virtual;
-+ oldbpp = display->var.bits_per_pixel;
-+ display->var = *var;
-+ if (oldxres != var->xres || oldyres != var->yres ||
-+ oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
-+ oldbpp != var->bits_per_pixel) {
-+
-+ display->screen_base = (char *) p->mqFbAddrVirt;
-+ display->visual = p->fix.visual;
-+ display->type = p->fix.type;
-+ display->type_aux = p->fix.type_aux;
-+ display->ypanstep = p->fix.ypanstep;
-+ display->ywrapstep = p->fix.ywrapstep;
-+ display->line_length = p->fix.line_length;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef CONFIG_FBCON_MFB
-+ case 1:
-+ display->dispsw = &fbcon_mfb;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB2
-+ case 2:
-+ display->dispsw = &fbcon_cfb2;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB4
-+ case 4:
-+ display->dispsw = &fbcon_cfb4;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB8
-+ case 8:
-+ display->dispsw = &fbcon_cfb8;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ display->dispsw = &fbcon_cfb16;
-+ display->dispsw_data = fbcon_cmap.cfb16;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ display->dispsw = &fbcon_cfb24;
-+ display->dispsw_data = fbcon_cmap.cfb24;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ display->dispsw = &fbcon_cfb32;
-+ display->dispsw_data = fbcon_cmap.cfb32;
-+ break;
-+#endif
-+ default:
-+ display->dispsw = &fbcon_dummy;
-+ break;
-+ }
-+
-+
-+ if (p->fb_info.changevar)
-+ (*p->fb_info.changevar)(con);
-+ }
-+
-+ if (oldbpp != var->bits_per_pixel) {
-+ if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-+ return err;
-+ do_install_cmap(con, info);
-+ }
-+
-+ }
-+
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Pan or Wrap the Display
-+ *
-+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-+ */
-+
-+static int mq200fb_pan_display(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ PDEBUG("mq200fb: %i---mq200fb_pan_display.\n", __LINE__);
-+
-+ if (var->vmode & FB_VMODE_YWRAP) {
-+ if (var->yoffset < 0 ||
-+ var->yoffset >= fb_display[con].var.yres_virtual ||
-+ var->xoffset)
-+ return -EINVAL;
-+ } else {
-+ if (var->xoffset+fb_display[con].var.xres >
-+ fb_display[con].var.xres_virtual ||
-+ var->yoffset+fb_display[con].var.yres >
-+ fb_display[con].var.yres_virtual)
-+ return -EINVAL;
-+ }
-+ fb_display[con].var.xoffset = var->xoffset;
-+ fb_display[con].var.yoffset = var->yoffset;
-+ if (var->vmode & FB_VMODE_YWRAP)
-+ fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-+ else
-+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
-+ return 0;
-+}
-+
-+ /*
-+ * Get the Colormap
-+ */
-+
-+static int mq200fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ PDEBUG("mq200fb: %i---mq200fb_get_cmap.\n", __LINE__);
-+
-+ if (con == currcon) /* current console? */
-+ return fb_get_cmap(cmap, kspc, mq200fb_getcolreg, info);
-+ else if (fb_display[con].cmap.len) /* non default colormap? */
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ {
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-+ }
-+ return 0;
-+}
-+
-+ /*
-+ * Set the Colormap
-+ */
-+
-+static int mq200fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err;
-+
-+ PDEBUG("mq200fb: %i---mq200fb_set_cmap.\n", __LINE__);
-+
-+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
-+ return err;
-+ }
-+ if (con == currcon) /* current console? */
-+ return fb_set_cmap(cmap, kspc, mq200fb_setcolreg, info);
-+ else
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ return 0;
-+}
-+
-+
-+static int mq200fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-+ u_long arg, int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+
-+int __init mq200fb_setup(char *options)
-+{
-+ PDEBUG("mq200fb.c: %i---mq200fb_setup\n", __LINE__);
-+
-+/*
-+ char *this_opt;
-+
-+ fb_info.fontname[0] = '\0';
-+
-+ if (!options || !*options)
-+ return 0;
-+
-+ for (this_opt = strtok(options, ","); this_opt;
-+ this_opt = strtok(NULL, ",")) {
-+ if (!strncmp(this_opt, "font:", 5))
-+ strcpy(fb_info.fontname, this_opt+5);
-+ }
-+*/
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Initialisation
-+ */
-+
-+int __init mq200fb_init(void)
-+{
-+ struct fb_info_mq200 *p = NULL;
-+ int i; /* used as loop counter */
-+ struct proc_dir_entry *entry;
-+
-+ p = (struct fb_info_mq200 *) kmalloc(sizeof(*p), GFP_ATOMIC);
-+ if(p==NULL)
-+ return 0;
-+ memset(p, 0, sizeof(*p));
-+
-+ mq200dir = proc_mkdir(MQ200_DIRNAME, NULL);
-+ if (mq200dir == NULL) {
-+ printk(KERN_ERR "mq200fb: can't create /proc/" MQ200_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ regdir = proc_mkdir(REG_DIRNAME, mq200dir);
-+ if (regdir == NULL) {
-+ printk(KERN_ERR "mq200fb: can't create /proc/" MQ200_DIRNAME "/" REG_DIRNAME "\n");
-+ return(-ENOMEM);
-+ }
-+
-+ for(i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ entry = create_proc_entry(mq200_regs[i].name,
-+ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH,
-+ regdir);
-+ if(entry) {
-+ mq200_regs[i].low_ino = entry->low_ino;
-+ entry->proc_fops = &proc_reg_operations;
-+ }
-+ else {
-+ printk( KERN_ERR
-+ "mq200fb: can't create /proc/" REG_DIRNAME
-+ "/%s\n", mq200_regs[i].name);
-+ return(-ENOMEM);
-+ }
-+ }
-+
-+
-+#ifdef MQ_SA1110
-+
-+#ifdef CONFIG_SA1100_ASSABET
-+ pCPUReg=(u32 *)ioremap( MSC2, 4);
-+ *pCPUReg = 0x42194449;
-+ iounmap((void *) pCPUReg);
-+
-+ GPDR |= 0x08000000;
-+ GAFR |= 0x08000000;
-+ TUCR |= 0x20000000;
-+
-+ ASSABET_BCR_set(ASSABET_BCR_GFX_RST); /* ASSABET_BCR */
-+
-+ MQ_DELAY(8);
-+ ASSABET_BCR_clear(ASSABET_BCR_GFX_RST);
-+ MQ_DELAY(30);
-+ ASSABET_BCR_set(ASSABET_BCR_GFX_RST); /* ASSABET_BCR */
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+ GPDR |= (1<<3);
-+ GAFR |= ~(1<<3);
-+ GPSR |= (1<<3);
-+#endif
-+
-+ p->mqMmioAddrPhys=REGISTER_BASE;
-+ p->mqFbAddrPhys=FB_BASE;
-+
-+ p->mqMmioAddrVirt = mqMmioAddr = 0xf2e00000;
-+ p->mqFbAddrVirt = mqFbAddr = 0xf2800000;
-+
-+#endif /* MQ_SA1110 */
-+
-+ mqflag = dc.flag;
-+
-+ PDEBUG("mq200fb.c: line %i, mqMmioAddr = 0X%08X, mqFbAddr = 0X%08X\n",\
-+ __LINE__, mqMmioAddr, mqFbAddr);
-+
-+ /* Setmode for MQ200 chip */
-+ setmqmode(&dc, (void *) mqMmioAddr);
-+
-+ /* Set fb_info_mq200.fix info */
-+ strcpy(p->fix.id, mq200fb_name);
-+ p->fix.smem_start = p->mqFbAddrPhys;
-+ p->fix.smem_len = MQ200_FB_SIZE;
-+ p->fix.mmio_start = p->mqMmioAddrPhys;
-+ p->fix.mmio_len = MQ200_MMIO_SIZE;
-+ p->fix.type = FB_TYPE_PACKED_PIXELS;
-+
-+ if(dc.bpp <= 8)
-+ p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else if (dc.bpp >= 16)
-+ p->fix.visual = FB_VISUAL_DIRECTCOLOR;
-+
-+ p->fix.line_length = dc.stride;
-+
-+ /* Set fb_info_mq200.var info */
-+ p->var.xres = dc.x;
-+ p->var.yres = dc.y;
-+ p->var.xres_virtual = dc.x;
-+ p->var.yres_virtual = dc.y;
-+ p->var.bits_per_pixel = dc.bpp;
-+
-+ if(dc.bpp == 8) {
-+ p->var.red.offset = 0;
-+ p->var.green.offset = 0;
-+ p->var.blue.offset = 0;
-+ p->var.red.length = p->var.green.length = \
-+ p->var.blue.length = dc.bpp;
-+ p->var.transp.length = 0;
-+ p->var.transp.offset = 0;
-+ }
-+ else if(dc.bpp == 16) {
-+#ifdef CONF
-+ IG_PREP
-+ p->var.red.offset = 2;
-+ p->var.green.offset = -3;
-+ p->var.blue.offset = 8;
-+#else
-+ p->var.red.offset = 11;
-+ p->var.green.offset = 5;
-+ p->var.blue.offset = 0;
-+#endif
-+
-+ p->var.red.length = 5;
-+ p->var.green.length = 6;
-+ p->var.blue.length = 5;
-+ }
-+ else if (dc.bpp == 24) {
-+#ifdef CONFIG_PREP
-+ p->var.red.offset = 8;
-+ p->var.green.offset = 16;
-+ p->var.blue.offset = 24;
-+#else
-+ p->var.red.offset = 16;
-+ p->var.green.offset = 8;
-+ p->var.blue.offset = 0;
-+#endif
-+ p->var.red.length = 8;
-+ p->var.green.length = 8;
-+ p->var.blue.length = 8;
-+ }
-+ else if(dc.bpp == 32) {
-+#ifdef CONFIG_PREP
-+ p->var.red.offset = 8;
-+ p->var.green.offset = 16;
-+ p->var.blue.offset = 24;
-+#else
-+ p->var.red.offset = 0;
-+ p->var.green.offset = 8;
-+ p->var.blue.offset = 16;
-+#endif /* CONFIG_PREP */
-+ p->var.red.length = 8;
-+ p->var.green.length = 8;
-+ p->var.blue.length = 8;
-+ }
-+
-+ p->var.transp.length = 0;
-+ p->var.transp.offset = 0;
-+ p->var.height = p->var.width = -1;
-+ p->var.vmode = FB_VMODE_NONINTERLACED;
-+ p->var.pixclock = 10000;
-+ p->var.left_margin = p->var.right_margin = 16;
-+ p->var.upper_margin = p->var.lower_margin = 16;
-+ p->var.hsync_len = p->var.vsync_len = 8;
-+
-+ /* Set fb_info_mq200.disp info */
-+ p->disp.var = p->var;
-+ p->disp.cmap.red = NULL;
-+ p->disp.cmap.green = NULL;
-+ p->disp.cmap.blue = NULL;
-+ p->disp.cmap.transp = NULL;
-+ p->disp.screen_base = (char *) p->mqFbAddrVirt;
-+ p->disp.visual = p->fix.visual;
-+ p->disp.type = p->fix.type;
-+ p->disp.type_aux = p->fix.type_aux;
-+ p->disp.line_length = p->fix.line_length;
-+ p->disp.can_soft_blank = 1;
-+
-+ switch(dc.bpp) {
-+#ifdef CONFIG_FBCON_CFB8
-+ case 8:
-+ p->disp.dispsw = &fbcon_cfb8;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ p->disp.dispsw = &fbcon_cfb16;
-+ p->disp.dispsw_data = fbcon_cmap.cfb16;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ p->disp.dispsw = &fbcon_cfb24;
-+ p->disp.dispsw_data = fbcon_cmap.cfb24;
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ p->disp.dispsw = &fbcon_cfb32;
-+ p->disp.dispsw_data = fbcon_cmap.cfb32;
-+ break;
-+#endif
-+ default:
-+ PDEBUG("mq200fb.c: %i---Wrong configuration options", __LINE__);
-+ }
-+
-+ p->disp.scrollmode = SCROLL_YREDRAW;
-+
-+ strcpy(p->fb_info.modename, p->fix.id);
-+ p->fb_info.changevar = NULL;
-+ p->fb_info.node = NODEV;
-+
-+ p->fb_info.fbops = &mq200fb_ops;
-+ p->fb_info.disp = &(p->disp);
-+ p->fb_info.switch_con = &mq200fbcon_switch;
-+ p->fb_info.updatevar = &mq200fbcon_updatevar;
-+ p->fb_info.blank = &mq200fbcon_blank;
-+ p->fb_info.flags = FBINFO_FLAG_DEFAULT;
-+
-+ for (i = 0; i < 16; i++) {
-+ int j = color_table[i];
-+ p->palette[i].red = default_red[j];
-+ p->palette[i].green = default_grn[j];
-+ p->palette[i].blue = default_blu[j];
-+ }
-+
-+ if (register_framebuffer(&p->fb_info) < 0) {
-+ PDEBUG("Oops...register_framebuffer failed!\n");
-+ iounmap(p);
-+ iounmap((void *)mqMmioAddr);
-+ iounmap((void *)mqFbAddr);
-+ return -EINVAL;
-+ }
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Note that the console registers this as well, but we want to
-+ * power down the display prior to sleeping.
-+ */
-+ p->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, mq200fb_pm_callback);
-+ if (p->pm)
-+ p->pm->data = p;
-+#endif
-+ PDEBUG("fb%d: Virtual frame buffer device, using %ldK of video memory\n", \
-+ GET_FB_IDX(p->fb_info.node), MQ200_FB_SIZE >> 10);
-+ return 0;
-+}
-+
-+static int mq200fbcon_switch(int con, struct fb_info *info)
-+{
-+ /* Do we have to save the colormap? */
-+
-+ PDEBUG("mq200fb: mq200fbcon_switch.\n");
-+
-+ if (fb_display[currcon].cmap.len)
-+ fb_get_cmap(&fb_display[currcon].cmap, 1, mq200fb_getcolreg, info);
-+
-+ currcon = con;
-+ /* Install new colormap */
-+ do_install_cmap(con, info);
-+ return 0;
-+}
-+
-+/*
-+ * Update the `var' structure (called by fbcon.c)
-+ */
-+
-+static int mq200fbcon_updatevar(int con, struct fb_info *info)
-+{
-+ /* Nothing */
-+
-+ PDEBUG("mq200fb: mq200fbcon_updatevar.\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Blank the display.
-+ */
-+
-+static void mq200fbcon_blank(int blank, struct fb_info *info)
-+{
-+ /*struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;*/
-+
-+ /* Nothing */
-+ /*
-+ if(blank)
-+ onoffdisplay(DISABLE_LCD_GC1, (void *) p->mqMmioAddrVirt);
-+ else
-+ onoffdisplay(ENABLE_LCD_GC1, (void *) p->mqMmioAddrVirt);*/
-+}
-+
-+static u_long get_line_length(int xres_virtual, int bpp)
-+{
-+ u_long length;
-+
-+ PDEBUG("mq200fb: get_line_length.\n");
-+
-+ length = (xres_virtual+bpp-1)/bpp;
-+ length = (length+31)&-32;
-+ length >>= 3;
-+ return(length);
-+}
-+
-+static void mq200fb_encode_fix(struct fb_fix_screeninfo *fix,
-+ struct fb_var_screeninfo *var)
-+{
-+
-+ PDEBUG("mq200fb: mq200fb_encode_fix.\n");
-+
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, mq200fb_name);
-+ fix->smem_start = mqFbAddr;
-+ fix->smem_len = MQ200_FB_SIZE;
-+ fix->type = FB_TYPE_PACKED_PIXELS;
-+ fix->type_aux = 0;
-+ switch (var->bits_per_pixel) {
-+ case 1:
-+ fix->visual = FB_VISUAL_MONO01;
-+ break;
-+ case 2:
-+ case 4:
-+ case 8:
-+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
-+ break;
-+ case 16:
-+ case 24:
-+ case 32:
-+ fix->visual = FB_VISUAL_DIRECTCOLOR;
-+ break;
-+ }
-+ fix->ywrapstep = 1;
-+ fix->xpanstep = 1;
-+ fix->ypanstep = 1;
-+ fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-+}
-+
-+static void set_color_bitfields(struct fb_var_screeninfo *var)
-+{
-+
-+ PDEBUG("mq200fb: set_color_bitfields.\n");
-+
-+ switch (var->bits_per_pixel) {
-+ case 1:
-+ 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 */
-+#ifdef CONFIG_PREP
-+ var->red.offset = 2;
-+ var->green.offset = -3;
-+ var->blue.offset = 8;
-+#else
-+ var->red.offset = 11;
-+ var->green.offset = 5;
-+ var->blue.offset = 0;
-+#endif
-+ var->red.length = 5;
-+ var->green.length = 6;
-+ var->blue.length = 5;
-+ var->transp.length = 0;
-+ var->transp.offset = 0;
-+ break;
-+ case 24: /* RGB 888 */
-+#ifdef CONFIG_PREP
-+ var->red.offset = 8;
-+ var->green.offset = 16;
-+ var->blue.offset = 24;
-+#else
-+ var->red.offset = 16;
-+ var->green.offset = 8;
-+ var->blue.offset = 0;
-+#endif
-+ var->red.length = 8;
-+ var->green.length = 8;
-+ var->blue.length = 8;
-+ break;
-+ case 32: /* RGBA 8888 */
-+ var->red.offset = 0;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 16;
-+ var->blue.length = 8;
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ break;
-+ }
-+ var->red.msb_right = 0;
-+ var->green.msb_right = 0;
-+ var->blue.msb_right = 0;
-+ var->transp.msb_right = 0;
-+}
-+
-+
-+ /*
-+ * Read a single color register and split it into
-+ * colors/transparent. Return != 0 for invalid regno.
-+ */
-+
-+static int mq200fb_getcolreg(u_int regno, u_int *red, u_int *green,
-+ u_int *blue, u_int *transp, struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+
-+ /*PDEBUG("mq200fb: mq200fb_getcolreg.\n");*/
-+
-+ if (regno > 255)
-+ return 1;
-+ *red = (p->palette[regno].red<<8) | p->palette[regno].red;
-+ *green = (p->palette[regno].green<<8) | p->palette[regno].green;
-+ *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
-+ *transp = 0;
-+ return 0;
-+}
-+
-+
-+ /*
-+ * Set a single color register. The values supplied are already
-+ * rounded down to the hardware's capabilities (according to the
-+ * entries in the var structure). Return != 0 for invalid regno.
-+ */
-+
-+static int mq200fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) info;
-+ unsigned long color;
-+
-+ if (regno > 255)
-+ return 1;
-+
-+ /*PDEBUG("In mq200fb_setcolreg, regno = %d, 0x%0x\n", regno, red);*/
-+
-+ /*PDEBUG("mq200fb: mq200fb_setcolreg.\n");*/
-+
-+ switch (p->var.bits_per_pixel) {
-+#ifdef CONFIG_FBCON_CFB16
-+ case 16:
-+ if(regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb16[regno] =
-+ ((red & 0xf800) >> 9) |
-+ ((green & 0xf800) >> 14) |
-+ ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
-+#else
-+ fbcon_cmap.cfb16[regno] =
-+ ((red & 0xf800) >> 0) |
-+ ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
-+
-+#endif /* CONFIG_PREP */
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB24
-+ case 24:
-+ if (regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb24[regno] =
-+ ((red & 0xff00)) |
-+ ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-+#else
-+ fbcon_cmap.cfb24[regno] =
-+ ((red & 0xff00) << 8) |
-+ ((green & 0xff00)) | ((blue & 0xff00) >> 8);
-+#endif
-+ break;
-+#endif
-+#ifdef CONFIG_FBCON_CFB32
-+ case 32:
-+ if(regno < CMAPSIZE)
-+#ifdef CONFIG_PREP
-+ fbcon_cmap.cfb32[regno] =
-+ ((red & 0xff00)) |
-+ ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-+#else
-+ fbcon_cmap.cfb32[regno] =
-+ ((red & 0xff00) >> 8) |
-+ ((green & 0xff00)) | ((blue & 0xff00) << 8);
-+#endif
-+
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ red &= 0xFF;
-+ green &= 0xFF;
-+ blue &= 0xFF;
-+
-+ p->palette[regno].red = red;
-+ p->palette[regno].green = green;
-+ p->palette[regno].blue = blue;
-+
-+ color = red | (green << 8) | (blue << 16);
-+ setpal(regno, color, (void *)p->mqMmioAddrVirt);
-+
-+ return 0;
-+}
-+
-+
-+static void do_install_cmap(int con, struct fb_info *info)
-+{
-+ if (con != currcon)
-+ return;
-+
-+ PDEBUG("mq200fb: do_install_cmap.\n");
-+
-+ if (fb_display[con].cmap.len)
-+ fb_set_cmap(&fb_display[con].cmap, 1, mq200fb_setcolreg, info);
-+ else {
-+ int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
-+ fb_set_cmap(fb_default_cmap(size), 1, mq200fb_setcolreg, info);
-+ }
-+}
-+
-+
-+#ifdef MODULE
-+int init_module(void)
-+{
-+ return mq200fb_init();
-+}
-+
-+void cleanup_module(void)
-+{
-+ unregister_framebuffer(&(fb_info_mq200.fb_info));
-+ iounmap((void *)(fb_info_mq200.mqMmioAddrVirt));
-+ iounmap((void *)(fb_info_mq200.mqFbAddrVirt));
-+}
-+
-+#endif /* MODULE */
-+
-+/* The following is copied from mq2hw.c for initialization of MQ200 */
-+
-+long idmqchip(void *pMQMMIO)
-+{
-+ unsigned long id;
-+
-+ id = READ32(PCI_VENDOR_DEVICE);
-+ return (id);
-+}
-+
-+/* Setmode for MediaQ chip
-+ *
-+ */
-+void setmqmode(PDISPLAY_CONFIG pDC, void *pMQMMIO)
-+{
-+ volatile unsigned long regdata, pmmisc;
-+ int x=0, y=0, freq=0, paneltype; /* i is used as loop counter */
-+ unsigned long screensize, gc_startaddr;
-+
-+ printk("mq200fb: setmqmode - before reset\n");
-+ regdata = SW_CHIP_RESET;
-+ REG32(DC_0, regdata);
-+ MQ_DELAY(10);
-+ /* use 50MHz for LCD only and 83MHz if CRT is on */
-+ if (pDC->flag & CRT_ON)
-+ regdata = PLL1_83MHZ;
-+ else
-+ regdata = PLL1_50MHZ;
-+ REG32(DC_0, regdata);
-+ MQ_DELAY(30);
-+
-+ /* Enter D0 state from reset D3 state */
-+
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D0);
-+ MQ_DELAY(30);
-+
-+ while(1)
-+ {
-+ if((READ32(PCI_PM_CNTL_STATUS) & POWER_STATE_MASK) == 0x0)
-+ break;
-+ }
-+
-+ /* In stable D3 state here ... */
-+ /*
-+ * Set up PMU misc registers
-+ * - also PMCLK_2048CYCLE and FP_PMCLK_128K if SA1110
-+ */
-+ if ((READ32(DC_1) & BUS_MODE_MASK) == BUS_MODE_SA1110)
-+ regdata = GE_ENABLE|GE_BY_PLL1|PMCLK_2048CYCLE|FP_PMCLK_512;
-+ else
-+ /* the rest of CPUs */
-+ regdata = GE_ENABLE|GE_BY_PLL1;
-+ REG32(PM_MISC, regdata);
-+
-+ REG32(D1_STATE, DEF_D1);
-+ REG32(D2_STATE, DEF_D2);
-+
-+ /* To initialize MIU block ... */
-+ REG32(MIU_CONTROL1, DRAM_RESET_DISABLE);
-+ MQ_DELAY(5);
-+
-+ REG32(MIU_CONTROL1, 0x00);
-+ MQ_DELAY(5);
-+
-+ if (pDC->flag & CRT_ON)
-+ regdata = DEF_MIU2_83MHZ;
-+ else
-+ regdata = DEF_MIU2_50MHZ;
-+ REG32(MIU_CONTROL2, regdata);
-+ REG32(MIU_CONTROL3, DEF_MIU3);
-+ /* MIU REG 5 MUST BE PROGRAMMED BEFORE MIU REG 4 */
-+ REG32(MIU_CONTROL5, DEF_MIU5);
-+ REG32(MIU_CONTROL4, DEF_MIU4);
-+ MQ_DELAY(5);
-+
-+ REG32(MIU_CONTROL1, MIU_ENABLE | MIU_RESET_DISABLE);
-+ MQ_DELAY(5);
-+
-+ /* Here, MIU is supposed to ready to serve ... */
-+
-+ gc_startaddr = 0;
-+ /* Last 1KB is reserved for hardware cursor */
-+ if (mqflag & ENA_HW_CURSOR)
-+ {
-+ printk("mq200fb: enabling hardware cursor\n");
-+ setup_cursor(pMQMMIO);
-+ enable_cursor(pMQMMIO);
-+
-+ }
-+ /* Set up GE Base Address */
-+ REG32(BASE_ADDRESS, gc_startaddr);
-+ /* Set up flat panel parameters
-+ *
-+ */
-+ paneltype = pDC->flag & PANEL_TYPE_MASK;
-+ if (paneltype)
-+ {
-+ /* Panel is used as a display in the system */
-+ setupfp(paneltype, pMQMMIO);
-+
-+ /* Set up DSTN half frame buffer */
-+ screensize = pDC->x * pDC->y * pDC->bpp / 8 + gc_startaddr;
-+ setuphfbuffer(paneltype, screensize, pMQMMIO);
-+
-+ /* Get flat panel frequency */
-+ freq = fpControlData[paneltype].freq;
-+ }
-+
-+ /* Based on display configuration, proper GC is set up .. */
-+ if (pDC->flag & LARGE_DESKTOP)
-+ {
-+ switch (pDC->flag & LCDCRT_POS_MASK)
-+ {
-+ case HORI_CRT_LCD:
-+ case HORI_LCD_CRT:
-+ x = pDC->x / 2;
-+ y = pDC->y;
-+ break;
-+
-+ case VERT_CRT_LCD:
-+ case VERT_LCD_CRT:
-+ x = pDC->x;
-+ y = pDC->y / 2;
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ /* SAME_IMAGE and simultaneous LCD and/or CRT */
-+ x = pDC->x;
-+ y = pDC->y;
-+ }
-+
-+ /* Set up GC memory configuration */
-+ setupgcmem(pDC, gc_startaddr, pMQMMIO);
-+
-+ pmmisc = READ32(PM_MISC);
-+
-+ /* Set up 2 GCs */
-+ if (pDC->flag & USE_2GCs)
-+ {
-+ /* Set up GC1 for CRT */
-+ setupgc(IS_GC1, x, y, pDC->bpp, pDC->refresh, pMQMMIO);
-+
-+ /* Set up GC2 for flat panel */
-+ setupgc(IS_GC2, x, y, pDC->bpp, freq, pMQMMIO);
-+
-+ /* PLL2 and PLL3 are both used ... */
-+ /* to save a little bit power, can shut down PLL3 if both LCD
-+ and CRT are the same frequency...
-+ */
-+ pmmisc |= (PLL2_ENABLE | PLL3_ENABLE);
-+ REG32(PM_MISC, pmmisc);
-+
-+ /* Enable panel and CRT accordingly */
-+ if (pDC->flag & LCD_ON)
-+ onoffdisplay(ENABLE_LCD_GC2, pMQMMIO);
-+
-+ if (pDC->flag & CRT_ON)
-+ onoffdisplay(ENABLE_CRT_GC1, pMQMMIO);
-+ }
-+ else
-+ {
-+ /* Simultaneous mode - set up GC1 only */
-+ if (paneltype)
-+ setupgc(IS_GC1, x, y, pDC->bpp, freq, pMQMMIO);
-+ else
-+ setupgc(IS_GC1, x, y, pDC->bpp, pDC->refresh, pMQMMIO);
-+
-+ /* Use PLL2 */
-+ pmmisc |= PLL2_ENABLE;
-+ REG32(PM_MISC, pmmisc);
-+
-+ /* Enable panel and CRT accordingly */
-+ if (pDC->flag & LCD_ON)
-+ onoffdisplay(ENABLE_LCD_GC1, pMQMMIO);
-+
-+ if (pDC->flag & CRT_ON)
-+ onoffdisplay(ENABLE_CRT_GC1, pMQMMIO);
-+ }
-+}
-+
-+/* Set up flat panel register depending on panel type
-+ *
-+ */
-+void setupfp(int panel, void *pMQMMIO)
-+{
-+ PFPDATA_CONTROL pFP;
-+ int frcaddr, frcidx, i;
-+
-+ /* Locate panel data pointer */
-+ pFP = &fpControlData[panel];
-+ printk("FP_PIN_CONTROL set to %x\n", (u_int)pFP->fpPinControl);
-+ REG32(FP_CONTROL, pFP->fpControl);
-+ REG32(FP_PIN_CONTROL, pFP->fpPinControl);
-+ REG32(STN_CONTROL, pFP->stnControl);
-+ REG32(FP_GPO_CONTROL, DEF_GPO_CONTROL);
-+ REG32(FP_GPIO_CONTROL, DEF_GPIO_CONTROL);
-+ REG32(PWM_CONTROL, DEF_PWM_CONTROL);
-+
-+ /* Program FRC registers for STN panel (DSTN and SSTN) */
-+ frcidx = 0; /* DSTN */
-+ if ( (pFP->fpControl & FP_TYPE_MASK) != FP_TYPE_TFT )
-+ {
-+ if ((pFP->fpControl & FP_TYPE_MASK) == FP_TYPE_SSTN)
-+ frcidx++; /* SSTN index */
-+
-+ for ( i = frcaddr = 0; i < FRC_PATTERN_CNT; i++,frcaddr+=4 )
-+ REG32((FRC_PATTERN + frcaddr),
-+ FRCControlData[frcidx].frcPattern[i]);
-+
-+ for ( i = frcaddr = 0; i < FRC_WEIGHT_CNT; i++,frcaddr+=4 )
-+ REG32((FRC_WEIGHT + frcaddr), FRCControlData[frcidx].frcWeight[i]);
-+ }
-+
-+ /* Set up flat panel GPO and GPIO register from default */
-+ REG32(FP_GPO_CONTROL, DEF_GPO_CONTROL);
-+ REG32(FP_GPIO_CONTROL, DEF_GPIO_CONTROL);
-+
-+ return;
-+}
-+
-+/* Set up DSTN half frame buffer register depending on panel type
-+ *
-+ * panel : panel type
-+ * sizeused : used (occupied) area of frame buffer
-+ *
-+ */
-+void setuphfbuffer(int panel, unsigned long sizeused, void *pMQMMIO)
-+{
-+ PFPDATA_CONTROL pFP;
-+ unsigned long dstnfbsize, dstnstart, dstnend;
-+
-+ /* Locate panel data pointer */
-+ pFP = &fpControlData[panel];
-+
-+ /* Figure out half frame buffer for DSTN panel */
-+ if ( (pFP->fpControl & FP_TYPE_MASK) == FP_TYPE_DSTN )
-+ {
-+ /* Color D-STN memory requirement - no need to *3 for mono dstn panel */
-+ if (pFP->fpControl & FP_MONO)
-+ dstnfbsize = pFP->x;
-+ else
-+ dstnfbsize = pFP->x * 3;
-+ dstnfbsize = (((dstnfbsize + 127) >> 7) * pFP->y) << 3;
-+
-+ /* make it suitable for register bits definition */
-+ dstnstart = (sizeused + 127) >> 7;
-+ dstnend = (sizeused + dstnfbsize + 15) >> 4;
-+ REG32(DSTN_FB_CONTROL, (dstnstart | ((dstnend - 1) << 16)));
-+ }
-+ return;
-+}
-+
-+/* Set up graphics controller (GC1 or GC2) timing registers and PLLx
-+ *
-+ * gc: GC1 or GC2
-+ * x : horizontal viewport size
-+ * y : vertical viewport size
-+ * refresh : refresh rate (mainly VESA-supported mode)
-+ *
-+ */
-+void setupgc(int gc, int x, int y, int bpp, int refresh, void *pMQMMIO)
-+{
-+ PDISPLAY_TIMING pDT;
-+ unsigned long gccontrol;
-+
-+ /* Locate GC timing parameters first */
-+ pDT = getgcparam(x, y, refresh);
-+
-+ /* error checking for pDT here */
-+
-+ gccontrol = getbppbits(bpp) |
-+ FDx_1 | (1L << 24) |
-+ IM_ENABLE;
-+
-+ if (gc == IS_GC1)
-+ {
-+ /* Set up GC window as display */
-+ REG32(HW1_CONTROL, ((x - 1) << 16) | (1 << 28));
-+ REG32(VW1_CONTROL, ((y - 1) << 16));
-+
-+ REG32(HD1_CONTROL, pDT->hd);
-+ REG32(VD1_CONTROL, pDT->vd);
-+ REG32(HS1_CONTROL, pDT->hs);
-+ REG32(VS1_CONTROL, pDT->vs);
-+ REG32(VS1_CONTROL, pDT->vs);
-+ REG32(GC1_CRT_CONTROL, pDT->crtc);
-+
-+ /* Program PLL2 for GC1 */
-+ REG32(PLL2_CONTROL, pDT->pll);
-+
-+ /* GC1 control register */
-+ gccontrol |= GxRCLK_PLL2;
-+ REG32(GC1_CONTROL, gccontrol);
-+ }
-+ else
-+ if (gc == IS_GC2)
-+ {
-+ /* Set up GC window as display */
-+ REG32(HW2_CONTROL, ((x - 1) << 16));
-+ REG32(VW2_CONTROL, ((y - 1) << 16));
-+
-+ REG32(HD2_CONTROL, pDT->hd);
-+ REG32(VD2_CONTROL, pDT->vd);
-+ REG32(HS2_CONTROL, pDT->hs);
-+ REG32(VS2_CONTROL, pDT->vs);
-+ REG32(VS2_CONTROL, pDT->vs);
-+ REG32(GC1_CRT_CONTROL, pDT->crtc);
-+
-+ /* Program PLL3 for GC2 */
-+ REG32(PLL3_CONTROL, pDT->pll);
-+
-+ /* GC2 control register */
-+ gccontrol |= GxRCLK_PLL3;
-+ REG32(GC2_CONTROL, gccontrol);
-+ }
-+ return;
-+}
-+
-+/* Set up graphics controller (GC1 or GC2) memory configuration (stride and
-+ * starting address etc.)
-+ *
-+ * pDC : pointer to active DIPSLAY_CONFIG structure
-+ * startaddr : starting address - 0 if starting from very beginning
-+ *
-+ * - use GC1 for Simultaneous mode (1 GC)
-+ * - use GC1 for CRT and GC2 for LCD at QView mode
-+ *
-+ */
-+void setupgcmem(PDISPLAY_CONFIG pDC, unsigned long startaddr, void *pMQMMIO)
-+{
-+ unsigned long stride=0, start1=0, start2=0;
-+
-+ if (pDC->flag & LARGE_DESKTOP)
-+ {
-+ /* 4 possible layouts */
-+ switch (pDC->flag & LCDCRT_POS_MASK)
-+ {
-+ case HORI_CRT_LCD:
-+ stride = (pDC->x / 2) * pDC->bpp / 8;
-+ start1 = startaddr;
-+ start2 = startaddr + stride;
-+ break;
-+
-+ case HORI_LCD_CRT:
-+ stride = (pDC->x / 2) * pDC->bpp / 8;
-+ start1 = startaddr + stride;
-+ start2 = startaddr;
-+ break;
-+
-+ case VERT_CRT_LCD:
-+ stride = pDC->x * pDC->bpp / 8;
-+ start1 = startaddr;
-+ start2 = startaddr + stride * pDC->y / 2;
-+ break;
-+
-+ case VERT_LCD_CRT:
-+ stride = pDC->x * pDC->bpp / 8;
-+ start1 = startaddr + stride * pDC->y / 2;
-+ start2 = startaddr;
-+ break;
-+ }
-+
-+ /* Program to the chip */
-+ REG32(IW1_STRIDE, stride);
-+ REG32(IW2_STRIDE, stride);
-+
-+ REG32(IW1_START_ADDR, start1);
-+ REG32(IW2_START_ADDR, start2);
-+ }
-+ else
-+ {
-+ /* QView Same Image and Simultaneous LCD and/or CRT
-+ *
-+ * - set up 2 GCs in any cases ...
-+ * - 2 addidtional registers write vs. code size
-+ *
-+ */
-+
-+ /* Calculate stride */
-+ stride = pDC->x * pDC->bpp / 8;
-+
-+ REG32(IW1_STRIDE, stride);
-+ REG32(IW2_STRIDE, stride);
-+
-+ REG32(IW1_START_ADDR, startaddr);
-+ REG32(IW2_START_ADDR, startaddr);
-+ }
-+ return;
-+}
-+
-+/* Program palette entry
-+ *
-+ */
-+void setpal(int index, unsigned long color, void *pMQMMIO)
-+{
-+ /*PDEBUG("mq200fb: setpal. %d %d\n", index, color);*/
-+
-+ REG32_PAL(index, color);
-+}
-+
-+/* Vertical blank time is in progress ..
-+ *
-+ */
-+void invblank(void *pMQMMIO)
-+{
-+ unsigned long *intstat = (unsigned long *)(pMQMMIO+INT_STATUS_REG);
-+
-+ /* Make sure int occurs first */
-+ while ( !(*intstat & ST_GC1_VDE_F) );
-+
-+ /* Reset GC1 VDE F status bit - write 1 to clear the status */
-+ REG32(INT_STATUS_REG,ST_GC1_VDE_F);
-+
-+ /* Wait for next VDE falling edge for DAC access */
-+ while ( !(*intstat & ST_GC1_VDE_F) );
-+
-+ /* Here MQ200 should be in V blank period ... */
-+ return;
-+}
-+
-+/* Retrive graphics controller parameters from supported table
-+ *
-+ */
-+PDISPLAY_TIMING getgcparam(int x, int y, int refresh)
-+{
-+ int i;
-+
-+ for (i=0; i < MAX_MQMODE; i++)
-+ {
-+ if ( TimingParam[i].x == x
-+ && TimingParam[i].y == y
-+ && TimingParam[i].refresh == refresh )
-+ return ( (PDISPLAY_TIMING)&TimingParam[i] );
-+ }
-+ return (NULL); /* not existed */
-+}
-+
-+/* Return color depth setting for GC
-+ *
-+ */
-+unsigned long getbppbits(int bpp)
-+{
-+ unsigned long bppbits = 0;
-+
-+ switch(bpp)
-+ {
-+ case 8UL: bppbits = GC_8BPP; break;
-+ case 16UL: bppbits = GC_16BPP_BP; break;
-+ case 24UL: bppbits = GC_24BPP_BP; break;
-+ case 32UL: bppbits = GC_32BPP_ARGB_BP; break;
-+ case 4UL: bppbits = GC_4BPP; break;
-+ case 2UL: bppbits = GC_2BPP; break;
-+ case 1UL: bppbits = GC_1BPP; break;
-+ }
-+ return (bppbits);
-+}
-+
-+/* Turn on/off LCD or CRT driven by either GC1 or GC2
-+ *
-+ */
-+void onoffdisplay(int display_flag, void *pMQMMIO)
-+{
-+ unsigned long fpcontrol, gccontrol, crtcontrol;
-+
-+ switch (display_flag)
-+ {
-+ case ENABLE_LCD_GC1:
-+ /* Obtain current setting */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ gccontrol = READ32(GC1_CONTROL);
-+
-+ /* Turn on GC1 first if remain disabled */
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC1_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Flat panel controlled by GC1 */
-+ REG32(FP_CONTROL, fpcontrol | FPI_BY_GC1);
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+ mq200_backlight(pMQMMIO, 1);
-+#endif
-+
-+ break;
-+
-+ case ENABLE_LCD_GC2:
-+ /* Obtain current setting */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ gccontrol = READ32(GC2_CONTROL);
-+
-+ /* Turn on GC1 first if remain disabled */
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC2_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Flat panel controlled by GC1 */
-+ REG32(FP_CONTROL, fpcontrol | FPI_BY_GC2);
-+ break;
-+
-+ case DISABLE_LCD_GC1:
-+ /* Disable flat panel first */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ REG32(FP_CONTROL, fpcontrol);
-+
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & (~CRT_BY_GCxMASK);
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+ mq200_backlight(pMQMMIO, 0);
-+#endif
-+
-+ /* Disable GC1 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC1))
-+ {
-+ gccontrol = READ32(GC1_CONTROL);
-+ REG32(GC1_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case DISABLE_LCD_GC2:
-+ /* Disable flat panel first */
-+ fpcontrol = READ32(FP_CONTROL) & FPI_BY_GCxMASK;
-+ REG32(FP_CONTROL, fpcontrol);
-+
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & (~CRT_BY_GCxMASK);
-+
-+ /* Disable GC2 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC2))
-+ {
-+ gccontrol = READ32(GC2_CONTROL);
-+ REG32(GC2_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case ENABLE_CRT_GC1:
-+ /* Enable GC1 if not yet enabled */
-+ gccontrol = READ32(GC1_CONTROL);
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC1_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Enable CRT by GC1 */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol | CRT_BY_GC1);
-+ break;
-+
-+ case ENABLE_CRT_GC2:
-+ /* Enable GC2 if not yet enabled */
-+ gccontrol = READ32(GC2_CONTROL);
-+ if (!(gccontrol & GC_ENABLE))
-+ REG32(GC2_CONTROL, gccontrol | GC_ENABLE);
-+
-+ /* Enable CRT by GC2 */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol | CRT_BY_GC2);
-+ break;
-+
-+ case DISABLE_CRT_GC1:
-+ /* Disable CRT first */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol);
-+
-+ fpcontrol = READ32(FP_CONTROL) & (~FPI_BY_GCxMASK);
-+
-+ /* Disable GC1 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC1))
-+ {
-+ gccontrol = READ32(GC1_CONTROL);
-+ REG32(GC1_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+
-+ case DISABLE_CRT_GC2:
-+ /* Disable CRT first */
-+ crtcontrol = READ32(GC1_CRT_CONTROL) & CRT_BY_GCxMASK;
-+ REG32(GC1_CRT_CONTROL, crtcontrol);
-+
-+ fpcontrol = READ32(FP_CONTROL) & (~FPI_BY_GCxMASK);
-+
-+ /* Disable GC2 if not used for CRT */
-+ if (!(crtcontrol == CRT_BY_GC2))
-+ {
-+ gccontrol = READ32(GC2_CONTROL);
-+ REG32(GC2_CONTROL, gccontrol & GC_DISABLE);
-+ }
-+ break;
-+ }
-+ return;
-+}
-+
-+/* Setup hardware cursor data area start address in the frame buffer
-+ *
-+ */
-+void setup_cursor(void *pMQMMIO)
-+{
-+ REG32(HW_CURSOR1_FGCLR, CURSOR_FGCLR);
-+ REG32(HW_CURSOR2_FGCLR, CURSOR_FGCLR);
-+ REG32(HW_CURSOR1_BGCLR, CURSOR_BGCLR);
-+ REG32(HW_CURSOR2_BGCLR, CURSOR_BGCLR);
-+ REG32(HW_CURSOR1_ADDR, 0x000007ff);
-+ REG32(HW_CURSOR2_ADDR, 0x000007ff);
-+}
-+
-+/* Move cursor position and adjust hot spot offset
-+ *
-+ */
-+void move_cursor(unsigned long pos, unsigned long addr, void *pMQMMIO)
-+{
-+ REG32(HW_CURSOR1_POS, pos);
-+ REG32(HW_CURSOR2_POS, pos);
-+}
-+
-+/* Enable hardware cursor
-+ *
-+ */
-+void enable_cursor(void *pMQMMIO)
-+{
-+ u32 temp;
-+
-+ temp = READ32(GC1_CONTROL) | HC_ENABLE;
-+ REG32(GC1_CONTROL, temp);
-+ if (mqflag & USE_2GCs)
-+ {
-+ temp = READ32(GC2_CONTROL) | HC_ENABLE;
-+ REG32(GC2_CONTROL, temp);
-+ }
-+}
-+
-+/* Disable hardware cursor
-+ *
-+ */
-+void disable_cursor(void *pMQMMIO)
-+{
-+ u32 temp;
-+
-+ temp = READ32(GC1_CONTROL) & HC_DISABLE;
-+ REG32(GC1_CONTROL, temp);
-+ if (mqflag & USE_2GCs)
-+ {
-+ temp = READ32(GC2_CONTROL) & HC_DISABLE;
-+ REG32(GC2_CONTROL, temp);
-+ }
-+}
-+/* The above is copied from mq2hw.c for initialization of MQ200 */
-+
-+void turnoffMQ200(void * pMQMMIO)
-+{
-+ volatile u32 temp;
-+
-+ temp = READ32(FP_CONTROL);
-+ temp &=0xfffffffc;
-+ REG32(FP_CONTROL, temp);
-+ udelay(5000);
-+ temp =READ32(FP_CONTROL) & 0x3;
-+ if(temp != 0)
-+ PDEBUG("FP_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("FP_CONTROL is cleared properly");
-+
-+ temp = READ32(FP_PIN_CONTROL);
-+ temp |= 0x1;
-+ REG32(FP_PIN_CONTROL, temp);
-+ udelay(5000);
-+
-+ temp = READ32(GC1_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC1_CONTROL, temp);
-+ udelay(5000);
-+ temp = READ32(GC1_CONTROL) & 0x1;
-+ if(temp != 0)
-+ PDEBUG("GC1_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("GC1_CONTROL is cleared properly");
-+
-+ temp = READ32(GC1_CRT_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC1_CRT_CONTROL, temp);
-+ udelay(5000);
-+
-+ temp = READ32(GC2_CONTROL);
-+ temp &=0xfffffffe;
-+ REG32(GC2_CONTROL, temp);
-+ udelay(5000);
-+ temp = READ32(GC2_CONTROL) & 0x1;
-+ if(temp != 0)
-+ PDEBUG("GC2_CONTROL is not cleared properly");
-+ else
-+ PDEBUG("GC2_CONTROL is cleared properly");
-+
-+ return;
-+}
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Power management hook. Note that we won't be called from IRQ context,
-+ * unlike the blank functions above, so we may sleep.
-+ */
-+static int
-+mq200fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ struct fb_info_mq200 *p = (struct fb_info_mq200 *) pm_dev->data;
-+ void * pMQMMIO = (void *) p->mqMmioAddrVirt;
-+
-+ if (req == PM_SUSPEND){
-+
-+ onoffdisplay(DISABLE_LCD_GC1, pMQMMIO);
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D3);
-+ MQ_DELAY(30);
-+ }
-+ if( req == PM_RESUME){
-+ setmqmode(&dc, pMQMMIO);
-+ onoffdisplay(ENABLE_LCD_GC1, pMQMMIO);
-+ REG32(PCI_PM_CNTL_STATUS, ENTER_D0);
-+ MQ_DELAY(30);
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+#if defined(CONFIG_SA1100_GDS2200) || defined(CONFIG_SA1100_SIMPAD)
-+
-+static void mq200_backlight(void *pMQMMIO, int flag)
-+{
-+
-+#ifdef CONFIG_SA1100_GDS2200
-+ unsigned long gpiocontrol, data;
-+ int i;
-+
-+ gpiocontrol = READ32(FP_GPIO_CONTROL) & 0x3f;
-+ data = (flag ? GPIO2_OUT_HIGH : 0);
-+ for(i = 0 ; i < 128 ; i++) {
-+ REG32(FP_GPIO_CONTROL, gpiocontrol | data);
-+ MQ_DELAY(1);
-+ REG32(FP_GPIO_CONTROL, gpiocontrol | GPIO1_OUT_HIGH | data);
-+ MQ_DELAY(1);
-+ REG32(FP_GPIO_CONTROL, gpiocontrol);
-+ MQ_DELAY(1);
-+ }
-+
-+#endif /* CONFIG_SA1100_GDS2200 */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+ if(flag)
-+ set_cs3_bit(DISPLAY_ON);
-+ else
-+ clear_cs3_bit(DISPLAY_ON);
-+
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+}
-+#endif /* CONFIG_SA1100_GDS2200 || CONFIG_SA1100_SIMPAD */
-+
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+static void writeBrightness(void *pMQMMIO, int brightness)
-+{
-+ unsigned long dutyCycle, pwmcontrol;
-+ int MAX_BRIGHT_REG = 0x000000fc; /* int 254 */
-+
-+ if(brightness > MAX_BRIGHT_REG)
-+ return;
-+ else
-+ {
-+ /*
-+ *Determine dutyCycle.
-+ *Note: the lower the value, the brighter the display!
-+ */
-+
-+ dutyCycle = MAX_BRIGHT_REG - brightness;
-+
-+ /*
-+ *Configure PWM0 (source clock = oscillator clock, pwm always enabled,
-+ *zero, clock pre-divider = 4) pwm frequency = 12.0kHz
-+ */
-+ pwmcontrol = READ32(PWM_CONTROL);
-+ REG32(PWM_CONTROL, 0x00000044 | (pwmcontrol & 0xffffff00));
-+
-+
-+ /* Write to pwm duty cycle register. */
-+
-+ REG32(PWM_CONTROL, ((dutyCycle << 8) & 0x0000ff00) |
-+ (pwmcontrol & 0xffff00ff));
-+ }
-+}
-+
-+#endif /* CONFIG_SA1100_SIMPAD */
-+
-+static int proc_read_reg(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ char outputbuf[15];
-+ int count;
-+ int i;
-+ mq200_reg_entry_t* current_reg=NULL;
-+ if (*ppos>0) /* Assume reading completed in previous read*/
-+ return 0;
-+ for (i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ if (mq200_regs[i].low_ino==i_ino) {
-+ current_reg = &mq200_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ count = sprintf(outputbuf, "0x%08X\n",
-+ *((volatile *) mq200_p2v(current_reg->phyaddr)));
-+ *ppos+=count;
-+ if (count>nbytes) /* Assume output can be read at one time */
-+ return -EINVAL;
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+ return count;
-+}
-+
-+static ssize_t proc_write_reg(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ int i_ino = (file->f_dentry->d_inode)->i_ino;
-+ mq200_reg_entry_t* current_reg=NULL;
-+ int i;
-+ unsigned long newRegValue;
-+ char *endp;
-+
-+ for (i=0;i<NUM_OF_MQ200_REG_ENTRY;i++) {
-+ if (mq200_regs[i].low_ino==i_ino) {
-+ current_reg = &mq200_regs[i];
-+ break;
-+ }
-+ }
-+ if (current_reg==NULL)
-+ return -EINVAL;
-+
-+ newRegValue = simple_strtoul(buffer,&endp,0);
-+ *((volatile *) mq200_p2v(current_reg->phyaddr))=newRegValue;
-+ return (count+endp-buffer);
-+}
-+
---- linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h
-@@ -28,6 +28,7 @@
- #define GPIO_UART3_DCD GPIO_GPIO18
- #define GPIO_UART3_DSR GPIO_GPIO17
-
-+#define GPIO_POWER_BUTTON GPIO_GPIO0
- #define GPIO_UCB1300_IRQ GPIO_GPIO (22) /* UCB GPIO and touchscreen */
-
- #define IRQ_UART1_CTS IRQ_GPIO15
-@@ -37,7 +38,12 @@
- #define IRQ_UART3_DCD GPIO_GPIO18
- #define IRQ_UART3_DSR GPIO_GPIO17
-
--#define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
-+#define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
-+#define IRQ_GPIO_POWER_BUTTON IRQ_GPIO0
-+
-+/*--- SmartCard ---*/
-+#define GPIO_SMART_CARD GPIO_GPIO10
-+#define IRQ_GPIO_SMART_CARD IRQ_GPIO10
-
- /*--- PCMCIA ---*/
- #define GPIO_CF_CD GPIO_GPIO24
-@@ -65,7 +71,7 @@
- #define LED2_ON 0x1000
- #define IRDA_MODE 0x2000 // Fast/Slow IrDA mode
- #define ENABLE_5V 0x4000 // Enable 5V circuit
--#define RESET_SIMCARD 0x8000
-+#define nRESET_SIMCARD 0x8000
-
- #define RS232_ENABLE 0x0440
- #define PCMCIAMASK 0x402f
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad_pm.h
-@@ -0,0 +1,236 @@
-+/*
-+* Abstraction interface for microcontroller connection to rest of system
-+*
-+* Copyright 2003 Peter Pregler
-+* Copyright 2000,1 Compaq Computer Corporation.
-+*
-+* Use consistent with the GNU GPL is permitted,
-+* provided that this copyright notice is
-+* preserved in its entirety in all copies and derived works.
-+*
-+* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-+* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-+* FITNESS FOR ANY PARTICULAR PURPOSE.
-+*
-+* Author: Peter Pregler (based on work for ipaq by Andrew Christian)
-+*
-+*/
-+
-+#ifndef __SIMPAD_HAL_H
-+#define __SIMPAD_HAL_H
-+
-+extern int simpad_apm_get_power_status(unsigned char *ac_line_status, unsigned char *battery_status,
-+ unsigned char *battery_flag, unsigned char *battery_percentage,
-+ unsigned short *battery_life);
-+
-+
-+struct simpad_battery {
-+ unsigned char ac_status; /* line connected yes/no */
-+ unsigned char status; /* battery loading yes/no */
-+ unsigned char percentage; /* percentage loaded */
-+ unsigned short life; /* life till empty */
-+};
-+
-+extern int simpad_get_battery(struct simpad_battery *bstat);
-+
-+/* These should match the apm_bios.h definitions */
-+#define SIMPAD_AC_STATUS_AC_OFFLINE 0x00
-+#define SIMPAD_AC_STATUS_AC_ONLINE 0x01
-+#define SIMPAD_AC_STATUS_AC_BACKUP 0x02 /* What does this mean? */
-+#define SIMPAD_AC_STATUS_AC_UNKNOWN 0xff
-+
-+/* These bitfields are rarely "or'd" together */
-+#define SIMPAD_BATT_STATUS_HIGH 0x01
-+#define SIMPAD_BATT_STATUS_LOW 0x02
-+#define SIMPAD_BATT_STATUS_CRITICAL 0x04
-+#define SIMPAD_BATT_STATUS_CHARGING 0x08
-+#define SIMPAD_BATT_STATUS_CHARGE_MAIN 0x10
-+#define SIMPAD_BATT_STATUS_DEAD 0x20 /* Battery will not charge */
-+#define SIMPAD_BATT_NOT_INSTALLED 0x20 /* For expansion pack batteries */
-+#define SIMPAD_BATT_STATUS_FULL 0x40 /* Battery fully charged (and connected to AC) */
-+#define SIMPAD_BATT_STATUS_NOBATT 0x80
-+#define SIMPAD_BATT_STATUS_UNKNOWN 0xff
-+
-+#if FIXME
-+#include <linux/simpad_ts.h>
-+
-+enum simpad_asset_type {
-+ ASSET_TCHAR = 0,
-+ ASSET_SHORT,
-+ ASSET_LONG
-+};
-+
-+#define TTYPE(_type) (((unsigned int)_type) << 8)
-+#define TCHAR(_len) (TTYPE(ASSET_TCHAR) | (_len))
-+#define TSHORT TTYPE(ASSET_SHORT)
-+#define TLONG TTYPE(ASSET_LONG)
-+#define ASSET(_type,_num) ((((unsigned int)_type)<<16) | (_num))
-+
-+#define ASSET_HM_VERSION ASSET( TCHAR(10), 0 ) /* 1.1, 1.2 */
-+#define ASSET_SERIAL_NUMBER ASSET( TCHAR(40), 1 ) /* Unique iPAQ serial number */
-+#define ASSET_MODULE_ID ASSET( TCHAR(20), 2 ) /* E.g., "iPAQ 3700" */
-+#define ASSET_PRODUCT_REVISION ASSET( TCHAR(10), 3 ) /* 1.0, 2.0 */
-+#define ASSET_PRODUCT_ID ASSET( TSHORT, 4 ) /* 2 = Palm-sized computer */
-+#define ASSET_FRAME_RATE ASSET( TSHORT, 5 )
-+#define ASSET_PAGE_MODE ASSET( TSHORT, 6 ) /* 0 = Flash memory */
-+#define ASSET_COUNTRY_ID ASSET( TSHORT, 7 ) /* 0 = USA */
-+#define ASSET_IS_COLOR_DISPLAY ASSET( TSHORT, 8 ) /* Boolean, 1 = yes */
-+#define ASSET_ROM_SIZE ASSET( TSHORT, 9 ) /* 16, 32 */
-+#define ASSET_RAM_SIZE ASSET( TSHORT, 10 ) /* 32768 */
-+#define ASSET_HORIZONTAL_PIXELS ASSET( TSHORT, 11 ) /* 240 */
-+#define ASSET_VERTICAL_PIXELS ASSET( TSHORT, 12 ) /* 320 */
-+
-+#define ASSET_TYPE(_asset) (((_asset)&0xff000000)>>24)
-+#define ASSET_TCHAR_LEN(_asset) (((_asset)&0x00ff0000)>>16)
-+#define ASSET_NUMBER(_asset) ((_asset)&0x0000ffff)
-+
-+#define MAX_TCHAR_LEN 40
-+
-+struct simpad_asset {
-+ unsigned int type;
-+ union {
-+ unsigned char tchar[ MAX_TCHAR_LEN ];
-+ unsigned short vshort;
-+ unsigned long vlong;
-+ } a;
-+};
-+
-+/********************************************************************
-+ * Interface to the hardware-type specific functions
-+ *
-+ * get_version Read the version number of the microcontroller on the option pack SPI bus
-+ * spi_read Reads from the serial EEPROM memory on the option pack SPI bus
-+ * spi_write Write to the serial EEPROM memory on the option pack SPI bus
-+ * get_option_detect Returns whether or not an option pack is present
-+ *
-+ * get_thermal_sensor Return measured temperature of the unit, in units of 0.125 deg C
-+ * set_notify_led Turns on, off, or blinks the Green LED
-+ * read_light_sensor Returns the value of the front light sensor
-+ * get_battery Returns the current voltage and charging state of all batteries
-+ * audio_clock Sets the audio CODEC to run at a particular rate
-+ * audio_power Turns on/off audio CODEC (internally calls audio_clock)
-+ * audio_mute Mutes the audio CODEC
-+ * asset_read Extracts PocketPC-style asset information from persistent memory
-+ * backlight_control Adjusts the backlight level (only on/off for 3100)
-+ *
-+ *
-+ * iPAQ 3100 only
-+ * ==============
-+ * codec_control Reset/mute/control level of 3100 audio codec
-+ * contrast_control Adjusts the contrast level (only for 3100)
-+ *
-+ * iPAQ 3600, 3700 only
-+ * ====================
-+ * eeprom_read Reads from the asset information on the eeprom of a 3600 (deprecated)
-+ * eeprom_write Writes to the asset information on the eeprom (deprecated)
-+ *
-+ * The interfaces to the EEPROM functions are maintained only because the simpad_ts driver has
-+ * a deprecated ioctl call for them. They are used internally by the "asset_read" function.
-+ *
-+ * iPAQ 3800, 3900 only
-+ * ====================
-+ * set_ebat Tells enhanced PCMCIA sleeves that this iPAQ can handle
-+ * a wider voltage range (applies to 3800, 3900)
-+ *
-+ *********************************************************************/
-+
-+struct simpad_hal_ops {
-+ /* Functions provided by the underlying hardware */
-+ int (*get_version)( struct simpad_ts_version * );
-+ int (*eeprom_read)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*eeprom_write)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*get_thermal_sensor)( unsigned short * );
-+ int (*set_notify_led)( unsigned char mode, unsigned char duration,
-+ unsigned char ontime, unsigned char offtime );
-+ int (*read_light_sensor)( unsigned char *result );
-+ int (*get_battery)( struct simpad_battery * );
-+ int (*spi_read)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*spi_write)( unsigned short address, unsigned char *data, unsigned short len );
-+ int (*codec_control)( unsigned char, unsigned char );
-+ int (*get_option_detect)( int *result );
-+ int (*audio_clock)( long samplerate );
-+ int (*audio_power)( long samplerate );
-+ int (*audio_mute)( int mute );
-+ int (*asset_read)( struct simpad_asset *asset );
-+ int (*set_ebat)( void );
-+
-+ /* Functions indirectly provided by the underlying hardware */
-+ int (*backlight_control)( enum flite_pwr power, unsigned char level );
-+ int (*contrast_control)( unsigned char level );
-+
-+ /* for module use counting */
-+ struct module *owner;
-+};
-+
-+/* Used by the device-specific hardware module to register itself */
-+extern int simpad_hal_register_interface( struct simpad_hal_ops *ops );
-+extern void simpad_hal_unregister_interface( struct simpad_hal_ops *ops );
-+
-+/*
-+ * Calls into HAL from the device-specific hardware module
-+ * These run at interrupt time
-+ */
-+extern void simpad_hal_keypress( unsigned char key );
-+extern void simpad_hal_touchpanel( unsigned short x, unsigned short y, int down );
-+extern void simpad_hal_option_detect( int present );
-+
-+/* Callbacks registered by device drivers */
-+struct simpad_driver_ops {
-+ void (*keypress)( unsigned char key );
-+ void (*touchpanel)( unsigned short x, unsigned short y, int down );
-+ void (*option_detect)( int present );
-+};
-+
-+extern int simpad_hal_register_driver( struct simpad_driver_ops * );
-+extern void simpad_hal_unregister_driver( struct simpad_driver_ops * );
-+
-+
-+/* Calls into HAL from device drivers and other kernel modules */
-+extern void simpad_get_flite( struct simpad_ts_backlight *bl );
-+extern void simpad_get_contrast( unsigned char *contrast );
-+extern int simpad_set_flite( enum flite_pwr pwr, unsigned char brightness );
-+extern int simpad_set_contrast( unsigned char contrast );
-+extern int simpad_toggle_frontlight( void );
-+
-+extern int simpad_apm_get_power_status(unsigned char *ac_line_status, unsigned char *battery_status,
-+ unsigned char *battery_flag, unsigned char *battery_percentage,
-+ unsigned short *battery_life);
-+
-+extern struct simpad_hal_ops *simpad_hal_ops;
-+
-+/* Do not use this macro in driver files - instead, use the inline functions defined below */
-+#define CALL_HAL( f, args... ) \
-+ { int __result = -EIO; \
-+ if ( simpad_hal_ops && simpad_hal_ops->f ) { \
-+ __MOD_INC_USE_COUNT(simpad_hal_ops->owner); \
-+ __result = simpad_hal_ops->f(args); \
-+ __MOD_DEC_USE_COUNT(simpad_hal_ops->owner); \
-+ } \
-+ return __result; }
-+
-+#define HFUNC static __inline__ int
-+
-+/* The eeprom_read/write address + len has a maximum value of 512. Both must be even numbers */
-+HFUNC simpad_eeprom_read( u16 addr, u8 *data, u16 len ) CALL_HAL(eeprom_read,addr,data,len)
-+HFUNC simpad_eeprom_write( u16 addr, u8 *data, u16 len) CALL_HAL(eeprom_write,addr,data,len)
-+HFUNC simpad_spi_read( u8 addr, u8 *data, u16 len) CALL_HAL(spi_read,addr,data,len)
-+HFUNC simpad_spi_write( u8 addr, u8 *data, u16 len) CALL_HAL(spi_write,addr,data,len)
-+HFUNC simpad_get_version( struct simpad_ts_version *v ) CALL_HAL(get_version,v)
-+HFUNC simpad_get_thermal_sensor( u16 *thermal ) CALL_HAL(get_thermal_sensor,thermal)
-+HFUNC simpad_set_led( u8 mode, u8 dur, u8 ont, u8 offt ) CALL_HAL(set_notify_led, mode, dur, ont, offt)
-+HFUNC simpad_get_light_sensor( u8 *result ) CALL_HAL(read_light_sensor,result)
-+HFUNC simpad_get_battery( struct simpad_battery *bat ) CALL_HAL(get_battery,bat)
-+HFUNC simpad_get_option_detect( int *result) CALL_HAL(get_option_detect,result)
-+HFUNC simpad_audio_clock( long samplerate ) CALL_HAL(audio_clock,samplerate)
-+HFUNC simpad_audio_power( long samplerate ) CALL_HAL(audio_power,samplerate)
-+HFUNC simpad_audio_mute( int mute ) CALL_HAL(audio_mute,mute)
-+HFUNC simpad_asset_read( struct simpad_asset *asset ) CALL_HAL(asset_read,asset)
-+HFUNC simpad_set_ebat( void ) CALL_HAL(set_ebat)
-+
-+/* Don't use these functions directly - rather, call {get,set}_{flite,contrast} */
-+ /* Functions indirectly provided by the underlying hardware */
-+HFUNC simpad_backlight_control( enum flite_pwr p, u8 v ) CALL_HAL(backlight_control,p,v)
-+HFUNC simpad_contrast_control( u8 level ) CALL_HAL(contrast_control,level)
-+
-+#endif
-+#endif
---- linux-2.4.27/include/linux/apm_bios.h~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/include/linux/apm_bios.h
-@@ -216,4 +216,19 @@
- #define APM_IOC_STANDBY _IO('A', 1)
- #define APM_IOC_SUSPEND _IO('A', 2)
-
-+#define APM_AC_OFFLINE 0
-+#define APM_AC_ONLINE 1
-+#define APM_AC_BACKUP 2
-+#define APM_AC_UNKNOWN 0xFF
-+
-+#define APM_BATTERY_STATUS_HIGH 0
-+#define APM_BATTERY_STATUS_LOW 1
-+#define APM_BATTERY_STATUS_CRITICAL 2
-+#define APM_BATTERY_STATUS_CHARGING 3
-+#define APM_BATTERY_STATUS_UNKNOWN 0xFF
-+
-+#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
-+#define APM_BATTERY_LIFE_MINUTES 0x8000
-+#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
-+
- #endif /* LINUX_APM_H */
---- /dev/null
-+++ linux-2.4.27/include/linux/switches.h
-@@ -0,0 +1,74 @@
-+/*
-+ * linux/include/linux/switches.h
-+ *
-+ * Copyright (C) 2000 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 23 October 2000 - created.
-+ */
-+
-+#if !defined(_LINUX_SWITCHES_H)
-+#define _LINUX_SWITCHES_H
-+
-+#define SWITCHES_MASK_SIZE (128)
-+
-+typedef unsigned long switches_bitfield;
-+
-+#define SWITCHES_BITS (sizeof(switches_bitfield) * 8)
-+#define SWITCHES_NUM_FIELDS (SWITCHES_MASK_SIZE / SWITCHES_BITS)
-+#define SWITCHES_FIELD_SELECT(i) ((i) / SWITCHES_BITS)
-+#define SWITCHES_FIELD_MASK(i) ((switches_bitfield)(1 << (i) % \
-+ SWITCHES_BITS))
-+
-+typedef struct switches_mask_t {
-+ unsigned int count;
-+ switches_bitfield events[SWITCHES_NUM_FIELDS];
-+ switches_bitfield states[SWITCHES_NUM_FIELDS];
-+} switches_mask_t;
-+
-+#define SWITCHES_ZERO(m) \
-+do { \
-+ unsigned int sz_i; \
-+ (m)->count = 0; \
-+ for(sz_i = 0; sz_i < SWITCHES_NUM_FIELDS; ++sz_i) \
-+ (m)->events[sz_i] = (m)->states[sz_i] = 0; \
-+} while (0)
-+
-+/* `s' is the state of the switch, either 0 or non-zero: */
-+#define SWITCHES_SET(m, i, s) \
-+do { \
-+ ((m)->events[SWITCHES_FIELD_SELECT((i))] |= \
-+ SWITCHES_FIELD_MASK((i))); \
-+ if(s) \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] |= \
-+ SWITCHES_FIELD_MASK((i))); \
-+ else \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ ++((m)->count); \
-+} while (0)
-+
-+/* Should only use to clear an event set by SWITCHES_SET(): */
-+#define SWITCHES_CLEAR(m, i) \
-+do { \
-+ ((m)->events[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ ((m)->states[SWITCHES_FIELD_SELECT((i))] &= \
-+ ~SWITCHES_FIELD_MASK((i))); \
-+ --((m)->count); \
-+}
-+
-+#define SWITCHES_COUNT(m) ((m)->count)
-+
-+/* Returns 0 or non-zero: */
-+#define SWITCHES_EVENT(m, i) \
-+((m)->events[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i)))
-+
-+/* Returns 0 or non-zero: */
-+#define SWITCHES_STATE(m, i) \
-+((m)->states[SWITCHES_FIELD_SELECT((i))] & SWITCHES_FIELD_MASK((i)))
-+
-+#endif /* !defined(_LINUX_SWITCHES_H) */
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mq2ge.h
-@@ -0,0 +1,81 @@
-+#ifndef _VIDEO_MQ200_MQ2GE_H
-+#define _VIDEO_MQ200_MQ2GE_H
-+
-+
-+/* Misc. GE Function Macro */
-+#undef CHECK_SRCFIFO
-+#define RGB_RASTER_CHECK
-+#define INCLUDE_GENERIC_CODE
-+
-+#ifdef CHECK_SRCFIFO
-+#define geWAITSRCFIFO(cnt) geWaitSrcFIFO(cnt)
-+#define geWAITCMDFIFO(cnt) geWaitCmdFIFO(cnt)
-+#define geWAITNOTBUSY() geWaitNotBusy()
-+#else
-+#define geWAITSRCFIFO(cnt)
-+#define geWAITCMDFIFO(cnt)
-+#define geWAITNOTBUSY()
-+#endif
-+
-+/* Additional UGL Raster Ops */
-+#define UGL_RASTER_OP_NOP 0x00000000L
-+
-+#define UGL_RASTER_OP_BLACKNESS 0x00000001L
-+#define UGL_RASTER_OP_BSRC_BLACK 0x00000002L
-+#define UGL_RASTER_OP_BSRC_OCOPY 0x00000003L
-+#define UGL_RASTER_OP_BSRC_XCOPY 0x00000004L
-+
-+#define UGL_RASTER_OP_WHITENESS 0x00010001L
-+#define UGL_RASTER_OP_WSRC_COPY 0x00010002L
-+#define UGL_RASTER_OP_WSRC_WHITE 0x00010003L
-+#define UGL_RASTER_OP_WSRC_INVERT 0x00010004L
-+
-+#define UGL_RASTER_OP_SRC_COPY 0x00020001L
-+#define UGL_RASTER_OP_SRCDEST_AND 0x00020002L
-+#define UGL_RASTER_OP_SRCDEST_OR 0x00020003L
-+#define UGL_RASTER_OP_SRCDEST_XOR 0x00020004L
-+
-+#define UGL_RASTER_OP_DEST_COPY 0x00030001L
-+#define UGL_RASTER_OP_DESTSRC_AND 0x00030002L
-+#define UGL_RASTER_OP_DESTSRC_OR 0x00030003L
-+#define UGL_RASTER_OP_DESTSRC_XOR 0x00030004L
-+
-+/* MediaQ Raster Ops */
-+#define MQ200_SOURCE_ROP 0x01
-+#define MQ200_PATTERN_ROP 0x02
-+#define MQ200_GE_NOP 0x000000AAL
-+#define MQ200_GE_BLACKNESS 0x00000000L
-+#define MQ200_GE_WHITENESS 0x000000FFL
-+#define MQ200_GE_SRC_INVERT 0x00000033L
-+#define MQ200_GE_SRC_COPY 0x000000CCL
-+#define MQ200_GE_SRCDEST_XOR 0x00000066L
-+#define MQ200_GE_SRCDEST_AND 0x00000088L
-+#define MQ200_GE_SRCDEST_OR 0x000000EEL
-+#define MQ200_GE_PATTERN_INVERT 0x0000000FL
-+#define MQ200_GE_PATTERN_COPY 0x000000F0L
-+#define MQ200_GE_PATDEST_XOR 0x0000005AL
-+#define MQ200_GE_PATDEST_AND 0x000000A0L
-+#define MQ200_GE_PATDEST_OR 0x000000FAL
-+/* MediaQ Raster Ops mapping table */
-+#define UGL_NR_OPERAND 4
-+#define UGL_NR_OPERATION 5
-+
-+#define geREG_2( idx1, val1, idx2, val2 ) \
-+ geREG( idx2, val2 ); \
-+ geREG( idx1, val1 )
-+#define geREG_3( idx1, val1, idx2, val2, idx3, val3 ) \
-+ geREG_2( idx2, val2, idx3, val3 ); \
-+ geREG( idx1, val1 )
-+#define geREG_4( idx1, val1, idx2, val2, idx3, val3, idx4, val4 ) \
-+ geREG_3( idx2, val2, idx3, val3, idx4, val4 ); \
-+ geREG( idx1, val1 )
-+#define geREG_5( idx1, val1, idx2, val2, idx3, val3, idx4, val4, idx5, val5 ) \
-+ geREG_4( idx2, val2, idx3, val3, idx4, val4, idx5, val5 ); \
-+ geREG( idx1, val1 )
-+
-+/* Declare MQ200 GE Utility Functions */
-+void geWaitNotBusy(void);
-+void geWaitCmdFIFO(u32 cnt);
-+void geWaitSrcFIFO(u32 cnt);
-+
-+#endif /* _VIDEO_MQ200_MQ2GE_H */
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mq2hw.h
-@@ -0,0 +1,879 @@
-+/***************************************************************************
-+ MQ200HW.H
-+
-+ MQ200 chip definition file
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQ2HW_H
-+#define _VIDEO_MQ200_MQ2HW_H
-+
-+#define MQ200_VENDOR_ID 0x4D51
-+#define MQ200_DEVICE_ID 0x0200
-+#define MQ200_ID 0x02004D51
-+#define PM_ID_CAP 0x06210001 /* Power management ID/capability */
-+
-+/* Revision ID */
-+#define MQ200_REV_0X 0x00
-+#define MQ200_REV_1A 0x01
-+#define MQ200_REV_1B1C 0x11
-+#define MQ200_REV_1D 0x10
-+
-+/* Some useful defines */
-+#ifndef ULONG
-+#define ULONG unsigned long
-+#endif
-+#ifndef USHORT
-+#define USHORT unsigned short
-+#endif
-+#ifndef BYTE
-+#define BYTE unsigned char
-+#endif
-+
-+/* To access MediaQ memory-mapped IO register (32bit in size) */
-+#define REG32(addr,val) (*(volatile ULONG *)((ULONG)pMQMMIO+addr)=(val))
-+#define READ32(addr) (*((volatile ULONG *)((ULONG)pMQMMIO+addr)))
-+#define geREG(addr,val) (*(volatile ULONG *)(mqMmioAddr+addr)=(val))
-+#define geREAD(addr) (*((volatile ULONG *)(mqMmioAddr+addr)))
-+#define gcREG(addr,val) geREG(addr,val)
-+#define gcREAD(addr) geREAD(addr)
-+#define cpuREG(addr,val) geREG(addr,val)
-+#define cpuREAD(addr) geREAD(addr)
-+#define pmuREG(addr,val) geREG(addr,val)
-+#define pmuREAD(addr) geREAD(addr)
-+#define pciREG(addr,val) geREG(addr,val)
-+#define pciREAD(addr) geREAD(addr)
-+
-+/* To access MediaQ DAC - index-based */
-+#define REG32_PAL(idx,val) (*(ULONG *)((ULONG)pMQMMIO+C1_BASE+idx*4)=(val))
-+#define READ32_PAL(idx) (*(ULONG *)((ULONG)pMQMMIO+C1_BASE+idx*4))
-+
-+/* MQ200 module offset */
-+#define PM_BASE (0) /* Power Management + Clk Gen */
-+#define CC_BASE (0x2000) /* CPU interface */
-+#define MM_BASE (0x4000) /* Memory Controller (m1/m2) */
-+#define VI_BASE (0x6000) /* Video-in controller */
-+#define IN_BASE (0x8000) /* Interrupt controller */
-+#define GC_BASE (0xA000) /* Graphics Controller 1/2 */
-+#define GE_BASE (0xC000) /* Graphics engine */
-+#define GE2_BASE (0xC200) /* Graphics engine (GE2) */
-+#define FP_BASE (0xE000) /* Flat panel interface */
-+#define C1_BASE (0x10000) /* Color palette 1 */
-+#define C2_BASE (0x12000) /* Color palette 2 */
-+#define DC_BASE (0x14000) /* Device Configuration Space */
-+#define PC_BASE (0x16000) /* PCI Configuration Header */
-+#define PSF_BASE (0x18000) /* Primary Source FIFO Space */
-+#define SSF_BASE (0x1A000) /* Secondary Source FIFO Space */
-+
-+#define MQ200_MMIO_SIZE (0x1C0000L)
-+#define MQ200_FB_SIZE (0x200000L) /* 2MB memory */
-+#define GC_OFFSET (0x80)
-+
-+/* Interrupt Controller */
-+#define INT_CONTROL_REG (IN_BASE + 0x00) /* Global interrupt ctrl reg */
-+#define INT_MASK_REG (IN_BASE + 0x04) /* Interrupt mask reg */
-+#define INT_STATUS_REG (IN_BASE + 0x08) /* Interrupt status reg */
-+#define INT_RAW_STATUS_REG (IN_BASE + 0x0C) /* Interrupt pin raw */
-+ /* status reg*/
-+
-+/* INT_CONTROL_REG - Global Interrupt Control Register */
-+#define INT_ENABLE 0x00000001 /* Interrupt to CPU enabled */
-+#define INT_PORLARITY_HIGH 0x00000002 /* Interrupt is active high */
-+#define INT_GPIO1_0To1 0x00000004 /* Interrupt as xition 0 to 1 */
-+#define INT_GPIO2_0To1 0x00000008 /* Interrupt as xition 0 to 1 */
-+#define INT_GPIO3_0To1 0x00000010 /* Interrupt as xtion 0 to 1 */
-+
-+/* INT_MASK_REG -- Interrupt Mask Register */
-+#define UM_GC1_VSE_R 0x00000001 /* GC1 VSE - Rising edge */
-+#define UM_GC1_VSE_F 0x00000002 /* GC1 VSE - Falling edge */
-+#define UM_GC1_VDE_R 0x00000004 /* GC1 VDE - Rising edge */
-+#define UM_GC1_VDE_F 0x00000008 /* GC1 VDE - Falling edge */
-+#define UM_GC2_VSE_R 0x00000010 /* GC2 VSE - Rising edge */
-+#define UM_GC2_VSE_F 0x00000020 /* GC2 VSE - Falling edge */
-+#define UM_GC2_VDE_R 0x00000040 /* GC2 VDE - Rising edge */
-+#define UM_GC2_VDE_F 0x00000080 /* GC2 VDE - Falling edge */
-+#define UM_CFIFO_HALF_EMPTY 0x00000100 /* Command fifo half empty */
-+#define UM_CFIFO_EMPTY 0x00000200 /* Command fifo empty */
-+#define UM_SFIFO_HALF_EMPTY 0x00000400 /* Source fifo half empty */
-+#define UM_SFIFO_EMPTY 0x00000800 /* Source fifo empty */
-+#define UM_GE_IDLE 0x00001000 /* GE is idle */
-+#define UM_GPIO_1 0x00002000 /* GPIO pin 1 */
-+#define UM_GPIO_2 0x00004000 /* GPIO pin 2 */
-+#define UM_GPIO_3 0x00008000 /* GPIO pin 3 */
-+
-+/* INT_STATUS_REG -- Interrupt Status Register */
-+#define ST_GC1_VSE_R 0x00000001 /* GC1 VSE - Rising edge */
-+#define ST_GC1_VSE_F 0x00000002 /* GC1 VSE - Falling edge */
-+#define ST_GC1_VDE_R 0x00000004 /* GC1 VDE - Rising edge */
-+#define ST_GC1_VDE_F 0x00000008 /* GC1 VDE - Falling edge */
-+#define ST_GC2_VSE_R 0x00000010 /* GC2 VSE - Rising edge */
-+#define ST_GC2_VSE_F 0x00000020 /* GC2 VSE - Falling edge */
-+#define ST_GC2_VDE_R 0x00000040 /* GC2 VDE - Rising edge */
-+#define ST_GC2_VDE_F 0x00000080 /* GC2 VDE - Falling edge */
-+#define ST_CFIFO_HALF_EMPTY 0x00000100 /* Command fifo half empty */
-+#define ST_CFIFO_EMPTY 0x00000200 /* Command fifo empty */
-+#define ST_SFIFO_HALF_EMPTY 0x00000400 /* Source fifo half empty */
-+#define ST_SFIFO_EMPTY 0x00000800 /* Source fifo empty */
-+#define ST_GE_IDLE 0x00001000 /* GE is idle */
-+#define ST_GPIO_1 0x00002000 /* GPIO pin 1 */
-+#define ST_GPIO_2 0x00004000 /* GPIO pin 2 */
-+#define ST_GPIO_3 0x00008000 /* GPIO pin 3 */
-+
-+/* INT_RAW_STATUA_REG -- Interrupt Pin Raw Status Register */
-+#define GC1_VSE 0x00000001 /* GC1 - VSE */
-+#define GC1_VDE 0x00000004 /* GC1 - VDE */
-+#define GC2_VSE 0x00000010 /* GC2 - VSE */
-+#define GC2_VDE 0x00000040 /* GC2 - VDE */
-+#define INT_GE_BUSY 0x00000100 /* GE busy */
-+#define SFIFO_EMPTY 0x00000200 /* Source fifo empty */
-+#define SFIFO_HEMPTY 0x00000400 /* Source fifo half empty */
-+#define CFIFO_EMPTY 0x00000800 /* Command fifo empty */
-+#define CFIFO_HEMPTY 0x00001000 /* Command fifo half empty */
-+#define GPIO_PIN_1 0x00002000 /* GPIO pin 1 */
-+#define GPIO_PIN_2 0x00004000 /* GPIO pin 2 */
-+#define GPIO_PIN_3 0x00008000 /* GPIO pin 3 */
-+
-+/* 2D Engine registers - GE1 (0x00 - 0x7F) */
-+#define DRAW_CMD (GE_BASE + 0x00) /* Drawing command register */
-+#define WIDTH_HEIGHT (GE_BASE + 0x04) /* Width/height register */
-+#define LINE_DRAW WIDTH_HEIGHT /* Bresenham Line Draw reg */
-+#define DEST_XY (GE_BASE + 0x08) /* Destination X/Y register */
-+#define LINE_MAJOR_X DEST_XY /* Bresenham Line Start X/Y reg */
-+#define PAT_OFFSET DEST_XY /* Pattern Offset register */
-+#define SRC_XY (GE_BASE + 0x0C) /* Source X/Y register */
-+#define LINE_MINOR_Y SRC_XY /* Bresenham Line Delta register */
-+#define COLOR_COMPARE (GE_BASE + 0x10) /* Color compare register */
-+#define CLIP_LeftT (GE_BASE + 0x14) /* Clip Left/Top register */
-+#define CLIP_RightB (GE_BASE + 0x18) /* Clip Right/Bottom register */
-+#define FG_COLOR (GE_BASE + 0x1C) /* Fg color for Mono src reg */
-+#define BG_COLOR (GE_BASE + 0x20) /* Bg color for Mono src reg */
-+#define SRC_STRIDE_OFFSET (GE_BASE + 0x24) /* Source Stride & Offset Reg */
-+#define DEST_STRIDE (GE_BASE + 0x28) /* Base address register */
-+#define BASE_ADDRESS (GE_BASE + 0x2C) /* Base address register */
-+#define TEST_RESULT_REG (GE_BASE + 0x7C) /* Test result register */
-+#define COLOR_PATTERN (GE_BASE + 0x100) /* Color pattern registers */
-+#define MONO_PATTERN0 COLOR_PATTERN /* Mono Pattern register 0 */
-+#define MONO_PATTERN1 (GE_BASE + 0x104) /* Mono Pattern register 1 */
-+#define PAT_FG_COLOR (GE_BASE + 0x108) /* Mono Pattern Fg color reg */
-+#define PAT_BG_COLOR (GE_BASE + 0x10C) /* Mono Pattern Bg color reg */
-+#define _FIRST_GE DRAW_CMD
-+#define _LAST_GE (COLOR_PATTERN + 0x80)
-+#define SRC_IMAGE_DATA (GE_BASE + 0xC000) /* Source Data register */
-+
-+/* 2D Engine registers - GE2 (0x80 to 0xFF) */
-+#define DRAW_CMD2 (GE2_BASE + 0x00) /* Drawing command register */
-+#define WIDTH_HEIGHT2 (GE2_BASE + 0x04) /* Width/height register */
-+#define LINE_DRAW2 WIDTH_HEIGHT2 /* Bresenham Line Draw register */
-+#define DEST_XY2 (GE2_BASE + 0x08) /* Destination X/Y register */
-+#define LINE_MAJOR_X2 DEST_XY2 /* Bresenham Line Start X/Y reg */
-+#define PAT_OFFSET2 DEST_XY2 /* Pattern Offset register */
-+#define SRC_XY2 (GE2_BASE + 0x0C) /* Source X/Y register */
-+#define LINE_MINOR_Y2 SRC_XY2 /* Bresenham Line Delta register */
-+#define COLOR_COMPARE2 (GE2_BASE + 0x10) /* Color compare register */
-+#define CLIP_LeftT2 (GE2_BASE + 0x14) /* Clip Left/Top register */
-+#define CLIP_RightB2 (GE2_BASE + 0x18) /* Clip Right/Bottom register */
-+#define FG_COLOR2 (GE2_BASE + 0x1C) /* Fg color for Mono src reg */
-+#define BG_COLOR2 (GE2_BASE + 0x20) /* Bg color for Mono src reg */
-+#define SRC_STRIDE_OFFSET2 (GE2_BASE + 0x24) /* Source Stride & Offset Reg */
-+#define DEST_STRIDE2 (GE2_BASE + 0x28) /* Base address register */
-+#define BASE_ADDRESS2 (GE2_BASE + 0x2C) /* Base address register */
-+#define TEST_RESULT_REG2 (GE2_BASE + 0x7C) /* Test result register */
-+#define COLOR_PATTERN2 (GE2_BASE + 0x100) /* Color pattern registers */
-+#define MONO_PATTERN02 COLOR_PATTERN2 /* Mono Pattern register 0 */
-+#define MONO_PATTERN12 (GE2_BASE + 0x104) /* Mono Pattern register 1 */
-+#define PAT_FG_COLOR2 (GE2_BASE + 0x108) /* Mono Pattern Fg color reg */
-+#define PAT_BG_COLOR2 (GE2_BASE + 0x10C) /* Mono Pattern Bg color reg */
-+#define _FIRST_GE2 DRAW_CMD2
-+#define _LAST_GE2 (COLOR_PATTERN2 + 0x80)
-+#define SRC_IMAGE_DATA2 (GE2_BASE + 0xC000) /* Source Data register */
-+
-+
-+/* DEST_STRIDE color depth */
-+#define GE_8BPP 0x00000000 /* 8BPP mode */
-+#define GE_16BPP 0x40000000 /* 16BPP mode */
-+#define GE_24BPP 0x80000000 /* 24BPP mode */
-+#define GE_32BPP 0xC0000000 /* 24BPP mode */
-+
-+/* BASE_ADDRESS */
-+#define GE_TEST_MODE_ENABLE 0x20000000 /* Test mode enabled */
-+#define GE_TEST_MASK 0xc0000000 /* Test mode read path select */
-+#define SEL_CLIP_LR 0x40000000 /* Select clipping left/right */
-+#define SEL_CLIP_TB 0x80000000 /* Select clipping top/bottom */
-+
-+/* Draw command register bits */
-+#define DO_BITBLT 0x00000200
-+#define DO_AAFONT 0x00000300
-+#define DO_LINEDRAW 0x00000400
-+#define X_DIR 0x00000800 /* Negative X direction */
-+#define Y_DIR 0x00001000 /* Negative Y direction */
-+#define SRC_IS_MEMORY 0x00002000 /* Source is in system memory */
-+#define MONO_SRC 0x00004000 /* Source is mono bitmap */
-+#define MONO_PATTERN 0x00008000 /* Pattern is monochrome */
-+#define TRANS_COLOR 0x00010000 /* Transparency is enabled */
-+#define TRANS_NOT_EQUAL 0x00020000 /* Polarity for color */
-+#define TRANS_MONO 0x00040000 /* Mono xparency is enabled */
-+#define TRANS_MONO_FG 0x00080000 /* Polarity for mono */
-+#define PACKED_MODE 0x00100000 /* Memory xfer mode select */
-+#define ALPHA_BYTE_MASK 0x00600000 /* Alpha Byte mask for 32bpp */
-+#define MONO_SOLID 0x00800000 /* Solid Mono Pattern */
-+#define SRC_NE_DEST_STRIDE 0x01000000 /* Src Not Equal Dest Stride */
-+#define ROP2_ENABLE 0x02000000 /* Use Rop2 code */
-+#define CLIP_ENABLE 0x04000000 /* Clipping is enabled */
-+#define AUTO_EXEC 0x08000000 /* Auto execute at dest X/Y */
-+#define VDE_GC2_ENABLE 0x10000000 /* Enable falling edge check */
-+#define VDE_GC1_ENABLE 0x20000000 /* Enable falling edge check */
-+#define COLOR_DEPTH_MASK 0xC0000000 /* Color Depth mask */
-+#define GE_8BPP 0x00000000 /* 8BPP mode */
-+#define GE_16BPP 0x40000000 /* 16BPP mode */
-+#define GE_24BPP 0x80000000 /* 24BPP mode */
-+
-+/* Graphics Controller 1 Registers */
-+#define GC1_CONTROL (GC_BASE + 0x00) /* Graphics Controll 1 Control Reg */
-+#define GC1_CRT_CONTROL (GC_BASE + 0x04) /* CRT controll register */
-+#define HD1_CONTROL (GC_BASE + 0x08) /* Horizontal Display 1 Control */
-+#define VD1_CONTROL (GC_BASE + 0x0C) /* Vertical Display 1 Control */
-+#define HS1_CONTROL (GC_BASE + 0x10) /* Horizontal Sync 1 Control */
-+#define VS1_CONTROL (GC_BASE + 0x14) /* Vertical Sync 1 Control */
-+#define HW1_CONTROL (GC_BASE + 0x20) /* Horizontal Window 1 Control */
-+#define VW1_CONTROL (GC_BASE + 0x24) /* Vertical Window 1 Control */
-+#define AHW1_CONTROL (GC_BASE + 0x28) /* Alt Horizontal Window 1 Control */
-+#define AVW1_CONTROL (GC_BASE + 0x2C) /* Alt Vertical Window 1 Control */
-+#define IW1_START_ADDR (GC_BASE + 0x30) /* Image Window 1 Start Address */
-+#define AIW1_START_ADDR (GC_BASE + 0x34) /* Alt Image Window 1 Start Address */
-+#define IW1_STRIDE (GC_BASE + 0x38) /* (Alt) Image Window 1 Stride */
-+#define IW1_LINE_SIZE (GC_BASE + 0x3C) /* (Alt) Image Window 1 Line Size */
-+#define HW_CURSOR1_POS (GC_BASE + 0x40) /* Hardware cursor 1 position */
-+#define HW_CURSOR1_ADDR (GC_BASE + 0x44) /* Start address and offset */
-+#define HW_CURSOR1_FGCLR (GC_BASE + 0x48) /* Foreground color */
-+#define HW_CURSOR1_BGCLR (GC_BASE + 0x4C) /* Background color */
-+
-+/* Graphics Controller 2 Registers */
-+#define GC2_CONTROL (GC_BASE + 0x80) /* Graphics Controll 2 Control Reg */
-+#define GC2_CRC_CONTROL (GC_BASE + 0x84) /* CRC Control */
-+#define HD2_CONTROL (GC_BASE + 0x88) /* Horizontal Display 2 Control */
-+#define VD2_CONTROL (GC_BASE + 0x8C) /* Vertical Display 2 Control */
-+#define HS2_CONTROL (GC_BASE + 0x90) /* Horizontal Sync 2 Control */
-+#define VS2_CONTROL (GC_BASE + 0x94) /* Vertical Sync 2 Control */
-+#define HW2_CONTROL (GC_BASE + 0xA0) /* Horizontal Window 2 Control */
-+#define VW2_CONTROL (GC_BASE + 0xA4) /* Vertical Window 2 Control */
-+#define AHW2_CONTROL (GC_BASE + 0xA8) /* Alt Horizontal Window 2 Control */
-+#define AVW2_CONTROL (GC_BASE + 0xAC) /* Alt Vertical Window 2 Control */
-+#define IW2_START_ADDR (GC_BASE + 0xB0) /* Image Window 2 Start Address */
-+#define AIW2_START_ADDR (GC_BASE + 0xB4) /* Alt Image Window 2 Start Address */
-+#define IW2_STRIDE (GC_BASE + 0xB8) /* (Alt) Image Window 2 Stride */
-+#define IW2_LINE_SIZE (GC_BASE + 0xBC) /* (Alt) Image Window 2 Line Size */
-+#define HW_CURSOR2_POS (GC_BASE + 0xC0) /* Hardware cursor 2 position */
-+#define HW_CURSOR2_ADDR (GC_BASE + 0xC4) /* Start address and offset */
-+#define HW_CURSOR2_FGCLR (GC_BASE + 0xC8) /* Foreground color */
-+#define HW_CURSOR2_BGCLR (GC_BASE + 0xCC) /* Background color */
-+
-+/* GC1_CONTROL/GC2_CONTROL register */
-+#define GC_ENABLE 0x00000001UL /* Controll 1/2 enabled */
-+#define GC_DISABLE 0xfffffffeUL /* Controll 1/2 disabled */
-+#define HORZ_COUNT_RESET 0x00000002UL /* Horiz counter 1/2 reset */
-+#define VERT_COUNT_RESET 0x00000004UL /* Vertical counter 1/2 reset */
-+#define IM_ENABLE 0x00000008UL /* Image Window 1/2 Enable */
-+#define IM_DISABLE 0xfffffff7UL /* Image Window 1/2 Disable */
-+
-+#define GC_1BPP 0x00000000UL /* GC1/2 color depth */
-+#define GC_2BPP 0x00000010UL
-+#define GC_4BPP 0x00000020UL
-+#define GC_8BPP 0x00000030UL
-+#define GC_16BPP 0x00000040UL /* with color palette enabled */
-+#define GC_24BPP_NBP 0x00000050UL /* with color palette enabled */
-+#define GC_32BPP_ABGR 0x00000060UL /* with color palette enabled */
-+#define GC_32BPP_ARGB 0x00000070UL /* with color palette enabled */
-+#define GC_16BPP_BP 0x000000C0UL /* with color pal bypassed */
-+#define GC_24BPP_BP 0x000000D0UL /* with color pal bypassed */
-+#define GC_32BPP_ABGR_BP 0x000000E0UL /* with color pal bypassed */
-+#define GC_32BPP_ARGB_BP 0x000000F0UL /* with color pal bypassed */
-+#define GC_32BPP GC_32BPP_ARGB /* Default 32bpp with ARGB */
-+#define GC_24BPP GC_24BPP_NBP
-+
-+#define HC_ENABLE 0x00000100UL /* Hardware cursor enable */
-+#define HC_DISABLE 0xfffffeffUL /* And mask to disable HC */
-+#define AIM_ENABLE 0x00000800UL /* Alt Image Win 1/2 Enable */
-+
-+#define AGC_1BPP 0x00000000UL /* Alt GC1/2 color depth */
-+#define AGC_2BPP 0x00001000UL
-+#define AGC_4BPP 0x00002000UL
-+#define AGC_8BPP 0x00003000UL
-+#define AGC_16BPP 0x00004000UL
-+#define AGC_24BPP 0x00005000UL
-+#define AGC_32BPP_ABGR 0x00006000UL
-+#define AGC_32BPP_ARGB 0x00007000UL
-+#define AGC_16BPP_BP 0x0000C000UL
-+#define AGC_24BPP_BP 0x0000D000UL
-+#define AGC_32BPP_ABGR_BP 0x0000E000UL
-+#define AGC_32BPP_ARGB_BP 0x0000F000UL
-+#define AGC_32BPP AGC_32BPP_ARGB_BP /* Default 32bpp w/ ARGB_BP */
-+
-+#define GxRCLK_BUSCLK 0x00000000UL /* G1RCLK source is bus clock */
-+#define GxRCLK_PLL1 0x00010000UL /* G1RCLK source is PLL1 */
-+#define GxRCLK_PLL2 0x00020000UL /* G1RCLK source is PLL2 */
-+#define GxRCLK_PLL3 0x00030000UL /* G1RCLK source is PLL3 */
-+#define GxRCLK_PLL_MASK 0x00030000UL /* G1RCLK source mask */
-+#define GC_TEST_MODE0 0x00040000UL /* Test mode 0 enabled */
-+#define GC_TEST_MODE1 0x00080000UL /* Test mode 1 enabled */
-+
-+#define FDx_1 0x00000000UL /* FD1 = 1 */
-+#define FDx_15 0x00100000UL /* FD1 = 1.5 */
-+#define FDx_25 0x00200000UL /* FD1 = 2.5 */
-+#define FDx_35 0x00300000UL /* FD1 = 3.5 */
-+#define FDx_45 0x00400000UL /* FD1 = 4.5 */
-+#define FDx_55 0x00500000UL /* FD1 = 5.5 */
-+#define FDx_65 0x00600000UL /* FD1 = 6.5 */
-+
-+/* GC1_CRT_CONTROL register */
-+#define CRT_ENABLE 0x00000001UL /* CRT DAC enabled */
-+#define CRT_DISABLE 0xfffffffeUL /* CRT DAC disabled -and mask */
-+#define CRT_BY_GC1 0x00000001UL /* CRT DAC driven by GC1 */
-+#define CRT_BY_GC2 0x00000003UL /* CRT DAC driven by GC2 */
-+#define CRT_BY_GCxMASK 0xfffffffcUL /* Mask for CRT DAC */
-+#define VSYNC_OUT_PMCLK 0x00000004UL /* CRT VSYNC output PMCLK
-+ at PwrDn */
-+#define HSYNC_OUT_PMCLK 0x00000008UL /* CRT HSYNC output PMCLK
-+ at PwrDn */
-+#define HSYNC_OUT_LOW 0x00000010UL /* CRT HSYNC output pin low */
-+#define HSYNC_OUT_HIGH 0x00000020UL /* CRT HSYNC output pin high */
-+#define VSYNC_OUT_LOW 0x00000040UL /* CRT VSYNC output pin low */
-+#define VSYNC_OUT_HIGH 0x00000080UL /* CRT VSYNC output pin high */
-+#define HSYNC_POLARITY_LOW 0x00000100UL /* active low */
-+#define VSYNC_POLARITY_LOW 0x00000200UL /* active low */
-+#define SYNC_PED_ENABLE 0x00000400UL /* Sync pedestal enable */
-+#define BLANK_PED_ENABLE 0x00000800UL /* Blank pedestal enable */
-+#define CSYNC_ENABLE 0x00001000UL /* Composite Sync Enable */
-+#define VREF_EXTERNAL 0x00002000UL /* Select external VREF */
-+#define MON_SENSE_ENABLE 0x00004000UL /* CRT DAC monitor sense
-+ enable */
-+#define CONST_OUT_ENABLE 0x00008000UL /* Constant output enable */
-+#define BLUE_NOT_LOADED 0x01000000UL /* Blue DAC is not loaded */
-+#define GREEN_NOT_LOADED 0x02000000UL /* Green DAC is not loaded */
-+#define RED_NOT_LOADED 0x04000000UL /* Red DAC is not loaded */
-+
-+/* GC2_CRC_CONTROL */
-+#define CRC_ENABLE 0x00000001UL /* Enable CRC logic */
-+#define CRC_2_VSYNC 0x00000002UL /* Wait for 2 vsync */
-+#define CRC_READ_BLUE 0x00000000UL /* Read CRC result for blue */
-+#define CRC_READ_GREEN 0x00000004UL /* Read CRC result for green */
-+#define CRC_READ_RED 0x00000008UL /* Read CRC result for red */
-+#define CRC_RESULT_MASK 0x3fffff00UL /* CRC result mask */
-+
-+/* Flat Panel Interface Registers */
-+#define FP_CONTROL (FP_BASE + 0x00) /* Flat panel control */
-+#define FP_PIN_CONTROL (FP_BASE + 0x04) /* Flat panel pin control */
-+#define FP_GPO_CONTROL (FP_BASE + 0x08) /* FP Gen. purpose output ctrl */
-+#define FP_GPIO_CONTROL (FP_BASE + 0x0C) /* FP Gen. purpose I/O control */
-+#define STN_CONTROL (FP_BASE + 0x10) /* STN panel control */
-+#define DSTN_FB_CONTROL (FP_BASE + 0x14) /* D-STN frame buffer control */
-+#define PWM_CONTROL (FP_BASE + 0x3C) /* PWM control */
-+#define FRC_PATTERN (FP_BASE + 0x40) /* FRC pattern starting index */
-+#define FRC_WEIGHT (FP_BASE + 0xC0) /* FRC weight starting index */
-+
-+/* FP_CONTROL */
-+#define FPI_ENABLE 0x00000001UL /* Trigger fp power up sequence */
-+#define FPI_DISABLE 0xfffffffeUL /* Trigger fp power down sequence */
-+#define FPI_BY_GC1 0x00000001UL /* FPI enabled & driven by GC1 */
-+#define FPI_BY_GC2 0x00000003UL /* FPI enabled & driven by GC2 */
-+#define FPI_BY_GCxMASK 0xfffffffcUL /* mask */
-+#define FP_TYPE_TFT 0x00000000UL /* Flat panel type TFT */
-+#define FP_TYPE_SSTN 0x00000004UL /* Flat panel type S-STN */
-+#define FP_TYPE_DSTN 0x00000008UL /* Flat panel type D-STN */
-+#define FP_TYPE_MASK 0x0000000cUL /* Flat panel type mask */
-+#define FP_COLOR 0x00000000UL /* Color flat panel */
-+#define FP_MONO 0x00000010UL /* Mono flat panel */
-+#define TFT_4BITS_MONO 0x00000000UL /* Specify num of bits/pixel */
-+#define TFT_12BITS_COLOR 0x00000000UL /* Specify num of bits/pixel */
-+#define SSTN_4BITS_MONOCLR 0x00000000UL /* Specify num of bits/pixel */
-+#define DSTN_8BITS_MONOCLR 0x00000000UL /* Specify num of bits/pixel */
-+#define TFT_6BITS_MONO 0x00000020UL /* Specify num of bits/pixel */
-+#define TFT_18BITS_COLOR 0x00000020UL /* Specify num of bits/pixel */
-+#define SSTN_8BITS_MONOCLR 0x00000020UL /* Specify num of bits/pixel */
-+#define DSTN_16BITS_MONOCLR 0x00000020UL /* Specify num of bits/pixel */
-+#define TFT_8BITS_MONO 0x00000040UL /* Specify num of bits/pixel */
-+#define TFT_24BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define SSTN_12BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define DSTN_24BITS_COLOR 0x00000040UL /* Specify num of bits/pixel */
-+#define SSTN_16BITS_MONOCLR 0x00000060UL /* Specify num of bits/pixel */
-+#define SSTN_24BITS_COLOR 0x00000080UL /* Specify num of bits/pixel */
-+#define DITHER_PATTERN_0 0x00000000UL /* Dither pattern */
-+#define DITHER_PATTERN_1 0x00000100UL /* Dither pattern */
-+#define DITHER_PATTERN_2 0x00000200UL /* Dither pattern */
-+#define DITHER_PATTERN_3 0x00000300UL /* Dither pattern */
-+#define DITHER_BASE_8BITS 0x00000000UL /* No dithering */
-+#define DITHER_BASE_2BITS 0x00002000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_3BITS 0x00003000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_4BITS 0x00004000UL /* Num of bits to be dithered */
-+#define DITHER_BASE_6BITS 0x00006000UL /* Num of bits to be dithered */
-+#define FRC_ALTWIN_DISABLE 0x00008000UL /* Disable Dither/FRC if Alt enabled */
-+#define FRC_2LEVEL 0x00000000UL /* Disable FRC */
-+#define FRC_4LEVEL 0x00010000UL /* 4-level FRC */
-+#define FRC_8LEVEL 0x00020000UL /* 8-level FRC */
-+#define FRC_16LEVEL 0x00030000UL /* 16-level FRC */
-+#define DITHER_PATTERN_ADJ1 0x00fc0000UL /* Dither pattern adjust 1 */
-+#define DITHER_PATTERN_ADJ2 0x07000000UL /* Dither pattern adjust 2 */
-+#define DITHER_PATTERN_ADJ3 0x08000000UL /* Dither pattern adjust 3 */
-+#define TEST_MODE0_ENABLE 0x10000000UL /* Enable test mode 0 */
-+#define TEST_MODE1_ENABLE 0x20000000UL /* Enable test mode 1 */
-+#define TEST_MODE2_ENABLE 0x40000000UL /* Enable test mode 2 */
-+#define TEST_MODE3_ENABLE 0x80000000UL /* Enable test mode 3 */
-+
-+/* FP_PIN_CONTROL */
-+#define FP_PIN_DISABLE 0x00000001UL /* Disable flat panel pins */
-+#define DATA_INV_ENABLE 0x00000002UL /* TFT fp data inversion enabled */
-+#define FP_DISP_ENABLE 0x00000004UL /* FP Display enable control */
-+#define FMOD_ENABLE 0x00000008UL /* Flat panel AC mod enable */
-+#define FD2_SCLK 0x00000010UL /* STN output shift clk on FD2 pin*/
-+#define FSCLK_OUTPUT_ENABLE 0x00000020UL /* FSCLK output enable */
-+#define TFT_SCLK_SELECT 0x00000040UL /* TFT shift clock select */
-+#define SCLK_MASK 0x00000080UL /* Shift clock mask */
-+#define STN_LP_DISABLE 0x00000100UL /* STN LP control */
-+#define SCLK_DISABLE 0x00000200UL /* STN shift clock control */
-+#define STN_ExtraLP_ENABLE 0x00000400UL /* STN extra LP control */
-+#define FP_FD2_MAX 0x00000000UL /* FD2 drive strength - max (16mA)*/
-+#define FP_FD2_MEDIUM 0x00001000UL /* FD2 drive strength - medium */
-+#define FP_FD2_MEDIUM2 0x00002000UL /* FD2 drive strength - medium 2 */
-+#define FP_FD2_MIN 0x00003000UL /* FD2 drive strength - min */
-+#define FP_DATA_MAX 0x00000000UL /* Data drv strength - max (16mA) */
-+#define FP_DATA_MEDIUM 0x00004000UL /* Data drive strength - medium */
-+#define FP_DATA_MEDIUM2 0x00008000UL /* Data drive strength - medium 2 */
-+#define FP_DATA_MIN 0x0000c000UL /* Data drive strength - min */
-+#define FD2_ACTIVE_L 0x00010000UL /* Flat panel data bit 2 polarity */
-+#define FD_ACTIVE_L 0x00020000UL /* Flat panel data polarity */
-+#define FDE_ACTIVE_L 0x00040000UL /* Data enable polarity */
-+#define FHSYNC_ACTIVE_L 0x00080000UL /* Horz sync polarity */
-+#define FVSYNC_ACTIVE_L 0x00100000UL /* Vert sync polarity */
-+#define FSCLK_ACTIVE_L 0x00200000UL /* Shift clock polarity */
-+#define FP_FSCLK_MAX 0x00000000UL /* Sh clk drv strength -max (16mA)*/
-+#define FP_FSCLK_MEDIUM 0x00400000UL /* Sh clk drv strength -medium */
-+#define FP_FSCLK_MEDIUM2 0x00800000UL /* Sh clk drv strength -medium 2 */
-+#define FP_FSCLK_MIN 0x00c00000UL /* Sh clk drv strength -min */
-+#define FSCLK_DELAY 0x07000000UL /* Shift clock delay */
-+
-+/* FP_GPO_CONTROL */
-+#define ENCTL_AS_GPO0 0x00000001UL /* ENCTL used as GPO 0 */
-+#define ENCTL_AS_OSC 0x00000002UL /* ENCTL used as Oscillator clock */
-+#define ENCTL_AS_PLL3 0x00000003UL /* ENCTL used as PLL3 clock */
-+#define ENVEE_AS_GPO1 0x00000004UL /* ENVEE used as GPO 1 */
-+#define PWM0_AS_GPO2 0x00000010UL /* PWM0 pin used as GPO 2 */
-+#define PWM1_AS_GPO3 0x00000040UL /* PWM1 pin used as GPO 3 */
-+#define ENVDD_AS_GPO4 0x00000100UL /* ENVDD pin used as GPO 4 */
-+#define FP_PWM_MAX 0x00000000UL /* PWM0/1 drv strength -max (16mA)*/
-+#define FP_PWM_MEDIUM 0x00000400UL /* PWM0/1 drv strength -medium */
-+#define FP_PWM_MEDIUM2 0x00000800UL /* PWM0/1 drv strength -medium 2 */
-+#define FP_PWM_MIN 0x00000c00UL /* PWM0/1 drv strength -min */
-+#define FP_GPIO_MAX 0x00000000UL /* GPIO0/1/2 drv strgth. -max 16mA*/
-+#define FP_GPIO_MEDIUM 0x00001000UL /* GPIO0/1/2 drv strgth. -medium */
-+#define FP_GPIO_MEDIUM2 0x00002000UL /* GPIO0/1/2 drv strgth. -medium 2*/
-+#define FP_GPIO_MIN 0x00003000UL /* GPIO0/1/2 drv strgth. -min */
-+#define FP_EN_MAX 0x00000000UL /* ENVDD/ENCTL/ENVEE -max (16mA) */
-+#define FP_EN_MEDIUM 0x00004000UL /* ENVDD/ENCTL/ENVEE -medium */
-+#define FP_EN_MEDIUM2 0x00008000UL /* ENVDD/ENCTL/ENVEE -medium 2 */
-+#define FP_EN_MIN 0x0000c000UL /* ENVDD/ENCTL/ENVEE -min */
-+#define GPO0_DATA_HIGH 0x00010000UL /* ENCTL is driven high */
-+#define GPO1_DATA_HIGH 0x00020000UL /* ENVEE is driven high */
-+#define GPO2_DATA_HIGH 0x00040000UL /* PWM0 is driven high */
-+#define GPO3_DATA_HIGH 0x00080000UL /* PWM1 is driven high */
-+#define GPO4_DATA_HIGH 0x00100000UL /* ENVDD is driven high */
-+
-+/* FP_GPIO_CONTROL */
-+#define GPIO0_IN 0x00000000UL /* General-purpose input */
-+#define GPIO0_OUT 0x00000001UL /* General-purpose output */
-+#define GPIO0_PLL1 0x00000002UL /* GPIO0 used to output PLL 1 clk */
-+#define GPIO0_CRC_B 0x00000003UL /* GPIO0 used to output CRC Blue */
-+#define GPIO1_IN 0x00000000UL /* General-purpose input */
-+#define GPIO1_OUT 0x00000004UL /* General-purpose output */
-+#define GPIO1_PLL2 0x00000008UL /* GPIO1 used to output PLL 2 clk */
-+#define GPIO1_CRC_G 0x0000000cUL /* GPIO1 used to output CRC Green */
-+#define GPIO2_IN 0x00000000UL /* General-purpose input */
-+#define GPIO2_OUT 0x00000010UL /* General-purpose output */
-+#define GPIO2_PLL3 0x00000020UL /* GPIO2 used to output PLL 3 clk */
-+#define GPIO2_CRC_R 0x00000030UL /* GPIO2 used to output CRC Red */
-+#define GPIO0_OUT_HIGH 0x00010000UL /* GOIO0 output data */
-+#define GPIO1_OUT_HIGH 0x00020000UL /* GOIO1 output data */
-+#define GPIO2_OUT_HIGH 0x00040000UL /* GOIO2 output data */
-+#define GPIO0_IN_HIGH 0x01000000UL /* GOIO0 input data */
-+#define GPIO1_IN_HIGH 0x02000000UL /* GOIO1 input data */
-+#define GPIO2_IN_HIGH 0x04000000UL /* GOIO2 input data */
-+
-+/* STN_CONTROL */
-+#define FMOD_FRAMECLK 0x00000000UL /* FMOD generated using frame clock */
-+#define FMOD_LINECLK 0x80000000UL /* FMOD generated using line clock */
-+
-+/* PWM_CONTROL */
-+#define PWM0_BY_PLL 0x00000000UL /* PWM 0 signal by PLL */
-+#define PWM0_BY_BUS 0x00000001UL /* PWM 0 signal using bus clk */
-+#define PWM0_BY_PMC 0x00000002UL /* PWM 0 signal by power mgt clock */
-+#define PWM0_ALWAYS_ON 0x00000004UL /* PWM 0 signal always generated */
-+#define PWM0_DC_MASK 0xffff00ffUL /* PWM 0 duty cycle mask */
-+#define PWM0_MASK 0xffff0000UL /* PWM 0 mask */
-+#define PWM1_BY_PLL 0x00000000UL /* PWM 1 signal by PLL */
-+#define PWM1_BY_BUS 0x00010000UL /* PWM 1 signal using bus clk */
-+#define PWM1_BY_PMC 0x00020000UL /* PWM 1 signal by power mgt clock */
-+#define PWM1_ALWAYS_ON 0x00040000UL /* PWM 1 signal always generated */
-+#define PWM1_DC_MASK 0x00ffffffUL /* PWM 0 duty cycle mask */
-+#define PWM1_MASK 0x0000ffffUL /* PWM 1 mask */
-+
-+/* PCI Power Management Interface Registers */
-+#ifndef PCI_VENDOR_DEVICE
-+#define PCI_VENDOR_DEVICE (PC_BASE + 0x00)
-+#endif
-+
-+#ifndef PCI_CMD_STATUS
-+#define PCI_CMD_STATUS (PC_BASE + 0x04)
-+#endif
-+
-+#ifndef PCI_REV_CLASS
-+#define PCI_REV_CLASS (PC_BASE + 0x08)
-+#endif
-+
-+#ifndef PCI_HEADER_TYPE
-+#define PCI_HEADER_TYPE (PC_BASE + 0x0c)
-+#endif
-+
-+#ifndef PCI_SUB_ID
-+#define PCI_SUB_ID (PC_BASE + 0x2c)
-+#endif
-+
-+#ifndef PCI_ROM_BASE
-+#define PCI_ROM_BASE (PC_BASE + 0x30)
-+#endif
-+
-+#ifndef PCI_CAP_PTR
-+#define PCI_CAP_PTR (PC_BASE + 0x34)
-+#endif
-+
-+#ifndef PCI_INTERRUPT
-+#define PCI_INTERRUPT (PC_BASE + 0x3c)
-+#endif
-+
-+#ifndef PCI_PM_REGISTER
-+#define PCI_PM_REGISTER (PC_BASE + 0x40)
-+#endif
-+
-+#ifndef PCI_PM_CNTL_STATUS
-+#define PCI_PM_CNTL_STATUS (PC_BASE + 0x44)
-+#endif
-+
-+/* POWER_STATE */
-+#define POWER_STATE_MASK 0x00000003UL /* Device power state mask */
-+#define ENTER_D0 0x00000000UL /* Enter D0 state */
-+#define ENTER_D1 0x00000001UL /* Enter D1 state */
-+#define ENTER_D2 0x00000002UL /* Enter D2 state */
-+#define ENTER_D3 0x00000003UL /* Enter D3 state */
-+
-+/* DC (Device Configuration Unit) Registers */
-+#define DC_0 (DC_BASE + 0x00) /* Device Configruation Register 0 */
-+#define DC_1 (DC_BASE + 0x04) /* Device Configruation Register 1 */
-+#define DC_SW_0 (DC_BASE + 0x08) /* Software Register 0 */
-+#define DC_SW_1 (DC_BASE + 0x0C) /* Software Register 1 */
-+
-+/* DC_0 */
-+#define OSC_BYPASSED 0x00000001UL /* Oscillator bypassed, powered down */
-+#define OSC_ENABLE 0x00000002UL /* Oscillator control can be enabled */
-+#define PLL1_BYPASSED 0x00000004UL /* PLL1 bypassed */
-+#define PLL1_ENABLE 0x00000008UL /* PLL1 can be enabled */
-+#define PLL1_DIVBY1 0x00000000UL /* PLL1 P output divisor by 1 */
-+#define PLL1_DIVBY2 0x00000010UL /* PLL1 P output divisor by 2 */
-+#define PLL1_DIVBY4 0x00000020UL /* PLL1 P output divisor by 4 */
-+#define PLL1_DIVBY8 0x00000030UL /* PLL1 P output divisor by 8 */
-+#define PLL1_DIVBY16 0x00000040UL /* PLL1 P output divisor by 16 */
-+#define PLL1_DIV_MASK 0x00000070UL /* PLL1 P output divisor mask */
-+#define CIF_DIVBY1 0x00000000UL /* CPU Interface clk divisor by 1 */
-+#define CIF_DIVBY2 0x00000080UL /* CPU Interface clk divisor by 2 */
-+#define STRONGARM_SYNC_F 0x00002000UL /* StrongARM bus intrf at fall edge */
-+#define SW_CHIP_RESET 0x00004000UL /* Software chip reset */
-+#define MEM_STANDBY_DISABLE 0x00008000UL /* Memory Power unit Standby disab. */
-+#define OSC_SHAPER_DISABLE 0x01000000UL /* Oscillator waveform shaper disab. */
-+#define FAST_POWER_DISABLE 0x02000000UL /* Fast Power Sequencing disable */
-+#define OSC_FREQ_SEL_0 0x00000000UL /* Osc frequency select range 0 */
-+#define OSC_FREQ_SEL_1 0x04000000UL /* Osc frequency select range 1 */
-+#define OSC_FREQ_SEL_2 0x08000000UL /* Osc frequency select range 2 */
-+#define OSC_FREQ_SEL_3 0x0c000000UL /* Osc frequency select range 3 */
-+
-+/* DC_1 */
-+#define BUS_MODE_MASK 0x0000003FUL /* Bus interface mode mask */
-+#define BUS_MODE_SH7709 0x00000001UL /* Bus interface mode - SH7709 */
-+#define BUS_MODE_SH7750 0x00000002UL /* Bus interface mode - SH7750 */
-+#define BUS_MODE_VR41xx 0x00000004UL /* Bus interface mode - VR4111/21 */
-+#define BUS_MODE_SA1110 0x00000008UL /* Bus interface mode - SA1110 */
-+#define BUS_MODE_TX3922 0x00000010UL /* Bus interface mode - TX3922 */
-+#define BUS_MODE_PCI 0x00000020UL /* Bus interface mode - PCI */
-+
-+/* PMU (Power Management Unit) Registers */
-+#define PM_MISC (PM_BASE + 0x00) /* Power management misc ctrl */
-+#define D1_STATE (PM_BASE + 0x04) /* D1 state control */
-+#define D2_STATE (PM_BASE + 0x08) /* D2 state control */
-+#define PLL2_CONTROL (PM_BASE + 0x18) /* PLL2 programming */
-+#define PLL3_CONTROL (PM_BASE + 0x1C) /* PLL3 programming */
-+
-+/* PM_MISC */
-+#define PLL1_N_BIT5 0x00000001UL /* Bit 5 of PLL1 N parameter */
-+#define PLL2_ENABLE 0x00000004UL /* PLL2 can be enabled */
-+#define PLL3_ENABLE 0x00000008UL /* PLL3 can be enabled */
-+#define FORCE_POWER_STATE 0x00000020UL /* For testing */
-+#define GE_ENABLE 0x00000100UL /* GE can be enabled */
-+#define GE_CLOCK_ON 0x00000200UL /* GE clock is always running */
-+#define GE_PIPELINE_ON 0x00000400UL /* GE pipeline always running */
-+#define GE_BY_BUS 0x00000000UL /* GE driven by bus intf clk */
-+#define GE_BY_PLL1 0x00000800UL /* GE driven by PLL1 */
-+#define GE_BY_PLL2 0x00001000UL /* GE driven by PLL2 */
-+#define GE_BY_PLL3 0x00001800UL /* GE driven by PLL3 */
-+#define GE_BY_MASK 0x00001800UL /* GE clock select mask */
-+#define GE_CMDFIFO_RESET 0x00002000UL /* GE command FIFO is reset */
-+#define GE_SRCFIFO_RESET 0x00004000UL /* GE CPU src FIFO is reset */
-+#define POWER_ON_IF_MIU_ON 0x00008000UL /* Pwr seq on when MIU enab.*/
-+#define D3_MEM_REFRESF 0x00010000UL /* FrameBuf refreshed in D3 */
-+#define D4_MEM_REFRESF 0x00020000UL /* FrameBuf refreshed in D4 */
-+#define PMCLK_4CYCLE 0x00000000UL /* Power sequencing interval */
-+#define PMCLK_8CYCLE 0x00040000UL /* Power sequencing interval */
-+#define PMCLK_16CYCLE 0x00080000UL /* Power sequencing interval */
-+#define PMCLK_2048CYCLE 0x000c0000UL /* Power sequencing interval */
-+#define FP_PMCLK_512 0x00000000UL /* FP power seq interval */
-+#define FP_PMCLK_1024 0x00100000UL /* FP power seq interval */
-+#define FP_PMCLK_2048 0x00200000UL /* FP power seq interval */
-+#define FP_PMCLK_128K 0x00300000UL /* FP power seq interval */
-+#define POWER_SEQ_ALL 0x00400000UL /* General power seq interval */
-+#define PMU_TEST_MODE 0x008000UL /* PMU test mode */
-+#define PM_POWER_MASK 0x03000000UL /* Power state mask */
-+#define PM_D0_STATE 0x00000000UL /* Power state D0 */
-+#define PM_D1_STATE 0x01000000UL /* Power state D1 */
-+#define PM_D2_STATE 0x02000000UL /* Power state D2 */
-+#define PM_D3_STATE 0x03000000UL /* Power state D3 */
-+#define POWER_IN_PROGRESS 0x04000000UL /* Power seq. active status */
-+
-+/* D1_STATE and D2_STATE */
-+#define DxOSC_ENABLE 0x00000001UL /* Oscillator can be enabled in D1/2 */
-+#define DxPLL1_ENABLE 0x00000002UL /* PLL1 can be enabled in D1/2 */
-+#define DxPLL2_ENABLE 0x00000004UL /* PLL2 can be enabled in D1/2 */
-+#define DxPLL3_ENABLE 0x00000008UL /* PLL3 can be enabled in D1/2 */
-+#define DxMIU_ENABLE 0x00000010UL /* MIU can be enabled in D1/2 */
-+#define DxMEM_REFRESH 0x00000020UL /* Memory is refreshed in D1/2 */
-+#define DxGE_ENABLE 0x00000040UL /* GE can be enabled in D1/2 */
-+#define DxCRT_ENABLE 0x00000100UL /* CRT can be enabled in D1/2 */
-+#define DxFP_ENABLE 0x00000200UL /* Flat panel can be enabled in D1/2 */
-+#define DxGC1_ENABLE 0x00010000UL /* GC1 can be enabled in D1/2 */
-+#define DxW1_ENABLE 0x00020000UL /* Window 1 can be enabled in D1/2 */
-+#define DxAW1_ENABLE 0x00040000UL /* Alt window 1 enabled in D1/2 */
-+#define DxHC1_ENABLE 0x00080000UL /* Cursor 1 enabled in D1/2 */
-+#define DxGC2_ENABLE 0x01000000UL /* GC2 can be enabled in D1/2 */
-+#define DxW2_ENABLE 0x02000000UL /* Window 2 can be enabled in D1/2 */
-+#define DxAW2_ENABLE 0x04000000UL /* Alt window 2 enabled in D1/2 */
-+#define DxHC2_ENABLE 0x08000000UL /* Cursor 2 enabled in D1/2 */
-+
-+/* PLL2_CONTROL/PLL3_CONTROL */
-+#define PLL_FROM_OSC 0x00000000UL /* PLL2/3 ref clock from OSCCLK */
-+#define PLL_FROM_PxCLK 0x00000001UL /* PLL2/3 ref clock from P2CLK */
-+#define PLL_BYPASSED 0x00000002UL /* PLL2/3 is bypassed */
-+#define PLL_DIVBY1 0x00000000UL /* PLL2/3 P output divisor by 1 */
-+#define PLL_DIVBY2 0x00000010UL /* PLL2/3 P output divisor by 2 */
-+#define PLL_DIVBY4 0x00000020UL /* PLL2/3 P output divisor by 4 */
-+#define PLL_DIVBY8 0x00000030UL /* PLL2/3 P output divisor by 8 */
-+#define PLL_DIVBY16 0x00000040UL /* PLL2/3 P output divisor by 16 */
-+#define PLL_DIV_MASK 0x00000070UL /* PLL2/3 P output divisor mask */
-+
-+/* CPU Interface Registers */
-+#define CPU_CONTROL (CC_BASE + 0x00) /* CPU control register */
-+#define DRAW_STATUS (CC_BASE + 0x04) /* Drawing status register */
-+
-+/* CPU_CONTROL */
-+#define SW_RESET 0x00000002UL /* Reset all modules except CIF */
-+#define MIU_READ_REQ 0x00000004UL /* MIU read request */
-+#define CLKRUN_ENABLE 0x00000008UL /* CLKRUN enabled. On Pwr-on, disab. */
-+
-+/* DRAW_STATUS */
-+#define CMD_FIFO_MASK 0x0000001fUL /* Command FIFO entries mask */
-+#define SRC_FIFO_MASK 0x00000f00UL /* Source FIFO entry mask */
-+#define GE_BUSY 0x00010000UL /* Any command in Comm FIFO */
-+#define CMD_FIFO_FULL 0x00000000UL /* Cmd fifo full bit */
-+#define CMD_FIFO_EMPTY 0x00000010UL /* Cmd fifo empty, 16x32 bits free */
-+#define SRC_FIFO_FULL 0x00000000UL /* Src fifo full bit */
-+#define SRC_FIFO_EMPTY 0x00000800UL /* Src fifo empty, 8x128 bits free */
-+
-+#define CMD_FIFO_CNT 16 /* Command FIFO full entry */
-+#define CMD_FIFO_MAX_INDEX 64
-+#define SRC_FIFO_MAX_BYTES 128 /* max pixels in src fifo - 8bits */
-+#define SRC_FIFO_MAX_WORDS 64 /* max pixels in src fifo - 16bits */
-+#define SRC_FIFO_MAX_DWORDS 32 /* max dwords in src fifo - 32bits */
-+
-+/* MIU (Memory Interface Unit) Registers */
-+#define MIU_CONTROL1 (MM_BASE + 0x00) /* Memory interface control 1 */
-+#define MIU_CONTROL2 (MM_BASE + 0x04) /* Memory interface control 2 */
-+#define MIU_CONTROL3 (MM_BASE + 0x08) /* Memory interface control 3 */
-+#define MIU_CONTROL4 (MM_BASE + 0x0C) /* Memory interface control 4 */
-+#define MIU_CONTROL5 (MM_BASE + 0x10) /* Memory interface control 5 */
-+
-+/* MIU_CONTROL1 */
-+#define MIU_ENABLE 0x00000001UL /* Enable MIU */
-+#define MIU_RESET_DISABLE 0x00000002UL /* MIU reset is disabled */
-+#define DRAM_RESET_DISABLE 0x00000004UL /* DRAM reset is disabled */
-+
-+/* MIU_CONTROL2 */
-+#define CLK_FROM_BUS 0x00000001UL /* Bus clk for mem clk src */
-+#define CLK_FROM_PLL2 0x00000001UL /* PLL2 for mem clock source */
-+#define MEM_REFRESH_ENABLE 0x00000002UL /* Mem ref disab at pwr dw mod*/
-+#define CPU_PB_ENABLE 0x00000004UL /* Page Break enab after CPU mem cyc */
-+#define GC1_PB_ENABLE 0x00000008UL /* Page Break after GC1 mem cycles */
-+#define GC2_PB_ENABLE 0x00000010UL /* Page Break after GC2 mem cycles */
-+#define STN_R_PB_ENABLE 0x00000020UL /* Page Break after STN read mem cyc */
-+#define STN_W_PB_ENABLE 0x00000040UL /* Page Break after STN wr. mem cyc */
-+#define GE_PB_ENABLE 0x00000080UL /* Page Break after GE memory cycles */
-+#define AUTO_REF_ENABLE 0x40000000UL /* Standby sig enab. when MIU active */
-+#define STANDBY_ENABLE 0x80000000UL /* Standby sig enab. when MIU active */
-+
-+/* MIU_CONTROL3 */
-+#define DISPLAY_BURST2 0x00000000UL /* Burst size for disp mem refresh */
-+#define DISPLAY_BURST4 0x00000001UL
-+#define DISPLAY_BURST6 0x00000002UL
-+#define DISPLAY_BURST8 0x00000003UL
-+#define STN_R_BURST2 0x00000000UL /* Burst size for STN read mem cycle */
-+#define STN_R_BURST4 0x00000004UL
-+#define STN_R_BURST6 0x00000008UL
-+#define STN_R_BURST8 0x0000000cUL
-+#define STN_W_BURST2 0x00000000UL /* Burst size for STN write mem cyc */
-+#define STN_W_BURST4 0x00000010UL
-+#define STN_W_BURST6 0x00000020UL
-+#define STN_W_BURST8 0x00000030UL
-+#define GE_RW_BURST2 0x00000000UL /* Burst size for GE r/w mem cycle */
-+#define GE_RW_BURST4 0x00000040UL
-+#define GE_RW_BURST6 0x00000080UL
-+#define GE_RW_BURST8 0x000000c0UL
-+#define CPU_RW_BURST2 0x00000000UL /* Burst size for CPU r/w mem cycle */
-+#define CPU_RW_BURST4 0x00000100UL
-+#define CPU_RW_BURST6 0x00000200UL
-+#define CPU_RW_BURST8 0x00000300UL
-+
-+/* MIU_CONTROL4 */
-+#define R_LATENCY_REQUEST 0x00000001UL /* Read Latency Request */
-+
-+/* MIU_CONTROL5 */
-+#define LATENCY_1 0x00000001UL /* EDRAM Latency 1 */
-+#define LATENCY_2 0x00000005UL /* EDRAM Latency 2 */
-+#define LATENCY_3 0x00000007UL /* EDRAM Latency 3 */
-+#define DUMMY_IN_COMMANDS 0x00000008UL /* Dummy cycle insertion betw cmds */
-+#define DUMMY_IN_PRECHARGE 0x00000010UL /* Dummy cyc between precharge cyc */
-+#define DELAY_1ns 0x00000000UL /* Internal memory clock delay */
-+#define ACT_TO_CLOSE_3 0x00000100UL /* Bank activate to close - 3 mclk */
-+#define ACT_TO_CLOSE_4 0x00000200UL /* Bank activate to close - 4 mclk */
-+#define ACT_TO_CLOSE_5 0x00000300UL /* Bank activate to close - 5 mclk */
-+#define ACT_TO_COMMAND_2 0x00000000UL /* Bank activate to cmd r/w - 2 mclk */
-+#define ACT_TO_COMMAND_3 0x00000400UL /* Bank activate to cmd r/w - 3 mclk */
-+#define CLOSE_TO_ACT_2 0x00000000UL /* Bank close to activate - 2 mclk */
-+#define CLOSE_TO_ACT_3 0x00000800UL /* Bank close to activate - 3 mclk */
-+#define ROW_CYCLE_6 0x00000000UL /* Row Cycle time - 6 memory clock */
-+#define ROW_CYCLE_8 0x00001000UL /* Row Cycle time - 8 memory clock */
-+#define DELAY_R_CLOCK_0_0 0x00000000UL /* Delay for read clock - no delay */
-+#define DELAY_R_CLOCK_0_5 0x00010000UL /* Delay for read clock - 0.5ns */
-+#define DELAY_R_CLOCK_1_0 0x00020000UL /* Delay for read clock - 1.0ns */
-+#define DELAY_R_CLOCK_1_5 0x00030000UL /* Delay for read clock - 1.5ns */
-+#define DELAY_M_CLOCK_0_0 0x00000000UL /* Delay for memory clock - no delay */
-+#define DELAY_M_CLOCK_0_5 0x00020000UL /* Delay for memory clock - 0.5ns */
-+#define DELAY_M_CLOCK_1_0 0x00080000UL /* Delay for memory clock - 1.0ns */
-+#define DELAY_M_CLOCK_1_5 0x000c0000UL /* Delay for memory clock - 1.5ns */
-+
-+
-+/*
-+ * Data structure and defines for MQ chip and driver interface
-+ */
-+
-+/* Display configuration structure - for interface */
-+typedef struct DisplayConfig
-+{
-+ int x; /* x resolution */
-+ int y; /* y resolution */
-+ int bpp; /* color depth */
-+ int refresh; /* CRT refresh rate */
-+ int stride; /* memory stride */
-+ unsigned long flag; /* display flag */
-+} DISPLAY_CONFIG, *PDISPLAY_CONFIG;
-+
-+/* Flag definition */
-+#define PANEL_TYPE_MASK 0x000000ff /* Panel type mask */
-+#define PROCESSOR_MASK 0x00003f00 /* Mask of processor type */
-+#define IS_SH3 0x00000000
-+#define IS_SH4 0x00000100
-+#define IS_NEC 0x00000200
-+#define IS_SARM 0x00000300
-+#define IS_TOSHIBA 0x00000400
-+#define IS_PCI 0x00000500
-+#define LCD_ON 0x00010000 /* LCD mode */
-+#define CRT_ON 0x00020000 /* CRT mode */
-+#define LARGE_DESKTOP 0x00040000 /* Large desktop mode is on */
-+#define INDEP_DISPLAY 0x00080000 /* Independent display */
-+#define SAME_IMAGE 0x00100000 /* Use 2 GC but same image */
-+#define USE_2GCs 0x001C0000 /* 2 GCs are used */
-+#define USE_2GCs_MASK 0x001C0000 /* mask for 2 GCs */
-+#define ENA_HW_CURSOR 0x00200000 /* Enable hw cursor */
-+#define HORI_LCD_CRT 0x00000000 /* QView hori arrangement */
-+#define HORI_CRT_LCD 0x10000000 /* QView hori arrangement */
-+#define VERT_CRT_LCD 0x20000000 /* QView vert arrangement */
-+#define VERT_LCD_CRT 0x30000000 /* QView vert arrangement */
-+#define LCDCRT_POS_MASK 0x30000000 /* mask for QV orientation */
-+
-+/* Display timing structure */
-+typedef struct DisplayTiming
-+{
-+ int x; /* x resolution */
-+ int y; /* y resolution */
-+ int refresh; /* refresh rate */
-+ unsigned long hd; /* hori display control */
-+ unsigned long vd; /* vert display control */
-+ unsigned long hs; /* hori sync control */
-+ unsigned long vs; /* vert sync control */
-+ unsigned long crtc; /* crt control */
-+ unsigned long pll; /* PLL2 or PLL3 setting */
-+} DISPLAY_TIMING, *PDISPLAY_TIMING;
-+
-+/* Flat panel register */
-+typedef struct FPControl
-+{
-+ int x; /* panel size x */
-+ int y; /* panel size y */
-+ int freq; /* panel freq */
-+ unsigned long fpControl; /* flat panel control */
-+ unsigned long fpPinControl; /* flat panel pin control */
-+ unsigned long stnControl; /* stn panel control */
-+} FPDATA_CONTROL, *PFPDATA_CONTROL;
-+
-+/* Frame rate control */
-+#define FRC_PATTERN_CNT 32
-+#define FRC_WEIGHT_CNT 8
-+typedef struct FRCControl
-+{
-+ ULONG frcPattern[FRC_PATTERN_CNT]; /* FRC pattern control */
-+ ULONG frcWeight[FRC_WEIGHT_CNT]; /* FRC weight control */
-+} FRC_CONTROL, *PFRC_CONTROL;
-+
-+/* Miscellaneous defines */
-+#define IS_GC1 1
-+#define IS_GC2 2
-+
-+/* Turn on/off display */
-+#define ENABLE_LCD_GC1 0
-+#define ENABLE_LCD_GC2 1
-+#define DISABLE_LCD_GC1 2
-+#define DISABLE_LCD_GC2 3
-+#define ENABLE_CRT_GC1 4
-+#define ENABLE_CRT_GC2 5
-+#define DISABLE_CRT_GC1 6
-+#define DISABLE_CRT_GC2 7
-+
-+/*
-+ * Handy macro
-+ *
-+ */
-+/*
-+#define CHECK_IF_STATE_D(s) {\
-+ unsigned long ulState = (s);\
-+ unsigned long ulPMReg;\
-+ while(1)\
-+ {\
-+ ulPMReg = READ32(PCI_PM_CNTL_STATUS);\
-+ if((ulPMReg &0x03) == ulState)\
-+ break;\
-+ } }
-+*/
-+#endif /* _VIDEO_MQ200_MQ2HW_H */
-+
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mqdata.h
-@@ -0,0 +1,754 @@
-+/***************************************************************************
-+ MQDATA.C
-+
-+ This file contains timing and flat panel parameters for MediaQ graphics
-+ chip.
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQDATA_H
-+#define _VIDEO_MQ200_MQDATA_H
-+/* LCD/CRT timing parameters for each resolution - VESA modes
-+ *
-+ * . the first entry is reserved to provide customized panel timing support
-+ * . OEM can fill in proper timing for non-VESA LCD (or CRT)
-+ *
-+ */
-+DISPLAY_TIMING TimingParam[] =
-+{
-+ { /* customized refresh rate - reserved for non-VESA panel timing */
-+ 0,0,0, /* X/Y/Freq */
-+ 0, /* HD Total + HD End */
-+ 0, /* VD Total + VD End */
-+ 0, /* HS Start + HS End */
-+ 0, /* VS Start + VS End */
-+ 0x00000000, /* CRT control */
-+ 0x00000000, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 240 90Hz (25.175 MHz) */
-+ 640,240,90, /* X/Y/Freq */
-+ (793-2) | (640L << 16), /* HD Total + HD End */
-+ (262-1) | ((240L-1) << 16), /* VD Total + VD End */
-+ 647 | (704L << 16), /* HS Start + HS End */
-+ 245 | (246L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00a30930, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 60Hz (25.175 MHz) */
-+ 640,480,60, /* X/Y/Freq */
-+ (800-2) | (640L << 16), /* HD Total + HD End */
-+ (525-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 656 | (752L << 16), /* HS Start + HS End */
-+ 490 | (492L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00a30930, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 72Hz (31.5 MHz) */
-+ 640,480,72, /* X/Y/Freq */
-+ (832-2) | (640L << 16), /* HD Total + HD End */
-+ (520-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 688 | (728L << 16), /* HS Start + HS End */
-+ 489 | (492L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f50b30, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 75Hz (31.5 MHz) */
-+ 640,480,75, /* X/Y/Freq */
-+ (840-2) | (640L << 16), /* HD Total + HD End */
-+ (500-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 680 | (744L << 16), /* HS Start + HS End */
-+ 481 | (484L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f50b30, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 640 x 480 85Hz (36 MHz) */
-+ 640,480,85, /* X/Y/Freq */
-+ (832-2) | (640L << 16), /* HD Total + HD End */
-+ (509-1) | ((480L-1) << 16), /* VD Total + VD End */
-+ 696 | (752L << 16), /* HS Start + HS End */
-+ 481 | (484L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00d20830, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 60Hz (40 MHz) */
-+ 800,600,60, /* X/Y/Freq */
-+ (1056-2) | (800L << 16), /* HD Total + HD End */
-+ (628-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 839 | (967L << 16), /* HS Start + HS End */
-+ 601 | (605L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00e90830, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 72Hz 50 MHz) */
-+ 800,600,72, /* X/Y/Freq */
-+ (1040-2) | (800L << 16), /* HD Total + HD End */
-+ (666-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 856 | (976L << 16), /* HS Start + HS End */
-+ 637 | (643L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00b20a20, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 75Hz (49.5 MHz) */
-+ 800,600,75, /* X/Y/Freq */
-+ (1056-2) | (800L << 16), /* HD Total + HD End */
-+ (625-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 816 | (896L << 16), /* HS Start + HS End */
-+ 601 | (604L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00900820, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 800 x 600 85Hz (56.25 MHz) */
-+ 800,600,85, /* X/Y/Freq */
-+ (1047-2) | (800L << 16), /* HD Total + HD End */
-+ (631-1) | ((600L-1) << 16), /* VD Total + VD End */
-+ 832 | (896L << 16), /* HS Start + HS End */
-+ 601 | (604L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00b60920, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 60Hz (65 MHz) */
-+ 1024,768,60, /* X/Y/Freq */
-+ (1344-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1048 | (1184L << 16), /* HS Start + HS End */
-+ 771 | (777L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00fd0b20, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 70Hz (75 MHz) */
-+ 1024,768,70, /* X/Y/Freq */
-+ (1327-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1047 | (1183L << 16), /* HS Start + HS End */
-+ 771 | (777L << 16), /* VS Start + VS End */
-+ HSYNC_POLARITY_LOW|VSYNC_POLARITY_LOW|BLANK_PED_ENABLE,
-+ /* CRT control */
-+ 0x00f30920, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 75Hz (78.750 MHz) */
-+ 1024,768,75, /* X/Y/Freq */
-+ (1312-2) | (1024L << 16), /* HD Total + HD End */
-+ (806-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1040 | (1136L << 16), /* HS Start + HS End */
-+ 769 | (772L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x00cc0720, /* PLLx multiplier and control */
-+ },
-+
-+ { /* 1024 x 768 85Hz (94.5 MHz) */
-+ 1024,768,85, /* X/Y/Freq */
-+ (1375-2) | (1024L << 16), /* HD Total + HD End */
-+ (808-1) | ((768L-1) << 16), /* VD Total + VD End */
-+ 1072 | (1168L << 16), /* HS Start + HS End */
-+ 769 | (772L << 16), /* VS Start + VS End */
-+ BLANK_PED_ENABLE, /* CRT control */
-+ 0x007a0710, /* PLLx multiplier and control */
-+ }
-+};
-+#define MAX_MQMODE (sizeof(TimingParam) / sizeof(TimingParam[0]))
-+
-+/* Flat panel control registers
-+ */
-+FPDATA_CONTROL fpControlData[] =
-+{
-+ /* Type 0 : OEM Specific panel
-+ */
-+ { /* Flat panel info */
-+ 0, 0, 0,
-+
-+ /* Flat panel Control */
-+ 0
-+ ,
-+
-+ /* Flat panel pin control */
-+ 0
-+ ,
-+
-+ /* STN panel control */
-+ 0x0
-+ },
-+ /* Type 1 : SSTN VGA 8Bit Color - 72Hz
-+ * - Sanyo SSTN 640x480 8-bit color interface
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 2 : DSTN 16 Bit VGA Color - 72Hz
-+ * - Hitachi 8.2" SX21V001
-+ * - Sanyo 10.4" LM-CJ53-22NTK
-+ * - Sharp 10.4" LM64C35P
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 3 : TFT 18 Bit VGA - 60Hz
-+ * - NEC 10.4" NL6448AC33-24
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 4 : TFT 18 Bit SVGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 5 : DSTN 16Bit SVGA Color Panel - 72Hz
-+ * - Hitachi 10.0" SX25S001
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 6 : DSTN 8 Bit VGA Color - 72Hz
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 7 : SSTN VGA 16Bit Color - 72Hz
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 72,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 8 : SSTN VGA 8Bit Color - 60Hz
-+ * - Sanyo SSTN 640x480 8-bit color interface
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ },
-+
-+ /* Type 9 : DSTN 16 Bit VGA Color - 60Hz
-+ * - Hitachi 8.2" SX21V001
-+ * - Sanyo 10.4" LM-CJ53-22NTK
-+ * - Sharp 10.4" LM64C35P
-+ */
-+ { /* Flat panel info */
-+ 640, 480, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_1
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 10 : DSTN 16Bit SVGA Color Panel - 60Hz
-+ * - Hitachi 10.0" SX25S001
-+ * - Hitachi 12.1" SX25S003
-+ * - Sanyo LM-FC53-22NTK
-+ */
-+ { /* Flat panel info */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+#if 1
-+ 0x0C1B4128
-+#else
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0C840000
-+#endif
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 11 : DSTN 24Bit XGA Color Panel - 60Hz
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_24BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 12 : DSTN 16Bit XGA Color Panel - 60Hz
-+ * - Hitachi 12.1" SX25S003
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_DSTN
-+ | FP_COLOR
-+ | DSTN_16BITS_MONOCLR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x0c840000
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 13 : TFT 18Bit XGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 14 : TFT 24Bit XGA - 60Hz
-+ * - Hitachi 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel info */
-+ 1024, 768, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_24BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 15 : TFT 18 Bit SVGA - 60Hz (Similar to type 4)
-+ * - NEC 12.1" 800x600 TX31D24VC1CAA
-+ */
-+ { /* Flat panel control */
-+ 800, 600, 60,
-+
-+ /* Flat panel Control */
-+ FP_TYPE_TFT
-+ | FP_COLOR
-+ | TFT_18BITS_COLOR
-+ | DITHER_PATTERN_3
-+ | DITHER_BASE_6BITS
-+ ,
-+
-+ /* Flat panel pin control */
-+ FSCLK_OUTPUT_ENABLE
-+ | FHSYNC_ACTIVE_L
-+ | FVSYNC_ACTIVE_L
-+ | FSCLK_ACTIVE_L
-+ | FSCLK_DELAY
-+ ,
-+ /* STN panel control */
-+ 0x00bd0001
-+ },
-+
-+ /* Type 16 : SSTN VGA 8Bit Color - 90Hz
-+ * - Sharp LM8M64 SSTN 640x240 8-bit color interface
-+ */
-+ { /* Flat panel control */
-+ 640, 240, 90,
-+
-+ FP_TYPE_SSTN
-+ | FP_COLOR
-+ | SSTN_8BITS_MONOCLR
-+ | DITHER_PATTERN_1
-+ | DITHER_BASE_4BITS
-+ | FRC_16LEVEL
-+ | 0x00400000
-+ ,
-+
-+ FSCLK_OUTPUT_ENABLE
-+ | SCLK_MASK
-+ | FDE_ACTIVE_L
-+ ,
-+
-+ /* STN panel control */
-+ 0x00bd0000
-+ }
-+};
-+
-+/* Flat panel FRC weight/pattern registers - for SSTN and DSTN panel only
-+ *
-+ */
-+FRC_CONTROL FRCControlData[] =
-+{
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0x0E3D5C61,
-+ 0xF87A429B,
-+ 0x4A791825,
-+ 0xBC3E06DF,
-+ 0xC2F190AD,
-+ 0x34B68E57,
-+ 0x86B5D4E9,
-+ 0x70F2CA13,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0x685B3A07,
-+ 0x9E1C24FD,
-+ 0x2C1F7E43,
-+ 0xDA5860B9,
-+ 0xA497F6CB,
-+ 0x52D0E831,
-+ 0xE0D3B28F,
-+ 0x1694AC75,
-+ },
-+
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ },
-+
-+ /* FRC Pattern Data - 2FCA (for SSTN) */
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x4A791825,
-+ 0xBC3E06DF,
-+ 0x0E3D5C61,
-+ 0xF87A429B,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0x2C1F7E43,
-+ 0xDA5860B9,
-+ 0x685B3A07,
-+ 0x9E1C24FD,
-+ 0xE0D3B28F,
-+ 0x1694AC75,
-+ 0xA497F6CB,
-+ 0x52D0E831,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0x86B5D4E9,
-+ 0x70F2CA13,
-+ 0xC2F190AD,
-+ 0x34B68E57,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ },
-+
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ },
-+
-+ /* FRC Pattern Data - (for Panletype 4-> Simpad) */
-+ {
-+ {
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x794A2B16,
-+ 0x8F0D35EC,
-+ 0xD3E081BC,
-+ 0x25A79F46,
-+ 0x97A4C5F8,
-+ 0x61E3DB02,
-+ 0x3D0E6F52,
-+ 0xCB4971A8,
-+ 0xF1C2A39E,
-+ 0x0785BD64,
-+ 0x5B680934,
-+ 0xAD2F17CE,
-+ 0x1F2C4D70,
-+ 0xE96B538A,
-+ 0xB586E7DA,
-+ 0x43C1F920,
-+ },
-+ {
-+ /* FRC weight data */
-+ 0x80800000,
-+ 0x88888420,
-+ 0x94a49248,
-+ 0xaaaaaa54,
-+ 0x6b5b55ab,
-+ 0x77776db7,
-+ 0x7f7f7bdf,
-+ 0xffff7fff
-+ }
-+ }
-+};
-+#endif /* _VIDEO_MQ200_MQDATA_H */
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mqmacros.h
-@@ -0,0 +1,86 @@
-+#ifndef _VIDEO_MQ200_MQMACROS_H
-+#define _VIDEO_MQ200_MQMACROS_H
-+
-+#ifdef CHECK_SRCFIFO
-+
-+#define PUMP_PACKED_SRCFIFO(pSrcData,srcStride,nDwords,height,extras) \
-+ { \
-+ u32 *pData; \
-+ u32 i,j; \
-+ while( height-- ) \
-+ { \
-+ pData = (u32 *)((u32)(pSrcData + 3UL) & ~0x03UL); \
-+ j = nDwords; \
-+ while ( j >= SRC_FIFO_MAX_DWORDS ) \
-+ { \
-+ geWAITSRCFIFO( SRC_FIFO_MAX_DWORDS ); \
-+ for ( i = 0; i < SRC_FIFO_MAX_DWORDS; i++ ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ j -= SRC_FIFO_MAX_DWORDS; \
-+ } \
-+ geWAITSRCFIFO( j ); \
-+ while( j-- ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ pSrcData += srcStride; \
-+ } \
-+ geWAITSRCFIFO( extras ); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+
-+#define PUMP_REAL_PACKED_SRCFIFO(pSrcData,nDwords,extras) \
-+ { \
-+ u32 *pData =(u32 *)pSrcData; \
-+ u32 i; \
-+ while(nDwords) \
-+ { \
-+ if (nDwords >= SRC_FIFO_MAX_DWORDS) \
-+ { \
-+ geWAITSRCFIFO( SRC_FIFO_MAX_DWORDS ); \
-+ for (i = SRC_FIFO_MAX_DWORDS; i > 0; i--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ nDwords -= SRC_FIFO_MAX_DWORDS; \
-+ } \
-+ else \
-+ { \
-+ geWAITSRCFIFO( nDwords ); \
-+ for (i = nDwords; i > 0; i--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ nDwords -= nDwords; \
-+ } \
-+ } \
-+ geWAITSRCFIFO(extras); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#else /* CHECK_SRCFIFO */
-+
-+#define PUMP_PACKED_SRCFIFO(pSrcData,srcStride,nDwords,height,extras) \
-+ { \
-+ u32 *pData; \
-+ u32 i; \
-+ while( height-- ) \
-+ { \
-+ pData = (u32 *)((u32)(pSrcData + 3UL) & ~0x03UL); \
-+ for ( i = 0; i < nDwords; i++ ) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ pSrcData += srcStride; \
-+ } \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#define PUMP_REAL_PACKED_SRCFIFO(pSrcData,nDwords,extras) \
-+ { \
-+ u32 *pData =(u32 *)pSrcData; \
-+ while(nDwords--) \
-+ geREG(SRC_IMAGE_DATA, *pData++); \
-+ while( extras-- ) \
-+ geREG(SRC_IMAGE_DATA, 0UL); \
-+ }
-+
-+#endif
-+
-+#endif /* _VIDEO_MQ200_MQMACROS_H */
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mqplat.h
-@@ -0,0 +1,106 @@
-+/***************************************************************************
-+ MQPLAT.H
-+
-+ MQ200 platform, system or OS specific header file
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef _VIDEO_MQ200_MQPLAT_H
-+#define _VIDEO_MQ200_MQPLAT_H
-+
-+/* OS variation - ONLY define one */
-+#undef MQ_VXWORKS
-+#undef MQ_EPOC32
-+#undef MQ_WINCE
-+#undef MQ_OS9
-+#define MQ_LINUX
-+
-+/* CPU variation - ONLY define one */
-+#undef MQ_X86
-+#define MQ_SA1110
-+#undef MQ_MIPS_NEC
-+#undef MQ_MIPS_TOSHIBA
-+#undef MQ_SH4
-+
-+/* PCI support - undef accordingly */
-+#undef MQ_PCI
-+#ifdef MQ_PCI
-+ #warning "MQ200 driver compiled for PCI !"
-+#endif
-+
-+/* Derived equates from CPU type */
-+#ifdef MQ_SHx
-+ #warning "MQ200 driver compiled for SHx !"
-+ #define FB_BASE 0x93800000L /* MQ200 frame buffer adddr */
-+#endif
-+
-+#ifdef MQ_MIPS_NEC
-+ #warning "MQ200 driver compiled for NEC MIPS !"
-+ #define CHECK_FIFO_REQUIRED /* GE fifo checking required */
-+ #define FB_BASE 0xAA000000L
-+
-+ #ifdef MQ_PCI
-+ #define IOREGS_BASE 0xAF000000L /* for VR4122 */
-+ #define IOREGS_SIZE 0x00002000L
-+ #else
-+ #define IOREGS_BASE 0xAB000000L /* for VR 4111/21 */
-+ #define IOREGS_SIZE 0x00001000L
-+ #define CHECK_NOTBUSY /* Needed for NEC MIPS */
-+ #define CHECK_CMDFIFO /* Needed for NEC MIPS */
-+ #endif /* MQ_PCI */
-+#endif
-+
-+#ifdef MQ_MIPS_TOSHIBA
-+ #warning "MQ200 driver compiled for TOSHIBA MIPS !"
-+ #define FB_BASE 0x6D800000L
-+#endif
-+
-+#ifdef MQ_SA1110
-+ #warning "MQ200 driver compiled for Intel SA1110 !"
-+ #define FB_BASE_CS3 0x1b800000L /* configured as CS3 */
-+ #define FB_BASE_CS4 0x43800000L /* configured as CS4 */
-+#define FB_BASE_CS5 0x4b800000L /* configured as CS5 */
-+#define FB_BASE FB_BASE_CS5 /* change accordingly! */
-+#define REGISTER_BASE 0x4be00000L
-+#endif
-+
-+/* OS-derived misc defines */
-+#ifdef MQ_VXWORKS
-+ #warning "MQ200 driver compiled for VxWorks !"
-+ #define MQ_DELAY(cnt) taskDelay(cnt*30);
-+ #define MQ_COLOR_RGB /* Color (32bit):ARGB */
-+#endif
-+
-+#ifdef MQ_WINCE
-+ #warning "MQ200 driver compiled for Window CE !"
-+ #define MQ_DELAY(cnt) Sleep(cnt)
-+#endif
-+
-+#ifdef MQ_LINUX
-+ #warning "MQ200 driver compiled for Linux !"
-+/* #define MQ_DELAY(cnt) {volatile int delay; for (delay=0; delay<10000*cnt; delay++); } */
-+
-+#define MQ_DELAY(cnt) mdelay(cnt * 10)
-+#endif
-+
-+/* Further derivation
-+#ifdef MQ_COLOR_RGB
-+ #define GETR(color) (unsigned char)(color >> 16)
-+ #define GETG(color) (unsigned char)((unsigned short)(color) >> 8)
-+ #define GETB(color) (unsigned char)(color)
-+ #define MAKERGB(r,g,b) ((unsigned long)(((unsigned char)(r)|\
-+ ((unsigned short)((unsigned char)(g))<<8))|\
-+ (((unsigned long)(unsigned char)(b))<<16)))
-+#endif
-+*/
-+
-+/* Cursor color */
-+#ifndef CURSOR_FGCLR
-+ #define CURSOR_FGCLR 0x0000FFFF /* Yellow */
-+#endif
-+#ifndef CURSOR_BGCLR
-+ #define CURSOR_BGCLR 0x00000000 /* Black */
-+#endif
-+#endif /* _VIDEO_MQ200_MQPLAT_H */
---- /dev/null
-+++ linux-2.4.27/include/video/MQ200/mqproto.h
-@@ -0,0 +1,19 @@
-+/***************************************************************************
-+ MQPROTO.H
-+
-+ MQ200 common function prototypes
-+
-+ Copyright (c) 2000 by MediaQ, Incorporated.
-+ All Rights Reserved.
-+
-+***************************************************************************/
-+#ifndef MQPROTO_H
-+#define MQPROTO_H
-+
-+/*
-+ * mqdata.h
-+ */
-+extern FPDATA_CONTROL fpControlData[];
-+extern DISPLAY_TIMING TimingParam[];
-+
-+#endif /* MQPROTO_H */
---- linux-2.4.27/init/do_mounts.c~2.4.27-vrs1-pxa1-jpm1
-+++ linux-2.4.27/init/do_mounts.c
-@@ -789,7 +789,13 @@
- return;
- }
- printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
-+#ifdef CONFIG_SA1100_SIMPAD
-+ /* no floppy -> cramfs */
-+ printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying cramfs.\n");
-+ ROOT_DEV = MKDEV(31, 2);
-+#else
- ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-+#endif
- }
- #endif
- devfs_make_root(root_device_name);
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1.patch
deleted file mode 100644
index 7c1252e93c..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1-pxa1.patch
+++ /dev/null
@@ -1,40457 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/Documentation/Configure.help~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/Documentation/Configure.help
-@@ -4630,6 +4630,24 @@
- building a kernel for install/rescue disks or your system is very
- limited in memory.
-
-+Kernel Execute-In-Place from ROM
-+CONFIG_XIP_KERNEL
-+ Execute-In-Place allows the kernel to run directly from
-+ non-volatile storage, such as flash. This saves RAM space since
-+ the text section of the kernel is not loaded from flash to
-+ RAM. Read-write sections, such as the data section and stack,
-+ are still copied to RAM. The XIP kernel is not compressed since it
-+ has to run directly from flash, so it will take more space to store
-+ it. The flash address where the kernel is linked to run from and
-+ is stored is board dependent. Therefore, if you say Y, you must
-+ know the proper physical address where to store the kernel image.
-+
-+ Also note that the make target becomes "make xipImage" rather than
-+ "make zImage" or "make Image". The final kernel binary to put in
-+ ROM memory will be arch/arm/boot/xipImage.
-+
-+ If unsure, say N.
-+
- # Choice: kcore
- Kernel core (/proc/kcore) format
- CONFIG_KCORE_ELF
-@@ -13609,6 +13627,30 @@
-
- If you don't know what this all is, saying Y is a safe choice.
-
-+Workaround for XScale cache errata
-+CONFIG_XSCALE_CACHE_ERRATA
-+ There are couple errata that say that the cache may get confused
-+ whether some cache lines are dirty or not, resulting in some memory
-+ corruptions. The workaround (using the cache only in write through
-+ mode) is performance impairing, and the bug _might_ just not be
-+ that visible or critical to you depending on many esoteric
-+ hardware factors.
-+
-+ Not using the workaround makes Linux unreliable. If you're used
-+ to some other OSes which requires to be rebooted once in a while
-+ then this won't look so bad to you. On the other hand you may
-+ stress test the system for hours without seeing any effect of this
-+ bug.
-+
-+ So this is configurable. Let's hope a future core revision will tell
-+ this was just a bad dream. But in the mean time the risk and
-+ trade-off is yours to decide.
-+
-+ This should apply to all PXA250 up to rev B2 (erratum #120) and
-+ possibly other current XScale cores as well.
-+
-+ If you don't know what to answer, say Y.
-+
- Support CD-ROM drives that are not SCSI or IDE/ATAPI
- CONFIG_CD_NO_IDESCSI
- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
-@@ -16812,6 +16854,40 @@
-
- If unsure, say N.
-
-+Use linear addressing for cramfs
-+CONFIG_CRAMFS_LINEAR
-+ This option tells the cramfs driver to load data directly from a linear
-+ adressed memory range (usually non volatile memory like flash) instead
-+ of going through the block device layer. This saves some memory since
-+ no intermediate buffering is necessary.
-+
-+ This is also a prerequisite for XIP of binaries stored on the filesystem.
-+
-+ The location of the cramfs image in memory is board dependent. Therefore,
-+ if you say Y, you must know the proper physical address where to store
-+ the cramfs image and specify it using the physaddr=0x******** mount
-+ option (for example: "mount -t cramfs -o physaddr=0x100000 none /mnt").
-+
-+ If unsure, say N.
-+
-+Support XIP on linear cramfs
-+CONFIG_CRAMFS_LINEAR_XIP
-+ You must say Y to this option if you want to be able to run applications
-+ directly from non-volatile memory. XIP applications are marked by
-+ setting the sticky bit (ie, "chmod +t <app name>"). A cramfs file system
-+ then needs to be created using mkcramfs (with XIP cramfs support
-+ in it). Applications marked for XIP execution will not be compressed
-+ since they have to run directly from flash.
-+
-+Root file system on linear cramfs
-+CONFIG_ROOT_CRAMFS_LINEAR
-+ Say Y if you have enabled linear cramfs, and you want to be able to use
-+ the linear cramfs image as a root file system. To actually have the
-+ kernel mount this cramfs image as a root file system, you must also pass
-+ the command line parameter "root=/dev/null rootflags=physaddr=0x********"
-+ to the kernel (replace 0x******** with the physical address location
-+ of the linear cramfs image to boot with).
-+
- CMS file system support
- CONFIG_CMS_FS
- Read only support for CMS minidisk file systems found on IBM
---- /dev/null
-+++ linux-2.4.27/Documentation/arm/XScale/PXA/USB-client
-@@ -0,0 +1,38 @@
-+Date: Wed, 05 Jun 2002 13:38:53 -0700
-+From: Frank Becker <fbecker@intrinsyc.com>
-+To: Nicolas Pitre <nico@cam.org>
-+Subject: [PATCH] PXA-USB
-+
-+Hi Nicolas,
-+
-+one more patch...
-+
-+This patch adds minimal USB client (UDC) support.
-+
-+Some notes:
-+It adds just enough to get usb-eth working. I.e.
-+endpoints 0-2, no dma. Performance isn't stellar
-+partially due to UDC bug workarounds...
-+(~350K @ 100Mhz, ~550K @ 200Mhz).
-+
-+Endpoint 1&2 have changed direction compared to
-+the SA, so the host side requires a change to
-+usbnet.c to flip endpoints (in:2/out:1 -> in:1/out:2).
-+
-+usb-eth and usb-char for PXA are almost identical
-+to the SA versions, so they could probably be merged at
-+one point. I made some minor changes to the eth driver
-+to grab the usb resources at open, rather than at init
-+and allow eth&char to be loaded at the same time.
-+
-+Stuart Lynne was working on his own USB client driver
-+(and he was getting higher throughput than my driver).
-+Assuming you guys have something in the oven for USB
-+as well, there should be good selection for best of
-+breed :)
-+
-+Cheers,
-+Frank.
-+--
-+Frank Becker - Intrinsyc Software, Inc. - http://www.intrinsyc.com/
-+Need a break? http://criticalmass.sf.net/
---- linux-2.4.27/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/Makefile
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 27
--EXTRAVERSION = -vrs1
-+EXTRAVERSION =-vrs1-pxa1
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
-@@ -167,6 +167,7 @@
- DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
- DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
- DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
-+DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmcdrivers.o
- DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o
- DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o
- DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o
---- linux-2.4.27/arch/arm/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/Makefile
-@@ -13,10 +13,11 @@
- CFLAGS +=-Uarm -fno-common -pipe
-
- ifeq ($(CONFIG_FRAME_POINTER),y)
--CFLAGS :=$(CFLAGS:-fomit-frame-pointer=-mapcs -mno-sched-prolog)
-+CFLAGS :=$(CFLAGS:-fomit-frame-pointer=)
-+CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
- endif
-
--CFLAGS :=$(CFLAGS:-O2=-Os)
-+#CFLAGS :=$(CFLAGS:-O2=-Os)
-
- ifeq ($(CONFIG_DEBUG_INFO),y)
- CFLAGS +=-g
-@@ -38,6 +39,8 @@
- arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
- arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
- arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 -march=armv5
-+#arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -mcpu=xscale
-+arch-$(CONFIG_CPU_XSCALE) :=-D__LINUX_ARM_ARCH__=5 -march=armv4 -Wa,-mxscale
-
- # This selects how we optimise for the processor.
- tune-y :=
-@@ -49,6 +52,8 @@
- tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
- tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
- tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
-+#tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale
-+tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm
-
- CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
- CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
-@@ -127,6 +132,10 @@
- MACHINE = sa1100
- endif
-
-+ifeq ($(CONFIG_ARCH_PXA),y)
-+MACHINE = pxa
-+endif
-+
- ifeq ($(CONFIG_ARCH_L7200),y)
- MACHINE = l7200
- endif
-@@ -164,6 +173,17 @@
- MACHINE = omaha
- endif
-
-+ifeq ($(CONFIG_XIP_KERNEL),y)
-+ DATAADDR := $(TEXTADDR)
-+ # Replace phys addr with virt addr while keeping offset from base.
-+ # Virt base addr also defined in include/asm-arm/arch-*/hardware.h
-+ TEXTADDR = $(shell echo 0x`echo $(CONFIG_XIP_PHYS_ADDR)|sed -e's/^0x//'` |\
-+ awk --non-decimal-data '/[:xdigit:]/ \
-+ {printf("0x%x\n",and($$0,0x001fffff)+0xe8000000)}' )
-+ LDSCRIPT = arch/arm/vmlinux-armv-xip.lds.in
-+ export DATAADDR
-+endif
-+
- export MACHINE PROCESSOR TEXTADDR GZFLAGS CFLAGS_BOOT OBJCOPYFLAGS
-
- # Only set INCDIR if its not already defined above
-@@ -269,7 +289,7 @@
- arch/arm/kernel arch/arm/mm arch/arm/lib: dummy
- $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
-
--bzImage zImage zinstall Image bootpImage install: vmlinux
-+bzImage zImage zinstall Image xipImage bootpImage install: vmlinux
- @$(MAKEBOOT) $@
-
- CLEAN_FILES += \
---- linux-2.4.27/arch/arm/boot/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/boot/Makefile
-@@ -113,6 +113,10 @@
- endif
- endif
-
-+ifeq ($(CONFIG_ARCH_PXA),y)
-+ZRELADDR = 0xa0008000
-+endif
-+
- ifeq ($(CONFIG_ARCH_ANAKIN),y)
- ZRELADDR = 0x20008000
- endif
-@@ -140,6 +144,14 @@
- zImage: compressed/vmlinux
- $(OBJCOPY) $(OBJCOPYFLAGS) $< $@
-
-+ifeq ($(CONFIG_XIP_KERNEL),y)
-+xipImage: $(CONFIGURE) $(SYSTEM)
-+ $(OBJCOPY) -S -O binary -R .data $(SYSTEM) vmlinux-text.bin
-+ $(OBJCOPY) -S -O binary -R .init -R .text -R __ex_table -R __ksymtab $(SYSTEM) vmlinux-data.bin
-+ cat vmlinux-text.bin vmlinux-data.bin > $@
-+ $(RM) -f vmlinux-text.bin vmlinux-data.bin
-+endif
-+
- bootpImage: bootp/bootp
- $(OBJCOPY) $(OBJCOPYFLAGS) $< $@
-
-@@ -160,7 +172,7 @@
- sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
-
- clean:
-- $(RM) Image zImage bootpImage
-+ $(RM) Image xipImage zImage bootpImage
- @$(MAKE) -C compressed clean
- @$(MAKE) -C bootp clean
-
---- linux-2.4.27/arch/arm/boot/compressed/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/boot/compressed/Makefile
-@@ -71,6 +71,10 @@
- OBJS += head-sa1100.o
- endif
-
-+ifeq ($(CONFIG_CPU_XSCALE),y)
-+OBJS += head-xscale.o
-+endif
-+
- SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
-
- LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
---- /dev/null
-+++ linux-2.4.27/arch/arm/boot/compressed/head-xscale.S
-@@ -0,0 +1,50 @@
-+/*
-+ * linux/arch/arm/boot/compressed/head-xscale.S
-+ *
-+ * XScale specific tweaks. This is merged into head.S by the linker.
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/mach-types.h>
-+
-+ .section ".start", #alloc, #execinstr
-+
-+__XScale_start:
-+
-+ @ Preserve r8/r7 i.e. kernel entry values
-+
-+ @ Data cache might be active.
-+ @ Be sure to flush kernel binary out of the cache,
-+ @ whatever state it is, before it is turned off.
-+ @ This is done by fetching through currently executed
-+ @ memory to be sure we hit the same cache.
-+ bic r2, pc, #0x1f
-+ add r3, r2, #0x10000 @ 64 kb is quite enough...
-+1: ldr r0, [r2], #32
-+ teq r2, r3
-+ bne 1b
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
-+
-+ @ disabling MMU and caches
-+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
-+ bic r0, r0, #0x05 @ clear DC, MMU
-+ bic r0, r0, #0x1000 @ clear Icache
-+ mcr p15, 0, r0, c1, c0, 0
-+
-+#ifdef CONFIG_ARCH_LUBBOCK
-+ mov r7, #MACH_TYPE_LUBBOCK
-+#endif
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ mov r7, #MACH_TYPE_PXA_IDP
-+#endif
-+
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ mov r7, #(MACH_TYPE_TRIZEPS2 & 0xFF00)
-+ add r7, r7, #(MACH_TYPE_TRIZEPS2 & 0xFF)
-+#endif
-+
-+
---- linux-2.4.27/arch/arm/boot/compressed/head.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/boot/compressed/head.S
-@@ -351,7 +351,11 @@
- orr r1, r1, #3 << 10
- add r2, r3, #16384
- 1: cmp r1, r8 @ if virt > start of RAM
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ orrhs r1, r1, #0x08 @ set cacheable, not bufferable
-+#else
- orrhs r1, r1, #0x0c @ set cacheable, bufferable
-+#endif
- cmp r1, r9 @ if virt > end of RAM
- bichs r1, r1, #0x0c @ clear cacheable, bufferable
- str r1, [r0], #4 @ 1:1 mapping
-@@ -364,7 +368,11 @@
- * so there is no map overlap problem for up to 1 MB compressed kernel.
- * If the execution is in RAM then we would only be duplicating the above.
- */
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ mov r1, #0x1a
-+#else
- mov r1, #0x1e
-+#endif
- orr r1, r1, #3 << 10
- mov r2, pc, lsr #20
- orr r1, r1, r2, lsl #20
---- linux-2.4.27/arch/arm/config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/config.in
-@@ -38,6 +38,7 @@
- Cirrus-CL-PS7500FE CONFIG_ARCH_CLPS7500 \
- CLPS711x/EP721x-based CONFIG_ARCH_CLPS711X \
- Co-EBSA285 CONFIG_ARCH_CO285 \
-+ PXA250/210-based CONFIG_ARCH_PXA \
- EBSA-110 CONFIG_ARCH_EBSA110 \
- Excalibur-ARM CONFIG_ARCH_CAMELOT \
- FootBridge CONFIG_ARCH_FOOTBRIDGE \
-@@ -148,6 +149,47 @@
- endmenu
-
- mainmenu_option next_comment
-+comment 'Intel PXA250/210 Implementations'
-+dep_bool ' Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA
-+dep_bool ' Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA
-+dep_bool ' Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA
-+dep_bool ' Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA
-+
-+if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then
-+ define_bool CONFIG_PXA_CERF y
-+
-+ choice 'CerfBoard Style' \
-+ "PDA CONFIG_PXA_CERF_PDA \
-+ BOARD CONFIG_PXA_CERF_BOARD" PDA
-+
-+ choice 'CerfBoard RAM Available' \
-+ "128MB CONFIG_PXA_CERF_RAM_128MB \
-+ 64MB CONFIG_PXA_CERF_RAM_64MB \
-+ 32MB CONFIG_PXA_CERF_RAM_32MB \
-+ 16MB CONFIG_PXA_CERF_RAM_16MB" 64MB
-+
-+ choice 'CerfBoard Flash Available' \
-+ "64MB CONFIG_PXA_CERF_FLASH_64MB \
-+ 32MB CONFIG_PXA_CERF_FLASH_32MB \
-+ 16MB CONFIG_PXA_CERF_FLASH_16MB \
-+ 8MB CONFIG_PXA_CERF_FLASH_8MB" 32MB
-+fi
-+
-+if [ "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
-+ define_bool CONFIG_SA1111 y
-+fi
-+
-+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
-+ define_bool CONFIG_TRIZEPS2 y
-+fi
-+
-+dep_tristate 'PXA USB function support' CONFIG_PXA_USB $CONFIG_ARCH_PXA
-+dep_tristate ' Support for PXA USB network link function' CONFIG_PXA_USB_NETLINK $CONFIG_PXA_USB
-+dep_tristate ' Support for PXA USB character device emulation' CONFIG_PXA_USB_CHAR $CONFIG_PXA_USB
-+
-+endmenu
-+
-+mainmenu_option next_comment
- comment 'CLPS711X/EP721X Implementations'
- dep_bool ' AUTCPU12' CONFIG_ARCH_AUTCPU12 $CONFIG_ARCH_CLPS711X
- dep_bool ' CDB89712' CONFIG_ARCH_CDB89712 $CONFIG_ARCH_CLPS711X
-@@ -385,6 +427,12 @@
- define_bool CONFIG_CPU_SA1100 n
- fi
-
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ define_bool CONFIG_CPU_32v5 y
-+ define_bool CONFIG_CPU_XSCALE y
-+ bool 'Workaround for XScale cache errata (see help)' CONFIG_XSCALE_CACHE_ERRATA
-+fi
-+
- # Figure out what processor architecture version we should be using.
- # This defines the compiler instruction set which depends on the machine type.
-
-@@ -493,6 +541,7 @@
- hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
-
- if [ "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
- dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL
- fi
-@@ -501,8 +550,10 @@
- bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
- if [ "$CONFIG_HOTPLUG" = "y" ]; then
- source drivers/pcmcia/Config.in
-+ source drivers/mmc/Config.in
- else
- define_bool CONFIG_PCMCIA n
-+ define_bool CONFIG_MMC n
- fi
- if [ "$CONFIG_SA1100_ACCELENT" = "y" ]; then
- if [ "$CONFIG_PCMCIA" != "n" ]; then
-@@ -513,6 +564,14 @@
- bool 'System V IPC' CONFIG_SYSVIPC
- bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
- bool 'Sysctl support' CONFIG_SYSCTL
-+
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_bool 'Kernel Execute-In-Place from ROM (EXPERIMENTAL)' CONFIG_XIP_KERNEL $CONFIG_EXPERIMENTAL
-+ if [ "$CONFIG_XIP_KERNEL" = "y" ]; then
-+ hex ' Kernel .text physical address' CONFIG_XIP_PHYS_ADDR 0
-+ fi
-+fi
-+
- comment 'At least one math emulation must be selected'
- tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
- if [ "$CONFIG_FPE_NWFPE" != "n" ]; then
-@@ -538,6 +597,9 @@
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_CO285" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_LUBBOCK" = "y" -o \
-+ "$CONFIG_ARCH_PXA_IDP" = "y" -o \
-+ "$CONFIG_ARCH_PXA_CERF" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_CDB89712" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
-@@ -550,9 +612,12 @@
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_CO285" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_LUBBOCK" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
- "$CONFIG_ARCH_OMAHA" = "y" -o \
-+ "$CONFIG_ARCH_PXA_CERF" = "y" -o \
-+ "$CONFIG_ARCH_PXA_IDP" = "y" -o \
- "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
- bool ' Timer LED' CONFIG_LEDS_TIMER
- bool ' CPU usage LED' CONFIG_LEDS_CPU
-@@ -686,6 +751,7 @@
- if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o \
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_TBOX" = "y" -o \
- "$CONFIG_ARCH_CLPS7500" = "y" -o \
-@@ -707,6 +773,7 @@
- "$CONFIG_ARCH_TBOX" = "y" -o \
- "$CONFIG_ARCH_SHARK" = "y" -o \
- "$CONFIG_ARCH_SA1100" = "y" -o \
-+ "$CONFIG_ARCH_PXA" = "y" -o \
- "$CONFIG_PCI" = "y" ]; then
- mainmenu_option next_comment
- comment 'Sound'
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/cerfboard_pxa
-@@ -0,0 +1,857 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_PXA_CERF=y
-+CONFIG_PXA_CERF=y
-+# CONFIG_PXA_CERF_PDA is not set
-+CONFIG_PXA_CERF_BOARD=y
-+# CONFIG_PXA_CERF_RAM_128MB is not set
-+CONFIG_PXA_CERF_RAM_64MB=y
-+# CONFIG_PXA_CERF_RAM_32MB is not set
-+# CONFIG_PXA_CERF_RAM_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_64MB is not set
-+CONFIG_PXA_CERF_FLASH_32MB=y
-+# CONFIG_PXA_CERF_FLASH_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_8MB is not set
-+CONFIG_PXA_USB=y
-+CONFIG_PXA_USB_NETLINK=y
-+CONFIG_PXA_USB_CHAR=m
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
-+CONFIG_LEDS=y
-+# CONFIG_LEDS_TIMER is not set
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_PXA_CERF=y
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=m
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+CONFIG_FILTER=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+# CONFIG_PPP_SYNC_TTY is not set
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+CONFIG_PCMCIA_FMVJ18X=m
-+CONFIG_PCMCIA_PCNET=m
-+CONFIG_PCMCIA_AXNET=m
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+CONFIG_PCMCIA_RAYCS=m
-+CONFIG_PCMCIA_NETWAVE=m
-+CONFIG_PCMCIA_WAVELAN=m
-+CONFIG_AIRONET4500_CS=m
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+# CONFIG_I2C_CHARDEV is not set
-+# CONFIG_I2C_PROC is not set
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+CONFIG_WATCHDOG=y
-+# CONFIG_WATCHDOG_NOWAYOUT is not set
-+# CONFIG_ACQUIRE_WDT is not set
-+# CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM7101_WDT is not set
-+# CONFIG_SC520_WDT is not set
-+# CONFIG_PCWATCHDOG is not set
-+# CONFIG_21285_WATCHDOG is not set
-+# CONFIG_977_WATCHDOG is not set
-+# CONFIG_SA1100_WATCHDOG is not set
-+CONFIG_PXA_WATCHDOG=m
-+# CONFIG_OMAHA_WATCHDOG is not set
-+# CONFIG_EUROTECH_WDT is not set
-+# CONFIG_IB700_WDT is not set
-+# CONFIG_WAFER_WDT is not set
-+# CONFIG_I810_TCO is not set
-+# CONFIG_MIXCOMWD is not set
-+# CONFIG_60XX_WDT is not set
-+# CONFIG_SC1200_WDT is not set
-+# CONFIG_SOFT_WATCHDOG is not set
-+# CONFIG_W83877F_WDT is not set
-+# CONFIG_WDT is not set
-+# CONFIG_WDTPCI is not set
-+# CONFIG_MACHZ_WDT is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=y
-+CONFIG_PCMCIA_CHRDEV=y
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+CONFIG_ROMFS_FS=y
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+CONFIG_NLS_CODEPAGE_863=m
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+# CONFIG_FB is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/cerfpda_pxa
-@@ -0,0 +1,962 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_PXA_CERF=y
-+CONFIG_PXA_CERF=y
-+CONFIG_PXA_CERF_PDA=y
-+# CONFIG_PXA_CERF_BOARD is not set
-+# CONFIG_PXA_CERF_RAM_128MB is not set
-+CONFIG_PXA_CERF_RAM_64MB=y
-+# CONFIG_PXA_CERF_RAM_32MB is not set
-+# CONFIG_PXA_CERF_RAM_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_64MB is not set
-+CONFIG_PXA_CERF_FLASH_32MB=y
-+# CONFIG_PXA_CERF_FLASH_16MB is not set
-+# CONFIG_PXA_CERF_FLASH_8MB is not set
-+CONFIG_PXA_USB=y
-+CONFIG_PXA_USB_NETLINK=y
-+CONFIG_PXA_USB_CHAR=y
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_ARM_THUMB is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+CONFIG_BSD_PROCESS_ACCT=y
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=1f03 rw console=tty0 console=ttyS0,38400 init=/linuxrc"
-+CONFIG_LEDS=y
-+# CONFIG_LEDS_TIMER is not set
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_PXA_CERF=y
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+CONFIG_BLK_DEV_LOOP=m
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+CONFIG_FILTER=y
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+# CONFIG_PPP_SYNC_TTY is not set
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+CONFIG_PCMCIA_3C589=m
-+CONFIG_PCMCIA_3C574=m
-+CONFIG_PCMCIA_FMVJ18X=m
-+CONFIG_PCMCIA_PCNET=m
-+CONFIG_PCMCIA_AXNET=m
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+# CONFIG_NET_PCMCIA_RADIO is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=y
-+CONFIG_IRLAN=y
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=y
-+CONFIG_IRDA_ULTRA=y
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+CONFIG_IRDA_DEBUG=y
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=y
-+# CONFIG_IRPORT_SIR is not set
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+
-+#
-+# ATA/IDE/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_INTEL_RNG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=y
-+CONFIG_PCMCIA_CHRDEV=y
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+CONFIG_AUTOFS_FS=y
-+CONFIG_AUTOFS4_FS=y
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+CONFIG_UMSDOS_FS=m
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=m
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+CONFIG_ROMFS_FS=y
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+CONFIG_NLS_CODEPAGE_850=m
-+CONFIG_NLS_CODEPAGE_852=m
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+CONFIG_NLS_CODEPAGE_863=m
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_NLS_ISO8859_2=m
-+CONFIG_NLS_ISO8859_3=m
-+CONFIG_NLS_ISO8859_4=m
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_PXA_8BPP is not set
-+CONFIG_FB_PXA_16BPP=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+CONFIG_FBCON_FONTS=y
-+# CONFIG_FONT_8x8 is not set
-+# CONFIG_FONT_8x16 is not set
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_SUN12x22 is not set
-+# CONFIG_FONT_6x11 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+CONFIG_FONT_ACORN_8x8=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+# CONFIG_USB_UHCI is not set
-+# CONFIG_USB_UHCI_ALT is not set
-+# CONFIG_USB_OHCI is not set
-+# CONFIG_USB_OHCI_SA1111 is not set
-+# CONFIG_USB_AUDIO is not set
-+# CONFIG_USB_BLUETOOTH is not set
-+# CONFIG_USB_STORAGE is not set
-+# CONFIG_USB_STORAGE_DEBUG is not set
-+# CONFIG_USB_STORAGE_DATAFAB is not set
-+# CONFIG_USB_STORAGE_FREECOM is not set
-+# CONFIG_USB_STORAGE_ISD200 is not set
-+# CONFIG_USB_STORAGE_DPCM is not set
-+# CONFIG_USB_STORAGE_HP8200e is not set
-+# CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_JUMPSHOT is not set
-+# CONFIG_USB_ACM is not set
-+# CONFIG_USB_PRINTER is not set
-+# CONFIG_USB_HID is not set
-+# CONFIG_USB_HIDDEV is not set
-+# CONFIG_USB_KBD is not set
-+# CONFIG_USB_MOUSE is not set
-+# CONFIG_USB_WACOM is not set
-+# CONFIG_USB_DC2XX is not set
-+# CONFIG_USB_MDC800 is not set
-+# CONFIG_USB_SCANNER is not set
-+# CONFIG_USB_MICROTEK is not set
-+# CONFIG_USB_HPUSBSCSI is not set
-+# CONFIG_USB_PEGASUS is not set
-+# CONFIG_USB_KAWETH is not set
-+# CONFIG_USB_CATC is not set
-+# CONFIG_USB_CDCETHER is not set
-+# CONFIG_USB_USBNET is not set
-+# CONFIG_USB_USS720 is not set
-+
-+#
-+# USB Serial Converter support
-+#
-+# CONFIG_USB_SERIAL is not set
-+# CONFIG_USB_SERIAL_GENERIC is not set
-+# CONFIG_USB_SERIAL_BELKIN is not set
-+# CONFIG_USB_SERIAL_WHITEHEAT is not set
-+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-+# CONFIG_USB_SERIAL_EMPEG is not set
-+# CONFIG_USB_SERIAL_FTDI_SIO is not set
-+# CONFIG_USB_SERIAL_VISOR is not set
-+# CONFIG_USB_SERIAL_IPAQ is not set
-+# CONFIG_USB_SERIAL_IR is not set
-+# CONFIG_USB_SERIAL_EDGEPORT is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-+# CONFIG_USB_SERIAL_KEYSPAN is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-+# CONFIG_USB_SERIAL_MCT_U232 is not set
-+# CONFIG_USB_SERIAL_KLSI is not set
-+# CONFIG_USB_SERIAL_PL2303 is not set
-+# CONFIG_USB_SERIAL_CYBERJACK is not set
-+# CONFIG_USB_SERIAL_XIRCOM is not set
-+# CONFIG_USB_SERIAL_OMNINET is not set
-+# CONFIG_USB_RIO500 is not set
-+
-+#
-+# Bluetooth support
-+#
-+CONFIG_BLUEZ=y
-+CONFIG_BLUEZ_L2CAP=y
-+
-+#
-+# Bluetooth device drivers
-+#
-+# CONFIG_BLUEZ_HCIUSB is not set
-+CONFIG_BLUEZ_HCIUART=y
-+CONFIG_BLUEZ_HCIVHCI=y
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/csb226
-@@ -0,0 +1,615 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Board
-+#
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_INNOKOM is not set
-+CONFIG_ARCH_CSB226=y
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_CPU_FREQ is not set
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+# CONFIG_MMC is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="console=ttyS0,19200"
-+CONFIG_ALIGNMENT_TRAP=y
-+CONFIG_ARM_HWTIMER=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+# CONFIG_MTD is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+CONFIG_ARM_CIRRUS=y
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+# CONFIG_JFFS2_FS is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+# CONFIG_NFS_V3 is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+# CONFIG_MSDOS_PARTITION is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_WAITQ=y
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/innokom
-@@ -0,0 +1,699 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Board
-+#
-+# CONFIG_ARCH_PXA_IDP is not set
-+CONFIG_ARCH_INNOKOM=y
-+# CONFIG_ARCH_CSB226 is not set
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+CONFIG_XSCALE_CACHE_ERRATA=y
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_CPU_FREQ is not set
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+# CONFIG_MMC is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/nfs mem=32M ip=dhcp console=ttyS0,19200"
-+CONFIG_ALIGNMENT_TRAP=y
-+CONFIG_ARM_HWTIMER=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+CONFIG_MTD_CFI_AMDSTD=y
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_FORTUNET is not set
-+CONFIG_MTD_INNOKOM=y
-+CONFIG_MTD_INNOKOM_16MB=y
-+# CONFIG_MTD_INNOKOM_64MB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+# CONFIG_IP_PNP_BOOTP is not set
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91X=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_JFFS2_FS_NAND is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+# CONFIG_EXT2_FS is not set
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+# CONFIG_MSDOS_PARTITION is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Sound
-+#
-+# CONFIG_SOUND is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+# CONFIG_MCP_UCB1400_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+CONFIG_MAGIC_SYSRQ=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_WAITQ=y
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/lubbock
-@@ -0,0 +1,971 @@
-+#
-+# Automatically generated make config: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+# CONFIG_KMOD is not set
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_AT91RM9200 is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+
-+#
-+# Archimedes/A5000 Implementations (select only ONE)
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# AT91RM9200 Implementations
-+#
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+CONFIG_ARCH_LUBBOCK=y
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+# CONFIG_ARCH_TRIZEPS2 is not set
-+CONFIG_SA1111=y
-+# CONFIG_PXA_USB is not set
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+
-+#
-+# Processor Type
-+#
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+
-+#
-+# Processor Features
-+#
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_CPU_FREQ=y
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+
-+#
-+# MMC device drivers
-+#
-+CONFIG_MMC=m
-+CONFIG_MMC_PXA=m
-+CONFIG_MMC_BLOCK=m
-+CONFIG_MMC_PARTITIONS=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+# CONFIG_XIP_KERNEL is not set
-+
-+#
-+# At least one math emulation must be selected
-+#
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+CONFIG_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=32M"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+
-+#
-+# User Modules And Translation Layers
-+#
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+CONFIG_MTD_CFI_B2=y
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+CONFIG_MTD_CFI_I1=y
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+CONFIG_MTD_LUBBOCK=y
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+
-+#
-+# Disk-On-Chip Device Drivers
-+#
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+# CONFIG_BLK_STATS is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+
-+#
-+#
-+#
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91X=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+# CONFIG_PCMCIA_3C574 is not set
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=y
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+# CONFIG_PCMCIA_SMC91C92 is not set
-+# CONFIG_PCMCIA_XIRC2PS is not set
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+# CONFIG_NET_PCMCIA_RADIO is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+
-+#
-+# Please see Documentation/ide.txt for help/info on IDE drives
-+#
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+CONFIG_BLK_DEV_IDECS=y
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+
-+#
-+# IDE chipset support/bugfixes
-+#
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+CONFIG_BLK_DEV_IDE_MODES=y
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+# CONFIG_BLK_DEV_ATARAID_SII is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_INPUT_MX1TS is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_AT91 is not set
-+# CONFIG_SERIAL_AT91_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+
-+#
-+# Other L3 adapters
-+#
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+CONFIG_BUSMOUSE=y
-+# CONFIG_ATIXL_BUSMOUSE is not set
-+# CONFIG_LOGIBUSMOUSE is not set
-+# CONFIG_MS_BUSMOUSE is not set
-+CONFIG_MOUSE=y
-+CONFIG_PSMOUSE=y
-+# CONFIG_82C710_MOUSE is not set
-+# CONFIG_PC110_PAD is not set
-+# CONFIG_MK712_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_PXA_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+# CONFIG_PCMCIA_SERIAL_CS is not set
-+# CONFIG_SYNCLINK_CS is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=y
-+CONFIG_MSDOS_FS=y
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+# CONFIG_CRAMFS_LINEAR is not set
-+# CONFIG_CRAMFS_LINEAR_XIP is not set
-+# CONFIG_ROOT_CRAMFS_LINEAR is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+# CONFIG_NFS_V3 is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+# CONFIG_FB_DBMX1 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_PXA_8BPP is not set
-+CONFIG_FB_PXA_16BPP=y
-+# CONFIG_FB_PXA_QVGA is not set
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+CONFIG_FBCON_FONTWIDTH8_ONLY=y
-+# CONFIG_FBCON_FONTS is not set
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_ALI5455 is not set
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_FORTE is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_VIDC is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_ZLIB_INFLATE=y
-+CONFIG_ZLIB_DEFLATE=y
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/pxa_idp
-@@ -0,0 +1,933 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+CONFIG_ARCH_PXA_IDP=y
-+# CONFIG_ARCH_PXA_CERF is not set
-+CONFIG_PXA_USB=m
-+CONFIG_PXA_USB_NETLINK=m
-+CONFIG_PXA_USB_CHAR=m
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+CONFIG_PM=y
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/mtdblock2 init=/linuxrc console=ttyS0,115200"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+CONFIG_LEDS_CPU=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_CFI_NOSWAP=y
-+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-+CONFIG_MTD_CFI_GEOMETRY=y
-+# CONFIG_MTD_CFI_B1 is not set
-+# CONFIG_MTD_CFI_B2 is not set
-+CONFIG_MTD_CFI_B4=y
-+# CONFIG_MTD_CFI_B8 is not set
-+# CONFIG_MTD_CFI_I1 is not set
-+CONFIG_MTD_CFI_I2=y
-+# CONFIG_MTD_CFI_I4 is not set
-+# CONFIG_MTD_CFI_I8 is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+CONFIG_MTD_LUBBOCK=y
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_PXA_CERF is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+CONFIG_ASI_MTD0_SIZE=40000
-+CONFIG_ASI_MTD1_SIZE=100000
-+CONFIG_ASI_MTD2_SIZE=1e00000
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=4096
-+CONFIG_BLK_DEV_INITRD=y
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+# CONFIG_IP_PNP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+# CONFIG_SMC9194 is not set
-+CONFIG_SMC91111=m
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+CONFIG_NET_POCKET=y
-+# CONFIG_DE600 is not set
-+# CONFIG_DE620 is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+CONFIG_WAVELAN=m
-+# CONFIG_ARLAN is not set
-+CONFIG_AIRONET4500=y
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+CONFIG_HERMES=m
-+CONFIG_PCMCIA_HERMES=m
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+# CONFIG_PCMCIA_3C574 is not set
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+CONFIG_PCMCIA_PCNET=m
-+# CONFIG_PCMCIA_AXNET is not set
-+CONFIG_PCMCIA_NMCLAN=m
-+CONFIG_PCMCIA_SMC91C92=m
-+CONFIG_PCMCIA_XIRC2PS=m
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+CONFIG_PCMCIA_RAYCS=m
-+CONFIG_PCMCIA_NETWAVE=m
-+CONFIG_PCMCIA_WAVELAN=m
-+CONFIG_AIRONET4500_CS=m
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+CONFIG_IRDA=m
-+CONFIG_IRLAN=m
-+# CONFIG_IRNET is not set
-+CONFIG_IRCOMM=m
-+CONFIG_IRDA_ULTRA=y
-+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
-+# CONFIG_IRDA_FAST_RR is not set
-+CONFIG_IRDA_DEBUG=y
-+
-+#
-+# Infrared-port device drivers
-+#
-+CONFIG_IRTTY_SIR=m
-+# CONFIG_IRPORT_SIR is not set
-+# CONFIG_DONGLE is not set
-+# CONFIG_USB_IRDA is not set
-+# CONFIG_NSC_FIR is not set
-+# CONFIG_WINBOND_FIR is not set
-+# CONFIG_TOSHIBA_FIR is not set
-+# CONFIG_SMC_IRCC_FIR is not set
-+# CONFIG_ALI_FIR is not set
-+# CONFIG_VLSI_FIR is not set
-+CONFIG_PXA_FIR=m
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=y
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=y
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=y
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+CONFIG_INPUT=y
-+CONFIG_INPUT_KEYBDEV=m
-+CONFIG_INPUT_MOUSEDEV=m
-+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
-+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
-+# CONFIG_INPUT_JOYDEV is not set
-+CONFIG_INPUT_EVDEV=y
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+# CONFIG_IDP_KEYB is not set
-+CONFIG_MATRIX_KEYBOARD=y
-+# CONFIG_SA1111_PS2_KEYB is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+# CONFIG_I2C is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+CONFIG_BUSMOUSE=y
-+# CONFIG_ATIXL_BUSMOUSE is not set
-+# CONFIG_LOGIBUSMOUSE is not set
-+# CONFIG_MS_BUSMOUSE is not set
-+CONFIG_MOUSE=y
-+CONFIG_PSMOUSE=y
-+# CONFIG_82C710_MOUSE is not set
-+# CONFIG_PC110_PAD is not set
-+# CONFIG_MK712_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_INPUT_NS558 is not set
-+# CONFIG_INPUT_LIGHTNING is not set
-+# CONFIG_INPUT_PCIGAME is not set
-+# CONFIG_INPUT_CS461X is not set
-+# CONFIG_INPUT_EMU10K1 is not set
-+# CONFIG_INPUT_SERIO is not set
-+# CONFIG_INPUT_SERPORT is not set
-+# CONFIG_INPUT_ANALOG is not set
-+# CONFIG_INPUT_A3D is not set
-+# CONFIG_INPUT_ADI is not set
-+# CONFIG_INPUT_COBRA is not set
-+# CONFIG_INPUT_GF2K is not set
-+# CONFIG_INPUT_GRIP is not set
-+# CONFIG_INPUT_INTERACT is not set
-+# CONFIG_INPUT_TMDC is not set
-+# CONFIG_INPUT_SIDEWINDER is not set
-+# CONFIG_INPUT_IFORCE_USB is not set
-+# CONFIG_INPUT_IFORCE_232 is not set
-+# CONFIG_INPUT_WARRIOR is not set
-+# CONFIG_INPUT_MAGELLAN is not set
-+# CONFIG_INPUT_SPACEORB is not set
-+# CONFIG_INPUT_SPACEBALL is not set
-+# CONFIG_INPUT_STINGER is not set
-+# CONFIG_INPUT_DB9 is not set
-+# CONFIG_INPUT_GAMECON is not set
-+# CONFIG_INPUT_TURBOGRAFX is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+# CONFIG_PXA_RTC is not set
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+CONFIG_PCMCIA_SERIAL_CS=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=m
-+CONFIG_JBD=m
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+# CONFIG_UMSDOS_FS is not set
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+CONFIG_CRAMFS=y
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+CONFIG_ZLIB_FS_INFLATE=y
-+
-+#
-+# Partition Types
-+#
-+CONFIG_PARTITION_ADVANCED=y
-+# CONFIG_ACORN_PARTITION is not set
-+# CONFIG_OSF_PARTITION is not set
-+# CONFIG_AMIGA_PARTITION is not set
-+# CONFIG_ATARI_PARTITION is not set
-+# CONFIG_MAC_PARTITION is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_BSD_DISKLABEL is not set
-+# CONFIG_MINIX_SUBPARTITION is not set
-+# CONFIG_SOLARIS_X86_PARTITION is not set
-+# CONFIG_UNIXWARE_DISKLABEL is not set
-+# CONFIG_LDM_PARTITION is not set
-+# CONFIG_SGI_PARTITION is not set
-+# CONFIG_ULTRIX_PARTITION is not set
-+# CONFIG_SUN_PARTITION is not set
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+CONFIG_NLS_CODEPAGE_437=m
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+# CONFIG_FBCON_ADVANCED is not set
-+CONFIG_FBCON_CFB2=y
-+CONFIG_FBCON_CFB4=y
-+CONFIG_FBCON_CFB8=y
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-+# CONFIG_FBCON_FONTS is not set
-+CONFIG_FONT_8x8=y
-+CONFIG_FONT_8x16=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=m
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+CONFIG_DEBUG_SLAB=y
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+# CONFIG_DEBUG_LL is not set
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/trizeps2
-@@ -0,0 +1,873 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_H3600_SLEEVE is not set
-+
-+#
-+# Intel PXA250/210 Implementations
-+#
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_ARCH_PXA_CERF is not set
-+CONFIG_ARCH_TRIZEPS2=y
-+CONFIG_TRIZEPS2=y
-+CONFIG_PXA_USB=y
-+# CONFIG_PXA_USB_NETLINK is not set
-+# CONFIG_PXA_USB_CHAR is not set
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+# CONFIG_CPU_ARM920T is not set
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_PLD is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_XSCALE=y
-+# CONFIG_XSCALE_CACHE_ERRATA is not set
-+# CONFIG_CPU_32v3 is not set
-+# CONFIG_CPU_32v4 is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+CONFIG_HOTPLUG=y
-+
-+#
-+# PCMCIA/CardBus support
-+#
-+CONFIG_PCMCIA=y
-+# CONFIG_I82092 is not set
-+# CONFIG_I82365 is not set
-+# CONFIG_TCIC is not set
-+# CONFIG_PCMCIA_CLPS6700 is not set
-+# CONFIG_PCMCIA_SA1100 is not set
-+CONFIG_PCMCIA_PXA=y
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="root=/dev/mtdblock3 rw console=ttyS0,38400 mem=32M noinitrd init=/linuxrc"
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+CONFIG_MTD_PARTITIONS=y
-+# CONFIG_MTD_CONCAT is not set
-+CONFIG_MTD_REDBOOT_PARTS=y
-+CONFIG_MTD_CMDLINE_PARTS=y
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+# CONFIG_MTD_JEDECPROBE is not set
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_RAM is not set
-+# CONFIG_MTD_ROM is not set
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+# CONFIG_MTD_PHYSMAP is not set
-+# CONFIG_MTD_LUBBOCK is not set
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_PXA_CERF is not set
-+# CONFIG_MTD_EPXA10DB is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+CONFIG_MTD_TRIZEPS2=y
-+# CONFIG_MTD_PCI is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+# CONFIG_MTD_NAND is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+CONFIG_BLK_DEV_LOOP=y
-+# CONFIG_BLK_DEV_NBD is not set
-+# CONFIG_BLK_DEV_RAM is not set
-+# CONFIG_BLK_DEV_INITRD is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+# CONFIG_PACKET is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+CONFIG_NET_VENDOR_SMC=y
-+# CONFIG_WD80x3 is not set
-+# CONFIG_ULTRAMCA is not set
-+# CONFIG_ULTRA is not set
-+# CONFIG_ULTRA32 is not set
-+CONFIG_SMC9194=y
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+CONFIG_PPP=m
-+# CONFIG_PPP_MULTILINK is not set
-+# CONFIG_PPP_FILTER is not set
-+CONFIG_PPP_ASYNC=m
-+CONFIG_PPP_SYNC_TTY=m
-+CONFIG_PPP_DEFLATE=m
-+CONFIG_PPP_BSDCOMP=m
-+# CONFIG_PPPOE is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+CONFIG_NET_RADIO=y
-+# CONFIG_STRIP is not set
-+# CONFIG_WAVELAN is not set
-+# CONFIG_ARLAN is not set
-+# CONFIG_AIRONET4500 is not set
-+# CONFIG_AIRONET4500_NONCS is not set
-+# CONFIG_AIRONET4500_PROC is not set
-+# CONFIG_HERMES is not set
-+# CONFIG_PCMCIA_HERMES is not set
-+CONFIG_AIRO_CS=m
-+CONFIG_NET_WIRELESS=y
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# PCMCIA network device support
-+#
-+CONFIG_NET_PCMCIA=y
-+# CONFIG_PCMCIA_3C589 is not set
-+CONFIG_PCMCIA_3C574=m
-+# CONFIG_PCMCIA_FMVJ18X is not set
-+# CONFIG_PCMCIA_PCNET is not set
-+# CONFIG_PCMCIA_AXNET is not set
-+# CONFIG_PCMCIA_NMCLAN is not set
-+# CONFIG_PCMCIA_SMC91C92 is not set
-+# CONFIG_PCMCIA_XIRC2PS is not set
-+# CONFIG_ARCNET_COM20020_CS is not set
-+# CONFIG_PCMCIA_IBMTR is not set
-+CONFIG_NET_PCMCIA_RADIO=y
-+# CONFIG_PCMCIA_RAYCS is not set
-+# CONFIG_PCMCIA_NETWAVE is not set
-+# CONFIG_PCMCIA_WAVELAN is not set
-+# CONFIG_AIRONET4500_CS is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+CONFIG_IDE=m
-+
-+#
-+# IDE, ATA and ATAPI Block devices
-+#
-+CONFIG_BLK_DEV_IDE=m
-+# CONFIG_BLK_DEV_HD_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+CONFIG_BLK_DEV_IDEDISK=m
-+# CONFIG_IDEDISK_MULTI_MODE is not set
-+# CONFIG_IDEDISK_STROKE is not set
-+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-+# CONFIG_BLK_DEV_IDEDISK_WD is not set
-+# CONFIG_BLK_DEV_COMMERIAL is not set
-+# CONFIG_BLK_DEV_TIVO is not set
-+CONFIG_BLK_DEV_IDECS=m
-+# CONFIG_BLK_DEV_IDECD is not set
-+# CONFIG_BLK_DEV_IDETAPE is not set
-+# CONFIG_BLK_DEV_IDEFLOPPY is not set
-+# CONFIG_BLK_DEV_IDESCSI is not set
-+# CONFIG_IDE_TASK_IOCTL is not set
-+# CONFIG_BLK_DEV_CMD640 is not set
-+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-+# CONFIG_BLK_DEV_ISAPNP is not set
-+# CONFIG_IDE_CHIPSETS is not set
-+# CONFIG_IDEDMA_AUTO is not set
-+# CONFIG_DMA_NONPCI is not set
-+# CONFIG_BLK_DEV_IDE_MODES is not set
-+# CONFIG_BLK_DEV_ATARAID is not set
-+# CONFIG_BLK_DEV_ATARAID_PDC is not set
-+# CONFIG_BLK_DEV_ATARAID_HPT is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+# CONFIG_VT_CONSOLE is not set
-+CONFIG_SERIAL=y
-+CONFIG_SERIAL_CONSOLE=y
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_UNIX98_PTYS=y
-+CONFIG_UNIX98_PTY_COUNT=256
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_PXA_ALGO=y
-+CONFIG_I2C_PXA_ADAP=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+# CONFIG_I2C_DS1307 is not set
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+
-+#
-+# Watchdog Cards
-+#
-+# CONFIG_WATCHDOG is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_PXA_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+# CONFIG_DRM is not set
-+
-+#
-+# PCMCIA character devices
-+#
-+# CONFIG_PCMCIA_SERIAL_CS is not set
-+CONFIG_TRIZEPS2_TTLIO=m
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_BFS_FS is not set
-+CONFIG_EXT3_FS=y
-+CONFIG_JBD=y
-+# CONFIG_JBD_DEBUG is not set
-+CONFIG_FAT_FS=m
-+CONFIG_MSDOS_FS=m
-+# CONFIG_UMSDOS_FS is not set
-+CONFIG_VFAT_FS=m
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+CONFIG_JFFS2_FS=y
-+CONFIG_JFFS2_FS_DEBUG=0
-+# CONFIG_CRAMFS is not set
-+CONFIG_TMPFS=y
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+# CONFIG_DEVFS_FS is not set
-+# CONFIG_DEVFS_MOUNT is not set
-+# CONFIG_DEVFS_DEBUG is not set
-+CONFIG_DEVPTS_FS=y
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=m
-+# CONFIG_NFS_V3 is not set
-+# CONFIG_ROOT_NFS is not set
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+CONFIG_SUNRPC=m
-+CONFIG_LOCKD=m
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+# CONFIG_ZLIB_FS_INFLATE is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+CONFIG_NLS=y
-+
-+#
-+# Native Language Support
-+#
-+CONFIG_NLS_DEFAULT="iso8859-1"
-+# CONFIG_NLS_CODEPAGE_437 is not set
-+# CONFIG_NLS_CODEPAGE_737 is not set
-+# CONFIG_NLS_CODEPAGE_775 is not set
-+# CONFIG_NLS_CODEPAGE_850 is not set
-+# CONFIG_NLS_CODEPAGE_852 is not set
-+# CONFIG_NLS_CODEPAGE_855 is not set
-+# CONFIG_NLS_CODEPAGE_857 is not set
-+# CONFIG_NLS_CODEPAGE_860 is not set
-+# CONFIG_NLS_CODEPAGE_861 is not set
-+# CONFIG_NLS_CODEPAGE_862 is not set
-+# CONFIG_NLS_CODEPAGE_863 is not set
-+# CONFIG_NLS_CODEPAGE_864 is not set
-+# CONFIG_NLS_CODEPAGE_865 is not set
-+# CONFIG_NLS_CODEPAGE_866 is not set
-+# CONFIG_NLS_CODEPAGE_869 is not set
-+# CONFIG_NLS_CODEPAGE_936 is not set
-+# CONFIG_NLS_CODEPAGE_950 is not set
-+# CONFIG_NLS_CODEPAGE_932 is not set
-+# CONFIG_NLS_CODEPAGE_949 is not set
-+# CONFIG_NLS_CODEPAGE_874 is not set
-+# CONFIG_NLS_ISO8859_8 is not set
-+# CONFIG_NLS_CODEPAGE_1250 is not set
-+# CONFIG_NLS_CODEPAGE_1251 is not set
-+CONFIG_NLS_ISO8859_1=y
-+# CONFIG_NLS_ISO8859_2 is not set
-+# CONFIG_NLS_ISO8859_3 is not set
-+# CONFIG_NLS_ISO8859_4 is not set
-+# CONFIG_NLS_ISO8859_5 is not set
-+# CONFIG_NLS_ISO8859_6 is not set
-+# CONFIG_NLS_ISO8859_7 is not set
-+# CONFIG_NLS_ISO8859_9 is not set
-+# CONFIG_NLS_ISO8859_13 is not set
-+# CONFIG_NLS_ISO8859_14 is not set
-+# CONFIG_NLS_ISO8859_15 is not set
-+# CONFIG_NLS_KOI8_R is not set
-+# CONFIG_NLS_KOI8_U is not set
-+# CONFIG_NLS_UTF8 is not set
-+
-+#
-+# Console drivers
-+#
-+CONFIG_PC_KEYMAP=y
-+# CONFIG_VGA_CONSOLE is not set
-+
-+#
-+# Frame-buffer support
-+#
-+CONFIG_FB=y
-+CONFIG_DUMMY_CONSOLE=y
-+# CONFIG_FB_ACORN is not set
-+# CONFIG_FB_ANAKIN is not set
-+# CONFIG_FB_CLPS711X is not set
-+# CONFIG_FB_SA1100 is not set
-+CONFIG_FB_PXA=y
-+# CONFIG_FB_CYBER2000 is not set
-+# CONFIG_FB_VIRTUAL is not set
-+CONFIG_FBCON_ADVANCED=y
-+# CONFIG_FBCON_MFB is not set
-+# CONFIG_FBCON_CFB2 is not set
-+# CONFIG_FBCON_CFB4 is not set
-+# CONFIG_FBCON_CFB8 is not set
-+CONFIG_FBCON_CFB16=y
-+# CONFIG_FBCON_CFB24 is not set
-+# CONFIG_FBCON_CFB32 is not set
-+# CONFIG_FBCON_AFB is not set
-+# CONFIG_FBCON_ILBM is not set
-+# CONFIG_FBCON_IPLAN2P2 is not set
-+# CONFIG_FBCON_IPLAN2P4 is not set
-+# CONFIG_FBCON_IPLAN2P8 is not set
-+# CONFIG_FBCON_MAC is not set
-+# CONFIG_FBCON_VGA_PLANES is not set
-+# CONFIG_FBCON_VGA is not set
-+# CONFIG_FBCON_HGA is not set
-+CONFIG_FBCON_FONTWIDTH8_ONLY=y
-+CONFIG_FBCON_FONTS=y
-+# CONFIG_FONT_8x8 is not set
-+# CONFIG_FONT_8x16 is not set
-+# CONFIG_FONT_SUN8x16 is not set
-+# CONFIG_FONT_PEARL_8x8 is not set
-+CONFIG_FONT_ACORN_8x8=y
-+
-+#
-+# Sound
-+#
-+CONFIG_SOUND=y
-+# CONFIG_SOUND_BT878 is not set
-+# CONFIG_SOUND_CMPCI is not set
-+# CONFIG_SOUND_EMU10K1 is not set
-+# CONFIG_MIDI_EMU10K1 is not set
-+# CONFIG_SOUND_FUSION is not set
-+# CONFIG_SOUND_CS4281 is not set
-+# CONFIG_SOUND_ES1370 is not set
-+# CONFIG_SOUND_ES1371 is not set
-+# CONFIG_SOUND_ESSSOLO1 is not set
-+# CONFIG_SOUND_MAESTRO is not set
-+# CONFIG_SOUND_MAESTRO3 is not set
-+# CONFIG_SOUND_ICH is not set
-+# CONFIG_SOUND_RME96XX is not set
-+# CONFIG_SOUND_SONICVIBES is not set
-+# CONFIG_SOUND_TRIDENT is not set
-+# CONFIG_SOUND_MSNDCLAS is not set
-+# CONFIG_SOUND_MSNDPIN is not set
-+# CONFIG_SOUND_VIA82CXXX is not set
-+# CONFIG_MIDI_VIA82CXXX is not set
-+# CONFIG_SOUND_OSS is not set
-+# CONFIG_SOUND_WAVEARTIST is not set
-+CONFIG_SOUND_PXA_AC97=y
-+# CONFIG_SOUND_TVMIXER is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+CONFIG_MCP=y
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+CONFIG_MCP_UCB1400_TS=y
-+CONFIG_MCP_UCB1X00_TS_COMPAT=y
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+CONFIG_DEBUG_INFO=y
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+CONFIG_MAGIC_SYSRQ=y
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+CONFIG_DEBUG_BUGVERBOSE=y
-+CONFIG_DEBUG_ERRORS=y
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
---- linux-2.4.27/arch/arm/kernel/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/kernel/Makefile
-@@ -10,7 +10,7 @@
- HEAD_OBJ = head-$(PROCESSOR).o
- ENTRY_OBJ = entry-$(PROCESSOR).o
-
--AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
-+AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
- AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
-
- # This is depreciated.
-@@ -45,7 +45,7 @@
- $(CONFIG_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110) \
- $(CONFIG_ARCH_SA1100) $(CONFIG_ARCH_CAMELOT) \
- $(CONFIG_ARCH_MX1ADS) $(CONFIG_ARCH_OMAHA) \
-- $(CONFIG_ARCH_AT91RM9200)
-+ $(CONFIG_ARCH_AT91RM9200) $(CONFIG_ARCH_PXA)
-
- ifneq ($(findstring y,$(no-irq-arch)),y)
- obj-y += irq-arch.o
---- linux-2.4.27/arch/arm/kernel/debug-armv.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/kernel/debug-armv.S
-@@ -221,6 +221,31 @@
- bne 1001b
- .endm
-
-+#elif defined(CONFIG_ARCH_PXA)
-+
-+ .macro addruart,rx
-+ mrc p15, 0, \rx, c1, c0
-+ tst \rx, #1 @ MMU enabled?
-+ moveq \rx, #0x40000000 @ physical
-+ movne \rx, #io_p2v(0x40000000) @ virtual
-+ orr \rx, \rx, #0x00100000 @ FFUART
-+ .endm
-+
-+ .macro senduart,rd,rx
-+ str \rd, [\rx, #0]
-+ .endm
-+
-+ .macro busyuart,rd,rx
-+1002: ldr \rd, [\rx, #0x14]
-+ tst \rd, #(1 << 6)
-+ beq 1002b
-+ .endm
-+
-+ .macro waituart,rd,rx
-+1001: ldr \rd, [\rx, #0x14]
-+ tst \rd, #(1 << 5)
-+ beq 1001b
-+ .endm
- #elif defined(CONFIG_ARCH_CLPS7500)
- .macro addruart,rx
- mov \rx, #0xe0000000
---- linux-2.4.27/arch/arm/kernel/entry-armv.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/kernel/entry-armv.S
-@@ -615,6 +615,27 @@
- .text
- .endm
-
-+#elif CONFIG_ARCH_PXA
-+
-+ .macro disable_fiq
-+ .endm
-+
-+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-+ mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000
-+ add \base, \base, #0x00d00000
-+ ldr \irqstat, [\base, #0] @ ICIP
-+ ldr \irqnr, [\base, #4] @ ICMR
-+ ands \irqstat, \irqstat, \irqnr
-+ beq 1001f
-+ rsb \irqnr, \irqstat, #0
-+ and \irqstat, \irqstat, \irqnr
-+ clz \irqnr, \irqstat
-+ rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
-+1001:
-+ .endm
-+
-+ .macro irq_prio_table
-+ .endm
- #else
- #error Unknown architecture
- #endif
-@@ -891,9 +912,17 @@
- stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack
- mrs ip, cpsr
- str ip, [sp, #-4]! @ Save cpsr_SVC
-+#ifdef CONFIG_CPU_XSCALE
-+ mra r4, r5, acc0
-+ stmfd sp!, {r4, r5}
-+#endif
- str sp, [r0, #TSS_SAVE] @ Save sp_SVC
- ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r2, [r1, #TSS_DOMAIN]
-+#ifdef CONFIG_CPU_XSCALE
-+ ldmfd sp!, {r4, r5}
-+ mar acc0, r4, r5
-+#endif
- ldr ip, [sp], #4
- mcr p15, 0, r2, c3, c0 @ Set domain register
- msr spsr, ip @ Save tasks CPSR into SPSR for this return
---- linux-2.4.27/arch/arm/kernel/head-armv.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/kernel/head-armv.S
-@@ -30,6 +30,7 @@
- *
- * swapper_pg_dir, pgtbl and krnladr are all closely related.
- */
-+#ifndef CONFIG_XIP_KERNEL
- #if (TEXTADDR & 0xffff) != 0x8000
- #error TEXTADDR must start at 0xXXXX8000
- #endif
-@@ -41,6 +42,26 @@
- adr \reg, stext
- sub \reg, \reg, #0x4000
- .endm
-+#else
-+#if (DATAADDR & 0xffff) != 0x8000
-+#error DATAADDR must start at 0xXXXX8000
-+#endif
-+
-+#define PAGE_OFFSET 0xc0000000
-+#ifdef CONFIG_ARCH_LUBBOCK
-+#define PHYS_OFFSET 0xa0000000
-+#elif CONFIG_ARCH_OMAP
-+#define PHYS_OFFSET 0x10000000
-+#endif
-+
-+ .globl SYMBOL_NAME(swapper_pg_dir)
-+ .equ SYMBOL_NAME(swapper_pg_dir), DATAADDR - 0x4000
-+
-+ .macro pgtbl, reg, rambase
-+ ldr \reg, PGTBL
-+ add \reg, \reg, #PHYS_OFFSET - PAGE_OFFSET
-+ .endm
-+#endif
-
- /*
- * Since the page table is closely related to the kernel start address, we
-@@ -131,6 +152,32 @@
- mov r1, #MACH_TYPE_L7200
- #endif
-
-+#ifdef CONFIG_XIP_KERNEL
-+
-+#if defined(CONFIG_ARCH_LUBBOCK)
-+ mov r1, #MACH_TYPE_LUBBOCK
-+#endif
-+
-+ @ Data cache might be active.
-+ @ Be sure to flush kernel binary out of the cache,
-+ @ whatever state it is, before it is turned off.
-+ @ This is done by fetching through currently executed
-+ @ memory to be sure we hit the same cache.
-+ bic r2, pc, #0x1f
-+ add r3, r2, #0x10000 @ 64 kb is quite enough...
-+1: ldr r0, [r2], #32
-+ teq r2, r3
-+ bne 1b
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches
-+
-+ @ disabling MMU and caches
-+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
-+ bic r0, r0, #0x05 @ clear DC, MMU
-+ bic r0, r0, #0x1000 @ clear Icache
-+ mcr p15, 0, r0, c1, c0, 0
-+#endif
-+
- mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
- msr cpsr_c, r0 @ and all irqs disabled
- bl __lookup_processor_type
-@@ -179,6 +226,17 @@
- */
- .align 5
- __mmap_switched:
-+#ifdef CONFIG_XIP_KERNEL
-+ ldr r3, ETEXT @ data section copy
-+ ldr r4, SDATA
-+ ldr r5, EDATA
-+1:
-+ ldr r6, [r3], #4
-+ str r6, [r4], #4
-+ cmp r4, r5
-+ blo 1b
-+#endif
-+
- adr r3, __switch_data + 4
- ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
- @ sp = stack pointer
-@@ -233,6 +291,8 @@
- teq r0, r2
- bne 1b
-
-+#ifndef CONFIG_XIP_KERNEL
-+
- /*
- * Create identity mapping for first MB of kernel to
- * cater for the MMU enable. This identity mapping
-@@ -271,6 +331,43 @@
- add r3, r8, r2 @ flags + rambase
- str r3, [r0]
-
-+#else /* CONFIG_XIP_KERNEL */
-+
-+ mov r3, pc, lsr #20
-+ mov r3, r3, lsl #20 @ phys kernel start
-+
-+ add r0, r4, r3, lsr #18
-+ orr r3, r3, r8
-+ str r3, [r0]
-+
-+ mov r0, #TEXTADDR & 0xff000000
-+ add r0, r0, #TEXTADDR & 0x00f00000 @ virt kernel start
-+ add r0, r4, r0, lsr #18
-+ add r2, r3, #4 << 20 @ kernel + 4MB
-+
-+1:
-+ str r3, [r0], #4
-+ add r3, r3, #1 << 20
-+ cmp r3, r2
-+ bne 1b
-+
-+ bic r3, r4, #0x000ff000 @ ram start
-+ add r0, r4, r3, lsr #18
-+ orr r3, r3, r8
-+ str r3, [r0], #4
-+
-+ add r0, r3, #PAGE_OFFSET - PHYS_OFFSET
-+ add r0, r4, r0, lsr #18
-+ add r2, r3, #4 << 20 @ ram + 4MB
-+
-+1:
-+ str r3, [r0], #4
-+ add r3, r3, #1 << 20
-+ cmp r3, r2
-+ bne 1b
-+
-+#endif /* CONFIG_XIP_KERNEL */
-+
- bic r8, r8, #0x0c @ turn off cacheable
- @ and bufferable bits
- #ifdef CONFIG_DEBUG_LL
-@@ -433,3 +530,13 @@
- mov pc, lr
- 2: ldmib r4, {r5, r6, r7} @ found, get results
- mov pc, lr
-+
-+#ifdef CONFIG_XIP_KERNEL
-+
-+PGTBL: .long SYMBOL_NAME(swapper_pg_dir)
-+
-+ETEXT: .long SYMBOL_NAME(_endtext)
-+SDATA: .long SYMBOL_NAME(_sdata)
-+EDATA: .long SYMBOL_NAME(__bss_start)
-+
-+#endif
---- linux-2.4.27/arch/arm/kernel/setup.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/kernel/setup.c
-@@ -55,6 +55,10 @@
- extern void reboot_setup(char *str);
- extern int root_mountflags;
- extern int _stext, _text, _etext, _edata, _end;
-+#ifdef CONFIG_XIP_KERNEL
-+extern int _endtext, _sdata;
-+#endif
-+
-
- unsigned int processor_id;
- unsigned int __machine_arch_type;
-@@ -105,6 +109,109 @@
- #define lp1 io_res[1]
- #define lp2 io_res[2]
-
-+#ifdef CONFIG_CPU_32
-+static const char *cache_types[16] = {
-+ "write-through",
-+ "write-back",
-+ "write-back",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "write-back",
-+ "write-back",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+static const char *cache_clean[16] = {
-+ "not required",
-+ "read-block",
-+ "cp15 c7 ops",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "cp15 c7 ops",
-+ "cp15 c7 ops",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+static const char *cache_lockdown[16] = {
-+ "not supported",
-+ "not supported",
-+ "not supported",
-+ "undefined 3",
-+ "undefined 4",
-+ "undefined 5",
-+ "format A",
-+ "format B",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15",
-+};
-+
-+#define CACHE_TYPE(x) (((x) >> 25) & 15)
-+#define CACHE_S(x) ((x) & (1 << 24))
-+#define CACHE_DSIZE(x) (((x) >> 12) & 4095) /* only if S=1 */
-+#define CACHE_ISIZE(x) ((x) & 4095)
-+
-+#define CACHE_SIZE(y) (((y) >> 6) & 7)
-+#define CACHE_ASSOC(y) (((y) >> 3) & 7)
-+#define CACHE_M(y) ((y) & (1 << 2))
-+#define CACHE_LINE(y) ((y) & 3)
-+
-+static inline void dump_cache(const char *prefix, unsigned int cache)
-+{
-+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-+
-+ printk("%s size %dK associativity %d line length %d sets %d\n",
-+ prefix,
-+ mult << (8 + CACHE_SIZE(cache)),
-+ (mult << CACHE_ASSOC(cache)) >> 1,
-+ 8 << CACHE_LINE(cache),
-+ 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-+ CACHE_LINE(cache)));
-+}
-+
-+static inline void dump_cpu_cache_id(void)
-+{
-+ unsigned int cache_info;
-+
-+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
-+
-+ if (cache_info == processor_id)
-+ return;
-+
-+ printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
-+ if (CACHE_S(cache_info)) {
-+ dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
-+ dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
-+ } else {
-+ dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
-+ }
-+}
-+
-+#else
-+#define dump_cpu_cache_id() do { } while (0)
-+#endif
-+
- static void __init setup_processor(void)
- {
- extern struct proc_info_list __proc_info_begin, __proc_info_end;
-@@ -272,7 +379,11 @@
-
- kernel_code.start = __virt_to_phys(init_mm.start_code);
- kernel_code.end = __virt_to_phys(init_mm.end_code - 1);
-+#ifndef CONFIG_XIP_KERNEL
- kernel_data.start = __virt_to_phys(init_mm.end_code);
-+#else
-+ kernel_data.start = __virt_to_phys(init_mm.start_data);
-+#endif
- kernel_data.end = __virt_to_phys(init_mm.brk - 1);
-
- for (i = 0; i < mi->nr_banks; i++) {
-@@ -531,7 +642,12 @@
- }
-
- init_mm.start_code = (unsigned long) &_text;
-+#ifndef CONFIG_XIP_KERNEL
- init_mm.end_code = (unsigned long) &_etext;
-+#else
-+ init_mm.end_code = (unsigned long) &_endtext;
-+ init_mm.start_data = (unsigned long) &_sdata;
-+#endif
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_end;
-
-@@ -568,6 +684,41 @@
- NULL
- };
-
-+static const char *proc_arch[16] = {
-+ "undefined 0",
-+ "4",
-+ "4T",
-+ "5",
-+ "5T",
-+ "5TE",
-+ "undefined 6",
-+ "undefined 7",
-+ "undefined 8",
-+ "undefined 9",
-+ "undefined 10",
-+ "undefined 11",
-+ "undefined 12",
-+ "undefined 13",
-+ "undefined 14",
-+ "undefined 15"
-+};
-+
-+static void
-+c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
-+{
-+ unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-+
-+ seq_printf(m, "%s size\t\t: %d\n"
-+ "%s assoc\t\t: %d\n"
-+ "%s line length\t: %d\n"
-+ "%s sets\t\t: %d\n",
-+ type, mult << (8 + CACHE_SIZE(cache)),
-+ type, (mult << CACHE_ASSOC(cache)) >> 1,
-+ type, 8 << CACHE_LINE(cache),
-+ type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-+ CACHE_LINE(cache)));
-+}
-+
- static int c_show(struct seq_file *m, void *v)
- {
- int i;
-@@ -586,7 +737,60 @@
- if (elf_hwcap & (1 << i))
- seq_printf(m, "%s ", hwcap_str[i]);
-
-- seq_puts(m, "\n\n");
-+ seq_puts(m, "\n");
-+
-+ if ((processor_id & 0x0000f000) == 0x00000000) {
-+ /* pre-ARM7 */
-+ seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
-+ } else if ((processor_id & 0x0000f000) == 0x00007000) {
-+ /* ARM7 */
-+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
-+ "CPU architecture: %s\n"
-+ "CPU variant\t: 0x%02x\n"
-+ "CPU part\t: 0x%03x\n",
-+ processor_id >> 24,
-+ processor_id & (1 << 23) ? "4T" : "3",
-+ (processor_id >> 16) & 127,
-+ (processor_id >> 4) & 0xfff);
-+ } else {
-+ /* post-ARM7 */
-+ seq_printf(m, "CPU implementor\t: 0x%02x\n"
-+ "CPU architecture: %s\n"
-+ "CPU variant\t: 0x%x\n"
-+ "CPU part\t: 0x%03x\n",
-+ processor_id >> 24,
-+ proc_arch[(processor_id >> 16) & 15],
-+ (processor_id >> 20) & 15,
-+ (processor_id >> 4) & 0xfff);
-+ }
-+ seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);
-+
-+#ifdef CONFIG_CPU_32
-+ {
-+ unsigned int cache_info;
-+
-+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
-+ if (cache_info != processor_id) {
-+ seq_printf(m, "Cache type\t: %s\n"
-+ "Cache clean\t: %s\n"
-+ "Cache lockdown\t: %s\n"
-+ "Cache unified\t: %s\n",
-+ cache_types[CACHE_TYPE(cache_info)],
-+ cache_clean[CACHE_TYPE(cache_info)],
-+ cache_lockdown[CACHE_TYPE(cache_info)],
-+ CACHE_S(cache_info) ? "harvard" : "unified");
-+
-+ if (CACHE_S(cache_info)) {
-+ c_show_cache(m, "I", CACHE_ISIZE(cache_info));
-+ c_show_cache(m, "D", CACHE_DSIZE(cache_info));
-+ } else {
-+ c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
-+ }
-+ }
-+ }
-+#endif
-+
-+ seq_puts(m, "\n");
-
- seq_printf(m, "Hardware\t: %s\n", machine_name);
- seq_printf(m, "Revision\t: %04x\n", system_rev);
---- linux-2.4.27/arch/arm/lib/copy_page.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/lib/copy_page.S
-@@ -13,6 +13,8 @@
- #include <asm/assembler.h>
- #include <asm/constants.h>
-
-+#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
-+
- .text
- .align 5
- /*
-@@ -23,9 +25,13 @@
- */
- ENTRY(copy_page)
- stmfd sp!, {r4, lr} @ 2
-- mov r2, #PAGE_SZ/64 @ 1
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r1, #32] )
-+ mov r2, #COPY_COUNT @ 1
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
--1: stmia r0!, {r3, r4, ip, lr} @ 4
-+1: PLD( pld [r1, #64] )
-+ PLD( pld [r1, #96] )
-+2: stmia r0!, {r3, r4, ip, lr} @ 4
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
- stmia r0!, {r3, r4, ip, lr} @ 4
- ldmia r1!, {r3, r4, ip, lr} @ 4+1
-@@ -33,6 +39,8 @@
- ldmia r1!, {r3, r4, ip, lr} @ 4
- subs r2, r2, #1 @ 1
- stmia r0!, {r3, r4, ip, lr} @ 4
-- ldmneia r1!, {r3, r4, ip, lr} @ 4
-- bne 1b @ 1
-+ ldmgtia r1!, {r3, r4, ip, lr} @ 4
-+ bgt 1b @ 1
-+ PLD( ldmeqia r1!, {r3, r4, ip, lr} )
-+ PLD( beq 2b )
- LOADREGS(fd, sp!, {r4, pc}) @ 3
---- linux-2.4.27/arch/arm/lib/findbit.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/lib/findbit.S
-@@ -43,7 +43,15 @@
- /*
- * One or more bits in the LSB of r3 are assumed to be set.
- */
--.found: tst r3, #0x0f
-+.found:
-+#if __LINUX_ARM_ARCH__ >= 5
-+ rsb r1, r3, #0
-+ and r3, r3, r1
-+ clz r3, r3
-+ rsb r3, r3, #31
-+ add r0, r2, r3
-+#else
-+ tst r3, #0x0f
- addeq r2, r2, #4
- movne r3, r3, lsl #4
- tst r3, #0x30
-@@ -52,5 +60,6 @@
- tst r3, #0x40
- addeq r2, r2, #1
- mov r0, r2
-+#endif
- RETINSTR(mov,pc,lr)
-
---- linux-2.4.27/arch/arm/lib/getuser.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/lib/getuser.S
-@@ -18,7 +18,7 @@
- * Inputs: r0 contains the address
- * Outputs: r0 is the error code
- * r1, r2 contains the zero-extended value
-- * lr corrupted
-+ * ip, lr corrupted
- *
- * No other registers must be altered. (see include/asm-arm/uaccess.h
- * for specific ASM register usage).
-@@ -42,14 +42,14 @@
-
- .global __get_user_2
- __get_user_2:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #2
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #2
-+ cmp r0, ip
- 2: ldrlsbt r1, [r0], #1
--3: ldrlsbt r2, [r0]
-- orrls r1, r1, r2, lsl #8
-+3: ldrlsbt ip, [r0]
-+ orrls r1, r1, ip, lsl #8
- movls r0, #0
- movls pc, lr
- b __get_user_bad
---- linux-2.4.27/arch/arm/lib/memcpy.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/lib/memcpy.S
-@@ -8,6 +8,9 @@
- * published by the Free Software Foundation.
- *
- * ASM optimised string functions
-+ *
-+ * Big Endian, prefetching and code factorization provided by Nicolas Pitre:
-+ * Copyright (C) 2002-2003 MontaVista Software, Inc.
- */
- #include <linux/linkage.h>
- #include <asm/assembler.h>
-@@ -27,15 +30,16 @@
-
- /*
- * Prototype: void memcpy(void *to,const void *from,unsigned long n);
-- * ARM3: cant use memcopy here!!!
- */
- ENTRY(memcpy)
- ENTRY(memmove)
- ENTER
-- cmp r1, r0
-- bcc 19f
-+ subs ip, r0, r1
-+ cmphi r2, ip
-+ bhi 18f
- subs r2, r2, #4
- blt 6f
-+ PLD( pld [r1, #0] )
- ands ip, r0, #3
- bne 7f
- ands ip, r1, #3
-@@ -43,29 +47,59 @@
-
- 1: subs r2, r2, #8
- blt 5f
-- subs r2, r2, #0x14
-- blt 3f
--2: ldmia r1!,{r3 - r9, ip}
-- stmia r0!,{r3 - r9, ip}
-+ subs r2, r2, #20
-+ blt 4f
-+
-+ PLD( subs r2, r2, #65 )
-+ PLD( blt 3f )
-+ PLD( pld [r1, #32] )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #64] )
-+ PLD( beq 2f )
-+ PLD( rsb ip, ip, #32 )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #96] )
-+ PLD( blt 2f )
-+ PLD( cmp ip, #16 )
-+ PLD( sub r2, r2, ip )
-+ PLD( ldmgeia r1!, {r3 - r6} )
-+ PLD( stmgeia r0!, {r3 - r6} )
-+ PLD( beq 2f )
-+ PLD( and ip, ip, #15 )
-+ PLD( cmp ip, #8 )
-+ PLD( ldr r3, [r1], #4 )
-+ PLD( ldrge r4, [r1], #4 )
-+ PLD( ldrgt r5, [r1], #4 )
-+ PLD( str r3, [r0], #4 )
-+ PLD( strge r4, [r0], #4 )
-+ PLD( strgt r5, [r0], #4 )
-+
-+2: PLD( pld [r1, #96] )
-+3: ldmia r1!, {r3 - r9, ip}
- subs r2, r2, #32
-+ stmia r0!, {r3 - r9, ip}
- bge 2b
-- cmn r2, #16
-+ PLD( cmn r2, #65 )
-+ PLD( bge 3b )
-+ PLD( add r2, r2, #65 )
-+4: cmn r2, #16
- ldmgeia r1!, {r3 - r6}
-+ subge r2, r2, #16
- stmgeia r0!, {r3 - r6}
-- subge r2, r2, #0x10
--3: adds r2, r2, #0x14
--4: ldmgeia r1!, {r3 - r5}
-+ adds r2, r2, #20
-+ ldmgeia r1!, {r3 - r5}
-+ subge r2, r2, #12
- stmgeia r0!, {r3 - r5}
-- subges r2, r2, #12
-- bge 4b
- 5: adds r2, r2, #8
- blt 6f
- subs r2, r2, #4
- ldrlt r3, [r1], #4
- ldmgeia r1!, {r4, r5}
-+ subge r2, r2, #4
- strlt r3, [r0], #4
- stmgeia r0!, {r4, r5}
-- subge r2, r2, #4
-
- 6: adds r2, r2, #4
- EXITEQ
-@@ -92,122 +126,175 @@
- beq 1b
-
- 8: bic r1, r1, #3
-- ldr r7, [r1], #4
- cmp ip, #2
-- bgt 15f
-- beq 11f
-+ ldr lr, [r1], #4
-+ bgt 17f
-+ beq 16f
-+
-+
-+ .macro forward_copy_shift pull push
-+
- cmp r2, #12
-- blt 10f
-- sub r2, r2, #12
--9: mov r3, r7, lsr #8
-- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-+ PLD( pld [r1, #0] )
-+ blt 14f
-+ subs r2, r2, #28
-+ blt 12f
-+
-+ PLD( subs r2, r2, #97 )
-+ PLD( blt 11f )
-+ PLD( pld [r1, #32] )
-+
-+ PLD( @ cache alignment )
-+ PLD( rsb ip, r1, #36 )
-+ PLD( pld [r1, #64] )
-+ PLD( ands ip, ip, #31 )
-+ PLD( pld [r1, #96] )
-+ PLD( beq 10f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #128] )
-+ PLD( blt 10f )
-+ PLD( sub r2, r2, ip )
-+9: PLD( mov r3, lr, pull #\pull )
-+ PLD( ldr lr, [r1], #4 )
-+ PLD( subs ip, ip, #4 )
-+ PLD( orr r3, r3, lr, push #\push )
-+ PLD( str r3, [r0], #4 )
-+ PLD( bgt 9b )
-+
-+10: PLD( pld [r1, #128] )
-+11: mov r3, lr, pull #\pull
-+ ldmia r1!, {r4 - r9, ip, lr}
-+ subs r2, r2, #32
-+ orr r3, r3, r4, push #\push
-+ mov r4, r4, pull #\pull
-+ orr r4, r4, r5, push #\push
-+ mov r5, r5, pull #\pull
-+ orr r5, r5, r6, push #\push
-+ mov r6, r6, pull #\pull
-+ orr r6, r6, r7, push #\push
-+ mov r7, r7, pull #\pull
-+ orr r7, r7, r8, push #\push
-+ mov r8, r8, pull #\pull
-+ orr r8, r8, r9, push #\push
-+ mov r9, r9, pull #\pull
-+ orr r9, r9, ip, push #\push
-+ mov ip, ip, pull #\pull
-+ orr ip, ip, lr, push #\push
-+ stmia r0!, {r3 - r9, ip}
-+ bge 10b
-+ PLD( cmn r2, #97 )
-+ PLD( bge 11b )
-+ PLD( add r2, r2, #97 )
-+ cmn r2, #16
-+ blt 13f
-+12: mov r3, lr, pull #\pull
-+ ldmia r1!, {r4 - r6, lr}
-+ sub r2, r2, #16
-+ orr r3, r3, r4, push #\push
-+ mov r4, r4, pull #\pull
-+ orr r4, r4, r5, push #\push
-+ mov r5, r5, pull #\pull
-+ orr r5, r5, r6, push #\push
-+ mov r6, r6, pull #\pull
-+ orr r6, r6, lr, push #\push
- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 9b
-- adds r2, r2, #12
-- blt 100f
--10: mov r3, r7, lsr #8
-- ldr r7, [r1], #4
-+13: adds r2, r2, #28
-+ blt 15f
-+14: mov r3, lr, pull #\pull
-+ ldr lr, [r1], #4
- subs r2, r2, #4
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, lr, push #\push
- str r3, [r0], #4
-- bge 10b
--100: sub r1, r1, #3
-+ bge 14b
-+15:
-+ .endm
-+
-+
-+ forward_copy_shift pull=8 push=24
-+ sub r1, r1, #3
- b 6b
-
--11: cmp r2, #12
-- blt 13f /* */
-- sub r2, r2, #12
--12: mov r3, r7, lsr #16
-- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7,LSL#16
-- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 12b
-- adds r2, r2, #12
-- blt 14f
--13: mov r3, r7, lsr #16
-- ldr r7, [r1], #4
-- subs r2, r2, #4
-- orr r3, r3, r7, lsl #16
-- str r3, [r0], #4
-- bge 13b
--14: sub r1, r1, #2
-+16: forward_copy_shift pull=16 push=16
-+ sub r1, r1, #2
- b 6b
-
--15: cmp r2, #12
-- blt 17f
-- sub r2, r2, #12
--16: mov r3, r7, lsr #24
-- ldmia r1!,{r4 - r7}
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-- stmia r0!, {r3 - r6}
-- subs r2, r2, #16
-- bge 16b
-- adds r2, r2, #12
-- blt 18f
--17: mov r3, r7, lsr #24
-- ldr r7, [r1], #4
-- subs r2, r2, #4
-- orr r3, r3, r7, lsl#8
-- str r3, [r0], #4
-- bge 17b
--18: sub r1, r1, #1
-+17: forward_copy_shift pull=24 push=8
-+ sub r1, r1, #1
- b 6b
-
-
--19: add r1, r1, r2
-+18: add r1, r1, r2
- add r0, r0, r2
- subs r2, r2, #4
- blt 24f
-+ PLD( pld [r1, #-4] )
- ands ip, r0, #3
- bne 25f
- ands ip, r1, #3
- bne 26f
-
--20: subs r2, r2, #8
-+19: subs r2, r2, #8
- blt 23f
-- subs r2, r2, #0x14
-+ subs r2, r2, #20
- blt 22f
--21: ldmdb r1!, {r3 - r9, ip}
-- stmdb r0!, {r3 - r9, ip}
-+
-+ PLD( subs r2, r2, #96 )
-+ PLD( pld [r1, #-32] )
-+ PLD( blt 21f )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #-64] )
-+ PLD( beq 20f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #-96] )
-+ PLD( blt 20f )
-+ PLD( cmp ip, #16 )
-+ PLD( sub r2, r2, ip )
-+ PLD( ldmgedb r1!, {r3 - r6} )
-+ PLD( stmgedb r0!, {r3 - r6} )
-+ PLD( beq 20f )
-+ PLD( and ip, ip, #15 )
-+ PLD( cmp ip, #8 )
-+ PLD( ldr r3, [r1, #-4]! )
-+ PLD( ldrge r4, [r1, #-4]! )
-+ PLD( ldrgt r5, [r1, #-4]! )
-+ PLD( str r3, [r0, #-4]! )
-+ PLD( strge r4, [r0, #-4]! )
-+ PLD( strgt r5, [r0, #-4]! )
-+
-+20: PLD( pld [r1, #-96] )
-+ PLD( pld [r1, #-128] )
-+21: ldmdb r1!, {r3 - r6}
- subs r2, r2, #32
-- bge 21b
--22: cmn r2, #16
-+ stmdb r0!, {r3 - r6}
-+ ldmdb r1!, {r3 - r6}
-+ stmgedb r0!, {r3 - r6}
- ldmgedb r1!, {r3 - r6}
- stmgedb r0!, {r3 - r6}
-+ ldmgedb r1!, {r3 - r6}
-+ subges r2, r2, #32
-+ stmdb r0!, {r3 - r6}
-+ bge 20b
-+ PLD( cmn r2, #96 )
-+ PLD( bge 21b )
-+ PLD( add r2, r2, #96 )
-+22: cmn r2, #16
-+ ldmgedb r1!, {r3 - r6}
- subge r2, r2, #16
-+ stmgedb r0!, {r3 - r6}
- adds r2, r2, #20
- ldmgedb r1!, {r3 - r5}
-- stmgedb r0!, {r3 - r5}
- subge r2, r2, #12
-+ stmgedb r0!, {r3 - r5}
- 23: adds r2, r2, #8
- blt 24f
- subs r2, r2, #4
- ldrlt r3, [r1, #-4]!
- ldmgedb r1!, {r4, r5}
-+ subge r2, r2, #4
- strlt r3, [r0, #-4]!
- stmgedb r0!, {r4, r5}
-- subge r2, r2, #4
-
- 24: adds r2, r2, #4
- EXITEQ
-@@ -230,89 +317,101 @@
- subs r2, r2, ip
- blt 24b
- ands ip, r1, #3
-- beq 20b
-+ beq 19b
-
- 26: bic r1, r1, #3
-- ldr r3, [r1], #0
- cmp ip, #2
-- blt 34f
-- beq 30f
-- cmp r2, #12
-- blt 28f
-- sub r2, r2, #12
--27: mov r7, r3, lsl #8
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #24
-- mov r6, r6, lsl #8
-- orr r6, r6, r5, lsr #24
-- mov r5, r5, lsl #8
-- orr r5, r5, r4, lsr #24
-- mov r4, r4, lsl #8
-- orr r4, r4, r3, lsr #24
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 27b
-- adds r2, r2, #12
-- blt 29f
--28: mov ip, r3, lsl #8
-- ldr r3, [r1, #-4]!
-- subs r2, r2, #4
-- orr ip, ip, r3, lsr #24
-- str ip, [r0, #-4]!
-- bge 28b
--29: add r1, r1, #3
-- b 24b
-+ ldr r3, [r1], #0
-+ blt 35f
-+ beq 34f
-
--30: cmp r2, #12
-+
-+ .macro backward_copy_shift push pull
-+
-+ cmp r2, #12
-+ PLD( pld [r1, #-4] )
- blt 32f
-- sub r2, r2, #12
--31: mov r7, r3, lsl #16
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #16
-- mov r6, r6, lsl #16
-- orr r6, r6, r5, lsr #16
-- mov r5, r5, lsl #16
-- orr r5, r5, r4, lsr #16
-- mov r4, r4, lsl #16
-- orr r4, r4, r3, lsr #16
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 31b
-- adds r2, r2, #12
-+ subs r2, r2, #28
-+ blt 30f
-+
-+ PLD( subs r2, r2, #96 )
-+ PLD( pld [r1, #-32] )
-+ PLD( blt 29f )
-+ PLD( pld [r1, #-64] )
-+
-+ PLD( @ cache alignment )
-+ PLD( ands ip, r1, #31 )
-+ PLD( pld [r1, #-96] )
-+ PLD( beq 28f )
-+ PLD( cmp r2, ip )
-+ PLD( pld [r1, #-128] )
-+ PLD( blt 28f )
-+ PLD( sub r2, r2, ip )
-+27: PLD( mov r4, r3, push #\push )
-+ PLD( ldr r3, [r1, #-4]! )
-+ PLD( subs ip, ip, #4 )
-+ PLD( orr r4, r4, r3, pull #\pull )
-+ PLD( str r4, [r0, #-4]! )
-+ PLD( bgt 27b )
-+
-+28: PLD( pld [r1, #-128] )
-+29: mov lr, r3, push #\push
-+ ldmdb r1!, {r3 - r9, ip}
-+ subs r2, r2, #32
-+ orr lr, lr, ip, pull #\pull
-+ mov ip, ip, push #\push
-+ orr ip, ip, r9, pull #\pull
-+ mov r9, r9, push #\push
-+ orr r9, r9, r8, pull #\pull
-+ mov r8, r8, push #\push
-+ orr r8, r8, r7, pull #\pull
-+ mov r7, r7, push #\push
-+ orr r7, r7, r6, pull #\pull
-+ mov r6, r6, push #\push
-+ orr r6, r6, r5, pull #\pull
-+ mov r5, r5, push #\push
-+ orr r5, r5, r4, pull #\pull
-+ mov r4, r4, push #\push
-+ orr r4, r4, r3, pull #\pull
-+ stmdb r0!, {r4 - r9, ip, lr}
-+ bge 28b
-+ PLD( cmn r2, #96 )
-+ PLD( bge 29b )
-+ PLD( add r2, r2, #96 )
-+ cmn r2, #16
-+ blt 31f
-+30: mov r7, r3, push #\push
-+ ldmdb r1!, {r3 - r6}
-+ sub r2, r2, #16
-+ orr r7, r7, r6, pull #\pull
-+ mov r6, r6, push #\push
-+ orr r6, r6, r5, pull #\pull
-+ mov r5, r5, push #\push
-+ orr r5, r5, r4, pull #\pull
-+ mov r4, r4, push #\push
-+ orr r4, r4, r3, pull #\pull
-+ stmdb r0!, {r4 - r7}
-+31: adds r2, r2, #28
- blt 33f
--32: mov ip, r3, lsl #16
-+32: mov r4, r3, push #\push
- ldr r3, [r1, #-4]!
- subs r2, r2, #4
-- orr ip, ip, r3, lsr #16
-- str ip, [r0, #-4]!
-+ orr r4, r4, r3, pull #\pull
-+ str r4, [r0, #-4]!
- bge 32b
--33: add r1, r1, #2
-+33:
-+ .endm
-+
-+
-+ backward_copy_shift push=8 pull=24
-+ add r1, r1, #3
- b 24b
-
--34: cmp r2, #12
-- blt 36f
-- sub r2, r2, #12
--35: mov r7, r3, lsl #24
-- ldmdb r1!, {r3, r4, r5, r6}
-- orr r7, r7, r6, lsr #8
-- mov r6, r6, lsl #24
-- orr r6, r6, r5, lsr #8
-- mov r5, r5, lsl #24
-- orr r5, r5, r4, lsr #8
-- mov r4, r4, lsl #24
-- orr r4, r4, r3, lsr #8
-- stmdb r0!, {r4, r5, r6, r7}
-- subs r2, r2, #16
-- bge 35b
-- adds r2, r2, #12
-- blt 37f
--36: mov ip, r3, lsl #24
-- ldr r3, [r1, #-4]!
-- subs r2, r2, #4
-- orr ip, ip, r3, lsr #8
-- str ip, [r0, #-4]!
-- bge 36b
--37: add r1, r1, #1
-+34: backward_copy_shift push=16 pull=16
-+ add r1, r1, #2
-+ b 24b
-+
-+35: backward_copy_shift push=24 pull=8
-+ add r1, r1, #1
- b 24b
-
-- .align
---- linux-2.4.27/arch/arm/lib/uaccess.S~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/lib/uaccess.S
-@@ -43,6 +43,8 @@
- stmfd sp!, {r2, r4 - r7, lr}
- cmp r2, #4
- blt .c2u_not_enough
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r0, #0] )
- ands ip, r0, #3
- bne .c2u_dest_not_aligned
- .c2u_dest_aligned:
-@@ -71,13 +73,26 @@
- sub r2, r2, ip
- subs ip, ip, #32
- blt .c2u_0rem8lp
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-+ PLD( subs ip, ip, #64 )
-+ PLD( blt .c2u_0cpynopld )
-+ PLD( pld [r1, #60] )
-+ PLD( pld [r0, #60] )
-
--.c2u_0cpy8lp: ldmia r1!, {r3 - r6}
-+.c2u_0cpy8lp:
-+ PLD( pld [r1, #92] )
-+ PLD( pld [r0, #92] )
-+.c2u_0cpynopld: ldmia r1!, {r3 - r6}
- stmia r0!, {r3 - r6} @ Shouldnt fault
- ldmia r1!, {r3 - r6}
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #32
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_0cpy8lp
-+ PLD( cmn ip, #64 )
-+ PLD( bge .c2u_0cpynopld )
-+ PLD( add ip, ip, #64 )
-+
- .c2u_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6}
- stmgeia r0!, {r3 - r6} @ Shouldnt fault
-@@ -115,9 +130,9 @@
- .c2u_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_1nowords
-- mov r3, r7, lsr #8
-+ mov r3, r7, pull #8
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, r7, push #24
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -128,50 +143,63 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_1rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_1cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_1cpy8lp: mov r3, r7, lsr #8
-+.c2u_1cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_1cpynopld: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #24
-+ mov r4, r4, pull #8
-+ orr r4, r4, r5, push #24
-+ mov r5, r5, pull #8
-+ orr r5, r5, r6, push #24
-+ mov r6, r6, pull #8
-+ orr r6, r6, r7, push #24
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_1cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_1cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_1rem8lp: tst ip, #8
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #24
-- movne r4, r4, lsr #8
-- orrne r4, r4, r7, lsl #24
-+ orrne r3, r3, r4, push #24
-+ movne r4, r4, pull #8
-+ orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #24
-+ orrne r3, r3, r7, push #24
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_1fupi
--.c2u_1nowords: mov r3, r7, lsr #8
-+.c2u_1nowords: mov r3, r7, lsr #byte(1)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(2)
- USER( strgebt r3, [r0], #1) @ May fault
-- movgt r3, r3, lsr #8
-+ movgt r3, r7, lsr #byte(3)
- USER( strgtbt r3, [r0], #1) @ May fault
- b .c2u_finished
-
- .c2u_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_2nowords
-- mov r3, r7, lsr #16
-+ mov r3, r7, pull #16
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #16
-+ orr r3, r3, r7, push #16
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -182,39 +210,52 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_2rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_2cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_2cpy8lp: mov r3, r7, lsr #16
-+.c2u_2cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_2cpynopld: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7, lsl #16
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #16
-+ mov r4, r4, pull #16
-+ orr r4, r4, r5, push #16
-+ mov r5, r5, pull #16
-+ orr r5, r5, r6, push #16
-+ mov r6, r6, pull #16
-+ orr r6, r6, r7, push #16
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_2cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_2cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_2rem8lp: tst ip, #8
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #16
-- movne r4, r4, lsr #16
-- orrne r4, r4, r7, lsl #16
-+ orrne r3, r3, r4, push #16
-+ movne r4, r4, pull #16
-+ orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #16
-+ orrne r3, r3, r7, push #16
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_2fupi
--.c2u_2nowords: mov r3, r7, lsr #16
-+.c2u_2nowords: mov r3, r7, lsr #byte(2)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(3)
- USER( strgebt r3, [r0], #1) @ May fault
- ldrgtb r3, [r1], #0
- USER( strgtbt r3, [r0], #1) @ May fault
-@@ -223,9 +264,9 @@
- .c2u_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .c2u_3nowords
-- mov r3, r7, lsr #24
-+ mov r3, r7, pull #24
- ldr r7, [r1], #4
-- orr r3, r3, r7, lsl #8
-+ orr r3, r3, r7, push #8
- USER( strt r3, [r0], #4) @ May fault
- mov ip, r0, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -236,41 +277,54 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .c2u_3rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .c2u_3cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.c2u_3cpy8lp: mov r3, r7, lsr #24
-+.c2u_3cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.c2u_3cpynopld: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7}
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-- stmia r0!, {r3 - r6} @ Shouldnt fault
- subs ip, ip, #16
-+ orr r3, r3, r4, push #8
-+ mov r4, r4, pull #24
-+ orr r4, r4, r5, push #8
-+ mov r5, r5, pull #24
-+ orr r5, r5, r6, push #8
-+ mov r6, r6, pull #24
-+ orr r6, r6, r7, push #8
-+ stmia r0!, {r3 - r6} @ Shouldnt fault
- bpl .c2u_3cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .c2u_3cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .c2u_3rem8lp: tst ip, #8
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldmneia r1!, {r4, r7}
-- orrne r3, r3, r4, lsl #8
-- movne r4, r4, lsr #24
-- orrne r4, r4, r7, lsl #8
-+ orrne r3, r3, r4, push #8
-+ movne r4, r4, pull #24
-+ orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4} @ Shouldnt fault
- tst ip, #4
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldrne r7, [r1], #4
-- orrne r3, r3, r7, lsl #8
-+ orrne r3, r3, r7, push #8
- strnet r3, [r0], #4 @ Shouldnt fault
- ands ip, ip, #3
- beq .c2u_3fupi
--.c2u_3nowords: mov r3, r7, lsr #24
-+.c2u_3nowords: mov r3, r7, lsr #byte(3)
- teq ip, #0
- beq .c2u_finished
- cmp ip, #2
- USER( strbt r3, [r0], #1) @ May fault
-- ldrge r3, [r1], #0
-+ ldrgeb r3, [r1], #1
- USER( strgebt r3, [r0], #1) @ May fault
-- movgt r3, r3, lsr #8
-+ ldrgtb r3, [r1], #0
- USER( strgtbt r3, [r0], #1) @ May fault
- b .c2u_finished
-
-@@ -302,6 +356,8 @@
- stmfd sp!, {r0, r2, r4 - r7, lr}
- cmp r2, #4
- blt .cfu_not_enough
-+ PLD( pld [r1, #0] )
-+ PLD( pld [r0, #0] )
- ands ip, r0, #3
- bne .cfu_dest_not_aligned
- .cfu_dest_aligned:
-@@ -329,13 +385,26 @@
- sub r2, r2, ip
- subs ip, ip, #32
- blt .cfu_0rem8lp
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-+ PLD( subs ip, ip, #64 )
-+ PLD( blt .cfu_0cpynopld )
-+ PLD( pld [r1, #60] )
-+ PLD( pld [r0, #60] )
-
--.cfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
-+.cfu_0cpy8lp:
-+ PLD( pld [r1, #92] )
-+ PLD( pld [r0, #92] )
-+.cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault
- stmia r0!, {r3 - r6}
- ldmia r1!, {r3 - r6} @ Shouldnt fault
-- stmia r0!, {r3 - r6}
- subs ip, ip, #32
-+ stmia r0!, {r3 - r6}
- bpl .cfu_0cpy8lp
-+ PLD( cmn ip, #64 )
-+ PLD( bge .cfu_0cpynopld )
-+ PLD( add ip, ip, #64 )
-+
- .cfu_0rem8lp: cmn ip, #16
- ldmgeia r1!, {r3 - r6} @ Shouldnt fault
- stmgeia r0!, {r3 - r6}
-@@ -374,9 +443,9 @@
- .cfu_1fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_1nowords
-- mov r3, r7, lsr #8
-+ mov r3, r7, pull #8
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #24
-+ orr r3, r3, r7, push #24
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -387,50 +456,63 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_1rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_1cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_1cpy8lp: mov r3, r7, lsr #8
-+.cfu_1cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_1cpynopld: mov r3, r7, pull #8
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #24
-- mov r4, r4, lsr #8
-- orr r4, r4, r5, lsl #24
-- mov r5, r5, lsr #8
-- orr r5, r5, r6, lsl #24
-- mov r6, r6, lsr #8
-- orr r6, r6, r7, lsl #24
-- stmia r0!, {r3 - r6}
- subs ip, ip, #16
-+ orr r3, r3, r4, push #24
-+ mov r4, r4, pull #8
-+ orr r4, r4, r5, push #24
-+ mov r5, r5, pull #8
-+ orr r5, r5, r6, push #24
-+ mov r6, r6, pull #8
-+ orr r6, r6, r7, push #24
-+ stmia r0!, {r3 - r6}
- bpl .cfu_1cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_1cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_1rem8lp: tst ip, #8
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #24
-- movne r4, r4, lsr #8
-- orrne r4, r4, r7, lsl #24
-+ orrne r3, r3, r4, push #24
-+ movne r4, r4, pull #8
-+ orrne r4, r4, r7, push #24
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #8
-+ movne r3, r7, pull #8
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #24
-+ orrne r3, r3, r7, push #24
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_1fupi
--.cfu_1nowords: mov r3, r7, lsr #8
-+.cfu_1nowords: mov r3, r7, lsr #byte(1)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(2)
- strgeb r3, [r0], #1
-- movgt r3, r3, lsr #8
-+ movgt r3, r7, lsr #byte(3)
- strgtb r3, [r0], #1
- b .cfu_finished
-
- .cfu_2fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_2nowords
-- mov r3, r7, lsr #16
-+ mov r3, r7, pull #16
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #16
-+ orr r3, r3, r7, push #16
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -441,39 +523,52 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_2rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_2cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_2cpy8lp: mov r3, r7, lsr #16
-+.cfu_2cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_2cpynopld: mov r3, r7, pull #16
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #16
-- mov r4, r4, lsr #16
-- orr r4, r4, r5, lsl #16
-- mov r5, r5, lsr #16
-- orr r5, r5, r6, lsl #16
-- mov r6, r6, lsr #16
-- orr r6, r6, r7, lsl #16
-- stmia r0!, {r3 - r6}
- subs ip, ip, #16
-+ orr r3, r3, r4, push #16
-+ mov r4, r4, pull #16
-+ orr r4, r4, r5, push #16
-+ mov r5, r5, pull #16
-+ orr r5, r5, r6, push #16
-+ mov r6, r6, pull #16
-+ orr r6, r6, r7, push #16
-+ stmia r0!, {r3 - r6}
- bpl .cfu_2cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_2cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_2rem8lp: tst ip, #8
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #16
-- movne r4, r4, lsr #16
-- orrne r4, r4, r7, lsl #16
-+ orrne r3, r3, r4, push #16
-+ movne r4, r4, pull #16
-+ orrne r4, r4, r7, push #16
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #16
-+ movne r3, r7, pull #16
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #16
-+ orrne r3, r3, r7, push #16
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_2fupi
--.cfu_2nowords: mov r3, r7, lsr #16
-+.cfu_2nowords: mov r3, r7, lsr #byte(2)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
-- movge r3, r3, lsr #8
-+ movge r3, r7, lsr #byte(3)
- strgeb r3, [r0], #1
- USER( ldrgtbt r3, [r1], #0) @ May fault
- strgtb r3, [r0], #1
-@@ -482,9 +577,9 @@
- .cfu_3fupi: subs r2, r2, #4
- addmi ip, r2, #4
- bmi .cfu_3nowords
-- mov r3, r7, lsr #24
-+ mov r3, r7, pull #24
- USER( ldrt r7, [r1], #4) @ May fault
-- orr r3, r3, r7, lsl #8
-+ orr r3, r3, r7, push #8
- str r3, [r0], #4
- mov ip, r1, lsl #32 - PAGE_SHIFT
- rsb ip, ip, #0
-@@ -495,41 +590,54 @@
- sub r2, r2, ip
- subs ip, ip, #16
- blt .cfu_3rem8lp
-+ PLD( pld [r1, #12] )
-+ PLD( pld [r0, #12] )
-+ PLD( subs ip, ip, #32 )
-+ PLD( blt .cfu_3cpynopld )
-+ PLD( pld [r1, #28] )
-+ PLD( pld [r0, #28] )
-
--.cfu_3cpy8lp: mov r3, r7, lsr #24
-+.cfu_3cpy8lp:
-+ PLD( pld [r1, #44] )
-+ PLD( pld [r0, #44] )
-+.cfu_3cpynopld: mov r3, r7, pull #24
- ldmia r1!, {r4 - r7} @ Shouldnt fault
-- orr r3, r3, r4, lsl #8
-- mov r4, r4, lsr #24
-- orr r4, r4, r5, lsl #8
-- mov r5, r5, lsr #24
-- orr r5, r5, r6, lsl #8
-- mov r6, r6, lsr #24
-- orr r6, r6, r7, lsl #8
-+ orr r3, r3, r4, push #8
-+ mov r4, r4, pull #24
-+ orr r4, r4, r5, push #8
-+ mov r5, r5, pull #24
-+ orr r5, r5, r6, push #8
-+ mov r6, r6, pull #24
-+ orr r6, r6, r7, push #8
- stmia r0!, {r3 - r6}
- subs ip, ip, #16
- bpl .cfu_3cpy8lp
-+ PLD( cmn ip, #32 )
-+ PLD( bge .cfu_3cpynopld )
-+ PLD( add ip, ip, #32 )
-+
- .cfu_3rem8lp: tst ip, #8
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- ldmneia r1!, {r4, r7} @ Shouldnt fault
-- orrne r3, r3, r4, lsl #8
-- movne r4, r4, lsr #24
-- orrne r4, r4, r7, lsl #8
-+ orrne r3, r3, r4, push #8
-+ movne r4, r4, pull #24
-+ orrne r4, r4, r7, push #8
- stmneia r0!, {r3 - r4}
- tst ip, #4
-- movne r3, r7, lsr #24
-+ movne r3, r7, pull #24
- USER( ldrnet r7, [r1], #4) @ May fault
-- orrne r3, r3, r7, lsl #8
-+ orrne r3, r3, r7, push #8
- strne r3, [r0], #4
- ands ip, ip, #3
- beq .cfu_3fupi
--.cfu_3nowords: mov r3, r7, lsr #24
-+.cfu_3nowords: mov r3, r7, lsr #byte(3)
- teq ip, #0
- beq .cfu_finished
- cmp ip, #2
- strb r3, [r0], #1
--USER( ldrget r3, [r1], #0) @ May fault
-+USER( ldrgebt r3, [r1], #1) @ May fault
- strgeb r3, [r0], #1
-- movgt r3, r3, lsr #8
-+USER( ldrgtbt r3, [r1], #1) @ May fault
- strgtb r3, [r0], #1
- b .cfu_finished
-
-@@ -544,7 +652,7 @@
- ldr r1, [sp], #4 @ unsigned long count
- subs r4, r1, r2 @ bytes left to copy
- movne r1, r4
-- blne SYMBOL_NAME(__memzero)
-+ blne __memzero
- mov r0, r4
- LOADREGS(fd,sp!, {r4 - r7, pc})
- .previous
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/Makefile
-@@ -0,0 +1,56 @@
-+#
-+# Makefile for the linux kernel.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+
-+USE_STANDARD_AS_RULE := true
-+
-+O_TARGET := pxa.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+export-objs := generic.o irq.o dma.o sa1111.o \
-+ usb_ctl.o usb_recv.o usb_send.o
-+
-+# Common support (must be linked before board specific support)
-+obj-y += generic.o irq.o dma.o
-+obj-$(CONFIG_SA1111) += sa1111.o
-+
-+# Specific board support
-+obj-$(CONFIG_ARCH_CSB226) += csb226.o
-+obj-$(CONFIG_ARCH_INNOKOM) += innokom.o
-+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
-+obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o
-+obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-+obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
-+
-+# Support for blinky lights
-+leds-y := leds.o
-+leds-$(CONFIG_ARCH_CSB226) += leds-csb226.o
-+leds-$(CONFIG_ARCH_INNOKOM) += leds-innokom.o
-+leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
-+leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
-+leds-$(CONFIG_ARCH_PXA_CERF) += leds-cerf.o
-+
-+obj-$(CONFIG_LEDS) += $(leds-y)
-+
-+# PXA USB client support
-+list-multi += pxausb_core.o
-+pxausb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
-+obj-$(CONFIG_PXA_USB) += pxausb_core.o
-+obj-$(CONFIG_PXA_USB_NETLINK) += usb-eth.o
-+obj-$(CONFIG_PXA_USB_CHAR) += usb-char.o
-+
-+# Misc features
-+obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+pxausb_core.o: $(pxausb_core-objs)
-+ $(LD) -r -o $@ $(pxausb_core-objs)
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/cerf.c
-@@ -0,0 +1,266 @@
-+/*
-+ * linux/arch/arm/mach-pxa/cerf.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/io.h>
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int cerf_debug = DEBUGGING;
-+#else
-+#define cerf_debug 0
-+#endif
-+
-+static void __init cerf_init_irq(void)
-+{
-+ pxa_init_irq();
-+
-+ if( cerf_debug > 1)
-+ {
-+#if 0
-+ GPDR0 = 0xc05b9130;
-+ GPDR1 = 0xfcffab82;
-+ GPDR2 = 0x0001ffff;
-+#endif
-+
-+ printk(KERN_INFO "Pin directions:\n");
-+ printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0);
-+ printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1);
-+ printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2);
-+
-+ printk(KERN_INFO "Pin State:\n");
-+ printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0);
-+ printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1);
-+ printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2);
-+
-+ printk(KERN_INFO "Rising Edge:\n");
-+ printk(KERN_INFO "GRER0 0x%08x\n", GRER0);
-+ printk(KERN_INFO "GRER1 0x%08x\n", GRER1);
-+ printk(KERN_INFO "GRER2 0x%08x\n", GRER2);
-+
-+ printk(KERN_INFO "Falling Edge:\n");
-+ printk(KERN_INFO "GFER0 0x%08x\n", GFER0);
-+ printk(KERN_INFO "GFER1 0x%08x\n", GFER1);
-+ printk(KERN_INFO "GFER2 0x%08x\n", GFER2);
-+ }
-+
-+ /* set_GPIO_IRQ_edge has to be called before an irq can be requested */
-+ set_GPIO_IRQ_edge( 0, GPIO_FALLING_EDGE); /* CPLD */
-+#ifdef CONFIG_PXA_CERF_PDA
-+ set_GPIO_IRQ_edge( 2, GPIO_RISING_EDGE); /* UART B Interrupt */
-+ set_GPIO_IRQ_edge( 3, GPIO_RISING_EDGE); /* UART A Interrupt */
-+ set_GPIO_IRQ_edge( 32, GPIO_RISING_EDGE); /* UCB1400 Interrupt */
-+#endif
-+ set_GPIO_IRQ_edge( 14, GPIO_FALLING_EDGE); /* PCMCIA Card Detect */
-+ set_GPIO_IRQ_edge( 21, GPIO_RISING_EDGE); /* Ethernet Interrupt */
-+}
-+
-+static int __init cerf_init(void)
-+{
-+ /*
-+ * All of the code that was here was SA1111 init code
-+ * which we do not have.
-+ */
-+ return 0;
-+}
-+
-+__initcall(cerf_init);
-+
-+static void __init
-+fixup_cerf(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ SET_BANK (0, CERF_RAM_BASE, CERF_RAM_SIZE);
-+ mi->nr_banks = 1;
-+
-+#if 0 // Enable this stuff if you plan on not using jffs2
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+/*
-+ * IO map for the devices.
-+ */
-+static struct map_desc cerf_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { CERF_FLASH_BASE , CERF_FLASH_PHYS , CERF_FLASH_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_ETH_BASE , CERF_ETH_PHYS , CERF_ETH_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+#ifdef CONFIG_PXA_CERF_PDA
-+ { CERF_BT_BASE , CERF_BT_PHYS , CERF_BT_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_SERIAL_BASE, CERF_SERIAL_PHYS, CERF_SERIAL_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
-+ { CERF_CPLD_BASE , CERF_CPLD_PHYS , CERF_CPLD_SIZE , DOMAIN_IO, 0, 1, 0, 0 },
-+#endif
-+
-+ LAST_DESC
-+};
-+
-+static void __init cerf_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(cerf_io_desc);
-+
-+ if( cerf_debug > 1)
-+ {
-+ printk(KERN_INFO "origMCS0 = 0x%08x\n", MSC0);
-+ printk(KERN_INFO "origMCS1 = 0x%08x\n", MSC1);
-+ printk(KERN_INFO "origMCS2 = 0x%08x\n", MSC2);
-+ }
-+
-+ /* setup memory timing for CS0/1 */
-+ MSC0 = MSC_CS(0, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(3) |
-+ MSC_RDN(15) |
-+ MSC_RDF(13) |
-+ MSC_RBW(0) |
-+ MSC_RT(0)) |
-+#ifdef CONFIG_PXA_CERF_PDA
-+ MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(7) |
-+ MSC_RDN(15) |
-+ MSC_RDF(15) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+#elif defined(CONFIG_PXA_CERF_BOARD)
-+ MSC_CS(1, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(1) |
-+ MSC_RDN(2) |
-+ MSC_RDF(4) |
-+ MSC_RBW(0) |
-+ MSC_RT(4));
-+#endif
-+ printk(KERN_INFO "MCS0 = 0x%08x\n", MSC0);
-+
-+ /* setup memory timing for CS2/3 */
-+ MSC1 = MSC_CS(2, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(5) |
-+ MSC_RDN(10) |
-+ MSC_RDF(10) |
-+ MSC_RBW(1) |
-+ MSC_RT(0)) |
-+ MSC_CS(3, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(5) |
-+ MSC_RDN(10) |
-+ MSC_RDF(10) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+ printk(KERN_INFO "MCS1 = 0x%08x\n", MSC1);
-+
-+ /* setup memory timing for CS4/5 */
-+ MSC2 = MSC_CS(4, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(2) |
-+ MSC_RDN(4) |
-+ MSC_RDF(4) |
-+ MSC_RBW(1) |
-+ MSC_RT(0)) |
-+ MSC_CS(5, MSC_RBUFF(MSC_RBUFF_SLOW) |
-+ MSC_RRR(2) |
-+ MSC_RDN(4) |
-+ MSC_RDF(4) |
-+ MSC_RBW(1) |
-+ MSC_RT(0));
-+ printk(KERN_INFO "MCS2 = 0x%08x\n", MSC2);
-+
-+#ifdef CONFIG_SOUND_PXA_AC97
-+ printk(KERN_INFO "Enabling sound amp for pxa cerf pda.\n");
-+ outw( CERF_PDA_SOUND_ENABLE, CERF_CPLD_BASE+CERF_PDA_CPLD_SOUND_ENA);
-+#endif
-+
-+#ifdef CONFIG_FB_PXA
-+ printk(KERN_INFO "Setting LCD to brightness to %d/15\n", CERF_PDA_DEFAULT_BRIGHTNESS);
-+ outw( CERF_PDA_DEFAULT_BRIGHTNESS, CERF_CPLD_BASE+CERF_PDA_CPLD_BRIGHTNESS);
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ /* Enable IrDA UART (SIR)*/
-+ CKEN |= CKEN5_STUART;
-+
-+ /* We want to get our goods from the STUART */
-+ set_GPIO_mode(GPIO46_STRXD_MD);
-+ set_GPIO_mode(GPIO47_STTXD_MD);
-+
-+ /* make sure FIR ICP is off */
-+ ICCR0 = 0;
-+
-+ /* configure STUART to for SIR
-+ * NOTE: RCVEIR and XMITIR must not be set at the same time!
-+ * Start with receive in IR mode, and switch transmit to IR only
-+ * when we need to send something in serial driver.
-+ */
-+ STISR = IrSR_IR_RECEIVE_ON;
-+#endif
-+
-+#if 0
-+ /* Connect FIR ICP to GPIO pins */
-+ CKEN |= CKEN13_FICP;
-+ set_GPIO_mode(GPIO46_ICPRXD_MD);
-+ set_GPIO_mode(GPIO47_ICPTXD_MD);
-+ ICCR0 = 0x1 | 0x18; //ICP unit enable
-+#endif
-+
-+#if 0
-+ /* Enable BT UART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+#endif
-+
-+ if( cerf_debug > 1)
-+ {
-+ printk(KERN_INFO "GPDR0 0x%08x\n", GPDR0);
-+ printk(KERN_INFO "GPDR1 0x%08x\n", GPDR1);
-+ printk(KERN_INFO "GPDR2 0x%08x\n", GPDR2);
-+ printk(KERN_INFO "GPLR0 0x%08x\n", GPLR0);
-+ printk(KERN_INFO "GPLR1 0x%08x\n", GPLR1);
-+ printk(KERN_INFO "GPLR2 0x%08x\n", GPLR2);
-+ printk(KERN_INFO "GAFR0_L 0x%08x\n", GAFR0_L);
-+ printk(KERN_INFO "GAFR0_U 0x%08x\n", GAFR0_U);
-+ printk(KERN_INFO "GAFR1_L 0x%08x\n", GAFR1_L);
-+ printk(KERN_INFO "GAFR1_U 0x%08x\n", GAFR1_U);
-+ printk(KERN_INFO "GAFR2_L 0x%08x\n", GAFR2_L);
-+ printk(KERN_INFO "GAFR2_U 0x%08x\n", GAFR2_U);
-+ printk(KERN_INFO "CKEN = 0x%08x\n", CKEN);
-+ printk(KERN_INFO "ICCR0 = 0x%08x\n", ICCR0);
-+ printk(KERN_INFO "STISR = 0x%08x\n", STISR);
-+ }
-+}
-+
-+MACHINE_START(PXA_CERF, "CerfBoard PXA Reference Board")
-+ MAINTAINER("Intrinsyc Software Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_cerf)
-+ MAPIO(cerf_map_io)
-+ INITIRQ(cerf_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/cpu-pxa.c
-@@ -0,0 +1,240 @@
-+/*
-+ * linux/arch/arm/mach-pxa/cpu-pxa.c
-+ *
-+ * Copyright (C) 2002,2003 Intrinsyc Software
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * 31-Jul-2002 : Initial version [FB]
-+ * 29-Jan-2003 : added PXA255 support [FB]
-+ *
-+ * Note:
-+ *
-+ * Quote from erratum 134:
-+ * ""If the operation of these peripherals would be adversely affected,
-+ * then these peripherals would have to be disabled during a frequency
-+ * change. (MMC,FFUART,STUART,BTUART,IRDA,SSP,UDC,AC97)""
-+ *
-+ * This sounds like they are not sure what the bug is...
-+ * If you run into problems with any of these peripherals, the effected
-+ * driver should register with cpu freq notification and disable/enable
-+ * the peripheral on CPUFREQ_PRECHANGE and CPUFREQ_POSTCHANGE.
-+ *
-+ * So far I've tested this code only under light load. It works for me.
-+ *
-+ * TODO:
-+ * - determine min/max freq at runtime
-+ * - determine pxbus value at runtime
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+
-+#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int freq_debug = DEBUGGING;
-+#else
-+#define freq_debug 0
-+#endif
-+
-+typedef struct
-+{
-+ unsigned int khz;
-+ unsigned int cccr;
-+ unsigned int pxbus;
-+} pxa_freqs_t;
-+
-+#define CCLKCFG_TURBO 0x1
-+#define CCLKCFG_FCS 0x2
-+
-+#define PXA250_REV_A1 0x1
-+#define PXA250_REV_B2 0x4
-+#define PXA25x_MIN_FREQ 99000
-+
-+//#define PXA25x_ALLOW_OVERCLOCK
-+
-+#ifdef PXA25x_ALLOW_OVERCLOCK
-+#warning *** Overclocking enabled - this may fry your hardware - you have been warned ***
-+#define OC(x...) x
-+#define PXA25x_MAX_FREQ 471000
-+#else
-+#define OC(x...)
-+#define PXA25x_MAX_FREQ 400000
-+#endif
-+
-+/* If CONFIG_CPU_FREQ is turned on but we find (at runtime)
-+ * we can't support scaling, try to handle requests gracefully.
-+ */
-+static int supported;
-+
-+static pxa_freqs_t pxa250_valid_freqs[] =
-+{
-+ {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
-+ {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
-+ {398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
-+ {0,0}
-+};
-+
-+static pxa_freqs_t pxa255_valid_freqs[] =
-+{
-+ { 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */
-+OC( {118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */
-+ {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
-+OC( {236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */
-+ {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
-+OC( {354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */
-+ {398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
-+ {398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */
-+OC( {471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */
-+ {0,0}
-+};
-+
-+static pxa_freqs_t *pxa_valid_freqs;
-+
-+/* This should be called with a valid freq point that was
-+ * obtained via pxa_validate_speed
-+ */
-+static pxa_freqs_t * pxa_get_freq_info( unsigned int khz)
-+{
-+ int i=0;
-+ while( pxa_valid_freqs[i].khz)
-+ {
-+ if( pxa_valid_freqs[i].khz == khz)
-+ return &pxa_valid_freqs[i];
-+ i++;
-+ }
-+
-+ /* shouldn't get here */
-+ return 0;
-+}
-+
-+/* find a valid frequency point */
-+static unsigned int pxa_validate_speed(unsigned int khz)
-+{
-+ int i=0;
-+ unsigned int vfreq = 0;
-+ while( pxa_valid_freqs[i].khz && (khz >= pxa_valid_freqs[i].khz))
-+ {
-+ vfreq = pxa_valid_freqs[i].khz;
-+ i++;
-+ }
-+ return vfreq;
-+}
-+
-+/* This should be called with a valid freq point that was
-+ * obtained via pxa_validate_speed
-+ */
-+static void pxa_setspeed(unsigned int khz)
-+{
-+ unsigned long flags;
-+ unsigned int unused;
-+ void *ramstart = phys_to_virt(0xa0000000);
-+ pxa_freqs_t *freq_info;
-+
-+ if( ! supported) return;
-+
-+ freq_info = pxa_get_freq_info( khz);
-+
-+ if( ! freq_info) return;
-+
-+ CCCR = freq_info->cccr;
-+ if( freq_debug)
-+ printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n",
-+ khz/1000, freq_info->pxbus);
-+
-+ local_irq_save(flags);
-+ __asm__ __volatile__("\
-+ ldr r4, [%1] @load MDREFR \n\
-+ b 2f \n\
-+ .align 5 \n\
-+1: \n\
-+ mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\
-+ \n\
-+ @ restart sdcke 0 / 1 \n\
-+ bic r5, r4, #(0x00001000 | 0x00008000) @ MDREFR_E0PIN | MDREFR_E1PIN \n\
-+ str r5, [%1] @clear \n\
-+ str r4, [%1] @restore \n\
-+ \n\
-+ @ Generate refresh cycles for all banks \n\
-+ ldr r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ str r4, [%3] \n\
-+ \n\
-+ b 3f \n\
-+2: b 1b \n\
-+3: nop \n\
-+ "
-+ : "=&r" (unused)
-+ : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart)
-+ : "r4", "r5");
-+ local_irq_restore(flags);
-+}
-+
-+static int pxa_init_freqs( void)
-+{
-+ int cpu_ver;
-+ asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver));
-+
-+ if( (cpu_ver & 0xf) <= PXA250_REV_A1)
-+ {
-+ return 0;
-+ }
-+
-+ if( (cpu_ver & 0xf) <= PXA250_REV_B2)
-+ {
-+ if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n");
-+ pxa_valid_freqs = pxa250_valid_freqs;
-+ }
-+ else /* C0 and above */
-+ {
-+ if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n");
-+ pxa_valid_freqs = pxa255_valid_freqs;
-+ }
-+
-+ return 1;
-+}
-+
-+static int __init pxa_clk_init(void)
-+{
-+ if( pxa_init_freqs())
-+ {
-+ if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n");
-+ supported = 1;
-+
-+ cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ);
-+ cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
-+ }
-+ else
-+ {
-+ if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n");
-+ /* Note that we have to initialize the generic code in order to
-+ * release a lock (cpufreq_sem). Any registration for freq changes
-+ * (e.g. lcd driver) will get blocked otherwise.
-+ */
-+ cpufreq_init( 0, 0, 0);
-+ cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
-+ }
-+
-+ return 0;
-+}
-+
-+module_init(pxa_clk_init);
-+
-+MODULE_AUTHOR ("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/csb226.c
-@@ -0,0 +1,180 @@
-+/*
-+ * linux/arch/arm/mach-pxa/csb226.c
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+static unsigned long csb226_irq_en_mask;
-+
-+static void csb226_mask_and_ack_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask &= ~(1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
-+ CSB226_IRQ_SET_CLR &= ~(1 << csb226_irq);
-+}
-+
-+static void csb226_mask_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask &= ~(1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN &= ~(1 << csb226_irq);
-+}
-+
-+static void csb226_unmask_irq(unsigned int irq)
-+{
-+ int csb226_irq = (irq - CSB226_IRQ(0));
-+ csb226_irq_en_mask |= (1 << csb226_irq);
-+ CSB226_IRQ_MASK_EN |= (1 << csb226_irq);
-+}
-+
-+void csb226_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long irq_status;
-+ int i;
-+
-+ while ((irq_status = CSB226_IRQ_SET_CLR & csb226_irq_en_mask)) {
-+ for (i = 0; i < 6; i++) {
-+ if(irq_status & (1<<i))
-+ do_IRQ(CSB226_IRQ(i), regs);
-+ }
-+ }
-+}
-+
-+/* FIXME: this should not be necessary on csb226 */
-+static struct irqaction csb226_irq = {
-+ name: "CSB226 FPGA",
-+ handler: csb226_irq_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+static void __init csb226_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ /* setup extra csb226 irqs */
-+/* RS: ???
-+ for(irq = CSB226_IRQ(0); irq <= CSB226_IRQ(5); irq++)
-+ {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = csb226_mask_and_ack_irq;
-+ irq_desc[irq].mask = csb226_mask_irq;
-+ irq_desc[irq].unmask = csb226_unmask_irq;
-+ }
-+
-+ set_GPIO_IRQ_edge(GPIO_CSB226_IRQ, GPIO_FALLING_EDGE);
-+ setup_arm_irq(IRQ_GPIO_CSB226_IRQ, &csb226_irq);
-+*/
-+}
-+
-+/* FIXME: not necessary on CSB226? */
-+static int __init csb226_init(void)
-+{
-+ int ret;
-+
-+ return 0;
-+}
-+
-+__initcall(csb226_init);
-+
-+static void __init
-+fixup_csb226(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+ mi->nr_banks = 1;
-+#if 0
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+/* FIXME: shouldn't this be moved to arch/arm/mach-pxa/mm.c? [RS] */
-+static struct map_desc csb226_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+// { 0xf4000000, 0x04000000, 0x00ffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* HT4562B PS/2 controller */
-+ { 0xf8000000, 0x08000000, 1024*1024, DOMAIN_IO, 0, 1, 0, 0 }, /* CS8900 LAN controller */
-+// { 0xe0000000, 0x20000000, 0x0fffffff, DOMAIN_IO, 1, 1, 0, 0 }, /* CompactFlash */
-+#if 0
-+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
-+ { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
-+#endif
-+ LAST_DESC
-+};
-+
-+static void __init csb226_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(csb226_io_desc);
-+
-+ /* This enables the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ /* This is for the CS8900 chip select */
-+ set_GPIO_mode(GPIO78_nCS_2_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(CSB226, "Cogent CSB226 Development Platform")
-+ MAINTAINER("Robert Schwebel, Pengutronix")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_csb226)
-+ MAPIO(csb226_map_io)
-+ INITIRQ(csb226_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/dma.c
-@@ -0,0 +1,131 @@
-+/*
-+ * linux/arch/arm/mach-pxa/dma.c
-+ *
-+ * PXA DMA registration and IRQ dispatching
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Nov 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+
-+#include <asm/system.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+
-+static struct dma_channel {
-+ char *name;
-+ void (*irq_handler)(int, void *, struct pt_regs *);
-+ void *data;
-+} dma_channels[16];
-+
-+
-+int pxa_request_dma (char *name, pxa_dma_prio prio,
-+ void (*irq_handler)(int, void *, struct pt_regs *),
-+ void *data)
-+{
-+ unsigned long flags;
-+ int i, found = 0;
-+
-+ /* basic sanity checks */
-+ if (!name || !irq_handler)
-+ return -EINVAL;
-+
-+ local_irq_save(flags);
-+
-+ /* try grabbing a DMA channel with the requested priority */
-+ for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
-+ if (!dma_channels[i].name) {
-+ found = 1;
-+ break;
-+ }
-+ }
-+
-+ if (!found) {
-+ /* requested prio group is full, try hier priorities */
-+ for (i = prio-1; i >= 0; i--) {
-+ if (!dma_channels[i].name) {
-+ found = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (found) {
-+ DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ dma_channels[i].name = name;
-+ dma_channels[i].irq_handler = irq_handler;
-+ dma_channels[i].data = data;
-+ } else {
-+ printk (KERN_WARNING "No more available DMA channels for %s\n", name);
-+ i = -ENODEV;
-+ }
-+
-+ local_irq_restore(flags);
-+ return i;
-+}
-+
-+void pxa_free_dma (int dma_ch)
-+{
-+ unsigned long flags;
-+
-+ if (!dma_channels[dma_ch].name) {
-+ printk (KERN_CRIT __FUNCTION__
-+ ": trying to free channel %d which is already freed\n",
-+ dma_ch);
-+ return;
-+ }
-+
-+ local_irq_save(flags);
-+ DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ dma_channels[dma_ch].name = NULL;
-+ local_irq_restore(flags);
-+}
-+
-+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int i, dint = DINT;
-+
-+ for (i = 0; i < 16; i++) {
-+ if (dint & (1 << i)) {
-+ struct dma_channel *channel = &dma_channels[i];
-+ if (channel->name && channel->irq_handler) {
-+ channel->irq_handler(i, channel->data, regs);
-+ } else {
-+ /*
-+ * IRQ for an unregistered DMA channel:
-+ * let's clear the interrupts and disable it.
-+ */
-+ printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
-+ DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-+ }
-+ }
-+ }
-+}
-+
-+static int __init pxa_dma_init (void)
-+{
-+ int ret;
-+
-+ ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
-+ if (ret)
-+ printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
-+ return ret;
-+}
-+
-+__initcall(pxa_dma_init);
-+
-+EXPORT_SYMBOL(pxa_request_dma);
-+EXPORT_SYMBOL(pxa_free_dma);
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/generic.c
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/arch/arm/mach-pxa/generic.c
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * Code common to all PXA machines.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Since this file should be linked before any other machine specific file,
-+ * the __initcall() here will be executed first. This serves as default
-+ * initialization stuff for PXA machines which can be overriden later if
-+ * need be.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+#include <asm/pgtable.h>
-+#include <asm/mach/map.h>
-+
-+#include "generic.h"
-+
-+/*
-+ * Various clock factors driven by the CCCR register.
-+ */
-+
-+/* Crystal Frequency to Memory Frequency Multiplier (L) */
-+static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
-+
-+/* Memory Frequency to Run Mode Frequency Multiplier (M) */
-+static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
-+
-+/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
-+/* Note: we store the value N * 2 here. */
-+static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
-+
-+/* Crystal clock */
-+#define BASE_CLK 3686400
-+
-+/*
-+ * Get the clock frequency as reflected by CCCR and the turbo flag.
-+ * We assume these values have been applied via a fcs.
-+ * If info is not 0 we also display the current settings.
-+ */
-+unsigned int get_clk_frequency_khz( int info)
-+{
-+ unsigned long cccr, turbo;
-+ unsigned int l, L, m, M, n2, N;
-+
-+ cccr = CCCR;
-+ asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) );
-+
-+ l = L_clk_mult[(cccr >> 0) & 0x1f];
-+ m = M_clk_mult[(cccr >> 5) & 0x03];
-+ n2 = N2_clk_mult[(cccr >> 7) & 0x07];
-+
-+ L = l * BASE_CLK;
-+ M = m * L;
-+ N = n2 * M / 2;
-+
-+ if( info)
-+ {
-+ L += 5000;
-+ printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n",
-+ L / 1000000, (L % 1000000) / 10000, l );
-+ M += 5000;
-+ printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n",
-+ M / 1000000, (M % 1000000) / 10000, m );
-+ N += 5000;
-+ printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n",
-+ N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5,
-+ (turbo & 1) ? "" : "in" );
-+ }
-+
-+ return (turbo & 1) ? (N/1000) : (M/1000);
-+}
-+
-+EXPORT_SYMBOL(get_clk_frequency_khz);
-+
-+/*
-+ * Return the current lclk requency in units of 10kHz
-+ */
-+unsigned int get_lclk_frequency_10khz(void)
-+{
-+ return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
-+}
-+
-+EXPORT_SYMBOL(get_lclk_frequency_10khz);
-+
-+/*
-+ * Handy function to set GPIO alternate functions
-+ */
-+
-+void set_GPIO_mode(int gpio_mode)
-+{
-+ long flags;
-+ int gpio = gpio_mode & GPIO_MD_MASK_NR;
-+ int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
-+ int gafr;
-+
-+ local_irq_save(flags);
-+ if (gpio_mode & GPIO_MD_MASK_DIR)
-+ GPDR(gpio) |= GPIO_bit(gpio);
-+ else
-+ GPDR(gpio) &= ~GPIO_bit(gpio);
-+ gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
-+ GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
-+ local_irq_restore(flags);
-+}
-+
-+EXPORT_SYMBOL(set_GPIO_mode);
-+
-+/*
-+ * Note that 0xfffe0000-0xffffffff is reserved for the vector table and
-+ * cache flush area.
-+ */
-+static struct map_desc standard_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
-+ { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
-+ { 0xf8000000, 0x40000000, 0x01800000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */
-+ { 0xfa000000, 0x44000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
-+ { 0xfc000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */
-+ { 0xff000000, 0x00000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* UNCACHED_PHYS_0 */
-+ LAST_DESC
-+};
-+
-+void __init pxa_map_io(void)
-+{
-+ iotable_init(standard_io_desc);
-+ get_clk_frequency_khz( 1);
-+}
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/generic.h
-@@ -0,0 +1,19 @@
-+/*
-+ * linux/arch/arm/mach-pxa/generic.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+extern void __init pxa_map_io(void);
-+extern void __init pxa_init_irq(void);
-+
-+#define SET_BANK(__nr,__start,__size) \
-+ mi->bank[__nr].start = (__start), \
-+ mi->bank[__nr].size = (__size), \
-+ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/idp.c
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/arch/arm/mach-pxa/idp.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
-+ *
-+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
-+ * Initial code
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+#define PXA_IDP_REV02
-+
-+#ifndef PXA_IDP_REV02
-+/* shadow registers for write only registers */
-+unsigned int idp_cpld_led_control_shadow = 0x1;
-+unsigned int idp_cpld_periph_pwr_shadow = 0xd;
-+unsigned int ipd_cpld_cir_shadow = 0;
-+unsigned int idp_cpld_kb_col_high_shadow = 0;
-+unsigned int idp_cpld_kb_col_low_shadow = 0;
-+unsigned int idp_cpld_pccard_en_shadow = 0xC3;
-+unsigned int idp_cpld_gpioh_dir_shadow = 0;
-+unsigned int idp_cpld_gpioh_value_shadow = 0;
-+unsigned int idp_cpld_gpiol_dir_shadow = 0;
-+unsigned int idp_cpld_gpiol_value_shadow = 0;
-+
-+/*
-+ * enable all LCD signals -- they should still be on
-+ * write protect flash
-+ * enable all serial port transceivers
-+ */
-+
-+unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */
-+ (0x1 << 19) | /* disable flash write enable */
-+ (0x7 << 9)); /* enable serial port transeivers */
-+
-+#endif
-+
-+static int __init idp_init(void)
-+{
-+ printk("idp_init()\n");
-+ return 0;
-+}
-+
-+__initcall(idp_init);
-+
-+static void __init idp_init_irq(void)
-+{
-+ pxa_init_irq();
-+}
-+
-+static void __init
-+fixup_idp(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+#ifdef PXA_IDP_REV02
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+#else
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+#endif
-+ mi->nr_banks = 1;
-+#if 0
-+ setup_ramdisk (1, 0, 0, 8192);
-+ setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
-+ ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-+#endif
-+}
-+
-+static struct map_desc idp_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+
-+
-+#ifndef PXA_IDP_REV02
-+ { IDP_CTRL_PORT_BASE,
-+ IDP_CTRL_PORT_PHYS,
-+ IDP_CTRL_PORT_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+#endif
-+
-+ { IDP_IDE_BASE,
-+ IDP_IDE_PHYS,
-+ IDP_IDE_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_ETH_BASE,
-+ IDP_ETH_PHYS,
-+ IDP_ETH_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_COREVOLT_BASE,
-+ IDP_COREVOLT_PHYS,
-+ IDP_COREVOLT_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+ { IDP_CPLD_BASE,
-+ IDP_CPLD_PHYS,
-+ IDP_CPLD_SIZE,
-+ DOMAIN_IO,
-+ 0, 1, 0, 0 },
-+
-+ LAST_DESC
-+};
-+
-+static void __init idp_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(idp_io_desc);
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(SMC_IRQ), GPIO_RISING_EDGE);
-+}
-+
-+MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
-+ MAINTAINER("Accelent Systems Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
-+ FIXUP(fixup_idp)
-+ MAPIO(idp_map_io)
-+ INITIRQ(idp_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/innokom.c
-@@ -0,0 +1,129 @@
-+/*
-+ * linux/arch/arm/mach-pxa/innokom.c
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/arch/irqs.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+
-+static void __init innokom_init_irq(void)
-+{
-+ pxa_init_irq();
-+}
-+
-+
-+void sw_update_handler( int irq, void* dev_id,struct pt_regs* regs)
-+{
-+}
-+
-+
-+void reset_handler( int irq, void* dev_id,struct pt_regs* regs)
-+{
-+}
-+
-+
-+static int __init innokom_init(void)
-+{
-+ int sw_irq = GPIO_2_80_TO_IRQ(11); /* software update button */
-+ int reset_irq = GPIO_2_80_TO_IRQ(3); /* reset button */
-+
-+ set_GPIO_IRQ_edge(11,GPIO_FALLING_EDGE);
-+ if (request_irq(sw_irq,sw_update_handler,SA_INTERRUPT,"software update button",NULL))
-+ printk(KERN_INFO "innokom: can't get assigned irq %i\n",sw_irq);
-+
-+ set_GPIO_IRQ_edge(3,GPIO_FALLING_EDGE);
-+ if (request_irq(reset_irq,reset_handler,SA_INTERRUPT,"reset button",NULL))
-+ printk(KERN_INFO "innokom: can't get assigned irq %i\n",reset_irq);
-+
-+ return 0;
-+}
-+
-+
-+__initcall(innokom_init);
-+
-+
-+static void __init
-+fixup_innokom(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ /* we probably want to get this information from the bootloader later */
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+ mi->nr_banks = 1;
-+}
-+
-+
-+/* memory mapping */
-+static struct map_desc innokom_io_desc[] __initdata = {
-+/* virtual physical length domain r w c b */
-+ { INNOKOM_ETH_BASE, INNOKOM_ETH_PHYS, INNOKOM_ETH_SIZE, DOMAIN_IO, 0, 1, 0, 0 }, /* ETH SMSC 91111 */
-+ LAST_DESC
-+};
-+
-+static void __init innokom_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(innokom_io_desc);
-+
-+ /* Enable the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ set_GPIO_mode(GPIO33_nCS_5_MD); /* SMSC network chip */
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(INNOKOM, "Auerswald Innokom")
-+ MAINTAINER("Robert Schwebel, Pengutronix")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ BOOT_PARAMS(0xa0000100)
-+ FIXUP(fixup_innokom)
-+ MAPIO(innokom_map_io)
-+ INITIRQ(innokom_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/irq.c
-@@ -0,0 +1,282 @@
-+/*
-+ * linux/arch/arm/mach-pxa/irq.c
-+ *
-+ * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/ptrace.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/mach/irq.h>
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+
-+/*
-+ * PXA GPIO edge detection for IRQs:
-+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
-+ * This must be called *before* the appropriate IRQ is registered.
-+ * Use this instead of directly setting GRER/GFER.
-+ */
-+
-+static int GPIO_IRQ_rising_edge[3];
-+static int GPIO_IRQ_falling_edge[3];
-+
-+void set_GPIO_IRQ_edge (int gpio_nr, int edge)
-+{
-+ long flags;
-+ local_irq_save(flags);
-+ set_GPIO_mode(gpio_nr | GPIO_IN);
-+ if (edge & GPIO_FALLING_EDGE)
-+ set_bit (gpio_nr, GPIO_IRQ_falling_edge);
-+ else
-+ clear_bit (gpio_nr, GPIO_IRQ_falling_edge);
-+ if (edge & GPIO_RISING_EDGE)
-+ set_bit (gpio_nr, GPIO_IRQ_rising_edge);
-+ else
-+ clear_bit (gpio_nr, GPIO_IRQ_rising_edge);
-+ irq_desc[IRQ_GPIO(gpio_nr)].valid = 1;
-+ local_irq_restore(flags);
-+}
-+
-+EXPORT_SYMBOL(set_GPIO_IRQ_edge);
-+
-+
-+/*
-+ * We don't need to ACK IRQs on the PXA unless they're GPIOs
-+ * this is for IRQs known as PXA_IRQ([10...31]).
-+ */
-+
-+static void pxa_mask_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+static void pxa_unmask_irq(unsigned int irq)
-+{
-+ ICMR |= (1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+/*
-+ * GPIO IRQs must be acknoledged. This is for GPIO 0 and 1.
-+ */
-+
-+static void pxa_mask_and_ack_GPIO_0_1_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+ GEDR0 = (1 << (irq - IRQ_GPIO0));
-+}
-+
-+static void pxa_mask_GPIO_0_1_irq(unsigned int irq)
-+{
-+ ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+static void pxa_unmask_GPIO_0_1_irq(unsigned int irq)
-+{
-+ int gpio = irq - IRQ_GPIO0;
-+ GRER0 = (GRER0 & ~(1 << gpio))|(GPIO_IRQ_rising_edge[0] & (1 << gpio));
-+ GFER0 = (GFER0 & ~(1 << gpio))|(GPIO_IRQ_falling_edge[0] & (1 << gpio));
-+ ICMR |= (1 << (irq + PXA_IRQ_SKIP));
-+}
-+
-+/*
-+ * Demux handler for GPIO 2-80 edge detect interrupts
-+ */
-+
-+static int GPIO_2_80_enabled[3]; /* enabled i.e. unmasked GPIO IRQs */
-+static int GPIO_2_80_spurious[3]; /* GPIOs that triggered when masked */
-+
-+static void pxa_GPIO_2_80_demux(int irq, void *dev_id,
-+ struct pt_regs *regs)
-+{
-+ int i, gedr, spurious;
-+
-+ while ((gedr = (GEDR0 & ~3))) {
-+ /*
-+ * We don't want to clear GRER/GFER when the corresponding
-+ * IRQ is masked because we could miss a level transition
-+ * i.e. an IRQ which need servicing as soon as it is
-+ * unmasked. However, such situation should happen only
-+ * during the loop below. Thus all IRQs which aren't
-+ * enabled at this point are considered spurious. Those
-+ * are cleared but only de-activated if they happen twice.
-+ */
-+ spurious = gedr & ~GPIO_2_80_enabled[0];
-+ if (spurious) {
-+ GEDR0 = spurious;
-+ GRER0 &= ~(spurious & GPIO_2_80_spurious[0]);
-+ GFER0 &= ~(spurious & GPIO_2_80_spurious[0]);
-+ GPIO_2_80_spurious[0] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 2; i < 32; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(2) + i - 2, regs);
-+ }
-+ }
-+ }
-+ while ((gedr = GEDR1)) {
-+ spurious = gedr & ~GPIO_2_80_enabled[1];
-+ if (spurious) {
-+ GEDR1 = spurious;
-+ GRER1 &= ~(spurious & GPIO_2_80_spurious[1]);
-+ GFER1 &= ~(spurious & GPIO_2_80_spurious[1]);
-+ GPIO_2_80_spurious[1] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 0; i < 32; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(32) + i, regs);
-+ }
-+ }
-+ }
-+ while ((gedr = (GEDR2 & 0x0001ffff))) {
-+ spurious = gedr & ~GPIO_2_80_enabled[2];
-+ if (spurious) {
-+ GEDR2 = spurious;
-+ GRER2 &= ~(spurious & GPIO_2_80_spurious[2]);
-+ GFER2 &= ~(spurious & GPIO_2_80_spurious[2]);
-+ GPIO_2_80_spurious[2] |= spurious;
-+ gedr ^= spurious;
-+ if (!gedr) continue;
-+ }
-+
-+ for (i = 0; i < 17; ++i) {
-+ if (gedr & (1<<i)) {
-+ do_IRQ (IRQ_GPIO(64) + i, regs);
-+ }
-+ }
-+ }
-+}
-+
-+static struct irqaction GPIO_2_80_irqaction = {
-+ name: "GPIO 2-80",
-+ handler: pxa_GPIO_2_80_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+#define GRER_x(i) (*(&GRER0 + (i)))
-+#define GFER_x(i) (*(&GFER0 + (i)))
-+#define GEDR_x(i) (*(&GEDR0 + (i)))
-+#define GPLR_x(i) (*(&GPLR0 + (i)))
-+
-+static void pxa_mask_and_ack_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ GPIO_2_80_spurious[index] &= ~mask;
-+ GPIO_2_80_enabled[index] &= ~mask;
-+ GEDR_x(index) = mask;
-+}
-+
-+static void pxa_mask_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ GPIO_2_80_spurious[index] &= ~mask;
-+ GPIO_2_80_enabled[index] &= ~mask;
-+}
-+
-+static void pxa_unmask_GPIO_2_80_irq(unsigned int irq)
-+{
-+ int gpio_nr = IRQ_TO_GPIO_2_80(irq);
-+ int mask = 1 << (gpio_nr & 0x1f);
-+ int index = gpio_nr >> 5;
-+ if (GPIO_2_80_spurious[index] & mask) {
-+ /*
-+ * We don't want to miss an interrupt that would have occurred
-+ * while it was masked. Simulate it if it is the case.
-+ */
-+ int state = GPLR_x(index);
-+ if (((state & GPIO_IRQ_rising_edge[index]) |
-+ (~state & GPIO_IRQ_falling_edge[index])) & mask)
-+ {
-+ /* just in case it gets referenced: */
-+ struct pt_regs dummy;
-+
-+ memzero(&dummy, sizeof(dummy));
-+ do_IRQ(irq, &dummy);
-+
-+ /* we are being called recursively from do_IRQ() */
-+ return;
-+ }
-+ }
-+ GPIO_2_80_enabled[index] |= mask;
-+ GRER_x(index) =
-+ (GRER_x(index) & ~mask) | (GPIO_IRQ_rising_edge[index] & mask);
-+ GFER_x(index) =
-+ (GFER_x(index) & ~mask) | (GPIO_IRQ_falling_edge[index] & mask);
-+}
-+
-+
-+void __init pxa_init_irq(void)
-+{
-+ int irq;
-+
-+ /* disable all IRQs */
-+ ICMR = 0;
-+
-+ /* all IRQs are IRQ, not FIQ */
-+ ICLR = 0;
-+
-+ /* clear all GPIO edge detects */
-+ GFER0 = GFER1 = GFER2 = 0;
-+ GRER0 = GRER1 = GRER2 = 0;
-+ GEDR0 = GEDR0;
-+ GEDR1 = GEDR1;
-+ GEDR2 = GEDR2;
-+
-+ /* only unmasked interrupts kick us out of idle */
-+ ICCR = 1;
-+
-+ for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 0;
-+ irq_desc[irq].mask_ack = pxa_mask_irq;
-+ irq_desc[irq].mask = pxa_mask_irq;
-+ irq_desc[irq].unmask = pxa_unmask_irq;
-+ }
-+
-+ /*
-+ * Note: GPIO IRQs are initially invalid until set_GPIO_IRQ_edge()
-+ * is called at least once.
-+ */
-+
-+ for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-+ irq_desc[irq].valid = 0;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_0_1_irq;
-+ irq_desc[irq].mask = pxa_mask_GPIO_0_1_irq;
-+ irq_desc[irq].unmask = pxa_unmask_GPIO_0_1_irq;
-+ }
-+
-+ for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
-+ irq_desc[irq].valid = 0;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = pxa_mask_and_ack_GPIO_2_80_irq;
-+ irq_desc[irq].mask = pxa_mask_GPIO_2_80_irq;
-+ irq_desc[irq].unmask = pxa_unmask_GPIO_2_80_irq;
-+ }
-+ setup_arm_irq( IRQ_GPIO_2_80, &GPIO_2_80_irqaction );
-+}
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/leds-cerf.c
-@@ -0,0 +1,135 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-cerf.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void pxa_cerf_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = CERF_HEARTBEAT_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= CERF_HEARTBEAT_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= CERF_SYS_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~CERF_SYS_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= CERF_HEARTBEAT_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+#ifndef CONFIG_PXA_CERF_PDA
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~CERF_SYS_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= CERF_SYS_BUSY_LED;
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ {
-+ switch (hw_led_state) {
-+ case 0: // all on
-+ CERF_HEARTBEAT_LED_ON;
-+ CERF_SYS_BUSY_LED_ON;
-+ break;
-+ case 1: // turn off heartbeat, status on:
-+ CERF_HEARTBEAT_LED_OFF;
-+ CERF_SYS_BUSY_LED_ON;
-+ break;
-+ case 2: // status off, heartbeat on:
-+ CERF_HEARTBEAT_LED_ON;
-+ CERF_SYS_BUSY_LED_OFF;
-+ break;
-+ case 3: // turn them both off...
-+ CERF_HEARTBEAT_LED_OFF;
-+ CERF_SYS_BUSY_LED_OFF;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ local_irq_restore(flags);
-+}
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/leds-idp.c
-@@ -0,0 +1,112 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-idp.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * Macros for actual LED manipulation should be in machine specific
-+ * files in this 'mach' directory.
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void idp_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= IDP_HB_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= IDP_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~IDP_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~IDP_HB_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= IDP_HB_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~IDP_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= IDP_BUSY_LED;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ IDP_WRITE_LEDS(hw_led_state);
-+
-+ local_irq_restore(flags);
-+}
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/leds-lubbock.c
-@@ -0,0 +1,134 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds-lubbock.c
-+ *
-+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ * Original (leds-footbridge.c) by Russell King
-+ *
-+ * See leds.h for bit definitions. The first version defines D28 on the
-+ * Lubbock dev board as the heartbeat, and D27 as the Sys_busy led.
-+ * There's plenty more if you're interested in adding them :)
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/leds.h>
-+#include <asm/system.h>
-+
-+#include "leds.h"
-+
-+
-+#define LED_STATE_ENABLED 1
-+#define LED_STATE_CLAIMED 2
-+
-+static unsigned int led_state;
-+static unsigned int hw_led_state;
-+
-+void lubbock_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch (evt) {
-+ case led_start:
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ led_state = LED_STATE_ENABLED;
-+ break;
-+
-+ case led_stop:
-+ led_state &= ~LED_STATE_ENABLED;
-+ break;
-+
-+ case led_claim:
-+ led_state |= LED_STATE_CLAIMED;
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ break;
-+
-+ case led_release:
-+ led_state &= ~LED_STATE_CLAIMED;
-+ hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state ^= HEARTBEAT_LED;
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state |= SYS_BUSY_LED;
-+ break;
-+
-+ case led_idle_end:
-+ if (!(led_state & LED_STATE_CLAIMED))
-+ hw_led_state &= ~SYS_BUSY_LED;
-+ break;
-+#endif
-+
-+ case led_halted:
-+ break;
-+
-+ case led_green_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~HEARTBEAT_LED;
-+ break;
-+
-+ case led_green_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= HEARTBEAT_LED;
-+ break;
-+
-+ case led_amber_on:
-+ break;
-+
-+ case led_amber_off:
-+ break;
-+
-+ case led_red_on:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state &= ~SYS_BUSY_LED;
-+ break;
-+
-+ case led_red_off:
-+ if (led_state & LED_STATE_CLAIMED)
-+ hw_led_state |= SYS_BUSY_LED;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (led_state & LED_STATE_ENABLED)
-+ {
-+ switch (hw_led_state) {
-+ case 0: // all on
-+ HEARTBEAT_LED_ON;
-+ SYS_BUSY_LED_ON;
-+ break;
-+ case 1: // turn off heartbeat, status on:
-+ HEARTBEAT_LED_OFF;
-+ SYS_BUSY_LED_ON;
-+ break;
-+ case 2: // status off, heartbeat on:
-+ HEARTBEAT_LED_ON;
-+ SYS_BUSY_LED_OFF;
-+ break;
-+ case 3: // turn them both off...
-+ HEARTBEAT_LED_OFF;
-+ SYS_BUSY_LED_OFF;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ local_irq_restore(flags);
-+}
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/leds.c
-@@ -0,0 +1,32 @@
-+/*
-+ * linux/arch/arm/mach-pxa/leds.c
-+ *
-+ * xscale LEDs dispatcher
-+ *
-+ * Copyright (C) 2001 Nicolas Pitre
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
-+ */
-+#include <linux/config.h>
-+#include <linux/init.h>
-+
-+#include <asm/leds.h>
-+#include <asm/mach-types.h>
-+
-+#include "leds.h"
-+
-+static int __init
-+pxa_leds_init(void)
-+{
-+ if (machine_is_lubbock())
-+ leds_event = lubbock_leds_event;
-+ if (machine_is_pxa_idp())
-+ leds_event = idp_leds_event;
-+ if (machine_is_pxa_cerf())
-+ leds_event = pxa_cerf_leds_event;
-+
-+ leds_event(led_start);
-+ return 0;
-+}
-+
-+__initcall(pxa_leds_init);
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/leds.h
-@@ -0,0 +1,12 @@
-+/*
-+ * include/asm-arm/arch-pxa/leds.h
-+ *
-+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
-+ *
-+ * blinky lights for various PXA-based systems:
-+ *
-+ */
-+
-+extern void lubbock_leds_event(led_event_t evt);
-+extern void idp_leds_event(led_event_t evt);
-+extern void pxa_cerf_leds_event(led_event_t evt);
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/lubbock.c
-@@ -0,0 +1,157 @@
-+/*
-+ * linux/arch/arm/mach-pxa/lubbock.c
-+ *
-+ * Support for the Intel DBPXA250 Development Platform.
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/bitops.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "generic.h"
-+
-+#ifdef CONFIG_SA1111
-+ #include "sa1111.h"
-+#endif
-+
-+
-+static unsigned long lubbock_irq_enabled;
-+
-+static void lubbock_mask_irq(unsigned int irq)
-+{
-+ int lubbock_irq = (irq - LUBBOCK_IRQ(0));
-+ LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
-+}
-+
-+static void lubbock_unmask_irq(unsigned int irq)
-+{
-+ int lubbock_irq = (irq - LUBBOCK_IRQ(0));
-+ /* the irq can be acknowledged only if deasserted, so it's done here */
-+ LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
-+ LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
-+}
-+
-+void lubbock_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
-+ do {
-+ GEDR(0) = GPIO_bit(0); /* clear useless edge notification */
-+ if (likely(pending))
-+ do_IRQ( LUBBOCK_IRQ(0) + __ffs(pending), regs );
-+ pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
-+ } while (pending);
-+}
-+
-+static struct irqaction lubbock_irq = {
-+ name: "Lubbock FPGA",
-+ handler: lubbock_irq_demux,
-+ flags: SA_INTERRUPT
-+};
-+
-+static void __init lubbock_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ /* setup extra lubbock irqs */
-+ for(irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
-+ irq_desc[irq].valid = 1;
-+ irq_desc[irq].probe_ok = 1;
-+ irq_desc[irq].mask_ack = lubbock_mask_irq;
-+ irq_desc[irq].mask = lubbock_mask_irq;
-+ irq_desc[irq].unmask = lubbock_unmask_irq;
-+ }
-+
-+ set_GPIO_IRQ_edge(GPIO_LUBBOCK_IRQ, GPIO_FALLING_EDGE);
-+ setup_arm_irq(IRQ_GPIO_LUBBOCK_IRQ, &lubbock_irq);
-+}
-+
-+static int __init lubbock_init(void)
-+{
-+ int ret;
-+
-+ ret = sa1111_probe(LUBBOCK_SA1111_BASE);
-+ if (ret)
-+ return ret;
-+ sa1111_wake();
-+ sa1111_init_irq(LUBBOCK_SA1111_IRQ);
-+ return 0;
-+}
-+
-+__initcall(lubbock_init);
-+
-+static void __init
-+fixup_lubbock(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+ /* Some boards have 32MB some 64MB. Let's use a safe default */
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+ mi->nr_banks = 1;
-+}
-+
-+static struct map_desc lubbock_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
-+ { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
-+ LAST_DESC
-+};
-+
-+static void __init lubbock_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(lubbock_io_desc);
-+
-+ /* This enables the BTUART */
-+ CKEN |= CKEN7_BTUART;
-+ set_GPIO_mode(GPIO42_BTRXD_MD);
-+ set_GPIO_mode(GPIO43_BTTXD_MD);
-+ set_GPIO_mode(GPIO44_BTCTS_MD);
-+ set_GPIO_mode(GPIO45_BTRTS_MD);
-+
-+ /* This is for the SMC chip select */
-+ set_GPIO_mode(GPIO79_nCS_3_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform")
-+ MAINTAINER("MontaVista Software Inc.")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ FIXUP(fixup_lubbock)
-+ MAPIO(lubbock_map_io)
-+ INITIRQ(lubbock_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/pm.c
-@@ -0,0 +1,265 @@
-+/*
-+ * PXA250/210 Power Management Routines
-+ *
-+ * Original code for the SA11x0:
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * Modified for the PXA250 by Nicolas Pitre:
-+ * Copyright (c) 2002 Monta Vista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+
-+
-+/*
-+ * Debug macros
-+ */
-+#undef DEBUG
-+
-+extern void pxa_cpu_suspend(void);
-+extern void pxa_cpu_resume(void);
-+
-+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
-+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-+
-+/*
-+ * List of global PXA peripheral registers to preserve.
-+ * More ones like CP and general purpose register values are preserved
-+ * with the stack pointer in sleep.S.
-+ */
-+enum { SLEEP_SAVE_START = 0,
-+
-+ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
-+ SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
-+
-+ SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
-+ SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
-+ SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
-+ SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L,
-+ SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U,
-+
-+ SLEEP_SAVE_FFIER, SLEEP_SAVE_FFLCR, SLEEP_SAVE_FFMCR,
-+ SLEEP_SAVE_FFSPR, SLEEP_SAVE_FFISR,
-+ SLEEP_SAVE_FFDLL, SLEEP_SAVE_FFDLH,
-+
-+ SLEEP_SAVE_ICMR,
-+ SLEEP_SAVE_CKEN,
-+
-+ SLEEP_SAVE_CKSUM,
-+
-+ SLEEP_SAVE_SIZE
-+};
-+
-+
-+int pm_do_suspend(void)
-+{
-+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+ unsigned long checksum = 0;
-+ int i;
-+
-+ cli();
-+ clf();
-+
-+ leds_event(led_stop);
-+
-+ /* preserve current time */
-+ RCNR = xtime.tv_sec;
-+
-+ /*
-+ * Temporary solution. This won't be necessary once
-+ * we move pxa support into the serial/* driver
-+ * Save the FF UART
-+ */
-+ SAVE(FFIER);
-+ SAVE(FFLCR);
-+ SAVE(FFMCR);
-+ SAVE(FFSPR);
-+ SAVE(FFISR);
-+ FFLCR |= 0x80;
-+ SAVE(FFDLL);
-+ SAVE(FFDLH);
-+ FFLCR &= 0xef;
-+
-+ /* save vital registers */
-+ SAVE(OSCR);
-+ SAVE(OSMR0);
-+ SAVE(OSMR1);
-+ SAVE(OSMR2);
-+ SAVE(OSMR3);
-+ SAVE(OIER);
-+
-+ SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
-+ SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
-+ SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
-+ SAVE(GAFR0_L); SAVE(GAFR0_U);
-+ SAVE(GAFR1_L); SAVE(GAFR1_U);
-+ SAVE(GAFR2_L); SAVE(GAFR2_U);
-+
-+ SAVE(ICMR);
-+ ICMR = 0;
-+
-+ SAVE(CKEN);
-+ CKEN = 0;
-+
-+ /* Note: wake up source are set up in each machine specific files */
-+
-+ /* clear GPIO transition detect bits */
-+ GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
-+
-+ /* Clear sleep reset status */
-+ RCSR = RCSR_SMR;
-+
-+ /* set resume return address */
-+ PSPR = virt_to_phys(pxa_cpu_resume);
-+
-+ /* before sleeping, calculate and save a checksum */
-+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
-+ checksum += sleep_save[i];
-+ sleep_save[SLEEP_SAVE_CKSUM] = checksum;
-+
-+ /* *** go zzz *** */
-+ pxa_cpu_suspend();
-+
-+ /* after sleeping, validate the checksum */
-+ checksum = 0;
-+ for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
-+ checksum += sleep_save[i];
-+
-+ /* if invalid, display message and wait for a hardware reset */
-+ if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
-+#ifdef CONFIG_ARCH_LUBBOCK
-+ LUB_HEXLED = 0xbadbadc5;
-+#endif
-+ while (1);
-+ }
-+
-+ /* ensure not to come back here if it wasn't intended */
-+ PSPR = 0;
-+
-+ /* restore registers */
-+ RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
-+ RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
-+ RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
-+ RESTORE(GAFR0_L); RESTORE(GAFR0_U);
-+ RESTORE(GAFR1_L); RESTORE(GAFR1_U);
-+ RESTORE(GAFR2_L); RESTORE(GAFR2_U);
-+
-+ PSSR = PSSR_PH;
-+
-+ RESTORE(OSMR0);
-+ RESTORE(OSMR1);
-+ RESTORE(OSMR2);
-+ RESTORE(OSMR3);
-+ RESTORE(OSCR);
-+ RESTORE(OIER);
-+
-+ RESTORE(CKEN);
-+
-+ ICLR = 0;
-+ ICCR = 1;
-+ RESTORE(ICMR);
-+
-+ /*
-+ * Temporary solution. This won't be necessary once
-+ * we move pxa support into the serial/* driver.
-+ * Restore the FF UART.
-+ */
-+ RESTORE(FFMCR);
-+ RESTORE(FFSPR);
-+ RESTORE(FFLCR);
-+ FFLCR |= 0x80;
-+ RESTORE(FFDLH);
-+ RESTORE(FFDLL);
-+ RESTORE(FFLCR);
-+ RESTORE(FFISR);
-+ FFFCR = 0x07;
-+ RESTORE(FFIER);
-+
-+ /* restore current time */
-+ xtime.tv_sec = RCNR;
-+
-+#ifdef DEBUG
-+ printk(KERN_DEBUG "*** made it back from resume\n");
-+#endif
-+
-+ leds_event(led_start);
-+
-+ sti();
-+
-+ return 0;
-+}
-+
-+unsigned long sleep_phys_sp(void *sp)
-+{
-+ return virt_to_phys(sp);
-+}
-+
-+#ifdef CONFIG_SYSCTL
-+/*
-+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
-+ * linux/sysctl.h.
-+ *
-+ * This means our interface here won't survive long - it needs a new
-+ * interface. Quick hack to get this working - use sysctl id 9999.
-+ */
-+#warning ACPI broke the kernel, this interface needs to be fixed up.
-+#define CTL_ACPI 9999
-+#define ACPI_S1_SLP_TYP 19
-+
-+/*
-+ * Send us to sleep.
-+ */
-+static int sysctl_pm_do_suspend(void)
-+{
-+ int retval;
-+
-+ retval = pm_send_all(PM_SUSPEND, (void *)3);
-+
-+ if (retval == 0) {
-+ retval = pm_do_suspend();
-+
-+ pm_send_all(PM_RESUME, (void *)0);
-+ }
-+
-+ return retval;
-+}
-+
-+static struct ctl_table pm_table[] =
-+{
-+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
-+ {0}
-+};
-+
-+static struct ctl_table pm_dir_table[] =
-+{
-+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-+ {0}
-+};
-+
-+/*
-+ * Initialize power interface
-+ */
-+static int __init pm_init(void)
-+{
-+ register_sysctl_table(pm_dir_table, 1);
-+ return 0;
-+}
-+
-+__initcall(pm_init);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/pxa_usb.h
-@@ -0,0 +1,230 @@
-+/*
-+ * pxa_usb.h
-+ *
-+ * Public interface to the pxa USB core. For use by client modules
-+ * like usb-eth and usb-char.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100_usb.h
-+ *
-+ */
-+
-+#ifndef _PXA_USB_H
-+#define _PXA_USB_H
-+#include <asm/byteorder.h>
-+
-+typedef void (*usb_callback_t)(int flag, int size);
-+
-+/* in usb_ctl.c (see also descriptor methods at bottom of file) */
-+
-+// Open the USB client for client and initialize data structures
-+// to default values, but _do not_ start UDC.
-+int pxa_usb_open( const char * client_name );
-+
-+// Start UDC running
-+int pxa_usb_start( void );
-+
-+// Immediately stop udc, fire off completion routines w/-EINTR
-+int pxa_usb_stop( void ) ;
-+
-+// Disconnect client from usb core
-+int pxa_usb_close( void ) ;
-+
-+// set notify callback for when core reaches configured state
-+// return previous pointer (if any)
-+typedef void (*usb_notify_t)(void);
-+usb_notify_t pxa_set_configured_callback( usb_notify_t callback );
-+
-+/* in usb_send.c */
-+int pxa_usb_xmitter_avail( void );
-+int pxa_usb_send(char *buf, int len, usb_callback_t callback);
-+void sa110a_usb_send_reset(void);
-+
-+/* in usb_recev.c */
-+int pxa_usb_recv(char *buf, int len, usb_callback_t callback);
-+void pxa_usb_recv_reset(void);
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Descriptor Management
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define DescriptorHeader \
-+ __u8 bLength; \
-+ __u8 bDescriptorType
-+
-+
-+// --- Device Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bcdUSB; /* USB specification revision number in BCD */
-+ __u8 bDeviceClass; /* USB class for entire device */
-+ __u8 bDeviceSubClass; /* USB subclass information for entire device */
-+ __u8 bDeviceProtocol; /* USB protocol information for entire device */
-+ __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
-+ __u16 idVendor; /* USB vendor ID */
-+ __u16 idProduct; /* USB product ID */
-+ __u16 bcdDevice; /* vendor assigned device release number */
-+ __u8 iManufacturer; /* index of manufacturer string */
-+ __u8 iProduct; /* index of string that describes product */
-+ __u8 iSerialNumber; /* index of string containing device serial number */
-+ __u8 bNumConfigurations; /* number fo configurations */
-+} __attribute__ ((packed)) device_desc_t;
-+
-+// --- Configuration Descriptor ------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
-+ __u8 bNumInterfaces; /* number of interfaces in this cfg */
-+ __u8 bConfigurationValue; /* used to uniquely ID this cfg */
-+ __u8 iConfiguration; /* index of string describing configuration */
-+ __u8 bmAttributes; /* bitmap of attributes for ths cfg */
-+ __u8 MaxPower; /* power draw in 2ma units */
-+} __attribute__ ((packed)) config_desc_t;
-+
-+// bmAttributes:
-+enum {
-+ USB_CONFIG_REMOTEWAKE=0x20,
-+ USB_CONFIG_SELFPOWERED=0x40,
-+ USB_CONFIG_BUSPOWERED=0x80
-+};
-+
-+// MaxPower:
-+#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
-+
-+// --- Interface Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
-+ __u8 bAlternateSetting; /* ids an alternate setting for this interface */
-+ __u8 bNumEndpoints; /* number of endpoints in this interface */
-+ __u8 bInterfaceClass; /* USB class info applying to this interface */
-+ __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
-+ __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
-+ __u8 iInterface; /* index of string describing interface */
-+} __attribute__ ((packed)) intf_desc_t;
-+
-+// --- Endpoint Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
-+ __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
-+ __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
-+ __u8 bInterval; /* polling interval for this ep in this cfg */
-+} __attribute__ ((packed)) ep_desc_t;
-+
-+// bEndpointAddress:
-+enum {
-+ USB_OUT =0,
-+ USB_IN =1
-+};
-+
-+#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
-+// bmAttributes:
-+enum {
-+ USB_EP_CNTRL =0,
-+ USB_EP_BULK =2,
-+ USB_EP_INT =3,
-+ USB_EP_ISO =4
-+};
-+
-+// --- String Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
-+} __attribute__ ((packed)) string_desc_t;
-+
-+/*=======================================================
-+ * Handy helpers when working with above
-+ *
-+ */
-+// these are x86-style 16 bit "words" ...
-+#define make_word_c( w ) __constant_cpu_to_le16(w)
-+#define make_word( w ) __cpu_to_le16(w)
-+
-+// descriptor types
-+enum {
-+ USB_DESC_DEVICE = 1,
-+ USB_DESC_CONFIG = 2,
-+ USB_DESC_STRING = 3,
-+ USB_DESC_INTERFACE = 4,
-+ USB_DESC_ENDPOINT = 5
-+};
-+
-+
-+/*=======================================================
-+ * Default descriptor layout for SA-1100 and SA-1110 UDC
-+ */
-+
-+enum {
-+ UNUSED = 0,
-+
-+ BULK_IN1 = 1,
-+ BULK_OUT1 = 2,
-+ ISO_IN1 = 3,
-+ ISO_OUT1 = 4,
-+ INT_IN1 = 5,
-+
-+ BULK_IN2 = 6,
-+ BULK_OUT2 = 7,
-+ ISO_IN2 = 8,
-+ ISO_OUT2 = 9,
-+ INT_IN2 = 10,
-+
-+ BULK_IN3 = 11,
-+ BULK_OUT3 = 12,
-+ ISO_IN3 = 13,
-+ ISO_OUT3 = 14,
-+ INT_IN3 = 15
-+} /*endpoint_type*/;
-+
-+/* "config descriptor buffer" - that is, one config,
-+ ..one interface and 2 endpoints */
-+struct cdb {
-+ config_desc_t cfg;
-+ intf_desc_t intf;
-+ ep_desc_t ep1;
-+ ep_desc_t ep2;
-+} __attribute__ ((packed));
-+
-+/* all SA device descriptors */
-+typedef struct {
-+ device_desc_t dev; /* device descriptor */
-+ struct cdb b; /* bundle of descriptors for this cfg */
-+} __attribute__ ((packed)) desc_t;
-+
-+
-+/*=======================================================
-+ * Descriptor API
-+ */
-+
-+/* Get the address of the statically allocated desc_t structure
-+ in the usb core driver. Clients can modify this between
-+ the time they call pxa_usb_open() and pxa_usb_start()
-+*/
-+desc_t *
-+pxa_usb_get_descriptor_ptr( void );
-+
-+
-+/* Set a pointer to the string descriptor at "index". The driver
-+ ..has room for 8 string indicies internally. Index zero holds
-+ ..a LANGID code and is set to US English by default. Inidices
-+ ..1-7 are available for use in the config descriptors as client's
-+ ..see fit. This pointer is assumed to be good as long as the
-+ ..SA usb core is open (so statically allocate them). Returnes -EINVAL
-+ ..if index out of range */
-+int pxa_usb_set_string_descriptor( int index, string_desc_t * p );
-+
-+/* reverse of above */
-+string_desc_t *
-+pxa_usb_get_string_descriptor( int index );
-+
-+/* kmalloc() a string descriptor and convert "p" to unicode in it */
-+string_desc_t *
-+pxa_usb_kmalloc_string_descriptor( const char * p );
-+
-+#endif /* _PXA_USB_H */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/sa1111.c
-@@ -0,0 +1,3 @@
-+#include "../mach-sa1100/sa1111.c"
-+
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/sa1111.h
-@@ -0,0 +1,2 @@
-+#include "../mach-sa1100/sa1111.h"
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/sleep.S
-@@ -0,0 +1,150 @@
-+/*
-+ * Low-level PXA250/210 sleep/wakeUp support
-+ *
-+ * Initial SA1110 code:
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * Adapted for PXA by Nicolas Pitre:
-+ * Copyright (c) 2002 Monta Vista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/assembler.h>
-+#include <asm/hardware.h>
-+
-+ .text
-+
-+/*
-+ * pxa_cpu_suspend()
-+ *
-+ * Forces CPU into sleep state
-+ */
-+
-+ENTRY(pxa_cpu_suspend)
-+
-+ mra r2, r3, acc0
-+ stmfd sp!, {r2 - r12, lr} @ save registers on stack
-+
-+ @ get coprocessor registers
-+ mrc p15, 0, r4, c15, c1, 0 @ CP access reg
-+ mrc p15, 0, r5, c13, c0, 0 @ PID
-+ mrc p15, 0, r6, c3, c0, 0 @ domain ID
-+ mrc p15, 0, r7, c2, c0, 0 @ translation table base addr
-+ mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
-+ mrc p15, 0, r9, c1, c0, 0 @ control reg
-+
-+ @ store them plus current virtual stack ptr on stack
-+ mov r10, sp
-+ stmfd sp!, {r4 - r10}
-+
-+ @ preserve phys address of stack
-+ mov r0, sp
-+ bl sleep_phys_sp
-+ ldr r1, =sleep_save_sp
-+ str r0, [r1]
-+
-+ @ clean data cache
-+ bl cpu_xscale_cache_clean_invalidate_all
-+
-+ @ Put the processor to sleep
-+ @ (also workaround for sighting 28071)
-+
-+ @ prepare value for sleep mode
-+ mov r1, #3 @ sleep mode
-+
-+ @ prepare to put SDRAM into self-refresh manually
-+ ldr r4, =MDREFR
-+ ldr r5, [r4]
-+ orr r5, r5, #MDREFR_SLFRSH
-+
-+ @ prepare pointer to physical address 0 (virtual mapping in generic.c)
-+ mov r2, #UNCACHED_PHYS_0
-+
-+ @ align execution to a cache line
-+ b 1f
-+
-+ .ltorg
-+ .align 5
-+1:
-+
-+ @ All needed values are now in registers.
-+ @ These last instructions should be in cache
-+
-+ @ put SDRAM into self-refresh
-+ str r5, [r4]
-+
-+ @ force address lines low by reading at physical address 0
-+ ldr r3, [r2]
-+
-+ @ enter sleep mode
-+ mcr p14, 0, r1, c7, c0, 0
-+
-+20: nop
-+ b 20b @ loop waiting for sleep
-+
-+/*
-+ * cpu_pxa_resume()
-+ *
-+ * entry point from bootloader into kernel during resume
-+ *
-+ * Note: Yes, part of the following code is located into the .data section.
-+ * This is to allow sleep_save_sp to be accessed with a relative load
-+ * while we can't rely on any MMU translation. We could have put
-+ * sleep_save_sp in the .text section as well, but some setups might
-+ * insist on it to be truely read-only.
-+ */
-+
-+ .data
-+ .align 5
-+ENTRY(pxa_cpu_resume)
-+ mov r0, #I_BIT | F_BIT | MODE_SVC @ set SVC, irqs off
-+ msr cpsr_c, r0
-+
-+ ldr r0, sleep_save_sp @ stack phys addr
-+ ldr r2, =resume_after_mmu @ its absolute virtual address
-+ ldmfd r0, {r4 - r9, sp} @ CP regs + virt stack ptr
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB
-+
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bic r9, r9, #0x0004 @ see cpu_xscale_proc_init
-+#endif
-+
-+ mcr p15, 0, r4, c15, c1, 0 @ CP access reg
-+ mcr p15, 0, r5, c13, c0, 0 @ PID
-+ mcr p15, 0, r6, c3, c0, 0 @ domain ID
-+ mcr p15, 0, r7, c2, c0, 0 @ translation table base addr
-+ mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
-+ b resume_turn_on_mmu @ cache align execution
-+
-+ .align 5
-+resume_turn_on_mmu:
-+ mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, caches, etc.
-+
-+ @ Let us ensure we jump to resume_after_mmu only when the mcr above
-+ @ actually took effect. They call it the "cpwait" operation.
-+ mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15
-+ sub pc, r2, r1, lsr #32 @ jump to virtual addr
-+ nop
-+ nop
-+ nop
-+
-+sleep_save_sp:
-+ .word 0 @ preserve stack phys ptr here
-+
-+ .text
-+resume_after_mmu:
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bl cpu_xscale_proc_init
-+#endif
-+ ldmfd sp!, {r2, r3}
-+ mar acc0, r2, r3
-+ ldmfd sp!, {r4 - r12, pc} @ return to caller
-+
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/trizeps2.c
-@@ -0,0 +1,105 @@
-+/*
-+ * linux/arch/arm/mach-pxa/trizeps2.c
-+ *
-+ * Support for the Keith&Koep MT6N Development Platform.
-+ *
-+ * Author: Luc De Cock
-+ * Created: Jan 13, 2003
-+ * Copyright: Teradyne DS, Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/init.h>
-+#include <linux/major.h>
-+#include <linux/fs.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+
-+#include <asm/types.h>
-+#include <asm/setup.h>
-+#include <asm/memory.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/mach/irq.h>
-+
-+#include <asm/arch/irq.h>
-+
-+#include "generic.h"
-+
-+static unsigned long trizeps2_irq_en_mask;
-+unsigned short trizeps2_bcr_shadow = 0x50; // 0x70
-+
-+
-+static void __init trizeps2_init_irq(void)
-+{
-+ int irq;
-+
-+ pxa_init_irq();
-+
-+ set_GPIO_IRQ_edge(GPIO_ETHERNET_IRQ, GPIO_RISING_EDGE);
-+}
-+
-+static int __init trizeps2_init(void)
-+{
-+ /* Configure the BCR register */
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+
-+ *bcr = trizeps2_bcr_shadow;
-+ return 0;
-+}
-+
-+__initcall(trizeps2_init);
-+
-+static void __init
-+fixup_trizeps2(struct machine_desc *desc, struct param_struct *params,
-+ char **cmdline, struct meminfo *mi)
-+{
-+#ifdef TRIZEPS2_MEM_64MB
-+ SET_BANK (0, 0xa0000000, 64*1024*1024);
-+#else
-+ SET_BANK (0, 0xa0000000, 32*1024*1024);
-+#endif
-+ mi->nr_banks = 1;
-+}
-+
-+static struct map_desc trizeps2_io_desc[] __initdata = {
-+ /* virtual physical length domain r w c b */
-+ { 0xf0000000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* BCR */
-+ { 0xf0100000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA STATUS */
-+ { 0xf1000000, 0x0c800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
-+ { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
-+ { 0xf2000000, 0x0d800000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* TTL-IO */
-+ LAST_DESC
-+};
-+
-+static void __init trizeps2_map_io(void)
-+{
-+ pxa_map_io();
-+ iotable_init(trizeps2_io_desc);
-+
-+ /* This is for the SMC chip select */
-+ set_GPIO_mode(GPIO79_nCS_3_MD);
-+
-+ /* setup sleep mode values */
-+ PWER = 0x00000002;
-+ PFER = 0x00000000;
-+ PRER = 0x00000002;
-+ PGSR0 = 0x00008000;
-+ PGSR1 = 0x003F0202;
-+ PGSR2 = 0x0001C000;
-+ PCFR |= PCFR_OPDE;
-+}
-+
-+MACHINE_START(TRIZEPS2, "Keith-n-Koep MT6N Development Platform")
-+ MAINTAINER("Luc De Cock")
-+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
-+ FIXUP(fixup_trizeps2)
-+ MAPIO(trizeps2_map_io)
-+ INITIRQ(trizeps2_init_irq)
-+MACHINE_END
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb-char.c
-@@ -0,0 +1,719 @@
-+/*
-+ * (C) Copyright 2000-2001 Extenex Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * usb-char.c
-+ *
-+ * Miscellaneous character device interface for SA1100 USB function
-+ * driver.
-+ *
-+ * Background:
-+ * The SA1100 function driver ported from the Compaq Itsy project
-+ * has an interface, usb-eth.c, to feed network packets over the
-+ * usb wire and into the Linux TCP/IP stack.
-+ *
-+ * This file replaces that one with a simple character device
-+ * interface that allows unstructured "byte pipe" style reads and
-+ * writes over the USB bulk endpoints by userspace programs.
-+ *
-+ * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
-+ * when set, (the default) causes the ethernet interface to be used.
-+ * When not set, this more pedestrian character interface is linked
-+ * in instead.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ * ward.willats@extenex.com
-+ *
-+ * To do:
-+ * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
-+ * uses and get bytes out at the same time DMA is going on. Investigate:
-+ * a) changing usb_recv to use alloc_consistent() at client request; or
-+ * b) non-ring-buffer based data structures. In the meantime, I am using
-+ * a bounce buffer. Simple, but wasteful.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/cache.h>
-+#include <linux/poll.h>
-+#include <linux/circ_buf.h>
-+#include <linux/timer.h>
-+
-+#include <asm/io.h>
-+#include <asm/semaphore.h>
-+#include <asm/proc/page.h>
-+#include <asm/mach-types.h>
-+
-+#include "usb-char.h"
-+#include "pxa_usb.h"
-+
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Driver Options
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define VERSION "0.4"
-+
-+
-+#define VERBOSITY 1
-+
-+#if VERBOSITY
-+# define PRINTK(x, a...) printk (x, ## a)
-+#else
-+# define PRINTK(x, a...) /**/
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals - Macros - Enums - Structures
-+//////////////////////////////////////////////////////////////////////////////
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+typedef int bool; enum { false = 0, true = 1 };
-+
-+static const char pszMe[] = "usbchr: ";
-+
-+static wait_queue_head_t wq_read;
-+static wait_queue_head_t wq_write;
-+static wait_queue_head_t wq_poll;
-+
-+/* Serialze multiple writers onto the transmit hardware
-+.. since we sleep the writer during transmit to stay in
-+.. sync. (Multiple writers don't make much sense, but..) */
-+static DECLARE_MUTEX( xmit_sem );
-+
-+// size of usb DATA0/1 packets. 64 is standard maximum
-+// for bulk transport, though most hosts seem to be able
-+// to handle larger.
-+#define TX_PACKET_SIZE 64
-+#define RX_PACKET_SIZE 64
-+#define RBUF_SIZE (4*PAGE_SIZE)
-+
-+static struct wcirc_buf {
-+ char *buf;
-+ int in;
-+ int out;
-+} rx_ring = { NULL, 0, 0 };
-+
-+static struct {
-+ unsigned long cnt_rx_complete;
-+ unsigned long cnt_rx_errors;
-+ unsigned long bytes_rx;
-+ unsigned long cnt_tx_timeouts;
-+ unsigned long cnt_tx_errors;
-+ unsigned long bytes_tx;
-+} charstats;
-+
-+
-+static char * tx_buf = NULL;
-+static char * packet_buffer = NULL;
-+static int sending = 0;
-+static int usb_ref_count = 0;
-+static int last_tx_result = 0;
-+static int last_rx_result = 0;
-+static int last_tx_size = 0;
-+static struct timer_list tx_timer;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+static char * what_the_f( int e );
-+static void free_txrx_buffers( void );
-+static void twiddle_descriptors( void );
-+static void free_string_descriptors( void ) ;
-+static int usbc_open( struct inode *pInode, struct file *pFile );
-+static void rx_done_callback_packet_buffer( int flag, int size );
-+
-+static void tx_timeout( unsigned long );
-+static void tx_done_callback( int flag, int size );
-+
-+static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
-+static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument );
-+static int usbc_close( struct inode *pInode, struct file *pFile );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+static void extenex_configured_notify_proc( void );
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static char * what_the_f( int e )
-+{
-+ char * p;
-+ switch( e ) {
-+ case 0:
-+ p = "noErr";
-+ break;
-+ case -ENODEV:
-+ p = "ENODEV - usb not in config state";
-+ break;
-+ case -EBUSY:
-+ p = "EBUSY - another request on the hardware";
-+ break;
-+ case -EAGAIN:
-+ p = "EAGAIN";
-+ break;
-+ case -EINTR:
-+ p = "EINTR - interrupted\n";
-+ break;
-+ case -EPIPE:
-+ p = "EPIPE - zero length xfer\n";
-+ break;
-+ default:
-+ p = "????";
-+ break;
-+ }
-+ return p;
-+}
-+
-+static void free_txrx_buffers( void )
-+{
-+ if ( rx_ring.buf != NULL ) {
-+ kfree( rx_ring.buf );
-+ rx_ring.buf = NULL;
-+ }
-+ if ( packet_buffer != NULL ) {
-+ kfree( packet_buffer );
-+ packet_buffer = NULL;
-+ }
-+ if ( tx_buf != NULL ) {
-+ kfree( tx_buf );
-+ tx_buf = NULL;
-+ }
-+}
-+
-+/* twiddle_descriptors()
-+ * It is between open() and start(). Setup descriptors.
-+ */
-+static void twiddle_descriptors( void )
-+{
-+ desc_t * pDesc = pxa_usb_get_descriptor_ptr();
-+ string_desc_t * pString;
-+
-+ pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
-+ pDesc->b.ep1.bmAttributes = USB_EP_BULK;
-+ pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
-+ pDesc->b.ep2.bmAttributes = USB_EP_BULK;
-+
-+ if ( machine_is_extenex1() ) {
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ pDesc->dev.idVendor = make_word_c( 0xC9F );
-+ pDesc->dev.idProduct = 1;
-+ pDesc->dev.bcdDevice = make_word_c( 0x0001 );
-+ pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
-+ pDesc->b.cfg.MaxPower = 0;
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "Extenex" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 1, pString );
-+ pDesc->dev.iManufacturer = 1;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "Handheld Theater" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 2, pString );
-+ pDesc->dev.iProduct = 2;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "00000000" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 3, pString );
-+ pDesc->dev.iSerialNumber = 3;
-+ }
-+
-+ pString = pxa_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
-+ if ( pString ) {
-+ pxa_usb_set_string_descriptor( 4, pString );
-+ pDesc->b.intf.iInterface = 4;
-+ }
-+ pxa_set_configured_callback( extenex_configured_notify_proc );
-+#endif
-+ }
-+}
-+
-+static void free_string_descriptors( void )
-+{
-+ if ( machine_is_extenex1() ) {
-+ string_desc_t * pString;
-+ int i;
-+ for( i = 1 ; i <= 4 ; i++ ) {
-+ pString = pxa_usb_get_string_descriptor( i );
-+ if ( pString )
-+ kfree( pString );
-+ }
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// ASYNCHRONOUS
-+//////////////////////////////////////////////////////////////////////////////
-+static void kick_start_rx( void )
-+{
-+ if ( usb_ref_count ) {
-+ int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ if ( total_space >= RX_PACKET_SIZE ) {
-+ pxa_usb_recv( packet_buffer,
-+ RX_PACKET_SIZE,
-+ rx_done_callback_packet_buffer
-+ );
-+ }
-+ }
-+}
-+/*
-+ * rx_done_callback_packet_buffer()
-+ * We have completed a DMA xfer into the temp packet buffer.
-+ * Move to ring.
-+ *
-+ * flag values:
-+ * on init, -EAGAIN
-+ * on reset, -EINTR
-+ * on RPE, -EIO
-+ * on short packet -EPIPE
-+ */
-+static void
-+rx_done_callback_packet_buffer( int flag, int size )
-+{
-+ charstats.cnt_rx_complete++;
-+
-+ if ( flag == 0 || flag == -EPIPE ) {
-+ size_t n;
-+
-+ charstats.bytes_rx += size;
-+
-+ n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ n = MIN( n, size );
-+ size -= n;
-+
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
-+ rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
-+ rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
-+
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+
-+ last_rx_result = 0;
-+
-+ kick_start_rx();
-+
-+ } else if ( flag != -EAGAIN ) {
-+ charstats.cnt_rx_errors++;
-+ last_rx_result = flag;
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+ }
-+ else /* init, start a read */
-+ kick_start_rx();
-+}
-+
-+
-+static void tx_timeout( unsigned long unused )
-+{
-+ printk( "%stx timeout\n", pszMe );
-+ pxa_usb_send_reset();
-+ charstats.cnt_tx_timeouts++;
-+}
-+
-+
-+// on init, -EAGAIN
-+// on reset, -EINTR
-+// on TPE, -EIO
-+static void tx_done_callback( int flags, int size )
-+{
-+ if ( flags == 0 )
-+ charstats.bytes_tx += size;
-+ else
-+ charstats.cnt_tx_errors++;
-+ last_tx_size = size;
-+ last_tx_result = flags;
-+ sending = 0;
-+ wake_up_interruptible( &wq_write );
-+ wake_up_interruptible( &wq_poll );
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Workers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static int usbc_open( struct inode *pInode, struct file *pFile )
-+{
-+ int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
-+
-+ /* start usb core */
-+ retval = pxa_usb_open( "usb-char" );
-+ if ( retval ) return retval;
-+
-+ /* allocate memory */
-+ if ( usb_ref_count == 0 ) {
-+ tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+ if ( tx_buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.buf =
-+ (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
-+
-+ if ( rx_ring.buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+
-+ packet_buffer =
-+ (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+
-+ if ( packet_buffer == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.in = rx_ring.out = 0;
-+ memset( &charstats, 0, sizeof( charstats ) );
-+ sending = 0;
-+ last_tx_result = 0;
-+ last_tx_size = 0;
-+ }
-+
-+ /* modify default descriptors */
-+ twiddle_descriptors();
-+
-+ retval = pxa_usb_start();
-+ if ( retval ) {
-+ printk( "%sAGHH! Could not USB core\n", pszMe );
-+ free_txrx_buffers();
-+ return retval;
-+ }
-+ usb_ref_count++; /* must do _before_ kick_start() */
-+ MOD_INC_USE_COUNT;
-+ kick_start_rx();
-+ return 0;
-+
-+ malloc_fail:
-+ free_txrx_buffers();
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Read endpoint. Note that you can issue a read to an
-+ * unconfigured endpoint. Eventually, the host may come along
-+ * and configure underneath this module and data will appear.
-+ */
-+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval;
-+ int flags;
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%sread()\n", pszMe );
-+
-+ local_irq_save( flags );
-+ if ( last_rx_result == 0 ) {
-+ local_irq_restore( flags );
-+ } else { /* an error happended and receiver is paused */
-+ local_irq_restore( flags );
-+ last_rx_result = 0;
-+ kick_start_rx();
-+ }
-+
-+ add_wait_queue( &wq_read, &wait );
-+ while( 1 ) {
-+ ssize_t bytes_avail;
-+ ssize_t bytes_to_end;
-+
-+ set_current_state( TASK_INTERRUPTIBLE );
-+
-+ /* snap ring buf state */
-+ local_irq_save( flags );
-+ bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ local_irq_restore( flags );
-+
-+ if ( bytes_avail != 0 ) {
-+ ssize_t bytes_to_move = MIN( stCount, bytes_avail );
-+ retval = 0; // will be bytes transfered
-+ if ( bytes_to_move != 0 ) {
-+ size_t n = MIN( bytes_to_end, bytes_to_move );
-+ if ( copy_to_user( pUserBuffer,
-+ &rx_ring.buf[ rx_ring.out ],
-+ n ) ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ bytes_to_move -= n;
-+ retval += n;
-+ // might go 1 char off end, so wrap
-+ rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
-+ if ( copy_to_user( pUserBuffer + n,
-+ &rx_ring.buf[ rx_ring.out ],
-+ bytes_to_move )
-+ ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_ring.out += bytes_to_move; // cannot wrap
-+ retval += bytes_to_move;
-+ kick_start_rx();
-+ }
-+ break;
-+ }
-+ else if ( last_rx_result ) {
-+ retval = last_rx_result;
-+ break;
-+ }
-+ else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
-+ retval = -EAGAIN;
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) { // no data, can sleep, but signal
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule(); // no data, can sleep
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_read, &wait );
-+
-+ if ( retval < 0 )
-+ printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
-+ return retval;
-+}
-+
-+/*
-+ * Write endpoint. This routine attempts to break the passed in buffer
-+ * into usb DATA0/1 packet size chunks and send them to the host.
-+ * (The lower-level driver tries to do this too, but easier for us
-+ * to manage things here.)
-+ *
-+ * We are at the mercy of the host here, in that it must send an IN
-+ * token to us to pull this data back, so hopefully some higher level
-+ * protocol is expecting traffic to flow in that direction so the host
-+ * is actually polling us. To guard against hangs, a 5 second timeout
-+ * is used.
-+ *
-+ * This routine takes some care to only report bytes sent that have
-+ * actually made it across the wire. Thus we try to stay in lockstep
-+ * with the completion routine and only have one packet on the xmit
-+ * hardware at a time. Multiple simultaneous writers will get
-+ * "undefined" results.
-+ *
-+ */
-+static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval = 0;
-+ ssize_t stSent = 0;
-+
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
-+
-+ down( &xmit_sem ); // only one thread onto the hardware at a time
-+
-+ while( stCount != 0 && retval == 0 ) {
-+ int nThisTime = MIN( TX_PACKET_SIZE, stCount );
-+ copy_from_user( tx_buf, pUserBuffer, nThisTime );
-+ sending = nThisTime;
-+ retval = pxa_usb_send( tx_buf, nThisTime, tx_done_callback );
-+ if ( retval < 0 ) {
-+ char * p = what_the_f( retval );
-+ printk( "%sCould not queue xmission. rc=%d - %s\n",
-+ pszMe, retval, p );
-+ sending = 0;
-+ break;
-+ }
-+ /* now have something on the diving board */
-+ add_wait_queue( &wq_write, &wait );
-+ tx_timer.expires = jiffies + ( HZ * 5 );
-+ add_timer( &tx_timer );
-+ while( 1 ) {
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ if ( sending == 0 ) { /* it jumped into the pool */
-+ del_timer( &tx_timer );
-+ retval = last_tx_result;
-+ if ( retval == 0 ) {
-+ stSent += last_tx_size;
-+ pUserBuffer += last_tx_size;
-+ stCount -= last_tx_size;
-+ }
-+ else
-+ printk( "%sxmission error rc=%d - %s\n",
-+ pszMe, retval, what_the_f(retval) );
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) {
-+ del_timer( &tx_timer );
-+ printk( "%ssignal\n", pszMe );
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_write, &wait );
-+ }
-+
-+ up( &xmit_sem );
-+
-+ if ( 0 == retval )
-+ retval = stSent;
-+ return retval;
-+}
-+
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
-+{
-+ unsigned int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%poll()\n", pszMe );
-+
-+ poll_wait( pFile, &wq_poll, pWait );
-+
-+ if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
-+ retval |= POLLIN | POLLRDNORM;
-+ if ( pxa_usb_xmitter_avail() )
-+ retval |= POLLOUT | POLLWRNORM;
-+ return retval;
-+}
-+
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument )
-+{
-+ int retval = 0;
-+
-+ switch( nCmd ) {
-+
-+ case USBC_IOC_FLUSH_RECEIVER:
-+ pxa_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ break;
-+
-+ case USBC_IOC_FLUSH_TRANSMITTER:
-+ pxa_usb_send_reset();
-+ break;
-+
-+ case USBC_IOC_FLUSH_ALL:
-+ pxa_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ pxa_usb_send_reset();
-+ break;
-+
-+ default:
-+ retval = -ENOIOCTLCMD;
-+ break;
-+
-+ }
-+ return retval;
-+}
-+
-+
-+static int usbc_close( struct inode *pInode, struct file * pFile )
-+{
-+ PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
-+ if ( --usb_ref_count == 0 ) {
-+ down( &xmit_sem );
-+ pxa_usb_stop();
-+ free_txrx_buffers();
-+ free_string_descriptors();
-+ del_timer( &tx_timer );
-+ pxa_usb_close();
-+ up( &xmit_sem );
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+#include "../../../drivers/char/ex_gpio.h"
-+void extenex_configured_notify_proc( void )
-+{
-+ if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
-+ printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
-+}
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Initialization
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static struct file_operations usbc_fops = {
-+ owner: THIS_MODULE,
-+ open: usbc_open,
-+ read: usbc_read,
-+ write: usbc_write,
-+ poll: usbc_poll,
-+ ioctl: usbc_ioctl,
-+ release: usbc_close,
-+};
-+
-+static struct miscdevice usbc_misc_device = {
-+ USBC_MINOR, "usb_char", &usbc_fops
-+};
-+
-+/*
-+ * usbc_init()
-+ */
-+
-+int __init usbc_init( void )
-+{
-+ int rc;
-+
-+ if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
-+ printk( KERN_WARNING "%sCould not register device 10, "
-+ "%d. (%d)\n", pszMe, USBC_MINOR, rc );
-+ return -EBUSY;
-+ }
-+
-+ // initialize wait queues
-+ init_waitqueue_head( &wq_read );
-+ init_waitqueue_head( &wq_write );
-+ init_waitqueue_head( &wq_poll );
-+
-+ // initialize tx timeout timer
-+ init_timer( &tx_timer );
-+ tx_timer.function = tx_timeout;
-+
-+ printk( KERN_INFO "USB Function Character Driver Interface"
-+ " - %s, (C) 2001, Extenex Corp.\n", VERSION
-+ );
-+
-+ return rc;
-+}
-+
-+void __exit usbc_exit( void )
-+{
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(usbc_init);
-+module_exit(usbc_exit);
-+
-+
-+
-+// end: usb-char.c
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb-char.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2001 Extenex Corporation
-+ *
-+ * usb-char.h
-+ *
-+ * Character device emulation client for SA-1100 client usb core.
-+ *
-+ *
-+ *
-+ */
-+#ifndef _USB_CHAR_H
-+#define _USB_CHAR_H
-+
-+#define USBC_MAJOR 10 /* miscellaneous character device */
-+#define USBC_MINOR 240 /* in the "reserved for local use" range */
-+
-+#define USBC_MAGIC 0x8E
-+
-+/* zap everything in receive ring buffer */
-+#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
-+
-+/* reset transmitter */
-+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
-+
-+/* do both of above */
-+#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
-+
-+
-+
-+
-+
-+
-+#endif /* _USB_CHAR_H */
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb-eth.c
-@@ -0,0 +1,479 @@
-+/*
-+ * Ethernet driver for the PXA USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original initial ethernet test driver
-+ * Copyright (c) Compaq Computer Corporation, 1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
-+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
-+ * Now, since we do not know what size of packet we are receiving
-+ * last usb packet in sequence will always be less than max packet
-+ * receive endpoint can accept.
-+ * Now the only way to check correct start of frame is to compare
-+ * MAC address. Also now we are stalling on each receive error.
-+ *
-+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
-+ * aligned buffer, but this breaks IP code (unaligned access).
-+ *
-+ * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
-+ * they are disabled now.
-+ *
-+ * 03/06/2001 - Readded "zerocopy" receive path (tunable).
-+ *
-+ */
-+
-+// Define DMA_NO_COPY if you want data to arrive directly into the
-+// receive network buffers, instead of arriving into bounce buffer
-+// and then get copied to network buffer.
-+// This does not work correctly right now.
-+#undef DMA_NO_COPY
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/timer.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/random.h>
-+
-+#include "pxa_usb.h"
-+
-+
-+#define ETHERNET_VENDOR_ID 0x49f
-+#define ETHERNET_PRODUCT_ID 0x505A
-+#define MAX_PACKET 32768
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+
-+// Should be global, so that insmod can change these
-+int usb_rsize=64;
-+int usb_wsize=64;
-+
-+static struct usbe_info_t {
-+ struct net_device *dev;
-+ u16 packet_id;
-+ struct net_device_stats stats;
-+} usbe_info;
-+
-+static char usb_eth_name[16] = "usbf";
-+static struct net_device usb_eth_device;
-+static struct sk_buff *cur_tx_skb, *next_tx_skb;
-+static struct sk_buff *cur_rx_skb, *next_rx_skb;
-+static volatile int terminating;
-+#ifndef DMA_NO_COPY
-+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
-+#endif
-+
-+static int usb_change_mtu (struct net_device *net, int new_mtu)
-+{
-+ if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
-+ return -EINVAL;
-+ // no second zero-length packet read wanted after mtu-sized packets
-+ if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
-+ return -EDOM;
-+
-+ net->mtu = new_mtu;
-+ return 0;
-+}
-+
-+static struct sk_buff *
-+usb_new_recv_skb(void)
-+{
-+ struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
-+
-+ if (skb) {
-+ skb_reserve(skb, 2);
-+ }
-+ return skb;
-+}
-+
-+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
-+static void
-+usb_recv_callback(int flag, int size)
-+{
-+ struct sk_buff *skb;
-+
-+ if (terminating)
-+ return;
-+
-+ skb = cur_rx_skb;
-+
-+ /* flag validation */
-+ if (flag == 0) {
-+ if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
-+ usbe_info.stats.rx_over_errors++;
-+ goto error;
-+ }
-+#ifndef DMA_NO_COPY
-+ memcpy(skb->tail,dmabuf,size);
-+#endif
-+ skb_put(skb, size);
-+ } else {
-+ if (flag == -EIO) {
-+ usbe_info.stats.rx_errors++;
-+ }
-+ goto error;
-+ }
-+
-+
-+ /*
-+ * If the real size of the packet is divisible by usb_rsize
-+ * an extra byte will be added. Thus size == usb_rsize
-+ * should only happen if more data is to come.
-+ */
-+ /* validate packet length */
-+ if (size == usb_rsize ) {
-+ /* packet not complete yet */
-+ skb = NULL;
-+ }
-+
-+ /*
-+ * At this point skb is non null if we have a complete packet.
-+ * If so take a fresh skb right away and restart USB receive without
-+ * further delays, then process the packet. Otherwise resume USB
-+ * receive on the current skb and exit.
-+ */
-+
-+ if (skb)
-+ cur_rx_skb = next_rx_skb;
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize,
-+ usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ if (!skb)
-+ return;
-+
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!next_rx_skb) {
-+ /*
-+ * We can't aford loosing buffer space...
-+ * So we drop the current packet and recycle its skb.
-+ */
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ usbe_info.stats.rx_dropped++;
-+ skb_trim(skb, 0);
-+ next_rx_skb = skb;
-+ return;
-+ }
-+ if ( skb->len >= sizeof(struct ethhdr)) {
-+ if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
-+ // This frame is not for us. nor it is broadcast
-+ usbe_info.stats.rx_frame_errors++;
-+ kfree_skb(skb);
-+ goto error;
-+ }
-+
-+#if 0
-+{
-+ int i;
-+
-+ for (i = 0; i < skb->len; i++)
-+ {
-+ printk("%02X ", skb->data[i]);
-+ if( (i%8)==7) printk("\n");
-+ }
-+ printk("...\n");
-+}
-+#endif
-+
-+ }
-+
-+ if (skb->len) {
-+ int status;
-+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
-+
-+ skb->dev = &usb_eth_device;
-+ skb->protocol = eth_type_trans (skb, &usb_eth_device);
-+ usbe_info.stats.rx_packets++;
-+ usbe_info.stats.rx_bytes += skb->len;
-+ skb->ip_summed = CHECKSUM_NONE;
-+ status = netif_rx (skb);
-+ if (status != NET_RX_SUCCESS)
-+ printk("netif_rx failed with code %d\n",status);
-+ } else {
-+error:
-+//printk("ERROR... tailroom=%d size=%d len=%d flag=%d\n", skb_tailroom(skb), size, skb->len, flag);
-+ /*
-+ * Error due to HW addr mismatch, or IO error.
-+ * Recycle the current skb and reset USB reception.
-+ */
-+ skb_trim(cur_rx_skb, 0);
-+// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
-+#endif
-+ }
-+}
-+
-+
-+static void
-+usb_send_callback(int flag, int size)
-+{
-+ struct net_device *dev = usbe_info.dev;
-+ struct net_device_stats *stats;
-+ struct sk_buff *skb=cur_tx_skb;
-+ int ret;
-+
-+ if (terminating)
-+ return;
-+
-+ stats = &usbe_info.stats;
-+ switch (flag) {
-+ case 0:
-+ stats->tx_packets++;
-+ stats->tx_bytes += size;
-+ break;
-+ case -EIO:
-+ stats->tx_errors++;
-+ break;
-+ default:
-+ stats->tx_dropped++;
-+ break;
-+ }
-+
-+ cur_tx_skb = next_tx_skb;
-+ next_tx_skb = NULL;
-+ dev_kfree_skb_irq(skb);
-+ if (!cur_tx_skb)
-+ return;
-+
-+ dev->trans_start = jiffies;
-+ ret = pxa_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb_irq(cur_tx_skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ netif_wake_queue(dev);
-+}
-+
-+static int
-+usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ int ret;
-+ long flags;
-+
-+ if (next_tx_skb) {
-+ printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
-+ return 1;
-+ }
-+
-+ if (skb_shared (skb)) {
-+ struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
-+ if (!skb2) {
-+ usbe_info.stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 1;
-+ }
-+ skb = skb2;
-+ }
-+
-+ if ((skb->len % usb_wsize) == 0) {
-+ skb->len++; // other side will ignore this one, anyway.
-+ }
-+
-+ save_flags_cli(flags);
-+ if (cur_tx_skb) {
-+ next_tx_skb = skb;
-+ netif_stop_queue(dev);
-+ } else {
-+ cur_tx_skb = skb;
-+ dev->trans_start = jiffies;
-+ ret = pxa_usb_send(skb->data, skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb(skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ }
-+ restore_flags(flags);
-+ return 0;
-+}
-+
-+static void
-+usb_xmit_timeout(struct net_device *dev )
-+{
-+ pxa_usb_send_reset();
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+
-+static int
-+usb_eth_open(struct net_device *dev)
-+{
-+ int rc;
-+ rc = pxa_usb_open( "usb-eth" );
-+ if ( rc == 0 ) {
-+ string_desc_t * pstr;
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+
-+ pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
-+ pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
-+ pd->dev.idVendor = ETHERNET_VENDOR_ID;
-+ pd->dev.idProduct = ETHERNET_PRODUCT_ID;
-+ pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" );
-+ if ( pstr ) {
-+ pxa_usb_set_string_descriptor( 1, pstr );
-+ pd->dev.iProduct = 1;
-+ }
-+ rc = pxa_usb_start();
-+ }
-+
-+ if( rc == 0)
-+ {
-+ terminating = 0;
-+ cur_tx_skb = next_tx_skb = NULL;
-+ cur_rx_skb = usb_new_recv_skb();
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!cur_rx_skb || !next_rx_skb) {
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+
-+ pxa_usb_stop();
-+ pxa_usb_close();
-+ return -ENOMEM;;
-+ }
-+
-+ MOD_INC_USE_COUNT;
-+#ifndef DMA_NO_COPY
-+ pxa_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ pxa_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ }
-+
-+ return rc;
-+}
-+
-+static int
-+usb_eth_release(struct net_device *dev)
-+{
-+ string_desc_t * pstr;
-+
-+ terminating = 1;
-+ pxa_usb_send_reset();
-+ pxa_usb_recv_reset();
-+ if (cur_tx_skb)
-+ kfree_skb(cur_tx_skb);
-+ if (next_tx_skb)
-+ kfree_skb(next_tx_skb);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+
-+ pxa_usb_stop();
-+ pxa_usb_close();
-+ if ( (pstr = pxa_usb_get_string_descriptor(1)) != NULL )
-+ kfree( pstr );
-+
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static struct net_device_stats *
-+usb_eth_stats(struct net_device *dev)
-+{
-+ struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
-+ struct net_device_stats *stats=NULL;
-+
-+ if (priv)
-+ stats = &priv->stats;
-+ return stats;
-+}
-+
-+static int
-+usb_eth_probe(struct net_device *dev)
-+{
-+ u8 node_id [ETH_ALEN];
-+
-+ get_random_bytes (node_id, sizeof node_id);
-+ node_id [0] &= 0xfe; // clear multicast bit
-+
-+ /*
-+ * Assign the hardware address of the board:
-+ * generate it randomly, as there can be many such
-+ * devices on the bus.
-+ */
-+ memcpy (dev->dev_addr, node_id, sizeof node_id);
-+
-+ dev->open = usb_eth_open;
-+ dev->change_mtu = usb_change_mtu;
-+ dev->stop = usb_eth_release;
-+ dev->hard_start_xmit = usb_eth_xmit;
-+ dev->get_stats = usb_eth_stats;
-+ dev->watchdog_timeo = 1*HZ;
-+ dev->tx_timeout = usb_xmit_timeout;
-+ dev->priv = &usbe_info;
-+
-+ usbe_info.dev = dev;
-+
-+ /* clear the statistics */
-+ memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
-+
-+ ether_setup(dev);
-+ dev->flags &= ~IFF_MULTICAST;
-+ dev->flags &= ~IFF_BROADCAST;
-+ //dev->flags |= IFF_NOARP;
-+
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+MODULE_PARM(usb_rsize, "1i");
-+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to pxa");
-+MODULE_PARM(usb_wsize, "1i");
-+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from pxa to host");
-+#endif
-+
-+static int __init
-+usb_eth_init(void)
-+{
-+#ifndef DMA_NO_COPY
-+ dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
-+ if (!dmabuf)
-+ return -ENOMEM;
-+#endif
-+ strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
-+ usb_eth_device.init = usb_eth_probe;
-+ if (register_netdev(&usb_eth_device) != 0)
-+ return -EIO;
-+
-+ printk( KERN_INFO "USB Function Ethernet Driver Interface\n");
-+
-+ return 0;
-+}
-+
-+static void __exit
-+usb_eth_cleanup(void)
-+{
-+#ifndef DMA_NO_COPY
-+ kfree(dmabuf);
-+#endif
-+ unregister_netdev(&usb_eth_device);
-+}
-+
-+module_init(usb_eth_init);
-+module_exit(usb_eth_cleanup);
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_ctl.c
-@@ -0,0 +1,769 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation, 2001
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * PXA USB controller core driver.
-+ *
-+ * This file provides interrupt routing and overall coordination
-+ * of the endpoints.
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for more info.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+
-+int usbctl_next_state_on_event( int event );
-+static void udc_int_hndlr(int, void *, struct pt_regs *);
-+static void initialize_descriptors( void );
-+static void soft_connect_hook( int enable );
-+static void udc_disable(void);
-+static void udc_enable(void);
-+
-+#if CONFIG_PROC_FS
-+#define PROC_NODE_NAME "driver/pxausb"
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals
-+//////////////////////////////////////////////////////////////////////////////
-+static const char pszMe[] = "usbctl: ";
-+struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
-+
-+/* device descriptors */
-+static desc_t desc;
-+
-+#define MAX_STRING_DESC 8
-+static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
-+static string_desc_t sd_zero; /* special sd_zero holds language codes */
-+
-+// called when configured
-+static usb_notify_t configured_callback = NULL;
-+
-+enum {
-+ kStateZombie = 0,
-+ kStateZombieSuspend = 1,
-+ kStateDefault = 2,
-+ kStateDefaultSuspend = 3,
-+ kStateAddr = 4,
-+ kStateAddrSuspend = 5,
-+ kStateConfig = 6,
-+ kStateConfigSuspend = 7
-+};
-+
-+/*
-+ * FIXME: The PXA UDC handles several host device requests without user
-+ * notification/intervention. The table could be collapsed quite a bit...
-+ */
-+static int device_state_machine[8][6] = {
-+// suspend reset resume adddr config deconfig
-+/* zombie */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError },
-+/* zom sus */ { kStateZombieSuspend , kStateDefault, kStateZombie , kError , kError , kError },
-+/* default */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kStateAddr, kStateConfig, kError },
-+/* def sus */ { kStateDefaultSuspend, kStateDefault, kStateDefault, kError , kError , kError },
-+/* addr */ { kStateAddrSuspend , kStateDefault, kStateAddr , kError , kStateConfig, kError },
-+/* addr sus */{ kStateAddrSuspend , kStateDefault, kStateAddr , kError , kError , kError },
-+/* config */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kStateDefault },
-+/* cfg sus */ { kStateConfigSuspend , kStateDefault, kStateConfig , kError , kError , kError }
-+};
-+
-+/* "device state" is the usb device framework state, as opposed to the
-+ "state machine state" which is whatever the driver needs and is much
-+ more fine grained
-+*/
-+static int sm_state_to_device_state[8] = {
-+// zombie zom suspend
-+USB_STATE_POWERED, USB_STATE_SUSPENDED,
-+// default default sus
-+USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
-+// addr addr sus
-+USB_STATE_ADDRESS, USB_STATE_SUSPENDED,
-+// config config sus
-+USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
-+};
-+
-+static char * state_names[8] =
-+{ "zombie", "zombie suspended",
-+ "default", "default suspended",
-+ "address", "address suspended",
-+ "configured", "config suspended"
-+};
-+
-+static char * event_names[6] =
-+{ "suspend", "reset", "resume",
-+ "address assigned", "configure", "de-configure"
-+};
-+
-+static char * device_state_names[] =
-+{ "not attached", "attached", "powered", "default",
-+ "address", "configured", "suspended" };
-+
-+static int sm_state = kStateZombie;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Async
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* The UDCCR reg contains mask and interrupt status bits,
-+ * so using '|=' isn't safe as it may ack an interrupt.
-+ */
-+
-+void udc_set_mask_UDCCR( int mask )
-+{
-+ UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
-+}
-+
-+void udc_clear_mask_UDCCR( int mask)
-+{
-+ UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
-+}
-+
-+void udc_ack_int_UDCCR( int mask)
-+{
-+ /* udccr contains the bits we dont want to change */
-+ __u32 udccr = UDCCR & UDCCR_MASK_BITS;
-+
-+ UDCCR = udccr | (mask & ~UDCCR_MASK_BITS);
-+}
-+
-+static void
-+udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ __u32 status = UDCCR;
-+ __u32 ir0_status = USIR0;
-+ __u32 ir1_status = USIR1;
-+ __u32 uicr0 = UICR0;
-+ __u32 uicr1 = UICR1;
-+
-+ //mask ints
-+ udc_set_mask_UDCCR( UDCCR_REM | UDCCR_SRM);
-+ UICR0 = 0xff;
-+ UICR1 = 0xff;
-+
-+ if( usb_debug > 2)
-+ {
-+ printk("%s--- udc_int_hndlr\n"
-+ "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
-+ "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n",
-+ pszMe, status, UDCCS0, UDCCS1, UDCCS2, ir0_status, ir1_status, uicr0, uicr1);
-+ }
-+
-+ /* SUSpend Interrupt Request */
-+ if ( status & UDCCR_SUSIR )
-+ {
-+ udc_ack_int_UDCCR( UDCCR_SUSIR);
-+ if( usb_debug) printk("%sSuspend...\n", pszMe);
-+ usbctl_next_state_on_event( kEvSuspend );
-+ }
-+
-+ /* RESume Interrupt Request */
-+ if ( status & UDCCR_RESIR )
-+ {
-+ udc_ack_int_UDCCR( UDCCR_RESIR);
-+ if( usb_debug) printk("%sResume...\n", pszMe);
-+ usbctl_next_state_on_event( kEvResume );
-+ }
-+
-+ /* ReSeT Interrupt Request - UDC has been reset */
-+ if ( status & UDCCR_RSTIR )
-+ {
-+ /* clear the reset interrupt */
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+
-+ /* check type of reset */
-+ if( (UDCCR & UDCCR_UDA) == 0)
-+ {
-+ /* reset assertion took place, nothing to do */
-+ if( usb_debug) printk("%sReset assertion...\n", pszMe);
-+ }
-+
-+ /* ok, it's a reset negation, go on with reset */
-+ else if ( usbctl_next_state_on_event( kEvReset ) != kError )
-+ {
-+ /* starting reset sequence now... */
-+ if( usb_debug) printk("%sResetting\n", pszMe);
-+
-+ ep0_reset();
-+ ep_bulk_in1_reset();
-+ ep_bulk_out1_reset();
-+
-+ usbctl_next_state_on_event( kEvConfig );
-+ }
-+ else
-+ {
-+ printk("%sUnexpected reset\n", pszMe);
-+ }
-+ }
-+ else
-+ {
-+ /* ep0 int */
-+ if (ir0_status & USIR0_IR0)
-+ ep0_int_hndlr();
-+
-+ /* transmit bulk */
-+ if (ir0_status & USIR0_IR1)
-+ ep_bulk_in1_int_hndlr(ir0_status);
-+
-+ /* receive bulk */
-+ if ( ir0_status & USIR0_IR2)
-+ ep_bulk_out1_int_hndlr(ir0_status);
-+
-+ while (UDCCS2 & UDCCS_BO_RNE)
-+ {
-+ if( usb_debug) printk("More Bulk-out data...\n");
-+ ep_bulk_out1_int_hndlr(ir0_status);
-+ }
-+ }
-+
-+ UICR0 = uicr0;
-+ UICR1 = uicr1;
-+ udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM); /* enable suspend/resume, reset */
-+
-+ /* clear all endpoint ints */
-+ USIR0 |= 0xff;
-+ USIR1 |= 0xff;
-+
-+ if( usb_debug > 2)
-+ {
-+ printk("%sudc_int_hndlr\n"
-+ "UDCCR=0x%08x UDCCS0=0x%08x UDCCS1=0x%08x UDCCS2=0x%08x\n"
-+ "USIR0=0x%08x USIR1=0x%08x UICR0=0x%08x UICR1=0x%08x\n",
-+ pszMe, UDCCR, UDCCS0, UDCCS1, UDCCS2, USIR0, USIR1, UICR0, UICR1);
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Public Interface
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* Open PXA usb core on behalf of a client, but don't start running */
-+
-+int
-+pxa_usb_open( const char * client )
-+{
-+ if ( usbd_info.client_name != NULL )
-+ {
-+ printk( "%sUnable to register %s (%s already registered).\n",
-+ pszMe, client, usbd_info.client_name );
-+ return -EBUSY;
-+ }
-+
-+ usbd_info.client_name = (char*) client;
-+ memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
-+ memset(string_desc_array, 0, sizeof(string_desc_array));
-+
-+ /* hack to start in zombie suspended state */
-+ sm_state = kStateZombieSuspend;
-+ usbd_info.state = USB_STATE_SUSPENDED;
-+
-+ /* create descriptors for enumeration */
-+ initialize_descriptors();
-+
-+ printk( "%s%s registered.\n", pszMe, client );
-+ return 0;
-+}
-+
-+/* Start running. Must have called usb_open (above) first */
-+int
-+pxa_usb_start( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+
-+ /* start UDC internal machinery running */
-+ udc_enable();
-+ udelay( 100 );
-+
-+ /* flush DMA and fire through some -EAGAINs */
-+ ep_bulk_out1_init( usbd_info.dmach_rx );
-+ ep_bulk_in1_init( usbd_info.dmach_tx );
-+
-+ /* give endpoint notification we are starting */
-+ ep_bulk_out1_state_change_notify( USB_STATE_SUSPENDED );
-+ ep_bulk_in1_state_change_notify( USB_STATE_SUSPENDED );
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* enable suspend/resume, reset */
-+ udc_clear_mask_UDCCR( UDCCR_SRM | UDCCR_REM);
-+ /* enable ep0, ep1, ep2 */
-+ UICR0 &= ~(UICR0_IM0 | UICR0_IM1 | UICR0_IM2);
-+
-+ if( usb_debug) printk( "%sStarted %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Stop USB core from running */
-+int
-+pxa_usb_stop( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ /* mask everything */
-+ /* disable suspend/resume, reset */
-+ udc_set_mask_UDCCR( UDCCR_SRM | UDCCR_REM);
-+ /* disable ep0, ep1, ep2 */
-+ UICR0 |= (UICR0_IM0 | UICR0_IM1 | UICR0_IM2);
-+
-+ ep_bulk_out1_reset();
-+ ep_bulk_in1_reset();
-+
-+ udc_disable();
-+ if( usb_debug) printk( "%sStopped %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Tell PXA core client is through using it */
-+int
-+pxa_usb_close( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ printk( "%s%s closed.\n", pszMe, (char*)usbd_info.client_name );
-+ usbd_info.client_name = NULL;
-+ return 0;
-+}
-+
-+/* set a proc to be called when device is configured */
-+usb_notify_t pxa_set_configured_callback( usb_notify_t func )
-+{
-+ usb_notify_t retval = configured_callback;
-+ configured_callback = func;
-+ return retval;
-+}
-+
-+/*====================================================
-+ * Descriptor Manipulation.
-+ * Use these between open() and start() above to setup
-+ * the descriptors for your device.
-+ *
-+ */
-+
-+/* get pointer to static default descriptor */
-+desc_t *
-+pxa_usb_get_descriptor_ptr( void ) { return &desc; }
-+
-+/* optional: set a string descriptor */
-+int
-+pxa_usb_set_string_descriptor( int i, string_desc_t * p )
-+{
-+ int retval;
-+ if ( i < MAX_STRING_DESC ) {
-+ string_desc_array[i] = p;
-+ retval = 0;
-+ } else {
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+/* optional: get a previously set string descriptor */
-+string_desc_t *
-+pxa_usb_get_string_descriptor( int i )
-+{
-+ return ( i < MAX_STRING_DESC )
-+ ? string_desc_array[i]
-+ : NULL;
-+}
-+
-+
-+/* optional: kmalloc and unicode up a string descriptor */
-+string_desc_t *
-+pxa_usb_kmalloc_string_descriptor( const char * p )
-+{
-+ string_desc_t * pResult = NULL;
-+
-+ if ( p ) {
-+ int len = strlen( p );
-+ int uni_len = len * sizeof( __u16 );
-+ pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
-+ if ( pResult != NULL ) {
-+ int i;
-+ pResult->bLength = uni_len + 2;
-+ pResult->bDescriptorType = USB_DESC_STRING;
-+ for( i = 0; i < len ; i++ ) {
-+ pResult->bString[i] = make_word( (__u16) p[i] );
-+ }
-+ }
-+ }
-+ return pResult;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Exports to rest of driver
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* called by the int handler here and the two endpoint files when interesting
-+ .."events" happen */
-+
-+int
-+usbctl_next_state_on_event( int event )
-+{
-+ int next_state = device_state_machine[ sm_state ][ event ];
-+ if ( next_state != kError )
-+ {
-+ int next_device_state = sm_state_to_device_state[ next_state ];
-+ if( usb_debug) printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ],
-+ state_names[ next_state ], device_state_names[ next_device_state ] );
-+
-+ sm_state = next_state;
-+ if ( usbd_info.state != next_device_state )
-+ {
-+ if ( configured_callback != NULL
-+ &&
-+ next_device_state == USB_STATE_CONFIGURED
-+ &&
-+ usbd_info.state != USB_STATE_SUSPENDED
-+ ) {
-+ configured_callback();
-+ }
-+ usbd_info.state = next_device_state;
-+
-+ ep_bulk_out1_state_change_notify( next_device_state );
-+ ep_bulk_in1_state_change_notify( next_device_state );
-+ }
-+ }
-+#if 1
-+ else
-+ printk( "%s%s --> [%s] --> ??? is an error.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ] );
-+#endif
-+ return next_state;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* setup default descriptors */
-+
-+static void
-+initialize_descriptors(void)
-+{
-+ desc.dev.bLength = sizeof( device_desc_t );
-+ desc.dev.bDescriptorType = USB_DESC_DEVICE;
-+ desc.dev.bcdUSB = 0x100; /* 1.0 */
-+ desc.dev.bDeviceClass = 0xFF; /* vendor specific */
-+ desc.dev.bDeviceSubClass = 0;
-+ desc.dev.bDeviceProtocol = 0;
-+ desc.dev.bMaxPacketSize0 = 16; /* ep0 max fifo size */
-+ desc.dev.idVendor = 0; /* vendor ID undefined */
-+ desc.dev.idProduct = 0; /* product */
-+ desc.dev.bcdDevice = 0; /* vendor assigned device release num */
-+ desc.dev.iManufacturer = 0; /* index of manufacturer string */
-+ desc.dev.iProduct = 0; /* index of product description string */
-+ desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
-+ desc.dev.bNumConfigurations = 1;
-+
-+ desc.b.cfg.bLength = sizeof( config_desc_t );
-+ desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
-+ desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
-+ desc.b.cfg.bNumInterfaces = 1;
-+ desc.b.cfg.bConfigurationValue = 1;
-+ desc.b.cfg.iConfiguration = 0;
-+ desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
-+ desc.b.cfg.MaxPower = USB_POWER( 500 );
-+
-+ desc.b.intf.bLength = sizeof( intf_desc_t );
-+ desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
-+ desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
-+ desc.b.intf.bAlternateSetting = 0;
-+ desc.b.intf.bNumEndpoints = 2;
-+ desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
-+ desc.b.intf.bInterfaceSubClass = 0;
-+ desc.b.intf.bInterfaceProtocol = 0;
-+ desc.b.intf.iInterface = 0;
-+
-+/*
-+ * FIXME...
-+ * The host usbnet driver expects EP1=out EP2=in. On the PXA UDC EP1=in, EP2=out
-+ */
-+ desc.b.ep1.bLength = sizeof( ep_desc_t );
-+ desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_IN );
-+ desc.b.ep1.bmAttributes = USB_EP_BULK;
-+ desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep1.bInterval = 0;
-+
-+ desc.b.ep2.bLength = sizeof( ep_desc_t );
-+ desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_OUT );
-+ desc.b.ep2.bmAttributes = USB_EP_BULK;
-+ desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep2.bInterval = 0;
-+
-+// FIXME: Add support for all endpoint...
-+
-+ /* set language */
-+ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
-+ sd_zero.bDescriptorType = USB_DESC_STRING;
-+ sd_zero.bLength = sizeof( string_desc_t );
-+ sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
-+ pxa_usb_set_string_descriptor( 0, &sd_zero );
-+}
-+
-+/* soft_connect_hook()
-+ * Some devices have platform-specific circuitry to make USB
-+ * not seem to be plugged in, even when it is. This allows
-+ * software to control when a device 'appears' on the USB bus
-+ * (after Linux has booted and this driver has loaded, for
-+ * example). If you have such a circuit, control it here.
-+ */
-+static void
-+soft_connect_hook( int enable )
-+{
-+}
-+
-+/* disable the UDC at the source */
-+static void
-+udc_disable(void)
-+{
-+ soft_connect_hook( 0 );
-+ /* clear UDC-enable */
-+ udc_clear_mask_UDCCR( UDCCR_UDE);
-+
-+ /* Disable clock for USB device */
-+ CKEN &= ~CKEN11_USB;
-+}
-+
-+
-+/* enable the udc at the source */
-+static void
-+udc_enable(void)
-+{
-+ /* Enable clock for USB device */
-+ CKEN |= CKEN11_USB;
-+
-+ /* try to clear these bits before we enable the udc */
-+ udc_ack_int_UDCCR( UDCCR_SUSIR);
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+ udc_ack_int_UDCCR( UDCCR_RESIR);
-+
-+ /* set UDC-enable */
-+ udc_set_mask_UDCCR( UDCCR_UDE);
-+ if( (UDCCR & UDCCR_UDA) == 0)
-+ {
-+ /* There's a reset on the bus,
-+ * clear the interrupt bit and keep going
-+ */
-+ udc_ack_int_UDCCR( UDCCR_RSTIR);
-+ }
-+
-+ /* "USB test mode" to work around errata 40-42 (stepping a0, a1)
-+ * which could result in missing packets and interrupts.
-+ * Supposedly this turns off double buffering for all endpoints.
-+ */
-+ if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
-+ UDC_RES1 = 0x00;
-+ UDC_RES2 = 0x00;
-+ if( usb_debug) printk( "USB RES1=%x RES2=%x RES3=%x\n", UDC_RES1, UDC_RES2, UDC_RES3);
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Proc Filesystem Support
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#if CONFIG_PROC_FS
-+
-+#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
-+#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
-+#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
-+#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
-+
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ const char * num_fmt = "%25.25s: %8.8lX\n";
-+ const char * cnt_fmt = "%25.25s: %lu\n";
-+ const char * yn_fmt = "%25.25s: %s\n";
-+ const char * yes = "YES";
-+ const char * no = "NO";
-+ unsigned long v;
-+ char * p = page;
-+ int len;
-+
-+ SAY( "PXA USB Controller Core\n" );
-+ SAY( "Active Client: %s\n", usbd_info.client_name ? usbd_info.client_name : "none");
-+ SAY( "USB state: %s (%s) %d\n",
-+ device_state_names[ sm_state_to_device_state[ sm_state ] ],
-+ state_names[ sm_state ],
-+ sm_state );
-+
-+ SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
-+ SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
-+ SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
-+ SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
-+
-+ SAY( "\n" );
-+
-+ v = UDCCR;
-+ SAY( "\nUDC Control Register\n" );
-+ SAYV( v );
-+ SAYC( "UDC Enabled", ( v & UDCCR_UDE ) ? yes : no );
-+ SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
-+ SAYC( "Suspend/Resume interrupts masked", ( v & UDCCR_SRM ) ? yes : no );
-+ SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
-+ SAYC( "Reset pending", ( v & UDCCR_RSTIR ) ? yes : no );
-+ SAYC( "Suspend pending", ( v & UDCCR_SUSIR ) ? yes : no );
-+ SAYC( "Resume pending", ( v & UDCCR_RESIR ) ? yes : no );
-+
-+ len = ( p - page ) - off;
-+ if ( len < 0 )
-+ len = 0;
-+ *eof = ( len <=count ) ? 1 : 0;
-+ *start = page + off;
-+ return len;
-+}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+#if 0
-+static void irq_handler(int channel, void *data, struct pt_regs *regs)
-+{
-+ if( channel == usbd_info.dmach_rx)
-+ {
-+ printk( "USB receive DMA\n");
-+ }
-+ else if( channel == usbd_info.dmach_tx)
-+ {
-+ printk( "USB transmit DMA\n");
-+ }
-+ else
-+ {
-+ printk( "USB unknown DMA channel\n");
-+ }
-+}
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Module Initialization and Shutdown
-+//////////////////////////////////////////////////////////////////////////////
-+/*
-+ * usbctl_init()
-+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs
-+ * entry. Leave UDC disabled.
-+ */
-+int __init usbctl_init( void )
-+{
-+ int retval = 0;
-+
-+ udc_disable();
-+
-+ memset( &usbd_info, 0, sizeof( usbd_info ) );
-+
-+#if CONFIG_PROC_FS
-+ create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
-+#endif
-+
-+#if 0
-+ /* setup rx dma */
-+ usbd_info.dmach_rx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
-+ if (usbd_info.dmach_rx < 0) {
-+ printk("%sunable to register for rx dma rc=%d\n", pszMe, usbd_info.dmach_rx );
-+ goto err_rx_dma;
-+ }
-+
-+ /* setup tx dma */
-+ usbd_info.dmach_tx = pxa_request_dma("USB receive", DMA_PRIO_MEDIUM, irq_handler, 0 /*data; DMA_Ser0UDCRd*/);
-+ if (usbd_info.dmach_tx < 0) {
-+ printk("%sunable to register for tx dma rc=%d\n",pszMe,usbd_info.dmach_tx);
-+ goto err_tx_dma;
-+ }
-+#endif
-+
-+ /* now allocate the IRQ. */
-+ retval = request_irq(IRQ_USB, udc_int_hndlr, SA_INTERRUPT, "PXA USB core", NULL);
-+ if (retval) {
-+ printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
-+ goto err_irq;
-+ }
-+
-+ printk( "PXA USB Controller Core Initialized\n");
-+ return 0;
-+
-+err_irq:
-+#if 0
-+ pxa_free_dma(usbd_info.dmach_tx);
-+ usbd_info.dmach_tx = 0;
-+err_tx_dma:
-+ pxa_free_dma(usbd_info.dmach_rx);
-+ usbd_info.dmach_rx = 0;
-+err_rx_dma:
-+#endif
-+ return retval;
-+}
-+/*
-+ * usbctl_exit()
-+ * Release DMA and interrupt resources
-+ */
-+void __exit usbctl_exit( void )
-+{
-+ printk("Unloading PXA USB Controller\n");
-+
-+ udc_disable();
-+
-+#if CONFIG_PROC_FS
-+ remove_proc_entry ( PROC_NODE_NAME, NULL);
-+#endif
-+
-+ pxa_free_dma(usbd_info.dmach_rx);
-+ pxa_free_dma(usbd_info.dmach_tx);
-+ free_irq(IRQ_USB, NULL);
-+}
-+
-+module_init( usbctl_init );
-+module_exit( usbctl_exit );
-+
-+EXPORT_SYMBOL( pxa_usb_open );
-+EXPORT_SYMBOL( pxa_usb_start );
-+EXPORT_SYMBOL( pxa_usb_stop );
-+EXPORT_SYMBOL( pxa_usb_close );
-+EXPORT_SYMBOL( pxa_usb_get_descriptor_ptr );
-+EXPORT_SYMBOL( pxa_usb_set_string_descriptor );
-+EXPORT_SYMBOL( pxa_usb_get_string_descriptor );
-+EXPORT_SYMBOL( pxa_usb_kmalloc_string_descriptor );
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_ctl.h
-@@ -0,0 +1,89 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation 2001
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * usb_ctl.h
-+ *
-+ * PRIVATE interface used to share info among components of the PXA USB
-+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
-+ * should use pxa_usb.h.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.h
-+ *
-+ */
-+
-+#ifndef _USB_CTL_H
-+#define _USB_CTL_H
-+
-+/* Interrupt mask bits and UDC enable bit */
-+#define UDCCR_MASK_BITS (UDCCR_REM | UDCCR_SRM | UDCCR_UDE)
-+
-+/*
-+ * These states correspond to those in the USB specification v1.0
-+ * in chapter 8, Device Framework.
-+ */
-+enum {
-+ USB_STATE_NOTATTACHED =0,
-+ USB_STATE_ATTACHED =1,
-+ USB_STATE_POWERED =2,
-+ USB_STATE_DEFAULT =3,
-+ USB_STATE_ADDRESS =4,
-+ USB_STATE_CONFIGURED =5,
-+ USB_STATE_SUSPENDED =6
-+};
-+
-+struct usb_stats_t {
-+ unsigned long ep0_fifo_write_failures;
-+ unsigned long ep0_bytes_written;
-+ unsigned long ep0_fifo_read_failures;
-+ unsigned long ep0_bytes_read;
-+};
-+
-+struct usb_info_t
-+{
-+ char * client_name;
-+ dmach_t dmach_tx, dmach_rx;
-+ int state;
-+ unsigned char address;
-+ struct usb_stats_t stats;
-+};
-+
-+/* in usb_ctl.c */
-+extern struct usb_info_t usbd_info;
-+
-+/*
-+ * Function Prototypes
-+ */
-+enum {
-+ kError =-1,
-+ kEvSuspend =0,
-+ kEvReset =1,
-+ kEvResume =2,
-+ kEvAddress =3,
-+ kEvConfig =4,
-+ kEvDeConfig =5
-+};
-+int usbctl_next_state_on_event( int event );
-+
-+/* endpoint zero */
-+void ep0_reset(void);
-+void ep0_int_hndlr(void);
-+
-+/* receiver */
-+void ep_bulk_out1_state_change_notify( int new_state );
-+int ep_bulk_out1_recv(void);
-+int ep_bulk_out1_init(int chn);
-+void ep_bulk_out1_int_hndlr(int status);
-+void ep_bulk_out1_reset(void);
-+void ep_bulk_out1_stall(void);
-+
-+/* xmitter */
-+void ep_bulk_in1_state_change_notify( int new_state );
-+void ep_bulk_in1_reset(void);
-+int ep_bulk_in1_init(int chn);
-+void ep_bulk_in1_int_hndlr(int status);
-+void ep_bulk_in1_stall(void);
-+
-+#endif /* _USB_CTL_H */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_ep0.c
-@@ -0,0 +1,556 @@
-+/*
-+ * Copyright (C) Extenex Corporation 2001
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * PXA USB controller driver - Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for more info.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+
-+#include "pxa_usb.h" /* public interface */
-+#include "usb_ctl.h" /* private stuff */
-+#include "usb_ep0.h"
-+
-+
-+// 1 == lots of trace noise, 0 = only "important' stuff
-+#define VERBOSITY 0
-+
-+enum { true = 1, false = 0 };
-+typedef int bool;
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+#if 1 && !defined( ASSERT )
-+# define ASSERT(expr) \
-+if(!(expr)) { \
-+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-+#expr,__FILE__,__FUNCTION__,__LINE__); \
-+}
-+#else
-+# define ASSERT(expr)
-+#endif
-+
-+#if VERBOSITY
-+#define PRINTKD(fmt, args...) printk( fmt , ## args)
-+#else
-+#define PRINTKD(fmt, args...)
-+#endif
-+
-+static EP0_state ep0_state = EP0_IDLE;
-+
-+/***************************************************************************
-+ Prototypes
-+ ***************************************************************************/
-+/* "setup handlers" -- the main functions dispatched to by the
-+ .. isr. These represent the major "modes" of endpoint 0 operation */
-+static void sh_setup_begin(void); /* setup begin (idle) */
-+static void sh_write( void ); /* writing data */
-+static int read_fifo( usb_dev_request_t * p );
-+static void write_fifo( void );
-+static void get_descriptor( usb_dev_request_t * pReq );
-+static void queue_and_start_write( void * p, int req, int act );
-+
-+/***************************************************************************
-+ Inline Helpers
-+ ***************************************************************************/
-+
-+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
-+
-+/* print string descriptor */
-+static inline void psdesc( string_desc_t * p )
-+{
-+ int i;
-+ int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
-+ printk( "'" );
-+ for( i = 0 ; i < nchars ; i++ ) {
-+ printk( "%c", (char) p->bString[i] );
-+ }
-+ printk( "'\n" );
-+}
-+
-+#if VERBOSITY
-+/* "pcs" == "print control status" */
-+static inline void pcs( void )
-+{
-+ __u32 foo = UDCCS0;
-+ printk( "%08x: %s %s %s %s %s %s\n",
-+ foo,
-+ foo & UDCCS0_SA ? "SA" : "",
-+ foo & UDCCS0_OPR ? "OPR" : "",
-+ foo & UDCCS0_RNE ? "RNE" : "",
-+ foo & UDCCS0_SST ? "SST" : "",
-+ foo & UDCCS0_FST ? "FST" : "",
-+ foo & UDCCS0_DRWF ? "DRWF" : ""
-+ );
-+}
-+static inline void preq( usb_dev_request_t * pReq )
-+{
-+ static char * tnames[] = { "dev", "intf", "ep", "oth" };
-+ static char * rnames[] = { "std", "class", "vendor", "???" };
-+ char * psz;
-+ switch( pReq->bRequest ) {
-+ case GET_STATUS: psz = "get stat"; break;
-+ case CLEAR_FEATURE: psz = "clr feat"; break;
-+ case SET_FEATURE: psz = "set feat"; break;
-+ case SET_ADDRESS: psz = "set addr"; break;
-+ case GET_DESCRIPTOR: psz = "get desc"; break;
-+ case SET_DESCRIPTOR: psz = "set desc"; break;
-+ case GET_CONFIGURATION: psz = "get cfg"; break;
-+ case SET_CONFIGURATION: psz = "set cfg"; break;
-+ case GET_INTERFACE: psz = "get intf"; break;
-+ case SET_INTERFACE: psz = "set intf"; break;
-+ case SYNCH_FRAME: psz = "synch frame"; break;
-+ default: psz = "unknown"; break;
-+ }
-+ printk( "- [%s: %s req to %s. dir=%s]\n", psz,
-+ rnames[ (pReq->bmRequestType >> 5) & 3 ],
-+ tnames[ pReq->bmRequestType & 3 ],
-+ ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
-+}
-+
-+#else
-+static inline void pcs( void ){}
-+static inline void preq( usb_dev_request_t *x){}
-+#endif
-+
-+/***************************************************************************
-+ Globals
-+ ***************************************************************************/
-+static const char pszMe[] = "usbep0: ";
-+
-+/* pointer to current setup handler */
-+static void (*current_handler)(void) = sh_setup_begin;
-+
-+/* global write struct to keep write
-+ ..state around across interrupts */
-+static struct {
-+ unsigned char *p;
-+ int bytes_left;
-+} wr;
-+
-+/***************************************************************************
-+ Public Interface
-+ ***************************************************************************/
-+
-+/* reset received from HUB (or controller just went nuts and reset by itself!)
-+ so udc core has been reset, track this state here */
-+void ep0_reset(void)
-+{
-+ PRINTKD( "%sep0_reset\n", pszMe);
-+ /* reset state machine */
-+ current_handler = sh_setup_begin;
-+ wr.p = NULL;
-+ wr.bytes_left = 0;
-+ usbd_info.address=0;
-+}
-+
-+/* handle interrupt for endpoint zero */
-+void ep0_int_hndlr( void )
-+{
-+ PRINTKD( "%sep0_int_hndlr\n", pszMe);
-+ pcs();
-+ (*current_handler)();
-+}
-+
-+/***************************************************************************
-+ Setup Handlers
-+ ***************************************************************************/
-+/*
-+ * sh_setup_begin()
-+ * This setup handler is the "idle" state of endpoint zero. It looks for OPR
-+ * (OUT packet ready) to see if a setup request has been been received from the
-+ * host.
-+ *
-+ */
-+static void sh_setup_begin( void )
-+{
-+ usb_dev_request_t req;
-+ int request_type;
-+ int n;
-+ __u32 cs_reg_in = UDCCS0;
-+
-+ PRINTKD( "%ssh_setup_begin\n", pszMe);
-+
-+ /* Be sure out packet ready, otherwise something is wrong */
-+ if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
-+ /* we can get here early...if so, we'll int again in a moment */
-+ PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ if( ((cs_reg_in & UDCCS0_SA) == 0) && (ep0_state == EP0_IN_DATA_PHASE))
-+ {
-+ PRINTKD( "%ssetup begin: premature status\n", pszMe );
-+
-+ /* premature status, reset tx fifo and go back to idle state*/
-+ UDCCS0 = UDCCS0_OPR | UDCCS0_FTF;
-+
-+ ep0_state = EP0_IDLE;
-+ return;
-+ }
-+
-+ if( (UDCCS0 & UDCCS0_RNE) == 0)
-+ {
-+ /* zero-length OUT? */
-+ printk( "%ssetup begin: zero-length OUT?\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ /* read the setup request */
-+ n = read_fifo( &req );
-+ if ( n != sizeof( req ) ) {
-+ printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
-+ " Stalling out...\n",
-+ pszMe, sizeof( req ), n );
-+ /* force stall, serviced out */
-+ UDCCS0 = UDCCS0_FST;
-+ goto sh_sb_end;
-+ }
-+
-+ /* Is it a standard request? (not vendor or class request) */
-+ request_type = type_code_from_request( req.bmRequestType );
-+ if ( request_type != 0 ) {
-+ printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
-+ pszMe, request_type );
-+ goto sh_sb_end;
-+ }
-+
-+#if VERBOSITY
-+ {
-+ unsigned char * pdb = (unsigned char *) &req;
-+ PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
-+ pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
-+ );
-+ preq( &req );
-+ }
-+#endif
-+
-+ /* Handle it */
-+ switch( req.bRequest ) {
-+
-+ case SET_ADDRESS:
-+ PRINTKD( "%sSET_ADDRESS handled by UDC\n", pszMe);
-+ break;
-+#if 0 /* NOT_NEEDED */
-+
-+ case SET_FEATURE:
-+ PRINTKD( "%sSET_FEATURE handled by UDC\n", pszMe);
-+ break;
-+
-+ case CLEAR_FEATURE:
-+ PRINTKD( "%sCLEAR_FEATURE handled by UDC\n", pszMe);
-+ break;
-+
-+ case GET_CONFIGURATION:
-+ PRINTKD( "%sGET_CONFIGURATION handled by UDC\n", pszMe );
-+ break;
-+
-+ case GET_STATUS:
-+ PRINTKD( "%s%sGET_STATUS handled by UDC\n", pszMe );
-+ break;
-+
-+ case GET_INTERFACE:
-+ PRINTKD( "%sGET_INTERFACE handled by UDC\n", pszMe);
-+ break;
-+
-+ case SYNCH_FRAME:
-+ PRINTKD( "%sSYNCH_FRAME handled by UDC\n", pszMe );
-+ break;
-+#endif
-+
-+ case GET_DESCRIPTOR:
-+ PRINTKD( "%sGET_DESCRIPTOR\n", pszMe );
-+ get_descriptor( &req );
-+ break;
-+
-+ case SET_INTERFACE:
-+ PRINTKD( "%sSET_INTERFACE TODO...\n", pszMe);
-+ break;
-+
-+ case SET_DESCRIPTOR:
-+ PRINTKD( "%sSET_DESCRIPTOR TODO...\n", pszMe );
-+ break;
-+
-+ case SET_CONFIGURATION:
-+ PRINTKD( "%sSET_CONFIGURATION %d\n", pszMe, req.wValue);
-+
-+/*
-+ * FIXME: Something is not quite right here... I only ever get a
-+ * de-configure from the host. Ignoring it for now, since usb
-+ * ethernet won't do anything unless usb is 'configured'.
-+ *
-+ */
-+#if 0
-+ switch( req.wValue)
-+ {
-+ case 0:
-+ /* configured */
-+ usbctl_next_state_on_event( kEvConfig );
-+ break;
-+ case 1:
-+ /* de-configured */
-+ usbctl_next_state_on_event( kEvDeConfig );
-+ break;
-+ default:
-+ PRINTKD( "%sSET_CONFIGURATION: unknown configuration value (%d)\n", pszMe, req.wValue);
-+ break;
-+ }
-+#endif
-+ break;
-+ default :
-+ printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
-+ break;
-+ } /* switch( bRequest ) */
-+
-+sh_sb_end:
-+ return;
-+}
-+
-+/*
-+ * sh_write()
-+ *
-+ * Due to UDC bugs we push everything into the fifo in one go.
-+ * Using interrupts just didn't work right...
-+ * This should be ok, since control request are small.
-+ */
-+static void sh_write()
-+{
-+ PRINTKD( "sh_write\n" );
-+ do
-+ {
-+ write_fifo();
-+ } while( ep0_state != EP0_END_XFER);
-+}
-+
-+/***************************************************************************
-+ Other Private Subroutines
-+ ***************************************************************************/
-+/*
-+ * queue_and_start_write()
-+ * data == data to send
-+ * req == bytes host requested
-+ * act == bytes we actually have
-+ *
-+ * Sets up the global "wr"-ite structure and load the outbound FIFO
-+ * with data.
-+ *
-+ */
-+static void queue_and_start_write( void * data, int req, int act )
-+{
-+ PRINTKD( "write start: bytes requested=%d actual=%d\n", req, act);
-+
-+ wr.p = (unsigned char*) data;
-+ wr.bytes_left = MIN( act, req );
-+
-+ ep0_state = EP0_IN_DATA_PHASE;
-+ sh_write();
-+
-+ return;
-+}
-+/*
-+ * write_fifo()
-+ * Stick bytes in the endpoint zero FIFO.
-+ *
-+ */
-+static void write_fifo( void )
-+{
-+ int bytes_this_time = MIN( wr.bytes_left, EP0_FIFO_SIZE );
-+ int bytes_written = 0;
-+
-+ while( bytes_this_time-- ) {
-+// PRINTKD( "%2.2X ", *wr.p );
-+ UDDR0 = *wr.p++;
-+ bytes_written++;
-+ }
-+ wr.bytes_left -= bytes_written;
-+
-+ usbd_info.stats.ep0_bytes_written += bytes_written;
-+
-+ if( (wr.bytes_left==0))
-+ {
-+ wr.p = NULL; /* be anal */
-+
-+ if(bytes_written < EP0_FIFO_SIZE)
-+ {
-+ int count;
-+ int udccs0;
-+
-+ /* We always end the transfer with a short or zero length packet */
-+ ep0_state = EP0_END_XFER;
-+ current_handler = sh_setup_begin;
-+
-+ /* Let the packet go... */
-+ UDCCS0 = UDCCS0_IPR;
-+
-+ /* Wait until we get to status-stage, then ack.
-+ *
-+ * When the UDC sets the UDCCS0[OPR] bit, an interrupt
-+ * is supposed to be generated (see 12.5.1 step 14ff, PXA Dev Manual).
-+ * That approach didn't work out. Usually a new SETUP command was
-+ * already in the fifo. I tried many approaches but was always losing
-+ * at least some OPR interrupts. Thus the polling below...
-+ */
-+ count = 1000;
-+ udccs0 = UDCCS0;
-+ do
-+ {
-+ if( (UDCCS0 & UDCCS0_OPR))
-+ {
-+ /* clear OPR, generate ack */
-+ UDCCS0 = UDCCS0_OPR;
-+ break;
-+ }
-+ count--;
-+ udelay(1);
-+ } while( count);
-+
-+ PRINTKD( "write fifo: count=%d UDCCS0=%x UDCCS0=%x\n", count, udccs0, UDCCS0);
-+ }
-+ }
-+ /* something goes poopy if I dont wait here ... */
-+ udelay(500);
-+
-+ PRINTKD( "write fifo: bytes sent=%d, bytes left=%d\n", bytes_written, wr.bytes_left);
-+}
-+
-+/*
-+ * read_fifo()
-+ * Read bytes out of FIFO and put in request.
-+ * Called to do the initial read of setup requests
-+ * from the host. Return number of bytes read.
-+ *
-+ */
-+static int read_fifo( usb_dev_request_t * request )
-+{
-+ int bytes_read = 0;
-+ unsigned char * pOut = (unsigned char*) request;
-+
-+ int udccs0 = UDCCS0;
-+
-+ if( (udccs0 & SETUP_READY) == SETUP_READY)
-+ {
-+ /* ok it's a setup command */
-+ while( UDCCS0 & UDCCS0_RNE)
-+ {
-+ if( bytes_read >= sizeof( usb_dev_request_t))
-+ {
-+ /* We've already read enought o fill usb_dev_request_t.
-+ * Our tummy is full. Go barf...
-+ */
-+ printk( "%sread_fifo(): read failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_read_failures++;
-+ break;
-+ }
-+
-+ *pOut++ = UDDR0;
-+ bytes_read++;
-+ }
-+ }
-+ PRINTKD( "read_fifo %d bytes\n", bytes_read );
-+
-+ /* clear SA & OPR */
-+ UDCCS0 = SETUP_READY;
-+
-+ usbd_info.stats.ep0_bytes_read += bytes_read;
-+ return bytes_read;
-+}
-+
-+/*
-+ * get_descriptor()
-+ * Called from sh_setup_begin to handle data return
-+ * for a GET_DESCRIPTOR setup request.
-+ */
-+static void get_descriptor( usb_dev_request_t * pReq )
-+{
-+ string_desc_t * pString;
-+ ep_desc_t * pEndpoint = 0;
-+
-+ desc_t * pDesc = pxa_usb_get_descriptor_ptr();
-+ int type = pReq->wValue >> 8;
-+ int idx = pReq->wValue & 0xFF;
-+
-+// PRINTKD( "%sget_descriptor for %d\n", pszMe, type );
-+ switch( type ) {
-+ case USB_DESC_DEVICE:
-+ queue_and_start_write( &pDesc->dev,
-+ pReq->wLength,
-+ pDesc->dev.bLength );
-+ break;
-+
-+ // return config descriptor buffer, cfg, intf, 2 ep
-+ case USB_DESC_CONFIG:
-+ queue_and_start_write( &pDesc->b,
-+ pReq->wLength,
-+ sizeof( struct cdb ) );
-+ break;
-+
-+ // not quite right, since doesn't do language code checking
-+ case USB_DESC_STRING:
-+ pString = pxa_usb_get_string_descriptor( idx );
-+ if ( pString ) {
-+ if ( idx != 0 ) { // if not language index
-+ printk( "%sReturn string %d: ", pszMe, idx );
-+ psdesc( pString );
-+ }
-+ queue_and_start_write( pString,
-+ pReq->wLength,
-+ pString->bLength );
-+ }
-+ else {
-+ printk("%sunkown string index %d Stall.\n", pszMe, idx );
-+ }
-+ break;
-+
-+ case USB_DESC_INTERFACE:
-+ if ( idx == pDesc->b.intf.bInterfaceNumber ) {
-+ queue_and_start_write( &pDesc->b.intf,
-+ pReq->wLength,
-+ pDesc->b.intf.bLength );
-+ }
-+ break;
-+
-+ case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
-+ if ( idx == 1 )
-+ pEndpoint = &pDesc->b.ep1; //[BULK_IN1];
-+ else if ( idx == 2 )
-+ pEndpoint = &pDesc->b.ep2; //[BULK_OUT1];
-+ else
-+ pEndpoint = NULL;
-+ if ( pEndpoint ) {
-+ queue_and_start_write( pEndpoint,
-+ pReq->wLength,
-+ pEndpoint->bLength );
-+ } else {
-+ printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
-+ }
-+ break;
-+
-+
-+ default :
-+ printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
-+ break;
-+
-+ }
-+}
-+
-+/* end usb_ep0.c - who needs this comment? */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_ep0.h
-@@ -0,0 +1,66 @@
-+/*
-+ * Copyright (C) Intrinsyc, Inc., 2002
-+ *
-+ * usb_ep0.h - PXA USB controller driver.
-+ * Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for details.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) -
-+ *
-+ */
-+
-+#ifndef __USB_EP0_H
-+#define __USB_EP0_H
-+
-+#define EP0_FIFO_SIZE 16
-+#define SETUP_READY (UDCCS0_SA | UDCCS0_OPR)
-+
-+/*================================================
-+ * USB Protocol Stuff
-+ */
-+
-+/* Request Codes */
-+enum {
-+ GET_STATUS =0,
-+ CLEAR_FEATURE =1,
-+ /* reserved =2 */
-+ SET_FEATURE =3,
-+ /* reserved =4 */
-+ SET_ADDRESS =5,
-+ GET_DESCRIPTOR =6,
-+ SET_DESCRIPTOR =7,
-+ GET_CONFIGURATION =8,
-+ SET_CONFIGURATION =9,
-+ GET_INTERFACE =10,
-+ SET_INTERFACE =11,
-+ SYNCH_FRAME =12
-+};
-+
-+typedef enum {
-+ EP0_IDLE,
-+ EP0_IN_DATA_PHASE,
-+ EP0_END_XFER,
-+ EP0_OUT_DATA_PHASE
-+} EP0_state;
-+
-+/* USB Device Requests */
-+typedef struct
-+{
-+ __u8 bmRequestType;
-+ __u8 bRequest;
-+ __u16 wValue;
-+ __u16 wIndex;
-+ __u16 wLength;
-+} usb_dev_request_t __attribute__ ((packed));
-+
-+/* Data extraction from usb_request_t fields */
-+enum {
-+ kTargetDevice =0,
-+ kTargetInterface=1,
-+ kTargetEndpoint =2
-+};
-+#endif
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_recv.c
-@@ -0,0 +1,173 @@
-+/*
-+ * Generic receive layer for the PXA USB client function
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_recv.c
-+ *
-+ * TODO: Add support for DMA.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static char *ep_bulk_out1_buf;
-+static int ep_bulk_out1_len;
-+static int ep_bulk_out1_remain;
-+static usb_callback_t ep_bulk_out1_callback;
-+static int rx_pktsize;
-+
-+static void
-+ep_bulk_out1_start(void)
-+{
-+ /* disable DMA */
-+ UDCCS2 &= ~UDCCS_BO_DME;
-+
-+ /* enable interrupts for endpoint 2 (bulk out) */
-+ UICR0 &= ~UICR0_IM2;
-+}
-+
-+static void
-+ep_bulk_out1_done(int flag)
-+{
-+ int size = ep_bulk_out1_len - ep_bulk_out1_remain;
-+
-+ if (!ep_bulk_out1_len)
-+ return;
-+
-+ ep_bulk_out1_len = 0;
-+ if (ep_bulk_out1_callback) {
-+ ep_bulk_out1_callback(flag, size);
-+ }
-+}
-+
-+void
-+ep_bulk_out1_state_change_notify( int new_state )
-+{
-+}
-+
-+void
-+ep_bulk_out1_stall( void )
-+{
-+ /* SET_FEATURE force stall at UDC */
-+ UDCCS2 |= UDCCS_BO_FST;
-+}
-+
-+int
-+ep_bulk_out1_init(int chn)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ ep_bulk_out1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep_bulk_out1_reset(void)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ UDCCS2 &= ~UDCCS_BO_FST;
-+ ep_bulk_out1_done(-EINTR);
-+}
-+
-+void
-+ep_bulk_out1_int_hndlr(int udcsr)
-+{
-+ int status = UDCCS2;
-+ if( usb_debug) printk("ep_bulk_out1_int_hndlr: UDCCS2=%x\n", status);
-+
-+ if( (status & (UDCCS_BO_RNE | UDCCS_BO_RSP)) == UDCCS_BO_RSP)
-+ {
-+ /* zero-length packet */
-+ }
-+
-+ if( status & UDCCS_BO_RNE)
-+ {
-+ int len;
-+ int i;
-+ char *buf = ep_bulk_out1_buf + ep_bulk_out1_len - ep_bulk_out1_remain;
-+
-+ /* bytes in FIFO */
-+ len = (UBCR2 & 0xff) +1;
-+
-+ if( usb_debug) printk("usb_recv: "
-+ "len=%d out1_len=%d out1_remain=%d\n",
-+ len,ep_bulk_out1_len,ep_bulk_out1_remain);
-+
-+ if( len > ep_bulk_out1_remain)
-+ {
-+ /* FIXME: if this happens, we need a temporary overflow buffer */
-+ printk("usb_recv: Buffer overwrite warning...\n");
-+ len = ep_bulk_out1_remain;
-+ }
-+
-+ /* read data out of fifo */
-+ for( i=0; i<len; i++)
-+ {
-+ *buf++ = UDDR2 & 0xff;
-+ }
-+
-+ ep_bulk_out1_remain -= len;
-+ ep_bulk_out1_done((len) ? 0 : -EPIPE);
-+ }
-+
-+ /* ack RPC - FIXME: '|=' we may ack SST here, too */
-+ UDCCS2 |= UDCCS_BO_RPC;
-+ return;
-+}
-+
-+int
-+pxa_usb_recv(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (ep_bulk_out1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep_bulk_out1_buf = buf;
-+ ep_bulk_out1_len = len;
-+ ep_bulk_out1_callback = callback;
-+ ep_bulk_out1_remain = len;
-+ ep_bulk_out1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+void
-+pxa_usb_recv_reset(void)
-+{
-+ ep_bulk_out1_reset();
-+}
-+
-+void
-+pxa_usb_recv_stall(void)
-+{
-+ ep_bulk_out1_stall();
-+}
-+
-+EXPORT_SYMBOL(pxa_usb_recv_stall);
-+EXPORT_SYMBOL(pxa_usb_recv);
-+EXPORT_SYMBOL(pxa_usb_recv_reset);
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-pxa/usb_send.c
-@@ -0,0 +1,190 @@
-+/*
-+ * Generic xmit layer for the PXA USB client function
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 02-May-2002
-+ * Frank Becker (Intrinsyc) - derived from sa1100 usb_send.c
-+ *
-+ * TODO: Add support for DMA.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+#include <asm/byteorder.h>
-+
-+#include "pxa_usb.h"
-+#include "usb_ctl.h"
-+
-+#if DEBUG
-+static unsigned int usb_debug = DEBUG;
-+#else
-+#define usb_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static char *ep_bulk_in1_buf;
-+static int ep_bulk_in1_len;
-+static int ep_bulk_in1_remain;
-+static usb_callback_t ep_bulk_in1_callback;
-+static int tx_pktsize;
-+
-+/* device state is changing, async */
-+void
-+ep_bulk_in1_state_change_notify( int new_state )
-+{
-+}
-+
-+/* set feature stall executing, async */
-+void
-+ep_bulk_in1_stall( void )
-+{
-+ UDCCS1 |= UDCCS_BI_FST;
-+}
-+
-+static void
-+ep_bulk_in1_send_packet(void)
-+{
-+ int i;
-+ char *buf = ep_bulk_in1_buf + ep_bulk_in1_len - ep_bulk_in1_remain;
-+ int out_size = tx_pktsize;
-+
-+ if( usb_debug) printk( "ep_bulk_in1_send_packet: UICR0=%x UDCCS1=%x\n", UICR0, UDCCS1);
-+
-+ if( out_size > ep_bulk_in1_remain)
-+ {
-+ out_size = ep_bulk_in1_remain;
-+ }
-+
-+ for( i=0; i<out_size; i++)
-+ {
-+ UDDR1 = *buf++;
-+ }
-+
-+ UDCCS1 = UDCCS_BI_TPC;
-+ if( out_size < tx_pktsize)
-+ {
-+ /* short packet */
-+ UDCCS1 = UDCCS_BI_TSP;
-+ }
-+ ep_bulk_in1_remain -= out_size;
-+
-+ if( usb_debug) printk( "ep_bulk_in1_send_packet: "
-+ "UICR0=%x UDCCS1=%x send bytes=%d left=%d\n",
-+ UICR0, UDCCS1, out_size, ep_bulk_in1_remain);
-+}
-+
-+static void
-+ep_bulk_in1_start(void)
-+{
-+ if (!ep_bulk_in1_len)
-+ return;
-+
-+ UICR0 &= ~UICR0_IM1;
-+
-+ ep_bulk_in1_send_packet();
-+}
-+
-+static void
-+ep_bulk_in1_done(int flag)
-+{
-+ int size = ep_bulk_in1_len - ep_bulk_in1_remain;
-+ if (ep_bulk_in1_len) {
-+ ep_bulk_in1_len = 0;
-+ if (ep_bulk_in1_callback)
-+ ep_bulk_in1_callback(flag, size);
-+ }
-+}
-+
-+int
-+ep_bulk_in1_init(int chn)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ ep_bulk_in1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep_bulk_in1_reset(void)
-+{
-+ desc_t * pd = pxa_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ UDCCS1 &= ~UDCCS_BI_FST;
-+ ep_bulk_in1_done(-EINTR);
-+}
-+
-+void
-+ep_bulk_in1_int_hndlr(int usir0)
-+{
-+ int status = UDCCS1;
-+
-+ if (ep_bulk_in1_remain != 0) {
-+ /* more data to go */
-+ ep_bulk_in1_start();
-+ } else {
-+ if( status & UDCCS_BI_TPC)
-+ {
-+ UDCCS1 = UDCCS_BI_TPC;
-+ }
-+ ep_bulk_in1_done(0);
-+ }
-+}
-+
-+int
-+pxa_usb_send(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if( usb_debug) printk( "pxa_usb_send: "
-+ "data len=%d state=%d blen=%d\n",
-+ len, usbd_info.state, ep_bulk_in1_len);
-+
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+
-+ if (ep_bulk_in1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep_bulk_in1_buf = buf;
-+ ep_bulk_in1_len = len;
-+ ep_bulk_in1_callback = callback;
-+ ep_bulk_in1_remain = len;
-+ ep_bulk_in1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+
-+void
-+pxa_usb_send_reset(void)
-+{
-+ ep_bulk_in1_reset();
-+}
-+
-+int
-+pxa_usb_xmitter_avail( void )
-+{
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+ if (ep_bulk_in1_len)
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+
-+EXPORT_SYMBOL(pxa_usb_xmitter_avail);
-+EXPORT_SYMBOL(pxa_usb_send);
-+EXPORT_SYMBOL(pxa_usb_send_reset);
---- linux-2.4.27/arch/arm/mach-sa1100/sa1111-ohci.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mach-sa1100/sa1111-ohci.c
-@@ -54,7 +54,7 @@
- * address as its return value, and the DMA address via
- * the dma_addr_t pointer.
- */
-- vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
-+ vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf, 0);
-
- SADTSA = (unsigned long)dma_buf;
- SADTCA = 4;
---- linux-2.4.27/arch/arm/mach-sa1100/sa1111.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mach-sa1100/sa1111.c
-@@ -243,9 +243,15 @@
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
-+#if CONFIG_ARCH_SA1100
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-+#elif CONFIG_ARCH_PXA
-+ set_GPIO_mode(GPIO11_3_6MHz_MD);
-+#else
-+#error missing clock setup
-+#endif
-
- /*
- * Turn VCO on, and disable PLL Bypass.
-@@ -300,6 +306,8 @@
- SBI_SMCR = smcr;
- }
-
-+#ifdef CONFIG_ARCH_SA1100
-+
- /*
- * Disable the memory bus request/grant signals on the SA1110 to
- * ensure that we don't receive spurious memory requests. We set
-@@ -341,5 +349,7 @@
- local_irq_restore(flags);
- }
-
-+#endif
-+
- EXPORT_SYMBOL(sa1111_wake);
- EXPORT_SYMBOL(sa1111_doze);
---- linux-2.4.27/arch/arm/mm/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mm/Makefile
-@@ -44,6 +44,7 @@
- p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
- p-$(CONFIG_CPU_SA110) += proc-sa110.o
- p-$(CONFIG_CPU_SA1100) += proc-sa110.o
-+p-$(CONFIG_CPU_XSCALE) += proc-xscale.o
-
- # Integrator follows "new style"
- # Soon, others will do too, and we can get rid of this
---- linux-2.4.27/arch/arm/mm/consistent.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mm/consistent.c
-@@ -37,7 +37,8 @@
- *
- * Note that this does *not* zero the allocated area!
- */
--void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
-+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle,
-+ unsigned long cache_flags)
- {
- struct page *page, *end, *free;
- unsigned long order;
-@@ -55,7 +56,7 @@
- goto no_page;
-
- *dma_handle = page_to_bus(page);
-- ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, 0);
-+ ret = __ioremap(page_to_pfn(page) << PAGE_SHIFT, size, cache_flags);
- if (!ret)
- goto no_remap;
-
-@@ -106,7 +107,7 @@
- #endif
- gfp |= GFP_DMA;
-
-- return consistent_alloc(gfp, size, handle);
-+ return consistent_alloc(gfp, size, handle, 0);
- }
-
- /*
---- linux-2.4.27/arch/arm/mm/init.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mm/init.c
-@@ -49,6 +49,9 @@
- static unsigned long totalram_pages;
- extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
- extern char _stext, _text, _etext, _end, __init_begin, __init_end;
-+#ifdef CONFIG_XIP_KERNEL
-+extern char _endtext, _sdata;
-+#endif
- extern unsigned long phys_initrd_start;
- extern unsigned long phys_initrd_size;
-
-@@ -347,7 +350,11 @@
- * Register the kernel text and data with bootmem.
- * Note that this can only be in node 0.
- */
-+#ifdef CONFIG_XIP_KERNEL
-+ reserve_bootmem_node(pgdat, __pa(&_sdata), &_end - &_sdata);
-+#else
- reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
-+#endif
-
- #ifdef CONFIG_CPU_32
- /*
-@@ -601,8 +608,13 @@
- unsigned int codepages, datapages, initpages;
- int i, node;
-
-+#ifndef CONFIG_XIP_KERNEL
- codepages = &_etext - &_text;
- datapages = &_end - &_etext;
-+#else
-+ codepages = &_endtext - &_text;
-+ datapages = &_end - &_sdata;
-+#endif
- initpages = &__init_end - &__init_begin;
-
- high_memory = (void *)__va(meminfo.end);
-@@ -658,11 +670,13 @@
-
- void free_initmem(void)
- {
-+#ifndef CONFIG_XIP_KERNEL
- if (!machine_is_integrator()) {
- free_area((unsigned long)(&__init_begin),
- (unsigned long)(&__init_end),
- "init");
- }
-+#endif
- }
-
- #ifdef CONFIG_BLK_DEV_INITRD
---- linux-2.4.27/arch/arm/mm/mm-armv.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/arch/arm/mm/mm-armv.c
-@@ -356,6 +356,19 @@
- p ++;
- #endif
-
-+#ifdef CONFIG_XIP_KERNEL
-+ p->physical = KERNEL_XIP_BASE_PHYS;
-+ p->virtual = KERNEL_XIP_BASE_VIRT;
-+ p->length = PGDIR_SIZE * 8;
-+ p->domain = DOMAIN_KERNEL;
-+ p->prot_read = 0; /* r=0, b=0 --> read-only for kernel mode */
-+ p->prot_write = 0;
-+ p->cacheable = 1;
-+ p->bufferable = 1;
-+
-+ p ++;
-+#endif
-+
- /*
- * Go through the initial mappings, but clear out any
- * pgdir entries that are not in the description.
-@@ -386,7 +399,7 @@
- init_maps->prot_read = 0;
- init_maps->prot_write = 0;
- init_maps->cacheable = 1;
-- init_maps->bufferable = 0;
-+ init_maps->bufferable = 1;
-
- create_mapping(init_maps);
-
---- /dev/null
-+++ linux-2.4.27/arch/arm/mm/proc-xscale.S
-@@ -0,0 +1,1086 @@
-+/*
-+ * linux/arch/arm/mm/proc-xscale.S
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: November 2000
-+ * Copyright: (C) 2000, 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * MMU functions for the Intel XScale CPUs
-+ *
-+ * 2001 Aug 21:
-+ * some contributions by Brett Gaines <brett.w.gaines@intel.com>
-+ * Copyright 2001 by Intel Corp.
-+ *
-+ * 2001 Sep 08:
-+ * Completely revisited, many important fixes
-+ * Nicolas Pitre <nico@cam.org>
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/linkage.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+#include <asm/proc/pgtable.h>
-+
-+/*
-+ * Some knobs for cache allocation policy.
-+ * Allocate on write may or may not be beneficial depending on the memory
-+ * usage pattern of your main application. Write through cache is definitely
-+ * a performance loss in most cases, but might be used for special purposes.
-+ */
-+#define PMD_CACHE_WRITE_ALLOCATE 1
-+#define PTE_CACHE_WRITE_ALLOCATE 1
-+#define CACHE_WRITE_THROUGH 0
-+
-+/*
-+ * There are errata that say that dirty status bits in the cache may get
-+ * corrupted. The workaround significantly affects performance, and the bug
-+ * _might_ just not be that visible or critical to you, so it is configurable.
-+ * Let's hope a future core revision will tell us this was only a bad dream.
-+ * But in the mean time the risk and tradeoff is yours to decide....
-+ */
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+#undef CACHE_WRITE_THROUGH
-+#define CACHE_WRITE_THROUGH 1
-+#endif
-+
-+/*
-+ * This is the maximum size of an area which will be flushed. If the area
-+ * is larger than this, then we flush the whole cache
-+ */
-+#define MAX_AREA_SIZE 32768
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define CACHELINESIZE 32
-+
-+/*
-+ * the size of the data cache
-+ */
-+#define CACHESIZE 32768
-+
-+/*
-+ * and the page size
-+ */
-+#define PAGESIZE 4096
-+
-+/*
-+ * Virtual address used to allocate the cache when flushed
-+ *
-+ * This must be an address range which is _never_ used. It should
-+ * apparently have a mapping in the corresponding page table for
-+ * compatibility with future CPUs that _could_ require it. For instance we
-+ * don't care.
-+ *
-+ * This must be aligned on a 2*CACHESIZE boundary. The code selects one of
-+ * the 2 areas in alternance each time the clean_d_cache macro is used.
-+ * Without this the XScale core exhibits cache eviction problems and no one
-+ * knows why.
-+ *
-+ * Reminder: the vector table is located at 0xffff0000-0xffff0fff.
-+ */
-+#define CLEAN_ADDR 0xfffe0000
-+
-+/*
-+ * This macro is used to wait for a CP15 write and is needed
-+ * when we have to ensure that the last operation to the co-pro
-+ * was completed before continuing with operation.
-+ */
-+ .macro cpwait, rd
-+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
-+ mov \rd, \rd @ wait for completion
-+ sub pc, pc, #4 @ flush instruction pipeline
-+ .endm
-+
-+ .macro cpwait_ret, lr, rd
-+ mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
-+ sub pc, \lr, \rd, LSR #32 @ wait for completion and
-+ @ flush instruction pipeline
-+ .endm
-+
-+#if !CACHE_WRITE_THROUGH
-+
-+/*
-+ * This macro cleans the entire dcache using line allocate.
-+ * The main loop has been unrolled to reduce loop overhead.
-+ * rd and rs are two scratch registers.
-+ */
-+ .macro clean_d_cache, rd, rs
-+ ldr \rs, =clean_addr
-+ ldr \rd, [\rs]
-+ eor \rd, \rd, #CACHESIZE
-+ str \rd, [\rs]
-+ add \rs, \rd, #CACHESIZE
-+1: mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ mcr p15, 0, \rd, c7, c2, 5 @ allocate D cache line
-+ add \rd, \rd, #CACHELINESIZE
-+ teq \rd, \rs
-+ bne 1b
-+ .endm
-+
-+ .macro clean_d_line, rd
-+ mcr p15, 0, \rd, c7, c10, 1
-+ .endm
-+
-+ .data
-+clean_addr: .word CLEAN_ADDR
-+
-+#else
-+
-+/*
-+ * If cache is write-through, there is no need to clean it.
-+ * Simply invalidating will do.
-+ */
-+
-+ .macro clean_d_cache, rd, rs
-+ mcr p15, 0, \rd, c7, c6, 0
-+ .endm
-+
-+ /* let's try to skip this needless operations at least within loops */
-+ .macro clean_d_line, rd
-+ .endm
-+
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_xscale_data_abort()
-+ *
-+ * obtain information about current aborted instruction.
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = saved SPSR
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR, bit 11 = write
-+ * r3 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ ldr r3, [r2] @ read aborted instruction
-+ bic r1, r1, #1 << 11 @ clear bits 11 of FSR
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_check_bugs()
-+ */
-+ENTRY(cpu_xscale_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+#ifndef CONFIG_XSCALE_CACHE_ERRATA
-+/*
-+ * cpu_xscale_proc_init()
-+ *
-+ * Nothing too exciting at the moment
-+ */
-+ENTRY(cpu_xscale_proc_init)
-+ mov pc, lr
-+#else
-+/*
-+ * We enable the cache here, but we make sure all the status bits for dirty
-+ * lines are cleared as well (see PXA250 erratum #120).
-+ */
-+ENTRY(cpu_xscale_proc_init)
-+ @ enable data cache
-+ ldr r0, cr_p
-+ ldmia r0, {r1, r2}
-+ orr r1, r1, #0x4
-+ orr r2, r2, #0x4
-+ stmia r0, {r1, r2}
-+ mcr p15, 0, r1, c1, c0, 0
-+ cpwait r0
-+
-+ @ invalidate data cache
-+ mcr p15, 0, r0, c7, c6, 0
-+
-+ @ fill main cache with write-through lines
-+ bic r0, pc, #0x1f
-+ add r1, r0, #CACHESIZE
-+1: ldr r2, [r0], #32
-+ cmp r0, r1
-+ bne 1b
-+
-+ @ enable test feature to force all fills to the mini-cache
-+ mov r1, #0x8
-+ mcr p15, 0, r1, c15, c15, 3
-+
-+ @ fill mini-cache with write-through lines (2kbytes, 64 lines)
-+ add r1, r0, #2048
-+2: ldr r2, [r0], #32
-+ cmp r0, r1
-+ bne 2b
-+
-+ @ disable test feature to force all fills to the mini-cache
-+ mov r1, #0x0
-+ mcr p15, 0, r1, c15, c15, 3
-+
-+ @ invalidate data cache again
-+ mcr p15, 0, r1, c7, c6, 0
-+ mov pc, lr
-+
-+cr_p: .long SYMBOL_NAME(cr_alignment)
-+#endif
-+
-+/*
-+ * cpu_xscale_proc_fin()
-+ */
-+ENTRY(cpu_xscale_proc_fin)
-+ str lr, [sp, #-4]!
-+ mov r0, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r0
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1800 @ ...IZ...........
-+ bic r0, r0, #0x0006 @ .............CA.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ bl cpu_xscale_cache_clean_invalidate_all @ clean caches
-+ ldr pc, [sp], #4
-+
-+/*
-+ * cpu_xscale_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_reset)
-+ mov r1, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r1 @ reset CPSR
-+ mrc p15, 0, r1, c1, c0, 0 @ ctrl register
-+ bic r1, r1, #0x0086 @ ........B....CA.
-+ bic r1, r1, #0x1900 @ ...IZ..S........
-+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
-+ bic r1, r1, #0x0001 @ ...............M
-+ mcr p15, 0, r1, c1, c0, 0 @ ctrl register
-+ @ CAUTION: MMU turned off from this point. We count on the pipeline
-+ @ already containing those two last instructions to survive.
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mov pc, r0
-+
-+/*
-+ * cpu_xscale_do_idle(type)
-+ *
-+ * Cause the processor to idle
-+ *
-+ * type:
-+ * 0 = slow idle
-+ * 1 = fast idle
-+ * 2 = switch to slow processor clock
-+ * 3 = switch to fast processor clock
-+ *
-+ * For now we do nothing but go to idle mode for every case
-+ *
-+ * XScale supports clock switching, but using idle mode support
-+ * allows external hardware to react to system state changes.
-+ */
-+ .align 5
-+
-+ENTRY(cpu_xscale_do_idle)
-+ mov r0, #1
-+ mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+/*
-+ * cpu_xscale_cache_clean_invalidate_all (void)
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. We should preserve r0 at all times.
-+ * 2. Even if this function implies cache "invalidation" by its name,
-+ * we don't need to actually use explicit invalidation operations
-+ * since the goal is to discard all valid references from the cache
-+ * and the cleaning of it already has that effect.
-+ * 3. Because of 2 above and the fact that kernel space memory is always
-+ * coherent across task switches there is no need to worry about
-+ * inconsistencies due to interrupts, ence no irq disabling.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_xscale_cache_clean_invalidate_all_r2:
-+ clean_d_cache r0, r1
-+ teq r2, #0
-+ mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_cache_clean_invalidate_range)
-+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhi cpu_xscale_cache_clean_invalidate_all_r2
-+1: clean_d_line r0 @ Clean D cache line
-+ mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ teq r2, #0
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ moveq pc, lr
-+ sub r0, r0, r3
-+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_flush_ram_page(page)
-+ *
-+ * clean all cache lines associated with this memory page
-+ *
-+ * page: page to clean
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_flush_ram_page)
-+#if !CACHE_WRITE_THROUGH
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #2 * CACHELINESIZE
-+ bne 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_xscale_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that on XScale we must clean all
-+ * entries also due to hardware errata (80200 A0 & A1 only).
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_invalidate_range)
-+ mrc p15, 0, r2, c0, c0, 0 @ Read part no.
-+ eor r2, r2, #0x69000000
-+ eor r2, r2, #0x00052000 @ 80200 XX part no.
-+ bics r2, r2, #0x1 @ Clear LSB in revision field
-+ moveq r2, #0
-+ beq cpu_xscale_cache_clean_invalidate_range @ An 80200 A0 or A1
-+
-+ tst r0, #CACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ tst r1, #CACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ Clean D cache line
-+ bic r0, r0, #CACHELINESIZE - 1 @ round down to cache line
-+1: mcr p15, 0, r0, c7, c6, 1 @ Invalidate D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_range)
-+#if !CACHE_WRITE_THROUGH
-+ bic r0, r0, #CACHELINESIZE - 1
-+ sub r2, r1, r0
-+ cmp r2, #MAX_AREA_SIZE
-+ movhi r2, #0
-+ bhi cpu_xscale_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_clean_dcache_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * Note:
-+ * 1. we don't need to flush the write buffer in this case. [really? -Nico]
-+ * 2. we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_page)
-+#if !CACHE_WRITE_THROUGH
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #4 * CACHELINESIZE
-+ bne 1b
-+#endif
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_dcache_clean_entry)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_xscale_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * Note: This is vaguely defined as supposed to bring the dcache and the
-+ * icache in sync by the way this function is used.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_icache_invalidate_range)
-+ bic r0, r0, #CACHELINESIZE - 1
-+1: clean_d_line r0 @ Clean D cache line
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ cmp r0, r1
-+ blo 1b
-+ mcr p15, 0, ip, c7, c5, 6 @ Invalidate BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_icache_invalidate_page(page)
-+ *
-+ * invalidate all Icache lines associated with this area of memory
-+ *
-+ * page: page to invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_icache_invalidate_page)
-+ mov r1, #PAGESIZE
-+1: mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
-+ add r0, r0, #CACHELINESIZE
-+ subs r1, r1, #4 * CACHELINESIZE
-+ bne 1b
-+ mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
-+ mov pc, lr
-+
-+/* ================================ CACHE LOCKING============================
-+ *
-+ * The XScale MicroArchitecture implements support for locking entries into
-+ * the data and instruction cache. The following functions implement the core
-+ * low level instructions needed to accomplish the locking. The developer's
-+ * manual states that the code that performs the locking must be in non-cached
-+ * memory. To accomplish this, the code in xscale-cache-lock.c copies the
-+ * following functions from the cache into a non-cached memory region that
-+ * is allocated through consistent_alloc().
-+ *
-+ */
-+ .align 5
-+/*
-+ * xscale_icache_lock
-+ *
-+ * r0: starting address to lock
-+ * r1: end address to lock
-+ */
-+ENTRY(xscale_icache_lock)
-+
-+iLockLoop:
-+ bic r0, r0, #CACHELINESIZE - 1
-+ mcr p15, 0, r0, c9, c1, 0 @ lock into cache
-+ cmp r0, r1 @ are we done?
-+ add r0, r0, #CACHELINESIZE @ advance to next cache line
-+ bls iLockLoop
-+ mov pc, lr
-+
-+/*
-+ * xscale_icache_unlock
-+ */
-+ENTRY(xscale_icache_unlock)
-+ mcr p15, 0, r0, c9, c1, 1 @ Unlock icache
-+ mov pc, lr
-+
-+/*
-+ * xscale_dcache_lock
-+ *
-+ * r0: starting address to lock
-+ * r1: end address to lock
-+ */
-+ENTRY(xscale_dcache_lock)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov r2, #1
-+ mcr p15, 0, r2, c9, c2, 0 @ Put dcache in lock mode
-+ cpwait ip @ Wait for completion
-+
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+dLockLoop:
-+ msr cpsr_c, r3
-+ mcr p15, 0, r0, c7, c10, 1 @ Write back line if it is dirty
-+ mcr p15, 0, r0, c7, c6, 1 @ Flush/invalidate line
-+ msr cpsr_c, r2
-+ ldr ip, [r0], #CACHELINESIZE @ Preload 32 bytes into cache from
-+ @ location [r0]. Post-increment
-+ @ r3 to next cache line
-+ cmp r0, r1 @ Are we done?
-+ bls dLockLoop
-+
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov r2, #0
-+ mcr p15, 0, r2, c9, c2, 0 @ Get out of lock mode
-+ cpwait_ret lr, ip
-+
-+/*
-+ * xscale_dcache_unlock
-+ */
-+ENTRY(xscale_dcache_unlock)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c9, c2, 1 @ Unlock cache
-+ mov pc, lr
-+
-+/*
-+ * Needed to determine the length of the code that needs to be copied.
-+ */
-+ .align 5
-+ENTRY(xscale_cache_dummy)
-+ mov pc, lr
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_all)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_range)
-+ bic r0, r0, #(PAGESIZE - 1) & 0x00ff
-+ bic r0, r0, #(PAGESIZE - 1) & 0xff00
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE @ arbitrary, should be tuned
-+ bhi cpu_xscale_tlb_invalidate_all
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ blo 1b
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_tlb_invalidate_page)
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r3, c8, c5, 1 @ invalidate I TLB entry
-+ cpwait_ret lr, ip
-+
-+/* ================================ TLB LOCKING==============================
-+ *
-+ * The XScale MicroArchitecture implements support for locking entries into
-+ * the Instruction and Data TLBs. The following functions provide the
-+ * low level support for supporting these under Linux. xscale-lock.c
-+ * implements some higher level management code. Most of the following
-+ * is taken straight out of the Developer's Manual.
-+ */
-+
-+/*
-+ * Lock I-TLB entry
-+ *
-+ * r0: Virtual address to translate and lock
-+ */
-+ .align 5
-+ENTRY(xscale_itlb_lock)
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+ msr cpsr_c, r3 @ Disable interrupts
-+ mcr p15, 0, r0, c8, c5, 1 @ Invalidate I-TLB entry
-+ mcr p15, 0, r0, c10, c4, 0 @ Translate and lock
-+ msr cpsr_c, r2 @ Restore interrupts
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Lock D-TLB entry
-+ *
-+ * r0: Virtual address to translate and lock
-+ */
-+ .align 5
-+ENTRY(xscale_dtlb_lock)
-+ mrs r2, cpsr
-+ orr r3, r2, #F_BIT | I_BIT
-+ msr cpsr_c, r3 @ Disable interrupts
-+ mcr p15, 0, r0, c8, c6, 1 @ Invalidate D-TLB entry
-+ mcr p15, 0, r0, c10, c8, 0 @ Translate and lock
-+ msr cpsr_c, r2 @ Restore interrupts
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Unlock all I-TLB entries
-+ */
-+ .align 5
-+ENTRY(xscale_itlb_unlock)
-+ mcr p15, 0, ip, c10, c4, 1 @ Unlock I-TLB
-+ mcr p15, 0, ip, c8, c5, 0 @ Invalidate I-TLB
-+ cpwait_ret lr, ip
-+
-+/*
-+ * Unlock all D-TLB entries
-+ */
-+ENTRY(xscale_dtlb_unlock)
-+ mcr p15, 0, ip, c10, c8, 1 @ Unlock D-TBL
-+ mcr p15, 0, ip, c8, c6, 0 @ Invalidate D-TLB
-+ cpwait_ret lr, ip
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_xscale_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pgd)
-+ clean_d_cache r1, r2
-+ mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ cpwait_ret lr, ip
-+
-+/*
-+ * cpu_xscale_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pmd)
-+#if PMD_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
-+ and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ orreq r1, r1, #PMD_SECT_TEX(1)
-+#elif CACHE_WRITE_THROUGH
-+ and r2, r1, #PMD_TYPE_MASK|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ cmp r2, #PMD_TYPE_SECT|PMD_SECT_CACHEABLE|PMD_SECT_BUFFERABLE
-+ biceq r1, r1, #PMD_SECT_BUFFERABLE
-+#endif
-+ str r1, [r0]
-+ mov ip, #0
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_xscale_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ *
-+ * Errata 40: must set memory to write-through for user read-only pages.
-+ */
-+ .align 5
-+ENTRY(cpu_xscale_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ bic r2, r1, #0xff0
-+ orr r2, r2, #PTE_TYPE_EXT @ extended page
-+
-+ eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
-+
-+ tst r3, #L_PTE_USER | L_PTE_EXEC @ User or Exec?
-+ orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
-+
-+ tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
-+ @ combined with user -> user r/w
-+
-+ @
-+ @ Handle the X bit. We want to set this bit for the minicache
-+ @ (U = E = B = W = 0, C = 1) or when write allocate is enabled,
-+ @ and we have a writeable, cacheable region. If we ignore the
-+ @ U and E bits, we can allow user space to use the minicache as
-+ @ well.
-+ @
-+ @ X = C & ~W & ~B
-+ @ | C & W & B & write_allocate
-+ @
-+ eor ip, r1, #L_PTE_CACHEABLE
-+ tst ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+#if PTE_CACHE_WRITE_ALLOCATE && !CACHE_WRITE_THROUGH
-+ eorne ip, r1, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+ tstne ip, #L_PTE_CACHEABLE | L_PTE_WRITE | L_PTE_BUFFERABLE
-+#endif
-+ orreq r2, r2, #PTE_EXT_TEX(1)
-+
-+#if CACHE_WRITE_THROUGH
-+ tst r1, #L_PTE_CACHEABLE
-+ bicne r2, r2, #L_PTE_BUFFERABLE @ clear B only if C is set
-+#else
-+ @
-+ @ Errata 40: The B bit must be cleared for a user read-only
-+ @ cacheable page.
-+ @
-+ @ B = B & ~((U|E) & C & ~W)
-+ @
-+ and ip, r1, #L_PTE_USER | L_PTE_EXEC | L_PTE_WRITE | L_PTE_CACHEABLE
-+ teq ip, #L_PTE_USER | L_PTE_CACHEABLE
-+ teqne ip, #L_PTE_EXEC | L_PTE_CACHEABLE
-+ teqne ip, #L_PTE_USER | L_PTE_EXEC | L_PTE_CACHEABLE
-+ biceq r2, r2, #PTE_BUFFERABLE
-+#endif
-+
-+ tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
-+ movne r2, #0 @ no -> fault
-+
-+ str r2, [r0] @ hardware version
-+
-+ @ We try to map 64K page entries when possible.
-+ @ We do that for kernel space only since the usage pattern from
-+ @ the setting of VM area is quite simple. User space is not worth
-+ @ the implied complexity because of ever randomly changing PTEs
-+ @ (page aging, swapout, etc) requiring constant coherency checks.
-+ @ Since PTEs are usually set in increasing order, we test the
-+ @ possibility for a large page only when given the last PTE of a
-+ @ 64K boundary.
-+ tsteq r1, #L_PTE_USER
-+ andeq r1, r0, #(15 << 2)
-+ teqeq r1, #(15 << 2)
-+ beq 1f
-+
-+ mov ip, #0
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+ @ See if we have 16 identical PTEs but with consecutive base addresses
-+1: bic r3, r2, #0x0000f000
-+ mov r1, #0x0000f000
-+2: eor r2, r2, r3
-+ teq r2, r1
-+ bne 4f
-+ subs r1, r1, #0x00001000
-+ ldr r2, [r0, #-4]!
-+ bne 2b
-+ eors r2, r2, r3
-+ bne 4f
-+
-+ @ Now create our LARGE PTE from the current EXT one.
-+ bic r3, r3, #PTE_TYPE_MASK
-+ orr r3, r3, #PTE_TYPE_LARGE
-+ and r2, r3, #0x30 @ EXT_AP --> LARGE_AP0
-+ orr r2, r2, r2, lsl #2 @ add LARGE_AP1
-+ orr r2, r2, r2, lsl #4 @ add LARGE_AP3 + LARGE_AP2
-+ and r1, r3, #0x3c0 @ EXT_TEX
-+ bic r3, r3, #0x3c0
-+ orr r2, r2, r1, lsl #(12 - 6) @ --> LARGE_TEX
-+ orr r2, r2, r3 @ add remaining bits
-+
-+ @ then put it in the pagetable
-+ mov r3, r2
-+3: strd r2, [r0], #8
-+ tst r0, #(15 << 2)
-+ bne 3b
-+
-+ @ Then sync the 2 corresponding cache lines
-+ sub r0, r0, #(16 << 2)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+4: orr r0, r0, #(15 << 2)
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mov pc, lr
-+
-+ .ltorg
-+
-+cpu_manu_name:
-+ .asciz "Intel"
-+
-+cpu_80200_name:
-+ .asciz "XScale-80200"
-+
-+cpu_pxa210_name:
-+ .asciz "XScale-PXA210"
-+
-+cpu_pxa250_name:
-+ .asciz "XScale-PXA250"
-+
-+cpu_pxa255_name:
-+ .asciz "XScale-PXA255"
-+
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__xscale_setup:
-+ mov r0, #F_BIT|I_BIT|SVC_MODE
-+ msr cpsr_c, r0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
-+ mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+ mov r0, #1 @ Allow user space to access
-+ mcr p15, 0, r0, c15, c1, 0 @ ... CP 0 only.
-+#if CACHE_WRITE_THROUGH
-+ mov r0, #0x20
-+#else
-+ mov r0, #0x00
-+#endif
-+ mcr p15, 0, r0, c1, c1, 0 @ set auxiliary control reg
-+ mrc p15, 0, r0, c1, c0, 0 @ get control register
-+ bic r0, r0, #0x0200 @ ......R.........
-+ bic r0, r0, #0x0082 @ ........B.....A.
-+ orr r0, r0, #0x0005 @ .............C.M
-+ orr r0, r0, #0x3900 @ ..VIZ..S........
-+#ifdef CONFIG_XSCALE_CACHE_ERRATA
-+ bic r0, r0, #0x0004 @ see cpu_xscale_proc_init
-+#endif
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+
-+ .type xscale_processor_functions, #object
-+ENTRY(xscale_processor_functions)
-+ .word cpu_xscale_data_abort
-+ .word cpu_xscale_check_bugs
-+ .word cpu_xscale_proc_init
-+ .word cpu_xscale_proc_fin
-+ .word cpu_xscale_reset
-+ .word cpu_xscale_do_idle
-+
-+ /* cache */
-+ .word cpu_xscale_cache_clean_invalidate_all
-+ .word cpu_xscale_cache_clean_invalidate_range
-+ .word cpu_xscale_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_xscale_dcache_invalidate_range
-+ .word cpu_xscale_dcache_clean_range
-+ .word cpu_xscale_dcache_clean_page
-+ .word cpu_xscale_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_xscale_icache_invalidate_range
-+ .word cpu_xscale_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_xscale_tlb_invalidate_all
-+ .word cpu_xscale_tlb_invalidate_range
-+ .word cpu_xscale_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_xscale_set_pgd
-+ .word cpu_xscale_set_pmd
-+ .word cpu_xscale_set_pte
-+ .size xscale_processor_functions, . - xscale_processor_functions
-+
-+ .type cpu_80200_info, #object
-+cpu_80200_info:
-+ .long cpu_manu_name
-+ .long cpu_80200_name
-+ .size cpu_80200_info, . - cpu_80200_info
-+
-+ .type cpu_pxa210_info, #object
-+cpu_pxa210_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa210_name
-+ .size cpu_pxa210_info, . - cpu_pxa210_info
-+
-+ .type cpu_pxa250_info, #object
-+cpu_pxa250_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa250_name
-+ .size cpu_pxa250_info, . - cpu_pxa250_info
-+
-+ .type cpu_pxa255_info, #object
-+cpu_pxa255_info:
-+ .long cpu_manu_name
-+ .long cpu_pxa255_name
-+ .size cpu_pxa255_info, . - cpu_pxa255_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5te"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __80200_proc_info,#object
-+__80200_proc_info:
-+ .long 0x69052000
-+ .long 0xfffffff0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_80200_info
-+ .long xscale_processor_functions
-+ .size __80200_proc_info, . - __80200_proc_info
-+
-+ .type __pxa210_proc_info,#object
-+__pxa210_proc_info:
-+ .long 0x69052120
-+ .long 0xfffff3f0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa210_info
-+ .long xscale_processor_functions
-+ .size __pxa210_proc_info, . - __pxa210_proc_info
-+
-+ .type __pxa250_proc_info,#object
-+__pxa250_proc_info:
-+ .long 0x69052100
-+ .long 0xfffff7f0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa250_info
-+ .long xscale_processor_functions
-+ .size __pxa250_proc_info, . - __pxa250_proc_info
-+
-+ .type __pxa255_proc_info,#object
-+__pxa255_proc_info:
-+ .long 0x69052d00
-+ .long 0xfffffff0
-+#if CACHE_WRITE_THROUGH
-+ .long 0x00000c0a
-+#else
-+ .long 0x00000c0e
-+#endif
-+ b __xscale_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_XSCALE
-+ .long cpu_pxa255_info
-+ .long xscale_processor_functions
-+ .size __pxa255_proc_info, . - __pxa255_proc_info
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/vmlinux-armv-xip.lds.in
-@@ -0,0 +1,125 @@
-+/*
-+ * ld script to make ARM Linux kernel
-+ *
-+ * (C) Copyright 2001 Lineo Japan, Inc.
-+ *
-+ * May be copied or modified under the terms of the GNU General Public
-+ * License. See linux/COPYING for more information.
-+ *
-+ * Based on arch/arm/vmlinux-armv.lds.in
-+ *
-+ * taken from the i386 version by Russell King
-+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
-+ */
-+OUTPUT_ARCH(arm)
-+ENTRY(stext)
-+SECTIONS
-+{
-+ . = TEXTADDR;
-+ .init : { /* Init code and data */
-+ _stext = .;
-+ __init_begin = .;
-+ *(.text.init)
-+ __proc_info_begin = .;
-+ *(.proc.info)
-+ __proc_info_end = .;
-+ __arch_info_begin = .;
-+ *(.arch.info)
-+ __arch_info_end = .;
-+ __tagtable_begin = .;
-+ *(.taglist)
-+ __tagtable_end = .;
-+ . = ALIGN(16);
-+ __setup_start = .;
-+ *(.setup.init)
-+ __setup_end = .;
-+ __initcall_start = .;
-+ *(.initcall.init)
-+ __initcall_end = .;
-+ . = ALIGN(4096);
-+ __init_end = .;
-+ }
-+
-+ /DISCARD/ : { /* Exit code and data */
-+ *(.text.exit)
-+ *(.data.exit)
-+ *(.exitcall.exit)
-+ }
-+
-+ .text : { /* Real text segment */
-+ _text = .; /* Text and read-only data */
-+ *(.text)
-+ *(.fixup)
-+ *(.gnu.warning)
-+ *(.text.lock) /* out-of-line lock text */
-+ *(.rodata)
-+ *(.rodata.*)
-+ *(.glue_7)
-+ *(.glue_7t)
-+ *(.kstrtab)
-+ *(.got) /* Global offset table */
-+ *(.got.plt)
-+
-+ _etext = .; /* End of text section */
-+ }
-+
-+ . = ALIGN(16);
-+ __ex_table : { /* Exception table */
-+ __start___ex_table = .;
-+ *(__ex_table)
-+ __stop___ex_table = .;
-+ }
-+
-+ __ksymtab : { /* Kernel symbol table */
-+ __start___ksymtab = .;
-+ *(__ksymtab)
-+ __stop___ksymtab = .;
-+ }
-+
-+ _endtext = .;
-+
-+ . = DATAADDR;
-+
-+ _sdata = .;
-+
-+ . = ALIGN(8192);
-+
-+ .data : {
-+ /*
-+ * first, the init task union, aligned
-+ * to an 8192 byte boundary.
-+ */
-+ *(.init.task)
-+
-+ /*
-+ * then the cacheline aligned data
-+ */
-+ . = ALIGN(32);
-+ *(.data.cacheline_aligned)
-+
-+ /*
-+ * and the usual data section
-+ */
-+ *(.data)
-+ CONSTRUCTORS
-+
-+ *(.data.init)
-+
-+ _edata = .;
-+ }
-+
-+ .bss : {
-+ __bss_start = .; /* BSS */
-+ *(.bss)
-+ *(COMMON)
-+ _end = . ;
-+ }
-+ /* Stabs debugging sections. */
-+ .stab 0 : { *(.stab) }
-+ .stabstr 0 : { *(.stabstr) }
-+ .stab.excl 0 : { *(.stab.excl) }
-+ .stab.exclstr 0 : { *(.stab.exclstr) }
-+ .stab.index 0 : { *(.stab.index) }
-+ .stab.indexstr 0 : { *(.stab.indexstr) }
-+ .comment 0 : { *(.comment) }
-+}
---- linux-2.4.27/drivers/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/Makefile
-@@ -25,6 +25,7 @@
- subdir-$(CONFIG_NUBUS) += nubus
- subdir-$(CONFIG_TC) += tc
- subdir-$(CONFIG_VT) += video
-+subdir-$(CONFIG_MMC) += mmc
- subdir-$(CONFIG_MAC) += macintosh
- subdir-$(CONFIG_PPC32) += macintosh
- subdir-$(CONFIG_USB) += usb
---- linux-2.4.27/drivers/char/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/char/Config.in
-@@ -253,6 +253,7 @@
- dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
- dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
- dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
-+ dep_tristate ' PXA250/210 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_PXA
- dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
- dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
- dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
-@@ -334,6 +335,9 @@
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
- tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
- fi
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ tristate 'PXA250/210 Real Time Clock' CONFIG_PXA_RTC
-+fi
- if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
- tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
- fi
-@@ -416,4 +420,8 @@
- dep_tristate 'HP OB600 C/CT Pop-up mouse support' CONFIG_OBMOUSE $CONFIG_INPUT_MOUSEDEV
- fi
-
-+if [ "$CONFIG_ARCH_TRIZEPS2" = "y" ]; then
-+ tristate ' MT6N TTL I/O suport' CONFIG_TRIZEPS2_TTLIO
-+fi
-+
- endmenu
---- linux-2.4.27/drivers/char/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/char/Makefile
-@@ -281,6 +281,7 @@
- obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
- obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
- obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
-+obj-$(CONFIG_PXA_RTC) += sa1100-rtc.o
- obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
- ifeq ($(CONFIG_PPC),)
- obj-$(CONFIG_NVRAM) += nvram.o
---- /dev/null
-+++ linux-2.4.27/drivers/char/mt6n_ttl.c
-@@ -0,0 +1,316 @@
-+/*
-+ * Trizeps-2 MT6N development board TTL-IO interface for Linux
-+ *
-+ * Copyright (C) 2003 Luc De Cock
-+ *
-+ * This driver allows use of the TTL-IO interface on the MT6N
-+ * from user space. It exports the /dev/ttlio interface supporting
-+ * some ioctl() and also the /proc/driver/ttlio pseudo-file
-+ * for status information.
-+ *
-+ * The ioctls can be used to set individual TTL output lines.
-+ * Only ioctls are supported.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Based on other minimal char device drivers, like Alan's
-+ * watchdog, Ted's random, Paul's rtc, etc. etc.
-+ *
-+ * 1.00 Luc De Cock: initial version.
-+ */
-+
-+#define TTLIO_VERSION "1.00"
-+
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/miscdevice.h>
-+#include <linux/fcntl.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+/* Writing to the register sets the output lines
-+* Reading from the register returns the status of the input lines
-+*/
-+static unsigned short *ttlio_base = (unsigned short *) TRIZEPS2_TTLIO_BASE;
-+static unsigned short ttlio_shadow = 0;
-+
-+/* interrupt stuff */
-+static struct fasync_struct *ttlio_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(ttlio_wait);
-+static int ttlio_irq_arrived = 0;
-+static spinlock_t ttlio_lock;
-+static unsigned short ttlio_in = 0;
-+static volatile unsigned long teller = 0;
-+
-+
-+static int ttlio_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg);
-+
-+static int ttlio_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+
-+
-+static void ttlio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ ttlio_in = *ttlio_base;
-+
-+ ttlio_irq_arrived = 1;
-+ teller++;
-+
-+ /* wake up the waiting process */
-+ wake_up_interruptible(&ttlio_wait);
-+ kill_fasync(&ttlio_async_queue, SIGIO, POLL_IN);
-+}
-+
-+/*
-+ * Now all the various file operations that we export.
-+ */
-+
-+static int ttlio_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ unsigned long ttlio_val;
-+
-+ switch (cmd) {
-+ case TTLIO_RESET: /* clear all lines */
-+ {
-+ *ttlio_base = 0;
-+ return 0;
-+ }
-+ case TTLIO_GET: /* get state of TTL input lines */
-+ {
-+ ttlio_val = *ttlio_base;
-+ return put_user(ttlio_val, (unsigned long *)arg);
-+ }
-+ case TTLIO_SET: /* set state of TTL output lines */
-+ {
-+ unsigned long user_val;
-+ if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
-+ return -EFAULT;
-+ ttlio_shadow |= (unsigned short) user_val;
-+ *ttlio_base = ttlio_shadow;
-+ return 0;
-+ }
-+ case TTLIO_UNSET: /* unset (clear) state of TTL output lines */
-+ {
-+ unsigned long user_val;
-+ if (copy_from_user(&user_val, arg, sizeof(unsigned long)))
-+ return -EFAULT;
-+ ttlio_shadow &= ~((unsigned short) user_val);
-+ *ttlio_base = ttlio_shadow;
-+ return 0;
-+ }
-+ case 100: /* get counter */
-+ {
-+ return put_user(teller, (unsigned long *)arg);
-+ }
-+ case 101: /* reset counter */
-+ {
-+ teller = 0;
-+ return 0;
-+ }
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+}
-+
-+static ssize_t ttlio_read(struct file *file, char *buf,
-+ size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned short data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned short))
-+ return -EINVAL;
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ spin_lock_irq(&ttlio_lock);
-+ data = *ttlio_base;
-+ spin_unlock_irq(&ttlio_lock);
-+ retval = put_user(data, (unsigned short *) buf);
-+ if (!retval)
-+ retval = sizeof(unsigned short);
-+ return retval;
-+ }
-+ /* blocking read: wait for interrupt */
-+ add_wait_queue(&ttlio_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq(&ttlio_lock);
-+ data = *ttlio_base;
-+ if (ttlio_irq_arrived) {
-+ ttlio_irq_arrived = 0;
-+ break;
-+ }
-+ spin_unlock_irq(&ttlio_lock);
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+ schedule();
-+ }
-+
-+ spin_unlock_irq(&ttlio_lock);
-+ retval = put_user(data, (unsigned short *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned short);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&ttlio_wait, &wait);
-+ return retval;
-+}
-+
-+static ssize_t ttlio_write(struct file *file,
-+ const char *buf, size_t count, loff_t *ppos)
-+{
-+ unsigned short content;
-+
-+ if (count < sizeof(unsigned short))
-+ return -EINVAL;
-+
-+ if (copy_from_user (&content, buf, sizeof(unsigned short)))
-+ return -EFAULT;
-+
-+ ttlio_shadow = content;
-+ *ttlio_base = ttlio_shadow;
-+
-+ *ppos += sizeof(unsigned short);
-+
-+ return sizeof(unsigned short);
-+}
-+
-+static int ttlio_open(struct inode *inode, struct file *file)
-+{
-+ ttlio_irq_arrived = 0;
-+ return 0;
-+}
-+
-+static int ttlio_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &ttlio_async_queue);
-+}
-+
-+static unsigned int ttlio_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait(file, &ttlio_wait, wait);
-+ return ttlio_irq_arrived ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t ttlio_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+/*
-+ * The various file operations we support.
-+ */
-+
-+static struct file_operations ttlio_fops = {
-+ owner: THIS_MODULE,
-+ llseek: ttlio_llseek,
-+ read: ttlio_read,
-+ poll: ttlio_poll,
-+ write: ttlio_write,
-+ ioctl: ttlio_ioctl,
-+ open: ttlio_open,
-+ fasync: ttlio_fasync,
-+};
-+
-+static struct miscdevice ttlio_dev = {
-+ TTLIO_MINOR,
-+ "ttlio",
-+ &ttlio_fops
-+};
-+
-+static int __init ttlio_init(void)
-+{
-+ printk(KERN_INFO "MT6N TTL-I/O driver (release %s)\n",
-+ TTLIO_VERSION);
-+
-+ misc_register(&ttlio_dev);
-+ create_proc_read_entry ("driver/ttlio", 0, 0, ttlio_read_proc, NULL);
-+
-+ set_GPIO_IRQ_edge(GPIO_TTLIO_IRQ, GPIO_FALLING_EDGE);
-+ if (request_irq(TTLIO_IRQ, ttlio_interrupt, SA_INTERRUPT, "ttlio irq", NULL)) {
-+ printk(KERN_ERR "ttlio: irq %d already in use\n", TTLIO_IRQ);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static void __exit ttlio_exit(void)
-+{
-+ free_irq(TTLIO_IRQ, NULL);
-+ remove_proc_entry ("driver/ttlio", NULL);
-+ misc_deregister(&ttlio_dev);
-+}
-+
-+module_init(ttlio_init);
-+module_exit(ttlio_exit);
-+EXPORT_NO_SYMBOLS;
-+
-+/*
-+ * Info exported via "/proc/driver/ttlio".
-+ */
-+
-+static int ttlio_proc_output(char *buf)
-+{
-+ char *p;
-+ unsigned short val;
-+ int i;
-+
-+ p = buf;
-+
-+ p += sprintf(p, "input : ");
-+ /* write the state of the input lines */
-+ val = *ttlio_base;
-+ for (i = 0; i < 8*sizeof(unsigned short); i++) {
-+ *p++ = (val & 1) ? '1' : '0';
-+ val >>= 1;
-+ }
-+ *p = 0;
-+ p += sprintf(p, "\noutput: ");
-+ /* write the state of the output lines */
-+ val = ttlio_shadow;
-+ for (i = 0; i < 8*sizeof(unsigned short); i++) {
-+ *p++ = (val & 1) ? '1' : '0';
-+ val >>= 1;
-+ }
-+ *p = 0;
-+ p += sprintf(p, "\n");
-+
-+ return p - buf;
-+}
-+
-+static int ttlio_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ int len = ttlio_proc_output (page);
-+ if (len <= off+count) *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count) len = count;
-+ if (len < 0) len = 0;
-+ return len;
-+}
-+
-+MODULE_AUTHOR("Luc De Cock");
-+MODULE_DESCRIPTION("MT6N TTL-I/O driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/char/sa1100-rtc.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/char/sa1100-rtc.c
-@@ -1,5 +1,6 @@
- /*
- * Real Time Clock interface for Linux on StrongARM SA1100
-+ * and XScale PXA250/210.
- *
- * Copyright (c) 2000 Nils Faerber
- *
-@@ -470,5 +471,5 @@
- module_exit(rtc_exit);
-
- MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
--MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
-+MODULE_DESCRIPTION("SA1100/PXA Realtime Clock Driver (RTC)");
- EXPORT_NO_SYMBOLS;
---- linux-2.4.27/drivers/char/sa1100_wdt.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/char/sa1100_wdt.c
-@@ -1,5 +1,5 @@
- /*
-- * Watchdog driver for the SA11x0
-+ * Watchdog driver for the SA11x0/PXA
- *
- * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
- * Based on SoftDog driver by Alan Cox <alan@redhat.com>
-@@ -35,13 +35,20 @@
-
- #define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
-
--static int sa1100_margin = TIMER_MARGIN; /* in seconds */
-+static int timer_margin = TIMER_MARGIN; /* in seconds */
- static int sa1100wdt_users;
- static int pre_margin;
- #ifdef MODULE
--MODULE_PARM(sa1100_margin,"i");
-+MODULE_PARM(timer_margin,"i");
- #endif
-
-+static void sa1100dog_ping( void)
-+{
-+ /* reload counter with (new) margin */
-+ pre_margin=3686400 * timer_margin;
-+ OSMR3 = OSCR + pre_margin;
-+}
-+
- /*
- * Allow only one person to hold it open
- */
-@@ -51,9 +58,7 @@
- if(test_and_set_bit(1,&sa1100wdt_users))
- return -EBUSY;
- MOD_INC_USE_COUNT;
-- /* Activate SA1100 Watchdog timer */
-- pre_margin=3686400 * sa1100_margin;
-- OSMR3 = OSCR + pre_margin;
-+ sa1100dog_ping();
- OSSR = OSSR_M3;
- OWER = OWER_WME;
- OIER |= OIER_E3;
-@@ -93,8 +98,11 @@
- unsigned int cmd, unsigned long arg)
- {
- static struct watchdog_info ident = {
-- identity: "SA1100 Watchdog",
-+ identity: "PXA/SA1100 Watchdog",
-+ options: WDIOF_SETTIMEOUT,
-+ firmware_version: 0,
- };
-+ int new_margin;
-
- switch(cmd){
- default:
-@@ -108,6 +116,16 @@
- case WDIOC_KEEPALIVE:
- OSMR3 = OSCR + pre_margin;
- return 0;
-+ case WDIOC_SETTIMEOUT:
-+ if (get_user(new_margin, (int *)arg))
-+ return -EFAULT;
-+ if (new_margin < 1)
-+ return -EINVAL;
-+ timer_margin = new_margin;
-+ sa1100dog_ping();
-+ /* Fall */
-+ case WDIOC_GETTIMEOUT:
-+ return put_user(timer_margin, (int *)arg);
- }
- }
-
-@@ -123,7 +141,11 @@
- static struct miscdevice sa1100dog_miscdev=
- {
- WATCHDOG_MINOR,
-- "SA1100 watchdog",
-+#if defined(CONFIG_SA1100_WATCHDOG)
-+ "SA1100_watchdog",
-+#elif defined(CONFIG_PXA_WATCHDOG)
-+ "PXA_watchdog",
-+#endif
- &sa1100dog_fops
- };
-
-@@ -136,7 +158,7 @@
- if (ret)
- return ret;
-
-- printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
-+ printk("SA1100/PXA Watchdog Timer: timer margin %d sec\n", timer_margin);
-
- return 0;
- }
---- linux-2.4.27/drivers/char/serial.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/char/serial.c
-@@ -133,6 +133,16 @@
- #endif
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+#define pxa_port(x) ((x) == PORT_PXA)
-+#define pxa_buggy_port(x) ({ \
-+ int cpu_ver; asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver)); \
-+ ((x) == PORT_PXA && (cpu_ver & ~1) == 0x69052100); })
-+#else
-+#define pxa_port(x) (0)
-+#define pxa_buggy_port(x) (0)
-+#endif
-+
- /* Set of debugging defines */
-
- #undef SERIAL_DEBUG_INTR
-@@ -311,6 +321,7 @@
- { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |
- UART_STARTECH },
- { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "PXA UART", 32, UART_CLEAR_FIFO | UART_USE_FIFO },
- { 0, 0}
- };
-
-@@ -424,6 +435,9 @@
- case SERIAL_IO_MEM:
- return readb((unsigned long) info->iomem_base +
- (offset<<info->iomem_reg_shift));
-+ case SERIAL_IO_MEM32:
-+ return readl((unsigned long) info->iomem_base +
-+ (offset<<info->iomem_reg_shift));
- default:
- return inb(info->port + offset);
- }
-@@ -443,6 +457,10 @@
- writeb(value, (unsigned long) info->iomem_base +
- (offset<<info->iomem_reg_shift));
- break;
-+ case SERIAL_IO_MEM32:
-+ writel(value, (unsigned long) info->iomem_base +
-+ (offset<<info->iomem_reg_shift));
-+ break;
- default:
- outb(value, info->port+offset);
- }
-@@ -1306,6 +1324,16 @@
- }
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+ if (state->type == PORT_PXA) {
-+ switch ((long)state->iomem_base) {
-+ case (long)&FFUART: CKEN |= CKEN6_FFUART; break;
-+ case (long)&BTUART: CKEN |= CKEN7_BTUART; break;
-+ case (long)&STUART: CKEN |= CKEN5_STUART; break;
-+ }
-+ }
-+#endif
-+
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in change_speed())
-@@ -1403,6 +1431,8 @@
- {
- if (state->irq != 0)
- info->MCR |= UART_MCR_OUT2;
-+ if (pxa_buggy_port(state->type) && state->irq != 0)
-+ info->MCR ^= UART_MCR_OUT2;
- }
- info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
- serial_outp(info, UART_MCR, info->MCR);
-@@ -1411,6 +1441,8 @@
- * Finally, enable interrupts
- */
- info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-+ if (pxa_port(state->type))
-+ info->IER |= UART_IER_UUE | UART_IER_RTOIE;
- serial_outp(info, UART_IER, info->IER); /* enable interrupts */
-
- #ifdef CONFIG_SERIAL_MANY_PORTS
-@@ -1542,6 +1574,8 @@
- } else
- #endif
- info->MCR &= ~UART_MCR_OUT2;
-+ if (pxa_buggy_port(state->type))
-+ info->MCR ^= UART_MCR_OUT2;
- info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
-
- /* disable break condition */
-@@ -1567,6 +1601,20 @@
- state->baud_base = SERIAL_RSA_BAUD_BASE_LO;
- #endif
-
-+#ifdef CONFIG_ARCH_PXA
-+ if (state->type == PORT_PXA
-+#ifdef CONFIG_SERIAL_CONSOLE
-+ && sercons.index != info->line
-+#endif
-+ ) {
-+ switch ((long)state->iomem_base) {
-+ case (long)&FFUART: CKEN &= ~CKEN6_FFUART; break;
-+ case (long)&BTUART: CKEN &= ~CKEN7_BTUART; break;
-+ case (long)&STUART: CKEN &= ~CKEN5_STUART; break;
-+ }
-+ }
-+#endif
-+
-
- (void)serial_in(info, UART_RX); /* read data port to reset things */
-
-@@ -1857,6 +1905,8 @@
- save_flags(flags); cli();
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type))
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
- restore_flags(flags);
- }
-
-@@ -1933,6 +1983,11 @@
- && !(info->IER & UART_IER_THRI)) {
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type)) {
-+ save_flags(flags); cli();
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
-+ restore_flags(flags);
-+ }
- }
- return ret;
- }
-@@ -1990,6 +2045,8 @@
- /* Make sure transmit interrupts are on */
- info->IER |= UART_IER_THRI;
- serial_out(info, UART_IER, info->IER);
-+ if (pxa_buggy_port(info->state->type))
-+ rs_interrupt_single(info->state->irq, NULL, NULL);
- }
- }
-
-@@ -5517,7 +5574,6 @@
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- state->magic = SSTATE_MAGIC;
- state->line = i;
-- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
-@@ -5531,14 +5587,18 @@
- state->irq = irq_cannonicalize(state->irq);
- if (state->hub6)
- state->io_type = SERIAL_IO_HUB6;
-- if (state->port && check_region(state->port,8))
-+ if (state->port && check_region(state->port,8)) {
-+ state->type = PORT_UNKNOWN;
- continue;
-+ }
- #ifdef CONFIG_MCA
- if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
- continue;
- #endif
-- if (state->flags & ASYNC_BOOT_AUTOCONF)
-+ if (state->flags & ASYNC_BOOT_AUTOCONF) {
-+ state->type = PORT_UNKNOWN;
- autoconfig(state);
-+ }
- }
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- if (state->type == PORT_UNKNOWN)
-@@ -5858,6 +5918,8 @@
- */
- ier = serial_in(info, UART_IER);
- serial_out(info, UART_IER, 0x00);
-+ if (pxa_port(info->state->type))
-+ serial_out(info, UART_IER, UART_IER_UUE);
-
- /*
- * Now, do each character
-@@ -6009,6 +6071,8 @@
- serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */
- serial_out(info, UART_LCR, cval); /* reset DLAB */
- serial_out(info, UART_IER, 0);
-+ if (pxa_port(info->state->type))
-+ serial_out(info, UART_IER, UART_IER_UUE);
- serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
- /*
---- linux-2.4.27/drivers/i2c/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/i2c/Config.in
-@@ -54,6 +54,11 @@
- fi
- fi
-
-+ if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_tristate 'PXA I2C Algorithm' CONFIG_I2C_PXA_ALGO $CONFIG_I2C
-+ dep_tristate 'PXA I2C Adapter' CONFIG_I2C_PXA_ADAP $CONFIG_I2C_PXA_ALGO
-+ fi
-+
- if [ "$CONFIG_ALL_PPC" = "y" ] ; then
- dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
- fi
---- linux-2.4.27/drivers/i2c/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/i2c/Makefile
-@@ -6,7 +6,7 @@
-
- export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
- i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
-- i2c-proc.o
-+ i2c-proc.o i2c-algo-pxa.o
-
- # Init order: core, chardev, bit adapters, pcf adapters
-
-@@ -34,6 +34,10 @@
- obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o i2c-sibyte.o
- obj-$(CONFIG_I2C_MAX1617) += i2c-max1617.o
- obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
-+# PXA adapters
-+obj-$(CONFIG_I2C_PXA_ALGO) += i2c-algo-pxa.o
-+obj-$(CONFIG_I2C_PXA_ADAP) += i2c-adap-pxa.o
-+
-
- # This is needed for automatic patch generation: sensors code starts here
- # This is needed for automatic patch generation: sensors code ends here
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-adap-pxa.c
-@@ -0,0 +1,396 @@
-+/*
-+ * i2c_adap_pxa.c
-+ *
-+ * I2C adapter for the PXA I2C bus access.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Apr 2002: Initial version [CS]
-+ * Jun 2002: Properly seperated algo/adap [FB]
-+ * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
-+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-id.h>
-+#include <linux/init.h>
-+#include <linux/time.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/irqs.h> /* for IRQ_I2C */
-+
-+#include "i2c-pxa.h"
-+
-+/*
-+ * Set this to zero to remove all debug statements via dead code elimination.
-+ */
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int i2c_debug = DEBUG;
-+#else
-+#define i2c_debug 0
-+#endif
-+
-+static int irq = 0;
-+static volatile int i2c_pending = 0; /* interrupt pending when 1 */
-+static volatile int bus_error = 0;
-+static volatile int tx_finished = 0;
-+static volatile int rx_finished = 0;
-+
-+static wait_queue_head_t i2c_wait;
-+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte);
-+
-+/* place a byte in the transmit register */
-+static void i2c_pxa_write_byte(u8 value)
-+{
-+ IDBR = value;
-+}
-+
-+/* read byte in the receive register */
-+static u8 i2c_pxa_read_byte(void)
-+{
-+ return (u8) (0xff & IDBR);
-+}
-+
-+static void i2c_pxa_start(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_START;
-+ icr &= ~(ICR_STOP | ICR_ALDIE | ICR_ACKNAK);
-+ ICR = icr;
-+
-+ bus_error=0; /* clear any bus_error from previous txfers */
-+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */
-+ rx_finished=0;
-+ i2c_pending = 0;
-+}
-+
-+static void i2c_pxa_repeat_start(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_START;
-+ icr &= ~(ICR_STOP | ICR_ALDIE);
-+ ICR = icr;
-+
-+ bus_error=0; /* clear any bus_error from previous txfers */
-+ tx_finished=0; /* clear rx and tx interrupts from previous txfers */
-+ rx_finished=0;
-+ i2c_pending = 0;
-+}
-+
-+static void i2c_pxa_stop(void)
-+{
-+ unsigned long icr = ICR;
-+ icr |= ICR_STOP;
-+ icr &= ~(ICR_START);
-+ ICR = icr;
-+}
-+
-+static void i2c_pxa_midbyte(void)
-+{
-+ unsigned long icr = ICR;
-+ icr &= ~(ICR_START | ICR_STOP);
-+ ICR = icr;
-+}
-+
-+static void i2c_pxa_abort(void)
-+{
-+ unsigned long timeout = jiffies + HZ/4;
-+
-+#ifdef PXA_ABORT_MA
-+ while ((long)(timeout - jiffies) > 0 && (ICR & ICR_TB)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+
-+ ICR |= ICR_MA;
-+ udelay(100);
-+#else
-+ while ((long)(timeout - jiffies) > 0 && (IBMR & 0x1) == 0) {
-+ i2c_pxa_transfer( 1, I2C_RECEIVE, 1);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+#endif
-+ ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
-+}
-+
-+static int i2c_pxa_wait_bus_not_busy( void)
-+{
-+ int timeout = DEF_TIMEOUT;
-+
-+ while (timeout-- && (ISR & ISR_IBB)) {
-+ udelay(100); /* wait for 100 us */
-+ }
-+
-+ return (timeout<=0);
-+}
-+
-+static void i2c_pxa_wait_for_ite(void){
-+ unsigned long flags;
-+ if (irq > 0) {
-+ save_flags_cli(flags);
-+ if (i2c_pending == 0) {
-+ interruptible_sleep_on_timeout(&i2c_wait, I2C_SLEEP_TIMEOUT );
-+ }
-+ i2c_pending = 0;
-+ restore_flags(flags);
-+ } else {
-+ udelay(100);
-+ }
-+}
-+
-+static int i2c_pxa_wait_for_int( int wait_type)
-+{
-+ int timeout = DEF_TIMEOUT;
-+#ifdef DEBUG
-+ if (bus_error)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Bus error on enter\n");
-+ if (rx_finished)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Receive interrupt on enter\n");
-+ if (tx_finished)
-+ printk(KERN_INFO"i2c_pxa_wait_for_int: Transmit interrupt on enter\n");
-+#endif
-+
-+ if (wait_type == I2C_RECEIVE){ /* wait on receive */
-+
-+ do {
-+ i2c_pxa_wait_for_ite();
-+ } while (!(rx_finished) && timeout-- && !signal_pending(current));
-+
-+#ifdef DEBUG
-+ if (timeout<0){
-+ if (tx_finished)
-+ printk("Error: i2c-algo-pxa.o: received a tx"
-+ " interrupt while waiting on a rx in wait_for_int");
-+ }
-+#endif
-+ } else { /* wait on transmit */
-+
-+ do {
-+ i2c_pxa_wait_for_ite();
-+ } while (!(tx_finished) && timeout-- && !signal_pending(current));
-+
-+#ifdef DEBUG
-+ if (timeout<0){
-+ if (rx_finished)
-+ printk("Error: i2c-algo-pxa.o: received a rx"
-+ " interrupt while waiting on a tx in wait_for_int");
-+ }
-+#endif
-+ }
-+
-+ udelay(ACK_DELAY); /* this is needed for the bus error */
-+
-+ tx_finished=0;
-+ rx_finished=0;
-+
-+ if (bus_error){
-+ bus_error=0;
-+ if( i2c_debug > 2)printk("wait_for_int: error - no ack.\n");
-+ return BUS_ERROR;
-+ }
-+
-+ if (signal_pending(current)) {
-+ return (-ERESTARTSYS);
-+ } else if (timeout < 0) {
-+ if( i2c_debug > 2)printk("wait_for_int: timeout.\n");
-+ return(-EIO);
-+ } else
-+ return(0);
-+}
-+
-+static void i2c_pxa_transfer( int lastbyte, int receive, int midbyte)
-+{
-+ if( lastbyte)
-+ {
-+ if( receive==I2C_RECEIVE) ICR |= ICR_ACKNAK;
-+ i2c_pxa_stop();
-+ }
-+ else if( midbyte)
-+ {
-+ i2c_pxa_midbyte();
-+ }
-+ ICR |= ICR_TB;
-+}
-+
-+static void i2c_pxa_reset( void)
-+{
-+#ifdef DEBUG
-+ printk("Resetting I2C Controller Unit\n");
-+#endif
-+
-+ /* abort any transfer currently under way */
-+ i2c_pxa_abort();
-+
-+ /* reset according to 9.8 */
-+ ICR = ICR_UR;
-+ ISR = I2C_ISR_INIT;
-+ ICR &= ~ICR_UR;
-+
-+ /* set the global I2C clock on */
-+ CKEN |= CKEN14_I2C;
-+
-+ /* set our slave address */
-+ ISAR = I2C_PXA_SLAVE_ADDR;
-+
-+ /* set control register values */
-+ ICR = I2C_ICR_INIT;
-+
-+ /* clear any leftover states from prior transmissions */
-+ i2c_pending = rx_finished = tx_finished = bus_error = 0;
-+
-+ /* enable unit */
-+ ICR |= ICR_IUE;
-+ udelay(100);
-+}
-+
-+static void i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int status, wakeup = 0;
-+ status = (ISR);
-+
-+ if (status & ISR_BED){
-+ (ISR) |= ISR_BED;
-+ bus_error=ISR_BED;
-+ wakeup = 1;
-+ }
-+ if (status & ISR_ITE){
-+ (ISR) |= ISR_ITE;
-+ tx_finished=ISR_ITE;
-+ wakeup = 1;
-+ }
-+ if (status & ISR_IRF){
-+ (ISR) |= ISR_IRF;
-+ rx_finished=ISR_IRF;
-+ wakeup = 1;
-+ }
-+ if (wakeup) {
-+ i2c_pending = 1;
-+ wake_up_interruptible(&i2c_wait);
-+ }
-+}
-+
-+static int i2c_pxa_resource_init( void)
-+{
-+ init_waitqueue_head(&i2c_wait);
-+
-+ if (request_irq(IRQ_I2C, &i2c_pxa_handler, SA_INTERRUPT, "I2C_PXA", 0) < 0) {
-+ irq = 0;
-+ if( i2c_debug)
-+ printk(KERN_INFO "I2C: Failed to register I2C irq %i\n", IRQ_I2C);
-+ return -ENODEV;
-+ }else{
-+ irq = IRQ_I2C;
-+ enable_irq(irq);
-+ }
-+ return 0;
-+}
-+
-+static void i2c_pxa_resource_release( void)
-+{
-+ if( irq > 0)
-+ {
-+ disable_irq(irq);
-+ free_irq(irq,0);
-+ irq=0;
-+ }
-+}
-+
-+static void i2c_pxa_inc_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_INC_USE_COUNT;
-+#endif
-+}
-+
-+static void i2c_pxa_dec_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_DEC_USE_COUNT;
-+#endif
-+}
-+
-+static int i2c_pxa_client_register(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static int i2c_pxa_client_unregister(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static struct i2c_algo_pxa_data i2c_pxa_data = {
-+ write_byte: i2c_pxa_write_byte,
-+ read_byte: i2c_pxa_read_byte,
-+
-+ start: i2c_pxa_start,
-+ repeat_start: i2c_pxa_repeat_start,
-+ stop: i2c_pxa_stop,
-+ abort: i2c_pxa_abort,
-+
-+ wait_bus_not_busy: i2c_pxa_wait_bus_not_busy,
-+ wait_for_interrupt: i2c_pxa_wait_for_int,
-+ transfer: i2c_pxa_transfer,
-+ reset: i2c_pxa_reset,
-+
-+ udelay: 10,
-+ timeout: DEF_TIMEOUT,
-+};
-+
-+static struct i2c_adapter i2c_pxa_ops = {
-+ name: "PXA-I2C-Adapter",
-+ id: I2C_ALGO_PXA,
-+ algo_data: &i2c_pxa_data,
-+ inc_use: i2c_pxa_inc_use,
-+ dec_use: i2c_pxa_dec_use,
-+ client_register: i2c_pxa_client_register,
-+ client_unregister: i2c_pxa_client_unregister,
-+ retries: 2,
-+};
-+
-+extern int i2c_pxa_add_bus(struct i2c_adapter *);
-+extern int i2c_pxa_del_bus(struct i2c_adapter *);
-+
-+static int __init i2c_adap_pxa_init(void)
-+{
-+ if( i2c_pxa_resource_init() == 0) {
-+
-+ if (i2c_pxa_add_bus(&i2c_pxa_ops) < 0) {
-+ i2c_pxa_resource_release();
-+ printk(KERN_INFO "I2C: Failed to add bus\n");
-+ return -ENODEV;
-+ }
-+ } else {
-+ return -ENODEV;
-+ }
-+
-+ printk(KERN_INFO "I2C: Successfully added bus\n");
-+
-+ return 0;
-+}
-+
-+static void i2c_adap_pxa_exit(void)
-+{
-+ i2c_pxa_del_bus( &i2c_pxa_ops);
-+ i2c_pxa_resource_release();
-+
-+ printk(KERN_INFO "I2C: Successfully removed bus\n");
-+}
-+
-+module_init(i2c_adap_pxa_init);
-+module_exit(i2c_adap_pxa_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-algo-pxa.c
-@@ -0,0 +1,376 @@
-+/*
-+ * i2c-algo-pxa.c
-+ *
-+ * I2C algorithm for the PXA I2C bus access.
-+ * Byte driven algorithm similar to pcf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Apr 2002: Initial version [CS]
-+ * Jun 2002: Properly seperated algo/adap [FB]
-+ * Jan 2003: added limited signal handling [Kai-Uwe Bloem]
-+ * Jan 2003: allow SMBUS_QUICK as valid msg [FB]
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/i2c.h> /* struct i2c_msg and others */
-+#include <linux/i2c-id.h>
-+
-+#include "i2c-pxa.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via dead code elimination.
-+ */
-+//#define DEBUG 1
-+
-+#if DEBUG
-+static unsigned int i2c_debug = DEBUG;
-+#else
-+#define i2c_debug 0
-+#endif
-+
-+static int pxa_scan = 1;
-+
-+static int i2c_pxa_valid_messages( struct i2c_msg msgs[], int num)
-+{
-+ int i;
-+ if (num < 1 || num > MAX_MESSAGES){
-+ if( i2c_debug)
-+ printk(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n",
-+ MAX_MESSAGES, num);
-+ return -EINVAL;
-+ }
-+
-+ /* check consistency of our messages */
-+ for (i=0;i<num;i++){
-+ if (&msgs[i]==NULL){
-+ if( i2c_debug) printk(KERN_INFO "Msgs is NULL\n");
-+ return -EINVAL;
-+ } else {
-+ if (msgs[i].len < 0 || msgs[i].buf == NULL){
-+ if( i2c_debug)printk(KERN_INFO "Length is less than zero");
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+static int i2c_pxa_readbytes(struct i2c_adapter *i2c_adap, char *buf,
-+ int count, int last)
-+{
-+
-+ int i, timeout=0;
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+
-+ /* increment number of bytes to read by one -- read dummy byte */
-+ for (i = 0; i <= count; i++) {
-+ if (i!=0){
-+ /* set ACK to NAK for last received byte ICR[ACKNAK] = 1
-+ only if not a repeated start */
-+
-+ if ((i == count) && last) {
-+ adap->transfer( last, I2C_RECEIVE, 0);
-+ }else{
-+ adap->transfer( 0, I2C_RECEIVE, 1);
-+ }
-+
-+ timeout = adap->wait_for_interrupt(I2C_RECEIVE);
-+
-+#ifdef DEBUG
-+ if (timeout==BUS_ERROR){
-+ printk(KERN_INFO "i2c_pxa_readbytes: bus error -> forcing reset\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout){
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_readbytes: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+
-+ }
-+
-+ if (i) {
-+ buf[i - 1] = adap->read_byte();
-+ } else {
-+ adap->read_byte(); /* dummy read */
-+ }
-+ }
-+ return (i - 1);
-+}
-+
-+static int i2c_pxa_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
-+ int count, int last)
-+{
-+
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+ int wrcount, timeout;
-+
-+ for (wrcount=0; wrcount<count; ++wrcount) {
-+
-+ adap->write_byte(buf[wrcount]);
-+ if ((wrcount==(count-1)) && last) {
-+ adap->transfer( last, I2C_TRANSMIT, 0);
-+ }else{
-+ adap->transfer( 0, I2C_TRANSMIT, 1);
-+ }
-+
-+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
-+
-+#ifdef DEBUG
-+ if (timeout==BUS_ERROR) {
-+ printk(KERN_INFO "i2c_pxa_sendbytes: bus error -> forcing reset.\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout) {
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_sendbytes: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+ }
-+ return (wrcount);
-+}
-+
-+
-+static inline int i2c_pxa_set_ctrl_byte(struct i2c_algo_pxa_data * adap, struct i2c_msg *msg)
-+{
-+ u16 flags = msg->flags;
-+ u8 addr;
-+ addr = (u8) ( (0x7f & msg->addr) << 1 );
-+ if (flags & I2C_M_RD )
-+ addr |= 1;
-+ if (flags & I2C_M_REV_DIR_ADDR )
-+ addr ^= 1;
-+ adap->write_byte(addr);
-+ return 0;
-+}
-+
-+static int i2c_pxa_do_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
-+{
-+ struct i2c_algo_pxa_data * adap;
-+ struct i2c_msg *pmsg=NULL;
-+ int i;
-+ int ret=0, timeout;
-+
-+ adap = i2c_adap->algo_data;
-+
-+ timeout = adap->wait_bus_not_busy();
-+
-+ if (timeout) {
-+ return I2C_RETRY;
-+ }
-+
-+ for (i = 0;ret >= 0 && i < num; i++) {
-+ int last = i + 1 == num;
-+ pmsg = &msgs[i];
-+
-+ ret = i2c_pxa_set_ctrl_byte(adap,pmsg);
-+
-+ /* Send START */
-+ if (i == 0) {
-+ adap->start();
-+ }else{
-+ adap->repeat_start();
-+ }
-+
-+ adap->transfer(0, I2C_TRANSMIT, 0);
-+
-+ /* Wait for ITE (transmit empty) */
-+ timeout = adap->wait_for_interrupt(I2C_TRANSMIT);
-+
-+#ifdef DEBUG
-+ /* Check for ACK (bus error) */
-+ if (timeout==BUS_ERROR){
-+ printk(KERN_INFO "i2c_pxa_do_xfer: bus error -> forcing reset\n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ } else
-+#endif
-+ if (timeout == -ERESTARTSYS) {
-+ adap->abort();
-+ return timeout;
-+ } else
-+ if (timeout) {
-+#ifdef DEBUG
-+ printk(KERN_INFO "i2c_pxa_do_xfer: timeout -> forcing reset\n");
-+#endif
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+/* FIXME: handle arbitration... */
-+#if 0
-+ /* Check for bus arbitration loss */
-+ if (adap->arbitration_loss()){
-+ printk("Arbitration loss detected \n");
-+ adap->reset();
-+ return I2C_RETRY;
-+ }
-+#endif
-+
-+ /* Read */
-+ if (pmsg->flags & I2C_M_RD) {
-+ /* read bytes into buffer*/
-+ ret = i2c_pxa_readbytes(i2c_adap, pmsg->buf, pmsg->len, last);
-+#if DEBUG > 2
-+ if (ret != pmsg->len) {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d/%d bytes.\n",
-+ ret, pmsg->len);
-+ } else {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: read %d bytes.\n",ret);
-+ }
-+#endif
-+ } else { /* Write */
-+ ret = i2c_pxa_sendbytes(i2c_adap, pmsg->buf, pmsg->len, last);
-+#if DEBUG > 2
-+ if (ret != pmsg->len) {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d/%d bytes.\n",
-+ ret, pmsg->len);
-+ } else {
-+ printk(KERN_INFO"i2c_pxa_do_xfer: wrote %d bytes.\n",ret);
-+ }
-+#endif
-+ }
-+ }
-+
-+ if (ret<0){
-+ return ret;
-+ }else{
-+ return i;
-+ }
-+}
-+
-+static int i2c_pxa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
-+{
-+ int retval = i2c_pxa_valid_messages( msgs, num);
-+ if( retval > 0)
-+ {
-+ int i;
-+ for (i=i2c_adap->retries; i>=0; i--){
-+ int retval = i2c_pxa_do_xfer(i2c_adap,msgs,num);
-+ if (retval!=I2C_RETRY){
-+ return retval;
-+ }
-+ if( i2c_debug)printk(KERN_INFO"Retrying transmission \n");
-+ udelay(100);
-+ }
-+ if( i2c_debug)printk(KERN_INFO"Retried %i times\n",i2c_adap->retries);
-+ return -EREMOTEIO;
-+
-+ }
-+ return retval;
-+}
-+
-+struct i2c_algorithm i2c_pxa_algorithm = {
-+ name: "PXA-I2C-Algorithm",
-+ id: I2C_ALGO_PXA,
-+ master_xfer: i2c_pxa_xfer,
-+ smbus_xfer: NULL,
-+ slave_send: NULL,
-+ slave_recv: NULL,
-+ algo_control: NULL,
-+};
-+
-+/*
-+ * registering functions to load algorithms at runtime
-+ */
-+int i2c_pxa_add_bus(struct i2c_adapter *i2c_adap)
-+{
-+ struct i2c_algo_pxa_data *adap = i2c_adap->algo_data;
-+
-+ printk(KERN_INFO"I2C: Adding %s.\n", i2c_adap->name);
-+
-+ i2c_adap->algo = &i2c_pxa_algorithm;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ /* register new adapter to i2c module... */
-+ i2c_add_adapter(i2c_adap);
-+
-+ adap->reset();
-+
-+ /* scan bus */
-+ if (pxa_scan) {
-+ int i;
-+ printk(KERN_INFO "I2C: Scanning bus ");
-+ for (i = 0x02; i < 0xff; i+=2) {
-+ if( i==(I2C_PXA_SLAVE_ADDR<<1)) continue;
-+
-+ if (adap->wait_bus_not_busy()) {
-+ printk(KERN_INFO "I2C: scanning bus %s - TIMEOUTed.\n",
-+ i2c_adap->name);
-+ return -EIO;
-+ }
-+ adap->write_byte(i);
-+ adap->start();
-+ adap->transfer(0, I2C_TRANSMIT, 0);
-+
-+ if ((adap->wait_for_interrupt(I2C_TRANSMIT) != BUS_ERROR)) {
-+ printk("(%02x)",i>>1);
-+ adap->abort();
-+ } else {
-+// printk(".");
-+ adap->stop();
-+ }
-+ udelay(adap->udelay);
-+ }
-+ printk("\n");
-+ }
-+ return 0;
-+}
-+
-+int i2c_pxa_del_bus(struct i2c_adapter *i2c_adap)
-+{
-+ int res;
-+ if ((res = i2c_del_adapter(i2c_adap)) < 0)
-+ return res;
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ printk(KERN_INFO "I2C: Removing %s.\n", i2c_adap->name);
-+
-+ return 0;
-+}
-+
-+static int __init i2c_algo_pxa_init (void)
-+{
-+ printk(KERN_INFO "I2C: PXA algorithm module loaded.\n");
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(i2c_pxa_add_bus);
-+EXPORT_SYMBOL(i2c_pxa_del_bus);
-+
-+MODULE_PARM(pxa_scan, "i");
-+MODULE_PARM_DESC(pxa_scan, "Scan for active chips on the bus");
-+
-+MODULE_AUTHOR("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
-+
-+module_init(i2c_algo_pxa_init);
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-pxa.h
-@@ -0,0 +1,76 @@
-+/*
-+ * i2c_pxa.h
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#ifndef _I2C_PXA_H_
-+#define _I2C_PXA_H_
-+
-+struct i2c_algo_pxa_data
-+{
-+ void (*write_byte) (u8 value);
-+ u8 (*read_byte) (void);
-+ void (*start) (void);
-+ void (*repeat_start) (void);
-+ void (*stop) (void);
-+ void (*abort) (void);
-+ int (*wait_bus_not_busy) (void);
-+ int (*wait_for_interrupt) (int wait_type);
-+ void (*transfer) (int lastbyte, int receive, int midbyte);
-+ void (*reset) (void);
-+
-+ int udelay;
-+ int timeout;
-+};
-+
-+#define DEF_TIMEOUT 3
-+#define BUS_ERROR (-EREMOTEIO)
-+#define ACK_DELAY 0 /* time to delay before checking bus error */
-+#define MAX_MESSAGES 65536 /* maximum number of messages to send */
-+
-+#define I2C_SLEEP_TIMEOUT 2 /* time to sleep for on i2c transactions */
-+#define I2C_RETRY (-2000) /* an error has occurred retry transmit */
-+#define I2C_TRANSMIT 1
-+#define I2C_RECEIVE 0
-+#define I2C_PXA_SLAVE_ADDR 0x1 /* slave pxa unit address */
-+#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) /* ICR initialization value */
-+/* ICR initialize bit values
-+*
-+* 15. FM 0 (100 Khz operation)
-+* 14. UR 0 (No unit reset)
-+* 13. SADIE 0 (Disables the unit from interrupting on slave addresses
-+* matching its slave address)
-+* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration
-+* in master mode)
-+* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode)
-+* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent)
-+* 9. IRFIE 1 (Enable interrupts from full buffer received)
-+* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty)
-+* 7. GCD 1 (Disables i2c unit response to general call messages as a slave)
-+* 6. IUE 0 (Disable unit until we change settings)
-+* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL)
-+* 4. MA 0 (Only send stop with the ICR stop bit)
-+* 3. TB 0 (We are not transmitting a byte initially)
-+* 2. ACKNAK 0 (Send an ACK after the unit receives a byte)
-+* 1. STOP 0 (Do not send a STOP)
-+* 0. START 0 (Do not send a START)
-+*
-+*/
-+
-+#define I2C_ISR_INIT 0x7FF /* status register init */
-+/* I2C status register init values
-+ *
-+ * 10. BED 1 (Clear bus error detected)
-+ * 9. SAD 1 (Clear slave address detected)
-+ * 7. IRF 1 (Clear IDBR Receive Full)
-+ * 6. ITE 1 (Clear IDBR Transmit Empty)
-+ * 5. ALD 1 (Clear Arbitration Loss Detected)
-+ * 4. SSD 1 (Clear Slave Stop Detected)
-+ */
-+
-+#endif
---- linux-2.4.27/drivers/misc/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/Config.in
-@@ -13,5 +13,6 @@
- dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
- dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
- dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
-+dep_tristate ' UCB1400 Touchscreen support' CONFIG_MCP_UCB1400_TS $CONFIG_ARCH_PXA $CONFIG_SOUND
-
- endmenu
---- linux-2.4.27/drivers/misc/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/Makefile
-@@ -11,13 +11,15 @@
-
- O_TARGET := misc.o
-
--export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
-+export-objs := mcp-core.o mcp-sa1100.o mcp-pxa.o \
-+ ucb1x00-core.o
-
--obj-$(CONFIG_MCP) += mcp-core.o
--obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
-+obj-$(CONFIG_MCP_SA1100) += mcp-core.o mcp-sa1100.o
- obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
- obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
- obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-+obj-$(CONFIG_MCP_UCB1400_TS) += mcp-pxa.o ucb1x00-core.o ucb1x00-ts.o
-+obj-$(CONFIG_PXA_CERF_PDA) += cerf_ucb1400gpio.o
-
- include $(TOPDIR)/Rules.make
-
---- /dev/null
-+++ linux-2.4.27/drivers/misc/cerf_ucb1400gpio.c
-@@ -0,0 +1,189 @@
-+/*
-+ * cerf_ucb1400gpio.c
-+ *
-+ * UCB1400 GPIO control stuff for the cerf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ * Jun 2002: Removed ac97 dependency [FB]
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int ucb_debug = DEBUGGING;
-+#else
-+#define ucb_debug 0
-+#endif
-+
-+#define UP 1
-+#define DOWN 0
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_lcd_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ if( ucb_debug > 2) printk( KERN_INFO "Enabling LCD.\n");
-+ /* Enable [not] LCD_RESET to enable the LCD display */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_LCD_RESET, 0);
-+
-+ /* Enable the Contrast circuit */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_ENA, 0);
-+}
-+
-+void cerf_ucb1400gpio_lcd_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ if( ucb_debug > 2) printk( KERN_INFO "Disabling LCD.\n");
-+ /* Disable the Contrast circuit */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_ENA);
-+
-+ /* Disable [not] LCD_RESET to enable the LCD display */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_LCD_RESET);
-+}
-+
-+void cerf_ucb1400gpio_lcd_contrast_step( int direction)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ // Assert the chip select and the up modifier
-+ ucb1x00_io_set_dir( ucb, 0,
-+ (UCB1400_GPIO_CONT_CS |
-+ UCB1400_GPIO_CONT_DOWN |
-+ UCB1400_GPIO_CONT_INC));
-+
-+ if( direction == DOWN)
-+ {
-+ if( ucb_debug > 3)
-+ printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
-+ "stepping up\n");
-+ //goin' up
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_DOWN, 0);
-+ }
-+ else
-+ {
-+ if( ucb_debug > 3)
-+ printk(KERN_INFO "cerf_ucb1400gpio_lcd_contrast_step: "
-+ "stepping down\n");
-+ //goin' down
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
-+ }
-+
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_CS);
-+
-+ // Assert the line up, down then up again
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
-+ udelay(1);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_INC, 0);
-+ udelay(1);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_INC);
-+
-+ // Deassert the chip select and the up modifier
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_CONT_DOWN);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_CONT_CS, 0);
-+}
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_irda_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Enabling IRDA.\n");
-+ /* Enable IRDA (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+}
-+
-+void cerf_ucb1400gpio_irda_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Disabling IRDA.\n");
-+ /* Disable IRDA (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_IRDA_ENABLE);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_IRDA_ENABLE, 0);
-+}
-+
-+/* -- -- */
-+
-+void cerf_ucb1400gpio_bt_enable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Enabling Bluetooth.\n");
-+ /* Enable BT (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+ ucb1x00_io_write( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+}
-+
-+void cerf_ucb1400gpio_bt_disable( void)
-+{
-+ struct ucb1x00 * ucb = ucb1x00_get();
-+ printk( KERN_INFO "Disabling Bluetooth.\n");
-+ /* Disable BT (active low) */
-+ ucb1x00_io_set_dir( ucb, 0, UCB1400_GPIO_BT_ENABLE);
-+ ucb1x00_io_write( ucb, UCB1400_GPIO_BT_ENABLE, 0);
-+}
-+
-+/* -- -- */
-+
-+/* -- Enable Bluetooth and IRDA automatically via pseudo module -- */
-+#if defined(CONFIG_BLUEZ) || defined(CONFIG_IRDA)
-+static int __init cerf_ucb1400gpio_module_init (void)
-+{
-+#ifdef CONFIG_BLUEZ
-+ cerf_ucb1400gpio_bt_enable();
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ cerf_ucb1400gpio_irda_enable();
-+#endif
-+ return 0;
-+}
-+
-+static void __exit cerf_ucb1400gpio_module_exit (void)
-+{
-+#ifdef CONFIG_BLUEZ
-+ cerf_ucb1400gpio_bt_disable();
-+#endif
-+
-+#ifdef CONFIG_IRDA
-+ cerf_ucb1400gpio_irda_disable();
-+#endif
-+}
-+
-+module_init(cerf_ucb1400gpio_module_init);
-+module_exit(cerf_ucb1400gpio_module_exit);
-+#endif
-+
---- /dev/null
-+++ linux-2.4.27/drivers/misc/mcp-pxa.c
-@@ -0,0 +1,57 @@
-+/*
-+ * linux/drivers/misc/mcp-pxa.c
-+ *
-+ * 2002-01-10 Jeff Sutherland <jeffs@accelent.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.
-+ *
-+ * NOTE: This is a quick hack to gain access to the aclink codec's
-+ * touch screen facility. Its audio is handled by a separate
-+ * (non-mcp) driver at the present time.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/ac97_codec.h>
-+
-+#include "mcp.h"
-+
-+
-+extern int pxa_ac97_get(struct ac97_codec **codec);
-+extern void pxa_ac97_put(void);
-+
-+
-+struct mcp *mcp_get(void)
-+{
-+ struct ac97_codec *codec;
-+ if (pxa_ac97_get(&codec) < 0)
-+ return NULL;
-+ return (struct mcp *)codec;
-+}
-+
-+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ struct ac97_codec *codec = (struct ac97_codec *)mcp;
-+ codec->codec_write(codec, reg, val);
-+}
-+
-+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
-+{
-+ struct ac97_codec *codec = (struct ac97_codec *)mcp;
-+ return codec->codec_read(codec, reg);
-+}
-+
-+void mcp_enable(struct mcp *mcp)
-+{
-+ /*
-+ * Should we do something here to make sure the aclink
-+ * codec is alive???
-+ * A: not for now --NP
-+ */
-+}
-+
-+void mcp_disable(struct mcp *mcp)
-+{
-+}
---- linux-2.4.27/drivers/misc/mcp.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/mcp.h
-@@ -10,16 +10,22 @@
- #ifndef MCP_H
- #define MCP_H
-
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/dma.h>
-+#endif
-+
- struct mcp {
- struct module *owner;
- spinlock_t lock;
- int use_count;
- unsigned int sclk_rate;
- unsigned int rw_timeout;
-+#ifdef CONFIG_ARCH_SA1100
- dma_device_t dma_audio_rd;
- dma_device_t dma_audio_wr;
- dma_device_t dma_telco_rd;
- dma_device_t dma_telco_wr;
-+#endif
- void (*set_telecom_divisor)(struct mcp *, unsigned int);
- void (*set_audio_divisor)(struct mcp *, unsigned int);
- void (*reg_write)(struct mcp *, unsigned int, unsigned int);
---- linux-2.4.27/drivers/misc/ucb1x00-core.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/ucb1x00-core.c
-@@ -23,12 +23,18 @@
- #include <linux/errno.h>
- #include <linux/interrupt.h>
- #include <linux/pm.h>
-+#include <linux/tqueue.h>
-+#include <linux/config.h>
-
--#include <asm/dma.h>
--#include <asm/hardware.h>
- #include <asm/irq.h>
- #include <asm/mach-types.h>
-+
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/arch/assabet.h>
- #include <asm/arch/shannon.h>
-+#endif
-+
-+#include <asm/hardware.h>
-
- #include "ucb1x00.h"
-
-@@ -155,6 +161,10 @@
- *
- * If called for a synchronised ADC conversion, it may sleep
- * with the ADC semaphore held.
-+ *
-+ * See ucb1x00.h for definition of the UCB_ADC_DAT macro. It
-+ * addresses a bug in the ucb1200/1300 which, of course, Philips
-+ * decided to finally fix in the ucb1400 ;-) -jws
- */
- unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
- {
-@@ -218,22 +228,75 @@
- * Since we need to read an internal register, we must re-enable
- * SIBCLK to talk to the chip. We leave the clock running until
- * we have finished processing all interrupts from the chip.
-+ *
-+ * A restriction with interrupts exists when using the ucb1400, as
-+ * the codec read/write routines may sleep while waiting for codec
-+ * access completion and uses semaphores for access control to the
-+ * AC97 bus. A complete codec read cycle could take anywhere from
-+ * 60 to 100uSec so we *definitely* don't want to spin inside the
-+ * interrupt handler waiting for codec access. So, we handle the
-+ * interrupt by scheduling a RT kernel thread to run in process
-+ * context instead of interrupt context.
- */
--static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+
-+static int ucb1x00_thread(void *_ucb)
- {
-- struct ucb1x00 *ucb = devid;
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ struct ucb1x00 *ucb = _ucb;
- struct ucb1x00_irq *irq;
- unsigned int isr, i;
-
-- ucb1x00_enable(ucb);
-- isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-- ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+ ucb->rtask = tsk;
-
-- for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-- if (isr & 1 && irq->fn)
-- irq->fn(i, irq->devid);
-- ucb1x00_disable(ucb);
-+ daemonize();
-+ reparent_to_init();
-+ tsk->tty = NULL;
-+ tsk->policy = SCHED_FIFO;
-+ tsk->rt_priority = 1;
-+ strcpy(tsk->comm, "kUCB1x00d");
-+
-+ /* only want to receive SIGKILL */
-+ spin_lock_irq(&tsk->sigmask_lock);
-+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-+ recalc_sigpending(tsk);
-+ spin_unlock_irq(&tsk->sigmask_lock);
-+
-+ add_wait_queue(&ucb->irq_wait, &wait);
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ complete(&ucb->complete);
-+
-+ for (;;) {
-+ if (signal_pending(tsk))
-+ break;
-+ enable_irq(ucb->irq);
-+ schedule();
-+
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ for (i = 0, irq = ucb->irq_handler;
-+ i < 16 && isr;
-+ i++, isr >>= 1, irq++)
-+ if (isr & 1 && irq->fn)
-+ irq->fn(i, irq->devid);
-+ ucb1x00_disable(ucb);
-+
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ }
-+
-+ remove_wait_queue(&ucb->irq_wait, &wait);
-+ ucb->rtask = NULL;
-+ complete_and_exit(&ucb->complete, 0);
-+}
-+
-+static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ struct ucb1x00 *ucb = devid;
-+ disable_irq(irqnr);
-+ wake_up(&ucb->irq_wait);
- }
-
- /**
-@@ -291,6 +354,11 @@
- spin_lock_irqsave(&ucb->lock, flags);
-
- ucb1x00_enable(ucb);
-+
-+ /* This prevents spurious interrupts on the UCB1400 */
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
- if (edges & UCB_RISING) {
- ucb->irq_ris_enbl |= 1 << idx;
- ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-@@ -456,6 +524,7 @@
- unsigned int irq_gpio_pin = 0;
- int irq, default_irq = NO_IRQ;
-
-+#ifdef CONFIG_ARCH_SA1100
- if (machine_is_adsbitsy())
- default_irq = IRQ_GPCIN4;
-
-@@ -514,12 +583,40 @@
- }
- #endif
-
-+#endif /* CONFIG_ARCH_SA1100 */
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if (machine_is_pxa_idp()) {
-+ default_irq = TOUCH_PANEL_IRQ;
-+ irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
-+ GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
-+ }
-+#endif
-+
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ if (machine_is_trizeps2()) {
-+ default_irq = TOUCH_PANEL_IRQ;
-+ irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
-+ GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
-+ }
-+#endif
-+
-+
-+#ifdef CONFIG_PXA_CERF_PDA
-+ if (machine_is_pxa_cerf()) {
-+ irq_gpio_pin = CERF_GPIO_UCB1400_IRQ;
-+ }
-+#endif
-+
- /*
- * Eventually, this will disappear.
- */
- if (irq_gpio_pin)
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE);
-+#else
- set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
--
-+#endif
- irq = ucb1x00_detect_irq(ucb);
- if (irq != NO_IRQ) {
- if (default_irq != NO_IRQ && irq != default_irq)
-@@ -541,21 +638,7 @@
-
- struct ucb1x00 *my_ucb;
-
--/**
-- * ucb1x00_get - get the UCB1x00 structure describing a chip
-- * @ucb: UCB1x00 structure describing chip
-- *
-- * Return the UCB1x00 structure describing a chip.
-- *
-- * FIXME: Currently very noddy indeed, which currently doesn't
-- * matter since we only support one chip.
-- */
--struct ucb1x00 *ucb1x00_get(void)
--{
-- return my_ucb;
--}
--
--static int __init ucb1x00_init(void)
-+static int ucb1x00_init_helper(void)
- {
- struct mcp *mcp;
- unsigned int id;
-@@ -568,23 +651,28 @@
- mcp_enable(mcp);
- id = mcp_reg_read(mcp, UCB_ID);
-
-- if (id != UCB_ID_1200 && id != UCB_ID_1300) {
-+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_1400) {
- printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
- goto out;
- }
-
-+ /* distinguish between UCB1400 revs 1B and 2A */
-+ if (id == UCB_ID_1400 && mcp_reg_read(mcp, 0x00) == 0x002a)
-+ id = UCB_ID_1400_BUGGY;
-+
- my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
- ret = -ENOMEM;
- if (!my_ucb)
- goto out;
-
-+#ifdef CONFIG_ARCH_SA1100
- if (machine_is_shannon()) {
- /* reset the codec */
- GPDR |= SHANNON_GPIO_CODEC_RESET;
- GPCR = SHANNON_GPIO_CODEC_RESET;
- GPSR = SHANNON_GPIO_CODEC_RESET;
--
- }
-+#endif
-
- memset(my_ucb, 0, sizeof(struct ucb1x00));
-
-@@ -599,13 +687,12 @@
- if (ret)
- goto out;
-
-+ init_waitqueue_head(&my_ucb->irq_wait);
- ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
- if (ret) {
- printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
- my_ucb->irq, ret);
-- kfree(my_ucb);
-- my_ucb = NULL;
-- goto out;
-+ goto irq_err;
- }
-
- #ifdef CONFIG_PM
-@@ -616,16 +703,55 @@
- my_ucb->pmdev->data = my_ucb;
- #endif
-
-+ init_completion(&my_ucb->complete);
-+ ret = kernel_thread(ucb1x00_thread, my_ucb, CLONE_FS | CLONE_FILES);
-+ if (ret >= 0) {
-+ wait_for_completion(&my_ucb->complete);
-+ ret = 0;
-+ goto out;
-+ }
-+
-+ free_irq(my_ucb->irq, my_ucb);
-+irq_err:
-+ kfree(my_ucb);
-+ my_ucb = NULL;
- out:
- mcp_disable(mcp);
- no_mcp:
- return ret;
- }
-
-+/**
-+ * ucb1x00_get - get the UCB1x00 structure describing a chip
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the UCB1x00 structure describing a chip.
-+ *
-+ * FIXME: Currently very noddy indeed, which currently doesn't
-+ * matter since we only support one chip.
-+ */
-+struct ucb1x00 *ucb1x00_get(void)
-+{
-+ if( !my_ucb) ucb1x00_init_helper();
-+
-+ return my_ucb;
-+}
-+
-+static int __init ucb1x00_init(void)
-+{
-+ /* check if driver is already initialized */
-+ if( my_ucb) return 0;
-+
-+ return ucb1x00_init_helper();
-+}
-+
- static void __exit ucb1x00_exit(void)
- {
-+ send_sig(SIGKILL, my_ucb->rtask, 1);
-+ wait_for_completion(&my_ucb->complete);
- free_irq(my_ucb->irq, my_ucb);
- kfree(my_ucb);
-+ my_ucb = 0;
- }
-
- module_init(ucb1x00_init);
---- linux-2.4.27/drivers/misc/ucb1x00-ts.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/ucb1x00-ts.c
-@@ -35,7 +35,11 @@
- /*
- * Define this if you want the UCB1x00 stuff to talk to the input layer
- */
-+#ifdef CONFIG_INPUT
-+#define USE_INPUT
-+#else
- #undef USE_INPUT
-+#endif
-
- #ifndef USE_INPUT
-
-@@ -73,7 +77,7 @@
- struct pm_dev *pmdev;
- #endif
-
-- wait_queue_head_t irq_wait;
-+ struct semaphore irq_wait;
- struct semaphore sem;
- struct completion init_exit;
- struct task_struct *rtask;
-@@ -259,6 +263,11 @@
- input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
- }
-
-+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
-+{
-+ input_report_abs(&ts->idev, ABS_PRESSURE, 0);
-+}
-+
- static int ucb1x00_ts_open(struct input_dev *idev)
- {
- struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-@@ -304,10 +313,15 @@
- */
- static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
- {
-- ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-- UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-- UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-- UCB_TS_CR_MODE_INT);
-+ if (ts->ucb->id == UCB_ID_1400_BUGGY)
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
-+ else
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
- }
-
- /*
-@@ -397,13 +411,13 @@
- /*
- * This is a RT kernel thread that handles the ADC accesses
- * (mainly so we can use semaphores in the UCB1200 core code
-- * to serialise accesses to the ADC).
-+ * to serialise accesses to the ADC). The UCB1400 access
-+ * functions are expected to be able to sleep as well.
- */
- static int ucb1x00_thread(void *_ts)
- {
- struct ucb1x00_ts *ts = _ts;
- struct task_struct *tsk = current;
-- DECLARE_WAITQUEUE(wait, tsk);
- int valid;
-
- ts->rtask = tsk;
-@@ -429,10 +443,8 @@
-
- valid = 0;
-
-- add_wait_queue(&ts->irq_wait, &wait);
- for (;;) {
- unsigned int x, y, p, val;
-- signed long timeout;
-
- ts->restart = 0;
-
-@@ -457,8 +469,6 @@
- val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
-
- if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
-- set_task_state(tsk, TASK_INTERRUPTIBLE);
--
- ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
- ucb1x00_disable(ts->ucb);
-
-@@ -471,7 +481,15 @@
- valid = 0;
- }
-
-- timeout = MAX_SCHEDULE_TIMEOUT;
-+ /*
-+ * Since ucb1x00_enable_irq() might sleep due
-+ * to the way the UCB1400 regs are accessed, we
-+ * can't use set_task_state() before that call,
-+ * and not changing state before enabling the
-+ * interrupt is racy. A semaphore solves all
-+ * those issues quite nicely.
-+ */
-+ down_interruptible(&ts->irq_wait);
- } else {
- ucb1x00_disable(ts->ucb);
-
-@@ -486,16 +504,13 @@
- }
-
- set_task_state(tsk, TASK_INTERRUPTIBLE);
-- timeout = HZ / 100;
-+ schedule_timeout(HZ / 100);
- }
-
-- schedule_timeout(timeout);
- if (signal_pending(tsk))
- break;
- }
-
-- remove_wait_queue(&ts->irq_wait, &wait);
--
- ts->rtask = NULL;
- ucb1x00_ts_evt_clear(ts);
- complete_and_exit(&ts->init_exit, 0);
-@@ -509,7 +524,7 @@
- {
- struct ucb1x00_ts *ts = id;
- ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-- wake_up(&ts->irq_wait);
-+ up(&ts->irq_wait);
- }
-
- static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
-@@ -525,7 +540,7 @@
- if (ts->rtask)
- panic("ucb1x00: rtask running?");
-
-- init_waitqueue_head(&ts->irq_wait);
-+ sema_init(&ts->irq_wait, 0);
- ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
- if (ret < 0)
- goto out;
-@@ -585,7 +600,7 @@
- * after sleep.
- */
- ts->restart = 1;
-- wake_up(&ts->irq_wait);
-+ up(&ts->irq_wait);
- }
- return 0;
- }
---- linux-2.4.27/drivers/misc/ucb1x00.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/misc/ucb1x00.h
-@@ -10,8 +10,47 @@
- #ifndef UCB1200_H
- #define UCB1200_H
-
-+#ifdef CONFIG_ARCH_PXA
-+
-+/* ucb1400 aclink register mappings: */
-+
-+#define UCB_IO_DATA 0x5a
-+#define UCB_IO_DIR 0x5c
-+#define UCB_IE_RIS 0x5e
-+#define UCB_IE_FAL 0x60
-+#define UCB_IE_STATUS 0x62
-+#define UCB_IE_CLEAR 0x62
-+#define UCB_TS_CR 0x64
-+#define UCB_ADC_CR 0x66
-+#define UCB_ADC_DATA 0x68
-+#define UCB_ID 0x7e /* 7c is mfr id, 7e part id (from aclink spec) */
-+
-+#define UCB_ADC_DAT(x) ((x) & 0x3ff)
-+
-+#else
-+
-+/* ucb1x00 SIB register mappings: */
-+
- #define UCB_IO_DATA 0x00
- #define UCB_IO_DIR 0x01
-+#define UCB_IE_RIS 0x02
-+#define UCB_IE_FAL 0x03
-+#define UCB_IE_STATUS 0x04
-+#define UCB_IE_CLEAR 0x04
-+#define UCB_TC_A 0x05
-+#define UCB_TC_B 0x06
-+#define UCB_AC_A 0x07
-+#define UCB_AC_B 0x08
-+#define UCB_TS_CR 0x09
-+#define UCB_ADC_CR 0x0a
-+#define UCB_ADC_DATA 0x0b
-+#define UCB_ID 0x0c
-+#define UCB_MODE 0x0d
-+
-+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-+
-+#endif
-+
-
- #define UCB_IO_0 (1 << 0)
- #define UCB_IO_1 (1 << 1)
-@@ -24,10 +63,6 @@
- #define UCB_IO_8 (1 << 8)
- #define UCB_IO_9 (1 << 9)
-
--#define UCB_IE_RIS 0x02
--#define UCB_IE_FAL 0x03
--#define UCB_IE_STATUS 0x04
--#define UCB_IE_CLEAR 0x04
- #define UCB_IE_ADC (1 << 11)
- #define UCB_IE_TSPX (1 << 12)
- #define UCB_IE_TSMX (1 << 13)
-@@ -36,11 +71,9 @@
-
- #define UCB_IRQ_TSPX 12
-
--#define UCB_TC_A 0x05
- #define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
- #define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
-
--#define UCB_TC_B 0x06
- #define UCB_TC_B_VOICE_ENA (1 << 3)
- #define UCB_TC_B_CLIP (1 << 4)
- #define UCB_TC_B_ATT (1 << 6)
-@@ -49,14 +82,11 @@
- #define UCB_TC_B_IN_ENA (1 << 14)
- #define UCB_TC_B_OUT_ENA (1 << 15)
-
--#define UCB_AC_A 0x07
--#define UCB_AC_B 0x08
- #define UCB_AC_B_LOOP (1 << 8)
- #define UCB_AC_B_MUTE (1 << 13)
- #define UCB_AC_B_IN_ENA (1 << 14)
- #define UCB_AC_B_OUT_ENA (1 << 15)
-
--#define UCB_TS_CR 0x09
- #define UCB_TS_CR_TSMX_POW (1 << 0)
- #define UCB_TS_CR_TSPX_POW (1 << 1)
- #define UCB_TS_CR_TSMY_POW (1 << 2)
-@@ -72,7 +102,6 @@
- #define UCB_TS_CR_TSPX_LOW (1 << 12)
- #define UCB_TS_CR_TSMX_LOW (1 << 13)
-
--#define UCB_ADC_CR 0x0a
- #define UCB_ADC_SYNC_ENA (1 << 0)
- #define UCB_ADC_VREFBYP_CON (1 << 1)
- #define UCB_ADC_INP_TSPX (0 << 2)
-@@ -87,15 +116,13 @@
- #define UCB_ADC_START (1 << 7)
- #define UCB_ADC_ENA (1 << 15)
-
--#define UCB_ADC_DATA 0x0b
- #define UCB_ADC_DAT_VAL (1 << 15)
--#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-
--#define UCB_ID 0x0c
- #define UCB_ID_1200 0x1004
- #define UCB_ID_1300 0x1005
-+#define UCB_ID_1400 0x4304
-+#define UCB_ID_1400_BUGGY 0x4303 /* fake ID */
-
--#define UCB_MODE 0x0d
- #define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
- #define UCB_MODE_AUD_OFF_CAN (1 << 13)
-
-@@ -115,6 +142,9 @@
- unsigned int irq;
- struct semaphore adc_sem;
- spinlock_t io_lock;
-+ wait_queue_head_t irq_wait;
-+ struct completion complete;
-+ struct task_struct *rtask;
- u16 id;
- u16 io_dir;
- u16 io_out;
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/Config.in
-@@ -0,0 +1,12 @@
-+mainmenu_option next_comment
-+comment 'MMC device drivers'
-+tristate 'Multi Media Card support' CONFIG_MMC
-+if [ "$CONFIG_MMC" = "y" -o "$CONFIG_MMC" = "m" ]; then
-+ dep_tristate 'PXA250 MMC driver' CONFIG_MMC_PXA $CONFIG_MMC
-+ dep_tristate 'MMC block driver' CONFIG_MMC_BLOCK $CONFIG_MMC
-+ if [ "$CONFIG_MMC_BLOCK" = "y" -o "$CONFIG_MMC_BLOCK" = "m" ]; then
-+ bool ' MMC partitioning support' CONFIG_MMC_PARTITIONS
-+ fi
-+fi
-+endmenu
-+
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/Makefile
-@@ -0,0 +1,14 @@
-+#
-+# Makefile for MMC drivers
-+#
-+
-+export-objs := mmc_core.o
-+
-+obj-$(CONFIG_MMC) += mmc_core.o # mmc_test.o
-+obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
-+obj-$(CONFIG_MMC_PXA) += mmc_pxa.o
-+# EXTRA_CFLAGS += -DCONFIG_MMC_DEBUG -DCONFIG_MMC_DEBUG_VERBOSE=2
-+
-+O_TARGET := mmcdrivers.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/error.h
-@@ -0,0 +1,70 @@
-+/*
-+ * linux/include/linux/mmc/error.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: error.h,v 0.2 2002/07/11 16:27:01 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_ERROR_H__
-+#define __MMC_ERROR_H__
-+
-+/* MMC protocol card error codes */
-+#define MMC_CARD_STATUS_OUT_OF_RANGE (1<<31)
-+#define MMC_CARD_STATUS_ADDRESS_ERROR (1<<30)
-+#define MMC_CARD_STATUS_BLOCK_LEN_ERROR (1<<29)
-+#define MMC_CARD_STATUS_ERASE_SEQ_ERROR (1<<28)
-+#define MMC_CARD_STATUS_ERASE_PARAM (1<<27)
-+#define MMC_CARD_STATUS_WP_VIOLATION (1<<26)
-+#define MMC_CARD_STATUS_CARD_IS_LOCKED (1<<25)
-+#define MMC_CARD_STATUS_LOCK_UNLOCK_FAILED (1<<24)
-+#define MMC_CARD_STATUS_COM_CRC_ERROR (1<<23)
-+#define MMC_CARD_STATUS_ILLEGAL_COMMAND (1<<22)
-+#define MMC_CARD_STATUS_CARD_ECC_FAILED (1<<21)
-+#define MMC_CARD_STATUS_CC_ERROR (1<<20)
-+#define MMC_CARD_STATUS_ERROR (1<<19)
-+#define MMC_CARD_STATUS_UNDERRUN (1<<18)
-+#define MMC_CARD_STATUS_OVERRUN (1<<17)
-+#define MMC_CARD_STATUS_CID_CSD_OVERWRITE (1<<16)
-+#define MMC_CARD_STATUS_ERASE_RESET (1<<13)
-+
-+#define MMC_ERROR( fmt, args... ) printk( KERN_ERR "%s(): " fmt, __FUNCTION__, ##args )
-+
-+/*
-+ * Error codes returned by MMC subsystem functions and
-+ * error reporting function prototypes
-+ */
-+enum _mmc_error {
-+/* controller errors */
-+ MMC_ERROR_GENERIC = -10000,
-+ MMC_ERROR_CRC_WRITE_ERROR = -10001,
-+ MMC_ERROR_CRC_READ_ERROR = -10002,
-+ MMC_ERROR_RES_CRC_ERROR = -10003,
-+ MMC_ERROR_READ_TIME_OUT = -10004,
-+ MMC_ERROR_TIME_OUT_RESPONSE = -10005,
-+ MMC_ERROR_INVAL = -10006,
-+/* protocol errors reported in card status (R1 response) */
-+ MMC_ERROR_OUT_OF_RANGE = -10007,
-+ MMC_ERROR_ADDRESS_ERROR = -10008,
-+ MMC_ERROR_BLOCK_LEN_ERROR = -10009,
-+ MMC_ERROR_ERASE_SEQ_ERROR = -10010,
-+ MMC_ERROR_ERASE_PARAM = -10011,
-+ MMC_ERROR_WP_VIOLATION = -10012,
-+ MMC_ERROR_CARD_IS_LOCKED = -10013,
-+ MMC_ERROR_LOCK_UNLOCK_FAILED = -10014,
-+ MMC_ERROR_COM_CRC_ERROR = -10015,
-+ MMC_ERROR_ILLEGAL_COMMAND = -10016,
-+ MMC_ERROR_CARD_ECC_FAILED = -10017,
-+ MMC_ERROR_CC_ERROR = -10018,
-+ MMC_ERROR_ERROR = -10019,
-+ MMC_ERROR_UNDERRUN = -10020,
-+ MMC_ERROR_OVERRUN = -10021,
-+ MMC_ERROR_CID_CSD_OVERWRITE = -10022,
-+ /* FIXME: incomplete */
-+ MMC_ERROR_ERASE_RESET = -10025
-+};
-+#endif /* __MMC_ERROR_H__ */
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc.h
-@@ -0,0 +1,463 @@
-+/*
-+ * linux/drivers/mmc/mmc.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc.h,v 0.3.1.8 2002/09/18 12:58:00 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_P_H__
-+#define __MMC_P_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+
-+#include <linux/spinlock.h>
-+
-+#ifdef CONFIG_PROC_FS
-+#include <linux/proc_fs.h>
-+#endif
-+
-+#include <asm/semaphore.h>
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+
-+#include "types.h"
-+
-+#include "error.h"
-+
-+#define MMC_CONTROLLERS_MAX (4)
-+#define MMC_CARDS_MAX (16)
-+
-+/* test device */
-+#define MMC_TEST_MAJOR (240)
-+#define MMC_TEST_TRANSFER_MODE_DEFAULT MMC_TRANSFER_MODE_BLOCK_SINGLE
-+
-+/* block device */
-+#define MMC_BLOCK_MAJOR (241) /* FIXME: MMC_MAJOR */
-+#define MMC_BLOCK_DEVICES_MAX (1<<MINORBITS) /* FIXME */
-+#define MMC_BLOCK_SECT_SIZE (512) /* FIXME */
-+#define MMC_BLOCK_PARTNBITS (3)
-+
-+/* Device minor number encoding:
-+ * [7:6] - host
-+ * [5:3] - card slot number
-+ * [2:0] - partition number
-+ */
-+#define MMC_MINOR_HOST_SHIFT (6)
-+#define MMC_MINOR_CARD_MASK (0x07)
-+
-+/*
-+ * MMC controller abstraction
-+ */
-+enum _mmc_controller_state {
-+ MMC_CONTROLLER_ABSENT = 0,
-+ MMC_CONTROLLER_FOUND,
-+ MMC_CONTROLLER_INITIALIZED,
-+ MMC_CONTROLLER_UNPLUGGED
-+};
-+
-+enum _mmc_dir {
-+ MMC_READ = 1,
-+ MMC_WRITE
-+};
-+
-+enum _mmc_buftype {
-+ MMC_USER = 1,
-+ MMC_KERNEL
-+};
-+
-+struct _mmc_data_transfer_req_rec {
-+ mmc_dir_t cmd; /* read or write operation requested */
-+ mmc_transfer_mode_t mode; /* requested data transfer mode */
-+ mmc_buftype_t type; /* whether supplied buffer resides in user or kernel space */
-+ char *buf; /* poiner to the caller's buffer */
-+ ssize_t cnt; /* number of bytes to transfer */
-+ loff_t addr; /* card address */
-+ ssize_t blksz; /* block size as for CSD[READ_BL_LEN] or CSD[WRITE_BL_LEN] */
-+ ssize_t nob; /* number of blocks to transfer */
-+};
-+
-+struct _mmc_controller_tmpl_rec {
-+ struct module *owner; /* driver module */
-+ char name[16];
-+
-+ const ssize_t block_size_max; /* max acceptable block size */
-+ const ssize_t nob_max; /* max blocks per one data transfer */
-+
-+ int (*probe)( mmc_controller_t ); /* hardware probe */
-+ int (*init)( mmc_controller_t ); /* initialize, e.g. request irq, DMA and allocate buffers */
-+ void (*remove)( mmc_controller_t ); /* free resources */
-+#if 0 /* CONFIG_HOTPLUG */
-+ void (*attach)( void ); /|* controller hotplug callbacks *|/
-+ void (*detach)( void );
-+#endif
-+#ifdef CONFIG_PM
-+ int (*suspend)( mmc_controller_t ); /* power management callbacks */
-+ void (*resume)( mmc_controller_t );
-+#endif
-+
-+/* MMC protocol macros, v3.4, p.120 */
-+ int (*init_card_stack)( mmc_controller_t );
-+ int (*update_acq)( mmc_controller_t ); /* update card stack management data */
-+ int (*single_card_acq)( mmc_controller_t );
-+ int (*check_card_stack)( mmc_controller_t );
-+ int (*setup_card)( mmc_controller_t, mmc_card_t );
-+ int (*stream_read)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*read_block)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*read_mblock)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*stream_write)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*write_block)( mmc_controller_t, mmc_data_transfer_req_t );
-+ int (*write_mblock)( mmc_controller_t, mmc_data_transfer_req_t );
-+/* TODO:
-+ int (*sg_io)( mmc_controller_t, sg_list_t );
-+*/
-+/* TODO:
-+ * 1) erase group macros
-+ * int (*erase_group)( mmc_controller_t, mmc_erase_group_info_t );
-+ * 2) write protection macros;
-+ * int (*set_write_prot)( mmc_controller_t, mmc_write_protection_info_t )
-+ * 3) lock/password management macros;
-+ */
-+};
-+
-+#ifndef MMC_CTRLR_BLKSZ_DEFAULT
-+#define MMC_CTRLR_BLKSZ_DEFAULT (512)
-+#endif
-+
-+#ifndef MMC_CTRLR_NOB_DEFAULT
-+#define MMC_CTRLR_NOB_DEFAULT (1)
-+#endif
-+
-+struct _mmc_card_rec {
-+/* public card interface */
-+ struct _mmc_card_info_rec info; /* see <linux/mmc/mmc.h> */
-+
-+/* private kernel specific data */
-+ mmc_state_t state; /* card's state as per last operation */
-+ mmc_card_t next; /* link to the stack */
-+ mmc_controller_t ctrlr; /* back reference to the controller */
-+ int usage; /* reference count */
-+ int slot; /* card's number for device reference */
-+/* TODO: async I/O queue */
-+#ifdef CONFIG_PROC_FS
-+ proc_dir_entry_t proc;
-+ char proc_name[16];
-+#endif
-+ unsigned long card_data[0] /* card specific data */
-+ __attribute__((aligned (sizeof(unsigned long))));
-+};
-+
-+struct _mmc_card_stack_rec {
-+ mmc_card_t first; /* first card on the stack */
-+ mmc_card_t last; /* last card on the stack */
-+ mmc_card_t selected; /* currently selected card */
-+ int ncards;
-+};
-+
-+struct _mmc_controller_rec {
-+ mmc_controller_state_t state; /* found, initialized, unplugged... */
-+ int usage; /* reference count */
-+ int slot; /* host's number for device reference */
-+ semaphore_t io_sem; /* I/O serialization */
-+ rwsemaphore_t update_sem; /* card stack check/update serialization */
-+
-+ mmc_controller_tmpl_t tmpl; /* methods provided by the driver */
-+ mmc_card_stack_rec_t stack; /* card stack management data */
-+
-+ u32 rca_next; /* next RCA to assign */
-+ int slot_next; /* next slot number to assign */
-+#ifdef CONFIG_PROC_FS
-+ char proc_name[16];
-+ proc_dir_entry_t proc;
-+#endif
-+ unsigned long host_data[0] /* driver can request some extra space */
-+ __attribute__((aligned (sizeof(unsigned long))));
-+};
-+
-+/*
-+ * MMC core interface
-+ */
-+enum _mmc_reg_type {
-+ MMC_REG_TYPE_USER = 1,
-+ MMC_REG_TYPE_HOST,
-+ MMC_REG_TYPE_CARD
-+};
-+
-+struct _mmc_notifier_rec {
-+ struct _mmc_notifier_rec *next;
-+ mmc_notifier_fn_t add;
-+ mmc_notifier_fn_t remove;
-+};
-+
-+enum _mmc_response {
-+ MMC_NORESPONSE = 1,
-+ MMC_R1,
-+ MMC_R2,
-+ MMC_R3,
-+ MMC_R4,
-+ MMC_R5
-+};
-+
-+#undef EXTERN
-+#ifndef __MMC_CORE_IMPLEMENTATION__
-+#define EXTERN extern
-+#else
-+#define EXTERN /* empty */
-+#endif
-+
-+EXTERN void *mmc_register( mmc_reg_type_t, void *, size_t );
-+EXTERN void mmc_unregister( mmc_reg_type_t, void * );
-+EXTERN int mmc_update_card_stack( int );
-+
-+EXTERN mmc_card_t mmc_get_card( int, int );/* get reference to the card */
-+EXTERN void mmc_put_card( mmc_card_t ); /* release card reference */
-+
-+EXTERN int mmc_notify_add( mmc_card_t ); /* user notification */
-+EXTERN int mmc_notify_remove( mmc_card_t );
-+
-+EXTERN ssize_t mmc_read( mmc_card_t, mmc_transfer_mode_t, char *, size_t, loff_t * ); /* generic read */
-+EXTERN ssize_t mmc_write( mmc_card_t, mmc_transfer_mode_t, const char *, size_t, loff_t * ); /* generic write */
-+EXTERN int mmc_ioctl( mmc_card_t, unsigned int, unsigned long ); /* generic ioctl */
-+/*
-+ * TODO: [?m.b. ioctl()] to erase, lock and write protect
-+ * 1) mmc_erase
-+ * 2) mmc_write_prot
-+ * 3) mmc_lock
-+ */
-+#undef EXTERN
-+
-+static inline mmc_card_t __mmc_card_alloc( size_t extra )
-+{
-+ mmc_card_t ret = kmalloc( sizeof( mmc_card_rec_t ) + extra, GFP_KERNEL );
-+
-+ if ( ret ) {
-+ memset( ret, 0, sizeof( mmc_card_rec_t ) + extra );
-+ }
-+
-+ return ret;
-+}
-+
-+static inline void __mmc_card_free( mmc_card_t card )
-+{
-+ if ( card ) {
-+ kfree( card );
-+ }
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_init( mmc_card_stack_t stack )
-+{
-+ mmc_card_stack_t ret = NULL;
-+ if ( stack ) {
-+ memset( stack, 0, sizeof( mmc_card_stack_rec_t ) );
-+ ret = stack;
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_add( mmc_card_stack_t stack, mmc_card_t card )
-+{
-+ mmc_card_stack_t ret = NULL;
-+
-+ if ( stack && card ) {
-+ card->next = NULL;
-+
-+ if ( stack->first ) {
-+ stack->last->next = card;
-+ stack->last = card;
-+ } else
-+ stack->first = stack->last = card;
-+
-+ ++stack->ncards;
-+ ret = stack;
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_card_stack_t __mmc_card_stack_remove( mmc_card_stack_t stack, mmc_card_t card )
-+{
-+ mmc_card_stack_t ret = NULL;
-+ register mmc_card_t prev;
-+ int found = FALSE;
-+
-+ if ( !stack || !card )
-+ goto error;
-+
-+ if ( stack->ncards > 0 ) {
-+ if ( stack->first == card ) {
-+ stack->first = stack->first->next;
-+ if ( stack->last == card )
-+ stack->last = stack->last->next;
-+ found = TRUE;
-+ } else {
-+ for ( prev = stack->first; prev; prev = prev->next )
-+ if ( prev->next == card ) {
-+ found = TRUE;
-+ break;
-+ }
-+ if ( found ) {
-+ if ( prev->next == stack->last )
-+ stack->last = prev->next;
-+ prev->next = prev->next->next;
-+ }
-+ }
-+ if ( found ) {
-+ --stack->ncards;
-+ ret = stack;
-+ }
-+ }
-+error:
-+ return ret;
-+}
-+
-+static inline void __mmc_card_stack_free( mmc_card_stack_t stack )
-+{
-+ mmc_card_t card, next;
-+
-+ if ( stack && (stack->ncards > 0) ) {
-+ card = stack->first;
-+ while ( card ) {
-+ next = card->next;
-+ kfree( card );
-+ card = next;
-+ }
-+ __mmc_card_stack_init( stack );
-+ }
-+}
-+
-+static inline int __mmc_card_stack_foreach( mmc_card_stack_t stack, mmc_notifier_fn_t fn, int unplugged_also )
-+{
-+ int ret = 0;
-+ register mmc_card_t card = NULL;
-+
-+ if ( stack && fn ) {
-+ for ( card = stack->first; card; card = card->next )
-+ if ( (card->state != MMC_CARD_STATE_UNPLUGGED)
-+ || unplugged_also )
-+ if ( fn( card ) ) {
-+ ret = -card->slot;
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * Debugging macros
-+ */
-+#ifdef CONFIG_MMC_DEBUG
-+
-+#define MMC_DEBUG_LEVEL0 (0) /* major */
-+#define MMC_DEBUG_LEVEL1 (1)
-+#define MMC_DEBUG_LEVEL2 (2) /* device */
-+#define MMC_DEBUG_LEVEL3 (3) /* protocol */
-+#define MMC_DEBUG_LEVEL4 (4) /* everything */
-+
-+#define MMC_DEBUG(n, args...) \
-+if (n <= CONFIG_MMC_DEBUG_VERBOSE) { \
-+ printk(KERN_INFO __FUNCTION__ "(): " args); \
-+}
-+#define __ENTER0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry\n" );
-+#define __LEAVE0( ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit\n" );
-+#define __ENTER( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "entry: " format "\n", args );
-+#define __LEAVE( format, args... ) MMC_DEBUG( MMC_DEBUG_LEVEL2, "exit: " format "\n", args );
-+
-+#define MMC_DUMP_CSD( card ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"CSD register:\n" \
-+" csd_structure=%u\n" \
-+" spec_vers=%u\n" \
-+" taac=%x\n" \
-+" nsac=%x\n" \
-+" tran_speed=%x\n" \
-+" ccc=%x\n" \
-+" read_bl_len=%u\n" \
-+" read_bl_partial=%u\n" \
-+" write_blk_misalign=%u\n" \
-+" read_blk_misalign=%u\n" \
-+" dsr_imp=%u\n" \
-+" c_size=%u\n" \
-+" vdd_r_curr_min=%u\n" \
-+" vdd_r_curr_max=%u\n" \
-+" vdd_w_curr_min=%u\n" \
-+" vdd_w_curr_max=%u\n" \
-+" c_size_mult=%u\n" \
-+" erase_grp_size=%u\n" \
-+" erase_grp_mult=%u\n" \
-+" wp_grp_size=%u\n" \
-+" wp_grp_enable=%u\n" \
-+" default_ecc=%u\n" \
-+" r2w_factor=%u\n" \
-+" write_bl_len=%u\n" \
-+" write_bl_partial=%u\n" \
-+" content_prot_app=%u\n" \
-+" file_format_grp=%u\n" \
-+" copy=%u\n" \
-+" perm_write_protect=%d\n" \
-+" tmp_write_protect=%d\n" \
-+" file_format=%d\n" \
-+" ecc=%d\n", \
-+card->info.csd.csd_structure, \
-+card->info.csd.spec_vers, \
-+card->info.csd.taac, \
-+card->info.csd.nsac, \
-+card->info.csd.tran_speed, \
-+card->info.csd.ccc, \
-+card->info.csd.read_bl_len, \
-+card->info.csd.read_bl_partial, \
-+card->info.csd.write_blk_misalign, \
-+card->info.csd.read_blk_misalign, \
-+card->info.csd.dsr_imp, \
-+card->info.csd.c_size, \
-+card->info.csd.vdd_r_curr_min, \
-+card->info.csd.vdd_r_curr_max, \
-+card->info.csd.vdd_w_curr_min, \
-+card->info.csd.vdd_w_curr_max, \
-+card->info.csd.c_size_mult, \
-+card->info.csd.erase_grp_size, \
-+card->info.csd.erase_grp_mult, \
-+card->info.csd.wp_grp_size, \
-+card->info.csd.wp_grp_enable, \
-+card->info.csd.default_ecc, \
-+card->info.csd.r2w_factor, \
-+card->info.csd.write_bl_len, \
-+card->info.csd.write_bl_partial, \
-+card->info.csd.content_prot_app, \
-+card->info.csd.file_format_grp, \
-+card->info.csd.copy, \
-+card->info.csd.perm_write_protect, \
-+card->info.csd.tmp_write_protect, \
-+card->info.csd.file_format, \
-+card->info.csd.ecc );
-+
-+#else /* CONFIG_MMC_DEBUG */
-+#define MMC_DEBUG(n, args...) /* empty */
-+#define __ENTER0( ) /* empty */
-+#define __LEAVE0( ) /* empty */
-+#define __ENTER( args... ) /* empty */
-+#define __LEAVE( args... ) /* empty */
-+#define MMC_DUMP_CSD( card ) /* empty */
-+#endif /* CONFIG_MMC_DEBUG */
-+
-+/*
-+ * Miscellaneous defines
-+ */
-+#ifndef MMC_DUMP_R1
-+#define MMC_DUMP_R1( ctrlr ) /* empty */
-+#endif
-+#ifndef MMC_DUMP_R2
-+#define MMC_DUMP_R2( ctrlr ) /* empty */
-+#endif
-+#ifndef MMC_DUMP_R3
-+#define MMC_DUMP_R3( ctrlr ) /* empty */
-+#endif
-+
-+#endif /* __KERNEL__ */
-+
-+#endif /* __MMC_P_H__ */
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc_block.c
-@@ -0,0 +1,989 @@
-+/*
-+ * linux/drivers/mmc/mmc_block.c
-+ * driver for the block device on the MMC card
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_block.c,v 0.3.1.16 2002/09/27 17:36:09 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/devfs_fs_kernel.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/hdreg.h>
-+#include <linux/blkpg.h>
-+#include <asm/uaccess.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+#include "error.h"
-+
-+#define MAJOR_NR MMC_BLOCK_MAJOR
-+#define MAJOR_NAME "mmc"
-+#define DEVICE_NAME "mmc_block"
-+#define DEVICE_REQUEST mmc_block_request
-+#define DEVICE_NR(device) (device)
-+#define DEVICE_ON(device)
-+#define DEVICE_OFF(device)
-+#define DEVICE_NO_RANDOM
-+#include <linux/blk.h>
-+/* for old kernels... */
-+#ifndef QUEUE_EMPTY
-+#define QUEUE_EMPTY (!CURRENT)
-+#endif
-+#if LINUX_VERSION_CODE < 0x20300
-+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
-+#else
-+#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
-+#endif
-+
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
-+#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
-+#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
-+#else
-+#define BLK_INC_USE_COUNT do {} while(0)
-+#define BLK_DEC_USE_COUNT do {} while(0)
-+#endif
-+
-+#define MMC_BLOCK_RAW_DEVICE( device ) ((device>>MMC_BLOCK_PARTNBITS)<<MMC_BLOCK_PARTNBITS)
-+#define MMC_BLOCK_MKDEV( host, slot ) \
-+ MKDEV( MMC_BLOCK_MAJOR, \
-+ (host<<MMC_MINOR_HOST_SHIFT) \
-+ | (slot<<MMC_BLOCK_PARTNBITS) )
-+
-+typedef struct _mmc_block_device mmc_block_device_rec_t;
-+typedef struct _mmc_block_device *mmc_block_device_t;
-+
-+struct _mmc_block_device {
-+ mmc_card_t card;
-+ int host;
-+ int slot;
-+ kdev_t rdev;
-+ int usage;
-+ semaphore_t sem;
-+};
-+
-+static int mmc_block_blk_sizes[1<<MINORBITS];
-+static int mmc_block_blk_blksizes[1<<MINORBITS];
-+static int mmc_block_hardsect_sizes[1<<MINORBITS];
-+static struct hd_struct mmc_block_partitions[1<<MINORBITS];
-+
-+/* Accessed under device table lock */
-+static gendisk_rec_t mmc_block_gendisk = {
-+ major: MMC_BLOCK_MAJOR,
-+ major_name: MAJOR_NAME,
-+ minor_shift: MMC_BLOCK_PARTNBITS,
-+ max_p: (1<<MMC_BLOCK_PARTNBITS),
-+ sizes: mmc_block_blk_sizes,
-+ part: mmc_block_partitions
-+};
-+
-+static mmc_block_device_rec_t mmc_block_device[1<<MINORBITS];
-+static rwsemaphore_t mmc_block_device_sem;
-+
-+static inline void __mmc_block_rdlock_devices( void )
-+{
-+ down_read( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_rdunlock_devices( void )
-+{
-+ up_read( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_wrlock_devices( void )
-+{
-+ down_write( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_wrunlock_devices( void )
-+{
-+ up_write( &mmc_block_device_sem );
-+}
-+
-+static inline void __mmc_block_lock_device( kdev_t rdev )
-+{
-+ __mmc_block_rdlock_devices();
-+ down( &mmc_block_device[MINOR( rdev )].sem );
-+}
-+
-+static inline void __mmc_block_unlock_device( kdev_t rdev )
-+{
-+ up( &mmc_block_device[MINOR( rdev )].sem );
-+ __mmc_block_rdunlock_devices();
-+}
-+
-+static inline void __mmc_block_device_init( int minor )
-+{
-+ mmc_block_device_t dev = &mmc_block_device[minor];
-+
-+ dev->usage = 0;
-+ dev->card = NULL;
-+ dev->host = minor >> MMC_MINOR_HOST_SHIFT;
-+ dev->slot = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
-+ dev->rdev = MKDEV( MMC_BLOCK_MAJOR, minor );
-+}
-+
-+static inline int __mmc_block_validate_device( kdev_t rdev )
-+{
-+ int ret = -1;
-+ int minor = MINOR( rdev );
-+
-+ if ( mmc_block_device[minor].card
-+ && (mmc_block_gendisk.part[minor].nr_sects > 0) )
-+ ret = 0;
-+
-+ return ret;
-+}
-+
-+static inline int __mmc_block_invalidate_card( mmc_card_t card, int invalidate )
-+{
-+ int ret = 0;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER( "card = 0x%p", card );
-+
-+ if ( card && card->ctrlr ) {
-+ register int i;
-+
-+ start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
-+ minor = MINOR( start );
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ if ( invalidate )
-+ invalidate_device( start + i, 0 );
-+
-+ __mmc_block_device_init( minor + i );
-+
-+ mmc_block_gendisk.part[minor + i].nr_sects = 0;
-+ mmc_block_gendisk.part[minor + i].start_sect = 0;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ }
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline int mmc_block_invalidate_card( int host, int slot, int invalidate )
-+{
-+ int ret = 0;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER( "host=%d slot=%d", host, slot );
-+
-+ if ( (host >= 0) && (slot >= 0) ) {
-+ register int i;
-+ mmc_card_t card = NULL;
-+
-+ start = MMC_BLOCK_MKDEV( host, slot );
-+ minor = MINOR( start );
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ if ( !card )
-+ card = mmc_block_device[minor + i].card;
-+
-+ if ( invalidate )
-+ invalidate_device( start + i, 0 );
-+
-+ __mmc_block_device_init( minor + i );
-+
-+ mmc_block_gendisk.part[minor + i].nr_sects = 0;
-+ mmc_block_gendisk.part[minor + i].start_sect = 0;
-+ }
-+ if ( card )
-+ mmc_put_card( card );
-+ __mmc_block_wrunlock_devices();
-+ }
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+/* Get device reference locked for writing */
-+static inline mmc_block_device_t __mmc_block_get_device( kdev_t rdev )
-+{
-+ mmc_block_device_t ret = NULL;
-+ u8 minor = MINOR( rdev );
-+ int host_no, card_no;
-+
-+ __ENTER( "rdev=%x:%x", MAJOR( rdev ), MINOR( rdev ) );
-+
-+ host_no = minor >> MMC_MINOR_HOST_SHIFT;
-+ if ( host_no >= MMC_CONTROLLERS_MAX )
-+ goto error;
-+
-+ card_no = (minor & MMC_MINOR_CARD_MASK)>>MMC_BLOCK_PARTNBITS;
-+ if ( card_no >= MMC_CARDS_MAX )
-+ goto error;
-+
-+ __mmc_block_lock_device( rdev );
-+ if ( __mmc_block_validate_device( rdev ) ) {
-+ __mmc_block_unlock_device( rdev );
-+ goto error;
-+ }
-+
-+ ret = &mmc_block_device[minor];
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
-+ MAJOR( ret->rdev ), MINOR( ret->rdev ),
-+ ret->card, ret->usage );
-+error:
-+ __LEAVE( "ret=0x%p", ret );
-+ return ret;
-+}
-+
-+/* Unlocks the device */
-+static inline void __mmc_block_put_device( mmc_block_device_t dev )
-+{
-+ __ENTER0();
-+
-+ if ( dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "(%x:%x) card=%p, dusage=%d\n",
-+ MAJOR( dev->rdev ), MINOR( dev->rdev ),
-+ dev->card, dev->usage );
-+ __mmc_block_unlock_device( dev->rdev );
-+ }
-+
-+ __LEAVE0();
-+}
-+
-+/* Atomically increases use count of the valid device */
-+static inline mmc_block_device_t mmc_block_get_device( kdev_t rdev )
-+{
-+ mmc_block_device_t ret = NULL;
-+
-+ __ENTER0();
-+
-+ ret = __mmc_block_get_device( rdev );
-+ if ( !ret )
-+ goto error;
-+
-+ ret->usage++;
-+ __mmc_block_put_device( ret );
-+error:
-+ __LEAVE( "ret=0x%p dusage=%d card=0x%p cusage=%d",
-+ ret, ret ? ret->usage : -1,
-+ ret ? ret->card : NULL,
-+ ret ? (ret->card ? ret->card->usage : -1) : -1 );
-+ return ret;
-+}
-+
-+/* Check is there references to the card */
-+static inline int __mmc_block_check_card( kdev_t rdev )
-+{
-+ int ret = TRUE;
-+ int start = MINOR( MMC_BLOCK_RAW_DEVICE( rdev ) );
-+ register int i;
-+
-+ for ( i = 0; i < mmc_block_gendisk.max_p; i++ )
-+ if ( mmc_block_device[start + i].usage > 0 ) {
-+ ret = FALSE;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+/* Atomically decreases device use count */
-+static inline void mmc_block_put_device( mmc_block_device_t dev )
-+{
-+ __ENTER0();
-+
-+ if ( dev ) {
-+ int invalidate = FALSE;
-+
-+ __mmc_block_get_device( dev->rdev );
-+ if ( dev->usage > 0 )
-+ --dev->usage;
-+
-+ if ( dev->usage ) {
-+ __mmc_block_put_device( dev );
-+ goto out;
-+
-+ } else {
-+ int host, slot;
-+ mmc_card_t card = NULL;
-+
-+ invalidate = __mmc_block_check_card( dev->rdev );
-+ if ( invalidate ) {
-+ host = dev->card->ctrlr->slot;
-+ slot = dev->card->slot;
-+
-+ if ( dev->card ) {
-+ card = dev->card;
-+ mmc_put_card( dev->card );
-+ dev->card = NULL;
-+ }
-+ }
-+ __mmc_block_put_device( dev );
-+
-+ if ( invalidate )
-+ __mmc_block_invalidate_card( card, TRUE );
-+ }
-+
-+ }
-+out:
-+ __LEAVE0();
-+}
-+
-+static int mmc_block_open( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_block_device_t dev = NULL;
-+
-+ __ENTER0();
-+
-+ if ( !inode || !file )
-+ goto error;
-+
-+ BLK_INC_USE_COUNT;
-+
-+ check_disk_change( inode->i_rdev );
-+
-+ dev = mmc_block_get_device( inode->i_rdev );
-+ if ( !dev )
-+ goto error;
-+
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+ if ( !dev )
-+ goto error;
-+
-+ if ( file->f_mode & FMODE_WRITE ) { /* FIXME */
-+ if ( dev->usage > 1 ) {
-+ ret = -EBUSY;
-+ __mmc_block_put_device( dev );
-+ mmc_block_put_device( dev );
-+ goto error;
-+ }
-+ }
-+
-+ __mmc_block_put_device( dev );
-+
-+ if ( file )
-+ file->private_data = dev;
-+
-+ ret = 0;
-+ goto out;
-+error:
-+ BLK_DEC_USE_COUNT;
-+out:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static int mmc_block_release( struct inode *inode, struct file *file )
-+{
-+ int ret = -EINVAL;
-+ mmc_block_device_t dev = NULL;
-+
-+ __ENTER( "inode=0x%p file=0x%p rdev=(%x:%x)", inode, file,
-+ inode ? MAJOR( inode->i_rdev ) : 0xff,
-+ inode ? MINOR( inode->i_rdev ) : 0xff );
-+
-+ if ( !file && !inode )
-+ goto error;
-+
-+ if ( file )
-+ dev = file->private_data;
-+ else
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
-+ goto error;
-+ }
-+
-+ if ( file ) {
-+ mmc_block_put_device( dev );
-+ file->private_data = NULL;
-+
-+ } else {
-+ int invalidate = FALSE;
-+
-+ if ( dev->usage > 0 )
-+ --dev->usage;
-+
-+ if ( dev->usage ) {
-+ __mmc_block_put_device( dev );
-+ goto out;
-+
-+ } else {
-+ int host, slot;
-+ mmc_card_t card = NULL;
-+
-+ invalidate = __mmc_block_check_card( dev->rdev );
-+ if ( invalidate ) {
-+ host = dev->card->ctrlr->slot;
-+ slot = dev->card->slot;
-+
-+ if ( dev->card ) {
-+ card = dev->card;
-+ mmc_put_card( dev->card );
-+ dev->card = NULL;
-+ }
-+ }
-+ __mmc_block_put_device( dev );
-+
-+ if ( invalidate )
-+ __mmc_block_invalidate_card( card, TRUE );
-+
-+ }
-+ }
-+
-+out:
-+ BLK_DEC_USE_COUNT;
-+ ret = 0;
-+error:
-+ __LEAVE0();
-+ return ret;
-+}
-+
-+static int mmc_block_check_disk_change( kdev_t rdev )
-+{
-+ int ret = 0;
-+#if 0
-+ mmc_block_device_t dev = &mmc_block_device[MINOR( rdev )];
-+
-+ __mmc_block_lock_device( rdev );
-+ if ( !dev->card )
-+ ret = 1;
-+ __mmc_block_unlock_device( rdev );
-+#else
-+ ret = 1;
-+#endif
-+ return ret;
-+}
-+
-+static int mmc_block_revalidate( kdev_t rdev )
-+{
-+ int ret = 1;
-+ mmc_card_t card;
-+ mmc_block_device_t dev;
-+ kdev_t start = MMC_BLOCK_RAW_DEVICE( rdev );
-+ int minor = MINOR( start );
-+ int host, slot;
-+ int i;
-+
-+ __ENTER0();
-+
-+ (void)mmc_update_card_stack( MINOR( start )>>MMC_MINOR_HOST_SHIFT );
-+
-+ __mmc_block_wrlock_devices();
-+
-+ dev = &mmc_block_device[minor];
-+ host = dev->host;
-+ slot = dev->slot;
-+
-+ if ( dev->card ) { /* card has not been changed actually */
-+ __mmc_block_wrunlock_devices();
-+ goto out;
-+
-+ } else {
-+ card = mmc_get_card( host, slot );
-+ if ( !card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "failed to get card: "
-+ "host=%d, slot=%d\n", host, slot );
-+ __mmc_block_wrunlock_devices();
-+ goto error;
-+ }
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ /* FIXME */
-+ __mmc_block_rdlock_devices(); /* handle the request for sector 0 */
-+ grok_partitions( &mmc_block_gendisk, MINOR( start ),
-+ mmc_block_gendisk.max_p,
-+ card->info.capacity>>9 /* sectors */
-+ );
-+ __mmc_block_rdunlock_devices();
-+ /* FIXME */
-+ __mmc_block_wrlock_devices();
-+ for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ int minor = MINOR( i );
-+
-+ dev = &mmc_block_device[minor];
-+ if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+out:
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static void mmc_block_handle_request( void )
-+{
-+ struct request *request;
-+ mmc_block_device_t dev;
-+ mmc_card_t card;
-+ char *buf;
-+ loff_t pos;
-+ unsigned int result = 0;
-+
-+ for (;;) {
-+ int minor;
-+
-+ INIT_REQUEST;
-+ request = CURRENT;
-+ spin_unlock_irq( &io_request_lock );
-+
-+ minor = MINOR( request->rq_dev );
-+ dev = __mmc_block_get_device( request->rq_dev );
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "invalid device (%x:%x)\n",
-+ MAJOR( request->rq_dev ), minor );
-+
-+ goto end_req;
-+ }
-+
-+ card = dev->card;
-+ (void)__mmc_block_put_device( dev );
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+// printk( KERN_INFO __FUNCTION__"(): "
-+ "request %p: cmd %i sec %li (nr. %li)\n",
-+ CURRENT, CURRENT->cmd, CURRENT->sector,
-+ CURRENT->current_nr_sectors );
-+
-+ if ( request->current_nr_sectors >
-+ mmc_block_gendisk.part[minor].nr_sects )
-+ goto end_req;
-+
-+ // Handle the request
-+ // TODO: handle clusterred requests in multiple block transfer mode
-+ buf = request->buffer;
-+ pos = (mmc_block_gendisk.part[minor].start_sect +
-+ request->sector) * MMC_BLOCK_SECT_SIZE;
-+
-+ switch ( request->cmd )
-+ {
-+ int i, ret;
-+
-+ case READ:
-+#if 0
-+ ret = mmc_read( card,
-+ (request->current_nr_sectors > 1) ?
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ request->current_nr_sectors
-+ * MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+
-+#else
-+ for ( i = 0;
-+ i < request->current_nr_sectors;
-+ i++ ) {
-+ ret = mmc_read( card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+ else
-+ buf += ret;
-+ }
-+#endif
-+ result = 1;
-+ break;
-+
-+ case WRITE:
-+ // TODO: Read only device
-+#if 0
-+ ret = mmc_write( card,
-+ (request->current_nr_sectors > 1) ?
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE :
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ request->current_nr_sectors
-+ * MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+
-+#else
-+ for ( i = 0;
-+ i < request->current_nr_sectors;
-+ i++ ) {
-+ ret = mmc_write( card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ buf,
-+ MMC_BLOCK_SECT_SIZE, /* FIXME */
-+ &pos );
-+ if ( ret < 0 )
-+ goto end_req;
-+ else
-+ buf += ret;
-+ }
-+#endif
-+ result = 1;
-+ break;
-+ }
-+
-+end_req:
-+ __LEAVE( "result=%d", result );
-+ spin_lock_irq( &io_request_lock );
-+ end_request( result );
-+ }
-+}
-+
-+static volatile int leaving = 0;
-+static DECLARE_MUTEX_LOCKED( thread_sem );
-+static DECLARE_WAIT_QUEUE_HEAD( thr_wq );
-+static pid_t thr_id = -1;
-+
-+int mmc_block_thread( void *arg )
-+{
-+ struct task_struct *task = current;
-+ DECLARE_WAITQUEUE(wait, task);
-+
-+ __ENTER0();
-+
-+ task->session = 1;
-+ task->pgrp = 1;
-+ task->flags |= PF_MEMALLOC;
-+ strcpy( task->comm, "mmcblockd" );
-+ task->tty = NULL;
-+ spin_lock_irq( &task->sigmask_lock );
-+ sigfillset( &task->blocked );
-+ recalc_sigpending( task );
-+ spin_unlock_irq( &task->sigmask_lock );
-+ exit_mm( task );
-+ exit_files( task );
-+ exit_sighand( task );
-+ exit_fs( task );
-+
-+ while ( !leaving ) {
-+ add_wait_queue( &thr_wq, &wait);
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ spin_lock_irq( &io_request_lock );
-+ if ( QUEUE_EMPTY || QUEUE_PLUGGED ) {
-+ spin_unlock_irq( &io_request_lock );
-+ schedule();
-+ remove_wait_queue( &thr_wq, &wait );
-+ } else {
-+ remove_wait_queue( &thr_wq, &wait );
-+ set_current_state( TASK_RUNNING );
-+ mmc_block_handle_request(); /* handle the request */
-+ spin_unlock_irq( &io_request_lock );
-+ }
-+ }
-+
-+ up( &thread_sem );
-+
-+ __LEAVE0();
-+ return 0;
-+}
-+
-+#if LINUX_VERSION_CODE < 0x20300
-+#define RQFUNC_ARG void
-+#else
-+#define RQFUNC_ARG request_queue_t *q
-+#endif
-+
-+static void mmc_block_request( RQFUNC_ARG )
-+{
-+ wake_up( &thr_wq );
-+}
-+
-+static int mmc_block_ioctl( struct inode * inode, struct file * file,
-+ unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -ENODEV;
-+ mmc_block_device_t dev;
-+ mmc_card_t card;
-+ int minor;
-+ __ENTER0();
-+
-+ if ( !inode || !file ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+ minor = MINOR( inode->i_rdev );
-+
-+ dev = __mmc_block_get_device( inode->i_rdev );
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );
-+ goto error;
-+ }
-+
-+ card = dev->card;
-+ __mmc_block_put_device( dev );
-+
-+ switch ( cmd ) {
-+ case BLKGETSIZE: /* Return device size */
-+ {
-+ unsigned long value;
-+
-+ __mmc_block_rdlock_devices();
-+ value = mmc_block_gendisk.part[minor].nr_sects;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( put_user( value, (unsigned long *) arg) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+
-+#ifdef BLKGETSIZE64
-+ case BLKGETSIZE64:
-+ {
-+ unsigned long value;
-+
-+ __mmc_block_rdlock_devices();
-+ value = mmc_block_gendisk.part[minor].nr_sects;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( put_user( (u64)value, (u64 *) arg) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+#endif
-+
-+ case HDIO_GETGEO:
-+ {
-+ struct hd_geometry geo;
-+
-+ ret = !access_ok( VERIFY_WRITE, arg, sizeof( geo ) );
-+ if ( ret ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+
-+ geo.heads = 1;
-+ geo.sectors = 1;
-+
-+ __mmc_block_rdlock_devices();
-+ geo.cylinders = mmc_block_gendisk.part[minor].nr_sects;
-+ geo.start = mmc_block_gendisk.part[minor].start_sect;
-+ __mmc_block_rdunlock_devices();
-+
-+ if ( copy_to_user( (int *)arg, &geo, sizeof( geo ) ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ }
-+ break;
-+
-+ case BLKRRPART:
-+ if ( !capable( CAP_SYS_ADMIN ) ) {
-+ ret = -EACCES;
-+ goto error;
-+ }
-+ (void)mmc_block_revalidate( inode->i_rdev );
-+ break;
-+
-+ default:
-+ ret = blk_ioctl( inode->i_rdev, cmd, arg );
-+ goto out;
-+ }
-+
-+ ret = 0;
-+error:
-+out:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+#if LINUX_VERSION_CODE < 0x20326
-+static struct file_operations mmc_block_fops =
-+{
-+ open: mmc_block_open,
-+ ioctl: mmc_block_ioctl,
-+ release: mmc_block_release,
-+ check_media_change: mmc_block_check_disk_change,
-+ revalidate: mmc_block_revalidate,
-+ read: block_read,
-+ write: block_write
-+};
-+#else
-+static struct block_device_operations mmc_block_fops =
-+{
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
-+ owner: THIS_MODULE,
-+#endif
-+ open: mmc_block_open,
-+ release: mmc_block_release,
-+ ioctl: mmc_block_ioctl,
-+ check_media_change: mmc_block_check_disk_change,
-+ revalidate: mmc_block_revalidate
-+};
-+#endif
-+
-+
-+static int mmc_block_notify_add( mmc_card_t card )
-+{
-+ int ret = -1;
-+ mmc_block_device_t dev;
-+ kdev_t start;
-+ int minor;
-+
-+ __ENTER0();
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );
-+ dev = &mmc_block_device[MINOR( start )];
-+
-+ __mmc_block_wrlock_devices();
-+ if ( !dev->card ) {
-+ dev->card = card;
-+ ret = 0;
-+ }
-+ __mmc_block_wrunlock_devices();
-+
-+ if ( !ret ) {
-+ int i;
-+
-+ /* allow to read partition table */
-+ __mmc_block_rdlock_devices();
-+ grok_partitions( &mmc_block_gendisk, MINOR( start ),
-+ mmc_block_gendisk.max_p,
-+ card->info.capacity>>9 /* sectors */
-+ );
-+ __mmc_block_rdunlock_devices();
-+
-+ __mmc_block_wrlock_devices();
-+ for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {
-+ minor = MINOR( i );
-+ dev = &mmc_block_device[minor];
-+ if ( mmc_block_gendisk.part[minor].nr_sects > 0 )
-+ dev->card = card;
-+ }
-+ __mmc_block_wrunlock_devices();
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+
-+static int mmc_block_notify_remove( mmc_card_t card )
-+{
-+ int ret = -1;
-+
-+ __ENTER( "card=0x%p", card );
-+
-+ if ( card && card->ctrlr )
-+ ret = __mmc_block_invalidate_card( card, FALSE );
-+
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static mmc_notifier_rec_t mmc_block_notifier = {
-+ add: mmc_block_notify_add,
-+ remove: mmc_block_notify_remove
-+};
-+
-+static int __init mmc_block_module_init( void )
-+{
-+ int ret = -ENODEV;
-+ int i;
-+
-+ __ENTER0();
-+
-+ init_rwsem( &mmc_block_device_sem );
-+
-+ if ( devfs_register_blkdev( MAJOR_NR, MAJOR_NAME, &mmc_block_fops ) ) {
-+ MMC_ERROR( "Can't allocate major number %d for MMC block devices.\n", MMC_BLOCK_MAJOR );
-+ ret = -EAGAIN;
-+ goto error;
-+ }
-+
-+ for ( i = 0; i < (1<<MINORBITS); i++ ) {
-+ __mmc_block_device_init( i );
-+ init_MUTEX( &mmc_block_device[i].sem );
-+
-+ /* We fill it in at open() time. */
-+ mmc_block_blk_sizes[i] = 0;
-+ mmc_block_blk_blksizes[i] = BLOCK_SIZE;
-+ mmc_block_hardsect_sizes[i] = 0;
-+ }
-+
-+ init_waitqueue_head( &thr_wq );
-+ /* Allow the block size to default to BLOCK_SIZE. */
-+ blksize_size[MAJOR_NR] = mmc_block_blk_blksizes;
-+ hardsect_size[MAJOR_NR] = mmc_block_hardsect_sizes;
-+ /* Gendisk stuff */
-+ memset( mmc_block_partitions, 0, sizeof( mmc_block_partitions ) );
-+ add_gendisk( &mmc_block_gendisk );
-+
-+/* FIXME: per controller request queue, I/O and card stack update threads */
-+ blk_init_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ), &mmc_block_request );
-+ thr_id = kernel_thread( mmc_block_thread, NULL,
-+ CLONE_FS|CLONE_FILES|CLONE_SIGHAND );
-+
-+ if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_block_notifier, 0 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+
-+ ret = 0;
-+ goto out;
-+error:
-+ if ( thr_id != -1 ) {
-+/* quit the thread */
-+ leaving = 1;
-+ wake_up(&thr_wq);
-+
-+ down(&thread_sem);
-+ }
-+ blksize_size[MAJOR_NR] = NULL;
-+ blk_size[MAJOR_NR] = NULL;
-+ hardsect_size[MAJOR_NR] = NULL;
-+out:
-+ __LEAVE0();
-+ return ret;
-+}
-+
-+static void __exit mmc_block_module_cleanup( void )
-+{
-+/* quit the thread */
-+ leaving = 1;
-+ wake_up(&thr_wq);
-+
-+ down(&thread_sem);
-+
-+ mmc_unregister( MMC_REG_TYPE_USER, &mmc_block_notifier );
-+ del_gendisk( &mmc_block_gendisk );
-+ devfs_unregister_blkdev( MAJOR_NR, MAJOR_NAME );
-+
-+ blk_cleanup_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ) );
-+ blksize_size[MAJOR_NR] = NULL;
-+ blk_size[MAJOR_NR] = NULL;
-+ hardsect_size[MAJOR_NR] = NULL;
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init( mmc_block_module_init );
-+module_exit( mmc_block_module_cleanup );
-+
-+
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc_core.c
-@@ -0,0 +1,1124 @@
-+/*
-+ * linux/drivers/mmc/mmc_core.c
-+ * MultiMediaCard subsystem core implementation
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_core.c,v 0.3.1.14 2002/09/27 17:36:09 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/slab.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+
-+#ifdef CONFIG_PM
-+#include <linux/pm.h>
-+#endif
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+
-+#define __MMC_CORE_IMPLEMENTATION__
-+#include "mmc.h"
-+
-+/* MMC controllers registered in the system */
-+static mmc_controller_t mmc_controller[MMC_CONTROLLERS_MAX];
-+static int mmc_ncontrollers = 0;
-+static rwsemaphore_t mmc_controller_sem; /* controller table lock */
-+#ifdef CONFIG_PM
-+static struct pm_dev *mmc_pm_dev = NULL;
-+#endif
-+
-+/* users' notification list */
-+static mmc_notifier_t mmc_notifier = NULL;
-+static rwsemaphore_t mmc_notifier_sem; /* notifiers' list lock */
-+#ifdef CONFIG_PROC_FS
-+static proc_dir_entry_t mmc_proc_dir = NULL;
-+#endif
-+
-+/************************************************
-+ * service function prototypes and declarations *
-+ ************************************************/
-+static inline int mmc_acquire_io( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ int ret = -EIO;
-+
-+ __ENTER0();
-+
-+ if ( !card || !ctrlr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+#ifdef CONFIG_HOTPLUG
-+/* TODO: account for controller removal */
-+#endif
-+ down( &ctrlr->io_sem );
-+#if 0
-+ down_read( &ctrlr->update_sem ); /* FIXME */
-+ if ( card->state != MMC_CARD_STATE_UNPLUGGED )
-+ ret = 0;
-+ up_read( &ctrlr->update_sem );
-+
-+ if ( ret )
-+ up( &ctrlr->io_sem );
-+#else
-+ ret = 0;
-+#endif
-+
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline void mmc_release_io( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ __ENTER0();
-+#ifdef CONFIG_HOTPLUG
-+/* TODO: account for controller removal */
-+#endif
-+ if ( !card && !ctrlr ) { /* FIXME */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "bad card reference\n" );
-+ goto error;
-+ }
-+ up( &ctrlr->io_sem );
-+error:
-+ __LEAVE0();
-+}
-+
-+/* TODO: there should be a separate context to be awaken
-+ * by the card intertion interrupt; called under ctrlr->update_sem
-+ * held down by now */
-+static int __mmc_update_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ mmc_card_t card, prev;
-+
-+ __ENTER0();
-+
-+ if ( !ctrlr || !ctrlr->tmpl )
-+ goto error;
-+
-+ /* check unplugged cards first... */
-+ if ( (ret = ctrlr->tmpl->check_card_stack( ctrlr )) )
-+ goto error;
-+
-+ /* unregister unplugged cards and free 'em immediately */
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ prev = ctrlr->stack.first;
-+ /* process the stack tail first */
-+ if ( prev->next ) {
-+ card = prev->next;
-+ while ( card ) {
-+ if ( card->state == MMC_CARD_STATE_UNPLUGGED ) {
-+ if ( ctrlr->stack.selected == card )
-+ ctrlr->stack.selected = NULL;
-+#ifdef CONFIG_PROC_FS
-+ if ( card->proc ) {
-+ remove_proc_entry( card->proc_name, ctrlr->proc );
-+ card->proc = NULL;
-+ }
-+#endif
-+ ctrlr->slot_next = card->slot; /* FIXME */
-+ prev->next = card->next;
-+ if ( ctrlr->stack.last == card )
-+ ctrlr->stack.last = prev;
-+ /* FIXME: controller use count */
-+ mmc_notify_remove( card );
-+ --ctrlr->stack.ncards;
-+ if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count "
-+ "decreased (%d)\n",
-+ ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT(
-+ ctrlr->tmpl->owner );
-+ }
-+ __mmc_card_free( card );
-+
-+ card = prev->next;
-+ }
-+ }
-+ }
-+ /* then the head */
-+ card = ctrlr->stack.first;
-+ if ( card && (card->state == MMC_CARD_STATE_UNPLUGGED) ) {
-+ if ( ctrlr->stack.selected == card )
-+ ctrlr->stack.selected = NULL;
-+#ifdef CONFIG_PROC_FS
-+ if ( card->proc ) {
-+ remove_proc_entry( card->proc_name, ctrlr->proc );
-+ card->proc = NULL;
-+ }
-+#endif
-+ ctrlr->slot_next = card->slot; /* FIXME */
-+ mmc_notify_remove( card ); /* FIXME: should unregister here */
-+ ctrlr->stack.first = card->next;
-+ if ( ctrlr->stack.last == card )
-+ ctrlr->stack.last = NULL;
-+ /* FIXME: controller use count */
-+ --ctrlr->stack.ncards;
-+ if ( (ctrlr->usage > 0) && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "'%s' use count "
-+ "decreased (%d)\n", ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT( ctrlr->tmpl->owner );
-+ }
-+ __mmc_card_free( card );
-+ }
-+ }
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "after stack check: ncards=%d"
-+ " first=0x%x last=0x%x\n", ctrlr->stack.ncards,
-+ ctrlr->stack.first, ctrlr->stack.last );
-+ /* ...then add newly inserted ones */
-+ if ( (ret = ctrlr->tmpl->update_acq( ctrlr )) )
-+ goto error;
-+ /* ret = 0; */
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+/*
-+ * 1) check error code returned by controller; it's up to
-+ * controller to detect error conditions reported by the card
-+ * and to abort data transfer requests properly (e.g. send
-+ * CMD12(STOP_TRANSMISSION) to abort ADDRESS_ERROR multiple
-+ * block transfers)
-+ * 2) arrange for card stack update when necessary
-+ * (all pending i/o requests must be held pending,
-+ * update procedure must start immediately after
-+ * error has been detected)
-+ */
-+static inline int __mmc_check_error( mmc_card_t card, int err )
-+{
-+ int ret = -EIO;
-+ mmc_controller_t ctrlr;
-+
-+ __ENTER0();
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+
-+ if ( err < 0 ) {
-+ switch ( err ) {
-+ /* bus error occurred */
-+ case MMC_ERROR_CRC_WRITE_ERROR:
-+ case MMC_ERROR_CRC_READ_ERROR:
-+ case MMC_ERROR_RES_CRC_ERROR:
-+ case MMC_ERROR_READ_TIME_OUT:
-+ case MMC_ERROR_TIME_OUT_RESPONSE:
-+ down_write( &ctrlr->update_sem ); /* FIXME */
-+ if ( !__mmc_update_card_stack( ctrlr ) )
-+ ret = -ENXIO;
-+ up_write( &ctrlr->update_sem );
-+ break;
-+ }
-+ } else
-+ ret = err;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static inline void __mmc_free_controller( mmc_controller_t ctrlr )
-+{
-+ if ( ctrlr ) {
-+ if ( ctrlr->stack.ncards > 0 )
-+ __mmc_card_stack_free( &ctrlr->stack );
-+ kfree( ctrlr );
-+ }
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+static int mmc_proc_read_card_info( char *page, char **start, off_t off, int count, int *eof, void *data )
-+{
-+ int ret = -EINVAL;
-+ mmc_card_t card = (mmc_card_t)data;
-+ char *cp = page;
-+
-+ if ( !card )
-+ goto error;
-+
-+ down_read( &card->ctrlr->update_sem );
-+/* TODO: proc report
-+ * Type: RO, RW or IO (by CCC)
-+ * MID: 0x%02x card->info.cid.mid
-+ * OID: 0x%04x card->info.cid.oid
-+ * PNM: %s card->info.pnm
-+ * PRV: %s card->info.prv
-+ * PSN: 0x%08x card->info.cid.psn
-+ * MDT: %s card->info.mdt
-+ * Capacity: card->info.capacity (Bytes)
-+ */
-+#if 1
-+ cp += sprintf( cp, "Capacity: %dKb.\n\n", (card->info.capacity>>10) );
-+#else /* TODO */
-+ cp += sprintf( cp, "Type : %s\n", card->info.type );
-+ cp += sprintf( cp, "MID : 0x%02x\n", card->info.cid.mid );
-+ cp += sprintf( cp, "OID : 0x%04x\n", card->info.cid.oid );
-+ cp += sprintf( cp, "PNM : %s\n", card->info.pnm );
-+ cp += sprintf( cp, "PRV : %s\n", card->info.prv );
-+ cp += sprintf( cp, "PSN : 0x%08x\n", card->info.cid.psn );
-+ cp += sprintf( cp, "MDT : %s\n", card->info.mdt );
-+ cp += sprintf( cp, "Capacity: %dKB\n",
-+ (card->info.capacity>>10) );
-+#endif
-+ up_read( &card->ctrlr->update_sem );
-+
-+ ret = cp - page;
-+error:
-+ return ret;
-+}
-+#endif
-+
-+/*************************************
-+ * MMC core interface implementation *
-+ *************************************/
-+int mmc_notify_add( mmc_card_t card )
-+{
-+ int ret = 0;
-+ mmc_notifier_t notifier;
-+
-+ __ENTER0();
-+ if ( card ) {
-+ for ( notifier = mmc_notifier; notifier;
-+ notifier = notifier->next )
-+ if ( notifier->add )
-+ if ( (ret = notifier->add( card )) )
-+ break;
-+ }
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_notify_add );
-+
-+int mmc_notify_remove( mmc_card_t card )
-+{
-+ int ret = 0;
-+ mmc_notifier_t notifier;
-+
-+ __ENTER0();
-+ if ( card ) {
-+ for ( notifier = mmc_notifier; notifier;
-+ notifier = notifier->next )
-+ if ( notifier->remove )
-+ if ( (ret = notifier->remove( card )) )
-+ break;
-+ }
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_notify_remove );
-+
-+int mmc_update_card_stack( int host )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+
-+ __ENTER0();
-+
-+ if ( (host < 0) || (host >= MMC_CONTROLLERS_MAX) )
-+ goto error;
-+
-+ down_read( &mmc_controller_sem );
-+ if ( (ctrlr = mmc_controller[host]) ) {
-+ down_write( &ctrlr->update_sem );
-+ (void)__mmc_update_card_stack( ctrlr );
-+ up_write( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+ ret = 0;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_update_card_stack );
-+
-+ssize_t mmc_read( mmc_card_t card, mmc_transfer_mode_t mode, char *buf, size_t size, loff_t *paddr )
-+{
-+ ssize_t ret = -EIO;
-+ mmc_controller_t ctrlr;
-+ mmc_data_transfer_req_rec_t transfer;
-+
-+ if ( !paddr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( !card ) {
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%x",
-+ card, card->usage, mode, buf, size, *paddr );
-+
-+ ctrlr = card->ctrlr;
-+ if ( (ret = mmc_acquire_io( ctrlr, card )) )
-+ goto error;
-+
-+ memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
-+ transfer.cmd = MMC_READ;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER; /* FIXME: buffer cache */
-+ transfer.buf = buf;
-+ transfer.addr = *paddr;
-+ transfer.cnt = size;
-+
-+/* max block size defined by CSD[read_bl_len] */
-+ transfer.blksz = card->info.read_bl_len;
-+ transfer.nob = size / transfer.blksz;
-+ if ( (size - (transfer.nob * transfer.blksz)) > 0 )
-+ transfer.nob++;
-+
-+/* TODO: controller may restrict maximum block size; set block size
-+ * and number of blocks that their accumulated length fit to
-+ * CSD[READ_BL_LEN] not to bother with block misalignment in multiple
-+ * block transfers */
-+ ctrlr = card->ctrlr;
-+ if ( transfer.blksz > ctrlr->tmpl->block_size_max ) {
-+ ret = -EINVAL; /* FIXME */
-+ goto error;
-+ }
-+
-+ if ( ctrlr->stack.selected != card ) {
-+ if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
-+ goto err_mmc;
-+ ctrlr->stack.selected = card;
-+ }
-+
-+ switch( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM:
-+ if ( !ctrlr->tmpl->stream_read ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+/* TODO: The max clock frequency for stream read operation is given by
-+ the following formula:
-+ max speed = min ( TRAN_SPEED, 8*2^(READ_BL_LEN) - NSAC/TAAC )
-+
-+ If the card is not able to sustain data transfer it will set the
-+ UNDERRUN error bit in the status register, abort the transmission
-+ and wait in the Data state for a stop command
-+ */
-+ ret = ctrlr->tmpl->stream_read( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ if ( !ctrlr->tmpl->read_block ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+/* TODO: buffer size and data alignment (v3.4, p.29):
-+ if CSD[READ_BL_PARTIAL] is set, smaller blocks whose starting
-+ and ending address are entirely contained within one physical
-+ block (as defined by CSD[READ_BL_LEN]) may also be transmitted
-+ */
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->read_block( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ if ( !ctrlr->tmpl->read_mblock ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+
-+ if ( transfer.nob > ctrlr->tmpl->nob_max ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+/* TODO: buffer size and data alignment (v3.4, p.29):
-+ if the host uses patrial blocks whose accumulated length is
-+ not block aligned and block misalignment is not allowed, the
-+ card should detect a block misalignment error condition at the
-+ beginning of the first misaligned block
-+ */
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->read_mblock( card->ctrlr, &transfer );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
-+ ret = -EINVAL;
-+ }
-+err_mmc:
-+ ret = __mmc_check_error( card, ret );
-+ if ( ret >= 0 ) {
-+ ret = size - transfer.cnt;
-+ *paddr += ret;
-+ }
-+err_down:
-+ mmc_release_io( ctrlr, card );
-+error:
-+ __LEAVE("ret=%d", ret);
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_read );
-+
-+ssize_t mmc_write( mmc_card_t card, mmc_transfer_mode_t mode, const char *buf, size_t size, loff_t *paddr )
-+{
-+ ssize_t ret = -ESPIPE;
-+ mmc_controller_t ctrlr;
-+ mmc_data_transfer_req_rec_t transfer;
-+
-+ if ( !paddr ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( !card ) {
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "card=%p usage=%d mode=%d buf=%p size=%d addr=%llx",
-+ card, card->usage, mode, buf, size, *paddr );
-+
-+ ctrlr = card->ctrlr;
-+ if ( (ret = mmc_acquire_io( ctrlr, card )) )
-+ goto error;
-+
-+ memset( &transfer, 0, sizeof( mmc_data_transfer_req_rec_t ) );
-+ transfer.cmd = MMC_WRITE;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER; /* FIXME: buffer cache */
-+ transfer.buf = (char *)buf;
-+ transfer.addr = *paddr;
-+ transfer.cnt = size;
-+
-+/* max block size defined by CSD[write_bl_len] */
-+ transfer.blksz = card->info.write_bl_len;
-+ transfer.nob = size / transfer.blksz;
-+ if ( (size - (transfer.nob * transfer.blksz)) > 0 )
-+ transfer.nob++;
-+
-+/* TODO: controller may restrict maximum block size; set block size
-+ * and number of blocks that their accumulated length fit to
-+ * CSD[WRITE_BL_LEN] not to bother with block misalignment in multiple
-+ * block transfers */
-+ ctrlr = card->ctrlr;
-+ if ( transfer.blksz > ctrlr->tmpl->block_size_max ) {
-+ ret = -EINVAL; /* FIXME */
-+ goto error;
-+ }
-+
-+ if ( ctrlr->stack.selected != card ) {
-+ if ( (ret = ctrlr->tmpl->setup_card( ctrlr, card )) )
-+ goto err_mmc;
-+ ctrlr->stack.selected = card;
-+ }
-+
-+ transfer.cmd = MMC_WRITE;
-+ transfer.mode = mode;
-+ transfer.type = MMC_USER;
-+ switch( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM:
-+ if ( !ctrlr->tmpl->stream_write ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ ret = ctrlr->tmpl->stream_write( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ if ( !ctrlr->tmpl->write_block ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->write_block( ctrlr, &transfer );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ if ( !ctrlr->tmpl->write_mblock ) {
-+ ret = -ENXIO;
-+ goto err_down;
-+ }
-+ transfer.type = MMC_KERNEL; /* FIXME */
-+ ret = ctrlr->tmpl->write_mblock( card->ctrlr, &transfer );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "request for unknown transfer type\n" );
-+ }
-+
-+err_mmc:
-+ ret = __mmc_check_error( card, ret ); /* FIXME */
-+ if ( ret >= 0 ) {
-+ ret = size - transfer.cnt;
-+ *paddr += ret;
-+ }
-+err_down:
-+ mmc_release_io( ctrlr, card );
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_write );
-+
-+int mmc_ioctl( mmc_card_t card, unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+
-+ if ( !card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" )
-+ goto error;
-+ }
-+
-+ ctrlr = card->ctrlr;
-+ if ( mmc_acquire_io( ctrlr, card ) ) {
-+ ret = -ENXIO;
-+ goto error;
-+ }
-+
-+ switch ( cmd ) {
-+ case IOCMMCGCARDESC:
-+ if ( copy_to_user( (void *)arg, &card->info, sizeof( mmc_card_info_rec_t ) ) )
-+ ret = -EFAULT;
-+ break;
-+/*
-+ * 1. TODO: erase region
-+ * 2. TODO: set/unset write protection, lock/password
-+ */
-+ default:
-+ ret = -ENOIOCTLCMD;
-+ }
-+
-+ mmc_release_io( ctrlr, card );
-+error:
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_ioctl );
-+
-+/*
-+ * registry stuff
-+ */
-+mmc_card_t mmc_get_card( int host, int slot )
-+{
-+ mmc_card_t ret = NULL;
-+ mmc_controller_t ctrlr = NULL;
-+ int found;
-+
-+ __ENTER( "host=%d, card=%d", host, slot );
-+
-+ if ( ((host < 0) || (host >= MMC_CONTROLLERS_MAX))
-+ && ((slot < 0) || (slot >= MMC_CARDS_MAX)) )
-+ goto error;
-+
-+ down_read( &mmc_controller_sem );
-+
-+ if ( (ctrlr = mmc_controller[host]) ) {
-+ down_write( &ctrlr->update_sem );
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ ret = ctrlr->stack.first;
-+ found = FALSE;
-+ while ( ret ) {
-+ if ( (ret->slot == slot) && (ret->state !=
-+ MMC_CARD_STATE_UNPLUGGED) ) {
-+ found = TRUE;
-+ break;
-+ }
-+ ret = ret->next;
-+ }
-+
-+ if ( found ) {
-+ if ( ctrlr->tmpl->owner ) {
-+ ++ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count increased (%d)\n",
-+ ctrlr->tmpl->name, ctrlr->usage );
-+ __MOD_INC_USE_COUNT( ctrlr->tmpl->owner );
-+ }
-+ ++ret->usage;
-+ } else
-+ ret = NULL;
-+ }
-+ up_write( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+error:
-+ __LEAVE("ret=0x%p usage=%d", ret, ret ? ret->usage : -1 );
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_get_card );
-+
-+void mmc_put_card( mmc_card_t card )
-+{
-+ mmc_card_t tmp = NULL;
-+ mmc_controller_t ctrlr;
-+ int found;
-+
-+ __ENTER( "card=0x%p", card );
-+
-+ if ( !card )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+
-+ down_read( &mmc_controller_sem );
-+ if ( !ctrlr || (ctrlr != mmc_controller[ctrlr->slot]) ) {
-+ MMC_ERROR( "bad controller reference: ctrlr=0x%p\n", ctrlr );
-+ goto err_down;
-+ }
-+
-+ down_write( &ctrlr->update_sem );
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ tmp = ctrlr->stack.first;
-+ found = FALSE;
-+ while ( tmp ) {
-+ if ( tmp == card ) {
-+ found = TRUE;
-+ break;
-+ }
-+ tmp = tmp->next;
-+ }
-+
-+ if ( found ) {
-+ if ( tmp->usage > 0 ) {
-+ --tmp->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "usage=%d"
-+ "owner=0x%p\n", tmp->usage,
-+ ctrlr->tmpl->owner );
-+ if ( !tmp->usage && (ctrlr->usage > 0)
-+ && ctrlr->tmpl->owner ) {
-+ --ctrlr->usage;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2,
-+ "'%s' use count "
-+ "decreased (%d)\n",
-+ ctrlr->tmpl->name,
-+ ctrlr->usage );
-+ __MOD_DEC_USE_COUNT(
-+ ctrlr->tmpl->owner );
-+ }
-+ }
-+ } else
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" );
-+
-+ }
-+ up_write( &ctrlr->update_sem );
-+err_down:
-+ up_read( &mmc_controller_sem );
-+error:
-+ __LEAVE( "found=%d", found );
-+ return;
-+}
-+EXPORT_SYMBOL( mmc_put_card );
-+
-+static inline void *mmc_register_user( mmc_notifier_t notifier )
-+{
-+ mmc_notifier_t ret = NULL, last = mmc_notifier;
-+
-+ MOD_INC_USE_COUNT;
-+ if ( notifier ) {
-+ down_write( &mmc_notifier_sem );
-+
-+ notifier->next = NULL;
-+ if ( !last ) {
-+ mmc_notifier = notifier;
-+ ret = notifier;
-+ } else {
-+ while ( last->next ) {
-+ if ( last == notifier ) {
-+ MOD_DEC_USE_COUNT;
-+ break;
-+ }
-+ last = last->next;
-+ }
-+ if ( last != notifier ) {
-+ last->next = notifier;
-+ ret = notifier;
-+ }
-+ }
-+ up_write( &mmc_notifier_sem );
-+ }
-+/* notify new user about the cards present in the system */
-+ if ( ret && ret->add ) {
-+ int i;
-+
-+ down_read( &mmc_controller_sem );
-+ for ( i = 0; i < mmc_ncontrollers; i++ ) {
-+ mmc_controller_t ctrlr = mmc_controller[i];
-+
-+ down_read( &ctrlr->update_sem ); /* FIXME */
-+ __mmc_card_stack_foreach( &ctrlr->stack,
-+ ret->add, FALSE );
-+ up_read( &ctrlr->update_sem ); /* FIXME */
-+ }
-+ up_read( &mmc_controller_sem );
-+ }
-+/* error: */
-+ __LEAVE( "mmc_notifier=0x%p, mmc_notifier->next=0x%p",
-+ mmc_notifier, mmc_notifier ? mmc_notifier->next : NULL );
-+ return ret;
-+}
-+
-+static inline mmc_controller_t mmc_register_controller( mmc_controller_tmpl_t tmpl, size_t extra )
-+{
-+ mmc_controller_t ret = NULL;
-+ int found;
-+ int i;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ down_write( &mmc_controller_sem );
-+
-+ if ( mmc_ncontrollers >= MMC_CONTROLLERS_MAX ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're too many controllers\n" );
-+ goto error;
-+ }
-+
-+ found = FALSE;
-+ for ( i = 0; i < MMC_CONTROLLERS_MAX; i++ )
-+ if ( !mmc_controller[i] ) {
-+ found = TRUE;
-+ break;
-+ }
-+
-+ if ( !found ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're no empty slots\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->init ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->probe ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'probe()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->init_card_stack ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init_card_stack()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->update_acq ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'update_acq()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->check_card_stack ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'check_card_stack()'\n" );
-+ goto error;
-+ }
-+
-+ if ( !tmpl->setup_card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'setup_card()'\n" );
-+ goto error;
-+ }
-+
-+ ret = kmalloc( sizeof( mmc_controller_rec_t ) + extra, GFP_ATOMIC ); /* FIXME: ISA + GFP_DMA */
-+ if ( !ret ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "out of memory\n" );
-+ goto error;
-+ }
-+
-+ memset( ret, 0, sizeof( mmc_controller_rec_t ) + extra );
-+
-+ if ( (tmpl->probe( ret ) != 1) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller probe failed\n" );
-+ goto err_free;
-+ }
-+
-+ if ( tmpl->init( ret ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller initialization failure\n" );
-+ goto err_free;
-+ }
-+
-+ ret->state = MMC_CONTROLLER_FOUND;
-+ ret->slot = i;
-+ ret->tmpl = tmpl;
-+ init_MUTEX( &ret->io_sem );
-+ init_rwsem( &ret->update_sem );
-+#ifdef CONFIG_PROC_FS
-+ if ( mmc_proc_dir ) {
-+ snprintf( ret->proc_name, sizeof( ret->proc_name ),
-+ "host%d", ret->slot );
-+ ret->proc = proc_mkdir( ret->proc_name, mmc_proc_dir );
-+ }
-+#endif
-+
-+/* initialize card stack */
-+ if ( ret->tmpl->init_card_stack( ret ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "card stack initialization failure\n" );
-+ if ( ret->tmpl->remove )
-+ ret->tmpl->remove( ret ); /* FIXME */
-+ goto err_free;
-+ }
-+
-+ mmc_controller[ret->slot] = ret;
-+ ++mmc_ncontrollers;
-+
-+/* notify users */
-+ if ( ret->stack.ncards > 0 ) {
-+ down_read( &mmc_notifier_sem );
-+ if ( (i = __mmc_card_stack_foreach( &ret->stack, mmc_notify_add, FALSE ) ) < 0 )
-+ MMC_ERROR( "device add notification failed at slot %d\n", -i );
-+ up_read( &mmc_notifier_sem );
-+ }
-+ goto out;
-+
-+err_free:
-+#ifdef CONFIG_PROC_FS
-+ if ( ret->proc )
-+ remove_proc_entry( ret->proc_name, mmc_proc_dir );
-+#endif
-+ kfree( ret );
-+error:
-+ ret = NULL;
-+ MOD_DEC_USE_COUNT;
-+out:
-+ up_write( &mmc_controller_sem );
-+ return ret;
-+}
-+
-+static inline mmc_card_t mmc_register_card( mmc_card_t card )
-+{
-+ mmc_card_t ret = NULL;
-+ mmc_controller_t ctrlr;
-+
-+ if ( !card || !card->ctrlr )
-+ goto error;
-+
-+ ctrlr = card->ctrlr;
-+#ifdef CONFIG_PROC_FS
-+ if ( ctrlr->proc ) {
-+ snprintf( card->proc_name, sizeof( card->proc_name ),
-+ "card%d", card->slot );
-+ card->proc = create_proc_read_entry( card->proc_name,
-+ 0444, ctrlr->proc,
-+ mmc_proc_read_card_info, card );
-+ }
-+#endif
-+ mmc_notify_add( card );
-+error:
-+ return ret;
-+}
-+
-+void *mmc_register( mmc_reg_type_t reg_type, void *tmpl, size_t extra )
-+{
-+ void *ret = NULL;
-+
-+ switch ( reg_type ) {
-+ case MMC_REG_TYPE_CARD:
-+ ret = mmc_register_card( (mmc_card_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_USER:
-+ ret = mmc_register_user( (mmc_notifier_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_HOST:
-+ ret = mmc_register_controller( (mmc_controller_tmpl_t)tmpl, extra );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "register request for unknown type\n" );
-+ }
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL( mmc_register );
-+
-+static inline void mmc_unregister_user( mmc_notifier_t notifier )
-+{
-+ mmc_notifier_t prev = mmc_notifier;
-+ int found = FALSE;
-+
-+ if ( notifier ) {
-+ down_write( &mmc_notifier_sem );
-+
-+ if ( mmc_notifier == notifier) {
-+ mmc_notifier = prev->next;
-+ found = TRUE;
-+
-+ } else if ( mmc_notifier ) {
-+ while( prev ) {
-+ if ( prev->next == notifier ) {
-+ found = TRUE;
-+ prev->next = prev->next->next;
-+ break;
-+ }
-+ prev = prev->next;
-+ }
-+ }
-+
-+ if ( found ) {
-+ if ( notifier->remove ) {
-+ int i;
-+
-+ down_read( &mmc_controller_sem );
-+ for ( i = 0; i < mmc_ncontrollers; i++ ) {
-+ mmc_controller_t ctrlr =
-+ mmc_controller[i];
-+
-+ down_read( &ctrlr->update_sem );
-+ __mmc_card_stack_foreach( &ctrlr->stack, notifier->remove, FALSE );
-+ up_read( &ctrlr->update_sem );
-+ }
-+ up_read( &mmc_controller_sem );
-+ }
-+ }
-+
-+ up_write( &mmc_notifier_sem );
-+ }
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static inline void mmc_unregister_controller( mmc_controller_t ctrlr )
-+{
-+ if ( !ctrlr || (mmc_controller[ctrlr->slot] != ctrlr ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad unregister request\n" );
-+ goto error;
-+ }
-+
-+ down_write( &mmc_controller_sem );
-+
-+/* notify users */
-+ if ( ctrlr->stack.ncards > 0 ) {
-+ int slot;
-+
-+ down_read( &mmc_notifier_sem );
-+ if ( (slot = __mmc_card_stack_foreach( &ctrlr->stack, mmc_notify_remove, FALSE ) ) )
-+ MMC_ERROR( "device remove notification failed at slot %d\n", -slot );
-+ up_read( &mmc_notifier_sem );
-+ }
-+
-+#ifdef CONFIG_PROC_FS
-+ if ( ctrlr->proc )
-+ remove_proc_entry( ctrlr->proc_name, mmc_proc_dir );
-+#endif
-+
-+ if ( ctrlr->tmpl && ctrlr->tmpl->remove )
-+ ctrlr->tmpl->remove( ctrlr );
-+
-+ mmc_controller[ctrlr->slot] = NULL;
-+ --mmc_ncontrollers;
-+
-+ __mmc_free_controller( ctrlr );
-+
-+ up_write( &mmc_controller_sem );
-+ MOD_DEC_USE_COUNT;
-+error:
-+ return;
-+}
-+
-+void mmc_unregister( mmc_reg_type_t reg_type, void *tmpl )
-+{
-+ switch ( reg_type ) {
-+ case MMC_REG_TYPE_USER:
-+ mmc_unregister_user( (mmc_notifier_t)tmpl );
-+ break;
-+
-+ case MMC_REG_TYPE_HOST:
-+ mmc_unregister_controller( (mmc_controller_t)tmpl );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "unregister request for unknown type\n" );
-+ }
-+}
-+EXPORT_SYMBOL( mmc_unregister );
-+
-+#ifdef CONFIG_PM
-+/* power management support */
-+static int mmc_pm_callback( struct pm_dev *pmdev, pm_request_t pmreq, void *pmdata )
-+{
-+ int ret = -EINVAL;
-+ mmc_controller_t ctrlr;
-+ int i;
-+
-+ __ENTER( "pmreq=%d", pmreq );
-+
-+ down_read( &mmc_controller_sem );
-+
-+ switch ( pmreq ) {
-+ case PM_SUSPEND:
-+ for ( ret = 0, i = 0; !ret && (i < mmc_ncontrollers); i++ ) {
-+ ctrlr = mmc_controller[i];
-+ if ( ctrlr->tmpl->suspend )
-+ ret = ctrlr->tmpl->suspend( ctrlr );
-+ }
-+ if ( !ret )
-+ break;
-+
-+ case PM_RESUME:
-+ for ( i = mmc_ncontrollers - 1; i >= 0; i-- ) {
-+ ctrlr = mmc_controller[i];
-+ if ( ctrlr->tmpl->resume )
-+ ctrlr->tmpl->resume( ctrlr );
-+ }
-+ ret = 0;
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "unsupported PM request %d\n",
-+ pmreq );
-+ }
-+
-+ up_read( &mmc_controller_sem );
-+/* error: */
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+#endif
-+
-+/* kernel module stuff */
-+static int __init mmc_core_module_init( void )
-+{
-+ int ret = -ENODEV;
-+
-+ memset( &mmc_controller, 0, sizeof( mmc_controller ) );
-+
-+ init_rwsem( &mmc_controller_sem );
-+ init_rwsem( &mmc_notifier_sem );
-+#ifdef CONFIG_PM
-+ if ( !(mmc_pm_dev = pm_register( PM_UNKNOWN_DEV, 0, mmc_pm_callback )) ) MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register PM callback\n" );
-+#endif
-+#ifdef CONFIG_PROC_FS
-+ mmc_proc_dir = proc_mkdir( "mmc", NULL );
-+#endif
-+ ret = 0;
-+/* error: */
-+ return ret;
-+}
-+
-+static void __exit mmc_core_module_cleanup( void )
-+{
-+#ifdef CONFIG_PROC_FS
-+ if ( mmc_proc_dir )
-+ remove_proc_entry( "mmc", NULL );
-+#endif
-+#ifdef CONFIG_PM
-+ pm_unregister( mmc_pm_dev );
-+#endif
-+}
-+
-+module_init( mmc_core_module_init );
-+module_exit( mmc_core_module_cleanup );
-+
-+MODULE_LICENSE( "GPL" );
-+
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc_pxa.c
-@@ -0,0 +1,1902 @@
-+/*
-+ * linux/drivers/mmc/mmc_pxa.c
-+ * driver for Cotulla MMC controller
-+ *
-+ * Authors: Vladimir Shebordaev, Igor Oblakov
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_pxa.c,v 0.3.1.12 2002/09/25 19:25:48 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/dma.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+#include "mmc_pxa.h"
-+
-+static mmc_controller_t host = NULL;
-+
-+/* service routines */
-+static inline int pxa_mmc_check_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( hostdata->state != state ) {
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "state (%s vs %s)\n", PXA_MMC_STATE_LABEL( hostdata->state ), PXA_MMC_STATE_LABEL( state ) );
-+ goto error;
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline void pxa_mmc_set_state( mmc_controller_t ctrlr, pxa_mmc_state_t state )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ hostdata->state = state;
-+}
-+
-+static inline int pxa_mmc_init_completion( mmc_controller_t ctrlr, u32 mask )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( xchg( &hostdata->busy, 1 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "another interrupt "
-+ "is already been expected\n" );
-+ goto error;
-+ }
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ hostdata->irqcnt = 1000;
-+#endif
-+ init_completion( &hostdata->completion );
-+
-+ MMC_I_MASK = MMC_I_MASK_ALL & ~mask;
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+static struct timer_list timer;
-+static void wait_timeo( unsigned long arg ) {
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)arg;
-+ hostdata->timeo = 1;
-+ complete( &hostdata->completion );
-+ return;
-+}
-+#endif
-+
-+static inline int pxa_mmc_wait_for_completion( mmc_controller_t ctrlr, u32 mask )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( !xchg( &hostdata->busy, 1 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "there were no "
-+ "interrupt awaited for\n" );
-+ goto error;
-+ }
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ hostdata->timeo = 0;
-+ del_timer( &timer );
-+ timer.function = wait_timeo;
-+ timer.expires = jiffies + 1UL*HZ;
-+ timer.data = (unsigned long)hostdata;
-+ add_timer( &timer );
-+#endif
-+ wait_for_completion( &hostdata->completion );
-+#if CONFIG_MMC_DEBUG_IRQ
-+ del_timer( &timer );
-+ if ( hostdata->timeo ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "irq timed out: " "mask=%x stat=%x\n", mask, MMC_STAT );
-+ goto error;
-+ }
-+#endif
-+ /* verify interrupt */
-+ if ( (mask == ~0UL) || !( hostdata->mmc_i_reg & ~mask ) )
-+ ret = 0;
-+
-+error:
-+ xchg( &hostdata->busy, 0 );
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_stop_bus_clock( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+
-+ if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_CLK_OFF ) )
-+ goto out;
-+
-+ if ( !pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "BUFFER_IN_TRANSIT\n" );
-+ goto error;
-+ }
-+
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_CLK_IS_OFF ) )
-+ goto error;
-+
-+ MMC_STRPCL = MMC_STRPCL_STOP_CLK;
-+
-+ if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_CLK_IS_OFF ) )
-+ goto error;
-+
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is off\n" );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_CLK_OFF );
-+out:
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_start_bus_clock( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
-+ && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n", PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ MMC_STRPCL = MMC_STRPCL_START_CLK;
-+ wmb();
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "clock is on\n" );
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/*
-+int pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t response )
-+
-+Effects: initializes completion to wait for END_CMD_RES intr,
-+ waits for intr to occur, checks controller and card status
-+Requiers: controller is in CLK_OFF state
-+Modifies: moves controller to the END_CMD state
-+Returns:
-+*/
-+static mmc_error_t pxa_mmc_complete_cmd( mmc_controller_t ctrlr, mmc_response_fmt_t format, int send_abort )
-+{
-+ mmc_error_t ret = MMC_ERROR_GENERIC;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ int mask, nwords;
-+ u32 status;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD%d(0x%04x%04x)\n", MMC_CMD & 0x3f, MMC_ARGH, MMC_ARGL);
-+
-+/* FIXME: check arguments */
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_CLK_OFF)
-+ && (hostdata->state != PXA_MMC_FSM_END_IO) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "illegal state %s\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ mask = MMC_I_MASK_END_CMD_RES;
-+ if ( pxa_mmc_init_completion( ctrlr, mask ) )
-+ goto error;
-+
-+ MMC_PRTBUF = MMC_PRTBUF_BUF_FULL;
-+/* start the clock */
-+ if ( pxa_mmc_start_bus_clock( ctrlr ) )
-+ goto error;
-+
-+/* wait for END_CMD_RES intr */
-+ if ( pxa_mmc_wait_for_completion( ctrlr, MMC_I_REG_END_CMD_RES ) )
-+ goto error;
-+
-+/* check status */
-+ if ( hostdata->mmc_stat & MMC_STAT_TIME_OUT_RESPONSE ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response timeout\n");
-+ ret = MMC_ERROR_TIME_OUT_RESPONSE;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_READ_TIME_OUT ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read timeout\n");
-+ ret = MMC_ERROR_READ_TIME_OUT;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_RES_CRC_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "response crc err\n");
-+ ret = MMC_ERROR_RES_CRC_ERROR;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_CRC_READ_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "read crc err\n");
-+ ret = MMC_ERROR_CRC_READ_ERROR;
-+ goto error;
-+
-+ } else if ( hostdata->mmc_stat & MMC_STAT_CRC_WRITE_ERROR ) {
-+ // MMC_DEBUG(MMC_DEBUG_LEVEL3, "write crc err\n");
-+ ret = MMC_ERROR_CRC_WRITE_ERROR;
-+ goto error;
-+ }
-+
-+ nwords = (format == MMC_NORESPONSE) ? 0 :
-+ (format == MMC_R1) ? 3 :
-+ (format == MMC_R2) ? 8 :
-+ (format == MMC_R3) ? 3 :
-+ -1;
-+ ret = nwords;
-+ if ( nwords > 0 ) {
-+ register int i;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "nwords=%d\n", nwords );
-+ for ( i = nwords - 1; i >= 0 ; i-- ) {
-+ u32 res = MMC_RES;
-+ int ibase = i<<1;
-+
-+ hostdata->mmc_res[ibase] = ((u8 *)&res)[0];
-+ hostdata->mmc_res[ibase + 1] = ((u8 *)&res)[1];
-+ --ret;
-+ }
-+#ifdef CONFIG_MMC_DEBUG
-+ switch ( format ) {
-+ case MMC_R1:
-+ MMC_DUMP_R1( ctrlr );
-+ break;
-+ case MMC_R2:
-+ MMC_DUMP_R2( ctrlr );
-+ break;
-+ case MMC_R3:
-+ MMC_DUMP_R3( ctrlr );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "unknown response format\n" );
-+ ret = MMC_ERROR_GENERIC;
-+ goto error;
-+ }
-+#endif
-+
-+/* check card status for R1(b) commands */
-+ if ( format == MMC_R1 ) {
-+ u8 cmd;
-+
-+ ((u8 *)&status)[0] = hostdata->mmc_res[1];
-+ ((u8 *)&status)[1] = hostdata->mmc_res[2];
-+ ((u8 *)&status)[2] = hostdata->mmc_res[3];
-+ ((u8 *)&status)[3] = hostdata->mmc_res[4];
-+ cmd = PXA_MMC_RESPONSE( ctrlr, 5 )&0x3f;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ //printk( KERN_INFO __FUNCTION__"(): "
-+ "cmd=%u status: 0x%08x\n",
-+ cmd, status );
-+ switch ( cmd ) {
-+ case 11:
-+ case 18:
-+ case 20:
-+ case 25:
-+ if ( !(status & 0x00000100) ) /* FIXME */
-+ goto mmc_error;
-+ default:
-+ break;
-+ }
-+ if ( status & MMC_CARD_STATUS_OUT_OF_RANGE ) {
-+ ret = MMC_ERROR_OUT_OF_RANGE;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ADDRESS_ERROR ) {
-+ ret = MMC_ERROR_ADDRESS_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_BLOCK_LEN_ERROR ) {
-+ ret = MMC_ERROR_ADDRESS_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_SEQ_ERROR ) {
-+ ret = MMC_ERROR_ERASE_SEQ_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_PARAM ) {
-+ ret = MMC_ERROR_ERASE_PARAM;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_WP_VIOLATION ) {
-+ ret = MMC_ERROR_WP_VIOLATION;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CARD_IS_LOCKED ) {
-+ ret = MMC_ERROR_CARD_IS_LOCKED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_LOCK_UNLOCK_FAILED ) {
-+ ret = MMC_ERROR_LOCK_UNLOCK_FAILED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_COM_CRC_ERROR ) {
-+ ret = MMC_ERROR_COM_CRC_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ILLEGAL_COMMAND ) {
-+ ret = MMC_ERROR_ILLEGAL_COMMAND;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CARD_ECC_FAILED ) {
-+ ret = MMC_ERROR_CARD_ECC_FAILED;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CC_ERROR ) {
-+ ret = MMC_ERROR_CC_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERROR ) {
-+ ret = MMC_ERROR_ERROR;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_UNDERRUN ) {
-+ ret = MMC_ERROR_UNDERRUN;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_OVERRUN ) {
-+ ret = MMC_ERROR_OVERRUN;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_CID_CSD_OVERWRITE ) {
-+ ret = MMC_ERROR_CID_CSD_OVERWRITE;
-+ goto mmc_error;
-+ } else if ( status & MMC_CARD_STATUS_ERASE_RESET ) {
-+ ret = MMC_ERROR_ERASE_RESET;
-+ goto mmc_error;
-+ }
-+ }
-+ }
-+
-+ if ( ret >= 0 )
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_CMD );
-+ goto out;
-+mmc_error:
-+#if 1
-+ if ( send_abort ) {
-+ /* send CMD12 to abort failed transfer */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ ret = -EIO;
-+ goto error;
-+ }
-+#endif
-+error:
-+ /* move controller to the IDLE state */
-+ pxa_mmc_stop_bus_clock( ctrlr );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+out:
-+ return ret;
-+}
-+
-+/*
-+int pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t cmd, mmc_dir_t dir, mmc_transfer_mode_t mode )
-+
-+Effects: finilizes data transfer request
-+Reqires: controller is in the END_BUFFER state
-+Modifies: moves controller to the IDLE state
-+Returns: zero upon success or error condition code otherwise
-+ */
-+static mmc_error_t pxa_mmc_complete_io( mmc_controller_t ctrlr, mmc_dir_t dir, mmc_transfer_mode_t mode )
-+{
-+ int ret = MMC_ERROR_GENERIC;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_IO ) )
-+ goto error;
-+
-+ switch ( mode ) {
-+ case MMC_TRANSFER_MODE_STREAM: /* FIXME */
-+ if ( dir == MMC_WRITE ) {
-+ /* 1. wait for STOP_CMD intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_STOP_CMD )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_STOP_CMD )) )
-+ goto error;
-+ }
-+ /* 2. send CMD12 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+ if ( dir == MMC_WRITE )
-+ MMC_CMDAT |= MMC_CMDAT_BUSY;
-+
-+ /* 3. wait for CMD12 to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "ready for CMD12\n" );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ /* 4. wait for DATA_TRAN_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 5. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ /* 1. wait for DATA_TRAN done intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ /* 2. send CMD12 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(12); /* STOP_TRANSMISSION */
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+ if ( dir == MMC_WRITE )
-+ MMC_CMDAT |= MMC_CMDAT_BUSY;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD12\n" );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 3. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ /* 1. wait for DATA_TRAN_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_DATA_TRAN_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_DATA_TRAN_DONE )) )
-+ goto error;
-+
-+ if ( dir == MMC_WRITE ) {
-+ /* 2. wait for PRG_DONE intr */
-+ if ( (ret = pxa_mmc_init_completion( ctrlr,
-+ MMC_I_MASK_PRG_DONE )) )
-+ goto error;
-+ if ( (ret = pxa_mmc_wait_for_completion( ctrlr,
-+ MMC_I_REG_PRG_DONE )) )
-+ goto error;
-+ }
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown transfer mode\n" );
-+ goto error;
-+ }
-+/* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_update_acq( mmc_controller_t ctrlr )
-+{
-+ int ret = -EINVAL;
-+ pxa_mmc_hostdata_t hostdata = NULL;
-+ mmc_card_t card = NULL;
-+ mmc_card_stack_rec_t fake;
-+ mmc_card_stack_t stack = &fake;
-+ u16 argl = 0U, argh = 0U;
-+ int ncards = 0;
-+
-+ if ( !ctrlr )
-+ goto error;
-+
-+ hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ __mmc_card_stack_init( stack );
-+
-+ /* max open-drain mode frequency is 400kHZ */
-+ MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
-+ MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
-+
-+ /* discover and add cards to the stack */
-+ /* I. bus operation condition setup */
-+ /* 1) send CMD1 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ argl = 0x0000;
-+ argh = 0x0004;
-+
-+ MMC_CMD = CMD(1);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+
-+ MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
-+ if ( !ret ) {
-+ argh = (PXA_MMC_RESPONSE( ctrlr, 4 ) << 8)
-+ | PXA_MMC_RESPONSE( ctrlr, 3 );
-+ argl = (PXA_MMC_RESPONSE( ctrlr, 2 ) << 8)
-+ | PXA_MMC_RESPONSE( ctrlr, 1 );
-+
-+ } else if ( ret != MMC_ERROR_TIME_OUT_RESPONSE )
-+ goto err_free;
-+
-+ if ( !argh && !argl ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "assuming full voltage range support\n" );
-+ argh = 0x00ff;
-+ argl = 0xff00;
-+ }
-+
-+ /* 2) continuously send CMD1 'till there're busy cards */
-+ for(;;) {
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(1);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+
-+ MMC_CMDAT = MMC_CMDAT_BUSY|MMC_CMDAT_R3;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD1(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R3, FALSE );
-+ if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
-+ break;
-+
-+ else if ( !ret ) {
-+ /* busy state reported by LOW signal level
-+ * (MMC v3.2, p.58)
-+ *
-+ * Thanks to Alexander Samoutin :)
-+ */
-+ if ( !(PXA_MMC_RESPONSE( ctrlr, 4 ) & 0x80) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "busy state reported\n");
-+ udelay( 20 );
-+ continue;
-+ } else
-+ break;
-+ } else
-+ goto err_free;
-+ }
-+
-+/* II. card identification: the cards in Ready state
-+ * are the only expected to respond
-+ */
-+ for (;;) {
-+ argh = 0U;
-+ argl = 0U;
-+
-+ /* 1) send CMD2 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(2);
-+ MMC_ARGH = 0x0003;
-+ MMC_ARGL = 0xf300;
-+ MMC_CMDAT = MMC_CMDAT_R2;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD2(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE );
-+ if ( ret == MMC_ERROR_TIME_OUT_RESPONSE )
-+ break;
-+
-+ else if ( ret ) /* bus error */
-+ goto err_free;
-+
-+ /* TODO: store CID for the card */
-+
-+ /* 2) assign RCA */
-+ if ( !++ctrlr->rca_next ) /* overflow */
-+ ++ctrlr->rca_next;
-+ argh = ctrlr->rca_next;
-+
-+ /* 3) send it to the card last responded (CMD3) */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(3);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD3(0x%04x%04x)\n", argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
-+ if ( ret ) /* CMD3 failed */
-+ goto err_free;
-+
-+ card = __mmc_card_alloc( sizeof( pxa_mmc_card_data_rec_t ) );
-+ if ( !card ) {
-+ MMC_ERROR( "out of memory\n" );
-+ goto err_free;
-+ }
-+
-+ card->info.rca = argh;
-+ card->slot = ctrlr->slot_next++; /* FIXME: minor encoding */
-+ card->ctrlr = ctrlr;
-+
-+ if ( !__mmc_card_stack_add( stack, card ) )
-+ goto err_free;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "added card: "
-+ "slot %d, RCA=0x%04x\n", card->slot, argh );
-+ ++ncards;
-+ }
-+
-+ if ( ncards ) {
-+/* III. read CSD registers of all cards; DSR support also reported there */
-+ for ( card = stack->first; card; card = card->next ) {
-+ pxa_mmc_card_data_t card_data =
-+ (pxa_mmc_card_data_t)card->card_data;
-+
-+ /* 1) send CMD9 */
-+ argh = card->info.rca;
-+ argl = 0U;
-+
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ MMC_CMD = CMD(9);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R2;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "CMD9(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R2, FALSE )) )
-+ goto err_free;
-+
-+ memcpy( &card->info.csd, hostdata->mmc_res, 15 );
-+ MMC_DUMP_CSD( card );
-+
-+ card->info.read_bl_len = (1<<card->info.csd.read_bl_len);
-+ card->info.write_bl_len = (1<<card->info.csd.write_bl_len);
-+ card->info.capacity = (card->info.csd.c_size + 1)
-+ * (1<<(card->info.csd.c_size_mult + 2))
-+ * card->info.read_bl_len;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "card capacity=%dMb\n",
-+ card->info.capacity>>20 );
-+ card->info.tran_speed = 20*1024; /* FIXME */
-+ card->info.transfer_mode = MMC_TRANSFER_MODE_BLOCK_SINGLE;
-+ /* 2) set bus operation freq */
-+ card_data->clkrt = pxa_mmc_clkrt( card->info.tran_speed );
-+ /* 3) register card with MMC core */
-+ mmc_register( MMC_REG_TYPE_CARD, card, 0 );
-+ }
-+/* IV. set DSR registers of the cards */
-+#if 0 /* TODO */
-+ if ( card->info.csd.dsr_imp ) {
-+ set_dsr = TRUE;
-+ /* calculate DSR */
-+ }
-+#endif
-+ }
-+#if 0 /* TODO */
-+ if ( set_dsr ) {
-+ /* send CMD4 */
-+ }
-+#endif
-+/* merge list of the newly inserted cards into controller card stack */
-+ if ( !ctrlr->stack.ncards ) {
-+ ctrlr->stack.first = stack->first;
-+ ctrlr->stack.last = stack->last;
-+ } else
-+ ctrlr->stack.last->next = stack->first;
-+
-+ ctrlr->stack.ncards += stack->ncards;
-+
-+ ret = 0;
-+ goto out;
-+err_free:
-+ __mmc_card_stack_free( stack );
-+error:
-+out:
-+ return ret;
-+}
-+
-+/* MMC protocol macros: v3.4, p.120 */
-+static int pxa_mmc_init_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -EIO;
-+ u16 argl = 0U, argh = 0U;
-+
-+ if ( !ctrlr || ctrlr->stack.ncards ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ /* initialize stack */
-+ /* 1) send CMD0 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ /* max open-drain mode frequency is 400kHZ */
-+ MMC_CLKRT = MMC_CLKRT_0_3125MHZ;
-+ MMC_RESTO = MMC_RES_TO_MAX; /* set response timeout */
-+ MMC_SPI = MMC_SPI_DISABLE;
-+
-+ MMC_CMD = CMD(0); /* CMD0 with zero argument */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_INIT;
-+
-+ //MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE, FALSE )) )
-+ goto error;
-+
-+ /* update card stack */
-+ if ( (ret = pxa_mmc_update_acq( ctrlr )) )
-+ goto err_free;
-+
-+ /* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto err_free;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "ncards=%d\n", ctrlr->stack.ncards );
-+ goto out;
-+
-+err_free:
-+ __mmc_card_stack_free( &ctrlr->stack );
-+error:
-+out:
-+ return ret;
-+}
-+
-+static int pxa_mmc_check_card_stack( mmc_controller_t ctrlr )
-+{
-+ int ret = -1;
-+ mmc_card_t card;
-+
-+ if ( !ctrlr )
-+ goto error;
-+
-+ if ( ctrlr->stack.ncards > 0 ) {
-+/* for each card in the stack: */
-+ for( card = ctrlr->stack.first; card; card = card->next ) {
-+ u16 argh = card->info.rca;
-+ u16 argl = 0UL;
-+
-+/* 1) send CMD9( card->rca ) */
-+ if ( pxa_mmc_stop_bus_clock( ctrlr ) )
-+ goto error;
-+
-+ /* SanDisk's cards do not respond to CMD9 */
-+ MMC_CMD = CMD(13);
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD13(0x%04x%04x)\n",
-+ argh, argl );
-+ ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE );
-+/* 2) if card responded, it is still there */
-+ if ( ret )
-+ card->state = MMC_CARD_STATE_UNPLUGGED;
-+ }
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure links the bus master with a single card
-+ * 1) cross checks with the internal stack management data if a card still
-+ * exists in the slot
-+ * 2) send CMD7( card->public.rca )
-+ * 3) setup data path and controller options
-+ */
-+static int pxa_mmc_setup_card( mmc_controller_t ctrlr, mmc_card_t card )
-+{
-+ int ret = -ENODEV;
-+ pxa_mmc_hostdata_t hostdata;
-+ pxa_mmc_card_data_t card_data;
-+ u16 argh = 0U;
-+#ifdef CONFIG_MMC_DEBUG
-+ u16 argl = 0U;
-+#endif
-+
-+ if ( !ctrlr || !card ) {
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ if ( card->ctrlr != ctrlr ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "card is on another bus\n" );
-+ goto error;
-+ }
-+
-+ hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ card_data = (pxa_mmc_card_data_t)card->card_data;
-+
-+ argh = card->info.rca;
-+
-+/* select requested card */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(7);
-+ MMC_ARGH = argh;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD7(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* set controller options */
-+#ifndef CONFIG_MMC_DEBUG
-+ MMC_CLKRT = card_data->clkrt;
-+#endif
-+/* move the controller to the IDLE state */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_IDLE );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static inline int pxa_mmc_iobuf_init( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+#ifdef PIO
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#endif
-+#ifndef PIO
-+/* TODO */
-+#else
-+ hostdata->iobuf.buf.pos = hostdata->iobuf.iodata;
-+ hostdata->iobuf.buf.cnt = cnt;
-+#endif
-+ return 0;
-+}
-+/* TODO: ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+effects: reads at most cnt bytes from the card to the controller I/O buffer;
-+ takes care of partial data transfers
-+requieres:
-+modifies: ctrlr->iobuf
-+returns: number of bytes actually transferred or negative error code if there were any errors
-+ */
-+ssize_t pxa_mmc_read_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int ndesc;
-+ int chan = hostdata->iobuf.buf.chan;
-+ pxa_dma_desc *desc;
-+#endif
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_END_CMD) && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
-+ goto error;
-+ }
-+
-+ if ( cnt > hostdata->iobuf.bufsz )
-+ cnt = hostdata->iobuf.bufsz;
-+
-+ if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
-+#ifndef PIO
-+ if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
-+ goto error;
-+
-+ if ( (desc = hostdata->iobuf.buf.last_read_desc) ) {
-+ desc->ddadr &= ~DDADR_STOP;
-+ desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
-+ desc->dcmd |= (1<<5);
-+ }
-+/* 1) setup descriptors for DMA transfer from the device */
-+ ndesc = (cnt>>5) - 1; /* FIXME: partial read */
-+ desc = &hostdata->iobuf.buf.read_desc[ndesc];
-+ hostdata->iobuf.buf.last_read_desc = desc;
-+ /* TODO: partial read */
-+ desc->ddadr |= DDADR_STOP;
-+ desc->dcmd |= DCMD_ENDIRQEN;
-+/* 2) start DMA channel */
-+ DDADR( chan ) = hostdata->iobuf.buf.read_desc_phys_addr;
-+ DCSR( chan ) |= DCSR_RUN;
-+#else
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_RXFIFO_RD_REQ ) )
-+ goto error;
-+#endif
-+
-+ if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
-+ goto error;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
-+ goto error;
-+
-+ if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+ssize_t pxa_mmc_write_buffer( mmc_controller_t ctrlr, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int ndesc;
-+ int chan = hostdata->iobuf.buf.chan;
-+ pxa_dma_desc *desc;
-+#endif
-+
-+ if ( (hostdata->state != PXA_MMC_FSM_END_CMD)
-+ && (hostdata->state != PXA_MMC_FSM_END_BUFFER) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state (%s)\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+ goto error;
-+ }
-+
-+ if ( cnt > hostdata->iobuf.bufsz )
-+ cnt = hostdata->iobuf.bufsz;
-+
-+ if ( (ret = pxa_mmc_iobuf_init( ctrlr, cnt )) )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_BUFFER_IN_TRANSIT );
-+#ifndef PIO
-+ if ( pxa_mmc_init_completion( ctrlr, ~MMC_I_MASK_ALL ) ) /* FIXME */
-+ goto error;
-+ if ( (desc = hostdata->iobuf.buf.last_write_desc) ) {
-+ desc->ddadr &= ~DDADR_STOP;
-+ desc->dcmd &= ~(DCMD_ENDIRQEN|DCMD_LENGTH);
-+ desc->dcmd |= (1<<5);
-+ }
-+/* 1) setup descriptors for DMA transfer to the device */
-+ ndesc = (cnt>>5) - 1; /* FIXME: partial write */
-+ desc = &hostdata->iobuf.buf.write_desc[ndesc];
-+ /* TODO: partial write */
-+ hostdata->iobuf.buf.last_write_desc = desc;
-+ desc->ddadr |= DDADR_STOP;
-+ desc->dcmd |= DCMD_ENDIRQEN;
-+/* 2) start DMA channel */
-+ DDADR( chan ) = hostdata->iobuf.buf.write_desc_phys_addr;
-+ DCSR( chan ) |= DCSR_RUN;
-+#else
-+ if ( pxa_mmc_init_completion( ctrlr, MMC_I_MASK_TXFIFO_WR_REQ ) )
-+ goto error;
-+#endif
-+ if ( pxa_mmc_wait_for_completion( ctrlr, ~0UL ) )
-+ goto error;
-+
-+ if ( pxa_mmc_check_state( ctrlr, PXA_MMC_FSM_END_BUFFER ) )
-+ goto error;
-+
-+ if ( !(hostdata->mmc_stat & MMC_STAT_ERRORS) ) /* FIXME */
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+/* TODO: ssize_t pxa_mmc_copy_from_buffer( ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+effects: copies at most cnt bytes from the controller I/O buffer to the user or kernel buffer
-+ pointed by buf
-+requiers:
-+modifies:
-+returns: number of bytes actually transferred or negative error code if there were any errors
-+ */
-+ssize_t pxa_mmc_copy_from_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+#ifndef PIO
-+/* TODO: check that DMA channel is not running */
-+#endif
-+ switch ( to ) {
-+ case MMC_USER:
-+ if ( copy_to_user( buf, hostdata->iobuf.iodata, cnt ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ break;
-+ case MMC_KERNEL:
-+ memcpy( buf, hostdata->iobuf.iodata, cnt );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
-+ goto error;
-+ }
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+ssize_t pxa_mmc_copy_to_buffer( mmc_controller_t ctrlr, mmc_buftype_t to, char *buf, ssize_t cnt )
-+{
-+ ssize_t ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+/* check that DMA channel is not running */
-+#endif
-+ switch ( to ) {
-+ case MMC_USER:
-+ if ( copy_from_user( hostdata->iobuf.iodata, buf, cnt ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ break;
-+ case MMC_KERNEL:
-+ memcpy( hostdata->iobuf.iodata, buf, cnt );
-+ break;
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unknown buffer type\n" );
-+ goto error;
-+ }
-+ ret = cnt;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally passes the data from the user buffer to the card */
-+static int pxa_mmc_stream_read( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u16 argh = 0UL, argl = 0UL;
-+ ssize_t size = 0;
-+
-+ while ( transfer->cnt > 0 ) {
-+ size = (transfer->cnt < hostdata->iobuf.blksz) ?
-+ transfer->cnt : hostdata->iobuf.blksz;
-+ /* 1. send CMD11 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ /* 2. setup controller registers to start stream data transfer */
-+ MMC_CMD = CMD(11); /* READ_DAT_UNTIL_STOP */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = 0xffff;
-+ MMC_BLKLEN = size;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+ /* 3. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD11(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+ /* 4. transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, size )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->addr += ret;
-+ transfer->cnt -= ret;
-+ }
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure reads a data block from a card at a given kernel address */
-+static int pxa_mmc_read_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -ENODEV;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+/* CMD17 (READ_SINGLE_BLOCK) */
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(17); /* READ_SINGLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+ MMC_NOB = 1;
-+ MMC_BLKLEN = transfer->blksz;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD17(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->blksz )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ transfer->nob -= 1;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally reads data blocks from
-+ * a card to the user buffer. Controller options and block size
-+ * are already set by setup_card(). Data alignment and partial
-+ * data accessibility assumed to be checked by mmc_core */
-+static int pxa_mmc_read_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start multiple block transfer */
-+ MMC_CMD = CMD(18); /* READ_MULTIPLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = transfer->nob;
-+ MMC_BLKLEN = transfer->blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_READ|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. start clock */
-+ if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 4. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD18(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 6. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ if ( (ret = pxa_mmc_read_buffer( ctrlr, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_copy_from_buffer( ctrlr, transfer->type, transfer->buf, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* Sequentally writes the data from a user buffer to the card */
-+static int pxa_mmc_stream_write( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u16 argh = 0UL, argl = 0UL;
-+ ssize_t size = 0;
-+
-+ __ENTER( "transfer: cmd=%d mode=%d type=%d blksz=%d "
-+ "nob=%d buf=%p cnt=%d addr=%Lx", transfer->cmd,
-+ transfer->mode, transfer->type, transfer->blksz,
-+ transfer->nob, transfer->buf, transfer->cnt, transfer->addr );
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start stream data transfer */
-+ MMC_CMD = CMD(20); /* WRITE_DAT_UNTIL_STOP */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = 0xffff;
-+ MMC_BLKLEN = hostdata->iobuf.blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_STREAM|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD20(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 4. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ size = (transfer->cnt < hostdata->iobuf.blksz) ?
-+ transfer->cnt : hostdata->iobuf.blksz;
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr,
-+ transfer->type, transfer->buf, size )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure writes a data block to a card at a given address */
-+static int pxa_mmc_write_block( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -ENODEV;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.read_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+/* CMD17 (READ_SINGLE_BLOCK) */
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(24); /* WRITE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+ MMC_NOB = 1;
-+ MMC_BLKLEN = transfer->blksz;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD24(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+
-+/* transfer the data to the caller supplied buffer */
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type, transfer->buf, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ transfer->nob -= 1;
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+/* This procedure sequentally writes data blocks to a card at a given address */
-+static ssize_t pxa_mmc_write_mblock( mmc_controller_t ctrlr, mmc_data_transfer_req_t transfer )
-+{
-+ int ret = -EIO;
-+ u16 argh = 0UL, argl = 0UL;
-+
-+/* send CMD16 (SET_BLOCK_LEN) when requested block size is not the default
-+ * for the current card */
-+ if ( transfer->blksz != ctrlr->stack.selected->info.write_bl_len ) {
-+ argh = transfer->blksz >> 16;
-+ argl = transfer->blksz;
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(16); /* SET_BLOCK_LEN */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_CMDAT = MMC_CMDAT_R1;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD16(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, FALSE )) )
-+ goto error;
-+ }
-+
-+ argh = transfer->addr >> 16;
-+ argl = transfer->addr;
-+/* 1. stop bus clock */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 2. setup controller registers to start multiple block transfer */
-+ MMC_CMD = CMD(25); /* WRITE_MULTIPLE_BLOCK */
-+ MMC_ARGH = argh;
-+ MMC_ARGL = argl;
-+ MMC_NOB = transfer->nob;
-+ MMC_BLKLEN = transfer->blksz;
-+ MMC_CMDAT = MMC_CMDAT_R1|MMC_CMDAT_WRITE|MMC_CMDAT_BLOCK|MMC_CMDAT_DATA_EN;
-+#ifndef PIO
-+ MMC_CMDAT |= MMC_CMDAT_MMC_DMA_EN;
-+#endif
-+
-+/* 3. start clock */
-+ if ( (ret = pxa_mmc_start_bus_clock( ctrlr )) )
-+ goto error;
-+
-+/* 4. wait for cmd to complete */
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD25(0x%04x%04x)\n", argh, argl );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_R1, TRUE )) )
-+ goto error;
-+
-+/* 6. transfer the data to the caller supplied buffer */
-+ while ( transfer->cnt > 0 ) {
-+ if ( (ret = pxa_mmc_copy_to_buffer( ctrlr, transfer->type,
-+ transfer->buf, transfer->cnt )) < 0 )
-+ goto error;
-+
-+ if ( (ret = pxa_mmc_write_buffer( ctrlr, ret )) < 0 )
-+ goto error;
-+
-+ transfer->buf += ret;
-+ transfer->cnt -= ret;
-+ }
-+
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_IO );
-+
-+ if ( (ret = pxa_mmc_complete_io( ctrlr, transfer->cmd, transfer->mode )) )
-+ goto error;
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void pxa_mmc_irq( int irq, void *dev_id, struct pt_regs *regs )
-+{
-+ mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifdef PIO
-+ register int i, cnt;
-+ register char *buf;
-+#endif
-+
-+ hostdata->mmc_i_reg = MMC_I_REG;
-+ hostdata->mmc_stat = MMC_STAT;
-+ hostdata->mmc_cmdat = MMC_CMDAT;
-+#if 0
-+ if (hostdata->mmc_i_reg != 0x0010) {
-+ printk("IREG %08x", hostdata->mmc_i_reg);
-+ if (hostdata->mmc_i_reg & 0x0001) printk(" DATA_TRAN_DONE");
-+ if (hostdata->mmc_i_reg & 0x0002) printk(" PRG_DONE");
-+ if (hostdata->mmc_i_reg & 0x0004) printk(" END_CMD");
-+ if (hostdata->mmc_i_reg & 0x0008) printk(" STOP_CMD");
-+ if (hostdata->mmc_i_reg & 0x0010) printk(" CLK_OFF");
-+ if (hostdata->mmc_i_reg & 0x0020) printk(" RX_FIFO");
-+ if (hostdata->mmc_i_reg & 0x0040) printk(" TX_FIFO");
-+ printk("\nSTAT %08x", hostdata->mmc_stat);
-+ if (hostdata->mmc_stat & 0x0001) printk(" READ_TO");
-+ if (hostdata->mmc_stat & 0x0002) printk(" RESP_TO");
-+ if (hostdata->mmc_stat & 0x0004) printk(" WR_CRC");
-+ if (hostdata->mmc_stat & 0x0008) printk(" READ_CRC");
-+ if (hostdata->mmc_stat & 0x0010) printk(" SPI_RD_TKN");
-+ if (hostdata->mmc_stat & 0x0020) printk(" RESP_CRC");
-+ if (hostdata->mmc_stat & 0x0040) printk(" TX_FIFO");
-+ if (hostdata->mmc_stat & 0x0080) printk(" RX_FIFO");
-+ if (hostdata->mmc_stat & 0x0100) printk(" CLK");
-+ if (hostdata->mmc_stat & 0x0800) printk(" DATA_TRAN_DONE");
-+ if (hostdata->mmc_stat & 0x1000) printk(" PRG_DONE");
-+ if (hostdata->mmc_stat & 0x2000) printk(" END_CMD");
-+ printk("\n");
-+ }
-+#endif
-+
-+#if CONFIG_MMC_DEBUG_IRQ
-+ if ( --hostdata->irqcnt <= 0 ) {
-+ printk( KERN_INFO __FUNCTION__"(): irqcnt exceeded\n" );
-+ goto complete;
-+ }
-+#endif
-+ switch ( hostdata->state ) {
-+ case PXA_MMC_FSM_IDLE:
-+ case PXA_MMC_FSM_CLK_OFF:
-+ case PXA_MMC_FSM_END_IO:
-+ case PXA_MMC_FSM_END_BUFFER:
-+ case PXA_MMC_FSM_END_CMD:
-+ goto complete;
-+#ifdef PIO
-+ case PXA_MMC_FSM_BUFFER_IN_TRANSIT:
-+ if ( hostdata->mmc_stat & MMC_STAT_ERRORS )
-+ goto complete;
-+
-+ buf = hostdata->iobuf.buf.pos;
-+ cnt = (hostdata->iobuf.buf.cnt < 32) ?
-+ hostdata->iobuf.buf.cnt : 32;
-+ if ( hostdata->mmc_cmdat & MMC_CMDAT_WRITE ) {
-+ if ( !(hostdata->mmc_stat & MMC_STAT_XMIT_FIFO_EMPTY) )
-+ break;
-+ for ( i = 0; i < cnt; i++ )
-+ MMC_TXFIFO = *buf++;
-+ if ( cnt < 32 )
-+ MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL;
-+ } else { /* i.e. MMC_CMDAT_READ */
-+ if( !(hostdata->mmc_stat & MMC_STAT_RECV_FIFO_FULL) )
-+ break;
-+ for( i = 0; i < cnt; i++ )
-+ *buf++ = MMC_RXFIFO;
-+ }
-+
-+ hostdata->iobuf.buf.pos = buf;
-+ hostdata->iobuf.buf.cnt -= i;
-+ if ( hostdata->iobuf.buf.cnt <= 0 ) {
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
-+ goto complete;
-+ }
-+ break;
-+#endif /* PIO */
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "unexpected state %d\n",
-+ hostdata->state );
-+ goto complete;
-+ }
-+ return;
-+complete:
-+ MMC_I_MASK = MMC_I_MASK_ALL;
-+ complete( &hostdata->completion );
-+ return;
-+}
-+
-+#ifndef PIO
-+static void pxa_mmc_dma_irq( int irq, void *dev_id, struct pt_regs *regs )
-+{
-+ mmc_controller_t ctrlr = (mmc_controller_t)dev_id;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+ u32 dcsr;
-+ u32 ddadr;
-+ int chan = hostdata->iobuf.buf.chan;
-+
-+ ddadr = DDADR( chan );
-+ dcsr = DCSR( chan );
-+ DCSR( chan ) = dcsr & ~DCSR_STOPIRQEN;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3,
-+ "MMC DMA interrupt: chan=%d ddadr=0x%08x "
-+ "dcmd=0x%08x dcsr=0x%08x\n",
-+ chan, ddadr, DCMD( chan ), dcsr );
-+/* bus error */
-+ if ( dcsr & DCSR_BUSERR ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "bus error on DMA channel %d\n",
-+ chan );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_ERROR );
-+ goto complete;
-+ }
-+/* data transfer completed */
-+ if ( dcsr & DCSR_ENDINTR ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "buffer transferred\n" );
-+ pxa_mmc_set_state( ctrlr, PXA_MMC_FSM_END_BUFFER );
-+ goto complete;
-+ }
-+ return;
-+complete:
-+ complete( &hostdata->completion );
-+ return;
-+}
-+#endif
-+
-+
-+static int pxa_mmc_init( mmc_controller_t ctrlr )
-+{
-+ int ret = -ENODEV;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+#ifndef PIO
-+ register int i;
-+ register pxa_dma_desc *desc;
-+#endif
-+
-+/* hardware initialization */
-+/* I. prepare to transfer data */
-+/* 1. allocate buffer */
-+#ifndef PIO
-+ hostdata->iobuf.buf.read_desc = consistent_alloc( GFP_KERNEL,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ &hostdata->iobuf.buf.read_desc_phys_addr, 0 );
-+ if ( !hostdata->iobuf.buf.read_desc ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ hostdata->iobuf.buf.write_desc = consistent_alloc( GFP_KERNEL,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ &hostdata->iobuf.buf.write_desc_phys_addr, 0 );
-+ if ( !hostdata->iobuf.buf.write_desc ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+ hostdata->iobuf.iodata = consistent_alloc( GFP_ATOMIC,
-+ PXA_MMC_IODATA_SIZE,
-+ &hostdata->iobuf.buf.phys_addr, 0 );
-+#else
-+ hostdata->iobuf.iodata = kmalloc( PXA_MMC_IODATA_SIZE, GFP_ATOMIC );
-+#endif
-+ if ( !hostdata->iobuf.iodata ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+/* 2. initialize iobuf */
-+ hostdata->iobuf.blksz = PXA_MMC_BLKSZ_MAX;
-+ hostdata->iobuf.bufsz = PXA_MMC_IODATA_SIZE;
-+ hostdata->iobuf.nob = PXA_MMC_BLOCKS_PER_BUFFER;
-+#ifndef PIO
-+ /* request DMA channel */
-+ if ( (hostdata->iobuf.buf.chan = pxa_request_dma( "MMC", DMA_PRIO_LOW,
-+ pxa_mmc_dma_irq, ctrlr )) < 0 ) {
-+ MMC_ERROR( "failed to request DMA channel\n" );
-+ goto error;
-+ }
-+
-+ DRCMRRXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
-+ DRCMRTXMMC = hostdata->iobuf.buf.chan | DRCMR_MAPVLD;
-+
-+ for ( i = 0; i < ((PXA_MMC_IODATA_SIZE>>5) - 1); i++ ) {
-+ desc = &hostdata->iobuf.buf.read_desc[i];
-+ desc->ddadr = hostdata->iobuf.buf.read_desc_phys_addr
-+ + ((i + 1) * sizeof( pxa_dma_desc ));
-+ desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
-+ desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+
-+ desc = &hostdata->iobuf.buf.write_desc[i];
-+ desc->ddadr = hostdata->iobuf.buf.write_desc_phys_addr
-+ + ((i + 1) * sizeof( pxa_dma_desc ));
-+ desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
-+ desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+ }
-+ desc = &hostdata->iobuf.buf.read_desc[i];
-+ desc->ddadr = (hostdata->iobuf.buf.read_desc_phys_addr +
-+ (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
-+ desc->dsadr = MMC_RXFIFO_PHYS_ADDR;
-+ desc->dtadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dcmd = DCMD_FLOWSRC|DCMD_INCTRGADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+
-+ desc = &hostdata->iobuf.buf.write_desc[i];
-+ desc->ddadr = (hostdata->iobuf.buf.write_desc_phys_addr +
-+ (i + 1) * sizeof( pxa_dma_desc))|DDADR_STOP;
-+ desc->dsadr = hostdata->iobuf.buf.phys_addr + (i<<5);
-+ desc->dtadr = MMC_TXFIFO_PHYS_ADDR;
-+ desc->dcmd = DCMD_FLOWTRG|DCMD_INCSRCADDR
-+ |DCMD_WIDTH1|DCMD_BURST32|(1<<5);
-+#endif
-+/* II. MMC */
-+/* 1) request irq */
-+ if ( request_irq( IRQ_MMC, pxa_mmc_irq, 0, "MMC", ctrlr ) ) {
-+ MMC_ERROR( "failed to request IRQ_MMC\n" );
-+ goto error;
-+ }
-+
-+/* 2) initialize h/w and ctrlr */
-+ set_GPIO_mode( GPIO6_MMCCLK_MD );
-+ CKEN |= CKEN12_MMC; /* enable MMC unit clock */
-+
-+ ret = 0;
-+ goto out;
-+error:
-+#ifndef PIO
-+/* free DMA resources */
-+ if ( hostdata->iobuf.buf.chan >= 0 ) {
-+ DRCMRRXMMC = 0;
-+ DRCMRTXMMC = 0;
-+ pxa_free_dma( hostdata->iobuf.buf.chan );
-+ }
-+ if ( hostdata->iobuf.iodata )
-+ consistent_free( hostdata->iobuf.iodata,
-+ PXA_MMC_IODATA_SIZE,
-+ hostdata->iobuf.buf.phys_addr );
-+ if ( hostdata->iobuf.buf.read_desc )
-+ consistent_free( hostdata->iobuf.buf.read_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.read_desc_phys_addr );
-+ if ( hostdata->iobuf.buf.write_desc )
-+ consistent_free( hostdata->iobuf.buf.write_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.write_desc_phys_addr );
-+#else
-+ kfree( hostdata->iobuf.iodata );
-+#endif
-+out:
-+ return ret;
-+}
-+
-+static void pxa_mmc_remove( mmc_controller_t ctrlr )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+/* 1) free buffer(s) */
-+#ifndef PIO
-+ consistent_free( hostdata->iobuf.iodata, PXA_MMC_IODATA_SIZE,
-+ hostdata->iobuf.buf.phys_addr );
-+ consistent_free( hostdata->iobuf.buf.read_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.read_desc_phys_addr );
-+ consistent_free( hostdata->iobuf.buf.write_desc,
-+ (PXA_MMC_IODATA_SIZE>>5)
-+ * sizeof( pxa_dma_desc ),
-+ hostdata->iobuf.buf.write_desc_phys_addr );
-+/* 2) release DMA channel */
-+ if ( hostdata->iobuf.buf.chan >= 0 ) {
-+ DRCMRRXMMC = 0;
-+ DRCMRTXMMC = 0;
-+ pxa_free_dma( hostdata->iobuf.buf.chan );
-+ }
-+#else
-+ kfree( hostdata->iobuf.iodata );
-+#endif
-+/* II. MMC */
-+/* 1) release irq */
-+ free_irq( IRQ_MMC, ctrlr );
-+ CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
-+}
-+
-+static int pxa_mmc_probe( mmc_controller_t ctrlr )
-+{
-+ return 1;
-+}
-+
-+#ifdef CONFIG_PM
-+static int pxa_mmc_suspend( mmc_controller_t ctrlr )
-+{
-+ int ret = -EBUSY;
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL2, "state=%s\n",
-+ PXA_MMC_STATE_LABEL( hostdata->state ) );
-+
-+ if ( hostdata->state == PXA_MMC_FSM_IDLE ) {
-+ /* save registers */
-+ SAVED_MMC_CLKRT = MMC_CLKRT;
-+ SAVED_MMC_RESTO = MMC_RESTO;
-+ SAVED_MMC_SPI = MMC_SPI;
-+ SAVED_DRCMRRXMMC = DRCMRRXMMC;
-+ SAVED_DRCMRTXMMC = DRCMRTXMMC;
-+
-+#if 0 /* FIXME */
-+ /* send CMD0 */
-+ if ( (ret = pxa_mmc_stop_bus_clock( ctrlr )) )
-+ goto error;
-+
-+ MMC_CMD = CMD(0); /* CMD0 with zero argument */
-+ MMC_ARGH = 0UL;
-+ MMC_ARGL = 0UL;
-+ MMC_CMDAT = 0UL;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL3, "CMD0(0x%04x%04x)\n", 0UL, 0UL );
-+ if ( (ret = pxa_mmc_complete_cmd( ctrlr, MMC_NORESPONSE,
-+ FALSE )) )
-+ {
-+ ret = -EIO;
-+ goto error;
-+ }
-+#endif
-+
-+ set_GPIO_mode( GPIO6_MMCCLK );
-+ CKEN &= ~CKEN12_MMC; /* disable MMC unit clock */
-+
-+ hostdata->suspended = TRUE;
-+ ret = 0;
-+ }
-+error:
-+ return ret;
-+}
-+
-+static void pxa_mmc_resume( mmc_controller_t ctrlr )
-+{
-+ pxa_mmc_hostdata_t hostdata = (pxa_mmc_hostdata_t)ctrlr->host_data;
-+
-+ if ( hostdata->suspended == TRUE ) {
-+ set_GPIO_mode( GPIO6_MMCCLK_MD );
-+ CKEN |= CKEN12_MMC; /* enable MMC unit clock */
-+
-+ /* restore registers */
-+ MMC_CLKRT = SAVED_MMC_CLKRT;
-+ MMC_RESTO = SAVED_MMC_RESTO;
-+ MMC_SPI = SAVED_MMC_SPI;
-+ DRCMRRXMMC = SAVED_DRCMRRXMMC;
-+ DRCMRTXMMC = SAVED_DRCMRTXMMC;
-+
-+ hostdata->suspended = FALSE;
-+
-+ mmc_update_card_stack( ctrlr->slot ); /* FIXME */
-+ }
-+
-+ return;
-+}
-+#endif
-+
-+static mmc_controller_tmpl_rec_t pxa_mmc_controller_tmpl_rec = {
-+ owner: THIS_MODULE,
-+ name: "PXA250",
-+ block_size_max: PXA_MMC_BLKSZ_MAX,
-+ nob_max: PXA_MMC_NOB_MAX,
-+ probe: pxa_mmc_probe,
-+ init: pxa_mmc_init,
-+ remove: __devexit_p( pxa_mmc_remove ),
-+#ifdef CONFIG_PM
-+ suspend: pxa_mmc_suspend,
-+ resume: pxa_mmc_resume,
-+#endif /* CONFIG_PM */
-+ update_acq: pxa_mmc_update_acq,
-+// single_card_acq: pxa_mmc_single_card_acq,
-+ init_card_stack: pxa_mmc_init_card_stack,
-+ check_card_stack: pxa_mmc_check_card_stack,
-+ setup_card: pxa_mmc_setup_card,
-+ stream_read: pxa_mmc_stream_read,
-+ read_block: pxa_mmc_read_block,
-+ read_mblock: pxa_mmc_read_mblock,
-+ stream_write: pxa_mmc_stream_write,
-+ write_block: pxa_mmc_write_block,
-+ write_mblock: pxa_mmc_write_mblock
-+ /* TODO
-+ sg_io: pxa_mmc_sg_io
-+ */
-+ /* TODO:
-+ * erase,
-+ * write protection,
-+ * lock/password management methods
-+ */
-+};
-+
-+static int __devinit mmc_pxa_module_init( void )
-+{
-+ int ret = -ENODEV;
-+#ifdef CONFIG_ARCH_RAMSES
-+ RAMSES_MMC_ON();
-+ udelay(1000);
-+#endif
-+
-+ host = mmc_register( MMC_REG_TYPE_HOST, &pxa_mmc_controller_tmpl_rec,
-+ sizeof( pxa_mmc_hostdata_rec_t ) );
-+ if ( !host ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void __devexit mmc_pxa_module_cleanup( void )
-+{
-+ mmc_unregister( MMC_REG_TYPE_HOST, host );
-+#ifdef CONFIG_ARCH_RAMSES
-+ RAMSES_MMC_OFF();
-+#endif
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE( "GPL" );
-+
-+module_init( mmc_pxa_module_init );
-+module_exit( mmc_pxa_module_cleanup );
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc_pxa.h
-@@ -0,0 +1,278 @@
-+/*
-+ * linux/drivers/mmc/mmc_pxa.h
-+ *
-+ * Author: Vladimir Shebordaev, Igor Oblakov
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_PXA_P_H__
-+#define __MMC_PXA_P_H__
-+
-+#include <linux/completion.h>
-+
-+#define PIO
-+
-+/* PXA-250 MMC controller registers */
-+
-+/* MMC_STRPCL */
-+#define MMC_STRPCL_STOP_CLK (0x0001UL)
-+#define MMC_STRPCL_START_CLK (0x0002UL)
-+
-+/* MMC_STAT */
-+#define MMC_STAT_END_CMD_RES (0x0001UL << 13)
-+#define MMC_STAT_PRG_DONE (0x0001UL << 12)
-+#define MMC_STAT_DATA_TRAN_DONE (0x0001UL << 11)
-+#define MMC_STAT_CLK_EN (0x0001UL << 8)
-+#define MMC_STAT_RECV_FIFO_FULL (0x0001UL << 7)
-+#define MMC_STAT_XMIT_FIFO_EMPTY (0x0001UL << 6)
-+#define MMC_STAT_RES_CRC_ERROR (0x0001UL << 5)
-+#define MMC_STAT_SPI_READ_ERROR_TOKEN (0x0001UL << 4)
-+#define MMC_STAT_CRC_READ_ERROR (0x0001UL << 3)
-+#define MMC_STAT_CRC_WRITE_ERROR (0x0001UL << 2)
-+#define MMC_STAT_TIME_OUT_RESPONSE (0x0001UL << 1)
-+#define MMC_STAT_READ_TIME_OUT (0x0001UL)
-+
-+#define MMC_STAT_ERRORS (MMC_STAT_RES_CRC_ERROR|MMC_STAT_SPI_READ_ERROR_TOKEN\
-+ |MMC_STAT_CRC_READ_ERROR|MMC_STAT_TIME_OUT_RESPONSE\
-+ |MMC_STAT_READ_TIME_OUT)
-+
-+/* MMC_CLKRT */
-+#define MMC_CLKRT_20MHZ (0x0000UL)
-+#define MMC_CLKRT_10MHZ (0x0001UL)
-+#define MMC_CLKRT_5MHZ (0x0002UL)
-+#define MMC_CLKRT_2_5MHZ (0x0003UL)
-+#define MMC_CLKRT_1_25MHZ (0x0004UL)
-+#define MMC_CLKRT_0_625MHZ (0x0005UL)
-+#define MMC_CLKRT_0_3125MHZ (0x0006UL)
-+
-+/* MMC_SPI */
-+#define MMC_SPI_DISABLE (0x00UL)
-+#define MMC_SPI_EN (0x01UL)
-+#define MMC_SPI_CS_EN (0x01UL << 2)
-+#define MMC_SPI_CS_ADDRESS (0x01UL << 3)
-+#define MMC_SPI_CRC_ON (0x01UL << 1)
-+
-+/* MMC_CMDAT */
-+#define MMC_CMDAT_MMC_DMA_EN (0x0001UL << 7)
-+#define MMC_CMDAT_INIT (0x0001UL << 6)
-+#define MMC_CMDAT_BUSY (0x0001UL << 5)
-+#define MMC_CMDAT_STREAM (0x0001UL << 4)
-+#define MMC_CMDAT_BLOCK (0x0000UL << 4)
-+#define MMC_CMDAT_WRITE (0x0001UL << 3)
-+#define MMC_CMDAT_READ (0x0000UL << 3)
-+#define MMC_CMDAT_DATA_EN (0x0001UL << 2)
-+#define MMC_CMDAT_R1 (0x0001UL)
-+#define MMC_CMDAT_R2 (0x0002UL)
-+#define MMC_CMDAT_R3 (0x0003UL)
-+
-+/* MMC_RESTO */
-+#define MMC_RES_TO_MAX (0x007fUL) /* [6:0] */
-+
-+/* MMC_RDTO */
-+#define MMC_READ_TO_MAX (0x0ffffUL) /* [15:0] */
-+
-+/* MMC_BLKLEN */
-+#define MMC_BLK_LEN_MAX (0x03ffUL) /* [9:0] */
-+
-+/* MMC_PRTBUF */
-+#define MMC_PRTBUF_BUF_PART_FULL (0x01UL)
-+#define MMC_PRTBUF_BUF_FULL (0x00UL )
-+
-+/* MMC_I_MASK */
-+#define MMC_I_MASK_TXFIFO_WR_REQ (0x01UL << 6)
-+#define MMC_I_MASK_RXFIFO_RD_REQ (0x01UL << 5)
-+#define MMC_I_MASK_CLK_IS_OFF (0x01UL << 4)
-+#define MMC_I_MASK_STOP_CMD (0x01UL << 3)
-+#define MMC_I_MASK_END_CMD_RES (0x01UL << 2)
-+#define MMC_I_MASK_PRG_DONE (0x01UL << 1)
-+#define MMC_I_MASK_DATA_TRAN_DONE (0x01UL)
-+#define MMC_I_MASK_ALL (0x07fUL)
-+
-+
-+/* MMC_I_REG */
-+#define MMC_I_REG_TXFIFO_WR_REQ (0x01UL << 6)
-+#define MMC_I_REG_RXFIFO_RD_REQ (0x01UL << 5)
-+#define MMC_I_REG_CLK_IS_OFF (0x01UL << 4)
-+#define MMC_I_REG_STOP_CMD (0x01UL << 3)
-+#define MMC_I_REG_END_CMD_RES (0x01UL << 2)
-+#define MMC_I_REG_PRG_DONE (0x01UL << 1)
-+#define MMC_I_REG_DATA_TRAN_DONE (0x01UL)
-+#define MMC_I_REG_ALL (0x007fUL)
-+
-+/* MMC_CMD */
-+#define MMC_CMD_INDEX_MAX (0x006fUL) /* [5:0] */
-+#define CMD(x) (x)
-+
-+/* MMC_ARGH */
-+/* MMC_ARGL */
-+/* MMC_RES */
-+/* MMC_RXFIFO */
-+#define MMC_RXFIFO_PHYS_ADDR 0x41100040 //MMC_RXFIFO physical address
-+/* MMC_TXFIFO */
-+#define MMC_TXFIFO_PHYS_ADDR 0x41100044 //MMC_TXFIFO physical address
-+
-+/* implementation specific declarations */
-+#define PXA_MMC_BLKSZ_MAX (1<<9) /* actually 1023 */
-+#define PXA_MMC_NOB_MAX ((1<<16)-2)
-+#define PXA_MMC_BLOCKS_PER_BUFFER (2)
-+
-+#define PXA_MMC_IODATA_SIZE (PXA_MMC_BLOCKS_PER_BUFFER*PXA_MMC_BLKSZ_MAX) /* 1K */
-+
-+typedef enum _pxa_mmc_fsm { /* command processing FSM */
-+ PXA_MMC_FSM_IDLE = 1,
-+ PXA_MMC_FSM_CLK_OFF,
-+ PXA_MMC_FSM_END_CMD,
-+ PXA_MMC_FSM_BUFFER_IN_TRANSIT,
-+ PXA_MMC_FSM_END_BUFFER,
-+ PXA_MMC_FSM_END_IO,
-+ PXA_MMC_FSM_END_PRG,
-+ PXA_MMC_FSM_ERROR
-+} pxa_mmc_state_t;
-+
-+#define PXA_MMC_STATE_LABEL( state ) (\
-+ (state == PXA_MMC_FSM_IDLE) ? "IDLE" :\
-+ (state == PXA_MMC_FSM_CLK_OFF) ? "CLK_OFF" :\
-+ (state == PXA_MMC_FSM_END_CMD) ? "END_CMD" :\
-+ (state == PXA_MMC_FSM_BUFFER_IN_TRANSIT) ? "IN_TRANSIT" :\
-+ (state == PXA_MMC_FSM_END_BUFFER) ? "END_BUFFER" :\
-+ (state == PXA_MMC_FSM_END_IO) ? "END_IO" :\
-+ (state == PXA_MMC_FSM_END_PRG) ? "END_PRG" : "UNKNOWN" )
-+
-+typedef enum _pxa_mmc_result {
-+ PXA_MMC_NORMAL = 0,
-+ PXA_MMC_INVALID_STATE = -1,
-+ PXA_MMC_TIMEOUT = -2,
-+ PXA_MMC_ERROR = -3
-+} pxa_mmc_result_t;
-+
-+typedef u32 pxa_mmc_clkrt_t;
-+
-+typedef char *pxa_mmc_iodata_t;
-+#ifdef PIO
-+typedef struct _pxa_mmc_piobuf_rec {
-+ char *pos; /* current buffer position */
-+ int cnt; /* byte counter */
-+} pxa_mmc_piobuf_rec_t, *pxa_mmc_piobuf_t;
-+#else /* i.e. DMA */
-+typedef struct _pxa_mmc_dmabuf_rec { /* TODO: buffer ring, DMA irq completion */
-+ int chan; /* dma channel no */
-+ dma_addr_t phys_addr; /* iodata physical address */
-+ pxa_dma_desc *read_desc; /* input descriptor array virtual address */
-+ pxa_dma_desc *write_desc; /* output descriptor array virtual address */
-+ dma_addr_t read_desc_phys_addr; /* descriptor array physical address */
-+ dma_addr_t write_desc_phys_addr; /* descriptor array physical address */
-+ pxa_dma_desc *last_read_desc; /* last input descriptor
-+ * used by the previous transfer
-+ */
-+ pxa_dma_desc *last_write_desc; /* last output descriptor
-+ * used by the previous transfer
-+ */
-+} pxa_mmc_dmabuf_rec_t, *pxa_mmc_dmabuf_t;
-+#endif
-+
-+typedef struct _pxa_mmc_iobuf_rec {
-+ ssize_t blksz; /* current block size in bytes */
-+ ssize_t bufsz; /* buffer size for each transfer */
-+ ssize_t nob; /* number of blocks pers buffer */
-+#ifndef PIO
-+ pxa_mmc_dmabuf_rec_t buf; /* i.e. DMA buffer ring on the iodata */
-+#else /* i.e. DMA */
-+ pxa_mmc_piobuf_rec_t buf; /* PIO buffer accounting */
-+#endif
-+ pxa_mmc_iodata_t iodata; /* I/O data buffer */
-+} pxa_mmc_iobuf_rec_t, *pxa_mmc_iobuf_t;
-+
-+typedef struct _pxa_mmc_hostdata_rec {
-+ pxa_mmc_state_t state; /* FSM */
-+#ifdef CONFIG_PM
-+ int suspended;
-+#endif
-+ pxa_mmc_iobuf_rec_t iobuf; /* data transfer state */
-+
-+ int busy; /* atomic busy flag */
-+ struct completion completion; /* completion */
-+#if CONFIG_MMC_DEBUG_IRQ
-+ int irqcnt;
-+ int timeo;
-+#endif
-+
-+/* cached controller state */
-+ u32 mmc_i_reg; /* interrupt last requested */
-+ u32 mmc_i_mask; /* mask to be set by intr handler */
-+ u32 mmc_stat; /* status register at the last intr */
-+ u32 mmc_cmdat; /* MMC_CMDAT at the last inr */
-+ u8 mmc_res[16]; /* response to the last command in host order */
-+ u32 saved_mmc_clkrt;
-+ u32 saved_mmc_resto;
-+ u32 saved_mmc_spi;
-+ u32 saved_drcmrrxmmc;
-+ u32 saved_drcmrtxmmc;
-+
-+/* controller options */
-+ pxa_mmc_clkrt_t clkrt; /* current bus clock rate */
-+} pxa_mmc_hostdata_rec_t, *pxa_mmc_hostdata_t;
-+
-+#define PXA_MMC_STATUS( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_stat)
-+#define PXA_MMC_RESPONSE( ctrlr, idx ) ((((pxa_mmc_hostdata_t)ctrlr->host_data)->mmc_res)[idx])
-+#define PXA_MMC_CLKRT( ctrlr ) (((pxa_mmc_hostdata_t)ctrlr->host_data)->clkrt)
-+
-+#define SAVED_MMC_CLKRT (hostdata->saved_mmc_clkrt)
-+#define SAVED_MMC_RESTO (hostdata->saved_mmc_resto)
-+#define SAVED_MMC_SPI (hostdata->saved_mmc_spi)
-+#define SAVED_DRCMRRXMMC (hostdata->saved_drcmrrxmmc )
-+#define SAVED_DRCMRTXMMC (hostdata->saved_drcmrtxmmc )
-+
-+static inline int pxa_mmc_clkrt( int speed )
-+{
-+ return MMC_CLKRT_20MHZ; /* TODO */
-+}
-+
-+/* PXA MMC controller specific card data */
-+typedef struct _pxa_mmc_card_data_rec {
-+ pxa_mmc_clkrt_t clkrt; /* clock rate to be set for the card */
-+} pxa_mmc_card_data_rec_t, *pxa_mmc_card_data_t;
-+
-+#ifdef CONFIG_MMC_DEBUG
-+#undef MMC_DUMP_R1
-+#undef MMC_DUMP_R2
-+#undef MMC_DUMP_R3
-+#define MMC_DUMP_R2( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R2 response: %02x %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 15 ), \
-+PXA_MMC_RESPONSE( ctrlr, 14 ), \
-+PXA_MMC_RESPONSE( ctrlr, 13 ), \
-+PXA_MMC_RESPONSE( ctrlr, 12 ), \
-+PXA_MMC_RESPONSE( ctrlr, 11 ), \
-+PXA_MMC_RESPONSE( ctrlr, 10 ), \
-+PXA_MMC_RESPONSE( ctrlr, 9 ), \
-+PXA_MMC_RESPONSE( ctrlr, 8 ), \
-+PXA_MMC_RESPONSE( ctrlr, 7 ), \
-+PXA_MMC_RESPONSE( ctrlr, 6 ), \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ), \
-+PXA_MMC_RESPONSE( ctrlr, 0 ) );
-+#define MMC_DUMP_R1( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R1(b) response: %02x %02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ) );
-+#define MMC_DUMP_R3( ctrlr ) MMC_DEBUG( MMC_DEBUG_LEVEL3, \
-+"R3 response: %02x %02x%02x%02x%02x\n", \
-+PXA_MMC_RESPONSE( ctrlr, 5 ), \
-+PXA_MMC_RESPONSE( ctrlr, 4 ), \
-+PXA_MMC_RESPONSE( ctrlr, 3 ), \
-+PXA_MMC_RESPONSE( ctrlr, 2 ), \
-+PXA_MMC_RESPONSE( ctrlr, 1 ) );
-+
-+#endif
-+#endif /* __MMC_PXA_P_H__ */
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/mmc_test.c
-@@ -0,0 +1,538 @@
-+/*
-+ * linux/drivers/mmc/mmc_test.c
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc_test.c,v 0.4 2002/08/01 12:26:40 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+
-+#include <linux/fs.h>
-+#ifdef CONFIG_DEVFS_FS
-+#include <linux/devfs_fs_kernel.h>
-+#endif
-+
-+#include <asm/uaccess.h>
-+
-+#include <mmc/types.h>
-+#include <mmc/mmc.h>
-+#include <mmc/ioctl.h>
-+
-+#include "types.h"
-+#include "mmc.h"
-+
-+typedef struct _mmc_test_device_rec mmc_test_device_rec_t;
-+typedef struct _mmc_test_device_rec *mmc_test_device_t;
-+
-+struct _mmc_test_device_rec {
-+ mmc_card_t card;
-+ mmc_transfer_mode_t transfer_mode;
-+ int usage;
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_handle_t devfs_handle;
-+#endif
-+};
-+
-+/* MMC device table */
-+static mmc_test_device_rec_t mmc_test_device[MMC_CONTROLLERS_MAX][MMC_CARDS_MAX];
-+static DECLARE_MUTEX(mmc_test_device_mutex);
-+
-+static inline mmc_test_device_t __mmc_test_get_device( kdev_t rdev )
-+{
-+ mmc_test_device_t ret = NULL;
-+ u8 minor = MINOR( rdev );
-+ int host_no, card_no;
-+
-+ host_no = minor >> MMC_MINOR_HOST_SHIFT;
-+ if ( host_no >= MMC_CONTROLLERS_MAX )
-+ goto error;
-+
-+ card_no = minor & MMC_MINOR_CARD_MASK;
-+ if ( card_no >= MMC_CARDS_MAX )
-+ goto error;
-+
-+ ret = &mmc_test_device[host_no][card_no];
-+ if ( !ret->card ) {
-+ ret->card = mmc_get_card( host_no, card_no );
-+ if ( !ret->card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to get card: host=%d, card=%d\n", host_no, card_no );
-+ ret = NULL;
-+ goto error;
-+ }
-+
-+ }
-+ ++ret->usage;
-+
-+error:
-+ return ret;
-+}
-+
-+static inline void __mmc_test_put_device( mmc_test_device_t dev )
-+{
-+ mmc_put_card( dev->card );
-+ --dev->usage;
-+}
-+
-+static inline mmc_test_device_t mmc_test_get_device( kdev_t kdev )
-+{
-+ mmc_test_device_t ret = NULL;
-+
-+ down( &mmc_test_device_mutex );
-+ ret = __mmc_test_get_device( kdev );
-+ up( &mmc_test_device_mutex );
-+
-+ return ret;
-+}
-+
-+static inline void mmc_test_put_device( mmc_test_device_t dev )
-+{
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ __mmc_test_put_device( dev );
-+ if ( !dev->usage ) {
-+ if ( dev->card ) {
-+ if ( dev->card->usage ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "broken card reference\n" );
-+ }
-+ memset( dev, 0, sizeof( mmc_test_device_rec_t ) );
-+ }
-+ }
-+ up( &mmc_test_device_mutex );
-+ }
-+}
-+
-+static inline int mmc_test_set_transfer_mode( mmc_test_device_t dev, mmc_transfer_mode_t mode )
-+{
-+ int ret = -1;
-+
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ dev->transfer_mode = mode;
-+ ret = 0;
-+ up( &mmc_test_device_mutex );
-+ }
-+ return ret;
-+}
-+
-+static inline mmc_transfer_mode_t mmc_test_get_transfer_mode( mmc_test_device_t dev )
-+{
-+ mmc_transfer_mode_t ret = MMC_TRANSFER_MODE_UNDEFINED;
-+
-+ if ( dev ) {
-+ down( &mmc_test_device_mutex );
-+ ret = dev->transfer_mode;
-+ up( &mmc_test_device_mutex );
-+ }
-+ return ret;
-+}
-+
-+static int mmc_test_open( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = NULL;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ __ENTER0( );
-+ dev = mmc_test_get_device( inode->i_rdev );
-+ if ( !dev || !dev->card ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to acquire device\n" );
-+ goto error;
-+ }
-+
-+ if ( dev->card->usage > 1 ) {
-+ ret = -EBUSY;
-+ goto error;
-+ }
-+
-+ dev->transfer_mode = MMC_TEST_TRANSFER_MODE_DEFAULT; /* FIXME: should check card CCC */
-+ file->private_data = dev;
-+
-+ __LEAVE0( );
-+ return 0;
-+error:
-+ MOD_DEC_USE_COUNT;
-+ mmc_test_put_device( dev );
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static int mmc_test_release( struct inode *inode, struct file *file )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ __ENTER( "host=%d, card=%d", dev->card->ctrlr->slot, dev->card->slot );
-+
-+ file->private_data = NULL;
-+
-+ mmc_test_put_device( dev );
-+ MOD_DEC_USE_COUNT;
-+
-+ ret = 0;
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static ssize_t mmc_test_read( struct file *file, char *buf, size_t size, loff_t *ppos )
-+{
-+ ssize_t ret = -ENODEV;
-+ ssize_t retsize = 0;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( dev->transfer_mode ) {
-+ char *mbuf;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual read_bl_len or ctrlr->block_size_max whichever is less ), GFP_KERNEL */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 512) ? 512 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_read( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 1024) ? 1024 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_read( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+
-+ case MMC_TRANSFER_MODE_STREAM:
-+ ret = mmc_read( dev->card, dev->transfer_mode,
-+ buf, size, ppos );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static ssize_t mmc_test_write( struct file *file, const char *buf, size_t size, loff_t *ppos )
-+{
-+ ssize_t ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+ int retsize=0;
-+
-+ __ENTER( "host=%d, card=%d, size=%d", dev->card->ctrlr->slot, dev->card->slot, size );
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( dev->transfer_mode ) {
-+ char *mbuf;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_SINGLE:
-+ mbuf = kmalloc( 512, GFP_ATOMIC ); /* FIXME: actual write_bl_len or ctrlr->block_size_max whichever is less, GFP_KERNEL */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while ( size > 0 ) {
-+ int lsize = ( size > 512 ) ? 512 : size;
-+
-+ /* Copy from user */
-+ if ( copy_from_user( mbuf, buf, lsize ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+
-+ ret = mmc_write( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ mbuf, lsize, ppos );
-+ if( ret <= 0 )
-+ break;
-+
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+
-+ kfree( mbuf );
-+ break;
-+
-+ case MMC_TRANSFER_MODE_BLOCK_MULTIPLE:
-+ mbuf = kmalloc( 1024, GFP_ATOMIC ); /* FIXME */
-+ if ( !mbuf ) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ while( size > 0 ) {
-+ int lsize = (size > 1024) ? 1024 : size;
-+
-+ MMC_DEBUG( MMC_DEBUG_LEVEL4,
-+ "before mmc_read mbuf=0x%x "
-+ "lsize=%d ppos=0x%x *ppos=%d\n",
-+ mbuf, lsize, ppos, *ppos );
-+ ret = mmc_write( dev->card,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ mbuf, lsize, ppos );
-+ if ( ret <= 0 )
-+ break;
-+
-+ /* Copy to user */
-+ if ( copy_to_user( (char *)buf, mbuf, ret ) ) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ retsize += ret;
-+ buf += ret;
-+ size -= ret;
-+ }
-+
-+ if ( retsize > 0 )
-+ ret = retsize;
-+ kfree(mbuf);
-+ break;
-+ case MMC_TRANSFER_MODE_STREAM:
-+ ret = mmc_write( dev->card, dev->transfer_mode,
-+ buf, size, ppos );
-+ break;
-+
-+ default:
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid transfer mode\n" );
-+ }
-+error:
-+ __LEAVE( "ret=%d", ret );
-+ return ret;
-+}
-+
-+static loff_t mmc_test_llseek( struct file *file, loff_t offset, int origin )
-+{
-+ loff_t ret = -ESPIPE;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+ mmc_card_t card;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+
-+ __ENTER( "host=%d, card=%d, off=%ld, orig=%d", dev->card->ctrlr->slot, dev->card->slot, (long)offset, origin );
-+
-+ card = dev->card;
-+
-+ switch ( origin ) {
-+ case SEEK_CUR:
-+ file->f_pos += offset;
-+ break;
-+
-+ case SEEK_END:
-+ file->f_pos = card->info.capacity + offset;
-+ break;
-+
-+ case SEEK_SET:
-+ file->f_pos = offset;
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+
-+ ret = file->f_pos;
-+error:
-+ __LEAVE( "ret=%ld", (long)ret );
-+ return ret;
-+}
-+
-+static int mmc_test_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg )
-+{
-+ int ret = -ENODEV;
-+ mmc_test_device_t dev = (mmc_test_device_t)file->private_data;
-+
-+ if ( !dev ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "file->private_data == NULL\n" );
-+ goto error;
-+ }
-+
-+ switch ( cmd ) {
-+ case IOCMMCSTRNSMODE:
-+ if ( get_user( ret, (int *)arg ) ) {
-+ ret = -EFAULT;
-+ goto error;
-+ }
-+ ret = mmc_test_set_transfer_mode( dev, ret );
-+ break;
-+
-+ case IOCMMCGTRNSMODE:
-+ ret = mmc_test_get_transfer_mode( dev );
-+ if ( put_user( ret, (int *)arg ) )
-+ ret = -EFAULT;
-+ break;
-+
-+ default:
-+ ret = mmc_ioctl( dev->card, cmd, arg );
-+ }
-+
-+error:
-+ return ret;
-+}
-+
-+struct file_operations mmc_test_fops = {
-+ owner: THIS_MODULE,
-+ open: mmc_test_open,
-+ release: mmc_test_release,
-+ read: mmc_test_read,
-+ write: mmc_test_write,
-+ ioctl: mmc_test_ioctl,
-+ llseek: mmc_test_llseek
-+};
-+
-+#ifdef CONFIG_DEVFS_FS
-+static int mmc_test_add_card( mmc_card_t card ) /* TODO */
-+{
-+ int ret = -1;
-+ __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
-+/* TODO: make kdev; register with devfs */
-+ __LEAVE0( );
-+ return ret;
-+}
-+
-+static int mmc_test_remove_card( mmc_card_t card ) /* TODO */
-+{
-+ int ret = -1;
-+ __ENTER( "host=%d, card=%d", card->ctrlr->slot, card->slot );
-+/* TODO: make kdev; unregister with devfs */
-+ __LEAVE0( );
-+ return ret;
-+}
-+
-+static mmc_notifier_rec_t mmc_test_notifier = {
-+ add: mmc_test_add_card,
-+ remove: mmc_test_remove_card
-+};
-+#endif /* CONFIG_DEVFS_FS */
-+
-+static int __init mmc_test_module_init( void )
-+{
-+ int ret = -ENODEV;
-+
-+#ifdef CONFIG_DEVFS_FS
-+ if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_test_notifier, 0 ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );
-+ goto error;
-+ }
-+#else
-+ mmc_register( MMC_REG_TYPE_USER, NULL, 0 );
-+ if ( register_chrdev( MMC_TEST_MAJOR, "mmc_test", &mmc_test_fops ) ) {
-+ MMC_DEBUG( MMC_DEBUG_LEVEL0,
-+ "failed to request device major number\n" );
-+ mmc_unregister( MMC_REG_TYPE_USER, NULL );
-+ goto error;
-+ }
-+#endif
-+
-+ memset( mmc_test_device, 0, sizeof( mmc_test_device ) );
-+
-+ ret = 0;
-+error:
-+ return ret;
-+}
-+
-+static void __exit mmc_test_module_cleanup( void )
-+{
-+#ifdef CONFIG_DEVFS_FS
-+ mmc_unregister( MMC_REG_TYPE_USER, &mmc_test_notifier );
-+#else
-+ mmc_unregister( MMC_REG_TYPE_USER, NULL );
-+ unregister_chrdev( MMC_TEST_MAJOR, "mmc_test" );
-+#endif
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init( mmc_test_module_init );
-+module_exit( mmc_test_module_cleanup );
-+
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/pm_test.c
-@@ -0,0 +1,29 @@
-+/* Power Managment Test Module. RTSoft Co. 2002 */
-+
-+/* The necessary header files */
-+
-+/* Standard in kernel modules */
-+#include <linux/kernel.h> /* We're doing kernel work */
-+#include <linux/module.h> /* Specifically, a module */
-+#define CONFIG_PM
-+#include <linux/pm.h>
-+
-+
-+static int pmdata = -1;
-+
-+/* Initialize the module - register the proc file */
-+
-+int init_module()
-+{
-+ pm_send_all(PM_SUSPEND,&pmdata);
-+ return(0);
-+}
-+
-+
-+/* Cleanup - unregister our file from /proc */
-+void cleanup_module()
-+{
-+ pm_send_all(PM_RESUME,NULL);
-+}
-+
-+MODULE_LICENSE( "GPL" );
---- /dev/null
-+++ linux-2.4.27/drivers/mmc/types.h
-@@ -0,0 +1,59 @@
-+/*
-+ * linux/drivers/mmc/types.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: types.h,v 0.5 2002/08/13 17:34:02 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_TYPES_P_H__
-+#define __MMC_TYPES_P_H__
-+
-+#ifdef __KERNEL__
-+#include <linux/kdev_t.h>
-+
-+typedef enum _mmc_reg_type mmc_reg_type_t;
-+typedef enum _mmc_response mmc_response_fmt_t;
-+
-+/* MMC card private description */
-+typedef struct _mmc_card_rec mmc_card_rec_t;
-+typedef struct _mmc_card_rec *mmc_card_t;
-+typedef enum _mmc_dir mmc_dir_t;
-+typedef enum _mmc_buftype mmc_buftype_t;
-+
-+/* notifier declarations */
-+typedef struct _mmc_notifier_rec mmc_notifier_rec_t;
-+typedef struct _mmc_notifier_rec *mmc_notifier_t;
-+
-+typedef int (*mmc_notifier_fn_t) ( mmc_card_t );
-+
-+/* MMC card stack */
-+typedef struct _mmc_card_stack_rec mmc_card_stack_rec_t;
-+typedef struct _mmc_card_stack_rec *mmc_card_stack_t;
-+
-+typedef struct _mmc_data_transfer_req_rec mmc_data_transfer_req_rec_t;
-+typedef struct _mmc_data_transfer_req_rec *mmc_data_transfer_req_t;
-+
-+/* MMC controller */
-+typedef struct _mmc_controller_tmpl_rec mmc_controller_tmpl_rec_t;
-+typedef struct _mmc_controller_tmpl_rec *mmc_controller_tmpl_t;
-+
-+typedef enum _mmc_controller_state mmc_controller_state_t;
-+typedef struct _mmc_controller_rec mmc_controller_rec_t;
-+typedef struct _mmc_controller_rec *mmc_controller_t;
-+
-+/* various kernel types */
-+typedef struct semaphore semaphore_t;
-+typedef struct rw_semaphore rwsemaphore_t;
-+typedef struct proc_dir_entry proc_dir_entry_rec_t;
-+typedef struct proc_dir_entry *proc_dir_entry_t;
-+typedef struct gendisk gendisk_rec_t;
-+typedef struct gendisk *gendisk_t;
-+#endif /* __KERNEL__ */
-+
-+#endif /* __MMC_TYPES_P_H__ */
-+
---- linux-2.4.27/drivers/mtd/maps/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/mtd/maps/Config.in
-@@ -75,6 +75,7 @@
- fi
-
- if [ "$CONFIG_ARM" = "y" ]; then
-+ dep_tristate ' CFI Flash device mapped on Lubbock board' CONFIG_MTD_LUBBOCK $CONFIG_MTD_CFI $CONFIG_ARCH_LUBBOCK $CONFIG_MTD_PARTITIONS
- dep_tristate ' CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI
- dep_tristate ' CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI
- dep_tristate ' Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712
---- linux-2.4.27/drivers/mtd/maps/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/mtd/maps/Makefile
-@@ -15,6 +15,9 @@
- obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
- obj-$(CONFIG_MTD_EPXA) += epxa-flash.o
- obj-$(CONFIG_MTD_IQ80310) += iq80310.o
-+obj-$(CONFIG_MTD_LUBBOCK) += lubbock.o
-+obj-$(CONFIG_MTD_PXA_CERF) += pxa_cerf.o
-+obj-$(CONFIG_MTD_TRIZEPS2) += trizeps2.o
- obj-$(CONFIG_MTD_L440GX) += l440gx.o
- obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
- obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/maps/lubbock.c
-@@ -0,0 +1,168 @@
-+/*
-+ * $Id:
-+ *
-+ * Map driver for the Lubbock developer platform.
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+
-+#define WINDOW_ADDR 0
-+//#define WINDOW_ADDR 0x04000000
-+#define WINDOW_SIZE 64*1024*1024
-+
-+static __u8 lubbock_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u8 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 lubbock_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u16 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 lubbock_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u32 *)(map->map_priv_1 + ofs);
-+}
-+
-+static void lubbock_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy(to, (void *)(map->map_priv_1 + from), len);
-+}
-+
-+static void lubbock_write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ *(__u8 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void lubbock_write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ *(__u16 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void lubbock_write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ *(__u32 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void lubbock_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy((void *)(map->map_priv_1 + to), from, len);
-+}
-+
-+static struct map_info lubbock_map = {
-+ name: "Lubbock flash",
-+ size: WINDOW_SIZE,
-+ read8: lubbock_read8,
-+ read16: lubbock_read16,
-+ read32: lubbock_read32,
-+ copy_from: lubbock_copy_from,
-+ write8: lubbock_write8,
-+ write16: lubbock_write16,
-+ write32: lubbock_write32,
-+ copy_to: lubbock_copy_to
-+};
-+
-+static struct mtd_partition lubbock_partitions[] = {
-+ {
-+ name: "Bootloader",
-+ size: 0x00040000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "Kernel",
-+ size: 0x00100000,
-+ offset: 0x00040000,
-+ },{
-+ name: "Filesystem",
-+ size: MTDPART_SIZ_FULL,
-+ offset: 0x00140000
-+ }
-+};
-+
-+#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-+
-+static struct mtd_info *mymtd;
-+static struct mtd_partition *parsed_parts;
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static int __init init_lubbock(void)
-+{
-+ struct mtd_partition *parts;
-+ int nb_parts = 0;
-+ int parsed_nr_parts = 0;
-+ char *part_type = "static";
-+
-+ lubbock_map.buswidth = (BOOT_DEF & 1) ? 2 : 4;
-+ printk( "Probing Lubbock flash at physical address 0x%08x (%d-bit buswidth)\n",
-+ WINDOW_ADDR, lubbock_map.buswidth * 8 );
-+ lubbock_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0);
-+ if (!lubbock_map.map_priv_1) {
-+ printk("Failed to ioremap\n");
-+ return -EIO;
-+ }
-+ mymtd = do_map_probe("cfi_probe", &lubbock_map);
-+ if (!mymtd) {
-+ iounmap((void *)lubbock_map.map_priv_1);
-+ return -ENXIO;
-+ }
-+ mymtd->module = THIS_MODULE;
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ if (parsed_nr_parts == 0) {
-+ int ret = parse_redboot_partitions(mymtd, &parsed_parts);
-+
-+ if (ret > 0) {
-+ part_type = "RedBoot";
-+ parsed_nr_parts = ret;
-+ }
-+ }
-+#endif
-+
-+ if (parsed_nr_parts > 0) {
-+ parts = parsed_parts;
-+ nb_parts = parsed_nr_parts;
-+ } else {
-+ parts = lubbock_partitions;
-+ nb_parts = NB_OF(lubbock_partitions);
-+ }
-+ if (nb_parts) {
-+ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-+ add_mtd_partitions(mymtd, parts, nb_parts);
-+ } else {
-+ add_mtd_device(mymtd);
-+ }
-+ return 0;
-+}
-+
-+static void __exit cleanup_lubbock(void)
-+{
-+ if (mymtd) {
-+ del_mtd_partitions(mymtd);
-+ map_destroy(mymtd);
-+ if (parsed_parts)
-+ kfree(parsed_parts);
-+ }
-+ if (lubbock_map.map_priv_1)
-+ iounmap((void *)lubbock_map.map_priv_1);
-+ return 0;
-+}
-+
-+module_init(init_lubbock);
-+module_exit(cleanup_lubbock);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/maps/pxa_cerf.c
-@@ -0,0 +1,172 @@
-+/*
-+ * Map driver for the PXA Cerf.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+
-+#define WINDOW_ADDR 0
-+#if defined (CONFIG_PXA_CERF_FLASH_64MB)
-+#define WINDOW_SIZE 64*1024*1024
-+#elif defined (CONFIG_PXA_CERF_FLASH_32MB)
-+#define WINDOW_SIZE 32*1024*1024
-+#elif defined (CONFIG_PXA_CERF_FLASH_16MB)
-+#define WINDOW_SIZE 16*1024*1024
-+#endif
-+#define BUSWIDTH 4
-+
-+static __u8 pxa_cerf_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u8 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 pxa_cerf_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u16 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 pxa_cerf_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u32 *)(map->map_priv_1 + ofs);
-+}
-+
-+static void pxa_cerf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy(to, (void *)(map->map_priv_1 + from), len);
-+}
-+
-+static void pxa_cerf_write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ *(__u8 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void pxa_cerf_write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ *(__u16 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void pxa_cerf_write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ *(__u32 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void pxa_cerf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy((void *)(map->map_priv_1 + to), from, len);
-+}
-+
-+static struct map_info pxa_cerf_map = {
-+ name: "PXA Cerf Flash",
-+ size: WINDOW_SIZE,
-+ buswidth: BUSWIDTH,
-+ read8: pxa_cerf_read8,
-+ read16: pxa_cerf_read16,
-+ read32: pxa_cerf_read32,
-+ copy_from: pxa_cerf_copy_from,
-+ write8: pxa_cerf_write8,
-+ write16: pxa_cerf_write16,
-+ write32: pxa_cerf_write32,
-+ copy_to: pxa_cerf_copy_to
-+};
-+
-+static struct mtd_partition pxa_cerf_partitions[] = {
-+ {
-+ name: "Bootloader",
-+ size: 0x00040000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "Partition Tables",
-+ size: 0x00080000,
-+ offset: 0x00040000,
-+ },{
-+ name: "Kernel",
-+ size: 0x00100000,
-+ offset: 0x000C0000,
-+ },{
-+ name: "Filesystem",
-+ size: WINDOW_SIZE-0x001C0000, //MTDPART_SIZ_FULL,
-+ offset: 0x001C0000
-+ }
-+};
-+
-+#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-+
-+static struct mtd_info *mymtd;
-+static struct mtd_partition *parsed_parts;
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static int __init init_pxa_cerf(void)
-+{
-+ struct mtd_partition *parts;
-+ int nb_parts = 0;
-+ int parsed_nr_parts = 0;
-+ char *part_type = "static";
-+
-+ printk("Probing PXA Cerf flash at physical address 0x%08x\n", WINDOW_ADDR);
-+ pxa_cerf_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0);
-+ if (!pxa_cerf_map.map_priv_1) {
-+ printk("Failed to ioremap\n");
-+ return -EIO;
-+ }
-+ mymtd = do_map_probe("cfi_probe", &pxa_cerf_map);
-+ if (!mymtd) {
-+ iounmap((void *)pxa_cerf_map.map_priv_1);
-+ return -ENXIO;
-+ }
-+ mymtd->module = THIS_MODULE;
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ if (parsed_nr_parts == 0) {
-+ int ret = parse_redboot_partitions(mymtd, &parsed_parts);
-+
-+ if (ret > 0) {
-+ part_type = "RedBoot";
-+ parsed_nr_parts = ret;
-+ }
-+ }
-+#endif
-+
-+ if (parsed_nr_parts > 0) {
-+ parts = parsed_parts;
-+ nb_parts = parsed_nr_parts;
-+ } else {
-+ parts = pxa_cerf_partitions;
-+ nb_parts = NB_OF(pxa_cerf_partitions);
-+ }
-+ if (nb_parts) {
-+ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-+ add_mtd_partitions(mymtd, parts, nb_parts);
-+ } else {
-+ add_mtd_device(mymtd);
-+ }
-+ return 0;
-+}
-+
-+static void __exit cleanup_pxa_cerf(void)
-+{
-+ if (mymtd) {
-+ del_mtd_partitions(mymtd);
-+ map_destroy(mymtd);
-+ if (parsed_parts)
-+ kfree(parsed_parts);
-+ }
-+ if (pxa_cerf_map.map_priv_1)
-+ iounmap((void *)pxa_cerf_map.map_priv_1);
-+ return;
-+}
-+
-+module_init(init_pxa_cerf);
-+module_exit(cleanup_pxa_cerf);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/maps/trizeps2.c
-@@ -0,0 +1,172 @@
-+/*
-+ * $Id:
-+ *
-+ * Map driver for the Trizeps-2 module.
-+ *
-+ * Author: Luc De Cock
-+ * Copyright: (C) 2003 Teradyne DS, Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+
-+#define WINDOW_ADDR 0
-+#define WINDOW_SIZE 16*1024*1024
-+
-+static __u8 trizeps2_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u8 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 trizeps2_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u16 *)(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 trizeps2_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return *(__u32 *)(map->map_priv_1 + ofs);
-+}
-+
-+static void trizeps2_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy(to, (void *)(map->map_priv_1 + from), len);
-+}
-+
-+static void trizeps2_write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ *(__u8 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void trizeps2_write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ *(__u16 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void trizeps2_write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ *(__u32 *)(map->map_priv_1 + adr) = d;
-+}
-+
-+static void trizeps2_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy((void *)(map->map_priv_1 + to), from, len);
-+}
-+
-+static struct map_info trizeps2_map = {
-+ name: "Trizeps-2 flash",
-+ size: WINDOW_SIZE,
-+ read8: trizeps2_read8,
-+ read16: trizeps2_read16,
-+ read32: trizeps2_read32,
-+ copy_from: trizeps2_copy_from,
-+ write8: trizeps2_write8,
-+ write16: trizeps2_write16,
-+ write32: trizeps2_write32,
-+ copy_to: trizeps2_copy_to
-+};
-+
-+static struct mtd_partition trizeps2_partitions[] = {
-+ {
-+ name: "Bootloader",
-+ size: 0x00040000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "Bootloader (backup)",
-+ size: 0x00040000,
-+ offset: 0x00040000,
-+ mask_flags: MTD_WRITEABLE /* force read-only */
-+ },{
-+ name: "Kernel",
-+ size: 0x000C0000,
-+ offset: 0x00080000,
-+ },{
-+ name: "Filesystem",
-+ size: MTDPART_SIZ_FULL,
-+ offset: 0x00140000
-+ }
-+};
-+
-+#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-+
-+static struct mtd_info *mymtd;
-+static struct mtd_partition *parsed_parts;
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static int __init init_trizeps2(void)
-+{
-+ struct mtd_partition *parts;
-+ int nb_parts = 0;
-+ int parsed_nr_parts = 0;
-+ char *part_type = "static";
-+
-+ trizeps2_map.buswidth = (BOOT_DEF & 1) ? 2 : 4;
-+ printk( "Probing Trizeps-2 flash at physical address 0x%08x (%d-bit buswidth)\n",
-+ WINDOW_ADDR, trizeps2_map.buswidth * 8 );
-+ trizeps2_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0);
-+ if (!trizeps2_map.map_priv_1) {
-+ printk("Failed to ioremap\n");
-+ return -EIO;
-+ }
-+ mymtd = do_map_probe("cfi_probe", &trizeps2_map);
-+ if (!mymtd) {
-+ iounmap((void *)trizeps2_map.map_priv_1);
-+ return -ENXIO;
-+ }
-+ mymtd->module = THIS_MODULE;
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ if (parsed_nr_parts == 0) {
-+ int ret = parse_redboot_partitions(mymtd, &parsed_parts);
-+
-+ if (ret > 0) {
-+ part_type = "RedBoot";
-+ parsed_nr_parts = ret;
-+ }
-+ }
-+#endif
-+
-+ if (parsed_nr_parts > 0) {
-+ parts = parsed_parts;
-+ nb_parts = parsed_nr_parts;
-+ } else {
-+ parts = trizeps2_partitions;
-+ nb_parts = NB_OF(trizeps2_partitions);
-+ }
-+ if (nb_parts) {
-+ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-+ add_mtd_partitions(mymtd, parts, nb_parts);
-+ } else {
-+ add_mtd_device(mymtd);
-+ }
-+ return 0;
-+}
-+
-+static void __exit cleanup_trizeps2(void)
-+{
-+ if (mymtd) {
-+ del_mtd_partitions(mymtd);
-+ map_destroy(mymtd);
-+ if (parsed_parts)
-+ kfree(parsed_parts);
-+ }
-+ if (trizeps2_map.map_priv_1)
-+ iounmap((void *)trizeps2_map.map_priv_1);
-+ return 0;
-+}
-+
-+module_init(init_trizeps2);
-+module_exit(cleanup_trizeps2);
-+
---- linux-2.4.27/drivers/net/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/net/Config.in
-@@ -125,6 +125,7 @@
- dep_tristate ' SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA
- dep_tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA
- dep_tristate ' SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA
-+ tristate ' SMC 91C9x/91C1xx support' CONFIG_SMC91X
- fi
- bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
- if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
---- linux-2.4.27/drivers/net/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/net/Makefile
-@@ -137,6 +137,7 @@
- obj-$(CONFIG_SK_G16) += sk_g16.o
- obj-$(CONFIG_HP100) += hp100.o
- obj-$(CONFIG_SMC9194) += smc9194.o
-+obj-$(CONFIG_SMC91X) += smc91x.o
- obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
- obj-$(CONFIG_ARM_ETHERH) += 8390.o
- obj-$(CONFIG_WD80x3) += wd.o 8390.o
---- linux-2.4.27/drivers/net/cirrus.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/net/cirrus.c
-@@ -67,6 +67,9 @@
- #elif CONFIG_ARCH_CDB89712
- # define CIRRUS_DEFAULT_IO ETHER_BASE + 0x300
- # define CIRRUS_DEFAULT_IRQ IRQ_EINT3
-+#elif CONFIG_ARCH_CSB226
-+# define CIRRUS_DEFAULT_IO 0xF8000000
-+# define CIRRUS_DEFAULT_IRQ IRQ_GPIO(14)
- #else
- # define CIRRUS_DEFAULT_IO 0
- # define CIRRUS_DEFAULT_IRQ 0
---- linux-2.4.27/drivers/net/irda/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/net/irda/Config.in
-@@ -42,5 +42,7 @@
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
- dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
- fi
--
-+if [ "$CONFIG_ARCH_PXA" = "y" ]; then
-+ dep_tristate 'Intel PXA2xx Internal IR' CONFIG_PXA_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
-+fi
- endmenu
---- linux-2.4.27/drivers/net/irda/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/net/irda/Makefile
-@@ -16,6 +16,7 @@
- obj-$(CONFIG_USB_IRDA) += irda-usb.o
- obj-$(CONFIG_NSC_FIR) += nsc-ircc.o
- obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
-+obj-$(CONFIG_PXA_FIR) += pxa_ir.o
- obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o
- obj-$(CONFIG_TOSHIBA_OLD) += toshoboe.o
- obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o
---- /dev/null
-+++ linux-2.4.27/drivers/net/irda/pxa_ir.c
-@@ -0,0 +1,1545 @@
-+/*
-+ * linux/drivers/net/irda/pxa_ir.c
-+ *
-+ * Author:
-+ * Alexey Lugovskoy RTSoft.
-+ * lugovskoy@rtsoft.msk.ru
-+ *
-+ * Dmitrij Frasenyak RTSoft.
-+ * sed@mipt.sw.ru
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Infra-red SIR and FIR driver for the PXA 210/250 embedded microprocessors
-+ * Based on linux/drivers/net/irda/sa1100_ir.c
-+ *
-+ */
-+
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/netdevice.h>
-+#include <linux/slab.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/interrupt.h>
-+#include <linux/delay.h>
-+#include <linux/ioport.h>
-+#include <linux/delay.h>
-+
-+#include <linux/pm.h>
-+
-+#include <net/irda/irda.h>
-+#include <net/irda/irmod.h>
-+#include <net/irda/wrapper.h>
-+#include <net/irda/irda_device.h>
-+
-+#include <asm/irq.h>
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/lubbock.h>
-+
-+
-+static int rx_count = 0;
-+static int tx_count = 0;
-+
-+/*
-+ * Our netdevice. There is only ever one of these.
-+ */
-+
-+static struct net_device *netdev;
-+
-+struct pxa250_irda {
-+
-+ unsigned char open;
-+
-+ int speed;
-+ int newspeed;
-+
-+ struct sk_buff *txskb;
-+ struct sk_buff *rxskb;
-+
-+
-+ /* => FIR */
-+ unsigned int fir_irq;
-+ int txdma_ch;
-+ int rxdma_ch;
-+ dma_addr_t txbuf_dma;
-+ dma_addr_t rxbuf_dma;
-+ void* txbuf_dma_virt;
-+ void* rxbuf_dma_virt;
-+ /* <= FIR*/
-+ struct net_device_stats stats;
-+ struct irlap_cb *irlap;
-+ struct pm_dev *pmdev;
-+ struct qos_info qos;
-+
-+ /* => SIR */
-+ iobuff_t tx_buff;
-+ iobuff_t rx_buff;
-+ /* <= SIR */
-+};
-+
-+#define IS_FIR(si) ((si)->speed >= 4000000)
-+
-+#define HPSIR_MAX_RXLEN 2050
-+#define HPSIR_MAX_TXLEN 2050
-+#define TXBUFF_MAX_SIZE HPSIR_MAX_TXLEN
-+#define SET_SIR_MODE STISR = STISR_RCVEIR | STISR_XMITIR | STISR_XMODE
-+
-+/*
-+ * If you want to disable debug information
-+ * please uncomment line bellow
-+ */
-+
-+#define PXA_FIR_DUMP_ENABLE
-+#undef PXA_FIR_DUMP_ENABLE
-+
-+
-+#define PXA_FIR_DEBUG_ENABLE
-+#undef PXA_FIR_DEBUG_ENABLE
-+
-+#define PXA_FIR_IRQ_DEBUG_ENABLE
-+#undef PXA_FIR_IRQ_DEBUG_ENABLE
-+
-+#ifdef PXA_FIR_DEBUG_ENABLE
-+#define __ECHO_IN printk(KERN_ERR "%s: enter\n",__FUNCTION__);
-+#define __ECHO_OUT printk(KERN_ERR "%s: exit\n",__FUNCTION__);
-+#define DBG(args...) printk(KERN_ERR __FUNCTION__"():"args);
-+#else
-+#define __ECHO_IN
-+#define __ECHO_OUT
-+#define DBG(args...)
-+#endif
-+
-+#ifdef PXA_FIR_IRQ_DEBUG_ENABLE
-+#define DBG_IRQ(args...) printk(KERN_ERR __FUNCTION__"():"args);
-+#else
-+#define DBG_IRQ(args...)
-+#endif
-+
-+
-+static int pxa250_irda_set_speed(struct net_device *dev,int speed);
-+static void pxa250_start_rx_dma(struct net_device *dev);
-+
-+
-+
-+/**************************************************************************
-+ * Misc FIR/SIR functions *
-+ **************************************************************************/
-+/*
-+ * Allocate the receive buffer, unless it is already allocated.
-+ */
-+
-+static int pxa250_irda_rx_alloc(struct pxa250_irda *si)
-+{
-+ __ECHO_IN;
-+
-+ if (si->rxskb)
-+ return 0;
-+
-+ si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-+
-+ if (!si->rxskb) {
-+ printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
-+ return -ENOMEM;
-+ }
-+
-+ /*
-+ * Align any IP headers that may be contained
-+ * within the frame.
-+ */
-+ skb_reserve(si->rxskb, 1);
-+
-+ __ECHO_OUT;
-+
-+ return 0;
-+}
-+
-+
-+
-+/**************************************************************************
-+ * FIR *
-+ **************************************************************************/
-+
-+
-+
-+
-+static inline void pxa250_dma_stop(int ch)
-+{
-+ __ECHO_IN;
-+
-+ DCSR(ch) &= ~DCSR_RUN;
-+
-+ __ECHO_OUT;
-+
-+}
-+
-+
-+static void pxa250_ficp_rx_start(void)
-+{
-+ ICCR0 = 0;
-+ ICCR2 = 1 << 2 | 0 << 3 ;
-+ ICCR0 = ICCR0_ITR ;
-+ ICCR0 |= ICCR0_RIE | ICCR0_RXE ;
-+}
-+
-+/*
-+ * Change Alternative Function encoding
-+ * Enable ICP unit
-+ * Disabe STUART unit
-+ * Enable IRQ unit clock;
-+ * Configure direction of GPIO used by ICP
-+ */
-+
-+
-+static void pxa250_do_fir_GPIO_config(void)
-+{
-+ /*
-+ * Modify GPIO 46 and 47 Alternate Function
-+ */
-+
-+ __ECHO_IN;
-+
-+ /*Switch AF*/
-+ set_GPIO_mode (GPIO46_ICPRXD_MD);
-+ set_GPIO_mode (GPIO47_ICPTXD_MD);
-+
-+ if (machine_is_lubbock())
-+ LUB_MISC_WR |= 1 << 4;
-+
-+ /*init clock*/
-+ CKEN |= CKEN13_FICP;
-+
-+ __ECHO_OUT;
-+}
-+
-+/*
-+ * Low level hardware configuration and startup.
-+ */
-+
-+static int pxa250_fir_irda_startup(struct pxa250_irda *si)
-+{
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Disable STUART
-+ */
-+
-+ STIER &= ~IER_UUE;
-+
-+ /*Disable STUART FIFO */
-+ STFCR = 0;
-+
-+ /*
-+ * Do low level configuration for HW AF and clock
-+ */
-+ pxa250_do_fir_GPIO_config();
-+
-+ __ECHO_OUT;
-+ return 0;
-+}
-+
-+
-+/*
-+ * Aieeeeee .. we should never get here :(
-+ */
-+static void pxa250_irda_rxdma_irq(int ch,void *id, struct pt_regs *regs)
-+{
-+ struct net_device *dev=id;
-+ struct pxa250_irda *si=dev->priv;
-+ u_int dcsr;
-+
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Make sure that irq is our.
-+ */
-+
-+ if ( ch != si->rxdma_ch )
-+ /*just*/ return;
-+
-+ /*
-+ * Check status
-+ */
-+ dcsr = DCSR(ch);
-+
-+ DBG("DCSR=%x\n",dcsr);
-+
-+ if (dcsr & DCSR_STOPSTATE )
-+ {
-+ DBG_IRQ("Chanel %d in stop state\n",ch);
-+ }
-+
-+ if (dcsr & DCSR_BUSERR )
-+ {
-+ /*
-+ * BUS Error we must restart reception
-+ */
-+
-+ DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
-+ DCSR(ch) |= DCSR_BUSERR;
-+ }
-+
-+ if (dcsr & DCSR_ENDINTR )
-+ {
-+ DBG("PXA IrDA: Normal end of dma channel %d - packet to big\n", ch);
-+ DCSR(ch) |= DCSR_ENDINTR;
-+ }
-+
-+ /* no mater what restart rx*/
-+ pxa250_start_rx_dma(dev);
-+
-+ return ;
-+
-+}
-+
-+
-+static void pxa250_irda_txdma_irq(int ch, void *id , struct pt_regs *regs)
-+{
-+ struct net_device *dev=id;
-+ struct pxa250_irda *si=dev->priv;
-+ struct sk_buff *skb = si->txskb;
-+ u_int dcsr;
-+
-+
-+ __ECHO_IN;
-+ DBG_IRQ("transmit\n");
-+
-+
-+ /*
-+ * Make sure that irq is our.
-+ */
-+
-+ if ( ch != si->txdma_ch )
-+ /*just*/ return;
-+
-+
-+ /*
-+ * Check status
-+ */
-+ dcsr = DCSR(ch);
-+
-+ DBG("DCSR=%x",dcsr);
-+
-+ if (dcsr & DCSR_STOPSTATE )
-+ {
-+ DBG("Chanel %d in stop state\n",ch);
-+ }
-+
-+ if (dcsr & DCSR_BUSERR )
-+ {
-+ DBG("PXA IrDA: bus error interrupt on channel %d\n", ch);
-+ DCSR(ch) |= DCSR_BUSERR;
-+ si->txskb = NULL;
-+ }
-+
-+ if (dcsr & DCSR_ENDINTR )
-+ {
-+ DBG("PXA IrDA: Normal end of dma channel %d\n", ch);
-+ DCSR(ch) |= DCSR_ENDINTR;
-+ si->txskb = NULL;
-+ }
-+
-+ /*
-+ * Account and free the packet.
-+ */
-+ if (skb)
-+ {
-+ si->stats.tx_packets ++;
-+ si->stats.tx_bytes += skb->len;
-+ dev_kfree_skb_irq(skb);
-+ }
-+
-+ /*Disable transceiver and enable receiver*/
-+
-+ if (si->newspeed) {
-+ pxa250_irda_set_speed(dev, si->newspeed);
-+ si->newspeed = 0;
-+ }
-+
-+ while (ICSR1 & ICSR1_TBY)
-+ udelay(1);
-+
-+ ICCR0 &= ~ICCR0_TXE;
-+
-+
-+ enable_irq(si->fir_irq);
-+
-+ ICCR0 |= ICCR0_RXE;
-+
-+ /*
-+ * Make sure that the TX queue is available for sending
-+ * (for retries). TX has priority over RX at all times.
-+ */
-+ netif_wake_queue(dev);
-+
-+ __ECHO_OUT;
-+}
-+
-+
-+static void pxa250_start_rx_dma(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int ch=si->rxdma_ch;
-+
-+ if (!si->rxskb) {
-+ DBG("rx buffer went missing\n");
-+/* return; */
-+ }
-+
-+ DCSR(ch)=0;
-+ DCSR(ch)=DCSR_NODESC;
-+ DSADR(ch) = __PREG(ICDR);
-+ DTADR(ch) = si->rxbuf_dma; /* phisical address */;
-+
-+ /* We should never do END_IRQ. !!!*/
-+ DCMD(ch) = DCMD_ENDIRQEN| DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | HPSIR_MAX_RXLEN;
-+
-+ /*
-+ * All right information will be available as soon as we set RXE flag
-+ */
-+
-+ DCSR(ch) = DCSR_ENDINTR | DCSR_BUSERR;
-+ DCSR(ch) = DCSR_RUN | DCSR_NODESC ;
-+
-+}
-+
-+
-+
-+
-+static int pxa250_get_rx_len(struct pxa250_irda *si)
-+{
-+ /*
-+ * DMA have to be stoped here
-+ */
-+
-+ if ( ! (DCSR(si->rxdma_ch) & DCSR_STOPSTATE) )
-+ printk("warning dma have to be stoped befor counting len\n");
-+
-+ return ( HPSIR_MAX_RXLEN - ( DCMD(si->rxdma_ch) & DCMD_LENGTH ) );
-+
-+}
-+
-+static void pxa250_irda_fir_error(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ struct sk_buff *skb = si->rxskb;
-+ int len;
-+ int stat,data;
-+
-+ __ECHO_IN;
-+
-+ if (!skb)
-+ {
-+ printk("pxa250 fir_error: SKB is NULL!\n");
-+ return;
-+ }
-+
-+ /*
-+ * Get the current data position.
-+ */
-+
-+ len=pxa250_get_rx_len(si);
-+ DBG("RXLEN=%d\n",len);
-+ memcpy(skb->data, si->rxbuf_dma_virt, len);
-+
-+ do {
-+ /*
-+ * Read Status, and then Data.
-+ */
-+ stat = ICSR1;
-+ rmb();
-+ data = ICDR;
-+ if (stat & (ICSR1_CRE | ICSR1_ROR)) {
-+ si->stats.rx_errors++;
-+ if (stat & ICSR1_CRE)
-+ si->stats.rx_crc_errors++;
-+ if (stat & ICSR1_ROR)
-+ si->stats.rx_frame_errors++;
-+ } else
-+ skb->data[len++] = data;
-+
-+ /*
-+ * If we hit the end of frame, there's
-+ * no point in continuing.
-+ */
-+ if (stat & ICSR1_EOF)
-+ break;
-+ } while (ICSR0 & ICSR0_EIF);
-+
-+ if (stat & ICSR1_EOF) {
-+ si->rxskb = NULL;
-+
-+ skb_put(skb, len);
-+ skb->dev = dev;
-+ skb->mac.raw = skb->data;
-+ skb->protocol = htons(ETH_P_IRDA);
-+ si->stats.rx_packets++;
-+ si->stats.rx_bytes += len;
-+
-+ /*
-+ * Before we pass the buffer up, allocate a new one.
-+ */
-+
-+ si->rxskb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC);
-+
-+ if (!si->rxskb) {
-+ printk(KERN_ERR "pxa250_ir: out of memory for RX SKB\n");
-+ return;
-+ }
-+
-+ /*
-+ * Align any IP headers that may be contained
-+ * within the frame.
-+ */
-+ skb_reserve(si->rxskb, 1);
-+
-+ netif_rx(skb);
-+ }
-+}
-+
-+/*
-+ * FIR format interrupt service routine. We only have to
-+ * handle RX events; transmit events go via the TX DMA irq handler.
-+ *
-+ * No matter what, we disable RX, process, and then restart RX.
-+ */
-+
-+static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+ struct pxa250_irda *si = dev->priv;
-+ int status;
-+
-+ /*
-+ * Stop RX
-+ */
-+
-+ __ECHO_IN;
-+
-+ pxa250_dma_stop(si->rxdma_ch);
-+
-+
-+ /*
-+ * Framing error - we throw away the packet completely.
-+ * Clearing RXE flushes the error conditions and data
-+ * from the fifo.
-+ */
-+ status=ICSR0;
-+
-+ if (status & (ICSR0_FRE | ICSR0_RAB)) {
-+ DBG_IRQ("Framing error or RAB\n");
-+
-+ si->stats.rx_errors++;
-+
-+ if (ICSR0 & ICSR0_FRE)
-+ si->stats.rx_frame_errors++;
-+
-+ /* Clear RX fifo
-+ * DMA will be cleared when we restart RX
-+ * Should we check RNE after that?
-+ */
-+
-+ ICCR0 &= ~ICCR0_RXE;
-+
-+ /*
-+ * Clear selected status bits now, so we
-+ * don't miss them next time around.
-+ */
-+ ICSR0 = status & (ICSR0_FRE | ICSR0_RAB);
-+ }
-+
-+
-+ /*
-+ * Deal with any receive errors. The any of the lowest
-+ * 8 bytes in the FIFO may contain an error. We must read
-+ * them one by one. The "error" could even be the end of
-+ * packet!
-+ */
-+ if (ICSR0 & ICSR0_EIF)
-+ pxa250_irda_fir_error(dev);
-+
-+ /*
-+ * No matter what happens, we must restart reception.
-+ */
-+
-+ ICCR0 = 0;
-+ pxa250_start_rx_dma(dev);
-+ pxa250_ficp_rx_start();
-+ __ECHO_OUT;
-+}
-+
-+
-+
-+
-+
-+/**************************************************************************
-+ * SIR *
-+ **************************************************************************/
-+/*
-+ * HP-SIR format interrupt service routines.
-+ */
-+static void pxa250_sir_transmit(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ if (si->tx_buff.len)
-+ {
-+ /* Disable receiver and enable transmiter*/
-+
-+
-+
-+ STISR &= ~STISR_RCVEIR;
-+// STISR |= STISR_XMITIR;
-+
-+
-+
-+ disable_irq(dev->irq);
-+
-+ do
-+ {
-+
-+ if (STLSR & LSR_TDRQ)
-+ {
-+ STTHR = *si->tx_buff.data++;
-+ si->tx_buff.len -= 1;
-+
-+ tx_count++;
-+ }
-+
-+
-+ } while (si->tx_buff.len);
-+
-+
-+ if (si->tx_buff.len == 0)
-+ {
-+
-+
-+ si->stats.tx_packets++;
-+ si->stats.tx_bytes += si->tx_buff.data -
-+ si->tx_buff.head;
-+
-+ /*
-+ * We need to ensure that the transmitter has
-+ * finished.
-+ */
-+
-+ do
-+ {
-+ udelay(1);
-+
-+ }
-+ while ( ! (STLSR & LSR_TEMT) );
-+
-+
-+ /*
-+
-+ * Ok, we've finished transmitting. Now enable
-+ * the receiver. Sometimes we get a receive IRQ
-+ * immediately after a transmit...
-+ */
-+
-+ if (si->newspeed)
-+ {
-+ pxa250_irda_set_speed(dev, si->newspeed);
-+ si->newspeed = 0;
-+ }
-+
-+ /* I'm hungry! */
-+ netif_wake_queue(dev);
-+ }
-+
-+ enable_irq (dev->irq);
-+ STIER = (IER_RAVIE | IER_UUE | IER_RTIOE);
-+
-+ STISR |= STISR_RCVEIR;
-+// STISR &= ~STISR_XMITIR;
-+ }
-+}
-+
-+static void pxa250_irda_hpsir_irq(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ /*
-+ * Deal with any receive errors first. The bytes in error may be
-+ * the only bytes in the receive FIFO, so we do this first.
-+ */
-+ __ECHO_IN;
-+
-+ while (STLSR & LSR_FIFOE)
-+ {
-+ int stat, data;
-+
-+ stat = STLSR;
-+ data = STRBR;
-+
-+
-+ if (stat & (LSR_FE | LSR_OE | LSR_PE))
-+
-+ {
-+ si->stats.rx_errors++;
-+ if (stat & LSR_FE)
-+ si->stats.rx_frame_errors++;
-+ if (stat & LSR_OE)
-+ si->stats.rx_fifo_errors++;
-+
-+ } else
-+ {
-+ rx_count++;
-+ async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
-+ }
-+
-+ }
-+
-+ /*
-+ * We must clear certain bits.
-+ */
-+
-+ if (STLSR & (LSR_DR))
-+ {
-+ /*
-+ * Fifo contains at least 1 character.
-+ */
-+ do
-+ {
-+ int data;
-+
-+ data = STRBR;
-+
-+ async_unwrap_char(dev, &si->stats, &si->rx_buff,
-+ data); /* was Ser2UTDR); Clo */
-+ rx_count++;
-+
-+ } while (STLSR & LSR_DR);
-+
-+ dev->last_rx = jiffies;
-+ }
-+
-+ __ECHO_OUT;
-+}
-+
-+static void pxa250_sir_irda_shutdown(struct pxa250_irda *si)
-+{
-+
-+ STIER = 0;
-+ STFCR = 0;
-+ STISR = 0;
-+ CKEN &= ~CKEN5_STUART;
-+}
-+
-+
-+/************************************************************************************/
-+
-+/*Low level init/uninstall function PM control and IrDA protocol stack registration */
-+
-+/*
-+ * Set the IrDA communications speed.
-+ * Interrupt have to be disabled here.
-+ */
-+
-+static int pxa250_irda_startup(struct net_device *dev)
-+{
-+
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Ensure that the ports for this device are setup correctly.
-+ */
-+
-+
-+ set_GPIO_mode (GPIO46_STRXD_MD);
-+ set_GPIO_mode (GPIO47_STTXD_MD);
-+
-+ STMCR = MCR_OUT2;
-+ STLCR = LCR_WLS1 | LCR_WLS0;
-+
-+ SET_SIR_MODE;
-+ CKEN |= CKEN5_STUART;
-+ /* enable irq from stuart */
-+ ICMR |= ( 1 << 20 );
-+
-+ /*reset FIFO*/
-+
-+/* STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF;// | FCR_ITL_16;
-+
-+ STIER = IER_UUE | IER_RAVIE | IER_RTOIE;
-+*/
-+ __ECHO_OUT;
-+
-+ return 0;
-+
-+}
-+
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Suspend the IrDA interface.
-+ */
-+
-+static int pxa250_irda_shutdown(struct pxa250_irda *si)
-+{
-+
-+ pxa250_sir_irda_shutdown(si);
-+ return 0;
-+
-+}
-+
-+
-+static int pxa250_irda_suspend(struct net_device *dev, int state)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ if (si && si->open) {
-+ /*
-+ * Stop the transmit queue
-+ */
-+ if (IS_FIR(si))
-+ return -1;
-+
-+ netif_stop_queue(dev);
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+ pxa250_sir_irda_shutdown(si);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Resume the IrDA interface.
-+ */
-+
-+static int pxa250_irda_resume(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ __ECHO_IN;
-+
-+ if (si && si->open) {
-+ /*
-+ * If we missed a speed change, initialise at the new speed
-+ * directly. It is debatable whether this is actually
-+ * required, but in the interests of continuing from where
-+ * we left off it is desireable. The converse argument is
-+ * that we should re-negotiate at 9600 baud again.
-+ */
-+ if (si->newspeed) {
-+ si->speed = si->newspeed;
-+ si->newspeed = 0;
-+ }
-+
-+ pxa250_irda_startup(dev);
-+ enable_irq(dev->irq);
-+
-+ /*
-+ * This automatically wakes up the queue
-+ */
-+ netif_wake_queue(dev);
-+ pxa250_irda_set_speed(dev,si->speed = 9600);
-+
-+ }
-+
-+ __ECHO_OUT;
-+ return 0;
-+}
-+
-+static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ int ret;
-+
-+
-+ if (!dev->data)
-+ return -EINVAL;
-+
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ ret = pxa250_irda_suspend((struct net_device *)dev->data,
-+ (int)data);
-+ break;
-+
-+ case PM_RESUME:
-+ ret = pxa250_irda_resume((struct net_device *)dev->data);
-+ break;
-+
-+ default:
-+
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+#endif
-+
-+
-+
-+
-+static void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+
-+ pxa250_irda_hpsir_irq(dev);
-+
-+}
-+
-+
-+static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int speed = irda_get_next_speed(skb);
-+ int mtt;
-+
-+ __ECHO_IN;
-+
-+ /*
-+ * Does this packet contain a request to change the interface
-+ * speed? If so, remember it until we complete the transmission
-+ * of this frame.
-+ */
-+ if (speed != si->speed && speed != -1)
-+ si->newspeed = speed;
-+
-+ /*
-+ * If this is an empty frame, we can bypass a lot.
-+ */
-+ if (skb->len == 0) {
-+ if (si->newspeed) {
-+ si->newspeed = 0;
-+ pxa250_irda_set_speed(dev, speed);
-+ }
-+ dev_kfree_skb(skb);
-+ return 0;
-+ }
-+
-+
-+ DBG("stop queue\n");
-+ netif_stop_queue(dev);
-+
-+ if(!IS_FIR(si))
-+ {
-+
-+ si->tx_buff.data = si->tx_buff.head;
-+ si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
-+ si->tx_buff.truesize);
-+
-+
-+ pxa250_sir_transmit(dev);
-+
-+
-+
-+ dev_kfree_skb(skb);
-+
-+ dev->trans_start = jiffies;
-+
-+ return 0;
-+ }
-+ else /* FIR */
-+ {
-+ DBG("Enter FIR transmit\n");
-+ /*
-+ * We must not be transmitting...
-+ */
-+ if (si->txskb)
-+ BUG();
-+
-+ disable_irq(si->fir_irq);
-+
-+ netif_stop_queue(dev);
-+ DBG("queue stoped\n");
-+ si->txskb = skb;
-+
-+ /* we could not just map so we'll need some triks */
-+ /* skb->data may be not DMA capable -Sed- */
-+
-+
-+ if (skb->len > TXBUFF_MAX_SIZE)
-+ {
-+ printk (KERN_ERR "skb data too large\n");
-+ printk (KERN_ERR "len=%d",skb->len);
-+ BUG();
-+ }
-+
-+
-+ DBG("gonna copy %d bytes to txbuf\n",skb->len);
-+
-+ memcpy (si->txbuf_dma_virt, skb->data , skb->len);
-+
-+ /* Actual sending ;must not be receiving !!! */
-+ /* Write data and source address */
-+
-+ DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 );
-+
-+ /*Disable receiver and enable transifer */
-+ ICCR0 &= ~ICCR0_RXE;
-+
-+ if (ICSR1 & ICSR1_TBY)
-+ BUG();
-+
-+ ICCR0 |= ICCR0_TXE;
-+
-+ DBG("FICP status %x\n",ICSR0);
-+
-+ if (0){
-+ int i;
-+
-+ DBG("sending packet\n");
-+ for (i=0;i<skb->len;i++)
-+ (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ;
-+ DBG(" done\n");
-+
-+ }
-+ /*
-+ * If we have a mean turn-around time, impose the specified
-+ * specified delay. We could shorten this by timing from
-+ * the point we received the packet.
-+ */
-+
-+ mtt = irda_get_mtt(skb);
-+ if(mtt)
-+ udelay(mtt);
-+
-+ DCSR(si->txdma_ch)=0;
-+ DCSR(si->txdma_ch)=DCSR_NODESC;
-+ DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */
-+ DTADR(si->txdma_ch) = __PREG(ICDR);
-+
-+ DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len;
-+
-+ DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;
-+ DCSR(si->txdma_ch) = DCSR_RUN | DCSR_NODESC ;
-+
-+ DBG("FICP status %x\n",ICSR0);
-+
-+ return 0;
-+ }
-+
-+}
-+
-+static int
-+pxa250_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
-+{
-+ struct if_irda_req *rq = (struct if_irda_req *)ifreq;
-+ struct pxa250_irda *si = dev->priv;
-+ int ret = -EOPNOTSUPP;
-+
-+ __ECHO_IN;
-+
-+ switch (cmd) {
-+ case SIOCSBANDWIDTH:
-+ if (capable(CAP_NET_ADMIN)) {
-+ /*
-+ * We are unable to set the speed if the
-+ * device is not running.
-+ */
-+ if (si->open) {
-+ ret = pxa250_irda_set_speed(dev,
-+ rq->ifr_baudrate);
-+ } else {
-+ printk("pxa250_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
-+ ret = 0;
-+ }
-+ }
-+ break;
-+
-+ case SIOCSMEDIABUSY:
-+ ret = -EPERM;
-+ if (capable(CAP_NET_ADMIN)) {
-+ irda_device_set_media_busy(dev, TRUE);
-+ ret = 0;
-+ }
-+ break;
-+
-+ case SIOCGRECEIVING:
-+ rq->ifr_receiving = IS_FIR(si) ? 0
-+ : si->rx_buff.state != OUTSIDE_FRAME;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ __ECHO_OUT;
-+
-+ return ret;
-+}
-+
-+static struct net_device_stats *pxa250_irda_stats(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ return &si->stats;
-+}
-+
-+static int pxa250_irda_start(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int err;
-+ unsigned int flags;
-+
-+
-+ MOD_INC_USE_COUNT;
-+
-+ __ECHO_IN;
-+ si->speed = 9600;
-+
-+ local_irq_save(flags);
-+
-+ err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0, dev->name, dev);
-+ if (err)
-+ goto err_fir_irq;
-+
-+ err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev);
-+ if (err)
-+ goto err_irq;
-+
-+ /*
-+ * The interrupt must remain disabled for now.
-+ */
-+
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+
-+ local_irq_restore(flags);
-+
-+
-+ /* Allocate DMA channel for receiver (not used) */
-+ err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev);
-+ if (err < 0 )
-+ goto err_rx_dma;
-+ si->rxdma_ch=err;
-+
-+ DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch;
-+
-+
-+ /* Allocate DMA channel for transmit */
-+ err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev);
-+ if (err < 0 )
-+ goto err_tx_dma;
-+
-+ si->txdma_ch=err;
-+
-+ /*
-+ * Make sure that ICP will be able
-+ * to assert the transmit dma request bit
-+ * through the peripherals request bus (PREQ)
-+ */
-+
-+ DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch;
-+
-+ DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch);
-+
-+ /* allocate consistent buffers for dma access
-+ * buffers have to be aligned and situated in dma capable memory region;
-+ */
-+ si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma);
-+ if (! si->rxbuf_dma_virt )
-+ goto err_rxbuf_dma;
-+
-+ si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN, &si->txbuf_dma);
-+ if (! si->txbuf_dma_virt )
-+ goto err_txbuf_dma;
-+
-+ /* Alocate skb for receiver */
-+ err=pxa250_irda_rx_alloc(si);
-+ if (err)
-+ goto err_rx_alloc;
-+
-+ /*
-+ * Setup the serial port for the specified config.
-+ */
-+ err = pxa250_irda_startup(dev);
-+ if (err)
-+ goto err_startup;
-+
-+ pxa250_irda_set_speed(dev,si->speed = 9600);
-+
-+
-+ /*
-+ * Open a new IrLAP layer instance.
-+ */
-+ si->irlap = irlap_open(dev, &si->qos, "pxa250");
-+ err = -ENOMEM;
-+ if (!si->irlap)
-+ goto err_irlap;
-+
-+ /*
-+ * Now enable the interrupt and start the queue
-+ */
-+ si->open = 1;
-+ enable_irq(dev->irq);
-+ netif_start_queue(dev);
-+ return 0;
-+
-+err_irlap:
-+ si->open = 0;
-+ pxa250_sir_irda_shutdown(si);
-+err_startup:
-+ dev_kfree_skb(si->rxskb);
-+err_rx_alloc:
-+ consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
-+err_txbuf_dma:
-+ consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
-+err_rxbuf_dma:
-+ pxa_free_dma(si->txdma_ch);
-+err_tx_dma:
-+ pxa_free_dma(si->rxdma_ch);
-+err_rx_dma:
-+ free_irq(dev->irq, dev);
-+err_irq:
-+ free_irq(si->fir_irq, dev);
-+err_fir_irq:
-+ MOD_DEC_USE_COUNT;
-+ return err;
-+}
-+
-+static int pxa250_irda_stop(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ printk(KERN_ERR "Irda stop... RX = %d TX = %d\n",rx_count,tx_count);
-+
-+ disable_irq(dev->irq);
-+ disable_irq(si->fir_irq);
-+/* pxa250_irda_shutdown(si); */
-+
-+ /*
-+ * If we have been doing DMA receive, make sure we
-+ * tidy that up cleanly.
-+ */
-+ if (si->rxskb) {
-+ dev_kfree_skb(si->rxskb);
-+ si->rxskb = NULL;
-+ }
-+
-+ /* Stop IrLAP */
-+ if (si->irlap) {
-+ irlap_close(si->irlap);
-+ si->irlap = NULL;
-+ }
-+
-+ consistent_free (si->txbuf_dma_virt,HPSIR_MAX_TXLEN,si->txbuf_dma);
-+ consistent_free (si->rxbuf_dma_virt,HPSIR_MAX_RXLEN,si->rxbuf_dma);
-+ pxa_free_dma(si->txdma_ch);
-+ pxa_free_dma(si->rxdma_ch);
-+
-+ netif_stop_queue(dev);
-+ si->open = 0;
-+
-+ /*
-+ * Free resources
-+ */
-+ free_irq(dev->irq, dev);
-+ free_irq(si->fir_irq, dev);
-+
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+static int pxa250_irda_init_iobuf(iobuff_t *io, int size)
-+{
-+ io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);
-+ if (io->head != NULL) {
-+ io->truesize = size;
-+ io->in_frame = FALSE;
-+ io->state = OUTSIDE_FRAME;
-+ io->data = io->head;
-+ }
-+ return io->head ? 0 : -ENOMEM;
-+}
-+
-+
-+
-+
-+static int pxa250_stop_fir(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ unsigned int flag;
-+
-+ save_flags(flag);
-+ cli();
-+
-+ pxa250_dma_stop(si->txdma_ch);
-+ pxa250_dma_stop(si->rxdma_ch);
-+
-+ if (si->txskb)
-+ dev_kfree_skb_irq(si->txskb);
-+
-+ ICCR0 &= ~(ICCR0_RXE | ICCR0_TXE );
-+ disable_irq(si->fir_irq);
-+ CKEN &= ~CKEN13_FICP;
-+
-+ restore_flags(flag);
-+
-+ return 0;
-+}
-+
-+
-+
-+static int pxa250_irda_set_speed(struct net_device *dev, int speed)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ int brd, ret = -EINVAL;
-+ static int last_fir_speed=0;
-+
-+ __ECHO_IN;
-+
-+
-+
-+ switch (speed) {
-+ case 9600: case 19200: case 38400:
-+ case 57600: case 115200:
-+
-+ /* Baud rate fixed - Clo */
-+
-+ /*
-+ * FIXME
-+ */
-+ if (last_fir_speed)
-+ {
-+
-+ pxa250_stop_fir(dev);
-+ set_GPIO_mode (GPIO46_STRXD_MD);
-+ set_GPIO_mode (GPIO47_STTXD_MD);
-+
-+ enable_irq(dev->irq);
-+ netif_wake_queue(dev);
-+ last_fir_speed=0;
-+ }
-+
-+
-+ LUB_MISC_WR &= ~(1 << 4);
-+
-+ brd = 14745600 / (16 * speed);
-+
-+ STLCR |= LCR_DLAB;
-+
-+ STDLH = brd >> 8; /* Clo: set Divisor Latch High */
-+ STDLL = brd & 0xFF; /* Clo: set Devisor Latch Low */
-+
-+ STLCR &= ~LCR_DLAB; /* Clo: clear DLAB bit */
-+
-+ STMCR = MCR_OUT2;
-+
-+ CKEN |= CKEN5_STUART;
-+
-+ ICMR |= ( 1 << 20 );
-+
-+ STLCR = LCR_WLS1 | LCR_WLS0;
-+
-+ SET_SIR_MODE;
-+
-+ STFCR = FCR_TRFIFOE | FCR_RESETTF | FCR_RESETRF | FCR_ITL_1 ;// | FCR_ITL_16;
-+
-+ STIER = IER_UUE | IER_RAVIE | IER_RTIOE;
-+
-+ si->speed = speed;
-+
-+ ret = 0;
-+ break;
-+
-+ case 4000000:
-+
-+ if (last_fir_speed)
-+ goto speed_out;
-+
-+ disable_irq(dev->irq);
-+
-+ pxa250_sir_irda_shutdown(si);
-+ pxa250_fir_irda_startup(si);
-+ pxa250_irda_rx_alloc(si);
-+ ICCR0=0;
-+ pxa250_start_rx_dma(dev);
-+ pxa250_ficp_rx_start();
-+
-+ enable_irq(si->fir_irq);
-+ DBG("enable FIR \n");
-+ si->speed = speed;
-+
-+ netif_wake_queue(dev);
-+ last_fir_speed=1;
-+speed_out:
-+
-+ ret=0;
-+
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ __ECHO_OUT;
-+
-+ return ret;
-+}
-+
-+
-+static int pxa250_irda_net_init(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+ unsigned int baudrate_mask;
-+ int err = -ENOMEM;
-+
-+ si = kmalloc(sizeof(struct pxa250_irda), GFP_KERNEL);
-+ if (!si)
-+ goto out;
-+
-+ memset(si, 0, sizeof(*si));
-+
-+ /*
-+ * Initialise the HP-SIR buffers
-+ */
-+
-+ err = pxa250_irda_init_iobuf(&si->rx_buff, 14384);
-+ if (err)
-+ goto out;
-+ err = pxa250_irda_init_iobuf(&si->tx_buff, 4000);
-+ if (err)
-+ goto out_free_rx;
-+
-+ si->fir_irq = IRQ_ICP;
-+ dev->priv = si;
-+ dev->hard_start_xmit = pxa250_irda_hard_xmit;
-+ dev->open = pxa250_irda_start;
-+ dev->stop = pxa250_irda_stop;
-+ dev->do_ioctl = pxa250_irda_ioctl;
-+ dev->get_stats = pxa250_irda_stats;
-+
-+ irda_device_setup(dev);
-+ irda_init_max_qos_capabilies(&si->qos);
-+
-+ /*
-+ * We support original IRDA up to 115k2. (we don't currently
-+ * support 4Mbps). Min Turn Time set to 1ms or greater.
-+ */
-+ baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-+ baudrate_mask |= IR_4000000 << 8;
-+ si->qos.baud_rate.bits &= baudrate_mask;
-+ si->qos.min_turn_time.bits = 7;
-+
-+ irda_qos_bits_to_value(&si->qos);
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Power-Management is optional.
-+ */
-+ si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, pxa250_irda_pmproc);
-+ if (si->pmdev)
-+ si->pmdev->data = dev;
-+#endif
-+
-+ return 0;
-+
-+ kfree(si->tx_buff.head);
-+out_free_rx:
-+ kfree(si->rx_buff.head);
-+out:
-+ kfree(si);
-+
-+ return err;
-+}
-+
-+/*
-+ * Remove all traces of this driver module from the kernel, so we can't be
-+ * called. Note that the device has already been stopped, so we don't have
-+ * to worry about interrupts or dma.
-+ */
-+static void pxa250_irda_net_uninit(struct net_device *dev)
-+{
-+ struct pxa250_irda *si = dev->priv;
-+
-+ dev->hard_start_xmit = NULL;
-+ dev->open = NULL;
-+ dev->stop = NULL;
-+ dev->do_ioctl = NULL;
-+ dev->get_stats = NULL;
-+ dev->priv = NULL;
-+
-+ pm_unregister(si->pmdev);
-+
-+ kfree(si->tx_buff.head);
-+ kfree(si->rx_buff.head);
-+ kfree(si);
-+}
-+
-+static int __init pxa250_irda_init(void)
-+{
-+ struct net_device *dev;
-+ int err;
-+
-+ /* STUART */
-+ err = request_mem_region(__PREG(STRBR), 0x24, "IrDA") ? 0 : -EBUSY;
-+ if (err)
-+ goto err_mem_1;
-+
-+ /* FIR */
-+ err = request_mem_region(__PREG(ICCR0), 0x1c, "IrDA") ? 0 : -EBUSY;
-+ if (err)
-+ goto err_mem_2;
-+
-+
-+ rtnl_lock();
-+ dev = dev_alloc("irda%d", &err);
-+ if (dev) {
-+ dev->irq = IRQ_STUART;
-+ dev->init = pxa250_irda_net_init;
-+ dev->uninit = pxa250_irda_net_uninit;
-+
-+ err = register_netdevice(dev);
-+
-+ if (err)
-+ kfree(dev);
-+ else
-+ netdev = dev;
-+ }
-+ rtnl_unlock();
-+
-+ if (err) {
-+ release_mem_region(__PREG(ICCR0), 0x1c);
-+err_mem_2:
-+ release_mem_region(__PREG(STRBR), 0x24);
-+ }
-+err_mem_1:
-+ return err;
-+}
-+
-+static void __exit pxa250_irda_exit(void)
-+{
-+ struct net_device *dev = netdev;
-+
-+ netdev = NULL;
-+ if (dev) {
-+ rtnl_lock();
-+ unregister_netdevice(dev);
-+ rtnl_unlock();
-+ }
-+
-+ release_mem_region(__PREG(ICCR0), 0x1c);
-+
-+ release_mem_region(__PREG(STRBR), 0x24);
-+
-+ /*
-+ * We now know that the netdevice is no longer in use, and all
-+ * references to our driver have been removed. The only structure
-+ * which may still be present is the netdevice, which will get
-+ * cleaned up by net/core/dev.c
-+ */
-+}
-+
-+module_init(pxa250_irda_init);
-+module_exit(pxa250_irda_exit);
-+
-+MODULE_AUTHOR("Alexey Lugovskoy Frasenyak Dmitrij");
-+MODULE_DESCRIPTION("PXA250 SIR/FIR");
-+MODULE_LICENSE("GPL");
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/net/smc91x.c
-@@ -0,0 +1,2123 @@
-+/*------------------------------------------------------------------------
-+ . smc91x.c
-+ . This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices.
-+ .
-+ . Copyright (C) 1996 by Erik Stahlman
-+ . Copyright (C) 2001 Standard Microsystems Corporation
-+ . Developed by Simple Network Magic Corporation
-+ . Copyright (C) 2003 Monta Vista Software, Inc.
-+ . Unified SMC91x driver by Nicolas Pitre
-+ .
-+ . This program is free software; you can redistribute it and/or modify
-+ . it under the terms of the GNU General Public License as published by
-+ . the Free Software Foundation; either version 2 of the License, or
-+ . (at your option) any later version.
-+ .
-+ . This program is distributed in the hope that it will be useful,
-+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ . GNU General Public License for more details.
-+ .
-+ . You should have received a copy of the GNU General Public License
-+ . along with this program; if not, write to the Free Software
-+ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ .
-+ . Arguments:
-+ . io = for the base address
-+ . irq = for the IRQ
-+ . nowait = 0 for normal wait states, 1 eliminates additional wait states
-+ .
-+ . original author:
-+ . Erik Stahlman <erik@vt.edu>
-+ .
-+ . hardware multicast code:
-+ . Peter Cammaert <pc@denkart.be>
-+ .
-+ . contributors:
-+ . Daris A Nevil <dnevil@snmc.com>
-+ . Nicolas Pitre <nico@cam.org>
-+ .
-+ . History:
-+ . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
-+ . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
-+ . 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111
-+ . 08/22/01 Scott Anderson merge changes from smc9194 to smc91111
-+ . 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111
-+ . 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support
-+ . 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races,
-+ . more bus abstraction, big cleanup, etc.
-+ ----------------------------------------------------------------------------*/
-+
-+static const char version[] =
-+ "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
-+
-+/* Debugging level */
-+#ifndef SMC_DEBUG
-+#define SMC_DEBUG 0
-+#endif
-+
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/timer.h>
-+#include <linux/errno.h>
-+#include <linux/ioport.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#ifdef CONFIG_PM
-+#include <linux/pm.h>
-+#endif
-+
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+
-+#include "smc91x.h"
-+
-+
-+#ifdef CONFIG_ISA
-+/*
-+ . the LAN91C111 can be at any of the following port addresses. To change,
-+ . for a slightly different card, you can add it to the array. Keep in
-+ . mind that the array must end in zero.
-+*/
-+static unsigned int smc_portlist[] __initdata = {
-+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
-+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
-+};
-+#endif /* CONFIG_ISA */
-+
-+#ifndef SMC_IOADDR
-+# define SMC_IOADDR -1
-+#endif
-+static int io = SMC_IOADDR;
-+
-+#ifndef SMC_IRQ
-+# define SMC_IRQ -1
-+#endif
-+static int irq = SMC_IRQ;
-+
-+#ifndef SMC_NOWAIT
-+# define SMC_NOWAIT 0
-+#endif
-+static int nowait = SMC_NOWAIT;
-+
-+MODULE_PARM(io, "i");
-+MODULE_PARM(irq, "i");
-+MODULE_PARM(nowait, "i");
-+MODULE_PARM_DESC(io, "I/O base address");
-+MODULE_PARM_DESC(irq, "IRQ number");
-+MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
-+
-+
-+/*------------------------------------------------------------------------
-+ .
-+ . The internal workings of the driver. If you are changing anything
-+ . here with the SMC stuff, you should have the datasheet and know
-+ . what you are doing.
-+ .
-+ -------------------------------------------------------------------------*/
-+#define CARDNAME "LAN91x"
-+
-+// Use power-down feature of the chip
-+#define POWER_DOWN 1
-+
-+/*
-+ . Wait time for memory to be free. This probably shouldn't be
-+ . tuned that much, as waiting for this means nothing else happens
-+ . in the system
-+*/
-+#define MEMORY_WAIT_TIME 16
-+
-+/*
-+ . This selects whether TX packets are sent one by one to the SMC91x internal
-+ . memory ans throttled until transmission completes. This may prevent
-+ . RX overruns a litle by keeping much of the memory free for RX packets
-+ . but to the expense of reduced TX throughput and increased IRQ overhead.
-+ . Note this is not a cure for a too slow data bus or too high IRQ latency.
-+ */
-+#define THROTTLE_TX_PKTS 0
-+
-+
-+/* store this information for the driver.. */
-+struct smc_local {
-+
-+ // If I have to wait until memory is available to send
-+ // a packet, I will store the skbuff here, until I get the
-+ // desired memory. Then, I'll send it out and free it.
-+ struct sk_buff *saved_skb;
-+
-+ // these are things that the kernel wants me to keep, so users
-+ // can find out semi-useless statistics of how well the card is
-+ // performing
-+ struct net_device_stats stats;
-+
-+ // version/revision of the SMC91x chip
-+ int version;
-+
-+ // Set to true during the auto-negotiation sequence
-+ int autoneg_active;
-+
-+ // Address of our PHY port
-+ int phyaddr;
-+
-+ // Type of PHY
-+ int phytype;
-+
-+ // Last contents of PHY Register 18
-+ int lastPhy18;
-+
-+ // Contains the current active transmission mode
-+ int tcr_cur_mode;
-+
-+ // Contains the current active receive mode
-+ int rcr_cur_mode;
-+
-+ // Contains the current active receive/phy mode
-+ int rpc_cur_mode;
-+ int ctl_autoneg;
-+ int ctl_rfduplx;
-+ int ctl_rspeed;
-+
-+#ifdef CONFIG_PM
-+ struct pm_dev* pm;
-+#endif
-+
-+};
-+
-+
-+#if SMC_DEBUG > 2
-+#define PRINTK3(args...) printk(args)
-+#else
-+#define PRINTK3(args...) do { } while(0)
-+#endif
-+
-+#if SMC_DEBUG > 1
-+#define PRINTK2(args...) printk(args)
-+#else
-+#define PRINTK2(args...) do { } while(0)
-+#endif
-+
-+#if SMC_DEBUG > 0
-+#define PRINTK1(args...) printk(args)
-+#define PRINTK(args...) printk(args)
-+#else
-+#define PRINTK1(args...) do { } while(0)
-+#define PRINTK(args...) printk(KERN_DEBUG args)
-+#endif
-+
-+#if SMC_DEBUG > 3
-+static void PRINT_PKT(u_char *buf, int length)
-+{
-+ int i;
-+ int remainder;
-+ int lines;
-+
-+ lines = length / 16;
-+ remainder = length % 16;
-+
-+ for (i = 0; i < lines ; i ++) {
-+ int cur;
-+ for (cur = 0; cur < 8; cur++) {
-+ u_char a, b;
-+ a = *buf++;
-+ b = *buf++;
-+ printk("%02x%02x ", a, b);
-+ }
-+ printk("\n");
-+ }
-+ for (i = 0; i < remainder/2 ; i++) {
-+ u_char a, b;
-+ a = *buf++;
-+ b = *buf++;
-+ printk("%02x%02x ", a, b );
-+ }
-+ printk("\n");
-+}
-+#else
-+#define PRINT_PKT(x...) do { } while(0)
-+#endif
-+
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) do { \
-+ unsigned long flags; \
-+ unsigned char mask; \
-+ local_irq_save(flags); \
-+ mask = SMC_GET_INT_MASK(); \
-+ mask |= (x); \
-+ SMC_SET_INT_MASK(mask); \
-+ local_irq_restore(flags); \
-+} while (0)
-+
-+/* this disables an interrupt from the interrupt mask register */
-+#define SMC_DISABLE_INT(x) do { \
-+ unsigned long flags; \
-+ unsigned char mask; \
-+ local_irq_save(flags); \
-+ mask = SMC_GET_INT_MASK(); \
-+ mask &= ~(x); \
-+ SMC_SET_INT_MASK(mask); \
-+ local_irq_restore(flags); \
-+} while (0)
-+
-+/* wait while MMU is busy */
-+#define SMC_WAIT_MMU_BUSY() do { \
-+ if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \
-+ unsigned long timeout = jiffies + 2; \
-+ while (SMC_GET_MMU_CMD() & MC_BUSY) { \
-+ if (time_after(jiffies, timeout)) { \
-+ printk("%s: timeout %s line %d\n", \
-+ dev->name, __FILE__, __LINE__); \
-+ break; \
-+ } \
-+ } \
-+ } \
-+} while (0)
-+
-+
-+/* this does a soft reset on the device */
-+static void
-+smc_reset(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int status;
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* This resets the registers mostly to defaults, but doesn't
-+ affect EEPROM. That seems unnecessary */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_SOFTRST );
-+
-+ /* Setup the Configuration Register */
-+ /* This is necessary because the CONFIG_REG is not affected */
-+ /* by a soft reset */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( CONFIG_DEFAULT );
-+
-+ /* Setup for fast accesses if requested */
-+ /* If the card/system can't handle it then there will */
-+ /* be no recovery except for a hard reset or power cycle */
-+ if (nowait)
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT );
-+
-+#ifdef POWER_DOWN
-+ /* Release from possible power-down state */
-+ /* Configuration register is not affected by Soft Reset */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN );
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+ status &= ~PHY_CNTL_PDN;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+#endif
-+
-+ /* this should pause enough for the chip to be happy */
-+ udelay(1);
-+
-+ /* Disable transmit and receive functionality */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_CLEAR );
-+ SMC_SET_TCR( TCR_CLEAR );
-+
-+ /* set the control register to automatically
-+ release successfully transmitted packets, to make the best
-+ use out of our limited memory */
-+ SMC_SELECT_BANK( 1 );
-+#if ! THROTTLE_TX_PKTS
-+ SMC_SET_CTL( SMC_GET_CTL() | CTL_AUTO_RELEASE );
-+#else
-+ SMC_SET_CTL( SMC_GET_CTL() & ~CTL_AUTO_RELEASE );
-+#endif
-+
-+ /* Disable all interrupts */
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* Reset the MMU */
-+ SMC_SET_MMU_CMD( MC_RESET );
-+ SMC_WAIT_MMU_BUSY();
-+}
-+
-+/* Enable Interrupts, Receive, and Transmit */
-+static void
-+smc_enable(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int mask;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* see the header file for options in TCR/RCR DEFAULT*/
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+
-+ /* now, enable interrupts */
-+ mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
-+ if (lp->version >= 0x70)
-+ mask |= IM_MDINT;
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( mask );
-+}
-+
-+/* this puts the device in an inactive state */
-+static void
-+smc_shutdown(struct net_device *dev)
-+{
-+ int ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int status;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ /* no more interrupts for me */
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* and tell the card to stay away from that nasty outside world */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RCR( RCR_CLEAR );
-+ SMC_SET_TCR( TCR_CLEAR );
-+
-+#ifdef POWER_DOWN
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+ status |= PHY_CNTL_PDN;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
-+
-+ /* finally, shut the chip down */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_CONFIG( SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN );
-+#endif
-+}
-+
-+/* This is the procedure to handle the receipt of a packet. */
-+static inline void
-+smc_rcv(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ unsigned int packet_number, status, packet_len;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ packet_number = SMC_GET_RXFIFO();
-+ if (unlikely(packet_number & RXFIFO_REMPTY)) {
-+ PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
-+ return;
-+ }
-+
-+ /* read from start of packet */
-+ SMC_SET_PTR( PTR_READ | PTR_RCV | PTR_AUTOINC );
-+
-+ /* First two words are status and packet length */
-+ SMC_GET_PKT_HDR(status, packet_len);
-+ packet_len &= 0x07ff; /* mask off top bits */
-+ PRINTK2("%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
-+ dev->name, packet_number, status,
-+ packet_len, packet_len);
-+
-+ if (unlikely(status & RS_ERRORS)) {
-+ lp->stats.rx_errors++;
-+ if (status & RS_ALGNERR)
-+ lp->stats.rx_frame_errors++;
-+ if (status & (RS_TOOSHORT | RS_TOOLONG))
-+ lp->stats.rx_length_errors++;
-+ if (status & RS_BADCRC)
-+ lp->stats.rx_crc_errors++;
-+ } else {
-+ struct sk_buff *skb;
-+ unsigned char *data;
-+ unsigned int data_len;
-+
-+ /* set multicast stats */
-+ if (status & RS_MULTICAST)
-+ lp->stats.multicast++;
-+
-+ /*
-+ * Actual payload is packet_len - 4 (or 3 if odd byte).
-+ * We want skb_reserve(2) and the final ctrl word
-+ * (2 bytes, possibly containing the payload odd byte).
-+ * Ence packet_len - 4 + 2 + 2.
-+ */
-+ skb = dev_alloc_skb(packet_len);
-+ if (unlikely(skb == NULL)) {
-+ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-+ dev->name);
-+ lp->stats.rx_dropped++;
-+ goto done;
-+ }
-+
-+ /* Align IP header to 32 bits */
-+ skb_reserve(skb, 2);
-+
-+ /* BUG: the LAN91C111 rev A never sets this bit. Force it. */
-+ if (lp->version == 0x90)
-+ status |= RS_ODDFRAME;
-+
-+ /*
-+ * If odd length: packet_len - 3,
-+ * otherwise packet_len - 4.
-+ */
-+ data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4);
-+ data = skb_put(skb, data_len);
-+ SMC_PULL_DATA(data, packet_len - 2);
-+
-+ PRINT_PKT(data, packet_len - 2);
-+
-+ dev->last_rx = jiffies;
-+ skb->dev = dev;
-+ skb->protocol = eth_type_trans(skb, dev);
-+ netif_rx(skb);
-+ lp->stats.rx_packets++;
-+ lp->stats.rx_bytes += data_len;
-+ }
-+
-+done:
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_MMU_CMD( MC_RELEASE );
-+}
-+
-+/*
-+ * This is called to actually send a packet to the chip.
-+ * Returns non-zero when successful.
-+ */
-+static void
-+smc_hardware_send_packet(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ struct sk_buff *skb = lp->saved_skb;
-+ unsigned int packet_no, len;
-+ unsigned char *buf;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ if (unlikely(!skb)) {
-+ printk ("%s: In XMIT with no packet to send\n", dev->name);
-+ return;
-+ }
-+
-+ packet_no = SMC_GET_AR();
-+ if (unlikely(packet_no & AR_FAILED)) {
-+ printk("%s: Memory allocation failed.\n", dev->name);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_fifo_errors++;
-+ dev_kfree_skb_any(skb);
-+ return;
-+ }
-+
-+ /* point to the beginning of the packet */
-+ SMC_SET_PN( packet_no );
-+ SMC_SET_PTR( PTR_AUTOINC );
-+
-+ buf = skb->data;
-+ len = skb->len;
-+ PRINTK2("%s: TX PNR 0x%x lENGTH 0x%04x (%d) BUF 9x%p\n",
-+ dev->name, packet_no, len, len, buf);
-+ PRINT_PKT(buf, len);
-+
-+ /*
-+ * Send the packet length ( +6 for status words, length, and ctl.
-+ * The card will pad to 64 bytes with zeroes if packet is too small.
-+ */
-+ SMC_PUT_PKT_HDR(0, len + 6);
-+
-+ /* send the actual data */
-+ SMC_PUSH_DATA(buf, len & ~1);
-+
-+ /* Send final ctl word with the last byte if there is one */
-+ SMC_outw( ((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG );
-+
-+ /* and let the chipset deal with it */
-+ SMC_SET_MMU_CMD( MC_ENQUEUE );
-+ SMC_ACK_INT( IM_TX_EMPTY_INT );
-+
-+ dev->trans_start = jiffies;
-+ dev_kfree_skb_any(skb);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_packets++;
-+ lp->stats.tx_bytes += len;
-+}
-+
-+/*
-+ . Since I am not sure if I will have enough room in the chip's ram
-+ . to store the packet, I call this routine which either sends it
-+ . now, or set the card to generates an interrupt when ready
-+ . for the packet.
-+ */
-+static int
-+smc_hard_start_xmit( struct sk_buff * skb, struct net_device * dev )
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ unsigned int numPages, poll_count, status, saved_bank;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ if (unlikely(lp->saved_skb != NULL)) {
-+ /* THIS SHOULD NEVER HAPPEN. */
-+ printk( KERN_CRIT
-+ "%s: Bad Craziness - sent packet while busy.\n",
-+ dev->name );
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_aborted_errors++;
-+ return 1;
-+ }
-+ lp->saved_skb = skb;
-+
-+ /*
-+ ** The MMU wants the number of pages to be the number of 256 bytes
-+ ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
-+ **
-+ ** The 91C111 ignores the size bits, but the code is left intact
-+ ** for backwards and future compatibility.
-+ **
-+ ** Pkt size for allocating is data length +6 (for additional status
-+ ** words, length and ctl!)
-+ **
-+ ** If odd size then last byte is included in ctl word.
-+ */
-+ numPages = ((skb->len & ~1) + (6 - 1)) >> 8;
-+ if (unlikely(numPages > 7)) {
-+ printk("%s: Far too big packet error.\n", dev->name);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 0;
-+ }
-+
-+ /* now, try to allocate the memory */
-+ saved_bank = SMC_CURRENT_BANK();
-+ SMC_SELECT_BANK( 2 );
-+ SMC_SET_MMU_CMD( MC_ALLOC | numPages );
-+
-+ /*
-+ * Poll the chip for a short amount of time in case the
-+ * allocation succeeds quickly.
-+ */
-+ poll_count = MEMORY_WAIT_TIME;
-+ do {
-+ status = SMC_GET_INT();
-+ if (status & IM_ALLOC_INT) {
-+ SMC_ACK_INT( IM_ALLOC_INT );
-+ break;
-+ }
-+ } while (--poll_count);
-+
-+ if (!poll_count) {
-+ /* oh well, wait until the chip finds memory later */
-+ netif_stop_queue(dev);
-+ PRINTK2("%s: TX memory allocation deferred.\n", dev->name);
-+ SMC_ENABLE_INT( IM_ALLOC_INT );
-+ } else {
-+ /* Send current packet immediately.. */
-+#if THROTTLE_TX_PKTS
-+ netif_stop_queue(dev);
-+#endif
-+ smc_hardware_send_packet(dev);
-+ SMC_ENABLE_INT( IM_TX_INT | IM_TX_EMPTY_INT );
-+ }
-+
-+ SMC_SELECT_BANK( saved_bank );
-+ return 0;
-+}
-+
-+/*
-+ . This handles a TX interrupt, which is only called when an error
-+ . relating to a packet is sent or CTL_AUTO_RELEASE is not set.
-+*/
-+static void
-+smc_tx(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned int saved_packet, packet_no, tx_status, pkt_len;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* If the TX FIFO is empty then nothing to do */
-+ packet_no = SMC_GET_TXFIFO();
-+ if (unlikely(packet_no & TXFIFO_TEMPTY)) {
-+ PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
-+ return;
-+ }
-+
-+ /* select packet to read from */
-+ saved_packet = SMC_GET_PN();
-+ SMC_SET_PN( packet_no );
-+
-+ /* read the first word (status word) from this packet */
-+ SMC_SET_PTR( PTR_AUTOINC | PTR_READ );
-+ SMC_GET_PKT_HDR(tx_status, pkt_len);
-+ PRINTK2("%s: TX STATUS 0x%04x PNR 0x%02x\n",
-+ dev->name, tx_status, packet_no);
-+
-+ if (!(tx_status & TS_SUCCESS))
-+ lp->stats.tx_errors++;
-+ if (tx_status & TS_LOSTCAR)
-+ lp->stats.tx_carrier_errors++;
-+ if (tx_status & TS_LATCOL) {
-+ printk( KERN_DEBUG
-+ "%s: Late collision occurred on last xmit.\n",
-+ dev->name);
-+ lp->stats.tx_window_errors++;
-+ }
-+
-+ /* kill the packet */
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_MMU_CMD( MC_FREEPKT );
-+
-+ /* Don't restore Packet Number Reg until busy bit is cleared */
-+ SMC_WAIT_MMU_BUSY();
-+ SMC_SET_PN( saved_packet );
-+
-+ /* re-enable transmit */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+ SMC_SELECT_BANK( 2 );
-+}
-+
-+
-+//---PHY CONTROL AND CONFIGURATION-----------------------------------------
-+
-+/*------------------------------------------------------------
-+ . Debugging function for viewing MII Management serial bitstream
-+ .-------------------------------------------------------------*/
-+#if SMC_DEBUG > 3
-+static void
-+PRINT_MII_STREAM(u_char *bits, int size)
-+{
-+ int i;
-+
-+ printk("BIT#:");
-+ for (i = 0; i < size; ++i)
-+ printk("%d", i%10);
-+
-+ printk("\nMDOE:");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDOE)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\nMDO :");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDO)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\nMDI :");
-+ for (i = 0; i < size; ++i) {
-+ if (bits[i] & MII_MDI)
-+ printk("1");
-+ else
-+ printk("0");
-+ }
-+
-+ printk("\n");
-+}
-+#else
-+#define PRINT_MII_STREAM(x...)
-+#endif
-+
-+/*------------------------------------------------------------
-+ . Reads a register from the MII Management serial interface
-+ .-------------------------------------------------------------*/
-+static int
-+smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg)
-+{
-+ int oldBank;
-+ int i, mask, mii_reg;
-+ u_char bits[64];
-+ int input_idx, phydata;
-+ int clk_idx = 0;
-+
-+ // 32 consecutive ones on MDO to establish sync
-+ for (i = 0; i < 32; ++i)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Start code <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Read command <10>
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Output the PHY address, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyaddr & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Output the phy register number, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyreg & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Tristate and turnaround (2 bit times)
-+ bits[clk_idx++] = 0;
-+ //bits[clk_idx++] = 0;
-+
-+ // Input starts at this bit time
-+ input_idx = clk_idx;
-+
-+ // Will input 16 bits
-+ for (i = 0; i < 16; ++i)
-+ bits[clk_idx++] = 0;
-+
-+ // Final clock bit
-+ bits[clk_idx++] = 0;
-+
-+ // Save the current bank
-+ oldBank = SMC_CURRENT_BANK();
-+
-+ // Select bank 3
-+ SMC_SELECT_BANK( 3 );
-+
-+ // Get the current MII register value
-+ mii_reg = SMC_GET_MII();
-+
-+ // Turn off all MII Interface bits
-+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-+
-+ // Clock all 64 cycles
-+ for (i = 0; i < sizeof bits; ++i) {
-+ // Clock Low - output data
-+ SMC_SET_MII( mii_reg | bits[i] );
-+ udelay(50);
-+
-+ // Clock Hi - input data
-+ SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
-+ udelay(50);
-+ bits[i] |= SMC_GET_MII() & MII_MDI;
-+ }
-+
-+ // Return to idle state
-+ // Set clock to low, data to low, and output tristated
-+ SMC_SET_MII( mii_reg );
-+ udelay(50);
-+
-+ // Restore original bank select
-+ SMC_SELECT_BANK( oldBank );
-+
-+ // Recover input data
-+ phydata = 0;
-+ for (i = 0; i < 16; ++i) {
-+ phydata <<= 1;
-+
-+ if (bits[input_idx++] & MII_MDI)
-+ phydata |= 0x0001;
-+ }
-+
-+ PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
-+ __FUNCTION__, phyaddr, phyreg, phydata);
-+ PRINT_MII_STREAM(bits, sizeof(bits));
-+
-+ return phydata;
-+}
-+
-+/*------------------------------------------------------------
-+ . Writes a register to the MII Management serial interface
-+ .-------------------------------------------------------------*/
-+static void
-+smc_write_phy_register( unsigned long ioaddr, int phyaddr,
-+ int phyreg, int phydata )
-+{
-+ int oldBank;
-+ int i, mask, mii_reg;
-+ u_char bits[65];
-+ int clk_idx = 0;
-+
-+ // 32 consecutive ones on MDO to establish sync
-+ for (i = 0; i < 32; ++i)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Start code <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Write command <01>
-+ bits[clk_idx++] = MII_MDOE;
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+
-+ // Output the PHY address, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyaddr & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Output the phy register number, msb first
-+ mask = 0x10;
-+ for (i = 0; i < 5; ++i) {
-+ if (phyreg & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Tristate and turnaround (2 bit times)
-+ bits[clk_idx++] = 0;
-+ bits[clk_idx++] = 0;
-+
-+ // Write out 16 bits of data, msb first
-+ mask = 0x8000;
-+ for (i = 0; i < 16; ++i) {
-+ if (phydata & mask)
-+ bits[clk_idx++] = MII_MDOE | MII_MDO;
-+ else
-+ bits[clk_idx++] = MII_MDOE;
-+
-+ // Shift to next lowest bit
-+ mask >>= 1;
-+ }
-+
-+ // Final clock bit (tristate)
-+ bits[clk_idx++] = 0;
-+
-+ // Save the current bank
-+ oldBank = SMC_CURRENT_BANK();
-+
-+ // Select bank 3
-+ SMC_SELECT_BANK( 3 );
-+
-+ // Get the current MII register value
-+ mii_reg = SMC_GET_MII();
-+
-+ // Turn off all MII Interface bits
-+ mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
-+
-+ // Clock all cycles
-+ for (i = 0; i < sizeof bits; ++i) {
-+ // Clock Low - output data
-+ SMC_SET_MII( mii_reg | bits[i] );
-+ udelay(50);
-+
-+ // Clock Hi - input data
-+ SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
-+ udelay(50);
-+ bits[i] |= SMC_GET_MII() & MII_MDI;
-+ }
-+
-+ // Return to idle state
-+ // Set clock to low, data to low, and output tristated
-+ SMC_SET_MII( mii_reg );
-+ udelay(50);
-+
-+ // Restore original bank select
-+ SMC_SELECT_BANK( oldBank );
-+
-+ PRINTK3("%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
-+ __FUNCTION__, phyaddr, phyreg, phydata);
-+ PRINT_MII_STREAM(bits, sizeof(bits));
-+}
-+
-+
-+/*------------------------------------------------------------
-+ . Finds and reports the PHY address
-+ .-------------------------------------------------------------*/
-+static int smc_detect_phy(struct net_device* dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+ int phy_id1, phy_id2;
-+ int phyaddr;
-+ int found = 0;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ // Scan all 32 PHY addresses if necessary
-+ for (phyaddr = 0; phyaddr < 32; ++phyaddr) {
-+ // Read the PHY identifiers
-+ phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
-+ phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
-+
-+ PRINTK3("%s: phy_id1=0x%x, phy_id2=0x%x\n",
-+ dev->name, phy_id1, phy_id2);
-+
-+ // Make sure it is a valid identifier
-+ if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
-+ (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) {
-+ if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) {
-+ // Save the PHY's address
-+ lp->phyaddr = phyaddr;
-+ found = 1;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!found) {
-+ PRINTK("%s: No PHY found\n", dev->name);
-+ return(0);
-+ }
-+
-+ // Set the PHY type
-+ if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) {
-+ lp->phytype = PHY_LAN83C183;
-+ PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name);
-+ }
-+
-+ if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) {
-+ lp->phytype = PHY_LAN83C180;
-+ PRINTK("%s: PHY=LAN83C180\n", dev->name);
-+ }
-+
-+ return 1;
-+}
-+
-+/*------------------------------------------------------------
-+ . Waits the specified number of milliseconds - kernel friendly
-+ .-------------------------------------------------------------*/
-+static void
-+smc_wait_ms(unsigned int ms)
-+{
-+ if (!in_interrupt()) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(1 + ms * HZ / 1000);
-+ } else {
-+ /* if this happens it must be fixed */
-+ printk( KERN_WARNING "%s: busy wait while in interrupt!\n",
-+ __FUNCTION__);
-+ mdelay(ms);
-+ }
-+}
-+
-+/*------------------------------------------------------------
-+ . Sets the PHY to a configuration as determined by the user
-+ .-------------------------------------------------------------*/
-+static int
-+smc_phy_fixed(struct net_device *dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int my_fixed_caps, cfg1;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ // Enter Link Disable state
-+ cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG);
-+ cfg1 |= PHY_CFG1_LNKDIS;
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1);
-+
-+ // Set our fixed capabilities
-+ // Disable auto-negotiation
-+ my_fixed_caps = 0;
-+
-+ if (lp->ctl_rfduplx)
-+ my_fixed_caps |= PHY_CNTL_DPLX;
-+
-+ if (lp->ctl_rspeed == 100)
-+ my_fixed_caps |= PHY_CNTL_SPEED;
-+
-+ // Write our capabilities to the phy control register
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps);
-+
-+ // Re-Configure the Receive/Phy Control register
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+
-+ // Success
-+ return(1);
-+}
-+
-+/*------------------------------------------------------------
-+ . Configures the specified PHY through the MII management interface
-+ . using Autonegotiation.
-+ . Calls smc_phy_fixed() if the user has requested a certain config.
-+ .-------------------------------------------------------------*/
-+static void
-+smc_phy_configure(struct net_device* dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int timeout;
-+ int phyaddr;
-+ int my_phy_caps; // My PHY capabilities
-+ int my_ad_caps; // My Advertised capabilities
-+ int status;
-+
-+ PRINTK3("%s:smc_program_phy()\n", dev->name);
-+
-+ // Set the blocking flag
-+ lp->autoneg_active = 1;
-+
-+ // Find the address and type of our phy
-+ if (!smc_detect_phy(dev))
-+ goto smc_phy_configure_exit;
-+
-+ // Get the detected phy address
-+ phyaddr = lp->phyaddr;
-+
-+ // Reset the PHY, setting all other bits to zero
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
-+
-+ // Wait for the reset to complete, or time out
-+ timeout = 6; // Wait up to 3 seconds
-+ while (timeout--) {
-+ if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
-+ & PHY_CNTL_RST))
-+ // reset complete
-+ break;
-+ smc_wait_ms(500); // wait 500 millisecs
-+ if (signal_pending(current)) { // Exit anyway if signaled
-+ PRINTK("%s: PHY reset interrupted by signal\n",
-+ dev->name);
-+ timeout = 0;
-+ break;
-+ }
-+ }
-+
-+ if (timeout < 1) {
-+ printk("%s: PHY reset timed out\n", dev->name);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ // Read PHY Register 18, Status Output
-+ lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
-+
-+ // Enable PHY Interrupts (for register 18)
-+ // Interrupts listed here are disabled
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
-+ PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
-+ PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
-+ PHY_INT_SPDDET | PHY_INT_DPLXDET);
-+
-+ /* Configure the Receive/Phy Control register */
-+ SMC_SELECT_BANK( 0 );
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+
-+ // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
-+ my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+
-+ // If the user requested no auto neg, then go set his request
-+ if (!(lp->ctl_autoneg)) {
-+ smc_phy_fixed(dev);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ if( !( my_phy_caps & PHY_STAT_CAP_ANEG))
-+ {
-+ printk(KERN_INFO "Auto negotiation NOT supported\n");
-+ smc_phy_fixed(dev);
-+ goto smc_phy_configure_exit;
-+ }
-+
-+ my_ad_caps = PHY_AD_CSMA; // I am CSMA capable
-+
-+ if (my_phy_caps & PHY_STAT_CAP_T4)
-+ my_ad_caps |= PHY_AD_T4;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TXF)
-+ my_ad_caps |= PHY_AD_TX_FDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TXH)
-+ my_ad_caps |= PHY_AD_TX_HDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TF)
-+ my_ad_caps |= PHY_AD_10_FDX;
-+
-+ if (my_phy_caps & PHY_STAT_CAP_TH)
-+ my_ad_caps |= PHY_AD_10_HDX;
-+
-+ // Disable capabilities not selected by our user
-+ if (lp->ctl_rspeed != 100)
-+ my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);
-+
-+ if (!lp->ctl_rfduplx)
-+ my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);
-+
-+ // Update our Auto-Neg Advertisement Register
-+ smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
-+
-+ // Read the register back. Without this, it appears that when
-+ // auto-negotiation is restarted, sometimes it isn't ready and
-+ // the link does not come up.
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG);
-+
-+ PRINTK2("%s: phy caps=%x\n", dev->name, my_phy_caps);
-+ PRINTK2("%s: phy advertised caps=%x\n", dev->name, my_ad_caps);
-+
-+ // Restart auto-negotiation process in order to advertise my caps
-+ smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
-+ PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
-+
-+ // Wait for the auto-negotiation to complete. This may take from
-+ // 2 to 3 seconds.
-+ // Wait for the reset to complete, or time out
-+ timeout = 20; // Wait up to 10 seconds
-+ while (timeout--) {
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_RMT_REG);
-+ if (status & PHY_AD_ACK)
-+ // auto-negotiate complete
-+ break;
-+
-+ smc_wait_ms(500); // wait 500 millisecs
-+ if (signal_pending(current)) { // Exit anyway if signaled
-+ printk(KERN_DEBUG
-+ "%s: PHY auto-negotiate interrupted by signal\n",
-+ dev->name);
-+ timeout = 0;
-+ break;
-+ }
-+ }
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+
-+ if (timeout < 1) {
-+ PRINTK("%s: PHY auto-negotiate timed out\n", dev->name);
-+ }
-+
-+ // Fail if we detected an auto-negotiate remote fault
-+ if (status & PHY_STAT_REM_FLT) {
-+ PRINTK("%s: PHY remote fault detected\n", dev->name);
-+ }
-+
-+ // Wait for link. Once the link is up, phy18 should be up to date
-+ timeout = 200;
-+ do
-+ {
-+ udelay(100);
-+ status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
-+ } while ( ((status & PHY_STAT_LINK)==0) && --timeout);
-+
-+ if (status & PHY_STAT_LINK)
-+ {
-+ PRINTK("%s: Ethernet Link Detected\n", dev->name);
-+ }
-+
-+ // The smc_phy_interrupt() routine will be called to update lastPhy18
-+
-+ // Set our sysctl parameters to match auto-negotiation results
-+ if ( lp->lastPhy18 & PHY_INT_SPDDET ) {
-+ PRINTK("%s: PHY 100BaseT\n", dev->name);
-+ lp->rpc_cur_mode |= RPC_SPEED;
-+ } else {
-+ PRINTK("%s: PHY 10BaseT\n", dev->name);
-+ lp->rpc_cur_mode &= ~RPC_SPEED;
-+ }
-+
-+ if ( lp->lastPhy18 & PHY_INT_DPLXDET ) {
-+ PRINTK("%s: PHY Full Duplex\n", dev->name);
-+ lp->rpc_cur_mode |= RPC_DPLX;
-+ lp->tcr_cur_mode |= TCR_SWFDUP;
-+ } else {
-+ PRINTK("%s: PHY Half Duplex\n", dev->name);
-+ lp->rpc_cur_mode &= ~RPC_DPLX;
-+ lp->tcr_cur_mode &= ~TCR_SWFDUP;
-+ }
-+
-+ // Re-Configure the Receive/Phy Control register and TCR
-+ SMC_SET_RPC( lp->rpc_cur_mode );
-+ SMC_SET_TCR( lp->tcr_cur_mode );
-+
-+smc_phy_configure_exit:
-+ // Exit auto-negotiation
-+ lp->autoneg_active = 0;
-+}
-+
-+/*************************************************************************
-+ . smc_phy_interrupt
-+ .
-+ . Purpose: Handle interrupts relating to PHY register 18. This is
-+ . called from the "hard" interrupt handler.
-+ .
-+ ************************************************************************/
-+static void
-+smc_phy_interrupt(struct net_device* dev)
-+{
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int phyaddr = lp->phyaddr;
-+ int phy18;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ for(;;) {
-+ // Read PHY Register 18, Status Output
-+ phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
-+
-+ // Exit if not more changes
-+ if (phy18 == lp->lastPhy18)
-+ break;
-+
-+#if SMC_DEBUG > 1
-+ PRINTK2("%s: phy18=0x%04x\n", dev->name, phy18);
-+ PRINTK2("%s: lastPhy18=0x%04x\n", dev->name, lp->lastPhy18);
-+
-+ // Handle events
-+ if ((phy18 & PHY_INT_LNKFAIL) !=
-+ (lp->lastPhy18 & PHY_INT_LNKFAIL))
-+ PRINTK2("%s: PHY Link Fail=%x\n", dev->name,
-+ phy18 & PHY_INT_LNKFAIL);
-+
-+ if ((phy18 & PHY_INT_LOSSSYNC) !=
-+ (lp->lastPhy18 & PHY_INT_LOSSSYNC))
-+ PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name,
-+ phy18 & PHY_INT_LOSSSYNC);
-+
-+ if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD))
-+ PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name,
-+ phy18 & PHY_INT_CWRD);
-+
-+ if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD))
-+ PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name,
-+ phy18 & PHY_INT_SSD);
-+
-+ if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD))
-+
-+ PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name,
-+ phy18 & PHY_INT_ESD);
-+
-+ if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL))
-+ PRINTK2("%s: PHY Reverse Polarity Detected=%x\n",
-+ dev->name, phy18 & PHY_INT_RPOL);
-+
-+ if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB))
-+ PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name,
-+ phy18 & PHY_INT_JAB);
-+
-+ if ((phy18 & PHY_INT_SPDDET) !=
-+ (lp->lastPhy18 & PHY_INT_SPDDET))
-+ PRINTK2("%s: PHY Speed Detect=%x\n", dev->name,
-+ phy18 & PHY_INT_SPDDET);
-+
-+ if ((phy18 & PHY_INT_DPLXDET) !=
-+ (lp->lastPhy18 & PHY_INT_DPLXDET))
-+ PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name,
-+ phy18 & PHY_INT_DPLXDET);
-+#endif
-+ // Update the last phy 18 variable
-+ lp->lastPhy18 = phy18;
-+ }
-+}
-+
-+//--- END PHY CONTROL AND CONFIGURATION-------------------------------------
-+
-+
-+/*
-+ * This is the main routine of the driver, to handle the device when
-+ * it needs some attention.
-+ */
-+static void
-+smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = dev_id;
-+ unsigned long ioaddr = dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ int status, mask, timeout, card_stats;
-+ int saved_bank, saved_pointer;
-+
-+ PRINTK3("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ saved_bank = SMC_CURRENT_BANK();
-+ SMC_SELECT_BANK(2);
-+ saved_pointer = SMC_GET_PTR();
-+ mask = SMC_GET_INT_MASK();
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* set a timeout value, so I don't stay here forever */
-+ timeout = 8;
-+
-+ do {
-+ status = SMC_GET_INT();
-+
-+ PRINTK2("%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
-+ dev->name, status, mask,
-+ ({ int meminfo; SMC_SELECT_BANK(0);
-+ meminfo = SMC_GET_MIR();
-+ SMC_SELECT_BANK(2); meminfo; }),
-+ SMC_GET_FIFO());
-+
-+ status &= mask;
-+ if (!status)
-+ break;
-+
-+ if (status & IM_RCV_INT) {
-+ PRINTK3("%s: RX irq\n", dev->name);
-+ smc_rcv(dev);
-+ } else if (status & IM_TX_INT) {
-+ PRINTK3("%s: TX int\n", dev->name);
-+ smc_tx(dev);
-+ SMC_ACK_INT( IM_TX_INT );
-+#if THROTTLE_TX_PKTS
-+ netif_wake_queue(dev);
-+#endif
-+ } else if (status & IM_ALLOC_INT) {
-+ PRINTK3("%s: Allocation irq\n", dev->name);
-+ smc_hardware_send_packet(dev);
-+ mask |= (IM_TX_INT | IM_TX_EMPTY_INT);
-+ mask &= ~IM_ALLOC_INT;
-+#if ! THROTTLE_TX_PKTS
-+ netif_wake_queue(dev);
-+#endif
-+ } else if (status & IM_TX_EMPTY_INT) {
-+ PRINTK3("%s: TX empty\n", dev->name);
-+ mask &= ~IM_TX_EMPTY_INT;
-+
-+ /* update stats */
-+ SMC_SELECT_BANK( 0 );
-+ card_stats = SMC_GET_COUNTER();
-+ SMC_SELECT_BANK( 2 );
-+
-+ /* single collisions */
-+ lp->stats.collisions += card_stats & 0xF;
-+ card_stats >>= 4;
-+
-+ /* multiple collisions */
-+ lp->stats.collisions += card_stats & 0xF;
-+ } else if (status & IM_RX_OVRN_INT) {
-+ PRINTK1( "%s: RX overrun\n", dev->name);
-+ SMC_ACK_INT( IM_RX_OVRN_INT );
-+ lp->stats.rx_errors++;
-+ lp->stats.rx_fifo_errors++;
-+ } else if (status & IM_EPH_INT) {
-+ PRINTK("%s: UNSUPPORTED: EPH INTERRUPT\n", dev->name);
-+ } else if (status & IM_MDINT) {
-+ SMC_ACK_INT( IM_MDINT );
-+ smc_phy_interrupt(dev);
-+ } else if (status & IM_ERCV_INT ) {
-+ SMC_ACK_INT( IM_ERCV_INT );
-+ PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
-+ }
-+ } while (--timeout);
-+
-+ /* restore register states */
-+ SMC_SET_INT_MASK( mask );
-+ SMC_SET_PTR( saved_pointer );
-+ SMC_SELECT_BANK( saved_bank );
-+
-+ PRINTK3("%s: Interrupt done\n", dev->name);
-+}
-+
-+/* Our watchdog timed out. Called by the networking layer */
-+static void
-+smc_timeout(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ smc_reset(dev);
-+ smc_enable(dev);
-+
-+#if 0
-+ /* Reconfiguring the PHY doesn't seem like a bad idea here, but
-+ * it introduced a problem. Now that this is a timeout routine,
-+ * we are getting called from within an interrupt context.
-+ * smc_phy_configure() calls smc_wait_ms() which calls
-+ * schedule_timeout() which calls schedule(). When schedule()
-+ * is called from an interrupt context, it prints out
-+ * "Scheduling in interrupt" and then calls BUG(). This is
-+ * obviously not desirable. This was worked around by removing
-+ * the call to smc_phy_configure() here because it didn't seem
-+ * absolutely necessary. Ultimately, if smc_wait_ms() is
-+ * supposed to be usable from an interrupt context (which it
-+ * looks like it thinks it should handle), it should be fixed.
-+ */
-+ /* Reconfigure the PHY */
-+ smc_phy_configure(dev);
-+#endif
-+
-+ /* clear anything saved */
-+ if (lp->saved_skb != NULL) {
-+ dev_kfree_skb (lp->saved_skb);
-+ lp->saved_skb = NULL;
-+ lp->stats.tx_errors++;
-+ lp->stats.tx_aborted_errors++;
-+ }
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+/*
-+ * Finds the CRC32 of a set of bytes.
-+ * (from Peter Cammaert's code)
-+ */
-+static int
-+crc32(char *s, int length)
-+{
-+ /* indices */
-+ int perByte;
-+ int perBit;
-+ /* crc polynomial for Ethernet */
-+ const unsigned long poly = 0xedb88320;
-+ /* crc value - preinitialized to all 1's */
-+ unsigned long crc_value = 0xffffffff;
-+
-+ for ( perByte = 0; perByte < length; perByte ++ ) {
-+ unsigned char c;
-+
-+ c = *(s++);
-+ for ( perBit = 0; perBit < 8; perBit++ ) {
-+ crc_value = (crc_value>>1)^
-+ (((crc_value^c)&0x01)?poly:0);
-+ c >>= 1;
-+ }
-+ }
-+ return crc_value;
-+}
-+
-+/*
-+ . This sets the internal hardware table to filter out unwanted multicast
-+ . packets before they take up memory.
-+ .
-+ . The SMC chip uses a hash table where the high 6 bits of the CRC of
-+ . address are the offset into the table. If that bit is 1, then the
-+ . multicast packet is accepted. Otherwise, it's dropped silently.
-+ .
-+ . To use the 6 bits as an offset into the table, the high 3 bits are the
-+ . number of the 8 bit register, while the low 3 bits are the bit within
-+ . that register.
-+ .
-+ . This routine is based very heavily on the one provided by Peter Cammaert.
-+*/
-+static void
-+smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs)
-+{
-+ int i;
-+ unsigned char multicast_table[ 8 ];
-+ struct dev_mc_list *cur_addr;
-+
-+ /* table for flipping the order of 3 bits */
-+ static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
-+
-+ /* start with a table of all zeros: reject all */
-+ memset( multicast_table, 0, sizeof( multicast_table ) );
-+
-+ cur_addr = addrs;
-+ for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
-+ int position;
-+
-+ /* do we have a pointer here? */
-+ if ( !cur_addr )
-+ break;
-+ /* make sure this is a multicast address - shouldn't this
-+ be a given if we have it here ? */
-+ if ( !( *cur_addr->dmi_addr & 1 ) )
-+ continue;
-+
-+ /* only use the low order bits */
-+ position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f;
-+
-+ /* do some messy swapping to put the bit in the right spot */
-+ multicast_table[invert3[position&7]] |=
-+ (1<<invert3[(position>>3)&7]);
-+
-+ }
-+ /* now, the table can be loaded into the chipset */
-+ SMC_SELECT_BANK( 3 );
-+ SMC_SET_MCAST( multicast_table );
-+}
-+
-+/*
-+ . This routine will, depending on the values passed to it,
-+ . either make it accept multicast packets, go into
-+ . promiscuous mode ( for TCPDUMP and cousins ) or accept
-+ . a select set of multicast packets
-+*/
-+static void smc_set_multicast_list(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ SMC_SELECT_BANK(0);
-+ if ( dev->flags & IFF_PROMISC ) {
-+ PRINTK2("%s: RCR_PRMS\n", dev->name);
-+ lp->rcr_cur_mode |= RCR_PRMS;
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ }
-+
-+/* BUG? I never disable promiscuous mode if multicasting was turned on.
-+ Now, I turn off promiscuous mode, but I don't do anything to multicasting
-+ when promiscuous mode is turned on.
-+*/
-+
-+ /* Here, I am setting this to accept all multicast packets.
-+ I don't need to zero the multicast table, because the flag is
-+ checked before the table is
-+ */
-+ else if (dev->flags & IFF_ALLMULTI) {
-+ lp->rcr_cur_mode |= RCR_ALMUL;
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ PRINTK2("%s: RCR_ALMUL\n", dev->name);
-+ }
-+
-+ /* We just get all multicast packets even if we only want them
-+ . from one source. This will be changed at some future
-+ . point. */
-+ else if (dev->mc_count ) {
-+ /* support hardware multicasting */
-+
-+ /* be sure I get rid of flags I might have set */
-+ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+ /* NOTE: this has to set the bank, so make sure it is the
-+ last thing called. The bank is set to zero at the top */
-+ smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
-+ } else {
-+ PRINTK2("%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name);
-+ lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL);
-+ SMC_SET_RCR( lp->rcr_cur_mode );
-+
-+ /*
-+ since I'm disabling all multicast entirely, I need to
-+ clear the multicast list
-+ */
-+ SMC_SELECT_BANK( 3 );
-+ SMC_CLEAR_MCAST();
-+ }
-+}
-+
-+
-+/*
-+ * Open and Initialize the board
-+ *
-+ * Set up everything, reset the card, etc ..
-+ */
-+static int
-+smc_open(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ unsigned long ioaddr = dev->base_addr;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ /* clear out all the junk that was put here before... */
-+ memset(dev->priv, 0, sizeof(struct smc_local));
-+
-+ // Setup the default Register Modes
-+ lp->tcr_cur_mode = TCR_DEFAULT;
-+ lp->rcr_cur_mode = RCR_DEFAULT;
-+ lp->rpc_cur_mode = RPC_DEFAULT;
-+
-+ /* Set default parameters */
-+#ifdef CONFIG_ARCH_RAMSES
-+ lp->ctl_autoneg = 0;
-+ lp->ctl_rfduplx = 0;
-+ lp->ctl_rspeed = 10;
-+#else
-+ lp->ctl_autoneg = 1;
-+ lp->ctl_rfduplx = 1;
-+ lp->ctl_rspeed = 100;
-+#endif
-+
-+ SMC_SELECT_BANK(3);
-+ lp->version = SMC_GET_REV() & 0xff;
-+
-+ /* reset the hardware */
-+ smc_reset(dev);
-+ smc_enable(dev);
-+
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_MAC_ADDR(dev->dev_addr);
-+
-+ /* Configure the PHY */
-+ if (lp->version >= 0x70)
-+ smc_phy_configure(dev);
-+
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+/*----------------------------------------------------
-+ . smc_close
-+ .
-+ . this makes the board clean up everything that it can
-+ . and not talk to the outside world. Caused by
-+ . an 'ifconfig ethX down'
-+ .
-+ -----------------------------------------------------*/
-+static int
-+smc_close(struct net_device *dev)
-+{
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ netif_stop_queue(dev);
-+
-+ /* clear everything */
-+ smc_shutdown(dev);
-+
-+ return 0;
-+}
-+
-+/*------------------------------------------------------------
-+ . Get the current statistics.
-+ . This may be called with the card open or closed.
-+ .-------------------------------------------------------------*/
-+static struct net_device_stats *
-+smc_query_statistics(struct net_device *dev)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+
-+ PRINTK2("%s: %s\n", dev->name, __FUNCTION__);
-+
-+ return &lp->stats;
-+}
-+
-+/*----------------------------------------------------------------------
-+ . smc_findirq
-+ .
-+ . This routine has a simple purpose -- make the SMC chip generate an
-+ . interrupt, so an auto-detect routine can detect it, and find the IRQ,
-+ ------------------------------------------------------------------------
-+*/
-+int __init
-+smc_findirq( unsigned long ioaddr )
-+{
-+ int timeout = 20;
-+ unsigned long cookie;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ cookie = probe_irq_on();
-+
-+ /*
-+ * What I try to do here is trigger an ALLOC_INT. This is done
-+ * by allocating a small chunk of memory, which will give an interrupt
-+ * when done.
-+ */
-+
-+ /* enable ALLOCation interrupts ONLY */
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT_MASK( IM_ALLOC_INT );
-+
-+ /*
-+ . Allocate 512 bytes of memory. Note that the chip was just
-+ . reset so all the memory is available
-+ */
-+ SMC_SET_MMU_CMD( MC_ALLOC | 1 );
-+
-+ /*
-+ . Wait until positive that the interrupt has been generated
-+ */
-+ do {
-+ int int_status;
-+ udelay(10);
-+ int_status = SMC_GET_INT();
-+ if (int_status & IM_ALLOC_INT)
-+ break; /* got the interrupt */
-+ } while (--timeout);
-+
-+ /* there is really nothing that I can do here if timeout fails,
-+ as autoirq_report will return a 0 anyway, which is what I
-+ want in this case. Plus, the clean up is needed in both
-+ cases. */
-+
-+ /* and disable all interrupts again */
-+ SMC_SET_INT_MASK( 0 );
-+
-+ /* and return what I found */
-+ return probe_irq_off(cookie);
-+}
-+
-+/*----------------------------------------------------------------------
-+ . Function: smc_probe( unsigned long ioaddr )
-+ .
-+ . Purpose:
-+ . Tests to see if a given ioaddr points to an SMC91x chip.
-+ . Returns a 0 on success
-+ .
-+ . Algorithm:
-+ . (1) see if the high byte of BANK_SELECT is 0x33
-+ . (2) compare the ioaddr with the base register's address
-+ . (3) see if I recognize the chip ID in the appropriate register
-+ .
-+ .---------------------------------------------------------------------
-+ */
-+/*---------------------------------------------------------------
-+ . Here I do typical initialization tasks.
-+ .
-+ . o Initialize the structure if needed
-+ . o print out my vanity message if not done so already
-+ . o print out what type of hardware is detected
-+ . o print out the ethernet address
-+ . o find the IRQ
-+ . o set up my private data
-+ . o configure the dev structure with my subroutines
-+ . o actually GRAB the irq.
-+ . o GRAB the region
-+ .-----------------------------------------------------------------
-+*/
-+static int __init
-+smc_probe(struct net_device *dev, unsigned long ioaddr)
-+{
-+ struct smc_local *lp = (struct smc_local *)dev->priv;
-+ static int version_printed = 0;
-+ int i, retval;
-+ unsigned int val, revision_register;
-+ const char *version_string;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+ /* Grab the region so that no one else tries to probe our ioports. */
-+ if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
-+ return -EBUSY;
-+
-+ /* First, see if the high byte is 0x33 */
-+ val = SMC_CURRENT_BANK();
-+ PRINTK2("%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
-+ if ( (val & 0xFF00) != 0x3300 ) {
-+ if ( (val & 0xFF) == 0x33 ) {
-+ printk( KERN_WARNING
-+ "%s: Detected possible byte-swapped interface"
-+ " at IOADDR 0x%lx\n", CARDNAME, ioaddr);
-+ }
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* The above MIGHT indicate a device, but I need to write to further
-+ test this. */
-+ SMC_SELECT_BANK(0);
-+ val = SMC_CURRENT_BANK();
-+ if ( (val & 0xFF00 ) != 0x3300 ) {
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* well, we've already written once, so hopefully another time won't
-+ hurt. This time, I need to switch the bank register to bank 1,
-+ so I can access the base address register */
-+ SMC_SELECT_BANK(1);
-+ val = SMC_GET_BASE();
-+ val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
-+ if ( (ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val ) {
-+ printk( "%s: IOADDR %lx doesn't match configuration (%x).\n",
-+ CARDNAME, ioaddr, val );
-+ }
-+
-+ /* check if the revision register is something that I recognize.
-+ These might need to be added to later, as future revisions
-+ could be added. */
-+ SMC_SELECT_BANK(3);
-+ revision_register = SMC_GET_REV();
-+ PRINTK2("%s: revision = 0x%04x\n", CARDNAME, revision_register);
-+ version_string = chip_ids[ (revision_register >> 4) & 0xF];
-+ if (!version_string || (revision_register & 0xff00) != 0x3300) {
-+ /* I don't recognize this chip, so... */
-+ printk( "%s: IO 0x%lx: Unrecognized revision register 0x%04x"
-+ ", Contact author.\n", CARDNAME,
-+ ioaddr, revision_register);
-+
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+
-+ /* At this point I'll assume that the chip is an SMC91x. */
-+ if (version_printed++ == 0)
-+ printk("%s", version);
-+
-+ /* set the private data to zero by default */
-+ memset(lp, 0, sizeof(struct smc_local));
-+
-+ /* fill in some of the fields */
-+ dev->base_addr = ioaddr;
-+ lp->version = revision_register & 0xff;
-+
-+ /* Get the MAC address */
-+ SMC_SELECT_BANK( 1 );
-+ SMC_GET_MAC_ADDR(dev->dev_addr);
-+
-+ /* now, reset the chip, and put it into a known state */
-+ smc_reset( dev );
-+
-+ /*
-+ . If dev->irq is 0, then the device has to be banged on to see
-+ . what the IRQ is.
-+ .
-+ . This banging doesn't always detect the IRQ, for unknown reasons.
-+ . a workaround is to reset the chip and try again.
-+ .
-+ . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-+ . be what is requested on the command line. I don't do that, mostly
-+ . because the card that I have uses a non-standard method of accessing
-+ . the IRQs, and because this _should_ work in most configurations.
-+ .
-+ . Specifying an IRQ is done with the assumption that the user knows
-+ . what (s)he is doing. No checking is done!!!!
-+ .
-+ */
-+ if ( dev->irq < 1 ) {
-+ int trials;
-+
-+ trials = 3;
-+ while ( trials-- ) {
-+ dev->irq = smc_findirq( ioaddr );
-+ if ( dev->irq )
-+ break;
-+ /* kick the card and try again */
-+ smc_reset( dev );
-+ }
-+ }
-+ if (dev->irq == 0 ) {
-+ printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
-+ dev->name);
-+ retval = -ENODEV;
-+ goto err_out;
-+ }
-+ dev->irq = irq_cannonicalize(dev->irq);
-+
-+ /* now, print out the card info, in a short format.. */
-+ printk( "%s: %s (rev %d) at %#lx IRQ %d%s%s\n",
-+ dev->name, version_string, revision_register & 0x0f,
-+ ioaddr, dev->irq, nowait ? " [nowait]" : "",
-+ THROTTLE_TX_PKTS ? " [throttle_tx]" : "" );
-+
-+ /* Print the Ethernet address */
-+ printk("%s: Ethernet addr: ", dev->name);
-+ for (i = 0; i < 5; i++)
-+ printk("%2.2x:", dev->dev_addr[i] );
-+ printk("%2.2x\n", dev->dev_addr[5] );
-+
-+ /* Fill in the fields of the device structure with ethernet values. */
-+ ether_setup(dev);
-+
-+ /* Grab the IRQ */
-+ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-+ if (retval) {
-+ goto err_out;
-+ }
-+
-+ dev->open = smc_open;
-+ dev->stop = smc_close;
-+ dev->hard_start_xmit = smc_hard_start_xmit;
-+ dev->tx_timeout = smc_timeout;
-+ dev->watchdog_timeo = HZ/10;
-+ dev->get_stats = smc_query_statistics;
-+ dev->set_multicast_list = smc_set_multicast_list;
-+
-+ return 0;
-+
-+err_out:
-+ release_region(ioaddr, SMC_IO_EXTENT);
-+ return retval;
-+}
-+
-+/*-------------------------------------------------------------------------
-+ |
-+ | smc_init( void )
-+ | Input parameters:
-+ | dev->base_addr == 0, try to find all possible locations
-+ | dev->base_addr > 0x1ff, this is the address to check
-+ | dev->base_addr == <anything else>, return failure code
-+ |
-+ | Output:
-+ | 0 --> there is a device
-+ | anything else, error
-+ |
-+ ---------------------------------------------------------------------------
-+*/
-+static struct net_device *global_dev = NULL; /* needs to be fixed */
-+
-+#ifdef CONFIG_PM
-+
-+static int smc_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ unsigned long ioaddr = global_dev->base_addr;
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ smc_shutdown(global_dev);
-+ break;
-+ case PM_RESUME:
-+ smc_reset(global_dev);
-+ smc_enable(global_dev);
-+ SMC_SELECT_BANK( 1 );
-+ SMC_SET_MAC_ADDR(global_dev->dev_addr);
-+ if (lp->version >= 0x70)
-+ smc_phy_configure(global_dev);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+#endif
-+
-+static int __init
-+smc_init(void)
-+{
-+ int ret;
-+
-+ PRINTK2("%s: %s\n", CARDNAME, __FUNCTION__);
-+
-+#ifdef MODULE
-+ if (io == -1)
-+ printk( KERN_WARNING
-+ "%s: You shouldn't use auto-probing with insmod!\n",
-+ CARDNAME );
-+#endif
-+
-+ if (global_dev) {
-+ printk("%s: already initialized.\n", CARDNAME);
-+ return -EBUSY;
-+ }
-+
-+ global_dev = init_etherdev(0, sizeof(struct smc_local));
-+ if (!global_dev) {
-+ printk("%s: could not allocate device.\n", CARDNAME);
-+ return -ENOMEM;
-+ }
-+ SET_MODULE_OWNER(global_dev);
-+
-+ /* copy the parameters from insmod into the device structure */
-+ if (io != -1)
-+ global_dev->base_addr = io;
-+ if (irq != -1)
-+ global_dev->irq = irq;
-+
-+#ifdef CONFIG_ISA
-+ /* try a specific location */
-+ if (global_dev->base_addr > 0x1ff)
-+ ret = smc_probe(global_dev, global_dev->base_addr);
-+ else if (global_dev->base_addr != 0)
-+ ret = -ENXIO;
-+ else {
-+ int i;
-+
-+ /* check every ethernet address */
-+ for (i = 0; smc_portlist[i]; i++) {
-+ ret = smc_probe(global_dev, smc_portlist[i]);
-+ if (ret == 0)
-+ break;
-+ }
-+ }
-+#elif defined(CONFIG_ARCH_LUBBOCK)
-+ {
-+ int ioaddr = LUBBOCK_ETH_VIRT + (0x300 << 2);
-+ volatile int *attaddr = (int *)(LUBBOCK_ETH_VIRT + 0x100000);
-+ unsigned long flags;
-+
-+ /* first reset, then enable the device. Sequence is critical */
-+ local_irq_save(flags);
-+ attaddr[ECOR] |= ECOR_RESET;
-+ udelay(100);
-+ attaddr[ECOR] &= ~ECOR_RESET;
-+ attaddr[ECOR] |= ECOR_ENABLE;
-+
-+ /* force 16-bit mode */
-+ attaddr[ECSR] &= ~ECSR_IOIS8;
-+ mdelay(1);
-+ local_irq_restore(flags);
-+
-+ global_dev->irq = LUBBOCK_ETH_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#elif defined(CONFIG_ARCH_PXA_IDP)
-+ {
-+ int ioaddr = IDP_ETH_BASE + 0x300;
-+ global_dev->irq = SMC_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#elif defined(CONFIG_ARCH_RAMSES)
-+ {
-+ int ioaddr = RAMSES_ETH_BASE + 0x300;
-+ global_dev->irq = SMC_IRQ;
-+ ret = smc_probe(global_dev, ioaddr);
-+ }
-+#else
-+ if (global_dev->base_addr == -1) {
-+ printk(KERN_WARNING"%s: SMC91X_BASE_ADDR not set!\n", CARDNAME);
-+ ret = -ENXIO;
-+ } else {
-+ void *ioaddr = ioremap(global_dev->base_addr, SMC_IO_EXTENT);
-+ ret = smc_probe(global_dev, (unsigned long)ioaddr);
-+ if (ret != 0)
-+ iounmap(ioaddr);
-+ }
-+#endif
-+
-+#ifdef SMC_USE_PXA_DMA
-+ if (ret == 0) {
-+ int dma = pxa_request_dma(global_dev->name, DMA_PRIO_LOW,
-+ smc_pxa_dma_irq, NULL);
-+ if (dma >= 0) {
-+ global_dev->dma = dma;
-+ PRINTK("%s: using DMA channel %d\n", global_dev->name, dma);
-+ } else {
-+ global_dev->dma = -1;
-+ }
-+ }
-+#endif
-+
-+#ifdef CONFIG_PM
-+ if (ret == 0) {
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+ lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback);
-+ }
-+#endif
-+
-+ if (ret != 0) {
-+ printk("%s: not found.\n", CARDNAME);
-+ kfree(global_dev->priv);
-+ unregister_netdev(global_dev);
-+ kfree(global_dev);
-+ }
-+
-+ return ret;
-+}
-+
-+static void __exit
-+smc_cleanup(void)
-+{
-+ unregister_netdev(global_dev);
-+#ifdef CONFIG_PM
-+ {
-+ struct smc_local *lp = (struct smc_local *)global_dev->priv;
-+ pm_unregister(lp->pm);
-+ }
-+#endif
-+ free_irq(global_dev->irq, global_dev);
-+ release_region(global_dev->base_addr, SMC_IO_EXTENT);
-+
-+#ifndef CONFIG_ISA
-+ iounmap((void *)global_dev->base_addr);
-+#endif
-+
-+ kfree(global_dev);
-+ global_dev = NULL;
-+}
-+
-+module_init(smc_init);
-+module_exit(smc_cleanup);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/net/smc91x.h
-@@ -0,0 +1,835 @@
-+/*------------------------------------------------------------------------
-+ . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device.
-+ .
-+ . Copyright (C) 1996 by Erik Stahlman
-+ . Copyright (C) 2001 Standard Microsystems Corporation
-+ . Developed by Simple Network Magic Corporation
-+ . Copyright (C) 2003 Monta Vista Software, Inc.
-+ . Unified SMC91x driver by Nicolas Pitre
-+ .
-+ . This program is free software; you can redistribute it and/or modify
-+ . it under the terms of the GNU General Public License as published by
-+ . the Free Software Foundation; either version 2 of the License, or
-+ . (at your option) any later version.
-+ .
-+ . This program is distributed in the hope that it will be useful,
-+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ . GNU General Public License for more details.
-+ .
-+ . You should have received a copy of the GNU General Public License
-+ . along with this program; if not, write to the Free Software
-+ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ .
-+ . Information contained in this file was obtained from the LAN91C111
-+ . manual from SMC. To get a copy, if you really want one, you can find
-+ . information under www.smsc.com.
-+ .
-+ . Authors
-+ . Erik Stahlman <erik@vt.edu>
-+ . Daris A Nevil <dnevil@snmc.com>
-+ . Nicolas Pitre <nico@cam.org>
-+ .
-+ ---------------------------------------------------------------------------*/
-+#ifndef _SMC91X_H_
-+#define _SMC91X_H_
-+
-+
-+/*
-+ * Define your architecture specific configuration parameters here.
-+ */
-+
-+#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \
-+ defined(CONFIG_SA1100_PFS168) || \
-+ defined(CONFIG_SA1100_FLEXANET) || \
-+ defined(CONFIG_SA1100_GRAPHICSMASTER) || \
-+ defined(CONFIG_ARCH_LUBBOCK)
-+
-+/* We can only do 16-bit reads and writes in the static memory space. */
-+#define SMC_CAN_USE_8BIT 0
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 0
-+#define SMC_NOWAIT 1
-+
-+/* The first two address lines aren't connected... */
-+#define SMC_IO_SHIFT 2
-+
-+#define SMC_inw(a, r) readw((a) + (r))
-+#define SMC_outw(v, a, r) writew(v, (a) + (r))
-+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-+
-+#ifdef CONFIG_ARCH_LUBBOCK
-+#define SMC_IOADDR LUBBOCK_ETH_PHYS
-+#endif
-+
-+#elif defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_ARCH_PXA_IDP) || defined(CONFIG_ARCH_RAMSES)
-+
-+#ifdef CONFIG_ARCH_MAINSTONE
-+#include <asm/arch/mainstone.h>
-+#define SMC_IOADDR (MST_ETH_PHYS + 0x300)
-+#define SMC_IRQ MAINSTONE_IRQ(3)
-+
-+#elif CONFIG_ARCH_PXA_IDP
-+#include <asm/arch/idp.h>
-+#define SMC_IOADDR (IDP_ETH_PHYS + 0x300)
-+#define SMC_IRQ ETHERNET_IRQ
-+
-+#elif CONFIG_ARCH_RAMSES
-+#include <asm/arch/ramses.h>
-+#define SMC_IOADDR (RAMSES_ETH_PHYS + 0x300)
-+#define SMC_IRQ ETHERNET_IRQ
-+#endif
-+
-+#define SMC_CAN_USE_8BIT 1
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 1
-+#define SMC_IO_SHIFT 0
-+#define SMC_NOWAIT 1
-+#define SMC_USE_PXA_DMA 1
-+
-+#define SMC_inb(a, r) readb((a) + (r))
-+#define SMC_inw(a, r) readw((a) + (r))
-+#define SMC_inl(a, r) readl((a) + (r))
-+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-+#define SMC_outl(v, a, r) writel(v, (a) + (r))
-+#define SMC_insl(a, r, p, l) insl((a) + (r), p, l)
-+#define SMC_outsl(a, r, p, l) outsl((a) + (r), p, l)
-+
-+/* We actually can't write halfwords properly if not word aligned */
-+static inline void
-+SMC_outw(u16 val, unsigned long ioaddr, int reg)
-+{
-+ if (reg & 2) {
-+ unsigned int v = val << 16;
-+ v |= readl(ioaddr + (reg & ~2)) & 0xffff;
-+ writel(v, ioaddr + (reg & ~2));
-+ } else {
-+ writew(val, ioaddr + reg);
-+ }
-+}
-+
-+#elif defined(CONFIG_ISA)
-+
-+#define SMC_CAN_USE_8BIT 1
-+#define SMC_CAN_USE_16BIT 1
-+#define SMC_CAN_USE_32BIT 0
-+
-+#define SMC_inb(a, r) inb((a) + (r))
-+#define SMC_inw(a, r) inw((a) + (r))
-+#define SMC_outb(v, a, r) outb(v, (a) + (r))
-+#define SMC_outw(v, a, r) outw(v, (a) + (r))
-+#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-+#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-+
-+#endif
-+
-+
-+#ifdef SMC_USE_PXA_DMA
-+/*
-+ * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
-+ * always happening in irq context so no need to worry about races. TX is
-+ * different and probably not worth it for that reason, and not as critical
-+ * as RX which can overrun memory and lose packets.
-+ */
-+#include <linux/pci.h>
-+#include <asm/dma.h>
-+
-+#ifdef SMC_insl
-+#undef SMC_insl
-+#define SMC_insl(a, r, p, l) smc_pxa_dma_insl(a, r, dev->dma, p, l)
-+static inline void
-+smc_pxa_dma_insl(u_long ioaddr, int reg, int dma, u_char *buf, int len)
-+{
-+ dma_addr_t dmabuf;
-+
-+ /* fallback if no DMA available */
-+ if (dma == -1) {
-+ insl(ioaddr + reg, buf, len);
-+ return;
-+ }
-+
-+ /* 64 bit alignment is required for memory to memory DMA */
-+ if ((long)buf & 4) {
-+ *((u32 *)buf)++ = SMC_inl(ioaddr, reg);
-+ len--;
-+ }
-+
-+ len *= 4;
-+ dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
-+ DCSR(dma) = DCSR_NODESC;
-+ DTADR(dma) = dmabuf;
-+ DSADR(dma) = SMC_IOADDR + reg;
-+ DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-+ DCMD_WIDTH4 | (DCMD_LENGTH & len));
-+ DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-+ while (!(DCSR(dma) & DCSR_STOPSTATE));
-+ DCSR(dma) = 0;
-+ pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
-+}
-+#endif
-+
-+#ifdef SMC_insw
-+#undef SMC_insw
-+#define SMC_insw(a, r, p, l) smc_pxa_dma_insw(a, r, dev->dma, p, l)
-+static inline void
-+smc_pxa_dma_insw(u_long ioaddr, int reg, int dma, u_char *buf, int len)
-+{
-+ dma_addr_t dmabuf;
-+
-+ /* fallback if no DMA available */
-+ if (dma == -1) {
-+ insw(ioaddr + reg, buf, len);
-+ return;
-+ }
-+
-+ /* 64 bit alignment is required for memory to memory DMA */
-+ while ((long)buf & 6) {
-+ *((u16 *)buf)++ = SMC_inw(ioaddr, reg);
-+ len--;
-+ }
-+
-+ len *= 2;
-+ dmabuf = pci_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE);
-+ DCSR(dma) = DCSR_NODESC;
-+ DTADR(dma) = dmabuf;
-+ DSADR(dma) = SMC_IOADDR + reg;
-+ DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-+ DCMD_WIDTH2 | (DCMD_LENGTH & len));
-+ DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-+ while (!(DCSR(dma) & DCSR_STOPSTATE));
-+ DCSR(dma) = 0;
-+ pci_unmap_single(NULL, dmabuf,len, PCI_DMA_FROMDEVICE);
-+}
-+#endif
-+
-+static void
-+smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
-+{
-+ DCSR(dma) = 0;
-+}
-+#endif /* SMC_USE_PXA_DMA */
-+
-+
-+/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */
-+#ifndef SMC_IO_SHIFT
-+#define SMC_IO_SHIFT 0
-+#endif
-+#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-+
-+
-+/*
-+ . Bank Select Register:
-+ .
-+ . yyyy yyyy 0000 00xx
-+ . xx = bank number
-+ . yyyy yyyy = 0x33, for identification purposes.
-+*/
-+#define BANK_SELECT (14 << SMC_IO_SHIFT)
-+
-+
-+// Transmit Control Register
-+/* BANK 0 */
-+#define TCR_REG SMC_REG(0x0000, 0)
-+#define TCR_ENABLE 0x0001 // When 1 we can transmit
-+#define TCR_LOOP 0x0002 // Controls output pin LBK
-+#define TCR_FORCOL 0x0004 // When 1 will force a collision
-+#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0
-+#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames
-+#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier
-+#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation
-+#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error
-+#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback
-+#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode
-+
-+#define TCR_CLEAR 0 /* do NOTHING */
-+/* the default settings for the TCR register : */
-+#define TCR_DEFAULT (TCR_ENABLE | TCR_PAD_EN)
-+
-+
-+// EPH Status Register
-+/* BANK 0 */
-+#define EPH_STATUS_REG SMC_REG(0x0002, 0)
-+#define ES_TX_SUC 0x0001 // Last TX was successful
-+#define ES_SNGL_COL 0x0002 // Single collision detected for last tx
-+#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx
-+#define ES_LTX_MULT 0x0008 // Last tx was a multicast
-+#define ES_16COL 0x0010 // 16 Collisions Reached
-+#define ES_SQET 0x0020 // Signal Quality Error Test
-+#define ES_LTXBRD 0x0040 // Last tx was a broadcast
-+#define ES_TXDEFR 0x0080 // Transmit Deferred
-+#define ES_LATCOL 0x0200 // Late collision detected on last tx
-+#define ES_LOSTCARR 0x0400 // Lost Carrier Sense
-+#define ES_EXC_DEF 0x0800 // Excessive Deferral
-+#define ES_CTR_ROL 0x1000 // Counter Roll Over indication
-+#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin
-+#define ES_TXUNRN 0x8000 // Tx Underrun
-+
-+
-+// Receive Control Register
-+/* BANK 0 */
-+#define RCR_REG SMC_REG(0x0004, 0)
-+#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted
-+#define RCR_PRMS 0x0002 // Enable promiscuous mode
-+#define RCR_ALMUL 0x0004 // When set accepts all multicast frames
-+#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets
-+#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets
-+#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision
-+#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier
-+#define RCR_SOFTRST 0x8000 // resets the chip
-+
-+/* the normal settings for the RCR register : */
-+#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN)
-+#define RCR_CLEAR 0x0 // set it to a base state
-+
-+
-+// Counter Register
-+/* BANK 0 */
-+#define COUNTER_REG SMC_REG(0x0006, 0)
-+
-+
-+// Memory Information Register
-+/* BANK 0 */
-+#define MIR_REG SMC_REG(0x0008, 0)
-+
-+
-+// Receive/Phy Control Register
-+/* BANK 0 */
-+#define RPC_REG SMC_REG(0x000A, 0)
-+#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
-+#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
-+#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
-+#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb
-+#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb
-+#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect
-+#define RPC_LED_RES (0x01) // LED = Reserved
-+#define RPC_LED_10 (0x02) // LED = 10Mbps link detect
-+#define RPC_LED_FD (0x03) // LED = Full Duplex Mode
-+#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred
-+#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect
-+#define RPC_LED_TX (0x06) // LED = TX packet occurred
-+#define RPC_LED_RX (0x07) // LED = RX packet occurred
-+#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
-+
-+
-+/* Bank 0 0x0C is reserved */
-+
-+// Bank Select Register
-+/* All Banks */
-+#define BSR_REG 0x000E
-+
-+
-+// Configuration Reg
-+/* BANK 1 */
-+#define CONFIG_REG SMC_REG(0x0000, 1)
-+#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy
-+#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL
-+#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus
-+#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
-+
-+// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
-+#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN)
-+
-+
-+// Base Address Register
-+/* BANK 1 */
-+#define BASE_REG SMC_REG(0x0002, 1)
-+
-+
-+// Individual Address Registers
-+/* BANK 1 */
-+#define ADDR0_REG SMC_REG(0x0004, 1)
-+#define ADDR1_REG SMC_REG(0x0006, 1)
-+#define ADDR2_REG SMC_REG(0x0008, 1)
-+
-+
-+// General Purpose Register
-+/* BANK 1 */
-+#define GP_REG SMC_REG(0x000A, 1)
-+
-+
-+// Control Register
-+/* BANK 1 */
-+#define CTL_REG SMC_REG(0x000C, 1)
-+#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received
-+#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
-+#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt
-+#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt
-+#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt
-+#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
-+#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers
-+#define CTL_STORE 0x0001 // When set stores registers into EEPROM
-+
-+
-+// MMU Command Register
-+/* BANK 2 */
-+#define MMU_CMD_REG SMC_REG(0x0000, 2)
-+#define MC_BUSY 1 // When 1 the last release has not completed
-+#define MC_NOP (0<<5) // No Op
-+#define MC_ALLOC (1<<5) // OR with number of 256 byte packets
-+#define MC_RESET (2<<5) // Reset MMU to initial state
-+#define MC_REMOVE (3<<5) // Remove the current rx packet
-+#define MC_RELEASE (4<<5) // Remove and release the current rx packet
-+#define MC_FREEPKT (5<<5) // Release packet in PNR register
-+#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit
-+#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs
-+
-+
-+// Packet Number Register
-+/* BANK 2 */
-+#define PN_REG SMC_REG(0x0002, 2)
-+
-+
-+// Allocation Result Register
-+/* BANK 2 */
-+#define AR_REG SMC_REG(0x0003, 2)
-+#define AR_FAILED 0x80 // Alocation Failed
-+
-+
-+// TX FIFO Ports Register
-+/* BANK 2 */
-+#define TXFIFO_REG SMC_REG(0x0004, 2)
-+#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty
-+
-+// RX FIFO Ports Register
-+/* BANK 2 */
-+#define RXFIFO_REG SMC_REG(0x0005, 2)
-+#define RXFIFO_REMPTY 0x80 // RX FIFO Empty
-+
-+#define FIFO_REG SMC_REG(0x0004, 2)
-+
-+// Pointer Register
-+/* BANK 2 */
-+#define PTR_REG SMC_REG(0x0006, 2)
-+#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area
-+#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access
-+#define PTR_READ 0x2000 // When 1 the operation is a read
-+
-+
-+// Data Register
-+/* BANK 2 */
-+#define DATA_REG SMC_REG(0x0008, 2)
-+
-+
-+// Interrupt Status/Acknowledge Register
-+/* BANK 2 */
-+#define INT_REG SMC_REG(0x000C, 2)
-+
-+
-+// Interrupt Mask Register
-+/* BANK 2 */
-+#define IM_REG SMC_REG(0x000D, 2)
-+#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt
-+#define IM_ERCV_INT 0x40 // Early Receive Interrupt
-+#define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section
-+#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns
-+#define IM_ALLOC_INT 0x08 // Set when allocation request is completed
-+#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty
-+#define IM_TX_INT 0x02 // Transmit Interrupt
-+#define IM_RCV_INT 0x01 // Receive Interrupt
-+
-+
-+// Multicast Table Registers
-+/* BANK 3 */
-+#define MCAST_REG1 SMC_REG(0x0000, 3)
-+#define MCAST_REG2 SMC_REG(0x0002, 3)
-+#define MCAST_REG3 SMC_REG(0x0004, 3)
-+#define MCAST_REG4 SMC_REG(0x0006, 3)
-+
-+
-+// Management Interface Register (MII)
-+/* BANK 3 */
-+#define MII_REG SMC_REG(0x0008, 3)
-+#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
-+#define MII_MDOE 0x0008 // MII Output Enable
-+#define MII_MCLK 0x0004 // MII Clock, pin MDCLK
-+#define MII_MDI 0x0002 // MII Input, pin MDI
-+#define MII_MDO 0x0001 // MII Output, pin MDO
-+
-+
-+// Revision Register
-+/* BANK 3 */
-+/* ( hi: chip id low: rev # ) */
-+#define REV_REG SMC_REG(0x000A, 3)
-+
-+
-+// Early RCV Register
-+/* BANK 3 */
-+/* this is NOT on SMC9192 */
-+#define ERCV_REG SMC_REG(0x000C, 3)
-+#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received
-+#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask
-+
-+
-+// External Register
-+/* BANK 7 */
-+#define EXT_REG SMC_REG(0x0000, 7)
-+
-+
-+#define CHIP_9192 3
-+#define CHIP_9194 4
-+#define CHIP_9195 5
-+#define CHIP_9196 6
-+#define CHIP_91100 7
-+#define CHIP_91100FD 8
-+#define CHIP_91111FD 9
-+
-+static const char * chip_ids[ 16 ] = {
-+ NULL, NULL, NULL,
-+ /* 3 */ "SMC91C90/91C92",
-+ /* 4 */ "SMC91C94",
-+ /* 5 */ "SMC91C95",
-+ /* 6 */ "SMC91C96",
-+ /* 7 */ "SMC91C100",
-+ /* 8 */ "SMC91C100FD",
-+ /* 9 */ "SMC91C11xFD",
-+ NULL, NULL, NULL,
-+ NULL, NULL, NULL};
-+
-+
-+/*
-+ . Transmit status bits
-+*/
-+#define TS_SUCCESS 0x0001
-+#define TS_LOSTCAR 0x0400
-+#define TS_LATCOL 0x0200
-+#define TS_16COL 0x0010
-+
-+/*
-+ . Receive status bits
-+*/
-+#define RS_ALGNERR 0x8000
-+#define RS_BRODCAST 0x4000
-+#define RS_BADCRC 0x2000
-+#define RS_ODDFRAME 0x1000
-+#define RS_TOOLONG 0x0800
-+#define RS_TOOSHORT 0x0400
-+#define RS_MULTICAST 0x0001
-+#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
-+
-+
-+// PHY Types
-+enum {
-+ PHY_LAN83C183 = 1, // LAN91C111 Internal PHY
-+ PHY_LAN83C180
-+};
-+
-+
-+// PHY Register Addresses (LAN91C111 Internal PHY)
-+
-+// PHY Control Register
-+#define PHY_CNTL_REG 0x00
-+#define PHY_CNTL_RST 0x8000 // 1=PHY Reset
-+#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback
-+#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs
-+#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation
-+#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode
-+#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled
-+#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate
-+#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex
-+#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test
-+
-+// PHY Status Register
-+#define PHY_STAT_REG 0x01
-+#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable
-+#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable
-+#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable
-+#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable
-+#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable
-+#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble
-+#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed
-+#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected
-+#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable
-+#define PHY_STAT_LINK 0x0004 // 1=valid link
-+#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition
-+#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented
-+
-+// PHY Identifier Registers
-+#define PHY_ID1_REG 0x02 // PHY Identifier 1
-+#define PHY_ID2_REG 0x03 // PHY Identifier 2
-+
-+// PHY Auto-Negotiation Advertisement Register
-+#define PHY_AD_REG 0x04
-+#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page
-+#define PHY_AD_ACK 0x4000 // 1=got link code word from remote
-+#define PHY_AD_RF 0x2000 // 1=advertise remote fault
-+#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4
-+#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX
-+#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX
-+#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX
-+#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX
-+#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA
-+
-+// PHY Auto-negotiation Remote End Capability Register
-+#define PHY_RMT_REG 0x05
-+// Uses same bit definitions as PHY_AD_REG
-+
-+// PHY Configuration Register 1
-+#define PHY_CFG1_REG 0x10
-+#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled
-+#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled
-+#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down
-+#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler
-+#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable
-+#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled
-+#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm)
-+#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db
-+#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust
-+#define PHY_CFG1_TLVL_MASK 0x003C
-+#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time
-+
-+
-+// PHY Configuration Register 2
-+#define PHY_CFG2_REG 0x11
-+#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled
-+#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled
-+#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt)
-+#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo
-+
-+// PHY Status Output (and Interrupt status) Register
-+#define PHY_INT_REG 0x12 // Status Output (Interrupt Status)
-+#define PHY_INT_INT 0x8000 // 1=bits have changed since last read
-+#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected
-+#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync
-+#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx
-+#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx
-+#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx
-+#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected
-+#define PHY_INT_JAB 0x0100 // 1=Jabber detected
-+#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode
-+#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex
-+
-+// PHY Interrupt/Status Mask Register
-+#define PHY_MASK_REG 0x13 // Interrupt Mask
-+// Uses the same bit definitions as PHY_INT_REG
-+
-+
-+/*
-+ * SMC91C96 ethernet config and status registers.
-+ * These are in the "attribute" space.
-+ */
-+#define ECOR 0x8000
-+#define ECOR_RESET 0x80
-+#define ECOR_LEVEL_IRQ 0x40
-+#define ECOR_WR_ATTRIB 0x04
-+#define ECOR_ENABLE 0x01
-+
-+#define ECSR 0x8002
-+#define ECSR_IOIS8 0x20
-+#define ECSR_PWRDWN 0x04
-+#define ECSR_INT 0x02
-+
-+
-+/*
-+ * Macros to abstract register access according to the data bus
-+ * capabilities. Please try to use those and not the in/out primitives.
-+ * Note: the following macros do *not* select the bank -- this must
-+ * be done separately as needed in the main code. The SMC_REG() macro
-+ * only uses the bank argument for debugging purposes.
-+ */
-+
-+#if SMC_DEBUG > 0
-+#define SMC_REG(reg, bank) \
-+ ({ \
-+ int __b = SMC_CURRENT_BANK(); \
-+ if ((__b & ~0xf0) != (0x3300 | bank)) { \
-+ printk( "%s: bank reg screwed (0x%04x)\n", \
-+ CARDNAME, __b ); \
-+ BUG(); \
-+ } \
-+ reg<<SMC_IO_SHIFT; \
-+ })
-+#else
-+#define SMC_REG(reg, bank) (reg<<SMC_IO_SHIFT)
-+#endif
-+
-+#if SMC_CAN_USE_8BIT
-+#define SMC_GET_PN() SMC_inb( ioaddr, PN_REG )
-+#define SMC_SET_PN(x) SMC_outb( x, ioaddr, PN_REG )
-+#define SMC_GET_AR() SMC_inb( ioaddr, AR_REG )
-+#define SMC_GET_TXFIFO() SMC_inb( ioaddr, TXFIFO_REG )
-+#define SMC_GET_RXFIFO() SMC_inb( ioaddr, RXFIFO_REG )
-+#define SMC_GET_INT() SMC_inb( ioaddr, INT_REG )
-+#define SMC_ACK_INT(x) SMC_outb( x, ioaddr, INT_REG )
-+#define SMC_GET_INT_MASK() SMC_inb( ioaddr, IM_REG )
-+#define SMC_SET_INT_MASK(x) SMC_outb( x, ioaddr, IM_REG )
-+#else
-+#define SMC_GET_PN() (SMC_inw( ioaddr, PN_REG ) & 0xFF)
-+#define SMC_SET_PN(x) SMC_outw( x, ioaddr, PN_REG )
-+#define SMC_GET_AR() (SMC_inw( ioaddr, PN_REG ) >> 8)
-+#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF)
-+#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8)
-+#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF)
-+#define SMC_ACK_INT(x) \
-+ do { \
-+ unsigned long __flags; \
-+ int __mask; \
-+ local_irq_save(__flags); \
-+ __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \
-+ SMC_outw( __mask | (x), ioaddr, INT_REG ); \
-+ local_irq_restore(__flags); \
-+ } while (0)
-+#define SMC_GET_INT_MASK() (SMC_inw( ioaddr, INT_REG ) >> 8)
-+#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG )
-+#endif
-+
-+#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT )
-+#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT )
-+#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG )
-+#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG )
-+#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG )
-+#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG )
-+#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG )
-+#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG )
-+#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG )
-+#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG )
-+#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG )
-+#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG )
-+#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG )
-+#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG )
-+#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG )
-+#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG )
-+#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG )
-+#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG )
-+#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG )
-+#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG )
-+#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG )
-+#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG )
-+#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG )
-+#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG )
-+#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG )
-+
-+#ifndef SMC_GET_MAC_ADDR
-+#define SMC_GET_MAC_ADDR(addr) \
-+ do { \
-+ unsigned int __v; \
-+ __v = SMC_inw( ioaddr, ADDR0_REG ); \
-+ addr[0] = __v; addr[1] = __v >> 8; \
-+ __v = SMC_inw( ioaddr, ADDR1_REG ); \
-+ addr[2] = __v; addr[3] = __v >> 8; \
-+ __v = SMC_inw( ioaddr, ADDR2_REG ); \
-+ addr[4] = __v; addr[5] = __v >> 8; \
-+ } while (0)
-+#endif
-+
-+#define SMC_SET_MAC_ADDR(addr) \
-+ do { \
-+ SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \
-+ SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \
-+ SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \
-+ } while (0)
-+
-+#define SMC_CLEAR_MCAST() \
-+ do { \
-+ SMC_outw( 0, ioaddr, MCAST_REG1 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG2 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG3 ); \
-+ SMC_outw( 0, ioaddr, MCAST_REG4 ); \
-+ } while (0)
-+#define SMC_SET_MCAST(x) \
-+ do { \
-+ unsigned char *mt = (x); \
-+ SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \
-+ SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \
-+ SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \
-+ SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \
-+ } while (0)
-+
-+#if SMC_CAN_USE_32BIT
-+/*
-+ * Some setups just can't write 8 or 16 bits reliably when not aligned
-+ * to a 32 bit boundary. I tell you that exists!
-+ * We do the ones that can have their low parts written to 0 here.
-+ */
-+#undef SMC_SELECT_BANK
-+#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<<SMC_IO_SHIFT )
-+#undef SMC_SET_RPC
-+#define SMC_SET_RPC(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(8, 0) )
-+#undef SMC_SET_PN
-+#define SMC_SET_PN(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(0, 2) )
-+#undef SMC_SET_PTR
-+#define SMC_SET_PTR(x) SMC_outl( (x)<<16, ioaddr, SMC_REG(4, 2) )
-+#endif
-+
-+#if SMC_CAN_USE_32BIT
-+#define SMC_PUT_PKT_HDR(status, length) \
-+ SMC_outl( (status) | (length) << 16, ioaddr, DATA_REG )
-+#define SMC_GET_PKT_HDR(status, length) \
-+ do { \
-+ unsigned int __val = SMC_inl( ioaddr, DATA_REG ); \
-+ (status) = __val & 0xffff; \
-+ (length) = __val >> 16; \
-+ } while (0)
-+#else
-+#define SMC_PUT_PKT_HDR(status, length) \
-+ do { \
-+ SMC_outw( status, ioaddr, DATA_REG ); \
-+ SMC_outw( length, ioaddr, DATA_REG ); \
-+ } while (0)
-+#define SMC_GET_PKT_HDR(status, length) \
-+ do { \
-+ (status) = SMC_inw( ioaddr, DATA_REG ); \
-+ (length) = SMC_inw( ioaddr, DATA_REG ); \
-+ } while (0)
-+#endif
-+
-+#if SMC_CAN_USE_32BIT
-+#define SMC_PUSH_DATA(p, l) \
-+ do { \
-+ char *__ptr = (p); \
-+ int __len = (l); \
-+ if (__len >= 2 && (long)__ptr & 2) { \
-+ __len -= 2; \
-+ SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
-+ } \
-+ SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \
-+ if (__len & 2) { \
-+ __ptr += (__len & ~3); \
-+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
-+ } \
-+ } while (0)
-+#define SMC_PULL_DATA(p, l) \
-+ do { \
-+ char *__ptr = (p); \
-+ int __len = (l); \
-+ if ((long)__ptr & 2) { \
-+ /* \
-+ * We want 32bit alignment here. \
-+ * Since some buses perform a full 32bit \
-+ * fetch even for 16bit data we can't use \
-+ * SMC_inw() here. Back both source (on chip \
-+ * and destination) pointers of 2 bytes. \
-+ */ \
-+ (long)__ptr &= ~2; \
-+ __len += 2; \
-+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
-+ } \
-+ __len += 2; \
-+ SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
-+ } while (0)
-+#elif SMC_CAN_USE_16BIT
-+#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-+#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
-+#elif SMC_CAN_USE_8BIT
-+#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-+#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
-+#endif
-+
-+#if ! SMC_CAN_USE_16BIT
-+#define SMC_outw(x, ioaddr, reg) \
-+ do { \
-+ unsigned int __val16 = (x); \
-+ SMC_outb( __val16, ioaddr, reg ); \
-+ SMC_outb( __val16 >> 8, ioaddr, reg + 1 ); \
-+ } while (0)
-+#define SMC_inw(ioaddr, reg) \
-+ ({ \
-+ unsigned int __val16; \
-+ __val16 = SMC_inb( ioaddr, reg ); \
-+ __val16 |= SMC_inb( ioaddr, reg + 1 ) << 8; \
-+ __val16; \
-+ })
-+#endif
-+
-+
-+#endif /* _SMC91X_H_ */
---- linux-2.4.27/drivers/pcmcia/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/pcmcia/Config.in
-@@ -45,6 +45,7 @@
- if [ "$CONFIG_ARM" = "y" ]; then
- dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
- dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
-+ dep_tristate ' PXA250/210 support' CONFIG_PCMCIA_PXA $CONFIG_ARCH_PXA $CONFIG_PCMCIA
- fi
-
- endmenu
---- linux-2.4.27/drivers/pcmcia/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/pcmcia/Makefile
-@@ -94,6 +94,11 @@
-
- obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
-
-+subdir-$(CONFIG_PCMCIA_PXA) += pxa
-+ifeq ($(CONFIG_PCMCIA_PXA),y)
-+ obj-y += pxa/pxa_cs.o
-+endif
-+
- include $(TOPDIR)/Rules.make
-
- pcmcia_core.o: $(pcmcia_core-objs)
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/Makefile
-@@ -0,0 +1,18 @@
-+#
-+# Makefile for the Intel PXA250/210 PCMCIA driver
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+
-+O_TARGET := pxa_cs.o
-+
-+obj-y := pxa.o
-+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
-+obj-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o
-+obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
-+obj-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o
-+
-+obj-m := $(O_TARGET)
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/lubbock.c
-@@ -0,0 +1,329 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/lubbock.c
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
-+ *
-+ * Lubbock PCMCIA specific routines.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+#include <asm/hardware/sa1111.h>
-+
-+/*
-+ * I'd really like to move the INTPOL stuff to arch/arm/mach-sa1100/sa1111.c
-+ * ... and maybe even arch/arm/mach-pxa/sa1111.c now too! : )
-+ */
-+#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
-+#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
-+
-+static int lubbock_pcmcia_init(struct pcmcia_init *init){
-+ int return_val=0;
-+
-+ /* Set PCMCIA Socket 0 power to standby mode.
-+ */
-+ PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+
-+ /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller.
-+ * Note that this is done only after first initializing GPIO_A<3:0>
-+ * output state above to be certain that we drive signals to the same
-+ * state as the pull-downs connected to these lines. The pull-downs are
-+ * req'd to make sure PCMCIA power is OFF until we can get around to
-+ * setting up the GPIO_A<3:0> state and direction.
-+ */
-+ PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+
-+ /* Set CF Socket 1 power to standby mode. */
-+ LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+#warning what if a request_irq fails?
-+ return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
-+ "Lubbock PCMCIA (0) CD", NULL);
-+ return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
-+ "Lubbock CF (1) CD", NULL);
-+ return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
-+ "Lubbock PCMCIA (0) BVD1", NULL);
-+ return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
-+ "Lubbock CF (1) BVD1", NULL);
-+
-+ return (return_val<0) ? -1 : 2;
-+}
-+
-+static int lubbock_pcmcia_shutdown(void){
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+
-+ return 0;
-+}
-+
-+static int lubbock_pcmcia_socket_state(struct pcmcia_state_array
-+ *state_array){
-+ unsigned long status;
-+ int return_val=1;
-+
-+ if(state_array->size<2) return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-+
-+ status=PCSR;
-+
-+ state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-+
-+ state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-+
-+ state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-+
-+ state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-+
-+ state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-+
-+ state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-+
-+ state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-+
-+ state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-+
-+ state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-+
-+ state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-+
-+ state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-+
-+ state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-+
-+ state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-+
-+ state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-+
-+ return return_val;
-+}
-+
-+static int lubbock_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-+
-+ switch(info->sock){
-+ case 0:
-+ info->irq=S0_READY_NINT;
-+ break;
-+
-+ case 1:
-+ info->irq=S1_READY_NINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+lubbock_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ unsigned long flags, pccr, gpio, misc_wr, status;
-+ int ret=1;
-+
-+ local_irq_save(flags);
-+
-+ pccr=PCCR;
-+ gpio=PA_DWR;
-+ misc_wr = LUB_MISC_WR;
-+
-+ /* Lubbock uses the Maxim MAX1602, with the following connections:
-+ *
-+ * Socket 0 (PCMCIA):
-+ * MAX1602 Lubbock Register
-+ * Pin Signal
-+ * ----- ------- ----------------------
-+ * A0VPP S0_PWR0 SA-1111 GPIO A<0>
-+ * A1VPP S0_PWR1 SA-1111 GPIO A<1>
-+ * A0VCC S0_PWR2 SA-1111 GPIO A<2>
-+ * A1VCC S0_PWR3 SA-1111 GPIO A<3>
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ * Socket 1 (CF):
-+ * MAX1602 Lubbock Register
-+ * Pin Signal
-+ * ----- ------- ----------------------
-+ * A0VPP GND VPP is not connected
-+ * A1VPP GND VPP is not connected
-+ * A0VCC S1_PWR0 MISC_WR<14>
-+ * A1VCC S1_PWR0 MISC_WR<15>
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN GND VPP is not connected
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ */
-+
-+again:
-+ switch(sock){
-+ case 0:
-+
-+ switch(state->Vcc){
-+ case 0:
-+ pccr = (pccr & ~PCCR_S0_FLT);
-+ gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
-+ break;
-+
-+ case 33:
-+ pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
-+ break;
-+
-+ case 50:
-+ pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
-+ ret = -1;
-+ break;
-+ }
-+
-+ switch(state->Vpp){
-+ case 0:
-+ gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
-+ break;
-+
-+ case 120:
-+ gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
-+ break;
-+
-+ default:
-+ /* REVISIT: I'm not sure about this? Is this correct?
-+ Is it always safe or do we have potential problems
-+ with bogus combinations of Vcc and Vpp settings? */
-+ if(state->Vpp == state->Vcc)
-+ gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp);
-+ ret = -1;
-+ break;
-+ }
-+ }
-+
-+ pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S0_RST) : (pccr&~PCCR_S0_RST);
-+
-+ break;
-+
-+ case 1:
-+ switch(state->Vcc){
-+ case 0:
-+ pccr = (pccr & ~PCCR_S1_FLT);
-+ misc_wr &= ~((1 << 15) | (1 << 14));
-+ break;
-+
-+ case 33:
-+ pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
-+ misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
-+ gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
-+ break;
-+
-+ case 50:
-+ pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
-+ misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
-+ ret = -1;
-+ break;
-+ }
-+
-+ if(state->Vpp!=state->Vcc && state->Vpp!=0){
-+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp);
-+ ret = -1;
-+ break;
-+ }
-+
-+ pccr = (state->flags&SS_RESET) ? (pccr|PCCR_S1_RST) : (pccr&~PCCR_S1_RST);
-+
-+ break;
-+
-+ default:
-+ ret = -1;
-+ }
-+
-+ if (ret >= 0) {
-+ PCCR = pccr;
-+ LUB_MISC_WR = misc_wr;
-+ PA_DWR = gpio;
-+ }
-+
-+ if (ret > 0) {
-+ ret = 0;
-+ /*
-+ * HACK ALERT:
-+ * We can't sense the voltage properly on Lubbock before actually
-+ * applying some power to the socket (catch 22).
-+ * Resense the socket Voltage Sense pins after applying socket power.
-+ */
-+ if (sock == 0)
-+ status = PCSR & (PCSR_S0_VS1 | PCSR_S0_VS2);
-+ else
-+ status = PCSR & (PCSR_S1_VS1 | PCSR_S1_VS2);
-+
-+ if ((status == (PCSR_S0_VS1 | PCSR_S0_VS2)) && (state->Vcc == 33)) {
-+ /* Switch to 5V, Configure socket 0 with 5V voltage */
-+ PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+ PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
-+ state->Vcc = 50;
-+ state->Vpp = 50;
-+ goto again;
-+ }
-+ if ((status == (PCSR_S1_VS1 | PCSR_S1_VS2)) && (state->Vcc == 33)) {
-+ /* Switch to 5V, Configure socket 1 with 5V voltage */
-+ LUB_MISC_WR &= ~((1 << 15) | (1 << 14));
-+ state->Vcc = 50;
-+ state->Vpp = 50;
-+ goto again;
-+ }
-+ }
-+
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+
-+struct pcmcia_low_level lubbock_pcmcia_ops = {
-+ lubbock_pcmcia_init,
-+ lubbock_pcmcia_shutdown,
-+ lubbock_pcmcia_socket_state,
-+ lubbock_pcmcia_get_irq_info,
-+ lubbock_pcmcia_configure_socket
-+};
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/pxa.c
-@@ -0,0 +1,1247 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa.c
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.c
-+ *
-+ */
-+
-+/*======================================================================
-+
-+ Device driver for the PCMCIA control functionality of Intel
-+ PXA250/210 microprocessors.
-+
-+ The contents of this file are subject to the Mozilla Public
-+ License Version 1.1 (the "License"); you may not use this file
-+ except in compliance with the License. You may obtain a copy of
-+ the License at http://www.mozilla.org/MPL/
-+
-+ Software distributed under the License is distributed on an "AS
-+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-+ implied. See the License for the specific language governing
-+ rights and limitations under the License.
-+
-+ The initial developer of the original code is John G. Dorsey
-+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
-+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
-+
-+ Alternatively, the contents of this file may be used under the
-+ terms of the GNU Public License version 2 (the "GPL"), in which
-+ case the provisions of the GPL are applicable instead of the
-+ above. If you wish to allow the use of your version of this file
-+ only under the terms of the GPL and not to allow others to use
-+ your version of this file under the MPL, indicate your decision
-+ by deleting the provisions above and replace them with the notice
-+ and other provisions required by the GPL. If you do not delete
-+ the provisions above, a recipient may use your version of this
-+ file under either the MPL or the GPL.
-+
-+======================================================================*/
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/config.h>
-+#include <linux/cpufreq.h>
-+#include <linux/delay.h>
-+#include <linux/ioport.h>
-+#include <linux/kernel.h>
-+#include <linux/tqueue.h>
-+#include <linux/timer.h>
-+#include <linux/mm.h>
-+#include <linux/notifier.h>
-+#include <linux/proc_fs.h>
-+#include <linux/version.h>
-+#include <linux/cpufreq.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/cs.h>
-+#include <pcmcia/ss.h>
-+#include <pcmcia/bus_ops.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/arch/lubbock.h>
-+
-+#include "pxa.h"
-+
-+#ifdef PCMCIA_DEBUG
-+static int pc_debug;
-+#endif
-+
-+MODULE_AUTHOR("George Davis <davis_g@mvista.com>");
-+MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA250/210 Socket Controller");
-+
-+/* This structure maintains housekeeping state for each socket, such
-+ * as the last known values of the card detect pins, or the Card Services
-+ * callback value associated with the socket:
-+ */
-+static struct pxa_pcmcia_socket
-+pxa_pcmcia_socket[PXA_PCMCIA_MAX_SOCK];
-+
-+static int pxa_pcmcia_socket_count;
-+
-+
-+/* Returned by the low-level PCMCIA interface: */
-+static struct pcmcia_low_level *pcmcia_low_level;
-+
-+/* Event poll timer structure */
-+static struct timer_list poll_timer;
-+
-+
-+/* Prototypes for routines which are used internally: */
-+
-+static int pxa_pcmcia_driver_init(void);
-+static void pxa_pcmcia_driver_shutdown(void);
-+static void pxa_pcmcia_task_handler(void *data);
-+static void pxa_pcmcia_poll_event(unsigned long data);
-+static void pxa_pcmcia_interrupt(int irq, void *dev,
-+ struct pt_regs *regs);
-+static struct tq_struct pxa_pcmcia_task;
-+
-+#ifdef CONFIG_PROC_FS
-+static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
-+ int count, int *eof, void *data);
-+#endif
-+
-+
-+/* Prototypes for operations which are exported to the
-+ * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
-+ */
-+
-+static int pxa_pcmcia_init(unsigned int sock);
-+static int pxa_pcmcia_suspend(unsigned int sock);
-+static int pxa_pcmcia_register_callback(unsigned int sock,
-+ void (*handler)(void *,
-+ unsigned int),
-+ void *info);
-+static int pxa_pcmcia_inquire_socket(unsigned int sock,
-+ socket_cap_t *cap);
-+static int pxa_pcmcia_get_status(unsigned int sock, u_int *value);
-+static int pxa_pcmcia_get_socket(unsigned int sock,
-+ socket_state_t *state);
-+static int pxa_pcmcia_set_socket(unsigned int sock,
-+ socket_state_t *state);
-+static int pxa_pcmcia_get_io_map(unsigned int sock,
-+ struct pccard_io_map *io);
-+static int pxa_pcmcia_set_io_map(unsigned int sock,
-+ struct pccard_io_map *io);
-+static int pxa_pcmcia_get_mem_map(unsigned int sock,
-+ struct pccard_mem_map *mem);
-+static int pxa_pcmcia_set_mem_map(unsigned int sock,
-+ struct pccard_mem_map *mem);
-+#ifdef CONFIG_PROC_FS
-+static void pxa_pcmcia_proc_setup(unsigned int sock,
-+ struct proc_dir_entry *base);
-+#endif
-+
-+static struct pccard_operations pxa_pcmcia_operations = {
-+ pxa_pcmcia_init,
-+ pxa_pcmcia_suspend,
-+ pxa_pcmcia_register_callback,
-+ pxa_pcmcia_inquire_socket,
-+ pxa_pcmcia_get_status,
-+ pxa_pcmcia_get_socket,
-+ pxa_pcmcia_set_socket,
-+ pxa_pcmcia_get_io_map,
-+ pxa_pcmcia_set_io_map,
-+ pxa_pcmcia_get_mem_map,
-+ pxa_pcmcia_set_mem_map,
-+#ifdef CONFIG_PROC_FS
-+ pxa_pcmcia_proc_setup
-+#endif
-+};
-+
-+#ifdef CONFIG_CPU_FREQ
-+/* forward declaration */
-+static struct notifier_block pxa_pcmcia_notifier_block;
-+#endif
-+
-+
-+/* pxa_pcmcia_driver_init()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ *
-+ * This routine performs a basic sanity check to ensure that this
-+ * kernel has been built with the appropriate board-specific low-level
-+ * PCMCIA support, performs low-level PCMCIA initialization, registers
-+ * this socket driver with Card Services, and then spawns the daemon
-+ * thread which is the real workhorse of the socket driver.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
-+ * on the low-level kernel interface.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int __init pxa_pcmcia_driver_init(void){
-+ servinfo_t info;
-+ struct pcmcia_init pcmcia_init;
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+ unsigned int i, clock;
-+ unsigned long mecr;
-+
-+ printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE);
-+
-+ CardServices(GetCardServicesInfo, &info);
-+
-+ if(info.Revision!=CS_RELEASE_CODE){
-+ printk(KERN_ERR "Card Services release codes do not match\n");
-+ return -1;
-+ }
-+
-+ /* Setup GPIOs for PCMCIA/CF alternate function mode.
-+ *
-+ * It would be nice if set_GPIO_mode included support
-+ * for driving GPIO outputs to default high/low state
-+ * before programming GPIOs as outputs. Setting GPIO
-+ * outputs to default high/low state via GPSR/GPCR
-+ * before defining them as outputs should reduce
-+ * the possibility of glitching outputs during GPIO
-+ * setup. This of course assumes external terminators
-+ * are present to hold GPIOs in a defined state.
-+ *
-+ * In the meantime, setup default state of GPIO
-+ * outputs before we enable them as outputs.
-+ */
-+
-+ GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-+ GPIO_bit(GPIO49_nPWE) |
-+ GPIO_bit(GPIO50_nPIOR) |
-+ GPIO_bit(GPIO51_nPIOW) |
-+ GPIO_bit(GPIO52_nPCE_1) |
-+ GPIO_bit(GPIO53_nPCE_2);
-+
-+ set_GPIO_mode(GPIO48_nPOE_MD);
-+ set_GPIO_mode(GPIO49_nPWE_MD);
-+ set_GPIO_mode(GPIO50_nPIOR_MD);
-+ set_GPIO_mode(GPIO51_nPIOW_MD);
-+ set_GPIO_mode(GPIO52_nPCE_1_MD);
-+ set_GPIO_mode(GPIO53_nPCE_2_MD);
-+ set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
-+ set_GPIO_mode(GPIO55_nPREG_MD);
-+ set_GPIO_mode(GPIO56_nPWAIT_MD);
-+ set_GPIO_mode(GPIO57_nIOIS16_MD);
-+
-+
-+ if(machine_is_lubbock()){
-+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_CSB226)
-+ pcmcia_low_level=&lubbock_pcmcia_ops;
-+#endif
-+ } else if (machine_is_pxa_idp()) {
-+ pcmcia_low_level=&pxa_idp_pcmcia_ops;
-+ } else if( machine_is_pxa_cerf()){
-+ pcmcia_low_level=&cerf_pcmcia_ops;
-+ } else if (machine_is_trizeps2()){
-+#ifdef CONFIG_ARCH_TRIZEPS2
-+ pcmcia_low_level=&trizeps2_pcmcia_ops;
-+#endif
-+ }
-+
-+ if (!pcmcia_low_level) {
-+ printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n");
-+ return -ENODEV;
-+ }
-+
-+ pcmcia_init.handler=pxa_pcmcia_interrupt;
-+
-+ if((pxa_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){
-+ printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n");
-+ return -EIO;
-+ }
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ /* Configure MECR based on the number of sockets present. */
-+ if (pxa_pcmcia_socket_count == 2) {
-+ MECR |= GPIO_bit(0);
-+ } else {
-+ MECR &= ~GPIO_bit(0);
-+ }
-+
-+ if(pcmcia_low_level->socket_state(&state_array)<0){
-+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
-+ return -EIO;
-+ }
-+
-+ /* Well, it looks good to go. So we can now enable the PCMCIA
-+ * controller.
-+ */
-+ MECR |= GPIO_bit(1);
-+
-+ /* We need to initialize the MCXX registers to default values
-+ * here because we're not guaranteed to see a SetIOMap operation
-+ * at runtime.
-+ */
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ for(i=0; i<pxa_pcmcia_socket_count; ++i){
-+ pxa_pcmcia_socket[i].k_state=state[i];
-+
-+ /* This is an interim fix. Apparently, SetSocket is no longer
-+ * called to initialize each socket (prior to the first detect
-+ * event). For now, we'll just manually set up the mask.
-+ */
-+ pxa_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
-+
-+ pxa_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE;
-+ pxa_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i);
-+ pxa_pcmcia_socket[i].phys_mem=_PCMCIAMem(i);
-+
-+ /* REVISIT: cleanup these macros */
-+ //MCIO_SET(i, PXA_PCMCIA_IO_ACCESS, clock);
-+ //MCATTR_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
-+ //MCMEM_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock);
-+
-+ pxa_pcmcia_socket[i].speed_io=PXA_PCMCIA_IO_ACCESS;
-+ pxa_pcmcia_socket[i].speed_attr=PXA_PCMCIA_ATTR_MEM_ACCESS;
-+ pxa_pcmcia_socket[i].speed_mem=PXA_PCMCIA_5V_MEM_ACCESS;
-+ }
-+
-+/* REVISIT: cleanup these macros */
-+MCMEM0 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCMEM1 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCIO0 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+MCIO1 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+
-+#ifdef CONFIG_CPU_FREQ
-+ if(cpufreq_register_notifier(&pxa_pcmcia_notifier_block) < 0){
-+ printk(KERN_ERR "Unable to register CPU frequency change notifier\n");
-+ return -ENXIO;
-+ }
-+#endif
-+
-+ /* Only advertise as many sockets as we can detect: */
-+ if(register_ss_entry(pxa_pcmcia_socket_count,
-+ &pxa_pcmcia_operations)<0){
-+ printk(KERN_ERR "Unable to register socket service routine\n");
-+ return -ENXIO;
-+ }
-+
-+ /* Start the event poll timer. It will reschedule by itself afterwards. */
-+ pxa_pcmcia_poll_event(0);
-+
-+ DEBUG(1, "pxa_cs: initialization complete\n");
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_driver_init() */
-+
-+module_init(pxa_pcmcia_driver_init);
-+
-+
-+/* pxa_pcmcia_driver_shutdown()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Invokes the low-level kernel service to free IRQs associated with this
-+ * socket controller and reset GPIO edge detection.
-+ */
-+static void __exit pxa_pcmcia_driver_shutdown(void){
-+
-+ del_timer_sync(&poll_timer);
-+ unregister_ss_entry(&pxa_pcmcia_operations);
-+#ifdef CONFIG_CPU_FREQ
-+ cpufreq_unregister_notifier(&pxa_pcmcia_notifier_block);
-+#endif
-+ pcmcia_low_level->shutdown();
-+ flush_scheduled_tasks();
-+
-+ DEBUG(1, "pxa_cs: shutdown complete\n");
-+}
-+
-+module_exit(pxa_pcmcia_driver_shutdown);
-+
-+
-+/* pxa_pcmcia_init()
-+ * ^^^^^^^^^^^^^^^^^^^^
-+ * We perform all of the interesting initialization tasks in
-+ * pxa_pcmcia_driver_init().
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_init(unsigned int sock){
-+
-+ DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_suspend()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^
-+ * We don't currently perform any actions on a suspend.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_suspend(unsigned int sock)
-+{
-+ socket_state_t st;
-+ int ret;
-+
-+ DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
-+
-+ st.Vcc = 0;
-+ st.Vpp = 0;
-+ st.flags = SS_RESET;
-+
-+ ret = pcmcia_low_level->configure_socket(sock, &st);
-+
-+ if (ret == 0)
-+ pxa_pcmcia_socket[sock].cs_state = dead_socket;
-+
-+ return ret;
-+}
-+
-+
-+/* pxa_pcmcia_events()
-+ * ^^^^^^^^^^^^^^^^^^^^^^
-+ * Helper routine to generate a Card Services event mask based on
-+ * state information obtained from the kernel low-level PCMCIA layer
-+ * in a recent (and previous) sampling. Updates `prev_state'.
-+ *
-+ * Returns: an event mask for the given socket state.
-+ */
-+static inline unsigned pxa_pcmcia_events(struct pcmcia_state *state,
-+ struct pcmcia_state *prev_state,
-+ unsigned int mask,
-+ unsigned int flags){
-+ unsigned int events=0;
-+
-+ if(state->detect!=prev_state->detect){
-+
-+ DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
-+
-+ events|=mask&SS_DETECT;
-+ }
-+
-+ if(state->ready!=prev_state->ready){
-+
-+ DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
-+
-+ events|=mask&((flags&SS_IOCARD)?0:SS_READY);
-+ }
-+
-+ if(state->bvd1!=prev_state->bvd1){
-+
-+ DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
-+
-+ events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD;
-+ }
-+
-+ if(state->bvd2!=prev_state->bvd2){
-+
-+ DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
-+
-+ events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN;
-+ }
-+
-+ DEBUG(2, "events: %s%s%s%s%s%s\n",
-+ (events==0)?"<NONE>":"",
-+ (events&SS_DETECT)?"DETECT ":"",
-+ (events&SS_READY)?"READY ":"",
-+ (events&SS_BATDEAD)?"BATDEAD ":"",
-+ (events&SS_BATWARN)?"BATWARN ":"",
-+ (events&SS_STSCHG)?"STSCHG ":"");
-+
-+ *prev_state=*state;
-+
-+ return events;
-+
-+} /* pxa_pcmcia_events() */
-+
-+
-+/* pxa_pcmcia_task_handler()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Processes serviceable socket events using the "eventd" thread context.
-+ *
-+ * Event processing (specifically, the invocation of the Card Services event
-+ * callback) occurs in this thread rather than in the actual interrupt
-+ * handler due to the use of scheduling operations in the PCMCIA core.
-+ */
-+static void pxa_pcmcia_task_handler(void *data) {
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+ int i, events, all_events, irq_status;
-+
-+ DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ do {
-+
-+ DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
-+
-+ if((irq_status=pcmcia_low_level->socket_state(&state_array))<0)
-+ printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
-+
-+ all_events=0;
-+
-+ if(irq_status>0){
-+
-+ for(i=0; i<state_array.size; ++i, all_events|=events)
-+ if((events=
-+ pxa_pcmcia_events(&state[i],
-+ &pxa_pcmcia_socket[i].k_state,
-+ pxa_pcmcia_socket[i].cs_state.csc_mask,
-+ pxa_pcmcia_socket[i].cs_state.flags)))
-+ if(pxa_pcmcia_socket[i].handler!=NULL)
-+ pxa_pcmcia_socket[i].handler(pxa_pcmcia_socket[i].handler_info,
-+ events);
-+ }
-+
-+ } while(all_events);
-+} /* pxa_pcmcia_task_handler() */
-+
-+static struct tq_struct pxa_pcmcia_task = {
-+ routine: pxa_pcmcia_task_handler
-+};
-+
-+
-+/* pxa_pcmcia_poll_event()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Let's poll for events in addition to IRQs since IRQ only is unreliable...
-+ */
-+static void pxa_pcmcia_poll_event(unsigned long dummy)
-+{
-+ DEBUG(3, "%s(): polling for events\n", __FUNCTION__);
-+ poll_timer.function = pxa_pcmcia_poll_event;
-+ poll_timer.expires = jiffies + PXA_PCMCIA_POLL_PERIOD;
-+ add_timer(&poll_timer);
-+ schedule_task(&pxa_pcmcia_task);
-+}
-+
-+
-+/* pxa_pcmcia_interrupt()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Service routine for socket driver interrupts (requested by the
-+ * low-level PCMCIA init() operation via pxa_pcmcia_thread()).
-+ * The actual interrupt-servicing work is performed by
-+ * pxa_pcmcia_thread(), largely because the Card Services event-
-+ * handling code performs scheduling operations which cannot be
-+ * executed from within an interrupt context.
-+ */
-+static void pxa_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
-+ DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
-+ schedule_task(&pxa_pcmcia_task);
-+}
-+
-+
-+/* pxa_pcmcia_register_callback()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the register_callback() operation for the in-kernel
-+ * PCMCIA service (formerly SS_RegisterCallback in Card Services). If
-+ * the function pointer `handler' is not NULL, remember the callback
-+ * location in the state for `sock', and increment the usage counter
-+ * for the driver module. (The callback is invoked from the interrupt
-+ * service routine, pxa_pcmcia_interrupt(), to notify Card Services
-+ * of interesting events.) Otherwise, clear the callback pointer in the
-+ * socket state and decrement the module usage count.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_register_callback(unsigned int sock,
-+ void (*handler)(void *,
-+ unsigned int),
-+ void *info){
-+ if(handler==NULL){
-+ pxa_pcmcia_socket[sock].handler=NULL;
-+ MOD_DEC_USE_COUNT;
-+ } else {
-+ MOD_INC_USE_COUNT;
-+ pxa_pcmcia_socket[sock].handler=handler;
-+ pxa_pcmcia_socket[sock].handler_info=info;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_inquire_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the inquire_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_InquireSocket in Card Services). Of note is
-+ * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of
-+ * `cap' to "trick" Card Services into tolerating large "I/O memory"
-+ * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory
-+ * resource database check. (Mapped memory is set up within the socket
-+ * driver itself.)
-+ *
-+ * In conjunction with the STATIC_MAP capability is a new field,
-+ * `io_offset', recommended by David Hinds. Rather than go through
-+ * the SetIOMap interface (which is not quite suited for communicating
-+ * window locations up from the socket driver), we just pass up
-+ * an offset which is applied to client-requested base I/O addresses
-+ * in alloc_io_space().
-+ *
-+ * Returns: 0 on success, -1 if no pin has been configured for `sock'
-+ */
-+static int pxa_pcmcia_inquire_socket(unsigned int sock,
-+ socket_cap_t *cap){
-+ struct pcmcia_irq_info irq_info;
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(sock>=pxa_pcmcia_socket_count){
-+ printk(KERN_ERR "pxa_cs: socket %u not configured\n", sock);
-+ return -1;
-+ }
-+
-+ /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
-+ * force_low argument to validate_mem() in rsrc_mgr.c -- since in
-+ * general, the mapped * addresses of the PCMCIA memory regions
-+ * will not be within 0xffff, setting force_low would be
-+ * undesirable.
-+ *
-+ * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
-+ * resource database; we instead pass up physical address ranges
-+ * and allow other parts of Card Services to deal with remapping.
-+ *
-+ * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
-+ * not 32-bit CardBus devices.
-+ */
-+ cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
-+
-+ irq_info.sock=sock;
-+ irq_info.irq=-1;
-+
-+ if(pcmcia_low_level->get_irq_info(&irq_info)<0){
-+ printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n",
-+ sock);
-+ return -1;
-+ }
-+
-+ cap->irq_mask=0;
-+ cap->map_size=PAGE_SIZE;
-+ cap->pci_irq=irq_info.irq;
-+ cap->io_offset=pxa_pcmcia_socket[sock].virt_io;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_inquire_socket() */
-+
-+
-+/* pxa_pcmcia_get_status()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_status() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetStatus in Card Services). Essentially just
-+ * fills in bits in `status' according to internal driver state or
-+ * the value of the voltage detect chipselect register.
-+ *
-+ * As a debugging note, during card startup, the PCMCIA core issues
-+ * three set_socket() commands in a row the first with RESET deasserted,
-+ * the second with RESET asserted, and the last with RESET deasserted
-+ * again. Following the third set_socket(), a get_status() command will
-+ * be issued. The kernel is looking for the SS_READY flag (see
-+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_get_status(unsigned int sock,
-+ unsigned int *status){
-+ struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
-+ struct pcmcia_state_array state_array;
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ state_array.size=pxa_pcmcia_socket_count;
-+ state_array.state=state;
-+
-+ if((pcmcia_low_level->socket_state(&state_array))<0){
-+ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
-+ return -1;
-+ }
-+
-+ pxa_pcmcia_socket[sock].k_state=state[sock];
-+
-+ *status=state[sock].detect?SS_DETECT:0;
-+
-+ *status|=state[sock].ready?SS_READY:0;
-+
-+ /* The power status of individual sockets is not available
-+ * explicitly from the hardware, so we just remember the state
-+ * and regurgitate it upon request:
-+ */
-+ *status|=pxa_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
-+
-+ if(pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
-+ *status|=state[sock].bvd1?SS_STSCHG:0;
-+ else {
-+ if(state[sock].bvd1==0)
-+ *status|=SS_BATDEAD;
-+ else if(state[sock].bvd2==0)
-+ *status|=SS_BATWARN;
-+ }
-+
-+ *status|=state[sock].vs_3v?SS_3VCARD:0;
-+
-+ *status|=state[sock].vs_Xv?SS_XVCARD:0;
-+
-+ DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n",
-+ (*status&SS_DETECT)?"DETECT ":"",
-+ (*status&SS_READY)?"READY ":"",
-+ (*status&SS_BATDEAD)?"BATDEAD ":"",
-+ (*status&SS_BATWARN)?"BATWARN ":"",
-+ (*status&SS_POWERON)?"POWERON ":"",
-+ (*status&SS_STSCHG)?"STSCHG ":"",
-+ (*status&SS_3VCARD)?"3VCARD ":"",
-+ (*status&SS_XVCARD)?"XVCARD ":"");
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_get_status() */
-+
-+
-+/* pxa_pcmcia_get_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetSocket in Card Services). Not a very
-+ * exciting routine.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_get_socket(unsigned int sock,
-+ socket_state_t *state){
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ /* This information was given to us in an earlier call to set_socket(),
-+ * so we're just regurgitating it here:
-+ */
-+ *state=pxa_pcmcia_socket[sock].cs_state;
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_socket()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_socket() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetSocket in Card Services). We more or
-+ * less punt all of this work and let the kernel handle the details
-+ * of power configuration, reset, &c. We also record the value of
-+ * `state' in order to regurgitate it to the PCMCIA core later.
-+ *
-+ * Returns: 0
-+ */
-+static int pxa_pcmcia_set_socket(unsigned int sock,
-+ socket_state_t *state){
-+
-+ DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
-+ "\tVcc %d Vpp %d irq %d\n",
-+ (state->csc_mask==0)?"<NONE>":"",
-+ (state->csc_mask&SS_DETECT)?"DETECT ":"",
-+ (state->csc_mask&SS_READY)?"READY ":"",
-+ (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-+ (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-+ (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-+ (state->flags==0)?"<NONE>":"",
-+ (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-+ (state->flags&SS_IOCARD)?"IOCARD ":"",
-+ (state->flags&SS_RESET)?"RESET ":"",
-+ (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-+ (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
-+ state->Vcc, state->Vpp, state->io_irq);
-+
-+ if(pcmcia_low_level->configure_socket(sock, state)<0){
-+ printk(KERN_ERR "Unable to configure socket %u\n", sock);
-+ return -1;
-+ }
-+
-+ pxa_pcmcia_socket[sock].cs_state=*state;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_socket() */
-+
-+
-+/* pxa_pcmcia_get_io_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_io_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetIOMap in Card Services). Just returns an
-+ * I/O map descriptor which was assigned earlier by a set_io_map().
-+ *
-+ * Returns: 0 on success, -1 if the map index was out of range
-+ */
-+static int pxa_pcmcia_get_io_map(unsigned int sock,
-+ struct pccard_io_map *map){
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(map->map>=MAX_IO_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ *map=pxa_pcmcia_socket[sock].io_map[map->map];
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_io_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_io_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetIOMap in Card Services). We configure
-+ * the map speed as requested, but override the address ranges
-+ * supplied by Card Services.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_set_io_map(unsigned int sock,
-+ struct pccard_io_map *map){
-+ unsigned int clock, speed;
-+ unsigned long mecr, start;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n"
-+ "\tflags: %s%s%s%s%s%s%s%s\n",
-+ map->map, map->speed, map->start, map->stop,
-+ (map->flags==0)?"<NONE>":"",
-+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-+ (map->flags&MAP_16BIT)?"16BIT ":"",
-+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-+ (map->flags&MAP_0WS)?"0WS ":"",
-+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
-+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-+ (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
-+
-+ if(map->map>=MAX_IO_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ if(map->flags&MAP_ACTIVE){
-+
-+ speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS;
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ pxa_pcmcia_socket[sock].speed_io=speed;
-+
-+ if (sock == 0) {
-+ MCIO0 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCIO1 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+
-+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
-+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
-+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
-+ sock, MECR_BSIO_GET(mecr, sock));
-+
-+ }
-+
-+ start=map->start;
-+
-+ if(map->stop==1)
-+ map->stop=PAGE_SIZE-1;
-+
-+ map->start=pxa_pcmcia_socket[sock].virt_io;
-+ map->stop=map->start+(map->stop-start);
-+
-+ pxa_pcmcia_socket[sock].io_map[map->map]=*map;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_io_map() */
-+
-+
-+/* pxa_pcmcia_get_mem_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the get_mem_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_GetMemMap in Card Services). Just returns a
-+ * memory map descriptor which was assigned earlier by a
-+ * set_mem_map() request.
-+ *
-+ * Returns: 0 on success, -1 if the map index was out of range
-+ */
-+static int pxa_pcmcia_get_mem_map(unsigned int sock,
-+ struct pccard_mem_map *map){
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if(map->map>=MAX_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ *map=pxa_pcmcia_socket[sock].mem_map[map->map];
-+
-+ return 0;
-+}
-+
-+
-+/* pxa_pcmcia_set_mem_map()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the set_mem_map() operation for the in-kernel PCMCIA
-+ * service (formerly SS_SetMemMap in Card Services). We configure
-+ * the map speed as requested, but override the address ranges
-+ * supplied by Card Services.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_set_mem_map(unsigned int sock,
-+ struct pccard_mem_map *map){
-+ unsigned int clock, speed;
-+ unsigned long mecr, start;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n"
-+ "\tsys_stop %#lx\n\tcard_start %#x\n"
-+ "\tflags: %s%s%s%s%s%s%s%s\n",
-+ map->map, map->speed, map->sys_start, map->sys_stop,
-+ map->card_start, (map->flags==0)?"<NONE>":"",
-+ (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-+ (map->flags&MAP_16BIT)?"16BIT ":"",
-+ (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-+ (map->flags&MAP_0WS)?"0WS ":"",
-+ (map->flags&MAP_WRPROT)?"WRPROT ":"",
-+ (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-+ (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
-+
-+ if(map->map>=MAX_WIN){
-+ printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
-+ map->map);
-+ return -1;
-+ }
-+
-+ if(map->flags&MAP_ACTIVE){
-+ /* When clients issue RequestMap, the access speed is not always
-+ * properly configured:
-+ */
-+ if(map->speed > 0)
-+ speed = map->speed;
-+ else
-+ switch(pxa_pcmcia_socket[sock].cs_state.Vcc){
-+ case 33:
-+ speed = PXA_PCMCIA_3V_MEM_ACCESS;
-+ break;
-+ default:
-+ speed = PXA_PCMCIA_5V_MEM_ACCESS;
-+ }
-+
-+ clock = get_lclk_frequency_10khz();
-+
-+ if(map->flags&MAP_ATTRIB){
-+ if (sock == 0) {
-+ MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(PXA_PCMCIA_ATTR_MEM_ACCESS, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+ pxa_pcmcia_socket[sock].speed_attr=speed;
-+ } else {
-+ if (sock == 0) {
-+ MCMEM0 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ } else {
-+ MCMEM1 = ((pxa_mcxx_setup(speed, clock)
-+ & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
-+ | ((pxa_mcxx_asst(speed, clock)
-+ & MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
-+ | ((pxa_mcxx_hold(speed, clock)
-+ & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
-+ }
-+ pxa_pcmcia_socket[sock].speed_mem=speed;
-+ }
-+ DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
-+ __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
-+ MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
-+ sock, MECR_BSIO_GET(mecr, sock));
-+ }
-+
-+ start=map->sys_start;
-+
-+ if(map->sys_stop==0)
-+ map->sys_stop=PAGE_SIZE-1;
-+
-+ map->sys_start=(map->flags & MAP_ATTRIB)?\
-+ pxa_pcmcia_socket[sock].phys_attr:\
-+ pxa_pcmcia_socket[sock].phys_mem;
-+
-+ map->sys_stop=map->sys_start+(map->sys_stop-start);
-+
-+ pxa_pcmcia_socket[sock].mem_map[map->map]=*map;
-+
-+ return 0;
-+
-+} /* pxa_pcmcia_set_mem_map() */
-+
-+
-+#if defined(CONFIG_PROC_FS)
-+
-+/* pxa_pcmcia_proc_setup()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the proc_setup() operation for the in-kernel PCMCIA
-+ * service (formerly SS_ProcSetup in Card Services).
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static void pxa_pcmcia_proc_setup(unsigned int sock,
-+ struct proc_dir_entry *base){
-+ struct proc_dir_entry *entry;
-+
-+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-+
-+ if((entry=create_proc_entry("status", 0, base))==NULL){
-+ printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
-+ return;
-+ }
-+
-+ entry->read_proc=pxa_pcmcia_proc_status;
-+ entry->data=(void *)sock;
-+}
-+
-+
-+/* pxa_pcmcia_proc_status()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * Implements the /proc/bus/pccard/??/status file.
-+ *
-+ * Returns: the number of characters added to the buffer
-+ */
-+static int pxa_pcmcia_proc_status(char *buf, char **start, off_t pos,
-+ int count, int *eof, void *data){
-+ char *p=buf;
-+ unsigned int sock=(unsigned int)data;
-+ unsigned int clock = get_lclk_frequency_10khz();
-+ unsigned long mecr = MECR;
-+
-+ p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].k_state.detect?"detect ":"",
-+ pxa_pcmcia_socket[sock].k_state.ready?"ready ":"",
-+ pxa_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
-+ pxa_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
-+ pxa_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
-+
-+ p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
-+ pxa_pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
-+ pxa_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
-+ "SS_IOCARD ":"",
-+ (pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
-+ pxa_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
-+ ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
-+ (pxa_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
-+ ((pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
-+ (pxa_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
-+ pxa_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
-+
-+ p+=sprintf(p, "mask : %s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
-+ "SS_DETECT ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
-+ "SS_READY ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
-+ "SS_BATDEAD ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
-+ "SS_BATWARN ":"",
-+ pxa_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
-+ "SS_STSCHG ":"");
-+
-+ p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
-+ "SS_PWR_AUTO ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
-+ "SS_IOCARD ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_RESET?\
-+ "SS_RESET ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
-+ "SS_SPKR_ENA ":"",
-+ pxa_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
-+ "SS_OUTPUT_ENA ":"");
-+
-+ p+=sprintf(p, "Vcc : %d\n", pxa_pcmcia_socket[sock].cs_state.Vcc);
-+
-+ p+=sprintf(p, "Vpp : %d\n", pxa_pcmcia_socket[sock].cs_state.Vpp);
-+
-+ p+=sprintf(p, "irq : %d\n", pxa_pcmcia_socket[sock].cs_state.io_irq);
-+
-+ p+=sprintf(p, "I/O : %u (%u)\n", pxa_pcmcia_socket[sock].speed_io,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCIO1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCIO0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ p+=sprintf(p, "attribute: %u (%u)\n", pxa_pcmcia_socket[sock].speed_attr,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCATT1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCATT0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ p+=sprintf(p, "common : %u (%u)\n", pxa_pcmcia_socket[sock].speed_mem,
-+ sock ?
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCMEM1 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)) :
-+ pxa_pcmcia_cmd_time(clock,
-+ ((MCMEM0 >> MCXX_ASST_SHIFT) & MCXX_ASST_MASK)));
-+
-+ return p-buf;
-+}
-+
-+#endif /* defined(CONFIG_PROC_FS) */
-+
-+
-+#ifdef CONFIG_CPU_FREQ
-+
-+/* pxa_pcmcia_update_mecr()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * When pxa_pcmcia_notifier() decides that a MECR adjustment (due
-+ * to a core clock frequency change) is needed, this routine establishes
-+ * new BS_xx values consistent with the clock speed `clock'.
-+ */
-+static void pxa_pcmcia_update_mecr(unsigned int clock){
-+ unsigned int sock;
-+
-+ for(sock = 0; sock < PXA_PCMCIA_MAX_SOCK; ++sock){
-+
-+ // REVISIT: MCXX macros needed here
-+ // MECR_BSIO_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_io,
-+// clock));
-+ // MECR_BSA_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_attr,
-+// clock));
-+ // MECR_BSM_SET(mecr, sock,
-+// pxa_pcmcia_mecr_bs(pxa_pcmcia_socket[sock].speed_mem,
-+// clock));
-+ }
-+}
-+
-+/* pxa_pcmcia_notifier()
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^
-+ * When changing the processor core clock frequency, it is necessary
-+ * to adjust the MECR timings accordingly. We've recorded the timings
-+ * requested by Card Services, so this is just a matter of finding
-+ * out what our current speed is, and then recomputing the new MECR
-+ * values.
-+ *
-+ * Returns: 0 on success, -1 on error
-+ */
-+static int pxa_pcmcia_notifier(struct notifier_block *nb,
-+ unsigned long val, void *data){
-+ struct cpufreq_info *ci = data;
-+
-+ switch(val){
-+ case CPUFREQ_MINMAX:
-+
-+ break;
-+
-+ case CPUFREQ_PRECHANGE:
-+
-+ if(ci->new_freq > ci->old_freq){
-+ DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
-+ __FUNCTION__,
-+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
-+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
-+ pxa_pcmcia_update_mecr(ci->new_freq);
-+ }
-+
-+ break;
-+
-+ case CPUFREQ_POSTCHANGE:
-+
-+ if(ci->new_freq < ci->old_freq){
-+ DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
-+ __FUNCTION__,
-+ ci->new_freq / 1000, (ci->new_freq / 100) % 10,
-+ ci->old_freq / 1000, (ci->old_freq / 100) % 10);
-+ pxa_pcmcia_update_mecr(ci->new_freq);
-+ }
-+
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__,
-+ val);
-+ return -1;
-+
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static struct notifier_block pxa_pcmcia_notifier_block = {
-+ notifier_call: pxa_pcmcia_notifier
-+};
-+
-+#endif
-+
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/pxa.h
-@@ -0,0 +1,233 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Originally based upon linux/drivers/pcmcia/sa1100_generic.h
-+ *
-+ */
-+
-+/*======================================================================
-+
-+ Device driver for the PCMCIA control functionality of Intel
-+ PXA250/210 microprocessors.
-+
-+ The contents of this file are subject to the Mozilla Public
-+ License Version 1.1 (the "License"); you may not use this file
-+ except in compliance with the License. You may obtain a copy of
-+ the License at http://www.mozilla.org/MPL/
-+
-+ Software distributed under the License is distributed on an "AS
-+ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-+ implied. See the License for the specific language governing
-+ rights and limitations under the License.
-+
-+ The initial developer of the original code is John G. Dorsey
-+ <john+@cs.cmu.edu>. Portions created by John G. Dorsey are
-+ Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
-+
-+ Alternatively, the contents of this file may be used under the
-+ terms of the GNU Public License version 2 (the "GPL"), in which
-+ case the provisions of the GPL are applicable instead of the
-+ above. If you wish to allow the use of your version of this file
-+ only under the terms of the GPL and not to allow others to use
-+ your version of this file under the MPL, indicate your decision
-+ by deleting the provisions above and replace them with the notice
-+ and other provisions required by the GPL. If you do not delete
-+ the provisions above, a recipient may use your version of this
-+ file under either the MPL or the GPL.
-+
-+======================================================================*/
-+
-+#if !defined(_PCMCIA_PXA_H)
-+# define _PCMCIA_PXA_H
-+
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/ss.h>
-+#include <pcmcia/bulkmem.h>
-+#include <pcmcia/cistpl.h>
-+#include "../cs_internal.h"
-+
-+#include <asm/arch/pcmcia.h>
-+
-+
-+/* MECR: Expansion Memory Configuration Register
-+ * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
-+ *
-+ * MECR layout is:
-+ *
-+ * FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
-+ *
-+ * (This layout is actually true only for the SA-1110; the FASTn bits are
-+ * reserved on the SA-1100.)
-+ */
-+
-+#define MCXX_SETUP_MASK (0x7f)
-+#define MCXX_ASST_MASK (0x1f)
-+#define MCXX_HOLD_MASK (0x3f)
-+#define MCXX_SETUP_SHIFT (0)
-+#define MCXX_ASST_SHIFT (7)
-+#define MCXX_HOLD_SHIFT (14)
-+
-+
-+#define MECR_SET(mecr, sock, shift, mask, bs) \
-+((mecr)=((mecr)&~(((mask)<<(shift))<<\
-+ ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
-+ (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
-+
-+#define MECR_GET(mecr, sock, shift, mask) \
-+((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
-+ (shift))&(mask))
-+
-+#define MECR_BSIO_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSIO_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_BSA_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSA_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_BSM_SET(mecr, sock, bs) \
-+MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
-+
-+#define MECR_BSM_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
-+
-+#define MECR_FAST_SET(mecr, sock, fast) \
-+MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
-+
-+#define MECR_FAST_GET(mecr, sock) \
-+MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
-+
-+
-+/* This function implements the BS value calculation for setting the MECR
-+ * using integer arithmetic:
-+ */
-+static inline unsigned int pxa_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
-+ unsigned int cpu_clock_khz){
-+ unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
-+ return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
-+}
-+
-+static inline u_int pxa_mcxx_hold(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 300000) + ((code % 300000) ? 1 : 0);
-+}
-+
-+static inline u_int pxa_mcxx_asst(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 300000) + ((code % 300000) ? 1 : 0);
-+}
-+
-+static inline u_int pxa_mcxx_setup(u_int pcmcia_cycle_ns,
-+ u_int mem_clk_10khz){
-+ u_int code = pcmcia_cycle_ns * mem_clk_10khz;
-+ return (code / 100000) + ((code % 100000) ? 1 : 0) + 1;
-+}
-+
-+/* This function returns the (approxmiate) command assertion period, in
-+ * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
-+ */
-+
-+static inline u_int pxa_pcmcia_cmd_time(u_int mem_clk_10khz,
-+ u_int pcmcia_mcxx_asst){
-+ return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
-+}
-+
-+
-+/* SA-1100 PCMCIA Memory and I/O timing
-+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-+ * The SA-1110 Developer's Manual, section 10.2.5, says the following:
-+ *
-+ * "To calculate the recommended BS_xx value for each address space:
-+ * divide the command width time (the greater of twIOWR and twIORD,
-+ * or the greater of twWE and twOE) by processor cycle time; divide
-+ * by 2; divide again by 3 (number of BCLK's per command assertion);
-+ * round up to the next whole number; and subtract 1."
-+ *
-+ * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
-+ * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
-+ * a minimum value of 165ns, as well. Section 4.7.2 (describing
-+ * common and attribute memory write timing) says that twWE has a
-+ * minimum value of 150ns for a 250ns cycle time (for 5V operation;
-+ * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
-+ * operation, also section 4.7.4). Section 4.7.3 says that taOE
-+ * has a maximum value of 150ns for a 300ns cycle time (for 5V
-+ * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
-+ *
-+ * When configuring memory maps, Card Services appears to adopt the policy
-+ * that a memory access time of "0" means "use the default." The default
-+ * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
-+ * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
-+ * memory command width time is 300ns.
-+ */
-+
-+/* The PXA 250 and PXA 210 Application Processors Developer's Manual
-+ * was used to determine correct PXA_PCMCIA_IO_ACCES time
-+ */
-+
-+#define PXA_PCMCIA_IO_ACCESS (165)
-+
-+/* Default PC Card Common Memory timings*/
-+
-+#define PXA_PCMCIA_5V_MEM_ACCESS (250)
-+#define PXA_PCMCIA_3V_MEM_ACCESS (250)
-+
-+/* Atrribute Memory timing - must be constant via PC Card standart*/
-+
-+#define PXA_PCMCIA_ATTR_MEM_ACCESS (300)
-+
-+
-+/* The socket driver actually works nicely in interrupt-driven form,
-+ * so the (relatively infrequent) polling is "just to be sure."
-+ */
-+#define PXA_PCMCIA_POLL_PERIOD (2*HZ)
-+
-+
-+/* This structure encapsulates per-socket state which we might need to
-+ * use when responding to a Card Services query of some kind.
-+ */
-+struct pxa_pcmcia_socket {
-+ socket_state_t cs_state;
-+ struct pcmcia_state k_state;
-+ unsigned int irq;
-+ void (*handler)(void *, unsigned int);
-+ void *handler_info;
-+ pccard_io_map io_map[MAX_IO_WIN];
-+ pccard_mem_map mem_map[MAX_WIN];
-+ ioaddr_t virt_io, phys_attr, phys_mem;
-+ unsigned short speed_io, speed_attr, speed_mem;
-+};
-+
-+
-+/* I/O pins replacing memory pins
-+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
-+ *
-+ * These signals change meaning when going from memory-only to
-+ * memory-or-I/O interface:
-+ */
-+#define iostschg bvd1
-+#define iospkr bvd2
-+
-+
-+/*
-+ * Declaration for all implementation specific low_level operations.
-+ */
-+extern struct pcmcia_low_level lubbock_pcmcia_ops;
-+extern struct pcmcia_low_level pxa_idp_pcmcia_ops;
-+extern struct pcmcia_low_level cerf_pcmcia_ops;
-+extern struct pcmcia_low_level trizeps2_pcmcia_ops;
-+
-+#endif /* !defined(_PCMCIA_PXA_H) */
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/pxa_idp.c
-@@ -0,0 +1,297 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/pxa_idp.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
-+ *
-+ * Platform specific routines for the Accelent PXA250 IDP, based on those
-+ * first done for the Lubbock.
-+ *
-+ * Version 1.0 2002-05-02 Jeff Sutherland <jeffs@accelent.com>
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+static int
-+pxa_idp_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int return_val = 0;
-+
-+ /* Set PCMCIA Socket 0 power to standby mode.
-+ * PXA IDP has dedicated CPLD pins for all this stuff :-)
-+ */
-+
-+ /* both slots disabled, reset NOT active */
-+ IDP_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE;
-+
-+ IDP_CPLD_PCCARD_PWR = 0; //all power to both slots off
-+
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID));
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID));
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_CD_VALID),
-+ GPIO_BOTH_EDGES);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_CD_VALID),
-+ GPIO_BOTH_EDGES);
-+
-+ /* irq's for slots: */
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT));
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT));
-+
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S0_RDYINT),
-+ GPIO_FALLING_EDGE);
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S1_RDYINT),
-+ GPIO_FALLING_EDGE);
-+
-+ return_val =
-+ request_irq(PCMCIA_S0_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD0", NULL);
-+
-+ if (return_val < 0)
-+ return -1;
-+
-+ return_val +=
-+ request_irq(PCMCIA_S1_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD1", NULL);
-+
-+ if (return_val < 0) {
-+ free_irq(PCMCIA_S0_CD_VALID, NULL);
-+ return -1;
-+ }
-+
-+ return 2;
-+}
-+
-+static int
-+pxa_idp_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(PCMCIA_S0_CD_VALID, NULL);
-+ free_irq(PCMCIA_S1_CD_VALID, NULL);
-+
-+ IDP_CPLD_PCCARD_EN = 0x03; //disable slots
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR = 0; //shut off all power
-+
-+ return 0;
-+}
-+
-+static int
-+pxa_idp_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ unsigned long status;
-+ int return_val = 1;
-+ int i;
-+ volatile unsigned long *stat_regs[2] = { &IDP_CPLD_PCCARD0_STATUS,
-+ &IDP_CPLD_PCCARD1_STATUS
-+ };
-+
-+ if (state_array->size < 2)
-+ return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size) * sizeof (struct pcmcia_state));
-+
-+ for (i = 0; i < 2; i++) {
-+
-+ status = *stat_regs[i];
-+
-+ /* this one is a gpio */
-+ state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1;
-+
-+ state_array->state[i].ready =
-+ ((status & _PCC_IRQ) == 0) ? 0 : 1;
-+ state_array->state[i].bvd1 = (status & PCC_BVD1) ? 0 : 1;
-+ state_array->state[i].bvd2 = (status & PCC_BVD2) ? 0 : 1;
-+ state_array->state[i].wrprot =
-+ (status & _PCC_WRPROT) ? 1 : 0;
-+ state_array->state[i].vs_3v = (status & PCC_VS1) ? 0 : 1;
-+ state_array->state[i].vs_Xv = (status & PCC_VS2) ? 0 : 1;
-+ }
-+
-+ return return_val;
-+}
-+
-+static int
-+pxa_idp_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-+{
-+ switch (info->sock) {
-+ case 0:
-+ info->irq = PCMCIA_S0_RDYINT;
-+ break;
-+
-+ case 1:
-+ info->irq = PCMCIA_S1_RDYINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+pxa_idp_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ /* The PXA Idp uses the Maxim MAX1602, with the following connections:
-+ *
-+ * Socket 0 (PCMCIA):
-+ * MAX1602 PXA_IDP Register
-+ * Pin Signal IDP_CPLD_PCCARD_PWR:
-+ * ----- ------- ----------------------
-+ * A0VPP PCC0_PWR0 bit0
-+ * A1VPP PCC0_PWR1 bit1
-+ * A0VCC PCC0_PWR2 bit2
-+ * A1VCC PCC0_PWR3 bit3
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ * Socket 1 (PCMCIA):
-+ * MAX1602 PXA_IDP Register
-+ * Pin Signal IDP_CPLD_PCCARD_PWR:
-+ * ----- ------- ----------------------
-+ * A0VPP PCC1_PWR0 bit4
-+ * A1VPP PCC1_PWR1 bit5
-+ * A0VCC PCC1_PWR2 bit6
-+ * A1VCC PCC1_PWR3 bit7
-+ * VX VCC
-+ * VY +3.3V
-+ * 12IN +12V
-+ * CODE +3.3V Cirrus Code, CODE = High (VY)
-+ *
-+ */
-+
-+ switch (sock) {
-+ case 0:
-+ switch (state->Vcc) {
-+ case 0:
-+ IDP_CPLD_PCCARD_EN |= PCC0_ENABLE; // disable socket
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ break;
-+
-+ case 33:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR3;
-+ IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE; //turn it on
-+ break;
-+
-+ case 50:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR2 | PCC0_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR2;
-+ IDP_CPLD_PCCARD_EN &= ~PCC0_ENABLE;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
-+ break;
-+
-+ case 120:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC0_PWR0 | PCC0_PWR1);
-+ IDP_CPLD_PCCARD_PWR |= PCC0_PWR1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc)
-+ IDP_CPLD_PCCARD_PWR =
-+ (IDP_CPLD_PCCARD_PWR &
-+ ~(PCC0_PWR0 | PCC0_PWR1)) | PCC0_PWR0;
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+
-+ IDP_CPLD_PCCARD_EN =
-+ (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC0_RESET)
-+ : (IDP_CPLD_PCCARD_EN & ~PCC0_RESET);
-+ break;
-+
-+ case 1:
-+ switch (state->Vcc) {
-+ case 0:
-+ IDP_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket
-+ udelay(200);
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ break;
-+
-+ case 33:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR3;
-+ IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on
-+ break;
-+
-+ case 50:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR2;
-+ IDP_CPLD_PCCARD_EN &= ~PCC1_ENABLE;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
-+ break;
-+
-+ case 120:
-+ IDP_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
-+ IDP_CPLD_PCCARD_PWR |= PCC1_PWR1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc)
-+ IDP_CPLD_PCCARD_PWR =
-+ (IDP_CPLD_PCCARD_PWR &
-+ ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0;
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+ IDP_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (IDP_CPLD_PCCARD_EN | PCC1_RESET)
-+ : (IDP_CPLD_PCCARD_EN & ~PCC1_RESET);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+struct pcmcia_low_level pxa_idp_pcmcia_ops = {
-+ pxa_idp_pcmcia_init,
-+ pxa_idp_pcmcia_shutdown,
-+ pxa_idp_pcmcia_socket_state,
-+ pxa_idp_pcmcia_get_irq_info,
-+ pxa_idp_pcmcia_configure_socket
-+};
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/pxa/trizeps2.c
-@@ -0,0 +1,187 @@
-+/*
-+ * linux/drivers/pcmcia/pxa/trizeps2.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Accelent Systems, Inc. All Rights Reserved
-+ *
-+ * Platform specific routines for the Keith-n-Koep Trizeps-II, based on IDP
-+ *
-+ * Copyright (c) 2003 Teradyne DS, Ltd.
-+ * Port to Trizeps-2 MT6N board by Luc De Cock
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+
-+#include <pcmcia/ss.h>
-+
-+#include <asm/delay.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+static int trizeps2_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int return_val = 0;
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+ unsigned short val;
-+
-+ /* reset the PCMCIA controller */
-+ val = trizeps2_bcr_shadow | BCR_PCMCIA_RESET;
-+ *bcr = val;
-+ udelay(500);
-+ /* un-reset it again */
-+ trizeps2_bcr_shadow &= ~BCR_PCMCIA_RESET;
-+ /* enable the PCMCIA buffer */
-+ trizeps2_bcr_shadow &= ~(1 << 5);
-+ *bcr = trizeps2_bcr_shadow;
-+
-+ GPDR(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID));
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(PCMCIA_S_CD_VALID),
-+ PCMCIA_S_CD_VALID_EDGE);
-+ GPDR(IRQ_TO_GPIO(PCMCIA_S_RDYINT)) &=
-+ ~GPIO_bit(IRQ_TO_GPIO(PCMCIA_S_RDYINT));
-+ set_GPIO_IRQ_edge(IRQ_TO_GPIO(PCMCIA_S_RDYINT),
-+ PCMCIA_S_RDYINT_EDGE);
-+
-+ return_val = request_irq(PCMCIA_S_CD_VALID, init->handler, SA_INTERRUPT,
-+ "PXA PCMCIA CD", NULL);
-+ if (return_val < 0) {
-+ return -1;
-+ }
-+ /* only 1 slot */
-+ return 1;
-+}
-+
-+static int trizeps2_pcmcia_shutdown(void)
-+{
-+ free_irq(PCMCIA_S_CD_VALID, NULL);
-+
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+ trizeps2_bcr_shadow |= (1 << 5); /* pcmcia buffer off */
-+ *bcr = trizeps2_bcr_shadow;
-+ trizeps2_bcr_shadow &= 0xFFF0; /* pcmcia control logic grounded */
-+ *bcr = trizeps2_bcr_shadow;
-+
-+ return 0;
-+}
-+
-+static int trizeps2_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ unsigned long status;
-+ int return_val = 1;
-+ volatile unsigned short *stat_regs[1] = {
-+ &TRIZEPS2_PCCARD_STATUS
-+ };
-+
-+ if (state_array->size < 1)
-+ return -1;
-+
-+ memset(state_array->state, 0,
-+ (state_array->size) * sizeof (struct pcmcia_state));
-+
-+ status = *stat_regs[0];
-+
-+ /* this one is a gpio */
-+ state_array->state[0].detect = (PCC_DETECT) ? 0 : 1;
-+ state_array->state[0].ready = (PCC_READY) ? 1 : 0;
-+ state_array->state[0].bvd1 = (status & PCC_BVD1) ? 1 : 0;
-+ state_array->state[0].bvd2 = (status & PCC_BVD2) ? 1 : 0;
-+ state_array->state[0].wrprot = 0; /* r/w all the time */
-+ state_array->state[0].vs_3v = (status & PCC_VS1) ? 0 : 1;
-+ state_array->state[0].vs_Xv = (status & PCC_VS2) ? 0 : 1;
-+
-+ return return_val;
-+}
-+
-+static int trizeps2_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-+{
-+ switch (info->sock) {
-+ case 0:
-+ info->irq = PCMCIA_S_RDYINT;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int trizeps2_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
-+{
-+ unsigned short cntr_logic = trizeps2_bcr_shadow & 0xF;
-+ unsigned short *bcr = (unsigned short *) TRIZEPS2_BCR_BASE;
-+
-+ /* configure Vcc and Vpp */
-+ switch (sock) {
-+ case 0:
-+ switch (state->Vcc) {
-+ case 0:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ break;
-+
-+ case 33:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ cntr_logic |= PCC_3V;
-+ break;
-+
-+ case 50:
-+ cntr_logic &= ~(PCC_3V | PCC_5V);
-+ cntr_logic |= PCC_5V;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-+
-+ switch (state->Vpp) {
-+ case 0:
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ break;
-+
-+ case 120:
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ cntr_logic |= PCC_EN1;
-+ break;
-+
-+ default:
-+ if (state->Vpp == state->Vcc) {
-+ cntr_logic &= ~(PCC_EN0 | PCC_EN1);
-+ cntr_logic |= PCC_EN0;
-+ }
-+ else {
-+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
-+ __FUNCTION__, state->Vpp);
-+ return -1;
-+ }
-+ }
-+ trizeps2_bcr_shadow &= ~(PCC_EN0 | PCC_EN1 | PCC_3V | PCC_5V |
-+ BCR_PCMCIA_RESET);
-+ trizeps2_bcr_shadow |= cntr_logic;
-+ *bcr = trizeps2_bcr_shadow;
-+ /* reset PCMCIA controller if requested */
-+ trizeps2_bcr_shadow |=
-+ (state->flags & SS_RESET) ? BCR_PCMCIA_RESET : 0;
-+ *bcr = trizeps2_bcr_shadow;
-+ udelay(500);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+struct pcmcia_low_level trizeps2_pcmcia_ops = {
-+ trizeps2_pcmcia_init,
-+ trizeps2_pcmcia_shutdown,
-+ trizeps2_pcmcia_socket_state,
-+ trizeps2_pcmcia_get_irq_info,
-+ trizeps2_pcmcia_configure_socket
-+};
-+
---- linux-2.4.27/drivers/pcmcia/sa1100_cerf.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_cerf.c
-@@ -7,15 +7,25 @@
- */
- #include <linux/kernel.h>
- #include <linux/sched.h>
-+#include <linux/delay.h>
-
- #include <asm/hardware.h>
- #include <asm/irq.h>
--#include "sa1100_generic.h"
-
--#ifdef CONFIG_SA1100_CERF_CPLD
--#define CERF_SOCKET 0
-+#include <pcmcia/ss.h>
-+#include <asm/arch/pcmcia.h>
-+#include "sa1100_cerf.h"
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination
-+ */
-+//#define DEBUGGING 1
-+
-+#if DEBUGGING
-+static unsigned int pcmcia_debug = DEBUGGING;
- #else
--#define CERF_SOCKET 1
-+#define pcmcia_debug 0 /* gcc will remove all the debug code for us */
- #endif
-
- static struct irqs {
-@@ -23,122 +33,178 @@
- unsigned int gpio;
- const char *str;
- } irqs[] = {
-- { IRQ_GPIO_CF_CD, GPIO_CF_CD, "CF_CD" },
-- { IRQ_GPIO_CF_BVD2, GPIO_CF_BVD2, "CF_BVD2" },
-- { IRQ_GPIO_CF_BVD1, GPIO_CF_BVD1, "CF_BVD1" }
-+ { PCMCIA_IRQ_CF_CD, PCMCIA_GPIO_CF_CD_EDGE, "CF_CD" },
-+ { PCMCIA_IRQ_CF_BVD2, PCMCIA_GPIO_CF_BVD2_EDGE, "CF_BVD2" },
-+ { PCMCIA_IRQ_CF_BVD1, PCMCIA_GPIO_CF_BVD1_EDGE, "CF_BVD1" }
- };
-
-+static void cerf_pcmcia_reset( void)
-+{
-+ int i;
-+
-+ // Make sure SKTSEL is 0 (single slot)
-+ set_GPIO_mode(54 | GPIO_OUT);
-+ GPCR1 = GPIO_bit(54);
-+ set_GPIO_mode(GPIO54_pSKTSEL_MD);
-+
-+ PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
-+ mdelay(300);
-+
-+ PCMCIA_GPSR = PCMCIA_GPIO_CF_RESET_MASK;
-+ udelay(20);
-+
-+ PCMCIA_GPCR = PCMCIA_GPIO_CF_RESET_MASK;
-+ mdelay(50);
-+
-+ for( i=0; i<10; i++)
-+ {
-+ if( cerf_pcmcia_level_ready()) break;
-+ mdelay(100);
-+ }
-+}
-+
- static int cerf_pcmcia_init(struct pcmcia_init *init)
- {
-- int i, res;
-+ int i, res;
-
-- set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_init: enter\n");
-
-- for (i = 0; i < ARRAY_SIZE(irqs); i++) {
-- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
-- res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-- irqs[i].str, NULL);
-- if (res)
-- goto irq_err;
-- }
-+ cerf_pcmcia_set_gpio_direction();
-
-- return 2;
-+ set_GPIO_IRQ_edge( PCMCIA_GPIO_CF_IRQ_EDGE, GPIO_FALLING_EDGE );
-
-- irq_err:
-- printk(KERN_ERR "%s: Request for IRQ%d failed\n", __FUNCTION__, irqs[i].irq);
-+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
-
-- while (i--)
-- free_irq(irqs[i].irq, NULL);
-+ set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
-
-- return -1;
-+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (res)
-+ goto irq_err;
-+ }
-+
-+ printk( KERN_INFO "PCMCIA for Cerf: OK\n");
-+
-+ return CERF_SOCKET+1; /* last socket used +1 */
-+
-+irq_err:
-+ printk(KERN_ERR "%s: Request for IRQ%d failed\n",
-+ __FUNCTION__, irqs[i].irq);
-+
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ return -1;
- }
-
- static int cerf_pcmcia_shutdown(void)
- {
-- int i;
-+ int i;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_shutdown: enter\n");
-
-- for (i = 0; i < ARRAY_SIZE(irqs); i++)
-- free_irq(irqs[i].irq, NULL);
-+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
-+ free_irq(irqs[i].irq, NULL);
-
-- return 0;
-+ return 0;
- }
-
--static int cerf_pcmcia_socket_state(struct pcmcia_state_array
-- *state_array){
-- unsigned long levels;
-- int i = CERF_SOCKET;
-+static int cerf_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-+{
-+ int i = CERF_SOCKET;
-
-- if(state_array->size<2) return -1;
-+ if( pcmcia_debug > 3)
-+ printk( KERN_INFO "cerf_pcmcia_socket_state: i=%d, size=%d\n",
-+ i, state_array->size);
-
-- levels=GPLR;
-+ memset(state_array->state, 0,
-+ (state_array->size)*sizeof(struct pcmcia_state));
-
-- state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
-- state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
-- state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
-- state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
-- state_array->state[i].wrprot=0;
-- state_array->state[i].vs_3v=1;
-- state_array->state[i].vs_Xv=0;
-+ state_array->state[i].detect = cerf_pcmcia_level_detect();
-+ state_array->state[i].ready = cerf_pcmcia_level_ready();
-+ state_array->state[i].bvd1 = cerf_pcmcia_level_bvd1();
-+ state_array->state[i].bvd2 = cerf_pcmcia_level_bvd2();
-+ state_array->state[i].wrprot=0;
-+ state_array->state[i].vs_3v=1;
-+ state_array->state[i].vs_Xv=0;
-
-- return 1;
-+ if( pcmcia_debug > 3)
-+ printk( KERN_INFO "cerf_pcmcia_socket_state: "
-+ "detect=%d ready=%d bvd1=%d bvd2=%d\n",
-+ state_array->state[i].detect,
-+ state_array->state[i].ready,
-+ state_array->state[i].bvd1,
-+ state_array->state[i].bvd2);
-+
-+ return 1;
- }
-
- static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-
-- if(info->sock>1) return -1;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_get_irq_info: "
-+ "sock=%d\n", info->sock);
-
-- if (info->sock == CERF_SOCKET)
-- info->irq=IRQ_GPIO_CF_IRQ;
-+ if(info->sock>1) return -1;
-
-- return 0;
-+ if (info->sock == CERF_SOCKET)
-+ info->irq=PCMCIA_IRQ_CF_IRQ;
-+
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_get_irq_info: irq=%d\n",info->irq);
-+
-+ return 0;
- }
-
--static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
-- *configure)
-+static int cerf_pcmcia_configure_socket( unsigned int sock, socket_state_t *state)
- {
-- if(configure->sock>1)
-- return -1;
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_configure_socket:"
-+ "sock=%d vcc=%d flags=%x\n",
-+ sock, state->Vcc, state->flags);
-
-- if (configure->sock != CERF_SOCKET)
-- return 0;
-+ if(sock>1)
-+ return -1;
-
-- switch(configure->vcc){
-- case 0:
-- break;
-+ if (sock != CERF_SOCKET)
-+ return 0;
-
-- case 50:
-- case 33:
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPCR = GPIO_PWR_SHUTDOWN;
-+ switch(state->Vcc){
-+ case 0:
-+ break;
-+
-+ case 50:
-+ case 33:
-+#if defined(CONFIG_SA1100_CERF_CPLD)
-+ PCMCIA_GPDR |= PCMCIA_PWR_SHUTDOWN;
-+ PCMCIA_GPCR |= PCMCIA_PWR_SHUTDOWN;
- #endif
-- break;
-+ /* voltage selected automatically */
-+ break;
-
-- default:
-- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
-- configure->vcc);
-- return -1;
-- }
-+ default:
-+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
-+ __FUNCTION__, state->Vcc);
-+ return -1;
-+ }
-
-- if(configure->reset)
-- {
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPSR = GPIO_CF_RESET;
--#endif
-- }
-- else
-- {
--#ifdef CONFIG_SA1100_CERF_CPLD
-- GPCR = GPIO_CF_RESET;
--#endif
-- }
-+ if(state->flags&SS_RESET)
-+ {
-+ cerf_pcmcia_reset();
-+ }
-
-- return 0;
-+ return 0;
- }
-
-+#ifdef CONFIG_SA1100_CERF
- static int cerf_pcmcia_socket_init(int sock)
- {
- int i;
-
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_socket_init: sock=%d\n",sock);
-+
- if (sock == CERF_SOCKET)
- for (i = 0; i < ARRAY_SIZE(irqs); i++)
- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
-@@ -150,21 +216,26 @@
- {
- int i;
-
-+ if( pcmcia_debug)
-+ printk( KERN_INFO "cerf_pcmcia_socket_suspend: sock=%d\n",sock);
-+
- if (sock == CERF_SOCKET)
- for (i = 0; i < ARRAY_SIZE(irqs); i++)
- set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
-
- return 0;
- }
-+#endif
-
- struct pcmcia_low_level cerf_pcmcia_ops = {
-- init: cerf_pcmcia_init,
-- shutdown: cerf_pcmcia_shutdown,
-- socket_state: cerf_pcmcia_socket_state,
-- get_irq_info: cerf_pcmcia_get_irq_info,
-- configure_socket: cerf_pcmcia_configure_socket,
-+init: cerf_pcmcia_init,
-+shutdown: cerf_pcmcia_shutdown,
-+socket_state: cerf_pcmcia_socket_state,
-+get_irq_info: cerf_pcmcia_get_irq_info,
-+configure_socket: cerf_pcmcia_configure_socket,
-
-- socket_init: cerf_pcmcia_socket_init,
-- socket_suspend: cerf_pcmcia_socket_suspend,
-+#ifdef CONFIG_SA1100_CERF
-+socket_init: cerf_pcmcia_socket_init,
-+socket_suspend: cerf_pcmcia_socket_suspend,
-+#endif
- };
--
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/sa1100_cerf.h
-@@ -0,0 +1,138 @@
-+/*
-+ * drivers/pcmcia/cerf.h
-+ *
-+ * PCMCIA implementation routines for CerfBoard
-+ * Based off the Assabet.
-+ *
-+ */
-+#ifndef _LINUX_PCMCIA_CERF_H
-+#define _LINUX_PCMCIA_CERF_H
-+
-+#include <linux/config.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/arch/pcmcia.h>
-+
-+#ifdef CONFIG_PXA_CERF /* PXA */
-+
-+#define PCMCIA_GPCR GPCR0
-+#define PCMCIA_GPSR GPSR0
-+
-+#define PCMCIA_GPIO_CF_CD 14
-+#define PCMCIA_GPIO_CF_IRQ 13
-+#define PCMCIA_GPIO_CF_RESET 12
-+#ifdef CONFIG_PXA_CERF_PDA
-+# define PCMCIA_GPIO_CF_BVD1 11
-+# define PCMCIA_GPIO_CF_BVD2 10
-+#elif defined( CONFIG_PXA_CERF_BOARD)
-+# define PCMCIA_GPIO_CF_BVD1 32
-+# define PCMCIA_GPIO_CF_BVD2 10
-+#endif
-+
-+#define PCMCIA_GPIO_CF_CD_MASK (GPIO_bit(PCMCIA_GPIO_CF_CD))
-+#define PCMCIA_GPIO_CF_IRQ_MASK (GPIO_bit(PCMCIA_GPIO_CF_IRQ))
-+#define PCMCIA_GPIO_CF_RESET_MASK (GPIO_bit(PCMCIA_GPIO_CF_RESET))
-+#define PCMCIA_GPIO_CF_BVD1_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD1))
-+#define PCMCIA_GPIO_CF_BVD2_MASK (GPIO_bit(PCMCIA_GPIO_CF_BVD2))
-+
-+#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD
-+#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ
-+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET
-+#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1
-+#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2
-+
-+#define PCMCIA_IRQ_CF_CD IRQ_GPIO(PCMCIA_GPIO_CF_CD)
-+#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO(PCMCIA_GPIO_CF_IRQ)
-+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO(PCMCIA_GPIO_CF_BVD1)
-+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO(PCMCIA_GPIO_CF_BVD2)
-+
-+#define PCMCIA_PWR_SHUTDOWN 0 /* not needed */
-+#define CERF_SOCKET 0
-+
-+inline void cerf_pcmcia_set_gpio_direction(void)
-+{
-+ GPDR(PCMCIA_GPIO_CF_CD) &= ~(PCMCIA_GPIO_CF_CD_MASK);
-+ GPDR(PCMCIA_GPIO_CF_BVD1) &= ~(PCMCIA_GPIO_CF_BVD1_MASK);
-+ GPDR(PCMCIA_GPIO_CF_BVD2) &= ~(PCMCIA_GPIO_CF_BVD2_MASK);
-+ GPDR(PCMCIA_GPIO_CF_IRQ) &= ~(PCMCIA_GPIO_CF_IRQ_MASK);
-+ GPDR(PCMCIA_GPIO_CF_RESET)|= (PCMCIA_GPIO_CF_RESET_MASK);
-+}
-+
-+inline int cerf_pcmcia_level_detect( void)
-+{
-+ return ((GPLR(PCMCIA_GPIO_CF_CD)&PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
-+}
-+inline int cerf_pcmcia_level_ready( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_IRQ)&PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd1( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_BVD1)&PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd2( void)
-+{
-+ return (GPLR(PCMCIA_GPIO_CF_BVD2)&PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
-+}
-+
-+#elif defined(CONFIG_SA1100_CERF) /* SA1100 */
-+
-+#define PCMCIA_GPDR GPDR
-+#define PCMCIA_GPCR GPCR
-+#define PCMCIA_GPSR GPSR
-+#define PCMCIA_GPLR GPLR
-+
-+#define PCMCIA_GPIO_CF_CD_MASK GPIO_CF_CD
-+#define PCMCIA_GPIO_CF_IRQ_MASK GPIO_CF_IRQ
-+#define PCMCIA_GPIO_CF_RESET_MASK GPIO_CF_RESET
-+#define PCMCIA_GPIO_CF_BVD1_MASK GPIO_CF_BVD1
-+#define PCMCIA_GPIO_CF_BVD2_MASK GPIO_CF_BVD2
-+
-+#define PCMCIA_GPIO_CF_CD_EDGE PCMCIA_GPIO_CF_CD_MASK
-+#define PCMCIA_GPIO_CF_IRQ_EDGE PCMCIA_GPIO_CF_IRQ_MASK
-+#define PCMCIA_GPIO_CF_RESET_EDGE PCMCIA_GPIO_CF_RESET_MASK
-+#define PCMCIA_GPIO_CF_BVD1_EDGE PCMCIA_GPIO_CF_BVD1_MASK
-+#define PCMCIA_GPIO_CF_BVD2_EDGE PCMCIA_GPIO_CF_BVD2_MASK
-+
-+#define PCMCIA_IRQ_CF_CD IRQ_GPIO_CF_CD
-+#define PCMCIA_IRQ_CF_IRQ IRQ_GPIO_CF_IRQ
-+#define PCMCIA_IRQ_CF_BVD1 IRQ_GPIO_CF_BVD1
-+#define PCMCIA_IRQ_CF_BVD2 IRQ_GPIO_CF_BVD2
-+
-+#define PCMCIA_PWR_SHUTDOWN GPIO_PWR_SHUTDOWN
-+
-+#ifdef CONFIG_SA1100_CERF_CPLD
-+#define CERF_SOCKET 0
-+#else
-+#define CERF_SOCKET 1
-+#endif
-+
-+inline void cerf_pcmcia_set_gpio_direction(void)
-+{
-+ PCMCIA_GPDR &= ~(PCMCIA_GPIO_CF_CD_MASK |
-+ PCMCIA_GPIO_CF_BVD1_MASK |
-+ PCMCIA_GPIO_CF_BVD2_MASK |
-+ PCMCIA_GPIO_CF_IRQ_MASK);
-+ PCMCIA_GPDR |= PCMCIA_GPIO_CF_RESET_MASK;
-+}
-+
-+inline int cerf_pcmcia_level_detect( void)
-+{
-+ return ((PCMCIA_GPLR & PCMCIA_GPIO_CF_CD_MASK)==0)?1:0;
-+}
-+inline int cerf_pcmcia_level_ready( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_IRQ_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd1( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD1_MASK)?1:0;
-+}
-+inline int cerf_pcmcia_level_bvd2( void)
-+{
-+ return (PCMCIA_GPLR & PCMCIA_GPIO_CF_BVD2_MASK)?1:0;
-+}
-+
-+#endif
-+
-+#endif
---- linux-2.4.27/drivers/sound/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/sound/Config.in
-@@ -239,6 +239,7 @@
- dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
- fi
- dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
-+ dep_tristate ' Intel PXA250/210 AC97 audio' CONFIG_SOUND_PXA_AC97 $CONFIG_ARCH_PXA $CONFIG_SOUND
- fi
-
- dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
---- linux-2.4.27/drivers/sound/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/sound/Makefile
-@@ -11,7 +11,7 @@
- msnd.o opl3.o sb_common.o sequencer_syms.o \
- sound_core.o sound_syms.o uart401.o \
- nm256_audio.o ac97.o ac97_codec.o aci.o \
-- sa1100-audio.o
-+ sa1100-audio.o pxa-audio.o pxa-ac97.o
-
- # Each configuration option enables a list of files.
-
-@@ -85,6 +85,7 @@
- obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
- obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
- obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
-+obj-$(CONFIG_SOUND_PXA_AC97)+= pxa-ac97.o pxa-audio.o ac97_codec.o
- obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
- obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
- obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
---- linux-2.4.27/drivers/sound/ac97_codec.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/sound/ac97_codec.c
-@@ -155,6 +155,7 @@
- {0x45838308, "ESS Allegro ES1988", &null_ops},
- {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */
- {0x4e534331, "National Semiconductor LM4549", &null_ops},
-+ {0x50534304, "Philips UCB1400", &default_ops},
- {0x53494c22, "Silicon Laboratory Si3036", &null_ops},
- {0x53494c23, "Silicon Laboratory Si3038", &null_ops},
- {0x545200FF, "TriTech TR?????", &tritech_m_ops},
---- /dev/null
-+++ linux-2.4.27/drivers/sound/pxa-ac97.c
-@@ -0,0 +1,370 @@
-+/*
-+ * linux/drivers/sound/pxa-ac97.c -- AC97 interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * AC97 GPIO Changes:-
-+ * In order to read/write codec GPIO bits using AC97 link slot 12,
-+ * all IO to AC97_GPIO_STATUS must be via the Xscale modem codec
-+ * address space.
-+ * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/poll.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ac97_codec.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "pxa-audio.h"
-+
-+static struct completion CAR_completion;
-+static int waitingForMask;
-+static DECLARE_MUTEX(CAR_mutex);
-+
-+static u16 pxa_ac97_read(struct ac97_codec *codec, u8 reg)
-+{
-+ u16 val = -1;
-+
-+ down(&CAR_mutex);
-+ if (!(CAR & CAR_CAIP)) {
-+ volatile u32 *reg_addr;
-+
-+ // if we are reading the GPIO status then this is cached
-+ // in hardware so we don't need to read over the link.
-+ if (reg == AC97_GPIO_STATUS) {
-+ reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
-+ val = *reg_addr;
-+ return val;
-+ }
-+
-+ reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
-+
-+ waitingForMask=GSR_SDONE;
-+
-+ init_completion(&CAR_completion);
-+ (void)*reg_addr; //start read access across the ac97 link
-+ wait_for_completion(&CAR_completion);
-+
-+ if (GSR & GSR_RDCS) {
-+ GSR |= GSR_RDCS; //write a 1 to clear
-+ printk(KERN_CRIT __FUNCTION__": read codec register timeout.\n");
-+ }
-+
-+ init_completion(&CAR_completion);
-+ val = *reg_addr; //valid data now but we've just started another cycle...
-+ wait_for_completion(&CAR_completion);
-+
-+ } else {
-+ printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
-+ }
-+ up(&CAR_mutex);
-+ //printk("%s(0x%02x) = 0x%04x\n", __FUNCTION__, reg, val);
-+ return val;
-+}
-+
-+static void pxa_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
-+{
-+ down(&CAR_mutex);
-+ if (!(CAR & CAR_CAIP)) {
-+ volatile u32 *reg_addr;
-+
-+ // if we are writing to the codec GPIO using slot 12
-+ // then we have to write to the modem register space
-+ if (reg == AC97_GPIO_STATUS) {
-+ reg_addr = (u32 *)&PMC_REG_BASE + (reg >> 1);
-+ *reg_addr = val;
-+ return;
-+ }
-+
-+ reg_addr = (u32 *)&PAC_REG_BASE + (reg >> 1);
-+
-+ waitingForMask=GSR_CDONE;
-+ init_completion(&CAR_completion);
-+ *reg_addr = val;
-+ wait_for_completion(&CAR_completion);
-+ } else {
-+ printk(KERN_CRIT __FUNCTION__": CAR_CAIP already set\n");
-+ }
-+ up(&CAR_mutex);
-+ //printk("%s(0x%02x, 0x%04x)\n", __FUNCTION__, reg, val);
-+}
-+
-+static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ int gsr = GSR;
-+ GSR = gsr & (GSR_SDONE|GSR_CDONE); //write a 1 to clear
-+ if (gsr & waitingForMask)
-+ {
-+ complete(&CAR_completion);
-+ }
-+}
-+
-+static struct ac97_codec pxa_ac97_codec = {
-+ codec_read: pxa_ac97_read,
-+ codec_write: pxa_ac97_write,
-+};
-+
-+static DECLARE_MUTEX(pxa_ac97_mutex);
-+static int pxa_ac97_refcount;
-+
-+int pxa_ac97_get(struct ac97_codec **codec)
-+{
-+ int ret;
-+
-+ *codec = NULL;
-+ down(&pxa_ac97_mutex);
-+
-+ if (!pxa_ac97_refcount) {
-+ ret = request_irq(IRQ_AC97, pxa_ac97_irq, 0, "AC97", NULL);
-+ if (ret)
-+ return ret;
-+
-+ CKEN |= CKEN2_AC97;
-+ set_GPIO_mode(GPIO31_SYNC_AC97_MD);
-+ set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD);
-+ set_GPIO_mode(GPIO28_BITCLK_AC97_MD);
-+ set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD);
-+
-+ GCR = 0;
-+ udelay(10);
-+ GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE;
-+ while (!(GSR & GSR_PCR)) {
-+ schedule();
-+ }
-+
-+ ret = ac97_probe_codec(&pxa_ac97_codec);
-+ if (ret != 1) {
-+ free_irq(IRQ_AC97, NULL);
-+ GCR = GCR_ACLINK_OFF;
-+ CKEN &= ~CKEN2_AC97;
-+ return ret;
-+ }
-+
-+ // need little hack for UCB1400 (should be moved elsewhere)
-+ pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1);
-+ //pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7);
-+ pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);
-+ pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);
-+ }
-+
-+ pxa_ac97_refcount++;
-+ up(&pxa_ac97_mutex);
-+ *codec = &pxa_ac97_codec;
-+ return 0;
-+}
-+
-+void pxa_ac97_put(void)
-+{
-+ down(&pxa_ac97_mutex);
-+ pxa_ac97_refcount--;
-+ if (!pxa_ac97_refcount) {
-+ GCR = GCR_ACLINK_OFF;
-+ CKEN &= ~CKEN2_AC97;
-+ free_irq(IRQ_AC97, NULL);
-+ }
-+ up(&pxa_ac97_mutex);
-+}
-+
-+EXPORT_SYMBOL(pxa_ac97_get);
-+EXPORT_SYMBOL(pxa_ac97_put);
-+
-+
-+/*
-+ * Audio Mixer stuff
-+ */
-+
-+static audio_state_t ac97_audio_state;
-+static audio_stream_t ac97_audio_in;
-+
-+static int mixer_ioctl( struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret, val;
-+
-+ ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg);
-+ if (ret)
-+ return ret;
-+
-+ /* We must snoop for some commands to provide our own extra processing */
-+ switch (cmd) {
-+ case SOUND_MIXER_WRITE_RECSRC:
-+ /*
-+ * According to the PXA250 spec, mic-in should use different
-+ * DRCMR and different AC97 FIFO.
-+ * Unfortunately current UCB1400 versions (up to ver 2A) don't
-+ * produce slot 6 for the audio input frame, therefore the PXA
-+ * AC97 mic-in FIFO is always starved.
-+ */
-+#if 0
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ pxa_audio_clear_buf(&ac97_audio_in);
-+ *ac97_audio_in.drcmr = 0;
-+ if (val & (1 << SOUND_MIXER_MIC)) {
-+ ac97_audio_in.dcmd = DCMD_RXMCDR;
-+ ac97_audio_in.drcmr = &DRCMRRXMCDR;
-+ ac97_audio_in.dev_addr = __PREG(MCDR);
-+ } else {
-+ ac97_audio_in.dcmd = DCMD_RXPCDR;
-+ ac97_audio_in.drcmr = &DRCMRRXPCDR;
-+ ac97_audio_in.dev_addr = __PREG(PCDR);
-+ }
-+ if (ac97_audio_state.rd_ref)
-+ *ac97_audio_in.drcmr =
-+ ac97_audio_in.dma_ch | DRCMR_MAPVLD;
-+#endif
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static struct file_operations mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ llseek: no_llseek,
-+ owner: THIS_MODULE
-+};
-+
-+/*
-+ * AC97 codec ioctls
-+ */
-+
-+static int codec_adc_rate = 48000;
-+static int codec_dac_rate = 48000;
-+
-+static int ac97_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret;
-+ long val;
-+
-+ switch(cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* FIXME: do we support mono? */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* FIXME: do we support mono? */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret)
-+ return ret;
-+ if (file->f_mode & FMODE_READ)
-+ codec_adc_rate = ac97_set_adc_rate(&pxa_ac97_codec, val);
-+ if (file->f_mode & FMODE_WRITE)
-+ codec_dac_rate = ac97_set_dac_rate(&pxa_ac97_codec, val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ if (file->f_mode & FMODE_READ)
-+ val = codec_adc_rate;
-+ if (file->f_mode & FMODE_WRITE)
-+ val = codec_dac_rate;
-+ return put_user(val, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* FIXME: can we do other fmts? */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+ return 0;
-+}
-+
-+
-+/*
-+ * Audio stuff
-+ */
-+
-+static audio_stream_t ac97_audio_out = {
-+ name: "AC97 audio out",
-+ dcmd: DCMD_TXPCDR,
-+ drcmr: &DRCMRTXPCDR,
-+ dev_addr: __PREG(PCDR),
-+};
-+
-+static audio_stream_t ac97_audio_in = {
-+ name: "AC97 audio in",
-+ dcmd: DCMD_RXPCDR,
-+ drcmr: &DRCMRRXPCDR,
-+ dev_addr: __PREG(PCDR),
-+};
-+
-+static audio_state_t ac97_audio_state = {
-+ output_stream: &ac97_audio_out,
-+ input_stream: &ac97_audio_in,
-+ client_ioctl: ac97_ioctl,
-+ sem: __MUTEX_INITIALIZER(ac97_audio_state.sem),
-+};
-+
-+static int ac97_audio_open(struct inode *inode, struct file *file)
-+{
-+ return pxa_audio_attach(inode, file, &ac97_audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to pxa_audio_attach().
-+ */
-+
-+static struct file_operations ac97_audio_fops = {
-+ open: ac97_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int __init pxa_ac97_init(void)
-+{
-+ int ret;
-+ struct ac97_codec *dummy;
-+
-+ ret = pxa_ac97_get(&dummy);
-+ if (ret)
-+ return ret;
-+
-+ ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1);
-+ pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1);
-+
-+ return 0;
-+}
-+
-+static void __exit pxa_ac97_exit(void)
-+{
-+ unregister_sound_dsp(ac97_audio_state.dev_dsp);
-+ unregister_sound_mixer(pxa_ac97_codec.dev_mixer);
-+ pxa_ac97_put();
-+}
-+
-+
-+module_init(pxa_ac97_init);
-+module_exit(pxa_ac97_exit);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/sound/pxa-audio.c
-@@ -0,0 +1,853 @@
-+/*
-+ * linux/drivers/sound/pxa-audio.c -- audio interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/poll.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "pxa-audio.h"
-+
-+
-+#define AUDIO_NBFRAGS_DEFAULT 8
-+#define AUDIO_FRAGSIZE_DEFAULT 8192
-+
-+#define MAX_DMA_SIZE 4096
-+#define DMA_DESC_SIZE sizeof(pxa_dma_desc)
-+
-+
-+/*
-+ * This function frees all buffers
-+ */
-+#define audio_clear_buf pxa_audio_clear_buf
-+
-+void pxa_audio_clear_buf(audio_stream_t * s)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ int frag;
-+
-+ if (!s->buffers)
-+ return;
-+
-+ /* Ensure DMA isn't running */
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ add_wait_queue(&s->stop_wq, &wait);
-+ DCSR(s->dma_ch) = DCSR_STOPIRQEN;
-+ schedule();
-+ remove_wait_queue(&s->stop_wq, &wait);
-+
-+ /* free DMA buffers */
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+ if (!b->master)
-+ continue;
-+ consistent_free(b->data, b->master, b->dma_desc->dsadr);
-+ }
-+
-+ /* free descriptor ring */
-+ if (s->buffers->dma_desc)
-+ consistent_free(s->buffers->dma_desc,
-+ s->nbfrags * s->descs_per_frag * DMA_DESC_SIZE,
-+ s->dma_desc_phys);
-+
-+ /* free buffer structure array */
-+ kfree(s->buffers);
-+ s->buffers = NULL;
-+}
-+
-+/*
-+ * This function allocates the DMA descriptor array and buffer data space
-+ * according to the current number of fragments and fragment size.
-+ */
-+static int audio_setup_buf(audio_stream_t * s)
-+{
-+ pxa_dma_desc *dma_desc;
-+ dma_addr_t dma_desc_phys;
-+ int nb_desc, frag, i, buf_size = 0;
-+ char *dma_buf = NULL;
-+ dma_addr_t dma_buf_phys = 0;
-+
-+ if (s->buffers)
-+ return -EBUSY;
-+
-+ /* Our buffer structure array */
-+ s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
-+ if (!s->buffers)
-+ goto err;
-+ memzero(s->buffers, sizeof(audio_buf_t) * s->nbfrags);
-+
-+ /*
-+ * Our DMA descriptor array:
-+ * for Each fragment we have one checkpoint descriptor plus one
-+ * descriptor per MAX_DMA_SIZE byte data blocks.
-+ */
-+ nb_desc = (1 + (s->fragsize + MAX_DMA_SIZE - 1)/MAX_DMA_SIZE) * s->nbfrags;
-+ dma_desc = consistent_alloc(GFP_KERNEL,
-+ nb_desc * DMA_DESC_SIZE,
-+ &dma_desc_phys,
-+ 0);
-+ if (!dma_desc)
-+ goto err;
-+ s->descs_per_frag = nb_desc / s->nbfrags;
-+ s->buffers->dma_desc = dma_desc;
-+ s->dma_desc_phys = dma_desc_phys;
-+ for (i = 0; i < nb_desc - 1; i++)
-+ dma_desc[i].ddadr = dma_desc_phys + (i + 1) * DMA_DESC_SIZE;
-+ dma_desc[i].ddadr = dma_desc_phys;
-+
-+ /* Our actual DMA buffers */
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+
-+ /*
-+ * Let's allocate non-cached memory for DMA buffers.
-+ * We try to allocate all memory at once.
-+ * If this fails (a common reason is memory fragmentation),
-+ * then we'll try allocating smaller buffers.
-+ */
-+ if (!buf_size) {
-+ buf_size = (s->nbfrags - frag) * s->fragsize;
-+ do {
-+ dma_buf = consistent_alloc(GFP_KERNEL,
-+ buf_size,
-+ &dma_buf_phys,
-+ 0);
-+ if (!dma_buf)
-+ buf_size -= s->fragsize;
-+ } while (!dma_buf && buf_size);
-+ if (!dma_buf)
-+ goto err;
-+ b->master = buf_size;
-+ memzero(dma_buf, buf_size);
-+ }
-+
-+ /*
-+ * Set up our checkpoint descriptor. Since the count
-+ * is always zero, we'll abuse the dsadr and dtadr fields
-+ * just in case this one is picked up by the hardware
-+ * while processing SOUND_DSP_GETPTR.
-+ */
-+ dma_desc->dsadr = dma_buf_phys;
-+ dma_desc->dtadr = dma_buf_phys;
-+ dma_desc->dcmd = DCMD_ENDIRQEN;
-+ if (s->output && !s->mapped)
-+ dma_desc->ddadr |= DDADR_STOP;
-+ b->dma_desc = dma_desc++;
-+
-+ /* set up the actual data descriptors */
-+ for (i = 0; (i * MAX_DMA_SIZE) < s->fragsize; i++) {
-+ dma_desc[i].dsadr = (s->output) ?
-+ (dma_buf_phys + i*MAX_DMA_SIZE) : s->dev_addr;
-+ dma_desc[i].dtadr = (s->output) ?
-+ s->dev_addr : (dma_buf_phys + i*MAX_DMA_SIZE);
-+ dma_desc[i].dcmd = s->dcmd |
-+ ((s->fragsize < MAX_DMA_SIZE) ?
-+ s->fragsize : MAX_DMA_SIZE);
-+ }
-+ dma_desc += i;
-+
-+ /* handle buffer pointers */
-+ b->data = dma_buf;
-+ dma_buf += s->fragsize;
-+ dma_buf_phys += s->fragsize;
-+ buf_size -= s->fragsize;
-+ }
-+
-+ s->usr_frag = s->dma_frag = 0;
-+ s->bytecount = 0;
-+ s->fragcount = 0;
-+ sema_init(&s->sem, (s->output) ? s->nbfrags : 0);
-+ return 0;
-+
-+err:
-+ printk("pxa-audio: unable to allocate audio memory\n ");
-+ audio_clear_buf(s);
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Our DMA interrupt handler
-+ */
-+static void audio_dma_irq(int ch, void *dev_id, struct pt_regs *regs)
-+{
-+ audio_stream_t *s = dev_id;
-+ u_int dcsr;
-+
-+ dcsr = DCSR(ch);
-+ DCSR(ch) = dcsr & ~DCSR_STOPIRQEN;
-+
-+ if (!s->buffers) {
-+ printk("AC97 DMA: wow... received IRQ for channel %d but no buffer exists\n", ch);
-+ return;
-+ }
-+
-+ if (dcsr & DCSR_BUSERR)
-+ printk("AC97 DMA: bus error interrupt on channel %d\n", ch);
-+
-+ if (dcsr & DCSR_ENDINTR) {
-+ u_long cur_dma_desc;
-+ u_int cur_dma_frag;
-+
-+ /*
-+ * Find out which DMA desc is current. Note that DDADR
-+ * points to the next desc, not the current one.
-+ */
-+ cur_dma_desc = DDADR(ch) - s->dma_desc_phys - DMA_DESC_SIZE;
-+
-+ /*
-+ * Let the compiler nicely optimize constant divisors into
-+ * multiplications for the common cases which is much faster.
-+ * Common cases: x = 1 + (1 << y) for y = [0..3]
-+ */
-+ switch (s->descs_per_frag) {
-+ case 2: cur_dma_frag = cur_dma_desc / (2*DMA_DESC_SIZE); break;
-+ case 3: cur_dma_frag = cur_dma_desc / (3*DMA_DESC_SIZE); break;
-+ case 5: cur_dma_frag = cur_dma_desc / (5*DMA_DESC_SIZE); break;
-+ case 9: cur_dma_frag = cur_dma_desc / (9*DMA_DESC_SIZE); break;
-+ default: cur_dma_frag =
-+ cur_dma_desc / (s->descs_per_frag * DMA_DESC_SIZE);
-+ }
-+
-+ /* Account for possible wrap back of cur_dma_desc above */
-+ if (cur_dma_frag >= s->nbfrags)
-+ cur_dma_frag = s->nbfrags - 1;
-+
-+ while (s->dma_frag != cur_dma_frag) {
-+ if (!s->mapped) {
-+ /*
-+ * This fragment is done - set the checkpoint
-+ * descriptor to STOP until it is gets
-+ * processed by the read or write function.
-+ */
-+ s->buffers[s->dma_frag].dma_desc->ddadr |= DDADR_STOP;
-+ up(&s->sem);
-+ }
-+ if (++s->dma_frag >= s->nbfrags)
-+ s->dma_frag = 0;
-+
-+ /* Accounting */
-+ s->bytecount += s->fragsize;
-+ s->fragcount++;
-+ }
-+
-+ /* ... and for polling processes */
-+ wake_up(&s->frag_wq);
-+ }
-+
-+ if ((dcsr & DCSR_STOPIRQEN) && (dcsr & DCSR_STOPSTATE))
-+ wake_up(&s->stop_wq);
-+}
-+
-+/*
-+ * Validate and sets up buffer fragments, etc.
-+ */
-+static int audio_set_fragments(audio_stream_t *s, int val)
-+{
-+ if (s->mapped || DCSR(s->dma_ch) & DCSR_RUN)
-+ return -EBUSY;
-+ if (s->buffers)
-+ audio_clear_buf(s);
-+ s->nbfrags = (val >> 16) & 0x7FFF;
-+ val &= 0xffff;
-+ if (val < 5)
-+ val = 5;
-+ if (val > 15)
-+ val = 15;
-+ s->fragsize = 1 << val;
-+ if (s->nbfrags < 2)
-+ s->nbfrags = 2;
-+ if (s->nbfrags * s->fragsize > 256 * 1024)
-+ s->nbfrags = 256 * 1024 / s->fragsize;
-+ if (audio_setup_buf(s))
-+ return -ENOMEM;
-+ return val|(s->nbfrags << 16);
-+}
-+
-+
-+/*
-+ * The fops functions
-+ */
-+
-+static int audio_write(struct file *file, const char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ const char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ int chunksize, ret = 0;
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = &s->buffers[s->usr_frag];
-+
-+ /* Grab a fragment */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&s->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&s->sem))
-+ break;
-+ }
-+
-+ /* Feed the current buffer */
-+ chunksize = s->fragsize - b->offset;
-+ if (chunksize > count)
-+ chunksize = count;
-+ if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
-+ up(&s->sem);
-+ return -EFAULT;
-+ }
-+ b->offset += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->offset < s->fragsize) {
-+ up(&s->sem);
-+ break;
-+ }
-+
-+ /*
-+ * Activate DMA on current buffer.
-+ * We unlock this fragment's checkpoint descriptor and
-+ * kick DMA if it is idle. Using checkpoint descriptors
-+ * allows for control operations without the need for
-+ * stopping the DMA channel if it is already running.
-+ */
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+
-+ /* move the index to the next fragment */
-+ if (++s->usr_frag >= s->nbfrags)
-+ s->usr_frag = 0;
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ return ret;
-+}
-+
-+
-+static int audio_read(struct file *file, char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ char *buffer0 = buffer;
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s = state->input_stream;
-+ int chunksize, ret = 0;
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = &s->buffers[s->usr_frag];
-+
-+ /* prime DMA */
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) =
-+ s->buffers[s->dma_frag].dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+
-+ /* Wait for a buffer to become full */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&s->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&s->sem))
-+ break;
-+ }
-+
-+ /* Grab data from current buffer */
-+ chunksize = s->fragsize - b->offset;
-+ if (chunksize > count)
-+ chunksize = count;
-+ if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
-+ up(&s->sem);
-+ return -EFAULT;
-+ }
-+ b->offset += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->offset < s->fragsize) {
-+ up(&s->sem);
-+ break;
-+ }
-+
-+ /*
-+ * Make this buffer available for DMA again.
-+ * We unlock this fragment's checkpoint descriptor and
-+ * kick DMA if it is idle. Using checkpoint descriptors
-+ * allows for control operations without the need for
-+ * stopping the DMA channel if it is already running.
-+ */
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+
-+ /* move the index to the next fragment */
-+ if (++s->usr_frag >= s->nbfrags)
-+ s->usr_frag = 0;
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ return ret;
-+}
-+
-+
-+static int audio_sync(struct file *file)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ audio_buf_t *b;
-+ pxa_dma_desc *final_desc;
-+ u_long dcmd_save = 0;
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
-+ return 0;
-+
-+ /*
-+ * Send current buffer if it contains data. Be sure to send
-+ * a full sample count.
-+ */
-+ final_desc = NULL;
-+ b = &s->buffers[s->usr_frag];
-+ if (b->offset &= ~3) {
-+ final_desc = &b->dma_desc[1 + b->offset/MAX_DMA_SIZE];
-+ b->offset &= (MAX_DMA_SIZE-1);
-+ dcmd_save = final_desc->dcmd;
-+ final_desc->dcmd = b->offset | s->dcmd | DCMD_ENDIRQEN;
-+ final_desc->ddadr |= DDADR_STOP;
-+ b->offset = 0;
-+ b->dma_desc->ddadr &= ~DDADR_STOP;
-+ if (DCSR(s->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(s->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(s->dma_ch) = DCSR_RUN;
-+ }
-+ }
-+
-+ /* Wait for DMA to complete. */
-+ set_current_state(TASK_INTERRUPTIBLE);
-+#if 0
-+ /*
-+ * The STOPSTATE IRQ never seem to occur if DCSR_STOPIRQEN is set
-+ * along wotj DCSR_RUN. Silicon bug?
-+ */
-+ add_wait_queue(&s->stop_wq, &wait);
-+ DCSR(s->dma_ch) |= DCSR_STOPIRQEN;
-+ schedule();
-+#else
-+ add_wait_queue(&s->frag_wq, &wait);
-+ while ((DCSR(s->dma_ch) & DCSR_RUN) && !signal_pending(current)) {
-+ schedule();
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ }
-+#endif
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&s->frag_wq, &wait);
-+
-+ /* Restore the descriptor chain. */
-+ if (final_desc) {
-+ final_desc->dcmd = dcmd_save;
-+ final_desc->ddadr &= ~DDADR_STOP;
-+ b->dma_desc->ddadr |= DDADR_STOP;
-+ }
-+ return 0;
-+}
-+
-+
-+static unsigned int audio_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ unsigned int mask = 0;
-+
-+ if (file->f_mode & FMODE_READ) {
-+ /* Start audio input if not already active */
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ if (DCSR(is->dma_ch) & DCSR_STOPSTATE) {
-+ DDADR(is->dma_ch) =
-+ is->buffers[is->dma_frag].dma_desc->ddadr;
-+ DCSR(is->dma_ch) = DCSR_RUN;
-+ }
-+ poll_wait(file, &is->frag_wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ poll_wait(file, &os->frag_wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_READ)
-+ if (( is->mapped && is->bytecount > 0) ||
-+ (!is->mapped && atomic_read(&is->sem.count) > 0))
-+ mask |= POLLIN | POLLRDNORM;
-+
-+ if (file->f_mode & FMODE_WRITE)
-+ if (( os->mapped && os->bytecount > 0) ||
-+ (!os->mapped && atomic_read(&os->sem.count) > 0))
-+ mask |= POLLOUT | POLLWRNORM;
-+
-+ return mask;
-+}
-+
-+
-+static int audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *os = state->output_stream;
-+ audio_stream_t *is = state->input_stream;
-+ long val;
-+
-+ switch (cmd) {
-+ case OSS_GETVERSION:
-+ return put_user(SOUND_VERSION, (int *)arg);
-+
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ if (file->f_mode & FMODE_WRITE)
-+ return put_user(os->fragsize, (int *)arg);
-+ else
-+ return put_user(is->fragsize, (int *)arg);
-+
-+ case SNDCTL_DSP_GETCAPS:
-+ val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
-+ if (is && os)
-+ val |= DSP_CAP_DUPLEX;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if (get_user(val, (long *) arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ int ret = audio_set_fragments(is, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ int ret = audio_set_fragments(os, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_SYNC:
-+ return audio_sync(file);
-+
-+ case SNDCTL_DSP_SETDUPLEX:
-+ return 0;
-+
-+ case SNDCTL_DSP_POST:
-+ return 0;
-+
-+ case SNDCTL_DSP_GETTRIGGER:
-+ val = 0;
-+ if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN)
-+ val |= PCM_ENABLE_INPUT;
-+ if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN)
-+ val |= PCM_ENABLE_OUTPUT;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETTRIGGER:
-+ if (get_user(val, (int *)arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ if (val & PCM_ENABLE_INPUT) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ if (!(DCSR(is->dma_ch) & DCSR_RUN)) {
-+ audio_buf_t *b = &is->buffers[is->dma_frag];
-+ DDADR(is->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(is->dma_ch) = DCSR_RUN;
-+ }
-+ } else {
-+ DCSR(is->dma_ch) = 0;
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (val & PCM_ENABLE_OUTPUT) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ if (!(DCSR(os->dma_ch) & DCSR_RUN)) {
-+ audio_buf_t *b = &os->buffers[os->dma_frag];
-+ DDADR(os->dma_ch) = b->dma_desc->ddadr;
-+ DCSR(os->dma_ch) = DCSR_RUN;
-+ }
-+ } else {
-+ DCSR(os->dma_ch) = 0;
-+ }
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_GETOSPACE:
-+ case SNDCTL_DSP_GETISPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ inf.bytes = atomic_read(&s->sem.count) * s->fragsize;
-+ inf.bytes -= s->buffers[s->usr_frag].offset;
-+ inf.fragments = inf.bytes / s->fragsize;
-+ inf.fragsize = s->fragsize;
-+ inf.fragstotal = s->nbfrags;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETOPTR:
-+ case SNDCTL_DSP_GETIPTR:
-+ {
-+ count_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
-+ dma_addr_t ptr;
-+ int bytecount, offset, flags;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (DCSR(s->dma_ch) & DCSR_RUN) {
-+ audio_buf_t *b;
-+ save_flags_cli(flags);
-+ ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch);
-+ b = &s->buffers[s->dma_frag];
-+ offset = ptr - b->dma_desc->dsadr;
-+ if (offset >= s->fragsize)
-+ offset = s->fragsize - 4;
-+ } else {
-+ save_flags(flags);
-+ offset = 0;
-+ }
-+ inf.ptr = s->dma_frag * s->fragsize + offset;
-+ bytecount = s->bytecount + offset;
-+ s->bytecount = -offset;
-+ inf.blocks = s->fragcount;
-+ s->fragcount = 0;
-+ restore_flags(flags);
-+ if (bytecount < 0)
-+ bytecount = 0;
-+ inf.bytes = bytecount;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_NONBLOCK:
-+ file->f_flags |= O_NONBLOCK;
-+ return 0;
-+
-+ case SNDCTL_DSP_RESET:
-+ if (file->f_mode & FMODE_WRITE)
-+ audio_clear_buf(os);
-+ if (file->f_mode & FMODE_READ)
-+ audio_clear_buf(is);
-+ return 0;
-+
-+ default:
-+ return state->client_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ audio_state_t *state = file->private_data;
-+ audio_stream_t *s;
-+ unsigned long size, vma_addr;
-+ int i, ret;
-+
-+ if (vma->vm_pgoff != 0)
-+ return -EINVAL;
-+
-+ if (vma->vm_flags & VM_WRITE) {
-+ if (!state->wr_ref)
-+ return -EINVAL;;
-+ s = state->output_stream;
-+ } else if (vma->vm_flags & VM_READ) {
-+ if (!state->rd_ref)
-+ return -EINVAL;
-+ s = state->input_stream;
-+ } else return -EINVAL;
-+
-+ if (s->mapped)
-+ return -EINVAL;
-+ size = vma->vm_end - vma->vm_start;
-+ if (size != s->fragsize * s->nbfrags)
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ vma_addr = vma->vm_start;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *buf = &s->buffers[i];
-+ if (!buf->master)
-+ continue;
-+ ret = remap_page_range(vma_addr, buf->dma_desc->dsadr,
-+ buf->master, vma->vm_page_prot);
-+ if (ret)
-+ return ret;
-+ vma_addr += buf->master;
-+ }
-+ for (i = 0; i < s->nbfrags; i++)
-+ s->buffers[i].dma_desc->ddadr &= ~DDADR_STOP;
-+ s->mapped = 1;
-+ return 0;
-+}
-+
-+
-+static int audio_release(struct inode *inode, struct file *file)
-+{
-+ audio_state_t *state = file->private_data;
-+
-+ down(&state->sem);
-+
-+ if (file->f_mode & FMODE_READ) {
-+ audio_clear_buf(state->input_stream);
-+ *state->input_stream->drcmr = 0;
-+ pxa_free_dma(state->input_stream->dma_ch);
-+ state->rd_ref = 0;
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_sync(file);
-+ audio_clear_buf(state->output_stream);
-+ *state->output_stream->drcmr = 0;
-+ pxa_free_dma(state->output_stream->dma_ch);
-+ state->wr_ref = 0;
-+ }
-+
-+ up(&state->sem);
-+ return 0;
-+}
-+
-+
-+int pxa_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state)
-+{
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ int err;
-+
-+ down(&state->sem);
-+
-+ /* access control */
-+ err = -ENODEV;
-+ if ((file->f_mode & FMODE_WRITE) && !os)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && !is)
-+ goto out;
-+ err = -EBUSY;
-+ if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && state->rd_ref)
-+ goto out;
-+
-+ /* request DMA channels */
-+ if (file->f_mode & FMODE_WRITE) {
-+ err = pxa_request_dma(os->name, DMA_PRIO_LOW,
-+ audio_dma_irq, os);
-+ if (err < 0)
-+ goto out;
-+ os->dma_ch = err;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ err = pxa_request_dma(is->name, DMA_PRIO_LOW,
-+ audio_dma_irq, is);
-+ if (err < 0) {
-+ if (file->f_mode & FMODE_WRITE) {
-+ *os->drcmr = 0;
-+ pxa_free_dma(os->dma_ch);
-+ }
-+ goto out;
-+ }
-+ is->dma_ch = err;
-+ }
-+
-+ file->private_data = state;
-+ file->f_op->release = audio_release;
-+ file->f_op->write = audio_write;
-+ file->f_op->read = audio_read;
-+ file->f_op->mmap = audio_mmap;
-+ file->f_op->poll = audio_poll;
-+ file->f_op->ioctl = audio_ioctl;
-+ file->f_op->llseek = no_llseek;
-+
-+ if ((file->f_mode & FMODE_WRITE)) {
-+ state->wr_ref = 1;
-+ os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ os->output = 1;
-+ os->mapped = 0;
-+ init_waitqueue_head(&os->frag_wq);
-+ init_waitqueue_head(&os->stop_wq);
-+ *os->drcmr = os->dma_ch | DRCMR_MAPVLD;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ state->rd_ref = 1;
-+ is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ is->output = 0;
-+ is->mapped = 0;
-+ init_waitqueue_head(&is->frag_wq);
-+ init_waitqueue_head(&is->stop_wq);
-+ *is->drcmr = is->dma_ch | DRCMR_MAPVLD;
-+ }
-+
-+ err = 0;
-+
-+out:
-+ up(&state->sem);
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(pxa_audio_attach);
-+EXPORT_SYMBOL(pxa_audio_clear_buf);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/sound/pxa-audio.h
-@@ -0,0 +1,55 @@
-+/*
-+ * linux/drivers/sound/pxa-audio.h -- audio interface for the Cotula chip
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Aug 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+typedef struct {
-+ int offset; /* current buffer position */
-+ char *data; /* actual buffer */
-+ pxa_dma_desc *dma_desc; /* pointer to the starting desc */
-+ int master; /* owner for buffer allocation, contain size whn true */
-+} audio_buf_t;
-+
-+typedef struct {
-+ char *name; /* stream identifier */
-+ audio_buf_t *buffers; /* pointer to audio buffer array */
-+ u_int usr_frag; /* user fragment index */
-+ u_int dma_frag; /* DMA fragment index */
-+ u_int fragsize; /* fragment size */
-+ u_int nbfrags; /* number of fragments */
-+ u_int dma_ch; /* DMA channel number */
-+ dma_addr_t dma_desc_phys; /* phys addr of descriptor ring */
-+ u_int descs_per_frag; /* nbr descriptors per fragment */
-+ int bytecount; /* nbr of processed bytes */
-+ int fragcount; /* nbr of fragment transitions */
-+ struct semaphore sem; /* account for fragment usage */
-+ wait_queue_head_t frag_wq; /* for poll(), etc. */
-+ wait_queue_head_t stop_wq; /* for users of DCSR_STOPIRQEN */
-+ u_long dcmd; /* DMA descriptor dcmd field */
-+ volatile u32 *drcmr; /* the DMA request channel to use */
-+ u_long dev_addr; /* device physical address for DMA */
-+ int mapped:1; /* mmap()'ed buffers */
-+ int output:1; /* 0 for input, 1 for output */
-+} audio_stream_t;
-+
-+typedef struct {
-+ audio_stream_t *output_stream;
-+ audio_stream_t *input_stream;
-+ int dev_dsp; /* audio device handle */
-+ int rd_ref:1; /* open reference for recording */
-+ int wr_ref:1; /* open reference for playback */
-+ int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
-+ struct semaphore sem; /* prevent races in attach/release */
-+} audio_state_t;
-+
-+extern int pxa_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state);
-+extern void pxa_audio_clear_buf(audio_stream_t *s);
-+
---- linux-2.4.27/drivers/sound/sa1100-audio.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/sound/sa1100-audio.c
-@@ -148,7 +148,8 @@
- do {
- dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
- dmasize,
-- &dmaphys);
-+ &dmaphys,
-+ 0);
- if (!dmabuf)
- dmasize -= s->fragsize;
- } while (!dmabuf && dmasize);
---- linux-2.4.27/drivers/video/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/video/Config.in
-@@ -50,6 +50,15 @@
- if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
- bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
- fi
-+ tristate ' PXA LCD support' CONFIG_FB_PXA $CONFIG_ARCH_PXA
-+ if [ "$CONFIG_FB_PXA" != "n" ]; then
-+ choice 'LCD Bit Depth' \
-+ "8-Bpp CONFIG_FB_PXA_8BPP \
-+ 16-Bpp CONFIG_FB_PXA_16BPP" Bit-Depth
-+ fi
-+ if [ "$CONFIG_FB_PXA" != "n" -a "$CONFIG_ARCH_LUBBOCK" = "y" ]; then
-+ bool ' Lubbock QVGA LCD support instead of DSTN' CONFIG_FB_PXA_QVGA
-+ fi
- fi
- dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
- if [ "$CONFIG_APOLLO" = "y" ]; then
-@@ -295,7 +304,7 @@
- if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
- "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
- "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
-- "$CONFIG_FB_DBMX1" = "y" ]; then
-+ "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB2 y
- define_tristate CONFIG_FBCON_CFB4 y
- else
-@@ -329,7 +338,7 @@
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
- "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
- "$CONFIG_FB_INTEL" = "y" -o \
-- "$CONFIG_FB_DBMX1" = "y" ]; then
-+ "$CONFIG_FB_DBMX1" = "y" -o "$CONFIG_FB_PXA" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB8 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
-@@ -372,7 +381,7 @@
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
- "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
- "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
-- "$CONFIG_FB_ANAKIN" = "y" -o \
-+ "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_PXA" = "y" -o \
- "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB16 y
- else
---- linux-2.4.27/drivers/video/Makefile~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/video/Makefile
-@@ -14,7 +14,7 @@
- fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
- fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
- fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
-- fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
-+ fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o pxafb.o \
- cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
-
- # Each configuration option enables a list of files.
-@@ -129,6 +129,10 @@
- obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
- obj-$(CONFIG_FB_HGA) += hgafb.o
- obj-$(CONFIG_FB_SA1100) += sa1100fb.o
-+obj-$(CONFIG_FB_PXA) += pxafb.o
-+ifeq ($(CONFIG_PXA_CERF_PDA),y)
-+ obj-$(CONFIG_FB_PXA) += lcdctrl.o lcdctrl_cerf.o
-+endif
- obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
- obj-$(CONFIG_FB_VIRTUAL) += vfb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
---- linux-2.4.27/drivers/video/fbmem.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/video/fbmem.c
-@@ -109,6 +109,7 @@
- extern int chips_init(void);
- extern int g364fb_init(void);
- extern int sa1100fb_init(void);
-+extern int pxafb_init(void);
- extern int fm2fb_init(void);
- extern int fm2fb_setup(char*);
- extern int q40fb_init(void);
-@@ -305,6 +306,9 @@
- #ifdef CONFIG_FB_SA1100
- { "sa1100", sa1100fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_PXA
-+ { "pxa", pxafb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_SUN3
- { "sun3", sun3fb_init, sun3fb_setup },
- #endif
-@@ -677,13 +681,13 @@
- #elif defined(__i386__) || defined(__x86_64__)
- if (boot_cpu_data.x86 > 3)
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
--#elif defined(__arm__) || defined(__mips__)
-+#elif defined(__mips__)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- #elif defined(__sh__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
- #elif defined(__hppa__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
--#elif defined(__ia64__)
-+#elif defined(__ia64__) || defined(__arm__)
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- #elif defined(__hppa__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
---- /dev/null
-+++ linux-2.4.27/drivers/video/lcdctrl.c
-@@ -0,0 +1,223 @@
-+/*
-+ * lcdctrl.c
-+ *
-+ * Generic LCD control for brightness, contrast, etc.
-+ * Device specific drivers implement a lcdctrl_device and
-+ * provides access to it via lcdctrl_device_get_ops().
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#include <video/lcdctrl.h>
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int lcd_debug = DEBUGGING;
-+#else
-+#define lcd_debug 0
-+#endif
-+
-+/* -- prototypes -- */
-+
-+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
-+ unsigned int cmd , unsigned long arg);
-+static int lcdctrl_open(struct inode *inode, struct file *filp);
-+static int lcdctrl_close(struct inode *inode, struct file *filp);
-+
-+/* -- variables -- */
-+
-+struct lcdctrl_device *lcd_device;
-+
-+static int intensity;
-+static int brightness;
-+static int contrast;
-+
-+static int enabled;
-+static int sync_needed;
-+static int chrdev_major;
-+
-+static struct file_operations lcdctrl_fops = {
-+ ioctl: lcdctrl_ioctl,
-+ open: lcdctrl_open,
-+ release: lcdctrl_close
-+};
-+
-+/* -- ioctl -- */
-+
-+static int lcdctrl_ioctl(struct inode * inode, struct file *filp,
-+ unsigned int cmd , unsigned long arg)
-+{
-+ int ret;
-+ ret = -EINVAL;
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "lcdctrl_ioctl: cmd=%d, arg=%ld\n", cmd, arg);
-+
-+ switch(cmd)
-+ {
-+ case _LCDCTRL_IOCTL_ON:
-+ ret = lcdctrl_enable();
-+ break;
-+ case _LCDCTRL_IOCTL_OFF:
-+ ret = lcdctrl_disable();
-+ break;
-+ case _LCDCTRL_IOCTL_INTENSITY:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_intensity(arg);
-+ break;
-+ case _LCDCTRL_IOCTL_BRIGHTNESS:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_brightness(arg);
-+ break;
-+ case _LCDCTRL_IOCTL_CONTRAST:
-+ if ((arg >=0) && (arg <= 100))
-+ ret = lcdctrl_set_contrast(arg, LCD_NO_SYNC);
-+ break;
-+ case _LCDCTRL_IOCTL_GET_BRIGHTNESS:
-+ ret = brightness;
-+ break;
-+ case _LCDCTRL_IOCTL_GET_CONTRAST:
-+ ret = contrast;
-+ break;
-+ case _LCDCTRL_IOCTL_GET_INTENSITY:
-+ ret = intensity;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "lcdctrl_ioctl: invalid ioctl\n");
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int lcdctrl_open(struct inode *inode, struct file *filp)
-+{
-+// MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int lcdctrl_close(struct inode *inode, struct file *filp)
-+{
-+// MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/* -- -- */
-+
-+int lcdctrl_enable( void)
-+{
-+ int result;
-+
-+ if( enabled) return 0;
-+
-+ result = lcd_device->enable();
-+
-+ lcdctrl_set_intensity( intensity);
-+ lcdctrl_set_brightness( brightness);
-+ lcdctrl_set_contrast( contrast, sync_needed);
-+ sync_needed = LCD_NO_SYNC;
-+
-+ enabled = 1;
-+ return result;
-+}
-+
-+int lcdctrl_disable( void)
-+{
-+ enabled = 0;
-+ return lcd_device->disable();
-+}
-+
-+int lcdctrl_set_intensity( int i)
-+{
-+ intensity = i;
-+ return lcd_device->set_intensity( i);
-+}
-+
-+int lcdctrl_set_brightness( int b)
-+{
-+ brightness = b;
-+ return lcd_device->set_brightness( b);
-+}
-+
-+int lcdctrl_set_contrast( int c, int sync)
-+{
-+ contrast = c;
-+ return lcd_device->set_contrast( c, sync);
-+}
-+
-+int lcdctrl_get_intensity( void)
-+{
-+ return intensity;
-+}
-+
-+int lcdctrl_get_brightness( void)
-+{
-+ return brightness;
-+}
-+
-+int lcdctrl_get_contrast( void)
-+{
-+ return contrast;
-+}
-+
-+/* -- -- */
-+
-+/* the device specific driver should implement this */
-+struct lcdctrl_device *lcdctrl_device_get_ops(void);
-+
-+int lcdctrl_init( void)
-+{
-+ int ret;
-+
-+ lcd_device = lcdctrl_device_get_ops();
-+
-+ if( !lcd_device)
-+ {
-+ printk(KERN_ERR "lcdctrl_init: No lcd_device registered.\n");
-+ return -EINVAL;
-+ }
-+
-+ ret = lcd_device->init( &intensity, &brightness, &contrast);
-+
-+ sync_needed = LCD_SYNC_NEEDED;
-+
-+ if( ret == 0)
-+ {
-+ chrdev_major =
-+ register_chrdev( 0,_LCD_CONTROL_NAME,&lcdctrl_fops);
-+ if( lcd_debug)
-+ printk(KERN_INFO "lcdctrl_init: OK\n");
-+ }
-+ return ret;
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/video/lcdctrl_cerf.c
-@@ -0,0 +1,175 @@
-+/*
-+ * lcdctrl_cerf.c
-+ *
-+ * Cerf LCD control for brightness and contrast.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/arch/cerf_ucb1400gpio.h>
-+
-+#include <video/lcdctrl.h>
-+
-+/*
-+ * Set this to zero to remove all the debug statements via
-+ * dead code elimination.
-+ */
-+#define DEBUGGING 0
-+
-+#if DEBUGGING
-+static unsigned int lcd_debug = DEBUGGING;
-+#else
-+#define lcd_debug 0
-+#endif
-+
-+#define LCD_MAX_INTENSITY 0
-+#define LCD_MAX_BRIGHTNESS 15
-+#define LCD_MAX_CONTRAST 100
-+
-+#define LCD_DEFAULT_INTENSITY 0
-+#define LCD_DEFAULT_BRIGHTNESS 14*100/(LCD_MAX_BRIGHTNESS)
-+#define LCD_DEFAULT_CONTRAST 90*100/(LCD_MAX_CONTRAST)
-+
-+#define UP 1
-+#define DOWN 0
-+
-+/* -- prototypes -- */
-+
-+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast);
-+static int cerf_lcdctrl_enable(void);
-+static int cerf_lcdctrl_disable(void);
-+static int cerf_lcdctrl_set_intensity( int i);
-+static int cerf_lcdctrl_set_brightness( int b);
-+static int cerf_lcdctrl_set_contrast( int c, int sync);
-+
-+static void cerf_lcdctrl_contrast_step( int direction);
-+
-+/* -- variables -- */
-+
-+static int dev_contrast;
-+
-+/* -- -- */
-+
-+static struct lcdctrl_device cerf_dev = {
-+ init: cerf_lcdctrl_init,
-+ enable: cerf_lcdctrl_enable,
-+ disable: cerf_lcdctrl_disable,
-+ set_intensity: cerf_lcdctrl_set_intensity,
-+ set_brightness: cerf_lcdctrl_set_brightness,
-+ set_contrast: cerf_lcdctrl_set_contrast
-+};
-+
-+static int cerf_lcdctrl_enable( void)
-+{
-+ cerf_ucb1400gpio_lcd_enable();
-+
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_disable( void)
-+{
-+ cerf_ucb1400gpio_lcd_disable();
-+
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_intensity( int i)
-+{
-+ int dev_intensity = LCD_MAX_INTENSITY*i/100;
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_intensity: "
-+ "dev_intensity = %d\n", dev_intensity);
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_brightness( int b)
-+{
-+ int dev_brightness = LCD_MAX_BRIGHTNESS*b/100;
-+ outw( dev_brightness, CERF_PDA_CPLD+CERF_PDA_CPLD_BRIGHTNESS);
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_brightness: "
-+ "dev_brightness = %d\n", dev_brightness);
-+ return 0;
-+}
-+
-+static int cerf_lcdctrl_set_contrast( int c, int sync)
-+{
-+ int new_dev_contrast = LCD_MAX_CONTRAST*c/100;
-+ int i;
-+ int count;
-+ int direction = UP;
-+ if( sync == LCD_SYNC_NEEDED)
-+ {
-+ /* In order to sync we step down to the lowest contrast level */
-+ for( i=0; i<LCD_MAX_CONTRAST; i++)
-+ cerf_lcdctrl_contrast_step(DOWN);
-+ dev_contrast = 0;
-+ }
-+
-+ count = new_dev_contrast - dev_contrast;
-+ if( count < 0)
-+ {
-+ /* new contrast is lower then current setting */
-+ direction = DOWN;
-+ count = -count;
-+ }
-+
-+ for( i=0; i<count; i++)
-+ cerf_lcdctrl_contrast_step(direction);
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_set_contrast: "
-+ "dev_contrast = %d\n", new_dev_contrast);
-+ dev_contrast = new_dev_contrast;
-+
-+ return 0;
-+}
-+
-+/* -- -- */
-+
-+static void cerf_lcdctrl_contrast_step( int direction)
-+{
-+ cerf_ucb1400gpio_lcd_contrast_step( direction);
-+}
-+
-+/* -- -- */
-+
-+static int cerf_lcdctrl_init( int *intensity, int *brightness, int *contrast)
-+{
-+ *intensity = LCD_DEFAULT_INTENSITY;
-+ *brightness = LCD_DEFAULT_BRIGHTNESS;
-+ *contrast = LCD_DEFAULT_CONTRAST;
-+
-+ if( lcd_debug)
-+ printk(KERN_INFO "cerf_lcdctrl_init: OK\n");
-+ return 0;
-+}
-+
-+/* this is the hook for lcdctrl to access to the device specifics */
-+struct lcdctrl_device *lcdctrl_device_get_ops(void)
-+{
-+ return &cerf_dev;
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/video/pxafb.c
-@@ -0,0 +1,1410 @@
-+/*
-+ * linux/drivers/video/pxafb.c
-+ *
-+ * Copyright (C) 1999 Eric A. Thomas
-+ * Based on acornfb.c Copyright (C) Russell King.
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive for
-+ * more details.
-+ *
-+ * Intel PXA250/210 LCD Controller Frame Buffer Driver
-+ *
-+ * Please direct your questions and comments on this driver to the following
-+ * email address:
-+ *
-+ * linux-arm-kernel@lists.arm.linux.org.uk
-+ *
-+ *
-+ * Code Status:
-+ *
-+ * 2001/08/03: <cbrake@accelent.com>
-+ * - Ported from SA1100 to PXA250
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/fb.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/init.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-mfb.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb8.h>
-+#include <video/fbcon-cfb16.h>
-+#include <video/lcdctrl.h> /* brightness, contrast, etc. control */
-+
-+/*
-+ * debugging?
-+ */
-+#define DEBUG 0
-+/*
-+ * Complain if VAR is out of range.
-+ */
-+#define DEBUG_VAR 1
-+
-+#undef ASSABET_PAL_VIDEO
-+
-+#include "pxafb.h"
-+
-+void (*pxafb_blank_helper)(int blank);
-+EXPORT_SYMBOL(pxafb_blank_helper);
-+
-+/*
-+ * IMHO this looks wrong. In 8BPP, length should be 8.
-+ */
-+static struct pxafb_rgb rgb_8 = {
-+ red: { offset: 0, length: 4, },
-+ green: { offset: 0, length: 4, },
-+ blue: { offset: 0, length: 4, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct pxafb_rgb def_rgb_16 = {
-+ red: { offset: 11, length: 5, },
-+ green: { offset: 5, length: 6, },
-+ blue: { offset: 0, length: 5, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct pxafb_mach_info pxa_fb_info __initdata = {
-+ pixclock: LCD_PIXCLOCK, /* clock period in ps */
-+ bpp: LCD_BPP,
-+ xres: LCD_XRES,
-+ yres: LCD_YRES,
-+ hsync_len: LCD_HORIZONTAL_SYNC_PULSE_WIDTH,
-+ vsync_len: LCD_VERTICAL_SYNC_PULSE_WIDTH,
-+ left_margin: LCD_BEGIN_OF_LINE_WAIT_COUNT,
-+ upper_margin: LCD_BEGIN_FRAME_WAIT_COUNT,
-+ right_margin: LCD_END_OF_LINE_WAIT_COUNT,
-+ lower_margin: LCD_END_OF_FRAME_WAIT_COUNT,
-+ sync: LCD_SYNC,
-+ lccr0: LCD_LCCR0,
-+ lccr3: LCD_LCCR3
-+};
-+
-+static struct pxafb_mach_info * __init
-+pxafb_get_machine_info(struct pxafb_info *fbi)
-+{
-+ return &pxa_fb_info;
-+}
-+
-+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
-+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
-+
-+static inline void pxafb_schedule_task(struct pxafb_info *fbi, u_int state)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ /*
-+ * We need to handle two requests being made at the same time.
-+ * There are two important cases:
-+ * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
-+ * We must perform the unblanking, which will do our REENABLE for us.
-+ * 2. When we are blanking, but immediately unblank before we have
-+ * blanked. We do the "REENABLE" thing here as well, just to be sure.
-+ */
-+ if (fbi->task_state == C_ENABLE && state == C_REENABLE)
-+ state = (u_int) -1;
-+ if (fbi->task_state == C_DISABLE && state == C_ENABLE)
-+ state = C_REENABLE;
-+
-+ if (state != (u_int)-1) {
-+ fbi->task_state = state;
-+ schedule_task(&fbi->task);
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+/*
-+ * Get the VAR structure pointer for the specified console
-+ */
-+static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;
-+}
-+
-+/*
-+ * Get the DISPLAY structure pointer for the specified console
-+ */
-+static inline struct display *get_con_display(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con < 0) ? fbi->fb.disp : &fb_display[con];
-+}
-+
-+/*
-+ * Get the CMAP pointer for the specified console
-+ */
-+static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;
-+}
-+
-+static inline u_int
-+chan_to_field(u_int chan, struct fb_bitfield *bf)
-+{
-+ chan &= 0xffff;
-+ chan >>= 16 - bf->length;
-+ return chan << bf->offset;
-+}
-+
-+static int
-+pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ u_int val, ret = 1;
-+
-+ if (regno < fbi->palette_size) {
-+ val = ((red >> 0) & 0xf800);
-+ val |= ((green >> 5) & 0x07e0);
-+ val |= ((blue >> 11) & 0x001f);
-+
-+ fbi->palette_cpu[regno] = val;
-+ ret = 0;
-+ }
-+ return ret;
-+}
-+
-+static int
-+pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ u_int val;
-+ int ret = 1;
-+
-+ /*
-+ * If greyscale is true, then we convert the RGB value
-+ * to greyscale no mater what visual we are using.
-+ */
-+ if (fbi->fb.var.grayscale)
-+ red = green = blue = (19595 * red + 38470 * green +
-+ 7471 * blue) >> 16;
-+
-+ switch (fbi->fb.disp->visual) {
-+ case FB_VISUAL_TRUECOLOR:
-+ case FB_VISUAL_DIRECTCOLOR:
-+ /*
-+ * 12 or 16-bit True Colour. We encode the RGB value
-+ * according to the RGB bitfield information.
-+ */
-+ if (regno <= 16) {
-+ u16 *pal = fbi->fb.pseudo_palette;
-+
-+ val = chan_to_field(red, &fbi->fb.var.red);
-+ val |= chan_to_field(green, &fbi->fb.var.green);
-+ val |= chan_to_field(blue, &fbi->fb.var.blue);
-+
-+ pal[regno] = val;
-+ ret = 0;
-+ }
-+ break;
-+
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ ret = pxafb_setpalettereg(regno, red, green, blue, trans, info);
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * pxafb_decode_var():
-+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
-+ * if it's too big, return -EINVAL.
-+ *
-+ * Suggestion: Round up in the following order: bits_per_pixel, xres,
-+ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
-+ * bitfields, horizontal timing, vertical timing.
-+ */
-+static int pxafb_validate_var(struct fb_var_screeninfo *var,
-+ struct pxafb_info *fbi)
-+{
-+ int ret = -EINVAL;
-+
-+ if (var->xres < MIN_XRES)
-+ var->xres = MIN_XRES;
-+ if (var->yres < MIN_YRES)
-+ var->yres = MIN_YRES;
-+ if (var->xres > fbi->max_xres)
-+ var->xres = fbi->max_xres;
-+ if (var->yres > fbi->max_yres)
-+ var->yres = fbi->max_yres;
-+ var->xres_virtual =
-+ var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
-+ var->yres_virtual =
-+ var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
-+
-+ DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4: ret = 0; break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8: ret = 0; break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ /* make sure we are in passive mode */
-+ if (!(fbi->lccr0 & LCCR0_PAS))
-+ ret = 0;
-+ break;
-+
-+ case 16:
-+ /*
-+ * 16 bits works apparemtly fine in passive mode for those,
-+ * so don't complain
-+ */
-+ if (machine_is_lubbock() ||
-+ machine_is_pxa_cerf()) {
-+ ret = 0;
-+ } else
-+ /* make sure we are in active mode */
-+ if ((fbi->lccr0 & LCCR0_PAS))
-+ ret = 0;
-+ break;
-+#endif
-+ default:
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static inline void pxafb_set_truecolor(u_int is_true_color)
-+{
-+ DPRINTK("true_color = %d\n", is_true_color);
-+}
-+
-+static void
-+pxafb_hw_set_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
-+{
-+
-+ fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, &fbi->fb);
-+
-+ /* Set board control register to handle new color depth */
-+ pxafb_set_truecolor(var->bits_per_pixel >= 16);
-+
-+ pxafb_activate_var(var, fbi);
-+
-+}
-+
-+/*
-+ * pxafb_set_var():
-+ * Set the user defined part of the display for the specified console
-+ */
-+static int
-+pxafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
-+ struct display *display = get_con_display(&fbi->fb, con);
-+ int err, chgvar = 0, rgbidx;
-+
-+ DPRINTK("set_var\n");
-+
-+ /*
-+ * Decode var contents into a par structure, adjusting any
-+ * out of range values.
-+ */
-+ err = pxafb_validate_var(var, fbi);
-+ if (err)
-+ return err;
-+
-+ if (var->activate & FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
-+ return -EINVAL;
-+
-+ if (dvar->xres != var->xres)
-+ chgvar = 1;
-+ if (dvar->yres != var->yres)
-+ chgvar = 1;
-+ if (dvar->xres_virtual != var->xres_virtual)
-+ chgvar = 1;
-+ if (dvar->yres_virtual != var->yres_virtual)
-+ chgvar = 1;
-+ if (dvar->bits_per_pixel != var->bits_per_pixel)
-+ chgvar = 1;
-+ if (con < 0)
-+ chgvar = 0;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ if (fbi->cmap_static)
-+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-+ else
-+ display->visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->line_length = var->xres / 2;
-+ display->dispsw = &fbcon_cfb4;
-+ rgbidx = RGB_8;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ if (fbi->cmap_static)
-+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-+ else
-+ display->visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->line_length = var->xres;
-+ display->dispsw = &fbcon_cfb8;
-+ rgbidx = RGB_8;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ display->visual = FB_VISUAL_TRUECOLOR;
-+ display->line_length = var->xres * 2;
-+ display->dispsw = &fbcon_cfb16;
-+ display->dispsw_data = fbi->fb.pseudo_palette;
-+ rgbidx = RGB_16;
-+ break;
-+#endif
-+ default:
-+ rgbidx = 0;
-+ display->dispsw = &fbcon_dummy;
-+ break;
-+ }
-+
-+ display->screen_base = fbi->screen_cpu;
-+ display->next_line = display->line_length;
-+ display->type = fbi->fb.fix.type;
-+ display->type_aux = fbi->fb.fix.type_aux;
-+ display->ypanstep = fbi->fb.fix.ypanstep;
-+ display->ywrapstep = fbi->fb.fix.ywrapstep;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ *dvar = *var;
-+ dvar->activate &= ~FB_ACTIVATE_ALL;
-+
-+ /*
-+ * Copy the RGB parameters for this display
-+ * from the machine specific parameters.
-+ */
-+ dvar->red = fbi->rgb[rgbidx]->red;
-+ dvar->green = fbi->rgb[rgbidx]->green;
-+ dvar->blue = fbi->rgb[rgbidx]->blue;
-+ dvar->transp = fbi->rgb[rgbidx]->transp;
-+
-+ DPRINTK("RGBT length = %d:%d:%d:%d\n",
-+ dvar->red.length, dvar->green.length, dvar->blue.length,
-+ dvar->transp.length);
-+
-+ DPRINTK("RGBT offset = %d:%d:%d:%d\n",
-+ dvar->red.offset, dvar->green.offset, dvar->blue.offset,
-+ dvar->transp.offset);
-+
-+ /*
-+ * Update the old var. The fbcon drivers still use this.
-+ * Once they are using fbi->fb.var, this can be dropped.
-+ */
-+ display->var = *dvar;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ if (var->activate & FB_ACTIVATE_ALL)
-+ fbi->fb.disp->var = *dvar;
-+
-+ /*
-+ * If the console has changed and the console has defined
-+ * a changevar function, call that function.
-+ */
-+ if (chgvar && info && fbi->fb.changevar)
-+ fbi->fb.changevar(con);
-+
-+ /* If the current console is selected, activate the new var. */
-+ if (con != fbi->currcon)
-+ return 0;
-+
-+ pxafb_hw_set_var(dvar, fbi);
-+
-+ return 0;
-+}
-+
-+static int
-+__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct fb_cmap *dcmap = get_con_cmap(info, con);
-+ int err = 0;
-+
-+ if (con == -1)
-+ con = fbi->currcon;
-+
-+ /* no colormap allocated? (we always have "this" colour map allocated) */
-+ if (con >= 0)
-+ err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
-+
-+ if (!err && con == fbi->currcon)
-+ err = fb_set_cmap(cmap, kspc, pxafb_setcolreg, info);
-+
-+ if (!err)
-+ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
-+
-+ return err;
-+}
-+
-+static int
-+pxafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct display *disp = get_con_display(info, con);
-+
-+ if (disp->visual == FB_VISUAL_TRUECOLOR)
-+ return -EINVAL;
-+
-+ return __do_set_cmap(cmap, kspc, con, info);
-+}
-+
-+static int
-+pxafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ struct display *display = get_con_display(info, con);
-+
-+ *fix = info->fix;
-+
-+ fix->line_length = display->line_length;
-+ fix->visual = display->visual;
-+ return 0;
-+}
-+
-+static int
-+pxafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ *var = *get_con_var(info, con);
-+ return 0;
-+}
-+
-+static int
-+pxafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ struct fb_cmap *dcmap = get_con_cmap(info, con);
-+ fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+static struct fb_ops pxafb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: pxafb_get_fix,
-+ fb_get_var: pxafb_get_var,
-+ fb_set_var: pxafb_set_var,
-+ fb_get_cmap: pxafb_get_cmap,
-+ fb_set_cmap: pxafb_set_cmap,
-+};
-+
-+/*
-+ * pxafb_switch():
-+ * Change to the specified console. Palette and video mode
-+ * are changed to the console's stored parameters.
-+ *
-+ * Uh oh, this can be called from a tasklet (IRQ)
-+ */
-+static int pxafb_switch(int con, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ struct display *disp;
-+ struct fb_cmap *cmap;
-+
-+ DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
-+
-+ if (con == fbi->currcon)
-+ return 0;
-+
-+ if (fbi->currcon >= 0) {
-+ disp = fb_display + fbi->currcon;
-+
-+ /*
-+ * Save the old colormap and video mode.
-+ */
-+ disp->var = fbi->fb.var;
-+
-+ if (disp->cmap.len)
-+ fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
-+ }
-+
-+ fbi->currcon = con;
-+ disp = fb_display + con;
-+
-+ /*
-+ * Make sure that our colourmap contains 256 entries.
-+ */
-+ fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
-+
-+ if (disp->cmap.len)
-+ cmap = &disp->cmap;
-+ else
-+ cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
-+
-+ fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
-+
-+ fbi->fb.var = disp->var;
-+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ pxafb_set_var(&fbi->fb.var, con, info);
-+ return 0;
-+}
-+
-+/*
-+ * Formal definition of the VESA spec:
-+ * On
-+ * This refers to the state of the display when it is in full operation
-+ * Stand-By
-+ * This defines an optional operating state of minimal power reduction with
-+ * the shortest recovery time
-+ * Suspend
-+ * This refers to a level of power management in which substantial power
-+ * reduction is achieved by the display. The display can have a longer
-+ * recovery time from this state than from the Stand-by state
-+ * Off
-+ * This indicates that the display is consuming the lowest level of power
-+ * and is non-operational. Recovery from this state may optionally require
-+ * the user to manually power on the monitor
-+ *
-+ * Now, the fbdev driver adds an additional state, (blank), where they
-+ * turn off the video (maybe by colormap tricks), but don't mess with the
-+ * video itself: think of it semantically between on and Stand-By.
-+ *
-+ * So here's what we should do in our fbdev blank routine:
-+ *
-+ * VESA_NO_BLANKING (mode 0) Video on, front/back light on
-+ * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off
-+ * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off
-+ * VESA_POWERDOWN (mode 3) Video off, front/back light off
-+ *
-+ * This will match the matrox implementation.
-+ */
-+/*
-+ * pxafb_blank():
-+ * Blank the display by setting all palette values to zero. Note, the
-+ * 12 and 16 bpp modes don't really use the palette, so this will not
-+ * blank the display in all modes.
-+ */
-+static void pxafb_blank(int blank, struct fb_info *info)
-+{
-+ struct pxafb_info *fbi = (struct pxafb_info *)info;
-+ int i;
-+
-+ DPRINTK("pxafb_blank: blank=%d info->modename=%s\n", blank,
-+ fbi->fb.modename);
-+
-+ switch (blank) {
-+ case VESA_POWERDOWN:
-+ case VESA_VSYNC_SUSPEND:
-+ case VESA_HSYNC_SUSPEND:
-+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
-+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-+ for (i = 0; i < fbi->palette_size; i++)
-+ pxafb_setpalettereg(i, 0, 0, 0, 0, info);
-+ pxafb_schedule_task(fbi, C_DISABLE);
-+ if (pxafb_blank_helper)
-+ pxafb_blank_helper(blank);
-+ break;
-+
-+ case VESA_NO_BLANKING:
-+ if (pxafb_blank_helper)
-+ pxafb_blank_helper(blank);
-+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
-+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
-+ fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, info);
-+ pxafb_schedule_task(fbi, C_ENABLE);
-+ }
-+}
-+
-+static int pxafb_updatevar(int con, struct fb_info *info)
-+{
-+ DPRINTK("entered\n");
-+ return 0;
-+}
-+
-+/*
-+ * Calculate the PCD value from the clock rate (in picoseconds).
-+ * We take account of the PPCR clock setting.
-+ */
-+static inline int get_pcd(unsigned int pixclock)
-+{
-+ unsigned int pcd;
-+
-+ if (pixclock) {
-+ pcd = get_lclk_frequency_10khz() * pixclock;
-+ pcd /= 100000000;
-+ pcd += 1; /* make up for integer math truncations */
-+ } else {
-+ printk(KERN_WARNING "Please convert me to use the PCD calculations\n");
-+ pcd = 0;
-+ }
-+ return pcd;
-+}
-+
-+/*
-+ * pxafb_activate_var():
-+ * Configures LCD Controller based on entries in var parameter. Settings are
-+ * only written to the controller if changes were made.
-+ */
-+static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
-+{
-+ struct pxafb_lcd_reg new_regs;
-+// u_int pcd = get_pcd(var->pixclock);
-+ u_long flags;
-+
-+ DPRINTK("Configuring PXA LCD\n");
-+
-+ DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
-+ var->xres, var->hsync_len,
-+ var->left_margin, var->right_margin);
-+ DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
-+ var->yres, var->vsync_len,
-+ var->upper_margin, var->lower_margin);
-+
-+#if DEBUG_VAR
-+ if (var->xres < 16 || var->xres > 1024)
-+ printk(KERN_ERR "%s: invalid xres %d\n",
-+ fbi->fb.fix.id, var->xres);
-+ if (var->hsync_len < 1 || var->hsync_len > 64)
-+ printk(KERN_ERR "%s: invalid hsync_len %d\n",
-+ fbi->fb.fix.id, var->hsync_len);
-+ if (var->left_margin < 1 || var->left_margin > 255)
-+ printk(KERN_ERR "%s: invalid left_margin %d\n",
-+ fbi->fb.fix.id, var->left_margin);
-+ if (var->right_margin < 1 || var->right_margin > 255)
-+ printk(KERN_ERR "%s: invalid right_margin %d\n",
-+ fbi->fb.fix.id, var->right_margin);
-+ if (var->yres < 1 || var->yres > 1024)
-+ printk(KERN_ERR "%s: invalid yres %d\n",
-+ fbi->fb.fix.id, var->yres);
-+ if (var->vsync_len < 1 || var->vsync_len > 64)
-+ printk(KERN_ERR "%s: invalid vsync_len %d\n",
-+ fbi->fb.fix.id, var->vsync_len);
-+ if (var->upper_margin < 0 || var->upper_margin > 255)
-+ printk(KERN_ERR "%s: invalid upper_margin %d\n",
-+ fbi->fb.fix.id, var->upper_margin);
-+ if (var->lower_margin < 0 || var->lower_margin > 255)
-+ printk(KERN_ERR "%s: invalid lower_margin %d\n",
-+ fbi->fb.fix.id, var->lower_margin);
-+#endif
-+
-+#if defined (CONFIG_PXA_CERF_PDA)
-+ new_regs.lccr0 = fbi->lccr0;
-+ new_regs.lccr1 =
-+ LCCR1_DisWdth(var->xres) +
-+ LCCR1_HorSnchWdth(var->hsync_len) +
-+ LCCR1_BegLnDel(var->left_margin) +
-+ LCCR1_EndLnDel(var->right_margin);
-+
-+ new_regs.lccr2 =
-+ LCCR2_DisHght(var->yres) +
-+ LCCR2_VrtSnchWdth(var->vsync_len) +
-+ LCCR2_BegFrmDel(var->upper_margin) +
-+ LCCR2_EndFrmDel(var->lower_margin);
-+
-+ new_regs.lccr3 = fbi->lccr3
-+ |
-+ (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-+ (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
-+#elif defined (CONFIG_FB_PXA_QVGA)
-+ new_regs.lccr0 = fbi->lccr0;
-+ new_regs.lccr1 =
-+ LCCR1_DisWdth(var->xres) +
-+ LCCR1_HorSnchWdth(var->hsync_len) +
-+ LCCR1_BegLnDel(var->left_margin) +
-+ LCCR1_EndLnDel(var->right_margin);
-+ new_regs.lccr2 =
-+ LCCR2_DisHght(var->yres) +
-+ LCCR2_VrtSnchWdth(var->vsync_len) +
-+ LCCR2_BegFrmDel(var->upper_margin) +
-+ LCCR2_EndFrmDel(var->lower_margin);
-+ new_regs.lccr3 = fbi->lccr3;
-+#else
-+ // FIXME using hardcoded values for now
-+ new_regs.lccr0 = fbi->lccr0;
-+// |
-+// LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
-+// LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
-+
-+ new_regs.lccr1 = 0x3030A7F;
-+// LCCR1_DisWdth(var->xres) +
-+// LCCR1_HorSnchWdth(var->hsync_len) +
-+// LCCR1_BegLnDel(var->left_margin) +
-+// LCCR1_EndLnDel(var->right_margin);
-+
-+ new_regs.lccr2 = 0x4EF;
-+// LCCR2_DisHght(var->yres) +
-+// LCCR2_VrtSnchWdth(var->vsync_len) +
-+// LCCR2_BegFrmDel(var->upper_margin) +
-+// LCCR2_EndFrmDel(var->lower_margin);
-+
-+ new_regs.lccr3 = fbi->lccr3;
-+// |
-+// (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-+// (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
-+// LCCR3_ACBsCntOff;
-+#endif
-+
-+// if (pcd)
-+// new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
-+
-+ DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
-+ DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
-+ DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-+ DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
-+
-+ /* Update shadow copy atomically */
-+ local_irq_save(flags);
-+
-+ /* setup dma descriptors */
-+ fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
-+ fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
-+ fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
-+
-+ fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
-+ fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
-+ fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
-+
-+ #define BYTES_PER_PANEL ((fbi->lccr0 & LCCR0_SDS) ? (var->xres * var->yres * var->bits_per_pixel / 8 / 2) : \
-+ (var->xres * var->yres * var->bits_per_pixel / 8))
-+
-+ /* populate descriptors */
-+ fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
-+ fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
-+ fbi->dmadesc_fblow_cpu->fidr = 0;
-+ fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
-+
-+ fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */
-+
-+ fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
-+ fbi->dmadesc_fbhigh_cpu->fidr = 0;
-+ fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
-+
-+ fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
-+ fbi->dmadesc_palette_cpu->fidr = 0;
-+ fbi->dmadesc_palette_cpu->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
-+
-+ if( var->bits_per_pixel < 12)
-+ {
-+ /* assume any mode with <12 bpp is palette driven */
-+ fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-+ fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
-+ fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
-+ }
-+ else
-+ {
-+ /* palette shouldn't be loaded in true-color mode */
-+ fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-+ fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
-+ }
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu = 0x%x\n", fbi->dmadesc_fblow_cpu);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%x\n", fbi->dmadesc_fbhigh_cpu);
-+ DPRINTK("fbi->dmadesc_palette_cpu = 0x%x\n", fbi->dmadesc_palette_cpu);
-+ DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
-+ DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
-+ DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
-+ DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
-+ DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
-+
-+ DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
-+ DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
-+ DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
-+
-+ fbi->reg_lccr0 = new_regs.lccr0;
-+ fbi->reg_lccr1 = new_regs.lccr1;
-+ fbi->reg_lccr2 = new_regs.lccr2;
-+ fbi->reg_lccr3 = new_regs.lccr3;
-+ local_irq_restore(flags);
-+
-+ /*
-+ * Only update the registers if the controller is enabled
-+ * and something has changed.
-+ */
-+ if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
-+ (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
-+ (FDADR0 != fbi->fdadr0) || (FDADR1 != fbi->fdadr1))
-+ pxafb_schedule_task(fbi, C_REENABLE);
-+
-+ return 0;
-+}
-+
-+/*
-+ * NOTE! The following functions are purely helpers for set_ctrlr_state.
-+ * Do not call them directly; set_ctrlr_state does the correct serialisation
-+ * to ensure that things happen in the right way 100% of time time.
-+ * -- rmk
-+ */
-+
-+/*
-+ * FIXME: move LCD power stuff into pxafb_power_up_lcd()
-+ * Also, I'm expecting that the backlight stuff should
-+ * be handled differently.
-+ */
-+static void pxafb_backlight_on(struct pxafb_info *fbi)
-+{
-+ DPRINTK("backlight on\n");
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ FB_BACKLIGHT_ON();
-+ }
-+#endif
-+}
-+
-+/*
-+ * FIXME: move LCD power stuf into pxafb_power_down_lcd()
-+ * Also, I'm expecting that the backlight stuff should
-+ * be handled differently.
-+ */
-+static void pxafb_backlight_off(struct pxafb_info *fbi)
-+{
-+ DPRINTK("backlight off\n");
-+
-+#ifdef CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ FB_BACKLIGHT_OFF();
-+ }
-+#endif
-+
-+}
-+
-+static void pxafb_power_up_lcd(struct pxafb_info *fbi)
-+{
-+ DPRINTK("LCD power on\n");
-+ CKEN |= CKEN16_LCD;
-+
-+ if(machine_is_pxa_cerf()) {
-+ lcdctrl_enable();
-+ }
-+
-+#if CONFIG_ARCH_PXA_IDP
-+ /* set GPIOs, etc */
-+ if(machine_is_pxa_idp()) {
-+ // FIXME need to add proper delays
-+ FB_PWR_ON();
-+ FB_VLCD_ON(); // FIXME this should be after scanning starts
-+ }
-+#endif
-+}
-+
-+static void pxafb_power_down_lcd(struct pxafb_info *fbi)
-+{
-+ DPRINTK("LCD power off\n");
-+ CKEN &= ~CKEN16_LCD;
-+
-+ if(machine_is_pxa_cerf()) {
-+ lcdctrl_disable();
-+ }
-+
-+ /* set GPIOs, etc */
-+#if CONFIG_ARCH_PXA_IDP
-+ if(machine_is_pxa_idp()) {
-+ // FIXME need to add proper delays
-+ FB_PWR_OFF();
-+ FB_VLCD_OFF(); // FIXME this should be before scanning stops
-+ }
-+#endif
-+
-+}
-+
-+static void pxafb_setup_gpio(struct pxafb_info *fbi)
-+{
-+ unsigned int lccr0;
-+
-+ /*
-+ * setup is based on type of panel supported
-+ */
-+
-+ lccr0 = fbi->lccr0;
-+
-+ /* 4 bit interface */
-+ if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
-+ {
-+ // bits 58-61
-+ GPDR1 |= (0xf << 26);
-+ GAFR1_U = (GAFR1_U & ~(0xff << 20)) | (0xaa << 20);
-+
-+ // bits 74-77
-+ GPDR2 |= (0xf << 10);
-+ GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
-+ }
-+
-+ /* 8 bit interface */
-+ else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
-+ (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
-+ {
-+ // bits 58-65
-+ GPDR1 |= (0x3f << 26);
-+ GPDR2 |= (0x3);
-+
-+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
-+ GAFR2_L = (GAFR2_L & ~0xf) | (0xa);
-+
-+ // bits 74-77
-+ GPDR2 |= (0xf << 10);
-+ GAFR2_L = (GAFR2_L & ~(0xff << 20)) | (0xaa << 20);
-+ }
-+
-+ /* 16 bit interface */
-+ else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
-+ {
-+ // bits 58-77
-+ GPDR1 |= (0x3f << 26);
-+ GPDR2 |= 0x00003fff;
-+
-+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
-+ GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
-+ }
-+ else
-+ {
-+ printk( KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
-+ }
-+}
-+
-+static void pxafb_enable_controller(struct pxafb_info *fbi)
-+{
-+ DPRINTK("Enabling LCD controller\n");
-+
-+ /* Sequence from 11.7.10 */
-+ LCCR3 = fbi->reg_lccr3;
-+ LCCR2 = fbi->reg_lccr2;
-+ LCCR1 = fbi->reg_lccr1;
-+ LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
-+
-+ /* FIXME we used to have LCD power control here */
-+
-+ FDADR0 = fbi->fdadr0;
-+ FDADR1 = fbi->fdadr1;
-+ LCCR0 |= LCCR0_ENB;
-+
-+ DPRINTK("FDADR0 = 0x%08x\n", (unsigned int)FDADR0);
-+ DPRINTK("FDADR1 = 0x%08x\n", (unsigned int)FDADR1);
-+ DPRINTK("LCCR0 = 0x%08x\n", (unsigned int)LCCR0);
-+ DPRINTK("LCCR1 = 0x%08x\n", (unsigned int)LCCR1);
-+ DPRINTK("LCCR2 = 0x%08x\n", (unsigned int)LCCR2);
-+ DPRINTK("LCCR3 = 0x%08x\n", (unsigned int)LCCR3);
-+}
-+
-+static void pxafb_disable_controller(struct pxafb_info *fbi)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ DPRINTK("Disabling LCD controller\n");
-+
-+ /* FIXME add power down GPIO stuff here */
-+
-+ add_wait_queue(&fbi->ctrlr_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ LCSR = 0xffffffff; /* Clear LCD Status Register */
-+ LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
-+ LCCR0 &= ~LCCR0_ENB; /* Disable LCD Controller */
-+
-+ schedule_timeout(20 * HZ / 1000);
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&fbi->ctrlr_wait, &wait);
-+}
-+
-+/*
-+ * pxafb_handle_irq: Handle 'LCD DONE' interrupts.
-+ */
-+static void pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct pxafb_info *fbi = dev_id;
-+ unsigned int lcsr = LCSR;
-+
-+ if (lcsr & LCSR_LDD) {
-+ LCCR0 |= LCCR0_LDM;
-+ wake_up(&fbi->ctrlr_wait);
-+ }
-+
-+ LCSR = lcsr;
-+}
-+
-+/*
-+ * This function must be called from task context only, since it will
-+ * sleep when disabling the LCD controller, or if we get two contending
-+ * processes trying to alter state.
-+ */
-+static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
-+{
-+ u_int old_state;
-+
-+ down(&fbi->ctrlr_sem);
-+
-+ old_state = fbi->state;
-+
-+ switch (state) {
-+ case C_DISABLE_CLKCHANGE:
-+ /*
-+ * Disable controller for clock change. If the
-+ * controller is already disabled, then do nothing.
-+ */
-+ if (old_state != C_DISABLE) {
-+ fbi->state = state;
-+ pxafb_disable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_DISABLE:
-+ /*
-+ * Disable controller
-+ */
-+ if (old_state != C_DISABLE) {
-+ fbi->state = state;
-+
-+ pxafb_backlight_off(fbi);
-+ if (old_state != C_DISABLE_CLKCHANGE)
-+ pxafb_disable_controller(fbi);
-+ pxafb_power_down_lcd(fbi);
-+ }
-+ break;
-+
-+ case C_ENABLE_CLKCHANGE:
-+ /*
-+ * Enable the controller after clock change. Only
-+ * do this if we were disabled for the clock change.
-+ */
-+ if (old_state == C_DISABLE_CLKCHANGE) {
-+ fbi->state = C_ENABLE;
-+ pxafb_enable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_REENABLE:
-+ /*
-+ * Re-enable the controller only if it was already
-+ * enabled. This is so we reprogram the control
-+ * registers.
-+ */
-+ if (old_state == C_ENABLE) {
-+ pxafb_disable_controller(fbi);
-+ pxafb_setup_gpio(fbi);
-+ pxafb_enable_controller(fbi);
-+ }
-+ break;
-+
-+ case C_ENABLE:
-+ /*
-+ * Power up the LCD screen, enable controller, and
-+ * turn on the backlight.
-+ */
-+ if (old_state != C_ENABLE) {
-+ fbi->state = C_ENABLE;
-+ pxafb_setup_gpio(fbi);
-+ pxafb_power_up_lcd(fbi);
-+ pxafb_enable_controller(fbi);
-+ pxafb_backlight_on(fbi);
-+ }
-+ break;
-+ }
-+ up(&fbi->ctrlr_sem);
-+}
-+
-+/*
-+ * Our LCD controller task (which is called when we blank or unblank)
-+ * via keventd.
-+ */
-+static void pxafb_task(void *dummy)
-+{
-+ struct pxafb_info *fbi = dummy;
-+ u_int state = xchg(&fbi->task_state, -1);
-+
-+ set_ctrlr_state(fbi, state);
-+}
-+
-+#ifdef CONFIG_CPU_FREQ
-+/*
-+ * CPU clock speed change handler. We need to adjust the LCD timing
-+ * parameters when the CPU clock is adjusted by the power management
-+ * subsystem.
-+ */
-+static int
-+pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
-+ void *data)
-+{
-+ struct pxafb_info *fbi = TO_INF(nb, clockchg);
-+ u_int pcd;
-+
-+ switch (val) {
-+ case CPUFREQ_MINMAX:
-+ /* todo: fill in min/max values */
-+ break;
-+
-+ case CPUFREQ_PRECHANGE:
-+ set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
-+ break;
-+
-+ case CPUFREQ_POSTCHANGE:
-+ pcd = get_pcd(fbi->fb.var.pixclock);
-+ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
-+ set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
-+ break;
-+ }
-+ return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM
-+/*
-+ * Power management hook. Note that we won't be called from IRQ context,
-+ * unlike the blank functions above, so we may sleep.
-+ */
-+static int
-+pxafb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ struct pxafb_info *fbi = pm_dev->data;
-+
-+ DPRINTK("pm_callback: %d\n", req);
-+
-+ if (req == PM_SUSPEND || req == PM_RESUME) {
-+ int state = (int)data;
-+
-+ if (state == 0) {
-+ /* Enter D0. */
-+ set_ctrlr_state(fbi, C_ENABLE);
-+ } else {
-+ /* Enter D1-D3. Disable the LCD controller. */
-+ set_ctrlr_state(fbi, C_DISABLE);
-+ }
-+ }
-+ DPRINTK("done\n");
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * pxafb_map_video_memory():
-+ * Allocates the DRAM memory for the frame buffer. This buffer is
-+ * remapped into a non-cached, non-buffered, memory region to
-+ * allow palette and pixel writes to occur without flushing the
-+ * cache. Once this area is remapped, all virtual memory
-+ * access to the video memory should occur at the new region.
-+ */
-+static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
-+{
-+ u_long palette_mem_size;
-+
-+ /*
-+ * We reserve one page for the palette, plus the size
-+ * of the framebuffer.
-+ *
-+ * layout of stuff in memory
-+ *
-+ * fblow descriptor
-+ * fbhigh descriptor
-+ * palette descriptor
-+ * palette
-+ * page boundary->
-+ * frame buffer
-+ */
-+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
-+ fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-+ &fbi->map_dma, PTE_BUFFERABLE);
-+
-+ if (fbi->map_cpu) {
-+ fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
-+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
-+ fbi->fb.fix.smem_start = fbi->screen_dma;
-+
-+ fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
-+
-+ palette_mem_size = fbi->palette_size * sizeof(u16);
-+
-+ DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
-+
-+ fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
-+ fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
-+
-+ }
-+
-+ return fbi->map_cpu ? 0 : -ENOMEM;
-+}
-+
-+/* Fake monspecs to fill in fbinfo structure */
-+static struct fb_monspecs monspecs __initdata = {
-+ 30000, 70000, 50, 65, 0 /* Generic */
-+};
-+
-+
-+static struct pxafb_info * __init pxafb_init_fbinfo(void)
-+{
-+ struct pxafb_mach_info *inf;
-+ struct pxafb_info *fbi;
-+
-+ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(struct display) +
-+ sizeof(u16) * 16, GFP_KERNEL);
-+ if (!fbi)
-+ return NULL;
-+
-+ memset(fbi, 0, sizeof(struct pxafb_info) + sizeof(struct display));
-+
-+ fbi->currcon = -1;
-+
-+ strcpy(fbi->fb.fix.id, PXA_NAME);
-+
-+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
-+ fbi->fb.fix.type_aux = 0;
-+ fbi->fb.fix.xpanstep = 0;
-+ fbi->fb.fix.ypanstep = 0;
-+ fbi->fb.fix.ywrapstep = 0;
-+ fbi->fb.fix.accel = FB_ACCEL_NONE;
-+
-+ fbi->fb.var.nonstd = 0;
-+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
-+ fbi->fb.var.height = -1;
-+ fbi->fb.var.width = -1;
-+ fbi->fb.var.accel_flags = 0;
-+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
-+
-+ strcpy(fbi->fb.modename, PXA_NAME);
-+ strcpy(fbi->fb.fontname, "Acorn8x8");
-+
-+ fbi->fb.fbops = &pxafb_ops;
-+ fbi->fb.changevar = NULL;
-+ fbi->fb.switch_con = pxafb_switch;
-+ fbi->fb.updatevar = pxafb_updatevar;
-+ fbi->fb.blank = pxafb_blank;
-+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
-+ fbi->fb.node = -1;
-+ fbi->fb.monspecs = monspecs;
-+ fbi->fb.disp = (struct display *)(fbi + 1);
-+ fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
-+
-+ fbi->rgb[RGB_8] = &rgb_8;
-+ fbi->rgb[RGB_16] = &def_rgb_16;
-+
-+ inf = pxafb_get_machine_info(fbi);
-+
-+ fbi->max_xres = inf->xres;
-+ fbi->fb.var.xres = inf->xres;
-+ fbi->fb.var.xres_virtual = inf->xres;
-+ fbi->max_yres = inf->yres;
-+ fbi->fb.var.yres = inf->yres;
-+ fbi->fb.var.yres_virtual = inf->yres;
-+ fbi->max_bpp = inf->bpp;
-+ fbi->fb.var.bits_per_pixel = inf->bpp;
-+ fbi->fb.var.pixclock = inf->pixclock;
-+ fbi->fb.var.hsync_len = inf->hsync_len;
-+ fbi->fb.var.left_margin = inf->left_margin;
-+ fbi->fb.var.right_margin = inf->right_margin;
-+ fbi->fb.var.vsync_len = inf->vsync_len;
-+ fbi->fb.var.upper_margin = inf->upper_margin;
-+ fbi->fb.var.lower_margin = inf->lower_margin;
-+ fbi->fb.var.sync = inf->sync;
-+ fbi->fb.var.grayscale = inf->cmap_greyscale;
-+ fbi->cmap_inverse = inf->cmap_inverse;
-+ fbi->cmap_static = inf->cmap_static;
-+ fbi->lccr0 = inf->lccr0;
-+ fbi->lccr3 = inf->lccr3;
-+ fbi->state = C_DISABLE;
-+ fbi->task_state = (u_char)-1;
-+ fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
-+ fbi->max_bpp / 8;
-+
-+ init_waitqueue_head(&fbi->ctrlr_wait);
-+ INIT_TQUEUE(&fbi->task, pxafb_task, fbi);
-+ init_MUTEX(&fbi->ctrlr_sem);
-+
-+ return fbi;
-+}
-+
-+int __init pxafb_init(void)
-+{
-+ struct pxafb_info *fbi;
-+ int ret;
-+
-+ fbi = pxafb_init_fbinfo();
-+ ret = -ENOMEM;
-+ if (!fbi)
-+ goto failed;
-+
-+ if(machine_is_pxa_cerf()) {
-+ // brightness&contrast is handled via lcdctrl.
-+ lcdctrl_init();
-+ }
-+
-+ /* Initialize video memory */
-+ ret = pxafb_map_video_memory(fbi);
-+ if (ret)
-+ goto failed;
-+
-+ ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT,
-+ "LCD", fbi);
-+ if (ret) {
-+ printk(KERN_ERR "pxafb: failed in request_irq: %d\n", ret);
-+ goto failed;
-+ }
-+
-+ pxafb_set_var(&fbi->fb.var, -1, &fbi->fb);
-+
-+ ret = register_framebuffer(&fbi->fb);
-+ if (ret < 0)
-+ goto failed;
-+
-+#ifdef CONFIG_PM
-+ /*
-+ * Note that the console registers this as well, but we want to
-+ * power down the display prior to sleeping.
-+ */
-+ fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, pxafb_pm_callback);
-+ if (fbi->pm)
-+ fbi->pm->data = fbi;
-+#endif
-+#ifdef CONFIG_CPU_FREQ
-+ fbi->clockchg.notifier_call = pxafb_clkchg_notifier;
-+ cpufreq_register_notifier(&fbi->clockchg);
-+#endif
-+
-+ /*
-+ * Ok, now enable the LCD controller
-+ */
-+ set_ctrlr_state(fbi, C_ENABLE);
-+
-+ /* This driver cannot be unloaded at the moment */
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+
-+failed:
-+ if (fbi)
-+ kfree(fbi);
-+ return ret;
-+}
-+
-+
-+#ifdef MODULE
-+module_init(pxafb_init);
-+#endif
-+
-+MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/video/pxafb.h
-@@ -0,0 +1,238 @@
-+/*
-+ * linux/drivers/video/pxafb.h
-+ * -- Intel PXA250/210 LCD Controller Frame Buffer Device
-+ *
-+ * Copyright (C) 1999 Eric A. Thomas
-+ * Based on acornfb.c Copyright (C) Russell King.
-+ *
-+ * 2001-08-03: Cliff Brake <cbrake@acclent.com>
-+ * - ported SA1100 code to PXA
-+ *
-+ * This file is subject to the terms and conditions of the GNU General Public
-+ * License. See the file COPYING in the main directory of this archive
-+ * for more details.
-+ */
-+
-+/*
-+ * These are the bitfields for each
-+ * display depth that we support.
-+ */
-+struct pxafb_rgb {
-+ struct fb_bitfield red;
-+ struct fb_bitfield green;
-+ struct fb_bitfield blue;
-+ struct fb_bitfield transp;
-+};
-+
-+/*
-+ * This structure describes the machine which we are running on.
-+ */
-+struct pxafb_mach_info {
-+ u_long pixclock;
-+
-+ u_short xres;
-+ u_short yres;
-+
-+ u_char bpp;
-+ u_char hsync_len;
-+ u_char left_margin;
-+ u_char right_margin;
-+
-+ u_char vsync_len;
-+ u_char upper_margin;
-+ u_char lower_margin;
-+ u_char sync;
-+
-+ u_int cmap_greyscale:1,
-+ cmap_inverse:1,
-+ cmap_static:1,
-+ unused:29;
-+
-+ u_int lccr0;
-+ u_int lccr3;
-+};
-+
-+/* Shadows for LCD controller registers */
-+struct pxafb_lcd_reg {
-+ unsigned int lccr0;
-+ unsigned int lccr1;
-+ unsigned int lccr2;
-+ unsigned int lccr3;
-+};
-+
-+/* PXA LCD DMA descriptor */
-+struct pxafb_dma_descriptor {
-+ unsigned int fdadr;
-+ unsigned int fsadr;
-+ unsigned int fidr;
-+ unsigned int ldcmd;
-+};
-+
-+#define RGB_8 (0)
-+#define RGB_16 (1)
-+#define NR_RGB 2
-+
-+struct pxafb_info {
-+ struct fb_info fb;
-+ signed int currcon;
-+
-+ struct pxafb_rgb *rgb[NR_RGB];
-+
-+ u_int max_bpp;
-+ u_int max_xres;
-+ u_int max_yres;
-+
-+ /*
-+ * These are the addresses we mapped
-+ * the framebuffer memory region to.
-+ */
-+
-+ /* raw memory addresses */
-+ dma_addr_t map_dma; /* physical */
-+ u_char * map_cpu; /* virtual */
-+ u_int map_size;
-+
-+ /* addresses of pieces placed in raw buffer */
-+ u_char * screen_cpu; /* virtual address of frame buffer */
-+ dma_addr_t screen_dma; /* physical address of frame buffer */
-+ u16 * palette_cpu; /* virtual address of palette memory */
-+ dma_addr_t palette_dma; /* physical address of palette memory */
-+ u_int palette_size;
-+
-+ /* DMA descriptors */
-+ struct pxafb_dma_descriptor * dmadesc_fblow_cpu;
-+ dma_addr_t dmadesc_fblow_dma;
-+ struct pxafb_dma_descriptor * dmadesc_fbhigh_cpu;
-+ dma_addr_t dmadesc_fbhigh_dma;
-+ struct pxafb_dma_descriptor * dmadesc_palette_cpu;
-+ dma_addr_t dmadesc_palette_dma;
-+
-+ dma_addr_t fdadr0;
-+ dma_addr_t fdadr1;
-+
-+ u_int lccr0;
-+ u_int lccr3;
-+ u_int cmap_inverse:1,
-+ cmap_static:1,
-+ unused:30;
-+
-+ u_int reg_lccr0;
-+ u_int reg_lccr1;
-+ u_int reg_lccr2;
-+ u_int reg_lccr3;
-+
-+ volatile u_char state;
-+ volatile u_char task_state;
-+ struct semaphore ctrlr_sem;
-+ wait_queue_head_t ctrlr_wait;
-+ struct tq_struct task;
-+
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+#ifdef CONFIG_CPU_FREQ
-+ struct notifier_block clockchg;
-+#endif
-+};
-+
-+#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
-+
-+#define TO_INF(ptr,member) __type_entry(ptr,struct pxafb_info,member)
-+
-+/*
-+ * These are the actions for set_ctrlr_state
-+ */
-+#define C_DISABLE (0)
-+#define C_ENABLE (1)
-+#define C_DISABLE_CLKCHANGE (2)
-+#define C_ENABLE_CLKCHANGE (3)
-+#define C_REENABLE (4)
-+
-+#define PXA_NAME "PXA"
-+
-+/*
-+ * Debug macros
-+ */
-+#if DEBUG
-+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-+#else
-+# define DPRINTK(fmt, args...)
-+#endif
-+
-+/*
-+ * Minimum X and Y resolutions
-+ */
-+#define MIN_XRES 64
-+#define MIN_YRES 64
-+
-+/*
-+ * Are we configured for 8 or 16 bits per pixel?
-+ */
-+#ifdef CONFIG_FB_PXA_8BPP
-+# define PXAFB_BPP 8
-+# define PXAFB_BPP_BITS 0x03
-+#elif CONFIG_FB_PXA_16BPP
-+# define PXAFB_BPP 16
-+# define PXAFB_BPP_BITS 0x04
-+#endif
-+
-+#if defined(CONFIG_ARCH_LUBBOCK)
-+#define LCD_PIXCLOCK 150000
-+#define LCD_BPP PXAFB_BPP
-+#ifdef CONFIG_FB_PXA_QVGA
-+#define LCD_XRES 320
-+#define LCD_YRES 240
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 51
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 1
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 8
-+#define LCD_END_OF_LINE_WAIT_COUNT 1
-+#define LCD_END_OF_FRAME_WAIT_COUNT 1
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x003008F8
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+#else
-+#define LCD_XRES 640
-+#define LCD_YRES 480
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 1
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 3
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 3
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x0030087C
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+#endif
-+
-+#elif defined (CONFIG_ARCH_PXA_IDP)
-+#define LCD_PIXCLOCK 150000
-+#define LCD_BPP PXAFB_BPP
-+#define LCD_XRES 640
-+#define LCD_YRES 480
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 1
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 3
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 3
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 0x0030087C
-+#define LCD_LCCR3 (0x0040FF0C | (PXAFB_BPP_BITS << 24))
-+
-+#elif defined CONFIG_PXA_CERF_PDA
-+#define LCD_PIXCLOCK 171521
-+#define LCD_BPP PXAFB_BPP
-+#define LCD_XRES 240
-+#define LCD_YRES 320
-+#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH 7
-+#define LCD_VERTICAL_SYNC_PULSE_WIDTH 2
-+#define LCD_BEGIN_OF_LINE_WAIT_COUNT 17
-+#define LCD_BEGIN_FRAME_WAIT_COUNT 0
-+#define LCD_END_OF_LINE_WAIT_COUNT 17
-+#define LCD_END_OF_FRAME_WAIT_COUNT 0
-+#define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
-+#define LCD_LCCR0 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM | LCCR0_OUM)
-+#define LCD_LCCR3 (LCCR3_PCP | LCCR3_PixClkDiv(0x12) | LCCR3_Bpp(PXAFB_BPP_BITS) | LCCR3_Acb(0x18))
-+
-+#endif
---- linux-2.4.27/drivers/video/sa1100fb.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/drivers/video/sa1100fb.c
-@@ -2175,7 +2175,7 @@
- */
- fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
- fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
-- &fbi->map_dma);
-+ &fbi->map_dma, PTE_BUFFERABLE);
-
- if (fbi->map_cpu) {
- fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
---- linux-2.4.27/fs/Config.in~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/fs/Config.in
-@@ -51,6 +51,9 @@
- int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
- fi
- tristate 'Compressed ROM file system support' CONFIG_CRAMFS
-+dep_mbool ' Use linear addressing for cramfs' CONFIG_CRAMFS_LINEAR $CONFIG_CRAMFS
-+dep_bool ' Support XIP on linear cramfs' CONFIG_CRAMFS_LINEAR_XIP $CONFIG_CRAMFS_LINEAR
-+dep_bool ' Root file system on linear cramfs' CONFIG_ROOT_CRAMFS_LINEAR $CONFIG_CRAMFS_LINEAR
- bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
- define_bool CONFIG_RAMFS y
-
---- linux-2.4.27/fs/cramfs/inode.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/fs/cramfs/inode.c
-@@ -4,11 +4,29 @@
- * Copyright (C) 1999 Linus Torvalds.
- *
- * This file is released under the GPL.
-- */
--
--/*
-+ *
- * These are the VFS interfaces to the compressed rom filesystem.
- * The actual compression is based on zlib, see the other files.
-+ *
-+ * Linear Addressing code
-+ * Copyright (C) 2000 Shane Nay.
-+ *
-+ * Allows you to have a linearly addressed cramfs filesystem.
-+ * Saves the need for buffer, and the munging of the buffer.
-+ * Savings a bit over 32k with default PAGE_SIZE, BUFFER_SIZE
-+ * etc. Usefull on embedded platform with ROM :-).
-+ *
-+ * Downsides- Currently linear addressed cramfs partitions
-+ * don't co-exist with block cramfs partitions.
-+ *
-+ * 28-Dec-2000: XIP mode for linear cramfs
-+ * Copyright (C) 2000 Robert Leslie <rob@mars.org>
-+ *
-+ * Dynamic allocation of linear cramfs space by Nicolas Pitre
-+ * Copyright (C) 2003 Monta Vista Software, Inc.
-+ *
-+ * Linear cramfs now requires that you pass the physaddr= parameter to
-+ * the mount process. Allows for multiple linear cramfs partitions.
- */
-
- #include <linux/module.h>
-@@ -16,10 +34,12 @@
- #include <linux/pagemap.h>
- #include <linux/init.h>
- #include <linux/string.h>
-+#include <linux/kernel.h>
- #include <linux/locks.h>
- #include <linux/blkdev.h>
- #include <linux/cramfs_fs.h>
- #include <asm/semaphore.h>
-+#include <asm/io.h>
-
- #include <asm/uaccess.h>
-
-@@ -28,6 +48,8 @@
- #define CRAMFS_SB_BLOCKS u.cramfs_sb.blocks
- #define CRAMFS_SB_FILES u.cramfs_sb.files
- #define CRAMFS_SB_FLAGS u.cramfs_sb.flags
-+#define CRAMFS_SB_LINEAR_PHYS_ADDR u.cramfs_sb.linear_phys_addr
-+#define CRAMFS_SB_LINEAR_VIRT_ADDR u.cramfs_sb.linear_virt_addr
-
- static struct super_operations cramfs_ops;
- static struct inode_operations cramfs_dir_inode_operations;
-@@ -42,6 +64,74 @@
- #define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
- #define OFFSET(x) ((x)->i_ino)
-
-+
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+
-+static int cramfs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ unsigned long address, length;
-+ struct inode *inode = file->f_dentry->d_inode;
-+ struct super_block *sb = inode->i_sb;
-+
-+ /* this is only used in the case of read-only maps for XIP */
-+
-+ if (vma->vm_flags & VM_WRITE)
-+ return generic_file_mmap(file, vma);
-+
-+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
-+ return -EINVAL;
-+
-+ address = PAGE_ALIGN(sb->CRAMFS_SB_LINEAR_PHYS_ADDR + OFFSET(inode));
-+ address += vma->vm_pgoff << PAGE_SHIFT;
-+
-+ length = vma->vm_end - vma->vm_start;
-+
-+ if (length > inode->i_size)
-+ length = inode->i_size;
-+
-+ length = PAGE_ALIGN(length);
-+
-+
-+#if 0
-+ /* Doing the following makes it slower and more broken. bdl */
-+ /*
-+ * Accessing memory above the top the kernel knows about or
-+ * through a file pointer that was marked O_SYNC will be
-+ * done non-cached.
-+ */
-+ vma->vm_page_prot =
-+ __pgprot((pgprot_val(vma->vm_page_prot) & ~_CACHE_MASK)
-+ | _CACHE_UNCACHED);
-+#endif
-+
-+ /*
-+ * Don't dump addresses that are not real memory to a core file.
-+ */
-+ vma->vm_flags |= VM_IO;
-+ flush_tlb_page(vma, address);
-+ if (remap_page_range(vma->vm_start, address, length,
-+ vma->vm_page_prot))
-+ return -EAGAIN;
-+
-+#ifdef DEBUG_CRAMFS_XIP
-+ printk("cramfs_mmap: mapped %s at 0x%08lx, length %lu to vma 0x%08lx"
-+ ", page_prot 0x%08lx\n",
-+ file->f_dentry->d_name.name, address, length,
-+ vma->vm_start, pgprot_val(vma->vm_page_prot));
-+#endif
-+
-+ return 0;
-+}
-+
-+static struct file_operations cramfs_linear_xip_fops = {
-+ read: generic_file_read,
-+ mmap: cramfs_mmap,
-+};
-+
-+#define CRAMFS_INODE_IS_XIP(x) ((x)->i_mode & S_ISVTX)
-+
-+#endif
-+
- static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
- {
- struct inode * inode = new_inode(sb);
-@@ -60,7 +150,11 @@
- without -noleaf option. */
- insert_inode_hash(inode);
- if (S_ISREG(inode->i_mode)) {
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+ inode->i_fop = CRAMFS_INODE_IS_XIP(inode) ? &cramfs_linear_xip_fops : &generic_ro_fops;
-+#else
- inode->i_fop = &generic_ro_fops;
-+#endif
- inode->i_data.a_ops = &cramfs_aops;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &cramfs_dir_inode_operations;
-@@ -76,6 +170,18 @@
- return inode;
- }
-
-+#ifdef CONFIG_CRAMFS_LINEAR
-+/*
-+ * Return a pointer to the block in the linearly addressed cramfs image.
-+ */
-+static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
-+{
-+ if (!len)
-+ return NULL;
-+ return (void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + offset);
-+}
-+
-+#else /* Not linear addressing - aka regular block mode. */
- /*
- * We have our own block cache: don't fill up the buffer cache
- * with the rom-image, because the way the filesystem is set
-@@ -192,19 +298,59 @@
- }
- return read_buffers[buffer] + offset;
- }
--
-+#endif /* !CONFIG_CRAMFS_LINEAR */
-
- static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
- {
-+#ifndef CONFIG_CRAMFS_LINEAR
- int i;
-+#else
-+ char *p;
-+#endif
- struct cramfs_super super;
- unsigned long root_offset;
- struct super_block * retval = NULL;
-
-+#ifndef CONFIG_CRAMFS_LINEAR
- /* Invalidate the read buffers on mount: think disk change.. */
- for (i = 0; i < READ_BUFFERS; i++)
- buffer_blocknr[i] = -1;
-
-+#else
-+
-+ /*
-+ * The physical location of the cramfs image is specified as
-+ * a mount parameter. This parameter is mandatory for obvious
-+ * reasons. Some validation is made on the phys address but this
-+ * is not exhaustive and we count on the fact that someone using
-+ * this feature is supposed to know what he/she's doing.
-+ */
-+ if (!data || !(p = strstr((char *)data, "physaddr="))) {
-+ printk(KERN_ERR "cramfs: unknown physical address for linear cramfs image\n");
-+ goto out;
-+ }
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR = simple_strtoul(p + 9, NULL, 0);
-+ if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR & (PAGE_SIZE-1)) {
-+ printk(KERN_ERR "cramfs: physical address 0x%lx for linear cramfs isn't aligned to a page boundary\n",
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
-+ goto out;
-+ }
-+ if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR == 0) {
-+ printk(KERN_ERR "cramfs: physical address for linear cramfs image can't be 0\n");
-+ goto out;
-+ }
-+ printk(KERN_INFO "cramfs: checking physical address 0x%lx for linear cramfs image\n",
-+ sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
-+
-+ /* Map only one page for now. Will remap it when fs size is known. */
-+ sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
-+ ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, PAGE_SIZE);
-+ if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
-+ printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
-+ goto out;
-+ }
-+#endif
-+
- down(&read_mutex);
- /* Read the first block and get the superblock from it */
- memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
-@@ -256,8 +402,26 @@
- /* Set it all up.. */
- sb->s_op = &cramfs_ops;
- sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
-+
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ /* Remap the whole filesystem now */
-+ iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
-+ printk(KERN_INFO "cramfs: linear cramfs image appears to be %lu KB in size\n",
-+ sb->CRAMFS_SB_SIZE/1024);
-+ sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
-+ ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, sb->CRAMFS_SB_SIZE);
-+ if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
-+ printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
-+ goto out;
-+ }
-+#endif
-+
- retval = sb;
- out:
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ if (!retval && sb->CRAMFS_SB_LINEAR_VIRT_ADDR)
-+ iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
-+#endif
- return retval;
- }
-
-@@ -390,6 +554,18 @@
-
- maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- bytes_filled = 0;
-+#ifdef CONFIG_CRAMFS_LINEAR_XIP
-+ if (page->index < maxblock && CRAMFS_INODE_IS_XIP(inode)) {
-+ struct super_block *sb = inode->i_sb;
-+ u32 blkptr_offset = PAGE_ALIGN(OFFSET(inode)) +
-+ page->index * PAGE_CACHE_SIZE;
-+ memcpy( page_address(page),
-+ (void*)(sb->CRAMFS_SB_LINEAR_VIRT_ADDR + blkptr_offset),
-+ PAGE_CACHE_SIZE );
-+ bytes_filled = PAGE_CACHE_SIZE;
-+ pgdata = kmap(page);
-+ } else
-+#endif
- if (page->index < maxblock) {
- struct super_block *sb = inode->i_sb;
- u32 blkptr_offset = OFFSET(inode) + page->index*4;
-@@ -446,7 +622,11 @@
- statfs: cramfs_statfs,
- };
-
-+#ifndef CONFIG_CRAMFS_LINEAR
- static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
-+#else
-+static DECLARE_FSTYPE(cramfs_fs_type, "cramfs", cramfs_read_super, 0);
-+#endif
-
- static int __init init_cramfs_fs(void)
- {
---- /dev/null
-+++ linux-2.4.27/fs/cramfs/mkcramfs.c
-@@ -0,0 +1,821 @@
-+/*
-+ * mkcramfs - make a cramfs file system, optionally with XIP files.
-+ *
-+ * Copyright (C) 1999-2001 Transmeta Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <sys/types.h>
-+#include <stdio.h>
-+#include <sys/stat.h>
-+#include <unistd.h>
-+#include <sys/mman.h>
-+#include <sys/fcntl.h>
-+#include <dirent.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <assert.h>
-+#include <getopt.h>
-+#include <linux/cramfs_fs.h>
-+#include <zlib.h>
-+
-+#define PAD_SIZE 512 /* only 0 and 512 supported by kernel */
-+
-+static const char *progname = "mkcramfs";
-+
-+/* N.B. If you change the disk format of cramfs, please update fs/cramfs/README. */
-+
-+/* Input status of 0 to print help and exit without an error. */
-+static void usage(int status)
-+{
-+ FILE *stream = status ? stderr : stdout;
-+
-+ fprintf(stream, "usage: %s [-h] [-e edition] [-i file] [-n name] dirname outfile\n"
-+ " -h print this help\n"
-+ " -E make all warnings errors (non-zero exit status)\n"
-+ " -e edition set edition number (part of fsid)\n"
-+ " -i file insert a file image into the filesystem (requires >= 2.4.0)\n"
-+ " -n name set name of cramfs filesystem\n"
-+ " -p pad by %d bytes for boot code\n"
-+ " -s sort directory entries (old option, ignored)\n"
-+ " -x make marked files eXecute In Place\n"
-+ " -z make explicit holes (requires >= 2.3.39)\n"
-+ " dirname root of the filesystem to be compressed\n"
-+ " outfile output file\n", progname, PAD_SIZE);
-+
-+ exit(status);
-+}
-+
-+#define PAGE_SIZE (4096)
-+#define PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
-+#define ROM_OFFSET 0
-+#define ROM_ALIGN(x) (PAGE_ALIGN((x) + ROM_OFFSET) - ROM_OFFSET)
-+#define PAGE_CACHE_SIZE (4096)
-+/* The kernel assumes PAGE_CACHE_SIZE as block size. */
-+static unsigned int blksize = PAGE_CACHE_SIZE;
-+static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
-+static int image_length = 0;
-+
-+/*
-+ * If opt_holes is set, then mkcramfs can create explicit holes in the
-+ * data, which saves 26 bytes per hole (which is a lot smaller a
-+ * saving than most most filesystems).
-+ *
-+ * Note that kernels up to at least 2.3.39 don't support cramfs holes,
-+ * which is why this is turned off by default.
-+ */
-+static int opt_edition = 0;
-+static int opt_errors = 0;
-+static int opt_holes = 0;
-+static int opt_xip = 0;
-+static int opt_pad = 0;
-+static char *opt_image = NULL;
-+static char *opt_name = NULL;
-+
-+static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
-+
-+#ifndef MIN
-+# define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
-+#endif
-+
-+/* In-core version of inode / directory entry. */
-+struct entry {
-+ /* stats */
-+ char *name;
-+ unsigned int mode, size, uid, gid;
-+
-+ /* FS data */
-+ void *uncompressed;
-+ /* points to other identical file */
-+ struct entry *same;
-+ unsigned int offset; /* pointer to compressed data in archive */
-+ unsigned int dir_offset; /* Where in the archive is the directory entry? */
-+
-+ /* organization */
-+ struct entry *child; /* null for non-directories and empty directories */
-+ struct entry *next;
-+};
-+
-+/*
-+ * The longest file name component to allow for in the input directory tree.
-+ * Ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
-+ * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
-+ * >255-byte names in the input directory tree given that such names get
-+ * truncated to 255 bytes when written to cramfs.
-+ */
-+#define MAX_INPUT_NAMELEN 255
-+
-+static int find_identical_file(struct entry *orig,struct entry *newfile)
-+{
-+ if(orig==newfile) return 1;
-+ if(!orig) return 0;
-+ if(orig->size==newfile->size && orig->uncompressed && !memcmp(orig->uncompressed,newfile->uncompressed,orig->size)) {
-+ newfile->same=orig;
-+ return 1;
-+ }
-+ return find_identical_file(orig->child,newfile) ||
-+ find_identical_file(orig->next,newfile);
-+}
-+
-+static void eliminate_doubles(struct entry *root,struct entry *orig) {
-+ if(orig) {
-+ if(orig->size && orig->uncompressed)
-+ find_identical_file(root,orig);
-+ eliminate_doubles(root,orig->child);
-+ eliminate_doubles(root,orig->next);
-+ }
-+}
-+
-+/*
-+ * We define our own sorting function instead of using alphasort which
-+ * uses strcoll and changes ordering based on locale information.
-+ */
-+static int cramsort (const void *a, const void *b)
-+{
-+ return strcmp ((*(const struct dirent **) a)->d_name,
-+ (*(const struct dirent **) b)->d_name);
-+}
-+
-+static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
-+{
-+ struct dirent **dirlist;
-+ int totalsize = 0, dircount, dirindex;
-+ char *path, *endpath;
-+ size_t len = strlen(name);
-+
-+ /* Set up the path. */
-+ /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
-+ path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
-+ if (!path) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ memcpy(path, name, len);
-+ endpath = path + len;
-+ *endpath = '/';
-+ endpath++;
-+
-+ /* read in the directory and sort */
-+ dircount = scandir(name, &dirlist, 0, cramsort);
-+
-+ if (dircount < 0) {
-+ perror(name);
-+ exit(8);
-+ }
-+
-+ /* process directory */
-+ for (dirindex = 0; dirindex < dircount; dirindex++) {
-+ struct dirent *dirent;
-+ struct entry *entry;
-+ struct stat st;
-+ int size;
-+ size_t namelen;
-+
-+ dirent = dirlist[dirindex];
-+
-+ /* Ignore "." and ".." - we won't be adding them to the archive */
-+ if (dirent->d_name[0] == '.') {
-+ if (dirent->d_name[1] == '\0')
-+ continue;
-+ if (dirent->d_name[1] == '.') {
-+ if (dirent->d_name[2] == '\0')
-+ continue;
-+ }
-+ }
-+ namelen = strlen(dirent->d_name);
-+ if (namelen > MAX_INPUT_NAMELEN) {
-+ fprintf(stderr,
-+ "Very long (%u bytes) filename `%s' found.\n"
-+ " Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile. Exiting.\n",
-+ namelen, dirent->d_name);
-+ exit(8);
-+ }
-+ memcpy(endpath, dirent->d_name, namelen + 1);
-+
-+ if (lstat(path, &st) < 0) {
-+ perror(endpath);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ entry = calloc(1, sizeof(struct entry));
-+ if (!entry) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ entry->name = strdup(dirent->d_name);
-+ if (!entry->name) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ if (namelen > 255) {
-+ /* Can't happen when reading from ext2fs. */
-+
-+ /* TODO: we ought to avoid chopping in half
-+ multi-byte UTF8 characters. */
-+ entry->name[namelen = 255] = '\0';
-+ warn_namelen = 1;
-+ }
-+ entry->mode = st.st_mode;
-+ entry->size = st.st_size;
-+ entry->uid = st.st_uid;
-+ if (entry->uid >= 1 << CRAMFS_UID_WIDTH)
-+ warn_uid = 1;
-+ entry->gid = st.st_gid;
-+ if (entry->gid >= 1 << CRAMFS_GID_WIDTH)
-+ /* TODO: We ought to replace with a default
-+ gid instead of truncating; otherwise there
-+ are security problems. Maybe mode should
-+ be &= ~070. Same goes for uid once Linux
-+ supports >16-bit uids. */
-+ warn_gid = 1;
-+ size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
-+ *fslen_ub += size;
-+ if (S_ISDIR(st.st_mode)) {
-+ entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
-+ } else if (S_ISREG(st.st_mode)) {
-+ /* TODO: We ought to open files in do_compress, one
-+ at a time, instead of amassing all these memory
-+ maps during parse_directory (which don't get used
-+ until do_compress anyway). As it is, we tend to
-+ get EMFILE errors (especially if mkcramfs is run
-+ by non-root).
-+
-+ While we're at it, do analagously for symlinks
-+ (which would just save a little memory). */
-+ int fd = open(path, O_RDONLY);
-+ if (fd < 0) {
-+ perror(path);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ if (entry->size) {
-+ if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) {
-+ warn_size = 1;
-+ entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
-+ }
-+
-+ entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
-+ if (-1 == (int) (long) entry->uncompressed) {
-+ perror("mmap");
-+ exit(8);
-+ }
-+ }
-+ close(fd);
-+ } else if (S_ISLNK(st.st_mode)) {
-+ entry->uncompressed = malloc(entry->size);
-+ if (!entry->uncompressed) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ if (readlink(path, entry->uncompressed, entry->size) < 0) {
-+ perror(path);
-+ warn_skip = 1;
-+ continue;
-+ }
-+ } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
-+ /* maybe we should skip sockets */
-+ entry->size = 0;
-+ } else {
-+ entry->size = st.st_rdev;
-+ if (entry->size & -(1<<CRAMFS_SIZE_WIDTH))
-+ warn_dev = 1;
-+ }
-+
-+ if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
-+ int blocks = ((entry->size - 1) / blksize + 1);
-+
-+ /* block pointers & data expansion allowance + data */
-+ if(entry->size)
-+ *fslen_ub += (4+26)*blocks + entry->size + 3;
-+ }
-+
-+ if (opt_xip && entry->mode & S_ISVTX) {
-+ /* worse case, depending on where the offsets falls,
-+ * a single XIP entry could expand the sizeof the
-+ * file system by 8k, since we're aligning the start
-+ * and end on page boundary.
-+ */
-+ *fslen_ub += 2*PAGE_CACHE_SIZE;
-+ }
-+
-+ /* Link it into the list */
-+ *prev = entry;
-+ prev = &entry->next;
-+ totalsize += size;
-+ }
-+ free(path);
-+ free(dirlist); /* allocated by scandir() with malloc() */
-+ return totalsize;
-+}
-+
-+/* Returns sizeof(struct cramfs_super), which includes the root inode. */
-+static unsigned int write_superblock(struct entry *root, char *base, int size)
-+{
-+ struct cramfs_super *super = (struct cramfs_super *) base;
-+ unsigned int offset = sizeof(struct cramfs_super) + image_length;
-+
-+ if (opt_pad) {
-+ offset += opt_pad;
-+ }
-+
-+ super->magic = CRAMFS_MAGIC;
-+ super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS;
-+ if (opt_holes)
-+ super->flags |= CRAMFS_FLAG_HOLES;
-+ if (image_length > 0)
-+ super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET;
-+ super->size = size;
-+ memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
-+
-+ super->fsid.crc = crc32(0L, Z_NULL, 0);
-+ super->fsid.edition = opt_edition;
-+ super->fsid.blocks = total_blocks;
-+ super->fsid.files = total_nodes;
-+
-+ memset(super->name, 0x00, sizeof(super->name));
-+ if (opt_name)
-+ strncpy(super->name, opt_name, sizeof(super->name));
-+ else
-+ strncpy(super->name, "Compressed", sizeof(super->name));
-+
-+ super->root.mode = root->mode;
-+ super->root.uid = root->uid;
-+ super->root.gid = root->gid;
-+ super->root.size = root->size;
-+ super->root.offset = offset >> 2;
-+
-+ return offset;
-+}
-+
-+static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
-+{
-+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
-+#ifdef DEBUG
-+ assert ((offset & 3) == 0);
-+#endif /* DEBUG */
-+ if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
-+ fprintf(stderr, "filesystem too big. Exiting.\n");
-+ exit(8);
-+ }
-+ inode->offset = (offset >> 2);
-+}
-+
-+
-+/*
-+ * We do a width-first printout of the directory
-+ * entries, using a stack to remember the directories
-+ * we've seen.
-+ */
-+#define MAXENTRIES (100)
-+static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
-+{
-+ int stack_entries = 0;
-+ struct entry *entry_stack[MAXENTRIES];
-+
-+ for (;;) {
-+ int dir_start = stack_entries;
-+ while (entry) {
-+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
-+ size_t len = strlen(entry->name);
-+
-+ entry->dir_offset = offset;
-+
-+ inode->mode = entry->mode;
-+ inode->uid = entry->uid;
-+ inode->gid = entry->gid;
-+ inode->size = entry->size;
-+ inode->offset = 0;
-+ /* Non-empty directories, regfiles and symlinks will
-+ write over inode->offset later. */
-+
-+ offset += sizeof(struct cramfs_inode);
-+ total_nodes++; /* another node */
-+ memcpy(base + offset, entry->name, len);
-+ /* Pad up the name to a 4-byte boundary */
-+ while (len & 3) {
-+ *(base + offset + len) = '\0';
-+ len++;
-+ }
-+ inode->namelen = len >> 2;
-+ offset += len;
-+
-+ /* TODO: this may get it wrong for chars >= 0x80.
-+ Most filesystems use UTF8 encoding for filenames,
-+ whereas the console is a single-byte character
-+ set like iso-latin-1. */
-+ printf(" %s\n", entry->name);
-+ if (entry->child) {
-+ if (stack_entries >= MAXENTRIES) {
-+ fprintf(stderr, "Exceeded MAXENTRIES. Raise this value in mkcramfs.c and recompile. Exiting.\n");
-+ exit(8);
-+ }
-+ entry_stack[stack_entries] = entry;
-+ stack_entries++;
-+ }
-+ entry = entry->next;
-+ }
-+
-+ /*
-+ * Reverse the order the stack entries pushed during
-+ * this directory, for a small optimization of disk
-+ * access in the created fs. This change makes things
-+ * `ls -UR' order.
-+ */
-+ {
-+ struct entry **lo = entry_stack + dir_start;
-+ struct entry **hi = entry_stack + stack_entries;
-+ struct entry *tmp;
-+
-+ while (lo < --hi) {
-+ tmp = *lo;
-+ *lo++ = *hi;
-+ *hi = tmp;
-+ }
-+ }
-+
-+ /* Pop a subdirectory entry from the stack, and recurse. */
-+ if (!stack_entries)
-+ break;
-+ stack_entries--;
-+ entry = entry_stack[stack_entries];
-+
-+ set_data_offset(entry, base, offset);
-+ printf("'%s':\n", entry->name);
-+ entry = entry->child;
-+ }
-+ return offset;
-+}
-+
-+static int is_zero(char const *begin, unsigned len)
-+{
-+ if (opt_holes)
-+ /* Returns non-zero iff the first LEN bytes from BEGIN are
-+ all NULs. */
-+ return (len-- == 0 ||
-+ (begin[0] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[1] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[2] == '\0' &&
-+ (len-- == 0 ||
-+ (begin[3] == '\0' &&
-+ memcmp(begin, begin + 4, len) == 0))))))));
-+ else
-+ /* Never create holes. */
-+ return 0;
-+}
-+
-+static unsigned int do_xip(char *base, unsigned int offset,
-+ char const *name, char *uncompressed,
-+ unsigned int size)
-+{
-+ unsigned int start, end;
-+
-+ /* align to page boundary */
-+
-+ start = ROM_ALIGN(offset);
-+ memset(base + offset, 0, start - offset);
-+
-+ memcpy(base + start, uncompressed, size);
-+
-+ /* pad to page boundary */
-+
-+ end = ROM_ALIGN(start + size);
-+ memset(base + start + size, 0, end - (start + size));
-+
-+ printf("XIP (%u+%u bytes)\toffset %u\t%s\n",
-+ size, (end - offset) - size, offset, name);
-+
-+ return end;
-+}
-+
-+/*
-+ * One 4-byte pointer per block and then the actual blocked
-+ * output. The first block does not need an offset pointer,
-+ * as it will start immediately after the pointer block;
-+ * so the i'th pointer points to the end of the i'th block
-+ * (i.e. the start of the (i+1)'th block or past EOF).
-+ *
-+ * Note that size > 0, as a zero-sized file wouldn't ever
-+ * have gotten here in the first place.
-+ */
-+static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size)
-+{
-+ unsigned long original_size = size;
-+ unsigned long original_offset = offset;
-+ unsigned long new_size;
-+ unsigned long blocks = (size - 1) / blksize + 1;
-+ unsigned long curr = offset + 4 * blocks;
-+ int change;
-+
-+ total_blocks += blocks;
-+
-+ do {
-+ unsigned long len = 2 * blksize;
-+ unsigned int input = size;
-+ if (input > blksize)
-+ input = blksize;
-+ size -= input;
-+ if (!is_zero (uncompressed, input)) {
-+ compress(base + curr, &len, uncompressed, input);
-+ curr += len;
-+ }
-+ uncompressed += input;
-+
-+ if (len > blksize*2) {
-+ /* (I don't think this can happen with zlib.) */
-+ printf("AIEEE: block \"compressed\" to > 2*blocklength (%ld)\n", len);
-+ exit(8);
-+ }
-+
-+ *(u32 *) (base + offset) = curr;
-+ offset += 4;
-+ } while (size);
-+
-+ curr = (curr + 3) & ~3;
-+ new_size = curr - original_offset;
-+ /* TODO: Arguably, original_size in these 2 lines should be
-+ st_blocks * 512. But if you say that then perhaps
-+ administrative data should also be included in both. */
-+ change = new_size - original_size;
-+ printf("%6.2f%% (%+d bytes)\toffset %lu\t%s\n",
-+ (change * 100) / (double) original_size, change, original_offset, name);
-+
-+ return curr;
-+}
-+
-+
-+/*
-+ * Traverse the entry tree, writing data for every item that has
-+ * non-null entry->compressed (i.e. every symlink and non-empty
-+ * regfile).
-+ */
-+static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
-+{
-+ do {
-+ if (entry->uncompressed) {
-+ if(entry->same) {
-+ set_data_offset(entry, base, entry->same->offset);
-+ entry->offset=entry->same->offset;
-+ } else {
-+ set_data_offset(entry, base, offset);
-+ entry->offset=offset;
-+ if (opt_xip && entry->mode & S_ISVTX)
-+ offset = do_xip(base, offset, entry->name, entry->uncompressed, entry->size);
-+ else
-+ offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size);
-+ }
-+ }
-+ else if (entry->child)
-+ offset = write_data(entry->child, base, offset);
-+ entry=entry->next;
-+ } while (entry);
-+ return offset;
-+}
-+
-+static unsigned int write_file(char *file, char *base, unsigned int offset)
-+{
-+ int fd;
-+ char *buf;
-+
-+ fd = open(file, O_RDONLY);
-+ if (fd < 0) {
-+ perror(file);
-+ exit(8);
-+ }
-+ buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0);
-+ memcpy(base + offset, buf, image_length);
-+ munmap(buf, image_length);
-+ close (fd);
-+ /* Pad up the image_length to a 4-byte boundary */
-+ while (image_length & 3) {
-+ *(base + offset + image_length) = '\0';
-+ image_length++;
-+ }
-+ return (offset + image_length);
-+}
-+
-+/*
-+ * Maximum size fs you can create is roughly 256MB. (The last file's
-+ * data must begin within 256MB boundary but can extend beyond that.)
-+ *
-+ * Note that if you want it to fit in a ROM then you're limited to what the
-+ * hardware and kernel can support (64MB?).
-+ */
-+#define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \
-+ + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \
-+ + (1 << CRAMFS_SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
-+
-+
-+/*
-+ * Usage:
-+ *
-+ * mkcramfs directory-name outfile
-+ *
-+ * where "directory-name" is simply the root of the directory
-+ * tree that we want to generate a compressed filesystem out
-+ * of.
-+ */
-+int main(int argc, char **argv)
-+{
-+ struct stat st; /* used twice... */
-+ struct entry *root_entry;
-+ char *rom_image;
-+ ssize_t offset, written;
-+ int fd;
-+ /* initial guess (upper-bound) of required filesystem size */
-+ loff_t fslen_ub = sizeof(struct cramfs_super);
-+ char const *dirname, *outfile;
-+ u32 crc = crc32(0L, Z_NULL, 0);
-+ int c; /* for getopt */
-+
-+ total_blocks = 0;
-+
-+ if (argc)
-+ progname = argv[0];
-+
-+ /* command line options */
-+ while ((c = getopt(argc, argv, "hEe:i:n:psxz")) != EOF) {
-+ switch (c) {
-+ case 'h':
-+ usage(0);
-+ case 'E':
-+ opt_errors = 1;
-+ break;
-+ case 'e':
-+ opt_edition = atoi(optarg);
-+ break;
-+ case 'i':
-+ opt_image = optarg;
-+ if (lstat(opt_image, &st) < 0) {
-+ perror(opt_image);
-+ exit(16);
-+ }
-+ image_length = st.st_size; /* may be padded later */
-+ fslen_ub += (image_length + 3); /* 3 is for padding */
-+ break;
-+ case 'n':
-+ opt_name = optarg;
-+ break;
-+ case 'p':
-+ opt_pad = PAD_SIZE;
-+ fslen_ub += PAD_SIZE;
-+ break;
-+ case 's':
-+ /* old option, ignored */
-+ break;
-+ case 'x':
-+ opt_xip = 1;
-+ break;
-+ case 'z':
-+ opt_holes = 1;
-+ break;
-+ }
-+ }
-+
-+ if ((argc - optind) != 2)
-+ usage(16);
-+ dirname = argv[optind];
-+ outfile = argv[optind + 1];
-+
-+ if (stat(dirname, &st) < 0) {
-+ perror(dirname);
-+ exit(16);
-+ }
-+ fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-+
-+ root_entry = calloc(1, sizeof(struct entry));
-+ if (!root_entry) {
-+ perror(NULL);
-+ exit(8);
-+ }
-+ root_entry->mode = st.st_mode;
-+ root_entry->uid = st.st_uid;
-+ root_entry->gid = st.st_gid;
-+
-+ root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub);
-+
-+ /* always allocate a multiple of blksize bytes because that's
-+ what we're going to write later on */
-+ fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1;
-+
-+ if (fslen_ub > MAXFSLEN) {
-+ fprintf(stderr,
-+ "warning: guestimate of required size (upper bound) is %LdMB, but maximum image size is %uMB. We might die prematurely.\n",
-+ fslen_ub >> 20,
-+ MAXFSLEN >> 20);
-+ fslen_ub = MAXFSLEN;
-+ }
-+
-+ /* find duplicate files. TODO: uses the most inefficient algorithm
-+ possible. */
-+ eliminate_doubles(root_entry,root_entry);
-+
-+ /* TODO: Why do we use a private/anonymous mapping here
-+ followed by a write below, instead of just a shared mapping
-+ and a couple of ftruncate calls? Is it just to save us
-+ having to deal with removing the file afterwards? If we
-+ really need this huge anonymous mapping, we ought to mmap
-+ in smaller chunks, so that the user doesn't need nn MB of
-+ RAM free. If the reason is to be able to write to
-+ un-mmappable block devices, then we could try shared mmap
-+ and revert to anonymous mmap if the shared mmap fails. */
-+ rom_image = mmap(NULL, fslen_ub?fslen_ub:1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-+
-+ if (-1 == (int) (long) rom_image) {
-+ perror("ROM image map");
-+ exit(8);
-+ }
-+
-+ /* Skip the first opt_pad bytes for boot loader code */
-+ offset = opt_pad;
-+ memset(rom_image, 0x00, opt_pad);
-+
-+ /* Skip the superblock and come back to write it later. */
-+ offset += sizeof(struct cramfs_super);
-+
-+ /* Insert a file image. */
-+ if (opt_image) {
-+ printf("Including: %s\n", opt_image);
-+ offset = write_file(opt_image, rom_image, offset);
-+ }
-+
-+ offset = write_directory_structure(root_entry->child, rom_image, offset);
-+ printf("Directory data: %d bytes\n", offset);
-+
-+ offset = write_data(root_entry, rom_image, offset);
-+
-+ /* We always write a multiple of blksize bytes, so that
-+ losetup works. */
-+ offset = ((offset - 1) | (blksize - 1)) + 1;
-+ printf("Everything: %d kilobytes\n", offset >> 10);
-+
-+ /* Write the superblock now that we can fill in all of the fields. */
-+ write_superblock(root_entry, rom_image+opt_pad, offset);
-+ printf("Super block: %d bytes\n", sizeof(struct cramfs_super));
-+
-+ /* Put the checksum in. */
-+ crc = crc32(crc, (rom_image+opt_pad), (offset-opt_pad));
-+ ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc;
-+ printf("CRC: %x\n", crc);
-+
-+ /* Check to make sure we allocated enough space. */
-+ if (fslen_ub < offset) {
-+ fprintf(stderr, "not enough space allocated for ROM image (%Ld allocated, %d used)\n",
-+ fslen_ub, offset);
-+ exit(8);
-+ }
-+
-+ written = write(fd, rom_image, offset);
-+ if (written < 0) {
-+ perror("ROM image");
-+ exit(8);
-+ }
-+ if (offset != written) {
-+ fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
-+ exit(8);
-+ }
-+
-+ /* (These warnings used to come at the start, but they scroll off the
-+ screen too quickly.) */
-+ if (warn_namelen) /* (can't happen when reading from ext2fs) */
-+ fprintf(stderr, /* bytes, not chars: think UTF8. */
-+ "warning: filenames truncated to 255 bytes.\n");
-+ if (warn_skip)
-+ fprintf(stderr, "warning: files were skipped due to errors.\n");
-+ if (warn_size)
-+ fprintf(stderr,
-+ "warning: file sizes truncated to %luMB (minus 1 byte).\n",
-+ 1L << (CRAMFS_SIZE_WIDTH - 20));
-+ if (warn_uid) /* (not possible with current Linux versions) */
-+ fprintf(stderr,
-+ "warning: uids truncated to %u bits. (This may be a security concern.)\n",
-+ CRAMFS_UID_WIDTH);
-+ if (warn_gid)
-+ fprintf(stderr,
-+ "warning: gids truncated to %u bits. (This may be a security concern.)\n",
-+ CRAMFS_GID_WIDTH);
-+ if (warn_dev)
-+ fprintf(stderr,
-+ "WARNING: device numbers truncated to %u bits. This almost certainly means\n"
-+ "that some device files will be wrong.\n",
-+ CRAMFS_OFFSET_WIDTH);
-+ if (opt_errors &&
-+ (warn_namelen||warn_skip||warn_size||warn_uid||warn_gid||warn_dev))
-+ exit(8);
-+ return 0;
-+}
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/bitfield.h
-@@ -0,0 +1,113 @@
-+/*
-+ * FILE bitfield.h
-+ *
-+ * Version 1.1
-+ * Author Copyright (c) Marc A. Viredaz, 1998
-+ * DEC Western Research Laboratory, Palo Alto, CA
-+ * Date April 1998 (April 1997)
-+ * System Advanced RISC Machine (ARM)
-+ * Language C or ARM Assembly
-+ * Purpose Definition of macros to operate on bit fields.
-+ */
-+
-+
-+
-+#ifndef __BITFIELD_H
-+#define __BITFIELD_H
-+
-+#ifndef __ASSEMBLY__
-+#define UData(Data) ((unsigned long) (Data))
-+#else
-+#define UData(Data) (Data)
-+#endif
-+
-+
-+/*
-+ * MACRO: Fld
-+ *
-+ * Purpose
-+ * The macro "Fld" encodes a bit field, given its size and its shift value
-+ * with respect to bit 0.
-+ *
-+ * Note
-+ * A more intuitive way to encode bit fields would have been to use their
-+ * mask. However, extracting size and shift value information from a bit
-+ * field's mask is cumbersome and might break the assembler (255-character
-+ * line-size limit).
-+ *
-+ * Input
-+ * Size Size of the bit field, in number of bits.
-+ * Shft Shift value of the bit field with respect to bit 0.
-+ *
-+ * Output
-+ * Fld Encoded bit field.
-+ */
-+
-+#define Fld(Size, Shft) (((Size) << 16) + (Shft))
-+
-+
-+/*
-+ * MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit
-+ *
-+ * Purpose
-+ * The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return
-+ * the size, shift value, mask, aligned mask, and first bit of a
-+ * bit field.
-+ *
-+ * Input
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FSize Size of the bit field, in number of bits.
-+ * FShft Shift value of the bit field with respect to bit 0.
-+ * FMsk Mask for the bit field.
-+ * FAlnMsk Mask for the bit field, aligned on bit 0.
-+ * F1stBit First bit of the bit field.
-+ */
-+
-+#define FSize(Field) ((Field) >> 16)
-+#define FShft(Field) ((Field) & 0x0000FFFF)
-+#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))
-+#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
-+#define F1stBit(Field) (UData (1) << FShft (Field))
-+
-+
-+/*
-+ * MACRO: FInsrt
-+ *
-+ * Purpose
-+ * The macro "FInsrt" inserts a value into a bit field by shifting the
-+ * former appropriately.
-+ *
-+ * Input
-+ * Value Bit-field value.
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FInsrt Bit-field value positioned appropriately.
-+ */
-+
-+#define FInsrt(Value, Field) \
-+ (UData (Value) << FShft (Field))
-+
-+
-+/*
-+ * MACRO: FExtr
-+ *
-+ * Purpose
-+ * The macro "FExtr" extracts the value of a bit field by masking and
-+ * shifting it appropriately.
-+ *
-+ * Input
-+ * Data Data containing the bit-field to be extracted.
-+ * Field Encoded bit field (using the macro "Fld").
-+ *
-+ * Output
-+ * FExtr Bit-field value.
-+ */
-+
-+#define FExtr(Data, Field) \
-+ ((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
-+
-+
-+#endif /* __BITFIELD_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/cerf.h
-@@ -0,0 +1,177 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/cerf.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * Add CerfBoard Specifics here...
-+ */
-+
-+/*
-+ * Memory sizes
-+ */
-+
-+#define CERF_RAM_BASE 0xa0000000
-+
-+#ifdef CONFIG_PXA_CERF_RAM_128MB
-+#define CERF_RAM_SIZE 128*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_64MB)
-+#define CERF_RAM_SIZE 64*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_32MB)
-+#define CERF_RAM_SIZE 32*1024*1024
-+
-+#elif defined (CONFIG_PXA_CERF_RAM_16MB)
-+#define CERF_RAM_SIZE 16*1024*1024
-+#endif
-+
-+/*
-+ * CS memory timing via Static Memory Control Register (MSC0-2)
-+ */
-+
-+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
-+
-+#define MSC_RBUFF_SHIFT 15
-+#define MSC_RBUFF_SLOW (0)
-+#define MSC_RBUFF_FAST (1)
-+#define MSC_RBUFF(x) ((x)<<MSC_RBUFF_SHIFT)
-+
-+#define MSC_RRR_SHIFT 12
-+#define MSC_RRR(x) ((x)<<MSC_RRR_SHIFT)
-+
-+#define MSC_RDN_SHIFT 8
-+#define MSC_RDN(x) ((x)<<MSC_RDN_SHIFT)
-+
-+#define MSC_RDF_SHIFT 4
-+#define MSC_RDF(x) ((x)<<MSC_RDF_SHIFT)
-+
-+#define MSC_RBW_SHIFT 3
-+#define MSC_RBW(x) ((x)<<MSC_RBW_SHIFT)
-+
-+#define MSC_RT_SHIFT 0
-+#define MSC_RT(x) ((x)<<MSC_RT_SHIFT)
-+
-+/*
-+ * IO Pins for devices
-+ */
-+
-+#define CERF_FLASH_BASE 0xe8000000
-+#define CERF_FLASH_SIZE 0x02000000
-+#define CERF_FLASH_PHYS PXA_CS0_PHYS
-+
-+#define CERF_ETH_BASE 0xf0000000
-+#define CERF_ETH_SIZE 0x00100000
-+#define CERF_ETH_PHYS PXA_CS1_PHYS
-+
-+#define CERF_BT_BASE 0xf2000000
-+#define CERF_BT_SIZE 0x00100000
-+#define CERF_BT_PHYS PXA_CS2_PHYS
-+
-+#define CERF_SERIAL_BASE 0xf3000000
-+#define CERF_SERIAL_SIZE 0x00100000
-+#define CERF_SERIAL_PHYS PXA_CS3_PHYS
-+
-+#define CERF_CPLD_BASE 0xf1000000
-+#define CERF_CPLD_SIZE 0x00100000
-+#define CERF_CPLD_PHYS PXA_CS4_PHYS
-+
-+#define CERF_PDA_CPLD_WRCLRINT (0x0)
-+#define CERF_PDA_CPLD_BRIGHTNESS (0x2)
-+#define CERF_PDA_CPLD_KEYPAD_A (0x6)
-+#define CERF_PDA_CPLD_BATTFAULT (0x8)
-+#define CERF_PDA_CPLD_KEYPAD_B (0xa)
-+#define CERF_PDA_CPLD_SOUND_ENA (0xc)
-+
-+#define CERF_PDA_SOUND_ENABLE 0x1
-+#define CERF_PDA_DEFAULT_BRIGHTNESS 0x9
-+
-+/*
-+ * Access functions (registers are 4-bit wide)
-+ */
-+
-+#define CERF_PDA_CPLD CERF_CPLD_BASE
-+
-+#define CERF_PDA_CPLD_Get(x, y) (*((char*)(CERF_PDA_CPLD + (x))) & (y))
-+#define CERF_PDA_CPLD_Set(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) | (y))
-+#define CERF_PDA_CPLD_UnSet(x, y, z) (*((char*)(CERF_PDA_CPLD + (x))) = (*((char*)(CERF_PDA_CPLD + (x))) & ~(z)) & ~(y))
-+
-+/*
-+ * IO and IRQ settings for cs8900 ethernet chip
-+ */
-+#define CERF_ETH_IO CERF_ETH_BASE
-+#define CERF_ETH_IRQ GPIO_2_80_TO_IRQ(21)
-+
-+/*
-+ * We only have one LED on the XScale CerfPDA so only the
-+ * time or idle should ever be selected.
-+ */
-+#define CERF_HEARTBEAT_LED 0x1
-+#define CERF_SYS_BUSY_LED 0x2
-+
-+#define CERF_HEARTBEAT_LED_GPIO 16 // GPIO 4
-+#define CERF_SYS_BUSY_LED_GPIO 16 // GPIO 4
-+
-+#define CERF_HEARTBEAT_LED_ON (GPSR0 = CERF_HEARTBEAT_LED_GPIO)
-+#define CERF_HEARTBEAT_LED_OFF (GPCR0 = CERF_HEARTBEAT_LED_GPIO)
-+#define CERF_SYS_BUSY_LED_ON (GPSR0 = CERF_SYS_BUSY_LED_GPIO)
-+#define CERF_SYS_BUSY_LED_OFF (GPCR0 = CERF_SYS_BUSY_LED_GPIO)
-+
-+/*
-+ * UCB 1400 gpio
-+ */
-+
-+#define CERF_GPIO_UCB1400_IRQ 32
-+
-+#define UCB_IO_0 (1 << 0)
-+#define UCB_IO_1 (1 << 1)
-+#define UCB_IO_2 (1 << 2)
-+#define UCB_IO_3 (1 << 3)
-+#define UCB_IO_4 (1 << 4)
-+#define UCB_IO_5 (1 << 5)
-+#define UCB_IO_6 (1 << 6)
-+#define UCB_IO_7 (1 << 7)
-+#define UCB_IO_8 (1 << 8)
-+#define UCB_IO_9 (1 << 9)
-+
-+#define UCB1400_GPIO_CONT_CS UCB_IO_0
-+#define UCB1400_GPIO_CONT_DOWN UCB_IO_1
-+#define UCB1400_GPIO_CONT_INC UCB_IO_2
-+#define UCB1400_GPIO_CONT_ENA UCB_IO_3
-+#define UCB1400_GPIO_LCD_RESET UCB_IO_4
-+#define UCB1400_GPIO_IRDA_ENABLE UCB_IO_5
-+#define UCB1400_GPIO_BT_ENABLE UCB_IO_6
-+#define UCB1400_GPIO_TEST_P1 UCB_IO_7
-+#define UCB1400_GPIO_TEST_P2 UCB_IO_8
-+#define UCB1400_GPIO_TEST_P3 UCB_IO_9
-+
-+/*
-+ * IRQ for devices
-+ */
-+#define UCB1400_IRQ(x) (NR_IRQS + 1 + (x))
-+
-+#define IRQ_UCB1400_IO0 UCB1400_IRQ(0)
-+#define IRQ_UCB1400_IO1 UCB1400_IRQ(1)
-+#define IRQ_UCB1400_IO2 UCB1400_IRQ(2)
-+#define IRQ_UCB1400_IO3 UCB1400_IRQ(3)
-+#define IRQ_UCB1400_IO4 UCB1400_IRQ(4)
-+#define IRQ_UCB1400_IO5 UCB1400_IRQ(5)
-+#define IRQ_UCB1400_IO6 UCB1400_IRQ(6)
-+#define IRQ_UCB1400_IO7 UCB1400_IRQ(7)
-+#define IRQ_UCB1400_IO8 UCB1400_IRQ(8)
-+#define IRQ_UCB1400_IO9 UCB1400_IRQ(9)
-+
-+#define IRQ_UCB1400_CONT_CS IRQ_UCB1400_IO0
-+#define IRQ_UCB1400_CONT_DOWN IRQ_UCB1400_IO1
-+#define IRQ_UCB1400_CONT_INC IRQ_UCB1400_IO2
-+#define IRQ_UCB1400_CONT_ENA IRQ_UCB1400_IO3
-+#define IRQ_UCB1400_LCD_RESET IRQ_UCB1400_IO4
-+#define IRQ_UCB1400_IRDA_ENABLE IRQ_UCB1400_IO5
-+#define IRQ_UCB1400_BT_ENABLE IRQ_UCB1400_IO6
-+#define IRQ_UCB1400_TEST_P1 IRQ_UCB1400_IO7
-+#define IRQ_UCB1400_TEST_P2 IRQ_UCB1400_IO8
-+#define IRQ_UCB1400_TEST_P3 IRQ_UCB1400_IO9
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/cerf_ucb1400gpio.h
-@@ -0,0 +1,30 @@
-+/*
-+ * cerf_ucb1400gpio.h
-+ *
-+ * UCB1400 GPIO control stuff for the cerf.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+/* -- lcd -- */
-+extern void cerf_ucb1400gpio_lcd_enable( void);
-+extern void cerf_ucb1400gpio_lcd_disable( void);
-+extern void cerf_ucb1400gpio_lcd_contrast_step( int direction);
-+
-+/* -- irda -- */
-+extern void cerf_ucb1400gpio_irda_enable( void);
-+extern void cerf_ucb1400gpio_irda_disable( void);
-+
-+/* -- bt -- */
-+extern void cerf_ucb1400gpio_bt_enable( void);
-+extern void cerf_ucb1400gpio_bt_disable( void);
-+
-+/* -- init -- */
-+extern int cerf_ucb1400gpio_init(void);
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/csb226.h
-@@ -0,0 +1,99 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/csb226.h
-+ *
-+ * Author: Robert Schwebel (stolen from lubbock.h)
-+ * Created: Oct 30, 2002
-+ * Copyright: Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define CSB226_FPGA_PHYS PXA_CS2_PHYS
-+
-+#define CSB226_FPGA_VIRT (0xf0000000) /* phys 0x08000000 */
-+#define CSB226_ETH_BASE (0xf1000000) /* phys 0x0c000000 */
-+
-+#define CSB226_P2V(x) ((x) - CSB226_FPGA_PHYS + CSB226_FPGA_VIRT)
-+#define CSB226_V2P(x) ((x) - CSB226_FPGA_VIRT + CSB226_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CSB226_REG(x) (*((volatile unsigned long *)CSB226_P2V(x)))
-+#else
-+# define __CSB226_REG(x) CSB226_P2V(x)
-+#endif
-+
-+
-+/* register physical addresses */
-+#define _CSB226_MISC_WR (CSB226_FPGA_PHYS + 0x080)
-+#define _CSB226_MISC_RD (CSB226_FPGA_PHYS + 0x090)
-+#define _CSB226_IRQ_MASK_EN (CSB226_FPGA_PHYS + 0x0C0)
-+#define _CSB226_IRQ_SET_CLR (CSB226_FPGA_PHYS + 0x0D0)
-+#define _CSB226_GP (CSB226_FPGA_PHYS + 0x100)
-+
-+
-+
-+/* register virtual addresses */
-+
-+#define CSB226_MISC_WR __CSB226_REG(_CSB226_MISC_WR)
-+#define CSB226_MISC_RD __CSB226_REG(_CSB226_MISC_RD)
-+#define CSB226_IRQ_MASK_EN __CSB226_REG(_CSB226_IRQ_MASK_EN)
-+#define CSB226_IRQ_SET_CLR __CSB226_REG(_CSB226_IRQ_SET_CLR)
-+#define CSB226_GP __CSB226_REG(_CSB226_GP)
-+
-+
-+/* GPIOs */
-+
-+#define GPIO_CSB226_IRQ 0
-+#define IRQ_GPIO_CSB226_IRQ IRQ_GPIO0
-+
-+
-+/*
-+ * LED macros
-+ */
-+
-+// #define LEDS_BASE LUB_DISC_BLNK_LED
-+
-+// 8 discrete leds available for general use:
-+
-+/*
-+#define D28 0x1
-+#define D27 0x2
-+#define D26 0x4
-+#define D25 0x8
-+#define D24 0x10
-+#define D23 0x20
-+#define D22 0x40
-+#define D21 0x80
-+*/
-+
-+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
-+* be sure to not monkey with them here.
-+*/
-+
-+/*
-+#define HEARTBEAT_LED D28
-+#define SYS_BUSY_LED D27
-+#define HEXLEDS_BASE LUB_HEXLED
-+
-+#define HEARTBEAT_LED_ON (LEDS_BASE &= ~HEARTBEAT_LED)
-+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
-+#define SYS_BUSY_LED_OFF (LEDS_BASE |= SYS_BUSY_LED)
-+#define SYS_BUSY_LED_ON (LEDS_BASE &= ~SYS_BUSY_LED)
-+
-+// use x = D26-D21 for these, please...
-+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
-+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
-+*/
-+
-+#ifndef __ASSEMBLY__
-+
-+//extern int hexled_val = 0;
-+
-+#endif
-+
-+/*
-+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
-+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
-+*/
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/dma.h
-@@ -0,0 +1,49 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/dma.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __ASM_ARCH_DMA_H
-+#define __ASM_ARCH_DMA_H
-+
-+#define MAX_DMA_ADDRESS 0xffffffff
-+
-+/* No DMA as the rest of the world see it */
-+#define MAX_DMA_CHANNELS 0
-+
-+/*
-+ * Descriptor structure for PXA's DMA engine
-+ * Note: this structure must always be aligned to a 16-byte boundary.
-+ */
-+
-+typedef struct {
-+ volatile u32 ddadr; /* Points to the next descriptor + flags */
-+ volatile u32 dsadr; /* DSADR value for the current transfer */
-+ volatile u32 dtadr; /* DTADR value for the current transfer */
-+ volatile u32 dcmd; /* DCMD value for the current transfer */
-+} pxa_dma_desc;
-+
-+/*
-+ * DMA registration
-+ */
-+
-+typedef enum {
-+ DMA_PRIO_HIGH = 0,
-+ DMA_PRIO_MEDIUM = 4,
-+ DMA_PRIO_LOW = 8
-+} pxa_dma_prio;
-+
-+int pxa_request_dma (char *name,
-+ pxa_dma_prio prio,
-+ void (*irq_handler)(int, void *, struct pt_regs *),
-+ void *data);
-+
-+void pxa_free_dma (int dma_ch);
-+
-+#endif /* _ASM_ARCH_DMA_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/hardware.h
-@@ -0,0 +1,142 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/hardware.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef __ASM_ARCH_HARDWARE_H
-+#define __ASM_ARCH_HARDWARE_H
-+
-+#include <linux/config.h>
-+#include <asm/mach-types.h>
-+
-+
-+/*
-+ * These are statically mapped PCMCIA IO space for designs using it as a
-+ * generic IO bus, typically with ISA parts, hardwired IDE interfaces, etc.
-+ * The actual PCMCIA code is mapping required IO region at run time.
-+ */
-+#define PCMCIA_IO_0_BASE 0xf6000000
-+#define PCMCIA_IO_1_BASE 0xf7000000
-+
-+
-+/*
-+ * XIP kernel text mapping.
-+ * Note: the exact virtual address is also specified in arch/arm/Makefile.
-+ */
-+#ifdef CONFIG_XIP_KERNEL
-+#define KERNEL_XIP_BASE_PHYS (CONFIG_XIP_PHYS_ADDR & 0xffe00000)
-+#define KERNEL_XIP_BASE_VIRT 0xe8000000
-+#endif
-+
-+
-+/*
-+ * We requires absolute addresses.
-+ */
-+#define PCIO_BASE 0
-+
-+/*
-+ * Workarounds for at least 2 errata so far require this.
-+ * The mapping is set in mach-pxa/generic.c.
-+ */
-+#define UNCACHED_PHYS_0 0xff000000
-+#define UNCACHED_ADDR UNCACHED_PHYS_0
-+
-+/*
-+ * Intel PXA internal I/O mappings:
-+ *
-+ * 0x40000000 - 0x41ffffff <--> 0xf8000000 - 0xf9ffffff
-+ * 0x44000000 - 0x45ffffff <--> 0xfa000000 - 0xfbffffff
-+ * 0x48000000 - 0x49ffffff <--> 0xfc000000 - 0xfdffffff
-+ */
-+
-+#define io_p2v(x) ( ((x) | 0xbe000000) ^ (~((x) >> 1) & 0x06000000) )
-+#define io_v2p( x ) ( ((x) & 0x41ffffff) ^ ( ((x) & 0x06000000) << 1) )
-+
-+#ifndef __ASSEMBLY__
-+
-+#if 0
-+# define __REG(x) (*((volatile u32 *)io_p2v(x)))
-+#else
-+/*
-+ * This __REG() version gives the same results as the one above, except
-+ * that we are fooling gcc somehow so it generates far better and smaller
-+ * assembly code for access to contigous registers. It's a shame that gcc
-+ * doesn't guess this by itself.
-+ */
-+#include <asm/types.h>
-+typedef struct { volatile u32 offset[4096]; } __regbase;
-+# define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-+# define __REG(x) __REGP(io_p2v(x))
-+#endif
-+
-+/* Let's kick gcc's ass again... */
-+# define __REG2(x,y) \
-+ ( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-+ : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
-+
-+# define __PREG(x) (io_v2p((u32)&(x)))
-+
-+#else
-+
-+# define __REG(x) io_p2v(x)
-+# define __PREG(x) io_v2p(x)
-+
-+#endif
-+
-+#include "pxa-regs.h"
-+
-+#ifndef __ASSEMBLY__
-+
-+/*
-+ * GPIO edge detection for IRQs:
-+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
-+ * This must be called *before* the corresponding IRQ is registered.
-+ * Use this instead of directly setting GRER/GFER.
-+ */
-+#define GPIO_FALLING_EDGE 1
-+#define GPIO_RISING_EDGE 2
-+#define GPIO_BOTH_EDGES 3
-+extern void set_GPIO_IRQ_edge( int gpio_nr, int edge_mask );
-+
-+/*
-+ * Handy routine to set GPIO alternate functions
-+ */
-+extern void set_GPIO_mode( int gpio_mode );
-+
-+/*
-+ * return current lclk frequency in units of 10kHz
-+ */
-+extern unsigned int get_lclk_frequency_10khz(void);
-+
-+/*
-+ * return current clk frequency in units of 1kHz
-+ */
-+extern unsigned int get_clk_frequency_khz( int info);
-+
-+#endif
-+
-+
-+/*
-+ * Implementation specifics
-+ */
-+
-+//#ifdef CONFIG_ARCH_LUBBOCK
-+#include "lubbock.h"
-+//#endif
-+
-+//#ifdef CONFIG_ARCH_PXA_IDP
-+#include "idp.h"
-+//#endif
-+
-+//#ifdef CONFIG_ARCH_PXA_CERF
-+#include "cerf.h"
-+//#endif
-+
-+#endif /* _ASM_ARCH_HARDWARE_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/ide.h
-@@ -0,0 +1,59 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/ide.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ * Originally based upon linux/include/asm-arm/arch-sa1100/ide.h
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+
-+
-+/*
-+ * Set up a hw structure for a specified data port, control port and IRQ.
-+ * This should follow whatever the default interface uses.
-+ */
-+static __inline__ void
-+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
-+{
-+ ide_ioreg_t reg;
-+
-+ memset(hw, 0, sizeof(*hw));
-+
-+ reg = (ide_ioreg_t)data_port;
-+
-+ hw->io_ports[IDE_DATA_OFFSET] = reg + 0;
-+ hw->io_ports[IDE_ERROR_OFFSET] = reg + 1;
-+ hw->io_ports[IDE_NSECTOR_OFFSET] = reg + 2;
-+ hw->io_ports[IDE_SECTOR_OFFSET] = reg + 3;
-+ hw->io_ports[IDE_LCYL_OFFSET] = reg + 4;
-+ hw->io_ports[IDE_HCYL_OFFSET] = reg + 5;
-+ hw->io_ports[IDE_SELECT_OFFSET] = reg + 6;
-+ hw->io_ports[IDE_STATUS_OFFSET] = reg + 7;
-+
-+ hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-+
-+ if (irq)
-+ *irq = 0;
-+}
-+
-+
-+/*
-+ * Register the standard ports for this architecture with the IDE driver.
-+ */
-+static __inline__ void
-+ide_init_default_hwifs(void)
-+{
-+ /* Nothing to declare... */
-+}
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/idp.h
-@@ -0,0 +1,468 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/idp.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
-+ *
-+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
-+ * Initial code
-+ *
-+ */
-+
-+
-+/*
-+ * Note: this file must be safe to include in assembly files
-+ */
-+
-+/* comment out following if you have a rev01 board */
-+#define PXA_IDP_REV02 1
-+//#undef PXA_IDP_REV02
-+
-+#ifdef PXA_IDP_REV02
-+
-+//Use this as well for 0017-x004 and greater pcb's:
-+#define PXA_IDP_REV04 1
-+
-+#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
-+#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define IDP_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define IDP_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define IDP_ETH_PHYS (PXA_CS5_PHYS + 0x03400000)
-+#define IDP_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define IDP_CPLD_PHYS (PXA_CS5_PHYS + 0x03C00000)
-+
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define IDP_IDE_BASE (0xf0000000)
-+#define IDP_IDE_SIZE (1*1024*1024)
-+
-+#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-+#define IDP_ETH_SIZE (1*1024*1024)
-+#define ETH_BASE IDP_ETH_BASE //smc9194 driver compatibility issue
-+
-+#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
-+#define IDP_COREVOLT_SIZE (1*1024*1024)
-+
-+#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-+#define IDP_CPLD_SIZE (1*1024*1024)
-+
-+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-+#error Your custom IO space is getting a bit large !!
-+#endif
-+
-+#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define _IDP_CPLD_REV (IDP_CPLD_PHYS + 0x00)
-+#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
-+#define _IDP_CPLD_LED_CONTROL (IDP_CPLD_PHYS + 0x08)
-+#define _IDP_CPLD_KB_COL_HIGH (IDP_CPLD_PHYS + 0x0C)
-+#define _IDP_CPLD_KB_COL_LOW (IDP_CPLD_PHYS + 0x10)
-+#define _IDP_CPLD_PCCARD_EN (IDP_CPLD_PHYS + 0x14)
-+#define _IDP_CPLD_GPIOH_DIR (IDP_CPLD_PHYS + 0x18)
-+#define _IDP_CPLD_GPIOH_VALUE (IDP_CPLD_PHYS + 0x1C)
-+#define _IDP_CPLD_GPIOL_DIR (IDP_CPLD_PHYS + 0x20)
-+#define _IDP_CPLD_GPIOL_VALUE (IDP_CPLD_PHYS + 0x24)
-+#define _IDP_CPLD_PCCARD_PWR (IDP_CPLD_PHYS + 0x28)
-+#define _IDP_CPLD_MISC_CTRL (IDP_CPLD_PHYS + 0x2C)
-+#define _IDP_CPLD_LCD (IDP_CPLD_PHYS + 0x30)
-+#define _IDP_CPLD_FLASH_WE (IDP_CPLD_PHYS + 0x34)
-+
-+#define _IDP_CPLD_KB_ROW (IDP_CPLD_PHYS + 0x50)
-+#define _IDP_CPLD_PCCARD0_STATUS (IDP_CPLD_PHYS + 0x54)
-+#define _IDP_CPLD_PCCARD1_STATUS (IDP_CPLD_PHYS + 0x58)
-+#define _IDP_CPLD_MISC_STATUS (IDP_CPLD_PHYS + 0x5C)
-+
-+/* FPGA register virtual addresses */
-+
-+#define IDP_CPLD_REV __CPLD_REG(_IDP_CPLD_REV)
-+#define IDP_CPLD_PERIPH_PWR __CPLD_REG(_IDP_CPLD_PERIPH_PWR)
-+#define IDP_CPLD_LED_CONTROL __CPLD_REG(_IDP_CPLD_LED_CONTROL)
-+#define IDP_CPLD_KB_COL_HIGH __CPLD_REG(_IDP_CPLD_KB_COL_HIGH)
-+#define IDP_CPLD_KB_COL_LOW __CPLD_REG(_IDP_CPLD_KB_COL_LOW)
-+#define IDP_CPLD_PCCARD_EN __CPLD_REG(_IDP_CPLD_PCCARD_EN)
-+#define IDP_CPLD_GPIOH_DIR __CPLD_REG(_IDP_CPLD_GPIOH_DIR)
-+#define IDP_CPLD_GPIOH_VALUE __CPLD_REG(_IDP_CPLD_GPIOH_VALUE)
-+#define IDP_CPLD_GPIOL_DIR __CPLD_REG(_IDP_CPLD_GPIOL_DIR)
-+#define IDP_CPLD_GPIOL_VALUE __CPLD_REG(_IDP_CPLD_GPIOL_VALUE)
-+#define IDP_CPLD_PCCARD_PWR __CPLD_REG(_IDP_CPLD_PCCARD_PWR)
-+#define IDP_CPLD_MISC_CTRL __CPLD_REG(_IDP_CPLD_MISC_CTRL)
-+#define IDP_CPLD_LCD __CPLD_REG(_IDP_CPLD_LCD)
-+#define IDP_CPLD_FLASH_WE __CPLD_REG(_IDP_CPLD_FLASH_WE)
-+
-+#define IDP_CPLD_KB_ROW __CPLD_REG(_IDP_CPLD_KB_ROW)
-+#define IDP_CPLD_PCCARD0_STATUS __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)
-+#define IDP_CPLD_PCCARD1_STATUS __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)
-+#define IDP_CPLD_MISC_STATUS __CPLD_REG(_IDP_CPLD_MISC_STATUS)
-+
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+// IDP_CPLD_PCCARD_PWR
-+#define PCC0_PWR0 (1 << 0)
-+#define PCC0_PWR1 (1 << 1)
-+#define PCC0_PWR2 (1 << 2)
-+#define PCC0_PWR3 (1 << 3)
-+#define PCC1_PWR0 (1 << 4)
-+#define PCC1_PWR1 (1 << 5)
-+#define PCC1_PWR2 (1 << 6)
-+#define PCC1_PWR3 (1 << 7)
-+
-+// IDP_CPLD_PCCARD_EN
-+#define PCC0_RESET (1 << 6)
-+#define PCC1_RESET (1 << 7)
-+#define PCC0_ENABLE (1 << 0)
-+#define PCC1_ENABLE (1 << 1)
-+
-+// IDP_CPLD_PCCARDx_STATUS
-+#define _PCC_WRPROT (1 << 7) // 7-4 read as low true
-+#define _PCC_RESET (1 << 6)
-+#define _PCC_IRQ (1 << 5)
-+#define _PCC_INPACK (1 << 4)
-+#define PCC_BVD2 (1 << 3)
-+#define PCC_BVD1 (1 << 2)
-+#define PCC_VS2 (1 << 1)
-+#define PCC_VS1 (1 << 0)
-+
-+#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x)))
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON() (IDP_CPLD_LCD |= (1<<1))
-+#define FB_BACKLIGHT_OFF() (IDP_CPLD_LCD &= ~(1<<1))
-+
-+#define FB_PWR_ON() (IDP_CPLD_LCD |= (1<< 0))
-+#define FB_PWR_OFF() (IDP_CPLD_LCD &= ~(1<<0))
-+
-+#define FB_VLCD_ON() (IDP_CPLD_LCD |= (1<<2))
-+#define FB_VLCD_OFF() (IDP_CPLD_LCD &= ~(1<<2))
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#ifdef PXA_IDP_REV04
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(5)
-+#define IDE_IRQ IRQ_GPIO(21)
-+#else
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-+#define IDE_IRQ IRQ_GPIO(5)
-+#endif
-+
-+#define TOUCH_PANEL_IRQ_EDGE GPIO_FALLING_EDGE
-+
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define ETHERNET_IRQ IRQ_GPIO(4)
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define PCMCIA_S0_CD_VALID IRQ_GPIO(7)
-+#define PCMCIA_S0_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S1_CD_VALID IRQ_GPIO(8)
-+#define PCMCIA_S1_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S0_RDYINT IRQ_GPIO(19)
-+#define PCMCIA_S1_RDYINT IRQ_GPIO(22)
-+
-+/*
-+ * Macros for LED Driver
-+ */
-+
-+/* leds 0 = ON */
-+#define IDP_HB_LED (1<<5)
-+#define IDP_BUSY_LED (1<<6)
-+
-+#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-+
-+#define IDP_WRITE_LEDS(value) (IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() ((IDP_CPLD_FLASH_WE) &= ~(0x1))
-+#define FLASH_WRITE_PROTECT_ENABLE() ((IDP_CPLD_FLASH_WE) |= (0x1))
-+
-+/*
-+ * macros for matrix keyboard driver
-+ */
-+
-+#define KEYBD_MATRIX_NUMBER_INPUTS 7
-+#define KEYBD_MATRIX_NUMBER_OUTPUTS 14
-+
-+#define KEYBD_MATRIX_INVERT_OUTPUT_LOGIC FALSE
-+#define KEYBD_MATRIX_INVERT_INPUT_LOGIC FALSE
-+
-+#define KEYBD_MATRIX_SETTLING_TIME_US 100
-+#define KEYBD_MATRIX_KEYSTATE_DEBOUNCE_CONSTANT 2
-+
-+#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \
-+{\
-+ IDP_CPLD_KB_COL_LOW = outputs;\
-+ IDP_CPLD_KB_COL_HIGH = outputs >> 7;\
-+}
-+
-+#define KEYBD_MATRIX_GET_INPUTS(inputs) \
-+{\
-+ inputs = (IDP_CPLD_KB_ROW & 0x7f);\
-+}
-+
-+//------------------------------------------------------------------------------
-+
-+#else // must be rev 01
-+
-+/* -----------------------------------------------------------------------------
-+ * following is for rev01 boards only
-+ */
-+
-+#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
-+#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define IDP_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define IDP_CTRL_PORT_PHYS (PXA_CS5_PHYS + 0x02C00000)
-+#define IDP_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define IDP_ETH_PHYS (PXA_CS5_PHYS + 0x03400000)
-+#define IDP_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define IDP_CPLD_PHYS (PXA_CS5_PHYS + 0x03C00000)
-+
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define IDP_CTRL_PORT_BASE (0xf0000000)
-+#define IDP_CTRL_PORT_SIZE (1*1024*1024)
-+
-+#define IDP_IDE_BASE (IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
-+#define IDP_IDE_SIZE (1*1024*1024)
-+
-+#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-+#define IDP_ETH_SIZE (1*1024*1024)
-+
-+#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
-+#define IDP_COREVOLT_SIZE (1*1024*1024)
-+
-+#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-+#define IDP_CPLD_SIZE (1*1024*1024)
-+
-+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-+#error Your custom IO space is getting a bit large !!
-+#endif
-+
-+#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define _IDP_CPLD_LED_CONTROL (IDP_CPLD_PHYS + 0x00)
-+#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
-+#define _IDP_CPLD_CIR (IDP_CPLD_PHYS + 0x08)
-+#define _IDP_CPLD_KB_COL_HIGH (IDP_CPLD_PHYS + 0x0C)
-+#define _IDP_CPLD_KB_COL_LOW (IDP_CPLD_PHYS + 0x10)
-+#define _IDP_CPLD_PCCARD_EN (IDP_CPLD_PHYS + 0x14)
-+#define _IDP_CPLD_GPIOH_DIR (IDP_CPLD_PHYS + 0x18)
-+#define _IDP_CPLD_GPIOH_VALUE (IDP_CPLD_PHYS + 0x1C)
-+#define _IDP_CPLD_GPIOL_DIR (IDP_CPLD_PHYS + 0x20)
-+#define _IDP_CPLD_GPIOL_VALUE (IDP_CPLD_PHYS + 0x24)
-+#define _IDP_CPLD_MISC (IDP_CPLD_PHYS + 0x28)
-+#define _IDP_CPLD_PCCARD0_STATUS (IDP_CPLD_PHYS + 0x2C)
-+#define _IDP_CPLD_PCCARD1_STATUS (IDP_CPLD_PHYS + 0x30)
-+
-+/* FPGA register virtual addresses */
-+#define IDP_CPLD_LED_CONTROL __CPLD_REG(_IDP_CPLD_LED_CONTROL) /* write only */
-+#define IDP_CPLD_PERIPH_PWR __CPLD_REG(_IDP_CPLD_PERIPH_PWR) /* write only */
-+#define IDP_CPLD_CIR __CPLD_REG(_IDP_CPLD_CIR) /* write only */
-+#define IDP_CPLD_KB_COL_HIGH __CPLD_REG(_IDP_CPLD_KB_COL_HIGH) /* write only */
-+#define IDP_CPLD_KB_COL_LOW __CPLD_REG(_IDP_CPLD_KB_COL_LOW) /* write only */
-+#define IDP_CPLD_PCCARD_EN __CPLD_REG(_IDP_CPLD_PCCARD_EN) /* write only */
-+#define IDP_CPLD_GPIOH_DIR __CPLD_REG(_IDP_CPLD_GPIOH_DIR) /* write only */
-+#define IDP_CPLD_GPIOH_VALUE __CPLD_REG(_IDP_CPLD_GPIOH_VALUE) /* write only */
-+#define IDP_CPLD_GPIOL_DIR __CPLD_REG(_IDP_CPLD_GPIOL_DIR) /* write only */
-+#define IDP_CPLD_GPIOL_VALUE __CPLD_REG(_IDP_CPLD_GPIOL_VALUE) /* write only */
-+#define IDP_CPLD_MISC __CPLD_REG(_IDP_CPLD_MISC) /* read only */
-+#define IDP_CPLD_PCCARD0_STATUS __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS) /* read only */
-+#define IDP_CPLD_PCCARD1_STATUS __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS) /* read only */
-+
-+
-+#ifndef __ASSEMBLY__
-+
-+/* shadow registers for write only registers */
-+extern unsigned int idp_cpld_led_control_shadow;
-+extern unsigned int idp_cpld_periph_pwr_shadow;
-+extern unsigned int idp_cpld_cir_shadow;
-+extern unsigned int idp_cpld_kb_col_high_shadow;
-+extern unsigned int idp_cpld_kb_col_low_shadow;
-+extern unsigned int idp_cpld_pccard_en_shadow;
-+extern unsigned int idp_cpld_gpioh_dir_shadow;
-+extern unsigned int idp_cpld_gpioh_value_shadow;
-+extern unsigned int idp_cpld_gpiol_dir_shadow;
-+extern unsigned int idp_cpld_gpiol_value_shadow;
-+
-+extern unsigned int idp_control_port_shadow;
-+
-+/*
-+ * macros to write to write only register
-+ *
-+ * none of these macros are protected from
-+ * multiple drivers using them in interrupt context.
-+ */
-+
-+#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
-+{\
-+ idp_cpld_led_control_shadow = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
-+ IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-+}
-+#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
-+{\
-+ idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
-+ IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
-+}
-+#define WRITE_IDP_CPLD_CIR(value, mask) \
-+{\
-+ idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
-+ IDP_CPLD_CIR = idp_cpld_cir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
-+{\
-+ idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
-+ IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
-+}
-+#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
-+{\
-+ idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
-+ IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
-+}
-+#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
-+{\
-+ idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
-+ IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
-+{\
-+ idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
-+ IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
-+{\
-+ idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
-+ IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
-+{\
-+ idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
-+ IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
-+}
-+#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
-+{\
-+ idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
-+ IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
-+}
-+
-+#define WRITE_IDP_CONTROL_PORT(value, mask) \
-+{\
-+ idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
-+ (*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
-+}
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-+#define TOUCH_PANEL_IRQ_EGDE GPIO_FALLING_EDGE
-+
-+#define ETHERNET_IRQ IRQ_GPIO(4)
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+
-+
-+/* control port */
-+#define IDP_CONTROL_PORT_PCSLOT0_0 (1 << 0)
-+#define IDP_CONTROL_PORT_PCSLOT0_1 (1 << 1)
-+#define IDP_CONTROL_PORT_PCSLOT0_2 (1 << 2)
-+#define IDP_CONTROL_PORT_PCSLOT0_3 (1 << 3)
-+#define IDP_CONTROL_PORT_PCSLOT1_1 (1 << 4)
-+#define IDP_CONTROL_PORT_PCSLOT1_2 (1 << 5)
-+#define IDP_CONTROL_PORT_PCSLOT1_3 (1 << 6)
-+#define IDP_CONTROL_PORT_PCSLOT1_4 (1 << 7)
-+#define IDP_CONTROL_PORT_SERIAL1_EN (1 << 9)
-+#define IDP_CONTROL_PORT_SERIAL2_EN (1 << 10)
-+#define IDP_CONTROL_PORT_SERIAL3_EN (1 << 11)
-+#define IDP_CONTROL_PORT_IRDA_FIR (1 << 12)
-+#define IDP_CONTROL_PORT_IRDA_M0 (1 << 13)
-+#define IDP_CONTROL_PORT_IRDA_M1 (1 << 14)
-+#define IDP_CONTROL_PORT_I2S_PWR (1 << 15)
-+#define IDP_CONTROL_PORT_FLASH_WP (1 << 19)
-+#define IDP_CONTROL_PORT_MILL_EN (1 << 20)
-+#define IDP_CONTROL_PORT_LCD_PWR (1 << 21)
-+#define IDP_CONTROL_PORT_LCD_BKLEN (1 << 22)
-+#define IDP_CONTROL_PORT_LCD_ENAVLCD (1 << 23)
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
-+#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
-+
-+#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
-+#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
-+
-+#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
-+#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
-+
-+#endif
-+
-+
-+/*
-+ * Macros for LED Driver
-+ */
-+
-+/* leds 0 = ON */
-+#define IDP_HB_LED 0x1
-+#define IDP_BUSY_LED 0x2
-+
-+#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-+
-+#define IDP_WRITE_LEDS(value) WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
-+#define FLASH_WRITE_PROTECT_ENABLE() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/innokom.h
-@@ -0,0 +1,47 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/innokom.h
-+ *
-+ * (c) 2003 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+/*
-+ * GPIOs
-+ */
-+#define GPIO_INNOKOM_RESET 3
-+#define GPIO_INNOKOM_SW_UPDATE 11
-+#define GPIO_INNOKOM_ETH 59
-+
-+/*
-+ * ethernet chip (SMSC91C111)
-+ */
-+#define INNOKOM_ETH_PHYS PXA_CS5_PHYS
-+#define INNOKOM_ETH_BASE (0xf0000000) /* phys 0x14000000 */
-+#define INNOKOM_ETH_SIZE (1*1024*1024)
-+#define INNOKOM_ETH_IRQ IRQ_GPIO(GPIO_INNOKOM_ETH)
-+#define INNOKOM_ETH_IRQ_EDGE GPIO_RISING_EDGE
-+
-+/*
-+ * virtual to physical conversion macros
-+ */
-+#define INNOKOM_P2V(x) ((x) - INNOKOM_FPGA_PHYS + INNOKOM_FPGA_VIRT)
-+#define INNOKOM_V2P(x) ((x) - INNOKOM_FPGA_VIRT + INNOKOM_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __INNOKOM_REG(x) (*((volatile unsigned long *)INNOKOM_P2V(x)))
-+#else
-+# define __INNOKOM_REG(x) INNOKOM_P2V(x)
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/io.h
-@@ -0,0 +1,34 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/io.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __ASM_ARM_ARCH_IO_H
-+#define __ASM_ARM_ARCH_IO_H
-+
-+#define IO_SPACE_LIMIT 0xffffffff
-+
-+/*
-+ * We don't actually have real ISA nor PCI buses, but there is so many
-+ * drivers out there that might just work if we fake them...
-+ */
-+#define __io(a) (a)
-+#define __mem_pci(a) ((unsigned long)(a))
-+#define __mem_isa(a) ((unsigned long)(a))
-+
-+/*
-+ * Generic virtual read/write
-+ */
-+#define __arch_getw(a) (*(volatile unsigned short *)(a))
-+#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
-+
-+#define iomem_valid_addr(iomem,sz) (1)
-+#define iomem_to_phys(iomem) (iomem)
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/irq.h
-@@ -0,0 +1,19 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/irq.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define fixup_irq(x) (x)
-+
-+/*
-+ * This prototype is required for cascading of multiplexed interrupts.
-+ * Since it doesn't exist elsewhere, we'll put it here for now.
-+ */
-+extern void do_IRQ(int irq, struct pt_regs *regs);
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/irqs.h
-@@ -0,0 +1,137 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/irqs.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define PXA_IRQ_SKIP 7 /* The first 7 IRQs are not yet used */
-+#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
-+
-+#define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error */
-+#define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
-+#define IRQ_GPIO1 PXA_IRQ(9) /* GPIO1 Edge Detect */
-+#define IRQ_GPIO_2_80 PXA_IRQ(10) /* GPIO[2-80] Edge Detect */
-+#define IRQ_USB PXA_IRQ(11) /* USB Service */
-+#define IRQ_PMU PXA_IRQ(12) /* Performance Monitoring Unit */
-+#define IRQ_I2S PXA_IRQ(13) /* I2S Interrupt */
-+#define IRQ_AC97 PXA_IRQ(14) /* AC97 Interrupt */
-+#define IRQ_ASSP PXA_IRQ(15) /* Audio SSP Service Request */
-+#define IRQ_NSSP PXA_IRQ(16) /* Network SSP Service Request */
-+#define IRQ_LCD PXA_IRQ(17) /* LCD Controller Service Request */
-+#define IRQ_I2C PXA_IRQ(18) /* I2C Service Request */
-+#define IRQ_ICP PXA_IRQ(19) /* ICP Transmit/Receive/Error */
-+#define IRQ_STUART PXA_IRQ(20) /* STUART Transmit/Receive/Error */
-+#define IRQ_BTUART PXA_IRQ(21) /* BTUART Transmit/Receive/Error */
-+#define IRQ_FFUART PXA_IRQ(22) /* FFUART Transmit/Receive/Error*/
-+#define IRQ_MMC PXA_IRQ(23) /* MMC Status/Error Detection */
-+#define IRQ_SSP PXA_IRQ(24) /* SSP Service Request */
-+#define IRQ_DMA PXA_IRQ(25) /* DMA Channel Service Request */
-+#define IRQ_OST0 PXA_IRQ(26) /* OS Timer match 0 */
-+#define IRQ_OST1 PXA_IRQ(27) /* OS Timer match 1 */
-+#define IRQ_OST2 PXA_IRQ(28) /* OS Timer match 2 */
-+#define IRQ_OST3 PXA_IRQ(29) /* OS Timer match 3 */
-+#define IRQ_RTC1Hz PXA_IRQ(30) /* RTC HZ Clock Tick */
-+#define IRQ_RTCAlrm PXA_IRQ(31) /* RTC Alarm */
-+
-+#define GPIO_2_80_TO_IRQ(x) \
-+ PXA_IRQ((x) - 2 + 32)
-+#define IRQ_GPIO(x) (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
-+
-+#define IRQ_TO_GPIO_2_80(i) \
-+ ((i) - PXA_IRQ(32) + 2)
-+#define IRQ_TO_GPIO(i) ((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
-+
-+#define NR_IRQS (IRQ_GPIO(80) + 1)
-+
-+#if defined(CONFIG_SA1111)
-+
-+#define IRQ_SA1111_START (IRQ_GPIO(80) + 1)
-+#define SA1111_IRQ(x) (IRQ_SA1111_START + (x))
-+
-+#define IRQ_GPAIN0 SA1111_IRQ(0)
-+#define IRQ_GPAIN1 SA1111_IRQ(1)
-+#define IRQ_GPAIN2 SA1111_IRQ(2)
-+#define IRQ_GPAIN3 SA1111_IRQ(3)
-+#define IRQ_GPBIN0 SA1111_IRQ(4)
-+#define IRQ_GPBIN1 SA1111_IRQ(5)
-+#define IRQ_GPBIN2 SA1111_IRQ(6)
-+#define IRQ_GPBIN3 SA1111_IRQ(7)
-+#define IRQ_GPBIN4 SA1111_IRQ(8)
-+#define IRQ_GPBIN5 SA1111_IRQ(9)
-+#define IRQ_GPCIN0 SA1111_IRQ(10)
-+#define IRQ_GPCIN1 SA1111_IRQ(11)
-+#define IRQ_GPCIN2 SA1111_IRQ(12)
-+#define IRQ_GPCIN3 SA1111_IRQ(13)
-+#define IRQ_GPCIN4 SA1111_IRQ(14)
-+#define IRQ_GPCIN5 SA1111_IRQ(15)
-+#define IRQ_GPCIN6 SA1111_IRQ(16)
-+#define IRQ_GPCIN7 SA1111_IRQ(17)
-+#define IRQ_MSTXINT SA1111_IRQ(18)
-+#define IRQ_MSRXINT SA1111_IRQ(19)
-+#define IRQ_MSSTOPERRINT SA1111_IRQ(20)
-+#define IRQ_TPTXINT SA1111_IRQ(21)
-+#define IRQ_TPRXINT SA1111_IRQ(22)
-+#define IRQ_TPSTOPERRINT SA1111_IRQ(23)
-+#define SSPXMTINT SA1111_IRQ(24)
-+#define SSPRCVINT SA1111_IRQ(25)
-+#define SSPROR SA1111_IRQ(26)
-+#define AUDXMTDMADONEA SA1111_IRQ(32)
-+#define AUDRCVDMADONEA SA1111_IRQ(33)
-+#define AUDXMTDMADONEB SA1111_IRQ(34)
-+#define AUDRCVDMADONEB SA1111_IRQ(35)
-+#define AUDTFSR SA1111_IRQ(36)
-+#define AUDRFSR SA1111_IRQ(37)
-+#define AUDTUR SA1111_IRQ(38)
-+#define AUDROR SA1111_IRQ(39)
-+#define AUDDTS SA1111_IRQ(40)
-+#define AUDRDD SA1111_IRQ(41)
-+#define AUDSTO SA1111_IRQ(42)
-+#define USBPWR SA1111_IRQ(43)
-+#define NIRQHCIM SA1111_IRQ(44)
-+#define HCIBUFFACC SA1111_IRQ(45)
-+#define HCIRMTWKP SA1111_IRQ(46)
-+#define NHCIMFCIR SA1111_IRQ(47)
-+#define PORT_RESUME SA1111_IRQ(48)
-+#define S0_READY_NINT SA1111_IRQ(49)
-+#define S1_READY_NINT SA1111_IRQ(50)
-+#define S0_CD_VALID SA1111_IRQ(51)
-+#define S1_CD_VALID SA1111_IRQ(52)
-+#define S0_BVD1_STSCHG SA1111_IRQ(53)
-+#define S1_BVD1_STSCHG SA1111_IRQ(54)
-+
-+#define SA1111_IRQ_MAX SA1111_IRQ(54)
-+
-+#undef NR_IRQS
-+#define NR_IRQS (SA1111_IRQ_MAX + 1)
-+
-+#endif // defined(CONFIG_SA1111)
-+
-+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP)
-+#if CONFIG_SA1111
-+#define LUBBOCK_IRQ(x) (SA1111_IRQ_MAX + 1 + (x))
-+#else
-+#define LUBBOCK_IRQ(x) (IRQ_GPIO(80) + 1 + (x))
-+#endif
-+
-+#define LUBBOCK_SD_IRQ LUBBOCK_IRQ(0)
-+#define LUBBOCK_SA1111_IRQ LUBBOCK_IRQ(1)
-+#define LUBBOCK_USB_IRQ LUBBOCK_IRQ(2)
-+#define LUBBOCK_ETH_IRQ LUBBOCK_IRQ(3)
-+#define LUBBOCK_UCB1400_IRQ LUBBOCK_IRQ(4)
-+#define LUBBOCK_BB_IRQ LUBBOCK_IRQ(5)
-+#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
-+#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
-+
-+#undef NR_IRQS
-+#define NR_IRQS (LUBBOCK_LAST_IRQ + 1)
-+
-+#endif // CONFIG_ARCH_LUBBOCK
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/keyboard.h
-@@ -0,0 +1,29 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/keyboard.h
-+ *
-+ * This file contains the architecture specific keyboard definitions
-+ */
-+
-+#ifndef _PXA_KEYBOARD_H
-+#define _PXA_KEYBOARD_H
-+
-+#include <linux/config.h>
-+#include <asm/mach-types.h>
-+#include <asm/hardware.h>
-+
-+extern struct kbd_ops_struct *kbd_ops;
-+
-+#define kbd_disable_irq() do { } while(0);
-+#define kbd_enable_irq() do { } while(0);
-+
-+extern int sa1111_kbd_init_hw(void);
-+
-+static inline void kbd_init_hw(void)
-+{
-+ if (machine_is_lubbock())
-+ sa1111_kbd_init_hw();
-+}
-+
-+
-+#endif /* _PXA_KEYBOARD_H */
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/lubbock.h
-@@ -0,0 +1,113 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/lubbock.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define LUBBOCK_FPGA_PHYS PXA_CS2_PHYS
-+#define LUBBOCK_FPGA_VIRT (0xf0000000) /* phys 0x08000000 */
-+#define LUBBOCK_ETH_PHYS PXA_CS3_PHYS
-+#define LUBBOCK_ETH_VIRT (0xf1000000)
-+#define LUBBOCK_SA1111_BASE (0xf4000000) /* phys 0x10000000 */
-+
-+#define LUB_P2V(x) ((x) - LUBBOCK_FPGA_PHYS + LUBBOCK_FPGA_VIRT)
-+#define LUB_V2P(x) ((x) - LUBBOCK_FPGA_VIRT + LUBBOCK_FPGA_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __LUB_REG(x) (*((volatile unsigned long *)LUB_P2V(x)))
-+#else
-+# define __LUB_REG(x) LUB_P2V(x)
-+#endif
-+
-+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-+
-+#define WHOAMI 0 // card ID's (see programmers manual)
-+#define HEX_LED 0x10 // R/W access to 8 7 segment displays
-+#define DISC_BLNK_LED 0x40 // R/W [15-8] enables for hex leds, [7-0] discrete LEDs
-+#define CONF_SWITCHES 0x50 // RO [1] flash wrt prot, [0] 0= boot from rom, 1= flash
-+#define USER_SWITCHES 0x60 // RO [15-8] dip switches, [7-0] 2 hex encoding switches
-+#define MISC_WR 0x80 // R/W various system controls -see manual
-+#define MISC_RD 0x90 // RO various system status bits -see manual
-+//#define LUB_IRQ_MASK_EN 0xC0 // R/W 0= mask, 1= enable of TS, codec, ethernet, USB, SA1111, and card det. irq's
-+//#define LUB_IRQ_SET_CLR 0xD0 // R/W 1= set, 0 = clear IRQ's from TS, codec, etc...
-+//#define LUB_GP 0x100 // R/W [15-0] 16 bits of general purpose I/o for hacking
-+
-+
-+/* FPGA register physical addresses */
-+#define _LUB_WHOAMI (LUBBOCK_FPGA_PHYS + 0x000)
-+#define _LUB_HEXLED (LUBBOCK_FPGA_PHYS + 0x010)
-+#define _LUB_DISC_BLNK_LED (LUBBOCK_FPGA_PHYS + 0x040)
-+#define _LUB_CONF_SWITCHES (LUBBOCK_FPGA_PHYS + 0x050)
-+#define _LUB_USER_SWITCHES (LUBBOCK_FPGA_PHYS + 0x060)
-+#define _LUB_MISC_WR (LUBBOCK_FPGA_PHYS + 0x080)
-+#define _LUB_MISC_RD (LUBBOCK_FPGA_PHYS + 0x090)
-+#define _LUB_IRQ_MASK_EN (LUBBOCK_FPGA_PHYS + 0x0C0)
-+#define _LUB_IRQ_SET_CLR (LUBBOCK_FPGA_PHYS + 0x0D0)
-+#define _LUB_GP (LUBBOCK_FPGA_PHYS + 0x100)
-+
-+/* FPGA register virtual addresses */
-+#define LUB_WHOAMI __LUB_REG(_LUB_WHOAMI)
-+#define LUB_HEXLED __LUB_REG(_LUB_HEXLED)
-+#define LUB_DISC_BLNK_LED __LUB_REG(_LUB_DISC_BLNK_LED)
-+#define LUB_CONF_SWITCHES __LUB_REG(_LUB_CONF_SWITCHES)
-+#define LUB_USER_SWITCHES __LUB_REG(_LUB_USER_SWITCHES)
-+#define LUB_MISC_WR __LUB_REG(_LUB_MISC_WR)
-+#define LUB_MISC_RD __LUB_REG(_LUB_MISC_RD)
-+#define LUB_IRQ_MASK_EN __LUB_REG(_LUB_IRQ_MASK_EN)
-+#define LUB_IRQ_SET_CLR __LUB_REG(_LUB_IRQ_SET_CLR)
-+#define LUB_GP __LUB_REG(_LUB_GP)
-+
-+/* GPIOs */
-+
-+#define GPIO_LUBBOCK_IRQ 0
-+#define IRQ_GPIO_LUBBOCK_IRQ IRQ_GPIO0
-+
-+
-+/*
-+ * LED macros
-+ */
-+
-+#define LEDS_BASE LUB_DISC_BLNK_LED
-+
-+// 8 discrete leds available for general use:
-+
-+#define D28 0x1
-+#define D27 0x2
-+#define D26 0x4
-+#define D25 0x8
-+#define D24 0x10
-+#define D23 0x20
-+#define D22 0x40
-+#define D21 0x80
-+
-+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
-+* be sure to not monkey with them here.
-+*/
-+
-+#define HEARTBEAT_LED D28
-+#define SYS_BUSY_LED D27
-+#define HEXLEDS_BASE LUB_HEXLED
-+
-+#define HEARTBEAT_LED_ON (LEDS_BASE &= ~HEARTBEAT_LED)
-+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
-+#define SYS_BUSY_LED_OFF (LEDS_BASE |= SYS_BUSY_LED)
-+#define SYS_BUSY_LED_ON (LEDS_BASE &= ~SYS_BUSY_LED)
-+
-+// use x = D26-D21 for these, please...
-+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
-+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
-+
-+#ifndef __ASSEMBLY__
-+
-+//extern int hexled_val = 0;
-+
-+#endif
-+
-+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
-+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/memory.h
-@@ -0,0 +1,106 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/memory.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef __ASM_ARCH_MEMORY_H
-+#define __ASM_ARCH_MEMORY_H
-+
-+
-+/*
-+ * Task size: 3GB
-+ */
-+#define TASK_SIZE (0xc0000000UL)
-+#define TASK_SIZE_26 (0x04000000UL)
-+
-+/*
-+ * This decides where the kernel will search for a free chunk of vm
-+ * space during mmap's.
-+ */
-+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-+
-+/*
-+ * Page offset: 3GB
-+ */
-+#define PAGE_OFFSET (0xc0000000UL)
-+
-+/*
-+ * Physical DRAM offset.
-+ */
-+#define PHYS_OFFSET (0xa0000000UL)
-+
-+/*
-+ * physical vs virtual ram conversion
-+ */
-+#define __virt_to_phys__is_a_macro
-+#define __phys_to_virt__is_a_macro
-+#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
-+#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
-+
-+/*
-+ * Virtual view <-> DMA view memory address translations
-+ * virt_to_bus: Used to translate the virtual address to an
-+ * address suitable to be passed to set_dma_addr
-+ * bus_to_virt: Used to convert an address for DMA operations
-+ * to an address that the kernel can use.
-+ */
-+#define __virt_to_bus__is_a_macro
-+#define __bus_to_virt__is_a_macro
-+#define __virt_to_bus(x) __virt_to_phys(x)
-+#define __bus_to_virt(x) __phys_to_virt(x)
-+
-+#ifdef CONFIG_DISCONTIGMEM
-+/*
-+ * The nodes are matched with the physical SDRAM banks as follows:
-+ *
-+ * node 0: 0xa0000000-0xa3ffffff --> 0xc0000000-0xc3ffffff
-+ * node 1: 0xa4000000-0xa7ffffff --> 0xc4000000-0xc7ffffff
-+ * node 2: 0xa8000000-0xabffffff --> 0xc8000000-0xcbffffff
-+ * node 3: 0xac000000-0xafffffff --> 0xcc000000-0xcfffffff
-+ */
-+
-+#define NR_NODES 4
-+
-+/*
-+ * Given a kernel address, find the home node of the underlying memory.
-+ */
-+#define KVADDR_TO_NID(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> 26)
-+
-+/*
-+ * Given a page frame number, convert it to a node id.
-+ */
-+#define PFN_TO_NID(pfn) (((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
-+
-+/*
-+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
-+ * and returns the mem_map of that node.
-+ */
-+#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
-+
-+/*
-+ * Given a page frame number, find the owning node of the memory
-+ * and returns the mem_map of that node.
-+ */
-+#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
-+
-+/*
-+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
-+ * and returns the index corresponding to the appropriate page in the
-+ * node's mem_map.
-+ */
-+#define LOCAL_MAP_NR(addr) \
-+ (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
-+
-+#else
-+
-+#define PFN_TO_NID(addr) (0)
-+
-+#endif
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/param.h
-@@ -0,0 +1,3 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/param.h
-+ */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/pcmcia.h
-@@ -0,0 +1,65 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/pcmcia.h
-+ *
-+ * Author: George Davis
-+ * Created: Jan 10, 2002
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ * Originally based upon linux/include/asm-arm/arch-sa1100/pcmcia.h
-+ *
-+ */
-+
-+#ifndef _ASM_ARCH_PCMCIA
-+#define _ASM_ARCH_PCMCIA
-+
-+
-+/* Ideally, we'd support up to MAX_SOCK sockets, but PXA250 only
-+ * provides support for a maximum of two.
-+ */
-+#define PXA_PCMCIA_MAX_SOCK (2)
-+
-+
-+#ifndef __ASSEMBLY__
-+
-+struct pcmcia_init {
-+ void (*handler)(int irq, void *dev, struct pt_regs *regs);
-+};
-+
-+struct pcmcia_state {
-+ unsigned detect: 1,
-+ ready: 1,
-+ bvd1: 1,
-+ bvd2: 1,
-+ wrprot: 1,
-+ vs_3v: 1,
-+ vs_Xv: 1;
-+};
-+
-+struct pcmcia_state_array {
-+ unsigned int size;
-+ struct pcmcia_state *state;
-+};
-+
-+struct pcmcia_irq_info {
-+ unsigned int sock;
-+ unsigned int irq;
-+};
-+
-+struct pcmcia_low_level {
-+ int (*init)(struct pcmcia_init *);
-+ int (*shutdown)(void);
-+ int (*socket_state)(struct pcmcia_state_array *);
-+ int (*get_irq_info)(struct pcmcia_irq_info *);
-+ int (*configure_socket)(unsigned int, socket_state_t *);
-+};
-+
-+extern struct pcmcia_low_level *pcmcia_low_level;
-+
-+#endif /* __ASSEMBLY__ */
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/pxa-regs.h
-@@ -0,0 +1,1327 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/pxa-regs.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef _PXA_REGS_H_
-+#define _PXA_REGS_H_
-+
-+#include "bitfield.h"
-+
-+
-+// FIXME hack so that SA-1111.h will work [cb]
-+
-+#ifndef __ASSEMBLY__
-+typedef unsigned short Word16 ;
-+typedef unsigned int Word32 ;
-+typedef Word32 Word ;
-+typedef Word Quad [4] ;
-+typedef void *Address ;
-+typedef void (*ExcpHndlr) (void) ;
-+#endif
-+
-+/*
-+ * PXA Chip selects
-+ */
-+
-+#define PXA_CS0_PHYS 0x00000000
-+#define PXA_CS1_PHYS 0x04000000
-+#define PXA_CS2_PHYS 0x08000000
-+#define PXA_CS3_PHYS 0x0C000000
-+#define PXA_CS4_PHYS 0x10000000
-+#define PXA_CS5_PHYS 0x14000000
-+
-+
-+/*
-+ * Personal Computer Memory Card International Association (PCMCIA) sockets
-+ */
-+
-+#define PCMCIAPrtSp 0x04000000 /* PCMCIA Partition Space [byte] */
-+#define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */
-+#define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */
-+#define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */
-+#define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */
-+
-+#define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */
-+#define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */
-+#define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */
-+#define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */
-+
-+#define PCMCIA1Sp PCMCIASp /* PCMCIA 1 Space [byte] */
-+#define PCMCIA1IOSp PCMCIAIOSp /* PCMCIA 1 I/O Space [byte] */
-+#define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */
-+#define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */
-+
-+#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \
-+ (0x20000000 + (Nb)*PCMCIASp)
-+#define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */
-+#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \
-+ (_PCMCIA (Nb) + 2*PCMCIAPrtSp)
-+#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \
-+ (_PCMCIA (Nb) + 3*PCMCIAPrtSp)
-+
-+#define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */
-+#define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */
-+#define _PCMCIA0Attr _PCMCIAAttr (0) /* PCMCIA 0 Attribute */
-+#define _PCMCIA0Mem _PCMCIAMem (0) /* PCMCIA 0 Memory */
-+
-+#define _PCMCIA1 _PCMCIA (1) /* PCMCIA 1 */
-+#define _PCMCIA1IO _PCMCIAIO (1) /* PCMCIA 1 I/O */
-+#define _PCMCIA1Attr _PCMCIAAttr (1) /* PCMCIA 1 Attribute */
-+#define _PCMCIA1Mem _PCMCIAMem (1) /* PCMCIA 1 Memory */
-+
-+
-+
-+/*
-+ * DMA Controller
-+ */
-+
-+#define DCSR0 __REG(0x40000000) /* DMA Control / Status Register for Channel 0 */
-+#define DCSR1 __REG(0x40000004) /* DMA Control / Status Register for Channel 1 */
-+#define DCSR2 __REG(0x40000008) /* DMA Control / Status Register for Channel 2 */
-+#define DCSR3 __REG(0x4000000c) /* DMA Control / Status Register for Channel 3 */
-+#define DCSR4 __REG(0x40000010) /* DMA Control / Status Register for Channel 4 */
-+#define DCSR5 __REG(0x40000014) /* DMA Control / Status Register for Channel 5 */
-+#define DCSR6 __REG(0x40000018) /* DMA Control / Status Register for Channel 6 */
-+#define DCSR7 __REG(0x4000001c) /* DMA Control / Status Register for Channel 7 */
-+#define DCSR8 __REG(0x40000020) /* DMA Control / Status Register for Channel 8 */
-+#define DCSR9 __REG(0x40000024) /* DMA Control / Status Register for Channel 9 */
-+#define DCSR10 __REG(0x40000028) /* DMA Control / Status Register for Channel 10 */
-+#define DCSR11 __REG(0x4000002c) /* DMA Control / Status Register for Channel 11 */
-+#define DCSR12 __REG(0x40000030) /* DMA Control / Status Register for Channel 12 */
-+#define DCSR13 __REG(0x40000034) /* DMA Control / Status Register for Channel 13 */
-+#define DCSR14 __REG(0x40000038) /* DMA Control / Status Register for Channel 14 */
-+#define DCSR15 __REG(0x4000003c) /* DMA Control / Status Register for Channel 15 */
-+
-+#define DCSR(x) __REG2(0x40000000, (x) << 2)
-+
-+#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */
-+#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */
-+#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */
-+#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */
-+#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */
-+#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */
-+#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */
-+#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */
-+
-+#define DINT __REG(0x400000f0) /* DMA Interrupt Register */
-+
-+#define DRCMR0 __REG(0x40000100) /* Request to Channel Map Register for DREQ 0 */
-+#define DRCMR1 __REG(0x40000104) /* Request to Channel Map Register for DREQ 1 */
-+#define DRCMR2 __REG(0x40000108) /* Request to Channel Map Register for I2S receive Request */
-+#define DRCMR3 __REG(0x4000010c) /* Request to Channel Map Register for I2S transmit Request */
-+#define DRCMR4 __REG(0x40000110) /* Request to Channel Map Register for BTUART receive Request */
-+#define DRCMR5 __REG(0x40000114) /* Request to Channel Map Register for BTUART transmit Request. */
-+#define DRCMR6 __REG(0x40000118) /* Request to Channel Map Register for FFUART receive Request */
-+#define DRCMR7 __REG(0x4000011c) /* Request to Channel Map Register for FFUART transmit Request */
-+#define DRCMR8 __REG(0x40000120) /* Request to Channel Map Register for AC97 microphone Request */
-+#define DRCMR9 __REG(0x40000124) /* Request to Channel Map Register for AC97 modem receive Request */
-+#define DRCMR10 __REG(0x40000128) /* Request to Channel Map Register for AC97 modem transmit Request */
-+#define DRCMR11 __REG(0x4000012c) /* Request to Channel Map Register for AC97 audio receive Request */
-+#define DRCMR12 __REG(0x40000130) /* Request to Channel Map Register for AC97 audio transmit Request */
-+#define DRCMR13 __REG(0x40000134) /* Request to Channel Map Register for SSP receive Request */
-+#define DRCMR14 __REG(0x40000138) /* Request to Channel Map Register for SSP transmit Request */
-+#define DRCMR15 __REG(0x4000013c) /* Reserved */
-+#define DRCMR16 __REG(0x40000140) /* Reserved */
-+#define DRCMR17 __REG(0x40000144) /* Request to Channel Map Register for ICP receive Request */
-+#define DRCMR18 __REG(0x40000148) /* Request to Channel Map Register for ICP transmit Request */
-+#define DRCMR19 __REG(0x4000014c) /* Request to Channel Map Register for STUART receive Request */
-+#define DRCMR20 __REG(0x40000150) /* Request to Channel Map Register for STUART transmit Request */
-+#define DRCMR21 __REG(0x40000154) /* Request to Channel Map Register for MMC receive Request */
-+#define DRCMR22 __REG(0x40000158) /* Request to Channel Map Register for MMC transmit Request */
-+#define DRCMR23 __REG(0x4000015c) /* Reserved */
-+#define DRCMR24 __REG(0x40000160) /* Reserved */
-+#define DRCMR25 __REG(0x40000164) /* Request to Channel Map Register for USB endpoint 1 Request */
-+#define DRCMR26 __REG(0x40000168) /* Request to Channel Map Register for USB endpoint 2 Request */
-+#define DRCMR27 __REG(0x4000016C) /* Request to Channel Map Register for USB endpoint 3 Request */
-+#define DRCMR28 __REG(0x40000170) /* Request to Channel Map Register for USB endpoint 4 Request */
-+#define DRCMR29 __REG(0x40000174) /* Reserved */
-+#define DRCMR30 __REG(0x40000178) /* Request to Channel Map Register for USB endpoint 6 Request */
-+#define DRCMR31 __REG(0x4000017C) /* Request to Channel Map Register for USB endpoint 7 Request */
-+#define DRCMR32 __REG(0x40000180) /* Request to Channel Map Register for USB endpoint 8 Request */
-+#define DRCMR33 __REG(0x40000184) /* Request to Channel Map Register for USB endpoint 9 Request */
-+#define DRCMR34 __REG(0x40000188) /* Reserved */
-+#define DRCMR35 __REG(0x4000018C) /* Request to Channel Map Register for USB endpoint 11 Request */
-+#define DRCMR36 __REG(0x40000190) /* Request to Channel Map Register for USB endpoint 12 Request */
-+#define DRCMR37 __REG(0x40000194) /* Request to Channel Map Register for USB endpoint 13 Request */
-+#define DRCMR38 __REG(0x40000198) /* Request to Channel Map Register for USB endpoint 14 Request */
-+#define DRCMR39 __REG(0x4000019C) /* Reserved */
-+
-+#define DRCMRRXSADR DRCMR2
-+#define DRCMRTXSADR DRCMR3
-+#define DRCMRRXBTRBR DRCMR4
-+#define DRCMRTXBTTHR DRCMR5
-+#define DRCMRRXFFRBR DRCMR6
-+#define DRCMRTXFFTHR DRCMR7
-+#define DRCMRRXMCDR DRCMR8
-+#define DRCMRRXMODR DRCMR9
-+#define DRCMRTXMODR DRCMR10
-+#define DRCMRRXPCDR DRCMR11
-+#define DRCMRTXPCDR DRCMR12
-+#define DRCMRRXSSDR DRCMR13
-+#define DRCMRTXSSDR DRCMR14
-+#define DRCMRRXICDR DRCMR17
-+#define DRCMRTXICDR DRCMR18
-+#define DRCMRRXSTRBR DRCMR19
-+#define DRCMRTXSTTHR DRCMR20
-+#define DRCMRRXMMC DRCMR21
-+#define DRCMRTXMMC DRCMR22
-+
-+#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */
-+#define DRCMR_CHLNUM 0x0f /* mask for Channel Number (read / write) */
-+
-+#define DDADR0 __REG(0x40000200) /* DMA Descriptor Address Register Channel 0 */
-+#define DSADR0 __REG(0x40000204) /* DMA Source Address Register Channel 0 */
-+#define DTADR0 __REG(0x40000208) /* DMA Target Address Register Channel 0 */
-+#define DCMD0 __REG(0x4000020c) /* DMA Command Address Register Channel 0 */
-+#define DDADR1 __REG(0x40000210) /* DMA Descriptor Address Register Channel 1 */
-+#define DSADR1 __REG(0x40000214) /* DMA Source Address Register Channel 1 */
-+#define DTADR1 __REG(0x40000218) /* DMA Target Address Register Channel 1 */
-+#define DCMD1 __REG(0x4000021c) /* DMA Command Address Register Channel 1 */
-+#define DDADR2 __REG(0x40000220) /* DMA Descriptor Address Register Channel 2 */
-+#define DSADR2 __REG(0x40000224) /* DMA Source Address Register Channel 2 */
-+#define DTADR2 __REG(0x40000228) /* DMA Target Address Register Channel 2 */
-+#define DCMD2 __REG(0x4000022c) /* DMA Command Address Register Channel 2 */
-+#define DDADR3 __REG(0x40000230) /* DMA Descriptor Address Register Channel 3 */
-+#define DSADR3 __REG(0x40000234) /* DMA Source Address Register Channel 3 */
-+#define DTADR3 __REG(0x40000238) /* DMA Target Address Register Channel 3 */
-+#define DCMD3 __REG(0x4000023c) /* DMA Command Address Register Channel 3 */
-+#define DDADR4 __REG(0x40000240) /* DMA Descriptor Address Register Channel 4 */
-+#define DSADR4 __REG(0x40000244) /* DMA Source Address Register Channel 4 */
-+#define DTADR4 __REG(0x40000248) /* DMA Target Address Register Channel 4 */
-+#define DCMD4 __REG(0x4000024c) /* DMA Command Address Register Channel 4 */
-+#define DDADR5 __REG(0x40000250) /* DMA Descriptor Address Register Channel 5 */
-+#define DSADR5 __REG(0x40000254) /* DMA Source Address Register Channel 5 */
-+#define DTADR5 __REG(0x40000258) /* DMA Target Address Register Channel 5 */
-+#define DCMD5 __REG(0x4000025c) /* DMA Command Address Register Channel 5 */
-+#define DDADR6 __REG(0x40000260) /* DMA Descriptor Address Register Channel 6 */
-+#define DSADR6 __REG(0x40000264) /* DMA Source Address Register Channel 6 */
-+#define DTADR6 __REG(0x40000268) /* DMA Target Address Register Channel 6 */
-+#define DCMD6 __REG(0x4000026c) /* DMA Command Address Register Channel 6 */
-+#define DDADR7 __REG(0x40000270) /* DMA Descriptor Address Register Channel 7 */
-+#define DSADR7 __REG(0x40000274) /* DMA Source Address Register Channel 7 */
-+#define DTADR7 __REG(0x40000278) /* DMA Target Address Register Channel 7 */
-+#define DCMD7 __REG(0x4000027c) /* DMA Command Address Register Channel 7 */
-+#define DDADR8 __REG(0x40000280) /* DMA Descriptor Address Register Channel 8 */
-+#define DSADR8 __REG(0x40000284) /* DMA Source Address Register Channel 8 */
-+#define DTADR8 __REG(0x40000288) /* DMA Target Address Register Channel 8 */
-+#define DCMD8 __REG(0x4000028c) /* DMA Command Address Register Channel 8 */
-+#define DDADR9 __REG(0x40000290) /* DMA Descriptor Address Register Channel 9 */
-+#define DSADR9 __REG(0x40000294) /* DMA Source Address Register Channel 9 */
-+#define DTADR9 __REG(0x40000298) /* DMA Target Address Register Channel 9 */
-+#define DCMD9 __REG(0x4000029c) /* DMA Command Address Register Channel 9 */
-+#define DDADR10 __REG(0x400002a0) /* DMA Descriptor Address Register Channel 10 */
-+#define DSADR10 __REG(0x400002a4) /* DMA Source Address Register Channel 10 */
-+#define DTADR10 __REG(0x400002a8) /* DMA Target Address Register Channel 10 */
-+#define DCMD10 __REG(0x400002ac) /* DMA Command Address Register Channel 10 */
-+#define DDADR11 __REG(0x400002b0) /* DMA Descriptor Address Register Channel 11 */
-+#define DSADR11 __REG(0x400002b4) /* DMA Source Address Register Channel 11 */
-+#define DTADR11 __REG(0x400002b8) /* DMA Target Address Register Channel 11 */
-+#define DCMD11 __REG(0x400002bc) /* DMA Command Address Register Channel 11 */
-+#define DDADR12 __REG(0x400002c0) /* DMA Descriptor Address Register Channel 12 */
-+#define DSADR12 __REG(0x400002c4) /* DMA Source Address Register Channel 12 */
-+#define DTADR12 __REG(0x400002c8) /* DMA Target Address Register Channel 12 */
-+#define DCMD12 __REG(0x400002cc) /* DMA Command Address Register Channel 12 */
-+#define DDADR13 __REG(0x400002d0) /* DMA Descriptor Address Register Channel 13 */
-+#define DSADR13 __REG(0x400002d4) /* DMA Source Address Register Channel 13 */
-+#define DTADR13 __REG(0x400002d8) /* DMA Target Address Register Channel 13 */
-+#define DCMD13 __REG(0x400002dc) /* DMA Command Address Register Channel 13 */
-+#define DDADR14 __REG(0x400002e0) /* DMA Descriptor Address Register Channel 14 */
-+#define DSADR14 __REG(0x400002e4) /* DMA Source Address Register Channel 14 */
-+#define DTADR14 __REG(0x400002e8) /* DMA Target Address Register Channel 14 */
-+#define DCMD14 __REG(0x400002ec) /* DMA Command Address Register Channel 14 */
-+#define DDADR15 __REG(0x400002f0) /* DMA Descriptor Address Register Channel 15 */
-+#define DSADR15 __REG(0x400002f4) /* DMA Source Address Register Channel 15 */
-+#define DTADR15 __REG(0x400002f8) /* DMA Target Address Register Channel 15 */
-+#define DCMD15 __REG(0x400002fc) /* DMA Command Address Register Channel 15 */
-+
-+#define DDADR(x) __REG2(0x40000200, (x) << 4)
-+#define DSADR(x) __REG2(0x40000204, (x) << 4)
-+#define DTADR(x) __REG2(0x40000208, (x) << 4)
-+#define DCMD(x) __REG2(0x4000020c, (x) << 4)
-+
-+#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */
-+#define DDADR_STOP (1 << 0) /* Stop (read / write) */
-+
-+#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */
-+#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */
-+#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */
-+#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */
-+#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */
-+#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */
-+#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */
-+#define DCMD_BURST8 (1 << 16) /* 8 byte burst */
-+#define DCMD_BURST16 (2 << 16) /* 16 byte burst */
-+#define DCMD_BURST32 (3 << 16) /* 32 byte burst */
-+#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */
-+#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */
-+#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */
-+#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
-+
-+/* default combinations */
-+#define DCMD_RXPCDR (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
-+#define DCMD_RXMCDR (DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
-+#define DCMD_TXPCDR (DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
-+
-+
-+/*
-+ * UARTs
-+ */
-+
-+/* Full Function UART (FFUART) */
-+#define FFUART FFRBR
-+#define FFRBR __REG(0x40100000) /* Receive Buffer Register (read only) */
-+#define FFTHR __REG(0x40100000) /* Transmit Holding Register (write only) */
-+#define FFIER __REG(0x40100004) /* Interrupt Enable Register (read/write) */
-+#define FFIIR __REG(0x40100008) /* Interrupt ID Register (read only) */
-+#define FFFCR __REG(0x40100008) /* FIFO Control Register (write only) */
-+#define FFLCR __REG(0x4010000C) /* Line Control Register (read/write) */
-+#define FFMCR __REG(0x40100010) /* Modem Control Register (read/write) */
-+#define FFLSR __REG(0x40100014) /* Line Status Register (read only) */
-+#define FFMSR __REG(0x40100018) /* Modem Status Register (read only) */
-+#define FFSPR __REG(0x4010001C) /* Scratch Pad Register (read/write) */
-+#define FFISR __REG(0x40100020) /* Infrared Selection Register (read/write) */
-+#define FFDLL __REG(0x40100000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define FFDLH __REG(0x40100004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+/* Bluetooth UART (BTUART) */
-+#define BTUART BTRBR
-+#define BTRBR __REG(0x40200000) /* Receive Buffer Register (read only) */
-+#define BTTHR __REG(0x40200000) /* Transmit Holding Register (write only) */
-+#define BTIER __REG(0x40200004) /* Interrupt Enable Register (read/write) */
-+#define BTIIR __REG(0x40200008) /* Interrupt ID Register (read only) */
-+#define BTFCR __REG(0x40200008) /* FIFO Control Register (write only) */
-+#define BTLCR __REG(0x4020000C) /* Line Control Register (read/write) */
-+#define BTMCR __REG(0x40200010) /* Modem Control Register (read/write) */
-+#define BTLSR __REG(0x40200014) /* Line Status Register (read only) */
-+#define BTMSR __REG(0x40200018) /* Modem Status Register (read only) */
-+#define BTSPR __REG(0x4020001C) /* Scratch Pad Register (read/write) */
-+#define BTISR __REG(0x40200020) /* Infrared Selection Register (read/write) */
-+#define BTDLL __REG(0x40200000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define BTDLH __REG(0x40200004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+/* Standard UART (STUART) */
-+#define STUART STRBR
-+#define STRBR __REG(0x40700000) /* Receive Buffer Register (read only) */
-+#define STTHR __REG(0x40700000) /* Transmit Holding Register (write only) */
-+#define STIER __REG(0x40700004) /* Interrupt Enable Register (read/write) */
-+#define STIIR __REG(0x40700008) /* Interrupt ID Register (read only) */
-+#define STFCR __REG(0x40700008) /* FIFO Control Register (write only) */
-+#define STLCR __REG(0x4070000C) /* Line Control Register (read/write) */
-+#define STMCR __REG(0x40700010) /* Modem Control Register (read/write) */
-+#define STLSR __REG(0x40700014) /* Line Status Register (read only) */
-+#define STMSR __REG(0x40700018) /* Reserved */
-+#define STSPR __REG(0x4070001C) /* Scratch Pad Register (read/write) */
-+#define STISR __REG(0x40700020) /* Infrared Selection Register (read/write) */
-+#define STDLL __REG(0x40700000) /* Divisor Latch Low Register (DLAB = 1) (read/write) */
-+#define STDLH __REG(0x40700004) /* Divisor Latch High Register (DLAB = 1) (read/write) */
-+
-+#define IER_DMAE (1 << 7) /* DMA Requests Enable */
-+#define IER_UUE (1 << 6) /* UART Unit Enable */
-+#define IER_NRZE (1 << 5) /* NRZ coding Enable */
-+#define IER_RTIOE (1 << 4) /* Receiver Time Out Interrupt Enable */
-+#define IER_MIE (1 << 3) /* Modem Interrupt Enable */
-+#define IER_RLSE (1 << 2) /* Receiver Line Status Interrupt Enable */
-+#define IER_TIE (1 << 1) /* Transmit Data request Interrupt Enable */
-+#define IER_RAVIE (1 << 0) /* Receiver Data Available Interrupt Enable */
-+
-+#define IIR_FIFOES1 (1 << 7) /* FIFO Mode Enable Status */
-+#define IIR_FIFOES0 (1 << 6) /* FIFO Mode Enable Status */
-+#define IIR_TOD (1 << 3) /* Time Out Detected */
-+#define IIR_IID2 (1 << 2) /* Interrupt Source Encoded */
-+#define IIR_IID1 (1 << 1) /* Interrupt Source Encoded */
-+#define IIR_IP (1 << 0) /* Interrupt Pending (active low) */
-+
-+#define FCR_ITL2 (1 << 7) /* Interrupt Trigger Level */
-+#define FCR_ITL1 (1 << 6) /* Interrupt Trigger Level */
-+#define FCR_RESETTF (1 << 2) /* Reset Transmitter FIFO */
-+#define FCR_RESETRF (1 << 1) /* Reset Receiver FIFO */
-+#define FCR_TRFIFOE (1 << 0) /* Transmit and Receive FIFO Enable */
-+#define FCR_ITL_1 (0)
-+#define FCR_ITL_8 (FCR_ITL1)
-+#define FCR_ITL_16 (FCR_ITL2)
-+#define FCR_ITL_32 (FCR_ITL2|FCR_ITL1)
-+
-+#define LCR_DLAB (1 << 7) /* Divisor Latch Access Bit */
-+#define LCR_SB (1 << 6) /* Set Break */
-+#define LCR_STKYP (1 << 5) /* Sticky Parity */
-+#define LCR_EPS (1 << 4) /* Even Parity Select */
-+#define LCR_PEN (1 << 3) /* Parity Enable */
-+#define LCR_STB (1 << 2) /* Stop Bit */
-+#define LCR_WLS1 (1 << 1) /* Word Length Select */
-+#define LCR_WLS0 (1 << 0) /* Word Length Select */
-+
-+#define LSR_FIFOE (1 << 7) /* FIFO Error Status */
-+#define LSR_TEMT (1 << 6) /* Transmitter Empty */
-+#define LSR_TDRQ (1 << 5) /* Transmit Data Request */
-+#define LSR_BI (1 << 4) /* Break Interrupt */
-+#define LSR_FE (1 << 3) /* Framing Error */
-+#define LSR_PE (1 << 2) /* Parity Error */
-+#define LSR_OE (1 << 1) /* Overrun Error */
-+#define LSR_DR (1 << 0) /* Data Ready */
-+
-+#define MCR_LOOP (1 << 4) */
-+#define MCR_OUT2 (1 << 3) /* force MSR_DCD in loopback mode */
-+#define MCR_OUT1 (1 << 2) /* force MSR_RI in loopback mode */
-+#define MCR_RTS (1 << 1) /* Request to Send */
-+#define MCR_DTR (1 << 0) /* Data Terminal Ready */
-+
-+#define MSR_DCD (1 << 7) /* Data Carrier Detect */
-+#define MSR_RI (1 << 6) /* Ring Indicator */
-+#define MSR_DSR (1 << 5) /* Data Set Ready */
-+#define MSR_CTS (1 << 4) /* Clear To Send */
-+#define MSR_DDCD (1 << 3) /* Delta Data Carrier Detect */
-+#define MSR_TERI (1 << 2) /* Trailing Edge Ring Indicator */
-+#define MSR_DDSR (1 << 1) /* Delta Data Set Ready */
-+#define MSR_DCTS (1 << 0) /* Delta Clear To Send */
-+
-+/*
-+ * IrSR (Infrared Selection Register)
-+ */
-+#define STISR_RXPL (1 << 4) /* Receive Data Polarity */
-+#define STISR_TXPL (1 << 3) /* Transmit Data Polarity */
-+#define STISR_XMODE (1 << 2) /* Transmit Pulse Width Select */
-+#define STISR_RCVEIR (1 << 1) /* Receiver SIR Enable */
-+#define STISR_XMITIR (1 << 0) /* Transmitter SIR Enable */
-+
-+
-+/*
-+ * I2C registers
-+ */
-+
-+#define IBMR __REG(0x40301680) /* I2C Bus Monitor Register - IBMR */
-+#define IDBR __REG(0x40301688) /* I2C Data Buffer Register - IDBR */
-+#define ICR __REG(0x40301690) /* I2C Control Register - ICR */
-+#define ISR __REG(0x40301698) /* I2C Status Register - ISR */
-+#define ISAR __REG(0x403016A0) /* I2C Slave Address Register - ISAR */
-+
-+#define ICR_START (1 << 0) /* start bit */
-+#define ICR_STOP (1 << 1) /* stop bit */
-+#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */
-+#define ICR_TB (1 << 3) /* transfer byte bit */
-+#define ICR_MA (1 << 4) /* master abort */
-+#define ICR_SCLE (1 << 5) /* master clock enable */
-+#define ICR_IUE (1 << 6) /* unit enable */
-+#define ICR_GCD (1 << 7) /* general call disable */
-+#define ICR_ITEIE (1 << 8) /* enable tx interrupts */
-+#define ICR_IRFIE (1 << 9) /* enable rx interrupts */
-+#define ICR_BEIE (1 << 10) /* enable bus error ints */
-+#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */
-+#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */
-+#define ICR_SADIE (1 << 13) /* slave address detected int enable */
-+#define ICR_UR (1 << 14) /* unit reset */
-+
-+#define ISR_RWM (1 << 0) /* read/write mode */
-+#define ISR_ACKNAK (1 << 1) /* ack/nak status */
-+#define ISR_UB (1 << 2) /* unit busy */
-+#define ISR_IBB (1 << 3) /* bus busy */
-+#define ISR_SSD (1 << 4) /* slave stop detected */
-+#define ISR_ALD (1 << 5) /* arbitration loss detected */
-+#define ISR_ITE (1 << 6) /* tx buffer empty */
-+#define ISR_IRF (1 << 7) /* rx buffer full */
-+#define ISR_GCAD (1 << 8) /* general call address detected */
-+#define ISR_SAD (1 << 9) /* slave address detected */
-+#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
-+
-+
-+/*
-+ * Serial Audio Controller
-+ */
-+
-+/* FIXME: This clash with SA1111 defines */
-+#ifndef CONFIG_SA1111
-+#define SACR0 __REG(0x40400000) /* Global Control Register */
-+#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
-+#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
-+#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */
-+#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */
-+#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
-+#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
-+#endif
-+
-+
-+/*
-+ * AC97 Controller registers
-+ */
-+
-+#define POCR __REG(0x40500000) /* PCM Out Control Register */
-+#define POCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define PICR __REG(0x40500004) /* PCM In Control Register */
-+#define PICR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define MCCR __REG(0x40500008) /* Mic In Control Register */
-+#define MCCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */
-+
-+#define GCR __REG(0x4050000C) /* Global Control Register */
-+#define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */
-+#define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */
-+#define GCR_SECRDY_IEN (1 << 9) /* Secondary Ready Interrupt Enable */
-+#define GCR_PRIRDY_IEN (1 << 8) /* Primary Ready Interrupt Enable */
-+#define GCR_SECRES_IEN (1 << 5) /* Secondary Resume Interrupt Enable */
-+#define GCR_PRIRES_IEN (1 << 4) /* Primary Resume Interrupt Enable */
-+#define GCR_ACLINK_OFF (1 << 3) /* AC-link Shut Off */
-+#define GCR_WARM_RST (1 << 2) /* AC97 Warm Reset */
-+#define GCR_COLD_RST (1 << 1) /* AC'97 Cold Reset (0 = active) */
-+#define GCR_GIE (1 << 0) /* Codec GPI Interrupt Enable */
-+
-+#define POSR __REG(0x40500010) /* PCM Out Status Register */
-+#define POSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define PISR __REG(0x40500014) /* PCM In Status Register */
-+#define PISR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MCSR __REG(0x40500018) /* Mic In Status Register */
-+#define MCSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define GSR __REG(0x4050001C) /* Global Status Register */
-+#define GSR_CDONE (1 << 19) /* Command Done */
-+#define GSR_SDONE (1 << 18) /* Status Done */
-+#define GSR_RDCS (1 << 15) /* Read Completion Status */
-+#define GSR_BIT3SLT12 (1 << 14) /* Bit 3 of slot 12 */
-+#define GSR_BIT2SLT12 (1 << 13) /* Bit 2 of slot 12 */
-+#define GSR_BIT1SLT12 (1 << 12) /* Bit 1 of slot 12 */
-+#define GSR_SECRES (1 << 11) /* Secondary Resume Interrupt */
-+#define GSR_PRIRES (1 << 10) /* Primary Resume Interrupt */
-+#define GSR_SCR (1 << 9) /* Secondary Codec Ready */
-+#define GSR_PCR (1 << 8) /* Primary Codec Ready */
-+#define GSR_MINT (1 << 7) /* Mic In Interrupt */
-+#define GSR_POINT (1 << 6) /* PCM Out Interrupt */
-+#define GSR_PIINT (1 << 5) /* PCM In Interrupt */
-+#define GSR_MOINT (1 << 2) /* Modem Out Interrupt */
-+#define GSR_MIINT (1 << 1) /* Modem In Interrupt */
-+#define GSR_GSCI (1 << 0) /* Codec GPI Status Change Interrupt */
-+
-+#define CAR __REG(0x40500020) /* CODEC Access Register */
-+#define CAR_CAIP (1 << 0) /* Codec Access In Progress */
-+
-+#define PCDR __REG(0x40500040) /* PCM FIFO Data Register */
-+#define MCDR __REG(0x40500060) /* Mic-in FIFO Data Register */
-+
-+#define MOCR __REG(0x40500100) /* Modem Out Control Register */
-+#define MOCR_FEIE (1 << 3) /* FIFO Error */
-+
-+#define MICR __REG(0x40500108) /* Modem In Control Register */
-+#define MICR_FEIE (1 << 3) /* FIFO Error */
-+
-+#define MOSR __REG(0x40500110) /* Modem Out Status Register */
-+#define MOSR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MISR __REG(0x40500118) /* Modem In Status Register */
-+#define MISR_FIFOE (1 << 4) /* FIFO error */
-+
-+#define MODR __REG(0x40500140) /* Modem FIFO Data Register */
-+
-+#define PAC_REG_BASE __REG(0x40500200) /* Primary Audio Codec */
-+#define SAC_REG_BASE __REG(0x40500300) /* Secondary Audio Codec */
-+#define PMC_REG_BASE __REG(0x40500400) /* Primary Modem Codec */
-+#define SMC_REG_BASE __REG(0x40500500) /* Secondary Modem Codec */
-+
-+
-+/*
-+ * USB Device Controller
-+ */
-+#define UDC_RES1 __REG(0x40600004) /* UDC Undocumented - Reserved1 */
-+#define UDC_RES2 __REG(0x40600008) /* UDC Undocumented - Reserved2 */
-+#define UDC_RES3 __REG(0x4060000C) /* UDC Undocumented - Reserved3 */
-+
-+#define UDCCR __REG(0x40600000) /* UDC Control Register */
-+#define UDCCR_UDE (1 << 0) /* UDC enable */
-+#define UDCCR_UDA (1 << 1) /* UDC active */
-+#define UDCCR_RSM (1 << 2) /* Device resume */
-+#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */
-+#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */
-+#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */
-+#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */
-+#define UDCCR_REM (1 << 7) /* Reset interrupt mask */
-+
-+#define UDCCS0 __REG(0x40600010) /* UDC Endpoint 0 Control/Status Register */
-+#define UDCCS0_OPR (1 << 0) /* OUT packet ready */
-+#define UDCCS0_IPR (1 << 1) /* IN packet ready */
-+#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */
-+#define UDCCS0_SST (1 << 4) /* Sent stall */
-+#define UDCCS0_FST (1 << 5) /* Force stall */
-+#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */
-+#define UDCCS0_SA (1 << 7) /* Setup active */
-+
-+/* Bulk IN - Endpoint 1,6,11 */
-+#define UDCCS1 __REG(0x40600014) /* UDC Endpoint 1 (IN) Control/Status Register */
-+#define UDCCS6 __REG(0x40600028) /* UDC Endpoint 6 (IN) Control/Status Register */
-+#define UDCCS11 __REG(0x4060003C) /* UDC Endpoint 11 (IN) Control/Status Register */
-+
-+#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_BI_SST (1 << 4) /* Sent stall */
-+#define UDCCS_BI_FST (1 << 5) /* Force stall */
-+#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */
-+
-+/* Bulk OUT - Endpoint 2,7,12 */
-+#define UDCCS2 __REG(0x40600018) /* UDC Endpoint 2 (OUT) Control/Status Register */
-+#define UDCCS7 __REG(0x4060002C) /* UDC Endpoint 7 (OUT) Control/Status Register */
-+#define UDCCS12 __REG(0x40600040) /* UDC Endpoint 12 (OUT) Control/Status Register */
-+
-+#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */
-+#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */
-+#define UDCCS_BO_DME (1 << 3) /* DMA enable */
-+#define UDCCS_BO_SST (1 << 4) /* Sent stall */
-+#define UDCCS_BO_FST (1 << 5) /* Force stall */
-+#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */
-+#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */
-+
-+/* Isochronous IN - Endpoint 3,8,13 */
-+#define UDCCS3 __REG(0x4060001C) /* UDC Endpoint 3 (IN) Control/Status Register */
-+#define UDCCS8 __REG(0x40600030) /* UDC Endpoint 8 (IN) Control/Status Register */
-+#define UDCCS13 __REG(0x40600044) /* UDC Endpoint 13 (IN) Control/Status Register */
-+
-+#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */
-+
-+/* Isochronous OUT - Endpoint 4,9,14 */
-+#define UDCCS4 __REG(0x40600020) /* UDC Endpoint 4 (OUT) Control/Status Register */
-+#define UDCCS9 __REG(0x40600034) /* UDC Endpoint 9 (OUT) Control/Status Register */
-+#define UDCCS14 __REG(0x40600048) /* UDC Endpoint 14 (OUT) Control/Status Register */
-+
-+#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */
-+#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */
-+#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */
-+#define UDCCS_IO_DME (1 << 3) /* DMA enable */
-+#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */
-+#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */
-+
-+/* Interrupt IN - Endpoint 5,10,15 */
-+#define UDCCS5 __REG(0x40600024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */
-+#define UDCCS10 __REG(0x40600038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */
-+#define UDCCS15 __REG(0x4060004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */
-+
-+#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */
-+#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */
-+#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */
-+#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */
-+#define UDCCS_INT_SST (1 << 4) /* Sent stall */
-+#define UDCCS_INT_FST (1 << 5) /* Force stall */
-+#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */
-+
-+#define UFNRH __REG(0x40600060) /* UDC Frame Number Register High */
-+#define UFNRL __REG(0x40600064) /* UDC Frame Number Register Low */
-+#define UBCR2 __REG(0x40600068) /* UDC Byte Count Reg 2 */
-+#define UBCR4 __REG(0x4060006c) /* UDC Byte Count Reg 4 */
-+#define UBCR7 __REG(0x40600070) /* UDC Byte Count Reg 7 */
-+#define UBCR9 __REG(0x40600074) /* UDC Byte Count Reg 9 */
-+#define UBCR12 __REG(0x40600078) /* UDC Byte Count Reg 12 */
-+#define UBCR14 __REG(0x4060007c) /* UDC Byte Count Reg 14 */
-+#define UDDR0 __REG(0x40600080) /* UDC Endpoint 0 Data Register */
-+#define UDDR1 __REG(0x40600100) /* UDC Endpoint 1 Data Register */
-+#define UDDR2 __REG(0x40600180) /* UDC Endpoint 2 Data Register */
-+#define UDDR3 __REG(0x40600200) /* UDC Endpoint 3 Data Register */
-+#define UDDR4 __REG(0x40600400) /* UDC Endpoint 4 Data Register */
-+#define UDDR5 __REG(0x406000A0) /* UDC Endpoint 5 Data Register */
-+#define UDDR6 __REG(0x40600600) /* UDC Endpoint 6 Data Register */
-+#define UDDR7 __REG(0x40600680) /* UDC Endpoint 7 Data Register */
-+#define UDDR8 __REG(0x40600700) /* UDC Endpoint 8 Data Register */
-+#define UDDR9 __REG(0x40600900) /* UDC Endpoint 9 Data Register */
-+#define UDDR10 __REG(0x406000C0) /* UDC Endpoint 10 Data Register */
-+#define UDDR11 __REG(0x40600B00) /* UDC Endpoint 11 Data Register */
-+#define UDDR12 __REG(0x40600B80) /* UDC Endpoint 12 Data Register */
-+#define UDDR13 __REG(0x40600C00) /* UDC Endpoint 13 Data Register */
-+#define UDDR14 __REG(0x40600E00) /* UDC Endpoint 14 Data Register */
-+#define UDDR15 __REG(0x406000E0) /* UDC Endpoint 15 Data Register */
-+
-+#define UICR0 __REG(0x40600050) /* UDC Interrupt Control Register 0 */
-+
-+#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */
-+#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */
-+#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */
-+#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */
-+#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */
-+#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */
-+#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */
-+#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */
-+
-+#define UICR1 __REG(0x40600054) /* UDC Interrupt Control Register 1 */
-+
-+#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */
-+#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */
-+#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */
-+#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */
-+#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */
-+#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */
-+#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */
-+#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */
-+
-+#define USIR0 __REG(0x40600058) /* UDC Status Interrupt Register 0 */
-+
-+#define USIR0_IR0 (1 << 0) /* Interrup request ep 0 */
-+#define USIR0_IR1 (1 << 1) /* Interrup request ep 1 */
-+#define USIR0_IR2 (1 << 2) /* Interrup request ep 2 */
-+#define USIR0_IR3 (1 << 3) /* Interrup request ep 3 */
-+#define USIR0_IR4 (1 << 4) /* Interrup request ep 4 */
-+#define USIR0_IR5 (1 << 5) /* Interrup request ep 5 */
-+#define USIR0_IR6 (1 << 6) /* Interrup request ep 6 */
-+#define USIR0_IR7 (1 << 7) /* Interrup request ep 7 */
-+
-+#define USIR1 __REG(0x4060005C) /* UDC Status Interrupt Register 1 */
-+
-+#define USIR1_IR8 (1 << 0) /* Interrup request ep 8 */
-+#define USIR1_IR9 (1 << 1) /* Interrup request ep 9 */
-+#define USIR1_IR10 (1 << 2) /* Interrup request ep 10 */
-+#define USIR1_IR11 (1 << 3) /* Interrup request ep 11 */
-+#define USIR1_IR12 (1 << 4) /* Interrup request ep 12 */
-+#define USIR1_IR13 (1 << 5) /* Interrup request ep 13 */
-+#define USIR1_IR14 (1 << 6) /* Interrup request ep 14 */
-+#define USIR1_IR15 (1 << 7) /* Interrup request ep 15 */
-+
-+
-+/*
-+ * Fast Infrared Communication Port
-+ */
-+
-+#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */
-+#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */
-+#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */
-+#define ICDR __REG(0x4080000c) /* ICP Data Register */
-+#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */
-+#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */
-+
-+#define ICCR0_AME (1 << 7) /* Adress match enable */
-+#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */
-+#define ICCR0_RIE (1 << 5) /* Recieve FIFO interrupt enable */
-+#define ICCR0_RXE (1 << 4) /* Receive enable */
-+#define ICCR0_TXE (1 << 3) /* Transmit enable */
-+#define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */
-+#define ICCR0_LBM (1 << 1) /* Loopback mode */
-+#define ICCR0_ITR (1 << 0) /* IrDA transmission */
-+
-+#define ICSR0_FRE (1 << 5) /* Framing error */
-+#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */
-+#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */
-+#define ICSR0_RAB (1 << 2) /* Receiver abort */
-+#define ICSR0_TUR (1 << 1) /* Trunsmit FIFO underun */
-+#define ICSR0_EIF (1 << 0) /* End/Error in FIFO */
-+
-+#define ICSR1_ROR (1 << 6) /* Receiver FIFO underrun */
-+#define ICSR1_CRE (1 << 5) /* CRC error */
-+#define ICSR1_EOF (1 << 4) /* End of frame */
-+#define ICSR1_TNF (1 << 3) /* Transmit FIFO not full */
-+#define ICSR1_RNE (1 << 2) /* Receive FIFO not empty */
-+#define ICSR1_TBY (1 << 1) /* Tramsmiter busy flag */
-+#define ICSR1_RSY (1 << 0) /* Recevier synchronized flag */
-+
-+
-+/*
-+ * Real Time Clock
-+ */
-+
-+#define RCNR __REG(0x40900000) /* RTC Count Register */
-+#define RTAR __REG(0x40900004) /* RTC Alarm Register */
-+#define RTSR __REG(0x40900008) /* RTC Status Register */
-+#define RTTR __REG(0x4090000C) /* RTC Timer Trim Register */
-+
-+#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
-+#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
-+#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
-+#define RTSR_AL (1 << 0) /* RTC alarm detected */
-+
-+
-+/*
-+ * OS Timer & Match Registers
-+ */
-+
-+#define OSMR0 __REG(0x40A00000) /* */
-+#define OSMR1 __REG(0x40A00004) /* */
-+#define OSMR2 __REG(0x40A00008) /* */
-+#define OSMR3 __REG(0x40A0000C) /* */
-+#define OSCR __REG(0x40A00010) /* OS Timer Counter Register */
-+#define OSSR __REG(0x40A00014) /* OS Timer Status Register */
-+#define OWER __REG(0x40A00018) /* OS Timer Watchdog Enable Register */
-+#define OIER __REG(0x40A0001C) /* OS Timer Interrupt Enable Register */
-+
-+#define OSSR_M3 (1 << 3) /* Match status channel 3 */
-+#define OSSR_M2 (1 << 2) /* Match status channel 2 */
-+#define OSSR_M1 (1 << 1) /* Match status channel 1 */
-+#define OSSR_M0 (1 << 0) /* Match status channel 0 */
-+
-+#define OWER_WME (1 << 0) /* Watchdog Match Enable */
-+
-+#define OIER_E3 (1 << 3) /* Interrupt enable channel 3 */
-+#define OIER_E2 (1 << 2) /* Interrupt enable channel 2 */
-+#define OIER_E1 (1 << 1) /* Interrupt enable channel 1 */
-+#define OIER_E0 (1 << 0) /* Interrupt enable channel 0 */
-+
-+
-+/*
-+ * Pulse Width Modulator
-+ */
-+
-+#define PWM_CTRL0 __REG(0x40B00000) /* PWM 0 Control Register */
-+#define PWM_PWDUTY0 __REG(0x40B00004) /* PWM 0 Duty Cycle Register */
-+#define PWM_PERVAL0 __REG(0x40B00008) /* PWM 0 Period Control Register */
-+
-+#define PWM_CTRL1 __REG(0x40C00000) /* PWM 1Control Register */
-+#define PWM_PWDUTY1 __REG(0x40C00004) /* PWM 1 Duty Cycle Register */
-+#define PWM_PERVAL1 __REG(0x40C00008) /* PWM 1 Period Control Register */
-+
-+
-+/*
-+ * Interrupt Controller
-+ */
-+
-+#define ICIP __REG(0x40D00000) /* Interrupt Controller IRQ Pending Register */
-+#define ICMR __REG(0x40D00004) /* Interrupt Controller Mask Register */
-+#define ICLR __REG(0x40D00008) /* Interrupt Controller Level Register */
-+#define ICFP __REG(0x40D0000C) /* Interrupt Controller FIQ Pending Register */
-+#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
-+#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */
-+
-+
-+/*
-+ * General Purpose I/O
-+ */
-+
-+#define GPLR0 __REG(0x40E00000) /* GPIO Pin-Level Register GPIO<31:0> */
-+#define GPLR1 __REG(0x40E00004) /* GPIO Pin-Level Register GPIO<63:32> */
-+#define GPLR2 __REG(0x40E00008) /* GPIO Pin-Level Register GPIO<80:64> */
-+
-+#define GPDR0 __REG(0x40E0000C) /* GPIO Pin Direction Register GPIO<31:0> */
-+#define GPDR1 __REG(0x40E00010) /* GPIO Pin Direction Register GPIO<63:32> */
-+#define GPDR2 __REG(0x40E00014) /* GPIO Pin Direction Register GPIO<80:64> */
-+
-+#define GPSR0 __REG(0x40E00018) /* GPIO Pin Output Set Register GPIO<31:0> */
-+#define GPSR1 __REG(0x40E0001C) /* GPIO Pin Output Set Register GPIO<63:32> */
-+#define GPSR2 __REG(0x40E00020) /* GPIO Pin Output Set Register GPIO<80:64> */
-+
-+#define GPCR0 __REG(0x40E00024) /* GPIO Pin Output Clear Register GPIO<31:0> */
-+#define GPCR1 __REG(0x40E00028) /* GPIO Pin Output Clear Register GPIO <63:32> */
-+#define GPCR2 __REG(0x40E0002C) /* GPIO Pin Output Clear Register GPIO <80:64> */
-+
-+#define GRER0 __REG(0x40E00030) /* GPIO Rising-Edge Detect Register GPIO<31:0> */
-+#define GRER1 __REG(0x40E00034) /* GPIO Rising-Edge Detect Register GPIO<63:32> */
-+#define GRER2 __REG(0x40E00038) /* GPIO Rising-Edge Detect Register GPIO<80:64> */
-+
-+#define GFER0 __REG(0x40E0003C) /* GPIO Falling-Edge Detect Register GPIO<31:0> */
-+#define GFER1 __REG(0x40E00040) /* GPIO Falling-Edge Detect Register GPIO<63:32> */
-+#define GFER2 __REG(0x40E00044) /* GPIO Falling-Edge Detect Register GPIO<80:64> */
-+
-+#define GEDR0 __REG(0x40E00048) /* GPIO Edge Detect Status Register GPIO<31:0> */
-+#define GEDR1 __REG(0x40E0004C) /* GPIO Edge Detect Status Register GPIO<63:32> */
-+#define GEDR2 __REG(0x40E00050) /* GPIO Edge Detect Status Register GPIO<80:64> */
-+
-+#define GAFR0_L __REG(0x40E00054) /* GPIO Alternate Function Select Register GPIO<15:0> */
-+#define GAFR0_U __REG(0x40E00058) /* GPIO Alternate Function Select Register GPIO<31:16> */
-+#define GAFR1_L __REG(0x40E0005C) /* GPIO Alternate Function Select Register GPIO<47:32> */
-+#define GAFR1_U __REG(0x40E00060) /* GPIO Alternate Function Select Register GPIO<63:48> */
-+#define GAFR2_L __REG(0x40E00064) /* GPIO Alternate Function Select Register GPIO<79:64> */
-+#define GAFR2_U __REG(0x40E00068) /* GPIO Alternate Function Select Register GPIO 80 */
-+
-+/* More handy macros. The argument is a literal GPIO number. */
-+
-+#define GPIO_bit(x) (1 << ((x) & 0x1f))
-+#define GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3)
-+#define GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3)
-+#define GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3)
-+#define GPCR(x) __REG2(0x40E00024, ((x) & 0x60) >> 3)
-+#define GRER(x) __REG2(0x40E00030, ((x) & 0x60) >> 3)
-+#define GFER(x) __REG2(0x40E0003C, ((x) & 0x60) >> 3)
-+#define GEDR(x) __REG2(0x40E00048, ((x) & 0x60) >> 3)
-+#define GAFR(x) __REG2(0x40E00054, ((x) & 0x70) >> 2)
-+
-+/* GPIO alternate function assignments */
-+
-+#define GPIO1_RST 1 /* reset */
-+#define GPIO6_MMCCLK 6 /* MMC Clock */
-+#define GPIO8_48MHz 7 /* 48 MHz clock output */
-+#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */
-+#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */
-+#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */
-+#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */
-+#define GPIO12_32KHz 12 /* 32 kHz out */
-+#define GPIO13_MBGNT 13 /* memory controller grant */
-+#define GPIO14_MBREQ 14 /* alternate bus master request */
-+#define GPIO15_nCS_1 15 /* chip select 1 */
-+#define GPIO16_PWM0 16 /* PWM0 output */
-+#define GPIO17_PWM1 17 /* PWM1 output */
-+#define GPIO18_RDY 18 /* Ext. Bus Ready */
-+#define GPIO19_DREQ1 19 /* External DMA Request */
-+#define GPIO20_DREQ0 20 /* External DMA Request */
-+#define GPIO23_SCLK 23 /* SSP clock */
-+#define GPIO24_SFRM 24 /* SSP Frame */
-+#define GPIO25_STXD 25 /* SSP transmit */
-+#define GPIO26_SRXD 26 /* SSP receive */
-+#define GPIO27_SEXTCLK 27 /* SSP ext_clk */
-+#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */
-+#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */
-+#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */
-+#define GPIO31_SYNC 31 /* AC97/I2S sync */
-+#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */
-+#define GPIO33_nCS_5 33 /* chip select 5 */
-+#define GPIO34_FFRXD 34 /* FFUART receive */
-+#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */
-+#define GPIO35_FFCTS 35 /* FFUART Clear to send */
-+#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */
-+#define GPIO37_FFDSR 37 /* FFUART data set ready */
-+#define GPIO38_FFRI 38 /* FFUART Ring Indicator */
-+#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */
-+#define GPIO39_FFTXD 39 /* FFUART transmit data */
-+#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */
-+#define GPIO41_FFRTS 41 /* FFUART request to send */
-+#define GPIO42_BTRXD 42 /* BTUART receive data */
-+#define GPIO43_BTTXD 43 /* BTUART transmit data */
-+#define GPIO44_BTCTS 44 /* BTUART clear to send */
-+#define GPIO45_BTRTS 45 /* BTUART request to send */
-+#define GPIO46_ICPRXD 46 /* ICP receive data */
-+#define GPIO46_STRXD 46 /* STD_UART receive data */
-+#define GPIO47_ICPTXD 47 /* ICP transmit data */
-+#define GPIO47_STTXD 47 /* STD_UART transmit data */
-+#define GPIO48_nPOE 48 /* Output Enable for Card Space */
-+#define GPIO49_nPWE 49 /* Write Enable for Card Space */
-+#define GPIO50_nPIOR 50 /* I/O Read for Card Space */
-+#define GPIO51_nPIOW 51 /* I/O Write for Card Space */
-+#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */
-+#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */
-+#define GPIO53_MMCCLK 53 /* MMC Clock */
-+#define GPIO54_MMCCLK 54 /* MMC Clock */
-+#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */
-+#define GPIO55_nPREG 55 /* Card Address bit 26 */
-+#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */
-+#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */
-+#define GPIO58_LDD_0 58 /* LCD data pin 0 */
-+#define GPIO59_LDD_1 59 /* LCD data pin 1 */
-+#define GPIO60_LDD_2 60 /* LCD data pin 2 */
-+#define GPIO61_LDD_3 61 /* LCD data pin 3 */
-+#define GPIO62_LDD_4 62 /* LCD data pin 4 */
-+#define GPIO63_LDD_5 63 /* LCD data pin 5 */
-+#define GPIO64_LDD_6 64 /* LCD data pin 6 */
-+#define GPIO65_LDD_7 65 /* LCD data pin 7 */
-+#define GPIO66_LDD_8 66 /* LCD data pin 8 */
-+#define GPIO66_MBREQ 66 /* alternate bus master req */
-+#define GPIO67_LDD_9 67 /* LCD data pin 9 */
-+#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */
-+#define GPIO68_LDD_10 68 /* LCD data pin 10 */
-+#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */
-+#define GPIO69_LDD_11 69 /* LCD data pin 11 */
-+#define GPIO69_MMCCLK 69 /* MMC_CLK */
-+#define GPIO70_LDD_12 70 /* LCD data pin 12 */
-+#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */
-+#define GPIO71_LDD_13 71 /* LCD data pin 13 */
-+#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */
-+#define GPIO72_LDD_14 72 /* LCD data pin 14 */
-+#define GPIO72_32kHz 72 /* 32 kHz clock */
-+#define GPIO73_LDD_15 73 /* LCD data pin 15 */
-+#define GPIO73_MBGNT 73 /* Memory controller grant */
-+#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */
-+#define GPIO75_LCD_LCLK 75 /* LCD line clock */
-+#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */
-+#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */
-+#define GPIO78_nCS_2 78 /* chip select 2 */
-+#define GPIO79_nCS_3 79 /* chip select 3 */
-+#define GPIO80_nCS_4 80 /* chip select 4 */
-+
-+/* GPIO alternate function mode & direction */
-+
-+#define GPIO_IN 0x000
-+#define GPIO_OUT 0x080
-+#define GPIO_ALT_FN_1_IN 0x100
-+#define GPIO_ALT_FN_1_OUT 0x180
-+#define GPIO_ALT_FN_2_IN 0x200
-+#define GPIO_ALT_FN_2_OUT 0x280
-+#define GPIO_ALT_FN_3_IN 0x300
-+#define GPIO_ALT_FN_3_OUT 0x380
-+#define GPIO_MD_MASK_NR 0x07f
-+#define GPIO_MD_MASK_DIR 0x080
-+#define GPIO_MD_MASK_FN 0x300
-+
-+#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN)
-+#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT)
-+#define GPIO8_48MHz_MD ( 8 | GPIO_ALT_FN_1_OUT)
-+#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT)
-+#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT)
-+#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT)
-+#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT)
-+#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT)
-+#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT)
-+#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN)
-+#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT)
-+#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT)
-+#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT)
-+#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
-+#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
-+#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
-+#define GPIO23_SCLK_md (23 | GPIO_ALT_FN_2_OUT)
-+#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
-+#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
-+#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN)
-+#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN)
-+#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN)
-+#define GPIO28_BITCLK_I2S_MD (28 | GPIO_ALT_FN_2_IN)
-+#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
-+#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
-+#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
-+#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
-+#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT)
-+#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT)
-+#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN)
-+#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT)
-+#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN)
-+#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT)
-+#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN)
-+#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
-+#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
-+#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
-+#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
-+#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
-+#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT)
-+#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT)
-+#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN)
-+#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT)
-+#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN)
-+#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT)
-+#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN)
-+#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN)
-+#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT)
-+#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT)
-+#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
-+#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT)
-+#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT)
-+#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
-+#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
-+#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
-+#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
-+#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT)
-+#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT)
-+#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT)
-+#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN)
-+#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN)
-+#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT)
-+#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT)
-+#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT)
-+#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT)
-+#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT)
-+#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT)
-+#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT)
-+#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT)
-+#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT)
-+#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN)
-+#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT)
-+#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT)
-+#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT)
-+#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT)
-+#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT)
-+#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT)
-+#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT)
-+#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT)
-+#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT)
-+#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT)
-+#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT)
-+#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT)
-+#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT)
-+#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT)
-+#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT)
-+#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT)
-+#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT)
-+#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT)
-+#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT)
-+#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT)
-+#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
-+
-+
-+/*
-+ * Power Manager
-+ */
-+
-+#define PMCR __REG(0x40F00000) /* Power Manager Control Register */
-+#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status Register */
-+#define PSPR __REG(0x40F00008) /* Power Manager Scratch Pad Register */
-+#define PWER __REG(0x40F0000C) /* Power Manager Wake-up Enable Register */
-+#define PRER __REG(0x40F00010) /* Power Manager GPIO Rising-Edge Detect Enable Register */
-+#define PFER __REG(0x40F00014) /* Power Manager GPIO Falling-Edge Detect Enable Register */
-+#define PEDR __REG(0x40F00018) /* Power Manager GPIO Edge Detect Status Register */
-+#define PCFR __REG(0x40F0001C) /* Power Manager General Configuration Register */
-+#define PGSR0 __REG(0x40F00020) /* Power Manager GPIO Sleep State Register for GP[31-0] */
-+#define PGSR1 __REG(0x40F00024) /* Power Manager GPIO Sleep State Register for GP[63-32] */
-+#define PGSR2 __REG(0x40F00028) /* Power Manager GPIO Sleep State Register for GP[84-64] */
-+#define RCSR __REG(0x40F00030) /* Reset Controller Status Register */
-+
-+#define PSSR_RDH (1 << 5) /* Read Disable Hold */
-+#define PSSR_PH (1 << 4) /* Peripheral Control Hold */
-+#define PSSR_VFS (1 << 2) /* VDD Fault Status */
-+#define PSSR_BFS (1 << 1) /* Battery Fault Status */
-+#define PSSR_SSS (1 << 0) /* Software Sleep Status */
-+
-+#define PCFR_DS (1 << 3) /* Deep Sleep Mode */
-+#define PCFR_FS (1 << 2) /* Float Static Chip Selects */
-+#define PCFR_FP (1 << 1) /* Float PCMCIA controls */
-+#define PCFR_OPDE (1 << 0) /* 3.6864 MHz oscillator power-down enable */
-+
-+#define RCSR_GPR (1 << 3) /* GPIO Reset */
-+#define RCSR_SMR (1 << 2) /* Sleep Mode */
-+#define RCSR_WDR (1 << 1) /* Watchdog Reset */
-+#define RCSR_HWR (1 << 0) /* Hardware Reset */
-+
-+
-+/*
-+ * SSP Serial Port Registers
-+ */
-+
-+#define SSCR0 __REG(0x41000000) /* SSP Control Register 0 */
-+#define SSCR1 __REG(0x41000004) /* SSP Control Register 1 */
-+#define SSSR __REG(0x41000008) /* SSP Status Register */
-+#define SSITR __REG(0x4100000C) /* SSP Interrupt Test Register */
-+#define SSDR __REG(0x41000010) /* (Write / Read) SSP Data Write Register/SSP Data Read Register */
-+
-+
-+/*
-+ * MultiMediaCard (MMC) controller
-+ */
-+
-+#define MMC_STRPCL __REG(0x41100000) /* Control to start and stop MMC clock */
-+#define MMC_STAT __REG(0x41100004) /* MMC Status Register (read only) */
-+#define MMC_CLKRT __REG(0x41100008) /* MMC clock rate */
-+#define MMC_SPI __REG(0x4110000c) /* SPI mode control bits */
-+#define MMC_CMDAT __REG(0x41100010) /* Command/response/data sequence control */
-+#define MMC_RESTO __REG(0x41100014) /* Expected response time out */
-+#define MMC_RDTO __REG(0x41100018) /* Expected data read time out */
-+#define MMC_BLKLEN __REG(0x4110001c) /* Block length of data transaction */
-+#define MMC_NOB __REG(0x41100020) /* Number of blocks, for block mode */
-+#define MMC_PRTBUF __REG(0x41100024) /* Partial MMC_TXFIFO FIFO written */
-+#define MMC_I_MASK __REG(0x41100028) /* Interrupt Mask */
-+#define MMC_I_REG __REG(0x4110002c) /* Interrupt Register (read only) */
-+#define MMC_CMD __REG(0x41100030) /* Index of current command */
-+#define MMC_ARGH __REG(0x41100034) /* MSW part of the current command argument */
-+#define MMC_ARGL __REG(0x41100038) /* LSW part of the current command argument */
-+#define MMC_RES __REG(0x4110003c) /* Response FIFO (read only) */
-+#define MMC_RXFIFO __REG(0x41100040) /* Receive FIFO (read only) */
-+#define MMC_TXFIFO __REG(0x41100044) /* Transmit FIFO (write only) */
-+
-+
-+/*
-+ * Core Clock
-+ */
-+
-+#define CCCR __REG(0x41300000) /* Core Clock Configuration Register */
-+#define CKEN __REG(0x41300004) /* Clock Enable Register */
-+#define OSCC __REG(0x41300008) /* Oscillator Configuration Register */
-+
-+#define CCCR_N_MASK 0x0380 /* Run Mode Frequency to Turbo Mode Frequency Multiplier */
-+#define CCCR_M_MASK 0x0060 /* Memory Frequency to Run Mode Frequency Multiplier */
-+#define CCCR_L_MASK 0x001f /* Crystal Frequency to Memory Frequency Multiplier */
-+
-+#define CKEN16_LCD (1 << 16) /* LCD Unit Clock Enable */
-+#define CKEN14_I2C (1 << 14) /* I2C Unit Clock Enable */
-+#define CKEN13_FICP (1 << 13) /* FICP Unit Clock Enable */
-+#define CKEN12_MMC (1 << 12) /* MMC Unit Clock Enable */
-+#define CKEN11_USB (1 << 11) /* USB Unit Clock Enable */
-+#define CKEN8_I2S (1 << 8) /* I2S Unit Clock Enable */
-+#define CKEN7_BTUART (1 << 7) /* BTUART Unit Clock Enable */
-+#define CKEN6_FFUART (1 << 6) /* FFUART Unit Clock Enable */
-+#define CKEN5_STUART (1 << 5) /* STUART Unit Clock Enable */
-+#define CKEN3_SSP (1 << 3) /* SSP Unit Clock Enable */
-+#define CKEN2_AC97 (1 << 2) /* AC97 Unit Clock Enable */
-+#define CKEN1_PWM1 (1 << 1) /* PWM1 Clock Enable */
-+#define CKEN0_PWM0 (1 << 0) /* PWM0 Clock Enable */
-+
-+#define OSCC_OON (1 << 1) /* 32.768kHz OON (write-once only bit) */
-+#define OSCC_OOK (1 << 0) /* 32.768kHz OOK (read-only bit) */
-+
-+
-+/*
-+ * LCD
-+ */
-+
-+#define LCCR0 __REG(0x44000000) /* LCD Controller Control Register 0 */
-+#define LCCR1 __REG(0x44000004) /* LCD Controller Control Register 1 */
-+#define LCCR2 __REG(0x44000008) /* LCD Controller Control Register 2 */
-+#define LCCR3 __REG(0x4400000C) /* LCD Controller Control Register 3 */
-+#define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
-+#define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
-+#define LCSR __REG(0x44000038) /* LCD Controller Status Register */
-+#define LIIDR __REG(0x4400003C) /* LCD Controller Interrupt ID Register */
-+#define TMEDRGBR __REG(0x44000040) /* TMED RGB Seed Register */
-+#define TMEDCR __REG(0x44000044) /* TMED Control Register */
-+
-+#define FDADR0 __REG(0x44000200) /* DMA Channel 0 Frame Descriptor Address Register */
-+#define FSADR0 __REG(0x44000204) /* DMA Channel 0 Frame Source Address Register */
-+#define FIDR0 __REG(0x44000208) /* DMA Channel 0 Frame ID Register */
-+#define LDCMD0 __REG(0x4400020C) /* DMA Channel 0 Command Register */
-+#define FDADR1 __REG(0x44000210) /* DMA Channel 1 Frame Descriptor Address Register */
-+#define FSADR1 __REG(0x44000214) /* DMA Channel 1 Frame Source Address Register */
-+#define FIDR1 __REG(0x44000218) /* DMA Channel 1 Frame ID Register */
-+#define LDCMD1 __REG(0x4400021C) /* DMA Channel 1 Command Register */
-+
-+#define LCCR0_ENB (1 << 0) /* LCD Controller enable */
-+#define LCCR0_CMS (1 << 1) /* Color = 0, Monochrome = 1 */
-+#define LCCR0_SDS (1 << 2) /* Single Panel = 0, Dual Panel = 1 */
-+#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */
-+#define LCCR0_SFM (1 << 4) /* Start of frame mask */
-+#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */
-+#define LCCR0_EFM (1 << 6) /* End of Frame mask */
-+#define LCCR0_PAS (1 << 7) /* Passive = 0, Active = 1 */
-+#define LCCR0_BLE (1 << 8) /* Little Endian = 0, Big Endian = 1 */
-+#define LCCR0_DPD (1 << 9) /* Double Pixel mode, 4 pixel value = 0, 8 pixle values = 1 */
-+#define LCCR0_DIS (1 << 10) /* LCD Disable */
-+#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */
-+#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */
-+#define LCCR0_PDD_S 12
-+#define LCCR0_BM (1 << 20) /* Branch mask */
-+#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */
-+
-+#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */
-+#define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \
-+ (((Pixel) - 1) << FShft (LCCR1_PPL))
-+
-+#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
-+#define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \
-+ /* pulse Width [1..64 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_HSW))
-+
-+#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */
-+ /* count - 1 [Tpix] */
-+#define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \
-+ /* [1..256 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_ELW))
-+
-+#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
-+ /* Wait count - 1 [Tpix] */
-+#define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \
-+ /* [1..256 Tpix] */ \
-+ (((Tpix) - 1) << FShft (LCCR1_BLW))
-+
-+
-+#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
-+#define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \
-+ (((Line) - 1) << FShft (LCCR2_LPP))
-+
-+#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */
-+ /* Width - 1 [Tln] (L_FCLK) */
-+#define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \
-+ /* Width [1..64 Tln] */ \
-+ (((Tln) - 1) << FShft (LCCR2_VSW))
-+
-+#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
-+ /* count [Tln] */
-+#define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \
-+ /* [0..255 Tln] */ \
-+ ((Tln) << FShft (LCCR2_EFW))
-+
-+#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
-+ /* Wait count [Tln] */
-+#define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \
-+ /* [0..255 Tln] */ \
-+ ((Tln) << FShft (LCCR2_BFW))
-+
-+#if 0
-+#define LCCR3_PCD (0xff) /* Pixel clock divisor */
-+#define LCCR3_ACB (0xff << 8) /* AC Bias pin frequency */
-+#define LCCR3_ACB_S 8
-+#endif
-+
-+#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */
-+#define LCCR3_API_S 16
-+#define LCCR3_VSP (1 << 20) /* vertical sync polarity */
-+#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */
-+#define LCCR3_PCP (1 << 22) /* pixel clock polarity */
-+#define LCCR3_OEP (1 << 23) /* output enable polarity */
-+#if 0
-+#define LCCR3_BPP (7 << 24) /* bits per pixel */
-+#define LCCR3_BPP_S 24
-+#endif
-+#define LCCR3_DPC (1 << 27) /* double pixel clock mode */
-+
-+
-+#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */
-+#define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor */ \
-+ (((Div) << FShft (LCCR3_PCD)))
-+
-+
-+#define LCCR3_BPP Fld (3, 24) /* Bit Per Pixel */
-+#define LCCR3_Bpp(Bpp) /* Bit Per Pixel */ \
-+ (((Bpp) << FShft (LCCR3_BPP)))
-+
-+#define LCCR3_ACB Fld (8, 8) /* AC Bias */
-+#define LCCR3_Acb(Acb) /* BAC Bias */ \
-+ (((Acb) << FShft (LCCR3_ACB)))
-+
-+#define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */
-+ /* pulse active High */
-+#define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */
-+
-+#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */
-+ /* active High */
-+#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */
-+ /* active Low */
-+
-+#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-+#define LCSR_SOF (1 << 1) /* Start of frame */
-+#define LCSR_BER (1 << 2) /* Bus error */
-+#define LCSR_ABC (1 << 3) /* AC Bias count */
-+#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-+#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-+#define LCSR_OU (1 << 6) /* output FIFO underrun */
-+#define LCSR_QD (1 << 7) /* quick disable */
-+#define LCSR_EOF (1 << 8) /* end of frame */
-+#define LCSR_BS (1 << 9) /* branch status */
-+#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-+
-+#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-+
-+#define LCSR_LDD (1 << 0) /* LCD Disable Done */
-+#define LCSR_SOF (1 << 1) /* Start of frame */
-+#define LCSR_BER (1 << 2) /* Bus error */
-+#define LCSR_ABC (1 << 3) /* AC Bias count */
-+#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */
-+#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */
-+#define LCSR_OU (1 << 6) /* output FIFO underrun */
-+#define LCSR_QD (1 << 7) /* quick disable */
-+#define LCSR_EOF (1 << 8) /* end of frame */
-+#define LCSR_BS (1 << 9) /* branch status */
-+#define LCSR_SINT (1 << 10) /* subsequent interrupt */
-+
-+#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
-+
-+/*
-+ * Memory controller
-+ */
-+
-+#define MDCNFG __REG(0x48000000) /* SDRAM Configuration Register 0 */
-+#define MDREFR __REG(0x48000004) /* SDRAM Refresh Control Register */
-+#define MSC0 __REG(0x48000008) /* Static Memory Control Register 0 */
-+#define MSC1 __REG(0x4800000C) /* Static Memory Control Register 1 */
-+#define MSC2 __REG(0x48000010) /* Static Memory Control Register 2 */
-+#define MECR __REG(0x48000014) /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
-+#define SXLCR __REG(0x48000018) /* LCR value to be written to SDRAM-Timing Synchronous Flash */
-+#define SXCNFG __REG(0x4800001C) /* Synchronous Static Memory Control Register */
-+#define SXMRS __REG(0x48000024) /* MRS value to be written to Synchronous Flash or SMROM */
-+#define MCMEM0 __REG(0x48000028) /* Card interface Common Memory Space Socket 0 Timing */
-+#define MCMEM1 __REG(0x4800002C) /* Card interface Common Memory Space Socket 1 Timing */
-+#define MCATT0 __REG(0x48000030) /* Card interface Attribute Space Socket 0 Timing Configuration */
-+#define MCATT1 __REG(0x48000034) /* Card interface Attribute Space Socket 1 Timing Configuration */
-+#define MCIO0 __REG(0x48000038) /* Card interface I/O Space Socket 0 Timing Configuration */
-+#define MCIO1 __REG(0x4800003C) /* Card interface I/O Space Socket 1 Timing Configuration */
-+#define MDMRS __REG(0x48000040) /* MRS value to be written to SDRAM */
-+#define BOOT_DEF __REG(0x48000044) /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
-+
-+#define MDREFR_K2FREE (1 << 25) /* SDRAM Free-Running Control */
-+#define MDREFR_K1FREE (1 << 24) /* SDRAM Free-Running Control */
-+#define MDREFR_K0FREE (1 << 23) /* SDRAM Free-Running Control */
-+#define MDREFR_SLFRSH (1 << 22) /* SDRAM Self-Refresh Control/Status */
-+#define MDREFR_APD (1 << 20) /* SDRAM/SSRAM Auto-Power-Down Enable */
-+#define MDREFR_K2DB2 (1 << 19) /* SDCLK2 Divide by 2 Control/Status */
-+#define MDREFR_K2RUN (1 << 18) /* SDCLK2 Run Control/Status */
-+#define MDREFR_K1DB2 (1 << 17) /* SDCLK1 Divide by 2 Control/Status */
-+#define MDREFR_K1RUN (1 << 16) /* SDCLK1 Run Control/Status */
-+#define MDREFR_E1PIN (1 << 15) /* SDCKE1 Level Control/Status */
-+#define MDREFR_K0DB2 (1 << 14) /* SDCLK0 Divide by 2 Control/Status */
-+#define MDREFR_K0RUN (1 << 13) /* SDCLK0 Run Control/Status */
-+#define MDREFR_E0PIN (1 << 12) /* SDCKE0 Level Control/Status */
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/serial.h
-@@ -0,0 +1,51 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/serial.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+#define BAUD_BASE 921600
-+
-+/* Standard COM flags */
-+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
-+
-+#define STD_SERIAL_PORT_DEFNS \
-+ { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&FFUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_FFUART, \
-+ flags: STD_COM_FLAGS, \
-+ }, { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&BTUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_BTUART, \
-+ flags: STD_COM_FLAGS, \
-+ }, { \
-+ type: PORT_PXA, \
-+ xmit_fifo_size: 32, \
-+ baud_base: BAUD_BASE, \
-+ iomem_base: (void *)&STUART,\
-+ iomem_reg_shift: 2, \
-+ io_type: SERIAL_IO_MEM32,\
-+ irq: IRQ_STUART, \
-+ flags: STD_COM_FLAGS, \
-+ }
-+
-+#define RS_TABLE_SIZE 8
-+
-+#define EXTRA_SERIAL_PORT_DEFNS
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/system.h
-@@ -0,0 +1,32 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/system.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "hardware.h"
-+
-+static inline void arch_idle(void)
-+{
-+ cpu_do_idle();
-+}
-+
-+static inline void arch_reset(char mode)
-+{
-+ if (mode == 's') {
-+ /* Jump into ROM at address 0 */
-+ cpu_reset(0);
-+ } else {
-+ /* Initialize the watchdog and let it fire */
-+ OWER = OWER_WME;
-+ OSSR = OSSR_M3;
-+ OSMR3 = OSCR + 368640; /* ... in 100 ms */
-+ }
-+}
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/time.h
-@@ -0,0 +1,86 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/time.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+
-+static inline unsigned long pxa_get_rtc_time(void)
-+{
-+ return RCNR;
-+}
-+
-+static int pxa_set_rtc(void)
-+{
-+ unsigned long current_time = xtime.tv_sec;
-+
-+ if (RTSR & RTSR_ALE) {
-+ /* make sure not to forward the clock over an alarm */
-+ unsigned long alarm = RTAR;
-+ if (current_time >= alarm && alarm >= RCNR)
-+ return -ERESTARTSYS;
-+ }
-+ RCNR = current_time;
-+ return 0;
-+}
-+
-+/* IRQs are disabled before entering here from do_gettimeofday() */
-+static unsigned long pxa_gettimeoffset (void)
-+{
-+ unsigned long ticks_to_match, elapsed, usec;
-+
-+ /* Get ticks before next timer match */
-+ ticks_to_match = OSMR0 - OSCR;
-+
-+ /* We need elapsed ticks since last match */
-+ elapsed = LATCH - ticks_to_match;
-+
-+ /* Now convert them to usec */
-+ usec = (unsigned long)(elapsed*tick)/LATCH;
-+
-+ return usec;
-+}
-+
-+static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ long flags;
-+ int next_match;
-+
-+ do_profile(regs);
-+
-+ /* Loop until we get ahead of the free running timer.
-+ * This ensures an exact clock tick count and time acuracy.
-+ * IRQs are disabled inside the loop to ensure coherence between
-+ * lost_ticks (updated in do_timer()) and the match reg value, so we
-+ * can use do_gettimeofday() from interrupt handlers.
-+ */
-+ do {
-+ do_leds();
-+ do_set_rtc();
-+ save_flags_cli( flags );
-+ do_timer(regs);
-+ OSSR = OSSR_M0; /* Clear match on timer 0 */
-+ next_match = (OSMR0 += LATCH);
-+ restore_flags( flags );
-+ } while( (signed long)(next_match - OSCR) <= 0 );
-+}
-+
-+extern inline void setup_timer (void)
-+{
-+ gettimeoffset = pxa_gettimeoffset;
-+ set_rtc = pxa_set_rtc;
-+ xtime.tv_sec = pxa_get_rtc_time();
-+ timer_irq.handler = pxa_timer_interrupt;
-+ OSMR0 = 0; /* set initial match at 0 */
-+ OSSR = 0xf; /* clear status on all timers */
-+ setup_arm_irq(IRQ_OST0, &timer_irq);
-+ OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */
-+ OSCR = 0; /* initialize free-running timer, force first match */
-+}
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/timex.h
-@@ -0,0 +1,17 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/timex.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Created: Jun 15, 2001
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * PXA250/210 timer
-+ */
-+#define CLOCK_TICK_RATE 3686400
-+#define CLOCK_TICK_FACTOR 80
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/trizeps2.h
-@@ -0,0 +1,206 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/trizeps2.h
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Copyright (c) 2002 Luc De Cock, Teradyne DS, Ltd.
-+ *
-+ * 2002-10-10: Initial code started from idp.h
-+ */
-+
-+
-+/*
-+ * Note: this file must be safe to include in assembly files
-+ */
-+
-+/* comment out following if you have a board with 32MB RAM */
-+//#define PXA_TRIZEPS2_64MB 1
-+#undef PXA_TRIZEPS2_64MB
-+
-+#define TRIZEPS2_FLASH_PHYS (PXA_CS0_PHYS)
-+#define TRIZEPS2_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-+#define TRIZEPS2_MEDIAQ_PHYS (PXA_CS3_PHYS)
-+#define TRIZEPS2_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-+#define TRIZEPS2_ETH_PHYS (0x0C800000)
-+#define TRIZEPS2_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-+#define TRIZEPS2_BCR_PHYS (0x0E000000)
-+#define TRIZEPS2_CPLD_PHYS (0x0C000000)
-+
-+/*
-+ * virtual memory map
-+ */
-+
-+#define TRIZEPS2_IDE_BASE (0xf0000000)
-+#define TRIZEPS2_IDE_SIZE (1*1024*1024)
-+
-+#define TRIZEPS2_ETH_BASE (0xf1000000)
-+#define TRIZEPS2_ETH_SIZE (1*1024*1024)
-+#define ETH_BASE TRIZEPS2_ETH_BASE //smc9194 driver compatibility issue
-+
-+#define TRIZEPS2_COREVOLT_BASE (TRIZEPS2_ETH_BASE + TRIZEPS2_ETH_SIZE)
-+#define TRIZEPS2_COREVOLT_SIZE (1*1024*1024)
-+
-+#define TRIZEPS2_BCR_BASE (0xf0000000)
-+#define TRIZEPS2_BCR_SIZE (1*1024*1024)
-+
-+#define BCR_P2V(x) ((x) - TRIZEPS2_BCR_PHYS + TRIZEPS2_BCR_BASE)
-+#define BCR_V2P(x) ((x) - TRIZEPS2_BCR_BASE + TRIZEPS2_BCR_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __BCR_REG(x) (*((volatile unsigned short *)BCR_P2V(x)))
-+#else
-+# define __BCR_REG(x) BCR_P2V(x)
-+#endif
-+
-+/* board level registers */
-+#define TRIZEPS2_CPLD_BASE (0xf0100000)
-+#define CPLD_P2V(x) ((x) - TRIZEPS2_CPLD_PHYS + TRIZEPS2_CPLD_BASE)
-+#define CPLD_V2P(x) ((x) - TRIZEPS2_CPLD_BASE + TRIZEPS2_CPLD_PHYS)
-+
-+#ifndef __ASSEMBLY__
-+# define __CPLD_REG(x) (*((volatile unsigned short *)CPLD_P2V(x)))
-+#else
-+# define __CPLD_REG(x) CPLD_P2V(x)
-+#endif
-+
-+#define _TRIZEPS2_PCCARD_STATUS (0x0c000000)
-+#define TRIZEPS2_PCCARD_STATUS __CPLD_REG(_TRIZEPS2_PCCARD_STATUS)
-+
-+/*
-+ * CS memory timing via Static Memory Control Register (MSC0-2)
-+ */
-+
-+#define MSC_CS(cs,val) ((val)<<((cs&1)<<4))
-+
-+#define MSC_RBUFF_SHIFT 15
-+#define MSC_RBUFF(x) ((x)<<MSC_RBUFF_SHIFT)
-+#define MSC_RBUFF_SLOW MSC_RBUFF(0)
-+#define MSC_RBUFF_FAST MSC_RBUFF(1)
-+
-+#define MSC_RRR_SHIFT 12
-+#define MSC_RRR(x) ((x)<<MSC_RRR_SHIFT)
-+
-+#define MSC_RDN_SHIFT 8
-+#define MSC_RDN(x) ((x)<<MSC_RDN_SHIFT)
-+
-+#define MSC_RDF_SHIFT 4
-+#define MSC_RDF(x) ((x)<<MSC_RDF_SHIFT)
-+
-+#define MSC_RBW_SHIFT 3
-+#define MSC_RBW(x) ((x)<<MSC_RBW_SHIFT)
-+#define MSC_RBW_16 MSC_RBW(1)
-+#define MSC_RBW_32 MSC_RBW(0)
-+
-+#define MSC_RT_SHIFT 0
-+#define MSC_RT(x) ((x)<<MSC_RT_SHIFT)
-+
-+
-+/*
-+ * Bit masks for various registers
-+ */
-+// TRIZEPS2_BCR_PCCARD_PWR
-+#define PCC_3V (1 << 0)
-+#define PCC_5V (1 << 1)
-+#define PCC_EN1 (1 << 2)
-+#define PCC_EN0 (1 << 3)
-+
-+// TRIZEPS2_BCR_PCCARD_EN
-+#define PCC_RESET (1 << 6)
-+#define PCC_ENABLE (1 << 0)
-+
-+// TRIZEPS2_BSR_PCCARDx_STATUS
-+#define _PCC_WRPROT (1 << 7) // 7-4 read as low true
-+#define _PCC_RESET (1 << 6)
-+#define _PCC_IRQ (1 << 5)
-+#define _PCC_INPACK (1 << 4)
-+#define PCC_BVD1 (1 << 0)
-+#define PCC_BVD2 (1 << 1)
-+#define PCC_VS1 (1 << 2)
-+#define PCC_VS2 (1 << 3)
-+
-+// TRIZEPS2_BCR_CONTROL bits
-+#define BCR_LCD_ON (1 << 4)
-+#define BCR_LCD_OFF (0)
-+#define BCR_LCD_MASK (1 << 4)
-+#define BCR_PCMCIA_RESET (1 << 7)
-+#define BCR_PCMCIA_NORMAL (0)
-+
-+#define PCC_DETECT (GPLR(24) & GPIO_bit(24))
-+#define PCC_READY (GPLR(1) & GPIO_bit(1))
-+
-+// Board Control Register
-+#define _TRIZEPS2_BCR_CONTROL (TRIZEPS2_BCR_PHYS)
-+#define TRIZEPS2_BCR_CONTROL __BCR_REG(_TRIZEPS2_BCR_CONTROL)
-+
-+// Board TTL-IO register
-+#define TRIZEPS2_TTLIO_PHYS (0x0d800000)
-+#define TRIZEPS2_TTLIO_BASE (0xf2000000)
-+// various ioctl cmds
-+#define TTLIO_RESET 0
-+#define TTLIO_GET 1
-+#define TTLIO_SET 2
-+#define TTLIO_UNSET 3
-+
-+/*
-+ * Macros for LCD Driver
-+ */
-+
-+#ifdef CONFIG_FB_PXA
-+
-+#define FB_BACKLIGHT_ON()
-+#define FB_BACKLIGHT_OFF()
-+
-+#define FB_PWR_ON()
-+#define FB_PWR_OFF()
-+
-+#define FB_VLCD_ON() WRITE_TRIZEPS2_BCR(BCR_LCD_ON,BCR_LCD_MASK);
-+#define FB_VLCD_OFF() WRITE_TRIZEPS2_BCR(BCR_LCD_OFF,BCR_LCD_MASK);
-+
-+#endif
-+
-+/* A listing of interrupts used by external hardware devices */
-+
-+#define GPIO_TOUCH_PANEL_IRQ 2
-+#define TOUCH_PANEL_IRQ IRQ_GPIO(GPIO_TOUCH_PANEL_IRQ)
-+#define GPIO_ETHERNET_IRQ 19
-+#define ETHERNET_IRQ IRQ_GPIO(GPIO_ETHERNET_IRQ)
-+#define GPIO_TTLIO_IRQ 23
-+#define TTLIO_IRQ IRQ_GPIO(GPIO_TTLIO_IRQ)
-+
-+#define TOUCH_PANEL_IRQ_EDGE GPIO_FALLING_EDGE
-+#define IDE_IRQ_EDGE GPIO_RISING_EDGE
-+#define ETHERNET_IRQ_EDGE GPIO_RISING_EDGE
-+
-+#define PCMCIA_S_CD_VALID IRQ_GPIO(24)
-+#define PCMCIA_S_CD_VALID_EDGE GPIO_BOTH_EDGES
-+
-+#define PCMCIA_S_RDYINT IRQ_GPIO(1)
-+#define PCMCIA_S_RDYINT_EDGE GPIO_FALLING_EDGE
-+
-+/*
-+ * macros for MTD driver
-+ */
-+
-+#define FLASH_WRITE_PROTECT_DISABLE() // ((TRIZEPS2_CPLD_FLASH_WE) &= ~(0x1))
-+#define FLASH_WRITE_PROTECT_ENABLE() // ((TRIZEPS2_CPLD_FLASH_WE) |= (0x1))
-+
-+/* shadow registers for write only registers */
-+#ifndef __ASSEMBLY__
-+extern unsigned short trizeps2_bcr_shadow;
-+#endif
-+
-+/*
-+ * macros to write to write only register
-+ *
-+ * none of these macros are protected from
-+ * multiple drivers using them in interrupt context.
-+ */
-+
-+#define WRITE_TRIZEPS2_BCR(value, mask) \
-+{\
-+ trizeps2_bcr_shadow = ((value & mask) | (trizeps2_bcr_shadow & ~mask));\
-+ TRIZEPS2_BCR_CONTROL = trizeps2_bcr_shadow;\
-+}
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/uncompress.h
-@@ -0,0 +1,42 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/uncompress.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#define FFUART ((volatile unsigned long *)0x40100000)
-+#define BTUART ((volatile unsigned long *)0x40200000)
-+#define STUART ((volatile unsigned long *)0x40700000)
-+
-+#define UART FFUART
-+
-+
-+static __inline__ void putc(char c)
-+{
-+ while (!(UART[5] & 0x20));
-+ UART[0] = c;
-+}
-+
-+/*
-+ * This does not append a newline
-+ */
-+static void puts(const char *s)
-+{
-+ while (*s) {
-+ putc(*s);
-+ if (*s == '\n')
-+ putc('\r');
-+ s++;
-+ }
-+}
-+
-+/*
-+ * nothing to do
-+ */
-+#define arch_decomp_setup()
-+#define arch_decomp_wdog()
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-pxa/vmalloc.h
-@@ -0,0 +1,23 @@
-+/*
-+ * linux/include/asm-arm/arch-pxa/vmalloc.h
-+ *
-+ * Author: Nicolas Pitre
-+ * Copyright: (C) 2001 MontaVista Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * Just any arbitrary offset to the start of the vmalloc VM area: the
-+ * current 8MB value just means that there will be a 8MB "hole" after the
-+ * physical memory until the kernel virtual memory starts. That means that
-+ * any out-of-bounds memory accesses will hopefully be caught.
-+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
-+ * area for the same reason. ;)
-+ */
-+#define VMALLOC_OFFSET (8*1024*1024)
-+#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-+#define VMALLOC_END (0xe8000000)
---- linux-2.4.27/include/asm-arm/assembler.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/assembler.h
-@@ -13,3 +13,26 @@
-
- #include <asm/proc/ptrace.h>
- #include <asm/proc/assembler.h>
-+
-+/*
-+ * Endian independent macros for shifting bytes within registers.
-+ */
-+#ifndef __ARMEB__
-+#define pull lsr
-+#define push lsl
-+#define byte(x) (x*8)
-+#else
-+#define pull lsl
-+#define push lsr
-+#define byte(x) ((3-x)*8)
-+#endif
-+
-+/*
-+ * Data preload for architectures that support it
-+ */
-+#if __LINUX_ARM_ARCH__ >= 5
-+#define PLD(code...) code
-+#else
-+#define PLD(code...)
-+#endif
-+
---- linux-2.4.27/include/asm-arm/bitops.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/bitops.h
-@@ -91,6 +91,8 @@
- return (((unsigned char *) addr)[nr >> 3] >> (nr & 7)) & 1;
- }
-
-+#if __LINUX_ARM_ARCH__ < 5
-+
- /*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
-@@ -117,6 +119,23 @@
-
- #define ffs(x) generic_ffs(x)
-
-+#else
-+
-+/*
-+ * On ARMv5 and above those functions can be implemented around
-+ * the clz instruction for much better code efficiency.
-+ */
-+
-+extern __inline__ int generic_fls(int x);
-+#define fls(x) \
-+ ( __builtin_constant_p(x) ? generic_fls(x) : \
-+ ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
-+#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
-+#define __ffs(x) (ffs(x) - 1)
-+#define ffz(x) __ffs( ~(x) )
-+
-+#endif
-+
- /*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
---- linux-2.4.27/include/asm-arm/io.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/io.h
-@@ -168,7 +168,7 @@
- * devices. This is the "generic" version. The PCI specific version
- * is in pci.h
- */
--extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
-+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle, unsigned long flags);
- extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
- extern void consistent_sync(void *vaddr, size_t size, int rw);
-
---- linux-2.4.27/include/asm-arm/memory.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/memory.h
-@@ -123,6 +123,9 @@
- ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size)); \
- })
-
-+/* We want large page mapping possible */
-+#define VMALLOC_ALIGN 0x10000
-+
- #endif
-
- /*
---- linux-2.4.27/include/asm-arm/proc-armv/pgtable.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/proc-armv/pgtable.h
-@@ -15,9 +15,6 @@
- #ifndef __ASM_PROC_PGTABLE_H
- #define __ASM_PROC_PGTABLE_H
-
--#include <asm/proc/domain.h>
--#include <asm/arch/vmalloc.h>
--
- /*
- * entries per page directory level: they are two-level, so
- * we don't really have any PMD directory.
-@@ -26,27 +23,92 @@
- #define PTRS_PER_PMD 1
- #define PTRS_PER_PGD 4096
-
--/****************
--* PMD functions *
--****************/
--
--/* PMD types (actually level 1 descriptor) */
--#define PMD_TYPE_MASK 0x0003
--#define PMD_TYPE_FAULT 0x0000
--#define PMD_TYPE_TABLE 0x0001
--#define PMD_TYPE_SECT 0x0002
--#define PMD_UPDATABLE 0x0010
--#define PMD_SECT_CACHEABLE 0x0008
--#define PMD_SECT_BUFFERABLE 0x0004
--#define PMD_SECT_AP_WRITE 0x0400
--#define PMD_SECT_AP_READ 0x0800
-+/*
-+ * Hardware page table definitions.
-+ *
-+ * + Level 1 descriptor (PMD)
-+ * - common
-+ */
-+#define PMD_TYPE_MASK (3 << 0)
-+#define PMD_TYPE_FAULT (0 << 0)
-+#define PMD_TYPE_TABLE (1 << 0)
-+#define PMD_TYPE_SECT (2 << 0)
-+#define PMD_UPDATABLE (1 << 4)
- #define PMD_DOMAIN(x) ((x) << 5)
-+#define PMD_PROTECTION (1 << 9) /* v5 */
-+/*
-+ * - section
-+ */
-+#define PMD_SECT_BUFFERABLE (1 << 2)
-+#define PMD_SECT_CACHEABLE (1 << 3)
-+#define PMD_SECT_AP_WRITE (1 << 10)
-+#define PMD_SECT_AP_READ (1 << 11)
-+#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
-+/*
-+ * - coarse table
-+ */
-+
-+/*
-+ * + Level 2 descriptor (PTE)
-+ * - common
-+ */
-+#define PTE_TYPE_MASK (3 << 0)
-+#define PTE_TYPE_FAULT (0 << 0)
-+#define PTE_TYPE_LARGE (1 << 0)
-+#define PTE_TYPE_SMALL (2 << 0)
-+#define PTE_TYPE_EXT (3 << 0) /* v5 */
-+#define PTE_BUFFERABLE (1 << 2)
-+#define PTE_CACHEABLE (1 << 3)
-+
-+/*
-+ * - extended small page/tiny page
-+ */
-+#define PTE_EXT_AP_UNO_SRO (0 << 4)
-+#define PTE_EXT_AP_UNO_SRW (1 << 4)
-+#define PTE_EXT_AP_URO_SRW (2 << 4)
-+#define PTE_EXT_AP_URW_SRW (3 << 4)
-+#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
-+
-+/*
-+ * - small page
-+ */
-+#define PTE_SMALL_AP_UNO_SRO (0x00 << 4)
-+#define PTE_SMALL_AP_UNO_SRW (0x55 << 4)
-+#define PTE_SMALL_AP_URO_SRW (0xaa << 4)
-+#define PTE_SMALL_AP_URW_SRW (0xff << 4)
-+#define PTE_AP_READ PTE_SMALL_AP_URO_SRW
-+#define PTE_AP_WRITE PTE_SMALL_AP_UNO_SRW
-+
-+/*
-+ * "Linux" PTE definitions.
-+ *
-+ * We keep two sets of PTEs - the hardware and the linux version.
-+ * This allows greater flexibility in the way we map the Linux bits
-+ * onto the hardware tables, and allows us to have YOUNG and DIRTY
-+ * bits.
-+ *
-+ * The PTE table pointer refers to the hardware entries; the "Linux"
-+ * entries are stored 1024 bytes below.
-+ */
-+#define L_PTE_PRESENT (1 << 0)
-+#define L_PTE_YOUNG (1 << 1)
-+#define L_PTE_BUFFERABLE (1 << 2) /* matches PTE */
-+#define L_PTE_CACHEABLE (1 << 3) /* matches PTE */
-+#define L_PTE_USER (1 << 4)
-+#define L_PTE_WRITE (1 << 5)
-+#define L_PTE_EXEC (1 << 6)
-+#define L_PTE_DIRTY (1 << 7)
-+
-+#ifndef __ASSEMBLY__
-+
-+#include <asm/proc/domain.h>
-+#include <asm/arch/vmalloc.h>
-
- #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
- #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
-
- #define pmd_bad(pmd) (pmd_val(pmd) & 2)
--#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp,pmd)
-+#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd)
-
- static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
- {
-@@ -75,49 +137,8 @@
- return __phys_to_virt(ptr);
- }
-
--/****************
--* PTE functions *
--****************/
--
--/* PTE types (actually level 2 descriptor) */
--#define PTE_TYPE_MASK 0x0003
--#define PTE_TYPE_FAULT 0x0000
--#define PTE_TYPE_LARGE 0x0001
--#define PTE_TYPE_SMALL 0x0002
--#define PTE_AP_READ 0x0aa0
--#define PTE_AP_WRITE 0x0550
--#define PTE_CACHEABLE 0x0008
--#define PTE_BUFFERABLE 0x0004
--
- #define set_pte(ptep, pte) cpu_set_pte(ptep,pte)
-
--/* We now keep two sets of ptes - the physical and the linux version.
-- * This gives us many advantages, and allows us greater flexibility.
-- *
-- * The Linux pte's contain:
-- * bit meaning
-- * 0 page present
-- * 1 young
-- * 2 bufferable - matches physical pte
-- * 3 cacheable - matches physical pte
-- * 4 user
-- * 5 write
-- * 6 execute
-- * 7 dirty
-- * 8-11 unused
-- * 12-31 virtual page address
-- *
-- * These are stored at the pte pointer; the physical PTE is at -1024bytes
-- */
--#define L_PTE_PRESENT (1 << 0)
--#define L_PTE_YOUNG (1 << 1)
--#define L_PTE_BUFFERABLE (1 << 2)
--#define L_PTE_CACHEABLE (1 << 3)
--#define L_PTE_USER (1 << 4)
--#define L_PTE_WRITE (1 << 5)
--#define L_PTE_EXEC (1 << 6)
--#define L_PTE_DIRTY (1 << 7)
--
- /*
- * The following macros handle the cache and bufferable bits...
- */
-@@ -162,5 +183,8 @@
- * Mark the prot value as uncacheable and unbufferable.
- */
- #define pgprot_noncached(prot) __pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
-+#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~L_PTE_CACHEABLE)
-+
-+#endif /* __ASSEMBLY__ */
-
- #endif /* __ASM_PROC_PGTABLE_H */
---- linux-2.4.27/include/asm-arm/proc-armv/processor.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/proc-armv/processor.h
-@@ -23,6 +23,9 @@
- #define KERNEL_STACK_SIZE PAGE_SIZE
-
- struct context_save_struct {
-+#ifdef CONFIG_CPU_XSCALE
-+ long long acc0;
-+#endif
- unsigned long cpsr;
- unsigned long r4;
- unsigned long r5;
-@@ -35,7 +38,11 @@
- unsigned long pc;
- };
-
-+#ifdef CONFIG_CPU_XSCALE
-+#define INIT_CSS (struct context_save_struct){ 0, SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-+#else
- #define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-+#endif
-
- #define EXTRA_THREAD_STRUCT \
- unsigned int domain;
---- linux-2.4.27/include/asm-arm/proc-fns.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/proc-fns.h
-@@ -124,6 +124,14 @@
- # define CPU_NAME sa1100
- # endif
- # endif
-+# ifdef CONFIG_CPU_XSCALE
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME xscale
-+# endif
-+# endif
- #endif
-
- #ifndef MULTI_CPU
---- linux-2.4.27/include/asm-arm/procinfo.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/procinfo.h
-@@ -55,7 +55,8 @@
- #define HWCAP_FAST_MULT 16
- #define HWCAP_FPA 32
- #define HWCAP_VFP 64
--#define HWCAP_EDSP 128
-+#define HWCAP_EDSP 128 /* El Segundo */
- #define HWCAP_JAVA 256
-+#define HWCAP_XSCALE 512 /* XScale DSP co-processor */
-
- #endif
---- linux-2.4.27/include/asm-arm/uaccess.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/asm-arm/uaccess.h
-@@ -86,7 +86,7 @@
- __get_user_x(__r1, __p, __e, 1, "lr"); \
- break; \
- case 2: \
-- __get_user_x(__r1, __p, __e, 2, "r2", "lr"); \
-+ __get_user_x(__r1, __p, __e, 2, "ip", "lr"); \
- break; \
- case 4: \
- __get_user_x(__r1, __p, __e, 4, "lr"); \
---- linux-2.4.27/include/linux/cramfs_fs_sb.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/linux/cramfs_fs_sb.h
-@@ -10,6 +10,10 @@
- unsigned long blocks;
- unsigned long files;
- unsigned long flags;
-+#ifdef CONFIG_CRAMFS_LINEAR
-+ unsigned long linear_phys_addr;
-+ char * linear_virt_addr;
-+#endif
- };
-
- #endif
---- linux-2.4.27/include/linux/i2c-id.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/linux/i2c-id.h
-@@ -100,6 +100,10 @@
- #define I2C_DRIVERID_SAA7191 57 /* video decoder */
- #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
-
-+#define I2C_DRIVERID_DS1307 46 /* real time clock: DS1307 */
-+#define I2C_DRIVERID_24LC64 47 /* EEprom 24LC64 */
-+#define I2C_DRIVERID_FM24CLB4 48 /* EEprom FM24CLB4 */
-+
- #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
- #define I2C_DRIVERID_EXP1 0xF1
- #define I2C_DRIVERID_EXP2 0xF2
-@@ -172,6 +176,8 @@
-
- #define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
-
-+#define I2C_ALGO_PXA 0x400000 /* Intel PXA I2C algorithm */
-+
- #define I2C_ALGO_EXP 0x800000 /* experimental */
-
- #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
---- linux-2.4.27/include/linux/serial.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/linux/serial.h
-@@ -75,11 +75,13 @@
- #define PORT_16654 11
- #define PORT_16850 12
- #define PORT_RSA 13 /* RSA-DV II/S card */
--#define PORT_MAX 13
-+#define PORT_PXA 14
-+#define PORT_MAX 14
-
- #define SERIAL_IO_PORT 0
- #define SERIAL_IO_HUB6 1
- #define SERIAL_IO_MEM 2
-+#define SERIAL_IO_MEM32 3
-
- struct serial_uart_config {
- char *name;
---- linux-2.4.27/include/linux/serial_reg.h~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/include/linux/serial_reg.h
-@@ -119,6 +119,14 @@
- #define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
-
- /*
-+ * The Intel PXA250/210 chip defines those bits
-+ */
-+#define UART_IER_DMAE 0x80 /* DMA Requests Enable */
-+#define UART_IER_UUE 0x40 /* UART Unit Enable */
-+#define UART_IER_NRZE 0x20 /* NRZ coding Enable */
-+#define UART_IER_RTOIE 0x10 /* Receiver Time Out Interrupt Enable */
-+
-+/*
- * These are the definitions for the Modem Control Register
- */
- #define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
---- /dev/null
-+++ linux-2.4.27/include/mmc/ioctl.h
-@@ -0,0 +1,25 @@
-+/*
-+ * linux/include/linux/mmc/ioctl.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: ioctl.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_IOCTL_H__
-+#define __MMC_IOCTL_H__
-+
-+#include <asm/ioctl.h>
-+
-+/* IOCTL commands provided by MMC subsystem */
-+#define IOCMMCSTRNSMODE _IOW('I',0x0f01,int)
-+#define IOCMMCGTRNSMODE _IOR('I',0x0f02,int)
-+#define IOCMMCGCARDESC _IOR('I',0x0f03,int) /* FIXME */
-+#define IOCMMCGBLKSZMAX _IOR('I',0x0f04,ssize_t)
-+#define IOCMMCGNOBMAX _IOR('I',0x0f05,ssize_t)
-+
-+#endif /* __MMC_IOCTL_H__ */
---- /dev/null
-+++ linux-2.4.27/include/mmc/mmc.h
-@@ -0,0 +1,143 @@
-+/*
-+ * linux/include/linux/mmc/mmc.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: mmc.h,v 0.2.1.2 2002/07/25 16:29:47 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_H__
-+#define __MMC_H__
-+
-+#include <linux/types.h>
-+#include <mmc/types.h>
-+
-+/*
-+ * MMC card type
-+ */
-+enum _mmc_type {
-+ MMC_CARD_TYPE_RO = 1,
-+ MMC_CARD_TYPE_RW,
-+ MMC_CARD_TYPE_IO
-+};
-+
-+/*
-+ * MMC card state
-+ */
-+enum _mmc_state {
-+ MMC_CARD_STATE_IDLE = 1,
-+ MMC_CARD_STATE_READY,
-+ MMC_CARD_STATE_IDENT,
-+ MMC_CARD_STATE_STNBY,
-+ MMC_CARD_STATE_TRAN,
-+ MMC_CARD_STATE_DATA,
-+ MMC_CARD_STATE_RCV,
-+ MMC_CARD_STATE_DIS,
-+ MMC_CARD_STATE_UNPLUGGED=0xff
-+};
-+
-+/*
-+ * Data transfer mode
-+ */
-+enum _mmc_transfer_mode {
-+ MMC_TRANSFER_MODE_STREAM = 1,
-+ MMC_TRANSFER_MODE_BLOCK_SINGLE,
-+ MMC_TRANSFER_MODE_BLOCK_MULTIPLE,
-+ MMC_TRANSFER_MODE_UNDEFINED = -1
-+};
-+
-+struct _mmc_card_csd_rec { /* CSD register contents */
-+/* FIXME: BYTE_ORDER */
-+ u8 ecc:2,
-+ file_format:2,
-+ tmp_write_protect:1,
-+ perm_write_protect:1,
-+ copy:1,
-+ file_format_grp:1;
-+ u64 content_prot_app:1,
-+ rsvd3:4,
-+ write_bl_partial:1,
-+ write_bl_len:4,
-+ r2w_factor:3,
-+ default_ecc:2,
-+ wp_grp_enable:1,
-+ wp_grp_size:5,
-+ erase_grp_mult:5,
-+ erase_grp_size:5,
-+ c_size_mult:3,
-+ vdd_w_curr_max:3,
-+ vdd_w_curr_min:3,
-+ vdd_r_curr_max:3,
-+ vdd_r_curr_min:3,
-+ c_size:12,
-+ rsvd2:2,
-+ dsr_imp:1,
-+ read_blk_misalign:1,
-+ write_blk_misalign:1,
-+ read_bl_partial:1;
-+
-+ u16 read_bl_len:4,
-+ ccc:12;
-+ u8 tran_speed;
-+ u8 nsac;
-+ u8 taac;
-+ u8 rsvd1:2,
-+ spec_vers:4,
-+ csd_structure:2;
-+};
-+
-+struct _mmc_card_cid_rec { /* CID register contents */
-+/* FIXME: BYTE_ORDER */
-+ u8 mdt_year:4,
-+ mdt_mon:4;
-+ u32 psn;
-+ u8 prv_minor:4,
-+ prv_major:4;
-+ u8 pnm[6];
-+ u16 oid;
-+ u8 mid;
-+};
-+
-+/*
-+ * Public card description
-+ */
-+struct _mmc_card_info_rec {
-+ mmc_type_t type;
-+ mmc_transfer_mode_t transfer_mode; /* current data transfer mode */
-+ __u16 rca; /* card's RCA assigned during initialization */
-+ struct _mmc_card_csd_rec csd;
-+ struct _mmc_card_cid_rec cid;
-+ __u32 tran_speed; /* kbits */
-+ __u16 read_bl_len;
-+ __u16 write_bl_len;
-+ size_t capacity; /* card's capacity in bytes */
-+};
-+
-+/*
-+ * Micsellaneous defines
-+ */
-+#ifndef SEEK_SET
-+#define SEEK_SET (0)
-+#endif
-+
-+#ifndef SEEK_CUR
-+#define SEEK_CUR (1)
-+#endif
-+
-+#ifndef SEEK_END
-+#define SEEK_END (2)
-+#endif
-+
-+#ifndef TRUE
-+#define TRUE (1)
-+#endif
-+
-+#ifndef FALSE
-+#define FALSE (0)
-+#endif
-+
-+#endif /* __MMC_H__ */
---- /dev/null
-+++ linux-2.4.27/include/mmc/types.h
-@@ -0,0 +1,29 @@
-+/*
-+ * linux/include/linux/mmc/types.h
-+ *
-+ * Author: Vladimir Shebordaev
-+ * Copyright: MontaVista Software Inc.
-+ *
-+ * $Id: types.h,v 0.2 2002/07/11 16:28:21 ted Exp ted $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef __MMC_TYPES_H__
-+#define __MMC_TYPES_H__
-+
-+/* MMC card */
-+typedef enum _mmc_type mmc_type_t;
-+typedef enum _mmc_state mmc_state_t;
-+typedef enum _mmc_transfer_mode mmc_transfer_mode_t;
-+
-+typedef struct _mmc_card_csd_rec mmc_card_csd_rec_t;
-+typedef struct _mmc_card_cid_rec mmc_card_cid_rec_t;
-+
-+typedef struct _mmc_card_info_rec mmc_card_info_rec_t;
-+typedef struct _mmc_card_info_rec *mmc_card_info_t;
-+
-+typedef enum _mmc_error mmc_error_t;
-+
-+#endif /* __MMC_TYPES_H__ */
---- /dev/null
-+++ linux-2.4.27/include/video/lcdctrl.h
-@@ -0,0 +1,61 @@
-+/*
-+ * lcdctrl.h
-+ *
-+ * Generic LCD control for brightness, contrast, etc.
-+ * Device specific drivers implement a lcdctrl_device and
-+ * provides access to it via lcdctrl_device_get_ops().
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * History:
-+ * Mar 2002: Initial version [FB]
-+ *
-+ */
-+#ifndef __LCD_CONTROL_H
-+#define __LCD_CONTROL_H
-+
-+#define _LCDCTRL_IOCTL_ON 1
-+#define _LCDCTRL_IOCTL_OFF 2
-+#define _LCDCTRL_IOCTL_INTENSITY 3
-+#define _LCDCTRL_IOCTL_BRIGHTNESS 4
-+#define _LCDCTRL_IOCTL_CONTRAST 5
-+#define _LCDCTRL_IOCTL_GET_BRIGHTNESS 6
-+#define _LCDCTRL_IOCTL_GET_CONTRAST 7
-+#define _LCDCTRL_IOCTL_GET_INTENSITY 8
-+
-+#define _LCD_CONTROL_NAME "lcdctrl"
-+
-+#define LCD_NO_SYNC 0
-+#define LCD_SYNC_NEEDED 1
-+
-+int lcdctrl_enable( void);
-+int lcdctrl_disable( void);
-+
-+/* intensity, contrast, and brightness take values
-+ * between 0..100.
-+ */
-+int lcdctrl_set_intensity( int intensity);
-+int lcdctrl_set_contrast( int contrast, int sync);
-+int lcdctrl_set_brightness( int brightness);
-+
-+int lcdctrl_get_intensity( void);
-+int lcdctrl_get_contrast( void);
-+int lcdctrl_get_brightness( void);
-+
-+struct lcdctrl_device
-+{
-+ int (*init)( int*, int*, int*);
-+ int (*enable)(void);
-+ int (*disable)(void);
-+ int (*set_intensity)( int i);
-+ int (*set_brightness)( int b);
-+ int (*set_contrast)( int c, int sync);
-+};
-+
-+int lcdctrl_init( void);
-+
-+#endif
---- linux-2.4.27/init/do_mounts.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/init/do_mounts.c
-@@ -394,6 +394,16 @@
- }
- #endif
-
-+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
-+static int __init mount_linear_cramfs_root(void)
-+{
-+ void *data = root_mount_data;
-+ if (sys_mount("/dev/root","/root","cramfs",root_mountflags,data) == 0)
-+ return 1;
-+ return 0;
-+}
-+#endif
-+
- static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
- {
- void *handle;
-@@ -759,6 +769,16 @@
-
- static void __init mount_root(void)
- {
-+#ifdef CONFIG_ROOT_CRAMFS_LINEAR
-+ if (ROOT_DEV == MKDEV(0, 0)) {
-+ if (mount_linear_cramfs_root()) {
-+ sys_chdir("/root");
-+ ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
-+ printk("VFS: Mounted root (linear cramfs filesystem).\n");
-+ return;
-+ }
-+ }
-+#endif
- #ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == NFS_MAJOR
- && MINOR(ROOT_DEV) == NFS_MINOR) {
---- linux-2.4.27/mm/memory.c~2.4.27-vrs1-pxa1
-+++ linux-2.4.27/mm/memory.c
-@@ -1018,6 +1018,41 @@
- return 1; /* Minor fault */
-
- bad_wp_page:
-+ if (pte_present(pte) && pte_read(pte)) {
-+ /*
-+ * Handle COW of XIP memory.
-+ * Note that the source memory actually isn't a ram page so
-+ * no struct page is associated to the source pte.
-+ */
-+ char *dst;
-+ int ret;
-+
-+ spin_unlock(&mm->page_table_lock);
-+ new_page = alloc_page(GFP_HIGHUSER);
-+ if (!new_page)
-+ return -1;
-+
-+ /* copy XIP data to memory */
-+ dst = kmap_atomic(new_page, KM_USER0);
-+ ret = copy_from_user(dst, (void*)address, PAGE_SIZE);
-+ kunmap_atomic(dst, KM_USER0);
-+
-+ /* make sure pte didn't change while we dropped the lock */
-+ spin_lock(&mm->page_table_lock);
-+ if (!ret && pte_same(*page_table, pte)) {
-+ ++mm->rss;
-+ break_cow(vma, new_page, address, page_table);
-+ lru_cache_add(new_page);
-+ spin_unlock(&mm->page_table_lock);
-+ return 1; /* Minor fault */
-+ }
-+
-+ /* pte changed: back off */
-+ spin_unlock(&mm->page_table_lock);
-+ page_cache_release(new_page);
-+ return ret ? -1 : 1;
-+ }
-+
- spin_unlock(&mm->page_table_lock);
- printk("do_wp_page: bogus page at address %08lx\n", address);
- return -1;
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1.patch
deleted file mode 100644
index f4118e8de5..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-vrs1.patch
+++ /dev/null
@@ -1,90901 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/Documentation/Configure.help~2.4.27-vrs1
-+++ linux-2.4.27/Documentation/Configure.help
-@@ -4941,6 +4941,13 @@
- Say Y to enable support for Permedia2 AGP frame buffer card from
- 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus.
-
-+Permedia3 support (EXPERIMENTAL)
-+CONFIG_FB_PM3
-+ This is the frame buffer device driver for the 3DLabs Permedia3
-+ chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
-+ similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
-+ and maybe other boards.
-+
- Phase5 CVisionPPC/BVisionPPC support
- CONFIG_FB_PM2_CVPPC
- Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC
-@@ -13338,6 +13345,17 @@
- The module will be called tmspci.o. If you want to compile it
- as a module, say M here and read <file:Documentation/modules.txt>.
-
-+Altera ether00 support
-+CONFIG_ETHER00
-+ This is the driver for Altera's ether00 ethernet mac IP core. Say
-+ Y here if you want to build support for this into the kernel. It
-+ is also available as a module (say M here) that can be inserted/
-+ removed from the kernel at the same time as the PLD is configured.
-+ If this driver is running on an epxa10 development board then it
-+ will generate a suitable hw address based on the board serial
-+ number (MTD support is required for this). Otherwise you will
-+ need to set a suitable hw address using ifconfig.
-+
- Generic TMS380 ISA support
- CONFIG_TMSISA
- This tms380 module supports generic TMS380-based ISA cards.
-@@ -15292,6 +15310,16 @@
- support" be compiled as a module for this driver to be used
- properly.
-
-+Altera's uart00 serial driver
-+CONFIG_SERIAL_UART00
-+ Say Y here if you want to use the hard logic uart on Excalibur. This
-+ driver also supports soft logic implentations of this uart core.
-+
-+Serial console on uart00
-+CONFIG_SERIAL_UART00_CONSOLE
-+ Say Y here if you want to support a serial console on an Excalibur
-+ hard logic uart or uart00 IP core.
-+
- USB ConnectTech WhiteHEAT Serial Driver
- CONFIG_USB_SERIAL_WHITEHEAT
- Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
-@@ -19326,6 +19354,20 @@
- <file:Documentation/modules.txt>.
- The module will be called i2c-velleman.o.
-
-+Guide GPIO adapter
-+CONFIG_I2C_GUIDE
-+ This supports the Iders GUIDE I2C bit-bashing adapter. If you have
-+ selected the GUIDE A07 as your ARM system type, you cannot deselect
-+ this option, as it is required for proper operation of the GUIDE.
-+
-+ This interface uses /dev/i2c-0 (major 89, minor 0).
-+
-+ Say Y if you own such an adapter.
-+
-+ This driver is also available as a module. If you want to compile
-+ it as a module, say M here and read Documentation/modules.txt. The
-+ module will be called i2c-guide.o.
-+
- I2C PCF 8584 interfaces
- CONFIG_I2C_ALGOPCF
- This allows you to use a range of I2C adapters called PCF adapters.
-@@ -20463,6 +20505,17 @@
- <file:Documentation/modules.txt>. The module will be called
- softdog.o.
-
-+SA1100 Internal Watchdog
-+CONFIG_SA1100_WATCHDOG
-+ Watchdog timer embedded into SA11x0 chips. This will reboot your
-+ system when timeout is reached.
-+ NOTE, that once enabled, this timer cannot be disabled.
-+
-+ This driver is also available as a module ( = code which can be
-+ inserted in and removed from the running kernel whenever you want).
-+ If you want to compile it as a module, say M here and read
-+ Documentation/modules.txt. The module will be called sa1100_wdt.o.
-+
- Berkshire Products PC Watchdog
- CONFIG_PCWATCHDOG
- This is the driver for the Berkshire Products PC Watchdog card.
-@@ -22124,6 +22177,30 @@
- from RME. If you want to acess advanced features of the card, read
- Documentation/sound/rme96xx.
-
-+Assabet audio (UDA1341) support
-+CONFIG_SOUND_ASSABET_UDA1341
-+ Say Y or M if you have an Intel Assabet evaluation board and want to
-+ use the Philips UDA 1341 audio chip (the one that drives the stereo
-+ audio output) on the SA1100 SSP port.
-+
-+Compaq iPAQ audio support
-+CONFIG_SOUND_H3600_UDA1341
-+ Say Y or M if you have a Compaq iPaq handheld computer and want to
-+ use its Philips UDA 1341 audio chip.
-+
-+Audio support for SA1111/UDA1341
-+CONFIG_SOUND_SA1111_UDA1341
-+ Say Y or M if you have an SA11x0 system with a Philips UDA 1341
-+ connected to the SA11x1. An example of such a system is the Intel
-+ Assabet evaluation board connected to a Neponset expansion board.
-+
-+Generic DAC on the SA11x0 SSP port
-+CONFIG_SOUND_SA1100SSP
-+ Say Y or M if you have an SA-11x0 system with a DAC on the SSP port.
-+ The LART has an Burr-Brown PCM 1710 digital to analog convertor on
-+ the SSP port, so you want to say Y or M for the LART. It might work
-+ on other SA-1100 platforms, too, but this is not tested.
-+
- Are you using a crosscompiler
- CONFIG_CROSSCOMPILE
- Say Y here if you are compiling the kernel on a different
-@@ -25818,6 +25895,20 @@
- Say Y if configuring for a Pangolin.
- Say N otherwise.
-
-+Shannon
-+CONFIG_SA1100_SHANNON
-+ The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
-+ limited edition webphone produced by Philips. The Shannon is a SA1100
-+ platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
-+ and a telco interface.
-+
-+Simputer
-+CONFIG_SA1100_SIMPUTER
-+ Say Y here if you are using an Intel(R) StrongARM(R) SA-1110
-+ based Simputer. See http://www.simputer.org/ for information
-+ on the Simputer. The Simputer software is actively maintained
-+ by PicoPeta Simputers Pvt. Ltd. (http://www.picopeta.com)
-+
- Victor
- CONFIG_SA1100_VICTOR
- Say Y here if you are using a Visu Aide Intel(R) StrongARM(R)
-@@ -25825,6 +25916,14 @@
- <http://www.visuaide.com/pagevictor.en.html> for information on
- this system.
-
-+Radisys Corp. Tulsa
-+CONFIG_SA1100_PFS168
-+ The Radisys Corp. PFS-168 (aka Tulsa) is an Intel® StrongArm® SA-1110 based
-+ computer which includes the SA-1111 Microprocessor Companion Chip and other
-+ custom I/O designed to add connectivity and multimedia features for vending
-+ and business machine applications. Say Y here if you require support for
-+ this target.
-+
- # Choice: cerf_ram
- Cerf on-board RAM size
- CONFIG_SA1100_CERF_8MB
-@@ -25892,37 +25991,65 @@
- Say Y if you want support for the ARM920T processor.
- Otherwise, say N.
-
--Support ARM1020 processor
--CONFIG_CPU_ARM1020
-- The ARM1020 is the cached version of the ARM10 processor,
-- with an addition of a floating-point unit.
-+Support ARM922T processor
-+CONFIG_CPU_ARM922T
-+ The ARM922T is a version of the ARM920T, but with smaller
-+ instruction and data caches. It is used in Altera's
-+ Excalibur XA device family.
-
-- Say Y if you want support for the ARM1020 processor.
-+ Say Y if you want support for the ARM922T processor.
- Otherwise, say N.
-
--Disable I-Cache
-+Disable instruction cache
- CONFIG_CPU_ICACHE_DISABLE
-- Say Y here to disable the processor instruction cache. Unless
-- you have a reason not to or are unsure, say N.
-+ Say Y here to disable the processor instruction cache. Unless
-+ you have a reason to do this, say N.
-
--Disable D-Cache
-+Disable data cache
- CONFIG_CPU_DCACHE_DISABLE
-- Say Y here to disable the processor data cache. Unless
-- you have a reason not to or are unsure, say N.
-+ Say Y here to disable the processor data cache. Unless
-+ you have a reason to do this, say N.
-
--Force write through D-cache
-+Use data cache in writethrough mode
- CONFIG_CPU_DCACHE_WRITETHROUGH
-- Say Y here to use the data cache in write-through mode. Unless you
-- specifically require this or are unsure, say N.
-+ Say Y here to use the data cache in writethough mode. Unless you
-+ specifically require this, say N.
-
--Round robin I and D cache replacement algorithm
-+Support ARM1020 processor
-+CONFIG_CPU_ARM1020
-+ The ARM1020 is the 32K cached version of the ARM10 processor,
-+ with an addition of a floating-point unit.
-+
-+ Say Y if you want support for the ARM1020 processor.
-+ Otherwise, say N.
-+
-+Support ARM1022 processor
-+CONFIG_CPU_ARM1022
-+ The ARM1022E is the 16K cached version of the ARM10 processor,
-+ with an addition of a floating-point unit.
-+
-+ Say Y if you want support for the ARM1022 processor.
-+ Otherwise, say N.
-+
-+Force round-robin cache line replacement
- CONFIG_CPU_CACHE_ROUND_ROBIN
-- Say Y here to use the predictable round-robin cache replacement
-- policy. Unless you specifically require this or are unsure, say N.
-+ Say Y here to force the caches to use a round-robin
-+ algorithm when picking a cache line to evict. Unless you
-+ specifically require this, say N.
-+
-+Disable the write buffer
-+CONFIG_CPU_WB_DISABLE
-+ Say Y here to turn off the write buffer (if possible)
-+ Unless you specifically require this, say N. Note that
-+ not all ARM processors allow the write buffer to be
-+ disabled.
-
- Disable branch prediction
- CONFIG_CPU_BPREDICT_DISABLE
-- Say Y here to disable branch prediction. If unsure, say N.
-+ The ARM10 family of processors support branch prediction,
-+ which can significantly speed up execution of loops.
-+ Say Y here to disable branch prediction. Unless you
-+ specifically require this, say N.
-
- Compressed boot loader in ROM/flash
- CONFIG_ZBOOT_ROM
-@@ -25969,6 +26096,11 @@
- Say Y here if you are using the inhand electronics OmniMeter. See
- <http://www.inhandelectronics.com/html/omni1.html> for details.
-
-+HP Laboratories BadgePAD 4
-+CONFIG_SA1100_BADGE4
-+ Say Y here if you want to build a kernel for the HP Laboratories
-+ BadgePAD 4.
-+
- Load kernel using Angel Debug Monitor
- CONFIG_ANGELBOOT
- Say Y if you plan to load the kernel using Angel, ARM Ltd's target
-@@ -25981,6 +26113,15 @@
- board includes 2 serial ports, Ethernet, IRDA, and expansion headers.
- It comes with 16 MB SDRAM and 8 MB flash ROM.
-
-+GUIDEA07
-+CONFIG_ARCH_GUIDEA07
-+ Say Y if you are using a GUIDE (A07) board.
-+
-+ This board is based on the cs89712 processor and shares much common
-+ hardware with the CDB89712 configuration. When you select this
-+ option and the CDB89712 becomes enabled also, don't worry. It's
-+ supposed to be that way.
-+
- CLPS-711X internal ROM bootstrap
- CONFIG_EP72XX_ROM_BOOT
- If you say Y here, your CLPS711x-based kernel will use the bootstrap
-@@ -26009,24 +26150,44 @@
- You may say N here if you are going to load the Acorn FPEmulator
- early in the bootup.
-
-+Math emulation 80-bit support
-+CONFIG_FPE_NWFPE_XP
-+ Say Y to include 80-bit support in the kernel floating-point
-+ emulator. Otherwise, only 32 and 64-bit support is compiled in.
-+ Note that gcc does not generate 80-bit operations by default,
-+ so in most cases this option only enlarges the size of the
-+ floating point emulator without any good reason.
-+
-+ You almost surely want to say N here.
-+
- FastFPE math emulation
- CONFIG_FPE_FASTFPE
- Say Y here to include the FAST floating point emulator in the kernel.
-- This is an experimental much faster emulator which has only 32 bit
-- precision for the mantissa. It does not support any exceptions.
-- This makes it very simple, it is approximately 4-8 times faster than
-- NWFPE.
-+ This is an experimental much faster emulator which is written
-+ completely in ARM assembly. All instructions that are not marked as
-+ deprecated in the ARM7500FE data sheet are implemented. It supports
-+ single, double and double extended precision. It does support
-+ exception flags, but not raising exceptions. It gives an average
-+ 5 times speed increase over NWFPE for FP only code.
-+
-+ FastFPE does not require long multiply instruction anymore and is
-+ now suitable for all ARM cpus. The presence of the long multiply
-+ instruction is detected during initialisation and used to speedup
-+ multiply and divide.
-
-- It should be sufficient for most programs. It is definitely not
-- suitable if you do scientific calculations that need double
-- precision for iteration formulas that sum up lots of very small
-- numbers. If you do not feel you need a faster FP emulation you
-- should better choose NWFPE.
-+ Compliance to IEEE Std 754-1985 was verified using the testfloat
-+ program of the SoftFloat package version 2a by John Hauser. All
-+ operations except square root were reported to be compliant. However,
-+ this is not a proof, and especially does not verify the instruction
-+ parser.
-+
-+ You can compile both emulators into the kernel and choose one
-+ of them at boot time by passing "fpe=fastfpe" or "fpe=nwfpe" as
-+ kernel parameter.
-
- It is also possible to say M to build the emulator as a module
-- (fastfpe.o). But keep in mind that you should only load the FP
-- emulator early in the bootup. You should never change from NWFPE to
-- FASTFPE or vice versa in an active system!
-+ (fastfpe.o). This was never tested. Only do it if you know what
-+ you are doing!
-
- DS1620 thermometer support
- CONFIG_DS1620
---- /dev/null
-+++ linux-2.4.27/Documentation/arm/Porting
-@@ -0,0 +1,135 @@
-+Taken from list archive at http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2001-July/004064.html
-+
-+Initial definitions
-+-------------------
-+
-+The following symbol definitions rely on you knowing the translation that
-+__virt_to_phys() does for your machine. This macro converts the passed
-+virtual address to a physical address. Normally, it is simply:
-+
-+ phys = virt - PAGE_OFFSET + PHYS_OFFSET
-+
-+
-+Decompressor Symbols
-+--------------------
-+
-+ZTEXTADDR
-+ Start address of decompressor. There's no point in talking about
-+ virtual or physical addresses here, since the MMU will be off at
-+ the time when you call the decompressor code. You normally call
-+ the kernel at this address to start it booting. This doesn't have
-+ to be located in RAM, it can be in flash or other read-only or
-+ read-write addressable medium.
-+
-+ZBSSADDR
-+ Start address of zero-initialised work area for the decompressor.
-+ This must be pointing at RAM. The decompressor will zero initialise
-+ this for you. Again, the MMU will be off.
-+
-+ZRELADDR
-+ This is the address where the decompressed kernel will be written,
-+ and eventually executed. The following constraint must be valid:
-+
-+ __virt_to_phys(TEXTADDR) == ZRELADDR
-+
-+ The initial part of the kernel is carefully coded to be position
-+ independent.
-+
-+INITRD_PHYS
-+ Physical address to place the initial RAM disk. Only relevant if
-+ you are using the bootpImage stuff (which only works on the old
-+ struct param_struct).
-+
-+INITRD_VIRT
-+ Virtual address of the initial RAM disk. The following constraint
-+ must be valid:
-+
-+ __virt_to_phys(INITRD_VIRT) == INITRD_PHYS
-+
-+PARAMS_PHYS
-+ Physical address of the struct param_struct or tag list, giving the
-+ kernel various parameters about its execution environment.
-+
-+
-+Kernel Symbols
-+--------------
-+
-+PHYS_OFFSET
-+ Physical start address of the first bank of RAM.
-+
-+PAGE_OFFSET
-+ Virtual start address of the first bank of RAM. During the kernel
-+ boot phase, virtual address PAGE_OFFSET will be mapped to physical
-+ address PHYS_OFFSET, along with any other mappings you supply.
-+ This should be the same value as TASK_SIZE.
-+
-+TASK_SIZE
-+ The maximum size of a user process in bytes. Since user space
-+ always starts at zero, this is the maximum address that a user
-+ process can access+1. The user space stack grows down from this
-+ address.
-+
-+ Any virtual address below TASK_SIZE is deemed to be user process
-+ area, and therefore managed dynamically on a process by process
-+ basis by the kernel. I'll call this the user segment.
-+
-+ Anything above TASK_SIZE is common to all processes. I'll call
-+ this the kernel segment.
-+
-+ (In other words, you can't put IO mappings below TASK_SIZE, and
-+ hence PAGE_OFFSET).
-+
-+TEXTADDR
-+ Virtual start address of kernel, normally PAGE_OFFSET + 0x8000.
-+ This is where the kernel image ends up. With the latest kernels,
-+ it must be located at 32768 bytes into a 128MB region. Previous
-+ kernels placed a restriction of 256MB here.
-+
-+DATAADDR
-+ Virtual address for the kernel data segment. Must not be defined
-+ when using the decompressor.
-+
-+VMALLOC_START
-+VMALLOC_END
-+ Virtual addresses bounding the vmalloc() area. There must not be
-+ any static mappings in this area; vmalloc will overwrite them.
-+ The addresses must also be in the kernel segment (see above).
-+ Normally, the vmalloc() area starts VMALLOC_OFFSET bytes above the
-+ last virtual RAM address (found using variable high_memory).
-+
-+VMALLOC_OFFSET
-+ Offset normally incorporated into VMALLOC_START to provide a hole
-+ between virtual RAM and the vmalloc area. We do this to allow
-+ out of bounds memory accesses (eg, something writing off the end
-+ of the mapped memory map) to be caught. Normally set to 8MB.
-+
-+Architecture Specific Macros
-+----------------------------
-+
-+BOOT_MEM(pram,pio,vio)
-+ `pram' specifies the physical start address of RAM. Must always
-+ be present, and should be the same as PHYS_OFFSET.
-+
-+ `pio' is the physical address of an 8MB region containing IO for
-+ use with the debugging macros in arch/arm/kernel/debug-armv.S.
-+
-+ `vio' is the virtual address of the 8MB debugging region.
-+
-+ It is expected that the debugging region will be re-initialised
-+ by the architecture specific code later in the code (via the
-+ MAPIO function).
-+
-+BOOT_PARAMS
-+ Same as, and see PARAMS_PHYS.
-+
-+FIXUP(func)
-+ Machine specific fixups, run before memory subsystems have been
-+ initialised.
-+
-+MAPIO(func)
-+ Machine specific function to map IO areas (including the debug
-+ region above).
-+
-+INITIRQ(func)
-+ Machine specific function to initialise interrupts.
-+
---- /dev/null
-+++ linux-2.4.27/Documentation/arm/mem_alignment
-@@ -0,0 +1,58 @@
-+Too many problems poped up because of unnoticed misaligned memory access in
-+kernel code lately. Therefore the alignment fixup is now unconditionally
-+configured in for SA11x0 based targets. According to Alan Cox, this is a
-+bad idea to configure it out, but Russell King has some good reasons for
-+doing so on some f***ed up ARM architectures like the EBSA110. However
-+this is not the case on many design I'm aware of, like all SA11x0 based
-+ones.
-+
-+Of course this is a bad idea to rely on the alignment trap to perform
-+unaligned memory access in general. If those access are predictable, you
-+are better to use the macros provided by include/asm/unaligned.h. The
-+alignment trap can fixup misaligned access for the exception cases, but at
-+a high performance cost. It better be rare.
-+
-+Now for user space applications, it is possible to configure the alignment
-+trap to SIGBUS any code performing unaligned access (good for debugging bad
-+code), or even fixup the access by software like for kernel code. The later
-+mode isn't recommended for performance reasons (just think about the
-+floating point emulation that works about the same way). Fix your code
-+instead!
-+
-+Please note that randomly changing the behaviour without good thought is
-+real bad - it changes the behaviour of all unaligned instructions in user
-+space, and might cause programs to fail unexpectedly.
-+
-+To change the alignment trap behavior, simply echo a number into
-+/proc/cpu/alignment. The number is made up from various bits:
-+
-+bit behavior when set
-+--- -----------------
-+
-+0 A user process performing an unaligned memory access
-+ will cause the kernel to print a message indicating
-+ process name, pid, pc, instruction, address, and the
-+ fault code.
-+
-+1 The kernel will attempt to fix up the user process
-+ performing the unaligned access. This is of course
-+ slow (think about the floating point emulator) and
-+ not recommended for production use.
-+
-+2 The kernel will send a SIGBUS signal to the user process
-+ performing the unaligned access.
-+
-+Note that not all combinations are supported - only values 0 through 5.
-+(6 and 7 don't make sense).
-+
-+For example, the following will turn on the warnings, but without
-+fixing up or sending SIGBUS signals:
-+
-+ echo 1 > /proc/cpu/alignment
-+
-+You can also read the content of the same file to get statistical
-+information on unaligned access occurrences plus the current mode of
-+operation for user space code.
-+
-+
-+Nicolas Pitre, Mar 13, 2001. Modified Russell King, Nov 30, 2001.
---- /dev/null
-+++ linux-2.4.27/Documentation/arm/memory.txt
-@@ -0,0 +1,74 @@
-+ Kernel Memory Layout on ARM Linux
-+
-+ Russell King <rmk@arm.linux.org.uk>
-+ April 27, 2003 (2.5.68)
-+
-+This document describes the virtual memory layout which the Linux
-+kernel uses for ARM processors. It indicates which regions are
-+free for platforms to use, and which are used by generic code.
-+
-+The ARM CPU is capable of addressing a maximum of 4GB virtual memory
-+space, and this must be shared between user space processes, the
-+kernel, and hardware devices.
-+
-+As the ARM architecture matures, it becomes necessary to reserve
-+certain regions of VM space for use for new facilities; therefore
-+this document may reserve more VM space over time.
-+
-+Start End Use
-+--------------------------------------------------------------------------
-+ffff8000 ffffffff copy_user_page / clear_user_page use.
-+ For SA11xx and Xscale, this is used to
-+ setup a minicache mapping.
-+
-+ffff1000 ffff7fff Reserved.
-+ Platforms must not use this address range.
-+
-+ffff0000 ffff0fff CPU vector page.
-+ The CPU vectors are mapped here if the
-+ CPU supports vector relocation (control
-+ register V bit.)
-+
-+ffe00000 fffeffff Free for platform use, not recommended.
-+
-+ffc00000 ffdfffff 2MB consistent memory mapping.
-+ Memory returned by the consistent_alloc
-+ low level function will be dynamically
-+ mapped here.
-+
-+ff000000 ffbfffff Free for platform use, not recommended.
-+
-+VMALLOC_END ff000000 Free for platform use, recommended.
-+
-+VMALLOC_START VMALLOC_END vmalloc() / ioremap() space.
-+ Memory returned by vmalloc/ioremap will
-+ be dynamically placed in this region.
-+ VMALLOC_START may be based upon the value
-+ of the high_memory variable.
-+
-+PAGE_OFFSET high_memory Kernel direct-mapped RAM region.
-+ This maps the platforms RAM, and typically
-+ maps all platform RAM in a 1:1 relationship.
-+
-+TASK_SIZE PAGE_OFFSET Kernel module space
-+ Kernel modules inserted via insmod are
-+ placed here using dynamic mappings.
-+
-+00001000 TASK_SIZE User space mappings
-+ Per-thread mappings are placed here via
-+ the mmap() system call.
-+
-+00000000 00000fff CPU vector page / null pointer trap
-+ CPUs which do not support vector remapping
-+ place their vector page here. NULL pointer
-+ dereferences by both the kernel and user
-+ space are also caught via this mapping.
-+
-+Please note that mappings which collide with the above areas may result
-+in a non-bootable kernel, or may cause the kernel to (eventually) panic
-+at run time.
-+
-+Since future CPUs may impact the kernel mapping layout, user programs
-+must not access any memory which is not mapped inside their 0x0001000
-+to TASK_SIZE address range. If they wish to access these areas, they
-+must set up their own mappings using open() and mmap().
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq/core.txt
-@@ -0,0 +1,94 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U F r e q C o r e
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+ David Kimdon <dwhedon@debian.org>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. CPUFreq core and interfaces
-+2. CPUFreq notifiers
-+
-+1. General Information
-+=======================
-+
-+The CPUFreq core code is located in linux/kernel/cpufreq.c. This
-+cpufreq code offers a standardized interface for the CPUFreq
-+architecture drivers (those pieces of code that do actual
-+frequency transitions), as well as to "notifiers". These are device
-+drivers or other part of the kernel that need to be informed of
-+policy changes (ex. thermal modules like ACPI) or of all
-+frequency changes (ex. timing code) or even need to force certain
-+speed limits (like LCD drivers on ARM architecture). Additionally, the
-+kernel "constant" loops_per_jiffy is updated on frequency changes
-+here.
-+
-+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
-+which make sure that the cpufreq processor driver is correctly
-+registered with the core, and will not be unloaded until
-+cpufreq_put_cpu is called.
-+
-+2. CPUFreq notifiers
-+====================
-+
-+CPUFreq notifiers conform to the standard kernel notifier interface.
-+See linux/include/linux/notifier.h for details on notifiers.
-+
-+There are two different CPUFreq notifiers - policy notifiers and
-+transition notifiers.
-+
-+
-+2.1 CPUFreq policy notifiers
-+----------------------------
-+
-+These are notified when a new policy is intended to be set. Each
-+CPUFreq policy notifier is called three times for a policy transition:
-+
-+1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if
-+ they see a need for this - may it be thermal considerations or
-+ hardware limitations.
-+
-+2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid
-+ hardware failure.
-+
-+3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy
-+ - if two hardware drivers failed to agree on a new policy before this
-+ stage, the incompatible hardware shall be shut down, and the user
-+ informed of this.
-+
-+The phase is specified in the second argument to the notifier.
-+
-+The third argument, a void *pointer, points to a struct cpufreq_policy
-+consisting of five values: cpu, min, max, policy and max_cpu_freq. min
-+and max are the lower and upper frequencies (in kHz) of the new
-+policy, policy the new policy, cpu the number of the affected CPU or
-+CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported
-+CPU frequency. This value is given for informational purposes only.
-+
-+
-+2.2 CPUFreq transition notifiers
-+--------------------------------
-+
-+These are notified twice when the CPUfreq driver switches the CPU core
-+frequency and this change has any external implications.
-+
-+The second argument specifies the phase - CPUFREQ_PRECHANGE or
-+CPUFREQ_POSTCHANGE.
-+
-+The third argument is a struct cpufreq_freqs with the following
-+values:
-+cpu - number of the affected CPU or CPUFREQ_ALL_CPUS
-+old - old frequency
-+new - new frequency
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq/cpu-drivers.txt
-@@ -0,0 +1,210 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U D r i v e r s
-+
-+ - information for developers -
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. What To Do?
-+1.1 Initialization
-+1.2 Per-CPU Initialization
-+1.3 verify
-+1.4 target or setpolicy?
-+1.5 target
-+1.6 setpolicy
-+2. Frequency Table Helpers
-+
-+
-+
-+1. What To Do?
-+==============
-+
-+So, you just got a brand-new CPU / chipset with datasheets and want to
-+add cpufreq support for this CPU / chipset? Great. Here are some hints
-+on what is neccessary:
-+
-+
-+1.1 Initialization
-+------------------
-+
-+First of all, in an __initcall level 7 or later (preferrably
-+module_init() so that your driver is modularized) function check
-+whether this kernel runs on the right CPU and the right chipset. If
-+so, register a struct cpufreq_driver with the CPUfreq core using
-+cpufreq_register_driver()
-+
-+What shall this struct cpufreq_driver contain?
-+
-+cpufreq_driver.name - The name of this driver.
-+
-+cpufreq_driver.init - A pointer to the per-CPU initialization
-+ function.
-+
-+cpufreq_driver.verify - A pointer to a "verfication" funciton.
-+
-+cpufreq_driver.setpolicy _or_
-+cpufreq_driver.target - See below on the differences.
-+
-+And optionally
-+
-+cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
-+
-+cpufreq_driver.attr - A pointer to a NULL-terminated list of
-+ "struct freq_attr" which allow to
-+ export values to sysfs.
-+
-+
-+1.2 Per-CPU Initialization
-+--------------------------
-+
-+Whenever a new CPU is registered with the device model, or after the
-+cpufreq driver registers itself, the per-CPU initialization fucntion
-+cpufreq_driver.init is called. It takes a struct cpufreq_policy
-+*policy as argument. What to do now?
-+
-+If necessary, activate the CPUfreq support on your CPU (unlock that
-+register etc.).
-+
-+Then, the driver must fill in the following values:
-+
-+policy->cpuinfo.min_freq _and_
-+policy->cpuinfo.max_freq - the minimum and maximum frequency
-+ (in kHz) which is supported by
-+ this CPU
-+policy->cpuinfo.transition_latency the time it takes on this CPU to
-+ switch between two frequencies (if
-+ appropriate, else specify
-+ CPUFREQ_ETERNAL)
-+
-+policy->cur The current operating frequency of
-+ this CPU (if appropriate)
-+policy->min,
-+policy->max,
-+policy->policy and, if neccessary,
-+policy->governor must contain the "default policy" for
-+ this CPU. A few moments later,
-+ cpufreq_driver.verify and either
-+ cpufreq_driver.setpolicy or
-+ cpufreq_driver.target is called with
-+ these values.
-+
-+For setting some of these values, the frequency table helpers might be
-+helpful. See the section 2 for more information on them.
-+
-+
-+1.3 verify
-+------------
-+
-+When the user decides a new policy (consisting of
-+"policy,governor,min,max") shall be set, this policy must be validated
-+so that incompatible values can be corrected. For verifying these
-+values, a frequency table helper and/or the
-+cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
-+int min_freq, unsigned int max_freq) function might be helpful. See
-+section 2 for details on frequency table helpers.
-+
-+You need to make sure that at least one valid frequency (or operating
-+range) is within policy->min and policy->max. If necessary, increase
-+policy->max fist, and only if this is no solution, decreas policy->min.
-+
-+
-+1.4 target or setpolicy?
-+----------------------------
-+
-+Most cpufreq drivers or even most cpu frequency scaling algorithms
-+only allow the CPU to be set to one frequency. For these, you use the
-+->target call.
-+
-+Some cpufreq-capable processors switch the frequency between certain
-+limits on their own. These shall use the ->setpolicy call
-+
-+
-+1.4. target
-+-------------
-+
-+The target call has three arguments: struct cpufreq_policy *policy,
-+unsigned int target_frequency, unsigned int relation.
-+
-+The CPUfreq driver must set the new frequency when called here. The
-+actual frequency must be determined using the following rules:
-+
-+- keep close to "target_freq"
-+- policy->min <= new_freq <= policy->max (THIS MUST BE VALID!!!)
-+- if relation==CPUFREQ_REL_L, try to select a new_freq higher than or equal
-+ target_freq. ("L for lowest, but no lower than")
-+- if relation==CPUFREQ_REL_H, try to select a new_freq lower than or equal
-+ target_freq. ("H for highest, but no higher than")
-+
-+Here again the frequency table helper might assist you - see section 3
-+for details.
-+
-+
-+1.5 setpolicy
-+---------------
-+
-+The setpolicy call only takes a struct cpufreq_policy *policy as
-+argument. You need to set the lower limit of the in-processor or
-+in-chipset dynamic frequency switching to policy->min, the upper limit
-+to policy->max, and -if supported- select a performance-oriented
-+setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a
-+powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check
-+the reference implementation in arch/i386/kernel/cpu/cpufreq/longrun.c
-+
-+
-+
-+2. Frequency Table Helpers
-+==========================
-+
-+As most cpufreq processors only allow for being set to a few specific
-+frequencies, a "frequency table" with some functions might assist in
-+some work of the processor driver. Such a "frequency table" consists
-+of an array of struct cpufreq_freq_table entries, with any value in
-+"index" you want to use, and the corresponding frequency in
-+"frequency". At the end of the table, you need to add a
-+cpufreq_freq_table entry with frequency set to CPUFREQ_TABLE_END. And
-+if you want to skip one entry in the table, set the frequency to
-+CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
-+order.
-+
-+By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table);
-+the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
-+policy->min and policy->max are set to the same values. This is
-+helpful for the per-CPU initialization stage.
-+
-+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table);
-+assures that at least one valid frequency is within policy->min and
-+policy->max, and all other criteria are met. This is helpful for the
-+->verify call.
-+
-+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table,
-+ unsigned int target_freq,
-+ unsigned int relation,
-+ unsigned int *index);
-+
-+is the corresponding frequency table helper for the ->target
-+stage. Just pass the values to this function, and the unsigned int
-+index returns the number of the frequency table entry which contains
-+the frequency the CPU shall be set to. PLEASE NOTE: This is not the
-+"index" which is in this cpufreq_table_entry.index, but instead
-+cpufreq_table[index]. So, the new frequency is
-+cpufreq_table[index].frequency, and the value you stored into the
-+frequency table "index" field is
-+cpufreq_table[index].index.
-+
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq/governors.txt
-@@ -0,0 +1,155 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ C P U F r e q G o v e r n o r s
-+
-+ - information for users and developers -
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. What is a CPUFreq Governor?
-+
-+2. Governors In the Linux Kernel
-+2.1 Performance
-+2.2 Powersave
-+2.3 Userspace
-+
-+3. The Governor Interface in the CPUfreq Core
-+
-+
-+
-+1. What Is A CPUFreq Governor?
-+==============================
-+
-+Most cpufreq drivers (in fact, all except one, longrun) or even most
-+cpu frequency scaling algorithms only offer the CPU to be set to one
-+frequency. In order to offer dynamic frequency scaling, the cpufreq
-+core must be able to tell these drivers of a "target frequency". So
-+these specific drivers will be transformed to offer a "->target"
-+call instead of the existing "->setpolicy" call. For "longrun", all
-+stays the same, though.
-+
-+How to decide what frequency within the CPUfreq policy should be used?
-+That's done using "cpufreq governors". Two are already in this patch
-+-- they're
-+set the frequency statically to the lowest or highest frequency,
-+respectively. At least two more such governors will be ready for
-+addition in the near future, but likely many more as there are various
-+different theories and models about dynamic frequency scaling
-+around. Using such a generic interface as cpufreq offers to scaling
-+governors, these can be tested extensively, and the best one can be
-+selected for each specific use.
-+
-+Basically, it's the following flow graph:
-+
-+CPU can be set to switch independetly | CPU can only be set
-+ within specific "limits" | to specific frequencies
-+
-+ "CPUfreq policy"
-+ consists of frequency limits (policy->{min,max})
-+ and CPUfreq governor to be used
-+ / \
-+ / \
-+ / the cpufreq governor decides
-+ / (dynamically or statically)
-+ / what target_freq to set within
-+ / the limits of policy->{min,max}
-+ / \
-+ / \
-+ Using the ->setpolicy call, Using the ->target call,
-+ the limits and the the frequency closest
-+ "policy" is set. to target_freq is set.
-+ It is assured that it
-+ is within policy->{min,max}
-+
-+
-+2. Governors In the Linux Kernel
-+================================
-+
-+2.1 Performance
-+---------------
-+
-+The CPUfreq governor "performance" sets the CPU statically to the
-+highest frequency within the borders of scaling_min_freq and
-+scaling_max_freq.
-+
-+
-+2.1 Powersave
-+-------------
-+
-+The CPUfreq governor "powersave" sets the CPU statically to the
-+lowest frequency within the borders of scaling_min_freq and
-+scaling_max_freq.
-+
-+
-+2.2 Userspace
-+-------------
-+
-+The CPUfreq governor "userspace" allows the user, or any userspace
-+program running with UID "root", to set the CPU to a specifc frequency
-+by making a sysfs file "scaling_setspeed" available in the CPU-device
-+directory.
-+
-+
-+
-+3. The Governor Interface in the CPUfreq Core
-+=============================================
-+
-+A new governor must register itself with the CPUfreq core using
-+"cpufreq_register_governor". The struct cpufreq_governor, which has to
-+be passed to that function, must contain the following values:
-+
-+governor->name - A unique name for this governor
-+governor->governor - The governor callback function
-+governor->owner - .THIS_MODULE for the governor module (if
-+ appropriate)
-+
-+The governor->governor callback is called with the current (or to-be-set)
-+cpufreq_policy struct for that CPU, and an unsigned int event. The
-+following events are currently defined:
-+
-+CPUFREQ_GOV_START: This governor shall start its duty for the CPU
-+ policy->cpu
-+CPUFREQ_GOV_STOP: This governor shall end its duty for the CPU
-+ policy->cpu
-+CPUFREQ_GOV_LIMITS: The limits for CPU policy->cpu have changed to
-+ policy->min and policy->max.
-+
-+If you need other "events" externally of your driver, _only_ use the
-+cpufreq_governor_l(unsigned int cpu, unsigned int event) call to the
-+CPUfreq core to ensure proper locking.
-+
-+
-+The CPUfreq governor may call the CPU processor driver using one of
-+these two functions:
-+
-+inline int cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation);
-+
-+inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation);
-+
-+target_freq must be within policy->min and policy->max, of course.
-+What's the difference between these two functions? When your governor
-+still is in a direct code path of a call to governor->governor, the
-+cpufreq_driver_sem lock is still held in the cpufreq core, and there's
-+no need to lock it again (in fact, this would cause a deadlock). So
-+use cpufreq_driver_target only in these cases. In all other cases (for
-+example, when there's a "daemonized" function that wakes up every
-+second), use cpufreq_driver_target_l to lock the cpufreq_driver_sem
-+before the command is passed to the cpufreq processor driver.
-+
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq/index.txt
-@@ -0,0 +1,56 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+
-+Documents in this directory:
-+----------------------------
-+core.txt - General description of the CPUFreq core and
-+ of CPUFreq notifiers
-+
-+cpu-drivers.txt - How to implement a new cpufreq processor driver
-+
-+governors.txt - What are cpufreq governors and how to
-+ implement them?
-+
-+index.txt - File index, Mailing list and Links (this document)
-+
-+user-guide.txt - User Guide to CPUFreq
-+
-+
-+Mailing List
-+------------
-+There is a CPU frequency changing CVS commit and general list where
-+you can report bugs, problems or submit patches. To post a message,
-+send an email to cpufreq@www.linux.org.uk, to subscribe go to
-+http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
-+mailing list are available to subscribers at
-+http://www.linux.org.uk/mailman/private/cpufreq/.
-+
-+
-+Links
-+-----
-+the FTP archives:
-+* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
-+
-+how to access the CVS repository:
-+* http://cvs.arm.linux.org.uk/
-+
-+the CPUFreq Mailing list:
-+* http://www.linux.org.uk/mailman/listinfo/cpufreq
-+
-+Clock and voltage scaling for the SA-1100:
-+* http://www.lart.tudelft.nl/projects/scaling
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq/user-guide.txt
-@@ -0,0 +1,166 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+ U S E R G U I D E
-+
-+
-+ Dominik Brodowski <linux@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+Contents:
-+---------
-+1. Supported Architectures and Processors
-+1.1 ARM
-+1.2 x86
-+1.3 sparc64
-+
-+2. "Policy" / "Governor"?
-+2.1 Policy
-+2.2 Governor
-+
-+3. How to change the CPU cpufreq policy and/or speed
-+3.1 Preferred interface: sysfs
-+3.2 Deprecated interfaces
-+
-+
-+
-+1. Supported Architectures and Processors
-+=========================================
-+
-+1.1 ARM
-+-------
-+
-+The following ARM processors are supported by cpufreq:
-+
-+ARM Integrator
-+ARM-SA1100
-+ARM-SA1110
-+
-+
-+1.2 x86
-+-------
-+
-+The following processors for the x86 architecture are supported by cpufreq:
-+
-+AMD Elan - SC400, SC410
-+AMD mobile K6-2+
-+AMD mobile K6-3+
-+Cyrix Media GXm
-+Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets
-+Intel Pentium 4, Intel Xeon
-+National Semiconductors Geode GX
-+Transmeta Crusoe
-+varios processors on some ACPI 2.0-compatible systems [**]
-+
-+[*] only certain Intel mobile PIII processors are supported. If you
-+know that you own a speedstep-capable processor, pass the option
-+"speedstep_coppermine=1" to the module speedstep.o
-+
-+[**] Only if "ACPI Processor Performance States" are available
-+to the ACPI<->BIOS interface.
-+
-+
-+1.3 sparc64
-+-----------
-+
-+The following processors for the sparc64 architecture are supported by
-+cpufreq:
-+
-+UltraSPARC-III
-+
-+
-+
-+2. "Policy" / "Governor" ?
-+==========================
-+
-+Some CPU frequency scaling-capable processor switch between varios
-+frequencies and operating voltages "on the fly" without any kernel or
-+user involvement. This guarantuees very fast switching to a frequency
-+which is high enough to serve the user's needs, but low enough to save
-+power.
-+
-+
-+2.1 Policy
-+----------
-+
-+On these systems, all you can do is select the lower and upper
-+frequency limit as well as whether you want more aggressive
-+power-saving or more instantly avaialble processing power.
-+
-+
-+2.2 Governor
-+------------
-+
-+On all other cpufreq implementations, these boundaries still need to
-+be set. Then, a "governor" must be selected. Such a "governor" decides
-+what speed the processor shall run within the boundaries. One such
-+"governor" is the "userspace" governor. This one allows the user - or
-+a yet-to-implement userspace program - to decide what specific speed
-+the processor shall run at.
-+
-+
-+3. How to change the CPU cpufreq policy and/or speed
-+====================================================
-+
-+3.1 Preferred Interface: sysfs
-+------------------------------
-+
-+The preferred interface is located in the sysfs filesystem. If you
-+mounted it at /sys, the cpufreq interface is located in a subdirectory
-+"cpufreq" within the cpu-device directory
-+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
-+
-+cpuinfo_min_freq : this file shows the minimum operating
-+ frequency the processor can run at(in kHz)
-+cpuinfo_max_freq : this file shows the maximum operating
-+ frequency the processor can run at(in kHz)
-+scaling_driver : this file shows what cpufreq driver is
-+ used to set the frequency on this CPU
-+
-+scaling_available_governors : this file shows the CPUfreq governors
-+ available in this kernel. You can see the
-+ currently activated governor in
-+
-+scaling_governor, and by "echoing" the name of another
-+ governor you can change it. Please note
-+ that some governors won't load - they only
-+ work on some specific architectures or
-+ processors.
-+scaling_min_freq and
-+scaling_max_freq show the current "policy limits" (in
-+ kHz). By echoing new values into these
-+ files, you can change these limits.
-+
-+
-+If you have selected the "userspace" governor which allows you to
-+set the CPU operating frequency to a specific value, you can read out
-+the current frequency in
-+
-+scaling_setspeed. By "echoing" a new frequency into this
-+ you can change the speed of the CPU,
-+ but only within the limits of
-+ scaling_min_freq and scaling_max_freq.
-+
-+
-+3.2 Deprecated Interfaces
-+-------------------------
-+
-+Depending on your kernel configuration, you might find the following
-+cpufreq-related files:
-+/proc/cpufreq
-+/proc/sys/cpu/*/speed
-+/proc/sys/cpu/*/speed-min
-+/proc/sys/cpu/*/speed-max
-+
-+These are files for deprecated interfaces to cpufreq, which offer far
-+less functionality. Because of this, these interfaces aren't described
-+here.
-+
---- /dev/null
-+++ linux-2.4.27/Documentation/cpufreq-old
-@@ -0,0 +1,332 @@
-+ CPU frequency and voltage scaling code in the Linux(TM) kernel
-+
-+
-+ L i n u x C P U F r e q
-+
-+
-+
-+
-+ Dominik Brodowski <devel@brodo.de>
-+
-+
-+
-+ Clock scaling allows you to change the clock speed of the CPUs on the
-+ fly. This is a nice method to save battery power, because the lower
-+ the clock speed, the less power the CPU consumes.
-+
-+
-+
-+Contents:
-+---------
-+1. Supported architectures
-+2. User interface
-+2.1 Sample script for command line interface
-+3. CPUFreq core and interfaces
-+3.1 General information
-+3.2 CPUFreq notifiers
-+3.3 CPUFreq architecture drivers
-+4. Mailing list and Links
-+
-+
-+
-+1. Supported architectures
-+==========================
-+
-+Some architectures detect the lowest and highest possible speed
-+settings, while others rely on user information on this. For the
-+latter, a boot parameter is required, for the former, you can specify
-+one to set the limits between speed settings may occur.
-+The boot parameter has the following syntax:
-+
-+ cpufreq=minspeed-maxspeed
-+
-+with both minspeed and maxspeed being given in kHz. To set the lower
-+limit to 59 MHz and the upper limit to 221 MHz, specify:
-+
-+ cpufreq=59000-221000
-+
-+Check the "Speed Limits Detection" information below on whether
-+the driver detects the lowest and highest allowed speed setting
-+automatically.
-+
-+
-+ARM Integrator:
-+ SA 1100, SA1110
-+--------------------------------
-+ Speed Limits Detection: On Integrators, the minimum speed is set
-+ and the maximum speed has to be specified using the boot
-+ parameter. On SA11x0s, the frequencies are fixed (59 - 287 MHz)
-+
-+
-+AMD Elan:
-+ SC400, SC410
-+--------------------------------
-+ Speed Limits Detection: Not implemented. You need to specify the
-+ minimum and maximum frequency in the boot parameter (see above).
-+
-+
-+VIA Cyrix Longhaul:
-+ VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3,
-+ VIA Cyrix Ezra, VIA Cyrix Ezra-T
-+--------------------------------
-+ Speed Limits Detection: working. No need for boot parameters.
-+ NOTE: Support for certain processors is currently disabled,
-+ waiting on updated docs from VIA.
-+
-+
-+Intel SpeedStep:
-+ certain mobile Intel Pentium III (Coppermine), and all mobile
-+ Intel Pentium III-M (Tulatin) and mobile Intel Pentium 4 P4-Ms.
-+--------------------------------
-+ Speed Limits Detection: working. No need for boot parameters.
-+ NOTE:
-+ 1.) mobile Intel Pentium III (Coppermine):
-+ The SpeedStep interface may only be used on SpeedStep
-+ capable processors. Unforunately, due to lack of documentation,
-+ such detection is not yet possible on mobile Intel PIII
-+ (Coppermine) processors. In order to activate SpeedStep on such a
-+ processor, you have to remove one line manually in
-+ linux/drivers/arch/i386/speedstep.c
-+
-+
-+P4 CPU Clock Modulation:
-+ Intel Pentium 4 Xeon processors
-+--------------------------------
-+ Speed Limits Detection: Not implemented. You need to specify the
-+ minimum and maximum frequency in the boot parameter (see above).
-+
-+
-+
-+2. User Interface
-+=================
-+
-+CPUFreq uses a "sysctl" interface which is located in
-+ /proc/sys/cpu/0/ on UP (uniprocessor) kernels, or
-+ /proc/sys/cpu/any/ on SMP (symmetric multiprocessoring) kernels.
-+
-+
-+In this directory, you will find three files of importance for
-+CPUFreq: speed-max, speed-min, and speed:
-+
-+speed shows the current CPU frequency in kHz,
-+speed-min the minimal supported CPU frequency, and
-+speed-max the maximal supported CPU frequency.
-+
-+Please note that you might have to specify these limits as a boot
-+parameter depending on the architecture (see above).
-+
-+
-+To change the CPU frequency, "echo" the desired CPU frequency (in kHz)
-+to speed. For example, to set the CPU speed to the lowest/highest
-+allowed frequency do:
-+
-+root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed
-+root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed
-+
-+
-+2.1 Sample script for command line interface
-+**********************************************
-+
-+
-+Michael Ossmann <mike@ossmann.com> has written a small command line
-+interface for the infinitely lazy.
-+
-+#!/bin/bash
-+#
-+# /usr/local/bin/freq
-+# simple command line interface to cpufreq
-+
-+[ -n "$1" ] && case "$1" in
-+ "min" )
-+ # set frequency to minimum
-+ cat /proc/sys/cpu/0/speed-min >/proc/sys/cpu/0/speed
-+ ;;
-+ "max" )
-+ # set frequency to maximum
-+ cat /proc/sys/cpu/0/speed-max >/proc/sys/cpu/0/speed
-+ ;;
-+ * )
-+ echo "Usage: $0 [min|max]"
-+ echo " min: set frequency to minimum and display new frequency"
-+ echo " max: set frequency to maximum and display new frequency"
-+ echo " no options: display current frequency"
-+ exit 1
-+ ;;
-+esac
-+
-+# display current frequency
-+cat /proc/sys/cpu/0/speed
-+exit 0
-+
-+
-+
-+3. CPUFreq core and interfaces
-+===============================
-+
-+3.1 General information
-+*************************
-+
-+The CPUFreq core code is located in linux/kernel/cpufreq.c. This
-+cpufreq code offers a standardized interface for the CPUFreq
-+architecture drivers (those pieces of code that do the actual
-+frequency transition), as well as to "notifiers". These are device
-+drivers or other part of the kernel that need to be informed of
-+frequency changes (like timing code) or even need to force certain
-+speed limits (like LCD drivers on ARM architecture). Aditionally, the
-+kernel "constant" loops_per_jiffy is updated on frequency changes
-+here.
-+
-+
-+3.2 CPUFreq notifiers
-+***********************
-+
-+CPUFreq notifiers are kernel code that need to be called to either
-+a) define certain minimum or maximum speed settings,
-+b) be informed of frequency changes in advance of the transition, or
-+c) be informed of frequency changes directly after the transition.
-+
-+A standard kernel notifier interface is offered for this. See
-+linux/include/linux/notifier.h for details on notifiers.
-+
-+
-+Data and value passed to CPUFreq notifiers
-+------------------------------------------
-+The second argument passed to any notifier is an unsigned int stating
-+the phase of the transition:
-+CPUFREQ_MINMAX during the process of determing a valid new CPU
-+ frequency,
-+CPUFREQ_PRECHANGE right before the transition, and
-+CPUFREQ_POSTCHANGE right after the transition.
-+
-+The third argument, a void *pointer, points to a struct
-+cpufreq_freqs. This consists of four values: min, max, cur and new.
-+
-+min and max are the current speed limits. Please note: Never update
-+these values directly, use cpufreq_updateminmax(struct cpufreq_freqs
-+*freqs, unsigned int min, unsigned int max) instead. cur is the
-+current/old speed, and new is the new speed, but might only be valid
-+on CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE.
-+
-+Each notifier gets called all three times on any transition:
-+
-+CPUFREQ_MINMAX
-+Here the notifier is supposed to update the min and max values to the
-+limits the protected device / kernel code needs. As stated above,
-+always use cpufreq_updateminmax for this.
-+
-+CPUFREQ_PRECHANGE
-+CPUFREQ_POSTCHANGE
-+Here the notifier is supposed to update all internal (e.g. device
-+driver) code which is dependend on the CPU frequency.
-+
-+
-+3.3 CPUFreq architecture drivers
-+**********************************
-+
-+CPUFreq architecture drivers are the pieces of kernel code that
-+actually perform CPU frequency transitions. These need to be
-+initialised seperately (seperate initcalls), and may be
-+modularized. They interact with the CPUFreq core in the following way:
-+
-+
-+cpufreq_register()
-+------------------
-+cpufreq_register registers an arch driver to the CPUFreq core. Please
-+note that only one arch driver may be registered at any time, -EBUSY
-+is returned when an arch driver is already registered. The argument to
-+cpufreq_register, cpufreq_driver_t driver, is described later.
-+
-+
-+cpufreq_unregister()
-+--------------------
-+cpufreq_unregister unregisters an arch driver, e.g. on module
-+unloading. Please note that there is no check done that this is called
-+from the driver which actually registered itself to the core, so
-+please only call this function when you are sure the arch driver got
-+registered correctly before.
-+
-+
-+struct cpufreq_driver
-+----------------
-+On initialisation, the arch driver is supposed to pass the following
-+entries in struct cpufreq_driver cpufreq_driver:
-+
-+cpufreq_verify_t validate: This is a pointer to a function with the
-+following definition:
-+ unsigned int validating_function (unsigned int kHz).
-+It is called right before a transition occurs. The proposed new
-+speed setting is passed as an argument in kHz; the validating code
-+should verify this is a valid speed setting which is currently
-+supported by the CPU. It shall return the closest valid CPU frequency
-+in kHz.
-+
-+cpufreq_setspeed_t setspeed: This is a pointer to a function with the
-+following definition:
-+ void setspeed_function (unsigned int kHz).
-+This function shall perform the transition to the new CPU frequency
-+given as argument in kHz. Note that this argument is exactly the same
-+as the one returned by cpufreq_verify_t validate.
-+
-+
-+unsigned int freq.cur: The current CPU core frequency. Note that this
-+is a requirement while the next two entries are optional.
-+
-+
-+unsigned int freq.min (optional): The minimal CPU core frequency this
-+CPU supports. This value may be limited further by the
-+cpufreq_verify_t validate function, and so this value should be the
-+minimal core frequency allowed "theoretically" on this system in this
-+configuration.
-+
-+
-+unsigned int freq.max (optional): The maximum CPU core frequency this
-+CPU supports. This value may be limited further by the
-+cpufreq_verify_t validate function, and so this value should be the
-+maximum core frequency allowed "theoretically" on this system in this
-+configuration.
-+
-+
-+Some Requirements to CPUFreq architecture drivers
-+-------------------------------------------------
-+* Only call cpufreq_register() when the ability to switch CPU
-+ frequencies is _verified_ or can't be missing
-+* cpufreq_unregister() may only be called if cpufreq_register() has
-+ been successfully(!) called before
-+* All CPUs have to be set to the same speed whenever setspeed() is
-+ called
-+* Be aware that there is currently no error management in the
-+ setspeed() code in the CPUFreq core. So only call yourself a
-+ cpufreq_driver if you are really a working cpufreq_driver!
-+
-+
-+
-+4. Mailing list and Links
-+**************************
-+
-+
-+Mailing List
-+------------
-+There is a CPU frequency changing CVS commit and general list where
-+you can report bugs, problems or submit patches. To post a message,
-+send an email to cpufreq@www.linux.org.uk, to subscribe go to
-+http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the
-+mailing list are available to subscribers at
-+http://www.linux.org.uk/mailman/private/cpufreq/.
-+
-+
-+Links
-+-----
-+the FTP archives:
-+* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
-+
-+how to access the CVS repository:
-+* http://www.arm.linux.org.uk/cvs/
-+
-+the CPUFreq Mailing list:
-+* http://www.linux.org.uk/mailman/listinfo/cpufreq
-+
-+Clock and voltage scaling for the SA-1100:
-+* http://www.lart.tudelft.nl/projects/scaling
-+
-+CPUFreq project homepage
-+* http://www.brodo.de/cpufreq/
---- /dev/null
-+++ linux-2.4.27/Documentation/l3/structure
-@@ -0,0 +1,36 @@
-+L3 Bus Driver
-+-------------
-+
-+The structure of the driver is as follows:
-+
-+ +----------+ +----------+ +----------+
-+ | client 1 | | client 2 | | client 3 |
-+ +-----^----+ +----^-----+ +----^-----+
-+ | | |
-+ +-----v--------------v---------------v-----+
-+ | |
-+ +-----^-------+ +-------^-----+
-+ | | core | |
-+ +-----v----+ | | +----v-----+
-+ | device | | | | device |
-+ | driver 1 | | | | driver 2 |
-+ +-----^----+ | | +----^-----+
-+ | | services | |
-+ +-----v-------+ +-------v-----+
-+ | |
-+ +-----------------^----^-------------------+
-+ | |
-+ | +-v---------+
-+ | | algorithm |
-+ | | driver |
-+ | +-v---------+
-+ | |
-+ +-v----v-+
-+ | bus |
-+ | driver |
-+ +--------+
-+
-+Clients talk to the core to attach device drivers and bus adapters, and
-+to instruct device drivers to perform actions. Device drivers then talk
-+to the core to perform L3 bus transactions via the algorithm driver and
-+ultimately bus driver.
---- /dev/null
-+++ linux-2.4.27/Documentation/serial/driver
-@@ -0,0 +1,208 @@
-+
-+ Low Level Serial API
-+ --------------------
-+
-+
-+ $Id: driver,v 1.3 2001/11/24 23:24:47 rmk Exp $
-+
-+
-+This document is meant as a brief overview of some aspects of the new serial
-+driver. It is not complete, any questions you have should be directed to
-+<rmk@arm.linux.org.uk>
-+
-+The reference implementation is contained within serial_amba.c.
-+
-+
-+
-+Low Level Serial Hardware Driver
-+--------------------------------
-+
-+The low level serial hardware driver is responsible for supplying port
-+information (defined by uart_port) and a set of control methods (defined
-+by uart_ops) to the core serial driver. The low level driver is also
-+responsible for handling interrupts for the port, and providing any
-+console support.
-+
-+
-+Console Support
-+---------------
-+
-+The serial core provides a few helper functions. This includes identifing
-+the correct port structure (via uart_get_console) and decoding command line
-+arguments (uart_parse_options).
-+
-+
-+Locking
-+-------
-+
-+Generally, all locking is done by the core driver, except for the interrupt
-+functions. It is the responsibility of the low level hardware driver to
-+perform the necessary locking there using info->lock. (since it is running
-+in an interrupt, you only need to use spin_lock() and spin_unlock() from
-+the interrupt handler).
-+
-+
-+uart_ops
-+--------
-+
-+The uart_ops structure is the main interface between serial_core and the
-+hardware specific driver. It contains all the methods to control the
-+hardware.
-+
-+ tx_empty(port)
-+ This function tests whether the transmitter fifo and shifter
-+ for the port described by 'port' is empty. If it is empty,
-+ this function should return TIOCSER_TEMT, otherwise return 0.
-+ If the port does not support this operation, then it should
-+ return TIOCSER_TEMT.
-+
-+ set_mctrl(port, mctrl)
-+ This function sets the modem control lines for port described
-+ by 'port' to the state described by mctrl. The relevant bits
-+ of mctrl are:
-+ - TIOCM_RTS RTS signal.
-+ - TIOCM_DTR DTR signal.
-+ - TIOCM_OUT1 OUT1 signal.
-+ - TIOCM_OUT2 OUT2 signal.
-+ If the appropriate bit is set, the signal should be driven
-+ active. If the bit is clear, the signal should be driven
-+ inactive.
-+
-+ get_mctrl(port)
-+ Returns the current state of modem control inputs. The state
-+ of the outputs should not be returned, since the core keeps
-+ track of their state. The state information should include:
-+ - TIOCM_DCD state of DCD signal
-+ - TIOCM_CTS state of CTS signal
-+ - TIOCM_DSR state of DSR signal
-+ - TIOCM_RI state of RI signal
-+ The bit is set if the signal is currently driven active. If
-+ the port does not support CTS, DCD or DSR, the driver should
-+ indicate that the signal is permanently active. If RI is
-+ not available, the signal should not be indicated as active.
-+
-+ stop_tx(port,from_tty)
-+ Stop transmitting characters. This might be due to the CTS
-+ line becoming inactive or the tty layer indicating we want
-+ to stop transmission.
-+
-+ start_tx(port,nonempty,from_tty)
-+ start transmitting characters. (incidentally, nonempty will
-+ always be nonzero, and shouldn't be used - it will be dropped).
-+
-+ stop_rx(port)
-+ Stop receiving characters; the port is in the process of
-+ being closed.
-+
-+ enable_ms(port)
-+ Enable the modem status interrupts.
-+
-+ break_ctl(port,ctl)
-+ Control the transmission of a break signal. If ctl is
-+ nonzero, the break signal should be transmitted. The signal
-+ should be terminated when another call is made with a zero
-+ ctl.
-+
-+ startup(port,info)
-+ Grab any interrupt resources and initialise any low level driver
-+ state. Enable the port for reception. It should not activate
-+ RTS nor DTR; this will be done via a separate call to set_mctrl.
-+
-+ shutdown(port,info)
-+ Disable the port, disable any break condition that may be in
-+ effect, and free any interrupt resources. It should not disable
-+ RTS nor DTR; this will have already been done via a separate
-+ call to set_mctrl.
-+
-+ change_speed(port,cflag,iflag,quot)
-+ Change the port parameters, including word length, parity, stop
-+ bits. Update read_status_mask and ignore_status_mask to indicate
-+ the types of events we are interested in receiving. Relevant
-+ cflag bits are:
-+ CSIZE - word size
-+ CSTOPB - 2 stop bits
-+ PARENB - parity enable
-+ PARODD - odd parity (when PARENB is in force)
-+ CREAD - enable reception of characters (if not set,
-+ still receive characters from the port, but
-+ throw them away.
-+ CRTSCTS - if set, enable CTS status change reporting
-+ CLOCAL - if not set, enable modem status change
-+ reporting.
-+ Relevant iflag bits are:
-+ INPCK - enable frame and parity error events to be
-+ passed to the TTY layer.
-+ BRKINT
-+ PARMRK - both of these enable break events to be
-+ passed to the TTY layer.
-+
-+ IGNPAR - ignore parity and framing errors
-+ IGNBRK - ignore break errors, If IGNPAR is also
-+ set, ignore overrun errors as well.
-+ The interaction of the iflag bits is as follows (parity error
-+ given as an example):
-+ Parity error INPCK IGNPAR
-+ None n/a n/a character received
-+ Yes n/a 0 character discarded
-+ Yes 0 1 character received, marked as
-+ TTY_NORMAL
-+ Yes 1 1 character received, marked as
-+ TTY_PARITY
-+
-+ pm(port,state,oldstate)
-+ perform any power management related activities on the specified
-+ port. state indicates the new state (defined by ACPI D0-D3),
-+ oldstate indicates the previous state. Essentially, D0 means
-+ fully on, D3 means powered down.
-+
-+ This function should not be used to grab any resources.
-+
-+ type(port)
-+ Return a pointer to a string constant describing the specified
-+ port, or return NULL, in which case the string 'unknown' is
-+ substituted.
-+
-+ release_port(port)
-+ Release any memory and IO region resources currently in use by
-+ the port.
-+
-+ request_port(port)
-+ Request any memory and IO region resources required by the port.
-+ If any fail, no resources should be registered when this function
-+ returns, and it should return -EBUSY on failure.
-+
-+ config_port(port,type)
-+ Perform any autoconfiguration steps required for the port. `type`
-+ contains a bit mask of the required configuration. UART_CONFIG_TYPE
-+ indicates that the port requires detection and identification.
-+ port->type should be set to the type found, or PORT_UNKNOWN if
-+ no port was detected.
-+
-+ UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal,
-+ which should be probed using standard kernel autoprobing techniques.
-+ This is not necessary on platforms where ports have interrupts
-+ internally hard wired (eg, system on a chip implementations).
-+
-+ verify_port(port,serinfo)
-+ Verify the new serial port information contained within serinfo is
-+ suitable for this port type.
-+
-+ ioctl(port,cmd,arg)
-+ Perform any port specific IOCTLs. IOCTL commands must be defined
-+ using the standard numbering system found in <asm/ioctl.h>
-+
-+
-+Other notes
-+-----------
-+
-+It is intended some day to drop the 'unused' entries from uart_port, and
-+allow low level drivers to register their own individual uart_port's with
-+the core. This will allow drivers to use uart_port as a pointer to a
-+structure containing both the uart_port entry with their own extensions,
-+thus:
-+
-+ struct my_port {
-+ struct uart_port port;
-+ int my_stuff;
-+ };
-+
---- linux-2.4.27/MAINTAINERS~2.4.27-vrs1
-+++ linux-2.4.27/MAINTAINERS
-@@ -262,6 +262,8 @@
- ARM/STRONGARM110 PORT
- P: Russell King
- M: rmk@arm.linux.org.uk
-+P: Vincent Sanders
-+M: vince@arm.linux.org.uk
- L: linux-arm-kernel@lists.arm.linux.org.uk
- W: http://www.arm.linux.org.uk/
- S: Maintained
---- linux-2.4.27/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/Makefile
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 4
- SUBLEVEL = 27
--EXTRAVERSION =
-+EXTRAVERSION = -vrs1
-
- KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
-
-@@ -137,7 +137,9 @@
-
- DRIVERS-$(CONFIG_ACPI_BOOT) += drivers/acpi/acpi.o
- DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
--DRIVERS-y += drivers/char/char.o \
-+DRIVERS-$(CONFIG_L3) += drivers/l3/l3.o
-+DRIVERS-y += drivers/serial/serial.o \
-+ drivers/char/char.o \
- drivers/block/block.o \
- drivers/misc/misc.o \
- drivers/net/net.o
-@@ -161,6 +163,7 @@
- DRIVERS-y += drivers/cdrom/driver.o
- endif
-
-+DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o
- DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o
- DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
- DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
-@@ -194,6 +197,8 @@
- DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
- DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
- DRIVERS-$(CONFIG_CRYPTO) += crypto/crypto.o
-+DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
-+DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o
-
- DRIVERS := $(DRIVERS-y)
-
-@@ -274,11 +279,6 @@
-
- export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
-
--.S.s:
-- $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $<
--.S.o:
-- $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -c -o $*.o $<
--
- Version: dummy
- @rm -f include/linux/compile.h
-
---- linux-2.4.27/Rules.make~2.4.27-vrs1
-+++ linux-2.4.27/Rules.make
-@@ -51,15 +51,15 @@
- #
-
- %.s: %.c
-- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
-+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o $@
-
- %.i: %.c
-- $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
-+ $(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) $< > $@
-
- %.o: %.c
-- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
-+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$(*F)) $(CFLAGS_$@) -c -o $@ $<
- @ ( \
-- echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \
-+ echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$(*F)) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$(*F)) $$(CFLAGS_$@))))' ; \
- echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
- echo 'endif' \
- ) > $(dir $@)/.$(notdir $@).flags
-@@ -272,7 +272,8 @@
- endif # CONFIG_MODVERSIONS
-
- ifneq "$(strip $(export-objs))" ""
--$(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
-+$(export-objs): $(TOPDIR)/include/linux/modversions.h
-+$(export-objs): %.o: %.c
- $(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
- @ ( \
- echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
---- linux-2.4.27/arch/alpha/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/alpha/config.in
-@@ -7,6 +7,7 @@
- define_bool CONFIG_UID16 n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Kernel configuration of Linux for Alpha machines"
-
---- linux-2.4.27/arch/arm/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/Makefile
-@@ -52,7 +52,7 @@
-
- CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
- CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
--AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
-+AFLAGS +=$(apcs-y) $(arch-y) -msoft-float
-
- ifeq ($(CONFIG_CPU_26),y)
- PROCESSOR := armo
---- linux-2.4.27/arch/arm/boot/compressed/head.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/boot/compressed/head.S
-@@ -40,6 +40,14 @@
- .macro writeb, rb
- strb \rb, [r3, #0x3f8 << 2]
- .endm
-+#elif defined(CONFIG_ARCH_RISCSTATION)
-+ .macro loadsp, rb
-+ mov \rb, #0x03000000
-+ orr \rb, \rb, #0x00010000
-+ .endm
-+ .macro writeb, rb
-+ strb \rb, [r3, #0x3f8 << 2]
-+ .endm
- #elif defined(CONFIG_ARCH_INTEGRATOR)
- .macro loadsp, rb
- mov \rb, #0x16000000
-@@ -396,6 +404,20 @@
- mcr p15, 0, r0, c1, c0, 0 @ load control register
- mov pc, r12
-
-+__arm7_cache_on:
-+ mov r12, lr
-+ bl __setup_mmu
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
-+ mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
-+ mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
-+ mov r0, #-1
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access control
-+ mov r0, #0x7d
-+ mcr p15, 0, r0, c1, c0, 0 @ load control register
-+ mov pc, r12
-+
-+
- /*
- * All code following this line is relocatable. It is relocated by
- * the above code to the end of the decompressed kernel image and
-@@ -480,9 +502,9 @@
-
- .word 0x41007000 @ ARM7/710
- .word 0xfff8fe00
-+ b __arm7_cache_on
- b __arm7_cache_off
-- b __arm7_cache_off
-- mov pc, lr
-+ b __armv3_cache_flush
-
- .word 0x41807200 @ ARM720T (writethrough)
- .word 0xffffff00
-@@ -490,14 +512,14 @@
- b __armv4_cache_off
- mov pc, lr
-
-- .word 0x41129200 @ ARM920T
-- .word 0xff00fff0
-+ .word 0x41009200 @ ARM920T, ARM922T, ARM926TEJ-S
-+ .word 0xff00ff90
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
-
-- .word 0x41029220 @ ARM922T
-- .word 0xff00fff0
-+ .word 0x4100a200 @ ARM1020T/E, ARM1022E, ARM1026TEJ-S
-+ .word 0xff00ff90
- b __armv4_cache_on
- b __armv4_cache_off
- b __armv4_cache_flush
---- linux-2.4.27/arch/arm/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/config.in
-@@ -144,6 +144,7 @@
- mainmenu_option next_comment
- comment 'AT91RM9200 Implementations'
- dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
-+dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200
- endmenu
-
- mainmenu_option next_comment
-@@ -189,6 +190,12 @@
- define_bool CONFIG_ARCH_ACORN n
- fi
-
-+if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
-+ define_bool CONFIG_PLD y
-+else
-+ define_bool CONFIG_PLD n
-+fi
-+
- #####################################################################
- # Footbridge support
- if [ "$CONFIG_ARCH_CO285" = "y" -o \
-@@ -315,26 +322,42 @@
- # ARM922T
- if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
- define_bool CONFIG_CPU_ARM922T y
-- define_bool CONFIG_PLD y
- else
-- define_bool CONFIG_CPU_ARM922T n
-- define_bool CONFIG_PLD n
-+ if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM922T(Excalibur) processor' CONFIG_ARM922T
-+ else
-+ define_bool CONFIG_CPU_ARM922T n
-+ fi
- fi
-
- # ARM926T
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-- bool 'Support ARM926T processor' CONFIG_CPU_ARM926T
-+ bool 'Support ARM926TEJ-S processor' CONFIG_CPU_ARM926T
- else
- define_bool CONFIG_CPU_ARM926T n
- fi
-
- # ARM1020
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-- bool 'Support ARM1020 processor' CONFIG_CPU_ARM1020
-+ bool 'Support ARM1020T (Rev0) processor' CONFIG_CPU_ARM1020
- else
- define_bool CONFIG_CPU_ARM1020 n
- fi
-
-+# ARM1020E
-+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM1020E (Rev1) processor' CONFIG_CPU_ARM1020E
-+else
-+ define_bool CONFIG_CPU_ARM1020E n
-+fi
-+
-+# ARM1022
-+if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
-+ bool 'Support ARM1022 processor' CONFIG_CPU_ARM1020E
-+else
-+ define_bool CONFIG_CPU_ARM1022 n
-+fi
-+
- # ARM1026EJ-S
- if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
- bool 'Support ARM1026EJ-S processor' CONFIG_CPU_ARM1026
-@@ -388,25 +411,29 @@
-
- if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
- "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
-- "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
-+ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
-+ "$CONFIG_CPU_ARM1022" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
- dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
- fi
- if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
- "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
-+ "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
- "$CONFIG_CPU_ARM1026" = "y" ]; then
- bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE
- bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE
-- if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then
-+ if [ "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
- bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH
- fi
- fi
- if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" -o \
-+ "$CONFIG_CPU_ARM1020E" = "y" -o "$CONFIG_CPU_ARM1022" = "y" -o \
- "$CONFIG_CPU_ARM1026" = "y" ]; then
- if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
- bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN
- fi
- fi
--if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then
-+if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1020E" = "y" -o \
-+ "$CONFIG_CPU_ARM1026" = "y" -o "$CONFIG_CPU_ARM1022" = "y" ]; then
- bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE
- fi
-
-@@ -491,7 +518,7 @@
- if [ "$CONFIG_FPE_NWFPE" != "n" ]; then
- bool ' Support extended precision' CONFIG_FPE_NWFPE_XP
- fi
--if [ "$CONFIG_CPU_26" = "n" -a "$CONFIG_CPU_32v3" = "n" ]; then
-+if [ "$CONFIG_CPU_26" = "n" ]; then
- dep_tristate 'FastFPE math emulation (EXPERIMENTAL)' CONFIG_FPE_FASTFPE $CONFIG_EXPERIMENTAL
- fi
- choice 'Kernel core (/proc/kcore) format' \
-@@ -514,7 +541,8 @@
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_CDB89712" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
-- "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ "$CONFIG_ARCH_OMAHA" = "y" -o \
-+ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
- bool 'Timer and CPU usage LEDs' CONFIG_LEDS
- if [ "$CONFIG_LEDS" = "y" ]; then
- if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
-@@ -524,7 +552,8 @@
- "$CONFIG_ARCH_SA1100" = "y" -o \
- "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
- "$CONFIG_ARCH_P720T" = "y" -o \
-- "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ "$CONFIG_ARCH_OMAHA" = "y" -o \
-+ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
- bool ' Timer LED' CONFIG_LEDS_TIMER
- bool ' CPU usage LED' CONFIG_LEDS_CPU
- fi
-@@ -729,10 +758,7 @@
- dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
- dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
- dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
--
--int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
--
- endmenu
-
--source crypto/Config.in
- source lib/Config.in
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/config.in.rej
-@@ -0,0 +1,16 @@
-+***************
-+*** 144,149 ****
-+ mainmenu_option next_comment
-+ comment 'AT91RM9200 Implementations'
-+ dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
-+ endmenu
-+
-+ mainmenu_option next_comment
-+--- 144,150 ----
-+ mainmenu_option next_comment
-+ comment 'AT91RM9200 Implementations'
-+ dep_bool ' Atmel AT91RM9200 Development Board' CONFIG_ARCH_AT91RM9200DK $CONFIG_ARCH_AT91RM9200
-++ dep_bool ' Cogent CSB337' CONFIG_MACH_CSB337 $CONFIG_ARCH_AT91RM9200
-+ endmenu
-+
-+ mainmenu_option next_comment
---- linux-2.4.27/arch/arm/def-configs/at91rm9200dk~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/def-configs/at91rm9200dk
-@@ -111,6 +111,7 @@
- # AT91RM9200 Implementations
- #
- CONFIG_ARCH_AT91RM9200DK=y
-+# CONFIG_MACH_CSB337 is not set
-
- #
- # CLPS711X/EP721X Implementations
-@@ -125,6 +126,7 @@
- # CONFIG_ARCH_EP7211 is not set
- # CONFIG_ARCH_EP7212 is not set
- # CONFIG_ARCH_ACORN is not set
-+# CONFIG_PLD is not set
- # CONFIG_FOOTBRIDGE is not set
- # CONFIG_FOOTBRIDGE_HOST is not set
- # CONFIG_FOOTBRIDGE_ADDIN is not set
-@@ -135,9 +137,10 @@
- # CONFIG_CPU_ARM720T is not set
- CONFIG_CPU_ARM920T=y
- # CONFIG_CPU_ARM922T is not set
--# CONFIG_PLD is not set
- # CONFIG_CPU_ARM926T is not set
- # CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1020E is not set
-+# CONFIG_CPU_ARM1022 is not set
- # CONFIG_CPU_ARM1026 is not set
- # CONFIG_CPU_SA110 is not set
- # CONFIG_CPU_SA1100 is not set
-@@ -146,6 +149,7 @@
- # CONFIG_ARM_THUMB is not set
- # CONFIG_CPU_ICACHE_DISABLE is not set
- # CONFIG_CPU_DCACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
- # CONFIG_DISCONTIGMEM is not set
-
- #
-@@ -164,6 +168,7 @@
- # CONFIG_BSD_PROCESS_ACCT is not set
- CONFIG_SYSCTL=y
- CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
- # CONFIG_FPE_FASTFPE is not set
- CONFIG_KCORE_ELF=y
- # CONFIG_KCORE_AOUT is not set
-@@ -173,6 +178,9 @@
- # CONFIG_PM is not set
- # CONFIG_ARTHUR is not set
- CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20210000,3145728 root=/dev/ram rw"
-+CONFIG_LEDS=y
-+CONFIG_LEDS_TIMER=y
-+# CONFIG_LEDS_CPU is not set
- CONFIG_ALIGNMENT_TRAP=y
-
- #
-@@ -204,6 +212,7 @@
- # CONFIG_MTD_CFI_ADV_OPTIONS is not set
- # CONFIG_MTD_CFI_INTELEXT is not set
- CONFIG_MTD_CFI_AMDSTD=y
-+# CONFIG_MTD_CFI_STAA is not set
- # CONFIG_MTD_RAM is not set
- # CONFIG_MTD_ROM is not set
- # CONFIG_MTD_ABSENT is not set
-@@ -230,7 +239,9 @@
- # CONFIG_MTD_AUTCPU12 is not set
- # CONFIG_MTD_EDB7312 is not set
- # CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
- # CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-
- #
- # Self-contained MTD device drivers
-@@ -250,9 +261,9 @@
- # NAND Flash Device Drivers
- #
- CONFIG_MTD_NAND=y
--CONFIG_MTD_NAND_ECC=y
- # CONFIG_MTD_NAND_VERIFY_WRITE is not set
--CONFIG_MTD_AT91_SMARTMEDIA=y
-+CONFIG_MTD_NAND_IDS=y
-+# CONFIG_MTD_AT91_SMARTMEDIA is not set
-
- #
- # Plug and Play configuration
-@@ -269,6 +280,7 @@
- # CONFIG_BLK_CPQ_DA is not set
- # CONFIG_BLK_CPQ_CISS_DA is not set
- # CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_CISS_MONITOR_THREAD is not set
- # CONFIG_BLK_DEV_DAC960 is not set
- # CONFIG_BLK_DEV_UMEM is not set
- # CONFIG_BLK_DEV_LOOP is not set
-@@ -276,6 +288,7 @@
- CONFIG_BLK_DEV_RAM=y
- CONFIG_BLK_DEV_RAM_SIZE=8192
- CONFIG_BLK_DEV_INITRD=y
-+# CONFIG_BLK_STATS is not set
-
- #
- # Multi-device support (RAID and LVM)
-@@ -312,6 +325,12 @@
- # CONFIG_SYN_COOKIES is not set
- # CONFIG_IPV6 is not set
- # CONFIG_KHTTPD is not set
-+
-+#
-+# SCTP Configuration (EXPERIMENTAL)
-+#
-+CONFIG_IPV6_SCTP__=y
-+# CONFIG_IP_SCTP is not set
- # CONFIG_ATM is not set
- # CONFIG_VLAN_8021Q is not set
- # CONFIG_IPX is not set
-@@ -382,10 +401,12 @@
- #
- # CONFIG_ACENIC is not set
- # CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
- # CONFIG_MYRI_SBUS is not set
- # CONFIG_NS83820 is not set
- # CONFIG_HAMACHI is not set
- # CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
- # CONFIG_SK98LIN is not set
- # CONFIG_TIGON3 is not set
- # CONFIG_FDDI is not set
-@@ -455,6 +476,8 @@
- # CONFIG_INPUT_MOUSEDEV is not set
- # CONFIG_INPUT_JOYDEV is not set
- # CONFIG_INPUT_EVDEV is not set
-+# CONFIG_INPUT_UINPUT is not set
-+# CONFIG_INPUT_MX1TS is not set
-
- #
- # Character devices
-@@ -502,6 +525,7 @@
- #
- CONFIG_I2C=y
- # CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_SCx200_ACB is not set
- # CONFIG_I2C_ALGOPCF is not set
- CONFIG_I2C_AT91=y
- CONFIG_I2C_CHARDEV=y
-@@ -528,6 +552,11 @@
- #
- # CONFIG_INPUT_GAMEPORT is not set
- # CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-
- #
- # Watchdog Cards
-@@ -536,12 +565,14 @@
- CONFIG_WATCHDOG_NOWAYOUT=y
- # CONFIG_ACQUIRE_WDT is not set
- # CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM1535_WDT is not set
- # CONFIG_ALIM7101_WDT is not set
- # CONFIG_SC520_WDT is not set
- # CONFIG_PCWATCHDOG is not set
- # CONFIG_21285_WATCHDOG is not set
- # CONFIG_977_WATCHDOG is not set
- # CONFIG_SA1100_WATCHDOG is not set
-+# CONFIG_EPXA_WATCHDOG is not set
- # CONFIG_OMAHA_WATCHDOG is not set
- CONFIG_AT91_WATCHDOG=y
- # CONFIG_EUROTECH_WDT is not set
-@@ -551,11 +582,16 @@
- # CONFIG_MIXCOMWD is not set
- # CONFIG_60XX_WDT is not set
- # CONFIG_SC1200_WDT is not set
-+# CONFIG_SCx200_WDT is not set
- # CONFIG_SOFT_WATCHDOG is not set
- # CONFIG_W83877F_WDT is not set
- # CONFIG_WDT is not set
- # CONFIG_WDTPCI is not set
- # CONFIG_MACHZ_WDT is not set
-+# CONFIG_AMD7XX_TCO is not set
-+# CONFIG_SCx200 is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
- # CONFIG_NVRAM is not set
- # CONFIG_RTC is not set
- CONFIG_AT91_RTC=y
-@@ -568,6 +604,10 @@
- #
- # CONFIG_FTAPE is not set
- # CONFIG_AGP is not set
-+
-+#
-+# Direct Rendering Manager (XFree86 DRI support)
-+#
- # CONFIG_DRM is not set
-
- #
-@@ -579,6 +619,7 @@
- # File systems
- #
- # CONFIG_QUOTA is not set
-+# CONFIG_QFMT_V2 is not set
- # CONFIG_AUTOFS_FS is not set
- # CONFIG_AUTOFS4_FS is not set
- # CONFIG_REISERFS_FS is not set
-@@ -588,6 +629,9 @@
- # CONFIG_ADFS_FS_RW is not set
- # CONFIG_AFFS_FS is not set
- # CONFIG_HFS_FS is not set
-+# CONFIG_HFSPLUS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
- # CONFIG_BFS_FS is not set
- # CONFIG_EXT3_FS is not set
- # CONFIG_JBD is not set
-@@ -605,6 +649,9 @@
- # CONFIG_ISO9660_FS is not set
- # CONFIG_JOLIET is not set
- # CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
- # CONFIG_MINIX_FS is not set
- # CONFIG_VXFS_FS is not set
- # CONFIG_NTFS_FS is not set
-@@ -624,6 +671,11 @@
- # CONFIG_UDF_RW is not set
- # CONFIG_UFS_FS is not set
- # CONFIG_UFS_FS_WRITE is not set
-+# CONFIG_XFS_FS is not set
-+# CONFIG_XFS_QUOTA is not set
-+# CONFIG_XFS_RT is not set
-+# CONFIG_XFS_TRACE is not set
-+# CONFIG_XFS_DEBUG is not set
-
- #
- # Network File Systems
-@@ -632,9 +684,11 @@
- # CONFIG_INTERMEZZO_FS is not set
- # CONFIG_NFS_FS is not set
- # CONFIG_NFS_V3 is not set
-+# CONFIG_NFS_DIRECTIO is not set
- # CONFIG_ROOT_NFS is not set
- # CONFIG_NFSD is not set
- # CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
- # CONFIG_SUNRPC is not set
- # CONFIG_LOCKD is not set
- # CONFIG_SMB_FS is not set
-@@ -648,7 +702,6 @@
- # CONFIG_NCPFS_NLS is not set
- # CONFIG_NCPFS_EXTRAS is not set
- # CONFIG_ZISOFS_FS is not set
--# CONFIG_ZLIB_FS_INFLATE is not set
-
- #
- # Partition Types
-@@ -674,16 +727,18 @@
- # CONFIG_USB_DEBUG is not set
- # CONFIG_USB_DEVICEFS is not set
- # CONFIG_USB_BANDWIDTH is not set
--# CONFIG_USB_LONG_TIMEOUT is not set
- # CONFIG_USB_EHCI_HCD is not set
- # CONFIG_USB_UHCI is not set
- # CONFIG_USB_UHCI_ALT is not set
- # CONFIG_USB_OHCI is not set
- # CONFIG_USB_OHCI_SA1111 is not set
-+# CONFIG_USB_SL811HS_ALT is not set
-+# CONFIG_USB_SL811HS is not set
- CONFIG_USB_OHCI_AT91=y
- # CONFIG_USB_AUDIO is not set
- # CONFIG_USB_EMI26 is not set
- # CONFIG_USB_BLUETOOTH is not set
-+# CONFIG_USB_MIDI is not set
- # CONFIG_USB_STORAGE is not set
- # CONFIG_USB_STORAGE_DEBUG is not set
- # CONFIG_USB_STORAGE_DATAFAB is not set
-@@ -692,6 +747,7 @@
- # CONFIG_USB_STORAGE_DPCM is not set
- # CONFIG_USB_STORAGE_HP8200e is not set
- # CONFIG_USB_STORAGE_SDDR09 is not set
-+# CONFIG_USB_STORAGE_SDDR55 is not set
- # CONFIG_USB_STORAGE_JUMPSHOT is not set
- # CONFIG_USB_ACM is not set
- # CONFIG_USB_PRINTER is not set
-@@ -700,7 +756,10 @@
- # CONFIG_USB_HIDDEV is not set
- # CONFIG_USB_KBD is not set
- # CONFIG_USB_MOUSE is not set
-+# CONFIG_USB_AIPTEK is not set
- # CONFIG_USB_WACOM is not set
-+# CONFIG_USB_KBTAB is not set
-+# CONFIG_USB_POWERMATE is not set
- # CONFIG_USB_DC2XX is not set
- # CONFIG_USB_MDC800 is not set
- # CONFIG_USB_SCANNER is not set
-@@ -718,35 +777,16 @@
- # USB Serial Converter support
- #
- # CONFIG_USB_SERIAL is not set
--# CONFIG_USB_SERIAL_GENERIC is not set
--# CONFIG_USB_SERIAL_BELKIN is not set
--# CONFIG_USB_SERIAL_WHITEHEAT is not set
--# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
--# CONFIG_USB_SERIAL_EMPEG is not set
--# CONFIG_USB_SERIAL_FTDI_SIO is not set
--# CONFIG_USB_SERIAL_VISOR is not set
--# CONFIG_USB_SERIAL_IPAQ is not set
--# CONFIG_USB_SERIAL_IR is not set
--# CONFIG_USB_SERIAL_EDGEPORT is not set
--# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
--# CONFIG_USB_SERIAL_KEYSPAN is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
--# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
--# CONFIG_USB_SERIAL_MCT_U232 is not set
--# CONFIG_USB_SERIAL_KLSI is not set
--# CONFIG_USB_SERIAL_PL2303 is not set
--# CONFIG_USB_SERIAL_CYBERJACK is not set
--# CONFIG_USB_SERIAL_XIRCOM is not set
--# CONFIG_USB_SERIAL_OMNINET is not set
- # CONFIG_USB_RIO500 is not set
- # CONFIG_USB_AUERSWALD is not set
-+# CONFIG_USB_TIGL is not set
- # CONFIG_USB_BRLVGER is not set
-+# CONFIG_USB_LCD is not set
-+
-+#
-+# Support for USB gadgets
-+#
-+# CONFIG_USB_GADGET is not set
-
- #
- # Bluetooth support
-@@ -770,3 +810,10 @@
- CONFIG_DEBUG_LL=y
- # CONFIG_DEBUG_DC21285_PORT is not set
- # CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_CRC32=y
-+# CONFIG_ZLIB_INFLATE is not set
-+# CONFIG_ZLIB_DEFLATE is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/def-configs/csb337
-@@ -0,0 +1,760 @@
-+#
-+# Automatically generated by make menuconfig: don't edit
-+#
-+CONFIG_ARM=y
-+# CONFIG_EISA is not set
-+# CONFIG_SBUS is not set
-+# CONFIG_MCA is not set
-+CONFIG_UID16=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
-+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-+# CONFIG_GENERIC_BUST_SPINLOCK is not set
-+# CONFIG_GENERIC_ISA_DMA is not set
-+
-+#
-+# Code maturity level options
-+#
-+CONFIG_EXPERIMENTAL=y
-+# CONFIG_OBSOLETE is not set
-+
-+#
-+# Loadable module support
-+#
-+CONFIG_MODULES=y
-+# CONFIG_MODVERSIONS is not set
-+CONFIG_KMOD=y
-+
-+#
-+# System Type
-+#
-+# CONFIG_ARCH_ANAKIN is not set
-+# CONFIG_ARCH_ARCA5K is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+# CONFIG_ARCH_EBSA110 is not set
-+# CONFIG_ARCH_CAMELOT is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
-+# CONFIG_ARCH_INTEGRATOR is not set
-+# CONFIG_ARCH_OMAHA is not set
-+# CONFIG_ARCH_L7200 is not set
-+# CONFIG_ARCH_MX1ADS is not set
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_RISCSTATION is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_SHARK is not set
-+CONFIG_ARCH_AT91RM9200=y
-+
-+#
-+# Archimedes/A5000 Implementations
-+#
-+# CONFIG_ARCH_ARC is not set
-+# CONFIG_ARCH_A5K is not set
-+
-+#
-+# Footbridge Implementations
-+#
-+# CONFIG_ARCH_CATS is not set
-+# CONFIG_ARCH_PERSONAL_SERVER is not set
-+# CONFIG_ARCH_EBSA285_ADDIN is not set
-+# CONFIG_ARCH_EBSA285_HOST is not set
-+# CONFIG_ARCH_NETWINDER is not set
-+
-+#
-+# SA11x0 Implementations
-+#
-+# CONFIG_SA1100_ACCELENT is not set
-+# CONFIG_SA1100_ASSABET is not set
-+# CONFIG_ASSABET_NEPONSET is not set
-+# CONFIG_SA1100_ADSAGC is not set
-+# CONFIG_SA1100_ADSBITSY is not set
-+# CONFIG_SA1100_ADSBITSYPLUS is not set
-+# CONFIG_SA1100_BRUTUS is not set
-+# CONFIG_SA1100_CEP is not set
-+# CONFIG_SA1100_CERF is not set
-+# CONFIG_SA1100_H3100 is not set
-+# CONFIG_SA1100_H3600 is not set
-+# CONFIG_SA1100_H3800 is not set
-+# CONFIG_SA1100_H3XXX is not set
-+# CONFIG_H3600_SLEEVE is not set
-+# CONFIG_SA1100_EXTENEX1 is not set
-+# CONFIG_SA1100_FLEXANET is not set
-+# CONFIG_SA1100_FREEBIRD is not set
-+# CONFIG_SA1100_FRODO is not set
-+# CONFIG_SA1100_GRAPHICSCLIENT is not set
-+# CONFIG_SA1100_GRAPHICSMASTER is not set
-+# CONFIG_SA1100_HACKKIT is not set
-+# CONFIG_SA1100_BADGE4 is not set
-+# CONFIG_SA1100_JORNADA720 is not set
-+# CONFIG_SA1100_HUW_WEBPANEL is not set
-+# CONFIG_SA1100_ITSY is not set
-+# CONFIG_SA1100_LART is not set
-+# CONFIG_SA1100_NANOENGINE is not set
-+# CONFIG_SA1100_OMNIMETER is not set
-+# CONFIG_SA1100_PANGOLIN is not set
-+# CONFIG_SA1100_PLEB is not set
-+# CONFIG_SA1100_PT_SYSTEM3 is not set
-+# CONFIG_SA1100_SHANNON is not set
-+# CONFIG_SA1100_SHERMAN is not set
-+# CONFIG_SA1100_SIMPAD is not set
-+# CONFIG_SA1100_SIMPUTER is not set
-+# CONFIG_SA1100_PFS168 is not set
-+# CONFIG_SA1100_VICTOR is not set
-+# CONFIG_SA1100_XP860 is not set
-+# CONFIG_SA1100_YOPY is not set
-+# CONFIG_SA1100_USB is not set
-+# CONFIG_SA1100_USB_NETLINK is not set
-+# CONFIG_SA1100_USB_CHAR is not set
-+# CONFIG_SA1100_SSP is not set
-+
-+#
-+# AT91RM9200 Implementations
-+#
-+# CONFIG_ARCH_AT91RM9200DK is not set
-+CONFIG_MACH_CSB337=y
-+
-+#
-+# CLPS711X/EP721X Implementations
-+#
-+# CONFIG_ARCH_AUTCPU12 is not set
-+# CONFIG_ARCH_CDB89712 is not set
-+# CONFIG_ARCH_CLEP7312 is not set
-+# CONFIG_ARCH_EDB7211 is not set
-+# CONFIG_ARCH_FORTUNET is not set
-+# CONFIG_ARCH_GUIDEA07 is not set
-+# CONFIG_ARCH_P720T is not set
-+# CONFIG_ARCH_EP7211 is not set
-+# CONFIG_ARCH_EP7212 is not set
-+# CONFIG_ARCH_ACORN is not set
-+# CONFIG_PLD is not set
-+# CONFIG_FOOTBRIDGE is not set
-+# CONFIG_FOOTBRIDGE_HOST is not set
-+# CONFIG_FOOTBRIDGE_ADDIN is not set
-+CONFIG_CPU_32=y
-+# CONFIG_CPU_26 is not set
-+# CONFIG_CPU_ARM610 is not set
-+# CONFIG_CPU_ARM710 is not set
-+# CONFIG_CPU_ARM720T is not set
-+CONFIG_CPU_ARM920T=y
-+# CONFIG_CPU_ARM922T is not set
-+# CONFIG_CPU_ARM926T is not set
-+# CONFIG_CPU_ARM1020 is not set
-+# CONFIG_CPU_ARM1020E is not set
-+# CONFIG_CPU_ARM1022 is not set
-+# CONFIG_CPU_ARM1026 is not set
-+# CONFIG_CPU_SA110 is not set
-+# CONFIG_CPU_SA1100 is not set
-+# CONFIG_CPU_32v3 is not set
-+CONFIG_CPU_32v4=y
-+# CONFIG_ARM_THUMB is not set
-+# CONFIG_CPU_ICACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_DISABLE is not set
-+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-+# CONFIG_DISCONTIGMEM is not set
-+
-+#
-+# General setup
-+#
-+# CONFIG_PCI is not set
-+# CONFIG_ISA is not set
-+# CONFIG_ISA_DMA is not set
-+# CONFIG_ZBOOT_ROM is not set
-+CONFIG_ZBOOT_ROM_TEXT=0
-+CONFIG_ZBOOT_ROM_BSS=0
-+# CONFIG_HOTPLUG is not set
-+# CONFIG_PCMCIA is not set
-+CONFIG_NET=y
-+CONFIG_SYSVIPC=y
-+# CONFIG_BSD_PROCESS_ACCT is not set
-+CONFIG_SYSCTL=y
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
-+# CONFIG_FPE_FASTFPE is not set
-+CONFIG_KCORE_ELF=y
-+# CONFIG_KCORE_AOUT is not set
-+# CONFIG_BINFMT_AOUT is not set
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_MISC is not set
-+# CONFIG_PM is not set
-+# CONFIG_ARTHUR is not set
-+CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20210000,3145728 root=/dev/ram rw"
-+# CONFIG_LEDS is not set
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Parallel port support
-+#
-+# CONFIG_PARPORT is not set
-+
-+#
-+# Memory Technology Devices (MTD)
-+#
-+CONFIG_MTD=y
-+# CONFIG_MTD_DEBUG is not set
-+# CONFIG_MTD_PARTITIONS is not set
-+# CONFIG_MTD_CONCAT is not set
-+# CONFIG_MTD_REDBOOT_PARTS is not set
-+# CONFIG_MTD_CMDLINE_PARTS is not set
-+# CONFIG_MTD_AFS_PARTS is not set
-+CONFIG_MTD_CHAR=y
-+CONFIG_MTD_BLOCK=y
-+# CONFIG_FTL is not set
-+# CONFIG_NFTL is not set
-+
-+#
-+# RAM/ROM/Flash chip drivers
-+#
-+CONFIG_MTD_CFI=y
-+CONFIG_MTD_JEDECPROBE=y
-+CONFIG_MTD_GEN_PROBE=y
-+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-+CONFIG_MTD_CFI_INTELEXT=y
-+# CONFIG_MTD_CFI_AMDSTD is not set
-+# CONFIG_MTD_CFI_STAA is not set
-+# CONFIG_MTD_RAM is not set
-+CONFIG_MTD_ROM=y
-+# CONFIG_MTD_ABSENT is not set
-+# CONFIG_MTD_OBSOLETE_CHIPS is not set
-+# CONFIG_MTD_AMDSTD is not set
-+# CONFIG_MTD_SHARP is not set
-+# CONFIG_MTD_JEDEC is not set
-+
-+#
-+# Mapping drivers for chip access
-+#
-+CONFIG_MTD_PHYSMAP=y
-+CONFIG_MTD_PHYSMAP_START=10000000
-+CONFIG_MTD_PHYSMAP_LEN=200000
-+CONFIG_MTD_PHYSMAP_BUSWIDTH=2
-+# CONFIG_MTD_NORA is not set
-+# CONFIG_MTD_ARM_INTEGRATOR is not set
-+# CONFIG_MTD_CDB89712 is not set
-+# CONFIG_MTD_SA1100 is not set
-+# CONFIG_MTD_DC21285 is not set
-+# CONFIG_MTD_IQ80310 is not set
-+# CONFIG_MTD_FORTUNET is not set
-+# CONFIG_MTD_EPXA is not set
-+# CONFIG_MTD_AUTCPU12 is not set
-+# CONFIG_MTD_EDB7312 is not set
-+# CONFIG_MTD_IMPA7 is not set
-+# CONFIG_MTD_CEIVA is not set
-+# CONFIG_MTD_PCI is not set
-+# CONFIG_MTD_PCMCIA is not set
-+
-+#
-+# Self-contained MTD device drivers
-+#
-+# CONFIG_MTD_PMC551 is not set
-+# CONFIG_MTD_SLRAM is not set
-+CONFIG_MTD_AT91_DATAFLASH=y
-+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
-+# CONFIG_MTD_MTDRAM is not set
-+# CONFIG_MTD_BLKMTD is not set
-+# CONFIG_MTD_DOC1000 is not set
-+# CONFIG_MTD_DOC2000 is not set
-+# CONFIG_MTD_DOC2001 is not set
-+# CONFIG_MTD_DOCPROBE is not set
-+
-+#
-+# NAND Flash Device Drivers
-+#
-+CONFIG_MTD_NAND=y
-+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-+CONFIG_MTD_NAND_IDS=y
-+# CONFIG_MTD_AT91_SMARTMEDIA is not set
-+
-+#
-+# Plug and Play configuration
-+#
-+# CONFIG_PNP is not set
-+# CONFIG_ISAPNP is not set
-+
-+#
-+# Block devices
-+#
-+# CONFIG_BLK_DEV_FD is not set
-+# CONFIG_BLK_DEV_XD is not set
-+# CONFIG_PARIDE is not set
-+# CONFIG_BLK_CPQ_DA is not set
-+# CONFIG_BLK_CPQ_CISS_DA is not set
-+# CONFIG_CISS_SCSI_TAPE is not set
-+# CONFIG_CISS_MONITOR_THREAD is not set
-+# CONFIG_BLK_DEV_DAC960 is not set
-+# CONFIG_BLK_DEV_UMEM is not set
-+# CONFIG_BLK_DEV_LOOP is not set
-+# CONFIG_BLK_DEV_NBD is not set
-+CONFIG_BLK_DEV_RAM=y
-+CONFIG_BLK_DEV_RAM_SIZE=8192
-+# CONFIG_BLK_DEV_INITRD is not set
-+# CONFIG_BLK_STATS is not set
-+
-+#
-+# Multi-device support (RAID and LVM)
-+#
-+# CONFIG_MD is not set
-+# CONFIG_BLK_DEV_MD is not set
-+# CONFIG_MD_LINEAR is not set
-+# CONFIG_MD_RAID0 is not set
-+# CONFIG_MD_RAID1 is not set
-+# CONFIG_MD_RAID5 is not set
-+# CONFIG_MD_MULTIPATH is not set
-+# CONFIG_BLK_DEV_LVM is not set
-+
-+#
-+# Networking options
-+#
-+CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+# CONFIG_NETLINK_DEV is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_FILTER is not set
-+CONFIG_UNIX=y
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_INET_ECN is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_IPV6 is not set
-+# CONFIG_KHTTPD is not set
-+
-+#
-+# SCTP Configuration (EXPERIMENTAL)
-+#
-+CONFIG_IPV6_SCTP__=y
-+# CONFIG_IP_SCTP is not set
-+# CONFIG_ATM is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+
-+#
-+# Appletalk devices
-+#
-+# CONFIG_DEV_APPLETALK is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_LLC is not set
-+# CONFIG_NET_DIVERT is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_FASTROUTE is not set
-+# CONFIG_NET_HW_FLOWCONTROL is not set
-+
-+#
-+# QoS and/or fair queueing
-+#
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+
-+#
-+# Network device support
-+#
-+CONFIG_NETDEVICES=y
-+
-+#
-+# ARCnet devices
-+#
-+# CONFIG_ARCNET is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_ETHERTAP is not set
-+
-+#
-+# Ethernet (10 or 100Mbit)
-+#
-+CONFIG_NET_ETHERNET=y
-+# CONFIG_ARM_AM79C961A is not set
-+# CONFIG_ARM_CIRRUS is not set
-+CONFIG_AT91_ETHER=y
-+# CONFIG_AT91_ETHER_RMII is not set
-+# CONFIG_SUNLANCE is not set
-+# CONFIG_SUNBMAC is not set
-+# CONFIG_SUNQE is not set
-+# CONFIG_SUNGEM is not set
-+# CONFIG_NET_VENDOR_3COM is not set
-+# CONFIG_LANCE is not set
-+# CONFIG_NET_VENDOR_SMC is not set
-+# CONFIG_NET_VENDOR_RACAL is not set
-+# CONFIG_NET_ISA is not set
-+# CONFIG_NET_PCI is not set
-+# CONFIG_NET_POCKET is not set
-+
-+#
-+# Ethernet (1000 Mbit)
-+#
-+# CONFIG_ACENIC is not set
-+# CONFIG_DL2K is not set
-+# CONFIG_E1000 is not set
-+# CONFIG_MYRI_SBUS is not set
-+# CONFIG_NS83820 is not set
-+# CONFIG_HAMACHI is not set
-+# CONFIG_YELLOWFIN is not set
-+# CONFIG_R8169 is not set
-+# CONFIG_SK98LIN is not set
-+# CONFIG_TIGON3 is not set
-+# CONFIG_FDDI is not set
-+# CONFIG_HIPPI is not set
-+# CONFIG_PLIP is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+
-+#
-+# Wireless LAN (non-hamradio)
-+#
-+# CONFIG_NET_RADIO is not set
-+
-+#
-+# Token Ring devices
-+#
-+# CONFIG_TR is not set
-+# CONFIG_NET_FC is not set
-+# CONFIG_RCPCI is not set
-+# CONFIG_SHAPER is not set
-+
-+#
-+# Wan interfaces
-+#
-+# CONFIG_WAN is not set
-+
-+#
-+# Amateur Radio support
-+#
-+# CONFIG_HAMRADIO is not set
-+
-+#
-+# IrDA (infrared) support
-+#
-+# CONFIG_IRDA is not set
-+
-+#
-+# ATA/ATAPI/MFM/RLL support
-+#
-+# CONFIG_IDE is not set
-+# CONFIG_BLK_DEV_HD is not set
-+
-+#
-+# SCSI support
-+#
-+# CONFIG_SCSI is not set
-+
-+#
-+# I2O device support
-+#
-+# CONFIG_I2O is not set
-+# CONFIG_I2O_BLOCK is not set
-+# CONFIG_I2O_LAN is not set
-+# CONFIG_I2O_SCSI is not set
-+# CONFIG_I2O_PROC is not set
-+
-+#
-+# ISDN subsystem
-+#
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input core support
-+#
-+# CONFIG_INPUT is not set
-+# CONFIG_INPUT_KEYBDEV is not set
-+# CONFIG_INPUT_MOUSEDEV is not set
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+# CONFIG_INPUT_UINPUT is not set
-+# CONFIG_INPUT_MX1TS is not set
-+
-+#
-+# Character devices
-+#
-+# CONFIG_VT is not set
-+# CONFIG_SERIAL is not set
-+# CONFIG_SERIAL_EXTENDED is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+CONFIG_AT91_SPIDEV=y
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_ANAKIN is not set
-+# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-+# CONFIG_SERIAL_AMBA is not set
-+# CONFIG_SERIAL_AMBA_CONSOLE is not set
-+# CONFIG_SERIAL_CLPS711X is not set
-+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-+# CONFIG_SERIAL_21285 is not set
-+# CONFIG_SERIAL_21285_OLD is not set
-+# CONFIG_SERIAL_21285_CONSOLE is not set
-+# CONFIG_SERIAL_UART00 is not set
-+# CONFIG_SERIAL_UART00_CONSOLE is not set
-+# CONFIG_SERIAL_SA1100 is not set
-+# CONFIG_SERIAL_SA1100_CONSOLE is not set
-+# CONFIG_SERIAL_OMAHA is not set
-+# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-+CONFIG_SERIAL_AT91=y
-+CONFIG_SERIAL_AT91_CONSOLE=y
-+# CONFIG_SERIAL_8250 is not set
-+# CONFIG_SERIAL_8250_CONSOLE is not set
-+# CONFIG_SERIAL_8250_EXTENDED is not set
-+# CONFIG_SERIAL_8250_MANY_PORTS is not set
-+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-+# CONFIG_SERIAL_8250_MULTIPORT is not set
-+# CONFIG_SERIAL_8250_HUB6 is not set
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
-+# CONFIG_UNIX98_PTYS is not set
-+
-+#
-+# I2C support
-+#
-+CONFIG_I2C=y
-+# CONFIG_I2C_ALGOBIT is not set
-+# CONFIG_SCx200_ACB is not set
-+# CONFIG_I2C_ALGOPCF is not set
-+CONFIG_I2C_AT91=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_PROC=y
-+CONFIG_I2C_DS1307=y
-+
-+#
-+# L3 serial bus support
-+#
-+# CONFIG_L3 is not set
-+# CONFIG_L3_ALGOBIT is not set
-+# CONFIG_L3_BIT_SA1100_GPIO is not set
-+# CONFIG_L3_SA1111 is not set
-+# CONFIG_BIT_SA1100_GPIO is not set
-+
-+#
-+# Mice
-+#
-+# CONFIG_BUSMOUSE is not set
-+# CONFIG_MOUSE is not set
-+
-+#
-+# Joysticks
-+#
-+# CONFIG_INPUT_GAMEPORT is not set
-+# CONFIG_QIC02_TAPE is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_IPMI_PANIC_EVENT is not set
-+# CONFIG_IPMI_DEVICE_INTERFACE is not set
-+# CONFIG_IPMI_KCS is not set
-+# CONFIG_IPMI_WATCHDOG is not set
-+
-+#
-+# Watchdog Cards
-+#
-+CONFIG_WATCHDOG=y
-+CONFIG_WATCHDOG_NOWAYOUT=y
-+# CONFIG_ACQUIRE_WDT is not set
-+# CONFIG_ADVANTECH_WDT is not set
-+# CONFIG_ALIM1535_WDT is not set
-+# CONFIG_ALIM7101_WDT is not set
-+# CONFIG_SC520_WDT is not set
-+# CONFIG_PCWATCHDOG is not set
-+# CONFIG_21285_WATCHDOG is not set
-+# CONFIG_977_WATCHDOG is not set
-+# CONFIG_SA1100_WATCHDOG is not set
-+# CONFIG_EPXA_WATCHDOG is not set
-+# CONFIG_OMAHA_WATCHDOG is not set
-+CONFIG_AT91_WATCHDOG=y
-+# CONFIG_EUROTECH_WDT is not set
-+# CONFIG_IB700_WDT is not set
-+# CONFIG_WAFER_WDT is not set
-+# CONFIG_I810_TCO is not set
-+# CONFIG_MIXCOMWD is not set
-+# CONFIG_60XX_WDT is not set
-+# CONFIG_SC1200_WDT is not set
-+# CONFIG_SCx200_WDT is not set
-+# CONFIG_SOFT_WATCHDOG is not set
-+# CONFIG_W83877F_WDT is not set
-+# CONFIG_WDT is not set
-+# CONFIG_WDTPCI is not set
-+# CONFIG_MACHZ_WDT is not set
-+# CONFIG_AMD7XX_TCO is not set
-+# CONFIG_SCx200 is not set
-+# CONFIG_SCx200_GPIO is not set
-+# CONFIG_AMD_PM768 is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_RTC is not set
-+CONFIG_AT91_RTC=y
-+# CONFIG_DTLK is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_APPLICOM is not set
-+
-+#
-+# Ftape, the floppy tape device driver
-+#
-+# CONFIG_FTAPE is not set
-+# CONFIG_AGP is not set
-+
-+#
-+# Direct Rendering Manager (XFree86 DRI support)
-+#
-+# CONFIG_DRM is not set
-+
-+#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+
-+#
-+# File systems
-+#
-+# CONFIG_QUOTA is not set
-+# CONFIG_QFMT_V2 is not set
-+# CONFIG_AUTOFS_FS is not set
-+# CONFIG_AUTOFS4_FS is not set
-+# CONFIG_REISERFS_FS is not set
-+# CONFIG_REISERFS_CHECK is not set
-+# CONFIG_REISERFS_PROC_INFO is not set
-+# CONFIG_ADFS_FS is not set
-+# CONFIG_ADFS_FS_RW is not set
-+# CONFIG_AFFS_FS is not set
-+# CONFIG_HFS_FS is not set
-+# CONFIG_HFSPLUS_FS is not set
-+# CONFIG_BEFS_FS is not set
-+# CONFIG_BEFS_DEBUG is not set
-+# CONFIG_BFS_FS is not set
-+# CONFIG_EXT3_FS is not set
-+# CONFIG_JBD is not set
-+# CONFIG_JBD_DEBUG is not set
-+# CONFIG_FAT_FS is not set
-+# CONFIG_MSDOS_FS is not set
-+# CONFIG_UMSDOS_FS is not set
-+# CONFIG_VFAT_FS is not set
-+# CONFIG_EFS_FS is not set
-+# CONFIG_JFFS_FS is not set
-+# CONFIG_JFFS2_FS is not set
-+# CONFIG_CRAMFS is not set
-+# CONFIG_TMPFS is not set
-+CONFIG_RAMFS=y
-+# CONFIG_ISO9660_FS is not set
-+# CONFIG_JOLIET is not set
-+# CONFIG_ZISOFS is not set
-+# CONFIG_JFS_FS is not set
-+# CONFIG_JFS_DEBUG is not set
-+# CONFIG_JFS_STATISTICS is not set
-+# CONFIG_MINIX_FS is not set
-+# CONFIG_VXFS_FS is not set
-+# CONFIG_NTFS_FS is not set
-+# CONFIG_NTFS_RW is not set
-+# CONFIG_HPFS_FS is not set
-+CONFIG_PROC_FS=y
-+CONFIG_DEVFS_FS=y
-+CONFIG_DEVFS_MOUNT=y
-+# CONFIG_DEVFS_DEBUG is not set
-+# CONFIG_DEVPTS_FS is not set
-+# CONFIG_QNX4FS_FS is not set
-+# CONFIG_QNX4FS_RW is not set
-+# CONFIG_ROMFS_FS is not set
-+CONFIG_EXT2_FS=y
-+# CONFIG_SYSV_FS is not set
-+# CONFIG_UDF_FS is not set
-+# CONFIG_UDF_RW is not set
-+# CONFIG_UFS_FS is not set
-+# CONFIG_UFS_FS_WRITE is not set
-+# CONFIG_XFS_FS is not set
-+# CONFIG_XFS_QUOTA is not set
-+# CONFIG_XFS_RT is not set
-+# CONFIG_XFS_TRACE is not set
-+# CONFIG_XFS_DEBUG is not set
-+
-+#
-+# Network File Systems
-+#
-+# CONFIG_CODA_FS is not set
-+# CONFIG_INTERMEZZO_FS is not set
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V3=y
-+# CONFIG_NFS_DIRECTIO is not set
-+CONFIG_ROOT_NFS=y
-+# CONFIG_NFSD is not set
-+# CONFIG_NFSD_V3 is not set
-+# CONFIG_NFSD_TCP is not set
-+CONFIG_SUNRPC=y
-+CONFIG_LOCKD=y
-+CONFIG_LOCKD_V4=y
-+# CONFIG_SMB_FS is not set
-+# CONFIG_NCP_FS is not set
-+# CONFIG_NCPFS_PACKET_SIGNING is not set
-+# CONFIG_NCPFS_IOCTL_LOCKING is not set
-+# CONFIG_NCPFS_STRONG is not set
-+# CONFIG_NCPFS_NFS_NS is not set
-+# CONFIG_NCPFS_OS2_NS is not set
-+# CONFIG_NCPFS_SMALLDOS is not set
-+# CONFIG_NCPFS_NLS is not set
-+# CONFIG_NCPFS_EXTRAS is not set
-+# CONFIG_ZISOFS_FS is not set
-+
-+#
-+# Partition Types
-+#
-+# CONFIG_PARTITION_ADVANCED is not set
-+CONFIG_MSDOS_PARTITION=y
-+# CONFIG_SMB_NLS is not set
-+# CONFIG_NLS is not set
-+
-+#
-+# Multimedia Capabilities Port drivers
-+#
-+# CONFIG_MCP is not set
-+# CONFIG_MCP_SA1100 is not set
-+# CONFIG_MCP_UCB1200 is not set
-+# CONFIG_MCP_UCB1200_AUDIO is not set
-+# CONFIG_MCP_UCB1200_TS is not set
-+
-+#
-+# USB support
-+#
-+# CONFIG_USB is not set
-+
-+#
-+# Support for USB gadgets
-+#
-+# CONFIG_USB_GADGET is not set
-+
-+#
-+# Bluetooth support
-+#
-+# CONFIG_BLUEZ is not set
-+
-+#
-+# Kernel hacking
-+#
-+CONFIG_FRAME_POINTER=y
-+CONFIG_DEBUG_USER=y
-+# CONFIG_DEBUG_INFO is not set
-+# CONFIG_NO_PGT_CACHE is not set
-+CONFIG_DEBUG_KERNEL=y
-+# CONFIG_DEBUG_SLAB is not set
-+# CONFIG_MAGIC_SYSRQ is not set
-+# CONFIG_DEBUG_SPINLOCK is not set
-+# CONFIG_DEBUG_WAITQ is not set
-+# CONFIG_DEBUG_BUGVERBOSE is not set
-+# CONFIG_DEBUG_ERRORS is not set
-+CONFIG_DEBUG_LL=y
-+# CONFIG_DEBUG_DC21285_PORT is not set
-+# CONFIG_DEBUG_CLPS711X_UART2 is not set
-+
-+#
-+# Library routines
-+#
-+CONFIG_CRC32=y
-+# CONFIG_ZLIB_INFLATE is not set
-+# CONFIG_ZLIB_DEFLATE is not set
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/CPDO.S
-@@ -0,0 +1,1786 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the number
-+represented is infinity if the mantissa is 0, otherwise it is a NaN.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+
-+The parameters to these functions are r0=destination pointer, r1 and r2
-+source pointers. r4 is the instruction. They may use r0-r8, r11. They return
-+to r14, which contains the address of a rounding function. The rounding
-+function expects r0=address, r1-r4=sign, mantissa high, mantissa low,
-+exponent, r5=additional lower mantissa bits.
-+
-+CPDO_rnf_core expects the return address in r14.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_adf
-+CPDO_adf:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+ cmp r11,#0x7fffffff
-+ cmpne r11,#0x80000000
-+ cmpne r4,#0x7fffffff
-+ cmpne r4,#0x80000000
-+ beq CPDO_adf_extra
-+
-+ cmp r1,r6
-+ bne CPDO_suf_s
-+
-+CPDO_adf_s:
-+ subs r6,r4,r11
-+ bmi CPDO_adf_normalize1st
-+
-+CPDO_adf_normalize2nd:
-+ cmp r6,#32
-+ ble CPDO_adf_normalize2nd_1
-+ cmp r6,#64
-+ bgt CPDO_adf_normalize2nd_3
-+
-+CPDO_adf_normalize2nd_2:
-+ sub r6,r6,#32
-+ rsb r11,r6,#32
-+ mov r5,r8,lsr r6
-+ add r5,r5,r7,lsl r11
-+ movs r11,r8,lsl r11
-+ orrne r5,r5,#1
-+ mov r8,r7,lsr r6
-+ mov r7,#0
-+ b CPDO_adf_add
-+
-+CPDO_adf_normalize2nd_1:
-+ rsb r11,r6,#32
-+ mov r5,r8,lsl r11
-+ mov r8,r8,lsr r6
-+ add r8,r8,r7,lsl r11
-+ mov r7,r7,lsr r6
-+ b CPDO_adf_add
-+
-+CPDO_adf_normalize2nd_3:
-+ mov r5,#0x40000000
-+ mov pc,r14
-+
-+CPDO_adf_normalize1st:
-+ mov r4,r11
-+ rsb r6,r6,#0
-+ cmp r6,#32
-+ ble CPDO_adf_normalize1st_1
-+ cmp r6,#64
-+ bgt CPDO_adf_normalize1st_3
-+
-+CPDO_adf_normalize1st_2:
-+ sub r6,r6,#32
-+ rsb r11,r6,#32
-+ mov r5,r3,lsr r6
-+ add r5,r5,r2,lsl r11
-+ movs r11,r3,lsl r11
-+ orrne r5,r5,#1
-+ mov r3,r2,lsr r6
-+ mov r2,#0
-+ b CPDO_adf_add
-+
-+CPDO_adf_normalize1st_1:
-+ rsb r11,r6,#32
-+ mov r5,r3,lsl r11
-+ mov r3,r3,lsr r6
-+ add r3,r3,r2,lsl r11
-+ mov r2,r2,lsr r6
-+ b CPDO_adf_add
-+
-+CPDO_adf_normalize1st_3:
-+ mov r5,#0x40000000
-+ mov r2,r7
-+ mov r3,r8
-+ mov pc,r14
-+
-+CPDO_adf_add:
-+ adds r3,r3,r8
-+ adcs r2,r2,r7
-+ bcc CPDO_adf_add_no_overflow
-+
-+ movs r2,r2,rrx
-+ movs r3,r3,rrx
-+ movs r5,r5,rrx
-+ orrcs r5,r5,#1
-+ add r4,r4,#1
-+
-+CPDO_adf_add_no_overflow:
-+ mov pc,r14
-+
-+CPDO_adf_extra:
-+ cmp r4,#0x7fffffff
-+ beq CPDO_adf_1st_infnan
-+ cmp r11,#0x7fffffff
-+ beq CPDO_adf_2nd_infnan
-+ cmp r11,#0x80000000
-+ beq CPDO_adf_2nd_0
-+
-+CPDO_adf_1st_0:
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11
-+ mov r5,#0
-+ mov pc,r14
-+
-+CPDO_adf_2nd_0:
-+ cmp r4,#0x80000000
-+ beq CPDO_adf_both_0
-+ mov r5,#0
-+ mov pc,r14
-+
-+CPDO_adf_both_0:
-+ cmp r1,r6
-+ beq CPDO_adf_both_0_equal_sign
-+ and r5,r5,#0x00000060
-+ cmp r5,#0x00000040 // rounding mode M?
-+ moveq r1,#0x80000000
-+ movne r1,#0
-+CPDO_adf_both_0_equal_sign:
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_adf_1st_infnan:
-+ cmp r11,#0x7fffffff
-+ beq CPDO_adf_both_infnan
-+CPDO_adf_1st_infnan_entry:
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ moveq pc,r14 // Inf
-+ tst r2,#0x40000000
-+ movne pc,r14 // QNaN
-+CPDO_adf_generate_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,#0xffffffff
-+ mov r4,#0x7fffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1 // set invalid operation flag
-+ str r5,[r10,#128]
-+ mov pc,r14
-+
-+CPDO_adf_2nd_infnan:
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11
-+ b CPDO_adf_1st_infnan_entry
-+
-+CPDO_adf_both_infnan:
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ beq CPDO_adf_1st_inf
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_adf_2nd_inf
-+ tst r2,#0x40000000
-+ tstne r7,#0x40000000
-+ beq CPDO_adf_generate_qnan // at least one is SNaN
-+ orrs r5,r3,r2,lsl#1 // ignore MSB, FIXME! what is going on here?
-+ moveq r1,r6 // if first is not NaN
-+ moveq r2,r7 // give second as result
-+ moveq r3,r8
-+ mov pc,r14
-+
-+CPDO_adf_1st_inf:
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_adf_both_inf
-+ tst r7,#0x40000000
-+ beq CPDO_adf_generate_qnan
-+ mov r1,r6 //if 2nd no SNaN return 2nd
-+ mov r2,r7
-+ mov r3,r8
-+ mov pc,r14
-+
-+CPDO_adf_2nd_inf:
-+ tst r2,#0x40000000
-+ beq CPDO_adf_generate_qnan
-+ mov pc,r14 // if 1st no SNaN just return it
-+
-+CPDO_adf_both_inf:
-+ cmp r1,r6
-+ bne CPDO_adf_generate_qnan // signs of both inf are different
-+ mov pc,r14
-+
-+/*--------------------------------------------------------------------------*/
-+
-+ .globl CPDO_suf
-+CPDO_suf:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+CPDO_suf_l:
-+ cmp r11,#0x7fffffff
-+ cmpne r11,#0x80000000
-+ cmpne r4,#0x7fffffff
-+ cmpne r4,#0x80000000
-+ beq CPDO_suf_extra
-+
-+ cmp r1,r6
-+ bne CPDO_adf_s
-+
-+CPDO_suf_s:
-+ subs r6,r4,r11
-+ blt CPDO_suf_normalize1st
-+ bgt CPDO_suf_normalize2nd
-+ cmp r2,r7
-+ cmpeq r3,r8
-+ beq CPDO_suf_zero
-+ mov r5,#0
-+ bcs CPDO_suf_sub_1stbigger
-+ eor r1,r1,#0x80000000
-+ b CPDO_suf_sub_2ndbigger
-+
-+CPDO_suf_normalize2nd:
-+ cmp r6,#32
-+ ble CPDO_suf_normalize2nd_1
-+ cmp r6,#64
-+ bgt CPDO_suf_normalize2nd_3
-+
-+CPDO_suf_normalize2nd_2:
-+ sub r6,r6,#32
-+ rsb r11,r6,#32
-+ mov r5,r8,lsr r6
-+ add r5,r5,r7,lsl r11
-+ movs r11,r8,lsl r11
-+ orrne r5,r5,#1
-+ mov r8,r7,lsr r6
-+ mov r7,#0
-+ b CPDO_suf_sub_1stbigger
-+
-+CPDO_suf_normalize2nd_1:
-+ rsb r11,r6,#32
-+ mov r5,r8,lsl r11
-+ mov r8,r8,lsr r6
-+ add r8,r8,r7,lsl r11
-+ mov r7,r7,lsr r6
-+ b CPDO_suf_sub_1stbigger
-+
-+CPDO_suf_normalize2nd_3:
-+ sub r6,r6,#64
-+ cmp r6,#32
-+ bge CPDO_suf_normalize2nd_4
-+ rsb r11,r6,#32
-+ mov r5,r7,lsr r6
-+ orrs r11,r8,r7,lsl r11
-+ orrne r5,r5,#1
-+ mov r7,#0
-+ mov r8,#0
-+ b CPDO_suf_sub_1stbigger
-+
-+CPDO_suf_normalize2nd_4:
-+ mov r5,#1
-+ mov r7,#0
-+ mov r8,#0
-+ b CPDO_suf_sub_1stbigger
-+
-+CPDO_suf_normalize1st:
-+ eor r1,r1,#0x80000000
-+ mov r4,r11
-+ rsb r6,r6,#0
-+ cmp r6,#32
-+ ble CPDO_suf_normalize1st_1
-+ cmp r6,#64
-+ bgt CPDO_suf_normalize1st_3
-+
-+CPDO_suf_normalize1st_2:
-+ sub r6,r6,#32
-+ rsb r11,r6,#32
-+ mov r5,r3,lsr r6
-+ add r5,r5,r2,lsl r11
-+ movs r11,r3,lsl r11
-+ orrne r5,r5,#1
-+ mov r3,r2,lsr r6
-+ mov r2,#0
-+ b CPDO_suf_sub_2ndbigger
-+
-+CPDO_suf_normalize1st_1:
-+ rsb r11,r6,#32
-+ mov r5,r3,lsl r11
-+ mov r3,r3,lsr r6
-+ add r3,r3,r2,lsl r11
-+ mov r2,r2,lsr r6
-+ b CPDO_suf_sub_2ndbigger
-+
-+CPDO_suf_normalize1st_3:
-+ sub r6,r6,#64
-+ cmp r6,#32
-+ bge CPDO_suf_normalize1st_4
-+ rsb r11,r6,#32
-+ mov r5,r2,lsr r6
-+ orrs r11,r3,r2,lsl r11
-+ orrne r5,r5,#1
-+ mov r2,#0
-+ mov r3,#0
-+ b CPDO_suf_sub_2ndbigger
-+
-+CPDO_suf_normalize1st_4:
-+ mov r5,#1
-+ mov r2,#0
-+ mov r3,#0
-+ b CPDO_suf_sub_2ndbigger
-+
-+CPDO_suf_sub_1stbigger:
-+ rsbs r5,r5,#0
-+ sbcs r3,r3,r8
-+ sbcs r2,r2,r7
-+ movmi pc,r14
-+ b CPDO_suf_norm
-+
-+CPDO_suf_sub_2ndbigger:
-+ rsbs r5,r5,#0
-+ sbcs r3,r8,r3
-+ sbcs r2,r7,r2
-+ movmi pc,r14
-+
-+CPDO_suf_norm:
-+ teq r2,#0 // normalize 32 bit
-+ bne CPDO_suf_norm16
-+ teq r3,#0 // normalize 64 bit
-+ bne CPDO_suf_norm32
-+ mov r2,r5
-+ mov r3,#0
-+ mov r5,#0
-+ sub r4,r4,#64
-+ mov pc,r14
-+CPDO_suf_norm32:
-+ mov r2,r3
-+ mov r3,r5
-+ mov r5,#0
-+ sub r4,r4,#32
-+CPDO_suf_norm16:
-+ cmp r2,#0x00010000 // normalize 16 bit
-+ bcs CPDO_suf_norm8
-+ mov r2,r2,lsl#16
-+ orr r2,r2,r3,lsr#16
-+ mov r3,r3,lsl#16
-+ orr r3,r3,r5,lsr#16
-+ mov r5,r5,lsl#16
-+ sub r4,r4,#16
-+CPDO_suf_norm8:
-+ cmp r2,#0x01000000 // normalize 8 bit
-+ bcs CPDO_suf_norm4
-+ mov r2,r2,lsl#8
-+ orr r2,r2,r3,lsr#24
-+ mov r3,r3,lsl#8
-+ orr r3,r3,r5,lsr#24
-+ mov r5,r5,lsl#8
-+ sub r4,r4,#8
-+CPDO_suf_norm4:
-+ cmp r2,#0x10000000 // normalize 4 bit
-+ bcs CPDO_suf_norm2
-+ mov r2,r2,lsl#4
-+ orr r2,r2,r3,lsr#28
-+ mov r3,r3,lsl#4
-+ orr r3,r3,r5,lsr#28
-+ mov r5,r5,lsl#4
-+ sub r4,r4,#4
-+CPDO_suf_norm2:
-+ cmp r2,#0x40000000 // normalize 2 bit
-+ bcs CPDO_suf_norm1
-+ mov r2,r2,lsl#2
-+ orr r2,r2,r3,lsr#30
-+ mov r3,r3,lsl#2
-+ orr r3,r3,r5,lsr#30
-+ mov r5,r5,lsl#2
-+ sub r4,r4,#2
-+CPDO_suf_norm1:
-+ cmp r2,#0x80000000 // normalize 1 bit
-+ bcs CPDO_suf_norme
-+ mov r2,r2,lsl#1
-+ orr r2,r2,r3,lsr#31
-+ mov r3,r3,lsl#1
-+ orr r3,r3,r5,lsr#31
-+ mov r5,r5,lsl#1
-+ sub r4,r4,#1
-+CPDO_suf_norme:
-+ mov pc,r14
-+
-+CPDO_suf_zero:
-+ and r5,r5,#0x00000060
-+ cmp r5,#0x00000040 // rounding mode M?
-+ moveq r1,#0x80000000
-+ movne r1,#0
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_suf_extra: // nearly the same as with adf
-+ cmp r11,#0x7fffffff // the only thing we need to do is
-+ bne CPDO_suf_extra_sign // to invert the second sign if
-+ orrnes r5,r8,r7,lsl#1 // it is not a NaN, ignore MSB
-+ bne CPDO_adf_extra
-+CPDO_suf_extra_sign:
-+ eor r6,r6,#0x80000000
-+ b CPDO_adf_extra
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rsf
-+CPDO_rsf:
-+ ldmia r1,{r6,r7,r8,r11}
-+ ldmia r2,{r1,r2,r3,r4}
-+ b CPDO_suf_l
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_muf
-+CPDO_muf:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+ cmp r11,#0x7fffffff
-+ cmpne r4,#0x7fffffff
-+ beq CPDO_muf_extra
-+ eor r1,r1,r6 // sign
-+ cmp r11,#0x80000000
-+ cmpne r4,#0x80000000
-+ beq CPDO_muf_zero
-+
-+ add r4,r4,r11 // exponent
-+#if 0
-+
-+#define x4 r0
-+#define x3 r1
-+#define x2 r4
-+#define x1 r6
-+#define y4 r9
-+#define y3 r7
-+#define y2 r10
-+#define y1 r8
-+#define z4 r2
-+#define z3 r3
-+#define z2 r5
-+#define z1 r11
-+#define tmp r12
-+
-+ stmdb r13!, {r0, r1, r4, r9, r10, r12}
-+ mov x4,r2,lsr#16
-+ bic x3,r2,x4,lsl#16
-+ mov x2,r3,lsr#16
-+ bic x1,r3,x2,lsl#16
-+ mov y4,r7,lsr#16
-+ bic y3,r7,y4,lsl#16
-+ mov y2,r8,lsr#16
-+ bic y1,r8,y2,lsl#16
-+ mul z1,x1,y1
-+ mul tmp,x1,y2
-+ mov z2,#0
-+ adds z1,z1,tmp,lsl#16
-+ adc z2,z2,tmp,lsr#16
-+ mul tmp,x2,y1
-+ adds z1,z1,tmp,lsl#16
-+ adcs z2,z2,tmp,lsr#16
-+ mul tmp,x1,y4
-+ mov z3,#0
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ mul tmp,x2,y3
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ mul tmp,x3,y2
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ mul tmp,x4,y1
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ mul tmp,x3,y4
-+ mul z4,x4,y4
-+ adds z3,z3,tmp,lsl#16
-+ adc z4,z4,tmp,lsr#16
-+ mul tmp,x4,y3
-+ adds z3,z3,tmp,lsl#16
-+ adc z4,z4,tmp,lsr#16
-+ mul tmp,x1,y3
-+ adds z2,z2,tmp
-+ mul tmp,x2,y4
-+ adcs z3,z3,tmp
-+ mul tmp,x2,y2
-+ adc z4,z4,#0
-+ adds z2,z2,tmp
-+ mul tmp,x3,y3
-+ adcs z3,z3,tmp
-+ mul tmp,x3,y1
-+ adc z4,z4,#0
-+ adds z2,z2,tmp
-+ teq z1,#0
-+ orrne z2,z2,#1 // z1 must not be lost for rounding
-+ mul tmp,x4,y2
-+ adcs z3,z3,tmp
-+ adcs z4,z4,#0
-+ ldmia r13!, {r0, r1, r4, r9, r10, r12}
-+#else
-+
-+#define x32 r2
-+#define x10 r3
-+#define y32 r7
-+#define y10 r8
-+#define z3 r0
-+#define z2 r1
-+#define z1 r4
-+#define z0 r6
-+#define v1 r9
-+#define v0 r11
-+#define tmp r5
-+
-+ stmdb r13!,{r0,r1,r4,r9}
-+
-+ mov z3,x32,lsr#16
-+ bic z2,x32,z3,lsl#16
-+ movs v1,y32,lsr#16
-+ bic v0,y32,v1,lsl#16
-+
-+ mul tmp,z3,v0
-+ mul z3,v1,z3
-+ mulne v1,z2,v1
-+ mul z2,v0,z2
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ adds z2,z2,v1,lsl#16
-+ adc z3,z3,v1,lsr#16
-+
-+ mov z1,x10,lsr#16
-+ bic z0,x10,z1,lsl#16
-+ movs v1,y10,lsr#16
-+ bic v0,y10,v1,lsl#16
-+
-+ mul tmp,z1,v0
-+ mul z1,v1,z1
-+ mulne v1,z0,v1
-+ mul z0,v0,z0
-+ adds z0,z0,tmp,lsl#16
-+ adc z1,z1,tmp,lsr#16
-+ adds z0,z0,v1,lsl#16
-+ adc z1,z1,v1,lsr#16
-+
-+ adds z2,z2,z1 // z3 is max. 0xfffffffe
-+ adc z3,z3,#0 // so this trick is possible
-+ adds z1,z2,z0 // to save one addition
-+ adcs z2,z2,z3
-+ adc z3,z3,#0
-+
-+ subs x10,x32,x10
-+ mov v0,#0
-+ mov v1,v0,rrx
-+
-+ sublo v0,y32,y10
-+ subnes y10,y10,y32
-+
-+ orreq v1,v1,#1<<31
-+ eorcs v1,v1,#1<<31
-+ subcc v0,v0,x10
-+
-+ movs x32,x10,lsr#16
-+ bic x10,x10,x32,lsl#16
-+ mov y32,y10,lsr#16
-+ bic y10,y10,y32,lsl#16
-+
-+ mul tmp,x10,y10
-+ mla v0,x32,y32,v0
-+ mulne x32,y10,x32
-+ adds tmp,tmp,x32,lsl#16
-+ adc v0,v0,x32,lsr#16
-+ mul y32,x10,y32
-+ adds tmp,tmp,y32,lsl#16
-+ adc v0,v0,y32,lsr#16
-+ adds r5,z1,tmp
-+ adcs r3,z2,v0
-+ adc r2,z3,v1,asr#31
-+
-+ teq z0,#0
-+ orrne r5,r5,#1 // z0 must not be lost for rounding
-+ cmp r2,#0
-+
-+ ldmia r13!,{r0,r1,r4,r9}
-+#endif
-+
-+ bpl CPDO_muf_norm
-+ add r4,r4,#1
-+ mov pc,r14
-+
-+CPDO_muf_norm:
-+ adds r5,r5,r5
-+ adcs r3,r3,r3
-+ adc r2,r2,r2
-+ mov pc,r14
-+
-+CPDO_muf_extra:
-+ cmp r4,#0x7fffffff
-+ beq CPDO_muf_1st_infnan
-+CPDO_muf_2nd_infnan:
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ bne CPDO_muf_2nd_nan
-+ cmp r4,#0x80000000
-+ beq CPDO_muf_generate_qnan
-+ mov r2,r7 // copy MSB
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+ eor r1,r1,r6
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_muf_1st_infnan:
-+ cmp r11,#0x7fffffff
-+ beq CPDO_muf_both_infnan
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ bne CPDO_muf_1st_nan
-+ cmp r11,#0x80000000
-+ beq CPDO_muf_generate_qnan
-+// mov r4,#0x7fffffff
-+ eor r1,r1,r6
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_muf_both_infnan:
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ beq CPDO_muf_both_infnan_1st_inf
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_muf_both_infnan_2nd_inf
-+ tst r2,#0x40000000
-+ tstne r7,#0x40000000
-+ beq CPDO_muf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_muf_both_infnan_1st_inf:
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_muf_both_inf
-+ b CPDO_muf_2nd_nan
-+
-+CPDO_muf_both_infnan_2nd_inf:
-+ b CPDO_muf_1st_nan
-+
-+CPDO_muf_both_inf:
-+ eor r1,r1,r6
-+ orr r2,r2,r7 // copy both MSB
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_muf_zero:
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_muf_1st_nan:
-+ tst r2,#0x40000000
-+ beq CPDO_muf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_muf_2nd_nan:
-+ tst r7,#0x40000000
-+ beq CPDO_muf_generate_qnan
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11
-+ mov pc,r14
-+
-+CPDO_muf_generate_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,#0xffffffff
-+ mov r4,#0x7fffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1
-+ str r5,[r10,#128]
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_muf_M
-+CPDO_muf_M:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+ cmp r11,#0x7fffffff
-+ cmpne r4,#0x7fffffff
-+ beq CPDO_muf_extra
-+ eor r1,r1,r6 // sign
-+ cmp r11,#0x80000000
-+ cmpne r4,#0x80000000
-+ beq CPDO_muf_zero
-+
-+ add r4,r4,r11 // exponent
-+#if 0
-+ umull r11,r5,r3,r8 // r5|r11 = lo1*lo2
-+ teq r11,#0
-+ orrne r5,r5,#0x00000001 // r11 must not be lost for rounding
-+ umull r11,r6,r8,r2 // r6|r11 = lo2*hi1
-+ umull r8,r2,r7,r2 // r2|r8 = hi1*hi2
-+ umull r12,r3,r7,r3 // r3|r12 = lo1*hi2
-+ adds r5,r5,r12
-+ adcs r3,r3,r6
-+ adc r2,r2,#0
-+ adds r5,r5,r11
-+ adcs r3,r3,r8
-+ adcs r2,r2,#0
-+#else
-+ umull r12,r11,r2,r7
-+ umull r2,r6,r8,r2
-+ umull r8,r5,r3,r8
-+ adds r5,r5,r2
-+ adcs r12,r12,r6
-+ adc r11,r11,#0
-+ umull r7,r6,r3,r7
-+ adds r5,r5,r7
-+ adcs r3,r12,r6
-+ adc r2,r11,#0
-+ teq r8,#0
-+ orrne r5,r5,#1 // r8 must not be lost for rounding
-+ cmp r2,#0
-+#endif
-+ bpl CPDO_muf_norm
-+ add r4,r4,#1
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDO_infnan_1:
-+ stmia r0,{r1,r3,r5,r7}
-+ b fastfpe_next
-+
-+CPDO_infnan_2:
-+ stmia r0,{r2,r4,r6,r8}
-+ b fastfpe_next
-+
-+CPDO_nan_12:
-+ orr r2,r3,r4
-+ b CPDO_inf_1
-+
-+CPDO_nan:
-+ mov r2,#0x40000000 @ create non signalling NaN
-+ b CPDO_inf_1
-+
-+CPDO_inf:
-+ mov r2,#0
-+CPDO_inf_1:
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+CPDO_store_1234:
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+CPDO_zero:
-+ mov r1,#0
-+CPDO_zero_1:
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+CPDO_muf_end:
-+ cmp r8,#0x20000000
-+ bge CPDO_inf
-+ cmp r8,#0xe0000000
-+ ble CPDO_zero_1
-+ stmia r0,{r1,r2,r7,r8}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_dvf
-+CPDO_dvf:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+CPDO_dvf_l:
-+ cmp r11,#0x7fffffff
-+ cmpne r4,#0x7fffffff
-+ beq CPDO_dvf_infnan
-+ eor r1,r1,r6
-+ cmp r11,#0x80000000
-+ cmpne r4,#0x80000000
-+ beq CPDO_dvf_zero
-+
-+ sub r4,r4,r11
-+
-+#define x4 r11
-+#define x3 r7
-+#define x2 r12
-+#define x1 r8
-+#define y2 r14
-+#define y1 r9
-+#define z3 r4
-+#define z2 r5
-+#define z1 r6
-+#define tmp r10
-+
-+ cmp r2,r7
-+ cmpeq r3,r8
-+ bcs CPDO_dvf_no_normalize
-+
-+ sub r4,r4,#1
-+ stmdb r13!,{r1,r4,r9,r10,r11,r14}
-+ mov r4,r2,lsr#31
-+ mov r5,r2,lsl#1
-+ orr r5,r5,r3,lsr#31
-+ mov r6,r3,lsl#1 // dividend
-+ b CPDO_dvf_normalize_back
-+
-+CPDO_dvf_no_normalize:
-+ stmdb r13!,{r1,r4,r9,r10,r11,r14}
-+ mov r4,#0
-+ mov r5,r2
-+ mov r6,r3 // dividend
-+
-+CPDO_dvf_normalize_back:
-+ mov r1,#0
-+ sub r10,r1,r7,lsr#1
-+ mov r11,#0x40000000
-+
-+ .macro inv_step
-+ adds r11,r10,r11,lsl#1
-+ subcc r11,r11,r10
-+ adc r1,r1,r1
-+ .endm
-+
-+ .rept 17
-+ inv_step
-+ .endr
-+
-+ mov r1,r1,lsl#15
-+ adds r1,r1,#1<<15
-+ movcs r1,#0xffffffff // inverse
-+ mov r1,r1,lsr#16
-+
-+ mov r2,#0
-+ mov r3,#0 // clear result space
-+
-+ mov x4,r7,lsr#16
-+ bic x3,r7,x4,lsl#16
-+ mov x2,r8,lsr#16
-+ bic x1,r8,x2,lsl#16 // split divisor for 16x16=32bit mul
-+
-+CPDO_dvf_loop_entry:
-+ mov r4,r4,lsl#16
-+ orrs r4,r4,r5,lsr#16
-+ mov r5,r5,lsl#16
-+ orr r5,r5,r6,lsr#16
-+ mov r6,r6,lsl#16 // shift dividend left by 16
-+
-+ bmi CPDO_dvf_loop_negative
-+ mov r10,r4,lsr#16
-+ mul r9,r10,r1
-+ bic r10,r4,r10,lsl#16
-+ mul r10,r1,r10
-+ add r9,r9,r10,lsr#16 //estimate 16 bits of result in r9
-+
-+ mov r2,r2,lsl#16
-+ orr r2,r2,r3,lsr#16
-+ adds r3,r9,r3,lsl#16 // shift result left by 16 and
-+ adc r2,r2,#0 // add in new result bits
-+
-+ mov r9,r9,lsl#1
-+ mov y2,r9,lsr#16
-+ bic y1,r9,y2,lsl#16
-+ mul tmp,x1,y1
-+ subs z1,z1,tmp
-+ mul tmp,x3,y1
-+ sbcs z2,z2,tmp
-+ mul tmp,x4,y2
-+ sbc z3,z3,tmp
-+ mul tmp,x2,y2
-+ subs z2,z2,tmp
-+ sbc z3,z3,#0
-+ mul tmp,x2,y1
-+ subs z1,z1,tmp,lsl#16
-+ sbcs z2,z2,tmp,lsr#16
-+ sbc z3,z3,#0
-+ mul tmp,x1,y2
-+ subs z1,z1,tmp,lsl#16
-+ sbcs z2,z2,tmp,lsr#16
-+ sbc z3,z3,#0
-+ mul tmp,x4,y1
-+ subs z2,z2,tmp,lsl#16
-+ sbc z3,z3,tmp,lsr#16
-+ mul tmp,x3,y2
-+ subs z2,z2,tmp,lsl#16
-+ sbc z3,z3,tmp,lsr#16 // subtract divisor * estimated result
-+
-+ tst r2,#0xff000000
-+ beq CPDO_dvf_loop_entry
-+
-+ b CPDO_dvf_end_entry
-+
-+CPDO_dvf_loop_negative:
-+ rsb r14,r4,#0
-+ mov r10,r14,lsr#16
-+ mul r9,r10,r1
-+ bic r10,r14,r10,lsl#16
-+ mul r10,r1,r10
-+ add r9,r9,r10,lsr#16 // estimate 16 bits of result in r9
-+
-+ mov r2,r2,lsl#16
-+ orr r2,r2,r3,lsr#16
-+ rsbs r3,r9,r3,lsl#16 // shift result left by 16 and
-+ sbc r2,r2,#0 // add in new result bits
-+
-+ mov r9,r9,lsl#1
-+ mov y2,r9,lsr#16
-+ bic y1,r9,y2,lsl#16
-+ mul tmp,x1,y1
-+ adds z1,z1,tmp
-+ mul tmp,x3,y1
-+ adcs z2,z2,tmp
-+ mul tmp,x4,y2
-+ adc z3,z3,tmp
-+ mul tmp,x2,y2
-+ adds z2,z2,tmp
-+ adc z3,z3,#0
-+ mul tmp,x2,y1
-+ adds z1,z1,tmp,lsl#16
-+ adcs z2,z2,tmp,lsr#16
-+ adc z3,z3,#0
-+ mul tmp,x1,y2
-+ adds z1,z1,tmp,lsl#16
-+ adcs z2,z2,tmp,lsr#16
-+ adc z3,z3,#0
-+ mul tmp,x4,y1
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16
-+ mul tmp,x3,y2
-+ adds z2,z2,tmp,lsl#16
-+ adc z3,z3,tmp,lsr#16 // subtract divisor * estimated result
-+
-+ tst r2,#0xff000000
-+ beq CPDO_dvf_loop_entry
-+
-+CPDO_dvf_end_entry:
-+ movs r4,r4,asr#1
-+ movs r5,r5,rrx // remainder was shifted left by 1
-+ movs r6,r6,rrx // relative to divisor
-+
-+ orr r7,x3,x4,lsl#16
-+ orr r8,x1,x2,lsl#16 // put the split divisor together again
-+
-+ cmp r4,#0
-+ blt CPDO_dvf_end_negative
-+ cmpeq r5,r7
-+ cmpeq r6,r8
-+ bcc CPDO_dvf_end
-+
-+CPDO_dvf_end_positive:
-+ adds r3,r3,#1
-+ adc r2,r2,#0
-+
-+ subs r6,r6,r8
-+ sbcs r5,r5,r7
-+ sbcs r4,r4,#0
-+ bne CPDO_dvf_end_positive
-+
-+ cmp r5,r7
-+ cmpeq r6,r8
-+ bcs CPDO_dvf_end_positive
-+ b CPDO_dvf_end
-+
-+CPDO_dvf_end_negative:
-+ subs r3,r3,#1
-+ sbc r2,r2,#0
-+
-+ adds r6,r6,r8
-+ adcs r5,r5,r7
-+ adcs r4,r4,#0
-+ bmi CPDO_dvf_end_negative
-+
-+CPDO_dvf_end:
-+ orrs r9,r5,r6
-+ ldmia r13!,{r1,r4,r9,r10,r11,r14}
-+ moveq pc,r14
-+
-+ adds r6,r6,r6
-+ adcs r5,r5,r5
-+ movcs r5,#0xc0000000
-+ movcs pc,r14
-+
-+ cmp r5,r7
-+ cmpeq r6,r8
-+ movcc r5,#0x40000000
-+ moveq r5,#0x80000000
-+ movhi r5,#0xc0000000
-+ mov pc,r14
-+
-+CPDO_dvf_zero:
-+ cmp r11,#0x80000000
-+ beq CPDO_dvf_by_zero
-+
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next // 0 already there
-+@ mov pc,r14
-+
-+CPDO_dvf_by_zero:
-+ cmp r4,#0x80000000
-+ beq CPDO_dvf_generate_qnan // first 0 too
-+
-+ mov r2,#0x80000000 // set MSB
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#2 // division by zero
-+ str r5,[r10,#128]
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_dvf_infnan:
-+ cmp r4,#0x7fffffff
-+ beq CPDO_dvf_1st_infnan
-+
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_dvf_2nd_inf
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11
-+ b CPDO_dvf_1st_or_2nd_nan
-+
-+CPDO_dvf_2nd_inf:
-+ eor r1,r1,r6
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next // zero created
-+@ mov pc,r14
-+
-+CPDO_dvf_1st_infnan:
-+ cmp r11,#0x7fffffff
-+ beq CPDO_dvf_both_infnan
-+
-+ orrs r5,r3,r2,lsl#1 // 1st inf? ignore MSB
-+ bne CPDO_dvf_1st_or_2nd_nan
-+
-+ eor r1,r1,r6 // sign for inf
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next // inf already there
-+@ mov pc,r14
-+
-+CPDO_dvf_1st_or_2nd_nan:
-+ tst r2,#0x40000000
-+ beq CPDO_dvf_generate_qnan
-+ mov pc,r14 // qnan1/2 already/copied there
-+
-+CPDO_dvf_both_infnan:
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ beq CPDO_dvf_both_infnan_1st_inf
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_dvf_both_infnan_2nd_inf
-+ tst r2,#0x40000000
-+ tstne r7,#0x40000000
-+ beq CPDO_dvf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_dvf_both_infnan_1st_inf:
-+ tst r7,#0x40000000 // 2nd inf or SNaN ?
-+ beq CPDO_dvf_generate_qnan
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11 // copy 2nd QNaN
-+ mov pc,r14
-+
-+CPDO_dvf_both_infnan_2nd_inf:
-+ tst r2,#0x40000000 // 1st SNaN ?
-+ beq CPDO_dvf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_dvf_generate_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,#0xffffffff
-+ mov r4,#0x7fffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1
-+ str r5,[r10,#128]
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_dvf_M
-+CPDO_dvf_M:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+CPDO_dvf_M_l:
-+ cmp r11,#0x7fffffff
-+ cmpne r4,#0x7fffffff
-+ beq CPDO_dvf_infnan
-+ eor r1,r1,r6
-+ cmp r11,#0x80000000
-+ cmpne r4,#0x80000000
-+ beq CPDO_dvf_zero
-+
-+ sub r4,r4,r11
-+
-+ cmp r2,r7
-+ cmpeq r3,r8
-+ bcs CPDO_dvf_M_no_normalize
-+
-+ sub r4,r4,#1
-+ stmdb r13!,{r1,r4,r9,r10}
-+ mov r4,r2,lsr#31
-+ mov r5,r2,lsl#1
-+ orr r5,r5,r3,lsr#31
-+ mov r6,r3,lsl#1 // dividend
-+ b CPDO_dvf_M_normalize_back
-+
-+CPDO_dvf_M_no_normalize:
-+ stmdb r13!,{r1,r4,r9,r10}
-+ mov r4,#0
-+ mov r5,r2
-+ mov r6,r3 // dividend
-+
-+CPDO_dvf_M_normalize_back:
-+ mov r1,#0
-+ sub r10,r1,r7,lsr#1
-+ mov r11,#0x40000000
-+
-+ .macro inv_step
-+ adds r11,r10,r11,lsl#1
-+ subcc r11,r11,r10
-+ adc r1,r1,r1
-+ .endm
-+
-+ .rept 18
-+ inv_step
-+ .endr
-+
-+ mov r1,r1,lsl#14
-+ adds r1,r1,#1<<15
-+ movcs r1,#0xffffffff // inverse
-+
-+ mov r2,#0
-+ mov r3,#0 // clear result space
-+
-+CPDO_dvf_M_loop_entry:
-+ mov r4,r4,lsl#16
-+ orrs r4,r4,r5,lsr#16
-+ mov r5,r5,lsl#16
-+ orr r5,r5,r6,lsr#16
-+ mov r6,r6,lsl#16 // shift dividend left by 16
-+
-+ bmi CPDO_dvf_M_loop_negative
-+ umull r10,r9,r4,r1 // estimate 16 bits of result in r9
-+
-+ mov r2,r2,lsl#16
-+ orr r2,r2,r3,lsr#16
-+ adds r3,r9,r3,lsl#16 // shift result left by 16 and
-+ adc r2,r2,#0 // add in new result bits
-+
-+ mov r9,r9,lsl#1
-+ umull r11,r10,r8,r9 // divisor lo * estimated result
-+ subs r6,r6,r11
-+ sbcs r5,r5,r10
-+ sbc r4,r4,#0
-+
-+ umull r11,r10,r7,r9 // divisor hi * estimated result
-+ subs r5,r5,r11
-+ sbc r4,r4,r10
-+
-+ tst r2,#0xff000000
-+ beq CPDO_dvf_M_loop_entry
-+
-+ b CPDO_dvf_M_end_entry
-+
-+CPDO_dvf_M_loop_negative:
-+ rsb r11,r4,#0
-+ umull r10,r9,r11,r1 // estimate 16 bits of result in r9
-+
-+ mov r2,r2,lsl#16
-+ orr r2,r2,r3,lsr#16
-+ rsbs r3,r9,r3,lsl#16 // shift result left by 16 and
-+ sbc r2,r2,#0 // add in new result bits
-+
-+ mov r9,r9,lsl#1
-+ umull r11,r10,r8,r9 // divisor lo * estimated result
-+ adds r6,r6,r11
-+ adcs r5,r5,r10
-+ adc r4,r4,#0
-+
-+ umlal r5,r4,r7,r9 // divisor hi * estimated result
-+
-+ tst r2,#0xff000000
-+ beq CPDO_dvf_M_loop_entry
-+
-+CPDO_dvf_M_end_entry:
-+ movs r4,r4,asr#1
-+ movs r5,r5,rrx // remainder was shifted left by 1
-+ movs r6,r6,rrx // relative to divisor
-+
-+ cmp r4,#0
-+ blt CPDO_dvf_M_end_negative
-+ cmpeq r5,r7
-+ cmpeq r6,r8
-+ bcc CPDO_dvf_M_end
-+
-+CPDO_dvf_M_end_positive:
-+ adds r3,r3,#1
-+ adc r2,r2,#0
-+
-+ subs r6,r6,r8
-+ sbcs r5,r5,r7
-+ sbcs r4,r4,#0
-+
-+ cmp r5,r7
-+ cmpeq r6,r8
-+ bcs CPDO_dvf_M_end_positive
-+ b CPDO_dvf_M_end
-+
-+CPDO_dvf_M_end_negative:
-+ subs r3,r3,#1
-+ sbc r2,r2,#0
-+
-+ adds r6,r6,r8
-+ adcs r5,r5,r7
-+ adcs r4,r4,#0
-+ bmi CPDO_dvf_M_end_negative
-+
-+CPDO_dvf_M_end:
-+ orrs r9,r5,r6
-+ ldmia r13!,{r1,r4,r9,r10}
-+ moveq pc,r14
-+
-+ adds r6,r6,r6
-+ adcs r5,r5,r5
-+ movcs r5,#0xc0000000
-+ movcs pc,r14
-+
-+ cmp r5,r7
-+ cmpeq r6,r8
-+ movcc r5,#0x40000000
-+ moveq r5,#0x80000000
-+ movhi r5,#0xc0000000
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rdf
-+CPDO_rdf:
-+ ldmia r1,{r6,r7,r8,r11}
-+ ldmia r2,{r1,r2,r3,r4}
-+ b CPDO_dvf_l
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rdf_M
-+CPDO_rdf_M:
-+ ldmia r1,{r6,r7,r8,r11}
-+ ldmia r2,{r1,r2,r3,r4}
-+ b CPDO_dvf_M_l
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rmf
-+CPDO_rmf:
-+ ldmia r2,{r6,r7,r8,r11}
-+ ldmia r1,{r1,r2,r3,r4}
-+
-+ cmp r11,#0x7fffffff
-+ cmpne r4,#0x7fffffff
-+ beq CPDO_rmf_infnan
-+ cmp r11,#0x80000000
-+ cmpne r4,#0x80000000
-+ beq CPDO_rmf_zero
-+
-+ cmp r4,r11
-+ bge CPDO_rmf_loop_entry
-+ b CPDO_rmf_smaller
-+
-+CPDO_rmf_loop_0:
-+ mov r5,#0
-+CPDO_rmf_loop:
-+ cmp r4,r11
-+ ble CPDO_rmf_loop_end
-+
-+ sub r4,r4,#1
-+
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_rmf_loop_anyway
-+
-+CPDO_rmf_loop_entry:
-+ cmp r2,r7
-+ cmpeq r3,r8
-+ bcc CPDO_rmf_loop_0
-+
-+CPDO_rmf_loop_anyway:
-+ subs r3,r3,r8
-+ sbc r2,r2,r7
-+ mov r5,#1
-+ b CPDO_rmf_loop
-+
-+CPDO_rmf_loop_end:
-+ teq r2,#0
-+ teqeq r3,#0
-+ beq CPDO_rmf_created_zero
-+
-+ //eor r1,r1,r6 // only if result not zero
-+
-+ mov r6,r2,lsr#31
-+ mov r11,r2,lsl#1
-+ orr r11,r11,r3,lsr#31
-+
-+ cmp r6,#0
-+ cmpeq r11,r7
-+ rsbeqs r6,r8,r3,lsl#1
-+ cmpeq r5,#1 // for nearest-even
-+ bcc CPDO_rmf_norm
-+
-+ eor r1,r1,#0x80000000
-+ subs r3,r8,r3
-+ sbc r2,r7,r2
-+
-+CPDO_rmf_norm:
-+ teq r2,#0 // normalize 32 bit
-+ moveq r2,r3
-+ moveq r3,#0
-+ subeq r4,r4,#32
-+
-+ cmp r2,#0x00010000 // normalize 16 bit
-+ movcc r2,r2,lsl#16
-+ orrcc r2,r2,r3,lsr#16
-+ movcc r3,r3,lsl#16
-+ subcc r4,r4,#16
-+
-+ cmp r2,#0x01000000 // normalize 8 bit
-+ movcc r2,r2,lsl#8
-+ orrcc r2,r2,r3,lsr#24
-+ movcc r3,r3,lsl#8
-+ subcc r4,r4,#8
-+
-+ cmp r2,#0x10000000 // normalize 4 bit
-+ movcc r2,r2,lsl#4
-+ orrcc r2,r2,r3,lsr#28
-+ movcc r3,r3,lsl#4
-+ subcc r4,r4,#4
-+
-+ cmp r2,#0x40000000 // normalize 2 bit
-+ movcc r2,r2,lsl#2
-+ orrcc r2,r2,r3,lsr#30
-+ movcc r3,r3,lsl#2
-+ subcc r4,r4,#2
-+
-+ cmp r2,#0x80000000 // normalize 1 bit
-+ movcc r2,r2,lsl#1
-+ orrcc r2,r2,r3,lsr#31
-+ movcc r3,r3,lsl#1
-+ subcc r4,r4,#1
-+
-+ mov r5,#0
-+ mov pc,r14
-+
-+CPDO_rmf_created_zero:
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_rmf_smaller:
-+ add r5,r4,#1
-+ cmp r5,r11
-+ blt CPDO_rmf_norm
-+ cmp r2,r7
-+ cmpeq r3,r8
-+ bls CPDO_rmf_norm
-+
-+ eor r1,r1,#0x80000000
-+ adds r8,r8,r8
-+ adc r7,r7,r7
-+ subs r3,r8,r3
-+ sbc r2,r7,r2
-+ b CPDO_rmf_norm
-+
-+CPDO_rmf_zero:
-+ cmp r11,#0x80000000
-+ beq CPDO_rmf_generate_qnan
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+@ mov pc,r14
-+
-+CPDO_rmf_infnan:
-+ cmp r4,#0x7fffffff
-+ beq CPDO_rmf_1st_infnan
-+
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_rmf_2nd_inf
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11
-+ b CPDO_rmf_1st_or_2nd_nan
-+
-+CPDO_rmf_2nd_inf:
-+ mov pc,r14 // result = 1st operand
-+
-+CPDO_rmf_1st_infnan:
-+ cmp r11,#0x7fffffff
-+ beq CPDO_rmf_both_infnan
-+
-+ orrs r5,r3,r2,lsl#1 // 1st inf?
-+ bne CPDO_rmf_1st_or_2nd_nan
-+
-+ b CPDO_rmf_generate_qnan
-+
-+CPDO_rmf_1st_or_2nd_nan:
-+ tst r2,#0x40000000
-+ beq CPDO_rmf_generate_qnan
-+ mov pc,r14 // qnan1/2 already/copied there
-+
-+CPDO_rmf_both_infnan:
-+ orrs r5,r3,r2,lsl#1 // ignore MSB
-+ beq CPDO_rmf_both_infnan_1st_inf
-+ orrs r5,r8,r7,lsl#1 // ignore MSB
-+ beq CPDO_rmf_both_infnan_2nd_inf
-+ tst r2,#0x40000000
-+ tstne r7,#0x40000000
-+ beq CPDO_rmf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_rmf_both_infnan_1st_inf:
-+ tst r7,#0x40000000 // 2nd inf or SNaN ?
-+ beq CPDO_rmf_generate_qnan
-+ mov r1,r6
-+ mov r2,r7
-+ mov r3,r8
-+ mov r4,r11 // copy 2nd QNaN
-+ mov pc,r14
-+
-+CPDO_rmf_both_infnan_2nd_inf:
-+ tst r2,#0x40000000 // 1st SNaN ?
-+ beq CPDO_rmf_generate_qnan
-+ mov pc,r14
-+
-+CPDO_rmf_generate_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,#0xffffffff
-+ mov r4,#0x7fffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1
-+ str r5,[r10,#128]
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_mvf
-+CPDO_mvf:
-+ ldmia r2,{r1,r2,r3,r4}
-+ mov r5,#0
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_mnf
-+CPDO_mnf:
-+ ldmia r2,{r1,r2,r3,r4}
-+ eor r1,r1,#0x80000000
-+ mov r5,#0
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_abs
-+CPDO_abs:
-+ ldmia r2,{r1,r2,r3,r4}
-+ bic r1,r1,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_sqt
-+CPDO_sqt:
-+ ldmia r2,{r1,r2,r3,r4}
-+ cmp r1,#0
-+ bne CPDO_nan
-+ cmp r4,#0x7fffffff
-+ beq CPDO_store_1234
-+
-+ tst r4,r4,lsr#1 @carry=exponent bit 0
-+ bcc CPDO_sqt_exponenteven
-+ adds r3,r3,r3
-+ adc r2,r2,r2
-+ cmp r2,#0x20000000 @set carry for loop
-+CPDO_sqt_exponenteven:
-+ mov r4,r4,asr #1
-+ str r4,[r0,#12]
-+
-+ mov r4,#0x80000000
-+ mov r5,#0
-+ sub r2,r2,#0x80000000
-+
-+ mov r8,#0x40000000
-+ mov r14,#0x80000000
-+
-+ mov r1,#1
-+ b CPDO_sqt_loop1_first
-+CPDO_sqt_loop1:
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+CPDO_sqt_loop1_first:
-+ add r6,r4,r8,lsr r1 @r7 const = r5
-+ bcs CPDO_sqt_loop1_1
-+ cmp r2,r6
-+ cmpeq r3,r5 @r5 for r7
-+ bcc CPDO_sqt_loop1_0
-+CPDO_sqt_loop1_1:
-+ orr r4,r4,r14,lsr r1
-+ subs r3,r3,r5 @r5 for r7
-+ sbc r2,r2,r6
-+CPDO_sqt_loop1_0:
-+ add r1,r1,#1
-+ cmp r1,#30
-+ ble CPDO_sqt_loop1
-+
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_between_1
-+ adds r7,r5,#0x80000000
-+ adc r6,r4,#0
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_between_0
-+CPDO_sqt_between_1:
-+ orr r4,r4,#0x00000001
-+ subs r3,r3,r5
-+ sbc r2,r2,r4
-+ subs r3,r3,#0x80000000
-+ sbc r2,r2,#0
-+CPDO_sqt_between_0:
-+ mov r1,#0
-+
-+CPDO_sqt_loop2:
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_loop2_1
-+ adds r7,r5,r8,lsr r1
-+ adc r6,r4,#0
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_loop2_0
-+CPDO_sqt_loop2_1:
-+ orr r5,r5,r14,lsr r1
-+ subs r3,r3,r5
-+ sbc r2,r2,r4
-+ subs r3,r3,r8,lsr r1
-+ sbc r2,r2,#0
-+CPDO_sqt_loop2_0:
-+ add r1,r1,#1
-+ cmp r1,#30
-+ ble CPDO_sqt_loop2
-+
-+ adds r3,r3,r3
-+ adcs r2,r2,r2
-+ bcs CPDO_sqt_after_1
-+ cmp r2,r6
-+ cmpeq r3,r7
-+ bcc CPDO_sqt_after_0
-+CPDO_sqt_after_1:
-+ orr r5,r5,#0x00000001
-+CPDO_sqt_after_0:
-+
-+ mov r1,#0
-+ stmia r0,{r1,r4,r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rnd
-+CPDO_rnd:
-+ ldmia r2,{r1,r2,r3,r5}
-+ bl CPDO_rnd_core
-+ ldr r6,[r10,#128]
-+ stmia r0,{r1,r2,r3,r5}
-+ orr r6,r6,r4
-+ str r6,[r10,#128]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDO_rnd_core
-+CPDO_rnd_core:
-+ and r6,r4,#0x00000060
-+ mov r4,#0 // for return of exception flags
-+ cmp r5,#63
-+ bge CPDO_rnd_big
-+ add pc,pc,r6,lsr#3
-+ mov r0,r0
-+ b CPDO_rnd_NE
-+ b CPDO_rnd_P
-+ b CPDO_rnd_M
-+ b CPDO_rnd_Z
-+
-+CPDO_rnd_NE:
-+ cmp r5,#0
-+ blt CPDO_rnd_NE_01
-+
-+ subs r6,r5,#31
-+ bpl CPDO_rnd_NE_2
-+ mov r7,#0x40000000
-+ mov r8,#0x7fffffff
-+ mov r7,r7,lsr r5
-+ mov r8,r8,lsr r5
-+ teq r3,#0
-+ tsteq r2,r8
-+ orrne r4,r4,#16 // set inexact flag
-+ adds r2,r2,r7
-+ bcs CPDO_rnd_overflow
-+ teq r3,#0
-+ tsteq r2,r8
-+ beq CPDO_rnd_NE_equal
-+ mov r3,#0
-+ bic r2,r2,r8
-+ mov pc,r14
-+
-+CPDO_rnd_NE_2:
-+ mov r7,#0x80000000
-+ mov r8,#0xffffffff
-+ mov r7,r7,lsr r6
-+ mov r8,r8,lsr r6
-+ tst r3,r8
-+ orrne r4,r4,#16 // set inexact flag
-+ adds r3,r3,r7
-+ adcs r2,r2,#0
-+ bcs CPDO_rnd_overflow
-+ tst r3,r8
-+ beq CPDO_rnd_NE_equal
-+ bic r3,r3,r8
-+ mov pc,r14
-+
-+CPDO_rnd_NE_equal:
-+ mov r7,#0x80000000
-+ subs r6,r5,#32
-+ bicpl r3,r3,r7,lsr r6
-+ bicmi r2,r2,r7,lsr r5
-+ mov pc,r14
-+
-+CPDO_rnd_NE_01:
-+ cmp r5,#-1
-+ bne CPDO_rnd_0
-+ cmp r2,#0x80000000
-+ cmpeq r3,#0
-+ beq CPDO_rnd_0
-+
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r5,#0
-+ orr r4,r4,#16 // set inexact flag
-+ mov pc,r14
-+
-+CPDO_rnd_P:
-+ teq r1,#0
-+ beq CPDO_rnd_NZ
-+ b CPDO_rnd_Z
-+
-+CPDO_rnd_M:
-+ teq r1,#0
-+ beq CPDO_rnd_Z
-+ b CPDO_rnd_NZ
-+
-+CPDO_rnd_Z:
-+ cmp r5,#0 // smaller than 1 will be 0
-+ blt CPDO_rnd_0
-+
-+ rsbs r6,r5,#31
-+ bmi CPDO_rnd_Z_2
-+ cmp r3,#0
-+ mov r3,#0
-+ mov r7,r2,lsr r6
-+ teqeq r2,r7,lsl r6
-+ mov r2,r7,lsl r6
-+ orrne r4,r4,#16 // set inexact flag
-+ mov pc,r14
-+
-+CPDO_rnd_Z_2:
-+ rsb r6,r5,#63
-+ mov r7,r3,lsr r6
-+ teq r3,r7,lsl r6
-+ mov r3,r7,lsl r6
-+ orrne r4,r4,#16 // set inexact flag
-+ mov pc,r14
-+
-+CPDO_rnd_0:
-+ cmp r5,#0x80000000
-+ moveq pc,r14 // already 0 -> ok
-+
-+ mov r2,#0
-+ mov r3,#0
-+ mov r5,#0x80000000
-+ orr r4,r4,#16 // set inexact flag
-+ mov pc,r14
-+
-+CPDO_rnd_NZ:
-+ cmp r5,#0 // smaller than 1 will be stay 0 or become 1
-+ blt CPDO_rnd_NZ_01
-+
-+ mov r7,#0x7fffffff
-+ subs r6,r5,#32
-+ bpl CPDO_rnd_NZ_2
-+ mov r7,r7,lsr r5
-+ teq r3,#0
-+ tsteq r2,r7
-+ orrne r4,r4,#16 // set inexact flag
-+ adds r3,r3,#0xffffffff
-+ adcs r2,r2,r7
-+ bcs CPDO_rnd_overflow
-+ mov r3,#0
-+ bic r2,r2,r7
-+ mov pc,r14
-+
-+CPDO_rnd_NZ_2:
-+ mov r7,r7,lsr r6
-+ tst r3,r7
-+ orrne r4,r4,#16 // set inexact flag
-+ adds r3,r3,r7
-+ adcs r2,r2,#0
-+ bcs CPDO_rnd_overflow
-+ bic r3,r3,r7
-+ mov pc,r14
-+
-+CPDO_rnd_NZ_01:
-+ cmp r5,#0x80000000
-+ moveq pc,r14 // already 0 -> ok
-+
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r5,#0
-+ orr r4,r4,#16 // set inexact flag
-+ mov pc,r14
-+
-+CPDO_rnd_overflow:
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ add r5,r5,#1
-+ mov pc,r14
-+
-+CPDO_rnd_big:
-+ cmp r5,#0x7fffffff
-+ movne pc,r14 // just big
-+ orrs r6,r3,r2,lsl#1 // ignore MSB
-+ moveq pc,r14 // infinity
-+ tst r2,#0x40000000 // signalling NaN ?
-+ orreq r4,r4,#1 // set invalid operation flag
-+ orreq r2,r2,#0x40000000 // make quiet NaN
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/CPDT.S
-@@ -0,0 +1,396 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the number
-+represented is infinity if the mantissa is 0, otherwise it is a NaN.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_single
-+CPDT_load_single:
-+ ldr r1,[r6]
-+
-+ and r2,r1,#0x80000000 @ r2 = sign
-+
-+ mov r5,r1,lsr#23
-+ bics r5,r5,#0x100
-+ beq CPDT_ls_e0 @ exponent = 0; zero/denormalized
-+ teq r5,#255
-+ beq CPDT_ls_e255 @ exponent = 255; infinity/NaN
-+
-+ sub r5,r5,#127 @ r5 = exponent, remove normalized bias
-+
-+ mov r3,r1,lsl#8
-+ orr r3,r3,#0x80000000
-+ mov r4,#0 @ r3,r4 = mantissa
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ls_e0:
-+ movs r3,r1,lsl#9
-+ beq CPDT_load_zero
-+
-+ mov r5,#-127
-+
-+CPDT_ls_e0_norm:
-+ tst r3,#0x80000000
-+ subeq r5,r5,#1
-+ moveq r3,r3,lsl#1
-+ beq CPDT_ls_e0_norm
-+
-+ mov r4,#0
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ls_e255:
-+ mov r3,r1,lsl#8
-+ bics r3,r3,#0x80000000
-+ orreq r3,r3,#0x80000000 // set MSB for inf
-+ mov r4,#0
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_load_zero:
-+ mov r3,#0
-+ mov r4,#0
-+ mov r5,#0x80000000
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_double
-+CPDT_load_double:
-+ ldr r1,[r6]
-+ ldr r6,[r6,#4]
-+
-+ and r2,r1,#0x80000000 @ r2 = sign
-+
-+ mov r5,r1,lsr#20
-+ bics r5,r5,#0x800
-+ beq CPDT_ld_e0 @ exponent = 0; zero/denormalized
-+ add r4,r5,#1
-+ teq r4,#2048
-+ beq CPDT_ld_e2047 @ exponent = 2047; infinity/NaN
-+
-+ add r5,r5,#1
-+ sub r5,r5,#1024 @ r5 = exponent, remove normalized bias
-+
-+ mov r3,r1,lsl#11
-+ orr r3,r3,#0x80000000
-+ orr r3,r3,r6,lsr #21
-+ mov r4,r6,lsl#11 @ r3,r4 = mantissa
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ld_e0:
-+ mov r3,r1,lsl#12
-+ orr r3,r3,r6,lsr#20
-+ movs r4,r6,lsl#12
-+ teqeq r3,#0
-+ beq CPDT_load_zero
-+
-+ mov r5,#1
-+ sub r5,r5,#1024
-+
-+CPDT_ld_e0_norm:
-+ tst r3,#0x80000000
-+ bne CPDT_ld_e0_norm_end
-+ sub r5,r5,#1
-+ movs r4,r4,lsl#1
-+ adc r3,r3,r3
-+ b CPDT_ld_e0_norm
-+CPDT_ld_e0_norm_end:
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_ld_e2047:
-+ mov r3,r1,lsl#11
-+ orr r3,r3,r6,lsr #21
-+ bic r3,r3,#0x80000000
-+ mov r4,r6,lsl#11 @ r3,r4 = mantissa
-+ orrs r5,r3,r4
-+ orreq r3,r3,#0x80000000 // set MSB fo inf
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_extended
-+CPDT_load_extended:
-+ ldr r1,[r6]
-+ ldr r3,[r6,#4]
-+ ldr r4,[r6,#8]
-+
-+ and r2,r1,#0x8000
-+ mov r2,r2,lsl#16
-+ mov r5,r1,lsl#17
-+ movs r5,r5,lsr#17
-+ beq CPDT_le_e0
-+ add r1,r5,#1
-+ teq r1,#32768
-+ beq CPDT_le_e32767
-+
-+ add r5,r5,#1
-+ sub r5,r5,#16384
-+
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+CPDT_le_e0:
-+ teq r3,#0
-+ teqeq r4,#0
-+ beq CPDT_load_zero
-+
-+ mov r5,#2
-+ sub r5,r5,#16384
-+ b CPDT_ld_e0_norm
-+
-+CPDT_le_e32767:
-+ mov r5,#0x7fffffff
-+ stmia r0,{r2-r5}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_load_decimal
-+CPDT_load_decimal:
-+
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_single
-+CPDT_store_single:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#-127
-+ ble CPDT_ss_e0
-+ cmp r4,#128
-+ bge CPDT_ss_e255
-+
-+ add r4,r4,#127
-+ orr r1,r1,r4,lsl#23
-+
-+ bic r2,r2,#0x80000000
-+ orr r1,r1,r2,lsr#8
-+
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+CPDT_ss_e0:
-+ cmp r4,#-150
-+ ble CPDT_ss_zero
-+
-+ add r4,r4,#126
-+ rsb r4,r4,#0
-+ mov r2,r2,lsr r4
-+
-+ orr r1,r1,r2,lsr#8
-+
-+CPDT_ss_zero:
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+CPDT_ss_e255:
-+ orr r1,r1,#0x7f000000
-+ orr r1,r1,#0x00800000
-+ cmp r4,#0x7fffffff
-+ movne r2,#0
-+ movne r3,#0
-+ bic r2,r2,#0x80000000
-+ orrs r4,r3,r2,lsl#24 // only bits not stored in single
-+ bne CPDT_ss_nan_special // NaN must not become Inf
-+CPDT_ss_nan_back:
-+ orr r1,r1,r2,lsr#8
-+ str r1,[r6]
-+ b fastfpe_next
-+
-+CPDT_ss_nan_special:
-+ cmp r2,#1<<8
-+ movlt r2,#1<<8
-+ b CPDT_ss_nan_back
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_double
-+CPDT_store_double:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#1024 @ this check has to be first, or
-+ bge CPDT_sd_e2047 @ overflow can occur on second !
-+ add r0,r4,#3
-+ cmp r0,#-1023+3 @ cmp with -1023
-+ ble CPDT_sd_e0
-+
-+ sub r4,r4,#1
-+ add r4,r4,#1024
-+ orr r1,r1,r4,lsl#20
-+
-+ bic r2,r2,#0x80000000
-+ orr r1,r1,r2,lsr#11
-+
-+ mov r2,r2,lsl#21
-+ orr r2,r2,r3,lsr#11
-+
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_e0:
-+ add r0,r4,#1075-1024
-+ cmp r0,#-1024
-+ ble CPDT_sd_zero
-+
-+ add r4,r4,#1024
-+ sub r4,r4,#2
-+CPDT_sd_unnormalize:
-+ movs r2,r2,lsr#1
-+ mov r3,r3,rrx
-+ adds r4,r4,#1
-+ bne CPDT_sd_unnormalize
-+
-+ orr r1,r1,r2,lsr#11
-+ mov r2,r2,lsl#21
-+ orr r2,r2,r3,lsr#11
-+
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_zero:
-+ mov r2,#0
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_e2047:
-+ orr r1,r1,#0x7f000000
-+ orr r1,r1,#0x00f00000
-+ cmp r4,#0x7fffffff
-+ movne r2,#0
-+ movne r3,#0
-+ movs r5,r3,lsl#21 // only bits not stored in double !
-+ bne CPDT_sd_nan_special
-+CPDT_sd_nan_back:
-+ orr r1,r1,r2,lsr#11
-+ mov r2,r2,lsl#21
-+ orr r2,r2,r3,lsr#11
-+ stmia r6,{r1,r2}
-+ b fastfpe_next
-+
-+CPDT_sd_nan_special:
-+ bics r2,r2,#0x80000000
-+ bne CPDT_sd_nan_back
-+ cmp r3,#1<<11
-+ movlt r3,#1<<11
-+ b CPDT_sd_nan_back
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_extended
-+CPDT_store_extended:
-+ ldmia r0,{r1-r4}
-+
-+ cmp r4,#16384 @ this check has to be first, or
-+ bge CPDT_se_e32767 @ overflow can occur with second !
-+ add r0,r4,#63
-+ cmp r0,#-16383+63
-+ ble CPDT_se_e0
-+
-+ sub r4,r4,#1
-+ add r4,r4,#16384
-+ orr r1,r4,r1,lsr#16
-+
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_e0:
-+ add r0,r4,#16446-16384
-+ cmp r0,#-16384
-+ ble CPDT_se_zero
-+
-+ add r4,r4,#16384
-+ sub r4,r4,#2
-+CPDT_se_unnormalize:
-+ movs r2,r2,lsr#1
-+ mov r3,r3,rrx
-+ adds r4,r4,#1
-+ bne CPDT_se_unnormalize
-+
-+ mov r1,r1,lsr#16
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_zero:
-+ mov r1,r1,lsr#16
-+ mov r2,#0
-+ mov r3,#0
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+CPDT_se_e32767:
-+ cmp r4,#0x7fffffff
-+ movne r2,#0
-+ movne r3,#0
-+ mov r1,r1,lsr#16
-+ orr r1,r1,#0x00007f00
-+ orr r1,r1,#0x000000ff
-+ stmia r6,{r1-r3}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_store_decimal
-+CPDT_store_decimal:
-+
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_sfm
-+CPDT_sfm_loop:
-+ add r0,r0,#1<<12
-+ and r0,r0,#7<<12
-+CPDT_sfm:
-+ add r7,r10,r0,lsr#8
-+ ldmia r7,{r2-r5}
-+ bic r3,r3,#0x80000000
-+ orr r3,r3,r2
-+ stmia r6!,{r3-r5}
-+
-+ subs r1,r1,#1
-+ bne CPDT_sfm_loop
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPDT_lfm
-+CPDT_lfm_loop:
-+ add r0,r0,#1<<12
-+ and r0,r0,#7<<12
-+CPDT_lfm:
-+ add r7,r10,r0,lsr#8
-+ ldmia r6!,{r3-r5}
-+ and r2,r3,#0x80000000
-+ cmp r5,#0x80000000 // check if the number was 0
-+ cmpne r5,#0x7fffffff // or inf/NaN
-+ biceq r3,r3,#0x80000000 // yes -> clear mantissa MSB
-+ orrne r3,r3,#0x80000000 // no -> set mantissa MSB
-+ stmia r7,{r2-r5}
-+
-+ subs r1,r1,#1
-+ bne CPDT_lfm_loop
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/CPRT.S
-@@ -0,0 +1,220 @@
-+/*
-+The FP structure has 4 words reserved for each register, the first is used just
-+for the sign in bit 31, the second and third are for the mantissa (unsigned
-+integer, high 32 bit first) and the fourth is the exponent (signed integer).
-+The mantissa is always normalized.
-+
-+If the exponent is 0x80000000, that is the most negative value, the number
-+represented is 0 and both mantissa words are also 0.
-+
-+If the exponent is 0x7fffffff, that is the biggest positive value, the number
-+represented is infinity if the mantissa is 0, otherwise it is a NaN.
-+
-+Decimal and packed decimal numbers are not supported yet.
-+*/
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .text
-+ .globl CPRT_flt
-+CPRT_flt:
-+ add r0,r13,r0,lsr#10
-+ ldr r2,[r0]
-+ mov r0,r1
-+ mov r3,#0
-+ cmp r2,#0
-+ beq CPRT_flt_zero
-+
-+ ldr r6,=round_table
-+ and r5,r4,#0x000000e0
-+ and r4,r4,#0x00080000
-+ orr r5,r5,r4,lsr#11
-+ ldr r6,[r6,r5,lsr#3] // address of rounding function
-+
-+ ands r1,r2,#0x80000000
-+ rsbne r2,r2,#0
-+ mov r4,#31
-+
-+ cmp r2,#0x00010000
-+ movcc r2,r2,lsl#16
-+ subcc r4,r4,#16
-+
-+ cmp r2,#0x01000000
-+ movcc r2,r2,lsl#8
-+ subcc r4,r4,#8
-+
-+ cmp r2,#0x10000000
-+ movcc r2,r2,lsl#4
-+ subcc r4,r4,#4
-+
-+ cmp r2,#0x40000000
-+ movcc r2,r2,lsl#2
-+ subcc r4,r4,#2
-+
-+ cmp r2,#0x80000000
-+ movcc r2,r2,lsl#1
-+ subcc r4,r4,#1
-+
-+ mov r5,#0
-+ ldr r14,=fastfpe_next
-+ mov pc,r6
-+
-+CPRT_flt_zero:
-+ mov r1,#0
-+ mov r4,#0x80000000
-+ stmia r0,{r1,r2,r3,r4}
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_fix
-+CPRT_fix:
-+ ldmia r2,{r1,r2,r3,r5}
-+ bl CPDO_rnd_core
-+
-+ add r0,r13,r0,lsr#10
-+ cmp r5,#0
-+ blt CPRT_fix_zero
-+ cmp r5,#30
-+ bgt CPRT_fix_overflow
-+
-+CPRT_fix_no_overflow:
-+ rsb r5,r5,#31
-+ mov r2,r2,lsr r5
-+ tst r1,#0x80000000
-+ rsbne r2,r2,#0
-+CPRT_fix_zero_back:
-+ str r2,[r0]
-+ ldr r1,[r10,#128]
-+ orr r1,r1,r4 // set flags possibly caused by rounding
-+ str r1,[r10,#128]
-+ b fastfpe_next
-+
-+CPRT_fix_zero:
-+ mov r2,#0
-+ b CPRT_fix_zero_back
-+
-+CPRT_fix_overflow:
-+ cmp r1,#0x80000000 // -2^31 is not exactly an overflow ...
-+ cmpeq r2,#0x80000000
-+ cmpeq r5,#31
-+ beq CPRT_fix_no_overflow
-+
-+ mov r2,#0x80000000
-+ tst r1,#0x80000000
-+ subeq r2,r2,#1
-+ str r2,[r0]
-+
-+ ldr r1,[r10,#128]
-+ orr r1,r1,#1 // set invalid operation flag
-+ str r1,[r10,#128]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_wfs
-+CPRT_wfs:
-+ ldr r0,[r13,r0,lsr#10]
-+ str r0,[r10,#128]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_rfs
-+CPRT_rfs:
-+ ldr r1,[r10,#128]
-+ bic r1,r1,#0xff000000
-+ orr r1,r1,#0x02000000 @ Software Emulation, not Acorn FPE
-+ str r1,[r13,r0,lsr#10]
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_cmf
-+CPRT_cmf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+
-+CPRT_cmf_e:
-+ ldr r0,[r13,#16*4]
-+ bic r0,r0,#0xf0000000
-+
-+ cmp r7,#0x7fffffff
-+ beq CPRT_cmf_nan1
-+CPRT_cmf_nixnan1:
-+ cmp r8,#0x7fffffff
-+ beq CPRT_cmf_nan2
-+CPRT_cmf_nixnan2:
-+
-+ cmp r1,r2
-+ beq CPRT_cmf_equalsign
-+ b CPRT_cmf_signx
-+
-+CPRT_cmf_nan1:
-+ orrs r11,r5,r3,lsl#1 // ignore MSB
-+ beq CPRT_cmf_nixnan1
-+ b CPRT_cmf_unordered
-+
-+CPRT_cmf_nan2:
-+ orrs r11,r6,r4,lsl#1 // ignore MSB
-+ beq CPRT_cmf_nixnan2
-+ b CPRT_cmf_unordered
-+
-+CPRT_cmf_equalsign:
-+ cmp r7,r8
-+ beq CPRT_cmf_equalexponent
-+ bgt CPRT_cmf_sign
-+ b CPRT_cmf_signb
-+
-+CPRT_cmf_equalexponent:
-+ cmp r3,r4
-+ cmpeq r5,r6
-+ beq CPRT_cmf_equal
-+ bhi CPRT_cmf_sign
-+ b CPRT_cmf_signb
-+
-+CPRT_cmf_signx:
-+ teq r7,#0x80000000
-+ teqeq r8,#0x80000000
-+ beq CPRT_cmf_equal
-+CPRT_cmf_sign:
-+ tst r1,#0x80000000
-+ orreq r0,r0,#0x20000000 // PSR carry
-+ orrne r0,r0,#0x80000000 // PSR negative
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_signb:
-+ tst r1,#0x80000000
-+ orrne r0,r0,#0x20000000 // PSR carry
-+ orreq r0,r0,#0x80000000 // PSR negative
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_equal:
-+ orr r0,r0,#0x60000000 // PSR carry, zero
-+ str r0,[r13,#16*4]
-+ b fastfpe_next
-+
-+CPRT_cmf_unordered:
-+ ldr r1,[r10,#128]
-+ orr r1,r1,#1 // set invalid operation flag
-+ str r1,[r10,#128]
-+
-+ tst r0,#1<<12 // FPSR AC bit set ?
-+ orrne r0,r0,#0x20000000 // PSR carry
-+ orr r0,r0,#0x10000000 // PSR overflow
-+ str r0,[r13,#16*4]
-+
-+ b fastfpe_next
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl CPRT_cnf
-+CPRT_cnf:
-+ ldmia r1,{r1,r3,r5,r7}
-+ ldmia r2,{r2,r4,r6,r8}
-+ eor r2,r2,#0x80000000
-+ b CPRT_cmf_e
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/Makefile
-@@ -0,0 +1,27 @@
-+#
-+# linux/arch/arm/fastfpe/Makefile
-+#
-+# Copyright (C) Peter Teichmann
-+#
-+
-+O_TARGET := fast-math-emu.o
-+
-+AFLAGS_CPDO.o := -march=armv3m
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+fastfpe-objs := module.o round.o CPDT.o CPRT.o CPDO.o entry.o
-+
-+list-multi := fastfpe.o
-+
-+obj-$(CONFIG_FPE_FASTFPE) += fastfpe.o
-+
-+USE_STANDARD_AS_RULE := true
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastfpe.o: $(fastfpe-objs)
-+ $(LD) -r -o $@ $(fastfpe-objs)
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/entry.S
-@@ -0,0 +1,339 @@
-+/*
-+At entry the registers contain the following information:
-+
-+r14 return address for undefined exception return
-+r9 return address for return from exception
-+r13 user registers on stack, offset 0 up to offset 4*15 contains
-+ registers r0..15, then the psr
-+r10 FP workspace 35 words (init, reg[8][4], fpsr, fpcr)
-+
-+*/
-+
-+#include <asm/procinfo.h>
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .data
-+fp_const:
-+ .word 0, 0x00000000, 0, 0x80000000 @ 0
-+ .word 0, 0x80000000, 0, 0 @ 1
-+ .word 0, 0x80000000, 0, 1 @ 2
-+ .word 0, 0xc0000000, 0, 1 @ 3
-+ .word 0, 0x80000000, 0, 2 @ 4
-+ .word 0, 0xa0000000, 0, 2 @ 5
-+ .word 0, 0x80000000, 0, -1 @ 0.5
-+ .word 0, 0xa0000000, 0, 3 @ 10
-+fp_undef:
-+ .word 0
-+fp_cond:
-+ .word 0xf0f0 @ eq
-+ .word 0x0f0f @ ne
-+ .word 0xcccc @ cs
-+ .word 0x3333 @ cc
-+ .word 0xff00 @ mi
-+ .word 0x00ff @ pl
-+ .word 0xaaaa @ vs
-+ .word 0x5555 @ vc
-+ .word 0x0c0c @ hi
-+ .word 0xf3f3 @ ls
-+ .word 0xaa55 @ ge
-+ .word 0x55aa @ lt
-+ .word 0x0a05 @ gt
-+ .word 0xf5fa @ le
-+ .word 0xffff @ al
-+ .word 0x0000 @ nv
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .text
-+ .globl fastfpe_enter
-+fastfpe_enter:
-+ ldr r4,=fp_undef
-+ str r14,[r4] @ to free one register
-+ add r10,r10,#4 @ to make the code simpler
-+ ldr r4,[r13,#60] @ r4=saved PC
-+ ldr r4,[r4,#-4] @ r4=trapped instruction
-+ and r1,r4,#0x00000f00 @ r1=coprocessor << 8
-+next_enter:
-+ cmp r1,#1<<8 @ copro 1 ?
-+ beq copro_1
-+ cmp r1,#2<<8
-+ movne pc,r14
-+
-+copro_2:
-+ and r1,r4,#0x0f000000
-+ cmp r1,#0x0c000000 @ CPDT with post indexing
-+ cmpne r1,#0x0d000000 @ CPDT with pre indexing
-+ beq CPDT_M_enter
-+ mov pc,r14
-+
-+copro_1:
-+ and r1,r4,#0x0f000000
-+ cmp r1,#0x0e000000 @ CPDO
-+ beq CPDO_CPRT_enter
-+ cmp r1,#0x0c000000 @ CPDT with post indexing
-+ cmpne r1,#0x0d000000 @ CPDT with pre indexing
-+ beq CPDT_1_enter
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ .globl fastfpe_next
-+fastfpe_next:
-+ ldr r5,[r13,#60]
-+next_after_cond_false:
-+__x1:
-+ ldrt r4,[r5],#4
-+
-+ ldr r0,=fp_cond @ check condition of next instruction
-+ mov r2,r4,lsr#28
-+ cmp r2,#0xe @ "always" condition code
-+ bne next_check_cond
-+
-+next_check_copro:
-+ and r1,r4,#0x0f000000 @ Test for copro instruction
-+ cmp r1,#0x0c000000
-+ rsbgts r0,r1,#0x0e000000 @ cmpgt #0x0e000000,r1
-+ movlt pc,r9 @ next is no copro instruction, return
-+
-+ ands r1,r4,#0x00000f00 @ r1 = coprocessor << 8
-+ cmpne r1,#3<<8
-+ movge pc,r9 @ copro = 0 or >=3, return
-+
-+ str r5,[r13,#60] @ save updated pc
-+ cmp r1,#1<<8 @ which copro ?
-+ beq copro_1
-+ b copro_2
-+
-+next_check_cond:
-+ ldr r1,[r13,#64] @ psr containing flags
-+ ldr r0,[r0,r2,lsl#2]
-+ mov r1,r1,lsr#28
-+ mov r0,r0,lsr r1
-+ tst r0,#1
-+ bne next_check_copro
-+ b next_after_cond_false @ must not necessarily have been an
-+ @ FP instruction !
-+
-+/*---------------------------------------------------------------------------*/
-+
-+undefined:
-+ ldr r4,=fp_undef
-+ ldr pc,[r4]
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDT_1_enter:
-+ and r5,r4,#0x000f0000 @ r5=base register number << 16
-+ ldr r6,[r13,r5,lsr#14] @ r6=base address
-+ cmp r5,#0x000f0000 @ base register = pc ?
-+ addeq r6,r6,#4
-+ and r7,r4,#0x000000ff @ r7=offset value
-+
-+ tst r4,#0x00800000 @ up or down?
-+ addne r7,r6,r7,lsl#2
-+ subeq r7,r6,r7,lsl#2 @ r6=base address +/- offset
-+ tst r4,#0x01000000 @ preindexing ?
-+ movne r6,r7
-+ tst r4,#0x00200000 @ write back ?
-+ cmpne r5,#0x000f0000 @ base register = pc ?
-+ strne r7,[r13,r5,lsr#14]
-+
-+ and r0,r4,#0x00007000 @ r0=fp register number << 12
-+ add r0,r10,r0,lsr#8 @ r0=address of fp register
-+
-+ and r1,r4,#0x00008000 @ T0
-+ tst r4,#0x00400000
-+ orrne r1,r1,#0x00010000 @ T1
-+ tst r4,#0x00100000
-+ orrne r1,r1,#0x00020000 @ L/S
-+
-+ ldr pc,[pc,r1,lsr#13]
-+ .word 0
-+ .word CPDT_store_single @ these functions get
-+ .word CPDT_store_double @ r0=address of fp register
-+ .word CPDT_store_extended @ r6=address of data
-+ .word undefined @ CPDT_store_decimal
-+ .word CPDT_load_single
-+ .word CPDT_load_double
-+ .word CPDT_load_extended
-+ .word undefined @ CPDT_load_decimal
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDT_M_enter:
-+ and r5,r4,#0x000f0000 @ r5=base register number << 16
-+ ldr r6,[r13,r5,lsr#14] @ r6=base address
-+ cmp r5,#0x000f0000 @ base register = pc ?
-+ addeq r6,r6,#4
-+ and r7,r4,#0x000000ff @ r7=offset value
-+
-+ tst r4,#0x00800000 @ up or down?
-+ addne r7,r6,r7,lsl#2
-+ subeq r7,r6,r7,lsl#2 @ r7=base address +/- offset
-+ tst r4,#0x01000000 @ preindexing ?
-+ movne r6,r7
-+ tst r4,#0x00200000 @ write back ?
-+ cmpne r5,#0x000f0000 @ base register = pc ?
-+ strne r7,[r13,r5,lsr#14]
-+
-+ and r0,r4,#0x00007000 @ r0=fp register number << 12
-+ and r1,r4,#0x00008000
-+ mov r1,r1,lsr#15 @ N0
-+ and r2,r4,#0x00400000
-+ orrs r1,r1,r2,lsr#21 @ N1
-+ addeq r1,r1,#4 @ r1=register count
-+
-+ tst r4,#0x00100000 @ load/store
-+ beq CPDT_sfm
-+ b CPDT_lfm
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPDO_CPRT_enter:
-+ tst r4,#0x00000010
-+ bne CPRT_enter
-+
-+ and r0,r4,#0x00007000
-+ add r0,r10,r0,lsr#8 @ r0=address of Fd
-+ and r1,r4,#0x00070000
-+ add r1,r10,r1,lsr#12 @ r1=address of Fn
-+ tst r4,#0x00000008
-+ bne CPDO_const
-+ and r2,r4,#0x00000007
-+ add r2,r10,r2,lsl#4 @ r2=address of Fm
-+
-+CPDO_constback:
-+ ldr r3,=round_table
-+ and r5,r4,#0x000000e0
-+ and r6,r4,#0x00080000
-+ orr r5,r5,r6,lsr#11 @ r5=containing rounding mode/precision
-+ ldr r14,[r3,r5,lsr#3] @ r14=address of rounding function
-+ and r3,r4,#0x00f00000
-+ tst r4,#0x00008000
-+ orrne r3,r3,#0x01000000 @ r3=operation code
-+
-+ ldr pc,[pc,r3,lsr#18]
-+ .word 0
-+CPDO_table:
-+ .word CPDO_adf
-+ .word CPDO_muf
-+ .word CPDO_suf
-+ .word CPDO_rsf
-+ .word CPDO_dvf
-+ .word CPDO_rdf
-+ .word undefined
-+ .word undefined
-+ .word CPDO_rmf
-+ .word CPDO_muf
-+ .word CPDO_dvf
-+ .word CPDO_rdf
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word CPDO_mvf
-+ .word CPDO_mnf
-+ .word CPDO_abs
-+ .word CPDO_rnd
-+ .word CPDO_sqt
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word CPDO_rnd
-+ .word fastfpe_next
-+
-+CPDO_const:
-+ ldr r2,=fp_const
-+ and r3,r4,#0x00000007
-+ add r2,r2,r3,lsl#4
-+ b CPDO_constback
-+
-+/*---------------------------------------------------------------------------*/
-+
-+CPRT_enter:
-+ and r0,r4,#0x0000f000 @ r0=Rd<<12
-+ and r1,r4,#0x00070000
-+ add r1,r10,r1,lsr#12 @ r1=address of Fn
-+ tst r4,#0x00000008
-+ bne CPRT_const
-+ and r2,r4,#0x00000007
-+ add r2,r10,r2,lsl#4 @ r2=address of Fm
-+
-+CPRT_constback:
-+ and r3,r4,#0x00f00000
-+
-+ ldr pc,[pc,r3,lsr#18]
-+ .word 0
-+ .word CPRT_flt
-+ .word CPRT_fix
-+ .word CPRT_wfs
-+ .word CPRT_rfs
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word undefined
-+ .word CPRT_cmf
-+ .word undefined
-+ .word CPRT_cnf
-+ .word undefined
-+ .word CPRT_cmf
-+ .word undefined
-+ .word CPRT_cnf
-+
-+CPRT_const:
-+ ldr r2,=fp_const
-+ and r3,r4,#0x00000007
-+ add r2,r2,r3,lsl#4
-+ b CPRT_constback
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ @ Test if long multiply instructions are available
-+
-+ .globl fastfpe_test
-+fastfpe_test:
-+ .globl elf_hwcap
-+ ldr r0,=elf_hwcap
-+ ldr r0,[r0]
-+ tst r0,#HWCAP_FAST_MULT
-+ bne fastfpe_has_long_multiply
-+ mov r0,#0
-+ mov pc,r14
-+
-+fastfpe_has_long_multiply:
-+ adr r0,CPDO_table
-+ ldr r1,=CPDO_muf_M
-+ str r1,[r0,#1*4] @ muf
-+ str r1,[r0,#9*4] @ fml
-+ ldr r1,=CPDO_dvf_M
-+ str r1,[r0,#4*4] @ dvf
-+ str r1,[r0,#10*4] @ fdv
-+ ldr r1,=CPDO_rdf_M
-+ str r1,[r0,#5*4] @ rdf
-+ str r1,[r0,#11*4] @ frd
-+ mov r0,#1
-+ mov pc,r14
-+
-+/*---------------------------------------------------------------------------*/
-+
-+ @ The fetch of the next instruction to emulate could fault
-+
-+ .section .fixup,"ax"
-+ .align
-+__f1:
-+ mov pc,r9
-+ .previous
-+ .section __ex_table,"a"
-+ .align 3
-+ .long __x1,__f1
-+ .previous
-+
-+/*---------------------------------------------------------------------------*/
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/module.c
-@@ -0,0 +1,64 @@
-+/*
-+ Fast Floating Point Emulator
-+ (c) Peter Teichmann <mail@peter-teichmann.de>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+
-+#ifndef MODULE
-+#define kern_fp_enter fp_enter
-+
-+extern char fpe_type[];
-+#endif
-+
-+static void (*orig_fp_enter)(void); /* old kern_fp_enter value */
-+extern void (*kern_fp_enter)(void); /* current FP handler */
-+extern void fastfpe_enter(void); /* forward declarations */
-+extern int fastfpe_test(void); /* long multiply available ? */
-+
-+static int __init fpe_init(void)
-+{
-+ if (fpe_type[0] && strcmp(fpe_type, "fastfpe"))
-+ return 0;
-+
-+ printk("Fast Floating Point Emulator V0.94");
-+ if (fastfpe_test() == 1) printk("M");
-+ printk(" by Peter Teichmann.\n");
-+
-+ /* Save pointer to the old FP handler and then patch ourselves in */
-+ orig_fp_enter = kern_fp_enter;
-+ kern_fp_enter = fastfpe_enter;
-+
-+ return 0;
-+}
-+
-+static void __exit fpe_exit(void)
-+{
-+ /* Restore the values we saved earlier. */
-+ kern_fp_enter = orig_fp_enter;
-+}
-+
-+module_init(fpe_init);
-+module_exit(fpe_exit);
-+
-+MODULE_AUTHOR("Peter Teichmann <mail@peter-teichmann.de>");
-+MODULE_DESCRIPTION("Fast floating point emulator with full precision");
---- /dev/null
-+++ linux-2.4.27/arch/arm/fastfpe/round.S
-@@ -0,0 +1,912 @@
-+
-+/*
-+Rounds fp register r1-r4, additional mantissa bits in r5 and stores result
-+at address r0. Returns to fastfpe_next.
-+*/
-+
-+/*------------------------------------------------------------------------*/
-+
-+ .data
-+ .globl round_table
-+round_table:
-+ .word round_single_ne
-+ .word round_single_p
-+ .word round_single_m
-+ .word round_single_z
-+ .word round_double_ne
-+ .word round_double_p
-+ .word round_double_m
-+ .word round_double_z
-+ .word round_extended_ne
-+ .word round_extended_p
-+ .word round_extended_m
-+ .word round_extended_z
-+ .word round_undef
-+ .word round_undef
-+ .word round_undef
-+ .word round_undef
-+
-+/*------------------------------------------------------------------------*/
-+
-+ .text
-+round_single_ne:
-+ cmp r4,#127
-+ bgt round_single_nz_ne_overflow
-+ cmp r4,#-126-23-1
-+ blt round_single_z_ne_underflow
-+ cmp r4,#-126
-+ blt round_single_ne_denormalized
-+
-+ adds r6,r2,#0x80 // add 0x80.00000000.00000000 to
-+ bcs round_single_add_ov // mantissa and additional bits
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,#0xff // test for inexact
-+
-+ ldrne r7,[r10,#128]
-+ orrne r7,r7,#16 // set inexact flag
-+ strne r7,[r10,#128]
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r6,#0xff
-+ biceq r6,r6,#0x100 // the even thingy
-+
-+ mov r3,#0 // remove bits not existing in single
-+ bic r2,r6,#0xff // remove bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_ne_denormalized:
-+ add r7,r4,#150
-+ mov r6,#0xffffffff
-+ mov r6,r6,lsr r7
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,r6
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, underflow flag
-+ strne r8,[r10,#128]
-+
-+ mov r8,#0x80000000
-+ mov r8,r8,lsr r7
-+ adds r2,r2,r8
-+ bcs round_single_ne_denormalized_ov
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,r6
-+ biceq r2,r2,r8,lsl #1 // the even thingy
-+
-+ mov r3,#0
-+ bic r2,r2,r6 // removing bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_ne_denormalized_ov:
-+ cmp r4,#-150
-+ cmpeq r3,#0
-+ cmpeq r2,#0
-+ beq round_single_z_ne_underflow // 1.0*2^-150 to zero!
-+ add r4,r4,#1
-+ cmp r4,#-126 // left denormalized range ?
-+ cmpge r2,#0x80 // yes -> overflow also without denormalisation ?
-+ ldrge r5,[r10,#128]
-+ bicge r5,r5,#8 // yes -> clear underflow flag
-+ strge r5,[r10,#128]
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_single_p:
-+ teq r1,#0
-+ beq round_single_nz
-+ b round_single_z
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_single_m:
-+ teq r1,#0
-+ beq round_single_z
-+ b round_single_nz
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_single_z:
-+ cmp r4,#127
-+ bgt round_single_z_overflow
-+ cmp r4,#-126-23
-+ blt round_single_z_ne_underflow
-+ cmp r4,#-126
-+ blt round_single_z_denormalized
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,#0xff // testing for inexact
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16 // set inexact flag
-+ strne r5,[r10,#128]
-+
-+ mov r3,#0
-+ bic r2,r2,#0xff // removing bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_z_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_single_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0xffffff00
-+ mov r3,#0
-+ mov r4,#127 // biggest non-infinity single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_infnan:
-+ orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB
-+ beq round_single_infnan_store
-+ tst r2,#0x40000000 // is it a SNaN?
-+ beq round_single_infnan_create_qnan
-+ mov r3,#0 // these bits can not be stored
-+ bic r2,r2,#0xff // in single precision
-+round_single_infnan_store:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_infnan_create_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0xffffff00
-+ bic r2,r2,#0x80000000 // r2 = 0x7fffff00
-+ mov r3,#0
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1 // set invalid operation flag
-+ str r5,[r10,#128]
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_z_ne_underflow:
-+ cmp r4,#0x80000000
-+ beq round_single_z_zero
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, underflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000 // was by ERROR -127
-+round_single_z_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_z_denormalized:
-+ mov r6,#0xffffffff
-+ add r7,r4,#150
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,r6,lsr r7 // testing for tinyness
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, undeflow flag
-+ strne r5,[r10,#128]
-+
-+ mov r3,#0
-+ bic r2,r2,r6,lsr r7 // removing bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_single_nz:
-+ cmp r4,#127
-+ bgt round_single_nz_ne_overflow
-+ cmp r4,#-126-23
-+ blt round_single_nz_underflow
-+ cmp r4,#-126
-+ blt round_single_nz_denormalized
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,#0xffffffff // add 0xff.ffffffff.ffffffff to
-+ adcs r2,r2,#0xff // mantissa and additional bits
-+ bcs round_single_add_ov
-+
-+ cmp r5,#0xffffffff
-+ cmpeq r3,#0xffffffff
-+ andeq r5,r2,#0xff
-+ cmpeq r5,#0xff // test for inexact
-+
-+ bic r2,r2,#0xff // remove bits not existing in single
-+
-+round_single_add_ov_back:
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16 // set inexact flag
-+ strne r5,[r10,#128]
-+
-+ mov r3,#0 // remove bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_add_ov:
-+ add r4,r4,#1
-+ cmp r4,#127
-+ bgt round_single_nz_ne_overflow
-+ movs r2,#0x80000000 // so that inexact flag gets set !!!
-+ b round_single_add_ov_back
-+
-+round_single_nz_ne_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_single_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000 // set MSB
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_nz_underflow:
-+ cmp r4,#0x80000000
-+ beq round_single_nz_zero
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, underflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r4,#-149 // smallest non-zero single
-+round_single_nz_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_nz_denormalized:
-+ mov r6,#0xffffffff
-+ add r7,r4,#150
-+ mov r6,r6,lsr r7
-+
-+ teq r5,#0
-+ teqeq r3,#0
-+ tsteq r2,r6
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, underflow flag
-+ strne r8,[r10,#128]
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,#0xffffffff
-+ adcs r2,r2,r6
-+ bcs round_single_nz_denormalized_ov
-+
-+ mov r3,#0
-+ bic r2,r2,r6 // removing bits not existing in single
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_single_nz_denormalized_ov:
-+ add r4,r4,#1
-+ cmp r4,#-126 // left denormalized range ?
-+ cmpge r2,#0x100 // yes -> overflow also without denormalisation ?
-+ ldrge r5,[r10,#128]
-+ bicge r5,r5,#8 // yes -> clear underflow flag
-+ strge r5,[r10,#128]
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_double_ne:
-+ mov r7,#0xffffffff // to generate e.g. 0x7ff
-+
-+ cmp r4,#1024
-+ bge round_double_nz_ne_overflow
-+ add r6,r4,#1024
-+ cmp r6,#-1022+1024
-+ blt round_double_ne_denormalized
-+
-+ teq r5,#0
-+ tsteq r3,r7,lsr#32-11 // testing for inexact
-+ ldrne r6,[r10,#128]
-+ orrne r6,r6,#16 // set inexact flag
-+ strne r6,[r10,#128]
-+
-+ adds r3,r3,#0x400 // add 0x0.00000400.00000000 to
-+ adcs r2,r2,#0 // mantissa and additional bits
-+ bcs round_double_add_ov
-+
-+ teq r5,#0
-+ tsteq r3,r7,lsr#32-11
-+ biceq r3,r3,#0x800 // the even thingy
-+
-+ bic r3,r3,r7,lsr#32-11 // remove bits not existing in double
-+
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_ne_denormalized:
-+ cmp r6,#-1022-52-1+1024
-+ blt round_double_z_ne_underflow
-+
-+ adds r6,r6,#1022+53-32-1024
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, undeflow flag
-+ strne r8,[r10,#128]
-+
-+ bics r8,r6,r6,lsr#1 // generate ...0001000...
-+ movne r11,#0 // from ...0001111...
-+ biceq r11,r7,r7,lsr#1 // 64bit
-+
-+ adds r3,r3,r11
-+ adcs r2,r2,r8
-+ bcs round_double_ne_denormalized_ov
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6
-+ bne round_double_ne_denormalized_noeventhingy
-+ adds r11,r11,r11
-+ adc r8,r8,r8
-+ bic r3,r3,r11
-+ bic r2,r2,r8 // the even thingy
-+
-+round_double_ne_denormalized_noeventhingy:
-+ bic r3,r3,r7 // removing bits not existing in
-+ bic r2,r2,r6 // denormalized double
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_ne_denormalized_ov:
-+ add r6,r4,#1024
-+ cmp r6,#-1023-52+1024
-+ cmpeq r3,#0
-+ cmpeq r2,#0
-+ beq round_single_z_ne_underflow // 1.0*2^(-1023-52) to zero!
-+ add r4,r4,#1
-+ cmp r6,#-1022-1+1024 // left denormalized range ?
-+ cmpge r3,#0x400 // yes -> overflow also without denormalisation ?
-+ ldrge r5,[r10,#128]
-+ bicge r5,r5,#8 // yes -> clear underflow flag
-+ strge r5,[r10,#128]
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_double_p:
-+ teq r1,#0
-+ beq round_double_nz
-+ b round_double_z
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_double_m:
-+ teq r1,#0
-+ beq round_double_z
-+ b round_double_nz
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_double_z:
-+ mov r7,#0xffffffff
-+
-+ cmp r4,#1024
-+ bge round_double_z_overflow
-+ add r6,r4,#1024
-+ cmp r6,#-1022+1024
-+ blt round_double_z_denormalized
-+
-+ teq r5,#0
-+ tsteq r3,r7,lsr#32-11 // testing for inexact
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16 // set inexact flag
-+ strne r5,[r10,#128]
-+
-+ bic r3,r3,r7,lsr#32-11 // removing bits not existing in double
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_z_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_double_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0xffffffff
-+ mov r3,r2,lsl#11 // 0xfffff800
-+ mov r4,#1024
-+ sub r4,r4,#1 // 1023; biggest non-infinity double
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_infnan:
-+ orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB
-+ beq round_double_infnan_store
-+ tst r2,#0x40000000 // is it a SNaN?
-+ beq round_double_infnan_create_qnan
-+ bic r3,r3,r7,lsr#32-11 // clear bits not in double
-+round_double_infnan_store:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_infnan_create_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,r2,lsl#11 // 0xfffff800
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1 // set invalid operation flag
-+ str r5,[r10,#128]
-+ b round_double_infnan_store
-+
-+round_double_z_ne_underflow:
-+ cmp r4,#0x80000000
-+ beq round_double_z_zero
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#16+8 // set inexact, underflow flag
-+ str r5,[r10,#128]
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+round_double_z_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_z_denormalized:
-+ cmp r6,#-1022-52+1024
-+ blt round_double_z_ne_underflow
-+
-+ adds r6,r6,#1022+53-32-1024
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, undeflow flag
-+ strne r5,[r10,#128]
-+
-+ bic r3,r3,r7 // rmoving bits not existing in
-+ bic r2,r2,r6 // denormalized double
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_double_nz:
-+ mov r7,#0xffffffff // to generate e.g. 0x7ff
-+
-+ cmp r4,#1024
-+ bge round_double_nz_ne_overflow
-+ add r6,r4,#1024
-+ cmp r6,#-1022+1024
-+ blt round_double_nz_denormalized
-+
-+ teq r5,#0
-+ tsteq r3,r7,lsr#32-11 // testing for inexact
-+ ldrne r6,[r10,#128]
-+ orrne r6,r6,#16 // set inexact flag
-+ strne r6,[r10,#128]
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,r7,lsr#32-11 // add 0x0.000007ff.ffffffff to
-+ adcs r2,r2,#0 // mantissa and additional bits
-+ bcs round_double_add_ov
-+
-+ bic r3,r3,r7,lsr#32-11 // remove bits not existing in double
-+
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_add_ov:
-+ add r4,r4,#1
-+ cmp r4,#1024
-+ bge round_double_nz_ne_overflow
-+
-+// ldrne r6,[r10,#128]
-+// orrne r6,r6,#16 // set inexact flag
-+// strne r6,[r10,#128]
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_nz_ne_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_double_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000 // set MSB
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_nz_underflow:
-+ cmp r4,#0x80000000
-+ beq round_double_nz_zero
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, underflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r4,#-1074+1024
-+ sub r4,r4,#1024 // smallest non-zero double
-+round_double_nz_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_nz_denormalized:
-+ cmp r6,#-1022-52+1024
-+ blt round_double_nz_underflow
-+
-+ adds r6,r6,#1022+53-32-1024
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, undeflow flag
-+ strne r8,[r10,#128]
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,r7
-+ adcs r2,r2,r6
-+ bcs round_double_nz_denormalized_ov
-+
-+ bic r3,r3,r7 // rmoving bits not existing in
-+ bic r2,r2,r6 // denormalized double
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_double_nz_denormalized_ov:
-+ add r4,r4,#1
-+ add r6,r4,#1024
-+ cmp r6,#-1022+1024 // left denormalized range ?
-+ cmpge r3,#0x800 // yes -> overflow also without denormalisation ?
-+ ldrge r5,[r10,#128]
-+ bicge r5,r5,#8 // yes -> clear underflow flag
-+ strge r5,[r10,#128]
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_extended_ne:
-+ mov r7,#0xffffffff // to generate e.g. 0x7ff
-+
-+ cmp r4,#16384
-+ bge round_extended_nz_ne_overflow
-+ add r6,r4,#16384
-+ cmp r6,#-16382+16384
-+ blt round_extended_ne_denormalized
-+
-+ teq r5,#0 // testing for inexact
-+ ldrne r6,[r10,#128]
-+ orrne r6,r6,#16 // set inexact flag
-+ strne r6,[r10,#128]
-+
-+ adds r5,r5,#0x80000000 // add 0x0.00000400.00000000 to
-+ adcs r3,r3,#0 // mantissa and additional bits
-+ adcs r2,r2,#0
-+ bcs round_extended_add_ov
-+
-+ teq r5,#0
-+ biceq r3,r3,#1 // the even thingy
-+
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_ne_denormalized:
-+ cmp r6,#-16382-63-1+16384
-+ blt round_extended_z_ne_underflow
-+
-+ adds r6,r6,#16382+64-32-16384
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, undeflow flag
-+ strne r8,[r10,#128]
-+
-+ bics r8,r6,r6,lsr#1 // generate ...0001000...
-+ movne r11,#0 // from ...0001111...
-+ biceq r11,r7,r7,lsr#1 // 64bit
-+
-+ adds r3,r3,r11
-+ adcs r2,r2,r8
-+ bcs round_extended_ne_denormalized_ov
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6
-+ bne round_extended_ne_denormalized_noeventhingy
-+ adds r11,r11,r11
-+ adc r8,r8,r8
-+ bic r3,r3,r11
-+ bic r2,r2,r8 // the even thingy
-+
-+round_extended_ne_denormalized_noeventhingy:
-+ bic r3,r3,r7 // removing bits not existing in
-+ bic r2,r2,r6 // denormalized extended
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_ne_denormalized_ov:
-+ add r6,r4,#16384
-+ cmp r6,#-16383-63+16384
-+ cmpeq r5,#0
-+ cmpeq r3,#0
-+ cmpeq r2,#0
-+ beq round_single_z_ne_underflow // 1.0*2^(-16383-63) to zero!
-+ add r4,r4,#1
-+ cmp r6,#-16382-1+16384 // left denormalized range ?
-+ blt round_extended_ne_still_denormalized
-+ cmp r5,#0x80000000 // FIXME yes -> overflow also without denormalisation ?
-+ ldrcs r5,[r10,#128]
-+ biccs r5,r5,#8 // yes -> clear underflow flag
-+ strcs r5,[r10,#128]
-+round_extended_ne_still_denormalized:
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_extended_p:
-+ teq r1,#0
-+ beq round_extended_nz
-+ b round_extended_z
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_extended_m:
-+ teq r1,#0
-+ beq round_extended_z
-+ b round_extended_nz
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_extended_z:
-+ mov r7,#0xffffffff
-+
-+ cmp r4,#16384
-+ bge round_extended_z_overflow
-+ add r6,r4,#16384
-+ cmp r6,#-16382+16384
-+ blt round_extended_z_denormalized
-+
-+ teq r5,#0 // testing for inexact
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16 // set inexact flag
-+ strne r5,[r10,#128]
-+
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_z_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_extended_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0xffffffff
-+ mov r3,#0xffffffff
-+ mov r4,#16384
-+ sub r4,r4,#1 // 16383; biggest non-infinity extended
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_infnan:
-+ orrs r5,r3,r2,lsl#1 // is it Inf? ignore MSB
-+ beq round_extended_infnan_store
-+ tst r2,#0x40000000 // is it a SNaN?
-+ beq round_extended_infnan_create_qnan
-+ bic r3,r3,r7,lsr#32-11 // clear bits not in extended
-+round_extended_infnan_store:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_infnan_create_qnan:
-+ mov r1,#0x80000000
-+ mov r2,#0x7fffffff
-+ mov r3,#0xffffffff
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#1 // set invalid operation flag
-+ str r5,[r10,#128]
-+ b round_extended_infnan_store
-+
-+round_extended_z_ne_underflow:
-+ cmp r4,#0x80000000
-+ beq round_extended_z_zero
-+ ldr r5,[r10,#128]
-+ orr r5,r5,#16+8 // set inexact, underflow flag
-+ str r5,[r10,#128]
-+ mov r2,#0
-+ mov r3,#0
-+ mov r4,#0x80000000
-+round_extended_z_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_z_denormalized:
-+ cmp r6,#-16382-63+16384
-+ blt round_extended_z_ne_underflow
-+
-+ adds r6,r6,#16382+64-32-16384
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, undeflow flag
-+ strne r5,[r10,#128]
-+
-+ bic r3,r3,r7 // removing bits not existing in
-+ bic r2,r2,r6 // denormalized extended
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_extended_nz:
-+ mov r7,#0xffffffff // to generate e.g. 0x7ff
-+
-+ cmp r4,#16384
-+ bge round_extended_nz_ne_overflow
-+ add r6,r4,#16384
-+ cmp r6,#-16382+16384
-+ blt round_extended_nz_denormalized
-+
-+ teq r5,#0 // testing for inexact
-+ ldrne r6,[r10,#128]
-+ orrne r6,r6,#16 // set inexact flag
-+ strne r6,[r10,#128]
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,#0 // add 0x0.0.ffffffff to
-+ adcs r2,r2,#0 // mantissa and additional bits
-+ bcs round_extended_add_ov
-+
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_add_ov:
-+ add r4,r4,#1
-+ cmp r4,#16384
-+ bge round_extended_nz_ne_overflow
-+
-+// ldrne r6,[r10,#128]
-+// orrne r6,r6,#16 // set inexact flag
-+// strne r6,[r10,#128]
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_nz_ne_overflow:
-+ cmp r4,#0x7fffffff
-+ beq round_extended_infnan
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+4 // set inexact,overflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000 // set MSB
-+ mov r3,#0
-+ mov r4,#0x7fffffff
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_nz_underflow:
-+ cmp r4,#0x80000000
-+ beq round_extended_nz_zero
-+
-+ ldrne r5,[r10,#128]
-+ orrne r5,r5,#16+8 // set inexact, underflow flag
-+ strne r5,[r10,#128]
-+ mov r2,#0x80000000
-+ mov r3,#0
-+ mov r4,#-16445+16384
-+ sub r4,r4,#16384 // smallest non-zero extended
-+round_extended_nz_zero:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_nz_denormalized:
-+ cmp r6,#-16382-63+16384
-+ blt round_extended_nz_underflow
-+
-+ adds r6,r6,#16382+64-32-16384
-+
-+ addmi r6,r6,#32
-+ movmi r6,r7,lsr r6
-+
-+ movpl r7,r7,lsr r6
-+ movpl r6,#0
-+
-+ teq r5,#0
-+ tsteq r3,r7
-+ tsteq r2,r6 // testing for tinyness
-+ ldrne r8,[r10,#128]
-+ orrne r8,r8,#16+8 // set inexact, undeflow flag
-+ strne r8,[r10,#128]
-+
-+ adds r5,r5,#0xffffffff
-+ adcs r3,r3,r7
-+ adcs r2,r2,r6
-+ bcs round_extended_nz_denormalized_ov
-+
-+ bic r3,r3,r7 // removing bits not existing in
-+ bic r2,r2,r6 // denormalized extended
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+round_extended_nz_denormalized_ov:
-+ add r4,r4,#1
-+ add r6,r4,#16384
-+ cmp r6,#-16382+16384 // left denormalized range ?
-+ cmpge r3,#1 // yes -> overflow also without denormalisation ?
-+ ldrge r5,[r10,#128]
-+ bicge r5,r5,#8 // yes -> clear underflow flag
-+ strge r5,[r10,#128]
-+ mov r3,#0
-+ mov r2,#0x80000000
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
-+
-+round_undef:
-+ stmia r0,{r1-r4}
-+ b fastfpe_next
-+
-+/*------------------------------------------------------------------------*/
---- linux-2.4.27/arch/arm/kernel/calls.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/calls.S
-@@ -115,7 +115,7 @@
- .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */
- .long SYMBOL_NAME(sys_statfs)
- /* 100 */ .long SYMBOL_NAME(sys_fstatfs)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 101 was sys_ioperm */
- .long SYMBOL_NAME(sys_socketcall)
- .long SYMBOL_NAME(sys_syslog)
- .long SYMBOL_NAME(sys_setitimer)
-@@ -126,7 +126,7 @@
- .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */
- /* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */
- .long SYMBOL_NAME(sys_vhangup)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 112 was sys_idle */
- .long SYMBOL_NAME(sys_syscall) /* call a syscall */
- .long SYMBOL_NAME(sys_wait4)
- /* 115 */ .long SYMBOL_NAME(sys_swapoff)
-@@ -137,7 +137,7 @@
- /* 120 */ .long SYMBOL_NAME(sys_clone_wapper)
- .long SYMBOL_NAME(sys_setdomainname)
- .long SYMBOL_NAME(sys_newuname)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 123 was sys_modify_ldt */
- .long SYMBOL_NAME(sys_adjtimex)
- /* 125 */ .long SYMBOL_NAME(sys_mprotect)
- .long SYMBOL_NAME(sys_sigprocmask)
-@@ -180,7 +180,7 @@
- .long SYMBOL_NAME(sys_arm_mremap)
- .long SYMBOL_NAME(sys_setresuid16)
- /* 165 */ .long SYMBOL_NAME(sys_getresuid16)
-- .long SYMBOL_NAME(sys_ni_syscall)
-+ .long SYMBOL_NAME(sys_ni_syscall) /* 166 was sys_vm86 */
- .long SYMBOL_NAME(sys_query_module)
- .long SYMBOL_NAME(sys_poll)
- .long SYMBOL_NAME(sys_nfsservctl)
---- linux-2.4.27/arch/arm/kernel/dma-rpc.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/dma-rpc.c
-@@ -26,19 +26,6 @@
- #include <asm/mach/dma.h>
- #include <asm/hardware/iomd.h>
-
--#if 0
--typedef enum {
-- dma_size_8 = 1,
-- dma_size_16 = 2,
-- dma_size_32 = 4,
-- dma_size_128 = 16
--} dma_size_t;
--
--typedef struct {
-- dma_size_t transfersize;
--} dma_t;
--#endif
--
- #define TRANSFER_SIZE 2
-
- #define CURA (0)
-@@ -48,10 +35,6 @@
- #define CR (IOMD_IO0CR - IOMD_IO0CURA)
- #define ST (IOMD_IO0ST - IOMD_IO0CURA)
-
--#define state_prog_a 0
--#define state_wait_a 1
--#define state_wait_b 2
--
- static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
- {
- unsigned long end, offset, flags = 0;
-@@ -65,7 +48,7 @@
- if (end > PAGE_SIZE)
- end = PAGE_SIZE;
-
-- if (offset + (int) TRANSFER_SIZE > end)
-+ if (offset + TRANSFER_SIZE >= end)
- flags |= DMA_END_L;
-
- sg->length = end - TRANSFER_SIZE;
-@@ -103,27 +86,31 @@
- if (!(status & DMA_ST_INT))
- return;
-
-- if (status & DMA_ST_OFL && !dma->sg)
-- break;
--
-- iomd_get_next_sg(&dma->cur_sg, dma);
-+ if ((dma->state ^ status) & DMA_ST_AB)
-+ iomd_get_next_sg(&dma->cur_sg, dma);
-
- switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
- case DMA_ST_OFL: /* OIA */
- case DMA_ST_AB: /* .IB */
- iomd_writel(dma->cur_sg.dma_address, base + CURA);
- iomd_writel(dma->cur_sg.length, base + ENDA);
-+ dma->state = DMA_ST_AB;
- break;
-
- case DMA_ST_OFL | DMA_ST_AB: /* OIB */
- case 0: /* .IA */
- iomd_writel(dma->cur_sg.dma_address, base + CURB);
- iomd_writel(dma->cur_sg.length, base + ENDB);
-+ dma->state = 0;
- break;
- }
-+
-+ if (status & DMA_ST_OFL &&
-+ dma->cur_sg.length == (DMA_END_S|DMA_END_L))
-+ break;
- } while (1);
-
-- iomd_writeb(0, base + CR);
-+ dma->state = ~DMA_ST_AB;
- disable_irq(irq);
- }
-
-@@ -158,6 +145,7 @@
- }
-
- iomd_writeb(DMA_CR_C, dma_base + CR);
-+ dma->state = DMA_ST_AB;
- }
-
- if (dma->dma_mode == DMA_MODE_READ)
-@@ -171,13 +159,11 @@
- {
- unsigned long dma_base = dma->dma_base;
- unsigned long flags;
-- unsigned int ctrl;
-
- local_irq_save(flags);
-- ctrl = iomd_readb(dma_base + CR);
-- if (ctrl & DMA_CR_E)
-+ if (dma->state != ~DMA_ST_AB)
- disable_irq(dma->dma_irq);
-- iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
-+ iomd_writeb(0, dma_base + CR);
- local_irq_restore(flags);
- }
-
---- linux-2.4.27/arch/arm/kernel/entry-armv.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/entry-armv.S
-@@ -677,12 +677,11 @@
- mrs r9, cpsr @ Enable interrupts if they were
- tst r3, #I_BIT
- biceq r9, r9, #I_BIT @ previously
-- mov r0, r2 @ *** remove once everyones in sync
- /*
- * This routine must not corrupt r9
- */
- #ifdef MULTI_CPU
-- ldr r4, .LCprocfns @ pass r0, r3 to
-+ ldr r4, .LCprocfns @ pass r2, r3 to
- mov lr, pc @ processor code
- ldr pc, [r4] @ call processor specific code
- #else
-@@ -788,9 +787,8 @@
- stmdb r5, {sp, lr}^
- alignment_trap r7, r7, __temp_abt
- zero_fp
-- mov r0, r2 @ remove once everyones in sync
- #ifdef MULTI_CPU
-- ldr r4, .LCprocfns @ pass r0, r3 to
-+ ldr r4, .LCprocfns @ pass r2, r3 to
- mov lr, pc @ processor code
- ldr pc, [r4] @ call processor specific code
- #else
-@@ -840,7 +838,8 @@
- adrsvc al, r9, ret_from_exception @ r9 = normal FP return
- adrsvc al, lr, fpundefinstr @ lr = undefined instr return
-
--call_fpe: get_current_task r10
-+call_fpe: enable_irq r10
-+ get_current_task r10
- mov r8, #1
- strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
- ldr r4, .LCfp
---- linux-2.4.27/arch/arm/kernel/fiq.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/fiq.c
-@@ -122,23 +122,23 @@
- register unsigned long tmp, tmp2;
- __asm__ volatile (
- #ifdef CONFIG_CPU_26
-- "mov %0, pc
-- bic %1, %0, #0x3
-- orr %1, %1, %3
-- teqp %1, #0 @ select FIQ mode
-- mov r0, r0
-- ldmia %2, {r8 - r14}
-- teqp %0, #0 @ return to SVC mode
-- mov r0, r0"
-+ "mov %0, pc \n"
-+ "bic %1, %0, #0x3 \n"
-+ "orr %1, %1, %3 \n"
-+ "teqp %1, #0 @ select FIQ mode \n"
-+ "mov r0, r0 \n"
-+ "ldmia %2, {r8 - r14} \n"
-+ "teqp %0, #0 @ return to SVC mode \n"
-+ "mov r0, r0 \n"
- #endif
- #ifdef CONFIG_CPU_32
-- "mrs %0, cpsr
-- mov %1, %3
-- msr cpsr_c, %1 @ select FIQ mode
-- mov r0, r0
-- ldmia %2, {r8 - r14}
-- msr cpsr_c, %0 @ return to SVC mode
-- mov r0, r0"
-+ "mrs %0, cpsr \n"
-+ "mov %1, %3 \n"
-+ "msr cpsr_c, %1 @ select FIQ mode \n"
-+ "mov r0, r0 \n"
-+ "ldmia %2, {r8 - r14} \n"
-+ "msr cpsr_c, %0 @ return to SVC mode \n"
-+ "mov r0, r0 \n"
- #endif
- : "=&r" (tmp), "=&r" (tmp2)
- : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
-@@ -154,23 +154,23 @@
- register unsigned long tmp, tmp2;
- __asm__ volatile (
- #ifdef CONFIG_CPU_26
-- "mov %0, pc
-- bic %1, %0, #0x3
-- orr %1, %1, %3
-- teqp %1, #0 @ select FIQ mode
-- mov r0, r0
-- stmia %2, {r8 - r14}
-- teqp %0, #0 @ return to SVC mode
-- mov r0, r0"
-+ "mov %0, pc \n"
-+ "bic %1, %0, #0x3 \n"
-+ "orr %1, %1, %3 \n"
-+ "teqp %1, #0 @ select FIQ mode \n"
-+ "mov r0, r0 \n"
-+ "stmia %2, {r8 - r14} \n"
-+ "teqp %0, #0 @ return to SVC mode \n"
-+ "mov r0, r0 \n"
- #endif
- #ifdef CONFIG_CPU_32
-- "mrs %0, cpsr
-- mov %1, %3
-- msr cpsr_c, %1 @ select FIQ mode
-- mov r0, r0
-- stmia %2, {r8 - r14}
-- msr cpsr_c, %0 @ return to SVC mode
-- mov r0, r0"
-+ "mrs %0, cpsr \n"
-+ "mov %1, %3 \n"
-+ "msr cpsr_c, %1 @ select FIQ mode \n"
-+ "mov r0, r0 \n"
-+ "stmia %2, {r8 - r14} \n"
-+ "msr cpsr_c, %0 @ return to SVC mode \n"
-+ "mov r0, r0 \n"
- #endif
- : "=&r" (tmp), "=&r" (tmp2)
- : "r" (&regs->ARM_r8), "I" (I_BIT | F_BIT | FIQ_MODE)
---- linux-2.4.27/arch/arm/kernel/head-armv.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/head-armv.S
-@@ -1,7 +1,7 @@
- /*
- * linux/arch/arm/kernel/head-armv.S
- *
-- * Copyright (C) 1994-1999 Russell King
-+ * Copyright (C) 1994-2003 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
-@@ -163,10 +163,10 @@
- */
- .type __ret, %function
- __ret: ldr lr, __switch_data
-- mcr p15, 0, r0, c1, c0
-- mrc p15, 0, r0, c1, c0, 0 @ read it back.
-- mov r0, r0
-- mov r0, r0
-+ mcr p15, 0, r0, c1, c0, 0
-+ mrc p15, 0, r3, c0, c0, 0
-+ mov r3, r3
-+ mov r3, r3
- mov pc, lr
-
- /*
-@@ -214,6 +214,11 @@
- */
- __create_page_tables:
- pgtbl r4, r5 @ page table address
-+#if defined(CONFIG_CPU_DCACHE_DISABLE)
-+ bic r8, r8, #0x00c @ clear B, C
-+#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
-+ bic r8, r8, #0x004 @ clear B
-+#endif
-
- /*
- * Clear the 16K level 1 swapper page table
---- linux-2.4.27/arch/arm/kernel/irq.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/irq.c
-@@ -549,7 +549,7 @@
- kfree(action);
- goto out;
- }
-- printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
-+ printk(KERN_ERR "Trying to free IRQ%d\n",irq);
- #ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
- #endif
---- linux-2.4.27/arch/arm/kernel/ptrace.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/ptrace.c
-@@ -725,11 +725,8 @@
- goto out_tsk;
- }
- ret = -ESRCH;
-- if (!(child->ptrace & PT_PTRACED))
-- goto out_tsk;
-- if (child->state != TASK_STOPPED && request != PTRACE_KILL)
-- goto out_tsk;
-- if (child->p_pptr != current)
-+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
-+ if (ret)
- goto out_tsk;
-
- ret = do_ptrace(request, child, addr, data);
---- linux-2.4.27/arch/arm/kernel/semaphore.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/semaphore.c
-@@ -193,7 +193,7 @@
- bl __down_interruptible \n\
- mov ip, r0 \n\
- ldmfd sp!, {r0 - r3, pc}^ \n\
--
-+ \n\
- .align 5 \n\
- .globl __down_trylock_failed \n\
- __down_trylock_failed: \n\
---- linux-2.4.27/arch/arm/kernel/signal.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/kernel/signal.c
-@@ -641,10 +641,7 @@
- /* FALLTHRU */
-
- default:
-- sigaddset(&current->pending.signal, signr);
-- recalc_sigpending(current);
-- current->flags |= PF_SIGNALED;
-- do_exit(exit_code);
-+ sig_exit(signr, exit_code, &info);
- /* NOTREACHED */
- }
- }
---- linux-2.4.27/arch/arm/lib/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/lib/Makefile
-@@ -15,7 +15,7 @@
- strnlen_user.o strchr.o strrchr.o testchangebit.o \
- testclearbit.o testsetbit.o uaccess.o getuser.o \
- putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
-- ucmpdi2.o udivdi3.o lib1funcs.o
-+ ucmpdi2.o udivdi3.o lib1funcs.o div64.o
- obj-m :=
- obj-n :=
-
---- /dev/null
-+++ linux-2.4.27/arch/arm/lib/div64.S
-@@ -0,0 +1,59 @@
-+#include <linux/linkage.h>
-+
-+#ifndef __ARMEB__
-+ql .req r0 @ quotient low
-+qh .req r1 @ quotient high
-+onl .req r0 @ original dividend low
-+onh .req r1 @ original dividend high
-+nl .req r4 @ dividend low
-+nh .req r5 @ dividend high
-+res .req r4 @ result
-+#else
-+ql .req r1
-+qh .req r0
-+onl .req r1
-+onh .req r0
-+nl .req r5
-+nh .req r4
-+res .req r5
-+#endif
-+
-+dl .req r3 @ divisor low
-+dh .req r2 @ divsor high
-+
-+
-+ENTRY(do_div64)
-+ stmfd sp!, {r4, r5, lr}
-+ mov nl, onl
-+ movs nh, onh @ if high bits are zero
-+ movne lr, #33
-+ moveq lr, #1 @ only divide low bits
-+ moveq nh, onl
-+
-+ tst dh, #0x80000000
-+ bne 2f
-+1: cmp nh, dh
-+ bls 2f
-+ add lr, lr, #1
-+ movs dh, dh, lsl #1 @ left justify disor
-+ bpl 1b
-+
-+2: movs nh, onh
-+ moveq dl, dh
-+ moveq dh, #0
-+ movne dl, #0
-+ mov ql, #0
-+ mov qh, #0
-+3: subs ip, nl, dl @ trial subtraction
-+ sbcs ip, nh, dh
-+ movcs nh, ip @ only update if successful
-+ subcs nl, nl, dl @ (repeat the subtraction)
-+ adcs ql, ql, ql @ C=1 if successful, shift into
-+ adc qh, qh, qh @ quotient
-+ movs dh, dh, lsr #1 @ shift base high part right
-+ mov dl, dl, rrx @ shift base low part right
-+ subs lr, lr, #1
-+ bne 3b
-+
-+ mov r2, res
-+ ldmfd sp!, {r4, r5, pc}
---- linux-2.4.27/arch/arm/lib/putuser.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/lib/putuser.S
-@@ -30,11 +30,11 @@
-
- .global __put_user_1
- __put_user_1:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #1
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #1
-+ cmp r0, ip
- 1: strlsbt r1, [r0]
- movls r0, #0
- movls pc, lr
-@@ -42,11 +42,11 @@
-
- .global __put_user_2
- __put_user_2:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #2
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #2
-+ cmp r0, ip
- 2: strlsbt r1, [r0], #1
- movls r1, r1, lsr #8
- 3: strlsbt r1, [r0]
-@@ -56,11 +56,11 @@
-
- .global __put_user_4
- __put_user_4:
-- bic r2, sp, #0x1f00
-- bic r2, r2, #0x00ff
-- ldr r2, [r2, #TSK_ADDR_LIMIT]
-- sub r2, r2, #4
-- cmp r0, r2
-+ bic ip, sp, #0x1f00
-+ bic ip, ip, #0x00ff
-+ ldr ip, [ip, #TSK_ADDR_LIMIT]
-+ sub ip, ip, #4
-+ cmp r0, ip
- 4: strlst r1, [r0]
- movls r0, #0
- movls pc, lr
---- linux-2.4.27/arch/arm/mach-at91rm9200/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mach-at91rm9200/Makefile
-@@ -18,4 +18,8 @@
-
- export-objs :=
-
-+# LEDs support
-+leds-$(CONFIG_ARCH_AT91RM9200DK) += dk-leds.o
-+obj-$(CONFIG_LEDS) += $(leds-y)
-+
- include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-at91rm9200/dk-leds.c
-@@ -0,0 +1,97 @@
-+/*
-+ * LED driver for the Atmel AT91RM9200 Development Kit.
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+
-+#include <asm/mach-types.h>
-+#include <asm/leds.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/pio.h>
-+
-+
-+static inline void at91_led_on(void)
-+{
-+ AT91_SYS->PIOB_CODR = AT91C_PIO_PB2;
-+}
-+
-+static inline void at91_led_off(void)
-+{
-+ AT91_SYS->PIOB_SODR = AT91C_PIO_PB2;
-+}
-+
-+static inline void at91_led_toggle(void)
-+{
-+ unsigned long curr = AT91_SYS->PIOB_ODSR;
-+ if (curr & AT91C_PIO_PB2)
-+ AT91_SYS->PIOB_CODR = AT91C_PIO_PB2;
-+ else
-+ AT91_SYS->PIOB_SODR = AT91C_PIO_PB2;
-+}
-+
-+
-+/*
-+ * Handle LED events.
-+ */
-+static void at91rm9200dk_leds_event(led_event_t evt)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ switch(evt) {
-+ case led_start: /* System startup */
-+ at91_led_on();
-+ break;
-+
-+ case led_stop: /* System stop / suspend */
-+ at91_led_off();
-+ break;
-+
-+#ifdef CONFIG_LEDS_TIMER
-+ case led_timer: /* Every 50 timer ticks */
-+ at91_led_toggle();
-+ break;
-+#endif
-+
-+#ifdef CONFIG_LEDS_CPU
-+ case led_idle_start: /* Entering idle state */
-+ at91_led_off();
-+ break;
-+
-+ case led_idle_end: /* Exit idle state */
-+ at91_led_on();
-+ break;
-+#endif
-+
-+ default:
-+ break;
-+ }
-+
-+ local_irq_restore(flags);
-+}
-+
-+
-+static int __init leds_init(void)
-+{
-+ /* Enable PIO to access the LEDs */
-+ AT91_SYS->PIOB_PER = AT91C_PIO_PB2;
-+ AT91_SYS->PIOB_OER = AT91C_PIO_PB2;
-+
-+ leds_event = at91rm9200dk_leds_event;
-+
-+ leds_event(led_start);
-+ return 0;
-+}
-+
-+__initcall(leds_init);
---- linux-2.4.27/arch/arm/mach-integrator/pci_v3.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mach-integrator/pci_v3.c
-@@ -21,7 +21,6 @@
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <linux/config.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/ptrace.h>
-@@ -32,6 +31,7 @@
- #include <linux/init.h>
-
- #include <asm/hardware.h>
-+#include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/system.h>
- #include <asm/mach/pci.h>
-@@ -447,15 +447,16 @@
- #define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20)
- #define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24)
-
--static int v3_fault(unsigned long addr, struct pt_regs *regs)
-+static int
-+v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- unsigned long pc = instruction_pointer(regs);
- unsigned long instr = *(unsigned long *)pc;
- #if 0
- char buf[128];
-
-- sprintf(buf, "V3 fault: address=0x%08lx, pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-- addr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
-+ sprintf(buf, "V3 fault: addr 0x%08lx, FSR 0x%03x, PC 0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x ISTAT=%02x\n",
-+ addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255,
- v3_readb(V3_LB_ISTAT));
- printk(KERN_DEBUG "%s", buf);
- printascii(buf);
-@@ -523,8 +524,6 @@
- #endif
- }
-
--extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
--
- /*
- * V3_LB_BASE? - local bus address
- * V3_LB_MAP? - pci bus address
-@@ -539,7 +538,10 @@
- /*
- * Hook in our fault handler for PCI errors
- */
-- external_fault = v3_fault;
-+ hook_fault_code(4, v3_pci_fault, SIGBUS, "external abort on linefetch");
-+ hook_fault_code(6, v3_pci_fault, SIGBUS, "external abort on linefetch");
-+ hook_fault_code(8, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
-+ hook_fault_code(10, v3_pci_fault, SIGBUS, "external abort on non-linefetch");
-
- spin_lock_irqsave(&v3_lock, flags);
-
-@@ -629,7 +631,7 @@
- #if 0
- ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
- if (ret)
-- printk(KERN_ERR "PCI: unable to grab local bus timeout ".
-+ printk(KERN_ERR "PCI: unable to grab local bus timeout "
- "interrupt: %d\n", ret);
- #endif
- }
---- linux-2.4.27/arch/arm/mach-sa1100/pm.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mach-sa1100/pm.c
-@@ -21,6 +21,8 @@
- *
- * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
- * Storage is local on the stack now.
-+ * 2003-06-25: Jeff Corrall <jcorrall@mac.com>
-+ * Saved the GPIO levels for resume after sleep.
- */
- #include <linux/config.h>
- #include <linux/init.h>
-@@ -70,13 +72,20 @@
- int pm_do_suspend(void)
- {
- unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+ unsigned long sleep_save_gpsr;
-+ unsigned long sleep_save_gpcr;
-+ unsigned long delta;
-
- cli();
-
- leds_event(led_stop);
-
- /* preserve current time */
-- RCNR = xtime.tv_sec;
-+ delta = xtime.tv_sec - RCNR;
-+
-+ /* save the current state of the GPIO output pins */
-+ sleep_save_gpsr = GPDR & GPLR;
-+ sleep_save_gpcr = GPDR & ~GPLR;
-
- /* save vital registers */
- SAVE(OSCR);
-@@ -121,6 +130,10 @@
- printk(KERN_DEBUG "*** made it back from resume\n");
- #endif
-
-+ /* restore GPIO output state before enabling the pins */
-+ GPSR = sleep_save_gpsr;
-+ GPCR = sleep_save_gpcr;
-+
- /* restore registers */
- RESTORE(GPDR);
- RESTORE(GRER);
-@@ -151,7 +164,7 @@
- RESTORE(ICMR);
-
- /* restore current time */
-- xtime.tv_sec = RCNR;
-+ xtime.tv_sec = RCNR + delta;
-
- leds_event(led_start);
-
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/sa1100_usb.h
-@@ -0,0 +1,193 @@
-+/*
-+ * sa1100_usb.h
-+ *
-+ * Public interface to the sa1100 USB core. For use by client modules
-+ * like usb-eth and usb-char.
-+ *
-+ */
-+
-+#ifndef _SA1100_USB_H
-+#define _SA1100_USB_H
-+#include <asm/byteorder.h>
-+
-+typedef void (*usb_callback_t)(int flag, int size);
-+
-+/* in usb_ctl.c (see also descriptor methods at bottom of file) */
-+
-+// Open the USB client for client and initialize data structures
-+// to default values, but _do not_ start UDC.
-+int sa1100_usb_open( const char * client_name );
-+
-+// Start UDC running
-+int sa1100_usb_start( void );
-+
-+// Immediately stop udc, fire off completion routines w/-EINTR
-+int sa1100_usb_stop( void ) ;
-+
-+// Disconnect client from usb core
-+int sa1100_usb_close( void ) ;
-+
-+// set notify callback for when core reaches configured state
-+// return previous pointer (if any)
-+typedef void (*usb_notify_t)(void);
-+usb_notify_t sa1100_set_configured_callback( usb_notify_t callback );
-+
-+/* in usb_send.c */
-+int sa1100_usb_xmitter_avail( void );
-+int sa1100_usb_send(char *buf, int len, usb_callback_t callback);
-+void sa1100_usb_send_reset(void);
-+
-+/* in usb_recev.c */
-+int sa1100_usb_recv(char *buf, int len, usb_callback_t callback);
-+void sa1100_usb_recv_reset(void);
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Descriptor Management
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define DescriptorHeader \
-+ __u8 bLength; \
-+ __u8 bDescriptorType
-+
-+
-+// --- Device Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bcdUSB; /* USB specification revision number in BCD */
-+ __u8 bDeviceClass; /* USB class for entire device */
-+ __u8 bDeviceSubClass; /* USB subclass information for entire device */
-+ __u8 bDeviceProtocol; /* USB protocol information for entire device */
-+ __u8 bMaxPacketSize0; /* Max packet size for endpoint zero */
-+ __u16 idVendor; /* USB vendor ID */
-+ __u16 idProduct; /* USB product ID */
-+ __u16 bcdDevice; /* vendor assigned device release number */
-+ __u8 iManufacturer; /* index of manufacturer string */
-+ __u8 iProduct; /* index of string that describes product */
-+ __u8 iSerialNumber; /* index of string containing device serial number */
-+ __u8 bNumConfigurations; /* number fo configurations */
-+} __attribute__ ((packed)) device_desc_t;
-+
-+// --- Configuration Descriptor ------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 wTotalLength; /* total # of bytes returned in the cfg buf 4 this cfg */
-+ __u8 bNumInterfaces; /* number of interfaces in this cfg */
-+ __u8 bConfigurationValue; /* used to uniquely ID this cfg */
-+ __u8 iConfiguration; /* index of string describing configuration */
-+ __u8 bmAttributes; /* bitmap of attributes for ths cfg */
-+ __u8 MaxPower; /* power draw in 2ma units */
-+} __attribute__ ((packed)) config_desc_t;
-+
-+// bmAttributes:
-+enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40,
-+ USB_CONFIG_BUSPOWERED=0x80 };
-+// MaxPower:
-+#define USB_POWER( x) ((x)>>1) /* convert mA to descriptor units of A for MaxPower */
-+
-+// --- Interface Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bInterfaceNumber; /* Index uniquely identfying this interface */
-+ __u8 bAlternateSetting; /* ids an alternate setting for this interface */
-+ __u8 bNumEndpoints; /* number of endpoints in this interface */
-+ __u8 bInterfaceClass; /* USB class info applying to this interface */
-+ __u8 bInterfaceSubClass; /* USB subclass info applying to this interface */
-+ __u8 bInterfaceProtocol; /* USB protocol info applying to this interface */
-+ __u8 iInterface; /* index of string describing interface */
-+} __attribute__ ((packed)) intf_desc_t;
-+
-+// --- Endpoint Descriptor ---------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
-+ __u8 bmAttributes; /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
-+ __u16 wMaxPacketSize; /* data payload size for this ep in this cfg */
-+ __u8 bInterval; /* polling interval for this ep in this cfg */
-+} __attribute__ ((packed)) ep_desc_t;
-+
-+// bEndpointAddress:
-+enum { USB_OUT= 0, USB_IN=1 };
-+#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
-+// bmAttributes:
-+enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 };
-+
-+// --- String Descriptor -------------------
-+
-+typedef struct {
-+ DescriptorHeader;
-+ __u16 bString[1]; /* unicode string .. actaully 'n' __u16s */
-+} __attribute__ ((packed)) string_desc_t;
-+
-+/*=======================================================
-+ * Handy helpers when working with above
-+ *
-+ */
-+// these are x86-style 16 bit "words" ...
-+#define make_word_c( w ) __constant_cpu_to_le16(w)
-+#define make_word( w ) __cpu_to_le16(w)
-+
-+// descriptor types
-+enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3,
-+ USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 };
-+
-+
-+/*=======================================================
-+ * Default descriptor layout for SA-1100 and SA-1110 UDC
-+ */
-+
-+/* "config descriptor buffer" - that is, one config,
-+ ..one interface and 2 endpoints */
-+struct cdb {
-+ config_desc_t cfg;
-+ intf_desc_t intf;
-+ ep_desc_t ep1;
-+ ep_desc_t ep2;
-+} __attribute__ ((packed));
-+
-+
-+/* all SA device descriptors */
-+typedef struct {
-+ device_desc_t dev; /* device descriptor */
-+ struct cdb b; /* bundle of descriptors for this cfg */
-+} __attribute__ ((packed)) desc_t;
-+
-+
-+/*=======================================================
-+ * Descriptor API
-+ */
-+
-+/* Get the address of the statically allocated desc_t structure
-+ in the usb core driver. Clients can modify this between
-+ the time they call sa1100_usb_open() and sa1100_usb_start()
-+*/
-+desc_t *
-+sa1100_usb_get_descriptor_ptr( void );
-+
-+
-+/* Set a pointer to the string descriptor at "index". The driver
-+ ..has room for 8 string indicies internally. Index zero holds
-+ ..a LANGID code and is set to US English by default. Inidices
-+ ..1-7 are available for use in the config descriptors as client's
-+ ..see fit. This pointer is assumed to be good as long as the
-+ ..SA usb core is open (so statically allocate them). Returnes -EINVAL
-+ ..if index out of range */
-+int sa1100_usb_set_string_descriptor( int index, string_desc_t * p );
-+
-+/* reverse of above */
-+string_desc_t *
-+sa1100_usb_get_string_descriptor( int index );
-+
-+/* kmalloc() a string descriptor and convert "p" to unicode in it */
-+string_desc_t *
-+sa1100_usb_kmalloc_string_descriptor( const char * p );
-+
-+
-+
-+
-+
-+
-+#endif /* _SA1100_USB_H */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/sa1111-ohci.c
-@@ -0,0 +1,140 @@
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/pci.h>
-+#include <linux/mm.h>
-+
-+#ifdef CONFIG_USB_OHCI
-+
-+/*
-+ * The SA-1111 errata says that the DMA hardware needs to be exercised
-+ * before the clocks are turned on to work properly. This code does
-+ * a tiny dma transfer to prime to hardware.
-+ *
-+ * What DMA errata? I've checked October 1999 and February 2001, both
-+ * of which do not mention such a bug, let alone any details of this
-+ * work-around.
-+ */
-+static void __init sa1111_dma_setup(void)
-+{
-+ dma_addr_t dma_buf;
-+ void * vbuf;
-+
-+ /* DMA init & setup */
-+
-+ /* WARNING: The SA-1111 L3 function is used as part of this
-+ * SA-1111 DMA errata workaround.
-+ *
-+ * N.B., When the L3 function is enabled, it uses GPIO_B<4:5>
-+ * and takes precedence over the PS/2 mouse and GPIO_B
-+ * functions. Refer to "Intel StrongARM SA-1111 Microprocessor
-+ * Companion Chip, Sect 10.2" for details. So this "fix" may
-+ * "break" support of either PS/2 mouse or GPIO_B if
-+ * precautions are not taken to avoid collisions in
-+ * configuration and use of these pins. AFAIK, no precautions
-+ * are taken at this time. So it is likely that the action
-+ * taken here may cause problems in PS/2 mouse and/or GPIO_B
-+ * pin use elsewhere.
-+ *
-+ * But wait, there's more... What we're doing here is
-+ * obviously altogether a bad idea. We're indiscrimanately bit
-+ * flipping config for a few different functions here which
-+ * are "owned" by other drivers. This needs to be handled
-+ * better than it is being done here at this time. */
-+
-+ /* prime the dma engine with a tiny dma */
-+ SKPCR |= SKPCR_I2SCLKEN;
-+ SKAUD |= SKPCR_L3CLKEN | SKPCR_SCLKEN;
-+
-+ SACR0 |= 0x00003305;
-+ SACR1 = 0x00000000;
-+
-+ /*
-+ * We need memory below 1MB.
-+ * NOTE: consistent_alloc gives you some random virtual
-+ * address as its return value, and the DMA address via
-+ * the dma_addr_t pointer.
-+ */
-+ vbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, 4, &dma_buf);
-+
-+ SADTSA = (unsigned long)dma_buf;
-+ SADTCA = 4;
-+
-+ SADTCS |= 0x00000011;
-+ SKPCR |= SKPCR_DCLKEN;
-+
-+ /* wait */
-+ udelay(100);
-+
-+ /* clear reserved but, then disable SAC */
-+ SACR0 &= ~(0x00000002);
-+ SACR0 &= ~(0x00000001);
-+
-+ /* toggle bit clock direction */
-+ SACR0 |= 0x00000004;
-+ SACR0 &= ~(0x00000004);
-+
-+ SKAUD &= ~(SKPCR_L3CLKEN | SKPCR_SCLKEN);
-+
-+ SKPCR &= ~SKPCR_I2SCLKEN;
-+
-+ consistent_free(vbuf, 4, dma_buf);
-+}
-+
-+/*
-+ * reset the SA-1111 usb controller and turn on it's clocks
-+ */
-+int __init sa1111_ohci_hcd_init(void)
-+{
-+ unsigned int usb_reset = 0;
-+
-+ if (machine_is_xp860() ||
-+ machine_has_neponset() ||
-+ machine_is_pfs168() ||
-+ machine_is_badge4())
-+ usb_reset = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
-+
-+ /*
-+ * turn on USB clocks
-+ */
-+ SKPCR |= SKPCR_UCLKEN;
-+ udelay(100);
-+
-+ /*
-+ * Force USB reset
-+ */
-+ USB_RESET = USB_RESET_FORCEIFRESET;
-+ USB_RESET |= USB_RESET_FORCEHCRESET;
-+ udelay(100);
-+
-+ /*
-+ * Take out of reset
-+ */
-+ USB_RESET = 0;
-+
-+ /*
-+ * set power sense and control lines (this from the diags code)
-+ */
-+ USB_RESET = usb_reset;
-+
-+ /*
-+ * Huh? This is a _read only_ register --rmk
-+ */
-+ USB_STATUS = 0;
-+
-+ udelay(10);
-+
-+ /*
-+ * compensate for dma bug
-+ */
-+ sa1111_dma_setup();
-+
-+ return 0;
-+}
-+
-+void sa1111_ohci_hcd_cleanup(void)
-+{
-+ /* turn the USB clock off */
-+ SKPCR &= ~SKPCR_UCLKEN;
-+}
-+
-+#endif /* CONFIG_USB_OHCI */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb-char.c
-@@ -0,0 +1,723 @@
-+/*
-+ * (C) Copyright 2000-2001 Extenex Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * usb-char.c
-+ *
-+ * Miscellaneous character device interface for SA1100 USB function
-+ * driver.
-+ *
-+ * Background:
-+ * The SA1100 function driver ported from the Compaq Itsy project
-+ * has an interface, usb-eth.c, to feed network packets over the
-+ * usb wire and into the Linux TCP/IP stack.
-+ *
-+ * This file replaces that one with a simple character device
-+ * interface that allows unstructured "byte pipe" style reads and
-+ * writes over the USB bulk endpoints by userspace programs.
-+ *
-+ * A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
-+ * when set, (the default) causes the ethernet interface to be used.
-+ * When not set, this more pedestrian character interface is linked
-+ * in instead.
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ * ward.willats@extenex.com
-+ *
-+ * To do:
-+ * - Can't dma into ring buffer directly with pci_map/unmap usb_recv
-+ * uses and get bytes out at the same time DMA is going on. Investigate:
-+ * a) changing usb_recv to use alloc_consistent() at client request; or
-+ * b) non-ring-buffer based data structures. In the meantime, I am using
-+ * a bounce buffer. Simple, but wasteful.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/cache.h>
-+#include <linux/poll.h>
-+#include <linux/circ_buf.h>
-+#include <linux/timer.h>
-+
-+#include <asm/io.h>
-+#include <asm/semaphore.h>
-+#include <asm/proc/page.h>
-+#include <asm/mach-types.h>
-+
-+#include "usb-char.h"
-+#include "sa1100_usb.h"
-+
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Driver Options
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#define VERSION "0.4"
-+
-+
-+#define VERBOSITY 1
-+
-+#if VERBOSITY
-+# define PRINTK(x, a...) printk (x, ## a)
-+#else
-+# define PRINTK(x, a...) /**/
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals - Macros - Enums - Structures
-+//////////////////////////////////////////////////////////////////////////////
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+typedef int bool; enum { false = 0, true = 1 };
-+
-+static const char pszMe[] = "usbchr: ";
-+
-+static wait_queue_head_t wq_read;
-+static wait_queue_head_t wq_write;
-+static wait_queue_head_t wq_poll;
-+
-+/* Serialze multiple writers onto the transmit hardware
-+.. since we sleep the writer during transmit to stay in
-+.. sync. (Multiple writers don't make much sense, but..) */
-+static DECLARE_MUTEX( xmit_sem );
-+
-+// size of usb DATA0/1 packets. 64 is standard maximum
-+// for bulk transport, though most hosts seem to be able
-+// to handle larger.
-+#define TX_PACKET_SIZE 64
-+#define RX_PACKET_SIZE 64
-+#define RBUF_SIZE (4*PAGE_SIZE)
-+
-+static struct wcirc_buf {
-+ char *buf;
-+ int in;
-+ int out;
-+} rx_ring = { NULL, 0, 0 };
-+
-+static struct {
-+ unsigned long cnt_rx_complete;
-+ unsigned long cnt_rx_errors;
-+ unsigned long bytes_rx;
-+ unsigned long cnt_tx_timeouts;
-+ unsigned long cnt_tx_errors;
-+ unsigned long bytes_tx;
-+} charstats;
-+
-+
-+static char * tx_buf = NULL;
-+static char * packet_buffer = NULL;
-+static int sending = 0;
-+static int usb_ref_count = 0;
-+static int last_tx_result = 0;
-+static int last_rx_result = 0;
-+static int last_tx_size = 0;
-+static struct timer_list tx_timer;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+static char * what_the_f( int e );
-+static void free_txrx_buffers( void );
-+static void twiddle_descriptors( void );
-+static void free_string_descriptors( void ) ;
-+static int usbc_open( struct inode *pInode, struct file *pFile );
-+static void rx_done_callback_packet_buffer( int flag, int size );
-+
-+static void tx_timeout( unsigned long );
-+static void tx_done_callback( int flag, int size );
-+
-+static ssize_t usbc_read( struct file *, char *, size_t, loff_t * );
-+static ssize_t usbc_write( struct file *, const char *, size_t, loff_t * );
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument );
-+static int usbc_close( struct inode *pInode, struct file *pFile );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+static void extenex_configured_notify_proc( void );
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static char * what_the_f( int e )
-+{
-+ char * p;
-+ switch( e ) {
-+ case 0:
-+ p = "noErr";
-+ break;
-+ case -ENODEV:
-+ p = "ENODEV - usb not in config state";
-+ break;
-+ case -EBUSY:
-+ p = "EBUSY - another request on the hardware";
-+ break;
-+ case -EAGAIN:
-+ p = "EAGAIN";
-+ break;
-+ case -EINTR:
-+ p = "EINTR - interrupted\n";
-+ break;
-+ case -EPIPE:
-+ p = "EPIPE - zero length xfer\n";
-+ break;
-+ default:
-+ p = "????";
-+ break;
-+ }
-+ return p;
-+}
-+
-+static void free_txrx_buffers( void )
-+{
-+ if ( rx_ring.buf != NULL ) {
-+ kfree( rx_ring.buf );
-+ rx_ring.buf = NULL;
-+ }
-+ if ( packet_buffer != NULL ) {
-+ kfree( packet_buffer );
-+ packet_buffer = NULL;
-+ }
-+ if ( tx_buf != NULL ) {
-+ kfree( tx_buf );
-+ tx_buf = NULL;
-+ }
-+}
-+
-+/* twiddle_descriptors()
-+ * It is between open() and start(). Setup descriptors.
-+ */
-+static void twiddle_descriptors( void )
-+{
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ string_desc_t * pString;
-+
-+ pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
-+ pDesc->b.ep1.bmAttributes = USB_EP_BULK;
-+ pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
-+ pDesc->b.ep2.bmAttributes = USB_EP_BULK;
-+
-+ if ( machine_is_extenex1() ) {
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ pDesc->dev.idVendor = make_word_c( 0xC9F );
-+ pDesc->dev.idProduct = 1;
-+ pDesc->dev.bcdDevice = make_word_c( 0x0001 );
-+ pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
-+ pDesc->b.cfg.MaxPower = 0;
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "Extenex" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 1, pString );
-+ pDesc->dev.iManufacturer = 1;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "Handheld Theater" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 2, pString );
-+ pDesc->dev.iProduct = 2;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "00000000" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 3, pString );
-+ pDesc->dev.iSerialNumber = 3;
-+ }
-+
-+ pString = sa1100_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
-+ if ( pString ) {
-+ sa1100_usb_set_string_descriptor( 4, pString );
-+ pDesc->b.intf.iInterface = 4;
-+ }
-+ sa1100_set_configured_callback( extenex_configured_notify_proc );
-+#endif
-+ }
-+}
-+
-+static void free_string_descriptors( void )
-+{
-+ if ( machine_is_extenex1() ) {
-+ string_desc_t * pString;
-+ int i;
-+ for( i = 1 ; i <= 4 ; i++ ) {
-+ pString = sa1100_usb_get_string_descriptor( i );
-+ if ( pString )
-+ kfree( pString );
-+ }
-+ }
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// ASYNCHRONOUS
-+//////////////////////////////////////////////////////////////////////////////
-+static void kick_start_rx( void )
-+{
-+ if ( usb_ref_count ) {
-+ int total_space = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ if ( total_space >= RX_PACKET_SIZE ) {
-+ sa1100_usb_recv( packet_buffer,
-+ RX_PACKET_SIZE,
-+ rx_done_callback_packet_buffer
-+ );
-+ }
-+ }
-+}
-+/*
-+ * rx_done_callback_packet_buffer()
-+ * We have completed a DMA xfer into the temp packet buffer.
-+ * Move to ring.
-+ *
-+ * flag values:
-+ * on init, -EAGAIN
-+ * on reset, -EINTR
-+ * on RPE, -EIO
-+ * on short packet -EPIPE
-+ */
-+static void
-+rx_done_callback_packet_buffer( int flag, int size )
-+{
-+ charstats.cnt_rx_complete++;
-+
-+ if ( flag == 0 || flag == -EPIPE ) {
-+ size_t n;
-+
-+ charstats.bytes_rx += size;
-+
-+ n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ n = MIN( n, size );
-+ size -= n;
-+
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
-+ rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
-+ memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
-+ rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
-+
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+
-+ last_rx_result = 0;
-+
-+ kick_start_rx();
-+
-+ } else if ( flag != -EAGAIN ) {
-+ charstats.cnt_rx_errors++;
-+ last_rx_result = flag;
-+ wake_up_interruptible( &wq_read );
-+ wake_up_interruptible( &wq_poll );
-+ }
-+ else /* init, start a read */
-+ kick_start_rx();
-+}
-+
-+
-+static void tx_timeout( unsigned long unused )
-+{
-+ printk( "%stx timeout\n", pszMe );
-+ sa1100_usb_send_reset();
-+ charstats.cnt_tx_timeouts++;
-+}
-+
-+
-+// on init, -EAGAIN
-+// on reset, -EINTR
-+// on TPE, -EIO
-+static void tx_done_callback( int flags, int size )
-+{
-+ if ( flags == 0 )
-+ charstats.bytes_tx += size;
-+ else
-+ charstats.cnt_tx_errors++;
-+ last_tx_size = size;
-+ last_tx_result = flags;
-+ sending = 0;
-+ wake_up_interruptible( &wq_write );
-+ wake_up_interruptible( &wq_poll );
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Workers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static int usbc_open( struct inode *pInode, struct file *pFile )
-+{
-+ int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%sopen()\n", pszMe );
-+
-+ /* start usb core */
-+ retval = sa1100_usb_open( "usb-char" );
-+ if ( retval ) return retval;
-+
-+ /* allocate memory */
-+ if ( usb_ref_count == 0 ) {
-+ tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+ if ( tx_buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.buf =
-+ (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
-+
-+ if ( rx_ring.buf == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+
-+ packet_buffer =
-+ (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
-+
-+ if ( packet_buffer == NULL ) {
-+ printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n", pszMe );
-+ goto malloc_fail;
-+ }
-+ rx_ring.in = rx_ring.out = 0;
-+ memset( &charstats, 0, sizeof( charstats ) );
-+ sending = 0;
-+ last_tx_result = 0;
-+ last_tx_size = 0;
-+ }
-+
-+ /* modify default descriptors */
-+ twiddle_descriptors();
-+
-+ retval = sa1100_usb_start();
-+ if ( retval ) {
-+ printk( "%sAGHH! Could not USB core\n", pszMe );
-+ free_txrx_buffers();
-+ return retval;
-+ }
-+ usb_ref_count++; /* must do _before_ kick_start() */
-+ MOD_INC_USE_COUNT;
-+ kick_start_rx();
-+ return 0;
-+
-+ malloc_fail:
-+ free_txrx_buffers();
-+ return -ENOMEM;
-+}
-+
-+/*
-+ * Read endpoint. Note that you can issue a read to an
-+ * unconfigured endpoint. Eventually, the host may come along
-+ * and configure underneath this module and data will appear.
-+ */
-+static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval;
-+ int flags;
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%sread()\n", pszMe );
-+
-+ local_irq_save( flags );
-+ if ( last_rx_result == 0 ) {
-+ local_irq_restore( flags );
-+ } else { /* an error happended and receiver is paused */
-+ local_irq_restore( flags );
-+ last_rx_result = 0;
-+ kick_start_rx();
-+ }
-+
-+ add_wait_queue( &wq_read, &wait );
-+ while( 1 ) {
-+ ssize_t bytes_avail;
-+ ssize_t bytes_to_end;
-+
-+ set_current_state( TASK_INTERRUPTIBLE );
-+
-+ /* snap ring buf state */
-+ local_irq_save( flags );
-+ bytes_avail = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
-+ local_irq_restore( flags );
-+
-+ if ( bytes_avail != 0 ) {
-+ ssize_t bytes_to_move = MIN( stCount, bytes_avail );
-+ retval = 0; // will be bytes transfered
-+ if ( bytes_to_move != 0 ) {
-+ size_t n = MIN( bytes_to_end, bytes_to_move );
-+ if ( copy_to_user( pUserBuffer,
-+ &rx_ring.buf[ rx_ring.out ],
-+ n ) ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ bytes_to_move -= n;
-+ retval += n;
-+ // might go 1 char off end, so wrap
-+ rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
-+ if ( copy_to_user( pUserBuffer + n,
-+ &rx_ring.buf[ rx_ring.out ],
-+ bytes_to_move )
-+ ) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_ring.out += bytes_to_move; // cannot wrap
-+ retval += bytes_to_move;
-+ kick_start_rx();
-+ }
-+ break;
-+ }
-+ else if ( last_rx_result ) {
-+ retval = last_rx_result;
-+ break;
-+ }
-+ else if ( pFile->f_flags & O_NONBLOCK ) { // no data, can't sleep
-+ retval = -EAGAIN;
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) { // no data, can sleep, but signal
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule(); // no data, can sleep
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_read, &wait );
-+
-+ if ( retval < 0 )
-+ printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );
-+ return retval;
-+}
-+
-+/*
-+ * Write endpoint. This routine attempts to break the passed in buffer
-+ * into usb DATA0/1 packet size chunks and send them to the host.
-+ * (The lower-level driver tries to do this too, but easier for us
-+ * to manage things here.)
-+ *
-+ * We are at the mercy of the host here, in that it must send an IN
-+ * token to us to pull this data back, so hopefully some higher level
-+ * protocol is expecting traffic to flow in that direction so the host
-+ * is actually polling us. To guard against hangs, a 5 second timeout
-+ * is used.
-+ *
-+ * This routine takes some care to only report bytes sent that have
-+ * actually made it across the wire. Thus we try to stay in lockstep
-+ * with the completion routine and only have one packet on the xmit
-+ * hardware at a time. Multiple simultaneous writers will get
-+ * "undefined" results.
-+ *
-+ */
-+static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,
-+ size_t stCount, loff_t *pPos )
-+{
-+ ssize_t retval = 0;
-+ ssize_t stSent = 0;
-+
-+ DECLARE_WAITQUEUE( wait, current );
-+
-+ PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, stCount );
-+
-+ down( &xmit_sem ); // only one thread onto the hardware at a time
-+
-+ while( stCount != 0 && retval == 0 ) {
-+ int nThisTime = MIN( TX_PACKET_SIZE, stCount );
-+ copy_from_user( tx_buf, pUserBuffer, nThisTime );
-+ sending = nThisTime;
-+ retval = sa1100_usb_send( tx_buf, nThisTime, tx_done_callback );
-+ if ( retval < 0 ) {
-+ char * p = what_the_f( retval );
-+ printk( "%sCould not queue xmission. rc=%d - %s\n",
-+ pszMe, retval, p );
-+ sending = 0;
-+ break;
-+ }
-+ /* now have something on the diving board */
-+ add_wait_queue( &wq_write, &wait );
-+ tx_timer.expires = jiffies + ( HZ * 5 );
-+ add_timer( &tx_timer );
-+ while( 1 ) {
-+ set_current_state( TASK_INTERRUPTIBLE );
-+ if ( sending == 0 ) { /* it jumped into the pool */
-+ del_timer( &tx_timer );
-+ retval = last_tx_result;
-+ if ( retval == 0 ) {
-+ stSent += last_tx_size;
-+ pUserBuffer += last_tx_size;
-+ stCount -= last_tx_size;
-+ }
-+ else
-+ printk( "%sxmission error rc=%d - %s\n",
-+ pszMe, retval, what_the_f(retval) );
-+ break;
-+ }
-+ else if ( signal_pending( current ) ) {
-+ del_timer( &tx_timer );
-+ printk( "%ssignal\n", pszMe );
-+ retval = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ }
-+ set_current_state( TASK_RUNNING );
-+ remove_wait_queue( &wq_write, &wait );
-+ }
-+
-+ up( &xmit_sem );
-+
-+ if ( 0 == retval )
-+ retval = stSent;
-+ return retval;
-+}
-+
-+static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
-+{
-+ unsigned int retval = 0;
-+
-+ PRINTK( KERN_DEBUG "%poll()\n", pszMe );
-+
-+ poll_wait( pFile, &wq_poll, pWait );
-+
-+ if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
-+ retval |= POLLIN | POLLRDNORM;
-+ if ( sa1100_usb_xmitter_avail() )
-+ retval |= POLLOUT | POLLWRNORM;
-+ return retval;
-+}
-+
-+static int usbc_ioctl( struct inode *pInode, struct file *pFile,
-+ unsigned int nCmd, unsigned long argument )
-+{
-+ int retval = 0;
-+
-+ switch( nCmd ) {
-+
-+ case USBC_IOC_FLUSH_RECEIVER:
-+ sa1100_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ break;
-+
-+ case USBC_IOC_FLUSH_TRANSMITTER:
-+ sa1100_usb_send_reset();
-+ break;
-+
-+ case USBC_IOC_FLUSH_ALL:
-+ sa1100_usb_recv_reset();
-+ rx_ring.in = rx_ring.out = 0;
-+ sa1100_usb_send_reset();
-+ break;
-+
-+ default:
-+ retval = -ENOIOCTLCMD;
-+ break;
-+
-+ }
-+ return retval;
-+}
-+
-+
-+static int usbc_close( struct inode *pInode, struct file * pFile )
-+{
-+ PRINTK( KERN_DEBUG "%sclose()\n", pszMe );
-+ if ( --usb_ref_count == 0 ) {
-+ down( &xmit_sem );
-+ sa1100_usb_stop();
-+ free_txrx_buffers();
-+ free_string_descriptors();
-+ del_timer( &tx_timer );
-+ sa1100_usb_close();
-+ up( &xmit_sem );
-+ }
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+#include "../../../drivers/char/ex_gpio.h"
-+void extenex_configured_notify_proc( void )
-+{
-+ if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
-+ printk( "%sWanted to BEEP but ex_gpio not open\n", pszMe );
-+}
-+#endif
-+//////////////////////////////////////////////////////////////////////////////
-+// Initialization
-+//////////////////////////////////////////////////////////////////////////////
-+
-+static struct file_operations usbc_fops = {
-+ owner: THIS_MODULE,
-+ open: usbc_open,
-+ read: usbc_read,
-+ write: usbc_write,
-+ poll: usbc_poll,
-+ ioctl: usbc_ioctl,
-+ release: usbc_close,
-+};
-+
-+static struct miscdevice usbc_misc_device = {
-+ USBC_MINOR, "usb_char", &usbc_fops
-+};
-+
-+/*
-+ * usbc_init()
-+ */
-+
-+int __init usbc_init( void )
-+{
-+ int rc;
-+
-+#if !defined( CONFIG_ARCH_SA1100 )
-+ return -ENODEV;
-+#endif
-+
-+ if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
-+ printk( KERN_WARNING "%sCould not register device 10, "
-+ "%d. (%d)\n", pszMe, USBC_MINOR, rc );
-+ return -EBUSY;
-+ }
-+
-+ // initialize wait queues
-+ init_waitqueue_head( &wq_read );
-+ init_waitqueue_head( &wq_write );
-+ init_waitqueue_head( &wq_poll );
-+
-+ // initialize tx timeout timer
-+ init_timer( &tx_timer );
-+ tx_timer.function = tx_timeout;
-+
-+ printk( KERN_INFO "USB Function Character Driver Interface"
-+ " - %s, (C) 2001, Extenex Corp.\n", VERSION
-+ );
-+
-+ return rc;
-+}
-+
-+void __exit usbc_exit( void )
-+{
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(usbc_init);
-+module_exit(usbc_exit);
-+
-+
-+
-+// end: usb-char.c
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb-char.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright (C) 2001 Extenex Corporation
-+ *
-+ * usb-char.h
-+ *
-+ * Character device emulation client for SA-1100 client usb core.
-+ *
-+ *
-+ *
-+ */
-+#ifndef _USB_CHAR_H
-+#define _USB_CHAR_H
-+
-+#define USBC_MAJOR 10 /* miscellaneous character device */
-+#define USBC_MINOR 240 /* in the "reserved for local use" range */
-+
-+#define USBC_MAGIC 0x8E
-+
-+/* zap everything in receive ring buffer */
-+#define USBC_IOC_FLUSH_RECEIVER _IO( USBC_MAGIC, 0x01 )
-+
-+/* reset transmitter */
-+#define USBC_IOC_FLUSH_TRANSMITTER _IO( USBC_MAGIC, 0x02 )
-+
-+/* do both of above */
-+#define USBC_IOC_FLUSH_ALL _IO( USBC_MAGIC, 0x03 )
-+
-+
-+
-+
-+
-+
-+#endif /* _USB_CHAR_H */
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb-eth.c
-@@ -0,0 +1,447 @@
-+ /*
-+ * Ethernet driver for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original initial ethernet test driver
-+ * Copyright (c) Compaq Computer Corporation, 1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * 19/02/2001 - Now we are compatible with generic usbnet driver. green@iXcelerator.com
-+ * 09/03/2001 - Dropped 'framing' scheme, as it seems to cause a lot of problems with little benefit.
-+ * Now, since we do not know what size of packet we are receiving
-+ * last usb packet in sequence will always be less than max packet
-+ * receive endpoint can accept.
-+ * Now the only way to check correct start of frame is to compare
-+ * MAC address. Also now we are stalling on each receive error.
-+ *
-+ * 15/03/2001 - Using buffer to get data from UDC. DMA needs to have 8 byte
-+ * aligned buffer, but this breaks IP code (unaligned access).
-+ *
-+ * 01/04/2001 - stall endpoint operations appeared to be very unstable, so
-+ * they are disabled now.
-+ *
-+ * 03/06/2001 - Readded "zerocopy" receive path (tunable).
-+ *
-+ */
-+
-+// Define DMA_NO_COPY if you want data to arrive directly into the
-+// receive network buffers, instead of arriving into bounce buffer
-+// and then get copied to network buffer.
-+// This does not work correctly right now.
-+#undef DMA_NO_COPY
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/timer.h>
-+
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/random.h>
-+
-+#include "sa1100_usb.h"
-+
-+
-+#define ETHERNET_VENDOR_ID 0x49f
-+#define ETHERNET_PRODUCT_ID 0x505A
-+#define MAX_PACKET 32768
-+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-+
-+// Should be global, so that insmod can change these
-+int usb_rsize=64;
-+int usb_wsize=64;
-+
-+static struct usbe_info_t {
-+ struct net_device *dev;
-+ u16 packet_id;
-+ struct net_device_stats stats;
-+} usbe_info;
-+
-+static char usb_eth_name[16] = "usbf";
-+static struct net_device usb_eth_device;
-+static struct sk_buff *cur_tx_skb, *next_tx_skb;
-+static struct sk_buff *cur_rx_skb, *next_rx_skb;
-+static volatile int terminating;
-+#ifndef DMA_NO_COPY
-+static char *dmabuf; // we need that, as dma expect it's buffers to be aligned on 8 bytes boundary
-+#endif
-+
-+static int usb_change_mtu (struct net_device *net, int new_mtu)
-+{
-+ if (new_mtu <= sizeof (struct ethhdr) || new_mtu > MAX_PACKET)
-+ return -EINVAL;
-+ // no second zero-length packet read wanted after mtu-sized packets
-+ if (((new_mtu + sizeof (struct ethhdr)) % usb_rsize) == 0)
-+ return -EDOM;
-+
-+ net->mtu = new_mtu;
-+ return 0;
-+}
-+
-+static struct sk_buff *
-+usb_new_recv_skb(void)
-+{
-+ struct sk_buff *skb = alloc_skb( 2 + sizeof (struct ethhdr) + usb_eth_device.mtu,GFP_ATOMIC);
-+
-+ if (skb) {
-+ skb_reserve(skb, 2);
-+ }
-+ return skb;
-+}
-+
-+static u8 bcast_hwaddr[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff};
-+static void
-+usb_recv_callback(int flag, int size)
-+{
-+ struct sk_buff *skb;
-+
-+ if (terminating)
-+ return;
-+
-+ skb = cur_rx_skb;
-+
-+ /* flag validation */
-+ if (flag == 0) {
-+ if ( skb_tailroom (skb) < size ) { // hey! we are overloaded!!!
-+ usbe_info.stats.rx_over_errors++;
-+ goto error;
-+ }
-+#ifndef DMA_NO_COPY
-+ memcpy(skb->tail,dmabuf,size);
-+#endif
-+ skb_put(skb, size);
-+ } else {
-+ if (flag == -EIO) {
-+ usbe_info.stats.rx_errors++;
-+ }
-+ goto error;
-+ }
-+
-+ /* validate packet length */
-+ if (size == usb_rsize ) {
-+ /* packet not complete yet */
-+ skb = NULL;
-+ }
-+
-+ /*
-+ * At this point skb is non null if we have a complete packet.
-+ * If so take a fresh skb right away and restart USB receive without
-+ * further delays, then process the packet. Otherwise resume USB
-+ * receive on the current skb and exit.
-+ */
-+
-+ if (skb)
-+ cur_rx_skb = next_rx_skb;
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize,
-+ usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ if (!skb)
-+ return;
-+
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!next_rx_skb) {
-+ /*
-+ * We can't aford loosing buffer space...
-+ * So we drop the current packet and recycle its skb.
-+ */
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ usbe_info.stats.rx_dropped++;
-+ skb_trim(skb, 0);
-+ next_rx_skb = skb;
-+ return;
-+ }
-+ if ( skb->len >= sizeof(struct ethhdr)) {
-+ if (memcmp(skb->data,usb_eth_device.dev_addr,ETH_ALEN) && memcmp(skb->data,bcast_hwaddr,ETH_ALEN) ) {
-+ // This frame is not for us. nor it is broadcast
-+ usbe_info.stats.rx_frame_errors++;
-+ kfree_skb(skb);
-+ goto error;
-+ }
-+ }
-+
-+ if (skb->len) {
-+ int status;
-+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
-+
-+ skb->dev = &usb_eth_device;
-+ skb->protocol = eth_type_trans (skb, &usb_eth_device);
-+ usbe_info.stats.rx_packets++;
-+ usbe_info.stats.rx_bytes += skb->len;
-+ skb->ip_summed = CHECKSUM_NONE;
-+ status = netif_rx (skb);
-+ if (status != NET_RX_SUCCESS)
-+ printk("netif_rx failed with code %d\n",status);
-+ } else {
-+error:
-+ /*
-+ * Error due to HW addr mismatch, or IO error.
-+ * Recycle the current skb and reset USB reception.
-+ */
-+ skb_trim(cur_rx_skb, 0);
-+// if ( flag == -EINTR || flag == -EAGAIN ) // only if we are coming out of stall
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)), usb_recv_callback);
-+#endif
-+ }
-+}
-+
-+
-+static void
-+usb_send_callback(int flag, int size)
-+{
-+ struct net_device *dev = usbe_info.dev;
-+ struct net_device_stats *stats;
-+ struct sk_buff *skb=cur_tx_skb;
-+ int ret;
-+
-+ if (terminating)
-+ return;
-+
-+ stats = &usbe_info.stats;
-+ switch (flag) {
-+ case 0:
-+ stats->tx_packets++;
-+ stats->tx_bytes += size;
-+ break;
-+ case -EIO:
-+ stats->tx_errors++;
-+ break;
-+ default:
-+ stats->tx_dropped++;
-+ break;
-+ }
-+
-+ cur_tx_skb = next_tx_skb;
-+ next_tx_skb = NULL;
-+ dev_kfree_skb_irq(skb);
-+ if (!cur_tx_skb)
-+ return;
-+
-+ dev->trans_start = jiffies;
-+ ret = sa1100_usb_send(cur_tx_skb->data, cur_tx_skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb_irq(cur_tx_skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ netif_wake_queue(dev);
-+}
-+
-+static int
-+usb_eth_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ int ret;
-+ unsigned long flags;
-+
-+ if (next_tx_skb) {
-+ printk("%s: called with next_tx_skb != NULL\n", __FUNCTION__);
-+ return 1;
-+ }
-+
-+ if (skb_shared (skb)) {
-+ struct sk_buff *skb2 = skb_unshare(skb, GFP_ATOMIC);
-+ if (!skb2) {
-+ usbe_info.stats.tx_dropped++;
-+ dev_kfree_skb(skb);
-+ return 1;
-+ }
-+ skb = skb2;
-+ }
-+
-+ if ((skb->len % usb_wsize) == 0) {
-+ skb->len++; // other side will ignore this one, anyway.
-+ }
-+
-+ local_irq_save(flags);
-+ if (cur_tx_skb) {
-+ next_tx_skb = skb;
-+ netif_stop_queue(dev);
-+ } else {
-+ cur_tx_skb = skb;
-+ dev->trans_start = jiffies;
-+ ret = sa1100_usb_send(skb->data, skb->len, usb_send_callback);
-+ if (ret) {
-+ /* If the USB core can't accept the packet, we drop it. */
-+ dev_kfree_skb(skb);
-+ cur_tx_skb = NULL;
-+ usbe_info.stats.tx_carrier_errors++;
-+ }
-+ }
-+ local_irq_restore(flags);
-+ return 0;
-+}
-+
-+static void
-+usb_xmit_timeout(struct net_device *dev )
-+{
-+ sa1100_usb_send_reset();
-+ dev->trans_start = jiffies;
-+ netif_wake_queue(dev);
-+}
-+
-+
-+static int
-+usb_eth_open(struct net_device *dev)
-+{
-+ terminating = 0;
-+ cur_tx_skb = next_tx_skb = NULL;
-+ cur_rx_skb = usb_new_recv_skb();
-+ next_rx_skb = usb_new_recv_skb();
-+ if (!cur_rx_skb || !next_rx_skb) {
-+ printk("%s: can't allocate new skb\n", __FUNCTION__);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+ return -ENOMEM;;
-+ }
-+
-+ MOD_INC_USE_COUNT;
-+#ifndef DMA_NO_COPY
-+ sa1100_usb_recv(dmabuf, usb_rsize, usb_recv_callback);
-+#else
-+ sa1100_usb_recv(cur_rx_skb->tail, MIN(usb_rsize, skb_tailroom (cur_rx_skb)),
-+ usb_recv_callback);
-+#endif
-+ return 0;
-+}
-+
-+static int
-+usb_eth_release(struct net_device *dev)
-+{
-+ terminating = 1;
-+ sa1100_usb_send_reset();
-+ sa1100_usb_recv_reset();
-+ if (cur_tx_skb)
-+ kfree_skb(cur_tx_skb);
-+ if (next_tx_skb)
-+ kfree_skb(next_tx_skb);
-+ if (cur_rx_skb)
-+ kfree_skb(cur_rx_skb);
-+ if (next_rx_skb)
-+ kfree_skb(next_rx_skb);
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static struct net_device_stats *
-+usb_eth_stats(struct net_device *dev)
-+{
-+ struct usbe_info_t *priv = (struct usbe_info_t*) dev->priv;
-+ struct net_device_stats *stats=NULL;
-+
-+ if (priv)
-+ stats = &priv->stats;
-+ return stats;
-+}
-+
-+static int
-+usb_eth_probe(struct net_device *dev)
-+{
-+ u8 node_id [ETH_ALEN];
-+
-+ get_random_bytes (node_id, sizeof node_id);
-+ node_id [0] &= 0xfe; // clear multicast bit
-+
-+ /*
-+ * Assign the hardware address of the board:
-+ * generate it randomly, as there can be many such
-+ * devices on the bus.
-+ */
-+ memcpy (dev->dev_addr, node_id, sizeof node_id);
-+
-+ dev->open = usb_eth_open;
-+ dev->change_mtu = usb_change_mtu;
-+ dev->stop = usb_eth_release;
-+ dev->hard_start_xmit = usb_eth_xmit;
-+ dev->get_stats = usb_eth_stats;
-+ dev->watchdog_timeo = 1*HZ;
-+ dev->tx_timeout = usb_xmit_timeout;
-+ dev->priv = &usbe_info;
-+
-+ usbe_info.dev = dev;
-+
-+ /* clear the statistics */
-+ memset(&usbe_info.stats, 0, sizeof(struct net_device_stats));
-+
-+ ether_setup(dev);
-+ dev->flags &= ~IFF_MULTICAST;
-+ dev->flags &= ~IFF_BROADCAST;
-+ //dev->flags |= IFF_NOARP;
-+
-+ return 0;
-+}
-+
-+#ifdef MODULE
-+MODULE_PARM(usb_rsize, "1i");
-+MODULE_PARM_DESC(usb_rsize, "number of bytes in packets from host to sa1100");
-+MODULE_PARM(usb_wsize, "1i");
-+MODULE_PARM_DESC(usb_wsize, "number of bytes in packets from sa1100 to host");
-+#endif
-+
-+static int __init
-+usb_eth_init(void)
-+{
-+ int rc;
-+
-+#ifndef DMA_NO_COPY
-+ dmabuf = kmalloc( usb_rsize, GFP_KERNEL | GFP_DMA );
-+ if (!dmabuf)
-+ return -ENOMEM;
-+#endif
-+ strncpy(usb_eth_device.name, usb_eth_name, IFNAMSIZ);
-+ usb_eth_device.init = usb_eth_probe;
-+ if (register_netdev(&usb_eth_device) != 0)
-+ return -EIO;
-+
-+ rc = sa1100_usb_open( "usb-eth" );
-+ if ( rc == 0 ) {
-+ string_desc_t * pstr;
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+
-+ pd->b.ep1.wMaxPacketSize = make_word( usb_rsize );
-+ pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
-+ pd->dev.idVendor = ETHERNET_VENDOR_ID;
-+ pd->dev.idProduct = ETHERNET_PRODUCT_ID;
-+ pstr = sa1100_usb_kmalloc_string_descriptor( "SA1100 USB NIC" );
-+ if ( pstr ) {
-+ sa1100_usb_set_string_descriptor( 1, pstr );
-+ pd->dev.iProduct = 1;
-+ }
-+ rc = sa1100_usb_start();
-+ }
-+ return rc;
-+}
-+
-+module_init(usb_eth_init);
-+
-+static void __exit
-+usb_eth_cleanup(void)
-+{
-+ string_desc_t * pstr;
-+ sa1100_usb_stop();
-+ sa1100_usb_close();
-+ if ( (pstr = sa1100_usb_get_string_descriptor(1)) != NULL )
-+ kfree( pstr );
-+#ifndef DMA_NO_COPY
-+ kfree(dmabuf);
-+#endif
-+ unregister_netdev(&usb_eth_device);
-+}
-+
-+module_exit(usb_eth_cleanup);
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.c
-@@ -0,0 +1,774 @@
-+ /*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation, 2001
-+ *
-+ * usb_ctl.c
-+ *
-+ * SA1100 USB controller core driver.
-+ *
-+ * This file provides interrupt routing and overall coordination
-+ * of the three endpoints in usb_ep0, usb_receive (1), and usb_send (2).
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/tqueue.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Prototypes
-+//////////////////////////////////////////////////////////////////////////////
-+
-+int usbctl_next_state_on_event( int event );
-+static void udc_int_hndlr(int, void *, struct pt_regs *);
-+static void initialize_descriptors( void );
-+static void soft_connect_hook( int enable );
-+static void udc_disable(void);
-+static void udc_enable(void);
-+
-+#if CONFIG_PROC_FS
-+#define PROC_NODE_NAME "sausb"
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+#endif
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Globals
-+//////////////////////////////////////////////////////////////////////////////
-+static const char pszMe[] = "usbctl: ";
-+struct usb_info_t usbd_info; /* global to ep0, usb_recv, usb_send */
-+
-+/* device descriptors */
-+static desc_t desc;
-+
-+#define MAX_STRING_DESC 8
-+static string_desc_t * string_desc_array[ MAX_STRING_DESC ];
-+static string_desc_t sd_zero; /* special sd_zero holds language codes */
-+
-+// called when configured
-+static usb_notify_t configured_callback = NULL;
-+
-+enum { kStateZombie = 0, kStateZombieSuspend = 1,
-+ kStateDefault = 2, kStateDefaultSuspend = 3,
-+ kStateAddr = 4, kStateAddrSuspend = 5,
-+ kStateConfig = 6, kStateConfigSuspend = 7
-+};
-+
-+static int device_state_machine[8][6] = {
-+// suspend reset resume adddr config deconfig
-+/* zombie */ { kStateZombieSuspend, kStateDefault, kError, kError, kError, kError },
-+/* zom sus */ { kError, kStateDefault, kStateZombie, kError, kError, kError },
-+/* default */ { kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError },
-+/* def sus */ { kError, kStateDefault, kStateDefault, kError, kError, kError },
-+/* addr */ { kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError },
-+/* addr sus */{ kError, kStateDefault, kStateAddr, kError, kError, kError },
-+/* config */ { kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr },
-+/* cfg sus */ { kError, kStateDefault, kStateConfig, kError, kError, kError }
-+};
-+
-+/* "device state" is the usb device framework state, as opposed to the
-+ "state machine state" which is whatever the driver needs and is much
-+ more fine grained
-+*/
-+static int sm_state_to_device_state[8] =
-+// zombie zom suspend default default sus
-+{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,
-+// addr addr sus config config sus
-+ USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED
-+};
-+
-+static char * state_names[8] =
-+{ "zombie", "zombie suspended", "default", "default suspended",
-+ "address", "address suspended", "configured", "config suspended"
-+};
-+
-+static char * event_names[6] =
-+{ "suspend", "reset", "resume",
-+ "address assigned", "configure", "de-configure"
-+};
-+
-+static char * device_state_names[] =
-+{ "not attached", "attached", "powered", "default",
-+ "address", "configured", "suspended" };
-+
-+static int sm_state = kStateZombie;
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Async
-+//////////////////////////////////////////////////////////////////////////////
-+static void core_kicker(void);
-+
-+static inline void enable_resume_mask_suspend( void );
-+static inline void enable_suspend_mask_resume(void);
-+
-+static void
-+udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ __u32 status = Ser0UDCSR;
-+
-+ /* ReSeT Interrupt Request - UDC has been reset */
-+ if ( status & UDCSR_RSTIR )
-+ {
-+ if ( usbctl_next_state_on_event( kEvReset ) != kError )
-+ {
-+ /* starting 20ms or so reset sequence now... */
-+ printk("%sResetting\n", pszMe);
-+ ep0_reset(); // just set state to idle
-+ ep1_reset(); // flush dma, clear false stall
-+ ep2_reset(); // flush dma, clear false stall
-+ }
-+ // mask reset ints, they flood during sequence, enable
-+ // suspend and resume
-+ Ser0UDCCR |= UDCCR_REM; // mask reset
-+ Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume
-+ UDC_flip( Ser0UDCSR, status ); // clear all pending sources
-+ return; // <-- no reason to continue if resetting
-+ }
-+ // else we have done something other than reset, so be sure reset enabled
-+ UDC_clear( Ser0UDCCR, UDCCR_REM );
-+
-+ /* RESume Interrupt Request */
-+ if ( status & UDCSR_RESIR )
-+ {
-+ usbctl_next_state_on_event( kEvResume );
-+ core_kicker();
-+ enable_suspend_mask_resume();
-+ }
-+
-+ /* SUSpend Interrupt Request */
-+ if ( status & UDCSR_SUSIR )
-+ {
-+ usbctl_next_state_on_event( kEvSuspend );
-+ enable_resume_mask_suspend();
-+ }
-+
-+ UDC_flip(Ser0UDCSR, status); // clear all pending sources
-+
-+ if (status & UDCSR_EIR)
-+ ep0_int_hndlr();
-+
-+ if (status & UDCSR_RIR)
-+ ep1_int_hndlr(status);
-+
-+ if (status & UDCSR_TIR)
-+ ep2_int_hndlr(status);
-+}
-+
-+static inline void enable_resume_mask_suspend( void )
-+{
-+ int i = 0;
-+
-+ while( 1 ) {
-+ Ser0UDCCR |= UDCCR_SUSIM; // mask future suspend events
-+ udelay( i );
-+ if ( (Ser0UDCCR & UDCCR_SUSIM) || (Ser0UDCSR & UDCSR_RSTIR) )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_resume(): Could not set SUSIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+
-+ i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR &= ~UDCCR_RESIM;
-+ udelay( i );
-+ if ( ( Ser0UDCCR & UDCCR_RESIM ) == 0
-+ ||
-+ (Ser0UDCSR & UDCSR_RSTIR)
-+ )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_resume(): Could not clear RESIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+}
-+
-+static inline void enable_suspend_mask_resume(void)
-+{
-+ int i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR |= UDCCR_RESIM; // mask future resume events
-+ udelay( i );
-+ if ( Ser0UDCCR & UDCCR_RESIM || (Ser0UDCSR & UDCSR_RSTIR) )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_suspend(): Could not set RESIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+ i = 0;
-+ while( 1 ) {
-+ Ser0UDCCR &= ~UDCCR_SUSIM;
-+ udelay( i );
-+ if ( ( Ser0UDCCR & UDCCR_SUSIM ) == 0
-+ ||
-+ (Ser0UDCSR & UDCSR_RSTIR)
-+ )
-+ break;
-+ if ( ++i == 50 ) {
-+ printk( "%senable_suspend(): Could not clear SUSIM %8.8X\n",
-+ pszMe, Ser0UDCCR );
-+ break;
-+ }
-+ }
-+}
-+
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Public Interface
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* Open SA usb core on behalf of a client, but don't start running */
-+
-+int
-+sa1100_usb_open( const char * client )
-+{
-+ if ( usbd_info.client_name != NULL )
-+ return -EBUSY;
-+
-+ usbd_info.client_name = (char*) client;
-+ memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));
-+ memset(string_desc_array, 0, sizeof(string_desc_array));
-+
-+ /* hack to start in zombie suspended state */
-+ sm_state = kStateZombieSuspend;
-+ usbd_info.state = USB_STATE_SUSPENDED;
-+
-+ /* create descriptors for enumeration */
-+ initialize_descriptors();
-+
-+ printk( "%sOpened for %s\n", pszMe, client );
-+ return 0;
-+}
-+
-+/* Start running. Must have called usb_open (above) first */
-+int
-+sa1100_usb_start( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+
-+ /* start UDC internal machinery running */
-+ udc_enable();
-+ udelay( 100 );
-+
-+ /* clear stall - receiver seems to start stalled? 19Jan01ww */
-+ /* also clear other stuff just to be thurough 22Feb01ww */
-+ UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
-+ UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );
-+
-+ /* mask everything */
-+ Ser0UDCCR = 0xFC;
-+
-+ /* flush DMA and fire through some -EAGAINs */
-+ ep1_init( usbd_info.dmach_rx );
-+ ep2_init( usbd_info.dmach_tx );
-+
-+ /* give endpoint notification we are starting */
-+ ep1_state_change_notify( USB_STATE_SUSPENDED );
-+ ep2_state_change_notify( USB_STATE_SUSPENDED );
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* clear all top-level sources */
-+ Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR |
-+ UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
-+
-+ /* EXERIMENT - a short line in the spec says toggling this
-+ ..bit diddles the internal state machine in the udc to
-+ ..expect a suspend */
-+ Ser0UDCCR |= UDCCR_RESIM;
-+ /* END EXPERIMENT 10Feb01ww */
-+
-+ /* enable any platform specific hardware */
-+ soft_connect_hook( 1 );
-+
-+ /* enable interrupts. If you are unplugged you will
-+ immediately get a suspend interrupt. If you are plugged
-+ and have a soft connect-circuit, you will get a reset
-+ If you are plugged without a soft-connect, I think you
-+ also get suspend. In short, start with suspend masked
-+ and everything else enabled */
-+ UDC_write( Ser0UDCCR, UDCCR_SUSIM );
-+
-+ printk( "%sStarted for %s\n", pszMe, usbd_info.client_name );
-+ return 0;
-+}
-+
-+/* Stop USB core from running */
-+int
-+sa1100_usb_stop( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ /* mask everything */
-+ Ser0UDCCR = 0xFC;
-+ ep1_reset();
-+ ep2_reset();
-+ udc_disable();
-+ printk( "%sStopped\n", pszMe );
-+ return 0;
-+}
-+
-+/* Tell SA core client is through using it */
-+int
-+sa1100_usb_close( void )
-+{
-+ if ( usbd_info.client_name == NULL ) {
-+ printk( "%s%s - no client registered\n",
-+ pszMe, __FUNCTION__ );
-+ return -EPERM;
-+ }
-+ usbd_info.client_name = NULL;
-+ printk( "%sClosed\n", pszMe );
-+ return 0;
-+}
-+
-+/* set a proc to be called when device is configured */
-+usb_notify_t sa1100_set_configured_callback( usb_notify_t func )
-+{
-+ usb_notify_t retval = configured_callback;
-+ configured_callback = func;
-+ return retval;
-+}
-+
-+/*====================================================
-+ * Descriptor Manipulation.
-+ * Use these between open() and start() above to setup
-+ * the descriptors for your device.
-+ *
-+ */
-+
-+/* get pointer to static default descriptor */
-+desc_t *
-+sa1100_usb_get_descriptor_ptr( void ) { return &desc; }
-+
-+/* optional: set a string descriptor */
-+int
-+sa1100_usb_set_string_descriptor( int i, string_desc_t * p )
-+{
-+ int retval;
-+ if ( i < MAX_STRING_DESC ) {
-+ string_desc_array[i] = p;
-+ retval = 0;
-+ } else {
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+/* optional: get a previously set string descriptor */
-+string_desc_t *
-+sa1100_usb_get_string_descriptor( int i )
-+{
-+ return ( i < MAX_STRING_DESC )
-+ ? string_desc_array[i]
-+ : NULL;
-+}
-+
-+
-+/* optional: kmalloc and unicode up a string descriptor */
-+string_desc_t *
-+sa1100_usb_kmalloc_string_descriptor( const char * p )
-+{
-+ string_desc_t * pResult = NULL;
-+
-+ if ( p ) {
-+ int len = strlen( p );
-+ int uni_len = len * sizeof( __u16 );
-+ pResult = (string_desc_t*) kmalloc( uni_len + 2, GFP_KERNEL ); /* ugh! */
-+ if ( pResult != NULL ) {
-+ int i;
-+ pResult->bLength = uni_len + 2;
-+ pResult->bDescriptorType = USB_DESC_STRING;
-+ for( i = 0; i < len ; i++ ) {
-+ pResult->bString[i] = make_word( (__u16) p[i] );
-+ }
-+ }
-+ }
-+ return pResult;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Exports to rest of driver
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* called by the int handler here and the two endpoint files when interesting
-+ .."events" happen */
-+
-+int
-+usbctl_next_state_on_event( int event )
-+{
-+ int next_state = device_state_machine[ sm_state ][ event ];
-+ if ( next_state != kError )
-+ {
-+ int next_device_state = sm_state_to_device_state[ next_state ];
-+ printk( "%s%s --> [%s] --> %s. Device in %s state.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ],
-+ state_names[ next_state ], device_state_names[ next_device_state ] );
-+
-+ sm_state = next_state;
-+ if ( usbd_info.state != next_device_state )
-+ {
-+ if ( configured_callback != NULL
-+ &&
-+ next_device_state == USB_STATE_CONFIGURED
-+ &&
-+ usbd_info.state != USB_STATE_SUSPENDED
-+ ) {
-+ configured_callback();
-+ }
-+ usbd_info.state = next_device_state;
-+ ep1_state_change_notify( next_device_state );
-+ ep2_state_change_notify( next_device_state );
-+ }
-+ }
-+#if 0
-+ else
-+ printk( "%s%s --> [%s] --> ??? is an error.\n",
-+ pszMe, state_names[ sm_state ], event_names[ event ] );
-+#endif
-+ return next_state;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Private Helpers
-+//////////////////////////////////////////////////////////////////////////////
-+
-+/* setup default descriptors */
-+
-+static void
-+initialize_descriptors(void)
-+{
-+ desc.dev.bLength = sizeof( device_desc_t );
-+ desc.dev.bDescriptorType = USB_DESC_DEVICE;
-+ desc.dev.bcdUSB = 0x100; /* 1.0 */
-+ desc.dev.bDeviceClass = 0xFF; /* vendor specific */
-+ desc.dev.bDeviceSubClass = 0;
-+ desc.dev.bDeviceProtocol = 0;
-+ desc.dev.bMaxPacketSize0 = 8; /* ep0 max fifo size */
-+ desc.dev.idVendor = 0; /* vendor ID undefined */
-+ desc.dev.idProduct = 0; /* product */
-+ desc.dev.bcdDevice = 0; /* vendor assigned device release num */
-+ desc.dev.iManufacturer = 0; /* index of manufacturer string */
-+ desc.dev.iProduct = 0; /* index of product description string */
-+ desc.dev.iSerialNumber = 0; /* index of string holding product s/n */
-+ desc.dev.bNumConfigurations = 1;
-+
-+ desc.b.cfg.bLength = sizeof( config_desc_t );
-+ desc.b.cfg.bDescriptorType = USB_DESC_CONFIG;
-+ desc.b.cfg.wTotalLength = make_word_c( sizeof(struct cdb) );
-+ desc.b.cfg.bNumInterfaces = 1;
-+ desc.b.cfg.bConfigurationValue = 1;
-+ desc.b.cfg.iConfiguration = 0;
-+ desc.b.cfg.bmAttributes = USB_CONFIG_BUSPOWERED;
-+ desc.b.cfg.MaxPower = USB_POWER( 500 );
-+
-+ desc.b.intf.bLength = sizeof( intf_desc_t );
-+ desc.b.intf.bDescriptorType = USB_DESC_INTERFACE;
-+ desc.b.intf.bInterfaceNumber = 0; /* unique intf index*/
-+ desc.b.intf.bAlternateSetting = 0;
-+ desc.b.intf.bNumEndpoints = 2;
-+ desc.b.intf.bInterfaceClass = 0xFF; /* vendor specific */
-+ desc.b.intf.bInterfaceSubClass = 0;
-+ desc.b.intf.bInterfaceProtocol = 0;
-+ desc.b.intf.iInterface = 0;
-+
-+ desc.b.ep1.bLength = sizeof( ep_desc_t );
-+ desc.b.ep1.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep1.bEndpointAddress = USB_EP_ADDRESS( 1, USB_OUT );
-+ desc.b.ep1.bmAttributes = USB_EP_BULK;
-+ desc.b.ep1.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep1.bInterval = 0;
-+
-+ desc.b.ep2.bLength = sizeof( ep_desc_t );
-+ desc.b.ep2.bDescriptorType = USB_DESC_ENDPOINT;
-+ desc.b.ep2.bEndpointAddress = USB_EP_ADDRESS( 2, USB_IN );
-+ desc.b.ep2.bmAttributes = USB_EP_BULK;
-+ desc.b.ep2.wMaxPacketSize = make_word_c( 64 );
-+ desc.b.ep2.bInterval = 0;
-+
-+ /* set language */
-+ /* See: http://www.usb.org/developers/data/USB_LANGIDs.pdf */
-+ sd_zero.bDescriptorType = USB_DESC_STRING;
-+ sd_zero.bLength = sizeof( string_desc_t );
-+ sd_zero.bString[0] = make_word_c( 0x409 ); /* American English */
-+ sa1100_usb_set_string_descriptor( 0, &sd_zero );
-+}
-+
-+/* soft_connect_hook()
-+ * Some devices have platform-specific circuitry to make USB
-+ * not seem to be plugged in, even when it is. This allows
-+ * software to control when a device 'appears' on the USB bus
-+ * (after Linux has booted and this driver has loaded, for
-+ * example). If you have such a circuit, control it here.
-+ */
-+static void
-+soft_connect_hook( int enable )
-+{
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ if (machine_is_extenex1() ) {
-+ if ( enable ) {
-+ PPDR |= PPC_USB_SOFT_CON;
-+ PPSR |= PPC_USB_SOFT_CON;
-+ } else {
-+ PPSR &= ~PPC_USB_SOFT_CON;
-+ PPDR &= ~PPC_USB_SOFT_CON;
-+ }
-+ }
-+#endif
-+}
-+
-+/* disable the UDC at the source */
-+static void
-+udc_disable(void)
-+{
-+ soft_connect_hook( 0 );
-+ UDC_set( Ser0UDCCR, UDCCR_UDD );
-+}
-+
-+
-+/* enable the udc at the source */
-+static void
-+udc_enable(void)
-+{
-+ UDC_clear(Ser0UDCCR, UDCCR_UDD);
-+}
-+
-+// HACK DEBUG 3Mar01ww
-+// Well, maybe not, it really seems to help! 08Mar01ww
-+static void
-+core_kicker( void )
-+{
-+ __u32 car = Ser0UDCAR;
-+ __u32 imp = Ser0UDCIMP;
-+ __u32 omp = Ser0UDCOMP;
-+
-+ UDC_set( Ser0UDCCR, UDCCR_UDD );
-+ udelay( 300 );
-+ UDC_clear(Ser0UDCCR, UDCCR_UDD);
-+
-+ Ser0UDCAR = car;
-+ Ser0UDCIMP = imp;
-+ Ser0UDCOMP = omp;
-+}
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Proc Filesystem Support
-+//////////////////////////////////////////////////////////////////////////////
-+
-+#if CONFIG_PROC_FS
-+
-+#define SAY( fmt, args... ) p += sprintf(p, fmt, ## args )
-+#define SAYV( num ) p += sprintf(p, num_fmt, "Value", num )
-+#define SAYC( label, yn ) p += sprintf(p, yn_fmt, label, yn )
-+#define SAYS( label, v ) p += sprintf(p, cnt_fmt, label, v )
-+
-+static int usbctl_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ const char * num_fmt = "%25.25s: %8.8lX\n";
-+ const char * cnt_fmt = "%25.25s: %lu\n";
-+ const char * yn_fmt = "%25.25s: %s\n";
-+ const char * yes = "YES";
-+ const char * no = "NO";
-+ unsigned long v;
-+ char * p = page;
-+ int len;
-+
-+ SAY( "SA1100 USB Controller Core\n" );
-+ SAY( "USB state: %s (%s) %d\n",
-+ device_state_names[ sm_state_to_device_state[ sm_state ] ],
-+ state_names[ sm_state ],
-+ sm_state );
-+
-+ SAYS( "ep0 bytes read", usbd_info.stats.ep0_bytes_read );
-+ SAYS( "ep0 bytes written", usbd_info.stats.ep0_bytes_written );
-+ SAYS( "ep0 FIFO read failures", usbd_info.stats.ep0_fifo_write_failures );
-+ SAYS( "ep0 FIFO write failures", usbd_info.stats.ep0_fifo_write_failures );
-+
-+ SAY( "\n" );
-+
-+ v = Ser0UDCAR;
-+ SAY( "%25.25s: 0x%8.8lX - %ld\n", "Address Register", v, v );
-+ v = Ser0UDCIMP;
-+ SAY( "%25.25s: %ld (%8.8lX)\n", "IN max packet size", v+1, v );
-+ v = Ser0UDCOMP;
-+ SAY( "%25.25s: %ld (%8.8lX)\n", "OUT max packet size", v+1, v );
-+
-+ v = Ser0UDCCR;
-+ SAY( "\nUDC Mask Register\n" );
-+ SAYV( v );
-+ SAYC( "UDC Active", ( v & UDCCR_UDA ) ? yes : no );
-+ SAYC( "Suspend interrupts masked", ( v & UDCCR_SUSIM ) ? yes : no );
-+ SAYC( "Resume interrupts masked", ( v & UDCCR_RESIM ) ? yes : no );
-+ SAYC( "Reset interrupts masked", ( v & UDCCR_REM ) ? yes : no );
-+
-+ v = Ser0UDCSR;
-+ SAY( "\nUDC Interrupt Request Register\n" );
-+ SAYV( v );
-+ SAYC( "Reset pending", ( v & UDCSR_RSTIR ) ? yes : no );
-+ SAYC( "Suspend pending", ( v & UDCSR_SUSIR ) ? yes : no );
-+ SAYC( "Resume pending", ( v & UDCSR_RESIR ) ? yes : no );
-+ SAYC( "ep0 pending", ( v & UDCSR_EIR ) ? yes : no );
-+ SAYC( "receiver pending", ( v & UDCSR_RIR ) ? yes : no );
-+ SAYC( "tramsitter pending", ( v & UDCSR_TIR ) ? yes : no );
-+
-+#ifdef CONFIG_SA1100_EXTENEX1
-+ SAYC( "\nSoft connect", (PPSR & PPC_USB_SOFT_CON) ? "Visible" : "Hidden" );
-+#endif
-+
-+#if 0
-+ v = Ser0UDCCS0;
-+ SAY( "\nUDC Endpoint Zero Status Register\n" );
-+ SAYV( v );
-+ SAYC( "Out Packet Ready", ( v & UDCCS0_OPR ) ? yes : no );
-+ SAYC( "In Packet Ready", ( v & UDCCS0_IPR ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS0_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS0_FST ) ? yes : no );
-+ SAYC( "Data End", ( v & UDCCS0_DE ) ? yes : no );
-+ SAYC( "Data Setup End", ( v & UDCCS0_SE ) ? yes : no );
-+ SAYC( "Serviced (SO)", ( v & UDCCS0_SO ) ? yes : no );
-+
-+ v = Ser0UDCCS1;
-+ SAY( "\nUDC Receiver Status Register\n" );
-+ SAYV( v );
-+ SAYC( "Receive Packet Complete", ( v & UDCCS1_RPC ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS1_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS1_FST ) ? yes : no );
-+ SAYC( "Receive Packet Error", ( v & UDCCS1_RPE ) ? yes : no );
-+ SAYC( "Receive FIFO not empty", ( v & UDCCS1_RNE ) ? yes : no );
-+
-+ v = Ser0UDCCS2;
-+ SAY( "\nUDC Transmitter Status Register\n" );
-+ SAYV( v );
-+ SAYC( "FIFO has < 8 of 16 chars", ( v & UDCCS2_TFS ) ? yes : no );
-+ SAYC( "Transmit Packet Complete", ( v & UDCCS2_TPC ) ? yes : no );
-+ SAYC( "Transmit FIFO underrun", ( v & UDCCS2_TUR ) ? yes : no );
-+ SAYC( "Transmit Packet Error", ( v & UDCCS2_TPE ) ? yes : no );
-+ SAYC( "Sent Stall", ( v & UDCCS2_SST ) ? yes : no );
-+ SAYC( "Force Stall", ( v & UDCCS2_FST ) ? yes : no );
-+#endif
-+
-+ len = ( p - page ) - off;
-+ if ( len < 0 )
-+ len = 0;
-+ *eof = ( len <=count ) ? 1 : 0;
-+ *start = page + off;
-+ return len;
-+}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+//////////////////////////////////////////////////////////////////////////////
-+// Module Initialization and Shutdown
-+//////////////////////////////////////////////////////////////////////////////
-+/*
-+ * usbctl_init()
-+ * Module load time. Allocate dma and interrupt resources. Setup /proc fs
-+ * entry. Leave UDC disabled.
-+ */
-+int __init usbctl_init( void )
-+{
-+ int retval = 0;
-+
-+ udc_disable();
-+
-+ memset( &usbd_info, 0, sizeof( usbd_info ) );
-+
-+#if CONFIG_PROC_FS
-+ create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
-+#endif
-+
-+ /* setup rx dma */
-+ retval = sa1100_request_dma(&usbd_info.dmach_rx, "USB receive", DMA_Ser0UDCRd);
-+ if (retval) {
-+ printk("%sunable to register for rx dma rc=%d\n", pszMe, retval );
-+ goto err_rx_dma;
-+ }
-+
-+ /* setup tx dma */
-+ retval = sa1100_request_dma(&usbd_info.dmach_tx, "USB transmit", DMA_Ser0UDCWr);
-+ if (retval) {
-+ printk("%sunable to register for tx dma rc=%d\n",pszMe,retval);
-+ goto err_tx_dma;
-+ }
-+
-+ /* now allocate the IRQ. */
-+ retval = request_irq(IRQ_Ser0UDC, udc_int_hndlr, SA_INTERRUPT,
-+ "SA USB core", NULL);
-+ if (retval) {
-+ printk("%sCouldn't request USB irq rc=%d\n",pszMe, retval);
-+ goto err_irq;
-+ }
-+
-+ printk( "SA1100 USB Controller Core Initialized\n");
-+ return 0;
-+
-+err_irq:
-+ sa1100_free_dma(usbd_info.dmach_tx);
-+ usbd_info.dmach_tx = 0;
-+err_tx_dma:
-+ sa1100_free_dma(usbd_info.dmach_rx);
-+ usbd_info.dmach_rx = 0;
-+err_rx_dma:
-+ return retval;
-+}
-+/*
-+ * usbctl_exit()
-+ * Release DMA and interrupt resources
-+ */
-+void __exit usbctl_exit( void )
-+{
-+ printk("Unloading SA1100 USB Controller\n");
-+
-+ udc_disable();
-+
-+#if CONFIG_PROC_FS
-+ remove_proc_entry ( PROC_NODE_NAME, NULL);
-+#endif
-+
-+ sa1100_free_dma(usbd_info.dmach_rx);
-+ sa1100_free_dma(usbd_info.dmach_tx);
-+ free_irq(IRQ_Ser0UDC, NULL);
-+}
-+
-+EXPORT_SYMBOL( sa1100_usb_open );
-+EXPORT_SYMBOL( sa1100_usb_start );
-+EXPORT_SYMBOL( sa1100_usb_stop );
-+EXPORT_SYMBOL( sa1100_usb_close );
-+
-+
-+EXPORT_SYMBOL( sa1100_usb_get_descriptor_ptr );
-+EXPORT_SYMBOL( sa1100_usb_set_string_descriptor );
-+EXPORT_SYMBOL( sa1100_usb_get_string_descriptor );
-+EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor );
-+
-+
-+module_init( usbctl_init );
-+module_exit( usbctl_exit );
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.h
-@@ -0,0 +1,123 @@
-+/*
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ * Copyright (C) Extenex Corporation 2001
-+ *
-+ * usb_ctl.h
-+ *
-+ * PRIVATE interface used to share info among components of the SA-1100 USB
-+ * core: usb_ctl, usb_ep0, usb_recv and usb_send. Clients of the USB core
-+ * should use sa1100_usb.h.
-+ *
-+ */
-+
-+#ifndef _USB_CTL_H
-+#define _USB_CTL_H
-+
-+#include <asm/dma.h> /* dmach_t */
-+
-+
-+/*
-+ * These states correspond to those in the USB specification v1.0
-+ * in chapter 8, Device Framework.
-+ */
-+enum { USB_STATE_NOTATTACHED=0, USB_STATE_ATTACHED=1,USB_STATE_POWERED=2,
-+ USB_STATE_DEFAULT=3, USB_STATE_ADDRESS=4, USB_STATE_CONFIGURED=5,
-+ USB_STATE_SUSPENDED=6};
-+
-+struct usb_stats_t {
-+ unsigned long ep0_fifo_write_failures;
-+ unsigned long ep0_bytes_written;
-+ unsigned long ep0_fifo_read_failures;
-+ unsigned long ep0_bytes_read;
-+};
-+
-+struct usb_info_t
-+{
-+ char * client_name;
-+ dmach_t dmach_tx, dmach_rx;
-+ int state;
-+ unsigned char address;
-+ struct usb_stats_t stats;
-+};
-+
-+/* in usb_ctl.c */
-+extern struct usb_info_t usbd_info;
-+
-+/*
-+ * Function Prototypes
-+ */
-+enum { kError=-1, kEvSuspend=0, kEvReset=1,
-+ kEvResume=2, kEvAddress=3, kEvConfig=4, kEvDeConfig=5 };
-+int usbctl_next_state_on_event( int event );
-+
-+/* endpoint zero */
-+void ep0_reset(void);
-+void ep0_int_hndlr(void);
-+
-+/* receiver */
-+void ep1_state_change_notify( int new_state );
-+int ep1_recv(void);
-+int ep1_init(int chn);
-+void ep1_int_hndlr(int status);
-+void ep1_reset(void);
-+void ep1_stall(void);
-+
-+/* xmitter */
-+void ep2_state_change_notify( int new_state );
-+void ep2_reset(void);
-+int ep2_init(int chn);
-+void ep2_int_hndlr(int status);
-+void ep2_stall(void);
-+
-+#define UDC_write(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) = (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: write %#x to %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while((reg) != (val)); \
-+}
-+
-+#define UDC_set(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) |= (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: set %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while(!((reg) & (val))); \
-+}
-+
-+#define UDC_clear(reg, val) { \
-+ int i = 10000; \
-+ do { \
-+ (reg) &= ~(val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: clear %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while((reg) & (val)); \
-+}
-+
-+#define UDC_flip(reg, val) { \
-+ int i = 10000; \
-+ (reg) = (val); \
-+ do { \
-+ (reg) = (val); \
-+ if (i-- <= 0) { \
-+ printk( "%s [%d]: flip %#x of %p (%#x) failed\n", \
-+ __FUNCTION__, __LINE__, (val), &(reg), (reg)); \
-+ break; \
-+ } \
-+ } while(((reg) & (val))); \
-+}
-+
-+
-+#define CHECK_ADDRESS { if ( Ser0UDCAR == 1 ) { printk("%s:%d I lost my address!!!\n",__FUNCTION__, __LINE__);}}
-+#endif /* _USB_CTL_H */
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_ep0.c
-@@ -0,0 +1,911 @@
-+/*
-+ * Copyright (C) Extenex Corporation 2001
-+ * Much folklore gleaned from original code:
-+ * Copyright (C) Compaq Computer Corporation, 1998, 1999
-+ *
-+ * usb_ep0.c - SA1100 USB controller driver.
-+ * Endpoint zero management
-+ *
-+ * Please see:
-+ * linux/Documentation/arm/SA1100/SA1100_USB
-+ * for details. (Especially since Intel docs are full of
-+ * errors about ep0 operation.) ward.willats@extenex.com.
-+ *
-+ * Intel also has a "Universal Serial Bus Client Device
-+ * Validation for the StrongARM SA-1100 Microprocessor"
-+ * document, which has flow charts and assembler test driver,
-+ * but be careful, since it is just for validation and not
-+ * a "real world" solution.
-+ *
-+ * A summary of three types of data-returning setups:
-+ *
-+ * 1. Setup request <= 8 bytes. That is, requests that can
-+ * be fullfilled in one write to the FIFO. DE is set
-+ * with IPR in queue_and_start_write(). (I don't know
-+ * if there really are any of these!)
-+ *
-+ * 2. Setup requests > 8 bytes (requiring more than one
-+ * IN to get back to the host), and we have at least
-+ * as much or more data than the host requested. In
-+ * this case we pump out everything we've got, and
-+ * when the final interrupt comes in due to the UDC
-+ * clearing the last IPR, we just set DE.
-+ *
-+ * 3. Setup requests > 8 bytes, but we don't have enough
-+ * data to satisfy the request. In this case, we send
-+ * everything we've got, and when the final interrupt
-+ * comes in due to the UDC clearing the last IPR
-+ * we write nothing to the FIFO and set both IPR and DE
-+ * so the UDC sends an empty packet and forces the host
-+ * to perform short packet retirement instead of stalling
-+ * out.
-+ *
-+ */
-+
-+#include <linux/delay.h>
-+#include "sa1100_usb.h" /* public interface */
-+#include "usb_ctl.h" /* private stuff */
-+
-+
-+// 1 == lots of trace noise, 0 = only "important' stuff
-+#define VERBOSITY 0
-+
-+enum { true = 1, false = 0 };
-+typedef int bool;
-+#ifndef MIN
-+#define MIN( a, b ) ((a)<(b)?(a):(b))
-+#endif
-+
-+#if 1 && !defined( ASSERT )
-+# define ASSERT(expr) \
-+ if(!(expr)) { \
-+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-+ #expr,__FILE__,__FUNCTION__,__LINE__); \
-+ }
-+#else
-+# define ASSERT(expr)
-+#endif
-+
-+#if VERBOSITY
-+#define PRINTKD(fmt, args...) printk( fmt , ## args)
-+#else
-+#define PRINTKD(fmt, args...)
-+#endif
-+
-+/*================================================
-+ * USB Protocol Stuff
-+ */
-+
-+/* Request Codes */
-+enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3,
-+ SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7,
-+ GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10,
-+ SET_INTERFACE=11 };
-+
-+
-+/* USB Device Requests */
-+typedef struct
-+{
-+ __u8 bmRequestType;
-+ __u8 bRequest;
-+ __u16 wValue;
-+ __u16 wIndex;
-+ __u16 wLength;
-+} usb_dev_request_t __attribute__ ((packed));
-+
-+/***************************************************************************
-+Prototypes
-+***************************************************************************/
-+/* "setup handlers" -- the main functions dispatched to by the
-+ .. isr. These represent the major "modes" of endpoint 0 operaton */
-+static void sh_setup_begin(void); /* setup begin (idle) */
-+static void sh_write( void ); /* writing data */
-+static void sh_write_with_empty_packet( void ); /* empty packet at end of xfer*/
-+/* called before both sh_write routines above */
-+static void common_write_preamble( void );
-+
-+/* other subroutines */
-+static __u32 queue_and_start_write( void * p, int req, int act );
-+static void write_fifo( void );
-+static int read_fifo( usb_dev_request_t * p );
-+static void get_descriptor( usb_dev_request_t * pReq );
-+
-+/* some voodo helpers 01Mar01ww */
-+static void set_cs_bits( __u32 set_bits );
-+static void set_de( void );
-+static void set_ipr( void );
-+static void set_ipr_and_de( void );
-+static bool clear_opr( void );
-+
-+/***************************************************************************
-+Inline Helpers
-+***************************************************************************/
-+
-+/* Data extraction from usb_request_t fields */
-+enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };
-+static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }
-+
-+static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }
-+inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }
-+
-+/* following is hook for self-powered flag in GET_STATUS. Some devices
-+ .. might like to override and return real info */
-+static inline bool self_powered_hook( void ) { return true; }
-+
-+/* print string descriptor */
-+static inline void psdesc( string_desc_t * p )
-+{
-+ int i;
-+ int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
-+ printk( "'" );
-+ for( i = 0 ; i < nchars ; i++ ) {
-+ printk( "%c", (char) p->bString[i] );
-+ }
-+ printk( "'\n" );
-+}
-+
-+
-+#if VERBOSITY
-+/* "pcs" == "print control status" */
-+static inline void pcs( void )
-+{
-+ __u32 foo = Ser0UDCCS0;
-+ printk( "%8.8X: %s %s %s %s\n",
-+ foo,
-+ foo & UDCCS0_SE ? "SE" : "",
-+ foo & UDCCS0_OPR ? "OPR" : "",
-+ foo & UDCCS0_IPR ? "IPR" : "",
-+ foo & UDCCS0_SST ? "SST" : ""
-+ );
-+}
-+static inline void preq( usb_dev_request_t * pReq )
-+{
-+ static char * tnames[] = { "dev", "intf", "ep", "oth" };
-+ static char * rnames[] = { "std", "class", "vendor", "???" };
-+ char * psz;
-+ switch( pReq->bRequest ) {
-+ case GET_STATUS: psz = "get stat"; break;
-+ case CLEAR_FEATURE: psz = "clr feat"; break;
-+ case SET_FEATURE: psz = "set feat"; break;
-+ case SET_ADDRESS: psz = "set addr"; break;
-+ case GET_DESCRIPTOR: psz = "get desc"; break;
-+ case SET_DESCRIPTOR: psz = "set desc"; break;
-+ case GET_CONFIGURATION: psz = "get cfg"; break;
-+ case SET_CONFIGURATION: psz = "set cfg"; break;
-+ case GET_INTERFACE: psz = "get intf"; break;
-+ case SET_INTERFACE: psz = "set intf"; break;
-+ default: psz = "unknown"; break;
-+ }
-+ printk( "- [%s: %s req to %s. dir=%s]\n", psz,
-+ rnames[ (pReq->bmRequestType >> 5) & 3 ],
-+ tnames[ pReq->bmRequestType & 3 ],
-+ ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
-+}
-+
-+#else
-+static inline void pcs( void ){}
-+static inline void preq( void ){}
-+#endif
-+
-+/***************************************************************************
-+Globals
-+***************************************************************************/
-+static const char pszMe[] = "usbep0: ";
-+
-+/* pointer to current setup handler */
-+static void (*current_handler)(void) = sh_setup_begin;
-+
-+/* global write struct to keep write
-+ ..state around across interrupts */
-+static struct {
-+ unsigned char *p;
-+ int bytes_left;
-+} wr;
-+
-+/***************************************************************************
-+Public Interface
-+***************************************************************************/
-+
-+/* reset received from HUB (or controller just went nuts and reset by itself!)
-+ so udc core has been reset, track this state here */
-+void
-+ep0_reset(void)
-+{
-+ /* reset state machine */
-+ current_handler = sh_setup_begin;
-+ wr.p = NULL;
-+ wr.bytes_left = 0;
-+ usbd_info.address=0;
-+}
-+
-+/* handle interrupt for endpoint zero */
-+void
-+ep0_int_hndlr( void )
-+{
-+ PRINTKD( "/\\(%d)\n", Ser0UDCAR );
-+ pcs();
-+
-+ /* if not in setup begin, we are returning data.
-+ execute a common preamble to both write handlers
-+ */
-+ if ( current_handler != sh_setup_begin )
-+ common_write_preamble();
-+
-+ (*current_handler)();
-+
-+ PRINTKD( "---\n" );
-+ pcs();
-+ PRINTKD( "\\/\n" );
-+}
-+
-+/***************************************************************************
-+Setup Handlers
-+***************************************************************************/
-+/*
-+ * sh_setup_begin()
-+ * This setup handler is the "idle" state of endpoint zero. It looks for OPR
-+ * (OUT packet ready) to see if a setup request has been been received from the
-+ * host. Requests without a return data phase are immediately handled. Otherwise,
-+ * in the case of GET_XXXX the handler may be set to one of the sh_write_xxxx
-+ * data pumpers if more than 8 bytes need to get back to the host.
-+ *
-+ */
-+static void
-+sh_setup_begin( void )
-+{
-+ unsigned char status_buf[2]; /* returned in GET_STATUS */
-+ usb_dev_request_t req;
-+ int request_type;
-+ int n;
-+ __u32 cs_bits;
-+ __u32 address;
-+ __u32 cs_reg_in = Ser0UDCCS0;
-+
-+ if (cs_reg_in & UDCCS0_SST) {
-+ PRINTKD( "%ssetup begin: sent stall. Continuing\n", pszMe );
-+ set_cs_bits( UDCCS0_SST );
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_SE ) {
-+ PRINTKD( "%ssetup begin: Early term of setup. Continuing\n", pszMe );
-+ set_cs_bits( UDCCS0_SSE ); /* clear setup end */
-+ }
-+
-+ /* Be sure out packet ready, otherwise something is wrong */
-+ if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
-+ /* we can get here early...if so, we'll int again in a moment */
-+ PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
-+ goto sh_sb_end;
-+ }
-+
-+ /* read the setup request */
-+ n = read_fifo( &req );
-+ if ( n != sizeof( req ) ) {
-+ printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
-+ " Stalling out...\n",
-+ pszMe, sizeof( req ), n );
-+ /* force stall, serviced out */
-+ set_cs_bits( UDCCS0_FST | UDCCS0_SO );
-+ goto sh_sb_end;
-+ }
-+
-+ /* Is it a standard request? (not vendor or class request) */
-+ request_type = type_code_from_request( req.bmRequestType );
-+ if ( request_type != 0 ) {
-+ printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
-+ pszMe, request_type );
-+ set_cs_bits( UDCCS0_DE | UDCCS0_SO );
-+ goto sh_sb_end;
-+ }
-+
-+#if VERBOSITY
-+ {
-+ unsigned char * pdb = (unsigned char *) &req;
-+ PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
-+ pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
-+ );
-+ preq( &req );
-+ }
-+#endif
-+
-+ /* Handle it */
-+ switch( req.bRequest ) {
-+
-+ /* This first bunch have no data phase */
-+
-+ case SET_ADDRESS:
-+ address = (__u32) (req.wValue & 0x7F);
-+ /* when SO and DE sent, UDC will enter status phase and ack,
-+ ..propagating new address to udc core. Next control transfer
-+ ..will be on the new address. You can't see the change in a
-+ ..read back of CAR until then. (about 250us later, on my box).
-+ ..The original Intel driver sets S0 and DE and code to check
-+ ..that address has propagated here. I tried this, but it
-+ ..would only work sometimes! The rest of the time it would
-+ ..never propagate and we'd spin forever. So now I just set
-+ ..it and pray...
-+ */
-+ Ser0UDCAR = address;
-+ usbd_info.address = address;
-+ usbctl_next_state_on_event( kEvAddress );
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ printk( "%sI have been assigned address: %d\n", pszMe, address );
-+ break;
-+
-+
-+ case SET_CONFIGURATION:
-+ if ( req.wValue == 1 ) {
-+ /* configured */
-+ if (usbctl_next_state_on_event( kEvConfig ) != kError){
-+ /* (re)set the out and in max packet sizes */
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ __u32 out = __le16_to_cpu( pDesc->b.ep1.wMaxPacketSize );
-+ __u32 in = __le16_to_cpu( pDesc->b.ep2.wMaxPacketSize );
-+ Ser0UDCOMP = ( out - 1 );
-+ Ser0UDCIMP = ( in - 1 );
-+ printk( "%sConfigured (OMP=%8.8X IMP=%8.8X)\n", pszMe, out, in );
-+ }
-+ } else if ( req.wValue == 0 ) {
-+ /* de-configured */
-+ if (usbctl_next_state_on_event( kEvDeConfig ) != kError )
-+ printk( "%sDe-Configured\n", pszMe );
-+ } else {
-+ printk( "%ssetup phase: Unknown "
-+ "\"set configuration\" data %d\n",
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+ case CLEAR_FEATURE:
-+ /* could check data length, direction...26Jan01ww */
-+ if ( req.wValue == 0 ) { /* clearing ENDPOINT_HALT/STALL */
-+ int ep = windex_to_ep_num( req.wIndex );
-+ if ( ep == 1 ) {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ " on receiver\n", pszMe );
-+ ep1_reset();
-+ }
-+ else if ( ep == 2 ) {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ "on xmitter\n", pszMe );
-+ ep2_reset();
-+ } else {
-+ printk( "%sclear feature \"endpoint halt\" "
-+ "on unsupported ep # %d\n",
-+ pszMe, ep );
-+ }
-+ } else {
-+ printk( "%sUnsupported feature selector (%d) "
-+ "in clear feature. Ignored.\n" ,
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+ case SET_FEATURE:
-+ if ( req.wValue == 0 ) { /* setting ENDPOINT_HALT/STALL */
-+ int ep = windex_to_ep_num( req.wValue );
-+ if ( ep == 1 ) {
-+ printk( "%set feature \"endpoint halt\" "
-+ "on receiver\n", pszMe );
-+ ep1_stall();
-+ }
-+ else if ( ep == 2 ) {
-+ printk( "%sset feature \"endpoint halt\" "
-+ " on xmitter\n", pszMe );
-+ ep2_stall();
-+ } else {
-+ printk( "%sset feature \"endpoint halt\" "
-+ "on unsupported ep # %d\n",
-+ pszMe, ep );
-+ }
-+ }
-+ else {
-+ printk( "%sUnsupported feature selector "
-+ "(%d) in set feature\n",
-+ pszMe, req.wValue );
-+ }
-+ set_cs_bits( UDCCS0_SO | UDCCS0_DE ); /* no data phase */
-+ break;
-+
-+
-+ /* The rest have a data phase that writes back to the host */
-+ case GET_STATUS:
-+ /* return status bit flags */
-+ status_buf[0] = status_buf[1] = 0;
-+ n = request_target(req.bmRequestType);
-+ switch( n ) {
-+ case kTargetDevice:
-+ if ( self_powered_hook() )
-+ status_buf[0] |= 1;
-+ break;
-+ case kTargetInterface:
-+ break;
-+ case kTargetEndpoint:
-+ /* return stalled bit */
-+ n = windex_to_ep_num( req.wIndex );
-+ if ( n == 1 )
-+ status_buf[0] |= (Ser0UDCCS1 & UDCCS1_FST) >> 4;
-+ else if ( n == 2 )
-+ status_buf[0] |= (Ser0UDCCS2 & UDCCS2_FST) >> 5;
-+ else {
-+ printk( "%sUnknown endpoint (%d) "
-+ "in GET_STATUS\n", pszMe, n );
-+ }
-+ break;
-+ default:
-+ printk( "%sUnknown target (%d) in GET_STATUS\n",
-+ pszMe, n );
-+ /* fall thru */
-+ break;
-+ }
-+ cs_bits = queue_and_start_write( status_buf,
-+ req.wLength,
-+ sizeof( status_buf ) );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case GET_DESCRIPTOR:
-+ get_descriptor( &req );
-+ break;
-+
-+ case GET_CONFIGURATION:
-+ status_buf[0] = (usbd_info.state == USB_STATE_CONFIGURED)
-+ ? 1
-+ : 0;
-+ cs_bits = queue_and_start_write( status_buf, req.wLength, 1 );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case GET_INTERFACE:
-+ printk( "%sfixme: get interface not supported\n", pszMe );
-+ cs_bits = queue_and_start_write( NULL, req.wLength, 0 );
-+ set_cs_bits( cs_bits );
-+ break;
-+ case SET_INTERFACE:
-+ printk( "%sfixme: set interface not supported\n", pszMe );
-+ set_cs_bits( UDCCS0_DE | UDCCS0_SO );
-+ break;
-+ default :
-+ printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
-+ break;
-+ } /* switch( bRequest ) */
-+
-+sh_sb_end:
-+ return;
-+
-+}
-+/*
-+ * common_wrtie_preamble()
-+ * Called before execution of sh_write() or sh_write_with_empty_packet()
-+ * Handles common abort conditions.
-+ *
-+ */
-+static void common_write_preamble( void )
-+{
-+ /* If "setup end" has been set, the usb controller has
-+ ..terminated a setup transaction before we set DE. This
-+ ..happens during enumeration with some hosts. For example,
-+ ..the host will ask for our device descriptor and specify
-+ ..a return of 64 bytes. When we hand back the first 8, the
-+ ..host will know our max packet size and turn around and
-+ ..issue a new setup immediately. This causes the UDC to auto-ack
-+ ..the new setup and set SE. We must then "unload" (process)
-+ ..the new setup, which is what will happen after this preamble
-+ ..is finished executing.
-+ */
-+ __u32 cs_reg_in = Ser0UDCCS0;
-+
-+ if ( cs_reg_in & UDCCS0_SE ) {
-+ PRINTKD( "%swrite_preamble(): Early termination of setup\n", pszMe );
-+ Ser0UDCCS0 = UDCCS0_SSE; /* clear setup end */
-+ current_handler = sh_setup_begin;
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_SST ) {
-+ PRINTKD( "%swrite_preamble(): UDC sent stall\n", pszMe );
-+ Ser0UDCCS0 = UDCCS0_SST; /* clear setup end */
-+ current_handler = sh_setup_begin;
-+ }
-+
-+ if ( cs_reg_in & UDCCS0_OPR ) {
-+ PRINTKD( "%swrite_preamble(): see OPR. Stopping write to "
-+ "handle new SETUP\n", pszMe );
-+ /* very rarely, you can get OPR and leftover IPR. Try to clear */
-+ UDC_clear( Ser0UDCCS0, UDCCS0_IPR );
-+ current_handler = sh_setup_begin;
-+ }
-+}
-+
-+/*
-+ * sh_write()
-+ * This is the setup handler when we are in the data return phase of
-+ * a setup request and have as much (or more) data than the host
-+ * requested. If we enter this routine and bytes left is zero, the
-+ * last data packet has gone (int is because IPR was just cleared)
-+ * so we just set DE and reset. Otheriwse, we write another packet
-+ * and set IPR.
-+ */
-+static void sh_write()
-+{
-+ PRINTKD( "W\n" );
-+
-+ if ( Ser0UDCCS0 & UDCCS0_IPR ) {
-+ PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
-+ return;
-+ }
-+
-+ /* If bytes left is zero, we are coming in on the
-+ ..interrupt after the last packet went out. And
-+ ..we know we don't have to empty packet this transfer
-+ ..so just set DE and we are done */
-+
-+ if ( 0 == wr.bytes_left ) {
-+ /* that's it, so data end */
-+ set_de();
-+ wr.p = NULL; /* be anal */
-+ current_handler = sh_setup_begin;
-+ } else {
-+ /* Otherwise, more data to go */
-+ write_fifo();
-+ set_ipr();
-+ }
-+}
-+/*
-+ * sh_write_with_empty_packet()
-+ * This is the setup handler when we don't have enough data to
-+ * satisfy the host's request. After we send everything we've got
-+ * we must send an empty packet (by setting IPR and DE) so the
-+ * host can perform "short packet retirement" and not stall.
-+ *
-+ */
-+static void sh_write_with_empty_packet( void )
-+{
-+ __u32 cs_reg_out = 0;
-+ PRINTKD( "WE\n" );
-+
-+ if ( Ser0UDCCS0 & UDCCS0_IPR ) {
-+ PRINTKD( "%ssh_write(): IPR set, exiting\n", pszMe );
-+ return;
-+ }
-+
-+ /* If bytes left is zero, we are coming in on the
-+ ..interrupt after the last packet went out.
-+ ..we must do short packet suff, so set DE and IPR
-+ */
-+
-+ if ( 0 == wr.bytes_left ) {
-+ set_ipr_and_de();
-+ wr.p = NULL;
-+ current_handler = sh_setup_begin;
-+ PRINTKD( "%ssh_write empty() Sent empty packet \n", pszMe );
-+ } else {
-+ write_fifo(); /* send data */
-+ set_ipr(); /* flag a packet is ready */
-+ }
-+ Ser0UDCCS0 = cs_reg_out;
-+}
-+
-+/***************************************************************************
-+Other Private Subroutines
-+***************************************************************************/
-+/*
-+ * queue_and_start_write()
-+ * p == data to send
-+ * req == bytes host requested
-+ * act == bytes we actually have
-+ * Returns: bits to be flipped in ep0 control/status register
-+ *
-+ * Called from sh_setup_begin() to begin a data return phase. Sets up the
-+ * global "wr"-ite structure and load the outbound FIFO with data.
-+ * If can't send all the data, set appropriate handler for next interrupt.
-+ *
-+ */
-+static __u32 queue_and_start_write( void * in, int req, int act )
-+{
-+ __u32 cs_reg_bits = UDCCS0_IPR;
-+ unsigned char * p = (unsigned char*) in;
-+
-+ PRINTKD( "Qr=%d a=%d\n",req,act );
-+
-+ /* thou shalt not enter data phase until the serviced OUT is clear */
-+ if ( ! clear_opr() ) {
-+ printk( "%sSO did not clear OPR\n", pszMe );
-+ return ( UDCCS0_DE | UDCCS0_SO ) ;
-+ }
-+ wr.p = p;
-+ wr.bytes_left = MIN( act, req );
-+
-+ write_fifo();
-+
-+ if ( 0 == wr.bytes_left ) {
-+ cs_reg_bits |= UDCCS0_DE; /* out in 1 so data end */
-+ wr.p = NULL; /* be anal */
-+ }
-+ else if ( act < req ) /* we are going to short-change host */
-+ current_handler = sh_write_with_empty_packet; /* so need nul to not stall */
-+ else /* we have as much or more than requested */
-+ current_handler = sh_write;
-+
-+ return cs_reg_bits; /* note: IPR was set uncondtionally at start of routine */
-+}
-+/*
-+ * write_fifo()
-+ * Stick bytes in the 8 bytes endpoint zero FIFO.
-+ * This version uses a variety of tricks to make sure the bytes
-+ * are written correctly. 1. The count register is checked to
-+ * see if the byte went in, and the write is attempted again
-+ * if not. 2. An overall counter is used to break out so we
-+ * don't hang in those (rare) cases where the UDC reverses
-+ * direction of the FIFO underneath us without notification
-+ * (in response to host aborting a setup transaction early).
-+ *
-+ */
-+static void write_fifo( void )
-+{
-+ int bytes_this_time = MIN( wr.bytes_left, 8 );
-+ int bytes_written = 0;
-+ int i=0;
-+
-+ PRINTKD( "WF=%d: ", bytes_this_time );
-+
-+ while( bytes_this_time-- ) {
-+ PRINTKD( "%2.2X ", *wr.p );
-+ i = 0;
-+ do {
-+ Ser0UDCD0 = *wr.p;
-+ udelay( 20 ); /* voodo 28Feb01ww */
-+ i++;
-+ } while( Ser0UDCWC == bytes_written && i < 10 );
-+ if ( i == 50 ) {
-+ printk( "%swrite_fifo: write failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_write_failures++;
-+ }
-+
-+ wr.p++;
-+ bytes_written++;
-+ }
-+ wr.bytes_left -= bytes_written;
-+
-+ /* following propagation voodo so maybe caller writing IPR in
-+ ..a moment might actually get it to stick 28Feb01ww */
-+ udelay( 300 );
-+
-+ usbd_info.stats.ep0_bytes_written += bytes_written;
-+ PRINTKD( "L=%d WCR=%8.8X\n", wr.bytes_left, Ser0UDCWC );
-+}
-+/*
-+ * read_fifo()
-+ * Read 1-8 bytes out of FIFO and put in request.
-+ * Called to do the initial read of setup requests
-+ * from the host. Return number of bytes read.
-+ *
-+ * Like write fifo above, this driver uses multiple
-+ * reads checked agains the count register with an
-+ * overall timeout.
-+ *
-+ */
-+static int
-+read_fifo( usb_dev_request_t * request )
-+{
-+ int bytes_read = 0;
-+ int fifo_count;
-+ int i;
-+
-+ unsigned char * pOut = (unsigned char*) request;
-+
-+ fifo_count = ( Ser0UDCWC & 0xFF );
-+
-+ ASSERT( fifo_count <= 8 );
-+ PRINTKD( "RF=%d ", fifo_count );
-+
-+ while( fifo_count-- ) {
-+ i = 0;
-+ do {
-+ *pOut = (unsigned char) Ser0UDCD0;
-+ udelay( 10 );
-+ } while( ( Ser0UDCWC & 0xFF ) != fifo_count && i < 10 );
-+ if ( i == 10 ) {
-+ printk( "%sread_fifo(): read failure\n", pszMe );
-+ usbd_info.stats.ep0_fifo_read_failures++;
-+ }
-+ pOut++;
-+ bytes_read++;
-+ }
-+
-+ PRINTKD( "fc=%d\n", bytes_read );
-+ usbd_info.stats.ep0_bytes_read++;
-+ return bytes_read;
-+}
-+
-+/*
-+ * get_descriptor()
-+ * Called from sh_setup_begin to handle data return
-+ * for a GET_DESCRIPTOR setup request.
-+ */
-+static void get_descriptor( usb_dev_request_t * pReq )
-+{
-+ __u32 cs_bits = 0;
-+ string_desc_t * pString;
-+ ep_desc_t * pEndpoint;
-+
-+ desc_t * pDesc = sa1100_usb_get_descriptor_ptr();
-+ int type = pReq->wValue >> 8;
-+ int idx = pReq->wValue & 0xFF;
-+
-+ switch( type ) {
-+ case USB_DESC_DEVICE:
-+ cs_bits =
-+ queue_and_start_write( &pDesc->dev,
-+ pReq->wLength,
-+ pDesc->dev.bLength );
-+ break;
-+
-+ // return config descriptor buffer, cfg, intf, 2 ep
-+ case USB_DESC_CONFIG:
-+ cs_bits =
-+ queue_and_start_write( &pDesc->b,
-+ pReq->wLength,
-+ sizeof( struct cdb ) );
-+ break;
-+
-+ // not quite right, since doesn't do language code checking
-+ case USB_DESC_STRING:
-+ pString = sa1100_usb_get_string_descriptor( idx );
-+ if ( pString ) {
-+ if ( idx != 0 ) { // if not language index
-+ printk( "%sReturn string %d: ", pszMe, idx );
-+ psdesc( pString );
-+ }
-+ cs_bits =
-+ queue_and_start_write( pString,
-+ pReq->wLength,
-+ pString->bLength );
-+ }
-+ else {
-+ printk("%sunkown string index %d Stall.\n", pszMe, idx );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ }
-+ break;
-+
-+ case USB_DESC_INTERFACE:
-+ if ( idx == pDesc->b.intf.bInterfaceNumber ) {
-+ cs_bits =
-+ queue_and_start_write( &pDesc->b.intf,
-+ pReq->wLength,
-+ pDesc->b.intf.bLength );
-+ }
-+ break;
-+
-+ case USB_DESC_ENDPOINT: /* correct? 21Feb01ww */
-+ if ( idx == 1 )
-+ pEndpoint = &pDesc->b.ep1;
-+ else if ( idx == 2 )
-+ pEndpoint = &pDesc->b.ep2;
-+ else
-+ pEndpoint = NULL;
-+ if ( pEndpoint ) {
-+ cs_bits =
-+ queue_and_start_write( pEndpoint,
-+ pReq->wLength,
-+ pEndpoint->bLength );
-+ } else {
-+ printk("%sunkown endpoint index %d Stall.\n", pszMe, idx );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ }
-+ break;
-+
-+
-+ default :
-+ printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
-+ cs_bits = ( UDCCS0_DE | UDCCS0_SO | UDCCS0_FST );
-+ break;
-+
-+ }
-+ set_cs_bits( cs_bits );
-+}
-+
-+
-+/* some voodo I am adding, since the vanilla macros just aren't doing it 1Mar01ww */
-+
-+#define ABORT_BITS ( UDCCS0_SST | UDCCS0_SE )
-+#define OK_TO_WRITE (!( Ser0UDCCS0 & ABORT_BITS ))
-+#define BOTH_BITS (UDCCS0_IPR | UDCCS0_DE)
-+
-+static void set_cs_bits( __u32 bits )
-+{
-+ if ( bits & ( UDCCS0_SO | UDCCS0_SSE | UDCCS0_FST ) )
-+ Ser0UDCCS0 = bits;
-+ else if ( (bits & BOTH_BITS) == BOTH_BITS )
-+ set_ipr_and_de();
-+ else if ( bits & UDCCS0_IPR )
-+ set_ipr();
-+ else if ( bits & UDCCS0_DE )
-+ set_de();
-+}
-+
-+static void set_de( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= UDCCS0_DE;
-+ } else {
-+ PRINTKD( "%sQuitting set DE because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( Ser0UDCCS0 & UDCCS0_DE )
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set DE! (DE=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_DE, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+static void set_ipr( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= UDCCS0_IPR;
-+ } else {
-+ PRINTKD( "%sQuitting set IPR because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( Ser0UDCCS0 & UDCCS0_IPR )
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set IPR! (IPR=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_IPR, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+
-+
-+static void set_ipr_and_de( void )
-+{
-+ int i = 1;
-+ while( 1 ) {
-+ if ( OK_TO_WRITE ) {
-+ Ser0UDCCS0 |= BOTH_BITS;
-+ } else {
-+ PRINTKD( "%sQuitting set IPR/DE because SST or SE set\n", pszMe );
-+ break;
-+ }
-+ if ( (Ser0UDCCS0 & BOTH_BITS) == BOTH_BITS)
-+ break;
-+ udelay( i );
-+ if ( ++i == 50 ) {
-+ printk( "%sDangnabbbit! Cannot set DE/IPR! (DE=%8.8X IPR=%8.8X CCS0=%8.8X)\n",
-+ pszMe, UDCCS0_DE, UDCCS0_IPR, Ser0UDCCS0 );
-+ break;
-+ }
-+ }
-+}
-+
-+static bool clear_opr( void )
-+{
-+ int i = 10000;
-+ bool is_clear;
-+ do {
-+ Ser0UDCCS0 = UDCCS0_SO;
-+ is_clear = ! ( Ser0UDCCS0 & UDCCS0_OPR );
-+ if ( i-- <= 0 ) {
-+ printk( "%sclear_opr(): failed\n", pszMe );
-+ break;
-+ }
-+ } while( ! is_clear );
-+ return is_clear;
-+}
-+
-+
-+
-+
-+
-+/* end usb_ep0.c */
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_recv.c
-@@ -0,0 +1,205 @@
-+/*
-+ * Generic receive layer for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+
-+static char *ep1_buf;
-+static int ep1_len;
-+static usb_callback_t ep1_callback;
-+static char *ep1_curdmabuf;
-+static dma_addr_t ep1_curdmapos;
-+static int ep1_curdmalen;
-+static int ep1_remain;
-+static int dmachn_rx;
-+static int rx_pktsize;
-+
-+static int naking;
-+
-+static void
-+ep1_start(void)
-+{
-+ sa1100_dma_flush_all(dmachn_rx);
-+ if (!ep1_curdmalen) {
-+ ep1_curdmalen = rx_pktsize;
-+ if (ep1_curdmalen > ep1_remain)
-+ ep1_curdmalen = ep1_remain;
-+ ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ }
-+ sa1100_dma_queue_buffer(dmachn_rx, NULL, ep1_curdmapos, ep1_curdmalen);
-+ if ( naking ) {
-+ /* turn off NAK of OUT packets, if set */
-+ UDC_flip( Ser0UDCCS1, UDCCS1_RPC );
-+ naking = 0;
-+ }
-+}
-+
-+static void
-+ep1_done(int flag)
-+{
-+ int size = ep1_len - ep1_remain;
-+
-+ if (!ep1_len)
-+ return;
-+ if (ep1_curdmalen)
-+ pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ ep1_len = ep1_curdmalen = 0;
-+ if (ep1_callback) {
-+ ep1_callback(flag, size);
-+ }
-+}
-+
-+void
-+ep1_state_change_notify( int new_state )
-+{
-+
-+}
-+
-+void
-+ep1_stall( void )
-+{
-+ /* SET_FEATURE force stall at UDC */
-+ UDC_set( Ser0UDCCS1, UDCCS1_FST );
-+}
-+
-+int
-+ep1_init(int chn)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ dmachn_rx = chn;
-+ sa1100_dma_flush_all(dmachn_rx);
-+ ep1_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep1_reset(void)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ rx_pktsize = __le16_to_cpu( pd->b.ep1.wMaxPacketSize );
-+ sa1100_dma_flush_all(dmachn_rx);
-+ UDC_clear(Ser0UDCCS1, UDCCS1_FST);
-+ ep1_done(-EINTR);
-+}
-+
-+void
-+ep1_int_hndlr(int udcsr)
-+{
-+ dma_addr_t dma_addr;
-+ unsigned int len;
-+ int status = Ser0UDCCS1;
-+
-+ if ( naking ) printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );
-+
-+ if (status & UDCCS1_RPC) {
-+
-+ if (!ep1_curdmalen) {
-+ printk("usb_recv: RPC for non-existent buffer\n");
-+ naking=1;
-+ return;
-+ }
-+
-+ sa1100_dma_stop(dmachn_rx);
-+
-+ if (status & UDCCS1_SST) {
-+ printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP);
-+ UDC_flip(Ser0UDCCS1, UDCCS1_SST);
-+ ep1_done(-EIO); // UDC aborted current transfer, so we do
-+ return;
-+ }
-+
-+ if (status & UDCCS1_RPE) {
-+ printk("usb_recv: RPError %x\n", status);
-+ UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
-+ ep1_done(-EIO);
-+ return;
-+ }
-+
-+ sa1100_dma_get_current(dmachn_rx, NULL, &dma_addr);
-+ pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen,
-+ PCI_DMA_FROMDEVICE);
-+ len = dma_addr - ep1_curdmapos;
-+ if (len < ep1_curdmalen) {
-+ char *buf = ep1_curdmabuf + len;
-+ while (Ser0UDCCS1 & UDCCS1_RNE) {
-+ if (len >= ep1_curdmalen) {
-+ printk("usb_recv: too much data in fifo\n");
-+ break;
-+ }
-+ *buf++ = Ser0UDCDR;
-+ len++;
-+ }
-+ } else if (Ser0UDCCS1 & UDCCS1_RNE) {
-+ printk("usb_recv: fifo screwed, shouldn't contain data\n");
-+ len = 0;
-+ }
-+ ep1_curdmalen = 0; /* dma unmap already done */
-+ ep1_remain -= len;
-+ naking = 1;
-+ ep1_done((len) ? 0 : -EPIPE);
-+ }
-+ /* else, you can get here if we are holding NAK */
-+}
-+
-+int
-+sa1100_usb_recv(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (ep1_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep1_buf = buf;
-+ ep1_len = len;
-+ ep1_callback = callback;
-+ ep1_remain = len;
-+ ep1_curdmabuf = buf;
-+ ep1_curdmalen = 0;
-+ ep1_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv);
-+
-+void
-+sa1100_usb_recv_reset(void)
-+{
-+ ep1_reset();
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv_reset);
-+
-+void
-+sa1100_usb_recv_stall(void)
-+{
-+ ep1_stall();
-+}
-+
-+EXPORT_SYMBOL(sa1100_usb_recv_stall);
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_send.c
-@@ -0,0 +1,205 @@
-+/*
-+ * Generic xmit layer for the SA1100 USB client function
-+ * Copyright (c) 2001 by Nicolas Pitre
-+ *
-+ * This code was loosely inspired by the original version which was
-+ * Copyright (c) Compaq Computer Corporation, 1998-1999
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is still work in progress...
-+ *
-+ * Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
-+ * 15/03/2001 - ep2_start now sets UDCAR to overcome something that is hardware
-+ * bug, I think. green@iXcelerator.com
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h> // for the massive_attack hack 28Feb01ww
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+#include <asm/byteorder.h>
-+
-+#include "sa1100_usb.h"
-+#include "usb_ctl.h"
-+
-+
-+static char *ep2_buf;
-+static int ep2_len;
-+static usb_callback_t ep2_callback;
-+static dma_addr_t ep2_dma;
-+static dma_addr_t ep2_curdmapos;
-+static int ep2_curdmalen;
-+static int ep2_remain;
-+static int dmachn_tx;
-+static int tx_pktsize;
-+
-+/* device state is changing, async */
-+void
-+ep2_state_change_notify( int new_state )
-+{
-+}
-+
-+/* set feature stall executing, async */
-+void
-+ep2_stall( void )
-+{
-+ UDC_set( Ser0UDCCS2, UDCCS2_FST ); /* force stall at UDC */
-+}
-+
-+static void
-+ep2_start(void)
-+{
-+ if (!ep2_len)
-+ return;
-+
-+ ep2_curdmalen = tx_pktsize;
-+ if (ep2_curdmalen > ep2_remain)
-+ ep2_curdmalen = ep2_remain;
-+
-+ /* must do this _before_ queue buffer.. */
-+ UDC_flip( Ser0UDCCS2,UDCCS2_TPC ); /* stop NAKing IN tokens */
-+ UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
-+
-+ /* Remove if never seen...8Mar01ww */
-+ {
-+ int massive_attack = 20;
-+ while ( Ser0UDCIMP != ep2_curdmalen-1 && massive_attack-- ) {
-+ printk( "usbsnd: Oh no you don't! Let me spin..." );
-+ udelay( 500 );
-+ printk( "and try again...\n" );
-+ UDC_write( Ser0UDCIMP, ep2_curdmalen-1 );
-+ }
-+ if ( massive_attack != 20 ) {
-+ if ( Ser0UDCIMP != ep2_curdmalen-1 )
-+ printk( "usbsnd: Massive attack FAILED :-( %d\n",
-+ 20 - massive_attack );
-+ else
-+ printk( "usbsnd: Massive attack WORKED :-) %d\n",
-+ 20 - massive_attack );
-+ }
-+ }
-+ /* End remove if never seen... 8Mar01ww */
-+
-+ Ser0UDCAR = usbd_info.address; // fighting stupid silicon bug
-+ sa1100_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen);
-+}
-+
-+static void
-+ep2_done(int flag)
-+{
-+ int size = ep2_len - ep2_remain;
-+ if (ep2_len) {
-+ pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE);
-+ ep2_len = 0;
-+ if (ep2_callback)
-+ ep2_callback(flag, size);
-+ }
-+}
-+
-+int
-+ep2_init(int chn)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ dmachn_tx = chn;
-+ sa1100_dma_flush_all(dmachn_tx);
-+ ep2_done(-EAGAIN);
-+ return 0;
-+}
-+
-+void
-+ep2_reset(void)
-+{
-+ desc_t * pd = sa1100_usb_get_descriptor_ptr();
-+ tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize );
-+ UDC_clear(Ser0UDCCS2, UDCCS2_FST);
-+ sa1100_dma_flush_all(dmachn_tx);
-+ ep2_done(-EINTR);
-+}
-+
-+void
-+ep2_int_hndlr(int udcsr)
-+{
-+ int status = Ser0UDCCS2;
-+
-+ if (Ser0UDCAR != usbd_info.address) // check for stupid silicon bug.
-+ Ser0UDCAR = usbd_info.address;
-+
-+ UDC_flip(Ser0UDCCS2, UDCCS2_SST);
-+
-+ if (status & UDCCS2_TPC) {
-+ sa1100_dma_flush_all(dmachn_tx);
-+
-+ if (status & (UDCCS2_TPE | UDCCS2_TUR)) {
-+ printk("usb_send: transmit error %x\n", status);
-+ ep2_done(-EIO);
-+ } else {
-+#if 1 // 22Feb01ww/Oleg
-+ ep2_curdmapos += ep2_curdmalen;
-+ ep2_remain -= ep2_curdmalen;
-+#else
-+ ep2_curdmapos += Ser0UDCIMP + 1; // this is workaround
-+ ep2_remain -= Ser0UDCIMP + 1; // for case when setting of Ser0UDCIMP was failed
-+#endif
-+
-+ if (ep2_remain != 0) {
-+ ep2_start();
-+ } else {
-+ ep2_done(0);
-+ }
-+ }
-+ } else {
-+ printk("usb_send: Not TPC: UDCCS2 = %x\n", status);
-+ }
-+}
-+
-+int
-+sa1100_usb_send(char *buf, int len, usb_callback_t callback)
-+{
-+ int flags;
-+
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+
-+ if (ep2_len)
-+ return -EBUSY;
-+
-+ local_irq_save(flags);
-+ ep2_buf = buf;
-+ ep2_len = len;
-+ ep2_dma = pci_map_single(NULL, buf, len, PCI_DMA_TODEVICE);
-+ ep2_callback = callback;
-+ ep2_remain = len;
-+ ep2_curdmapos = ep2_dma;
-+ ep2_start();
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+
-+void
-+sa1100_usb_send_reset(void)
-+{
-+ ep2_reset();
-+}
-+
-+int sa1100_usb_xmitter_avail( void )
-+{
-+ if (usbd_info.state != USB_STATE_CONFIGURED)
-+ return -ENODEV;
-+ if (ep2_len)
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+
-+EXPORT_SYMBOL(sa1100_usb_xmitter_avail);
-+EXPORT_SYMBOL(sa1100_usb_send);
-+EXPORT_SYMBOL(sa1100_usb_send_reset);
---- linux-2.4.27/arch/arm/mm/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/Makefile
-@@ -39,6 +39,8 @@
- p-$(CONFIG_CPU_ARM925T) += proc-arm925.o
- p-$(CONFIG_CPU_ARM926T) += proc-arm926.o
- p-$(CONFIG_CPU_ARM1020) += proc-arm1020.o
-+p-$(CONFIG_CPU_ARM1020E) += proc-arm1020E.o
-+p-$(CONFIG_CPU_ARM1022) += proc-arm1022.o
- p-$(CONFIG_CPU_ARM1026) += proc-arm1026.o
- p-$(CONFIG_CPU_SA110) += proc-sa110.o
- p-$(CONFIG_CPU_SA1100) += proc-sa110.o
---- linux-2.4.27/arch/arm/mm/alignment.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/alignment.c
-@@ -11,7 +11,6 @@
- #include <linux/config.h>
- #include <linux/compiler.h>
- #include <linux/signal.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -19,7 +18,6 @@
- #include <linux/ptrace.h>
- #include <linux/mman.h>
- #include <linux/mm.h>
--#include <linux/interrupt.h>
- #include <linux/proc_fs.h>
- #include <linux/bitops.h>
- #include <linux/init.h>
-@@ -30,13 +28,11 @@
- #include <asm/pgtable.h>
- #include <asm/unaligned.h>
-
--extern void
--do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-- int error_code, struct pt_regs *regs);
-+#include "fault.h"
-
- /*
- * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
-- * /proc/sys/debug/alignment, modified and integrated into
-+ * /proc/cpu/alignment, modified and integrated into
- * Linux 2.1 by Russell King
- *
- * Speed optimisations and better fault handling by Russell King.
-@@ -130,31 +126,6 @@
- return count;
- }
-
--/*
-- * This needs to be done after sysctl_init, otherwise sys/ will be
-- * overwritten. Actually, this shouldn't be in sys/ at all since
-- * it isn't a sysctl, and it doesn't contain sysctl information.
-- * We now locate it in /proc/cpu/alignment instead.
-- */
--static int __init alignment_init(void)
--{
-- struct proc_dir_entry *res;
--
-- res = proc_mkdir("cpu", NULL);
-- if (!res)
-- return -ENOMEM;
--
-- res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
-- if (!res)
-- return -ENOMEM;
--
-- res->read_proc = proc_alignment_read;
-- res->write_proc = proc_alignment_write;
--
-- return 0;
--}
--
--__initcall(alignment_init);
- #endif /* CONFIG_PROC_FS */
-
- union offset_union {
-@@ -429,7 +400,7 @@
- * For alignment faults on the ARM922T/ARM920T the MMU makes
- * the FSR (and hence addr) equal to the updated base address
- * of the multiple access rather than the restored value.
-- * Switch this messsage off if we've got a ARM92[02], otherwise
-+ * Switch this message off if we've got a ARM92[02], otherwise
- * [ls]dm alignment faults are noisy!
- */
- #if !(defined CONFIG_CPU_ARM922T) && !(defined CONFIG_CPU_ARM920T)
-@@ -486,7 +457,8 @@
- return TYPE_ERROR;
- }
-
--int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
-+static int
-+do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- union offset_union offset;
- unsigned long instr, instrptr;
-@@ -541,7 +513,7 @@
- case SHIFT_RORRRX:
- if (shiftval == 0) {
- offset.un >>= 1;
-- if (regs->ARM_cpsr & CC_C_BIT)
-+ if (regs->ARM_cpsr & PSR_C_BIT)
- offset.un |= 1 << 31;
- } else
- offset.un = offset.un >> shiftval |
-@@ -577,7 +549,7 @@
- /*
- * We got a fault - fix it up, or die.
- */
-- do_bad_area(current, current->mm, addr, error_code, regs);
-+ do_bad_area(current, current->mm, addr, fsr, regs);
- return 0;
-
- bad:
-@@ -594,8 +566,8 @@
-
- if (ai_usermode & 1)
- printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%08lx "
-- "Address=0x%08lx Code 0x%02x\n", current->comm,
-- current->pid, instrptr, instr, addr, error_code);
-+ "Address=0x%08lx FSR 0x%03x\n", current->comm,
-+ current->pid, instrptr, instr, addr, fsr);
-
- if (ai_usermode & 2)
- goto fixup;
-@@ -607,3 +579,34 @@
-
- return 0;
- }
-+
-+/*
-+ * This needs to be done after sysctl_init, otherwise sys/ will be
-+ * overwritten. Actually, this shouldn't be in sys/ at all since
-+ * it isn't a sysctl, and it doesn't contain sysctl information.
-+ * We now locate it in /proc/cpu/alignment instead.
-+ */
-+static int __init alignment_init(void)
-+{
-+#ifdef CONFIG_PROC_FS
-+ struct proc_dir_entry *res;
-+
-+ res = proc_mkdir("cpu", NULL);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
-+ if (!res)
-+ return -ENOMEM;
-+
-+ res->read_proc = proc_alignment_read;
-+ res->write_proc = proc_alignment_write;
-+#endif
-+
-+ hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
-+ hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
-+
-+ return 0;
-+}
-+
-+__initcall(alignment_init);
---- linux-2.4.27/arch/arm/mm/fault-armv.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/fault-armv.c
-@@ -2,116 +2,90 @@
- * linux/arch/arm/mm/fault-armv.c
- *
- * Copyright (C) 1995 Linus Torvalds
-- * Modifications for ARM processor (c) 1995-2001 Russell King
-+ * Modifications for ARM processor (c) 1995-2003 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
--#include <linux/config.h>
--#include <linux/signal.h>
- #include <linux/sched.h>
- #include <linux/kernel.h>
--#include <linux/errno.h>
--#include <linux/string.h>
- #include <linux/types.h>
- #include <linux/ptrace.h>
--#include <linux/mman.h>
- #include <linux/mm.h>
--#include <linux/interrupt.h>
--#include <linux/proc_fs.h>
- #include <linux/bitops.h>
- #include <linux/init.h>
-
--#include <asm/system.h>
--#include <asm/uaccess.h>
- #include <asm/pgalloc.h>
- #include <asm/pgtable.h>
-+#include <asm/io.h>
-
--extern void show_pte(struct mm_struct *mm, unsigned long addr);
--extern int do_page_fault(unsigned long addr, int error_code,
-- struct pt_regs *regs);
--extern int do_translation_fault(unsigned long addr, int error_code,
-- struct pt_regs *regs);
--extern void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-- unsigned long addr, int error_code,
-- struct pt_regs *regs);
--
--#ifdef CONFIG_ALIGNMENT_TRAP
--extern int do_alignment(unsigned long addr, int error_code, struct pt_regs *regs);
--#else
--#define do_alignment do_bad
--#endif
--
-+#include "fault.h"
-
- /*
- * Some section permission faults need to be handled gracefully.
- * They can happen due to a __{get,put}_user during an oops.
- */
- static int
--do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- struct task_struct *tsk = current;
-- do_bad_area(tsk, tsk->active_mm, addr, error_code, regs);
-+ do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
- return 0;
- }
-
- /*
-- * Hook for things that need to trap external faults. Note that
-- * we don't guarantee that this will be the final version of the
-- * interface.
-- */
--int (*external_fault)(unsigned long addr, struct pt_regs *regs);
--
--static int
--do_external_fault(unsigned long addr, int error_code, struct pt_regs *regs)
--{
-- if (external_fault)
-- return external_fault(addr, regs);
-- return 1;
--}
--
--/*
- * This abort handler always returns "fault".
- */
- static int
--do_bad(unsigned long addr, int error_code, struct pt_regs *regs)
-+do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- return 1;
- }
-
--static const struct fsr_info {
-- int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
-+static struct fsr_info {
-+ int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
- int sig;
- const char *name;
- } fsr_info[] = {
- { do_bad, SIGSEGV, "vector exception" },
-- { do_alignment, SIGILL, "alignment exception" },
-+ { do_bad, SIGILL, "alignment exception" },
- { do_bad, SIGKILL, "terminal exception" },
-- { do_alignment, SIGILL, "alignment exception" },
-- { do_external_fault, SIGBUS, "external abort on linefetch" },
-+ { do_bad, SIGILL, "alignment exception" },
-+ { do_bad, SIGBUS, "external abort on linefetch" },
- { do_translation_fault, SIGSEGV, "section translation fault" },
-- { do_external_fault, SIGBUS, "external abort on linefetch" },
-+ { do_bad, SIGBUS, "external abort on linefetch" },
- { do_page_fault, SIGSEGV, "page translation fault" },
-- { do_external_fault, SIGBUS, "external abort on non-linefetch" },
-+ { do_bad, SIGBUS, "external abort on non-linefetch" },
- { do_bad, SIGSEGV, "section domain fault" },
-- { do_external_fault, SIGBUS, "external abort on non-linefetch" },
-+ { do_bad, SIGBUS, "external abort on non-linefetch" },
- { do_bad, SIGSEGV, "page domain fault" },
- { do_bad, SIGBUS, "external abort on translation" },
- { do_sect_fault, SIGSEGV, "section permission fault" },
- { do_bad, SIGBUS, "external abort on translation" },
-- { do_page_fault, SIGSEGV, "page permission fault" }
-+ { do_page_fault, SIGSEGV, "page permission fault" },
- };
-
-+void __init
-+hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
-+ int sig, const char *name)
-+{
-+ if (nr >= 0 && nr < ARRAY_SIZE(fsr_info)) {
-+ fsr_info[nr].fn = fn;
-+ fsr_info[nr].sig = sig;
-+ fsr_info[nr].name = name;
-+ }
-+}
-+
- /*
- * Dispatch a data abort to the relevant handler.
- */
- asmlinkage void
--do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
-+do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- const struct fsr_info *inf = fsr_info + (fsr & 15);
-
-- if (!inf->fn(addr, error_code, regs))
-+ if (!inf->fn(addr, fsr, regs))
- return;
-
- printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
-@@ -127,25 +101,28 @@
- do_translation_fault(addr, 0, regs);
- }
-
-+static unsigned long shared_pte_mask = L_PTE_CACHEABLE;
-+
- /*
- * We take the easy way out of this problem - we make the
- * PTE uncacheable. However, we leave the write buffer on.
- */
--static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
-+static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
- {
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte, entry;
-+ int ret = 0;
-
- pgd = pgd_offset(vma->vm_mm, address);
- if (pgd_none(*pgd))
-- return;
-+ goto no_pgd;
- if (pgd_bad(*pgd))
- goto bad_pgd;
-
- pmd = pmd_offset(pgd, address);
- if (pmd_none(*pmd))
-- return;
-+ goto no_pmd;
- if (pmd_bad(*pmd))
- goto bad_pmd;
-
-@@ -156,33 +133,38 @@
- * If this page isn't present, or is already setup to
- * fault (ie, is old), we can safely ignore any issues.
- */
-- if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) {
-+ if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
- flush_cache_page(vma, address);
-- pte_val(entry) &= ~L_PTE_CACHEABLE;
-+ pte_val(entry) &= ~shared_pte_mask;
- set_pte(pte, entry);
- flush_tlb_page(vma, address);
-+ ret = 1;
- }
-- return;
-+ return ret;
-
- bad_pgd:
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
-- return;
-+no_pgd:
-+ return 0;
-
- bad_pmd:
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
-- return;
-+no_pmd:
-+ return 0;
- }
-
- static void
--make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page)
-+make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
- {
- struct vm_area_struct *mpnt;
- struct mm_struct *mm = vma->vm_mm;
-- unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
-+ unsigned long pgoff;
- int aliases = 0;
-
-+ pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
-+
- /*
- * If we have any shared mappings that are in the same mm
- * space, then we need to handle them specially to maintain
-@@ -194,7 +176,7 @@
-
- /*
- * If this VMA is not in our MM, we can ignore it.
-- * Note that we intentionally don't mask out the VMA
-+ * Note that we intentionally mask out the VMA
- * that we are fixing up.
- */
- if (mpnt->vm_mm != mm || mpnt == vma)
-@@ -210,14 +192,17 @@
- if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
- continue;
-
-+ off = mpnt->vm_start + (off << PAGE_SHIFT);
-+
- /*
- * Ok, it is within mpnt. Fix it up.
- */
-- adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
-- aliases ++;
-+ aliases += adjust_pte(mpnt, off);
- }
- if (aliases)
- adjust_pte(vma, addr);
-+ else if (dirty)
-+ flush_cache_page(vma, addr);
- }
-
- /*
-@@ -242,11 +227,85 @@
- return;
- page = pfn_to_page(pfn);
- if (page->mapping) {
-- if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
-+ int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
-+
-+ if (dirty) {
- unsigned long kvirt = (unsigned long)page_address(page);
- cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
- }
-
-- make_coherent(vma, addr, page);
-+ make_coherent(vma, addr, page, dirty);
-+ }
-+}
-+
-+/*
-+ * Check whether the write buffer has physical address aliasing
-+ * issues. If it has, we need to avoid them for the case where
-+ * we have several shared mappings of the same object in user
-+ * space.
-+ */
-+static int __init check_writebuffer(unsigned long *p1, unsigned long *p2)
-+{
-+ register unsigned long zero = 0, one = 1, val;
-+
-+ mb();
-+ *p1 = one;
-+ mb();
-+ *p2 = zero;
-+ mb();
-+ val = *p1;
-+ mb();
-+ return val != zero;
-+}
-+
-+static inline void *map_page(struct page *page)
-+{
-+ void *map;
-+
-+ map = __ioremap(page_to_phys(page), PAGE_SIZE, L_PTE_BUFFERABLE);
-+ if (map)
-+ get_page(page);
-+ return map;
-+}
-+
-+static inline void unmap_page(void *map)
-+{
-+ iounmap(map);
-+}
-+
-+void __init check_writebuffer_bugs(void)
-+{
-+ struct page *page;
-+ const char *reason;
-+ unsigned long v = 1;
-+
-+ printk(KERN_INFO "CPU: Testing write buffer: ");
-+
-+ page = alloc_page(GFP_KERNEL);
-+ if (page) {
-+ unsigned long *p1, *p2;
-+
-+ p1 = map_page(page);
-+ p2 = map_page(page);
-+
-+ if (p1 && p2) {
-+ v = check_writebuffer(p1, p2);
-+ reason = "enabling work-around";
-+ } else {
-+ reason = "unable to map memory\n";
-+ }
-+
-+ unmap_page(p1);
-+ unmap_page(p2);
-+ put_page(page);
-+ } else {
-+ reason = "unable to grab page\n";
-+ }
-+
-+ if (v) {
-+ printk("FAIL - %s\n", reason);
-+ shared_pte_mask |= L_PTE_BUFFERABLE;
-+ } else {
-+ printk("pass\n");
- }
- }
---- linux-2.4.27/arch/arm/mm/fault-common.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/fault-common.c
-@@ -11,21 +11,17 @@
- #include <linux/config.h>
- #include <linux/signal.h>
- #include <linux/sched.h>
--#include <linux/kernel.h>
--#include <linux/errno.h>
- #include <linux/string.h>
--#include <linux/types.h>
- #include <linux/ptrace.h>
--#include <linux/mman.h>
- #include <linux/mm.h>
- #include <linux/interrupt.h>
--#include <linux/proc_fs.h>
- #include <linux/init.h>
-
- #include <asm/system.h>
--#include <asm/uaccess.h>
- #include <asm/pgtable.h>
--#include <asm/unaligned.h>
-+#include <asm/uaccess.h>
-+
-+#include "fault.h"
-
- #ifdef CONFIG_CPU_26
- #define FAULT_CODE_WRITE 0x02
-@@ -34,13 +30,11 @@
- #define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
- #else
- /*
-- * On 32-bit processors, we define "mode" to be zero when reading,
-- * non-zero when writing. This now ties up nicely with the polarity
-- * of the 26-bit machines, and also means that we avoid the horrible
-- * gcc code for "int val = !other_val;".
-+ * "code" is actually the FSR register. Bit 11 set means the
-+ * instruction was performing a write.
- */
--#define DO_COW(m) (m)
--#define READ_FAULT(m) (!(m))
-+#define DO_COW(code) ((code) & (1 << 11))
-+#define READ_FAULT(code) (!DO_COW(code))
- #endif
-
- /*
-@@ -54,16 +48,17 @@
- if (!mm)
- mm = &init_mm;
-
-- printk(KERN_ALERT "mm = %p pgd = %p\n", mm, mm->pgd);
--
- fs = get_fs();
- set_fs(get_ds());
-+
- do {
-- pgd_t pg, *pgd = pgd_offset(mm, addr);
-+ pgd_t pg, *pgd;
- pmd_t pm, *pmd;
- pte_t pt, *pte;
-
-- printk(KERN_ALERT "*pgd = ");
-+ printk(KERN_ALERT "pgd = %p\n", mm->pgd);
-+ pgd = pgd_offset(mm, addr);
-+ printk(KERN_ALERT "[%08lx] *pgd=", addr);
-
- if (__get_user(pgd_val(pg), (unsigned long *)pgd)) {
- printk("(faulted)");
-@@ -122,7 +117,7 @@
- * Oops. The kernel tried to access some page that wasn't present.
- */
- static void
--__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
-+__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
- {
- unsigned long fixup;
-@@ -148,7 +143,7 @@
- "paging request", addr);
-
- show_pte(mm, addr);
-- die("Oops", regs, error_code);
-+ die("Oops", regs, fsr);
- do_exit(SIGKILL);
- }
-
-@@ -157,20 +152,20 @@
- * User mode accesses just cause a SIGSEGV
- */
- static void
--__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
-- int code, struct pt_regs *regs)
-+__do_user_fault(struct task_struct *tsk, unsigned long addr,
-+ unsigned int fsr, int code, struct pt_regs *regs)
- {
- struct siginfo si;
-
- #ifdef CONFIG_DEBUG_USER
- printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
- "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
-- tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
-+ tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, fsr);
- show_regs(regs);
- #endif
-
- tsk->thread.address = addr;
-- tsk->thread.error_code = error_code;
-+ tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- si.si_signo = SIGSEGV;
- si.si_errno = 0;
-@@ -181,20 +176,20 @@
-
- void
- do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
-- int error_code, struct pt_regs *regs)
-+ unsigned int fsr, struct pt_regs *regs)
- {
- /*
- * If we are in kernel mode at this point, we
- * have no context to handle this fault with.
- */
- if (user_mode(regs))
-- __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
-+ __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
- else
-- __do_kernel_fault(mm, addr, error_code, regs);
-+ __do_kernel_fault(mm, addr, fsr, regs);
- }
-
- static int
--__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
-+__do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
- struct task_struct *tsk)
- {
- struct vm_area_struct *vma;
-@@ -212,7 +207,7 @@
- * memory access, so we can handle it.
- */
- good_area:
-- if (READ_FAULT(error_code)) /* read? */
-+ if (READ_FAULT(fsr)) /* read? */
- mask = VM_READ|VM_EXEC;
- else
- mask = VM_WRITE;
-@@ -227,7 +222,7 @@
- * than endlessly redo the fault.
- */
- survive:
-- fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
-+ fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));
-
- /*
- * Handle the "normal" cases first - successful and sigbus
-@@ -260,7 +255,7 @@
- return fault;
- }
-
--int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
- {
- struct task_struct *tsk;
- struct mm_struct *mm;
-@@ -277,7 +272,7 @@
- goto no_context;
-
- down_read(&mm->mmap_sem);
-- fault = __do_page_fault(mm, addr, error_code, tsk);
-+ fault = __do_page_fault(mm, addr, fsr, tsk);
- up_read(&mm->mmap_sem);
-
- /*
-@@ -308,7 +303,7 @@
- printk("VM: killing process %s\n", tsk->comm);
- do_exit(SIGKILL);
- } else
-- __do_user_fault(tsk, addr, error_code, fault == -1 ?
-+ __do_user_fault(tsk, addr, fsr, fault == -1 ?
- SEGV_ACCERR : SEGV_MAPERR, regs);
- return 0;
-
-@@ -323,7 +318,7 @@
- * or user mode.
- */
- tsk->thread.address = addr;
-- tsk->thread.error_code = error_code;
-+ tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- force_sig(SIGBUS, tsk);
- #ifdef CONFIG_DEBUG_USER
-@@ -336,7 +331,7 @@
- return 0;
-
- no_context:
-- __do_kernel_fault(mm, addr, error_code, regs);
-+ __do_kernel_fault(mm, addr, fsr, regs);
- return 0;
- }
-
-@@ -357,21 +352,23 @@
- * interrupt or a critical region, and should only copy the information
- * from the master page table, nothing more.
- */
--int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
-+int do_translation_fault(unsigned long addr, unsigned int fsr,
-+ struct pt_regs *regs)
- {
- struct task_struct *tsk;
-- struct mm_struct *mm;
- int offset;
- pgd_t *pgd, *pgd_k;
- pmd_t *pmd, *pmd_k;
-
- if (addr < TASK_SIZE)
-- return do_page_fault(addr, error_code, regs);
-+ return do_page_fault(addr, fsr, regs);
-
- offset = __pgd_offset(addr);
-
- /*
- * FIXME: CP15 C1 is write only on ARMv3 architectures.
-+ * You really need to read the value in the page table
-+ * register, not a copy.
- */
- pgd = cpu_get_pgd() + offset;
- pgd_k = init_mm.pgd + offset;
-@@ -395,8 +392,7 @@
-
- bad_area:
- tsk = current;
-- mm = tsk->active_mm;
-
-- do_bad_area(tsk, mm, addr, error_code, regs);
-+ do_bad_area(tsk, tsk->active_mm, addr, fsr, regs);
- return 0;
- }
---- /dev/null
-+++ linux-2.4.27/arch/arm/mm/fault.h
-@@ -0,0 +1,9 @@
-+void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
-+ unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
-+void show_pte(struct mm_struct *mm, unsigned long addr);
-+
-+int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
-+int do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
-+
---- linux-2.4.27/arch/arm/mm/init.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/init.c
-@@ -9,7 +9,6 @@
- */
- #include <linux/config.h>
- #include <linux/signal.h>
--#include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -18,7 +17,6 @@
- #include <linux/mman.h>
- #include <linux/mm.h>
- #include <linux/swap.h>
--#include <linux/swapctl.h>
- #include <linux/smp.h>
- #include <linux/init.h>
- #include <linux/bootmem.h>
---- linux-2.4.27/arch/arm/mm/ioremap.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/ioremap.c
-@@ -144,7 +144,7 @@
- */
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
-- size = PAGE_ALIGN(last_addr) - phys_addr;
-+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
- /*
- * Ok, go for it..
---- linux-2.4.27/arch/arm/mm/mm-armv.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/mm-armv.c
-@@ -9,7 +9,6 @@
- *
- * Page table sludge for ARM v3 and v4 processor architectures.
- */
--#include <linux/sched.h>
- #include <linux/mm.h>
- #include <linux/init.h>
- #include <linux/bootmem.h>
-@@ -390,6 +389,9 @@
- init_maps->bufferable = 0;
-
- create_mapping(init_maps);
-+
-+ flush_cache_all();
-+ flush_tlb_all();
- }
-
- /*
---- linux-2.4.27/arch/arm/mm/proc-arm1020.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm1020.S
-@@ -65,18 +65,21 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm1020_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -170,10 +173,10 @@
- #endif
- subs r3, r3, #1
- cmp r3, #0
-- bge 2b @ entries 3F to 0
-+ bhs 2b @ entries 3F to 0
- subs r1, r1, #1
- cmp r1, #0
-- bge 1b @ segments 7 to 0
-+ bhs 1b @ segments 7 to 0
- #endif
-
- #ifndef CONFIG_CPU_ICACHE_DISABLE
-@@ -201,7 +204,7 @@
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm1020_cache_clean_invalidate_all_r2
-+ bhi cpu_arm1020_cache_clean_invalidate_all_r2
- mcr p15, 0, r3, c7, c10, 4
- #ifndef CONFIG_CPU_DCACHE_DISABLE
- 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-@@ -214,7 +217,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #endif
-
- #ifndef CONFIG_CPU_ICACHE_DISABLE
-@@ -302,7 +305,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #else
- /* D cache off, but still drain the write buffer */
- mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-@@ -328,7 +331,7 @@
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm1020_cache_clean_invalidate_all_r2
-+ bhi cpu_arm1020_cache_clean_invalidate_all_r2
- mcr p15, 0, r3, c7, c10, 4
- #ifndef CONFIG_CPU_DCACHE_DISABLE
- 1: mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-@@ -341,7 +344,7 @@
- #endif
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- #endif
-
- #ifndef CONFIG_CPU_BPREDICT_DISABLE
-@@ -488,7 +491,7 @@
- mov r0, r0
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -541,10 +544,10 @@
- #endif
- subs r3, r3, #1
- cmp r3, #0
-- bge 2b @ entries 3F to 0
-+ bhs 2b @ entries 3F to 0
- subs r1, r1, #1
- cmp r1, #0
-- bge 1b @ segments 15 to 0
-+ bhs 1b @ segments 15 to 0
-
- #endif
- mov r1, #0
-@@ -603,7 +606,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-@@ -740,12 +743,12 @@
-
- .type cpu_arch_name, #object
- cpu_arch_name:
-- .asciz "armv4"
-+ .asciz "armv5t"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
- cpu_elf_name:
-- .asciz "v4"
-+ .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
- .align
-
-@@ -753,9 +756,9 @@
-
- .type __arm1020_proc_info,#object
- __arm1020_proc_info:
-- .long 0x4100a200
-- .long 0xff00fff0
-- .long 0x00000c02 @ mmuflags
-+ .long 0x4104a200 @ ARM 1020T (Architecture v5T)
-+ .long 0xff0ffff0
-+ .long 0x00000c0e @ mmuflags
- b __arm1020_setup
- .long cpu_arch_name
- .long cpu_elf_name
---- /dev/null
-+++ linux-2.4.27/arch/arm/mm/proc-arm1020E.S
-@@ -0,0 +1,718 @@
-+/*
-+ * linux/arch/arm/mm/proc-arm1020E.S: MMU functions for ARM1020E
-+ *
-+ * Copyright (C) 2000 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *
-+ * These are the low level assembler for performing cache and TLB
-+ * functions on the arm1020E.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/config.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * This is the maximum size of an area which will be invalidated
-+ * using the single invalidate entry instructions. Anything larger
-+ * than this, and we go for the whole cache.
-+ *
-+ * This value should be chosen such that we choose the cheapest
-+ * alternative.
-+ */
-+#define MAX_AREA_SIZE 32768
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define DCACHELINESIZE 32
-+#define ICACHELINESIZE 32
-+
-+/*
-+ * and the page size
-+ */
-+#define LOG2PAGESIZE 12 /* == 4096 Bytes */
-+#define PAGESIZE (1 << LOG2PAGESIZE)
-+
-+/*
-+ * create some useful conditional macro definitions
-+ * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
-+ */
-+#ifdef CONFIG_CPU_DCACHE_DISABLE
-+ #undef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #undef CONFIG_CPU_DCACHE_ENABLE
-+#else
-+ #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #else
-+ #define CONFIG_CPU_DCACHE_WRITEBACK
-+ #endif
-+ #define CONFIG_CPU_DCACHE_ENABLE
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_DISABLE
-+ #undef CONFIG_CPU_ICACHE_ENABLE
-+#else
-+ #define CONFIG_CPU_ICACHE_ENABLE
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_arm1020E_data_abort()
-+ *
-+ * obtain information about current aborted instruction
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = cpsr
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR
-+ * r3 = corrupted
-+ * r4 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_check_bugs()
-+ */
-+ENTRY(cpu_arm1020E_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_proc_init()
-+ */
-+ENTRY(cpu_arm1020E_proc_init)
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_proc_fin()
-+ */
-+ENTRY(cpu_arm1020E_proc_fin)
-+ stmfd sp!, {lr}
-+ mov ip, #F_BIT | I_BIT | SVC_MODE
-+ msr cpsr_c, ip
-+ bl cpu_arm1020E_cache_clean_invalidate_all
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1000 @ ...i............
-+ bic r0, r0, #0x000e @ ............wca.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1020E_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_reset)
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
-+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
-+ bic ip, ip, #0x000f @ ............wcam
-+ bic ip, ip, #0x1100 @ ...i...s........
-+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
-+ mov pc, r0
-+
-+/*
-+ * cpu_arm1020E_do_idle()
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_do_idle)
-+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+
-+/*
-+ * cpu_arm1020E_cache_clean_invalidate_all()
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. we should preserve r0 and ip at all times
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_arm1020E_cache_clean_invalidate_all_r2:
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r1, #0x0F << 5 @ 16 segments
-+1: orr r3, r1, #63 << 26 @ 64 entries
-+2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
-+ subs r3, r3, #1 << 26
-+ bcs 2b
-+ subs r1, r1, #1 << 5
-+ bcs 1b @ segments 15 to 0
-+#endif
-+
-+ mov r1, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
-+#endif
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_cache_clean_invalidate_range)
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - must include end point (r1)!
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_flush_ram_page(page)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * page: page to clean and invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_flush_ram_page)
-+ mov r1, #PAGESIZE
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1020E_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that we must clean the D-cached entries
-+ * around the boundaries if the start and/or end address are not cache
-+ * aligned.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_invalidate_range)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ bic r0, r0, #DCACHELINESIZE - 1
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ tst r0, #DCACHELINESIZE - 1
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
-+ tst r1, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
-+#endif
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+
-+ /* Even if the D cache is off still drain the write buffer */
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_range)
-+
-+ mov r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+#endif
-+
-+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * page: virtual address of page to clean from dcache
-+ *
-+ * Note:
-+ * we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_page)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ mov r1, #PAGESIZE
-+1:
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_dcache_clean_entry)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1020E_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * This is a little misleading, it is not intended to clean out
-+ * the i-cache but to make sure that any data written to the
-+ * range is made consistent. This means that when we execute code
-+ * in that region, everything works as we expect.
-+ *
-+ * This generally means writing back data in the Dcache and
-+ * write buffer and invalidating the Icache over that region
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
-+ * loop twice, once for i-cache, once for d-cache)
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_icache_invalidate_range)
-+ bic r0, r0, #ICACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ movhs r2, #1
-+ bhs cpu_arm1020E_cache_clean_invalidate_all_r2
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - includes r1 entry
-+
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+ENTRY(cpu_arm1020E_icache_invalidate_page)
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ add r1, r0, #PAGESIZE
-+ b cpu_arm1020E_icache_invalidate_range
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_all)
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_range)
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE
-+ bhs cpu_arm1020E_tlb_invalidate_all
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r3, #PAGESIZE
-+ sub r3, r3, #1
-+ bic r0, r0, r3
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ bls 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_tlb_invalidate_page)
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ mov pc, lr
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_arm1020E_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pgd)
-+ stmfd sp!, {lr}
-+ bl cpu_arm1020E_cache_clean_invalidate_all @ preserves r0
-+ mov r1, #0
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1020E_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pmd)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r2, r1, #0x0a @ C & Section
-+ tst r2, #0x0b
-+ biceq r1, r1, #4 @ clear bufferable bit
-+#endif
-+ str r1, [r0]
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1020E_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ */
-+ .align 5
-+ENTRY(cpu_arm1020E_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
-+
-+ bic r2, r1, #0xff0
-+ bic r2, r2, #3
-+ orr r2, r2, #HPTE_TYPE_SMALL
-+
-+ tst r1, #LPTE_USER @ User?
-+ orrne r2, r2, #HPTE_AP_READ
-+
-+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #HPTE_AP_WRITE
-+
-+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
-+ movne r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r3, r2, #0x0a @ C and Small Page?
-+ tst r3, #0x0b @ if so..
-+ biceq r2, r2, #0x04 @ clear the bufferable bit
-+#endif
-+ str r2, [r0] @ hardware version
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+
-+cpu_manu_name:
-+ .asciz "ARM"
-+ENTRY(cpu_arm1020E_name)
-+ .ascii "Arm1020E"
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ .ascii "i"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "d"
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ .ascii "(wt)"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "(wb)"
-+#endif
-+#endif
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ .ascii "B"
-+#endif
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ .ascii "RR"
-+#endif
-+ .ascii "\0"
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__arm1020E_setup:
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
-+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+
-+ mrc p15, 0, r0, c1, c0, 0 @ Read current control register
-+/*
-+ * The only thing worth keeping from the initial control register is the endian bit
-+ */
-+
-+ and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
-+ orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
-+/*
-+ * Turn on what we want.
-+ */
-+ orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
-+ orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
-+ orr r0, r0, #0x2000 @ ..V............. Enable high vectors
-+
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
-+#endif
-+
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
-+#endif
-+
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ orr r0, r0, #0x0004 @ .............C.. Enable D cache
-+#endif
-+#ifndef CONFIG_CPU_WB_DISABLE
-+ orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ orr r0, r0, #0x1000 @ ...I............ Enable I Cache
-+#endif
-+
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+ .type arm1020E_processor_functions, #object
-+arm1020E_processor_functions:
-+ .word cpu_arm1020E_data_abort
-+ .word cpu_arm1020E_check_bugs
-+ .word cpu_arm1020E_proc_init
-+ .word cpu_arm1020E_proc_fin
-+ .word cpu_arm1020E_reset
-+ .word cpu_arm1020E_do_idle
-+
-+ /* cache */
-+ .word cpu_arm1020E_cache_clean_invalidate_all
-+ .word cpu_arm1020E_cache_clean_invalidate_range
-+ .word cpu_arm1020E_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_arm1020E_dcache_invalidate_range
-+ .word cpu_arm1020E_dcache_clean_range
-+ .word cpu_arm1020E_dcache_clean_page
-+ .word cpu_arm1020E_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_arm1020E_icache_invalidate_range
-+ .word cpu_arm1020E_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_arm1020E_tlb_invalidate_all
-+ .word cpu_arm1020E_tlb_invalidate_range
-+ .word cpu_arm1020E_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_arm1020E_set_pgd
-+ .word cpu_arm1020E_set_pmd
-+ .word cpu_arm1020E_set_pte
-+ .size arm1020E_processor_functions, . - arm1020E_processor_functions
-+
-+ .type cpu_arm1020E_info, #object
-+cpu_arm1020E_info:
-+ .long cpu_manu_name
-+ .long cpu_arm1020E_name
-+ .size cpu_arm1020E_info, . - cpu_arm1020E_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5te"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __arm1020E_proc_info,#object
-+__arm1020E_proc_info:
-+ .long 0x4105a200 @ ARM 1020E (Architecture v5TE)
-+ .long 0xff0ffff0
-+ .long 0x00000c1e @ mmuflags
-+ b __arm1020E_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-+ .long cpu_arm1020E_info
-+ .long arm1020E_processor_functions
-+ .size __arm1020E_proc_info, . - __arm1020E_proc_info
-+
---- /dev/null
-+++ linux-2.4.27/arch/arm/mm/proc-arm1022.S
-@@ -0,0 +1,716 @@
-+/*
-+ * linux/arch/arm/mm/proc-arm1022.S: MMU functions for ARM1022E
-+ *
-+ * Copyright (C) 2000 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *
-+ * These are the low level assembler for performing cache and TLB
-+ * functions on the arm1022E.
-+ */
-+#include <linux/linkage.h>
-+#include <linux/config.h>
-+#include <asm/assembler.h>
-+#include <asm/constants.h>
-+#include <asm/procinfo.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * This is the maximum size of an area which will be invalidated
-+ * using the single invalidate entry instructions. Anything larger
-+ * than this, and we go for the whole cache.
-+ *
-+ * This value should be chosen such that we choose the cheapest
-+ * alternative.
-+ */
-+#define MAX_AREA_SIZE 16384
-+
-+/*
-+ * the cache line size of the I and D cache
-+ */
-+#define DCACHELINESIZE 32
-+#define ICACHELINESIZE 32
-+
-+/*
-+ * and the page size
-+ */
-+#define LOG2PAGESIZE 12 /* == 4096 Bytes */
-+#define PAGESIZE (1 << LOG2PAGESIZE)
-+
-+/*
-+ * create some useful conditional macro definitions
-+ * we often need to know if we are ((not dcache disable) and writethrough) or ((not dcache disable) and writeback)
-+ */
-+#ifdef CONFIG_CPU_DCACHE_DISABLE
-+ #undef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #undef CONFIG_CPU_DCACHE_ENABLE
-+#else
-+ #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ #undef CONFIG_CPU_DCACHE_WRITEBACK
-+ #else
-+ #define CONFIG_CPU_DCACHE_WRITEBACK
-+ #endif
-+ #define CONFIG_CPU_DCACHE_ENABLE
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_DISABLE
-+ #undef CONFIG_CPU_ICACHE_ENABLE
-+#else
-+ #define CONFIG_CPU_ICACHE_ENABLE
-+#endif
-+
-+ .text
-+
-+/*
-+ * cpu_arm1022_data_abort()
-+ *
-+ * obtain information about current aborted instruction
-+ * Note: we read user space. This means we might cause a data
-+ * abort here if the I-TLB and D-TLB aren't seeing the same
-+ * picture. Unfortunately, this does happen. We live with it.
-+ *
-+ * r2 = address of aborted instruction
-+ * r3 = cpsr
-+ *
-+ * Returns:
-+ * r0 = address of abort
-+ * r1 = FSR
-+ * r3 = corrupted
-+ * r4 = corrupted
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_check_bugs()
-+ */
-+ENTRY(cpu_arm1022_check_bugs)
-+ mrs ip, cpsr
-+ bic ip, ip, #F_BIT
-+ msr cpsr, ip
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_proc_init()
-+ */
-+ENTRY(cpu_arm1022_proc_init)
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_proc_fin()
-+ */
-+ENTRY(cpu_arm1022_proc_fin)
-+ stmfd sp!, {lr}
-+ mov ip, #F_BIT | I_BIT | SVC_MODE
-+ msr cpsr_c, ip
-+ bl cpu_arm1022_cache_clean_invalidate_all
-+ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
-+ bic r0, r0, #0x1000 @ ...i............
-+ bic r0, r0, #0x000e @ ............wca.
-+ mcr p15, 0, r0, c1, c0, 0 @ disable caches
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1022_reset(loc)
-+ *
-+ * Perform a soft reset of the system. Put the CPU into the
-+ * same state as it would be if it had been reset, and branch
-+ * to what would be the reset vector.
-+ *
-+ * loc: location to jump to for soft reset
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_reset)
-+ mov ip, #0
-+ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
-+ mcr p15, 0, ip, c7, c10, 4 @ drain WB
-+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
-+ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
-+ bic ip, ip, #0x000f @ ............wcam
-+ bic ip, ip, #0x1100 @ ...i...s........
-+ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
-+ mov pc, r0
-+
-+/*
-+ * cpu_arm1022_do_idle()
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_do_idle)
-+ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
-+ mov pc, lr
-+
-+/* ================================= CACHE ================================ */
-+
-+
-+/*
-+ * cpu_arm1022_cache_clean_invalidate_all()
-+ *
-+ * clean and invalidate all cache lines
-+ *
-+ * Note:
-+ * 1. we should preserve r0 and ip at all times
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_cache_clean_invalidate_all)
-+ mov r2, #1
-+cpu_arm1022_cache_clean_invalidate_all_r2:
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r1, #7 << 5 @ 8 segments
-+1: orr r3, r1, #63 << 26 @ 64 entries
-+2: mcr p15, 0, r3, c7, c14, 2 @ clean and invalidate D index
-+ subs r3, r3, #1 << 26
-+ bcs 2b
-+ subs r1, r1, #1 << 5
-+ bcs 1b @ segments 7 to 0
-+#endif
-+
-+ mov r1, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r1, c7, c6, 0 @ invalidate D cache
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r1, c7, c5, 0 @ invalidate I cache
-+#endif
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_cache_clean_invalidate_range(start, end, flags)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * start: Area start address
-+ * end: Area end address
-+ * flags: nonzero for I cache as well
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_cache_clean_invalidate_range)
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ teq r2, #0
-+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - must include end point (r1)!
-+
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_flush_ram_page(page)
-+ *
-+ * clean and invalidate all cache lines associated with this area of memory
-+ *
-+ * page: page to clean and invalidate
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_flush_ram_page)
-+ mov r1, #PAGESIZE
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ D-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1022_dcache_invalidate_range(start, end)
-+ *
-+ * throw away all D-cached data in specified region without an obligation
-+ * to write them back. Note however that we must clean the D-cached entries
-+ * around the boundaries if the start and/or end address are not cache
-+ * aligned.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_invalidate_range)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ bic r0, r0, #DCACHELINESIZE - 1
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ tst r0, #DCACHELINESIZE - 1
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r0, c7, c10, 1 @ clean D entry at start
-+ tst r1, #DCACHELINESIZE - 1
-+ mcrne p15, 0, r1, c7, c10, 1 @ clean D entry at end
-+#endif
-+
-+1:
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+
-+ /* Even if the D cache is off still drain the write buffer */
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_range(start, end)
-+ *
-+ * For the specified virtual address range, ensure that all caches contain
-+ * clean data, such that peripheral accesses to the physical RAM fetch
-+ * correct data.
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_range)
-+
-+ mov r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+
-+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b
-+#endif
-+
-+ mcr p15, 0, r2, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_page(page)
-+ *
-+ * Cleans a single page of dcache so that if we have any future aliased
-+ * mappings, they will be consistent at the time that they are created.
-+ *
-+ * page: virtual address of page to clean from dcache
-+ *
-+ * Note:
-+ * we don't invalidate the entries since when we write the page
-+ * out to disk, the entries may get reloaded into the cache.
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_page)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ mov r1, #PAGESIZE
-+1:
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+ add r0, r0, #DCACHELINESIZE
-+ subs r1, r1, #DCACHELINESIZE
-+ bne 1b
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_dcache_clean_entry(addr)
-+ *
-+ * Clean the specified entry of any caches such that the MMU
-+ * translation fetches will obtain correct data.
-+ *
-+ * addr: cache-unaligned virtual address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_dcache_clean_entry)
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ bic r0, r0, #DCACHELINESIZE - 1
-+ mcr p15, 0, r0, c7, c10, 1 @ clean single D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/* ================================ I-CACHE =============================== */
-+
-+/*
-+ * cpu_arm1022_icache_invalidate_range(start, end)
-+ *
-+ * invalidate a range of virtual addresses from the Icache
-+ *
-+ * This is a little misleading, it is not intended to clean out
-+ * the i-cache but to make sure that any data written to the
-+ * range is made consistent. This means that when we execute code
-+ * in that region, everything works as we expect.
-+ *
-+ * This generally means writing back data in the Dcache and
-+ * write buffer and invalidating the Icache over that region
-+ *
-+ * start: virtual start address
-+ * end: virtual end address
-+ *
-+ * NOTE: ICACHELINESIZE == DCACHELINESIZE (so we don't need to
-+ * loop twice, once for i-cache, once for d-cache)
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_icache_invalidate_range)
-+ bic r0, r0, #ICACHELINESIZE - 1
-+ sub r3, r1, r0
-+ cmp r3, #MAX_AREA_SIZE
-+ movhs r2, #1
-+ bhs cpu_arm1022_cache_clean_invalidate_all_r2
-+1:
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
-+#endif
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ mcr p15, 0, r0, c7, c5, 1 @ Invalidate I entry
-+#endif
-+ add r0, r0, #DCACHELINESIZE
-+ cmp r0, r1
-+ bls 1b @ unsigned lower or same - includes r1 entry
-+
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+ENTRY(cpu_arm1022_icache_invalidate_page)
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ add r1, r0, #PAGESIZE
-+ b cpu_arm1022_icache_invalidate_range
-+
-+/* ================================== TLB ================================= */
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_all()
-+ *
-+ * Invalidate all TLB entries
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_all)
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I & D tlbs
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_range(start, end)
-+ *
-+ * invalidate TLB entries covering the specified range
-+ *
-+ * start: range start address
-+ * end: range end address
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_range)
-+ sub r3, r1, r0
-+ cmp r3, #256 * PAGESIZE
-+ bhs cpu_arm1022_tlb_invalidate_all
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r3, #PAGESIZE
-+ sub r3, r3, #1
-+ bic r0, r0, r3
-+1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ add r0, r0, #PAGESIZE
-+ cmp r0, r1
-+ bls 1b
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_tlb_invalidate_page(page, flags)
-+ *
-+ * invalidate the TLB entries for the specified page.
-+ *
-+ * page: page to invalidate
-+ * flags: non-zero if we include the I TLB
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_tlb_invalidate_page)
-+ mov r3, #0
-+ mcr p15, 0, r3, c7, c10, 4 @ drain WB
-+ mov r0, r0, LSR #LOG2PAGESIZE @ round down to nearest page
-+ mov r0, r0, LSL #LOG2PAGESIZE
-+ teq r1, #0
-+ mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
-+ mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
-+ mov pc, lr
-+
-+/* =============================== PageTable ============================== */
-+
-+/*
-+ * cpu_arm1022_set_pgd(pgd)
-+ *
-+ * Set the translation base pointer to be as described by pgd.
-+ *
-+ * pgd: new page tables
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pgd)
-+ stmfd sp!, {lr}
-+ bl cpu_arm1022_cache_clean_invalidate_all @ preserves r0
-+ mov r1, #0
-+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
-+ mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
-+ ldmfd sp!, {pc}
-+
-+/*
-+ * cpu_arm1022_set_pmd(pmdp, pmd)
-+ *
-+ * Set a level 1 translation table entry, and clean it out of
-+ * any caches such that the MMUs can load it correctly.
-+ *
-+ * pmdp: pointer to PMD entry
-+ * pmd: PMD value to store
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pmd)
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r2, r1, #0x0a @ C & Section
-+ tst r2, #0x0b
-+ biceq r1, r1, #4 @ clear bufferable bit
-+#endif
-+ str r1, [r0]
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+/*
-+ * cpu_arm1022_set_pte(ptep, pte)
-+ *
-+ * Set a PTE and flush it out
-+ */
-+ .align 5
-+ENTRY(cpu_arm1022_set_pte)
-+ str r1, [r0], #-1024 @ linux version
-+
-+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
-+
-+ bic r2, r1, #0xff0
-+ bic r2, r2, #3
-+ orr r2, r2, #HPTE_TYPE_SMALL
-+
-+ tst r1, #LPTE_USER @ User?
-+ orrne r2, r2, #HPTE_AP_READ
-+
-+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-+ orreq r2, r2, #HPTE_AP_WRITE
-+
-+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
-+ movne r2, #0
-+
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ eor r3, r2, #0x0a @ C and Small Page?
-+ tst r3, #0x0b @ if so..
-+ biceq r2, r2, #0x04 @ clear the bufferable bit
-+#endif
-+ str r2, [r0] @ hardware version
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
-+#endif
-+ mov r1, #0
-+ mcr p15, 0, r1, c7, c10, 4 @ drain WB
-+ mov pc, lr
-+
-+
-+cpu_manu_name:
-+ .asciz "ARM"
-+ENTRY(cpu_arm1022_name)
-+ .ascii "Arm1022E"
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ .ascii "i"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "d"
-+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-+ .ascii "(wt)"
-+#endif
-+#ifdef CONFIG_CPU_DCACHE_WRITEBACK
-+ .ascii "(wb)"
-+#endif
-+#endif
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ .ascii "B"
-+#endif
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ .ascii "RR"
-+#endif
-+ .ascii "\0"
-+ .align
-+
-+ .section ".text.init", #alloc, #execinstr
-+
-+__arm1022_setup:
-+ mov r0, #0
-+ mcr p15, 0, r0, c7, c7, 0 @ invalidate I,D caches on v4
-+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
-+ mcr p15, 0, r0, c8, c7, 0 @ invalidate I,D TLBs on v4
-+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-+ mov r0, #0x1f @ Domains 0, 1 = client
-+ mcr p15, 0, r0, c3, c0, 0 @ load domain access register
-+
-+ mrc p15, 0, r0, c1, c0, 0 @ Read current control register
-+/*
-+ * The only thing worth keeping from the initial control register is the endian bit
-+ */
-+
-+ and r0, r0, #0x0080 @ ........B....... Preserve endian bit, zero all others.
-+ orr r0, r0, #0x0070 @ .........111.... Set the SBO (Should Be One) bits
-+/*
-+ * Turn on what we want.
-+ */
-+ orr r0, r0, #0x0001 @ ...............M Enable MMU (Alignment is special cased elsewhere)
-+ orr r0, r0, #0x0100 @ .......S........ Enable system MMU protection
-+ orr r0, r0, #0x2000 @ ..V............. Enable high vectors
-+
-+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-+ orr r0, r0, #0x4000 @ .R.............. Force round-robin replacement
-+#endif
-+
-+#ifndef CONFIG_CPU_BPREDICT_DISABLE
-+ orr r0, r0, #0x0800 @ ....Z........... Enable branch prediction
-+#endif
-+
-+#ifdef CONFIG_CPU_DCACHE_ENABLE
-+ orr r0, r0, #0x0004 @ .............C.. Enable D cache
-+#endif
-+#ifndef CONFIG_CPU_WB_DISABLE
-+ orr r0, r0, #0x0008 @ ............W... Write Buffer enabled
-+#endif
-+
-+#ifdef CONFIG_CPU_ICACHE_ENABLE
-+ orr r0, r0, #0x1000 @ ...I............ Enable I Cache
-+#endif
-+
-+ mov pc, lr
-+
-+ .text
-+
-+/*
-+ * Purpose : Function pointers used to access above functions - all calls
-+ * come through these
-+ */
-+ .type arm1022_processor_functions, #object
-+arm1022_processor_functions:
-+ .word cpu_arm1022_data_abort
-+ .word cpu_arm1022_check_bugs
-+ .word cpu_arm1022_proc_init
-+ .word cpu_arm1022_proc_fin
-+ .word cpu_arm1022_reset
-+ .word cpu_arm1022_do_idle
-+
-+ /* cache */
-+ .word cpu_arm1022_cache_clean_invalidate_all
-+ .word cpu_arm1022_cache_clean_invalidate_range
-+ .word cpu_arm1022_flush_ram_page
-+
-+ /* dcache */
-+ .word cpu_arm1022_dcache_invalidate_range
-+ .word cpu_arm1022_dcache_clean_range
-+ .word cpu_arm1022_dcache_clean_page
-+ .word cpu_arm1022_dcache_clean_entry
-+
-+ /* icache */
-+ .word cpu_arm1022_icache_invalidate_range
-+ .word cpu_arm1022_icache_invalidate_page
-+
-+ /* tlb */
-+ .word cpu_arm1022_tlb_invalidate_all
-+ .word cpu_arm1022_tlb_invalidate_range
-+ .word cpu_arm1022_tlb_invalidate_page
-+
-+ /* pgtable */
-+ .word cpu_arm1022_set_pgd
-+ .word cpu_arm1022_set_pmd
-+ .word cpu_arm1022_set_pte
-+ .size arm1022_processor_functions, . - arm1022_processor_functions
-+
-+ .type cpu_arm1022_info, #object
-+cpu_arm1022_info:
-+ .long cpu_manu_name
-+ .long cpu_arm1022_name
-+ .size cpu_arm1022_info, . - cpu_arm1022_info
-+
-+ .type cpu_arch_name, #object
-+cpu_arch_name:
-+ .asciz "armv5t"
-+ .size cpu_arch_name, . - cpu_arch_name
-+
-+ .type cpu_elf_name, #object
-+cpu_elf_name:
-+ .asciz "v5"
-+ .size cpu_elf_name, . - cpu_elf_name
-+ .align
-+
-+ .section ".proc.info", #alloc, #execinstr
-+
-+ .type __arm1022_proc_info,#object
-+__arm1022_proc_info:
-+ .long 0x4100a220 @ ARM 1022
-+ .long 0xff00fff0
-+ .long 0x00000c1e @ mmuflags
-+ b __arm1022_setup
-+ .long cpu_arch_name
-+ .long cpu_elf_name
-+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
-+ .long cpu_arm1022_info
-+ .long arm1022_processor_functions
-+ .size __arm1022_proc_info, . - __arm1022_proc_info
---- linux-2.4.27/arch/arm/mm/proc-arm1026.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm1026.S
-@@ -66,19 +66,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm1026_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r2, r3, #0b1101 @ Check for translation error
-- sub r1, r2, #0b0101
--
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
--
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -254,7 +259,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -279,7 +284,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-@@ -309,7 +314,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -330,7 +335,7 @@
- */
- .align 5
- ENTRY(cpu_arm1026_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -473,7 +478,7 @@
- biceq r1, r1, #4 @ clear bufferable bit
- #endif
- str r1, [r0]
--#ifndef CONFIG_CPU_ARM1026_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -494,7 +499,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
-@@ -634,12 +639,12 @@
-
- .type cpu_arch_name, #object
- cpu_arch_name:
-- .asciz "armv5EJ"
-+ .asciz "armv5tej"
- .size cpu_arch_name, . - cpu_arch_name
-
- .type cpu_elf_name, #object
- cpu_elf_name:
-- .asciz "v5EJ"
-+ .asciz "v5"
- .size cpu_elf_name, . - cpu_elf_name
- .align
-
---- linux-2.4.27/arch/arm/mm/proc-arm6,7.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm6,7.S
-@@ -72,7 +72,7 @@
- 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
- add r0, r0, #4096
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- ENTRY(cpu_arm7_tlb_invalidate_range)
-@@ -85,7 +85,7 @@
- 1: mcr p15, 0, r0, c6, c0, 0 @ purge TLB
- add r0, r0, #0x4000
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
- #endif
-
-@@ -110,15 +110,13 @@
- * Purpose : obtain information about current aborted instruction
- *
- * Returns : r0 = address of abort
-- * : r1 != 0 if writing
-- * : r3 = FSR
-+ * : r1 = FSR, bit 11 set if writing
-+ * : r3 = corrupted
- * : sp = pointer to registers
- */
-
- ENTRY(cpu_arm6_data_abort)
- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #14 << 24
- teq r2, #8 << 24 @ was it ldm/stm
- bne Ldata_simple
-@@ -144,14 +142,14 @@
- addeq r7, r0, r7, lsl #2 @ Do correction (signed)
- Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
- Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ bic r1, r1, #1 << 11 | 1 << 10
-+ tst r4, #1 << 20
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- ENTRY(cpu_arm7_data_abort)
- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
- and r2, r4, #15 << 24
- add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
- movs pc, lr
-@@ -336,7 +334,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-arm720.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm720.S
-@@ -97,7 +97,7 @@
- 1: mcr p15, 0, r0, c8, c7, 1 @ flush TLB (v4)
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -124,8 +124,8 @@
- * picture. Unfortunately, this does happen. We live with it.
- *
- * Returns : r0 = address of abort
-- * : r1 != 0 if writing
-- * : r3 = FSR
-+ * : r1 = FSR, bit 11 set if writing
-+ * : r3 = corrupted
- * : sp = pointer to registers
- */
-
-@@ -150,16 +150,16 @@
- addeq r7, r0, r7, lsl #2 @ Do correction (signed)
- Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
- Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- and r3, r3, #255
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
-+ bic r1, r1, #1 << 11 | 1 << 10
-+ tst r4, #1 << 20
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- ENTRY(cpu_arm720_data_abort)
-- tst r3, #T_BIT
-+ tst r3, #PSR_T_BIT
- bne .data_thumb_abort
-- ldr r4, [r0] @ read instruction causing problem
-- tst r4, r4, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldr r4, [r2] @ read instruction causing problem
- and r2, r4, #15 << 24
- add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine
- movs pc, lr
-@@ -270,9 +270,9 @@
- b Ldata_saver7
-
- .data_thumb_abort:
-- ldrh r4, [r0] @ read instruction
-- tst r4, r4, lsr #12 @ C = bit 11
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldrh r4, [r2] @ read instruction
-+ tst r4, #1 << 11
-+ orrne r4, r4, #1 << 20
- and r2, r4, #15 << 12
- add pc, pc, r2, lsr #10 @ lookup in table
- nop
-@@ -318,8 +318,8 @@
- and r0, r0, #15 @ number of regs to transfer
- ldr r7, [sp, #13 << 2]
- tst r4, #1 << 11
-- addne r7, r7, r0, lsl #2 @ increment SP if PUSH
-- subeq r7, r7, r0, lsr #2 @ decrement SP if POP
-+ addeq r7, r7, r0, lsl #2 @ increment SP if PUSH
-+ subne r7, r7, r0, lsl #2 @ decrement SP if POP
- str r7, [sp, #13 << 2]
- b Ldata_simple
-
-@@ -336,7 +336,7 @@
- and r0, r0, #15 @ number of regs to transfer
- and r5, r4, #7 << 8
- ldr r7, [sp, r5, lsr #6]
-- sub r7, r7, r0, lsr #2 @ always decrement
-+ sub r7, r7, r0, lsl #2 @ always decrement
- str r7, [sp, r5, lsr #6]
- b Ldata_simple
-
-@@ -418,7 +418,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-arm920.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm920.S
-@@ -71,12 +71,16 @@
- */
- .align 5
- ENTRY(cpu_arm920_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -186,10 +190,9 @@
- .align 5
- ENTRY(cpu_arm920_cache_clean_invalidate_range)
- bic r0, r0, #DCACHELINESIZE - 1 @ && added by PGM
-- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -207,7 +210,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -253,18 +256,17 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
- mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
- #endif @ clean D entry
- bic r0, r0, #DCACHELINESIZE - 1
-- bic r1, r1, #DCACHELINESIZE - 1
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -279,20 +281,17 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
--
-- bic r1, r1, #DCACHELINESIZE -1
-- add r1, r1, #DCACHELINESIZE
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
-
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
- subs r1, r1, #DCACHELINESIZE
-- bpl 1b
-+ bcs 1b
- #endif
- mcr p15, 0, r2, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -312,7 +311,7 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -333,7 +332,7 @@
- */
- .align 5
- ENTRY(cpu_arm920_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -365,16 +364,13 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm920_cache_clean_invalidate_all_r2
--
-- bic r1, r1, #ICACHELINESIZE - 1
-- add r1, r1, #ICACHELINESIZE
-+ bhi cpu_arm920_cache_clean_invalidate_all_r2
-
- 1: mcr p15, 0, r0, c7, c5, 1 @ Clean I entry
- mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
- add r0, r0, #ICACHELINESIZE
- subs r1, r1, #ICACHELINESIZE
-- bne 1b
-+ bcs 1b
-
- mov r0, #0
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -418,13 +414,12 @@
- mov r3, #PAGESIZE
- sub r3, r3, #1
- bic r0, r0, r3
-- bic r1, r1, r3
-
- 1: mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -457,7 +452,6 @@
- ENTRY(cpu_arm920_set_pgd)
- mov ip, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-- /* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
- mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
- #else
- @ && 'Clean & Invalidate whole DCache'
-@@ -514,7 +508,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-arm922.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm922.S
-@@ -62,17 +62,20 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- */
- .align 5
- ENTRY(cpu_arm922_data_abort)
-- ldr r1, [r0] @ read aborted instruction
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- tst r1, r1, lsr #21 @ C = bit 20
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-- sbc r1, r1, r1 @ r1 = C - 1
-- and r3, r3, #255
-+ tst r3, #PSR_T_BIT
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -185,7 +188,7 @@
- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -203,7 +206,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -249,7 +252,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -260,7 +263,7 @@
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -275,12 +278,12 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
-
- bic r1, r1, #DCACHELINESIZE -1
- add r1, r1, #DCACHELINESIZE
-@@ -308,7 +311,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -329,7 +332,7 @@
- */
- .align 5
- ENTRY(cpu_arm922_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -361,7 +364,7 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm922_cache_clean_invalidate_all_r2
-+ bhi cpu_arm922_cache_clean_invalidate_all_r2
-
- bic r1, r1, #ICACHELINESIZE - 1
- add r1, r1, #ICACHELINESIZE
-@@ -420,7 +423,7 @@
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -510,7 +513,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-arm925.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm925.S
-@@ -69,24 +69,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm925_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r4, c5, c0, 0 @ get FSR
--
-- tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
-- ldrneh r1, [r2] @ Read aborted Thumb instruction
-- tstne r1, r1, lsr #12 @ C = bit 11
--
-- ldreq r1, [r2] @ Read aborted ARM instruction
-- tsteq r1, r1, lsr #21 @ C = bit 20
--
-- sbc r1, r1, r1 @ r1 = C - 1
-- and r3, r4, #255
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT @ Thumb?
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ L = 0 -> write
-+ orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
- /*
-@@ -207,7 +207,7 @@
- bic r1, r1, #DCACHELINESIZE - 1 @ && added by DHM
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
- 1: teq r2, #0
- #ifdef CONFIG_CPU_ARM925_WRITETHROUGH
- mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
-@@ -225,7 +225,7 @@
- add r0, r0, #DCACHELINESIZE
- #endif
- cmp r0, r1
-- blt 1b
-+ blo 1b
-
- mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mov pc, lr
-@@ -282,7 +282,7 @@
- 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
- add r0, r0, #DCACHELINESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -302,7 +302,7 @@
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
- mov r2, #0
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
-
- bic r1, r1, #DCACHELINESIZE -1
- add r1, r1, #DCACHELINESIZE
-@@ -383,7 +383,7 @@
- bic r0, r0, #ICACHELINESIZE - 1 @ Safety check
- sub r1, r1, r0
- cmp r1, #MAX_AREA_SIZE
-- bgt cpu_arm925_cache_clean_invalidate_all_r2
-+ bhi cpu_arm925_cache_clean_invalidate_all_r2
-
- bic r1, r1, #ICACHELINESIZE - 1
- add r1, r1, #ICACHELINESIZE
-@@ -443,7 +443,7 @@
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- add r0, r0, #PAGESIZE
- cmp r0, r1
-- blt 1b
-+ blo 1b
- mov pc, lr
-
- /*
-@@ -532,7 +532,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-arm926.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-arm926.S
-@@ -66,28 +66,24 @@
- *
- * Returns:
- * r0 = address of abort
-- * r1 != 0 if writing
-- * r3 = FSR
-+ * r1 = FSR, bit 11 set if writing
-+ * r3 = corrupted
- * r4 = corrupted
- */
- .align 5
- ENTRY(cpu_arm926_data_abort)
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- mrc p15, 0, r4, c5, c0, 0 @ get FSR
--
-- tst r3, #1<<24 @ Check for Jbit (NE -> found)
-- movne r3, #-1 @ Mark as writing
-- bne 2f
--
-- tst r3, #1<<5 @ Check for Thumb-bit (NE -> found)
-- ldrneh r1, [r2] @ Read aborted Thumb instruction
-- ldreq r1, [r2] @ Read aborted ARM instruction
-- movne r1, r1, lsl #(20-12) @ shift thumb bit 10 to ARM bit 20
-- tsteq r1, r1, lsr #21 @ C = bit 20
--
-- sbc r1, r1, r1 @ r1 = C - 1
--2:
-- and r3, r4, #255
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #PSR_J_BIT @ Java?
-+ orrne r1, r1, #1 << 11 @ always assume write
-+ movne pc, lr
-+ tst r3, #PSR_T_BIT @ Thumb?
-+ ldrneh r3, [r2] @ read aborted thumb instruction
-+ ldreq r3, [r2] @ read aborted ARM instruction
-+ movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
-+ tst r3, #1 << 20 @ L = 0 -> write
-+ orreq r1, r1, #1 << 11 @ yes.
- mov pc, lr
-
- /*
-@@ -263,7 +259,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_invalidate_range)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- tst r0, #DCACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
- tst r1, #DCACHELINESIZE - 1
-@@ -288,7 +284,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_range)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- bic r0, r0, #DCACHELINESIZE - 1
- sub r3, r1, r0
- cmp r3, #MAX_AREA_SIZE
-@@ -318,7 +314,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_page)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mov r1, #PAGESIZE
- 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- add r0, r0, #DCACHELINESIZE
-@@ -339,7 +335,7 @@
- */
- .align 5
- ENTRY(cpu_arm926_dcache_clean_entry)
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -482,7 +478,7 @@
- biceq r1, r1, #4 @ clear bufferable bit
- #endif
- str r1, [r0]
--#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
-+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry
- #endif
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
-@@ -503,7 +499,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/mm/proc-sa110.S~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/mm/proc-sa110.S
-@@ -86,12 +86,12 @@
- .align 5
- ENTRY(cpu_sa110_data_abort)
- ENTRY(cpu_sa1100_data_abort)
-- mrc p15, 0, r3, c5, c0, 0 @ get FSR
-+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
- mrc p15, 0, r0, c6, c0, 0 @ get FAR
-- ldr r1, [r2] @ read aborted instruction
-- and r3, r3, #255
-- tst r1, r1, lsr #21 @ C = bit 20
-- sbc r1, r1, r1 @ r1 = C - 1
-+ ldr r3, [r2] @ read aborted instruction
-+ bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
-+ tst r3, #1 << 20 @ check write
-+ orreq r1, r1, #1 << 11
- mov pc, lr
-
- /*
-@@ -551,7 +551,7 @@
- bic r2, r2, #3
- orr r2, r2, #HPTE_TYPE_SMALL
-
-- tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
-+ tst r1, #LPTE_USER @ User?
- orrne r2, r2, #HPTE_AP_READ
-
- tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
---- linux-2.4.27/arch/arm/tools/mach-types~2.4.27-vrs1
-+++ linux-2.4.27/arch/arm/tools/mach-types
-@@ -6,7 +6,7 @@
- # To add an entry into this database, please see Documentation/arm/README,
- # or contact rmk@arm.linux.org.uk
- #
--# Last update: Sat Jun 28 12:10:54 2003
-+# Last update: Mon Apr 19 21:11:35 2004
- #
- # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
- #
-@@ -202,7 +202,7 @@
- fester SA1100_FESTER FESTER 191
- gpi ARCH_GPI GPI 192
- smdk2410 ARCH_SMDK2410 SMDK2410 193
--premium ARCH_PREMIUM PREMIUM 194
-+i519 ARCH_I519 I519 194
- nexio SA1100_NEXIO NEXIO 195
- bitbox SA1100_BITBOX BITBOX 196
- g200 SA1100_G200 G200 197
-@@ -228,7 +228,7 @@
- arnold SA1100_ARNOLD ARNOLD 217
- psiboard SA1100_PSIBOARD PSIBOARD 218
- jz8028 ARCH_JZ8028 JZ8028 219
--h5400 ARCH_IPAQ3 IPAQ3 220
-+h5400 ARCH_H5400 H5400 220
- forte SA1100_FORTE FORTE 221
- acam SA1100_ACAM ACAM 222
- abox SA1100_ABOX ABOX 223
-@@ -259,7 +259,7 @@
- stork_egg ARCH_STORK_EGG STORK_EGG 248
- wismo SA1100_WISMO WISMO 249
- ezlinx ARCH_EZLINX EZLINX 250
--at91rm9200 ARCH_AT91 AT91 251
-+at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
- orion ARCH_ORION ORION 252
- neptune ARCH_NEPTUNE NEPTUNE 253
- hackkit SA1100_HACKKIT HACKKIT 254
-@@ -295,12 +295,12 @@
- adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
- adsagc SA1100_ADSAGC ADSAGC 285
- stp7312 ARCH_STP7312 STP7312 286
--nx_phnx ARCH_PXA255 PXA255 287
-+nx_phnx MACH_NX_PHNX NX_PHNX 287
- wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
- inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
- adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
- iyonix ARCH_IYONIX IYONIX 291
--damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
-+damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
- meg03 ARCH_MEG03 MEG03 293
- pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
- nwsc ARCH_NWSC NWSC 295
-@@ -356,3 +356,172 @@
- seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
- ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
- h1940 ARCH_H1940 H1940 347
-+scorpio ARCH_SCORPIO SCORPIO 348
-+viva ARCH_VIVA VIVA 349
-+pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
-+csb335 ARCH_CSB335 CSB335 351
-+ixrd425 ARCH_IXRD425 IXRD425 352
-+iq80315 ARCH_IQ80315 IQ80315 353
-+nmp7312 ARCH_NMP7312 NMP7312 354
-+cx861xx ARCH_CX861XX CX861XX 355
-+enp2611 ARCH_ENP2611 ENP2611 356
-+xda SA1100_XDA XDA 357
-+csir_ims ARCH_CSIR_IMS CSIR_IMS 358
-+ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
-+pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
-+toto ARCH_TOTO TOTO 361
-+s3c2440 ARCH_S3C2440 S3C2440 362
-+ks8695p ARCH_KS8695P KS8695P 363
-+se4000 ARCH_SE4000 SE4000 364
-+quadriceps ARCH_QUADRICEPS QUADRICEPS 365
-+bronco ARCH_BRONCO BRONCO 366
-+esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
-+esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
-+s5c7375 ARCH_S5C7375 S5C7375 369
-+spearhead ARCH_SPEARHEAD SPEARHEAD 370
-+pantera ARCH_PANTERA PANTERA 371
-+prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
-+gumstik ARCH_GUMSTIK GUMSTIK 373
-+rcube ARCH_RCUBE RCUBE 374
-+rea_olv ARCH_REA_OLV REA_OLV 375
-+pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
-+s3c3410 ARCH_S3C3410 S3C3410 377
-+espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
-+mp1x ARCH_MP1X MP1X 379
-+at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
-+adsvgx ARCH_ADSVGX ADSVGX 381
-+omap_h2 ARCH_OMAP_H2 OMAP_H2 382
-+pelee ARCH_PELEE PELEE 383
-+e740 MACH_E740 E740 384
-+iq80331 ARCH_IQ80331 IQ80331 385
-+versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
-+kev7a400 MACH_KEV7A400 KEV7A400 388
-+lpd7a400 MACH_LPD7A400 LPD7A400 389
-+lpd7a404 MACH_LPD7A404 LPD7A404 390
-+fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
-+janus2m ARCH_JANUS2M JANUS2M 392
-+embtf MACH_EMBTF EMBTF 393
-+hpm MACH_HPM HPM 394
-+smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
-+smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
-+streetracer MACH_STREETRACER STREETRACER 397
-+eframe MACH_EFRAME EFRAME 398
-+csb337 MACH_CSB337 CSB337 399
-+pxa_lark MACH_PXA_LARK PXA_LARK 400
-+pxa_pnp2110 MACH_PNP2110 PNP2110 401
-+tcc72x MACH_TCC72X TCC72X 402
-+altair MACH_ALTAIR ALTAIR 403
-+kc3 MACH_KC3 KC3 404
-+sinteftd MACH_SINTEFTD SINTEFTD 405
-+mainstone MACH_MAINSTONE MAINSTONE 406
-+aday4x MACH_ADAY4X ADAY4X 407
-+lite300 MACH_LITE300 LITE300 408
-+s5c7376 MACH_S5C7376 S5C7376 409
-+mt02 MACH_MT02 MT02 410
-+mport3s MACH_MPORT3S MPORT3S 411
-+ra_alpha MACH_RA_ALPHA RA_ALPHA 412
-+xcep MACH_XCEP XCEP 413
-+arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414
-+stargate MACH_STARGATE STARGATE 415
-+armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
-+elroy_jack MACH_ELROY_JACK ELROY_JACK 417
-+backend MACH_BACKEND BACKEND 418
-+s5linbox MACH_S5LINBOX S5LINBOX 419
-+nomadik MACH_NOMADIK NOMADIK 420
-+ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
-+at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
-+corgi MACH_CORGI CORGI 423
-+poodle MACH_POODLE POODLE 424
-+ten MACH_TEN TEN 425
-+roverp5p MACH_ROVERP5P ROVERP5P 426
-+sc2700 MACH_SC2700 SC2700 427
-+ex_eagle MACH_EX_EAGLE EX_EAGLE 428
-+nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
-+nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
-+blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
-+i819 MACH_I819 I819 432
-+ixmb995e MACH_IXMB995E IXMB995E 433
-+skyrider MACH_SKYRIDER SKYRIDER 434
-+skyhawk MACH_SKYHAWK SKYHAWK 435
-+enterprise MACH_ENTERPRISE ENTERPRISE 436
-+dep2410 MACH_DEP2410 DEP2410 437
-+armcore MACH_ARMCORE ARMCORE 438
-+hobbit MACH_HOBBIT HOBBIT 439
-+h7210 MACH_H7210 H7210 440
-+pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
-+acc MACH_ACC ACC 442
-+esl_sarva MACH_ESL_SARVA ESL_SARVA 443
-+xm250 MACH_XM250 XM250 444
-+t6tc1xb MACH_T6TC1XB T6TC1XB 445
-+ess710 MACH_ESS710 ESS710 446
-+mx3ads MACH_MX3ADS MX3ADS 447
-+himalaya MACH_HIMALAYA HIMALAYA 448
-+bolfenk MACH_BOLFENK BOLFENK 449
-+at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
-+edb9312 MACH_EDB9312 EDB9312 451
-+omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
-+aximx3 MACH_AXIMX3 AXIMX3 453
-+eb67xdip MACH_EB67XDIP EB67XDIP 454
-+webtxs MACH_WEBTXS WEBTXS 455
-+hawk MACH_HAWK HAWK 456
-+ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457
-+expresso MACH_EXPRESSO EXPRESSO 458
-+h4000 MACH_H4000 H4000 459
-+dino MACH_DINO DINO 460
-+ml675k MACH_ML675K ML675K 461
-+edb9301 MACH_EDB9301 EDB9301 462
-+edb9315 MACH_EDB9315 EDB9315 463
-+reciva_tt MACH_RECIVA_TT RECIVA_TT 464
-+cstcb01 MACH_CSTCB01 CSTCB01 465
-+cstcb1 MACH_CSTCB1 CSTCB1 466
-+shadwell MACH_SHADWELL SHADWELL 467
-+goepel263 MACH_GOEPEL263 GOEPEL263 468
-+acq100 MACH_ACQ100 ACQ100 469
-+mx1fs2 MACH_MX1FS2 MX1FS2 470
-+hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471
-+sparky MACH_SPARKY SPARKY 472
-+ns9750 MACH_NS9750 NS9750 473
-+phoenix MACH_PHOENIX PHOENIX 474
-+vr1000 MACH_VR1000 VR1000 475
-+deisterpxa MACH_DEISTERPXA DEISTERPXA 476
-+bcm1160 MACH_BCM1160 BCM1160 477
-+pcm022 MACH_PCM022 PCM022 478
-+adsgcx MACH_ADSGCX ADSGCX 479
-+dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480
-+dm320 MACH_DM320 DM320 481
-+markov MACH_MARKOV MARKOV 482
-+cos7a400 MACH_COS7A400 COS7A400 483
-+milano MACH_MILANO MILANO 484
-+ue9328 MACH_UE9328 UE9328 485
-+uex255 MACH_UEX255 UEX255 486
-+ue2410 MACH_UE2410 UE2410 487
-+a620 MACH_A620 A620 488
-+ocelot MACH_OCELOT OCELOT 489
-+cheetah MACH_CHEETAH CHEETAH 490
-+omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491
-+zvue MACH_ZVUE ZVUE 492
-+roverp1 MACH_ROVERP1 ROVERP1 493
-+asidial2 MACH_ASIDIAL2 ASIDIAL2 494
-+s3c24a0 MACH_S3C24A0 S3C24A0 495
-+e800 MACH_E800 E800 496
-+e750 MACH_E750 E750 497
-+s3c5500 MACH_S3C5500 S3C5500 498
-+smdk5500 MACH_SMDK5500 SMDK5500 499
-+signalsync MACH_SIGNALSYNC SIGNALSYNC 500
-+nbc MACH_NBC NBC 501
-+er4525 MACH_ER4525 ER4525 502
-+netbookpro MACH_NETBOOKPRO NETBOOKPRO 503
-+hw90200 MACH_HW90200 HW90200 504
-+condor MACH_CONDOR CONDOR 505
-+cup MACH_CUP CUP 506
-+kite MACH_KITE KITE 507
-+scb9328 MACH_SCB9328 SCB9328 508
-+omap_h3 MACH_OMAP_H3 OMAP_H3 509
-+omap_h4 MACH_OMAP_H4 OMAP_H4 510
-+n10 MACH_N10 N10 511
-+montajade MACH_MONTAJADE MONTAJADE 512
-+sg560 MACH_SG560 SG560 513
-+dp1000 MACH_DP1000 DP1000 514
-+omap_osk MACH_OMAP_OSK OMAP_OSK 515
-+rg100v3 MACH_RG100V3 RG100V3 516
-+mx2ads MACH_MX2ADS MX2ADS 517
---- linux-2.4.27/arch/i386/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/i386/config.in
-@@ -9,6 +9,7 @@
-
- define_bool CONFIG_UID16 y
-
-+define_bool CONFIG_GENERIC_ISA_DMA y
- mainmenu_option next_comment
- comment 'Code maturity level options'
- bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
---- linux-2.4.27/arch/i386/kernel/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/i386/kernel/Makefile
-@@ -7,8 +7,8 @@
- #
- # Note 2! The CFLAGS definitions are now in the main makefile...
-
--.S.o:
-- $(CC) $(AFLAGS) -traditional -c $< -o $*.o
-+USE_STANDARD_AS_RULE := true
-+EXTRA_AFLAGS := -traditional
-
- all: kernel.o head.o init_task.o
-
---- linux-2.4.27/arch/i386/kernel/apm.c~2.4.27-vrs1
-+++ linux-2.4.27/arch/i386/kernel/apm.c
-@@ -1267,6 +1267,7 @@
- as->suspend_wait = 0;
- as->suspend_result = err;
- }
-+ ignore_normal_resume = 1;
- wake_up_interruptible(&apm_suspend_waitqueue);
- return err;
- }
-@@ -1319,6 +1320,8 @@
- if (ignore_bounce
- && ((jiffies - last_resume) > bounce_interval))
- ignore_bounce = 0;
-+ if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
-+ ignore_normal_resume = 0;
-
- switch (event) {
- case APM_SYS_STANDBY:
---- linux-2.4.27/arch/i386/lib/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/i386/lib/Makefile
-@@ -2,8 +2,7 @@
- # Makefile for i386-specific library files..
- #
-
--.S.o:
-- $(CC) $(AFLAGS) -c $< -o $*.o
-+USE_STANDARD_AS_RULE := true
-
- L_TARGET = lib.a
-
---- linux-2.4.27/arch/i386/math-emu/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/arch/i386/math-emu/Makefile
-@@ -2,15 +2,15 @@
- # Makefile for wm-FPU-emu
- #
-
-+USE_STANDARD_AS_RULE := true
-+
- O_TARGET := math.o
-
- #DEBUG = -DDEBUGGING
- DEBUG =
- PARANOID = -DPARANOID
- CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin $(MATH_EMULATION)
--
--.S.o:
-- $(CC) $(AFLAGS) $(PARANOID) -c $<
-+EXTRA_AFLAGS := $(PARANOID)
-
- # From 'C' language sources:
- C_OBJS =fpu_entry.o errors.o \
---- linux-2.4.27/arch/ia64/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/ia64/config.in
-@@ -25,6 +25,7 @@
- define_bool CONFIG_SBUS n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- choice 'IA-64 processor type' \
- "Itanium CONFIG_ITANIUM \
---- linux-2.4.27/arch/m68k/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/m68k/config.in
-@@ -6,6 +6,7 @@
- define_bool CONFIG_UID16 y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Linux/68k Kernel Configuration"
-
---- linux-2.4.27/arch/mips/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/mips/config.in
-@@ -5,5 +5,6 @@
- define_bool CONFIG_MIPS y
- define_bool CONFIG_MIPS32 y
- define_bool CONFIG_MIPS64 n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- source arch/mips/config-shared.in
---- linux-2.4.27/arch/parisc/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/parisc/config.in
-@@ -9,6 +9,7 @@
- define_bool CONFIG_UID16 n
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.27/arch/ppc/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/ppc/config.in
-@@ -6,6 +6,7 @@
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
- define_bool CONFIG_HAVE_DEC_LOCK y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_name "Linux/PowerPC Kernel Configuration"
-
---- linux-2.4.27/arch/sh/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/sh/config.in
-@@ -9,6 +9,7 @@
- define_bool CONFIG_UID16 y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.27/arch/sparc/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/sparc/config.in
-@@ -6,6 +6,7 @@
-
- define_bool CONFIG_UID16 y
- define_bool CONFIG_HIGHMEM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
-
- mainmenu_option next_comment
- comment 'Code maturity level options'
---- linux-2.4.27/arch/sparc64/config.in~2.4.27-vrs1
-+++ linux-2.4.27/arch/sparc64/config.in
-@@ -43,6 +43,7 @@
- define_bool CONFIG_HAVE_DEC_LOCK y
- define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
- define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
-+define_bool CONFIG_GENERIC_ISA_DMA y
- define_bool CONFIG_ISA n
- define_bool CONFIG_ISAPNP n
- define_bool CONFIG_EISA n
---- linux-2.4.27/drivers/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/Makefile
-@@ -8,9 +8,9 @@
-
- mod-subdirs := dio hil mtd sbus video macintosh usb input telephony ide \
- message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
-- fc4 net/hamradio i2c acpi bluetooth usb/gadget
-+ fc4 net/hamradio i2c l3 acpi bluetooth serial usb/gadget
-
--subdir-y := parport char block net sound misc media cdrom hotplug
-+subdir-y := parport serial char block net sound misc media cdrom hotplug pld
- subdir-m := $(subdir-y)
-
-
-@@ -45,8 +45,12 @@
- # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
- subdir-$(CONFIG_HAMRADIO) += net/hamradio
- subdir-$(CONFIG_I2C) += i2c
-+subdir-$(CONFIG_L3) += l3
- subdir-$(CONFIG_ACPI_BOOT) += acpi
-
- subdir-$(CONFIG_BLUEZ) += bluetooth
-+subdir-$(CONFIG_SSI) += ssi
-+
-+subdir-$(CONFIG_ARCH_AT91RM9200)+= at91
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.27/drivers/acorn/char/i2c.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/char/i2c.c
-@@ -33,9 +33,13 @@
- static struct i2c_client *rtc_client;
- static const unsigned char days_in_mon[] =
- { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
--static unsigned int rtc_epoch = 1900;
-
- #define CMOS_CHECKSUM (63)
-+
-+/*
-+ * Acorn machines store the year in the static RAM at
-+ * location 128.
-+ */
- #define CMOS_YEAR (64 + 128)
-
- static inline int rtc_command(int cmd, void *data)
-@@ -49,51 +53,91 @@
- }
-
- /*
-+ * Update the century + year bytes in the CMOS RAM, ensuring
-+ * that the check byte is correctly adjusted for the change.
-+ */
-+static int rtc_update_year(unsigned int new_year)
-+{
-+ unsigned char yr[2], chk;
-+ struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr };
-+ struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
-+ int ret;
-+
-+ ret = rtc_command(MEM_READ, &cmos_check);
-+ if (ret)
-+ goto out;
-+ ret = rtc_command(MEM_READ, &cmos_year);
-+ if (ret)
-+ goto out;
-+
-+ chk -= yr[1] + yr[0];
-+
-+ yr[1] = new_year / 100;
-+ yr[0] = new_year % 100;
-+
-+ chk += yr[1] + yr[0];
-+
-+ ret = rtc_command(MEM_WRITE, &cmos_year);
-+ if (ret == 0)
-+ ret = rtc_command(MEM_WRITE, &cmos_check);
-+ out:
-+ return ret;
-+}
-+
-+
-+/*
- * Read the current RTC time and date, and update xtime.
- */
- static void get_rtc_time(struct rtc_tm *rtctm, unsigned int *year)
- {
- unsigned char ctrl, yr[2];
- struct mem rtcmem = { CMOS_YEAR, sizeof(yr), yr };
-+ int real_year, year_offset;
-
- /*
- * Ensure that the RTC is running.
- */
- rtc_command(RTC_GETCTRL, &ctrl);
- if (ctrl & 0xc0) {
-- unsigned char new_ctrl;
--
-- new_ctrl = ctrl & ~0xc0;
-+ unsigned char new_ctrl = ctrl & ~0xc0;
-
-- printk("RTC: resetting control %02X -> %02X\n",
-- ctrl, new_ctrl);
-+ printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
-+ ctrl, new_ctrl);
-
- rtc_command(RTC_SETCTRL, &new_ctrl);
- }
-
-+ if (rtc_command(RTC_GETDATETIME, rtctm) ||
-+ rtc_command(MEM_READ, &rtcmem))
-+ return;
-+
-+ real_year = yr[0];
-+
- /*
-- * Acorn machines store the year in
-- * the static RAM at location 192.
-+ * The RTC year holds the LSB two bits of the current
-+ * year, which should reflect the LSB two bits of the
-+ * CMOS copy of the year. Any difference indicates
-+ * that we have to correct the CMOS version.
- */
-- if (rtc_command(MEM_READ, &rtcmem))
-- return;
-+ year_offset = rtctm->year_off - (real_year & 3);
-+ if (year_offset < 0)
-+ /*
-+ * RTC year wrapped. Adjust it appropriately.
-+ */
-+ year_offset += 4;
-
-- if (rtc_command(RTC_GETDATETIME, rtctm))
-- return;
-+ *year = real_year + year_offset + yr[1] * 100;
-
-- *year = yr[1] * 100 + yr[0];
- }
-
- static int set_rtc_time(struct rtc_tm *rtctm, unsigned int year)
- {
-- unsigned char yr[2], leap, chk;
-- struct mem cmos_year = { CMOS_YEAR, sizeof(yr), yr };
-- struct mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
-+ unsigned char leap;
- int ret;
-
- leap = (!(year % 4) && (year % 100)) || !(year % 400);
-
-- if (rtctm->mon > 12 || rtctm->mday == 0)
-+ if (rtctm->mon > 12 || rtctm->mon == 0 || rtctm->mday == 0)
- return -EINVAL;
-
- if (rtctm->mday > (days_in_mon[rtctm->mon] + (rtctm->mon == 2 && leap)))
-@@ -102,21 +146,16 @@
- if (rtctm->hours >= 24 || rtctm->mins >= 60 || rtctm->secs >= 60)
- return -EINVAL;
-
-- ret = rtc_command(RTC_SETDATETIME, rtctm);
-- if (ret == 0) {
-- rtc_command(MEM_READ, &cmos_check);
-- rtc_command(MEM_READ, &cmos_year);
--
-- chk -= yr[1] + yr[0];
--
-- yr[1] = year / 100;
-- yr[0] = year % 100;
-+ /*
-+ * The RTC's own 2-bit year must reflect the least
-+ * significant two bits of the CMOS year.
-+ */
-+ rtctm->year_off = (year % 100) & 3;
-
-- chk += yr[1] + yr[0];
-+ ret = rtc_command(RTC_SETDATETIME, rtctm);
-+ if (ret == 0)
-+ ret = rtc_update_year(year);
-
-- rtc_command(MEM_WRITE, &cmos_year);
-- rtc_command(MEM_WRITE, &cmos_check);
-- }
- return ret;
- }
-
-@@ -166,7 +205,6 @@
- break;
-
- case RTC_RD_TIME:
-- memset(&rtctm, 0, sizeof(struct rtc_time));
- get_rtc_time(&rtc_raw, &year);
- rtctm.tm_sec = rtc_raw.secs;
- rtctm.tm_min = rtc_raw.mins;
-@@ -188,13 +226,12 @@
- rtc_raw.hours = rtctm.tm_hour;
- rtc_raw.mday = rtctm.tm_mday;
- rtc_raw.mon = rtctm.tm_mon + 1;
-- rtc_raw.year_off = 2;
- year = rtctm.tm_year + 1900;
- return set_rtc_time(&rtc_raw, year);
- break;
-
- case RTC_EPOCH_READ:
-- return put_user(rtc_epoch, (unsigned long *)arg);
-+ return put_user(1900, (unsigned long *)arg);
-
- }
- return -EINVAL;
---- linux-2.4.27/drivers/acorn/net/ether1.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/net/ether1.c
-@@ -80,7 +80,7 @@
- #define BUS_16 16
- #define BUS_8 8
-
--static const card_ids __init ether1_cids[] = {
-+static card_ids __initdata ether1_cids[] = {
- { MANU_ACORN, PROD_ACORN_ETHER1 },
- { 0xffff, 0xffff }
- };
-@@ -153,35 +153,35 @@
- length -= thislen;
-
- __asm__ __volatile__(
-- "subs %3, %3, #2
-- bmi 2f
--1: ldr %0, [%1], #2
-- mov %0, %0, lsl #16
-- orr %0, %0, %0, lsr #16
-- str %0, [%2], #4
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%1], #2
-- mov %0, %0, lsl #16
-- orr %0, %0, %0, lsr #16
-- str %0, [%2], #4
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%1], #2
-- mov %0, %0, lsl #16
-- orr %0, %0, %0, lsr #16
-- str %0, [%2], #4
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%1], #2
-- mov %0, %0, lsl #16
-- orr %0, %0, %0, lsr #16
-- str %0, [%2], #4
-- subs %3, %3, #2
-- bpl 1b
--2: adds %3, %3, #1
-- ldreqb %0, [%1]
-- streqb %0, [%2]"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+"1: ldr %0, [%1], #2 \n"
-+" mov %0, %0, lsl #16 \n"
-+" orr %0, %0, %0, lsr #16 \n"
-+" str %0, [%2], #4 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%1], #2 \n"
-+" mov %0, %0, lsl #16 \n"
-+" orr %0, %0, %0, lsr #16 \n"
-+" str %0, [%2], #4 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%1], #2 \n"
-+" mov %0, %0, lsl #16 \n"
-+" orr %0, %0, %0, lsr #16 \n"
-+" str %0, [%2], #4 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%1], #2 \n"
-+" mov %0, %0, lsl #16 \n"
-+" orr %0, %0, %0, lsr #16 \n"
-+" str %0, [%2], #4 \n"
-+" subs %3, %3, #2 \n"
-+" bpl 1b \n"
-+"2: adds %3, %3, #1 \n"
-+" ldreqb %0, [%1] \n"
-+" streqb %0, [%2] \n"
- : "=&r" (used), "=&r" (data)
- : "r" (addr), "r" (thislen), "1" (data));
-
-@@ -215,35 +215,35 @@
- length -= thislen;
-
- __asm__ __volatile__(
-- "subs %3, %3, #2
-- bmi 2f
--1: ldr %0, [%2], #4
-- strb %0, [%1], #1
-- mov %0, %0, lsr #8
-- strb %0, [%1], #1
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%2], #4
-- strb %0, [%1], #1
-- mov %0, %0, lsr #8
-- strb %0, [%1], #1
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%2], #4
-- strb %0, [%1], #1
-- mov %0, %0, lsr #8
-- strb %0, [%1], #1
-- subs %3, %3, #2
-- bmi 2f
-- ldr %0, [%2], #4
-- strb %0, [%1], #1
-- mov %0, %0, lsr #8
-- strb %0, [%1], #1
-- subs %3, %3, #2
-- bpl 1b
--2: adds %3, %3, #1
-- ldreqb %0, [%2]
-- streqb %0, [%1]"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+"1: ldr %0, [%2], #4 \n"
-+" strb %0, [%1], #1 \n"
-+" mov %0, %0, lsr #8 \n"
-+" strb %0, [%1], #1 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%2], #4 \n"
-+" strb %0, [%1], #1 \n"
-+" mov %0, %0, lsr #8 \n"
-+" strb %0, [%1], #1 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%2], #4 \n"
-+" strb %0, [%1], #1 \n"
-+" mov %0, %0, lsr #8 \n"
-+" strb %0, [%1], #1 \n"
-+" subs %3, %3, #2 \n"
-+" bmi 2f \n"
-+" ldr %0, [%2], #4 \n"
-+" strb %0, [%1], #1 \n"
-+" mov %0, %0, lsr #8 \n"
-+" strb %0, [%1], #1 \n"
-+" subs %3, %3, #2 \n"
-+" bpl 1b \n"
-+"2: adds %3, %3, #1 \n"
-+" ldreqb %0, [%2] \n"
-+" streqb %0, [%1] \n"
- : "=&r" (used), "=&r" (data)
- : "r" (addr), "r" (thislen), "1" (data));
-
---- linux-2.4.27/drivers/acorn/net/ether3.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/net/ether3.c
-@@ -75,7 +75,7 @@
- #include "ether3.h"
-
- static unsigned int net_debug = NET_DEBUG;
--static const card_ids __init ether3_cids[] = {
-+static card_ids __initdata ether3_cids[] = {
- { MANU_ANT2, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHERB },
---- linux-2.4.27/drivers/acorn/net/etherh.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/net/etherh.c
-@@ -57,7 +57,7 @@
-
- static unsigned int net_debug = NET_DEBUG;
-
--static const card_ids __init etherh_cids[] = {
-+static card_ids __initdata etherh_cids[] = {
- { MANU_ANT, PROD_ANT_ETHERM },
- { MANU_I3, PROD_I3_ETHERLAN500 },
- { MANU_I3, PROD_I3_ETHERLAN600 },
---- linux-2.4.27/drivers/acorn/scsi/cumana_1.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/scsi/cumana_1.c
-@@ -153,20 +153,20 @@
- ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
- outb(0x00, instance->io_port - 577);
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq == IRQ_NONE) {
-+ if (instance->irq == SCSI_IRQ_NONE) {
- printk("scsi%d: interrupts not enabled. for better interactive performance,\n", instance->host_no);
- printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
- }
-
- printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -185,7 +185,7 @@
- {
- int i;
-
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- linux-2.4.27/drivers/acorn/scsi/ecoscsi.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/scsi/ecoscsi.c
-@@ -106,7 +106,7 @@
- instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
- instance->io_port = 0x80ce8000;
- instance->n_io_port = 144;
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
-
- if (check_region (instance->io_port, instance->n_io_port)) {
- scsi_unregister (instance);
-@@ -130,20 +130,20 @@
- return 0;
- }
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_ecoscsi_intr, SA_INTERRUPT, "ecoscsi", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq != IRQ_NONE) {
-+ if (instance->irq != SCSI_IRQ_NONE) {
- printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
- printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
- }
-
- printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -157,7 +157,7 @@
-
- int ecoscsi_release (struct Scsi_Host *shpnt)
- {
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- linux-2.4.27/drivers/acorn/scsi/oak.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/acorn/scsi/oak.c
-@@ -97,7 +97,7 @@
- };
-
- #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
--#define OAK_IRQ(card) (IRQ_NONE)
-+#define OAK_IRQ(card) (SCSI_IRQ_NONE)
- /*
- * Function : int oakscsi_detect(Scsi_Host_Template * tpnt)
- *
-@@ -136,20 +136,20 @@
- instance->n_io_port = 255;
- request_region (instance->io_port, instance->n_io_port, "Oak SCSI");
-
-- if (instance->irq != IRQ_NONE)
-+ if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
-- instance->irq = IRQ_NONE;
-+ instance->irq = SCSI_IRQ_NONE;
- }
-
-- if (instance->irq != IRQ_NONE) {
-+ if (instance->irq != SCSI_IRQ_NONE) {
- printk("scsi%d: eek! Interrupts enabled, but I don't think\n", instance->host_no);
- printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
- }
-
- printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
-- if (instance->irq == IRQ_NONE)
-+ if (instance->irq == SCSI_IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
-@@ -172,7 +172,7 @@
- {
- int i;
-
-- if (shpnt->irq != IRQ_NONE)
-+ if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq (shpnt->irq, NULL);
- if (shpnt->io_port)
- release_region (shpnt->io_port, shpnt->n_io_port);
---- /dev/null
-+++ linux-2.4.27/drivers/at91/Makefile
-@@ -0,0 +1,23 @@
-+#
-+# Makefile for the AT91RM9200-specific Linux kernel device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (not a .c file).
-+
-+O_TARGET := at91drv.o
-+
-+subdir-y := serial net watchdog rtc usb i2c spi mtd
-+subdir-m := $(subdir-y)
-+
-+obj-$(CONFIG_SERIAL_AT91) += serial/at91serial.o
-+obj-$(CONFIG_AT91_ETHER) += net/at91net.o
-+obj-$(CONFIG_AT91_WATCHDOG) += watchdog/at91wdt.o
-+obj-$(CONFIG_AT91_RTC) += rtc/at91rtc.o
-+obj-$(CONFIG_USB) += usb/at91usb.o
-+obj-$(CONFIG_I2C_AT91) += i2c/at91i2c.o
-+obj-$(CONFIG_AT91_SPIDEV) += spi/at91spi.o
-+obj-$(CONFIG_MTD_AT91_DATAFLASH) += spi/at91spi.o mtd/at91mtd.o
-+obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += mtd/at91mtd.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/i2c/Makefile
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/i2c/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 I2C (TWI) device drivers
-+#
-+
-+O_TARGET := at91i2c.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_I2C_AT91) += at91_i2c.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/i2c/at91_i2c.c
-@@ -0,0 +1,257 @@
-+/*
-+ i2c Support for Atmel's AT91RM9200 Two-Wire Interface
-+
-+ (c) Rick Bronson
-+
-+ Borrowed heavily from original work by:
-+ Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/types.h>
-+#include <linux/delay.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+
-+#include <asm/arch/AT91RM9200_TWI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_i2c.h"
-+
-+#define DBG(x...) do {\
-+ if (debug > 0) \
-+ printk(KERN_DEBUG "i2c:" x); \
-+ } while(0)
-+
-+int debug = 0;
-+
-+static struct at91_i2c_local *at91_i2c_device;
-+
-+/*
-+ * Poll the i2c status register until the specified bit is set.
-+ * Returns 0 if timed out (100 msec)
-+ */
-+static short at91_poll_status(AT91PS_TWI twi, unsigned long bit) {
-+ int loop_cntr = 10000;
-+ do {
-+ udelay(10);
-+ } while (!(twi->TWI_SR & bit) && (--loop_cntr > 0));
-+
-+ return (loop_cntr > 0);
-+}
-+
-+/*
-+ * Generic i2c master transfer entrypoint
-+ */
-+static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
-+{
-+ struct at91_i2c_local *device = (struct at91_i2c_local *) adap->data;
-+ AT91PS_TWI twi = (AT91PS_TWI) device->base_addr;
-+
-+ struct i2c_msg *pmsg;
-+ int length;
-+ unsigned char *buf;
-+
-+ /*
-+ * i2c_smbus_xfer_emulated() in drivers/i2c/i2c-core.c states:
-+ * "... In the case of writing, we need to use only one message;
-+ * when reading, we need two..."
-+ */
-+
-+ pmsg = msgs; /* look at 1st message, it contains the address/command */
-+ if (num >= 1 && num <= 2) {
-+ DBG("xfer: doing %s %d bytes to 0x%02x - %d messages\n",
-+ pmsg->flags & I2C_M_RD ? "read" : "write",
-+ pmsg->len, pmsg->buf[0], num);
-+
-+ /* Set the TWI Master Mode Register */
-+ twi->TWI_MMR = (pmsg->addr << 16) | (pmsg->len << 8)
-+ | ((pmsg + 1)->flags & I2C_M_RD ? AT91C_TWI_MREAD : 0);
-+
-+ /* Set TWI Internal Address Register with first messages data field */
-+ if (pmsg->len == 1)
-+ twi->TWI_IADR = pmsg->buf[0];
-+ else if (pmsg->len == 2)
-+ twi->TWI_IADR = pmsg->buf[0] << 8 | pmsg->buf[1];
-+ else /* must be 3 */
-+ twi->TWI_IADR = pmsg->buf[0] << 16 | pmsg->buf[1] << 8 | pmsg->buf[2];
-+
-+ /* 1st message contains the address/command */
-+ if (num > 1)
-+ pmsg++; /* go to real message */
-+
-+ length = pmsg->len;
-+ buf = pmsg->buf;
-+ if (length && buf) { /* sanity check */
-+ if (pmsg->flags & I2C_M_RD) {
-+ twi->TWI_CR = AT91C_TWI_START;
-+ while (length--) {
-+ if (!length)
-+ twi->TWI_CR = AT91C_TWI_STOP;
-+ /* Wait until transfer is finished */
-+ if (!at91_poll_status(twi, AT91C_TWI_RXRDY)) {
-+ printk(KERN_ERR "at91_i2c: timeout 1\n");
-+ return 0;
-+ }
-+ *buf++ = twi->TWI_RHR;
-+ }
-+ if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
-+ printk(KERN_ERR "at91_i2c: timeout 2\n");
-+ return 0;
-+ }
-+ } else {
-+ twi->TWI_CR = AT91C_TWI_START;
-+ while (length--) {
-+ twi->TWI_THR = *buf++;
-+ if (!length)
-+ twi->TWI_CR = AT91C_TWI_STOP;
-+ if (!at91_poll_status(twi, AT91C_TWI_TXRDY)) {
-+ printk(KERN_ERR "at91_i2c: timeout 3\n");
-+ return 0;
-+ }
-+ }
-+ /* Wait until transfer is finished */
-+ if (!at91_poll_status(twi, AT91C_TWI_TXCOMP)) {
-+ printk(KERN_ERR "at91_i2c: timeout 4\n");
-+ return 0;
-+ }
-+ }
-+ }
-+ DBG("transfer complete\n");
-+ return num;
-+ }
-+ else {
-+ printk(KERN_ERR "at91_i2c: unexpected number of messages: %d\n", num);
-+ return 0;
-+ }
-+}
-+
-+/*
-+ * Return list of supported functionality
-+ */
-+static u32 at91_func(struct i2c_adapter *adapter)
-+{
-+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
-+ | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
-+ | I2C_FUNC_SMBUS_BLOCK_DATA;
-+}
-+
-+/*
-+ * Open
-+ */
-+static void at91_inc(struct i2c_adapter *adapter)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+/*
-+ * Close
-+ */
-+static void at91_dec(struct i2c_adapter *adapter)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+/* For now, we only handle combined mode (smbus) */
-+static struct i2c_algorithm at91_algorithm = {
-+ name:"at91 i2c",
-+ id:I2C_ALGO_SMBUS,
-+ master_xfer:at91_xfer,
-+ functionality:at91_func,
-+};
-+
-+/*
-+ * Main initialization routine
-+ */
-+static int __init i2c_at91_init(void)
-+{
-+ AT91PS_TWI twi = (AT91PS_TWI) AT91C_VA_BASE_TWI;
-+ struct at91_i2c_local *device;
-+ int rc;
-+
-+ AT91_CfgPIO_TWI();
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_TWI; /* enable peripheral clock */
-+
-+ twi->TWI_IDR = 0x3ff; /* Disable all interrupts */
-+ twi->TWI_CR = AT91C_TWI_SWRST; /* Reset peripheral */
-+ twi->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; /* Set Master mode */
-+
-+ /* Here, CKDIV = 1 and CHDIV=CLDIV ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6) */
-+ twi->TWI_CWGR = AT91C_TWI_CKDIV1 | AT91C_TWI_CLDIV3 | (AT91C_TWI_CLDIV3 << 8);
-+
-+ device = (struct at91_i2c_local *) kmalloc(sizeof(struct at91_i2c_local), GFP_KERNEL);
-+ if (device == NULL) {
-+ printk(KERN_ERR "at91_i2c: can't allocate inteface!\n");
-+ return -ENOMEM;
-+ }
-+ memset(device, 0, sizeof(struct at91_i2c_local));
-+ at91_i2c_device = device;
-+
-+ sprintf(device->adapter.name, "AT91RM9200");
-+ device->adapter.data = (void *) device;
-+ device->adapter.id = I2C_ALGO_SMBUS;
-+ device->adapter.algo = &at91_algorithm;
-+ device->adapter.algo_data = NULL;
-+ device->adapter.inc_use = at91_inc;
-+ device->adapter.dec_use = at91_dec;
-+ device->adapter.client_register = NULL;
-+ device->adapter.client_unregister = NULL;
-+ device->base_addr = AT91C_VA_BASE_TWI;
-+
-+ rc = i2c_add_adapter(&device->adapter);
-+ if (rc) {
-+ printk(KERN_ERR "at91_i2c: Adapter %s registration failed\n", device->adapter.name);
-+ device->adapter.data = NULL;
-+ kfree(device);
-+ }
-+ else
-+ printk(KERN_INFO "Found AT91 i2c\n");
-+ return rc;
-+}
-+
-+/*
-+ * Clean up routine
-+ */
-+static void __exit i2c_at91_cleanup(void)
-+{
-+ struct at91_i2c_local *device = at91_i2c_device;
-+ int rc;
-+
-+ rc = i2c_del_adapter(&device->adapter);
-+ device->adapter.data = NULL;
-+ kfree(device);
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_TWI; /* disable peripheral clock */
-+
-+ /* We aren't that prepared to deal with this... */
-+ if (rc)
-+ printk(KERN_ERR "at91_i2c: i2c_del_adapter failed (%i), that's bad!\n", rc);
-+}
-+
-+module_init(i2c_at91_init);
-+module_exit(i2c_at91_cleanup);
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("I2C driver for Atmel AT91RM9200");
-+MODULE_LICENSE("GPL");
-+MODULE_PARM(debug, "i");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/at91/i2c/at91_i2c.h
-@@ -0,0 +1,43 @@
-+/*
-+ i2c Support for Atmel's AT91RM9200 Two-Wire Interface
-+
-+ (c) Rick Bronson
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+*/
-+
-+#ifndef AT91_I2C_H
-+#define AT91_I2C_H
-+
-+#define AT91C_TWI_CLOCK 100000
-+#define AT91C_TWI_SCLOCK (10 * AT91C_MASTER_CLOCK / AT91C_TWI_CLOCK)
-+#define AT91C_TWI_CKDIV1 (2 << 16) /* TWI clock divider. NOTE: see Errata #22 */
-+
-+#if (AT91C_TWI_SCLOCK % 10) >= 5
-+#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 5)
-+#else
-+#define AT91C_TWI_CLDIV2 ((AT91C_TWI_SCLOCK / 10) - 6)
-+#endif
-+#define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2)
-+
-+#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16)
-+
-+/* Physical interface */
-+struct at91_i2c_local {
-+ struct i2c_adapter adapter;
-+ unsigned long base_addr;
-+};
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/at91/mtd/Makefile
-@@ -0,0 +1,19 @@
-+# File: drivers/at91/mtd/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 MTD devices.
-+# Includes: NAND flash (SmartMedia) & DataFlash
-+#
-+
-+O_TARGET := at91mtd.o
-+
-+export-objs :=
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_MTD_AT91_DATAFLASH) += at91_dataflash.o
-+obj-$(CONFIG_MTD_AT91_SMARTMEDIA) += at91_nand.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/mtd/at91_dataflash.c
-@@ -0,0 +1,540 @@
-+/*
-+ * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+#include <linux/slab.h>
-+#include <linux/pci.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/arch/AT91RM9200_SPI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_dataflash.h"
-+#include "../spi/at91_spi.h"
-+
-+#undef DEBUG_DATAFLASH
-+
-+/* Detected DataFlash devices */
-+static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES];
-+static int nr_devices = 0;
-+
-+/* ......................................................................... */
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+
-+static struct mtd_partition *mtd_parts = 0;
-+static int mtd_parts_nr = 0;
-+
-+#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
-+
-+static struct mtd_partition static_partitions[] =
-+{
-+ {
-+ name: "bootloader",
-+ offset: 0,
-+ size: 64 * 1024, /* 64 Kb */
-+ mask_flags: MTD_WRITEABLE /* read-only */
-+ },
-+ {
-+ name: "kernel",
-+ offset: MTDPART_OFS_NXTBLK,
-+ size: 768 *1024, /* 768 Kb */
-+ },
-+ {
-+ name: "filesystem",
-+ offset: MTDPART_OFS_NXTBLK,
-+ size: MTDPART_SIZ_FULL,
-+ }
-+};
-+
-+int parse_cmdline_partitions(struct mtd_info *master,
-+ struct mtd_partition **pparts, const char *mtd_id);
-+
-+#endif
-+
-+/* ......................................................................... */
-+
-+/* Allocate a single SPI transfer descriptor. We're assuming that if multiple
-+ SPI transfers occur at the same time, spi_access_bus() will serialize them.
-+ If this is not valid, then either (i) each dataflash 'priv' structure
-+ needs it's own transfer descriptor, (ii) we lock this one, or (iii) use
-+ another mechanism. */
-+static struct spi_transfer_list* spi_transfer_desc;
-+
-+/*
-+ * Perform a SPI transfer to access the DataFlash device.
-+ */
-+static int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len,
-+ char* txnext, int txnext_len, char* rxnext, int rxnext_len)
-+{
-+ struct spi_transfer_list* list = spi_transfer_desc;
-+
-+ list->tx[0] = tx; list->txlen[0] = tx_len;
-+ list->rx[0] = rx; list->rxlen[0] = rx_len;
-+
-+ list->tx[1] = txnext; list->txlen[1] = txnext_len;
-+ list->rx[1] = rxnext; list->rxlen[1] = rxnext_len;
-+
-+ list->nr_transfers = nr;
-+
-+ return spi_transfer(list);
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Poll the DataFlash device until it is READY.
-+ */
-+static void at91_dataflash_waitready(void)
-+{
-+ char* command = kmalloc(2, GFP_KERNEL);
-+
-+ if (!command)
-+ return;
-+
-+ do {
-+ command[0] = OP_READ_STATUS;
-+ command[1] = 0;
-+
-+ do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
-+ } while ((command[1] & 0x80) == 0);
-+
-+ kfree(command);
-+}
-+
-+/*
-+ * Return the status of the DataFlash device.
-+ */
-+static unsigned short at91_dataflash_status(void)
-+{
-+ unsigned short status;
-+ char* command = kmalloc(2, GFP_KERNEL);
-+
-+ if (!command)
-+ return 0;
-+
-+ command[0] = OP_READ_STATUS;
-+ command[1] = 0;
-+
-+ do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
-+ status = command[1];
-+
-+ kfree(command);
-+ return status;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Erase blocks of flash.
-+ */
-+static int at91_dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int pageaddr;
-+ char* command;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_erase: addr=%i len=%i\n", instr->addr, instr->len);
-+#endif
-+
-+ /* Sanity checks */
-+ if (instr->addr + instr->len > mtd->size)
-+ return -EINVAL;
-+ if ((instr->len % mtd->erasesize != 0) || (instr->len % priv->page_size != 0))
-+ return -EINVAL;
-+ if ((instr->addr % priv->page_size) != 0)
-+ return -EINVAL;
-+
-+ command = kmalloc(4, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ while (instr->len > 0) {
-+ /* Calculate flash page address */
-+ pageaddr = (instr->addr / priv->page_size) << priv->page_offset;
-+
-+ command[0] = OP_ERASE_PAGE;
-+ command[1] = (pageaddr & 0x00FF0000) >> 16;
-+ command[2] = (pageaddr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("ERASE: (%x) %x %x %x [%i]\n", command[0], command[1], command[2], command[3], pageaddr);
-+#endif
-+
-+ /* Send command to SPI device */
-+ spi_access_bus(priv->spi);
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+
-+ at91_dataflash_waitready(); /* poll status until ready */
-+ spi_release_bus(priv->spi);
-+
-+ instr->addr += priv->page_size; /* next page */
-+ instr->len -= priv->page_size;
-+ }
-+
-+ kfree(command);
-+
-+ /* Inform MTD subsystem that erase is complete */
-+ instr->state = MTD_ERASE_DONE;
-+ if (instr->callback)
-+ instr->callback(instr);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Read from the DataFlash device.
-+ * from : Start offset in flash device
-+ * len : Amount to read
-+ * retlen : About of data actually read
-+ * buf : Buffer containing the data
-+ */
-+static int at91_dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int addr;
-+ char* command;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_read: %lli .. %lli\n", from, from+len);
-+#endif
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len)
-+ return 0;
-+ if (from + len > mtd->size)
-+ return -EINVAL;
-+
-+ /* Calculate flash page/byte address */
-+ addr = (((unsigned)from / priv->page_size) << priv->page_offset) + ((unsigned)from % priv->page_size);
-+
-+ command = kmalloc(8, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ command[0] = OP_READ_CONTINUOUS;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = (addr & 0x000000FF);
-+#ifdef DEBUG_DATAFLASH
-+ printk("READ: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+
-+ /* Send command to SPI device */
-+ spi_access_bus(priv->spi);
-+ do_spi_transfer(2, command, 8, command, 8, buf, len, buf, len);
-+ spi_release_bus(priv->spi);
-+
-+ *retlen = len;
-+ kfree(command);
-+ return 0;
-+}
-+
-+/*
-+ * Write to the DataFlash device.
-+ * to : Start offset in flash device
-+ * len : Amount to write
-+ * retlen : Amount of data actually written
-+ * buf : Buffer containing the data
-+ */
-+static int at91_dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
-+{
-+ struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
-+ unsigned int pageaddr, addr, offset, writelen;
-+ size_t remaining;
-+ u_char *writebuf;
-+ unsigned short status;
-+ int res = 0;
-+ char* command;
-+ char* tmpbuf = NULL;
-+
-+#ifdef DEBUG_DATAFLASH
-+ printk("dataflash_write: %lli .. %lli\n", to, to+len);
-+#endif
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len)
-+ return 0;
-+ if (to + len > mtd->size)
-+ return -EINVAL;
-+
-+ command = kmalloc(4, GFP_KERNEL);
-+ if (!command)
-+ return -ENOMEM;
-+
-+ pageaddr = ((unsigned)to / priv->page_size);
-+ offset = ((unsigned)to % priv->page_size);
-+ if (offset + len > priv->page_size)
-+ writelen = priv->page_size - offset;
-+ else
-+ writelen = len;
-+ writebuf = buf;
-+ remaining = len;
-+
-+ /* Allocate temporary buffer */
-+ tmpbuf = kmalloc(priv->page_size, GFP_KERNEL);
-+ if (!tmpbuf) {
-+ kfree(command);
-+ return -ENOMEM;
-+ }
-+
-+ /* Gain access to the SPI bus */
-+ spi_access_bus(priv->spi);
-+
-+ while (remaining > 0) {
-+#ifdef DEBUG_DATAFLASH
-+ printk("write @ %i:%i len=%i\n", pageaddr, offset, writelen);
-+#endif
-+
-+ /* (1) Transfer to Buffer1 */
-+ if (writelen != priv->page_size) {
-+ addr = pageaddr << priv->page_offset;
-+ command[0] = OP_TRANSFER_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("TRANSFER: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+ at91_dataflash_waitready();
-+ }
-+
-+ /* (2) Program via Buffer1 */
-+ addr = (pageaddr << priv->page_offset) + offset;
-+ command[0] = OP_PROGRAM_VIA_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = (addr & 0x000000FF);
-+#ifdef DEBUG_DATAFLASH
-+ printk("PROGRAM: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(2, command, 4, command, 4, writebuf, writelen, tmpbuf, writelen);
-+ at91_dataflash_waitready();
-+
-+ /* (3) Compare to Buffer1 */
-+ addr = pageaddr << priv->page_offset;
-+ command[0] = OP_COMPARE_BUF1;
-+ command[1] = (addr & 0x00FF0000) >> 16;
-+ command[2] = (addr & 0x0000FF00) >> 8;
-+ command[3] = 0;
-+#ifdef DEBUG_DATAFLASH
-+ printk("COMPARE: (%x) %x %x %x\n", command[0], command[1], command[2], command[3]);
-+#endif
-+ do_spi_transfer(1, command, 4, command, 4, NULL, 0, NULL, 0);
-+ at91_dataflash_waitready();
-+
-+ /* Get result of the compare operation */
-+ status = at91_dataflash_status();
-+ if ((status & 0x40) == 1) {
-+ printk("at91_dataflash: Write error on page %i\n", pageaddr);
-+ remaining = 0;
-+ res = -EIO;
-+ }
-+
-+ remaining = remaining - writelen;
-+ pageaddr++;
-+ offset = 0;
-+ writebuf += writelen;
-+ *retlen += writelen;
-+
-+ if (remaining > priv->page_size)
-+ writelen = priv->page_size;
-+ else
-+ writelen = remaining;
-+ }
-+
-+ /* Release SPI bus */
-+ spi_release_bus(priv->spi);
-+
-+ kfree(tmpbuf);
-+ kfree(command);
-+ return res;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Initialize and register DataFlash device with MTD subsystem.
-+ */
-+static int add_dataflash(int channel, char *name, int IDsize, int nr_pages, int pagesize, int pageoffset)
-+{
-+ struct mtd_info *device;
-+ struct dataflash_local *priv;
-+#ifdef CONFIG_MTD_CMDLINE_PARTS
-+ char mtdID[14];
-+#endif
-+
-+ if (nr_devices >= DATAFLASH_MAX_DEVICES) {
-+ printk(KERN_ERR "at91_dataflash: Too many devices detected\n");
-+ return 0;
-+ }
-+
-+ device = (struct mtd_info *) kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+ if (!device)
-+ return -ENOMEM;
-+ memset(device, 0, sizeof(struct mtd_info));
-+
-+ device->name = name;
-+ device->size = nr_pages * pagesize;
-+ device->erasesize = pagesize;
-+ device->module = THIS_MODULE;
-+ device->type = MTD_NORFLASH;
-+ device->flags = MTD_CAP_NORFLASH;
-+ device->erase = at91_dataflash_erase;
-+ device->read = at91_dataflash_read;
-+ device->write = at91_dataflash_write;
-+
-+ priv = (struct dataflash_local *) kmalloc(sizeof(struct dataflash_local), GFP_KERNEL);
-+ if (!priv) {
-+ kfree(device);
-+ return -ENOMEM;
-+ }
-+ memset(priv, 0, sizeof(struct dataflash_local));
-+
-+ priv->spi = channel;
-+ priv->page_size = pagesize;
-+ priv->page_offset = pageoffset;
-+ device->priv = priv;
-+
-+ mtd_devices[nr_devices] = device;
-+ nr_devices++;
-+ printk("at91_dataflash: %s detected [spi%i] (%i bytes)\n", name, channel, device->size);
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+#ifdef CONFIG_MTD_CMDLINE_PARTS
-+ sprintf(mtdID, "dataflash%i", nr_devices-1);
-+ mtd_parts_nr = parse_cmdline_partitions(device, &mtd_parts, mtdID);
-+#endif
-+ if (mtd_parts_nr <= 0) {
-+ mtd_parts = static_partitions;
-+ mtd_parts_nr = NB_OF(static_partitions);
-+ }
-+
-+ if (mtd_parts_nr > 0) {
-+#ifdef DATAFLASH_ALWAYS_ADD_DEVICE
-+ add_mtd_device(device);
-+#endif
-+ return add_mtd_partitions(device, mtd_parts, mtd_parts_nr);
-+ }
-+#endif
-+ return add_mtd_device(device); /* add whole device */
-+}
-+
-+/*
-+ * Detect and initialize DataFlash device connected to specified SPI channel.
-+ *
-+ * Device Density ID code Nr Pages Page Size Page offset
-+ * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9
-+ * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9
-+ * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9
-+ * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9
-+ * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10
-+ * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10
-+ * AT45DB0642 64Mbit (8M) xx1111xx (0x3c) 8192 1056 11
-+ * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11
-+ */
-+static int at91_dataflash_detect(int channel)
-+{
-+ int res = 0;
-+ unsigned short status;
-+
-+ spi_access_bus(channel);
-+ status = at91_dataflash_status();
-+ if (status != 0xff) { /* no dataflash device there */
-+ switch (status & 0x3c) {
-+ case 0x0c: /* 0 0 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB011B", SZ_128K, 512, 264, 9);
-+ break;
-+ case 0x14: /* 0 1 0 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB021B", SZ_256K, 1025, 264, 9);
-+ break;
-+ case 0x1c: /* 0 1 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB041B", SZ_512K, 2048, 264, 9);
-+ break;
-+ case 0x24: /* 1 0 0 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB081B", SZ_1M, 4096, 264, 9);
-+ break;
-+ case 0x2c: /* 1 0 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB161B", SZ_2M, 4096, 528, 10);
-+ break;
-+ case 0x34: /* 1 1 0 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB321B", SZ_4M, 8192, 528, 10);
-+ break;
-+ case 0x3c: /* 1 1 1 1 */
-+ res = add_dataflash(channel, "Atmel AT45DB642", SZ_8M, 8192, 1056, 11);
-+ break;
-+// Currently unsupported since Atmel removed the "Main Memory Program via Buffer" commands.
-+// case 0x10: /* 0 1 0 0 */
-+// res = add_dataflash(channel, "Atmel AT45DB1282", SZ_16M, 16384, 1056, 11);
-+// break;
-+ default:
-+ printk(KERN_ERR "at91_dataflash: Unknown device (%x)\n", status & 0x3c);
-+ }
-+ }
-+ spi_release_bus(channel);
-+
-+ return res;
-+}
-+
-+static int __init at91_dataflash_init(void)
-+{
-+ spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
-+ if (!spi_transfer_desc)
-+ return -ENOMEM;
-+
-+ /* DataFlash (SPI chip select 0) */
-+ at91_dataflash_detect(0);
-+
-+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-+ /* DataFlash card (SPI chip select 3) */
-+ AT91_CfgPIO_DataFlashCard();
-+ at91_dataflash_detect(3);
-+#endif
-+
-+ return 0;
-+}
-+
-+static void __exit at91_dataflash_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) {
-+ if (mtd_devices[i]) {
-+#ifdef CONFIG_MTD_PARTITIONS
-+ del_mtd_partitions(mtd_devices[i]);
-+#else
-+ del_mtd_device(mtd_devices[i]);
-+#endif
-+ kfree(mtd_devices[i]->priv);
-+ kfree(mtd_devices[i]);
-+ }
-+ }
-+ nr_devices = 0;
-+ kfree(spi_transfer_desc);
-+}
-+
-+
-+EXPORT_NO_SYMBOLS;
-+
-+module_init(at91_dataflash_init);
-+module_exit(at91_dataflash_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("DataFlash driver for Atmel AT91RM9200")
---- /dev/null
-+++ linux-2.4.27/drivers/at91/mtd/at91_dataflash.h
-@@ -0,0 +1,43 @@
-+/*
-+ * Atmel DataFlash driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_DATAFLASH_H
-+#define AT91_DATAFLASH_H
-+
-+#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */
-+#undef DATAFLASH_ALWAYS_ADD_DEVICE /* always add whole device when using partitions? */
-+
-+#define OP_READ_CONTINUOUS 0xE8
-+#define OP_READ_PAGE 0xD2
-+#define OP_READ_BUFFER1 0xD4
-+#define OP_READ_BUFFER2 0xD6
-+#define OP_READ_STATUS 0xD7
-+
-+#define OP_ERASE_PAGE 0x81
-+#define OP_ERASE_BLOCK 0x50
-+
-+#define OP_TRANSFER_BUF1 0x53
-+#define OP_TRANSFER_BUF2 0x55
-+#define OP_COMPARE_BUF1 0x60
-+#define OP_COMPARE_BUF2 0x61
-+
-+#define OP_PROGRAM_VIA_BUF1 0x82
-+#define OP_PROGRAM_VIA_BUF2 0x85
-+
-+struct dataflash_local
-+{
-+ int spi; /* SPI chip-select number */
-+
-+ unsigned int page_size; /* number of bytes per page */
-+ unsigned short page_offset; /* page offset in flash address */
-+};
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/at91/mtd/at91_nand.c
-@@ -0,0 +1,328 @@
-+/*
-+ * drivers/at91/mtd/at91_nand.c
-+ *
-+ * Copyright (c) 2003 Rick Bronson
-+ *
-+ * Derived from drivers/mtd/nand/autcpu12.c
-+ * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
-+ *
-+ * Derived from drivers/mtd/spia.c
-+ * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/io.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/sizes.h>
-+
-+#include <asm/arch/pio.h>
-+#include "at91_nand.h"
-+
-+/*
-+ * MTD structure for AT91 board
-+ */
-+static struct mtd_info *at91_mtd = NULL;
-+static struct nand_chip *my_nand_chip = NULL;
-+
-+static int at91_fio_base;
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+
-+/*
-+ * Define partitions for flash devices
-+ */
-+
-+static struct mtd_partition partition_info32k[] = {
-+ { name: "AT91 NAND partition 1, kernel",
-+ offset: 0,
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 2, filesystem",
-+ offset: 1 * SZ_1M,
-+ size: 16 * SZ_1M },
-+ { name: "AT91 NAND partition 3a, storage",
-+ offset: (1 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3b, storage",
-+ offset: (2 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3c, storage",
-+ offset: (3 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 3d, storage",
-+ offset: (4 * SZ_1M) + (16 * SZ_1M),
-+ size: 1 * SZ_1M },
-+};
-+
-+static struct mtd_partition partition_info64k[] = {
-+ { name: "AT91 NAND partition 1, kernel",
-+ offset: 0,
-+ size: 1 * SZ_1M },
-+ { name: "AT91 NAND partition 2, filesystem",
-+ offset: 1 * SZ_1M,
-+ size: 16 * SZ_1M },
-+ { name: "AT91 NAND partition 3, storage",
-+ offset: (1 * SZ_1M) + (16 * SZ_1M),
-+ size: 47 * SZ_1M },
-+};
-+
-+#endif
-+
-+/*
-+ * Hardware specific access to control-lines
-+ */
-+static void at91_hwcontrol(int cmd)
-+{
-+ struct nand_chip *my_nand = my_nand_chip;
-+ switch(cmd)
-+ {
-+ case NAND_CTL_SETCLE:
-+ my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_CLE;
-+ break;
-+ case NAND_CTL_CLRCLE:
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ break;
-+ case NAND_CTL_SETALE:
-+ my_nand->IO_ADDR_W = at91_fio_base + AT91_SMART_MEDIA_ALE;
-+ break;
-+ case NAND_CTL_CLRALE:
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ break;
-+ case NAND_CTL_SETNCE:
-+ break;
-+ case NAND_CTL_CLRNCE:
-+ break;
-+ }
-+}
-+
-+/*
-+ * Send command to NAND device
-+ */
-+static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
-+{
-+ register struct nand_chip *my_nand = mtd->priv;
-+
-+ /* Begin command latch cycle */
-+ register unsigned long NAND_IO_ADDR = my_nand->IO_ADDR_W + AT91_SMART_MEDIA_CLE;
-+
-+ /*
-+ * Write out the command to the device.
-+ */
-+ if (command != NAND_CMD_SEQIN)
-+ writeb (command, NAND_IO_ADDR);
-+ else {
-+ if (mtd->oobblock == 256 && column >= 256) {
-+ column -= 256;
-+ writeb (NAND_CMD_RESET, NAND_IO_ADDR);
-+ writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ else
-+ if (mtd->oobblock == 512 && column >= 256) {
-+ if (column < 512) {
-+ column -= 256;
-+ writeb (NAND_CMD_READ1, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ } else {
-+ column -= 512;
-+ writeb (NAND_CMD_READOOB, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ } else {
-+ writeb (NAND_CMD_READ0, NAND_IO_ADDR);
-+ writeb (NAND_CMD_SEQIN, NAND_IO_ADDR);
-+ }
-+ }
-+
-+ /* Set ALE and clear CLE to start address cycle */
-+ NAND_IO_ADDR = at91_fio_base;
-+
-+ if (column != -1 || page_addr != -1)
-+ NAND_IO_ADDR += AT91_SMART_MEDIA_ALE;
-+
-+ /* Serially input address */
-+ if (column != -1)
-+ writeb (column, NAND_IO_ADDR);
-+ if (page_addr != -1) {
-+ writeb ((unsigned char) (page_addr & 0xff), NAND_IO_ADDR);
-+ writeb ((unsigned char) ((page_addr >> 8) & 0xff), NAND_IO_ADDR);
-+ /* One more address cycle for higher density devices */
-+ if (mtd->size & 0x0c000000) {
-+ writeb ((unsigned char) ((page_addr >> 16) & 0x0f), NAND_IO_ADDR);
-+ }
-+ }
-+
-+ /* wait until command is processed */
-+ while (!my_nand->dev_ready())
-+ ;
-+}
-+
-+/*
-+ * Read the Device Ready pin.
-+ */
-+static int at91_device_ready(void)
-+{
-+ return AT91_PIO_SmartMedia_RDY();
-+}
-+/*
-+ * Main initialization routine
-+ */
-+static int __init at91_init (void)
-+{
-+ struct nand_chip *my_nand;
-+ int err = 0;
-+
-+ /* Allocate memory for MTD device structure and private data */
-+ at91_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
-+ if (!at91_mtd) {
-+ printk ("Unable to allocate AT91 NAND MTD device structure.\n");
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ /* map physical adress */
-+ at91_fio_base = (unsigned long) ioremap(AT91_SMARTMEDIA_BASE, SZ_8M);
-+ if(!at91_fio_base) {
-+ printk("ioremap AT91 NAND failed\n");
-+ err = -EIO;
-+ goto out_mtd;
-+ }
-+
-+ /* Get pointer to private data */
-+ my_nand_chip = my_nand = (struct nand_chip *) (&at91_mtd[1]);
-+
-+ /* Initialize structures */
-+ memset((char *) at91_mtd, 0, sizeof(struct mtd_info));
-+ memset((char *) my_nand, 0, sizeof(struct nand_chip));
-+
-+ /* Link the private data with the MTD structure */
-+ at91_mtd->priv = my_nand;
-+
-+ /* Set address of NAND IO lines */
-+ my_nand->IO_ADDR_R = at91_fio_base;
-+ my_nand->IO_ADDR_W = at91_fio_base;
-+ my_nand->hwcontrol = at91_hwcontrol;
-+ my_nand->dev_ready = at91_device_ready;
-+ my_nand->cmdfunc = at91_nand_command; /* we need our own */
-+ my_nand->eccmode = NAND_ECC_SOFT; /* enable ECC */
-+ /* 20 us command delay time */
-+ my_nand->chip_delay = 20;
-+
-+ /* Setup Smart Media, first enable the address range of CS3 */
-+ AT91_SYS->EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia;
-+ /* set the bus interface characteristics based on
-+ tDS Data Set up Time 30 - ns
-+ tDH Data Hold Time 20 - ns
-+ tALS ALE Set up Time 20 - ns
-+ 16ns at 60 MHz ~= 3 */
-+#define AT91C_SM_ID_RWH (5 << 28) /* orig = 5 */
-+#define AT91C_SM_RWH (1 << 28) /* orig = 1 */
-+#define AT91C_SM_RWS (0 << 24) /* orig = 0 */
-+#define AT91C_SM_TDF (1 << 8) /* orig = 1 */
-+#define AT91C_SM_NWS (5) /* orig = 3 */
-+ AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS |
-+ AT91C_SMC2_ACSS_STANDARD |
-+ AT91C_SMC2_DBW_8 | AT91C_SM_TDF |
-+ AT91C_SMC2_WSEN | AT91C_SM_NWS);
-+
-+ AT91_CfgPIO_SmartMedia();
-+
-+ if (AT91_PIO_SmartMedia_CardDetect())
-+ printk ("No ");
-+ printk ("SmartMedia card inserted.\n");
-+
-+ /* Scan to find existance of the device */
-+ if (nand_scan (at91_mtd)) {
-+ err = -ENXIO;
-+ goto out_ior;
-+ }
-+
-+ /* Allocate memory for internal data buffer */
-+ my_nand->data_buf = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
-+ if (!my_nand->data_buf) {
-+ printk ("Unable to allocate AT91 NAND data buffer.\n");
-+ err = -ENOMEM;
-+ goto out_ior;
-+ }
-+
-+ /* Allocate memory for internal data buffer */
-+ my_nand->data_cache = kmalloc (sizeof(u_char) * (at91_mtd->oobblock + at91_mtd->oobsize), GFP_KERNEL);
-+ if (!my_nand->data_cache) {
-+ printk ("Unable to allocate AT91 NAND data cache.\n");
-+ err = -ENOMEM;
-+ goto out_buf;
-+ }
-+ my_nand->cache_page = -1;
-+
-+#ifdef CONFIG_MTD_PARTITIONS
-+ /* Register the partitions */
-+ switch(at91_mtd->size)
-+ {
-+ case SZ_32M:
-+ err = add_mtd_partitions(at91_mtd, partition_info32k,
-+ ARRAY_SIZE (partition_info32k));
-+ break;
-+ case SZ_64M:
-+ err = add_mtd_partitions(at91_mtd, partition_info64k,
-+ ARRAY_SIZE (partition_info64k));
-+ break;
-+ default:
-+ printk ("Unsupported SmartMedia device\n");
-+ err = -ENXIO;
-+ goto out_cac;
-+ }
-+#else
-+ err = add_mtd_device(at91_mtd);
-+#endif
-+ goto out;
-+
-+ out_cac:
-+ kfree (my_nand->data_cache);
-+ out_buf:
-+ kfree (my_nand->data_buf);
-+ out_ior:
-+ iounmap((void *)at91_fio_base);
-+ out_mtd:
-+ kfree (at91_mtd);
-+ out:
-+ return err;
-+}
-+
-+/*
-+ * Clean up routine
-+ */
-+static void __exit at91_cleanup (void)
-+{
-+ struct nand_chip *my_nand = (struct nand_chip *) &at91_mtd[1];
-+
-+ /* Unregister partitions */
-+ del_mtd_partitions(at91_mtd);
-+
-+ /* Unregister the device */
-+ del_mtd_device (at91_mtd);
-+
-+ /* Free internal data buffers */
-+ kfree (my_nand->data_buf);
-+ kfree (my_nand->data_cache);
-+
-+ /* unmap physical adress */
-+ iounmap((void *)at91_fio_base);
-+
-+ /* Free the MTD device structure */
-+ kfree (at91_mtd);
-+}
-+
-+module_init(at91_init);
-+module_exit(at91_cleanup);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on ATMEL AT91RM9200");
---- /dev/null
-+++ linux-2.4.27/drivers/at91/mtd/at91_nand.h
-@@ -0,0 +1,27 @@
-+/*
-+ * AT91RM9200 specific NAND (SmartMedia) defines
-+ *
-+ * (c) 2003 Rick Bronson
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef __AT91_NAND_H
-+#define __AT91_NAND_H
-+
-+#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */
-+#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/at91/net/Makefile
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/net/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 ethernet device drivers
-+#
-+
-+O_TARGET := at91net.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_ETHER) += at91_ether.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/net/at91_ether.c
-@@ -0,0 +1,875 @@
-+/*
-+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
-+ * Initial version by Rick Bronson 01/11/2003
-+ *
-+ * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
-+ * (Polaroid Corporation)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/config.h>
-+#include <linux/mii.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/skbuff.h>
-+#include <asm/io.h>
-+#include <linux/pci.h>
-+#include <linux/crc32.h>
-+#include <asm/uaccess.h>
-+#include <linux/ethtool.h>
-+
-+#include <asm/arch/AT91RM9200_EMAC.h>
-+#include <asm/arch/pio.h>
-+#include "at91_ether.h"
-+
-+static struct net_device at91_dev;
-+
-+/* ........................... PHY INTERFACE ........................... */
-+
-+/*
-+ * Enable the MDIO bit in MAC control register
-+ * When not called from an interrupt-handler, access to the PHY must be
-+ * protected by a spinlock.
-+ */
-+static void enable_mdi(AT91PS_EMAC regs)
-+{
-+ regs->EMAC_CTL |= AT91C_EMAC_MPE; /* enable management port */
-+}
-+
-+/*
-+ * Disable the MDIO bit in the MAC control register
-+ */
-+static void disable_mdi(AT91PS_EMAC regs)
-+{
-+ regs->EMAC_CTL &= ~AT91C_EMAC_MPE; /* disable management port */
-+}
-+
-+/*
-+ * Write value to the a PHY register
-+ * Note: MDI interface is assumed to already have been enabled.
-+ */
-+static void write_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int value)
-+{
-+ regs->EMAC_MAN = (AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_W
-+ | ((phy_addr & 0x1f) << 23) | (address << 18)) + (value & 0xffff);
-+
-+ /* Wait until IDLE bit in Network Status register is cleared */
-+ // TODO: Enforce some maximum loop-count?
-+ while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
-+}
-+
-+/*
-+ * Read value stored in a PHY register.
-+ * Note: MDI interface is assumed to already have been enabled.
-+ */
-+static void read_phy(AT91PS_EMAC regs, unsigned char phy_addr, unsigned char address, unsigned int *value)
-+{
-+ regs->EMAC_MAN = AT91C_EMAC_HIGH | AT91C_EMAC_CODE_802_3 | AT91C_EMAC_RW_R
-+ | ((phy_addr & 0x1f) << 23) | (address << 18);
-+
-+ /* Wait until IDLE bit in Network Status register is cleared */
-+ // TODO: Enforce some maximum loop-count?
-+ while (!(regs->EMAC_SR & AT91C_EMAC_IDLE)) { barrier(); }
-+
-+ *value = (regs->EMAC_MAN & 0x0000ffff);
-+}
-+
-+/* ........................... PHY MANAGEMENT .......................... */
-+
-+/*
-+ * Access the PHY to determine the current Link speed and Mode, and update the
-+ * MAC accordingly.
-+ * If no link or auto-negotiation is busy, then no changes are made.
-+ * Returns: 0 : OK
-+ * -1 : No link
-+ * -2 : AutoNegotiation still in progress
-+ */
-+static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) {
-+ unsigned int bmsr, bmcr, lpa, mac_cfg;
-+ unsigned int speed, duplex;
-+
-+ /* Link status is latched, so read twice to get current value */
-+ read_phy(regs, 0, MII_BMSR, &bmsr);
-+ read_phy(regs, 0, MII_BMSR, &bmsr);
-+ if (!(bmsr & BMSR_LSTATUS)) return -1; /* no link */
-+
-+ read_phy(regs, 0, MII_BMCR, &bmcr);
-+ if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
-+ if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */
-+
-+ read_phy(regs, 0, MII_LPA, &lpa);
-+ if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-+ else speed = SPEED_10;
-+ if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-+ else duplex = DUPLEX_HALF;
-+ } else {
-+ speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-+ duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-+ }
-+
-+ /* Update the MAC */
-+ mac_cfg = regs->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
-+ if (speed == SPEED_100) {
-+ if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
-+ else /* 100 Half Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_SPD;
-+ } else {
-+ if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
-+ regs->EMAC_CFG = mac_cfg | AT91C_EMAC_FD;
-+ else /* 10 Half Duplex */
-+ regs->EMAC_CFG = mac_cfg;
-+ }
-+
-+ printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-+ return 0;
-+}
-+
-+/*
-+ * Handle interrupts from the PHY
-+ */
-+static void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = (struct net_device *) dev_id;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
-+ int status;
-+ unsigned int phy;
-+
-+ enable_mdi(emac);
-+ if (lp->phy_type == MII_DM9161_ID)
-+ read_phy(emac, 0, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */
-+ else if (lp->phy_type == MII_LXT971A_ID)
-+ read_phy(emac, 0, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */
-+
-+ status = AT91_SYS->PIOC_ISR; /* acknowledge interrupt in PIO */
-+
-+ status = update_linkspeed(dev, emac);
-+ if (status == -1) { /* link is down */
-+ netif_carrier_off(dev);
-+ printk(KERN_INFO "%s: Link down.\n", dev->name);
-+ } else if (status == -2) { /* auto-negotiation in progress */
-+ /* Do nothing - another interrupt generated when negotiation complete */
-+ } else { /* link is operational */
-+ netif_carrier_on(dev);
-+ }
-+ disable_mdi(emac);
-+}
-+
-+/*
-+ * Initialize and enable the PHY interrupt when link-state changes
-+ */
-+static void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int dsintr, status;
-+
-+ // TODO: Check error code. Really need a generic PIO (interrupt)
-+ // layer since we're really only interested in the PC4 (DK) or PC2 (CSB337) line.
-+ (void) request_irq(AT91C_ID_PIOC, at91ether_phy_interrupt, 0, dev->name, dev);
-+
-+ status = AT91_SYS->PIOC_ISR; /* clear any pending PIO interrupts */
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_IER = AT91C_PIO_PC2; /* Enable interrupt */
-+#else
-+ AT91_SYS->PIOC_IER = AT91C_PIO_PC4; /* Enable interrupt */
-+#endif
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
-+ read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
-+ dsintr = dsintr & ~0xf00; /* clear bits 8..11 */
-+ write_phy(regs, 0, MII_DSINTR_REG, dsintr);
-+ }
-+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-+ read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
-+ dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */
-+ write_phy(regs, 0, MII_ISINTE_REG, dsintr);
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+}
-+
-+/*
-+ * Disable the PHY interrupt
-+ */
-+static void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int dsintr;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ if (lp->phy_type == MII_DM9161_ID) { /* for Davicom PHY */
-+ read_phy(regs, 0, MII_DSINTR_REG, &dsintr);
-+ dsintr = dsintr | 0xf00; /* set bits 8..11 */
-+ write_phy(regs, 0, MII_DSINTR_REG, dsintr);
-+ }
-+ else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */
-+ read_phy(regs, 0, MII_ISINTE_REG, &dsintr);
-+ dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */
-+ write_phy(regs, 0, MII_ISINTE_REG, dsintr);
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_IDR = AT91C_PIO_PC2; /* Disable interrupt */
-+#else
-+ AT91_SYS->PIOC_IDR = AT91C_PIO_PC4; /* Disable interrupt */
-+#endif
-+ free_irq(AT91C_ID_PIOC, dev); /* Free interrupt handler */
-+}
-+
-+/*
-+ * Perform a software reset of the PHY.
-+ */
-+static void reset_phy(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ unsigned int bmcr;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ /* Perform PHY reset */
-+ write_phy(regs, 0, MII_BMCR, BMCR_RESET);
-+
-+ /* Wait until PHY reset is complete */
-+ do {
-+ read_phy(regs, 0, MII_BMCR, &bmcr);
-+ } while (!(bmcr && BMCR_RESET));
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+}
-+
-+
-+/* ......................... ADDRESS MANAGEMENT ........................ */
-+
-+/*
-+ * Set the ethernet MAC address in dev->dev_addr
-+ */
-+static void get_mac_address(struct net_device *dev) {
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ char addr[6];
-+ unsigned int hi, lo;
-+
-+ /* Check if bootloader set address in Specific-Address 1 */
-+ hi = regs->EMAC_SA1H;
-+ lo = regs->EMAC_SA1L;
-+ addr[0] = (lo & 0xff);
-+ addr[1] = (lo & 0xff00) >> 8;
-+ addr[2] = (lo & 0xff0000) >> 16;
-+ addr[3] = (lo & 0xff000000) >> 24;
-+ addr[4] = (hi & 0xff);
-+ addr[5] = (hi & 0xff00) >> 8;
-+
-+ if (is_valid_ether_addr(addr)) {
-+ memcpy(dev->dev_addr, &addr, 6);
-+ return;
-+ }
-+
-+ /* Check if bootloader set address in Specific-Address 2 */
-+ hi = regs->EMAC_SA2H;
-+ lo = regs->EMAC_SA2L;
-+ addr[0] = (lo & 0xff);
-+ addr[1] = (lo & 0xff00) >> 8;
-+ addr[2] = (lo & 0xff0000) >> 16;
-+ addr[3] = (lo & 0xff000000) >> 24;
-+ addr[4] = (hi & 0xff);
-+ addr[5] = (hi & 0xff00) >> 8;
-+
-+ if (is_valid_ether_addr(addr)) {
-+ memcpy(dev->dev_addr, &addr, 6);
-+ return;
-+ }
-+}
-+
-+/*
-+ * Program the hardware MAC address from dev->dev_addr.
-+ */
-+static void update_mac_address(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ regs->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]);
-+ regs->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]);
-+}
-+
-+/*
-+ * Store the new hardware address in dev->dev_addr, and update the MAC.
-+ */
-+static int set_mac_address(struct net_device *dev, void* addr)
-+{
-+ struct sockaddr *address = addr;
-+
-+ if (!is_valid_ether_addr(address->sa_data))
-+ return -EADDRNOTAVAIL;
-+
-+ memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-+ update_mac_address(dev);
-+
-+ printk("%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
-+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Add multicast addresses to the internal multicast-hash table.
-+ */
-+static void at91ether_sethashtable(struct net_device *dev, AT91PS_EMAC regs)
-+{
-+ struct dev_mc_list *curr;
-+ unsigned char mc_filter[2];
-+ unsigned int i, bitnr;
-+
-+ mc_filter[0] = mc_filter[1] = 0;
-+
-+ curr = dev->mc_list;
-+ for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
-+ if (!curr) break; /* unexpected end of list */
-+
-+ bitnr = ether_crc(ETH_ALEN, curr->dmi_addr) >> 26;
-+ mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-+ }
-+
-+ regs->EMAC_HSH = mc_filter[1];
-+ regs->EMAC_HSL = mc_filter[0];
-+}
-+
-+/*
-+ * Enable/Disable promiscuous and multicast modes.
-+ */
-+static void at91ether_set_rx_mode(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */
-+ regs->EMAC_CFG |= AT91C_EMAC_CAF;
-+ } else if (dev->flags & (~IFF_PROMISC)) { /* Disable promiscuous mode */
-+ regs->EMAC_CFG &= ~AT91C_EMAC_CAF;
-+ }
-+
-+ if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */
-+ regs->EMAC_HSH = -1;
-+ regs->EMAC_HSL = -1;
-+ regs->EMAC_CFG |= AT91C_EMAC_MTI;
-+ } else if (dev->mc_count > 0) { /* Enable specific multicasts */
-+ at91ether_sethashtable(dev, regs);
-+ regs->EMAC_CFG |= AT91C_EMAC_MTI;
-+ } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */
-+ regs->EMAC_HSH = 0;
-+ regs->EMAC_HSL = 0;
-+ regs->EMAC_CFG &= ~AT91C_EMAC_MTI;
-+ }
-+}
-+
-+/* ............................... IOCTL ............................... */
-+
-+static int mdio_read(struct net_device *dev, int phy_id, int location)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ unsigned int value;
-+
-+ read_phy(regs, phy_id, location, &value);
-+ return value;
-+}
-+
-+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ write_phy(regs, phy_id, location, value);
-+}
-+
-+/*
-+ * ethtool support.
-+ */
-+static int at91ether_ethtool_ioctl (struct net_device *dev, void *useraddr)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ u32 ethcmd;
-+ int res = 0;
-+
-+ if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-+ return -EFAULT;
-+
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ switch (ethcmd) {
-+ case ETHTOOL_GSET: {
-+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-+ res = mii_ethtool_gset(&lp->mii, &ecmd);
-+ if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */
-+ ecmd.supported = SUPPORTED_FIBRE;
-+ ecmd.port = PORT_FIBRE;
-+ }
-+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-+ res = -EFAULT;
-+ break;
-+ }
-+ case ETHTOOL_SSET: {
-+ struct ethtool_cmd ecmd;
-+ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-+ res = -EFAULT;
-+ else
-+ res = mii_ethtool_sset(&lp->mii, &ecmd);
-+ break;
-+ }
-+ case ETHTOOL_NWAY_RST: {
-+ res = mii_nway_restart(&lp->mii);
-+ break;
-+ }
-+ case ETHTOOL_GLINK: {
-+ struct ethtool_value edata = { ETHTOOL_GLINK };
-+ edata.data = mii_link_ok(&lp->mii);
-+ if (copy_to_user(useraddr, &edata, sizeof(edata)))
-+ res = -EFAULT;
-+ break;
-+ }
-+ default:
-+ res = -EOPNOTSUPP;
-+ }
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ return res;
-+}
-+
-+/*
-+ * User-space ioctl interface.
-+ */
-+static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+ switch(cmd) {
-+ case SIOCETHTOOL:
-+ return at91ether_ethtool_ioctl(dev, (void *) rq->ifr_data);
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+}
-+
-+/* ................................ MAC ................................ */
-+
-+/*
-+ * Initialize and start the Receiver and Transmit subsystems
-+ */
-+static void at91ether_start(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ int i;
-+ struct recv_desc_bufs *dlist, *dlist_phys;
-+
-+ dlist = lp->dlist;
-+ dlist_phys = lp->dlist_phys;
-+
-+ for (i = 0; i < MAX_RX_DESCR; i++) {
-+ dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-+ dlist->descriptors[i].size = 0;
-+ }
-+
-+ /* Set the Wrap bit on the last descriptor */
-+ dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
-+
-+ /* Reset buffer index */
-+ lp->rxBuffIndex = 0;
-+
-+ /* Program address of descriptor list in Rx Buffer Queue register */
-+ regs->EMAC_RBQP = (AT91_REG) dlist_phys;
-+
-+ /* Enable Receive and Transmit */
-+ regs->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE);
-+}
-+
-+/*
-+ * Open the ethernet interface
-+ */
-+static int at91ether_open(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ return -EADDRNOTAVAIL;
-+
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Re-enable Peripheral clock */
-+ regs->EMAC_CTL |= AT91C_EMAC_CSR; /* Clear internal statistics */
-+
-+ /* Update the MAC address (incase user has changed it) */
-+ update_mac_address(dev);
-+
-+ /* Enable PHY interrupt */
-+ enable_phyirq(dev, regs);
-+
-+ /* Enable MAC interrupts */
-+ regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
-+ | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
-+ | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
-+
-+ /* Determine current link speed */
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+ (void) update_linkspeed(dev, regs);
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ at91ether_start(dev);
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+/*
-+ * Close the interface
-+ */
-+static int at91ether_close(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+
-+ /* Disable Receiver and Transmitter */
-+ regs->EMAC_CTL &= ~(AT91C_EMAC_TE | AT91C_EMAC_RE);
-+
-+ /* Disable PHY interrupt */
-+ disable_phyirq(dev, regs);
-+
-+ /* Disable MAC interrupts */
-+ regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA
-+ | AT91C_EMAC_TUND | AT91C_EMAC_RTRY | AT91C_EMAC_TCOM
-+ | AT91C_EMAC_ROVR | AT91C_EMAC_HRESP;
-+
-+ netif_stop_queue(dev);
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
-+
-+ return 0;
-+}
-+
-+/*
-+ * Transmit packet.
-+ */
-+static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+
-+ if (regs->EMAC_TSR & AT91C_EMAC_BNQ) {
-+ netif_stop_queue(dev);
-+
-+ /* Store packet information (to free when Tx completed) */
-+ lp->skb = skb;
-+ lp->skb_length = skb->len;
-+ lp->skb_physaddr = pci_map_single(NULL, skb->data, skb->len, PCI_DMA_TODEVICE);
-+ lp->stats.tx_bytes += skb->len;
-+
-+ /* Set address of the data in the Transmit Address register */
-+ regs->EMAC_TAR = lp->skb_physaddr;
-+ /* Set length of the packet in the Transmit Control register */
-+ regs->EMAC_TCR = skb->len;
-+
-+ dev->trans_start = jiffies;
-+ } else {
-+ printk(KERN_ERR "at91_ether.c: at91ether_tx() called, but device is busy!\n");
-+ return 1; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
-+ on this skb, he also reports -ENETDOWN and printk's, so either
-+ we free and return(0) or don't free and return 1 */
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * Update the current statistics from the internal statistics registers.
-+ */
-+static struct net_device_stats *at91ether_stats(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;
-+ int ale, lenerr, seqe, lcol, ecol;
-+
-+ if (netif_running(dev)) {
-+ lp->stats.rx_packets += regs->EMAC_OK; /* Good frames received */
-+ ale = regs->EMAC_ALE;
-+ lp->stats.rx_frame_errors += ale; /* Alignment errors */
-+ lenerr = regs->EMAC_ELR + regs->EMAC_USF;
-+ lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
-+ seqe = regs->EMAC_SEQE;
-+ lp->stats.rx_crc_errors += seqe; /* CRC error */
-+ lp->stats.rx_fifo_errors += regs->EMAC_DRFC; /* Receive buffer not available */
-+ lp->stats.rx_errors += (ale + lenerr + seqe + regs->EMAC_CDE + regs->EMAC_RJB);
-+
-+ lp->stats.tx_packets += regs->EMAC_FRA; /* Frames successfully transmitted */
-+ lp->stats.tx_fifo_errors += regs->EMAC_TUE; /* Transmit FIFO underruns */
-+ lp->stats.tx_carrier_errors += regs->EMAC_CSE; /* Carrier Sense errors */
-+ lp->stats.tx_heartbeat_errors += regs->EMAC_SQEE; /* Heartbeat error */
-+
-+ lcol = regs->EMAC_LCOL;
-+ ecol = regs->EMAC_ECOL;
-+ lp->stats.tx_window_errors += lcol; /* Late collisions */
-+ lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
-+
-+ lp->stats.collisions += (regs->EMAC_SCOL + regs->EMAC_MCOL + lcol + ecol);
-+ }
-+ return &lp->stats;
-+}
-+
-+/*
-+ * Extract received frame from buffer descriptors and sent to upper layers.
-+ * (Called from interrupt context)
-+ */
-+static void at91ether_rx(struct net_device *dev)
-+{
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ struct recv_desc_bufs *dlist;
-+ unsigned char *p_recv;
-+ struct sk_buff *skb;
-+ unsigned int pktlen;
-+
-+ dlist = lp->dlist;
-+ while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-+ p_recv = dlist->recv_buf[lp->rxBuffIndex];
-+ pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
-+ skb = alloc_skb(pktlen + 2, GFP_ATOMIC);
-+ if (skb != NULL) {
-+ skb_reserve(skb, 2);
-+ memcpy(skb_put(skb, pktlen), p_recv, pktlen);
-+
-+ skb->dev = dev;
-+ skb->protocol = eth_type_trans(skb, dev);
-+ skb->len = pktlen;
-+ dev->last_rx = jiffies;
-+ lp->stats.rx_bytes += pktlen;
-+ netif_rx(skb);
-+ }
-+ else {
-+ lp->stats.rx_dropped += 1;
-+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-+ }
-+
-+ if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-+ lp->stats.multicast++;
-+
-+ dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
-+ if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
-+ lp->rxBuffIndex = 0;
-+ else
-+ lp->rxBuffIndex++;
-+ }
-+}
-+
-+/*
-+ * MAC interrupt handler
-+ */
-+static void at91ether_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct net_device *dev = (struct net_device *) dev_id;
-+ struct at91_private *lp = (struct at91_private *) dev->priv;
-+ AT91PS_EMAC emac = (AT91PS_EMAC) dev->base_addr;
-+ unsigned long intstatus;
-+
-+ /* MAC Interrupt Status register indicates what interrupts are pending.
-+ It is automatically cleared once read. */
-+ intstatus = emac->EMAC_ISR;
-+
-+ if (intstatus & AT91C_EMAC_RCOM) /* Receive complete */
-+ at91ether_rx(dev);
-+
-+ if (intstatus & AT91C_EMAC_TCOM) { /* Transmit complete */
-+ /* The TCOM bit is set even if the transmission failed. */
-+ if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY))
-+ lp->stats.tx_errors += 1;
-+
-+ dev_kfree_skb_irq(lp->skb);
-+ pci_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, PCI_DMA_TODEVICE);
-+ netif_wake_queue(dev);
-+ }
-+
-+ if (intstatus & AT91C_EMAC_RBNA)
-+ printk("%s: RBNA error\n", dev->name);
-+ if (intstatus & AT91C_EMAC_ROVR)
-+ printk("%s: ROVR error\n", dev->name);
-+}
-+
-+/*
-+ * Initialize the ethernet interface
-+ */
-+static int at91ether_setup(struct net_device *dev, unsigned long phy_type)
-+{
-+ struct at91_private *lp;
-+ AT91PS_EMAC regs;
-+ static int already_initialized = 0;
-+ unsigned int val;
-+
-+ if (already_initialized)
-+ return 0;
-+
-+ dev = init_etherdev(dev, sizeof(struct at91_private));
-+ dev->base_addr = AT91C_VA_BASE_EMAC;
-+ dev->irq = AT91C_ID_EMAC;
-+ SET_MODULE_OWNER(dev);
-+
-+ /* Install the interrupt handler */
-+ if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev))
-+ return -EBUSY;
-+
-+ /* Allocate memory for private data structure */
-+ lp = (struct at91_private *) kmalloc(sizeof(struct at91_private), GFP_KERNEL);
-+ if (lp == NULL) {
-+ free_irq(dev->irq, dev);
-+ return -ENOMEM;
-+ }
-+ memset(lp, 0, sizeof(struct at91_private));
-+ dev->priv = lp;
-+
-+ /* Allocate memory for DMA Receive descriptors */
-+ lp->dlist = (struct recv_desc_bufs *) consistent_alloc(GFP_DMA | GFP_KERNEL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys);
-+ if (lp->dlist == NULL) {
-+ kfree(dev->priv);
-+ free_irq(dev->irq, dev);
-+ return -ENOMEM;
-+ }
-+
-+ spin_lock_init(&lp->lock);
-+
-+ ether_setup(dev);
-+ dev->open = at91ether_open;
-+ dev->stop = at91ether_close;
-+ dev->hard_start_xmit = at91ether_tx;
-+ dev->get_stats = at91ether_stats;
-+ dev->set_multicast_list = at91ether_set_rx_mode;
-+ dev->do_ioctl = at91ether_ioctl;
-+ dev->set_mac_address = set_mac_address;
-+
-+ get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */
-+ update_mac_address(dev); /* Program ethernet address into MAC */
-+
-+ regs = (AT91PS_EMAC) dev->base_addr;
-+ regs->EMAC_CTL = 0;
-+
-+#ifdef CONFIG_AT91_ETHER_RMII
-+ regs->EMAC_CFG = AT91C_EMAC_BIG | AT91C_EMAC_RMII;
-+#else
-+ regs->EMAC_CFG = AT91C_EMAC_BIG;
-+#endif
-+ if (phy_type == MII_LXT971A_ID)
-+ regs->EMAC_CFG |= AT91C_EMAC_CLK_HCLK_64; /* MDIO clock = system clock/64 */
-+
-+ if (phy_type == MII_DM9161_ID) {
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+
-+ read_phy(regs, 0, MII_DSCR_REG, &val);
-+ if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */
-+ lp->phy_media = PORT_FIBRE;
-+
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+ }
-+
-+ lp->mii.dev = dev; /* Support for ethtool */
-+ lp->mii.mdio_read = mdio_read;
-+ lp->mii.mdio_write = mdio_write;
-+
-+ lp->phy_type = phy_type; /* Type of PHY connected */
-+
-+ /* Determine current link speed */
-+ spin_lock_irq(&lp->lock);
-+ enable_mdi(regs);
-+ (void) update_linkspeed(dev, regs);
-+ disable_mdi(regs);
-+ spin_unlock_irq(&lp->lock);
-+
-+ /* Display ethernet banner */
-+ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
-+ dev->name, (uint) dev->base_addr, dev->irq,
-+ regs->EMAC_CFG & AT91C_EMAC_SPD ? "100-" : "10-",
-+ regs->EMAC_CFG & AT91C_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
-+ if (phy_type == MII_DM9161_ID)
-+ printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-+ else if (phy_type == MII_LXT971A_ID)
-+ printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-+
-+ already_initialized = 1;
-+ return 0;
-+}
-+
-+/*
-+ * Detect MAC and PHY and perform initialization
-+ */
-+static int at91ether_probe(struct net_device *dev)
-+{
-+ AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;
-+ unsigned int phyid1, phyid2;
-+ int detected = -1;
-+
-+ /* Configure the hardware - RMII vs MII mode */
-+#ifdef CONFIG_AT91_ETHER_RMII
-+ AT91_CfgPIO_EMAC_RMII();
-+#else
-+ AT91_CfgPIO_EMAC_MII();
-+#endif
-+
-+ AT91_CfgPIO_EMAC_PHY(); /* Configure PHY interrupt */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC; /* Enable Peripheral clock */
-+
-+ /* Read the PHY ID registers */
-+ enable_mdi(regs);
-+ read_phy(regs, 0, MII_PHYSID1, &phyid1);
-+ read_phy(regs, 0, MII_PHYSID2, &phyid2);
-+ disable_mdi(regs);
-+
-+ /* Davicom 9161: PHY_ID1 = 0x181 PHY_ID2 = B881 */
-+ if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_DM9161_ID) {
-+ detected = at91ether_setup(dev, MII_DM9161_ID);
-+ }
-+ /* Intel LXT971A: PHY_ID1 = 0x13 PHY_ID2 = 78E0 */
-+ else if (((phyid1 << 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {
-+ detected = at91ether_setup(dev, MII_LXT971A_ID);
-+ }
-+
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_EMAC; /* Disable Peripheral clock */
-+
-+ return detected;
-+}
-+
-+static int __init at91ether_init(void)
-+{
-+ if (!at91ether_probe(&at91_dev))
-+ return register_netdev(&at91_dev);
-+
-+ return -1;
-+}
-+
-+static void __exit at91ether_exit(void)
-+{
-+ unregister_netdev(&at91_dev);
-+}
-+
-+module_init(at91ether_init)
-+module_exit(at91ether_exit)
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
-+MODULE_AUTHOR("Andrew Victor");
---- /dev/null
-+++ linux-2.4.27/drivers/at91/net/at91_ether.h
-@@ -0,0 +1,79 @@
-+/*
-+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
-+ * Initial version by Rick Bronson.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_ETHERNET
-+#define AT91_ETHERNET
-+
-+
-+/* Davicom 9161 PHY */
-+#define MII_DM9161_ID 0x0181b880
-+
-+/* Davicom specific registers */
-+#define MII_DSCR_REG 16
-+#define MII_DSCSR_REG 17
-+#define MII_DSINTR_REG 21
-+
-+/* Intel LXT971A PHY */
-+#define MII_LXT971A_ID 0x001378E0
-+
-+/* Intel specific registers */
-+#define MII_ISINTE_REG 18
-+#define MII_ISINTS_REG 19
-+
-+/* ........................................................................ */
-+
-+#define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */
-+#define MAX_RX_DESCR 9 /* max number of receive buffers */
-+
-+#define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */
-+#define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */
-+
-+#define EMAC_BROADCAST 0x80000000 /* broadcast address */
-+#define EMAC_MULTICAST 0x40000000 /* multicast address */
-+#define EMAC_UNICAST 0x20000000 /* unicast address */
-+
-+struct rbf_t
-+{
-+ unsigned int addr;
-+ unsigned long size;
-+};
-+
-+struct recv_desc_bufs
-+{
-+ struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */
-+ char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */
-+};
-+
-+struct at91_private
-+{
-+ struct net_device_stats stats;
-+ struct mii_if_info mii; /* ethtool support */
-+
-+ /* PHY */
-+ unsigned long phy_type; /* type of PHY (PHY_ID) */
-+ spinlock_t lock; /* lock for MDI interface */
-+ short phy_media; /* media interface type */
-+
-+ /* Transmit */
-+ struct sk_buff *skb; /* holds skb until xmit interrupt completes */
-+ dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
-+ int skb_length; /* saved skb length for pci_unmap_single */
-+
-+ /* Receive */
-+ int rxBuffIndex; /* index into receive descriptor list */
-+ struct recv_desc_bufs *dlist; /* descriptor list address */
-+ struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */
-+};
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/at91/rtc/Makefile
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/rtc/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 real time clock device drivers
-+#
-+
-+O_TARGET := at91rtc.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_RTC) += at91_rtc.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/rtc/at91_rtc.c
-@@ -0,0 +1,441 @@
-+/*
-+ * Real Time Clock interface for Linux on Atmel AT91RM9200
-+ *
-+ * Copyright (c) 2002 Rick Bronson
-+ *
-+ * Based on sa1100-rtc.c by Nils Faerber
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russell King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+
-+#define AT91_RTC_FREQ 1
-+#define EPOCH 1970
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define AT91_RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define AT91_RTC_PF 0x40
-+#define AT91_RTC_AF 0x20
-+#define AT91_RTC_UF 0x10
-+
-+#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10)
-+#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10)
-+
-+static unsigned long rtc_status = 0;
-+static unsigned long rtc_irq_data;
-+static unsigned int at91_alarm_year = EPOCH;
-+
-+static struct fasync_struct *at91_rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait);
-+static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_update);
-+static spinlock_t at91_rtc_updlock; /* some spinlocks for saving/restoring interrupt levels */
-+extern spinlock_t at91_rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+static const unsigned short int __mon_yday[2][13] =
-+{
-+ /* Normal years. */
-+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
-+ /* Leap years. */
-+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-+};
-+
-+/*
-+ * Returns day since start of the year [0-365]
-+ * (from drivers/char/efirtc.c)
-+ */
-+static inline int compute_yday(int year, int month, int day)
-+{
-+ return __mon_yday[is_leap(year)][month] + day-1;
-+}
-+
-+/*
-+ * Set current time and date in RTC
-+ */
-+static void at91_rtc_settime(struct rtc_time *tval)
-+{
-+ unsigned long flags;
-+
-+ /* Stop Time/Calendar from counting */
-+ AT91_SYS->RTC_CR |= (AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
-+
-+ spin_lock_irqsave(&at91_rtc_updlock, flags); /* stop int's else we wakeup b4 we sleep */
-+ AT91_SYS->RTC_IER = AT91C_RTC_ACKUPD;
-+ interruptible_sleep_on(&at91_rtc_update); /* wait for ACKUPD interrupt to hit */
-+ spin_unlock_irqrestore(&at91_rtc_updlock, flags);
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD;
-+
-+ AT91_SYS->RTC_TIMR = BIN2BCD(tval->tm_sec) << 0
-+ | BIN2BCD(tval->tm_min) << 8
-+ | BIN2BCD(tval->tm_hour) << 16;
-+
-+ AT91_SYS->RTC_CALR = BIN2BCD((tval->tm_year + 1900) / 100) /* century */
-+ | BIN2BCD(tval->tm_year % 100) << 8 /* year */
-+ | BIN2BCD(tval->tm_mon + 1) << 16 /* tm_mon starts at zero */
-+ | BIN2BCD(tval->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
-+ | BIN2BCD(tval->tm_mday) << 24;
-+
-+ /* Restart Time/Calendar */
-+ AT91_SYS->RTC_CR &= ~(AT91C_RTC_UPDCAL | AT91C_RTC_UPDTIM);
-+}
-+
-+/*
-+ * Decode time/date into rtc_time structure
-+ */
-+static void at91_rtc_decodetime(AT91_REG *timereg, AT91_REG *calreg, struct rtc_time *tval)
-+{
-+ unsigned int time, date;
-+
-+ do { /* must read twice in case it changes */
-+ time = *timereg;
-+ date = *calreg;
-+ } while ((time != *timereg) || (date != *calreg));
-+
-+ tval->tm_sec = BCD2BIN((time & AT91C_RTC_SEC) >> 0);
-+ tval->tm_min = BCD2BIN((time & AT91C_RTC_MIN) >> 8);
-+ tval->tm_hour = BCD2BIN((time & AT91C_RTC_HOUR) >> 16);
-+
-+ /* The Calendar Alarm register does not have a field for
-+ the year - so these will return an invalid value. When an
-+ alarm is set, at91_alarm_year wille store the current year. */
-+ tval->tm_year = BCD2BIN(date & AT91C_RTC_CENT) * 100; /* century */
-+ tval->tm_year += BCD2BIN((date & AT91C_RTC_YEAR) >> 8); /* year */
-+
-+ tval->tm_wday = BCD2BIN((date & AT91C_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
-+ tval->tm_mon = BCD2BIN(((date & AT91C_RTC_MONTH) >> 16) - 1);
-+ tval->tm_mday = BCD2BIN((date & AT91C_RTC_DATE) >> 24);
-+}
-+
-+/*
-+ * IRQ handler for the RTC
-+ */
-+static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR;
-+
-+ /* update irq data & counter */
-+ if (rtsr) { /* this interrupt is shared! Is it ours? */
-+ if (rtsr & AT91C_RTC_ALARM)
-+ rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF);
-+ if (rtsr & AT91C_RTC_SECEV)
-+ rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF);
-+ if (rtsr & AT91C_RTC_ACKUPD)
-+ wake_up_interruptible(&at91_rtc_update);
-+ rtc_irq_data += 0x100;
-+ AT91_SYS->RTC_SCCR = rtsr; /* clear status reg */
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&at91_rtc_wait);
-+ kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN);
-+ }
-+}
-+
-+static int at91_rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit(1, &rtc_status))
-+ return -EBUSY;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int at91_rtc_release(struct inode *inode, struct file *file)
-+{
-+ rtc_status = 0;
-+ return 0;
-+}
-+
-+static int at91_rtc_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &at91_rtc_async_queue);
-+}
-+
-+static unsigned int at91_rtc_poll(struct file *file, poll_table * wait)
-+{
-+ poll_wait(file, &at91_rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&at91_rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq(&at91_rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+ retval = put_user(data, (unsigned long *) buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&at91_rtc_wait, &wait);
-+ return retval;
-+}
-+
-+/*
-+ * Handle commands from user-space
-+ */
-+static int at91_rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct rtc_time tm, tm2;
-+ int ret = 0;
-+
-+ spin_lock_irq(&at91_rtc_lock);
-+ switch (cmd) {
-+ case RTC_AIE_OFF: /* alarm off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ALARM;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_AIE_ON: /* alarm on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_ALARM;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_UIE_OFF: /* update off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_UIE_ON: /* update on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_PIE_OFF: /* periodic off */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_PIE_ON: /* periodic on */
-+ AT91_SYS->RTC_IER = AT91C_RTC_SECEV;
-+ rtc_irq_data = 0;
-+ break;
-+ case RTC_ALM_READ: /* read alarm */
-+ memset(&tm, 0, sizeof(struct rtc_time));
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
-+ tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
-+ tm.tm_year = at91_alarm_year - 1900;
-+ ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
-+ break;
-+ case RTC_ALM_SET: /* set alarm */
-+ if (copy_from_user(&tm2, (struct rtc_time *) arg, sizeof(tm2)))
-+ ret = -EFAULT;
-+ else {
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ at91_alarm_year = tm.tm_year;
-+ if ((unsigned) tm2.tm_hour < 24) /* do some range checking */
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned) tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned) tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+ AT91_SYS->RTC_TIMALR = BIN2BCD(tm.tm_sec) << 0
-+ | BIN2BCD(tm.tm_min) << 8
-+ | BIN2BCD(tm.tm_hour) << 16
-+ | AT91C_RTC_HOUREN | AT91C_RTC_MINEN
-+ | AT91C_RTC_SECEN;
-+ AT91_SYS->RTC_CALALR = BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
-+ | BIN2BCD(tm.tm_mday) << 24
-+ | AT91C_RTC_DATEEN | AT91C_RTC_MONTHEN;
-+ }
-+ break;
-+ case RTC_RD_TIME: /* read time */
-+ memset(&tm, 0, sizeof(struct rtc_time));
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ tm.tm_yday = compute_yday(tm.tm_year, tm.tm_mon, tm.tm_mday);
-+ tm.tm_year = tm.tm_year - 1900;
-+ ret = copy_to_user((void *) arg, &tm, sizeof(tm)) ? -EFAULT : 0;
-+ break;
-+ case RTC_SET_TIME: /* set time */
-+ if (!capable(CAP_SYS_TIME))
-+ ret = -EACCES;
-+ else {
-+ if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(tm)))
-+ ret = -EFAULT;
-+ else {
-+ int tm_year = tm.tm_year + 1900;
-+ if (tm_year < EPOCH
-+ || (unsigned) tm.tm_mon >= 12
-+ || tm.tm_mday < 1
-+ || tm.tm_mday > (days_in_mo[tm.tm_mon] + (tm.tm_mon == 1 && is_leap(tm_year)))
-+ || (unsigned) tm.tm_hour >= 24
-+ || (unsigned) tm.tm_min >= 60
-+ || (unsigned) tm.tm_sec >= 60)
-+ ret = -EINVAL;
-+ else
-+ at91_rtc_settime(&tm);
-+ }
-+ }
-+ break;
-+ case RTC_IRQP_READ: /* read periodic alarm frequency */
-+ ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
-+ break;
-+ case RTC_IRQP_SET: /* set periodic alarm frequency */
-+ if (arg != AT91_RTC_FREQ)
-+ ret = -EINVAL;
-+ break;
-+ case RTC_EPOCH_READ: /* read epoch */
-+ ret = put_user(EPOCH, (unsigned long *) arg);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+ spin_unlock_irq(&at91_rtc_lock);
-+ return ret;
-+}
-+
-+/*
-+ * Provide RTC information in /proc/driver/rtc
-+ */
-+static int at91_rtc_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMR), &(AT91_SYS->RTC_CALR), &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year, tm.tm_mon + 1, tm.tm_mday, EPOCH);
-+ at91_rtc_decodetime(&(AT91_SYS->RTC_TIMALR), &(AT91_SYS->RTC_CALALR), &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ at91_alarm_year, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "alarm_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ALARM) ? "yes" : "no");
-+ p += sprintf(p, "update_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_ACKUPD) ? "yes" : "no");
-+ p += sprintf(p, "periodic_IRQ\t: %s\n", (AT91_SYS->RTC_IMR & AT91C_RTC_SECEV) ? "yes" : "no");
-+ p += sprintf(p, "periodic_freq\t: %ld\n", (unsigned long) AT91_RTC_FREQ);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static struct file_operations at91_rtc_fops = {
-+ owner:THIS_MODULE,
-+ llseek:no_llseek,
-+ read:at91_rtc_read,
-+ poll:at91_rtc_poll,
-+ ioctl:at91_rtc_ioctl,
-+ open:at91_rtc_open,
-+ release:at91_rtc_release,
-+ fasync:at91_rtc_fasync,
-+};
-+
-+static struct miscdevice at91_rtc_miscdev = {
-+ minor:RTC_MINOR,
-+ name:"rtc",
-+ fops:&at91_rtc_fops,
-+};
-+
-+/*
-+ * Initialize and install RTC driver
-+ */
-+static int __init at91_rtc_init(void)
-+{
-+ int ret;
-+
-+ AT91_SYS->RTC_CR = 0;
-+ AT91_SYS->RTC_MR = 0; /* put in 24 hour format */
-+ /* Disable all interrupts */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
-+
-+ spin_lock_init(&at91_rtc_updlock);
-+ spin_lock_init(&at91_rtc_lock);
-+
-+ misc_register(&at91_rtc_miscdev);
-+ create_proc_read_entry("driver/rtc", 0, 0, at91_rtc_read_proc, NULL);
-+ ret = request_irq(AT91C_ID_SYS, at91_rtc_interrupt, SA_SHIRQ,
-+ "at91_rtc", &rtc_status);
-+ if (ret) {
-+ printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91C_ID_SYS);
-+ remove_proc_entry("driver/rtc", NULL);
-+ misc_deregister(&at91_rtc_miscdev);
-+ return ret;
-+ }
-+
-+ printk(KERN_INFO "AT91 Real Time Clock driver\n");
-+ return 0;
-+}
-+
-+/*
-+ * Disable and remove the RTC driver
-+ */
-+static void __exit at91_rtc_exit(void)
-+{
-+ /* Disable all interrupts */
-+ AT91_SYS->RTC_IDR = AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
-+ free_irq(AT91C_ID_SYS, &rtc_status);
-+
-+ rtc_status = 0;
-+ remove_proc_entry("driver/rtc", NULL);
-+ misc_deregister(&at91_rtc_miscdev);
-+}
-+
-+module_init(at91_rtc_init);
-+module_exit(at91_rtc_exit);
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("AT91 Realtime Clock Driver (AT91_RTC)");
-+MODULE_LICENSE("GPL");
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/at91/serial/Makefile
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/serial/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 serial and console device drivers
-+#
-+
-+O_TARGET := at91serial.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/serial/at91_serial.c
-@@ -0,0 +1,881 @@
-+/*
-+ * linux/drivers/char/at91_serial.c
-+ *
-+ * Driver for Atmel AT91RM9200 Serial ports
-+ *
-+ * Copyright (c) Rick Bronson
-+ *
-+ * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/arch/AT91RM9200_USART.h>
-+#include <asm/mach/serial_at91rm9200.h>
-+#include <asm/arch/pio.h>
-+
-+
-+#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#define SERIAL_AT91_MAJOR TTY_MAJOR
-+#define CALLOUT_AT91_MAJOR TTYAUX_MAJOR
-+#define MINOR_START 64
-+
-+#define AT91C_VA_BASE_DBGU ((unsigned long) &(AT91_SYS->DBGU_CR))
-+#define AT91_ISR_PASS_LIMIT 256
-+
-+#define UART_PUT_CR(port,v) ((AT91PS_USART)(port)->membase)->US_CR = v
-+#define UART_GET_MR(port) ((AT91PS_USART)(port)->membase)->US_MR
-+#define UART_PUT_MR(port,v) ((AT91PS_USART)(port)->membase)->US_MR = v
-+#define UART_PUT_IER(port,v) ((AT91PS_USART)(port)->membase)->US_IER = v
-+#define UART_PUT_IDR(port,v) ((AT91PS_USART)(port)->membase)->US_IDR = v
-+#define UART_GET_IMR(port) ((AT91PS_USART)(port)->membase)->US_IMR
-+#define UART_GET_CSR(port) ((AT91PS_USART)(port)->membase)->US_CSR
-+#define UART_GET_CHAR(port) ((AT91PS_USART)(port)->membase)->US_RHR
-+#define UART_PUT_CHAR(port,v) ((AT91PS_USART)(port)->membase)->US_THR = v
-+#define UART_GET_BRGR(port) ((AT91PS_USART)(port)->membase)->US_BRGR
-+#define UART_PUT_BRGR(port,v) ((AT91PS_USART)(port)->membase)->US_BRGR = v
-+#define UART_PUT_RTOR(port,v) ((AT91PS_USART)(port)->membase)->US_RTOR = v
-+
-+// #define UART_GET_CR(port) ((AT91PS_USART)(port)->membase)->US_CR // is write-only
-+
-+ /* PDC registers */
-+#define UART_PUT_PTCR(port,v) ((AT91PS_USART)(port)->membase)->US_PTCR = v
-+#define UART_PUT_RPR(port,v) ((AT91PS_USART)(port)->membase)->US_RPR = v
-+#define UART_PUT_RCR(port,v) ((AT91PS_USART)(port)->membase)->US_RCR = v
-+#define UART_GET_RCR(port) ((AT91PS_USART)(port)->membase)->US_RCR
-+#define UART_PUT_RNPR(port,v) ((AT91PS_USART)(port)->membase)->US_RNPR = v
-+#define UART_PUT_RNCR(port,v) ((AT91PS_USART)(port)->membase)->US_RNCR = v
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *at91_table[AT91C_NR_UART];
-+static struct termios *at91_termios[AT91C_NR_UART], *at91_termios_locked[AT91C_NR_UART];
-+
-+const int at91_serialmap[AT91C_NR_UART] = AT91C_UART_MAP;
-+
-+static int (*at91_open)(struct uart_port *);
-+static void (*at91_close)(struct uart_port *);
-+
-+#ifdef SUPPORT_SYSRQ
-+static struct console at91_console;
-+#endif
-+
-+/*
-+ * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
-+ */
-+static u_int at91_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_CSR(port) & AT91C_US_TXEMPTY ? TIOCSER_TEMT : 0;
-+}
-+
-+/*
-+ * Set state of the modem control output lines
-+ */
-+static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned int control = 0;
-+
-+ /*
-+ * Errata #39: RTS0 is not internally connected to PA21. We need to drive
-+ * the pin manually.
-+ */
-+ if (port->mapbase == AT91C_VA_BASE_US0) {
-+ if (mctrl & TIOCM_RTS)
-+ AT91_SYS->PIOA_CODR = AT91C_PA21_RTS0;
-+ else
-+ AT91_SYS->PIOA_SODR = AT91C_PA21_RTS0;
-+ }
-+
-+ if (mctrl & TIOCM_RTS)
-+ control |= AT91C_US_RTSEN;
-+ else
-+ control |= AT91C_US_RTSDIS;
-+
-+ if (mctrl & TIOCM_DTR)
-+ control |= AT91C_US_DTREN;
-+ else
-+ control |= AT91C_US_DTRDIS;
-+
-+ UART_PUT_CR(port,control);
-+}
-+
-+/*
-+ * Get state of the modem control input lines
-+ */
-+static u_int at91_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int status, ret = 0;
-+
-+ status = UART_GET_CSR(port);
-+ if (status & AT91C_US_DCD)
-+ ret |= TIOCM_CD;
-+ if (status & AT91C_US_CTS)
-+ ret |= TIOCM_CTS;
-+ if (status & AT91C_US_DSR)
-+ ret |= TIOCM_DSR;
-+ if (status & AT91C_US_RI)
-+ ret |= TIOCM_RI;
-+
-+ return ret;
-+}
-+
-+/*
-+ * Stop transmitting.
-+ */
-+static void at91_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ UART_PUT_IDR(port, AT91C_US_TXRDY);
-+ port->read_status_mask &= ~AT91C_US_TXRDY;
-+}
-+
-+/*
-+ * Start transmitting.
-+ */
-+static void at91_start_tx(struct uart_port *port, u_int from_tty)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ port->read_status_mask |= AT91C_US_TXRDY;
-+ UART_PUT_IER(port, AT91C_US_TXRDY);
-+ local_irq_restore(flags);
-+}
-+
-+/*
-+ * Stop receiving - port is in process of being closed.
-+ */
-+static void at91_stop_rx(struct uart_port *port)
-+{
-+ UART_PUT_IDR(port, AT91C_US_RXRDY);
-+}
-+
-+/*
-+ * Enable modem status interrupts
-+ */
-+static void at91_enable_ms(struct uart_port *port)
-+{
-+ UART_PUT_IER(port, AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC);
-+}
-+
-+/*
-+ * Control the transmission of a break signal
-+ */
-+static void at91_break_ctl(struct uart_port *port, int break_state)
-+{
-+ if (break_state != 0)
-+ UART_PUT_CR(port, AT91C_US_STTBRK); /* start break */
-+ else
-+ UART_PUT_CR(port, AT91C_US_STPBRK); /* stop break */
-+}
-+
-+/*
-+ * Characters received (called from interrupt handler)
-+ */
-+static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = UART_GET_CSR(port);
-+ while (status & (AT91C_US_RXRDY)) {
-+ ch = UART_GET_CHAR(port);
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ port->icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UART_GET_CSR(port);
-+ }
-+out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+handle_error:
-+ if (status & (AT91C_US_PARE | AT91C_US_FRAME | AT91C_US_OVRE))
-+ UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
-+ if (status & (AT91C_US_PARE))
-+ port->icount.parity++;
-+ else if (status & (AT91C_US_FRAME))
-+ port->icount.frame++;
-+ if (status & (AT91C_US_OVRE))
-+ port->icount.overrun++;
-+
-+ if (status & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+
-+ status &= port->read_status_mask;
-+
-+ UART_PUT_CR(port, AT91C_US_RSTSTA); /* clear error */
-+ if (status & AT91C_US_PARE)
-+ flg = TTY_PARITY;
-+ else if (status & AT91C_US_FRAME)
-+ flg = TTY_FRAME;
-+
-+ if (status & AT91C_US_OVRE) {
-+ /*
-+ * overrun does *not* affect the character
-+ * we read from the FIFO
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+/*
-+ * Transmit characters (called from interrupt handler)
-+ */
-+static void at91_tx_chars(struct uart_port *port)
-+{
-+ struct circ_buf *xmit = &port->info->xmit;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ at91_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ while (UART_GET_CSR(port) & AT91C_US_TXRDY) {
-+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ }
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ at91_stop_tx(port, 0);
-+}
-+
-+/*
-+ * Interrupt handler
-+ */
-+static void at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pending, pass_counter = 0;
-+
-+ status = UART_GET_CSR(port);
-+ pending = status & port->read_status_mask;
-+ if (pending) {
-+ do {
-+ if (pending & AT91C_US_RXRDY)
-+ at91_rx_chars(port, regs);
-+
-+ /* Clear the relevent break bits */
-+ if (pending & AT91C_US_RXBRK) {
-+ UART_PUT_CR(port, AT91C_US_RSTSTA);
-+ port->icount.brk++;
-+#ifdef SUPPORT_SYSRQ
-+ if (port->line == at91_console.index && !port->sysrq) {
-+ port->sysrq = jiffies + HZ*5;
-+ }
-+#endif
-+ }
-+
-+ // TODO: All reads to CSR will clear these interrupts!
-+ if (pending & AT91C_US_RIIC) port->icount.rng++;
-+ if (pending & AT91C_US_DSRIC) port->icount.dsr++;
-+ if (pending & AT91C_US_DCDIC) {
-+ port->icount.dcd++;
-+ uart_handle_dcd_change(port, status & AT91C_US_DCD);
-+ }
-+ if (pending & AT91C_US_CTSIC) {
-+ port->icount.cts++;
-+ uart_handle_cts_change(port, status & AT91C_US_CTS);
-+ }
-+ if (pending & (AT91C_US_RIIC | AT91C_US_DSRIC | AT91C_US_DCDIC | AT91C_US_CTSIC))
-+ wake_up_interruptible(&port->info->delta_msr_wait);
-+
-+ if (pending & AT91C_US_TXRDY)
-+ at91_tx_chars(port);
-+ if (pass_counter++ > AT91_ISR_PASS_LIMIT)
-+ break;
-+
-+ status = UART_GET_CSR(port);
-+ pending = status & port->read_status_mask;
-+ } while (pending);
-+ }
-+}
-+
-+/*
-+ * Perform initialization and enable port for reception
-+ */
-+static int at91_startup(struct uart_port *port)
-+{
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
-+ if (retval) {
-+ printk("at91_serial: at91_startup - Can't get irq\n");
-+ return retval;
-+ }
-+ /*
-+ * If there is a specific "open" function (to register
-+ * control line interrupts)
-+ */
-+ if (at91_open) {
-+ retval = at91_open(port);
-+ if (retval) {
-+ free_irq(port->irq, port);
-+ return retval;
-+ }
-+ }
-+
-+ /* Enable peripheral clock if required */
-+ if (port->irq != AT91C_ID_SYS)
-+ AT91_SYS->PMC_PCER = 1 << port->irq;
-+
-+ port->read_status_mask = AT91C_US_RXRDY | AT91C_US_TXRDY | AT91C_US_OVRE
-+ | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK;
-+ /*
-+ * Finally, clear and enable interrupts
-+ */
-+ UART_PUT_IDR(port, -1);
-+ UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN); /* enable xmit & rcvr */
-+ UART_PUT_IER(port, AT91C_US_RXRDY); /* do receive only */
-+ return 0;
-+}
-+
-+/*
-+ * Disable the port
-+ */
-+static void at91_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+
-+ /*
-+ * If there is a specific "close" function (to unregister
-+ * control line interrupts)
-+ */
-+ if (at91_close)
-+ at91_close(port);
-+
-+ /*
-+ * Disable all interrupts, port and break condition.
-+ */
-+ UART_PUT_CR(port, AT91C_US_RSTSTA);
-+ UART_PUT_IDR(port, -1);
-+
-+ /* Disable peripheral clock if required */
-+ if (port->irq != AT91C_ID_SYS)
-+ AT91_SYS->PMC_PCDR = 1 << port->irq;
-+}
-+
-+static struct uart_ops at91_pops; /* forward declaration */
-+
-+/*
-+ * Change the port parameters
-+ */
-+static void at91_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ unsigned long flags;
-+ unsigned int mode, imr;
-+
-+ /* Get current mode register */
-+ mode = UART_GET_MR(port) & ~(AT91C_US_CHRL | AT91C_US_NBSTOP | AT91C_US_PAR);
-+
-+ /* byte size */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ mode |= AT91C_US_CHRL_5_BITS;
-+ break;
-+ case CS6:
-+ mode |= AT91C_US_CHRL_6_BITS;
-+ break;
-+ case CS7:
-+ mode |= AT91C_US_CHRL_7_BITS;
-+ break;
-+ default:
-+ mode |= AT91C_US_CHRL_8_BITS;
-+ break;
-+ }
-+
-+ /* stop bits */
-+ if (cflag & CSTOPB)
-+ mode |= AT91C_US_NBSTOP_2_BIT;
-+
-+ /* parity */
-+ if (cflag & PARENB) {
-+ if (cflag & CMSPAR) { /* Mark or Space parity */
-+ if (cflag & PARODD)
-+ mode |= AT91C_US_PAR_MARK;
-+ else
-+ mode |= AT91C_US_PAR_SPACE;
-+ }
-+ else if (cflag & PARODD)
-+ mode |= AT91C_US_PAR_ODD;
-+ else
-+ mode |= AT91C_US_PAR_EVEN;
-+ }
-+ else
-+ mode |= AT91C_US_PAR_NONE;
-+
-+ port->read_status_mask |= AT91C_US_OVRE;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= AT91C_US_FRAME | AT91C_US_PARE;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= AT91C_US_RXBRK;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= (AT91C_US_FRAME | AT91C_US_PARE);
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= AT91C_US_RXBRK;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AT91C_US_OVRE;
-+ }
-+
-+ // TODO: Ignore all characters if CREAD is set.
-+
-+ /* first, disable interrupts and drain transmitter */
-+ local_irq_save(flags);
-+ imr = UART_GET_IMR(port); /* get interrupt mask */
-+ UART_PUT_IDR(port, -1); /* disable all interrupts */
-+ local_irq_restore(flags);
-+ while (!(UART_GET_CSR(port) & AT91C_US_TXEMPTY)) { barrier(); }
-+
-+ /* disable receiver and transmitter */
-+ UART_PUT_CR(port, AT91C_US_TXDIS | AT91C_US_RXDIS);
-+
-+ /* set the parity, stop bits and data size */
-+ UART_PUT_MR(port, mode);
-+
-+ /* set the baud rate */
-+ UART_PUT_BRGR(port, quot);
-+ UART_PUT_CR(port, AT91C_US_TXEN | AT91C_US_RXEN);
-+
-+ /* restore interrupts */
-+ UART_PUT_IER(port, imr);
-+
-+ /* CTS flow-control and modem-status interrupts */
-+ if (UART_ENABLE_MS(port, cflag))
-+ at91_pops.enable_ms(port);
-+}
-+
-+/*
-+ * Return string describing the specified port
-+ */
-+static const char *at91_type(struct uart_port *port)
-+{
-+ return port->type == PORT_AT91RM9200 ? "AT91_SERIAL" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'.
-+ */
-+static void at91_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase,
-+ port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'.
-+ */
-+static int at91_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase,
-+ port->mapbase == AT91C_VA_BASE_DBGU ? 512 : SZ_16K,
-+ "at91_serial") != NULL ? 0 : -EBUSY;
-+
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void at91_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_AT91RM9200;
-+ at91_request_port(port);
-+ }
-+}
-+
-+/*
-+ * Verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
-+ ret = -EINVAL;
-+ if (port->irq != ser->irq)
-+ ret = -EINVAL;
-+ if (ser->io_type != SERIAL_IO_MEM)
-+ ret = -EINVAL;
-+ if (port->uartclk / 16 != ser->baud_base)
-+ ret = -EINVAL;
-+ if ((void *)port->mapbase != ser->iomem_base)
-+ ret = -EINVAL;
-+ if (port->iobase != ser->port)
-+ ret = -EINVAL;
-+ if (ser->hub6 != 0)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops at91_pops = {
-+ tx_empty: at91_tx_empty,
-+ set_mctrl: at91_set_mctrl,
-+ get_mctrl: at91_get_mctrl,
-+ stop_tx: at91_stop_tx,
-+ start_tx: at91_start_tx,
-+ stop_rx: at91_stop_rx,
-+ enable_ms: at91_enable_ms,
-+ break_ctl: at91_break_ctl,
-+ startup: at91_startup,
-+ shutdown: at91_shutdown,
-+ change_speed: at91_change_speed,
-+ type: at91_type,
-+ release_port: at91_release_port,
-+ request_port: at91_request_port,
-+ config_port: at91_config_port,
-+ verify_port: at91_verify_port,
-+};
-+
-+static struct uart_port at91_ports[AT91C_NR_UART];
-+
-+void __init at91_init_ports(void)
-+{
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ at91_ports[i].iotype = SERIAL_IO_MEM;
-+ at91_ports[i].flags = ASYNC_BOOT_AUTOCONF;
-+ at91_ports[i].uartclk = AT91C_MASTER_CLOCK;
-+ at91_ports[i].ops = &at91_pops;
-+ at91_ports[i].fifosize = 1;
-+ at91_ports[i].line = i;
-+ }
-+}
-+
-+void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
-+{
-+ if (fns->enable_ms)
-+ at91_pops.enable_ms = fns->enable_ms;
-+ if (fns->get_mctrl)
-+ at91_pops.get_mctrl = fns->get_mctrl;
-+ if (fns->set_mctrl)
-+ at91_pops.set_mctrl = fns->set_mctrl;
-+ at91_open = fns->open;
-+ at91_close = fns->close;
-+ at91_pops.pm = fns->pm;
-+ at91_pops.set_wake = fns->set_wake;
-+}
-+
-+/*
-+ * Setup ports.
-+ */
-+void __init at91_register_uart(int idx, int port)
-+{
-+ if ((idx < 0) || (idx >= AT91C_NR_UART)) {
-+ printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);
-+ return;
-+ }
-+
-+ switch (port) {
-+ case 0:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US0;
-+ at91_ports[idx].irq = AT91C_ID_US0;
-+ AT91_CfgPIO_USART0();
-+ break;
-+ case 1:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US1;
-+ at91_ports[idx].irq = AT91C_ID_US1;
-+ AT91_CfgPIO_USART1();
-+ break;
-+ case 2:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US2;
-+ at91_ports[idx].irq = AT91C_ID_US2;
-+ AT91_CfgPIO_USART2();
-+ break;
-+ case 3:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_US3;
-+ at91_ports[idx].irq = AT91C_ID_US3;
-+ AT91_CfgPIO_USART3();
-+ break;
-+ case 4:
-+ at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;
-+ at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;
-+ at91_ports[idx].irq = AT91C_ID_SYS;
-+ AT91_CfgPIO_DBGU();
-+ break;
-+ default:
-+ printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);
-+ }
-+}
-+
-+#ifdef CONFIG_SERIAL_AT91_CONSOLE
-+
-+/*
-+ * Interrupts are disabled on entering
-+ */
-+static void at91_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = at91_ports + co->index;
-+ unsigned int status, i, imr;
-+
-+ /*
-+ * First, save IMR and then disable interrupts
-+ */
-+ imr = UART_GET_IMR(port); /* get interrupt mask */
-+ UART_PUT_IDR(port, AT91C_US_RXRDY | AT91C_US_TXRDY);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (!(status & AT91C_US_TXRDY));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (!(status & AT91C_US_TXRDY));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore IMR
-+ */
-+ do {
-+ status = UART_GET_CSR(port);
-+ } while (!(status & AT91C_US_TXRDY));
-+ UART_PUT_IER(port, imr); /* set interrupts back the way they were */
-+}
-+
-+static kdev_t at91_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_AT91_MAJOR, MINOR_START + co->index);
-+}
-+
-+/*
-+ * If the port was already initialised (eg, by a boot loader), try to determine
-+ * the current setup.
-+ */
-+static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ unsigned int mr, quot;
-+
-+// TODO: CR is a write-only register
-+// unsigned int cr;
-+//
-+// cr = UART_GET_CR(port) & (AT91C_US_RXEN | AT91C_US_TXEN);
-+// if (cr == (AT91C_US_RXEN | AT91C_US_TXEN)) {
-+// /* ok, the port was enabled */
-+//
-+// mr = UART_GET_MR(port) & AT91C_US_PAR;
-+//
-+// *parity = 'n';
-+// if (mr == AT91C_US_PAR_EVEN)
-+// *parity = 'e';
-+// else if (mr == AT91C_US_PAR_ODD)
-+// *parity = 'o';
-+// }
-+
-+ mr = UART_GET_MR(port) & AT91C_US_CHRL;
-+ if (mr == AT91C_US_CHRL_8_BITS)
-+ *bits = 8;
-+ else
-+ *bits = 7;
-+
-+ quot = UART_GET_BRGR(port);
-+ *baud = port->uartclk / (16 * (quot));
-+}
-+
-+static int __init at91_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = AT91C_CONSOLE_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(at91_ports, AT91C_NR_UART, co);
-+
-+ // TODO: The console port should be initialized, and clock enabled if
-+ // we're not relying on the bootloader to do it.
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ at91_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console at91_console = {
-+ name: "ttyS",
-+ write: at91_console_write,
-+ device: at91_console_device,
-+ setup: at91_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: AT91C_CONSOLE,
-+};
-+
-+#define AT91_CONSOLE_DEVICE &at91_console
-+
-+void __init at91_console_init(void)
-+{
-+ at91_init_ports();
-+ register_console(&at91_console);
-+}
-+
-+#else
-+#define AT91_CONSOLE_DEVICE NULL
-+#endif
-+
-+static struct uart_driver at91_reg = {
-+ owner: THIS_MODULE,
-+ normal_major: SERIAL_AT91_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ normal_name: "ttyS%d",
-+ callout_name: "cua%d",
-+#else
-+ normal_name: "ttyS",
-+ callout_name: "cua",
-+#endif
-+ normal_driver: &normal,
-+ callout_major: CALLOUT_AT91_MAJOR,
-+ callout_driver: &callout,
-+ table: at91_table,
-+ termios: at91_termios,
-+ termios_locked: at91_termios_locked,
-+ minor: MINOR_START,
-+ nr: AT91C_NR_UART,
-+ cons: AT91_CONSOLE_DEVICE,
-+};
-+
-+static int __init at91_serial_init(void)
-+{
-+ int ret, i;
-+
-+ at91_init_ports();
-+
-+ ret = uart_register_driver(&at91_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ if (at91_serialmap[i] >= 0)
-+ uart_add_one_port(&at91_reg, &at91_ports[i]);
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit at91_serial_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < AT91C_NR_UART; i++) {
-+ if (at91_serialmap[i] >= 0)
-+ uart_remove_one_port(&at91_reg, &at91_ports[i]);
-+ }
-+
-+ uart_unregister_driver(&at91_reg);
-+}
-+
-+module_init(at91_serial_init);
-+module_exit(at91_serial_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Rick Bronson");
-+MODULE_DESCRIPTION("AT91 generic serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/at91/spi/Makefile
-@@ -0,0 +1,17 @@
-+# File: drivers/at91/spi/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 SPI device drivers
-+#
-+
-+O_TARGET := at91spi.o
-+
-+export-objs := at91_spi.o
-+
-+obj-y := at91_spi.o
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_SPIDEV) += at91_spidev.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/spi/at91_spi.c
-@@ -0,0 +1,275 @@
-+/*
-+ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/init.h>
-+#include <linux/module.h>
-+#include <asm/semaphore.h>
-+#include <linux/pci.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+
-+#include <asm/arch/AT91RM9200_SPI.h>
-+#include <asm/arch/pio.h>
-+#include "at91_spi.h"
-+
-+#undef DEBUG_SPI
-+
-+static struct spi_local spi_dev[NR_SPI_DEVICES]; /* state of the SPI devices */
-+static int spi_enabled = 0;
-+static struct semaphore spi_lock; /* protect access to SPI bus */
-+static int current_device = -1; /* currently selected SPI device */
-+
-+DECLARE_COMPLETION(transfer_complete);
-+
-+/* SPI controller device */
-+static AT91PS_SPI controller = (AT91PS_SPI) AT91C_VA_BASE_SPI;
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Access and enable the SPI bus.
-+ * This MUST be called before any transfers are performed.
-+ */
-+void spi_access_bus(short device)
-+{
-+ /* Ensure that requested device is valid */
-+ if ((device < 0) || (device >= NR_SPI_DEVICES))
-+ panic("at91_spi: spi_access_bus called with invalid device");
-+
-+ if (spi_enabled == 0) {
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Enable Peripheral clock */
-+ controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
-+#ifdef DEBUG_SPI
-+ printk("SPI on\n");
-+#endif
-+ }
-+ MOD_INC_USE_COUNT;
-+ spi_enabled++;
-+
-+ /* Lock the SPI bus */
-+ down(&spi_lock);
-+ current_device = device;
-+
-+ /* Enable PIO */
-+ if (!spi_dev[device].pio_enabled) {
-+ switch (device) {
-+ case 0: AT91_CfgPIO_SPI_CS0(); break;
-+ case 1: AT91_CfgPIO_SPI_CS1(); break;
-+ case 2: AT91_CfgPIO_SPI_CS2(); break;
-+ case 3: AT91_CfgPIO_SPI_CS3(); break;
-+ }
-+ spi_dev[device].pio_enabled = 1;
-+#ifdef DEBUG_SPI
-+ printk("SPI CS%i enabled\n", device);
-+#endif
-+ }
-+
-+ /* Configure SPI bus for device */
-+ controller->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (spi_dev[device].pcs << 16);
-+}
-+
-+/*
-+ * Relinquish control of the SPI bus.
-+ */
-+void spi_release_bus(short device)
-+{
-+ if (device != current_device)
-+ panic("at91_spi: spi_release called with invalid device");
-+
-+ /* Release the SPI bus */
-+ current_device = -1;
-+ up(&spi_lock);
-+
-+ spi_enabled--;
-+ MOD_DEC_USE_COUNT;
-+ if (spi_enabled == 0) {
-+ controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_SPI; /* Disable Peripheral clock */
-+#ifdef DEBUG_SPI
-+ printk("SPI off\n");
-+#endif
-+ }
-+}
-+
-+/*
-+ * Perform a data transfer over the SPI bus
-+ */
-+int spi_transfer(struct spi_transfer_list* list)
-+{
-+ struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
-+
-+ if (!list)
-+ panic("at91_spi: spi_transfer called with NULL transfer list");
-+ if (current_device == -1)
-+ panic("at91_spi: spi_transfer called without acquiring bus");
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI transfer start [%i]\n", list->nr_transfers);
-+#endif
-+
-+ /* Store transfer list */
-+ device->xfers = list;
-+ list->curr = 0;
-+
-+ /* Assume there must be at least one transfer */
-+ device->tx = pci_map_single(NULL, list->tx[0], list->txlen[0], PCI_DMA_TODEVICE);
-+ device->rx = pci_map_single(NULL, list->rx[0], list->rxlen[0], PCI_DMA_FROMDEVICE);
-+
-+ /* Program PDC registers */
-+ controller->SPI_TPR = device->tx;
-+ controller->SPI_RPR = device->rx;
-+ controller->SPI_TCR = list->txlen[0];
-+ controller->SPI_RCR = list->rxlen[0];
-+
-+ /* Is there a second transfer? */
-+ if (list->nr_transfers > 1) {
-+ device->txnext = pci_map_single(NULL, list->tx[1], list->txlen[1], PCI_DMA_TODEVICE);
-+ device->rxnext = pci_map_single(NULL, list->rx[1], list->rxlen[1], PCI_DMA_FROMDEVICE);
-+
-+ /* Program Next PDC registers */
-+ controller->SPI_TNPR = device->txnext;
-+ controller->SPI_RNPR = device->rxnext;
-+ controller->SPI_TNCR = list->txlen[1];
-+ controller->SPI_RNCR = list->rxlen[1];
-+ }
-+ else {
-+ device->txnext = 0;
-+ device->rxnext = 0;
-+ controller->SPI_TNCR = 0;
-+ controller->SPI_RNCR = 0;
-+ }
-+
-+ // TODO: If we are doing consecutive transfers (at high speed, or
-+ // small buffers), then it might be worth modifying the 'Delay between
-+ // Consecutive Transfers' in the CSR registers.
-+ // This is an issue if we cannot chain the next buffer fast enough
-+ // in the interrupt handler.
-+
-+ /* Enable transmitter and receiver */
-+ controller->SPI_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
-+
-+ controller->SPI_IER = AT91C_SPI_SPENDRX; /* enable buffer complete interrupt */
-+ wait_for_completion(&transfer_complete);
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI transfer end\n");
-+#endif
-+
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Handle interrupts from the SPI controller.
-+ */
-+static void spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status;
-+ struct spi_local *device = (struct spi_local *) &spi_dev[current_device];
-+ struct spi_transfer_list *list = device->xfers;
-+
-+#ifdef DEBUG_SPI
-+ printk("SPI interrupt %i\n", current_device);
-+#endif
-+
-+ if (!list)
-+ panic("at91_spi: spi_interrupt with a NULL transfer list");
-+
-+ status = controller->SPI_SR & controller->SPI_IMR; /* read status */
-+
-+ pci_unmap_single(NULL, device->tx, list->txlen[list->curr], PCI_DMA_TODEVICE);
-+ pci_unmap_single(NULL, device->rx, list->rxlen[list->curr], PCI_DMA_FROMDEVICE);
-+
-+ device->tx = device->txnext; /* move next transfer to current transfer */
-+ device->rx = device->rxnext;
-+
-+ list->curr = list->curr + 1;
-+ if (list->curr == list->nr_transfers) { /* all transfers complete */
-+ controller->SPI_IDR = AT91C_SPI_SPENDRX; /* disable interrupt */
-+
-+ /* Disable transmitter and receiver */
-+ controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
-+
-+ device->xfers = NULL;
-+ complete(&transfer_complete);
-+ }
-+ else if (list->curr+1 == list->nr_transfers) { /* no more next transfers */
-+ device->txnext = 0;
-+ device->rxnext = 0;
-+ controller->SPI_TNCR = 0;
-+ controller->SPI_RNCR = 0;
-+ }
-+ else {
-+ int i = (list->curr)+1;
-+
-+ device->txnext = pci_map_single(NULL, list->tx[i], list->txlen[i], PCI_DMA_TODEVICE);
-+ device->rxnext = pci_map_single(NULL, list->rx[i], list->rxlen[i], PCI_DMA_FROMDEVICE);
-+ controller->SPI_TNPR = device->txnext;
-+ controller->SPI_RNPR = device->rxnext;
-+ controller->SPI_TNCR = list->txlen[i];
-+ controller->SPI_RNCR = list->rxlen[i];
-+ }
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Initialize the SPI controller
-+ */
-+static int __init at91_spi_init(void)
-+{
-+ init_MUTEX(&spi_lock);
-+
-+ AT91_CfgPIO_SPI();
-+
-+ controller->SPI_CR = AT91C_SPI_SWRST; /* software reset of SPI controller */
-+
-+ /* Set Chip Select registers to good defaults */
-+ controller->SPI_CSR0 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR1 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR2 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+ controller->SPI_CSR3 = AT91C_SPI_CPOL | AT91C_SPI_BITS_8 | (16 << 16) | (DEFAULT_SPI_BAUD << 8);
-+
-+ controller->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
-+
-+ memset(&spi_dev, 0, sizeof(spi_dev));
-+ spi_dev[0].pcs = 0xE;
-+ spi_dev[1].pcs = 0xD;
-+ spi_dev[2].pcs = 0xB;
-+ spi_dev[3].pcs = 0x7;
-+
-+ if (request_irq(AT91C_ID_SPI, spi_interrupt, 0, "spi", NULL))
-+ return -EBUSY;
-+
-+ controller->SPI_CR = AT91C_SPI_SPIEN; /* Enable SPI */
-+
-+ return 0;
-+}
-+
-+static void at91_spi_exit(void)
-+{
-+ controller->SPI_CR = AT91C_SPI_SPIDIS; /* Disable SPI */
-+
-+ free_irq(AT91C_ID_SPI, 0);
-+}
-+
-+
-+EXPORT_SYMBOL(spi_access_bus);
-+EXPORT_SYMBOL(spi_release_bus);
-+EXPORT_SYMBOL(spi_transfer);
-+
-+module_init(at91_spi_init);
-+module_exit(at91_spi_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("SPI driver for Atmel AT91RM9200")
---- /dev/null
-+++ linux-2.4.27/drivers/at91/spi/at91_spi.h
-@@ -0,0 +1,56 @@
-+/*
-+ * Serial Peripheral Interface (SPI) driver for the Atmel AT91RM9200
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef AT91_SPI_H
-+#define AT91_SPI_H
-+
-+/* Maximum number of buffers in a single SPI transfer.
-+ * DataFlash uses maximum of 2
-+ * spidev interface supports up to 8.
-+ */
-+#define MAX_SPI_TRANSFERS 8
-+
-+#define NR_SPI_DEVICES 4 /* number of devices on SPI bus */
-+
-+#define DATAFLASH_CLK 6000000
-+#define DEFAULT_SPI_BAUD AT91C_MASTER_CLOCK / (2 * DATAFLASH_CLK)
-+
-+#define SPI_MAJOR 153 /* registered device number */
-+
-+/*
-+ * Describes the buffers for a SPI transfer.
-+ * A transmit & receive buffer must be specified for each transfer
-+ */
-+struct spi_transfer_list {
-+ void* tx[MAX_SPI_TRANSFERS]; /* transmit */
-+ int txlen[MAX_SPI_TRANSFERS];
-+ void* rx[MAX_SPI_TRANSFERS]; /* receive */
-+ int rxlen[MAX_SPI_TRANSFERS];
-+ int nr_transfers; /* number of transfers */
-+ int curr; /* current transfer */
-+};
-+
-+struct spi_local {
-+ unsigned int pcs; /* Peripheral Chip Select value */
-+ short pio_enabled; /* has PIO been enabled? */
-+
-+ struct spi_transfer_list *xfers; /* current transfer list */
-+ dma_addr_t tx, rx; /* DMA address for current transfer */
-+ dma_addr_t txnext, rxnext; /* DMA address for next transfer */
-+};
-+
-+
-+/* Exported functions */
-+extern void spi_access_bus(short device);
-+extern void spi_release_bus(short device);
-+extern int spi_transfer(struct spi_transfer_list* list);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/at91/spi/at91_spidev.c
-@@ -0,0 +1,226 @@
-+/*
-+ * User-space interface to the SPI bus on Atmel AT91RM9200
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * Based on SPI driver by Rick Bronson
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/iobuf.h>
-+#include <linux/highmem.h>
-+
-+#ifdef CONFIG_DEVFS_FS
-+#include <linux/devfs_fs_kernel.h>
-+#endif
-+
-+#include "at91_spi.h"
-+
-+#undef DEBUG_SPIDEV
-+
-+#ifdef CONFIG_DEVFS_FS
-+static devfs_handle_t devfs_handle = NULL;
-+static devfs_handle_t devfs_spi[NR_SPI_DEVICES];
-+#endif
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Read or Write to SPI bus.
-+ */
-+static ssize_t spidev_rd_wr(struct file *file, char *buf, size_t count, loff_t *offset)
-+{
-+ unsigned int spi_device = (unsigned int) file->private_data;
-+ struct kiobuf *iobuf;
-+ unsigned int ofs, pagelen;
-+ int res, i;
-+
-+ struct spi_transfer_list* list = kmalloc(sizeof(struct spi_transfer_list), GFP_KERNEL);
-+ if (!list)
-+ return -ENOMEM;
-+
-+ res = alloc_kiovec(1, &iobuf);
-+ if (res) {
-+ kfree(list);
-+ return res;
-+ }
-+
-+ res = map_user_kiobuf(READ, iobuf, (unsigned long) buf, count);
-+ if (res) {
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+ return res;
-+ }
-+
-+ /* More pages than transfer slots in spi_transfer_list */
-+ if (iobuf->nr_pages >= MAX_SPI_TRANSFERS) {
-+ unmap_kiobuf(iobuf);
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+ return -EFBIG;
-+ }
-+
-+#ifdef DEBUG_SPIDEV
-+ printk("spidev_rd_rw: %i %i\n", count, iobuf->nr_pages);
-+#endif
-+
-+ /* Set default return value = transfer length */
-+ res = count;
-+
-+ /*
-+ * At this point, the virtual area buf[0] .. buf[count-1] will have
-+ * corresponding pages mapped in the physical memory and locked until
-+ * we unmap the kiobuf. The pages cannot be swapped out or moved
-+ * around.
-+ */
-+ ofs = iobuf->offset;
-+ pagelen = PAGE_SIZE - iobuf->offset;
-+ if (count < pagelen)
-+ pagelen = count;
-+
-+ for (i = 0; i < iobuf->nr_pages; i++) {
-+ list->tx[i] = list->rx[i] = page_address(iobuf->maplist[i]) + ofs;
-+ list->txlen[i] = list->rxlen[i] = pagelen;
-+
-+#ifdef DEBUG_SPIDEV
-+ printk(" %i: %x (%i)\n", i, list->tx[i], list->txlen[i]);
-+#endif
-+
-+ ofs = 0; /* all subsequent transfers start at beginning of a page */
-+ count = count - pagelen;
-+ pagelen = (count < PAGE_SIZE) ? count : PAGE_SIZE;
-+ }
-+ list->nr_transfers = iobuf->nr_pages;
-+
-+ /* Perform transfer on SPI bus */
-+ spi_access_bus(spi_device);
-+ spi_transfer(list);
-+ spi_release_bus(spi_device);
-+
-+ unmap_kiobuf(iobuf);
-+ free_kiovec(1, &iobuf);
-+ kfree(list);
-+
-+ return res;
-+}
-+
-+static int spidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ int spi_device = MINOR(inode->i_rdev);
-+
-+ if (spi_device >= NR_SPI_DEVICES)
-+ return -ENODEV;
-+
-+ // TODO: This interface can be used to configure the SPI bus.
-+ // Configurable options could include: Speed, Clock Polarity, Clock Phase
-+
-+ switch(cmd) {
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+/*
-+ * Open the SPI device
-+ */
-+static int spidev_open(struct inode *inode, struct file *file)
-+{
-+ unsigned int spi_device = MINOR(inode->i_rdev);
-+
-+ if (spi_device >= NR_SPI_DEVICES)
-+ return -ENODEV;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ /*
-+ * 'private_data' is actually a pointer, but we overload it with the
-+ * value we want to store.
-+ */
-+ (unsigned int) file->private_data = spi_device;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Close the SPI device
-+ */
-+static int spidev_close(struct inode *inode, struct file *file)
-+{
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+static struct file_operations spidev_fops = {
-+ owner: THIS_MODULE,
-+ llseek: no_llseek,
-+ read: spidev_rd_wr,
-+ write: spidev_rd_wr,
-+ ioctl: spidev_ioctl,
-+ open: spidev_open,
-+ release: spidev_close,
-+};
-+
-+/*
-+ * Install the SPI /dev interface driver
-+ */
-+static int __init at91_spidev_init(void)
-+{
-+ int i;
-+ char name[3];
-+
-+#ifdef CONFIG_DEVFS_FS
-+ if (devfs_register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
-+#else
-+ if (register_chrdev(SPI_MAJOR, "spi", &spidev_fops)) {
-+#endif
-+ printk(KERN_ERR "at91_spidev: Unable to get major %d for SPI bus\n", SPI_MAJOR);
-+ return -EIO;
-+ }
-+
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_handle = devfs_mk_dir(NULL, "spi", NULL);
-+
-+ for (i = 0; i < NR_SPI_DEVICES; i++) {
-+ sprintf (name, "%d", i);
-+ devfs_spi[i] = devfs_register (devfs_handle, name,
-+ DEVFS_FL_DEFAULT, SPI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR,
-+ &spidev_fops, NULL);
-+ }
-+#endif
-+ printk(KERN_INFO "AT91 SPI driver loaded\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Remove the SPI /dev interface driver
-+ */
-+static void __exit at91_spidev_exit(void)
-+{
-+#ifdef CONFIG_DEVFS_FS
-+ devfs_unregister(devfs_handle);
-+ if (devfs_unregister_chrdev(SPI_MAJOR, "spi")) {
-+#else
-+ if (unregister_chrdev(SPI_MAJOR,"spi")) {
-+#endif
-+ printk(KERN_ERR "at91_spidev: Unable to release major %d for SPI bus\n", SPI_MAJOR);
-+ return;
-+ }
-+}
-+
-+module_init(at91_spidev_init);
-+module_exit(at91_spidev_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("SPI /dev interface for Atmel AT91RM9200")
---- /dev/null
-+++ linux-2.4.27/drivers/at91/usb/Makefile
-@@ -0,0 +1,17 @@
-+# File: drivers/at91/usb/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 USB device drivers
-+#
-+
-+O_TARGET := at91usb.o
-+
-+export-objs :=
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_USB_OHCI_AT91) += at91_usb-ohci.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/usb/at91_usb-ohci.c
-@@ -0,0 +1,85 @@
-+/*
-+ * linux/drivers/at91/usb/at91_usb_ohci-at91.c
-+ *
-+ * (c) Rick Bronson
-+ *
-+ * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
-+ * original OHCI driver modifications, and reworked into a cleaner form
-+ * by Russell King <rmk@arm.linux.org.uk>.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/usb.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+
-+#include <asm/arch/AT91RM9200_UHP.h>
-+
-+/*
-+ NOTE:
-+ The following is so that we don't have to include usb-ohci.h or pci.h as the
-+ usb-ohci.c driver needs these routines even when the architecture
-+ has no PCI bus...
-+*/
-+
-+extern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase,
-+ unsigned long flags, void *ohci, const char *name,
-+ const char *slot_name);
-+extern void hc_remove_ohci(void *ohci);
-+
-+static void *at91_ohci;
-+AT91PS_UHP ohci_regs;
-+
-+static int __init at91_ohci_init(void)
-+{
-+ int ret;
-+
-+ ohci_regs = ioremap(AT91_UHP_BASE, SZ_4K);
-+ if (!ohci_regs) {
-+ printk(KERN_ERR "at91_usb-ohci: ioremap failed\n");
-+ return -EIO;
-+ }
-+
-+ /* Enable PLLB */
-+ AT91_SYS->CKGR_PLLBR = AT91_PLLB_INIT;
-+ while ((AT91_SYS->PMC_SR & 4) == 0);
-+
-+ /* Now, enable the USB clock */
-+ AT91_SYS->PMC_SCER = AT91C_PMC_UHP; /* enable system clock */
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_UHP; /* enable peripheral clock */
-+
-+ /* Take Hc out of reset */
-+ ohci_regs->UHP_HcControl = 2 << 6;
-+
-+ /* Initialise the generic OHCI driver. */
-+ ret = hc_add_ohci((struct pci_dev *) 1, AT91C_ID_UHP,
-+ (void *)ohci_regs, 0, &at91_ohci,
-+ "usb-ohci", "at91");
-+ if (ret)
-+ iounmap(ohci_regs);
-+
-+ return ret;
-+}
-+
-+static void __exit at91_ohci_exit(void)
-+{
-+ hc_remove_ohci(at91_ohci);
-+
-+ /* Force UHP_Hc to reset */
-+ ohci_regs->UHP_HcControl = 0;
-+
-+ /* Stop the USB clock. */
-+ AT91_SYS->PMC_SCDR = AT91C_PMC_UHP; /* disable system clock */
-+ AT91_SYS->PMC_PCDR = 1 << AT91C_ID_UHP; /* disable peripheral clock */
-+
-+ iounmap(ohci_regs);
-+}
-+
-+module_init(at91_ohci_init);
-+module_exit(at91_ohci_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/at91/watchdog/Makefile
-@@ -0,0 +1,15 @@
-+# File: drivers/at91/watchdog/Makefile
-+#
-+# Makefile for the Atmel AT91RM9200 watchdog device driver
-+#
-+
-+O_TARGET := at91wdt.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/at91/watchdog/at91_wdt.c
-@@ -0,0 +1,193 @@
-+/*
-+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
-+ *
-+ * (c) SAN People (Pty) Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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/module.h>
-+#include <linux/config.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <asm/uaccess.h>
-+#include <linux/init.h>
-+
-+#define WDT_DEFAULT_TIME 5 /* 5 seconds */
-+#define WDT_MAX_TIME 256 /* 256 seconds */
-+
-+static int at91wdt_time = WDT_DEFAULT_TIME;
-+static int at91wdt_busy;
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Disable the watchdog.
-+ */
-+static void at91_wdt_stop(void)
-+{
-+ AT91_SYS->ST_WDMR = AT91C_ST_EXTEN;
-+}
-+
-+/*
-+ * Enable and reset the watchdog.
-+ */
-+static void at91_wdt_start(void)
-+{
-+ AT91_SYS->ST_WDMR = AT91C_ST_EXTEN | AT91C_ST_RSTEN | (((65536 * at91wdt_time) >> 8) & AT91C_ST_WDV);
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST;
-+}
-+
-+/* ......................................................................... */
-+
-+/*
-+ * Watchdog device is opened, and watchdog starts running.
-+ */
-+static int at91_wdt_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit(1, &at91wdt_busy))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+
-+ /*
-+ * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
-+ *
-+ * Since WDV is a 16-bit counter, the maximum period is
-+ * 65536 / 0.256 = 256 seconds.
-+ */
-+
-+ at91_wdt_start();
-+ return 0;
-+}
-+
-+/*
-+ * Close the watchdog device.
-+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
-+ * disabled.
-+ */
-+static int at91_wdt_close(struct inode *inode, struct file *file)
-+{
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ /* Disable the watchdog when file is closed */
-+ at91_wdt_stop();
-+#endif
-+
-+ at91wdt_busy = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+/*
-+ * Handle commands from user-space.
-+ */
-+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ unsigned int new_value;
-+ static struct watchdog_info info = {
-+ identity: "at91 watchdog",
-+ options: WDIOF_SETTIMEOUT,
-+ };
-+
-+ switch(cmd) {
-+ case WDIOC_KEEPALIVE:
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
-+ return 0;
-+
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &info, sizeof(info));
-+
-+ case WDIOC_SETTIMEOUT:
-+ if (get_user(new_value, (int *)arg))
-+ return -EFAULT;
-+ if ((new_value <= 0) || (new_value > WDT_MAX_TIME))
-+ return -EINVAL;
-+
-+ /* Restart watchdog with new time */
-+ at91wdt_time = new_value;
-+ at91_wdt_start();
-+
-+ /* Return current value */
-+ return put_user(at91wdt_time, (int *)arg);
-+
-+ case WDIOC_GETTIMEOUT:
-+ return put_user(at91wdt_time, (int *)arg);
-+
-+ case WDIOC_GETSTATUS:
-+ return put_user(0, (int *)arg);
-+
-+ case WDIOC_SETOPTIONS:
-+ if (get_user(new_value, (int *)arg))
-+ return -EFAULT;
-+ if (new_value & WDIOS_DISABLECARD)
-+ at91_wdt_stop();
-+ if (new_value & WDIOS_ENABLECARD)
-+ at91_wdt_start();
-+ return 0;
-+
-+ default:
-+ return -ENOIOCTLCMD;
-+ }
-+}
-+
-+/*
-+ * Pat the watchdog whenever device is written to.
-+ */
-+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ if (len) {
-+ AT91_SYS->ST_CR = AT91C_ST_WDRST; /* Pat the watchdog */
-+ return len;
-+ }
-+
-+ return 0;
-+}
-+
-+/* ......................................................................... */
-+
-+static struct file_operations at91wdt_fops =
-+{
-+ .owner = THIS_MODULE,
-+ .ioctl = at91_wdt_ioctl,
-+ .open = at91_wdt_open,
-+ .release = at91_wdt_close,
-+ .write = at91_wdt_write,
-+};
-+
-+static struct miscdevice at91wdt_miscdev =
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "watchdog",
-+ .fops = &at91wdt_fops,
-+};
-+
-+static int __init at91_wdt_init(void)
-+{
-+ int res;
-+
-+ res = misc_register(&at91wdt_miscdev);
-+ if (res)
-+ return res;
-+
-+ printk("AT91 Watchdog Timer enabled (%d seconds)\n", WDT_DEFAULT_TIME);
-+ return 0;
-+}
-+
-+static void __exit at91_wdt_exit(void)
-+{
-+ misc_deregister(&at91wdt_miscdev);
-+}
-+
-+module_init(at91_wdt_init);
-+module_exit(at91_wdt_exit);
-+
-+MODULE_LICENSE("GPL")
-+MODULE_AUTHOR("Andrew Victor")
-+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200")
---- linux-2.4.27/drivers/block/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/block/Makefile
-@@ -27,7 +27,7 @@
- obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o
- obj-$(CONFIG_BLK_DEV_XD) += xd.o
- obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
--obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
-+obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
- obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
- obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
- obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
-@@ -35,4 +35,10 @@
-
- subdir-$(CONFIG_PARIDE) += paride
-
-+ifeq ($(CONFIG_ARCH_ACORN),y)
-+mod-subdirs += ../acorn/block
-+subdir-y += ../acorn/block
-+obj-y += ../acorn/block/acorn-block.o
-+endif
-+
- include $(TOPDIR)/Rules.make
---- linux-2.4.27/drivers/block/ll_rw_blk.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/block/ll_rw_blk.c
-@@ -32,6 +32,19 @@
- #include <linux/slab.h>
- #include <linux/module.h>
-
-+/* Maybe something to cleanup in 2.3?
-+ * We shouldn't touch 0x3f2 on machines which don't have a PC floppy controller
-+ * - it may contain something else which could cause a system hang. This is
-+ * now selected by a configuration option, but maybe it ought to be in the
-+ * floppy code itself? - rmk
-+ */
-+#if defined(__i386__) || (defined(__arm__) && defined(CONFIG_ARCH_ACORN))
-+#define FLOPPY_BOOT_DISABLE
-+#endif
-+#ifdef CONFIG_BLK_DEV_FD
-+#undef FLOPPY_BOOT_DISABLE
-+#endif
-+
- /*
- * MAC Floppy IWM hooks
- */
-@@ -524,7 +537,7 @@
- elevator_init(&q->elevator, ELEVATOR_LINUS);
- blk_init_free_list(q);
- q->request_fn = rfn;
-- q->back_merge_fn = ll_back_merge_fn;
-+ q->back_merge_fn = ll_back_merge_fn;
- q->front_merge_fn = ll_front_merge_fn;
- q->merge_requests_fn = ll_merge_requests_fn;
- q->make_request_fn = __make_request;
-@@ -1549,7 +1562,7 @@
- mfm_init();
- #endif
- #ifdef CONFIG_PARIDE
-- { extern void paride_init(void); paride_init(); };
-+ { extern void paride_init(void); paride_init(); }
- #endif
- #ifdef CONFIG_MAC_FLOPPY
- swim3_init();
-@@ -1563,12 +1576,14 @@
- #ifdef CONFIG_ATARI_FLOPPY
- atari_floppy_init();
- #endif
-+#ifdef CONFIG_BLK_DEV_FD1772
-+ fd1772_init();
-+#endif
- #ifdef CONFIG_BLK_DEV_FD
- floppy_init();
--#else
--#if defined(__i386__) /* Do we even need this? */
-- outb_p(0xc, 0x3f2);
- #endif
-+#ifdef FLOPPY_BOOT_DISABLE
-+ outb_p(0xc, 0x3f2);
- #endif
- #ifdef CONFIG_CDU31A
- cdu31a_init();
-@@ -1626,7 +1641,7 @@
- jsfd_init();
- #endif
- return 0;
--};
-+}
-
- EXPORT_SYMBOL(io_request_lock);
- EXPORT_SYMBOL(end_that_request_first);
---- linux-2.4.27/drivers/cdrom/cdrom.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/cdrom/cdrom.c
-@@ -246,8 +246,8 @@
- #define CD_DVD 0x80
-
- /* Define this to remove _all_ the debugging messages */
--/* #define ERRLOGMASK CD_NOTHING */
--#define ERRLOGMASK (CD_WARNING)
-+#define ERRLOGMASK CD_NOTHING
-+/* #define ERRLOGMASK (CD_WARNING) */
- /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
- /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
-
---- linux-2.4.27/drivers/char/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/Config.in
-@@ -20,10 +20,10 @@
- if [ "$CONFIG_IA64" = "y" ]; then
- bool ' Support for serial port described by EFI HCDP table' CONFIG_SERIAL_HCDP
- fi
-- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-- tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
-- tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
-- fi
-+fi
-+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-+ dep_tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_SERIAL
-+ dep_tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL $CONFIG_SERIAL
- fi
- dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
- if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
-@@ -132,18 +132,6 @@
- bool ' SGI SN2 IOC4 serial port support' CONFIG_SGI_IOC4_SERIAL
- fi
- fi
--fi
--if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
-- tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
--fi
--if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-- bool 'DC21285 serial port support' CONFIG_SERIAL_21285
-- if [ "$CONFIG_SERIAL_21285" = "y" ]; then
-- if [ "$CONFIG_OBSOLETE" = "y" ]; then
-- bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
-- fi
-- bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
-- fi
- if [ "$CONFIG_PARISC" = "y" ]; then
- bool ' PDC software console support' CONFIG_PDC_CONSOLE
- fi
-@@ -168,6 +156,16 @@
- if [ "$CONFIG_CPU_VR41XX" = "y" ]; then
- bool 'NEC VR4100 series Keyboard Interface Unit Support ' CONFIG_VR41XX_KIU
- fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'AT91RM9200 SPI device interface' CONFIG_AT91_SPIDEV
-+fi
-+
-+source drivers/serial/Config.in
-+
-+if [ "$CONFIG_ARCH_ANAKIN" = "y" ]; then
-+ tristate 'Anakin touchscreen support' CONFIG_TOUCHSCREEN_ANAKIN
-+fi
-+
- bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
- if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
- int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
-@@ -190,6 +188,12 @@
-
- source drivers/i2c/Config.in
-
-+if [ "$CONFIG_I2C" != "n" ]; then
-+ dep_tristate ' DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C
-+fi
-+
-+source drivers/l3/Config.in
-+
- mainmenu_option next_comment
- comment 'Mice'
- tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
-@@ -245,11 +249,13 @@
- tristate ' ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
- tristate ' AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
- tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
-- if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-- tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG
-- if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
-- tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG
-- fi
-+ if [ "$CONFIG_ARM" = "y" ]; then
-+ dep_tristate ' DC21285 watchdog' CONFIG_21285_WATCHDOG $CONFIG_FOOTBRIDGE
-+ dep_tristate ' NetWinder WB83C977 watchdog' CONFIG_977_WATCHDOG $CONFIG_ARCH_NETWINDER
-+ dep_tristate ' SA1100 watchdog' CONFIG_SA1100_WATCHDOG $CONFIG_ARCH_SA1100
-+ dep_tristate ' EPXA watchdog' CONFIG_EPXA_WATCHDOG $CONFIG_ARCH_CAMELOT
-+ dep_tristate ' Omaha watchdog' CONFIG_OMAHA_WATCHDOG $CONFIG_ARCH_OMAHA
-+ dep_tristate ' AT91RM9200 watchdog' CONFIG_AT91_WATCHDOG $CONFIG_ARCH_AT91RM9200
- fi
- tristate ' Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
- tristate ' IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
-@@ -325,6 +331,15 @@
- if [ "$CONFIG_TOSHIBA_RBTX4927" = "y" -o "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then
- tristate 'Dallas DS1742 RTC support' CONFIG_DS1742
- fi
-+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ tristate 'SA1100 Real Time Clock' CONFIG_SA1100_RTC
-+fi
-+if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ tristate 'Omaha Real Time Clock' CONFIG_OMAHA_RTC
-+fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'AT91RM9200 Real Time Clock' CONFIG_AT91_RTC
-+fi
-
- tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
- tristate 'Siemens R3964 line discipline' CONFIG_R3964
---- linux-2.4.27/drivers/char/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/Makefile
-@@ -29,7 +29,7 @@
-
- mod-subdirs := joystick ftape drm drm-4.0 pcmcia
-
--list-multi :=
-+list-multi :=
-
- KEYMAP =defkeymap.o
- KEYBD =pc_keyb.o
-@@ -106,11 +106,39 @@
- endif
-
- ifeq ($(ARCH),arm)
-- ifneq ($(CONFIG_PC_KEYMAP),y)
-- KEYMAP =
-+ KEYMAP :=
-+ KEYBD :=
-+ ifeq ($(CONFIG_PC_KEYMAP),y)
-+ KEYMAP := defkeymap.o
- endif
-- ifneq ($(CONFIG_PC_KEYB),y)
-- KEYBD =
-+ ifeq ($(CONFIG_PC_KEYB),y)
-+ KEYBD += pc_keyb.o
-+ endif
-+ ifeq ($(CONFIG_KMI_KEYB),y)
-+ KEYBD += amba_kmi_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1111),y)
-+ KEYBD += sa1111_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_EDB7211),y)
-+ KEYBD += edb7211_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_AUTCPU12),y)
-+ KEYMAP := defkeymap.o
-+ KEYBD += clps711x_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
-+ KEYMAP = gckeymap.o
-+ KEYBD += gc_keyb.o
-+ endif
-+ ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
-+ KEYBD += cerf_keyb.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_FORTUNET),y)
-+ KEYMAP := defkeymap.o
-+ endif
-+ ifeq ($(CONFIG_ARCH_GUIDEA07),y)
-+ KEYMAP := defkeymap.o
- endif
- endif
-
-@@ -173,11 +201,9 @@
- obj-$(CONFIG_SERIAL) += $(SERIAL)
- obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o
- obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
--obj-$(CONFIG_SERIAL_21285) += serial_21285.o
--obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
--obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o
- obj-$(CONFIG_TS_AU1X00_ADS7846) += au1000_ts.o
- obj-$(CONFIG_SERIAL_DEC) += decserial.o
-+obj-$(CONFIG_TOUCHSCREEN_ANAKIN) += anakin_ts.o
-
- ifndef CONFIG_SUN_KEYBOARD
- obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
-@@ -254,6 +280,8 @@
- obj-$(CONFIG_SGI_DS1286) += ds1286.o
- obj-$(CONFIG_MIPS_RTC) += mips_rtc.o
- obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
-+obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
-+obj-$(CONFIG_OMAHA_RTC) += omaha-rtc.o
- ifeq ($(CONFIG_PPC),)
- obj-$(CONFIG_NVRAM) += nvram.o
- endif
-@@ -292,6 +320,7 @@
- obj-$(CONFIG_NWFLASH) += nwflash.o
- obj-$(CONFIG_SCx200) += scx200.o
- obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
-+obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o
-
- # Only one watchdog can succeed. We probe the hardware watchdog
- # drivers first, then the softdog driver. This means if your hardware
-@@ -320,15 +349,27 @@
- obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
- obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
- obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
-+obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
-+obj-$(CONFIG_EPXA_WATCHDOG) += epxa_wdt.o
-+obj-$(CONFIG_OMAHA_WATCHDOG) += omaha_wdt.o
- obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
- obj-$(CONFIG_INDYDOG) += indydog.o
- obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
-
-+# I2C char devices
-+obj-$(CONFIG_I2C_DS1307) += ds1307.o
-+
- subdir-$(CONFIG_MWAVE) += mwave
- ifeq ($(CONFIG_MWAVE),y)
- obj-y += mwave/mwave.o
- endif
-
-+ifeq ($(CONFIG_ARCH_ACORN),y)
-+mod-subdirs += ../acorn/char
-+subdir-y += ../acorn/char
-+obj-y += ../acorn/char/acorn-char.o
-+endif
-+
- subdir-$(CONFIG_IPMI_HANDLER) += ipmi
- ifeq ($(CONFIG_IPMI_HANDLER),y)
- obj-y += ipmi/ipmi.o
---- /dev/null
-+++ linux-2.4.27/drivers/char/amba_kmi_keyb.c
-@@ -0,0 +1,999 @@
-+/*
-+ * linux/drivers/char/amba_kmi_keyb.c
-+ *
-+ * AMBA Keyboard and Mouse Interface Driver
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * This keyboard driver drives a PS/2 keyboard and mouse connected
-+ * to the KMI interfaces. The KMI interfaces are nothing more than
-+ * a uart; there is no inteligence in them to do keycode translation.
-+ * We leave all that up to the keyboard itself.
-+ *
-+ * FIXES:
-+ * dirk.uffmann@nokia.com: enabled PS/2 reconnection
-+ */
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h> /* for in_interrupt */
-+#include <linux/timer.h>
-+#include <linux/init.h>
-+#include <linux/delay.h> /* for udelay */
-+#include <linux/kbd_kern.h> /* for keyboard_tasklet */
-+#include <linux/kbd_ll.h>
-+
-+#include <asm/io.h>
-+#include <asm/hardware/amba_kmi.h>
-+#include <asm/mach/amba_kmi.h>
-+#include <asm/keyboard.h>
-+
-+//#define DEBUG(s) printk s
-+#define DEBUG(s) do { } while (0)
-+
-+#define CONFIG_AMBA_PS2_RECONNECT
-+
-+#define KMI_BASE (kmi->base)
-+
-+#define KMI_RESET 0x00
-+#define KMI_RESET_POR 0x01
-+#define KMI_RESET_DONE 0x02
-+
-+#define KMI_NO_ACK 0xffff
-+
-+#define PS2_O_RESET 0xff
-+#define PS2_O_RESEND 0xfe
-+#define PS2_O_DISABLE 0xf5
-+#define PS2_O_ENABLE 0xf4
-+#define PS2_O_ECHO 0xee
-+
-+/*
-+ * Keyboard
-+ */
-+#define PS2_O_SET_DEFAULT 0xf6
-+#define PS2_O_SET_RATE_DELAY 0xf3
-+#define PS2_O_SET_SCANSET 0xf0
-+#define PS2_O_INDICATORS 0xed
-+
-+/*
-+ * Mouse
-+ */
-+#define PS2_O_SET_SAMPLE 0xf3
-+#define PS2_O_SET_STREAM 0xea
-+#define PS2_O_SET_RES 0xe8
-+#define PS2_O_SET_SCALE21 0xe7
-+#define PS2_O_SET_SCALE11 0xe6
-+#define PS2_O_REQ_STATUS 0xe9
-+
-+/*
-+ * Responses
-+ */
-+#define PS2_I_RESEND 0xfe
-+#define PS2_I_DIAGFAIL 0xfc
-+#define PS2_I_ACK 0xfa
-+#define PS2_I_BREAK 0xf0
-+#define PS2_I_ECHO 0xee
-+#define PS2_I_BAT_OK 0xaa
-+
-+static char *kmi_type[] = { "Keyboard", "Mouse" };
-+
-+static struct kmi_info *kmi_keyb;
-+static struct kmi_info *kmi_mouse;
-+
-+static inline void __kmi_send(struct kmi_info *kmi, u_int val)
-+{
-+ u_int status;
-+
-+ do {
-+ status = __raw_readb(KMISTAT);
-+ } while (!(status & KMISTAT_TXEMPTY));
-+
-+ kmi->resend_count += 1;
-+ __raw_writeb(val, KMIDATA);
-+}
-+
-+static void kmi_send(struct kmi_info *kmi, u_int val)
-+{
-+ kmi->last_tx = val;
-+ kmi->resend_count = -1;
-+ __kmi_send(kmi, val);
-+}
-+
-+static u_int kmi_send_and_wait(struct kmi_info *kmi, u_int val, u_int timeo)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ if (kmi->present == 0)
-+ return KMI_NO_ACK;
-+
-+ kmi->res = KMI_NO_ACK;
-+ kmi->last_tx = val;
-+ kmi->resend_count = -1;
-+
-+ if (current->pid != 0 && !in_interrupt()) {
-+ add_wait_queue(&kmi->wait_q, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ __kmi_send(kmi, val);
-+ schedule_timeout(timeo);
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&kmi->wait_q, &wait);
-+ } else {
-+ int i;
-+
-+ __kmi_send(kmi, val);
-+ for (i = 0; i < 1000; i++) {
-+ if (kmi->res != KMI_NO_ACK)
-+ break;
-+ udelay(100);
-+ }
-+ }
-+
-+ return kmi->res;
-+}
-+
-+/*
-+ * This lot should probably be separated into a separate file...
-+ */
-+#ifdef CONFIG_KMI_MOUSE
-+
-+#include <linux/fs.h> /* for struct file_ops */
-+#include <linux/poll.h> /* for poll_table */
-+#include <linux/miscdevice.h> /* for struct miscdev */
-+#include <linux/random.h> /* for add_mouse_randomness */
-+#include <linux/slab.h> /* for kmalloc */
-+#include <linux/smp_lock.h> /* for {un,}lock_kernel */
-+#include <linux/spinlock.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define BUF_SZ 2048
-+
-+static spinlock_t kmi_mouse_lock;
-+static int kmi_mouse_count;
-+static struct queue {
-+ u_int head;
-+ u_int tail;
-+ struct fasync_struct *fasync;
-+ unsigned char buf[BUF_SZ];
-+} *queue;
-+
-+#define queue_empty() (queue->head == queue->tail)
-+
-+static u_char get_from_queue(void)
-+{
-+ unsigned long flags;
-+ u_char res;
-+
-+ spin_lock_irqsave(&kmi_mouse_lock, flags);
-+ res = queue->buf[queue->tail];
-+ queue->tail = (queue->tail + 1) & (BUF_SZ-1);
-+ spin_unlock_irqrestore(&kmi_mouse_lock, flags);
-+
-+ return res;
-+}
-+
-+static ssize_t
-+kmi_mouse_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ ssize_t i = count;
-+
-+ if (queue_empty()) {
-+ int ret;
-+
-+ if (file->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ ret = wait_event_interruptible(kmi_mouse->wait_q, !queue_empty());
-+ if (ret)
-+ return ret;
-+ }
-+ while (i > 0 && !queue_empty()) {
-+ u_char c;
-+ c = get_from_queue();
-+ put_user(c, buf++);
-+ i--;
-+ }
-+ if (count - i)
-+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-+ return count - i;
-+}
-+
-+static ssize_t
-+kmi_mouse_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-+{
-+ ssize_t retval = 0;
-+
-+ if (count > 32)
-+ count = 32;
-+
-+ do {
-+ char c;
-+ get_user(c, buf++);
-+ kmi_send_and_wait(kmi_mouse, c, HZ);
-+ retval++;
-+ } while (--count);
-+
-+ if (retval)
-+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-+
-+ return retval;
-+}
-+
-+static unsigned int
-+kmi_mouse_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait(file, &kmi_mouse->wait_q, wait);
-+ return (!queue_empty()) ? POLLIN | POLLRDNORM : 0;
-+}
-+
-+static int
-+kmi_mouse_release(struct inode *inode, struct file *file)
-+{
-+ lock_kernel();
-+ fasync_helper(-1, file, 0, &queue->fasync);
-+ if (--kmi_mouse_count == 0)
-+ kmi_send_and_wait(kmi_mouse, PS2_O_DISABLE, HZ);
-+ unlock_kernel();
-+ return 0;
-+}
-+
-+static int
-+kmi_mouse_open(struct inode *inode, struct file *file)
-+{
-+ if (kmi_mouse_count++)
-+ return 0;
-+ queue->head = queue->tail = 0;
-+ kmi_send_and_wait(kmi_mouse, PS2_O_ENABLE, HZ);
-+ return 0;
-+}
-+
-+static int
-+kmi_mouse_fasync(int fd, struct file *filp, int on)
-+{
-+ int retval = fasync_helper(fd, filp, on, &queue->fasync);
-+ if (retval > 0)
-+ retval = 0;
-+ return retval;
-+}
-+
-+static struct file_operations ps_fops = {
-+ read: kmi_mouse_read,
-+ write: kmi_mouse_write,
-+ poll: kmi_mouse_poll,
-+ open: kmi_mouse_open,
-+ release: kmi_mouse_release,
-+ fasync: kmi_mouse_fasync,
-+};
-+
-+static struct miscdevice ps_mouse = {
-+ minor: PSMOUSE_MINOR,
-+ name: "psaux",
-+ fops: &ps_fops,
-+};
-+
-+static u_char kmi_mse_init_string[] = {
-+ PS2_O_DISABLE,
-+ PS2_O_SET_SAMPLE, 100,
-+ PS2_O_SET_RES, 3,
-+ PS2_O_SET_SCALE21
-+};
-+
-+/*
-+ * The "normal" mouse scancode processing
-+ */
-+static void kmi_mse_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+ u_int head;
-+
-+ add_mouse_randomness(val);
-+
-+#ifdef CONFIG_AMBA_PS2_RECONNECT
-+ /* Try to detect a hot-plug event on the PS/2 mouse port */
-+ switch (kmi->hotplug_state) {
-+ case 0:
-+ /* Maybe we lost contact... */
-+ if (val == PS2_I_BAT_OK) {
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ }
-+ break;
-+
-+ case 1:
-+ /* Again, maybe (but only maybe) we lost contact... */
-+ if (val == 0) {
-+ kmi->hotplug_state++;
-+ kmi_send(kmi, PS2_O_REQ_STATUS);
-+ DEBUG(("%s: Got 0xAA 0x00. Sent Status Request\n", kmi->name));
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: No 0x00 followed 0xAA. No reconnect.\n", kmi->name));
-+ }
-+ break;
-+
-+ case 2:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK)
-+ kmi->hotplug_state++;
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 3:
-+ /* check if data reporting is still enabled, then no POR has happend */
-+ kmi->reconnect = !(val & 1<<5);
-+ DEBUG(("%s: Data reporting disabled?: (%d)\n", kmi->name, kmi->reconnect));
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ break;
-+
-+ case 4:
-+ /* Eat up one status byte */
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ break;
-+
-+ case 5:
-+ /* Eat up another status byte */
-+ if (kmi->reconnect) {
-+ kmi->config_num = 0;
-+ kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
-+ kmi->config_num++;
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: False Alarm...\n", kmi->name));
-+ }
-+ break;
-+
-+ case 6:
-+ if (val == PS2_I_ACK && kmi->config_num < sizeof(kmi_mse_init_string)) {
-+ kmi_send(kmi, kmi_mse_init_string[kmi->config_num]);
-+ kmi->config_num++;
-+ DEBUG(("%s: Sending byte %d of PS/2 init string.\n", kmi->name, kmi->config_num));
-+ } else {
-+ if (val == PS2_I_ACK) {
-+ DEBUG(("%s: Now enable the mouse again...\n", kmi->name));
-+ queue->head = queue->tail = 0;
-+ kmi_send(kmi, PS2_O_ENABLE);
-+ kmi->hotplug_state++;
-+ } else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ }
-+ break;
-+
-+ case 7:
-+ /* Eat up last acknowledge from enable */
-+ if (val == PS2_I_ACK)
-+ printk(KERN_ERR "%s: reconnected\n", kmi->name);
-+ else
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+
-+ kmi->hotplug_state = 0;
-+ break;
-+
-+ } /* switch (kmi->hotplug_state) */
-+
-+ /* while inside hotplug mechanism, don't misinterpret values */
-+ if (kmi->hotplug_state > 2)
-+ return;
-+#endif
-+
-+ /* We are waiting for the mouse to respond to a kmi_send_and_wait() */
-+ if (kmi->res == KMI_NO_ACK) {
-+ if (val == PS2_I_RESEND) {
-+ if (kmi->resend_count < 5)
-+ __kmi_send(kmi, kmi->last_tx);
-+ else {
-+ printk(KERN_ERR "%s: too many resends\n", kmi->name);
-+ return;
-+ }
-+ }
-+
-+ if (val == PS2_I_ACK) {
-+ kmi->res = val;
-+ wake_up(&kmi->wait_q);
-+ }
-+ return;
-+ }
-+
-+ /* The mouse autonomously send new data, so wake up mouse_read() */
-+ if (queue) {
-+ head = queue->head;
-+ queue->buf[head] = val;
-+ head = (head + 1) & (BUF_SZ - 1);
-+ if (head != queue->tail) {
-+ queue->head = head;
-+ kill_fasync(&queue->fasync, SIGIO, POLL_IN);
-+ wake_up_interruptible(&kmi->wait_q);
-+ }
-+ }
-+}
-+
-+static int kmi_init_mouse(struct kmi_info *kmi)
-+{
-+ u_int ret, i;
-+
-+ if (kmi->present) {
-+ kmi->rx = kmi_mse_intr;
-+
-+ for (i = 0; i < sizeof(kmi_mse_init_string); i++) {
-+ ret = kmi_send_and_wait(kmi, kmi_mse_init_string[i], HZ);
-+ if (ret != PS2_I_ACK)
-+ printk("%s: didn't get ack (0x%2.2x)\n",
-+ kmi->name, ret);
-+ }
-+ }
-+
-+ queue = kmalloc(sizeof(*queue), GFP_KERNEL);
-+ if (queue) {
-+ memset(queue, 0, sizeof(*queue));
-+ misc_register(&ps_mouse);
-+ ret = 0;
-+ } else
-+ ret = -ENOMEM;
-+
-+ return ret;
-+}
-+#endif /* CONFIG_KMI_MOUSE */
-+
-+/*
-+ * The "program" we send to the keyboard to set it up how we want it:
-+ * - default typematic delays
-+ * - scancode set 1
-+ */
-+static u_char kmi_kbd_init_string[] = {
-+ PS2_O_DISABLE,
-+ PS2_O_SET_DEFAULT,
-+ PS2_O_SET_SCANSET, 0x01,
-+ PS2_O_ENABLE
-+};
-+
-+static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs);
-+
-+static int __kmi_init_keyboard(struct kmi_info *kmi)
-+{
-+ u_int ret, i;
-+
-+ if (!kmi->present)
-+ return 0;
-+
-+ kmi->rx = kmi_kbd_intr;
-+
-+ for (i = 0; i < sizeof(kmi_kbd_init_string); i++) {
-+ ret = kmi_send_and_wait(kmi, kmi_kbd_init_string[i], HZ);
-+ if (ret != PS2_I_ACK)
-+ printk("%s: didn't ack (0x%2.2x)\n",
-+ kmi->name, ret);
-+ }
-+
-+ return 0;
-+}
-+
-+static void kmi_kbd_init_tasklet(unsigned long k)
-+{
-+ struct kmi_info *kmi = (struct kmi_info *)k;
-+ __kmi_init_keyboard(kmi);
-+}
-+
-+static DECLARE_TASKLET_DISABLED(kmikbd_init_tasklet, kmi_kbd_init_tasklet, 0);
-+
-+/*
-+ * The "normal" keyboard scancode processing
-+ */
-+static void kmi_kbd_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+#ifdef CONFIG_AMBA_PS2_RECONNECT
-+ /* Try to detect a hot-plug event on the PS/2 keyboard port */
-+ switch (kmi->hotplug_state) {
-+ case 0:
-+ /* Maybe we lost contact... */
-+ if (val == PS2_I_BAT_OK) {
-+ kmi_send(kmi, PS2_O_SET_SCANSET);
-+ kmi->hotplug_state++;
-+ DEBUG(("%s: Saw 0xAA. Going to hotplug state %d\n", kmi->name, kmi->hotplug_state));
-+ }
-+ break;
-+
-+ case 1:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK) {
-+ /* Request scan code set: '2' if POR has happend, '1' is false alarm */
-+ kmi_send(kmi, 0);
-+ kmi->hotplug_state++;
-+ }
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 2:
-+ /* Eat up acknowledge */
-+ if (val == PS2_I_ACK)
-+ kmi->hotplug_state++;
-+ else {
-+ kmi->hotplug_state = 0;
-+ DEBUG(("%s: didn't get ack (0x%2.2x)\n", kmi->name, val));
-+ }
-+ break;
-+
-+ case 3:
-+ kmi->hotplug_state = 0;
-+ if (val == 2) {
-+ DEBUG(("%s: POR detected. Scan code is: (%d)\n", kmi->name, val));
-+ kmi->present = 1;
-+ tasklet_schedule(&kmikbd_init_tasklet);
-+ printk(KERN_ERR "%s: reconnected\n", kmi->name);
-+ return;
-+ }
-+ else
-+ DEBUG(("%s: False Alarm...\n", kmi->name));
-+ break;
-+
-+ } /* switch (kmi->hotplug_state) */
-+#endif
-+
-+ if (val == PS2_I_DIAGFAIL) {
-+ printk(KERN_ERR "%s: diagnostic failed\n", kmi->name);
-+ return;
-+ }
-+
-+ /* We are waiting for the keyboard to respond to a kmi_send_and_wait() */
-+ if (kmi->res == KMI_NO_ACK) {
-+ if (val == PS2_I_RESEND) {
-+ if (kmi->resend_count < 5)
-+ __kmi_send(kmi, kmi->last_tx);
-+ else {
-+ printk(KERN_ERR "%s: too many resends\n", kmi->name);
-+ return;
-+ }
-+ }
-+
-+ if (val >= 0xee) {
-+ kmi->res = val;
-+ wake_up(&kmi->wait_q);
-+ }
-+ return;
-+ }
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+ handle_scancode(val, !(val & 0x80));
-+ tasklet_schedule(&keyboard_tasklet);
-+#endif
-+}
-+
-+static void kmi_intr(int nr, void *devid, struct pt_regs *regs)
-+{
-+ struct kmi_info *kmi = devid;
-+ u_int status = __raw_readb(KMIIR);
-+
-+ if (status & KMIIR_RXINTR) {
-+ u_int val = __raw_readb(KMIDATA);
-+
-+ if (kmi->rx)
-+ kmi->rx(kmi, val, regs);
-+ }
-+}
-+
-+static int kmi_init_keyboard(struct kmi_info *kmi)
-+{
-+ kmikbd_init_tasklet.data = (unsigned long)kmi;
-+ tasklet_enable(&kmikbd_init_tasklet);
-+
-+ return __kmi_init_keyboard(kmi);
-+}
-+
-+/*
-+ * Reset interrupt handler
-+ */
-+static void __init
-+kmi_reset_intr(struct kmi_info *kmi, u_int val, struct pt_regs *regs)
-+{
-+ if (kmi->state == KMI_RESET) {
-+ if (val == PS2_I_ACK)
-+ kmi->state = KMI_RESET_POR;
-+ else {
-+ val = KMI_NO_ACK;
-+ goto finished;
-+ }
-+ } else if (kmi->state == KMI_RESET_POR) {
-+finished:
-+ kmi->res = val;
-+ kmi->state = KMI_RESET_DONE;
-+ kmi->rx = NULL;
-+ wake_up(&kmi->wait_q);
-+ }
-+}
-+
-+/*
-+ * Reset the device plugged into this interface
-+ */
-+static int __init kmi_reset(struct kmi_info *kmi)
-+{
-+ u_int res;
-+ int ret = 0;
-+
-+ kmi->state = KMI_RESET;
-+ kmi->rx = kmi_reset_intr;
-+ res = kmi_send_and_wait(kmi, PS2_O_RESET, HZ);
-+ kmi->rx = NULL;
-+
-+ if (res != PS2_I_BAT_OK) {
-+ printk(KERN_ERR "%s: reset failed; ", kmi->name);
-+ if (kmi->res != KMI_NO_ACK)
-+ printk("code 0x%2.2x\n", kmi->res);
-+ else
-+ printk("no ack\n");
-+ ret = -EINVAL;
-+ }
-+ return ret;
-+}
-+
-+static int __init kmi_init_one_interface(struct kmi_info *kmi)
-+{
-+ u_int stat;
-+ int ret = -ENODEV;
-+
-+ init_waitqueue_head(&kmi->wait_q);
-+
-+ printk(KERN_INFO "%s at 0x%8.8x on irq %d (%s)\n", kmi->name,
-+ kmi->base, kmi->irq, kmi_type[kmi->type]);
-+
-+ /*
-+ * Initialise the KMI interface
-+ */
-+ __raw_writeb(kmi->divisor, KMICLKDIV);
-+ __raw_writeb(KMICR_EN, KMICR);
-+
-+ /*
-+ * Check that the data and clock lines are OK.
-+ */
-+ stat = __raw_readb(KMISTAT);
-+ if ((stat & (KMISTAT_IC|KMISTAT_ID)) != (KMISTAT_IC|KMISTAT_ID)) {
-+ printk(KERN_ERR "%s: %s%s%sline%s stuck low\n", kmi->name,
-+ (stat & KMISTAT_IC) ? "" : "clock ",
-+ (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "and ",
-+ (stat & KMISTAT_ID) ? "" : "data ",
-+ (stat & (KMISTAT_IC | KMISTAT_ID)) ? "" : "s");
-+ goto bad;
-+ }
-+
-+ /*
-+ * Claim the appropriate interrupts
-+ */
-+ ret = request_irq(kmi->irq, kmi_intr, 0, kmi->name, kmi);
-+ if (ret)
-+ goto bad;
-+
-+ /*
-+ * Enable the receive interrupt, and reset the device.
-+ */
-+ __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
-+ kmi->present = 1;
-+ kmi->present = kmi_reset(kmi) == 0;
-+
-+ switch (kmi->type) {
-+ case KMI_KEYBOARD:
-+ ret = kmi_init_keyboard(kmi);
-+ break;
-+
-+#ifdef CONFIG_KMI_MOUSE
-+ case KMI_MOUSE:
-+ ret = kmi_init_mouse(kmi);
-+ break;
-+#endif
-+ }
-+
-+ return ret;
-+
-+bad:
-+ /*
-+ * Oh dear, the interface was bad, disable it.
-+ */
-+ __raw_writeb(0, KMICR);
-+ return ret;
-+}
-+
-+#ifdef CONFIG_VT
-+/*
-+ * The fragment between #ifdef above and #endif * CONFIG_VT *
-+ * is from the pc_keyb.c driver. It is not copyrighted under the
-+ * above notice. This code is by various authors; please see
-+ * drivers/char/pc_keyb.c for further information.
-+ */
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+#define E1_PAUSE 119
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static u_char e0_keys[128] = {
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ E0_KPENTER, E0_RCTRL, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, E0_KPSLASH, 0, E0_PRSCR,
-+ E0_RALT, 0, 0, 0,
-+ 0, E0_F13, E0_F14, E0_HELP,
-+ E0_DO, E0_F17, 0, 0,
-+ 0, 0, E0_BREAK, E0_HOME,
-+ E0_UP, E0_PGUP, 0, E0_LEFT,
-+ E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, E0_MSLW,
-+ E0_MSRW, E0_MSTM, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, E0_MACRO,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0,
-+ 0, 0, 0, 0
-+};
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+u_char kmi_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+int kmi_kbd_setkeycode(u_int scancode, u_int keycode)
-+{
-+ if (scancode < 128 || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int kmi_kbd_getkeycode(u_int scancode)
-+{
-+ if (scancode < 128 || scancode > 255)
-+ return -EINVAL;
-+ return e0_keys[scancode - 128];
-+}
-+
-+int kmi_kbd_translate(u_char scancode, u_char *keycode, char raw_mode)
-+{
-+ static int prev_scancode = 0;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xff is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ int old_scancode = prev_scancode;
-+
-+ prev_scancode = 0;
-+ switch (old_scancode) {
-+ case 0xe0:
-+ /*
-+ * The keyboard maintains its own internal caps lock
-+ * and num lock status. In caps lock mode, E0 AA
-+ * precedes make code and E0 2A follows break code.
-+ * In numlock mode, E0 2A precedes make code, and
-+ * E0 AA follows break code. We do our own book-
-+ * keeping, so we will just ignore these.
-+ *
-+ * For my keyboard there is no caps lock mode, but
-+ * there are both Shift-L and Shift-R modes. The
-+ * former mode generates E0 2A / E0 AA pairs, the
-+ * latter E0 B6 / E0 36 pairs. So, we should also
-+ * ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scancode e0 %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+
-+ case 0xe1:
-+ if (scancode == 0x1d)
-+ prev_scancode = 0x100;
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scancode e1 %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+
-+ case 0x100:
-+ if (scancode == 0x45)
-+ *keycode = E1_PAUSE;
-+ else {
-+ if (!raw_mode)
-+ printk(KERN_INFO "kbd: unknown "
-+ "scan code e1 1d %02x\n",
-+ scancode);
-+ return 0;
-+ }
-+ break;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+char kmi_kbd_unexpected_up(u_char keycode)
-+{
-+ return 0x80;
-+}
-+
-+void kmi_kbd_leds(u_char leds)
-+{
-+ struct kmi_info *kmi = kmi_keyb;
-+ u_int ret;
-+
-+ if (kmi) {
-+ ret = kmi_send_and_wait(kmi, PS2_O_INDICATORS, HZ);
-+ if (ret != KMI_NO_ACK)
-+ ret = kmi_send_and_wait(kmi, leds, HZ);
-+ if (ret == KMI_NO_ACK)
-+ kmi->present = 0;
-+ }
-+}
-+
-+int __init kmi_kbd_init(void)
-+{
-+ int ret = -ENODEV;
-+
-+ if (kmi_keyb) {
-+ strcpy(kmi_keyb->name, "kmikbd");
-+ ret = kmi_init_one_interface(kmi_keyb);
-+ }
-+
-+ if (ret == 0) {
-+ k_setkeycode = kmi_kbd_setkeycode;
-+ k_getkeycode = kmi_kbd_getkeycode;
-+ k_translate = kmi_kbd_translate;
-+ k_unexpected_up = kmi_kbd_unexpected_up;
-+ k_leds = kmi_kbd_leds;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_xlate = kmi_kbd_sysrq_xlate;
-+ k_sysrq_key = 0x54;
-+#endif
-+ }
-+
-+ return ret;
-+}
-+
-+#endif /* CONFIG_VT */
-+
-+int register_kmi(struct kmi_info *kmi)
-+{
-+ struct kmi_info **kmip = NULL;
-+ int ret;
-+
-+ if (kmi->type == KMI_KEYBOARD)
-+ kmip = &kmi_keyb;
-+ else if (kmi->type == KMI_MOUSE)
-+ kmip = &kmi_mouse;
-+
-+ ret = -EINVAL;
-+ if (kmip) {
-+ ret = -EBUSY;
-+ if (!*kmip) {
-+ *kmip = kmi;
-+ ret = 0;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_KMI_MOUSE
-+static int __init kmi_init(void)
-+{
-+ int ret = -ENODEV;
-+
-+ if (kmi_mouse) {
-+ strcpy(kmi_mouse->name, "kmimouse");
-+ ret = kmi_init_one_interface(kmi_mouse);
-+ }
-+
-+ return ret;
-+}
-+
-+__initcall(kmi_init);
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/char/anakin_ts.c
-@@ -0,0 +1,208 @@
-+/*
-+ * linux/drivers/char/anakin_ts.c
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 18-Apr-2001 TTC Created
-+ * 23-Oct-2001 dwmw2 Cleanup
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/wait.h>
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/init.h>
-+#include <linux/compiler.h>
-+#include <linux/interrupt.h>
-+
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+
-+/*
-+ * TSBUF_SIZE must be a power of two
-+ */
-+#define ANAKIN_TS_MINOR 16
-+#define TSBUF_SIZE 256
-+#define NEXT(index) (((index) + 1) & (TSBUF_SIZE - 1))
-+
-+static unsigned short buffer[TSBUF_SIZE][4];
-+static int head, tail;
-+static DECLARE_WAIT_QUEUE_HEAD(queue);
-+static DECLARE_MUTEX(open_sem);
-+static spinlock_t tailptr_lock = SPIN_LOCK_UNLOCKED;
-+static struct fasync_struct *fasync;
-+
-+/*
-+ * Interrupt handler and standard file operations
-+ */
-+static void
-+anakin_ts_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status = __raw_readl(IO_BASE + IO_CONTROLLER + 0x24);
-+
-+ /*
-+ * iPAQ format (u16 pressure, x, y, millisecs)
-+ */
-+ switch (status >> 20 & 3) {
-+ case 0:
-+ return;
-+ case 2:
-+ buffer[head][0] = 0;
-+ break;
-+ default:
-+ buffer[head][0] = 0x7f;
-+ }
-+
-+ if (unlikely((volatile int)tail == NEXT(head))) {
-+ /* Run out of space in the buffer. Move the tail pointer */
-+ spin_lock(&tailptr_lock);
-+
-+ if ((volatile int)tail == NEXT(head)) {
-+ tail = NEXT(NEXT(head));
-+ }
-+ spin_unlock(&tailptr_lock);
-+ }
-+
-+ buffer[head][1] = status >> 2 & 0xff;
-+ buffer[head][2] = status >> 12 & 0xff;
-+ buffer[head][3] = jiffies;
-+ mb();
-+ head = NEXT(head);
-+
-+ wake_up_interruptible(&queue);
-+ kill_fasync(&fasync, SIGIO, POLL_IN);
-+
-+}
-+
-+static ssize_t
-+anakin_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
-+{
-+ unsigned short data[4];
-+ ssize_t written = 0;
-+
-+ if (head == tail) {
-+ if (filp->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ if (wait_event_interruptible(queue, (volatile int)head != (volatile int)tail))
-+ return -ERESTARTSYS;
-+ }
-+
-+ while ((volatile int)head != (volatile int)tail && count >= sizeof data) {
-+ /* Copy the data out with the spinlock held, so the
-+ interrupt can't fill the buffer and move the tail
-+ pointer while we're doing it */
-+ spin_lock_irq(&tailptr_lock);
-+
-+ memcpy(data, buffer[tail], sizeof data);
-+ tail = NEXT(tail);
-+
-+ spin_unlock_irq(&tailptr_lock);
-+
-+ if (copy_to_user(buf, data, sizeof data))
-+ return -EFAULT;
-+ count -= sizeof data;
-+ buf += sizeof data;
-+ written += sizeof data;
-+ }
-+ return written ? written : -EINVAL;
-+}
-+
-+static unsigned int
-+anakin_ts_poll(struct file *filp, poll_table *wait)
-+{
-+ poll_wait(filp, &queue, wait);
-+ return head != tail ? POLLIN | POLLRDNORM : 0;
-+}
-+
-+static int
-+anakin_ts_ioctl(struct inode *inode, struct file *filp,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ /*
-+ * Future ioctl goes here
-+ */
-+ return 0;
-+}
-+
-+static int
-+anakin_ts_open(struct inode *inode, struct file *filp)
-+{
-+ if (down_trylock(&open_sem))
-+ return -EBUSY;
-+ return 0;
-+}
-+
-+static int
-+anakin_ts_fasync(int fd, struct file *filp, int on)
-+{
-+ return fasync_helper(fd, filp, on, &fasync);
-+}
-+
-+static int
-+anakin_ts_release(struct inode *inode, struct file *filp)
-+{
-+ anakin_ts_fasync(-1, filp, 0);
-+ up(&open_sem);
-+ return 0;
-+}
-+
-+static struct file_operations anakin_ts_fops = {
-+ owner: THIS_MODULE,
-+ read: anakin_ts_read,
-+ poll: anakin_ts_poll,
-+ ioctl: anakin_ts_ioctl,
-+ open: anakin_ts_open,
-+ release: anakin_ts_release,
-+ fasync: anakin_ts_fasync,
-+};
-+
-+static struct miscdevice anakin_ts_miscdev = {
-+ ANAKIN_TS_MINOR,
-+ "anakin_ts",
-+ &anakin_ts_fops
-+};
-+
-+/*
-+ * Initialization and exit routines
-+ */
-+int __init
-+anakin_ts_init(void)
-+{
-+ int retval;
-+
-+ if ((retval = request_irq(IRQ_TOUCHSCREEN, anakin_ts_handler,
-+ SA_INTERRUPT, "anakin_ts", 0))) {
-+ printk(KERN_WARNING "anakin_ts: failed to get IRQ\n");
-+ return retval;
-+ }
-+ __raw_writel(1, IO_BASE + IO_CONTROLLER + 8);
-+ misc_register(&anakin_ts_miscdev);
-+
-+ printk(KERN_NOTICE "Anakin touchscreen driver initialised\n");
-+
-+ return 0;
-+}
-+
-+void __exit
-+anakin_ts_exit(void)
-+{
-+ __raw_writel(0, IO_BASE + IO_CONTROLLER + 8);
-+ free_irq(IRQ_TOUCHSCREEN, 0);
-+ misc_deregister(&anakin_ts_miscdev);
-+}
-+
-+module_init(anakin_ts_init);
-+module_exit(anakin_ts_exit);
-+
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_DESCRIPTION("Anakin touchscreen driver");
-+MODULE_SUPPORTED_DEVICE("touchscreen/anakin");
---- /dev/null
-+++ linux-2.4.27/drivers/char/cerf_keyb.c
-@@ -0,0 +1,380 @@
-+/*
-+ cerf_keyb.c: This is the end. Daniel is writing a device driver!!!
-+*/
-+#include <linux/config.h>
-+
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/mm.h>
-+#include <linux/signal.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/delay.h>
-+#include <linux/random.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/smp_lock.h>
-+#include <linux/timer.h>
-+
-+#include <asm/keyboard.h>
-+#include <asm/bitops.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+
-+#include <asm/io.h>
-+
-+#define KBD_REPORT_UNKN
-+
-+#define KBD_REPORT_ERR /* Report keyboard errors */
-+#define KBD_REPORT_UNKN /* Report unknown scan codes */
-+#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */
-+#define KBD_NO_DATA (-1) /* No data */
-+#define KBD_REPEAT_START (0x20)
-+#define KBD_REPEAT_CONTINUE (0x05)
-+#define KBD_KEY_DOWN_MAX (0x10)
-+#define UINT_LEN (20)
-+#define SC_LIM (69)
-+#define KBD_ROWS (5)
-+#define KBD_COLUMNS (8)
-+
-+#define KBD_KEYUP (0x80)
-+#define KBD_MODESCAN (0x7f)
-+#define KBD_CAPSSCAN (0x3a)
-+#define KBD_SHIFTSCAN (0x2a)
-+#define KBD_NUMCURSCAN (0x7c)
-+#define KBD_CTRLSCAN (0x1d)
-+#define KBD_ALTSCAN (0x38)
-+
-+#define KBD_UP_OFF (0)
-+#define KBD_UP_ON (1)
-+#define KBD_DOWN (2)
-+#define KBD_DOWN_HOLD (3)
-+
-+
-+
-+static unsigned char handle_kbd_event(void);
-+static unsigned char kbd_read_input(void);
-+static void column_set(unsigned int column);
-+static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS]);
-+
-+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
-+static struct timer_list kbd_timer;
-+
-+static short mode_ena = 0;
-+static short numcur_ena = 0;
-+static short shift_ena = 0;
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+#define E1_PAUSE 119
-+#define E0_MACRO 112
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+#define E0_OK 124
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+static unsigned char cerf_normal_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {KBD_ALTSCAN, KBD_MODESCAN, 0x1e, 0x30, 0x2e, 0x20, 0x00, 0x00},
-+ {0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x00},
-+ {0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x00},
-+ {0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x00},
-+ {0x2c, KBD_SHIFTSCAN, KBD_CTRLSCAN, 0x39, KBD_NUMCURSCAN, 0x2b, 0x1c, 0x00}
-+};
-+
-+static unsigned char cerf_mode_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
-+ {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00}, //
-+ {0x0d, 0x0c, 0x37, 0x35, 0x0d, 0x48, 0x28, 0x00},
-+ {0x01, 0x33, 0x34, 0x00, 0x4b, 0x27, 0x4d, 0x00}, //
-+ {0x0f, 0x00, KBD_CAPSSCAN, 0x0e, 0x00, 0x50, 0x00, 0x00}
-+};
-+
-+static unsigned char cerf_numcur_map[KBD_ROWS][KBD_COLUMNS] = {
-+ {0x00, 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00},
-+ {0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00},
-+ {0x0d, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00},
-+ {0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x4d, 0x00},
-+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00}
-+};
-+
-+static void column_set(unsigned int column)
-+{
-+ if (column < 0)
-+ {
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
-+ }
-+ else
-+ {
-+ if(column < 4)
-+ {
-+ CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_A, 1 << (column % 4), 0xFF);
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_B, 0xFF, 0xFF);
-+ }
-+ else
-+ {
-+ CERF_PDA_CPLD_UnSet(CERF_PDA_CPLD_KEYPAD_A, 0xFF, 0xFF);
-+ CERF_PDA_CPLD_Set(CERF_PDA_CPLD_KEYPAD_B, 1 << (column % 4), 0xFF);
-+ }
-+ }
-+}
-+
-+static int scancodes(unsigned char codeval[KBD_ROWS][KBD_COLUMNS])
-+{
-+ int i, j;
-+
-+ for(i = 0; i < KBD_COLUMNS; i++)
-+ {
-+ column_set(i);
-+ udelay(50);
-+ for(j = 0; j < KBD_ROWS; j++)
-+ {
-+ if(mode_ena)
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_mode_map[j][i]?cerf_mode_map[j][i]:cerf_normal_map[j][i]):0;
-+ else if(numcur_ena)
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?(cerf_numcur_map[j][i]?cerf_numcur_map[j][i]:cerf_normal_map[j][i]):0;
-+ else
-+ codeval[j][i] = (GPLR & (1 << (20 + j)))?cerf_normal_map[j][i]:0;
-+ }
-+ }
-+ column_set(-1);
-+
-+ return 0;
-+}
-+
-+static unsigned char kbd_read_input(void)
-+{
-+ int i, j, k, l;
-+ unsigned char prev;
-+ static unsigned char count = 0;
-+
-+ static unsigned char oldcodes[KBD_ROWS][KBD_COLUMNS]={{0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0},
-+ {0,0,0,0,0,0,0,0}};
-+ unsigned char inputcode[KBD_ROWS][KBD_COLUMNS];
-+
-+ memset(inputcode, 0, sizeof(unsigned char) * (KBD_ROWS * KBD_COLUMNS));
-+ scancodes(inputcode);
-+
-+ for(i = 0; i < KBD_COLUMNS; i++)
-+ {
-+ for(j = 0; j < KBD_ROWS; j++)
-+ {
-+// if(oldcodes[j][i] == 0xe0)
-+// oldcodes[j][i] =
-+ if(oldcodes[j][i] != inputcode[j][i])
-+ {
-+ // Value of the key before entering this function
-+ prev = oldcodes[j][i];
-+
-+ // KEYUP
-+ if(inputcode[j][i] == 0 && oldcodes[j][i] != 0 && !(oldcodes[j][i] & KBD_KEYUP))
-+ {
-+ oldcodes[j][i] |= KBD_KEYUP;
-+
-+ if(mode_ena == KBD_UP_ON)
-+ mode_ena = KBD_UP_OFF;
-+ if(prev == KBD_MODESCAN)
-+ if(mode_ena == KBD_DOWN_HOLD)
-+ mode_ena = KBD_UP_OFF;
-+ else if(mode_ena == KBD_DOWN)
-+ mode_ena = KBD_UP_ON;
-+ if(mode_ena == KBD_DOWN)
-+ mode_ena = KBD_DOWN_HOLD;
-+ }
-+ // RESET KEYUP
-+ else if(oldcodes[j][i] & KBD_KEYUP)
-+ oldcodes[j][i] = 0;
-+ // KEY DOWN
-+ else
-+ {
-+ oldcodes[j][i] = inputcode[j][i];
-+
-+ // Parse out mode modifiers before the keyboard interpreter can touch them
-+ if(inputcode[j][i] == KBD_MODESCAN)
-+ {
-+ if(!mode_ena)
-+ mode_ena = KBD_DOWN;
-+ continue;
-+ }
-+ if(inputcode[j][i] == KBD_NUMCURSCAN)
-+ {
-+ numcur_ena = numcur_ena?0:1;
-+ continue;
-+ }
-+ }
-+ //printk("Modified: (%#x,%#x), ipv:%#x, To: (%#.2x), From: (%#.2x), Flags:%d,%d,%d\r\n", j, i, inputcode[j][i], oldcodes[j][i], prev, mode_ena, shift_ena, numcur_ena);
-+ return oldcodes[j][i];
-+ }
-+ }
-+ }
-+
-+ return (unsigned char)(KBD_NO_DATA);
-+}
-+
-+int cerf_kbd_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode;
-+
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+static inline void handle_keyboard_event(unsigned char scancode)
-+{
-+ if(scancode != (unsigned char)(KBD_NO_DATA))
-+ {
-+#ifdef CONFIG_VT
-+ handle_scancode(scancode, !(scancode & KBD_KEYUP));
-+#endif
-+ tasklet_schedule(&keyboard_tasklet);
-+ }
-+}
-+
-+static unsigned char handle_kbd_event(void)
-+{
-+ unsigned char scancode;
-+
-+ scancode = kbd_read_input();
-+ handle_keyboard_event(scancode);
-+
-+ return 0;
-+}
-+
-+/* Handle the automatic interrupts handled by the timer */
-+static void keyboard_interrupt(unsigned long foo)
-+{
-+ spin_lock_irq(&kbd_controller_lock);
-+ handle_kbd_event();
-+ spin_unlock_irq(&kbd_controller_lock);
-+
-+ kbd_timer.expires = 8 + jiffies;
-+ kbd_timer.data = 0x00000000;
-+ kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
-+
-+ add_timer(&kbd_timer);
-+}
-+
-+void cerf_leds(unsigned char leds)
-+{
-+}
-+char cerf_unexpected_up(unsigned char keycode)
-+{
-+return 0;
-+}
-+int cerf_getkeycode(unsigned int scancode)
-+{
-+return 0;
-+}
-+int cerf_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+return 0;
-+}
-+
-+void cerf_kbd_init_hw(void)
-+{
-+ printk("Starting Cerf PDA Keyboard Driver... ");
-+
-+ k_setkeycode = cerf_setkeycode;
-+ k_getkeycode = cerf_getkeycode;
-+ k_translate = cerf_kbd_translate;
-+ k_unexpected_up = cerf_unexpected_up;
-+ k_leds = cerf_leds;
-+
-+ GPDR &= ~(GPIO_GPIO(20) | GPIO_GPIO(21) | GPIO_GPIO(22) | GPIO_GPIO(23) | GPIO_GPIO(24));
-+ kbd_timer.expires = 40 + jiffies;
-+ kbd_timer.data = 0x00000000;
-+ kbd_timer.function = (void(*)(unsigned long))&keyboard_interrupt;
-+
-+ add_timer(&kbd_timer);
-+
-+ printk("Done\r\n");
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/char/clps711x_keyb.c
-@@ -0,0 +1,547 @@
-+/*
-+ * drivers/char/clps711x_keyb.c
-+ *
-+ * Copyright (C) 2001 Thomas Gleixner <gleixner@autronix.de>
-+ *
-+ * based on drivers/edb7211_keyb.c, which is copyright (C) 2000 Bluemug Inc.
-+ *
-+ * Keyboard driver for ARM Linux on EP7xxx and CS89712 processors
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation. See the file COPYING
-+ * in the main directory of this archive for more details.
-+ *
-+ *
-+ * Hardware:
-+ *
-+ * matrix scan keyboards based on EP7209,7211,7212,7312 and CS89712
-+ * on chip keyboard scanner.
-+ * Adaption for different machines is done in init function.
-+ *
-+ * Basic Function:
-+ *
-+ * Basicly the driver is interrupt driven. It sets all column drivers
-+ * high. If any key is pressed, a interrupt occures. Now a seperate scan of
-+ * each column is done. This scan is timer based, because we use a keyboard
-+ * interface with decoupling capacitors (neccecary if you want to survive
-+ * EMC compliance tests). Always one line is set high. When next timer event
-+ * occures the scan data on port A are valid. This makes also sure, that no
-+ * spurious keys are scanned. The kbd int on these CPU's is not deglitched!
-+ * After scanning all columns, we switch back to int mode, if no key is
-+ * pressed. If any is pressed we reschedule the scan within a programmable
-+ * delay. If we would switch back to interrupt mode as long as a key is pressed,
-+ * we come right back to the interrupt, because the int. is level triggered !
-+ * The timer based scan of the seperate columns can also be done in one
-+ * timer event (set fastscan to 1).
-+ *
-+ * Summary:
-+ * The design of this keyboard controller chip is stupid at all !
-+ *
-+ * Matrix translation:
-+ * The matrix translation table is based on standard XT scancodes. Maybe
-+ * you have to adjust the KEYISPRINTABLE macro if you set other codes.
-+ *
-+ * HandyKey:
-+ *
-+ * On small matrix keyboards you don't have enough keys for operation.
-+ * The intention was to implement a operation mode as it's used on handys.
-+ * You can rotate trough four scancode levels and produce e.g. with a 4x3
-+ * matrix 4*3*4 = 48 different keycodes. That's basicly enough for editing
-+ * filenames or things like that. The HandyKey function takes care about
-+ * nonprintable keys like cursors, backspace, del ...
-+ * If a key is pressed and is a printable keycode, the code is put to the
-+ * main keyboard handler and a cursor left is applied. If you press the same
-+ * key again, the current character is deleted and the next level character
-+ * is applied. (e.g. 1, a, b, c, 1 ....). If you press a different key, the
-+ * driver applies cursor right, before processing the new key.
-+ * The autocomplete feature moves the cursor right, if you do not press a
-+ * key within a programmable time.
-+ * If HandyKey is off, the keyboard behaviour is that of a standard keyboard
-+ * HandyKey can be en/disabled from userspace with the proc/keyboard entry
-+ *
-+ * proc/keyboard:
-+ *
-+ * Read access gives back the actual state of the HandyKey function
-+ * h:0 Disabled
-+ * h:1 Enabled
-+ * Write access has two functions. Changing the HandyKey mode and applying
-+ * a different scancode translation table.
-+ * Syntax is: h:0 disable Handykey
-+ * h:1 enabled Handykey
-+ * t:array[256] of bytes Transfer translation table
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/ptrace.h>
-+#include <linux/signal.h>
-+#include <linux/timer.h>
-+#include <linux/tqueue.h>
-+#include <linux/random.h>
-+#include <linux/ctype.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/delay.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/keyboard.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/uaccess.h>
-+
-+#include <asm/io.h>
-+#include <asm/system.h>
-+
-+void clps711x_kbd_init_hw(void);
-+
-+/*
-+ * Values for the keyboard column scan control register.
-+ */
-+#define KBSC_HI 0x0 /* All driven high */
-+#define KBSC_LO 0x1 /* All driven low */
-+#define KBSC_X 0x2 /* All high impedance */
-+#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
-+#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
-+#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
-+#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
-+#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
-+#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
-+#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
-+#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
-+
-+/*
-+* Keycodes for cursor left/right and delete (used by HandyKey)
-+*/
-+#define KEYCODE_CLEFT 0x4b
-+#define KEYCODE_CRIGHT 0x4d
-+#define KEYCODE_DEL 0x53
-+#define KEYISPRINTABLE(code) ( (code > 0x01 && code < 0x37 && code != 0x1c \
-+ && code != 0x0e) || code == 0x39)
-+
-+/* Simple translation table for the SysRq keys */
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char clps711x_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * This table maps row/column keyboard matrix positions to XT scancodes.
-+ * It's a default table, which can be overriden by writing to proc/keyboard
-+ */
-+#ifdef CONFIG_ARCH_AUTCPU12
-+static unsigned char autcpu12_scancode[256] =
-+{
-+/* Column:
-+ Row 0 1 2 3 4 5 6 7 */
-+/* A0 */ 0x08, 0x09, 0x0a, 0x0e, 0x05, 0x06, 0x00, 0x00,
-+/* A1 */ 0x07, 0x53, 0x02, 0x03, 0x04, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x0b, 0x33, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x1e, 0x20, 0x22, 0x0e, 0x24, 0x32, 0x00, 0x00,
-+/* A1 */ 0x19, 0x53, 0x1f, 0x2f, 0x15, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x39, 0x34, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x30, 0x12, 0x23, 0x0e, 0x25, 0x31, 0x00, 0x00,
-+/* A1 */ 0x10, 0x53, 0x14, 0x11, 0x2c, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x0b, 0x27, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+/* A0 */ 0x2e, 0x21, 0x17, 0x0e, 0x26, 0x18, 0x00, 0x00,
-+/* A1 */ 0x13, 0x53, 0x16, 0x2D, 0x04, 0x0f, 0x00, 0x00,
-+/* A2 */ 0x0c, 0x39, 0x35, 0x1c, 0xff, 0x4b, 0x00, 0x00,
-+/* A3 */ 0x48, 0x50, 0x4d, 0x3b, 0x3c, 0x3d, 0x00, 0x00,
-+/* A4 */ 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+};
-+#endif
-+
-+static int keys[8];
-+static int new_keys[8];
-+static int previous_keys[8];
-+
-+static int fastscan;
-+static int scan_interval;
-+static int scan_delay;
-+static int last_column;
-+static int key_is_pressed;
-+
-+static unsigned char *act_scancode;
-+
-+static struct kbd_handy_key {
-+ int ena;
-+ int code;
-+ int shift;
-+ int autocomplete;
-+ unsigned long expires;
-+ unsigned long delay;
-+ unsigned char left;
-+ unsigned char right;
-+ unsigned char del;
-+} khandy;
-+
-+static struct tq_struct kbd_process_task;
-+static struct timer_list clps711x_kbd_timer;
-+static struct timer_list clps711x_kbdhandy_timer;
-+static struct proc_dir_entry *clps711x_keyboard_proc_entry = NULL;
-+
-+/*
-+ * Translate a raw keycode to an XT keyboard scancode.
-+ */
-+static int clps711x_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ *keycode = act_scancode[scancode];
-+ return 1;
-+}
-+
-+/*
-+* Initialize handykey structure
-+* clear code, clear shift
-+* scan scancode for cursor right/left and delete
-+*/
-+static void clps711x_handykey_init(void) {
-+
-+ int i;
-+
-+ khandy.ena = 0;
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ for(i = 0; i < 64; i++) {
-+ switch(act_scancode[i]) {
-+ case KEYCODE_CLEFT: khandy.left = i; break;
-+ case KEYCODE_CRIGHT: khandy.right = i; break;
-+ case KEYCODE_DEL: khandy.del = i; break;
-+ }
-+ }
-+}
-+
-+/*
-+* Check for handy key and process it
-+*/
-+void inline clps711x_checkhandy(int col, int row) {
-+
-+ int scode, down;
-+ unsigned char kcode;
-+
-+ scode = (row<<3) + col;
-+ down = keys[col]>>row & 0x01;
-+ kcode = act_scancode[scode];
-+
-+ if (!khandy.ena) {
-+ if (khandy.code) {
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ }
-+
-+ if(!kcode)
-+ return;
-+
-+ if (!down || !khandy.ena) {
-+ if (khandy.ena && KEYISPRINTABLE(act_scancode[scode]))
-+ khandy.autocomplete = 1;
-+ else
-+ handle_scancode(scode + khandy.shift, down);
-+ return;
-+ }
-+
-+ khandy.autocomplete = 0;
-+ if (KEYISPRINTABLE(kcode)) {
-+ if (khandy.code) {
-+ if(khandy.code == (scode|0x100)) {
-+ handle_scancode(khandy.del,1);
-+ handle_scancode(khandy.del,0);
-+ khandy.shift = khandy.shift < 3*64 ? khandy.shift + 64 : 0 ;
-+ } else {
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ khandy.shift = 0;
-+ }
-+ }
-+ handle_scancode(scode + khandy.shift, 1);
-+ handle_scancode(scode + khandy.shift, 0);
-+ khandy.code = scode | 0x100;
-+ handle_scancode(khandy.left,1);
-+ handle_scancode(khandy.left,0);
-+ } else {
-+ if (khandy.code) {
-+ khandy.code = 0;
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+ khandy.shift = 0;
-+ handle_scancode(scode, down);
-+ }
-+}
-+
-+
-+/*
-+ * Process the new key data
-+ */
-+static void clps711x_kbd_process(void* data)
-+{
-+ int col,row,res;
-+
-+ for (col = 0; col < 8; col++) {
-+ if (( res = previous_keys[col] ^ keys[col]) == 0)
-+ continue;
-+ for(row = 0; row < 8; row++) {
-+ if ( ((res >> row) & 0x01) != 0)
-+ clps711x_checkhandy(col,row);
-+ }
-+ }
-+ /* Update the state variables. */
-+ memcpy(previous_keys, keys, 8 * sizeof(int));
-+
-+ /* reschedule, if autocomplete pending */
-+ if (khandy.autocomplete) {
-+ khandy.expires = jiffies + khandy.delay;
-+ mod_timer(&clps711x_kbdhandy_timer,khandy.expires);
-+ }
-+
-+}
-+
-+static char clps711x_unexpected_up(unsigned char scancode)
-+{
-+ return 0200;
-+}
-+
-+/*
-+* Handle timer event, for autocomplete function
-+* Reschedule keyboard process task
-+*/
-+static void clps711x_kbdhandy_timeout(unsigned long data)
-+{
-+ if(khandy.autocomplete) {
-+ khandy.code = 0;
-+ khandy.shift = 0;
-+ khandy.autocomplete = 0;
-+ handle_scancode(khandy.right,1);
-+ handle_scancode(khandy.right,0);
-+ }
-+}
-+
-+/*
-+* Handle timer event, while in pollmode
-+*/
-+static void clps711x_kbd_timeout(unsigned long data)
-+{
-+ int i;
-+ unsigned long flags;
-+ /*
-+ * read bits of actual column or all columns in fastscan-mode
-+ */
-+ for (i = 0; i < 8; i++) {
-+ new_keys[last_column - KBSC_COL0] = clps_readb(PADR) & 0xff;
-+ key_is_pressed |= new_keys[last_column - KBSC_COL0];
-+ last_column = last_column < KBSC_COL7 ? last_column + 1 : KBSC_COL0;
-+ local_irq_save(flags);
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | last_column, SYSCON1);
-+ local_irq_restore(flags);
-+ /*
-+ * For fastscan, apply a short delay to settle scanlines
-+ * else break and wait for next timeout
-+ */
-+ if (fastscan)
-+ udelay(5);
-+ else
-+ break;
-+ }
-+
-+ if (key_is_pressed)
-+ khandy.autocomplete = 0;
-+
-+ /*
-+ * switch to interupt mode, if all columns scanned and no key pressed
-+ * else reschedule scan
-+ */
-+ if (last_column == KBSC_COL0) {
-+ if (!key_is_pressed) {
-+ local_irq_save(flags);
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_HI, SYSCON1);
-+ local_irq_restore(flags);
-+ clps_writel(0,KBDEOI);
-+ enable_irq(IRQ_KBDINT);
-+ } else {
-+ clps711x_kbd_timer.expires = jiffies + scan_interval;
-+ add_timer(&clps711x_kbd_timer);
-+ }
-+ key_is_pressed = 0;
-+ memcpy(keys, new_keys, 8 * sizeof(int));
-+ for (i = 0; i < 8; i++) {
-+ if (previous_keys[i] != keys[i]) {
-+ queue_task(&kbd_process_task, &tq_timer);
-+ return;
-+ }
-+ }
-+ } else {
-+ clps711x_kbd_timer.expires = jiffies + scan_delay;
-+ add_timer(&clps711x_kbd_timer);
-+ }
-+}
-+
-+/*
-+* Keyboard interrupt, change to scheduling mode
-+*/
-+static void clps711x_kbd_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+ disable_irq(IRQ_KBDINT);
-+ khandy.autocomplete = 0;
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_COL0, SYSCON1);
-+ clps711x_kbd_timer.expires = jiffies + scan_delay;
-+ add_timer(&clps711x_kbd_timer);
-+}
-+
-+
-+static int clps711x_kbd_proc_keyboard_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ if (count < 2)
-+ return -EINVAL;
-+
-+ return sprintf(page,"h:%d\n",khandy.ena);
-+}
-+
-+static int clps711x_kbd_proc_keyboard_write(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ unsigned char buf[260];
-+
-+ if (count < 3|| count > 258)
-+ return -EINVAL;
-+ if (copy_from_user(buf, buffer, count))
-+ return -EFAULT;
-+ if (buf[1] != ':')
-+ return -EINVAL;
-+
-+ if (buf[0] == 'h') {
-+ switch (buf[2]) {
-+ case '0':
-+ case '1':
-+ case '2': khandy.ena = buf[2]-'0'; return count;
-+ }
-+ }
-+
-+ if (buf[0] == 't' && count == 258) {
-+ memcpy(act_scancode,buf+2,256);
-+ /* rescan cursor left/right and del */
-+ clps711x_handykey_init();
-+ return count;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+
-+/*
-+ * Initialize the keyboard hardware.
-+ * Set all columns high
-+ * Install interrupt handler
-+ *
-+ * Machine dependent parameters:
-+ *
-+ * fastscan: 0 = timer based scan for each column
-+ * 1 = full scan is done in one timer event
-+ * scan_delay: time between column scans
-+ * setup even if you use fastscan (leeds to timer mode)
-+ * scan_interval: time between full scans
-+ * handy.delay: timeout before last entry get's automatically valid
-+ *
-+ */
-+void __init clps711x_kbd_init_hw(void)
-+{
-+
-+ /*
-+ * put here machine dependent init stuff
-+ */
-+ if (machine_is_autcpu12()) {
-+ fastscan = 0;
-+ scan_interval = 50*HZ/1000;
-+ scan_delay = 20*HZ/1000;
-+ khandy.delay = 750*HZ/1000;
-+ act_scancode = autcpu12_scancode;
-+ } else {
-+ printk("No initialization, keyboard killed\n");
-+ return;
-+ }
-+
-+ last_column = KBSC_COL0;
-+ key_is_pressed = 0;
-+
-+ clps711x_handykey_init();
-+
-+ /* Register the /proc entry */
-+ clps711x_keyboard_proc_entry = create_proc_entry("keyboard", 0444,
-+ &proc_root);
-+ if (clps711x_keyboard_proc_entry == NULL)
-+ printk("Couldn't create the /proc entry for the keyboard\n");
-+ else {
-+ clps711x_keyboard_proc_entry->read_proc =
-+ &clps711x_kbd_proc_keyboard_read;
-+ clps711x_keyboard_proc_entry->write_proc =
-+ &clps711x_kbd_proc_keyboard_write;
-+ }
-+
-+ /* Initialize the matrix processing task. */
-+ k_translate = clps711x_translate;
-+ k_unexpected_up = clps711x_unexpected_up;
-+ kbd_process_task.routine = clps711x_kbd_process;
-+ kbd_process_task.data = 0;
-+
-+ /* Setup the timer for keyboard polling, after kbd int */
-+ init_timer(&clps711x_kbd_timer);
-+ clps711x_kbd_timer.function = clps711x_kbd_timeout;
-+ clps711x_kbd_timer.data = 0;
-+ init_timer(&clps711x_kbdhandy_timer);
-+ clps711x_kbdhandy_timer.function = clps711x_kbdhandy_timeout;
-+ clps711x_kbdhandy_timer.data = 1;
-+
-+ /* Initialise scan hardware, request int */
-+ clps_writel( (clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK)
-+ | KBSC_HI, SYSCON1);
-+ request_irq(IRQ_KBDINT, clps711x_kbd_int, 0,"keyboard", NULL);
-+
-+ printk("clps711x keyboard init done\n");
-+
-+}
---- linux-2.4.27/drivers/char/console.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/console.c
-@@ -72,8 +72,14 @@
- *
- * Removed console_lock, enabled interrupts across all console operations
- * 13 March 2001, Andrew Morton
-+ *
-+ * Split out con_write_ctrl_* functions from do_con_write & changed
-+ * vc_state to function pointer
-+ * by Russell King <rmk@arm.linux.org.uk>, July 1998
- */
-
-+#define CONSOLE_WIP
-+
- #include <linux/module.h>
- #include <linux/sched.h>
- #include <linux/tty.h>
-@@ -228,7 +234,7 @@
- static inline unsigned short *screenpos(int currcons, int offset, int viewed)
- {
- unsigned short *p;
--
-+
- if (!viewed)
- p = (unsigned short *)(origin + offset);
- else if (!sw->con_screen_pos)
-@@ -729,7 +735,7 @@
- else {
- unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
- if (!p) {
-- for (i = first; i < currcons; i++)
-+ for (i = first; i< currcons; i++)
- if (newscreens[i])
- kfree(newscreens[i]);
- return -ENOMEM;
-@@ -847,7 +853,7 @@
- /* the default colour table, for VGA+ colour systems */
- int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
- 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
--int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
-+int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
- 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
- int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
- 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
-@@ -1393,6 +1399,19 @@
- need_wrap = 0;
- }
-
-+static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int);
-+static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int);
-+
- enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
- EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
- ESpalette };
-@@ -1402,7 +1421,7 @@
- {
- top = 0;
- bottom = video_num_lines;
-- vc_state = ESnormal;
-+ vc_state = con_write_ctrl_ESnormal;
- ques = 0;
- translate = set_translate(LAT1_MAP,currcons);
- G0_charset = LAT1_MAP;
-@@ -1500,328 +1519,426 @@
- disp_ctrl = 0;
- return;
- case 24: case 26:
-- vc_state = ESnormal;
-+ vc_state = con_write_ctrl_ESnormal;
- return;
- case 27:
-- vc_state = ESesc;
-+ vc_state = con_write_ctrl_ESesc;
- return;
- case 127:
- del(currcons);
- return;
- case 128+27:
-- vc_state = ESsquare;
-+ vc_state = con_write_ctrl_ESsquare;
- return;
- }
-- switch(vc_state) {
-- case ESesc:
-- vc_state = ESnormal;
-- switch (c) {
-- case '[':
-- vc_state = ESsquare;
-- return;
-- case ']':
-- vc_state = ESnonstd;
-- return;
-- case '%':
-- vc_state = ESpercent;
-- return;
-- case 'E':
-- cr(currcons);
-- lf(currcons);
-- return;
-- case 'M':
-- ri(currcons);
-- return;
-- case 'D':
-- lf(currcons);
-- return;
-- case 'H':
-- tab_stop[x >> 5] |= (1 << (x & 31));
-- return;
-- case 'Z':
-- respond_ID(tty);
-- return;
-- case '7':
-- save_cur(currcons);
-- return;
-- case '8':
-- restore_cur(currcons);
-- return;
-- case '(':
-- vc_state = ESsetG0;
-- return;
-- case ')':
-- vc_state = ESsetG1;
-- return;
-- case '#':
-- vc_state = EShash;
-- return;
-- case 'c':
-- reset_terminal(currcons,1);
-- return;
-- case '>': /* Numeric keypad */
-- clr_kbd(kbdapplic);
-- return;
-- case '=': /* Appl. keypad */
-- set_kbd(kbdapplic);
-- return;
-+ vc_state(currcons, tty, c);
-+}
-+
-+static int con_write_utf(int currcons, int c)
-+{
-+ unsigned int chr;
-+
-+ /* Combine UTF-8 into Unicode */
-+ /* Incomplete characters silently ignored */
-+ if (c < 0x80) {
-+ utf_count = 0;
-+ return c;
-+ }
-+
-+ if (utf_count > 0 && (c & 0xc0) == 0x80) {
-+ chr = (utf_char << 6) | (c & 0x3f);
-+ utf_count--;
-+ if (utf_count == 0)
-+ return chr;
-+ } else {
-+ unsigned int count;
-+ if ((c & 0xe0) == 0xc0) {
-+ count = 1;
-+ chr = (c & 0x1f);
-+ } else if ((c & 0xf0) == 0xe0) {
-+ count = 2;
-+ chr = (c & 0x0f);
-+ } else if ((c & 0xf8) == 0xf0) {
-+ count = 3;
-+ chr = (c & 0x07);
-+ } else if ((c & 0xfc) == 0xf8) {
-+ count = 4;
-+ chr = (c & 0x03);
-+ } else if ((c & 0xfe) == 0xfc) {
-+ count = 5;
-+ chr = (c & 0x01);
-+ } else {
-+ count = 0;
-+ chr = 0;
- }
-- return;
-- case ESnonstd:
-- if (c=='P') { /* palette escape sequence */
-- for (npar=0; npar<NPAR; npar++)
-- par[npar] = 0 ;
-- npar = 0 ;
-- vc_state = ESpalette;
-- return;
-- } else if (c=='R') { /* reset palette */
-- reset_palette(currcons);
-- vc_state = ESnormal;
-- } else
-- vc_state = ESnormal;
-- return;
-- case ESpalette:
-- if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-- par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
-- if (npar==7) {
-- int i = par[0]*3, j = 1;
-- palette[i] = 16*par[j++];
-- palette[i++] += par[j++];
-- palette[i] = 16*par[j++];
-- palette[i++] += par[j++];
-- palette[i] = 16*par[j++];
-- palette[i] += par[j];
-- set_palette(currcons);
-- vc_state = ESnormal;
-- }
-- } else
-- vc_state = ESnormal;
-- return;
-- case ESsquare:
-- for(npar = 0 ; npar < NPAR ; npar++)
-- par[npar] = 0;
-- npar = 0;
-- vc_state = ESgetpars;
-- if (c == '[') { /* Function key */
-- vc_state=ESfunckey;
-- return;
-+ utf_count = count;
-+ }
-+
-+ utf_char = chr;
-+ return -1;
-+}
-+
-+static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch (c) {
-+ case '[':
-+ vc_state = con_write_ctrl_ESsquare;
-+ break;
-+ case ']':
-+ vc_state = con_write_ctrl_ESnonstd;
-+ break;
-+ case '%':
-+ vc_state = con_write_ctrl_ESpercent;
-+ break;
-+ case 'E':
-+ cr(currcons);
-+ lf(currcons);
-+ break;
-+ case 'M':
-+ ri(currcons);
-+ break;
-+ case 'D':
-+ lf(currcons);
-+ break;
-+ case 'H':
-+ tab_stop[x >> 5] |= (1 << (x & 31));
-+ break;
-+ case 'Z':
-+ respond_ID(tty);
-+ break;
-+ case '7':
-+ save_cur(currcons);
-+ break;
-+ case '8':
-+ restore_cur(currcons);
-+ return 1;
-+ case '(':
-+ vc_state = con_write_ctrl_ESsetG0;
-+ break;
-+ case ')':
-+ vc_state = con_write_ctrl_ESsetG1;
-+ break;
-+ case '#':
-+ vc_state = con_write_ctrl_EShash;
-+ break;
-+ case 'c':
-+ reset_terminal(currcons,1);
-+ return 1;
-+ case '>': /* Numeric keypad */
-+ clr_kbd(kbdapplic);
-+ break;
-+ case '=': /* Appl. keypad */
-+ set_kbd(kbdapplic);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case 'P': /* palette escape sequence */
-+ for (npar=0; npar<NPAR; npar++)
-+ par[npar] = 0 ;
-+ npar = 0 ;
-+ vc_state = con_write_ctrl_ESpalette;
-+ break;
-+ case 'R': /* reset palette */
-+ reset_palette (currcons);
-+ default:
-+ vc_state = con_write_ctrl_ESnormal;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-+ par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
-+ if (npar==7) {
-+ int i = par[0]*3, j = 1;
-+ palette[i] = 16*par[j++];
-+ palette[i++] += par[j++];
-+ palette[i] = 16*par[j++];
-+ palette[i++] += par[j++];
-+ palette[i] = 16*par[j++];
-+ palette[i] += par[j];
-+ set_palette(currcons);
-+ vc_state = con_write_ctrl_ESnormal;
- }
-- ques = (c=='?');
-- if (ques)
-- return;
-- case ESgetpars:
-- if (c==';' && npar<NPAR-1) {
-- npar++;
-- return;
-- } else if (c>='0' && c<='9') {
-- par[npar] *= 10;
-- par[npar] += c-'0';
-- return;
-- } else vc_state=ESgotpars;
-- case ESgotpars:
-- vc_state = ESnormal;
-- switch(c) {
-- case 'h':
-- set_mode(currcons,1);
-- return;
-- case 'l':
-- set_mode(currcons,0);
-- return;
-- case 'c':
-- if (ques) {
-- if (par[0])
-- cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
-- else
-- cursor_type = CUR_DEFAULT;
-- return;
-- }
-- break;
-- case 'm':
-- if (ques) {
-- clear_selection();
-- if (par[0])
-- complement_mask = par[0]<<8 | par[1];
-- else
-- complement_mask = s_complement_mask;
-- return;
-- }
-- break;
-- case 'n':
-- if (!ques) {
-- if (par[0] == 5)
-- status_report(tty);
-- else if (par[0] == 6)
-- cursor_report(currcons,tty);
-- }
-- return;
-+ } else
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ for(npar = 0 ; npar < NPAR ; npar++)
-+ par[npar] = 0;
-+ npar = 0;
-+ vc_state = con_write_ctrl_ESgetpars;
-+ if (c == '[') { /* Function key */
-+ vc_state = con_write_ctrl_ESfunckey;
-+ return 0;
-+ }
-+ ques = (c=='?');
-+ if (ques)
-+ return 0;
-+ return con_write_ctrl_ESgetpars(currcons, tty, c);
-+}
-+
-+static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ if (c==';' && npar<NPAR-1) {
-+ npar++;
-+ return 0;
-+ } else if (c>='0' && c<='9') {
-+ par[npar] *= 10;
-+ par[npar] += c-'0';
-+ return 0;
-+ } else vc_state = con_write_ctrl_ESgotpars;
-+ return con_write_ctrl_ESgotpars(currcons, tty, c);
-+}
-+
-+static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch(c) {
-+ case 'h':
-+ set_mode(currcons,1);
-+ return 0;
-+ case 'l':
-+ set_mode(currcons,0);
-+ return 0;
-+ case 'c':
-+ if (ques) {
-+ if (par[0])
-+ cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
-+ else
-+ cursor_type = CUR_DEFAULT;
-+ return 0;
- }
-+ break;
-+ case 'm':
- if (ques) {
-- ques = 0;
-- return;
-+ clear_selection();
-+ if (par[0])
-+ complement_mask = par[0]<<8 | par[1];
-+ else
-+ complement_mask = s_complement_mask;
-+ return 0;
- }
-- switch(c) {
-- case 'G': case '`':
-- if (par[0]) par[0]--;
-- gotoxy(currcons,par[0],y);
-- return;
-- case 'A':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x,y-par[0]);
-- return;
-- case 'B': case 'e':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x,y+par[0]);
-- return;
-- case 'C': case 'a':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x+par[0],y);
-- return;
-- case 'D':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,x-par[0],y);
-- return;
-- case 'E':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,0,y+par[0]);
-- return;
-- case 'F':
-- if (!par[0]) par[0]++;
-- gotoxy(currcons,0,y-par[0]);
-- return;
-- case 'd':
-- if (par[0]) par[0]--;
-- gotoxay(currcons,x,par[0]);
-- return;
-- case 'H': case 'f':
-- if (par[0]) par[0]--;
-- if (par[1]) par[1]--;
-- gotoxay(currcons,par[1],par[0]);
-- return;
-- case 'J':
-- csi_J(currcons,par[0]);
-- return;
-- case 'K':
-- csi_K(currcons,par[0]);
-- return;
-- case 'L':
-- csi_L(currcons,par[0]);
-- return;
-- case 'M':
-- csi_M(currcons,par[0]);
-- return;
-- case 'P':
-- csi_P(currcons,par[0]);
-- return;
-- case 'c':
-- if (!par[0])
-- respond_ID(tty);
-- return;
-- case 'g':
-- if (!par[0])
-- tab_stop[x >> 5] &= ~(1 << (x & 31));
-- else if (par[0] == 3) {
-- tab_stop[0] =
-- tab_stop[1] =
-- tab_stop[2] =
-- tab_stop[3] =
-- tab_stop[4] = 0;
-- }
-- return;
-- case 'm':
-- csi_m(currcons);
-- return;
-- case 'q': /* DECLL - but only 3 leds */
-- /* map 0,1,2,3 to 0,1,2,4 */
-- if (par[0] < 4)
-- setledstate(kbd_table + currcons,
-- (par[0] < 3) ? par[0] : 4);
-- return;
-- case 'r':
-- if (!par[0])
-- par[0]++;
-- if (!par[1])
-- par[1] = video_num_lines;
-- /* Minimum allowed region is 2 lines */
-- if (par[0] < par[1] &&
-- par[1] <= video_num_lines) {
-- top=par[0]-1;
-- bottom=par[1];
-- gotoxay(currcons,0,0);
-- }
-- return;
-- case 's':
-- save_cur(currcons);
-- return;
-- case 'u':
-- restore_cur(currcons);
-- return;
-- case 'X':
-- csi_X(currcons, par[0]);
-- return;
-- case '@':
-- csi_at(currcons,par[0]);
-- return;
-- case ']': /* setterm functions */
-- setterm_command(currcons);
-- return;
-+ break;
-+ case 'n':
-+ if (!ques) {
-+ if (par[0] == 5)
-+ status_report(tty);
-+ else if (par[0] == 6)
-+ cursor_report(currcons,tty);
- }
-- return;
-- case ESpercent:
-- vc_state = ESnormal;
-- switch (c) {
-- case '@': /* defined in ISO 2022 */
-- utf = 0;
-- return;
-- case 'G': /* prelim official escape code */
-- case '8': /* retained for compatibility */
-- utf = 1;
-- return;
-+ return 0;
-+ }
-+ if (ques) {
-+ ques = 0;
-+ return 0;
-+ }
-+ switch(c) {
-+ case 'G': case '`':
-+ if (par[0]) par[0]--;
-+ gotoxy(currcons,par[0],y);
-+ break;
-+ case 'A':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x,y-par[0]);
-+ break;
-+ case 'B': case 'e':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x,y+par[0]);
-+ break;
-+ case 'C': case 'a':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x+par[0],y);
-+ break;
-+ case 'D':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,x-par[0],y);
-+ break;
-+ case 'E':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,0,y+par[0]);
-+ break;
-+ case 'F':
-+ if (!par[0]) par[0]++;
-+ gotoxy(currcons,0,y-par[0]);
-+ break;
-+ case 'd':
-+ if (par[0]) par[0]--;
-+ gotoxay(currcons,x,par[0]);
-+ break;
-+ case 'H': case 'f':
-+ if (par[0]) par[0]--;
-+ if (par[1]) par[1]--;
-+ gotoxay(currcons,par[1],par[0]);
-+ break;
-+ case 'J':
-+ csi_J(currcons,par[0]);
-+ break;
-+ case 'K':
-+ csi_K(currcons,par[0]);
-+ break;
-+ case 'L':
-+ csi_L(currcons,par[0]);
-+ break;
-+ case 'M':
-+ csi_M(currcons,par[0]);
-+ break;
-+ case 'P':
-+ csi_P(currcons,par[0]);
-+ break;
-+ case 'c':
-+ if (!par[0])
-+ respond_ID(tty);
-+ break;
-+ case 'g':
-+ if (!par[0])
-+ tab_stop[x >> 5] &= ~(1 << (x & 31));
-+ else if (par[0] == 3) {
-+ tab_stop[0] =
-+ tab_stop[1] =
-+ tab_stop[2] =
-+ tab_stop[3] =
-+ tab_stop[4] = 0;
- }
-- return;
-- case ESfunckey:
-- vc_state = ESnormal;
-- return;
-- case EShash:
-- vc_state = ESnormal;
-- if (c == '8') {
-- /* DEC screen alignment test. kludge :-) */
-- video_erase_char =
-- (video_erase_char & 0xff00) | 'E';
-- csi_J(currcons, 2);
-- video_erase_char =
-- (video_erase_char & 0xff00) | ' ';
-- do_update_region(currcons, origin, screenbuf_size/2);
-+ break;
-+ case 'm':
-+ csi_m(currcons);
-+ return 1;
-+ case 'q': /* DECLL - but only 3 leds */
-+ /* map 0,1,2,3 to 0,1,2,4 */
-+ if (par[0] < 4)
-+ setledstate(kbd_table + currcons,
-+ (par[0] < 3) ? par[0] : 4);
-+ break;
-+ case 'r':
-+ if (!par[0])
-+ par[0]++;
-+ if (!par[1])
-+ par[1] = video_num_lines;
-+ /* Minimum allowed region is 2 lines */
-+ if (par[0] < par[1] &&
-+ par[1] <= video_num_lines) {
-+ top=par[0]-1;
-+ bottom=par[1];
-+ gotoxay(currcons,0,0);
- }
-- return;
-- case ESsetG0:
-- if (c == '0')
-- G0_charset = GRAF_MAP;
-- else if (c == 'B')
-- G0_charset = LAT1_MAP;
-- else if (c == 'U')
-- G0_charset = IBMPC_MAP;
-- else if (c == 'K')
-- G0_charset = USER_MAP;
-- if (charset == 0)
-- translate = set_translate(G0_charset,currcons);
-- vc_state = ESnormal;
-- return;
-- case ESsetG1:
-- if (c == '0')
-- G1_charset = GRAF_MAP;
-- else if (c == 'B')
-- G1_charset = LAT1_MAP;
-- else if (c == 'U')
-- G1_charset = IBMPC_MAP;
-- else if (c == 'K')
-- G1_charset = USER_MAP;
-- if (charset == 1)
-- translate = set_translate(G1_charset,currcons);
-- vc_state = ESnormal;
-- return;
-- default:
-- vc_state = ESnormal;
-+ break;
-+ case 's':
-+ save_cur(currcons);
-+ break;
-+ case 'u':
-+ restore_cur(currcons);
-+ return 1;
-+ case 'X':
-+ csi_X(currcons, par[0]);
-+ break;
-+ case '@':
-+ csi_at(currcons,par[0]);
-+ break;
-+ case ']': /* setterm functions */
-+ setterm_command(currcons);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ switch (c) {
-+ case '@': /* defined in ISO 2022 */
-+ utf = 0;
-+ break;
-+ case 'G': /* prelim official escape code */
-+ case '8': /* retained for compatibility */
-+ utf = 1;
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ vc_state = con_write_ctrl_ESnormal;
-+ if (c == '8') {
-+ /* DEC screen alignment test. kludge :-) */
-+ video_erase_char =
-+ (video_erase_char & 0xff00) | 'E';
-+ csi_J(currcons, 2);
-+ video_erase_char =
-+ (video_erase_char & 0xff00) | ' ';
-+ do_update_region(currcons, origin, screenbuf_size/2);
-+ }
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case '0':
-+ G0_charset = GRAF_MAP;
-+ break;
-+ case 'B':
-+ G0_charset = LAT1_MAP;
-+ break;
-+ case 'U':
-+ G0_charset = IBMPC_MAP;
-+ break;
-+ case 'K':
-+ G0_charset = USER_MAP;
-+ break;
-+ }
-+ if (charset == 0) {
-+ translate = set_translate(G0_charset,currcons);
-+ return 1;
-+ }
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
-+}
-+
-+static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c)
-+{
-+ switch (c) {
-+ case '0':
-+ G1_charset = GRAF_MAP;
-+ break;
-+ case 'B':
-+ G1_charset = LAT1_MAP;
-+ break;
-+ case 'U':
-+ G1_charset = IBMPC_MAP;
-+ break;
-+ case 'K':
-+ G1_charset = USER_MAP;
-+ break;
-+ }
-+ if (charset == 1) {
-+ translate = set_translate(G1_charset,currcons);
-+ return 1;
- }
-+ vc_state = con_write_ctrl_ESnormal;
-+ return 0;
- }
-
- /* This is a temporary buffer used to prepare a tty console write
-@@ -1855,7 +1972,7 @@
- unsigned long draw_from = 0, draw_to = 0;
- struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
- u16 himask, charmask;
-- const unsigned char *orig_buf = NULL;
-+ const unsigned char *orig_buf;
- int orig_count;
-
- if (in_interrupt())
-@@ -1913,42 +2030,12 @@
- count--;
-
- if (utf) {
-- /* Combine UTF-8 into Unicode */
-- /* Incomplete characters silently ignored */
-- if(c > 0x7f) {
-- if (utf_count > 0 && (c & 0xc0) == 0x80) {
-- utf_char = (utf_char << 6) | (c & 0x3f);
-- utf_count--;
-- if (utf_count == 0)
-- tc = c = utf_char;
-- else continue;
-- } else {
-- if ((c & 0xe0) == 0xc0) {
-- utf_count = 1;
-- utf_char = (c & 0x1f);
-- } else if ((c & 0xf0) == 0xe0) {
-- utf_count = 2;
-- utf_char = (c & 0x0f);
-- } else if ((c & 0xf8) == 0xf0) {
-- utf_count = 3;
-- utf_char = (c & 0x07);
-- } else if ((c & 0xfc) == 0xf8) {
-- utf_count = 4;
-- utf_char = (c & 0x03);
-- } else if ((c & 0xfe) == 0xfc) {
-- utf_count = 5;
-- utf_char = (c & 0x01);
-- } else
-- utf_count = 0;
-+ tc = con_write_utf(currcons, c);
-+ if (tc < 0)
- continue;
-- }
-- } else {
-- tc = c;
-- utf_count = 0;
-- }
-- } else { /* no utf */
-- tc = translate[toggle_meta ? (c|0x80) : c];
-- }
-+ c = tc;
-+ } else /* no utf */
-+ tc = translate[toggle_meta ? (c|0x80) : c];
-
- /* If the original code was a control character we
- * only allow a glyph to be displayed if the code is
-@@ -1966,7 +2053,7 @@
- && (c != 127 || disp_ctrl)
- && (c != 128+27);
-
-- if (vc_state == ESnormal && ok) {
-+ if (vc_state == con_write_ctrl_ESnormal && ok) {
- /* Now try to find out how to display it */
- tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
- if ( tc == -4 ) {
-@@ -2112,7 +2199,7 @@
- if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
- currcons = kmsg_redirect - 1;
-
-- /* read `x' only after setting currecons properly (otherwise
-+ /* read `x' only after setting currcons properly (otherwise
- the `x' macro will read the x of the foreground console). */
- myx = x;
-
-@@ -2475,8 +2562,8 @@
- console_driver.init_termios = tty_std_termios;
- console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
- /* Tell tty_register_driver() to skip consoles because they are
-- * registered before kmalloc() is ready. We'll patch them in later.
-- * See comments at console_init(); see also con_init_devfs().
-+ * registered before kmalloc() is ready. We'll patch them in later.
-+ * See comments at console_init(); see also con_init_devfs().
- */
- console_driver.flags |= TTY_DRIVER_NO_DEVFS;
- console_driver.refcount = &console_refcount;
-@@ -2719,7 +2806,7 @@
-
- if (console_blank_hook && console_blank_hook(1))
- return;
-- if (vesa_blank_mode)
-+ if (vesa_blank_mode)
- sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
- }
-
-@@ -2893,7 +2980,7 @@
- if (!op->height) { /* Need to guess font height [compat] */
- int h, i;
- u8 *charmap = op->data, tmp;
--
-+
- /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
- so that we can get rid of this soon */
- if (!(op->flags & KD_FONT_FLAG_OLD))
-@@ -2940,18 +3027,18 @@
- op->data = old_op.data;
- if (!rc && !set) {
- int c = (op->width+7)/8 * 32 * op->charcount;
--
-+
- if (op->data && op->charcount > old_op.charcount)
- rc = -ENOSPC;
- if (!(op->flags & KD_FONT_FLAG_OLD)) {
-- if (op->width > old_op.width ||
-+ if (op->width > old_op.width ||
- op->height > old_op.height)
- rc = -ENOSPC;
- } else {
- if (op->width != 8)
- rc = -EIO;
- else if ((old_op.height && op->height > old_op.height) ||
-- op->height > 32)
-+ op->height > 32)
- rc = -ENOSPC;
- }
- if (!rc && op->data && copy_to_user(op->data, temp, c))
---- /dev/null
-+++ linux-2.4.27/drivers/char/ds1307.c
-@@ -0,0 +1,604 @@
-+/*
-+ * ds1307.c
-+ *
-+ * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/poll.h>
-+#include <linux/i2c.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/rtc.h>
-+#include <linux/string.h>
-+#include <linux/miscdevice.h>
-+#include <linux/proc_fs.h>
-+
-+#include "ds1307.h"
-+
-+#define DEBUG 0
-+
-+#if DEBUG
-+static unsigned int rtc_debug = DEBUG;
-+#else
-+#define rtc_debug 0 /* gcc will remove all the debug code for us */
-+#endif
-+
-+static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
-+
-+struct i2c_driver ds1307_driver;
-+struct i2c_client *ds1307_i2c_client = 0;
-+
-+static unsigned short ignore[] = { I2C_CLIENT_END };
-+static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
-+
-+static struct i2c_client_address_data addr_data = {
-+ normal_i2c: normal_addr,
-+ normal_i2c_range: ignore,
-+ probe: ignore,
-+ probe_range: ignore,
-+ ignore: ignore,
-+ ignore_range: ignore,
-+ force: ignore,
-+};
-+
-+static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
-+static int ds1307_rtc_open(struct inode *inode, struct file *file);
-+static int ds1307_rtc_release(struct inode *inode, struct file *file);
-+
-+static struct file_operations rtc_fops = {
-+ owner: THIS_MODULE,
-+ ioctl: ds1307_rtc_ioctl,
-+ open: ds1307_rtc_open,
-+ release: ds1307_rtc_release,
-+};
-+
-+static struct miscdevice ds1307_rtc_miscdev = {
-+ RTC_MINOR,
-+ "rtc",
-+ &rtc_fops
-+};
-+
-+static int ds1307_probe(struct i2c_adapter *adap);
-+static int ds1307_detach(struct i2c_client *client);
-+static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
-+
-+struct i2c_driver ds1307_driver = {
-+ name: "DS1307",
-+ id: I2C_DRIVERID_DS1307,
-+ flags: I2C_DF_NOTIFY,
-+ attach_adapter: ds1307_probe,
-+ detach_client: ds1307_detach,
-+ command: ds1307_command
-+};
-+
-+static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
-+
-+#define DAT(x) ((unsigned int)((x)->data)) /* keep the control register info */
-+
-+static int
-+ds1307_readram( char *buf, int len)
-+{
-+ unsigned long flags;
-+ unsigned char ad[1] = { 0 };
-+ int ret;
-+ struct i2c_msg msgs[2] = {
-+ { ds1307_i2c_client->addr , 0, 1, ad },
-+ { ds1307_i2c_client->addr , I2C_M_RD, len, buf } };
-+
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+
-+ return ret;
-+}
-+
-+static void
-+ds1307_dumpram( void)
-+{
-+ unsigned char buf[DS1307_RAM_SIZE];
-+ int ret;
-+
-+ ret = ds1307_readram( buf, DS1307_RAM_SIZE);
-+
-+ if( ret > 0)
-+ {
-+ int i;
-+ for( i=0; i<DS1307_RAM_SIZE; i++)
-+ {
-+ printk ("%02X ", buf[i]);
-+ if( (i%8) == 7) printk ("\n");
-+ }
-+ printk ("\n");
-+ }
-+}
-+
-+static void
-+ds1307_enable_clock( int enable)
-+{
-+ unsigned char buf[2], ad[1] = { 0 };
-+ struct i2c_msg msgs[2] = {
-+ { ds1307_i2c_client->addr , 0, 1, ad },
-+ { ds1307_i2c_client->addr , I2C_M_RD, 1, buf }
-+ };
-+ unsigned char ctrl_info;
-+ int ret;
-+
-+ if( enable)
-+ ctrl_info = SQW_ENABLE | RATE_32768HZ;
-+ else
-+ ctrl_info = SQW_DISABLE;
-+ ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
-+
-+ /* read addr 0 (Clock-Halt bit and second counter */
-+ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
-+
-+ if( enable)
-+ buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
-+ else
-+ buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
-+ buf[0] = 0; /* control register address on DS1307 */
-+
-+ ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
-+}
-+
-+static int
-+ds1307_attach(struct i2c_adapter *adap, int addr, unsigned short flags,int kind)
-+{
-+ struct i2c_client *c;
-+ unsigned char buf[1], ad[1] = { 7 };
-+ struct i2c_msg msgs[2] = {
-+ { addr , 0, 1, ad },
-+ { addr , I2C_M_RD, 1, buf }
-+ };
-+ int ret;
-+
-+ c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
-+ if (!c)
-+ return -ENOMEM;
-+
-+ strcpy(c->name, "DS1307");
-+ c->id = ds1307_driver.id;
-+ c->flags = 0;
-+ c->addr = addr;
-+ c->adapter = adap;
-+ c->driver = &ds1307_driver;
-+ c->data = NULL;
-+
-+ ret = i2c_transfer(c->adapter, msgs, 2);
-+
-+ if ( ret == 2 )
-+ {
-+ DAT(c) = buf[0];
-+ }
-+ else
-+ printk ("ds1307_attach(): i2c_transfer() returned %d.\n",ret);
-+
-+ ds1307_i2c_client = c;
-+ ds1307_enable_clock( 1);
-+
-+ return i2c_attach_client(c);
-+}
-+
-+static int
-+ds1307_probe(struct i2c_adapter *adap)
-+{
-+ return i2c_probe(adap, &addr_data, ds1307_attach);
-+}
-+
-+static int
-+ds1307_detach(struct i2c_client *client)
-+{
-+ i2c_detach_client(client);
-+ ds1307_enable_clock( 0);
-+
-+ return 0;
-+}
-+
-+static void
-+ds1307_convert_to_time( struct rtc_time *dt, char *buf)
-+{
-+ dt->tm_sec = BCD_TO_BIN(buf[0]);
-+ dt->tm_min = BCD_TO_BIN(buf[1]);
-+
-+ if ( TWELVE_HOUR_MODE(buf[2]) )
-+ {
-+ dt->tm_hour = HOURS_12(buf[2]);
-+ if (HOURS_AP(buf[2])) /* PM */
-+ {
-+ dt->tm_hour += 12;
-+ }
-+ }
-+ else /* 24-hour-mode */
-+ {
-+ dt->tm_hour = HOURS_24(buf[2]);
-+ }
-+
-+ dt->tm_mday = BCD_TO_BIN(buf[4]);
-+ /* dt->tm_mon is zero-based */
-+ dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
-+ /* year is 1900 + dt->tm_year */
-+ dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
-+
-+ if( rtc_debug > 2)
-+ {
-+ printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
-+ printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon);
-+ printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
-+ printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
-+ printk("ds1307_get_datetime: min = %d\n", dt->tm_min);
-+ printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec);
-+ }
-+}
-+
-+static int
-+ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
-+{
-+ unsigned char buf[7], addr[1] = { 0 };
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, I2C_M_RD, 7, buf }
-+ };
-+ int ret = -EIO;
-+
-+ memset(buf, 0, sizeof(buf));
-+
-+ ret = i2c_transfer(client->adapter, msgs, 2);
-+
-+ if (ret == 2) {
-+ ds1307_convert_to_time( dt, buf);
-+ ret = 0;
-+ }
-+ else
-+ printk("ds1307_get_datetime(), i2c_transfer() returned %d\n",ret);
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
-+{
-+ unsigned char buf[8];
-+ int ret, len = 4;
-+
-+ if( rtc_debug > 2)
-+ {
-+ printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
-+ printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon);
-+ printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
-+ printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
-+ printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min);
-+ printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec);
-+ }
-+
-+ buf[0] = 0; /* register address on DS1307 */
-+ buf[1] = (BIN_TO_BCD(dt->tm_sec));
-+ buf[2] = (BIN_TO_BCD(dt->tm_min));
-+ buf[3] = (BIN_TO_BCD(dt->tm_hour));
-+
-+ if (datetoo) {
-+ len = 8;
-+ /* we skip buf[4] as we don't use day-of-week. */
-+ buf[5] = (BIN_TO_BCD(dt->tm_mday));
-+ buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
-+ /* The year only ranges from 0-99, we are being passed an offset from 1900,
-+ * and the chip calulates leap years based on 2000, thus we adjust by 100.
-+ */
-+ buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
-+ }
-+ ret = i2c_master_send(client, (char *)buf, len);
-+ if (ret == len)
-+ ret = 0;
-+ else
-+ printk("ds1307_set_datetime(), i2c_master_send() returned %d\n",ret);
-+
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
-+{
-+ *ctrl = DAT(client);
-+
-+ return 0;
-+}
-+
-+static int
-+ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
-+{
-+ unsigned char buf[2];
-+ int ret;
-+
-+
-+ buf[0] = 7; /* control register address on DS1307 */
-+ buf[1] = *cinfo;
-+ /* save the control reg info in the client data field so that get_ctrl
-+ * function doesn't have to do an I2C transfer to get it.
-+ */
-+ DAT(client) = buf[1];
-+
-+ ret = i2c_master_send(client, (char *)buf, 2);
-+
-+ return ret;
-+}
-+
-+static int
-+ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
-+{
-+ unsigned char addr[1];
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, I2C_M_RD, mem->nr, mem->data }
-+ };
-+
-+ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
-+ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
-+ return -EINVAL;
-+
-+ addr[0] = mem->loc;
-+
-+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-+}
-+
-+static int
-+ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
-+{
-+ unsigned char addr[1];
-+ struct i2c_msg msgs[2] = {
-+ { client->addr, 0, 1, addr },
-+ { client->addr, 0, mem->nr, mem->data }
-+ };
-+
-+ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
-+ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
-+ return -EINVAL;
-+
-+ addr[0] = mem->loc;
-+
-+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
-+}
-+
-+static int
-+ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
-+{
-+ switch (cmd) {
-+ case DS1307_GETDATETIME:
-+ return ds1307_get_datetime(client, arg);
-+
-+ case DS1307_SETTIME:
-+ return ds1307_set_datetime(client, arg, 0);
-+
-+ case DS1307_SETDATETIME:
-+ return ds1307_set_datetime(client, arg, 1);
-+
-+ case DS1307_GETCTRL:
-+ return ds1307_get_ctrl(client, arg);
-+
-+ case DS1307_SETCTRL:
-+ return ds1307_set_ctrl(client, arg);
-+
-+ case DS1307_MEM_READ:
-+ return ds1307_read_mem(client, arg);
-+
-+ case DS1307_MEM_WRITE:
-+ return ds1307_write_mem(client, arg);
-+
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+static int
-+ds1307_rtc_open(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int
-+ds1307_rtc_release(struct inode *inode, struct file *file)
-+{
-+ return 0;
-+}
-+
-+static int
-+ds1307_rtc_ioctl( struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ unsigned long flags;
-+ struct rtc_time wtime;
-+ int status = 0;
-+
-+ switch (cmd) {
-+ default:
-+ case RTC_UIE_ON:
-+ case RTC_UIE_OFF:
-+ case RTC_PIE_ON:
-+ case RTC_PIE_OFF:
-+ case RTC_AIE_ON:
-+ case RTC_AIE_OFF:
-+ case RTC_ALM_SET:
-+ case RTC_ALM_READ:
-+ case RTC_IRQP_READ:
-+ case RTC_IRQP_SET:
-+ case RTC_EPOCH_READ:
-+ case RTC_EPOCH_SET:
-+ case RTC_WKALM_SET:
-+ case RTC_WKALM_RD:
-+ status = -EINVAL;
-+ break;
-+
-+ case RTC_RD_TIME:
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+
-+ if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
-+ status = -EFAULT;
-+ break;
-+
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ {
-+ status = -EACCES;
-+ break;
-+ }
-+
-+ if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
-+ {
-+ status = -EFAULT;
-+ break;
-+ }
-+
-+ spin_lock_irqsave(&ds1307_rtc_lock, flags);
-+ ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
-+ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
-+ break;
-+ }
-+
-+ return status;
-+}
-+
-+static char *
-+ds1307_mon2str( unsigned int mon)
-+{
-+ char *mon2str[12] = {
-+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-+ };
-+ if( mon > 11) return "error";
-+ else return mon2str[ mon];
-+}
-+
-+static int ds1307_rtc_proc_output( char *buf)
-+{
-+#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
-+ unsigned char ram[DS1307_RAM_SIZE];
-+ int ret;
-+
-+ char *p = buf;
-+
-+ ret = ds1307_readram( ram, DS1307_RAM_SIZE);
-+ if( ret > 0)
-+ {
-+ int i;
-+ struct rtc_time dt;
-+ char text[9];
-+
-+ p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
-+
-+ ds1307_convert_to_time( &dt, ram);
-+ p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n",
-+ dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
-+ dt.tm_hour, dt.tm_min, dt.tm_sec);
-+
-+ p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80));
-+ p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40));
-+ p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
-+ p += sprintf(p, "Freq : ");
-+
-+ switch( ram[7] & 0x03)
-+ {
-+ case RATE_1HZ:
-+ p += sprintf(p, "1Hz\n");
-+ break;
-+ case RATE_4096HZ:
-+ p += sprintf(p, "4.096kHz\n");
-+ break;
-+ case RATE_8192HZ:
-+ p += sprintf(p, "8.192kHz\n");
-+ break;
-+ case RATE_32768HZ:
-+ default:
-+ p += sprintf(p, "32.768kHz\n");
-+ break;
-+
-+ }
-+
-+ p += sprintf(p, "RAM dump:\n");
-+ text[8]='\0';
-+ for( i=0; i<DS1307_RAM_SIZE; i++)
-+ {
-+ p += sprintf(p, "%02X ", ram[i]);
-+
-+ if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
-+ text[i%8] = ram[i];
-+ if( (i%8) == 7) p += sprintf(p, "%s\n",text);
-+ }
-+ p += sprintf(p, "\n");
-+ }
-+ else
-+ {
-+ p += sprintf(p, "Failed to read RTC memory!\n");
-+ }
-+
-+ return p - buf;
-+}
-+
-+static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ int len = ds1307_rtc_proc_output (page);
-+ if (len <= off+count) *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len>count) len = count;
-+ if (len<0) len = 0;
-+ return len;
-+}
-+
-+static __init int ds1307_init(void)
-+{
-+ int retval=0;
-+
-+ if( slave_address != 0xffff)
-+ {
-+ normal_addr[0] = slave_address;
-+ }
-+
-+ if( normal_addr[0] == 0xffff)
-+ {
-+ printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
-+ normal_addr[0]);
-+ return -EINVAL;
-+ }
-+
-+ retval = i2c_add_driver(&ds1307_driver);
-+
-+ if (retval==0)
-+ {
-+ misc_register (&ds1307_rtc_miscdev);
-+ create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
-+ printk("I2C: DS1307 RTC driver successfully loaded\n");
-+
-+ if( rtc_debug) ds1307_dumpram();
-+ }
-+ return retval;
-+}
-+
-+static __exit void ds1307_exit(void)
-+{
-+ remove_proc_entry (PROC_DS1307_NAME, NULL);
-+ misc_deregister(&ds1307_rtc_miscdev);
-+ i2c_del_driver(&ds1307_driver);
-+}
-+
-+module_init(ds1307_init);
-+module_exit(ds1307_exit);
-+
-+MODULE_PARM (slave_address, "i");
-+MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
-+
-+MODULE_AUTHOR ("Intrinsyc Software Inc.");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/char/ds1307.h
-@@ -0,0 +1,58 @@
-+/*
-+ * ds1307.h
-+ *
-+ * Copyright (C) 2002 Intrinsyc Software Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#ifndef DS1307_H
-+#define DS1307_H
-+
-+#if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337)
-+ #define DS1307_I2C_SLAVE_ADDR 0x68
-+#else
-+ #define DS1307_I2C_SLAVE_ADDR 0xffff
-+#endif
-+
-+#define DS1307_RAM_ADDR_START 0x08
-+#define DS1307_RAM_ADDR_END 0x3F
-+#define DS1307_RAM_SIZE 0x40
-+
-+#define PROC_DS1307_NAME "driver/ds1307"
-+
-+struct rtc_mem {
-+ unsigned int loc;
-+ unsigned int nr;
-+ unsigned char *data;
-+};
-+
-+#define DS1307_GETDATETIME 0
-+#define DS1307_SETTIME 1
-+#define DS1307_SETDATETIME 2
-+#define DS1307_GETCTRL 3
-+#define DS1307_SETCTRL 4
-+#define DS1307_MEM_READ 5
-+#define DS1307_MEM_WRITE 6
-+
-+#define SQW_ENABLE 0x10 /* Square Wave Enable */
-+#define SQW_DISABLE 0x00 /* Square Wave disable */
-+
-+#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */
-+#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */
-+#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */
-+#define RATE_1HZ 0x00 /* Rate Select 1Hz */
-+
-+#define CLOCK_HALT 0x80 /* Clock Halt */
-+
-+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-+
-+#define TWELVE_HOUR_MODE(n) (((n)>>6)&1)
-+#define HOURS_AP(n) (((n)>>5)&1)
-+#define HOURS_12(n) BCD_TO_BIN((n)&0x1F)
-+#define HOURS_24(n) BCD_TO_BIN((n)&0x3F)
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/char/ds1307.h.rej
-@@ -0,0 +1,17 @@
-+***************
-+*** 11,17 ****
-+ #ifndef DS1307_H
-+ #define DS1307_H
-+
-+- #if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD)
-+ #define DS1307_I2C_SLAVE_ADDR 0x68
-+ #else
-+ #define DS1307_I2C_SLAVE_ADDR 0xffff
-+--- 11,17 ----
-+ #ifndef DS1307_H
-+ #define DS1307_H
-+
-++ #if defined(CONFIG_PXA_EMERSON_SBC) || defined(CONFIG_PXA_CERF_BOARD) || defined(CONFIG_MACH_CSB337)
-+ #define DS1307_I2C_SLAVE_ADDR 0x68
-+ #else
-+ #define DS1307_I2C_SLAVE_ADDR 0xffff
---- /dev/null
-+++ linux-2.4.27/drivers/char/edb7211_keyb.c
-@@ -0,0 +1,335 @@
-+/*
-+ * drivers/char/edb7211_keyb.c
-+ *
-+ * Copyright (C) 2000 Blue Mug, Inc. All Rights Reserved.
-+ *
-+ * EDB7211 Keyboard driver for ARM Linux.
-+ *
-+ * The EP7211 keyboard hardware only supports generating interrupts for 64 keys.
-+ * The EBD7211's keyboard has 84 keys. Therefore we need to poll for keys,
-+ * instead of waiting for interrupts.
-+ *
-+ * In a real-world hardware situation, this would be a bad thing. It would
-+ * kill power management.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/ptrace.h>
-+#include <linux/signal.h>
-+#include <linux/timer.h>
-+#include <linux/tqueue.h>
-+#include <linux/random.h>
-+#include <linux/ctype.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/delay.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/keyboard.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/io.h>
-+#include <asm/system.h>
-+
-+
-+/*
-+ * The number of jiffies between keyboard scans.
-+ */
-+#define KEYBOARD_SCAN_INTERVAL 5
-+
-+/*
-+ * Values for the keyboard column scan control register.
-+ */
-+#define KBSC_HI 0x0 /* All driven high */
-+#define KBSC_LO 0x1 /* All driven low */
-+#define KBSC_X 0x2 /* All high impedance */
-+#define KBSC_COL0 0x8 /* Column 0 high, others high impedance */
-+#define KBSC_COL1 0x9 /* Column 1 high, others high impedance */
-+#define KBSC_COL2 0xa /* Column 2 high, others high impedance */
-+#define KBSC_COL3 0xb /* Column 3 high, others high impedance */
-+#define KBSC_COL4 0xc /* Column 4 high, others high impedance */
-+#define KBSC_COL5 0xd /* Column 5 high, others high impedance */
-+#define KBSC_COL6 0xe /* Column 6 high, others high impedance */
-+#define KBSC_COL7 0xf /* Column 7 high, others high impedance */
-+
-+
-+/* XXX: Figure out what these values should be... */
-+/* Simple translation table for the SysRq keys */
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char edb7211_kbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * Row/column to scancode mappings.
-+ *
-+ * This table maps row/column keyboard matrix positions to XT scancodes.
-+ *
-+ * The port A rows come first, followed by the extended rows.
-+ */
-+static unsigned char colrow_2_scancode[128] =
-+{
-+/* Column:
-+ Row 0 1 2 3 4 5 6 7 */
-+/* A0 */ 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x40, 0x41,
-+/* A1 */ 0x02, 0x07, 0x06, 0x05, 0x04, 0x03, 0x08, 0x09,
-+/* A2 */ 0x0f, 0x14, 0x13, 0x12, 0x11, 0x10, 0x15, 0x16,
-+/* A3 */ 0x3a, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x23, 0x24,
-+/* A4 */ 0x29, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x31, 0x32,
-+/* A5 */ 0x39, 0x35, 0x6F, 0x52, 0x00, 0x6B, 0x34, 0x33,
-+/* A6 */ 0x6A, 0x27, 0x28, 0x00, 0x1c, 0x6D, 0x26, 0x25,
-+/* A7 */ 0x67, 0x19, 0x1a, 0x1b, 0x2b, 0x68, 0x18, 0x17,
-+/* E0 */ 0x6C, 0x0c, 0x0d, 0x0e, 0x00, 0x66, 0x0b, 0x0a,
-+/* E1 */ 0x69, 0x44, 0x45, 0x37, 0x46, 0x77, 0x43, 0x42,
-+/* E2 */ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E3 */ 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E4 */ 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E5 */ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E6 */ 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E7 */ 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+};
-+
-+/*
-+ * A bitfield array which contains the state of the keyboard after the last
-+ * scan. A bit set in this array corresponds to a key down. Only the lower
-+ * 16 bits of each array element are used.
-+ */
-+static unsigned long previous_keys[8];
-+static unsigned long keys[8];
-+
-+
-+/* This will be set to a non-zero value if a key was found to be pressed
-+ * in the last scan. */
-+static int key_is_pressed;
-+
-+static struct tq_struct kbd_process_task;
-+static struct timer_list edb7211_kbd_timer;
-+
-+/*
-+ * External methods.
-+ */
-+void edb7211_kbd_init_hw(void);
-+
-+/*
-+ * Internal methods.
-+ */
-+static int edb7211_kbd_scan_matrix(u_long* keys);
-+static void edb7211_kbd_timeout(unsigned long data);
-+static void edb7211_kbd_process(void* data);
-+
-+/*
-+ * Translate a raw keycode to an XT keyboard scancode.
-+ */
-+static int
-+edb7211_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ *keycode = colrow_2_scancode[scancode & 0x7f];
-+ return 1;
-+}
-+
-+/*
-+ * Scan the keyboard matrix; for each key that is pressed, set the
-+ * corresponding bit in the bitfield array.
-+ *
-+ * The parameter is expected to be an array of 8 32-bit values. Only the lower
-+ * 16 bits of each value is used. Each value contains the row bits for the
-+ * corresponding column.
-+ */
-+static int
-+edb7211_kbd_scan_matrix(u_long* keys)
-+{
-+ int column, row, key_pressed;
-+ unsigned char port_a_data, ext_port_data;
-+
-+ key_pressed = 0;
-+
-+ /* Drive all the columns low. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_LO,
-+ SYSCON1);
-+
-+ for (column = 0; column < 8; column++) {
-+
-+ /* Drive the column high. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) |
-+ (KBSC_COL0 + column), SYSCON1);
-+
-+ /* Read port A and the extended port. */
-+ port_a_data = clps_readb(PADR) & 0xff;
-+ ext_port_data = __raw_readb(EP7211_VIRT_EXTKBD) & 0xff;
-+
-+ /* Drive all columns tri-state. */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ /* Look at each column in port A. */
-+ for (row=0; row < 8; row++) {
-+ /* If the row's bit is set, set the bit in the bitfield.
-+ * Otherwise, clear it.
-+ */
-+ if (port_a_data & (1 << row)) {
-+ keys[column] |= (1 << row);
-+ key_pressed = 1;
-+ } else {
-+ keys[column] &= ~(1 << row);
-+ }
-+ }
-+
-+ /* Look at each column in the extended port. */
-+ for (row=0; row < 8; row++) {
-+ /* If the row's bit is set, set the bit in the bitfield.
-+ * Otherwise, clear it.
-+ */
-+ if (ext_port_data & (1 << row)) {
-+ keys[column] |= (1 << (row + 8));
-+ key_pressed = 1;
-+ } else {
-+ keys[column] &= ~(1 << (row + 8));
-+ }
-+ }
-+
-+ /*
-+ * Short delay: The example code for the EDB7211 runs an empty
-+ * loop 256 times. At this rate, there were some spurious keys
-+ * generated. I doubled the delay to let the column drives
-+ * settle some.
-+ */
-+ for (row=0; row < 512; row++) { }
-+ }
-+
-+ /* If we could use interrupts, we would drive all columns high so
-+ * that interrupts will be generated on key presses. But we can't,
-+ * so we leave all columns floating.
-+ */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ return key_pressed;
-+}
-+
-+/*
-+ * XXX: This is really ugly; this needs to be reworked to have less levels of
-+ * indentation.
-+ */
-+static void
-+edb7211_kbd_timeout(unsigned long data)
-+{
-+ /* Schedule the next timer event. */
-+ edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
-+ add_timer(&edb7211_kbd_timer);
-+
-+ if (edb7211_kbd_scan_matrix(keys) || key_is_pressed) {
-+ queue_task(&kbd_process_task, &tq_timer);
-+ } else {
-+ key_is_pressed = 0;
-+ }
-+}
-+
-+/*
-+ * Process the keys that have been pressed.
-+ */
-+static void
-+edb7211_kbd_process(void* data)
-+{
-+ int i;
-+
-+ /* First check if any keys have been released. */
-+ if (key_is_pressed) {
-+ for (i=0; i < 8; i++) {
-+ if (previous_keys[i]) {
-+ int row;
-+
-+ for (row=0; row < 16; row++) {
-+ if ((previous_keys[i] & (1 << row)) &&
-+ !(keys[i] & (1 << row))) {
-+ /* Generate the up event. */
-+ handle_scancode(
-+ (row<<3)+i, 0);
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ key_is_pressed = 0;
-+
-+ /* Now scan the keys and send press events. */
-+ for (i=0; i < 8; i++) {
-+ if (keys[i]) {
-+ int row;
-+
-+ for (row=0; row < 16; row++) {
-+ if (keys[i] & (1 << row)) {
-+ if (previous_keys[i] & (1 << row)) {
-+ /* Generate the hold event. */
-+ handle_scancode((row<<3)+i, 1);
-+ } else {
-+ /* Generate the down event. */
-+ handle_scancode((row<<3)+i, 1);
-+ }
-+
-+ key_is_pressed = 1;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Update the state variables. */
-+ memcpy(previous_keys, keys, 8 * sizeof(unsigned long));
-+}
-+
-+static char edb7211_unexpected_up(unsigned char scancode)
-+{
-+ return 0200;
-+}
-+
-+static void edb7211_leds(unsigned char leds)
-+{
-+}
-+
-+/*
-+ * Initialize the keyboard hardware. Set the column drives low and
-+ * start the timer.
-+ */
-+void __init
-+edb7211_kbd_init_hw(void)
-+{
-+ k_translate = edb7211_translate;
-+ k_unexpected_up = edb7211_unexpected_up;
-+ k_leds = edb7211_leds;
-+
-+ /*
-+ * If we had the ability to use interrupts, we would want to drive all
-+ * columns high. But we have more keys than can generate interrupts, so
-+ * we leave them floating.
-+ */
-+ clps_writel((clps_readl(SYSCON1) & ~SYSCON1_KBDSCANMASK) | KBSC_X,
-+ SYSCON1);
-+
-+ /* Initialize the matrix processing task. */
-+ kbd_process_task.routine = edb7211_kbd_process;
-+ kbd_process_task.data = NULL;
-+
-+ /* Setup the timer to poll the keyboard. */
-+ init_timer(&edb7211_kbd_timer);
-+ edb7211_kbd_timer.function = edb7211_kbd_timeout;
-+ edb7211_kbd_timer.data = (unsigned long)NULL;
-+ edb7211_kbd_timer.expires = jiffies + KEYBOARD_SCAN_INTERVAL;
-+ add_timer(&edb7211_kbd_timer);
-+}
-+
-+
---- /dev/null
-+++ linux-2.4.27/drivers/char/epxa_wdt.c
-@@ -0,0 +1,178 @@
-+/*
-+ * Watchdog driver for the Altera Excalibur EPXA1DB
-+ *
-+ * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
-+ * Based on SA11x0 Watchdog driver by Oleg Drokin <green@crimea.edu>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the 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 material is provided "AS-IS" and at no charge
-+ *
-+ * (c) Copyright 2003 Krzysztof Marianski <kmarian@konin.lm.pl>
-+ *
-+ * 1/08/2003 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+
-+#define WATCHDOG00_TYPE (volatile unsigned int*)
-+#include <asm/arch/watchdog00.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 30 /* (secs) Default is 30 seconds */
-+
-+static int margin = TIMER_MARGIN; /* in seconds */
-+static int epxa1wdt_users;
-+static unsigned char last_written_byte;
-+
-+#ifdef CONFIG_WATCHDOG_NOWAYOUT
-+static int nowayout=1;
-+#else
-+static int nowayout=0;
-+#endif
-+
-+#ifdef MODULE
-+MODULE_PARM(margin,"i");
-+MODULE_PARM(nowayout, "i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int epxa1dog_open(struct inode *inode, struct file *file)
-+{
-+ if(test_and_set_bit(1,&epxa1wdt_users))
-+ return -EBUSY;
-+
-+ /* Reset the Watchdog, just to be sure we don't set
-+ a value close to actual value of WDOG_COUNT register */
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+
-+ /* Activate EPXA1DB Watchdog timer */
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
-+
-+ last_written_byte = 'V'; //in case user opens it only to ioctl
-+ return 0;
-+}
-+
-+static int epxa1dog_release(struct inode *inode, struct file *file)
-+{
-+ /*
-+ * Shut off the timer and set lock bit when no special
-+ * character 'V' was last written
-+ */
-+
-+ if ((last_written_byte != 'V') && (nowayout)) {
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)) |= WDOG_CR_LK_MSK;
-+ printk("No special character 'V' was written to Watchdog just before closing it\n");
-+ printk("WATCHDOG LOCKED - Reboot expected!!!\n");
-+ } else
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))=0;
-+
-+ epxa1wdt_users = 0;
-+
-+ return 0;
-+}
-+
-+static ssize_t epxa1dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Reset Watchdog timer. */
-+ if(len) {
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+ last_written_byte = *data;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int epxa1dog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ static struct watchdog_info ident = {
-+ identity: "EPXA Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+// case WDIOC_GETSTATUS: //TODO
-+// return put_user(0,(int *)arg);
-+// case WDIOC_GETBOOTSTATUS: //TODO
-+// return 0;
-+ case WDIOC_KEEPALIVE:
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_1;
-+ *WDOG_RELOAD(IO_ADDRESS(EXC_WATCHDOG00_BASE))=WDOG_RELOAD_MAGIC_2;
-+ return 0;
-+ case WDIOC_SETTIMEOUT:
-+ *WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE))= (EXC_INPUT_CLK_FREQUENCY * margin) & WDOG_CR_TRIGGER_MSK;
-+ return 0;
-+ case WDIOC_GETTIMEOUT:
-+ return put_user( ((*WDOG_CR(IO_ADDRESS(EXC_WATCHDOG00_BASE)))/EXC_INPUT_CLK_FREQUENCY), (int*)arg);
-+ }
-+}
-+
-+static struct file_operations epxa1dog_fops = {
-+ .owner = THIS_MODULE,
-+ .write = epxa1dog_write,
-+ .ioctl = epxa1dog_ioctl,
-+ .open = epxa1dog_open,
-+ .release = epxa1dog_release,
-+};
-+
-+static struct miscdevice epxa1dog_miscdev=
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "EPXA watchdog",
-+ .fops = &epxa1dog_fops
-+};
-+
-+static int __init epxa1dog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&epxa1dog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("EPXA Watchdog Timer: timer margin %d sec\n", margin);
-+ printk("EPXA Watchdog Timer: no way out is %s\n", nowayout ? "enabled" : "disabled");
-+
-+ return 0;
-+}
-+
-+static void __exit epxa1dog_exit(void)
-+{
-+ misc_deregister(&epxa1dog_miscdev);
-+}
-+
-+module_init(epxa1dog_init);
-+module_exit(epxa1dog_exit);
-+
-+MODULE_AUTHOR("Krzysztof Marianski <kmarian@konin.lm.pl>");
-+MODULE_DESCRIPTION("EPXA Watchdog Timer");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/char/gc_kbmap.h
-@@ -0,0 +1,162 @@
-+
-+
-+#define KK_NONE 0x7f
-+#define KK_ESC 0x00
-+#define KK_F1 0x01
-+#define KK_F2 0x02
-+#define KK_F3 0x03
-+#define KK_F4 0x04
-+#define KK_F5 0x05
-+#define KK_F6 0x06
-+#define KK_F7 0x07
-+#define KK_F8 0x08
-+#define KK_F9 0x09
-+#define KK_F10 0x0a
-+#define KK_F11 0x0b
-+#define KK_F12 0x0c
-+#define KK_PRNT 0x0d
-+#define KK_SCRL 0x0e
-+#define KK_BRK 0x0f
-+#define KK_AGR 0x10
-+#define KK_1 0x11
-+#define KK_2 0x12
-+#define KK_3 0x13
-+#define KK_4 0x14
-+#define KK_5 0x15
-+#define KK_6 0x16
-+#define KK_7 0x17
-+#define KK_8 0x18
-+#define KK_9 0x19
-+#define KK_0 0x1a
-+#define KK_MINS 0x1b
-+#define KK_EQLS 0x1c
-+#define KK_BKSP 0x1e
-+#define KK_INS 0x1f
-+#define KK_HOME 0x20
-+#define KK_PGUP 0x21
-+#define KK_NUML 0x22
-+#define KP_SLH 0x23
-+#define KP_STR 0x24
-+#define KP_MNS 0x3a
-+#define KK_TAB 0x26
-+#define KK_Q 0x27
-+#define KK_W 0x28
-+#define KK_E 0x29
-+#define KK_R 0x2a
-+#define KK_T 0x2b
-+#define KK_Y 0x2c
-+#define KK_U 0x2d
-+#define KK_I 0x2e
-+#define KK_O 0x2f
-+#define KK_P 0x30
-+#define KK_LSBK 0x31
-+#define KK_RSBK 0x32
-+#define KK_ENTR 0x47
-+#define KK_DEL 0x34
-+#define KK_END 0x35
-+#define KK_PGDN 0x36
-+#define KP_7 0x37
-+#define KP_8 0x38
-+#define KP_9 0x39
-+#define KP_PLS 0x4b
-+#define KK_CAPS 0x5d
-+#define KK_A 0x3c
-+#define KK_S 0x3d
-+#define KK_D 0x3e
-+#define KK_F 0x3f
-+#define KK_G 0x40
-+#define KK_H 0x41
-+#define KK_J 0x42
-+#define KK_K 0x43
-+#define KK_L 0x44
-+#define KK_SEMI 0x45
-+#define KK_SQOT 0x46
-+#define KK_HASH 0x1d
-+#define KP_4 0x48
-+#define KP_5 0x49
-+#define KP_6 0x4a
-+#define KK_LSFT 0x4c
-+#define KK_BSLH 0x33
-+#define KK_Z 0x4e
-+#define KK_X 0x4f
-+#define KK_C 0x50
-+#define KK_V 0x51
-+#define KK_B 0x52
-+#define KK_N 0x53
-+#define KK_M 0x54
-+#define KK_COMA 0x55
-+#define KK_DOT 0x56
-+#define KK_FSLH 0x57
-+#define KK_RSFT 0x58
-+#define KK_UP 0x59
-+#define KP_1 0x5a
-+#define KP_2 0x5b
-+#define KP_3 0x5c
-+#define KP_ENT 0x67
-+#define KK_LCTL 0x3b
-+#define KK_LALT 0x5e
-+#define KK_SPCE 0x5f
-+#define KK_RALT 0x60
-+#define KK_RCTL 0x61
-+#define KK_LEFT 0x62
-+#define KK_DOWN 0x63
-+#define KK_RGHT 0x64
-+#define KP_0 0x65
-+#define KP_DOT 0x66
-+
-+static char kbmap[128] = {
-+KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_AGR, KK_BSLH, KK_TAB, KK_Z, KK_A, KK_X, KK_NONE,
-+KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_ESC, KK_DEL, KK_Q, KK_CAPS, KK_S, KK_C, KK_3,
-+KK_NONE, KK_1, KK_NONE, KK_W, KK_NONE, KK_D, KK_V, KK_4,
-+KK_NONE, KK_2, KK_T, KK_E, KK_NONE, KK_F, KK_B, KK_5,
-+KK_NONE, KK_9, KK_Y, KK_R, KK_K, KK_G, KK_N, KK_6,
-+KK_NONE, KK_0, KK_U, KK_O, KK_L, KK_H, KK_M, KK_7,
-+KK_NONE, KK_MINS, KK_I, KK_P, KK_SEMI, KK_J, KK_COMA, KK_8,
-+KK_NONE, KK_EQLS, KK_ENTR, KK_LSBK, KK_BSLH, KK_FSLH, KK_DOT, KK_NONE,
-+KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_BKSP, KK_DOWN, KK_RSBK, KK_UP, KK_LEFT, KK_SPCE, KK_RGHT,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+static char kbmapFN[128] = {
-+KK_NONE, KK_LALT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_LSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_LCTL, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, 0x21, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F3,
-+KK_NONE, KK_F1, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F4,
-+KK_NONE, KK_F2, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F5,
-+KK_NONE, KK_F9, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F6,
-+KK_NONE, KK_F10, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_F7,
-+KK_NONE, KK_NUML, KK_NONE, KK_INS, KK_PRNT, KK_NONE, KK_NONE, KK_F8,
-+KK_NONE, KK_BRK, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_RSFT, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_PGDN, KK_SCRL, KK_PGUP, KK_HOME, KK_NONE, KK_END,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+static char kbmapNL[128] = {
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KP_9, KK_NONE, KK_NONE, KP_2, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KP_STR, KP_4, KP_6, KP_3, KK_NONE, KP_0, KP_7,
-+KK_NONE, KK_NONE, KP_5, KP_MNS, KP_PLS, KP_1, KK_NONE, KP_8,
-+KK_NONE, KK_NONE, KP_ENT, KK_NONE, KK_NONE, KP_SLH, KP_DOT, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE,
-+KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE, KK_NONE};
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/drivers/char/gc_keyb.c
-@@ -0,0 +1,1145 @@
-+/*
-+ * linux/arch/arm/drivers/char/gc_keyb.c
-+ *
-+ * Copyright 2000 Applied Data Systems
-+ *
-+ * Keyboard & Smartio driver for GraphicsClient ARM Linux.
-+ * Graphics Client is SA1110 based single board computer by
-+ * Applied Data Systems (http://www.applieddata.net)
-+ *
-+ * Change log:
-+ * 7-10/6/01 Thomas Thaele <tthaele@papenmeier.de>
-+ * - Added Keyboard Sniffer on /dev/sio12 <minor = 12>
-+ * - First implementation of PC- compatible Scancodes (thanks to pc_keyb.c)
-+ * 3/23/01 Woojung Huh
-+ * Power Management added
-+ * 12/01/00 Woojung Huh
-+ * Bug fixed
-+ * 11/16/00 Woojung Huh [whuh@applieddata.net]
-+ * Added smartio device driver on it
-+ */
-+
-+/*
-+ * Introduced setkeycode, ketkeycode for the GC+ by Thomas Thaele
-+ * <tthaele@papenmeier.de> GC+ now performs like a real PC on the keyboard.
-+ * Warning: this code is still beta! PrntScrn and Pause keys are not
-+ * completely tested and implemented!!! Keyboard driver can be confused
-+ * by hacking like crazy on the keyboard. (hardware problem on serial line?)
-+ */
-+
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/kbd_kern.h>
-+
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/keyboard.h>
-+#include <linux/tqueue.h>
-+#include <linux/proc_fs.h>
-+#include <linux/pm.h>
-+
-+#define ADS_AVR_IRQ 63
-+
-+#define SMARTIO_IOCTL_BASES 's'
-+#define SMARTIO_KPD_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 0, int)
-+#define SMARTIO_KPD_SETUP _IOW(SMARTIO_IOCTL_BASES, 1, short)
-+#define SMARTIO_BL_CONTROL _IOW(SMARTIO_IOCTL_BASES, 2, char)
-+#define SMARTIO_BL_CONTRAST _IOW(SMARTIO_IOCTL_BASES, 3, char)
-+#define SMARTIO_PORT_CONFIG _IOW(SMARTIO_IOCTL_BASES, 4, char)
-+#define SMARTIO_SNIFFER_TIMEOUT _IOW(SMARTIO_IOCTL_BASES, 5, long)
-+
-+
-+/* Simple translation table for the SysRq keys */
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char pckbd_sysrq_xlate[128] =
-+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+#define E1_PAUSE 119
-+
-+/*
-+ * The keycodes below are randomly located in 89-95,112-118,120-127.
-+ * They could be thrown away (and all occurrences below replaced by 0),
-+ * but that would force many users to use the `setkeycodes' utility, where
-+ * they needed not before. It does not matter that there are duplicates, as
-+ * long as no duplication occurs for any single keyboard.
-+ */
-+#define SC_LIM 89
-+
-+#define FOCUS_PF1 85 /* actual code! */
-+#define FOCUS_PF2 89
-+#define FOCUS_PF3 90
-+#define FOCUS_PF4 91
-+#define FOCUS_PF5 92
-+#define FOCUS_PF6 93
-+#define FOCUS_PF7 94
-+#define FOCUS_PF8 95
-+#define FOCUS_PF9 120
-+#define FOCUS_PF10 121
-+#define FOCUS_PF11 122
-+#define FOCUS_PF12 123
-+
-+#define JAP_86 124
-+/* tfj@olivia.ping.dk:
-+ * The four keys are located over the numeric keypad, and are
-+ * labelled A1-A4. It's an rc930 keyboard, from
-+ * Regnecentralen/RC International, Now ICL.
-+ * Scancodes: 59, 5a, 5b, 5c.
-+ */
-+#define RGN1 124
-+#define RGN2 125
-+#define RGN3 126
-+#define RGN4 127
-+
-+static unsigned char high_keys[128 - SC_LIM] = {
-+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
-+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
-+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
-+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
-+};
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+int gc_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ if (scancode < 128)
-+ high_keys[scancode - SC_LIM] = keycode;
-+ else
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int gc_kbd_getkeycode(unsigned int scancode)
-+{
-+ return
-+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
-+ (scancode < 128) ? high_keys[scancode - SC_LIM] :
-+ e0_keys[scancode - 128];
-+}
-+
-+int gc_kbd_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ /*
-+ * usually it will be 0xe0, but a Pause key generates
-+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
-+ */
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ } else if (prev_scancode == 0x100 && scancode == 0x45) {
-+ *keycode = E1_PAUSE;
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ /*
-+ * The keyboard maintains its own internal caps lock and
-+ * num lock statuses. In caps lock mode E0 AA precedes make
-+ * code and E0 2A follows break code. In num lock mode,
-+ * E0 2A precedes make code and E0 AA follows break code.
-+ * We do our own book-keeping, so we will just ignore these.
-+ */
-+ /*
-+ * For my keyboard there is no caps lock mode, but there are
-+ * both Shift-L and Shift-R modes. The former mode generates
-+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
-+ * So, we should also ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else if (scancode >= SC_LIM) {
-+ /* This happens with the FOCUS 9000 keyboard
-+ Its keys PF1..PF12 are reported to generate
-+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
-+ Moreover, unless repeated, they do not generate
-+ key-down events, so we have to zero up_flag below */
-+ /* Also, Japanese 86/106 keyboards are reported to
-+ generate 0x73 and 0x7d for \ - and \ | respectively. */
-+ /* Also, some Brazilian keyboard is reported to produce
-+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
-+
-+ *keycode = high_keys[scancode - SC_LIM];
-+
-+ if (!*keycode) {
-+ if (!raw_mode) {
-+#ifdef KBD_REPORT_UNKN
-+ printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
-+ " - ignored\n", scancode);
-+#endif
-+ }
-+ return 0;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+// this table converts the hardware dependent codes of a MF-2 Keyboard to
-+// the codes normally comming out of a i8042. This table is 128 Bytes too
-+// big, but for stability reasons it should be kept like it is!
-+// There is no range checking in the code!
-+static int mf_two_kbdmap[256] = {
-+ 00, 67, 65, 63, 61, 59, 60, 88, 00, 68, 66, 64, 62, 15, 41, 00,
-+ 00, 56, 42, 00, 29, 16, 02, 00, 00, 00, 44, 31, 30, 17, 03, 00,
-+ 00, 46, 45, 32, 18, 05, 04, 00, 00, 57, 47, 33, 20, 19, 06, 00,
-+ 00, 49, 48, 35, 34, 21, 7, 00, 00, 00, 50, 36, 22, 8, 9, 00,
-+ 00, 51, 37, 23, 24, 11, 10, 00, 00, 52, 53, 38, 39, 25, 12, 00,
-+ 00, 00, 40, 00, 26, 13, 00, 00, 58, 54, 28, 27, 00, 43, 00, 00,
-+ 00, 86, 00, 00, 00, 00, 14, 00, 00, 79, 00, 75, 71, 00, 00, 00,
-+ 82, 83, 80, 76, 77, 72, 01, 69, 87, 78, 81, 74, 55, 73, 70, 00,
-+ 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 };
-+
-+
-+// some texts displayed by the proc_file_system
-+static char *kbd_sniff[2] = { "off", "on" };
-+static char *kbd_sniff_mode[2] = { "passive", "active" };
-+
-+#define PASSIVE 0
-+#define ACTIVE 1
-+
-+// is the sniffer active (1) or inactive (0)
-+static int SNIFFER = 0;
-+// do we get a copy (SNIFFMODE = PASSIVE) or do we get the original data (SNIFFMODE = ACTIVE)
-+// and have to reinsert the data
-+static int SNIFFMODE = PASSIVE;
-+
-+// we allow only one process to sniff
-+static int sniffer_in_use = 0;
-+
-+// timeout for the keyboard sniffer -1 = blocking, otherwise timeout in msecs
-+static long sniffer_timeout = -1;
-+
-+// the value we sniffed from the keyboard
-+static int sniffed_value;
-+
-+static char *smartio_version = "1.02 MF-II compatibility patch <tthaele@papenmeier.de>";
-+static char *smartio_date = "Aug-27-2001";
-+
-+static int sio_reset_flag;
-+static int kbd_press_flag;
-+
-+static void send_SSP_msg(unchar *pBuf, int num)
-+{
-+ ushort tmp;
-+ int i;
-+
-+ for (i=0;i<num;i++) {
-+ while ((Ser4SSSR & SSSR_TNF) == 0);
-+ tmp = pBuf[i];
-+ Ser4SSDR = (tmp << 8);
-+ }
-+
-+ // Throw away Echo
-+ for (i=0;i<num;i++) {
-+ while ((Ser4SSSR & SSSR_RNE) == 0);
-+ tmp = Ser4SSDR;
-+ }
-+}
-+
-+static unchar ReadSSPByte(void)
-+{
-+ if (Ser4SSSR & SSSR_ROR) {
-+ printk("%s() : Overrun\n", __FUNCTION__);
-+ return 0;
-+ }
-+
-+ Ser4SSDR = 0x00;
-+
-+ while ((Ser4SSSR & SSSR_RNE) == 0);
-+
-+ return ((unchar) Ser4SSDR);
-+}
-+
-+static ulong read_SSP_response(int num)
-+{
-+ int i;
-+ ulong ret;
-+
-+ // discard leading 0x00 and command echo 0 (command group value)
-+ while (ReadSSPByte() == 0);
-+ // discard command echo 1 (command code value)
-+ ReadSSPByte();
-+
-+ // data from SMARTIO
-+ // It assumes LSB first.
-+ // NOTE:Some command uses MSB first order
-+ ret = 0;
-+ for (i=0;i<num;i++) {
-+ ret |= ReadSSPByte() << (8*i);
-+ }
-+
-+ return ret;
-+}
-+
-+typedef struct t_SMARTIO_CMD {
-+ unchar Group;
-+ unchar Code;
-+ unchar Opt[2];
-+} SMARTIO_CMD;
-+
-+static SMARTIO_CMD RD_INT_CMD = { 0x83, 0x01, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_KBD_CMD = { 0x83, 0x02, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_ADC_CMD = { 0x83, 0x28, { 0x00, 0x00 } };
-+static SMARTIO_CMD RD_KPD_CMD = { 0x83, 0x04, { 0x00, 0x00 } };
-+
-+static volatile ushort adc_value;
-+static volatile unchar kpd_value;
-+static unsigned int kpd_timeout = 10000; // 10000 msec
-+
-+static ulong kbd_int, kpd_int, adc_int;
-+
-+static void smartio_interrupt_task(void *data);
-+
-+static struct tq_struct tq_smartio = {
-+ { NULL, NULL }, // struct list_head
-+ 0, // unsigned long sync
-+ smartio_interrupt_task, // void (*routine)(void *)
-+ NULL, // void *data
-+};
-+
-+DECLARE_WAIT_QUEUE_HEAD(smartio_queue);
-+DECLARE_WAIT_QUEUE_HEAD(smartio_adc_queue);
-+DECLARE_WAIT_QUEUE_HEAD(smartio_kpd_queue);
-+DECLARE_WAIT_QUEUE_HEAD(keyboard_done_queue);
-+DECLARE_WAIT_QUEUE_HEAD(sniffer_queue);
-+
-+static spinlock_t smartio_busy_lock = SPIN_LOCK_UNLOCKED;
-+static atomic_t smartio_busy = ATOMIC_INIT(0);
-+
-+static int f_five_pressed = 0;
-+static int f_seven_pressed = 0;
-+//static int e_null_counter = 0;
-+//static int f_null_counter = 0;
-+//static int keydown = 0;
-+static unchar previous_code = 0;
-+//static int e0 = 0;
-+
-+static void smartio_interrupt_task(void *arg)
-+{
-+ unchar code;
-+ unsigned long flags;
-+ unchar dummy;
-+
-+ spin_lock_irqsave(&smartio_busy_lock, flags);
-+ if (atomic_read(&smartio_busy) == 1) {
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+ queue_task(&tq_smartio, &tq_timer);
-+ }
-+ else {
-+ atomic_set(&smartio_busy, 1);
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+ }
-+
-+ /* Read SMARTIO Interrupt Status to check which Interrupt is occurred
-+ * and Clear SMARTIO Interrupt */
-+ send_SSP_msg((unchar *) &RD_INT_CMD, 2);
-+ code = (unchar) (read_SSP_response(1) & 0xFF);
-+
-+#ifdef CONFIG_VT
-+ if (code & 0x04) { // Keyboard Interrupt
-+ kbd_int++;
-+ /* Read Scan code */
-+ send_SSP_msg((unchar *) &RD_KBD_CMD, 2);
-+ code = (unchar) (read_SSP_response(1) & 0xFF);
-+ dummy = code & 0x80;
-+ if ((code == 0xE0) || (code == 0xE1) || (code == 0xF0)) { // combined code
-+ if (code == 0xF0) {
-+ if (!previous_code) {
-+ code = 0xE0;
-+ previous_code = 0xF0;
-+ } else {
-+ code = mf_two_kbdmap[code & 0x7F] | dummy;
-+ previous_code = 0;
-+ }
-+ } else if (code == 0xE0) {
-+ if (previous_code != 0) {
-+ code = mf_two_kbdmap[code & 0x7F] | dummy;
-+ previous_code = 0;
-+ } else previous_code = code;
-+ } else { // 0xE1
-+ if (!previous_code) {
-+ code = mf_two_kbdmap[code &0x7F] | dummy;
-+ previous_code = 0;
-+ } else {
-+ previous_code = code;
-+ }
-+ }
-+ } else {
-+ if (code == 0x03) {
-+ f_five_pressed = 1;
-+ } else if (code == 0x83) {
-+ if (f_five_pressed != 0) {
-+ f_five_pressed = 0;
-+ code = 0x03;
-+ } else if (f_seven_pressed == 0) {
-+ f_seven_pressed = 1;
-+ code = 2;
-+ dummy = 0;
-+ } else {
-+ f_seven_pressed = 0;
-+ code = 2;
-+ }
-+ }
-+ previous_code = 0;
-+ code &= 0x7F;
-+ code = mf_two_kbdmap[code] | dummy;
-+ }
-+ sniffed_value = (ushort)code;
-+ if (SNIFFER) wake_up_interruptible(&sniffer_queue);
-+ if (SNIFFMODE == PASSIVE) {
-+ handle_scancode( code, (code & 0x80) ? 0 : 1 );
-+ if (code & 0x80) {
-+ wake_up_interruptible(&keyboard_done_queue);
-+ mdelay(10); // this makes the whole thing a bit more stable
-+ // keyboard handling can be corrupted when hitting
-+ // thousands of keys like crazy. kbd_translate might catch up
-+ // with irq routine? or there is simply a buffer overflow on
-+ // the serial device? somehow it looses some key sequences.
-+ // if a break code is lost or coruppted the keyboard starts
-+ // to autorepeat like crazy and appears to hang.
-+ // this needs further investigations! Thomas
-+ kbd_press_flag = 0;
-+ }
-+ else
-+ kbd_press_flag = 1;
-+ }
-+ code = 0; // prevent furthermore if ... then to react!
-+ }
-+#endif
-+ // ADC resolution is 10bit (0x000 ~ 0x3FF)
-+ if (code & 0x02) { // ADC Complete Interrupt
-+ adc_int++;
-+ send_SSP_msg((unchar *) &RD_ADC_CMD, 2);
-+ adc_value = (ushort) (read_SSP_response(2) & 0x3FF);
-+ wake_up_interruptible(&smartio_adc_queue);
-+ }
-+
-+ if (code & 0x08) { // Keypad interrupt
-+ kpd_int++;
-+ send_SSP_msg((unchar *) &RD_KPD_CMD, 2);
-+ kpd_value = (unchar) (read_SSP_response(1) & 0xFF);
-+ wake_up_interruptible(&smartio_kpd_queue);
-+ }
-+
-+ spin_lock_irqsave(&smartio_busy_lock, flags);
-+ atomic_set(&smartio_busy, 0);
-+ spin_unlock_irqrestore(&smartio_busy_lock, flags);
-+
-+ enable_irq(ADS_AVR_IRQ);
-+
-+ wake_up_interruptible(&smartio_queue);
-+}
-+
-+static void gc_sio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+
-+ // *NOTE*
-+ // ADS SMARTIO interrupt is cleared after reading interrupt status
-+ // from smartio.
-+ // disable SMARTIO IRQ here and re-enable at samrtio_bh.
-+ // 11/13/00 Woojung
-+ disable_irq(ADS_AVR_IRQ);
-+
-+ queue_task(&tq_smartio, &tq_immediate);
-+ mark_bh(IMMEDIATE_BH);
-+}
-+
-+char gc_kbd_unexpected_up(unsigned char keycode)
-+{
-+ return 0;
-+}
-+
-+static inline void gc_sio_init(void)
-+{
-+ GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); // Output
-+ GPDR &= ~GPIO_GPIO11;
-+
-+ // Alternative Function
-+ GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13);
-+
-+ Ser4SSCR0 = 0xA707;
-+ Ser4SSSR = SSSR_ROR;
-+ Ser4SSCR1 = 0x0010;
-+ Ser4SSCR0 = 0xA787;
-+
-+ // Reset SMARTIO
-+ ADS_AVR_REG &= 0xFE;
-+ mdelay(300); // 10 mSec
-+ ADS_AVR_REG |= 0x01;
-+ mdelay(10); // 10 mSec
-+
-+}
-+
-+void __init gc_kbd_init_hw(void)
-+{
-+ printk (KERN_INFO "Graphics Client keyboard driver v1.0\n");
-+
-+ k_setkeycode = gc_kbd_setkeycode;
-+ k_getkeycode = gc_kbd_getkeycode;
-+ k_translate = gc_kbd_translate;
-+ k_unexpected_up = gc_kbd_unexpected_up;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_key = 0x54;
-+ /* sysrq table??? --rmk */
-+#endif
-+
-+ gc_sio_init();
-+
-+ if (request_irq(ADS_AVR_IRQ,gc_sio_interrupt,0,"smartio", NULL) != 0)
-+ printk("Could not allocate SMARTIO IRQ!\n");
-+
-+ sio_reset_flag = 1;
-+}
-+
-+/* SMARTIO ADC Interface */
-+#define SMARTIO_VERSION 0
-+#define SMARTIO_PORT_A 1
-+#define SMARTIO_PORT_B 2
-+#define SMARTIO_PORT_C 3
-+#define SMARTIO_PORT_D 4
-+#define SMARTIO_SELECT_OPTION 5
-+#define SMARTIO_BACKLITE 6
-+#define SMARTIO_KEYPAD 7
-+#define SMARTIO_ADC 8
-+#define SMARTIO_VEE_PWM 9
-+#define SMARTIO_SLEEP 11
-+#define SMARTIO_KBD_SNIFFER 12
-+
-+static SMARTIO_CMD CONV_ADC_CMD = { 0x80, 0x28, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_PORT_CMD = { 0x82, 0x00, { 0x00, 0x00 } };
-+
-+static SMARTIO_CMD READ_DEVVER_CMD = { 0x82, 0x05, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_DEVTYPE_CMD = { 0x82, 0x06, { 0x00, 0x00 } };
-+static SMARTIO_CMD READ_FWLEVEL_CMD = { 0x82, 0x07, { 0x00, 0x00 } };
-+
-+static int lock_smartio(unsigned long *flags)
-+{
-+ spin_lock_irqsave(&smartio_busy_lock, *flags);
-+ if (atomic_read(&smartio_busy) == 1) {
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+ interruptible_sleep_on(&smartio_queue);
-+ }
-+ else {
-+ atomic_set(&smartio_busy, 1);
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+ }
-+
-+ return 1;
-+}
-+
-+static int unlock_smartio(unsigned long *flags)
-+{
-+ spin_lock_irqsave(&smartio_busy_lock, *flags);
-+ atomic_set(&smartio_busy, 0);
-+ spin_unlock_irqrestore(&smartio_busy_lock, *flags);
-+
-+ return 1;
-+}
-+
-+static ushort read_sio_adc(int channel)
-+{
-+ unsigned long flags;
-+
-+ if ((channel < 0) || (channel > 7))
-+ return 0xFFFF;
-+
-+ CONV_ADC_CMD.Opt[0] = (unchar) channel;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONV_ADC_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ interruptible_sleep_on(&smartio_adc_queue);
-+
-+ return adc_value & 0x3FF;
-+}
-+
-+static ushort read_sio_port(int port)
-+{
-+ unsigned long flags;
-+ ushort ret;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ READ_PORT_CMD.Code = (unchar) port;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_PORT_CMD, 2);
-+ ret = read_SSP_response(1);
-+ unlock_smartio(&flags);
-+
-+ return ret;
-+}
-+
-+static ushort read_sio_kpd(void)
-+{
-+ long timeout;
-+
-+ // kpd_timeout is mSec order
-+ // interrupt_sleep_on_timeout is based on 10msec timer tick
-+ if (kpd_timeout == -1) {
-+ interruptible_sleep_on(&smartio_kpd_queue);
-+ }
-+ else {
-+ timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue,
-+ kpd_timeout/10);
-+ if (timeout == 0) {
-+ // timeout without keypad input
-+ return 0xFFFF;
-+ }
-+ }
-+ return kpd_value;
-+}
-+
-+static ushort read_sio_sniff(void)
-+{
-+ long timeout;
-+
-+ // kpd_timeout is mSec order
-+ // interrupt_sleep_on_timeout is based on 10msec timer tick
-+ if (sniffer_timeout == -1) {
-+ interruptible_sleep_on(&sniffer_queue);
-+ }
-+ else {
-+ timeout = interruptible_sleep_on_timeout(&sniffer_queue,
-+ sniffer_timeout/10);
-+ if (timeout == 0) {
-+ // timeout without keypad input
-+ return -1;
-+ }
-+ }
-+ return (ushort)sniffed_value;
-+}
-+
-+static struct sio_ver {
-+ uint DevVer;
-+ uint DevType;
-+ uint FwLevel;
-+};
-+
-+static ushort read_sio_version(struct sio_ver *ptr)
-+{
-+ unsigned long flags;
-+ ushort ret;
-+
-+ // Read Device Version
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2);
-+ ret = read_SSP_response(1);
-+ unlock_smartio(&flags);
-+ ptr->DevVer = (uint)ret;
-+ // Read Device Type
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2);
-+ ret = read_SSP_response(2);
-+ unlock_smartio(&flags);
-+ // swap MSB & LSB
-+ ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
-+ ptr->DevType = (uint)ret;
-+ // Read Firmware Level
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2);
-+ ret = read_SSP_response(2);
-+ unlock_smartio(&flags);
-+ // swap MSB & LSB
-+ ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8);
-+ ptr->FwLevel = (uint)ret;
-+
-+ return 0;
-+}
-+
-+static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ struct inode *inode = file->f_dentry->d_inode;
-+ unsigned int minor = MINOR(inode->i_rdev);
-+ ushort *ret = (ushort *)buf;
-+
-+ switch (minor) {
-+ case SMARTIO_ADC:
-+ if ((*ret = read_sio_adc(buf[0])) != 0xFFFF)
-+ return sizeof(ushort); // 2 bytes
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if ((*ret = read_sio_port(minor)) != 0xFFFF)
-+ return sizeof(ushort);
-+ case SMARTIO_VERSION:
-+ if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF)
-+ return sizeof(struct sio_ver);
-+ case SMARTIO_KEYPAD:
-+ if ((*ret = read_sio_kpd()) != 0xFFFF)
-+ return sizeof(ushort);
-+ case SMARTIO_KBD_SNIFFER:
-+ if ((*ret = read_sio_sniff()) != (ushort)-1)
-+ return 1;
-+ default :
-+ return -ENXIO;
-+ }
-+}
-+
-+static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } };
-+static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } };
-+
-+static ushort write_sio_port(int port, unchar value)
-+{
-+ unsigned long flags;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ WRITE_PORT_CMD.Code = (unchar) port;
-+ WRITE_PORT_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort write_sio_select(unchar select)
-+{
-+ unsigned long flags;
-+
-+ if ((select < 1) || (select > 2))
-+ return 0xFFFF;
-+
-+ SELECT_OPT_CMD.Code = (unchar) (select + 0x28);
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_backlite(int cmd, int value)
-+{
-+ unsigned long flags;
-+
-+ if (cmd == SMARTIO_BL_CONTRAST) {
-+ value &= 0xFF;
-+ CONTRAST_BL_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3);
-+ unlock_smartio(&flags);
-+ }
-+ else if (cmd == SMARTIO_BL_CONTROL) {
-+ if (value == 0x00) {
-+ // Backlite OFF
-+ CONTROL_BL_CMD.Code = 0x24;
-+ }
-+ else {
-+ // Backlite ON
-+ CONTROL_BL_CMD.Code = 0x23;
-+ }
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2);
-+ unlock_smartio(&flags);
-+ }
-+ else
-+ return 0xFFFF;
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_keypad(int x, int y)
-+{
-+ unsigned long flags;
-+
-+ if ( (x<1) || (x>8) || (y<1) || (y>8)) {
-+ return 0xFFFF;
-+ }
-+
-+ CONTROL_KPD_CMD.Opt[0] = (unchar) x;
-+ CONTROL_KPD_CMD.Opt[1] = (unchar) y;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ushort control_sio_vee(int value)
-+{
-+ unsigned long flags;
-+
-+ value &= 0xFF;
-+ CONTROL_VEE_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos)
-+{
-+ struct inode *inode = file->f_dentry->d_inode;
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ switch (minor) {
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if (write_sio_port(minor, buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_SELECT_OPTION:
-+ if (write_sio_select(buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_BACKLITE:
-+ if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_KEYPAD:
-+ if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF)
-+ return 2;
-+ case SMARTIO_VEE_PWM:
-+ if (control_sio_vee(buf[0]) != 0xFFFF)
-+ return 1;
-+ case SMARTIO_KBD_SNIFFER:
-+ // here are the scancodes injected
-+ handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1);
-+ wake_up_interruptible(&keyboard_done_queue);
-+ // give some time to process! File IO is a bit faster than manual typing ;-)
-+ udelay(10000);
-+ return 1;
-+ default:
-+ return -ENXIO;
-+ }
-+}
-+
-+static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait)
-+{
-+ return 0;
-+}
-+
-+static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };
-+
-+static ushort ioctl_sio_port(int port, unchar value)
-+{
-+ unsigned long flags;
-+
-+ if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D))
-+ return 0xFFFF;
-+
-+ IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08
-+ if (port == SMARTIO_PORT_B) {
-+ // Port B has 4 bits only
-+ IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F;
-+ }
-+ else
-+ IOCTL_PORT_CMD.Opt[0] = (unchar) value;
-+
-+ lock_smartio(&flags);
-+ send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3);
-+ unlock_smartio(&flags);
-+
-+ return 0;
-+}
-+
-+static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+ unchar *buf = (unchar *)arg;
-+
-+ switch (minor) {
-+ case SMARTIO_PORT_B:
-+ case SMARTIO_PORT_C:
-+ case SMARTIO_PORT_D:
-+ if (cmd == SMARTIO_PORT_CONFIG) {
-+ if (ioctl_sio_port(minor, buf[0]) != 0xFFFF)
-+ return 0;
-+ }
-+ return -EINVAL;
-+ case SMARTIO_SELECT_OPTION:
-+ if (write_sio_select(buf[0]) != 0xFFFF) return 0;
-+ return -EINVAL;
-+ case SMARTIO_BACKLITE:
-+ if (cmd == SMARTIO_BL_CONTROL) {
-+ if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0;
-+ }
-+ else if (cmd == SMARTIO_BL_CONTRAST) {
-+ if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0;
-+ }
-+ else return -EINVAL;
-+ case SMARTIO_KEYPAD:
-+ if (cmd == SMARTIO_KPD_TIMEOUT) {
-+ kpd_timeout = *(long*)buf;
-+ return 0;
-+ }
-+ else if (cmd == SMARTIO_KPD_SETUP) {
-+ if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0;
-+ }
-+ return -EINVAL;
-+ case SMARTIO_VEE_PWM:
-+ if (control_sio_vee(buf[0]) != 0xFFFF) return 0;
-+ return -EINVAL;
-+ case SMARTIO_KBD_SNIFFER:
-+ if (cmd == SMARTIO_SNIFFER_TIMEOUT) {
-+ sniffer_timeout = *(long*)buf;
-+ if (sniffer_timeout < 0) sniffer_timeout = -1;
-+ // the value will be devided by 10 later on
-+ if (!sniffer_timeout) sniffer_timeout = 10;
-+ return 0;
-+ }
-+ return -EINVAL;
-+ default:
-+ return -ENXIO;
-+ }
-+}
-+
-+static int sio_open(struct inode *inode, struct file *file)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ // we open all by default. we only have a special handler for the kbd sniffer
-+ switch (minor) {
-+ case SMARTIO_KBD_SNIFFER:
-+ if (sniffer_in_use) return -EBUSY;
-+ sniffer_in_use = 1;
-+ SNIFFER = 1;
-+ // sniff in active or passive mode
-+ if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0;
-+ // do we have a blocking or non blocking sniffer?
-+ if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1;
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static int sio_close(struct inode *inode, struct file *file)
-+{
-+ unsigned int minor = MINOR(inode->i_rdev);
-+
-+ switch (minor) {
-+ case SMARTIO_KBD_SNIFFER:
-+ SNIFFER = 0;
-+ SNIFFMODE = 0;
-+ sniffer_in_use = 0;
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static struct file_operations sio_fops = {
-+ read: sio_read,
-+ write: sio_write,
-+ poll: sio_poll,
-+ ioctl: sio_ioctl,
-+ open: sio_open,
-+ release: sio_close,
-+};
-+
-+static struct proc_dir_entry *sio_dir, *parent_dir = NULL;
-+
-+#define SMARTIO_MAJOR 58
-+#define MAJOR_NR SMARTIO_MAJOR
-+
-+#define PROC_NAME "sio"
-+
-+static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data)
-+{
-+ char *p = buf;
-+
-+ p += sprintf(p, "ADS SMARTIO Status: \n");
-+ p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int);
-+ p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int);
-+ p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int);
-+ p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]);
-+
-+ return (p-buf);
-+}
-+
-+#ifdef CONFIG_PM
-+static int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ switch (rqst) {
-+ case PM_RESUME:
-+ gc_sio_init();
-+ break;
-+ case PM_SUSPEND:
-+ // 4/5/01 Woojung
-+ // It checks Keybard received pair of press/release code.
-+ // System can sleep before receiving release code
-+ if (kbd_press_flag) {
-+ interruptible_sleep_on(&keyboard_done_queue);
-+ }
-+ break;
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+void __init sio_init(void)
-+{
-+ if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) {
-+ printk("smartio : unable to get major %d\n", MAJOR_NR);
-+ return;
-+ }
-+ else {
-+ printk("smartio driver initialized. version %s, date:%s\n",
-+ smartio_version, smartio_date);
-+
-+ if (sio_reset_flag != 1) {
-+ gc_sio_init();
-+ if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){
-+ printk("smartio : Could not allocate IRQ!\n");
-+ return;
-+ }
-+ }
-+
-+ if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) {
-+ printk("smartio : Unable to create /proc entry\n");
-+ return;
-+ }
-+ else {
-+ sio_dir->read_proc = sio_read_proc;
-+#ifdef CONFIG_PM
-+ pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback);
-+#endif
-+ }
-+ }
-+}
---- /dev/null
-+++ linux-2.4.27/drivers/char/gckeymap.c
-@@ -0,0 +1,262 @@
-+/* Do not edit this file! It was automatically generated by */
-+/* loadkeys --mktable defkeymap.map > defkeymap.c */
-+
-+#include <linux/types.h>
-+#include <linux/keyboard.h>
-+#include <linux/kd.h>
-+
-+u_short plain_map[NR_KEYS] = {
-+ 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
-+ 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
-+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
-+ 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
-+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
-+ 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
-+ 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
-+ 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
-+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short shift_map[NR_KEYS] = {
-+ 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
-+ 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
-+ 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
-+ 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
-+ 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
-+ 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
-+ 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
-+ 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
-+ 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short altgr_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
-+ 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
-+ 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
-+ 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
-+ 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
-+ 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
-+ 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
-+ 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
-+ 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
-+ 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short ctrl_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
-+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
-+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
-+ 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
-+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
-+ 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
-+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
-+ 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
-+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
-+ 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short shift_ctrl_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
-+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
-+ 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
-+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
-+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short alt_map[NR_KEYS] = {
-+ 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
-+ 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
-+ 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
-+ 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
-+ 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
-+ 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
-+ 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
-+ 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
-+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
-+ 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
-+ 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
-+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+u_short ctrl_alt_map[NR_KEYS] = {
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
-+ 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
-+ 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
-+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
-+ 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
-+ 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
-+ 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
-+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
-+ 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
-+ 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+ 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
-+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
-+ 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
-+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-+};
-+
-+ushort *key_maps[MAX_NR_KEYMAPS] = {
-+ plain_map, shift_map, altgr_map, 0,
-+ ctrl_map, shift_ctrl_map, 0, 0,
-+ alt_map, 0, 0, 0,
-+ ctrl_alt_map, 0
-+};
-+
-+unsigned int keymap_count = 7;
-+
-+/*
-+ * Philosophy: most people do not define more strings, but they who do
-+ * often want quite a lot of string space. So, we statically allocate
-+ * the default and allocate dynamically in chunks of 512 bytes.
-+ */
-+
-+char func_buf[] = {
-+ '\033', '[', '[', 'A', 0,
-+ '\033', '[', '[', 'B', 0,
-+ '\033', '[', '[', 'C', 0,
-+ '\033', '[', '[', 'D', 0,
-+ '\033', '[', '[', 'E', 0,
-+ '\033', '[', '1', '7', '~', 0,
-+ '\033', '[', '1', '8', '~', 0,
-+ '\033', '[', '1', '9', '~', 0,
-+ '\033', '[', '2', '0', '~', 0,
-+ '\033', '[', '2', '1', '~', 0,
-+ '\033', '[', '2', '3', '~', 0,
-+ '\033', '[', '2', '4', '~', 0,
-+ '\033', '[', '2', '5', '~', 0,
-+ '\033', '[', '2', '6', '~', 0,
-+ '\033', '[', '2', '8', '~', 0,
-+ '\033', '[', '2', '9', '~', 0,
-+ '\033', '[', '3', '1', '~', 0,
-+ '\033', '[', '3', '2', '~', 0,
-+ '\033', '[', '3', '3', '~', 0,
-+ '\033', '[', '3', '4', '~', 0,
-+ '\033', '[', '1', '~', 0,
-+ '\033', '[', '2', '~', 0,
-+ '\033', '[', '3', '~', 0,
-+ '\033', '[', '4', '~', 0,
-+ '\033', '[', '5', '~', 0,
-+ '\033', '[', '6', '~', 0,
-+ '\033', '[', 'M', 0,
-+ '\033', '[', 'P', 0,
-+};
-+
-+char *funcbufptr = func_buf;
-+int funcbufsize = sizeof(func_buf);
-+int funcbufleft = 0; /* space left */
-+
-+char *func_table[MAX_NR_FUNC] = {
-+ func_buf + 0,
-+ func_buf + 5,
-+ func_buf + 10,
-+ func_buf + 15,
-+ func_buf + 20,
-+ func_buf + 25,
-+ func_buf + 31,
-+ func_buf + 37,
-+ func_buf + 43,
-+ func_buf + 49,
-+ func_buf + 55,
-+ func_buf + 61,
-+ func_buf + 67,
-+ func_buf + 73,
-+ func_buf + 79,
-+ func_buf + 85,
-+ func_buf + 91,
-+ func_buf + 97,
-+ func_buf + 103,
-+ func_buf + 109,
-+ func_buf + 115,
-+ func_buf + 120,
-+ func_buf + 125,
-+ func_buf + 130,
-+ func_buf + 135,
-+ func_buf + 140,
-+ func_buf + 145,
-+ 0,
-+ 0,
-+ func_buf + 149,
-+ 0,
-+};
-+
-+struct kbdiacr accent_table[MAX_DIACR] = {
-+ {'`', 'A', '\300'}, {'`', 'a', '\340'},
-+ {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
-+ {'^', 'A', '\302'}, {'^', 'a', '\342'},
-+ {'~', 'A', '\303'}, {'~', 'a', '\343'},
-+ {'"', 'A', '\304'}, {'"', 'a', '\344'},
-+ {'O', 'A', '\305'}, {'o', 'a', '\345'},
-+ {'0', 'A', '\305'}, {'0', 'a', '\345'},
-+ {'A', 'A', '\305'}, {'a', 'a', '\345'},
-+ {'A', 'E', '\306'}, {'a', 'e', '\346'},
-+ {',', 'C', '\307'}, {',', 'c', '\347'},
-+ {'`', 'E', '\310'}, {'`', 'e', '\350'},
-+ {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
-+ {'^', 'E', '\312'}, {'^', 'e', '\352'},
-+ {'"', 'E', '\313'}, {'"', 'e', '\353'},
-+ {'`', 'I', '\314'}, {'`', 'i', '\354'},
-+ {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
-+ {'^', 'I', '\316'}, {'^', 'i', '\356'},
-+ {'"', 'I', '\317'}, {'"', 'i', '\357'},
-+ {'-', 'D', '\320'}, {'-', 'd', '\360'},
-+ {'~', 'N', '\321'}, {'~', 'n', '\361'},
-+ {'`', 'O', '\322'}, {'`', 'o', '\362'},
-+ {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
-+ {'^', 'O', '\324'}, {'^', 'o', '\364'},
-+ {'~', 'O', '\325'}, {'~', 'o', '\365'},
-+ {'"', 'O', '\326'}, {'"', 'o', '\366'},
-+ {'/', 'O', '\330'}, {'/', 'o', '\370'},
-+ {'`', 'U', '\331'}, {'`', 'u', '\371'},
-+ {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
-+ {'^', 'U', '\333'}, {'^', 'u', '\373'},
-+ {'"', 'U', '\334'}, {'"', 'u', '\374'},
-+ {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
-+ {'T', 'H', '\336'}, {'t', 'h', '\376'},
-+ {'s', 's', '\337'}, {'"', 'y', '\377'},
-+ {'s', 'z', '\337'}, {'i', 'j', '\377'},
-+};
-+
-+unsigned int accent_table_size = 68;
---- /dev/null
-+++ linux-2.4.27/drivers/char/gckeymap.map
-@@ -0,0 +1,357 @@
-+# Default kernel keymap. This uses 7 modifier combinations.
-+keymaps 0-2,4-5,8,12
-+# Change the above line into
-+# keymaps 0-2,4-6,8,12
-+# in case you want the entries
-+# altgr control keycode 83 = Boot
-+# altgr control keycode 111 = Boot
-+# below.
-+#
-+# In fact AltGr is used very little, and one more keymap can
-+# be saved by mapping AltGr to Alt (and adapting a few entries):
-+# keycode 100 = Alt
-+#
-+keycode 1 = Escape Escape
-+ alt keycode 1 = Meta_Escape
-+keycode 2 = one exclam
-+ alt keycode 2 = Meta_one
-+keycode 3 = two at at
-+ control keycode 3 = nul
-+ shift control keycode 3 = nul
-+ alt keycode 3 = Meta_two
-+keycode 4 = three numbersign
-+ control keycode 4 = Escape
-+ alt keycode 4 = Meta_three
-+keycode 5 = four dollar dollar
-+ control keycode 5 = Control_backslash
-+ alt keycode 5 = Meta_four
-+keycode 6 = five percent
-+ control keycode 6 = Control_bracketright
-+ alt keycode 6 = Meta_five
-+keycode 7 = six asciicircum
-+ control keycode 7 = Control_asciicircum
-+ alt keycode 7 = Meta_six
-+keycode 8 = seven ampersand braceleft
-+ control keycode 8 = Control_underscore
-+ alt keycode 8 = Meta_seven
-+keycode 9 = eight asterisk bracketleft
-+ control keycode 9 = Delete
-+ alt keycode 9 = Meta_eight
-+keycode 10 = nine parenleft bracketright
-+ alt keycode 10 = Meta_nine
-+keycode 11 = zero parenright braceright
-+ alt keycode 11 = Meta_zero
-+keycode 12 = minus underscore backslash
-+ control keycode 12 = Control_underscore
-+ shift control keycode 12 = Control_underscore
-+ alt keycode 12 = Meta_minus
-+keycode 13 = equal plus
-+ alt keycode 13 = Meta_equal
-+keycode 14 = Delete Delete
-+ control keycode 14 = BackSpace
-+ alt keycode 14 = Meta_Delete
-+keycode 15 = Tab Tab
-+ alt keycode 15 = Meta_Tab
-+keycode 16 = q
-+keycode 17 = w
-+keycode 18 = e
-+ altgr keycode 18 = Hex_E
-+keycode 19 = r
-+keycode 20 = t
-+keycode 21 = y
-+keycode 22 = u
-+keycode 23 = i
-+keycode 24 = o
-+keycode 25 = p
-+keycode 26 = bracketleft braceleft
-+ control keycode 26 = Escape
-+ alt keycode 26 = Meta_bracketleft
-+keycode 27 = bracketright braceright asciitilde
-+ control keycode 27 = Control_bracketright
-+ alt keycode 27 = Meta_bracketright
-+keycode 28 = Return
-+ alt keycode 28 = Meta_Control_m
-+keycode 29 = Control
-+keycode 30 = a
-+ altgr keycode 30 = Hex_A
-+keycode 31 = s
-+keycode 32 = d
-+ altgr keycode 32 = Hex_D
-+keycode 33 = f
-+ altgr keycode 33 = Hex_F
-+keycode 34 = g
-+keycode 35 = h
-+keycode 36 = j
-+keycode 37 = k
-+keycode 38 = l
-+keycode 39 = semicolon colon
-+ alt keycode 39 = Meta_semicolon
-+keycode 40 = apostrophe quotedbl
-+ control keycode 40 = Control_g
-+ alt keycode 40 = Meta_apostrophe
-+keycode 41 = grave asciitilde
-+ control keycode 41 = nul
-+ alt keycode 41 = Meta_grave
-+keycode 42 = Shift
-+keycode 43 = backslash bar
-+ control keycode 43 = Control_backslash
-+ alt keycode 43 = Meta_backslash
-+keycode 44 = z
-+keycode 45 = x
-+keycode 46 = c
-+ altgr keycode 46 = Hex_C
-+keycode 47 = v
-+keycode 48 = b
-+ altgr keycode 48 = Hex_B
-+keycode 49 = n
-+keycode 50 = m
-+keycode 51 = comma less
-+ alt keycode 51 = Meta_comma
-+keycode 52 = period greater
-+ control keycode 52 = Compose
-+ alt keycode 52 = Meta_period
-+keycode 53 = slash question
-+ control keycode 53 = Delete
-+ alt keycode 53 = Meta_slash
-+keycode 54 = Shift
-+keycode 55 = KP_Multiply
-+keycode 56 = Alt
-+keycode 57 = space space
-+ control keycode 57 = nul
-+ alt keycode 57 = Meta_space
-+keycode 58 = Caps_Lock
-+keycode 59 = F1 F11 Console_13
-+ control keycode 59 = F1
-+ alt keycode 59 = Console_1
-+ control alt keycode 59 = Console_1
-+keycode 60 = F2 F12 Console_14
-+ control keycode 60 = F2
-+ alt keycode 60 = Console_2
-+ control alt keycode 60 = Console_2
-+keycode 61 = F3 F13 Console_15
-+ control keycode 61 = F3
-+ alt keycode 61 = Console_3
-+ control alt keycode 61 = Console_3
-+keycode 62 = F4 F14 Console_16
-+ control keycode 62 = F4
-+ alt keycode 62 = Console_4
-+ control alt keycode 62 = Console_4
-+keycode 63 = F5 F15 Console_17
-+ control keycode 63 = F5
-+ alt keycode 63 = Console_5
-+ control alt keycode 63 = Console_5
-+keycode 64 = F6 F16 Console_18
-+ control keycode 64 = F6
-+ alt keycode 64 = Console_6
-+ control alt keycode 64 = Console_6
-+keycode 65 = F7 F17 Console_19
-+ control keycode 65 = F7
-+ alt keycode 65 = Console_7
-+ control alt keycode 65 = Console_7
-+keycode 66 = F8 F18 Console_20
-+ control keycode 66 = F8
-+ alt keycode 66 = Console_8
-+ control alt keycode 66 = Console_8
-+keycode 67 = F9 F19 Console_21
-+ control keycode 67 = F9
-+ alt keycode 67 = Console_9
-+ control alt keycode 67 = Console_9
-+keycode 68 = F10 F20 Console_22
-+ control keycode 68 = F10
-+ alt keycode 68 = Console_10
-+ control alt keycode 68 = Console_10
-+keycode 69 = Num_Lock
-+ shift keycode 69 = Bare_Num_Lock
-+keycode 70 = Scroll_Lock Show_Memory Show_Registers
-+ control keycode 70 = Show_State
-+ alt keycode 70 = Scroll_Lock
-+keycode 71 = KP_7
-+ alt keycode 71 = Ascii_7
-+ altgr keycode 71 = Hex_7
-+keycode 72 = KP_8
-+ alt keycode 72 = Ascii_8
-+ altgr keycode 72 = Hex_8
-+keycode 73 = KP_9
-+ alt keycode 73 = Ascii_9
-+ altgr keycode 73 = Hex_9
-+keycode 74 = KP_Subtract
-+keycode 75 = KP_4
-+ alt keycode 75 = Ascii_4
-+ altgr keycode 75 = Hex_4
-+keycode 76 = KP_5
-+ alt keycode 76 = Ascii_5
-+ altgr keycode 76 = Hex_5
-+keycode 77 = KP_6
-+ alt keycode 77 = Ascii_6
-+ altgr keycode 77 = Hex_6
-+keycode 78 = KP_Add
-+keycode 79 = KP_1
-+ alt keycode 79 = Ascii_1
-+ altgr keycode 79 = Hex_1
-+keycode 80 = KP_2
-+ alt keycode 80 = Ascii_2
-+ altgr keycode 80 = Hex_2
-+keycode 81 = KP_3
-+ alt keycode 81 = Ascii_3
-+ altgr keycode 81 = Hex_3
-+keycode 82 = KP_0
-+ alt keycode 82 = Ascii_0
-+ altgr keycode 82 = Hex_0
-+keycode 83 = KP_Period
-+# altgr control keycode 83 = Boot
-+ control alt keycode 83 = Boot
-+keycode 84 = Last_Console
-+keycode 85 =
-+keycode 86 = less greater bar
-+ alt keycode 86 = Meta_less
-+keycode 87 = F11 F11 Console_23
-+ control keycode 87 = F11
-+ alt keycode 87 = Console_11
-+ control alt keycode 87 = Console_11
-+keycode 88 = F12 F12 Console_24
-+ control keycode 88 = F12
-+ alt keycode 88 = Console_12
-+ control alt keycode 88 = Console_12
-+keycode 89 =
-+keycode 90 =
-+keycode 91 =
-+keycode 92 =
-+keycode 93 =
-+keycode 94 =
-+keycode 95 =
-+keycode 96 = KP_Enter
-+keycode 97 = Control
-+keycode 98 = KP_Divide
-+keycode 99 = Control_backslash
-+ control keycode 99 = Control_backslash
-+ alt keycode 99 = Control_backslash
-+keycode 100 = AltGr
-+keycode 101 = Break
-+keycode 102 = Find
-+keycode 103 = Up
-+keycode 104 = Prior
-+ shift keycode 104 = Scroll_Backward
-+keycode 105 = Left
-+ alt keycode 105 = Decr_Console
-+keycode 106 = Right
-+ alt keycode 106 = Incr_Console
-+keycode 107 = Select
-+keycode 108 = Down
-+keycode 109 = Next
-+ shift keycode 109 = Scroll_Forward
-+keycode 110 = Insert
-+keycode 111 = Remove
-+# altgr control keycode 111 = Boot
-+ control alt keycode 111 = Boot
-+keycode 112 = Macro
-+keycode 113 = F13
-+keycode 114 = F14
-+keycode 115 = Help
-+keycode 116 = Do
-+keycode 117 = F17
-+keycode 118 = KP_MinPlus
-+keycode 119 = Pause
-+keycode 120 =
-+keycode 121 =
-+keycode 122 =
-+keycode 123 =
-+keycode 124 =
-+keycode 125 =
-+keycode 126 =
-+keycode 127 =
-+string F1 = "\033[[A"
-+string F2 = "\033[[B"
-+string F3 = "\033[[C"
-+string F4 = "\033[[D"
-+string F5 = "\033[[E"
-+string F6 = "\033[17~"
-+string F7 = "\033[18~"
-+string F8 = "\033[19~"
-+string F9 = "\033[20~"
-+string F10 = "\033[21~"
-+string F11 = "\033[23~"
-+string F12 = "\033[24~"
-+string F13 = "\033[25~"
-+string F14 = "\033[26~"
-+string F15 = "\033[28~"
-+string F16 = "\033[29~"
-+string F17 = "\033[31~"
-+string F18 = "\033[32~"
-+string F19 = "\033[33~"
-+string F20 = "\033[34~"
-+string Find = "\033[1~"
-+string Insert = "\033[2~"
-+string Remove = "\033[3~"
-+string Select = "\033[4~"
-+string Prior = "\033[5~"
-+string Next = "\033[6~"
-+string Macro = "\033[M"
-+string Pause = "\033[P"
-+compose '`' 'A' to 'À'
-+compose '`' 'a' to 'à'
-+compose '\'' 'A' to 'Á'
-+compose '\'' 'a' to 'á'
-+compose '^' 'A' to 'Â'
-+compose '^' 'a' to 'â'
-+compose '~' 'A' to 'Ã'
-+compose '~' 'a' to 'ã'
-+compose '"' 'A' to 'Ä'
-+compose '"' 'a' to 'ä'
-+compose 'O' 'A' to 'Å'
-+compose 'o' 'a' to 'å'
-+compose '0' 'A' to 'Å'
-+compose '0' 'a' to 'å'
-+compose 'A' 'A' to 'Å'
-+compose 'a' 'a' to 'å'
-+compose 'A' 'E' to 'Æ'
-+compose 'a' 'e' to 'æ'
-+compose ',' 'C' to 'Ç'
-+compose ',' 'c' to 'ç'
-+compose '`' 'E' to 'È'
-+compose '`' 'e' to 'è'
-+compose '\'' 'E' to 'É'
-+compose '\'' 'e' to 'é'
-+compose '^' 'E' to 'Ê'
-+compose '^' 'e' to 'ê'
-+compose '"' 'E' to 'Ë'
-+compose '"' 'e' to 'ë'
-+compose '`' 'I' to 'Ì'
-+compose '`' 'i' to 'ì'
-+compose '\'' 'I' to 'Í'
-+compose '\'' 'i' to 'í'
-+compose '^' 'I' to 'Î'
-+compose '^' 'i' to 'î'
-+compose '"' 'I' to 'Ï'
-+compose '"' 'i' to 'ï'
-+compose '-' 'D' to 'Ð'
-+compose '-' 'd' to 'ð'
-+compose '~' 'N' to 'Ñ'
-+compose '~' 'n' to 'ñ'
-+compose '`' 'O' to 'Ò'
-+compose '`' 'o' to 'ò'
-+compose '\'' 'O' to 'Ó'
-+compose '\'' 'o' to 'ó'
-+compose '^' 'O' to 'Ô'
-+compose '^' 'o' to 'ô'
-+compose '~' 'O' to 'Õ'
-+compose '~' 'o' to 'õ'
-+compose '"' 'O' to 'Ö'
-+compose '"' 'o' to 'ö'
-+compose '/' 'O' to 'Ø'
-+compose '/' 'o' to 'ø'
-+compose '`' 'U' to 'Ù'
-+compose '`' 'u' to 'ù'
-+compose '\'' 'U' to 'Ú'
-+compose '\'' 'u' to 'ú'
-+compose '^' 'U' to 'Û'
-+compose '^' 'u' to 'û'
-+compose '"' 'U' to 'Ü'
-+compose '"' 'u' to 'ü'
-+compose '\'' 'Y' to 'Ý'
-+compose '\'' 'y' to 'ý'
-+compose 'T' 'H' to 'Þ'
-+compose 't' 'h' to 'þ'
-+compose 's' 's' to 'ß'
-+compose '"' 'y' to 'ÿ'
-+compose 's' 'z' to 'ß'
-+compose 'i' 'j' to 'ÿ'
---- linux-2.4.27/drivers/char/generic_serial.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/generic_serial.c
-@@ -883,6 +883,9 @@
- if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
- }
-
-+ /*
-+ * should be using tty_get_baud_rate() here -- rmk
-+ */
- baudrate = tiosp->c_cflag & CBAUD;
- if (baudrate & CBAUDEX) {
- baudrate &= ~CBAUDEX;
-@@ -957,6 +960,11 @@
- unsigned long flags;
- unsigned long page;
-
-+ /*
-+ * Do we expect to allocate tmp_buf from an interrupt routine?
-+ * If not, then save_flags() cli() and restore_flags() are
-+ * redundant here and should be replaced by a semaphore. -- rmk
-+ */
- save_flags (flags);
- if (!tmp_buf) {
- page = get_free_page(GFP_KERNEL);
-@@ -976,6 +984,11 @@
- if (port->flags & ASYNC_INITIALIZED)
- return 0;
-
-+ /*
-+ * Do we expect to allocate xmit_buf from an interrupt routine?
-+ * If not, then save_flags() cli() and restore_flags() are
-+ * redundant here and should be replaced by a semaphore. -- rmk
-+ */
- if (!port->xmit_buf) {
- /* We may sleep in get_free_page() */
- unsigned long tmp;
-@@ -1016,7 +1029,7 @@
- struct serial_struct sio;
-
- if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-- return(-EFAULT);
-+ return -EFAULT;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((sio.baud_base != port->baud_base) ||
---- linux-2.4.27/drivers/char/keyboard.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/keyboard.c
-@@ -14,13 +14,17 @@
- * `Sticky' modifier keys, 951006.
- *
- * 11-11-96: SAK should now work in the raw mode (Martin Mares)
-- *
-+ *
- * Modified to provide 'generic' keyboard support by Hamish Macdonald
- * Merge with the m68k keyboard driver and split-off of the PC low-level
- * parts by Geert Uytterhoeven, May 1997
- *
- * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
- * 30-07-98: Dead keys redone, aeb@cwi.nl.
-+ *
-+ * 04-04-1998: Added keyboard autorepeat support (some keyboards don't
-+ * autorepeat, and some keyboard changers interfere with keyboard
-+ * autorepeat settings). - Russell King (rmk@arm.linux.org.uk)
- */
-
- #include <linux/config.h>
-@@ -30,6 +34,7 @@
- #include <linux/tty_flip.h>
- #include <linux/mm.h>
- #include <linux/string.h>
-+#include <linux/timer.h>
- #include <linux/random.h>
- #include <linux/init.h>
-
-@@ -61,6 +66,14 @@
- #define KBD_DEFLOCK 0
- #endif
-
-+/*
-+ * Default autorepeat settings.
-+ * DEFAULT_REPEAT_TIMEOUT is the timeout from the keypress to the first repeat
-+ * DEFAULT_REPEAT_INTERVAL is the timeout between successive repeats
-+ */
-+#define DEFAULT_REPEAT_TIMEOUT HZ*300/1000
-+#define DEFAULT_REPEAT_INTERVAL HZ*30/1000
-+
- void (*kbd_ledfunc)(unsigned int led);
- EXPORT_SYMBOL(handle_scancode);
- EXPORT_SYMBOL(kbd_ledfunc);
-@@ -82,21 +95,25 @@
- static unsigned long key_down[256/BITS_PER_LONG];
-
- static int dead_key_next;
--/*
-+/*
- * In order to retrieve the shift_state (for the mouse server), either
-- * the variable must be global, or a new procedure must be created to
-+ * the variable must be global, or a new procedure must be created to
- * return the value. I chose the former way.
- */
- int shift_state;
- static int npadch = -1; /* -1 or number assembled on pad */
- static unsigned char diacr;
- static char rep; /* flag telling character repeat */
-+static int kbd_repeatkeycode= -1;
-+static int kbd_repeattimeout = DEFAULT_REPEAT_TIMEOUT;
-+static int kbd_repeatinterval= DEFAULT_REPEAT_INTERVAL;
- struct kbd_struct kbd_table[MAX_NR_CONSOLES];
- static struct tty_struct **ttytab;
- static struct kbd_struct * kbd = kbd_table;
- static struct tty_struct * tty;
- static unsigned char prev_scancode;
-
-+static void kbd_processkeycode(unsigned char scancode, char up_flag, int autorepeat);
- void compute_shiftstate(void);
-
- typedef void (*k_hand)(unsigned char value, char up_flag);
-@@ -163,7 +180,8 @@
- * string, and in both cases we might assume that it is
- * in utf-8 already.
- */
--void to_utf8(ushort c) {
-+void to_utf8(ushort c)
-+{
- if (c < 0x80)
- put_queue(c); /* 0******* */
- else if (c < 0x800) {
-@@ -182,17 +200,23 @@
- * Translation of escaped scancodes to keycodes.
- * This is now user-settable (for machines were it makes sense).
- */
--
- int setkeycode(unsigned int scancode, unsigned int keycode)
- {
-- return kbd_setkeycode(scancode, keycode);
-+ return kbd_setkeycode(scancode, keycode);
- }
-
- int getkeycode(unsigned int scancode)
- {
-- return kbd_getkeycode(scancode);
-+ return kbd_getkeycode(scancode);
- }
-
-+static void key_callback(unsigned long nr);
-+
-+static struct timer_list key_autorepeat_timer =
-+{
-+ function: key_callback
-+};
-+
- void handle_scancode(unsigned char scancode, int down)
- {
- unsigned char keycode;
-@@ -201,6 +225,7 @@
- char have_keycode;
-
- pm_access(pm_kbd);
-+
- add_keyboard_randomness(scancode | up_flag);
-
- tty = ttytab? ttytab[fg_console]: NULL;
-@@ -223,15 +248,15 @@
- if (raw_mode) {
- /*
- * The following is a workaround for hardware
-- * which sometimes send the key release event twice
-+ * which sometimes send the key release event twice
- */
- unsigned char next_scancode = scancode|up_flag;
- if (have_keycode && up_flag && next_scancode==prev_scancode) {
- /* unexpected 2nd release event */
- } else {
-- /*
-+ /*
- * Only save previous scancode if it was a key-up
-- * and had a single-byte scancode.
-+ * and had a single-byte scancode.
- */
- if (!have_keycode)
- prev_scancode = 1;
-@@ -256,12 +281,35 @@
- * return the keycode if in MEDIUMRAW mode.
- */
-
-+ kbd_processkeycode(keycode, up_flag, 0);
-+
-+out:
-+ do_poke_blanked_console = 1;
-+ schedule_console_callback();
-+}
-+
-+static void
-+kbd_processkeycode(unsigned char keycode, char up_flag, int autorepeat)
-+{
-+ char raw_mode = (kbd->kbdmode == VC_RAW);
-+
- if (up_flag) {
- rep = 0;
- if(!test_and_clear_bit(keycode, key_down))
- up_flag = kbd_unexpected_up(keycode);
-- } else
-+ } else {
- rep = test_and_set_bit(keycode, key_down);
-+ /* If the keyboard autorepeated for us, ignore it.
-+ * We do our own autorepeat processing.
-+ */
-+ if (rep && !autorepeat)
-+ return;
-+ }
-+
-+ if (kbd_repeatkeycode == keycode || !up_flag || raw_mode) {
-+ kbd_repeatkeycode = -1;
-+ del_timer(&key_autorepeat_timer);
-+ }
-
- #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
- if (keycode == SYSRQ_KEY) {
-@@ -275,6 +323,23 @@
- }
- #endif
-
-+ /*
-+ * Calculate the next time when we have to do some autorepeat
-+ * processing. Note that we do not do autorepeat processing
-+ * while in raw mode but we do do autorepeat processing in
-+ * medium raw mode.
-+ */
-+ if (!up_flag && !raw_mode) {
-+ kbd_repeatkeycode = keycode;
-+ if (vc_kbd_mode(kbd, VC_REPEAT)) {
-+ if (rep)
-+ key_autorepeat_timer.expires = jiffies + kbd_repeatinterval;
-+ else
-+ key_autorepeat_timer.expires = jiffies + kbd_repeattimeout;
-+ add_timer(&key_autorepeat_timer);
-+ }
-+ }
-+
- if (kbd->kbdmode == VC_MEDIUMRAW) {
- /* soon keycodes will require more than one byte */
- put_queue(keycode + up_flag);
-@@ -343,9 +408,24 @@
- #endif
- }
- }
-+ rep = 0;
- out:
-- do_poke_blanked_console = 1;
-- schedule_console_callback();
-+}
-+
-+/*
-+ * This clears the key down arrays when the keyboard is reset. On
-+ * keyboard reset, this must be called before any keycodes are
-+ * received.
-+ */
-+void kbd_reset_kdown(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_SHIFT; i++)
-+ k_down[i] = 0;
-+ for (i = 0; i < SIZE(key_down); i++)
-+ key_down[i] = 0;
-+ shift_state = 0;
- }
-
- void put_queue(int ch)
-@@ -453,7 +533,7 @@
- static void decr_console(void)
- {
- int i;
--
-+
- for (i = fg_console-1; i != fg_console; i--) {
- if (i == -1)
- i = MAX_NR_CONSOLES-1;
-@@ -531,7 +611,7 @@
- {
- }
-
--static void do_null()
-+static void do_null(void)
- {
- compute_shiftstate();
- }
-@@ -646,8 +726,8 @@
-
- static void do_pad(unsigned char value, char up_flag)
- {
-- static const char *pad_chars = "0123456789+-*/\015,.?()";
-- static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
-+ static const char *pad_chars = "0123456789+-*/\015,.?()#";
-+ static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
-
- if (up_flag)
- return; /* no action, if this is a key release */
-@@ -748,9 +828,10 @@
- }
- }
-
--/* called after returning from RAW mode or when changing consoles -
-- recompute k_down[] and shift_state from key_down[] */
--/* maybe called when keymap is undefined, so that shiftkey release is seen */
-+/* Called after returning from RAW mode or when changing consoles -
-+ * recompute k_down[] and shift_state from key_down[]
-+ * Maybe called when keymap is undefined so that shift key release is seen
-+ */
- void compute_shiftstate(void)
- {
- int i, j, k, sym, val;
-@@ -829,19 +910,22 @@
- }
-
- /*
-- * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
-- * or (ii) whatever pattern of lights people want to show using KDSETLED,
-- * or (iii) specified bits of specified words in kernel memory.
-+ * The leds display either
-+ * (i) the status of NumLock, CapsLock, ScrollLock, or
-+ * (ii) whatever pattern of lights people want to show using KDSETLED, or
-+ * (iii) specified bits of specified words in kernel memory.
- */
-
- static unsigned char ledstate = 0xff; /* undefined */
- static unsigned char ledioctl;
-
--unsigned char getledstate(void) {
-+unsigned char getledstate(void)
-+{
- return ledstate;
- }
-
--void setledstate(struct kbd_struct *kbd, unsigned int led) {
-+void setledstate(struct kbd_struct *kbd, unsigned int led)
-+{
- if (!(led & ~7)) {
- ledioctl = led;
- kbd->ledmode = LED_SHOW_IOCTL;
-@@ -857,7 +941,8 @@
- } ledptrs[3];
-
- void register_leds(int console, unsigned int led,
-- unsigned int *addr, unsigned int mask) {
-+ unsigned int *addr, unsigned int mask)
-+{
- struct kbd_struct *kbd = kbd_table + console;
- if (led < 3) {
- ledptrs[led].addr = addr;
-@@ -868,7 +953,8 @@
- kbd->ledmode = LED_SHOW_FLAGS;
- }
-
--static inline unsigned char getleds(void){
-+static inline unsigned char getleds(void)
-+{
- struct kbd_struct *kbd = kbd_table + fg_console;
- unsigned char leds;
-
-@@ -915,6 +1001,19 @@
- {
- unsigned char leds = getleds();
-
-+ if (rep && kbd_repeatkeycode != -1) {
-+ tty = ttytab? ttytab[fg_console]: NULL;
-+ kbd = kbd_table + fg_console;
-+
-+ /* This prevents the kbd_key routine from being called
-+ * twice, once by this BH, and once by the interrupt
-+ * routine.
-+ */
-+ kbd_disable_irq();
-+ kbd_processkeycode(kbd_repeatkeycode, 0, 1);
-+ kbd_enable_irq();
-+ }
-+
- if (leds != ledstate) {
- ledstate = leds;
- kbd_leds(leds);
-@@ -937,6 +1036,12 @@
- tasklet_enable(&keyboard_tasklet);
- }
-
-+static void key_callback(unsigned long nr)
-+{
-+ rep = 1;
-+ tasklet_schedule(&keyboard_tasklet);
-+}
-+
- typedef void (pm_kbd_func) (void);
-
- pm_callback pm_kbd_request_override = NULL;
-@@ -953,7 +1058,7 @@
- kbd0.slockstate = 0;
- kbd0.modeflags = KBD_DEFMODE;
- kbd0.kbdmode = VC_XLATE;
--
-+
- for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
- kbd_table[i] = kbd0;
-
-@@ -963,7 +1068,7 @@
-
- tasklet_enable(&keyboard_tasklet);
- tasklet_schedule(&keyboard_tasklet);
--
-+
- pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override);
-
- return 0;
---- linux-2.4.27/drivers/char/mem.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/mem.c
-@@ -27,9 +27,6 @@
- #include <asm/io.h>
- #include <asm/pgalloc.h>
-
--#ifdef CONFIG_I2C
--extern int i2c_init_all(void);
--#endif
- #ifdef CONFIG_FB
- extern void fbmem_init(void);
- #endif
-@@ -740,9 +737,6 @@
- printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- memory_devfs_register();
- rand_initialize();
--#ifdef CONFIG_I2C
-- i2c_init_all();
--#endif
- #if defined (CONFIG_FB)
- fbmem_init();
- #endif
---- /dev/null
-+++ linux-2.4.27/drivers/char/omaha-rtc.c
-@@ -0,0 +1,566 @@
-+/*
-+ * (C) ARM Limited 2002.
-+ *
-+ * Real Time Clock interface for Linux on Omaha
-+ *
-+ * Based on sa1100-rtc.c
-+ *
-+ * Copyright (c) 2000 Nils Faerber
-+ *
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russell King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
-+ * - added periodic timer capability using OSMR1
-+ * - flag compatibility with other RTC chips
-+ * - permission checks for ioctls
-+ * - major cleanup, partial rewrite
-+ *
-+ * 0.03 2001-03-07 CIH <cih@coventive.com>
-+ * - Modify the bug setups RTC clock.
-+ *
-+ * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
-+ * - removed mktime(), added alarm irq clear
-+ *
-+ * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
-+ * - initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+#include <linux/mc146818rtc.h>
-+
-+#define DRIVER_VERSION "1.00"
-+
-+#define epoch 1970
-+
-+#define TIMER_FREQ 3686400
-+
-+#define RTC_DEF_DIVIDER 32768 - 1
-+#define RTC_DEF_TRIM 0
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define RTC_PF 0x40
-+#define RTC_AF 0x20
-+#define RTC_UF 0x10
-+
-+// bitdefs for rtc registers
-+#define TICNT_ENABLE 0x80 // Enable tick interrupt
-+#define TICNT_PERIOD 0x7F // Divisor required for 1Hz tick
-+#define RTC_ENABLE 0x1 // Enable bit for RTC
-+
-+static unsigned long rtc_status;
-+static unsigned long rtc_irq_data;
-+static unsigned long rtc_freq = 1024;
-+
-+static struct fasync_struct *rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
-+
-+extern spinlock_t rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+// all the alarm and rtc registers
-+static volatile unsigned int almsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMSEC);
-+static volatile unsigned int almmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMIN);
-+static volatile unsigned int almhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMHOUR);
-+static volatile unsigned int almday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMDAY);
-+static volatile unsigned int almmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMMON);
-+static volatile unsigned int almyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_ALMYEAR);
-+
-+static volatile unsigned int bcdsec = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDSEC);
-+static volatile unsigned int bcdmin = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMIN);
-+static volatile unsigned int bcdhour = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDHOUR);
-+static volatile unsigned int bcdday = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDAY);
-+static volatile unsigned int bcddate = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDDATE);
-+static volatile unsigned int bcdmon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDMON);
-+static volatile unsigned int bcdyear = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_BCDYEAR);
-+
-+/*
-+ * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
-+ */
-+
-+static void decodetime (unsigned long t, struct rtc_time *tval)
-+{
-+ long days, month, year, rem;
-+
-+ days = t / 86400;
-+ rem = t % 86400;
-+ tval->tm_hour = rem / 3600;
-+ rem %= 3600;
-+ tval->tm_min = rem / 60;
-+ tval->tm_sec = rem % 60;
-+ tval->tm_wday = (4 + days) % 7;
-+
-+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-+
-+ year = epoch;
-+ while (days >= (365 + is_leap(year))) {
-+ unsigned long yg = year + days / 365;
-+ days -= ((yg - year) * 365
-+ + LEAPS_THRU_END_OF (yg - 1)
-+ - LEAPS_THRU_END_OF (year - 1));
-+ year = yg;
-+ }
-+ tval->tm_year = year - 1900;
-+ tval->tm_yday = days + 1;
-+
-+ month = 0;
-+ if (days >= 31) {
-+ days -= 31;
-+ month++;
-+ if (days >= (28 + is_leap(year))) {
-+ days -= (28 + is_leap(year));
-+ month++;
-+ while (days >= days_in_mo[month]) {
-+ days -= days_in_mo[month];
-+ month++;
-+ }
-+ }
-+ }
-+ tval->tm_mon = month;
-+ tval->tm_mday = days + 1;
-+}
-+
-+// Get alarm time in seconds
-+static unsigned long get_alarm_time(void)
-+{
-+ int sec, min,hour,date,mon,year;
-+
-+ // Read data from h/w
-+ year = __raw_readb(almyear);
-+ mon = __raw_readb(almmon);
-+ date = __raw_readb(almday);
-+ hour = __raw_readb(almhour);
-+ min = __raw_readb(almmin);
-+ sec = __raw_readb(almsec);
-+
-+ // convert all the data into binary
-+ year = BCD_TO_BIN(year);
-+ mon = BCD_TO_BIN(mon);
-+ date = BCD_TO_BIN(date);
-+ hour = BCD_TO_BIN(hour);
-+ min = BCD_TO_BIN(min);
-+ sec = BCD_TO_BIN(sec);
-+
-+ // convert year to 19xx or 20xx as appropriate
-+ if (year > 69)
-+ year += 1900;
-+ else
-+ year += 2000;
-+
-+ // Now calculate number of seconds since time began...
-+ return mktime(year,mon,date,hour,min,sec);
-+}
-+
-+// Get rtc time in seconds
-+static unsigned long get_rtc_time(void)
-+{
-+ int sec,min,hour,day,date,mon,year;
-+
-+ // Read data from h/w
-+ year = __raw_readb(bcdyear);
-+ mon = __raw_readb(bcdmon);
-+ date = __raw_readb(bcdday);
-+ day = __raw_readb(bcddate);
-+ hour = __raw_readb(bcdhour);
-+ min = __raw_readb(bcdmin);
-+ sec = __raw_readb(bcdsec);
-+
-+ // convert all the data into binary
-+ year = BCD_TO_BIN(year);
-+ mon = BCD_TO_BIN(mon);
-+ date = BCD_TO_BIN(date);
-+ day = BCD_TO_BIN(day);
-+ hour = BCD_TO_BIN(hour);
-+ min = BCD_TO_BIN(min);
-+ sec = BCD_TO_BIN(sec);
-+
-+ // convert year to 19xx or 20xx as appropriate
-+ if (year > 69)
-+ year += 1900;
-+ else
-+ year += 2000;
-+
-+ // Now calculate number of seconds since time began...
-+ return mktime(year,mon,date,hour,min,sec);
-+}
-+
-+/* Sets time of alarm */
-+static void set_alarm_time(struct rtc_time *tval)
-+{
-+
-+ int sec,min,hour,day,mon,year;
-+
-+ // Convert data from binary to 8-bit bcd
-+ sec = BIN_TO_BCD(tval->tm_sec);
-+ min = BIN_TO_BCD(tval->tm_min);
-+ hour = BIN_TO_BCD(tval->tm_hour);
-+ day = BIN_TO_BCD(tval->tm_mday);
-+ mon = BIN_TO_BCD(tval->tm_mon);
-+
-+ // Year is special
-+ year = tval->tm_year;
-+ if(year > 1999)
-+ year -=2000;
-+ else
-+ year -=1900;
-+
-+ year = BIN_TO_BCD(year);
-+
-+ // Write all the registers
-+ __raw_writeb(year,almyear);
-+ __raw_writeb(mon,almmon);
-+ __raw_writeb(day,almday);
-+ __raw_writeb(hour,almhour);
-+ __raw_writeb(min,almmin);
-+ __raw_writeb(sec,almsec);
-+}
-+
-+/* Sets time of alarm */
-+static void set_rtc_time(struct rtc_time *tval)
-+{
-+
-+ int sec,min,hour,day,date,mon,year;
-+
-+ // Convert data from binary to 8-bit bcd
-+ sec = BIN_TO_BCD(tval->tm_sec);
-+ min = BIN_TO_BCD(tval->tm_min);
-+ hour = BIN_TO_BCD(tval->tm_hour);
-+ day = BIN_TO_BCD(tval->tm_mday);
-+ date = BIN_TO_BCD(tval->tm_wday);
-+ mon = BIN_TO_BCD(tval->tm_mon);
-+
-+ // Year is special
-+ year = tval->tm_year;
-+ if(year > 1999)
-+ year -=2000;
-+ else
-+ year -=1900;
-+
-+ year = BIN_TO_BCD(year);
-+
-+ // Write all the registers
-+ __raw_writeb(year,bcdyear);
-+ __raw_writeb(mon,bcdmon);
-+ __raw_writeb(date,bcddate);
-+ __raw_writeb(day,bcdday);
-+ __raw_writeb(hour,bcdhour);
-+ __raw_writeb(min,bcdmin);
-+ __raw_writeb(sec,bcdsec);
-+}
-+
-+static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /* update irq data & counter */
-+ rtc_irq_data += 0x100;
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static int rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit (1, &rtc_status))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int rtc_release(struct inode *inode, struct file *file)
-+{
-+ rtc_status = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static int rtc_fasync (int fd, struct file *filp, int on)
-+{
-+ return fasync_helper (fd, filp, on, &rtc_async_queue);
-+}
-+
-+static unsigned int rtc_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait (file, &rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq (&rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+
-+ spin_unlock_irq (&rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+
-+ retval = put_user(data, (unsigned long *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&rtc_wait, &wait);
-+ return retval;
-+}
-+
-+static int rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ volatile unsigned int rtcalm = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCALM);
-+ volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
-+
-+ struct rtc_time tm, tm2;
-+ switch (cmd) {
-+ case RTC_AIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(0,rtcalm);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_AIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(0x7F,rtcalm);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(~TICNT_ENABLE,ticnt);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ __raw_writel(TICNT_ENABLE|TICNT_PERIOD,ticnt);
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ // Periodic int not available
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ // Periodic int not available
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_ALM_READ:
-+ decodetime(get_alarm_time(),&tm);
-+ break;
-+ case RTC_ALM_SET:
-+ if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
-+ return -EFAULT;
-+ decodetime(get_rtc_time(),&tm);
-+ if ((unsigned)tm2.tm_hour < 24)
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned)tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned)tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+
-+ // Munge (as per sa1100)
-+ tm.tm_year+=1900;
-+ tm.tm_mon+=1;
-+
-+ // Set the alarm
-+ set_alarm_time(&tm);
-+ return 0;
-+ case RTC_RD_TIME:
-+ decodetime (get_rtc_time(), &tm);
-+ break;
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ return -EACCES;
-+ if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
-+ return -EFAULT;
-+ tm.tm_year += 1900;
-+ if (tm.tm_year < epoch || (unsigned)tm.tm_mon >= 12 ||
-+ tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
-+ (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
-+ (unsigned)tm.tm_hour >= 24 ||
-+ (unsigned)tm.tm_min >= 60 ||
-+ (unsigned)tm.tm_sec >= 60)
-+ return -EINVAL;
-+ tm.tm_mon +=1; // wierd: same as sa1100 though (gets month wrong otherwise!)
-+ set_rtc_time(&tm);
-+ return 0;
-+ case RTC_IRQP_READ:
-+ return put_user(rtc_freq, (unsigned long *)arg);
-+ case RTC_IRQP_SET:
-+ if (arg < 1 || arg > TIMER_FREQ)
-+ return -EINVAL;
-+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-+ return -EACCES;
-+ rtc_freq = arg;
-+ return 0;
-+ case RTC_EPOCH_READ:
-+ return put_user (epoch, (unsigned long *)arg);
-+ default:
-+ return -EINVAL;
-+ }
-+ return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
-+}
-+
-+static struct file_operations rtc_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = rtc_llseek,
-+ .read = rtc_read,
-+ .poll = rtc_poll,
-+ .ioctl = rtc_ioctl,
-+ .open = rtc_open,
-+ .release = rtc_release,
-+ .fasync = rtc_fasync,
-+};
-+
-+static struct miscdevice omahartc_miscdev = {
-+ .minor = RTC_MINOR,
-+ .name = "rtc",
-+ .fops = &rtc_fops,
-+};
-+
-+static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ decodetime (get_rtc_time(), &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
-+ decodetime (get_alarm_time(), &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init rtc_init(void)
-+{
-+ volatile unsigned int ticnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_TICINT);
-+ volatile unsigned int rtccon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_RTCCON);
-+ int ret;
-+
-+ misc_register (&omahartc_miscdev);
-+ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
-+
-+ // Enable RTC
-+ __raw_writel(RTC_ENABLE,rtccon);
-+
-+ // Acquire 1Hz timer
-+ ret = request_irq (OMAHA_INT_TICK, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_TICK);
-+ goto IRQ_TICK_failed;
-+ }
-+
-+ // Acquire RTC (Alarm interrupt)
-+ ret = request_irq (OMAHA_INT_RTC, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", OMAHA_INT_RTC);
-+ goto IRQ_RTC_failed;
-+ }
-+
-+ printk (KERN_INFO "Omaha Real Time Clock driver v" DRIVER_VERSION "\n");
-+
-+ // Program tick interrupt divisor to generate real 1Hz clock and enable the interrupt
-+ __raw_writeb(TICNT_ENABLE|TICNT_PERIOD,ticnt);
-+
-+ return 0;
-+
-+IRQ_TICK_failed:
-+ free_irq (OMAHA_INT_TICK, NULL);
-+IRQ_RTC_failed:
-+ free_irq(OMAHA_INT_RTC, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&omahartc_miscdev);
-+ return ret;
-+}
-+
-+static void __exit rtc_exit(void)
-+{
-+ free_irq (OMAHA_INT_TICK, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&omahartc_miscdev);
-+}
-+
-+module_init(rtc_init);
-+module_exit(rtc_exit);
-+
-+MODULE_AUTHOR("ARM Limited <support@arm.com>");
-+MODULE_DESCRIPTION("Omaha Realtime Clock Driver (RTC)");
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/char/omaha_wdt.c
-@@ -0,0 +1,193 @@
-+/*
-+ * Watchdog driver for the Omaha
-+ * (C) ARM Limited 2002.
-+ *
-+ * Based on sa1100_wdt.c
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ * Based on SoftDog driver by Alan Cox <alan@redhat.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.
-+ *
-+ * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
-+ * warranty for any of this software. This material is provided
-+ * "AS-IS" and at no charge.
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ *
-+ * 27/11/2000 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 8 /* (secs) Default is 1 minute */
-+#define WT_TPS 7812 /* Watchdog ticks per second. */
-+#define WT_ENABLE 0x21 // Enable bits for watchdog
-+#define WT_CLKSEL_128 0x18 // Select 1/128 divider
-+
-+static int omaha_margin = TIMER_MARGIN; /* in seconds */
-+static int omahawdt_users;
-+static int pre_margin;
-+#ifdef MODULE
-+MODULE_PARM(omaha_margin,"i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int omahadog_open(struct inode *inode, struct file *file)
-+{
-+ volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
-+ volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
-+ volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
-+ unsigned int tmp;
-+
-+ if(test_and_set_bit(1,&omahawdt_users))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ /* Activate omaha Watchdog timer */
-+
-+ /* Assume that uhal has set up pre-scaler according
-+ * to the system clock frequency (don't change it!)
-+ *
-+ * Ie. all counting occurs at 1MHz / 128 = 7812.5Hz
-+ *
-+ * Since we have 16-bit counter, maximum period is
-+ * 65536/7812.5 = 8.338608 seconds!
-+ */
-+
-+ pre_margin = WT_TPS * omaha_margin;
-+
-+ // Set count to the maximum
-+ __raw_writel(pre_margin,wtcnt);
-+
-+ // Set the clock division factor
-+ tmp = __raw_readl(wtcon);
-+ tmp |= WT_CLKSEL_128;
-+ __raw_writel(tmp,wtcon);
-+
-+ // Program an initial count into WTDAT
-+ __raw_writel(0x8000,wtdat);
-+
-+ // enable the watchdog
-+ tmp = __raw_readl(wtcon);
-+ tmp |= WT_ENABLE;
-+
-+ __raw_writel(tmp,wtcon);
-+
-+ return 0;
-+}
-+
-+static int omahadog_release(struct inode *inode, struct file *file)
-+{
-+ volatile unsigned int wtcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCON);
-+ unsigned int tmp;
-+
-+ /*
-+ * Shut off the timer.
-+ * Lock it in if it's a module and we defined ...NOWAYOUT
-+ */
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ tmp = __raw_readl(wtcon);
-+ tmp &= ~WT_ENABLE;
-+ __raw_writel(tmp,wtcon);
-+#endif
-+ omahawdt_users = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static ssize_t omahadog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ volatile unsigned int wtcnt = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTCNT);
-+
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Refresh timer. */
-+ if(len) {
-+ __raw_writel(pre_margin,wtcnt);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int omahadog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ volatile unsigned int wtdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_WTDAT);
-+ static struct watchdog_info ident = {
-+ identity: "omaha Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+ case WDIOC_GETSTATUS:
-+ return put_user(0,(int *)arg);
-+ case WDIOC_GETBOOTSTATUS:
-+ return 0;
-+ case WDIOC_KEEPALIVE:
-+ __raw_writel(pre_margin,wtdat);
-+ return 0;
-+ }
-+}
-+
-+static struct file_operations omahadog_fops=
-+{
-+ .owner = THIS_MODULE,
-+ .write = omahadog_write,
-+ .ioctl = omahadog_ioctl,
-+ .open = omahadog_open,
-+ .release = omahadog_release,
-+};
-+
-+static struct miscdevice omahadog_miscdev=
-+{
-+ .minor = WATCHDOG_MINOR,
-+ .name = "omaha watchdog",
-+ .fops = &omahadog_fops
-+};
-+
-+static int __init omahadog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&omahadog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("Omaha Watchdog Timer: timer margin %d sec\n", omaha_margin);
-+
-+ return 0;
-+}
-+
-+static void __exit omahadog_exit(void)
-+{
-+ misc_deregister(&omahadog_miscdev);
-+}
-+
-+module_init(omahadog_init);
-+module_exit(omahadog_exit);
---- linux-2.4.27/drivers/char/pcmcia/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/pcmcia/Config.in
-@@ -5,7 +5,13 @@
- mainmenu_option next_comment
- comment 'PCMCIA character devices'
-
--dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_SERIAL
-+if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL_8250" = "y" ]; then
-+ dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS y
-+else
-+ if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_SERIAL_8250" = "m" ]; then
-+ dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS m
-+ fi
-+fi
- if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" ]; then
- define_bool CONFIG_PCMCIA_CHRDEV y
- fi
---- /dev/null
-+++ linux-2.4.27/drivers/char/pcmcia/memory_cs.c
-@@ -0,0 +1,214 @@
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/mtd.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/cs.h>
-+#include <pcmcia/cistpl.h>
-+#include <pcmcia/ciscode.h>
-+#include <pcmcia/ds.h>
-+#include <pcmcia/cisreg.h>
-+
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/mtd.h>
-+
-+static dev_info_t dev_info = "memory_cs";
-+static dev_link_t *dev_list;
-+
-+struct memcs_dev {
-+ dev_link_t link;
-+ struct map_info map;
-+};
-+
-+static __u8 mem_cs_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 mem_cs_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 mem_cs_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return readl(map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_copy_from(struct map_info *map, void *to, unsigned long ofs, ssize_t size)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + ofs, size);
-+}
-+
-+static void mem_cs_write8(struct map_info *map, __u8 val, unsigned long ofs)
-+{
-+ writeb(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_write16(struct map_info *map, __u16 val, unsigned long ofs)
-+{
-+ writew(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_write32(struct map_info *map, __u32 val, unsigned long ofs)
-+{
-+ writel(val, map->map_priv_1 + ofs);
-+}
-+
-+static void mem_cs_copy_to(struct map_info *map, unsigned long ofs, const void *to, ssize_t size)
-+{
-+ memcpy_toio(map->map_priv_1 + ofs, from, size);
-+}
-+
-+static void mem_cs_release(u_long arg);
-+
-+static void mem_cs_detach(dev_link_t *link)
-+{
-+ del_timer(&link->release);
-+ if (link->state & DEV_CONFIG) {
-+ mem_cs_release((u_long)link);
-+ if (link->state & DEV_STALE_CONFIG) {
-+ link->state |= DEV_STALE_LINK;
-+ return;
-+ }
-+ }
-+
-+ if (link->handle)
-+ CardServices(DeregisterClient, link->handle);
-+
-+ kfree(link);
-+}
-+
-+static void mem_cs_release(u_long arg)
-+{
-+ dev_link_t *link = (dev_link_t *)arg;
-+
-+ link->dev = NULL;
-+ if (link->win) {
-+ CardServices(ReleaseWindow, link->win);
-+ }
-+ link->state &= ~DEV_CONFIG;
-+
-+ if (link->state & DEV_STALE_LINK)
-+ mem_cs_detach(link);
-+}
-+
-+static void mem_cs_config(dev_link_t *link)
-+{
-+ struct memcs_dev *dev = link->priv;
-+ cs_status_t status;
-+ win_req_t req;
-+
-+ link->state |= DEV_CONFIG;
-+
-+ req.Attributes = word_width ? WIN_DATA_WIDTH_16 : WIN_DATA_WIDTH_8;
-+ req.Base = 0;
-+ req.Size = 0;
-+ req.AccessSpeed = mem_speed;
-+
-+ link->win = (window_handle_t)link->handle;
-+
-+ CS_CHECK(RequestWindow, &link->win, &req);
-+
-+ CS_CHECK(GetStatus, link->handle, &status);
-+
-+ dev->map.buswidth = word_width ? 2 : 1;
-+ dev->map.size = req.Size;
-+ dev->map.map_priv_1 = ioremap(req.Base, req.Size);
-+}
-+
-+static int
-+mem_cs_event(event_t event, int priority, event_callback_args_t *args)
-+{
-+ dev_link_t *link = args->client_data;
-+
-+ switch (event) {
-+ case CS_EVENT_CARD_REMOVAL:
-+ link->state &= ~DEV_PRESENT;
-+ if (link->state & DEV_CONFIG)
-+ mod_timer(&link->release, jiffies + HZ/20);
-+ break;
-+
-+ case CS_EVENT_CARD_INSERTION:
-+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-+ mem_cs_config(link);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static dev_link_t *mem_cs_attach(void)
-+{
-+ struct memcs_dev *dev;
-+ client_reg_t clnt;
-+
-+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-+ if (dev) {
-+ memset(dev, 0, sizeof(*dev));
-+
-+ dev->map.read8 = mem_cs_read8;
-+ dev->map.read16 = mem_cs_read16;
-+ dev->map.read32 = mem_cs_read32;
-+ dev->map.copy_from = mem_cs_copy_from;
-+ dev->map.write8 = mem_cs_write8;
-+ dev->map.write16 = mem_cs_write16;
-+ dev->map.write32 = mem_cs_write32;
-+ dev->map.copy_to = mem_cs_copy_to;
-+
-+ dev->link.release.function = &mem_cs_release;
-+ dev->link.release.data = (u_long)link;
-+ dev->link.priv = dev;
-+
-+ dev->link.next = dev_list;
-+ dev_list = &dev->link;
-+
-+ clnt.dev_info = &dev_info;
-+ clnt.Attributes = INOF_IO_CLIENT | INFO_CARD_SHARE;
-+ clnt.EventMask =
-+ CS_EVENT_WRITE_PROTECT | CS_EVENT_CARD_INSERTION |
-+ CS_EVENT_CARD_REMOVAL | CS_EVENT_BATTERY_DEAD |
-+ CS_EVENT_BATTERY_LOW;
-+
-+ clnt.event_handler = &mem_cs_event;
-+ clnt.Version = 0x0210;
-+ clnt.event_callback_args.client_data = &dev->link;
-+
-+ ret = CardServices(RegisterClient, &dev->link.handle, &clnt);
-+ if (ret != CS_SUCCESS) {
-+ error_info_t err = { RegisterClient, ret };
-+ CardServices(ReportError, dev->link.handle, &err);
-+ mem_cs_detach(&dev->link);
-+ dev = NULL;
-+ }
-+ }
-+
-+ return &dev->link;
-+}
-+
-+static int __init mem_cs_init(void)
-+{
-+ servinfo_t serv;
-+
-+ CardServices(GetCardServicesInfo, &serv);
-+ if (serv.Revision != CS_RELEASE_CODE) {
-+ printk(KERN_NOTICE "memory_cs: Card services release "
-+ "does not match\n");
-+ return -ENXIO;
-+ }
-+ register_pccard_driver(&dev_info, mem_cs_attach, mem_cs_detach);
-+ return 0;
-+}
-+
-+static void __exit mem_cs_exit(void)
-+{
-+ unregister_pccard_driver(&dev_info);
-+ while (dev_list != NULL)
-+ memory_detach(dev_list);
-+}
-+
-+module_init(mem_cs_init);
-+module_exit(mem_cs_exit);
-+
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/char/sa1100-rtc.c
-@@ -0,0 +1,474 @@
-+/*
-+ * Real Time Clock interface for Linux on StrongARM SA1100
-+ *
-+ * Copyright (c) 2000 Nils Faerber
-+ *
-+ * Based on rtc.c by Paul Gortmaker
-+ * Date/time conversion routines taken from arch/arm/kernel/time.c
-+ * by Linus Torvalds and Russel King
-+ * and the GNU C Library
-+ * ( ... I love the GPL ... just take what you need! ;)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
-+ * - added periodic timer capability using OSMR1
-+ * - flag compatibility with other RTC chips
-+ * - permission checks for ioctls
-+ * - major cleanup, partial rewrite
-+ *
-+ * 0.03 2001-03-07 CIH <cih@coventive.com>
-+ * - Modify the bug setups RTC clock.
-+ *
-+ * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
-+ * - removed mktime(), added alarm irq clear
-+ *
-+ * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
-+ * - initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/string.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+#include <linux/proc_fs.h>
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <linux/rtc.h>
-+
-+#define DRIVER_VERSION "1.00"
-+
-+#define TIMER_FREQ 3686400
-+
-+#define RTC_DEF_DIVIDER 32768 - 1
-+#define RTC_DEF_TRIM 0
-+
-+/* Those are the bits from a classic RTC we want to mimic */
-+#define RTC_IRQF 0x80 /* any of the following 3 is active */
-+#define RTC_PF 0x40
-+#define RTC_AF 0x20
-+#define RTC_UF 0x10
-+
-+static unsigned long rtc_status;
-+static unsigned long rtc_irq_data;
-+static unsigned long rtc_freq = 1024;
-+
-+static struct fasync_struct *rtc_async_queue;
-+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
-+
-+extern spinlock_t rtc_lock;
-+
-+static const unsigned char days_in_mo[] =
-+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-+
-+#define is_leap(year) \
-+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-+
-+/*
-+ * Converts seconds since 1970-01-01 00:00:00 to Gregorian date.
-+ */
-+
-+static void decodetime (unsigned long t, struct rtc_time *tval)
-+{
-+ long days, month, year, rem;
-+
-+ days = t / 86400;
-+ rem = t % 86400;
-+ tval->tm_hour = rem / 3600;
-+ rem %= 3600;
-+ tval->tm_min = rem / 60;
-+ tval->tm_sec = rem % 60;
-+ tval->tm_wday = (4 + days) % 7;
-+
-+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-+
-+ year = 1970 + days / 365;
-+ days -= ((year - 1970) * 365
-+ + LEAPS_THRU_END_OF (year - 1)
-+ - LEAPS_THRU_END_OF (1970 - 1));
-+ if (days < 0) {
-+ year -= 1;
-+ days += 365 + is_leap(year);
-+ }
-+ tval->tm_year = year - 1900;
-+ tval->tm_yday = days + 1;
-+
-+ month = 0;
-+ if (days >= 31) {
-+ days -= 31;
-+ month++;
-+ if (days >= (28 + is_leap(year))) {
-+ days -= (28 + is_leap(year));
-+ month++;
-+ while (days >= days_in_mo[month]) {
-+ days -= days_in_mo[month];
-+ month++;
-+ }
-+ }
-+ }
-+ tval->tm_mon = month;
-+ tval->tm_mday = days + 1;
-+}
-+
-+static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int rtsr = RTSR;
-+
-+ /* clear interrupt sources */
-+ RTSR = 0;
-+ RTSR = (RTSR_AL|RTSR_HZ);
-+
-+ /* clear alarm interrupt if it has occurred */
-+ if (rtsr & RTSR_AL)
-+ rtsr &= ~RTSR_ALE;
-+ RTSR = rtsr & (RTSR_ALE|RTSR_HZE);
-+
-+ /* update irq data & counter */
-+ if (rtsr & RTSR_AL)
-+ rtc_irq_data |= (RTC_AF|RTC_IRQF);
-+ if (rtsr & RTSR_HZ)
-+ rtc_irq_data |= (RTC_UF|RTC_IRQF);
-+ rtc_irq_data += 0x100;
-+
-+ /* wake up waiting process */
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /*
-+ * If we match for the first time, the periodic interrupt flag won't
-+ * be set. If it is, then we did wrap around (very unlikely but
-+ * still possible) and compute the amount of missed periods.
-+ * The match reg is updated only when the data is actually retrieved
-+ * to avoid unnecessary interrupts.
-+ */
-+ OSSR = OSSR_M1; /* clear match on timer1 */
-+ if (rtc_irq_data & RTC_PF) {
-+ rtc_irq_data += (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))) << 8;
-+ } else {
-+ rtc_irq_data += (0x100|RTC_PF|RTC_IRQF);
-+ }
-+
-+ wake_up_interruptible(&rtc_wait);
-+ kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+}
-+
-+static int rtc_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit (1, &rtc_status))
-+ return -EBUSY;
-+ rtc_irq_data = 0;
-+ return 0;
-+}
-+
-+static int rtc_release(struct inode *inode, struct file *file)
-+{
-+ spin_lock_irq (&rtc_lock);
-+ RTSR = 0;
-+ RTSR = (RTSR_AL|RTSR_HZ);
-+ OIER &= ~OIER_E1;
-+ OSSR = OSSR_M1;
-+ spin_unlock_irq (&rtc_lock);
-+ rtc_status = 0;
-+ return 0;
-+}
-+
-+static int rtc_fasync (int fd, struct file *filp, int on)
-+{
-+ return fasync_helper (fd, filp, on, &rtc_async_queue);
-+}
-+
-+static unsigned int rtc_poll(struct file *file, poll_table *wait)
-+{
-+ poll_wait (file, &rtc_wait, wait);
-+ return (rtc_irq_data) ? 0 : POLLIN | POLLRDNORM;
-+}
-+
-+static loff_t rtc_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned long data;
-+ ssize_t retval;
-+
-+ if (count < sizeof(unsigned long))
-+ return -EINVAL;
-+
-+ add_wait_queue(&rtc_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ for (;;) {
-+ spin_lock_irq (&rtc_lock);
-+ data = rtc_irq_data;
-+ if (data != 0) {
-+ rtc_irq_data = 0;
-+ break;
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ if (file->f_flags & O_NONBLOCK) {
-+ retval = -EAGAIN;
-+ goto out;
-+ }
-+
-+ if (signal_pending(current)) {
-+ retval = -ERESTARTSYS;
-+ goto out;
-+ }
-+
-+ schedule();
-+ }
-+
-+ if (data & RTC_PF) {
-+ /* interpolate missed periods and set match for the next one */
-+ unsigned long period = TIMER_FREQ/rtc_freq;
-+ unsigned long oscr = OSCR;
-+ unsigned long osmr1 = OSMR1;
-+ unsigned long missed = (oscr - osmr1)/period;
-+ data += missed << 8;
-+ OSSR = OSSR_M1; /* clear match on timer 1 */
-+ OSMR1 = osmr1 + (missed + 1)*period;
-+ /* ensure we didn't miss another match in the mean time */
-+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 0 ) {
-+ data += 0x100;
-+ OSSR = OSSR_M1; /* clear match on timer 1 */
-+ OSMR1 = osmr1 + period;
-+ }
-+ }
-+ spin_unlock_irq (&rtc_lock);
-+
-+ data -= 0x100; /* the first IRQ wasn't actually missed */
-+
-+ retval = put_user(data, (unsigned long *)buf);
-+ if (!retval)
-+ retval = sizeof(unsigned long);
-+
-+out:
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&rtc_wait, &wait);
-+ return retval;
-+}
-+
-+static int rtc_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ struct rtc_time tm, tm2;
-+
-+ switch (cmd) {
-+ case RTC_AIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR &= ~RTSR_ALE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_AIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR |= RTSR_ALE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR &= ~RTSR_HZE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_UIE_ON:
-+ spin_lock_irq(&rtc_lock);
-+ RTSR |= RTSR_HZE;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_OFF:
-+ spin_lock_irq(&rtc_lock);
-+ OIER &= ~OIER_E1;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_PIE_ON:
-+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
-+ return -EACCES;
-+ spin_lock_irq(&rtc_lock);
-+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
-+ OIER |= OIER_E1;
-+ rtc_irq_data = 0;
-+ spin_unlock_irq(&rtc_lock);
-+ return 0;
-+ case RTC_ALM_READ:
-+ decodetime (RTAR, &tm);
-+ break;
-+ case RTC_ALM_SET:
-+ if (copy_from_user (&tm2, (struct rtc_time*)arg, sizeof (tm2)))
-+ return -EFAULT;
-+ decodetime (RCNR, &tm);
-+ if ((unsigned)tm2.tm_hour < 24)
-+ tm.tm_hour = tm2.tm_hour;
-+ if ((unsigned)tm2.tm_min < 60)
-+ tm.tm_min = tm2.tm_min;
-+ if ((unsigned)tm2.tm_sec < 60)
-+ tm.tm_sec = tm2.tm_sec;
-+ RTAR = mktime ( tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-+ tm.tm_hour, tm.tm_min, tm.tm_sec);
-+ return 0;
-+ case RTC_RD_TIME:
-+ decodetime (RCNR, &tm);
-+ break;
-+ case RTC_SET_TIME:
-+ if (!capable(CAP_SYS_TIME))
-+ return -EACCES;
-+ if (copy_from_user (&tm, (struct rtc_time*)arg, sizeof (tm)))
-+ return -EFAULT;
-+ tm.tm_year += 1900;
-+ if (tm.tm_year < 1970 || (unsigned)tm.tm_mon >= 12 ||
-+ tm.tm_mday < 1 || tm.tm_mday > (days_in_mo[tm.tm_mon] +
-+ (tm.tm_mon == 1 && is_leap(tm.tm_year))) ||
-+ (unsigned)tm.tm_hour >= 24 ||
-+ (unsigned)tm.tm_min >= 60 ||
-+ (unsigned)tm.tm_sec >= 60)
-+ return -EINVAL;
-+ RCNR = mktime ( tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
-+ tm.tm_hour, tm.tm_min, tm.tm_sec);
-+ return 0;
-+ case RTC_IRQP_READ:
-+ return put_user(rtc_freq, (unsigned long *)arg);
-+ case RTC_IRQP_SET:
-+ if (arg < 1 || arg > TIMER_FREQ)
-+ return -EINVAL;
-+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-+ return -EACCES;
-+ rtc_freq = arg;
-+ return 0;
-+ case RTC_EPOCH_READ:
-+ return put_user (1970, (unsigned long *)arg);
-+ default:
-+ return -EINVAL;
-+ }
-+ return copy_to_user ((void *)arg, &tm, sizeof (tm)) ? -EFAULT : 0;
-+}
-+
-+static struct file_operations rtc_fops = {
-+ owner: THIS_MODULE,
-+ llseek: rtc_llseek,
-+ read: rtc_read,
-+ poll: rtc_poll,
-+ ioctl: rtc_ioctl,
-+ open: rtc_open,
-+ release: rtc_release,
-+ fasync: rtc_fasync,
-+};
-+
-+static struct miscdevice sa1100rtc_miscdev = {
-+ RTC_MINOR,
-+ "rtc",
-+ &rtc_fops
-+};
-+
-+static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ char *p = page;
-+ int len;
-+ struct rtc_time tm;
-+
-+ decodetime (RCNR, &tm);
-+ p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n"
-+ "rtc_date\t: %04d-%02d-%02d\n"
-+ "rtc_epoch\t: %04d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1970);
-+ decodetime (RTAR, &tm);
-+ p += sprintf(p, "alrm_time\t: %02d:%02d:%02d\n"
-+ "alrm_date\t: %04d-%02d-%02d\n",
-+ tm.tm_hour, tm.tm_min, tm.tm_sec,
-+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
-+ p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR);
-+ p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" );
-+ p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no");
-+ p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no");
-+ p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
-+
-+ len = (p - page) - off;
-+ if (len < 0)
-+ len = 0;
-+
-+ *eof = (len <= count) ? 1 : 0;
-+ *start = page + off;
-+
-+ return len;
-+}
-+
-+static int __init rtc_init(void)
-+{
-+ int ret;
-+
-+ misc_register (&sa1100rtc_miscdev);
-+ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
-+ ret = request_irq (IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
-+ if (ret) {
-+ printk (KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTC1Hz);
-+ goto IRQ_RTC1Hz_failed;
-+ }
-+ ret = request_irq (IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
-+ if (ret) {
-+ printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_RTCAlrm);
-+ goto IRQ_RTCAlrm_failed;
-+ }
-+ ret = request_irq (IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", NULL);
-+ if (ret) {
-+ printk(KERN_ERR "rtc: IRQ %d already in use.\n", IRQ_OST1);
-+ goto IRQ_OST1_failed;
-+ }
-+
-+ printk (KERN_INFO "SA1100 Real Time Clock driver v" DRIVER_VERSION "\n");
-+
-+ /*
-+ * According to the manual we should be able to let RTTR be zero
-+ * and then a default diviser for a 32.768KHz clock is used.
-+ * Apparently this doesn't work, at least for my SA1110 rev 5.
-+ * If the clock divider is uninitialized then reset it to the
-+ * default value to get the 1Hz clock.
-+ */
-+ if (RTTR == 0) {
-+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-+ printk (KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
-+ /* The current RTC value probably doesn't make sense either */
-+ RCNR = 0;
-+ }
-+
-+ return 0;
-+
-+IRQ_OST1_failed:
-+ free_irq (IRQ_RTCAlrm, NULL);
-+IRQ_RTCAlrm_failed:
-+ free_irq (IRQ_RTC1Hz, NULL);
-+IRQ_RTC1Hz_failed:
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&sa1100rtc_miscdev);
-+ return ret;
-+}
-+
-+static void __exit rtc_exit(void)
-+{
-+ free_irq (IRQ_OST1, NULL);
-+ free_irq (IRQ_RTCAlrm, NULL);
-+ free_irq (IRQ_RTC1Hz, NULL);
-+ remove_proc_entry ("driver/rtc", NULL);
-+ misc_deregister (&sa1100rtc_miscdev);
-+}
-+
-+module_init(rtc_init);
-+module_exit(rtc_exit);
-+
-+MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
-+MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/char/sa1100_wdt.c
-@@ -0,0 +1,150 @@
-+/*
-+ * Watchdog driver for the SA11x0
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ * Based on SoftDog driver by Alan Cox <alan@redhat.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.
-+ *
-+ * Neither Oleg Drokin nor iXcelerator.com admit liability nor provide
-+ * warranty for any of this software. This material is provided
-+ * "AS-IS" and at no charge.
-+ *
-+ * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
-+ *
-+ * 27/11/2000 Initial release
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/reboot.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+
-+#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
-+
-+static int sa1100_margin = TIMER_MARGIN; /* in seconds */
-+static int sa1100wdt_users;
-+static int pre_margin;
-+#ifdef MODULE
-+MODULE_PARM(sa1100_margin,"i");
-+#endif
-+
-+/*
-+ * Allow only one person to hold it open
-+ */
-+
-+static int sa1100dog_open(struct inode *inode, struct file *file)
-+{
-+ if(test_and_set_bit(1,&sa1100wdt_users))
-+ return -EBUSY;
-+ MOD_INC_USE_COUNT;
-+ /* Activate SA1100 Watchdog timer */
-+ pre_margin=3686400 * sa1100_margin;
-+ OSMR3 = OSCR + pre_margin;
-+ OSSR = OSSR_M3;
-+ OWER = OWER_WME;
-+ OIER |= OIER_E3;
-+ return 0;
-+}
-+
-+static int sa1100dog_release(struct inode *inode, struct file *file)
-+{
-+ /*
-+ * Shut off the timer.
-+ * Lock it in if it's a module and we defined ...NOWAYOUT
-+ */
-+ OSMR3 = OSCR + pre_margin;
-+#ifndef CONFIG_WATCHDOG_NOWAYOUT
-+ OIER &= ~OIER_E3;
-+#endif
-+ sa1100wdt_users = 0;
-+ MOD_DEC_USE_COUNT;
-+ return 0;
-+}
-+
-+static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-+{
-+ /* Can't seek (pwrite) on this device */
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+
-+ /* Refresh OSMR3 timer. */
-+ if(len) {
-+ OSMR3 = OSCR + pre_margin;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static int sa1100dog_ioctl(struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ static struct watchdog_info ident = {
-+ identity: "SA1100 Watchdog",
-+ };
-+
-+ switch(cmd){
-+ default:
-+ return -ENOIOCTLCMD;
-+ case WDIOC_GETSUPPORT:
-+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
-+ case WDIOC_GETSTATUS:
-+ return put_user(0,(int *)arg);
-+ case WDIOC_GETBOOTSTATUS:
-+ return put_user((RCSR & RCSR_WDR) ? WDIOF_CARDRESET : 0, (int *)arg);
-+ case WDIOC_KEEPALIVE:
-+ OSMR3 = OSCR + pre_margin;
-+ return 0;
-+ }
-+}
-+
-+static struct file_operations sa1100dog_fops=
-+{
-+ owner: THIS_MODULE,
-+ write: sa1100dog_write,
-+ ioctl: sa1100dog_ioctl,
-+ open: sa1100dog_open,
-+ release: sa1100dog_release,
-+};
-+
-+static struct miscdevice sa1100dog_miscdev=
-+{
-+ WATCHDOG_MINOR,
-+ "SA1100 watchdog",
-+ &sa1100dog_fops
-+};
-+
-+static int __init sa1100dog_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register(&sa1100dog_miscdev);
-+
-+ if (ret)
-+ return ret;
-+
-+ printk("SA1100 Watchdog Timer: timer margin %d sec\n", sa1100_margin);
-+
-+ return 0;
-+}
-+
-+static void __exit sa1100dog_exit(void)
-+{
-+ misc_deregister(&sa1100dog_miscdev);
-+}
-+
-+module_init(sa1100dog_init);
-+module_exit(sa1100dog_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/char/sa1111_keyb.c
-@@ -0,0 +1,1153 @@
-+/*
-+ * SA1111 PS/2 keyboard/mouse driver
-+ *
-+ * 2000 by VASARA RESEARCH INC.
-+ *
-+ * Changelog:
-+ * Jun.xx,2000: Kunihiko IMAI <imai@vasara.co.jp>
-+ * Port to 2.4.0test1-ac19-rmk1-np1
-+ * Apr.17,2000: Takafumi Kawana <kawana@pro.or.jp>
-+ * Internal Release for XP860
-+ *
-+ *
-+ * This driver is based on linux/drivers/char/pc_keyb.c
-+ * Original declaration follows:
-+
-+ *
-+ * linux/drivers/char/pc_keyb.c
-+ *
-+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
-+ * See keyboard.c for the whole history.
-+ *
-+ * Major cleanup by Martin Mares, May 1997
-+ *
-+ * Combined the keyboard and PS/2 mouse handling into one file,
-+ * because they share the same hardware.
-+ * Johan Myreen <jem@iki.fi> 1998-10-08.
-+ *
-+ * Code fixes to handle mouse ACKs properly.
-+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/spinlock.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/mm.h>
-+#include <linux/signal.h>
-+#include <linux/init.h>
-+#include <linux/kbd_ll.h>
-+#include <linux/delay.h>
-+#include <linux/random.h>
-+#include <linux/poll.h>
-+#include <linux/miscdevice.h>
-+#include <linux/slab.h>
-+#include <linux/kbd_kern.h>
-+#include <linux/ioport.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/bitops.h>
-+#include <asm/uaccess.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+
-+#include <asm/io.h>
-+
-+/* Some configuration switches are present in the include file... */
-+
-+#include <linux/pc_keyb.h>
-+#include <asm/keyboard.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#define KBD_STAT_RXB (1<<4)
-+#define KBD_STAT_RXF (1<<5)
-+#define KBD_STAT_TXB (1<<6)
-+#define KBD_STAT_TXE (1<<7)
-+#define KBD_STAT_STP (1<<8)
-+
-+#define MSE_STAT_RXB (1<<4)
-+#define MSE_STAT_RXF (1<<5)
-+#define MSE_STAT_TXB (1<<6)
-+#define MSE_STAT_TXE (1<<7)
-+#define MSE_STAT_STP (1<<8)
-+
-+/* Simple translation table for the SysRq keys */
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+unsigned char sa1111_sysrq_xlate[128] = "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
-+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
-+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
-+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
-+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
-+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-+ "\r\000/"; /* 0x60 - 0x6f */
-+#endif
-+
-+// static void kbd_write_command_w(int data);
-+static void kbd_write_output_w(int data);
-+
-+spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
-+static void handle_kbd_event(void);
-+
-+/* used only by send_data - set by keyboard_interrupt */
-+static volatile unsigned char reply_expected = 0;
-+static volatile unsigned char acknowledge = 0;
-+static volatile unsigned char resend = 0;
-+
-+
-+#if defined CONFIG_PSMOUSE
-+/*
-+ * PS/2 Auxiliary Device
-+ */
-+
-+static int __init psaux_init(void);
-+
-+static struct aux_queue *queue; /* Mouse data buffer. */
-+static int aux_count = 0;
-+/* used when we send commands to the mouse that expect an ACK. */
-+static unsigned char mouse_reply_expected = 0;
-+
-+#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
-+#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
-+
-+#define MAX_RETRIES 60 /* some aux operations take long time */
-+#endif /* CONFIG_PSMOUSE */
-+
-+/*
-+ * Wait for keyboard controller input buffer to drain.
-+ *
-+ * Don't use 'jiffies' so that we don't depend on
-+ * interrupts..
-+ *
-+ * Quote from PS/2 System Reference Manual:
-+ *
-+ * "Address hex 0060 and address hex 0064 should be written only when
-+ * the input-buffer-full bit and output-buffer-full bit in the
-+ * Controller Status register are set 0."
-+ */
-+
-+static void kb_wait(void)
-+{
-+ unsigned long timeout = KBC_TIMEOUT;
-+
-+ do {
-+ /*
-+ * "handle_kbd_event()" will handle any incoming events
-+ * while we wait - keypresses or mouse movement.
-+ */
-+ handle_kbd_event();
-+ if (KBDSTAT & KBD_STAT_TXE)
-+ return;
-+ mdelay(1);
-+ timeout--;
-+ }
-+ while (timeout);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING "Keyboard timed out[1]\n");
-+#endif
-+}
-+
-+/*
-+ * Translation of escaped scancodes to keycodes.
-+ * This is now user-settable.
-+ * The keycodes 1-88,96-111,119 are fairly standard, and
-+ * should probably not be changed - changing might confuse X.
-+ * X also interprets scancode 0x5d (KEY_Begin).
-+ *
-+ * For 1-88 keycode equals scancode.
-+ */
-+
-+#define E0_KPENTER 96
-+#define E0_RCTRL 97
-+#define E0_KPSLASH 98
-+#define E0_PRSCR 99
-+#define E0_RALT 100
-+#define E0_BREAK 101 /* (control-pause) */
-+#define E0_HOME 102
-+#define E0_UP 103
-+#define E0_PGUP 104
-+#define E0_LEFT 105
-+#define E0_RIGHT 106
-+#define E0_END 107
-+#define E0_DOWN 108
-+#define E0_PGDN 109
-+#define E0_INS 110
-+#define E0_DEL 111
-+
-+/* for USB 106 keyboard */
-+#define E0_YEN 124
-+#define E0_BACKSLASH 89
-+
-+
-+#define E1_PAUSE 119
-+
-+/*
-+ * The keycodes below are randomly located in 89-95,112-118,120-127.
-+ * They could be thrown away (and all occurrences below replaced by 0),
-+ * but that would force many users to use the `setkeycodes' utility, where
-+ * they needed not before. It does not matter that there are duplicates, as
-+ * long as no duplication occurs for any single keyboard.
-+ */
-+#define SC_LIM 89
-+
-+#define FOCUS_PF1 85 /* actual code! */
-+#define FOCUS_PF2 89
-+#define FOCUS_PF3 90
-+#define FOCUS_PF4 91
-+#define FOCUS_PF5 92
-+#define FOCUS_PF6 93
-+#define FOCUS_PF7 94
-+#define FOCUS_PF8 95
-+#define FOCUS_PF9 120
-+#define FOCUS_PF10 121
-+#define FOCUS_PF11 122
-+#define FOCUS_PF12 123
-+
-+#define JAP_86 124
-+/* tfj@olivia.ping.dk:
-+ * The four keys are located over the numeric keypad, and are
-+ * labelled A1-A4. It's an rc930 keyboard, from
-+ * Regnecentralen/RC International, Now ICL.
-+ * Scancodes: 59, 5a, 5b, 5c.
-+ */
-+#define RGN1 124
-+#define RGN2 125
-+#define RGN3 126
-+#define RGN4 127
-+
-+static unsigned char high_keys[128 - SC_LIM] = {
-+ RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */
-+ 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */
-+ FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */
-+ FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */
-+};
-+
-+/* BTC */
-+#define E0_MACRO 112
-+/* LK450 */
-+#define E0_F13 113
-+#define E0_F14 114
-+#define E0_HELP 115
-+#define E0_DO 116
-+#define E0_F17 117
-+#define E0_KPMINPLUS 118
-+/*
-+ * My OmniKey generates e0 4c for the "OMNI" key and the
-+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
-+ */
-+#define E0_OK 124
-+/*
-+ * New microsoft keyboard is rumoured to have
-+ * e0 5b (left window button), e0 5c (right window button),
-+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
-+ * [or: Windows_L, Windows_R, TaskMan]
-+ */
-+#define E0_MSLW 125
-+#define E0_MSRW 126
-+#define E0_MSTM 127
-+
-+static unsigned char e0_keys[128] = {
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
-+ 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
-+ 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */
-+ E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */
-+ E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */
-+ E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END, /* 0x48-0x4f */
-+ E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */
-+ 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */
-+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
-+ 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
-+ //0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0, /* 0x70-0x77 */
-+ 0, 0, 0, E0_YEN, 0, 0, 0, 0 /* 0x78-0x7f */
-+};
-+
-+int sa1111_setkeycode(unsigned int scancode, unsigned int keycode)
-+{
-+ if (scancode < SC_LIM || scancode > 255 || keycode > 127)
-+ return -EINVAL;
-+ if (scancode < 128)
-+ high_keys[scancode - SC_LIM] = keycode;
-+ else
-+ e0_keys[scancode - 128] = keycode;
-+ return 0;
-+}
-+
-+int sa1111_getkeycode(unsigned int scancode)
-+{
-+ return
-+ (scancode < SC_LIM || scancode > 255) ? -EINVAL :
-+ (scancode <
-+ 128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];
-+}
-+
-+static int do_acknowledge(unsigned char scancode)
-+{
-+ if (reply_expected) {
-+ /* Unfortunately, we must recognise these codes only if we know they
-+ * are known to be valid (i.e., after sending a command), because there
-+ * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
-+ * keys with such codes :(
-+ */
-+ if (scancode == KBD_REPLY_ACK) {
-+ acknowledge = 1;
-+ reply_expected = 0;
-+ return 0;
-+ } else if (scancode == KBD_REPLY_RESEND) {
-+ resend = 1;
-+ reply_expected = 0;
-+ return 0;
-+ }
-+ /* Should not happen... */
-+#if 0
-+ printk(KERN_DEBUG "keyboard reply expected - got %02x\n",
-+ scancode);
-+#endif
-+ }
-+ return 1;
-+}
-+
-+int
-+sa1111_translate(unsigned char scancode, unsigned char *keycode,
-+ char raw_mode)
-+{
-+ static int prev_scancode = 0;
-+
-+ /* special prefix scancodes.. */
-+ if (scancode == 0xe0 || scancode == 0xe1) {
-+ prev_scancode = scancode;
-+ return 0;
-+ }
-+
-+ /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
-+ if (scancode == 0x00 || scancode == 0xff) {
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+
-+ scancode &= 0x7f;
-+
-+ if (prev_scancode) {
-+ /*
-+ * usually it will be 0xe0, but a Pause key generates
-+ * e1 1d 45 e1 9d c5 when pressed, and nothing when released
-+ */
-+ if (prev_scancode != 0xe0) {
-+ if (prev_scancode == 0xe1 && scancode == 0x1d) {
-+ prev_scancode = 0x100;
-+ return 0;
-+ }
-+ else if (prev_scancode == 0x100
-+ && scancode == 0x45) {
-+ *keycode = E1_PAUSE;
-+ prev_scancode = 0;
-+ } else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO
-+ "keyboard: unknown e1 escape sequence\n");
-+#endif
-+ prev_scancode = 0;
-+ return 0;
-+ }
-+ } else {
-+ prev_scancode = 0;
-+ /*
-+ * The keyboard maintains its own internal caps lock and
-+ * num lock statuses. In caps lock mode E0 AA precedes make
-+ * code and E0 2A follows break code. In num lock mode,
-+ * E0 2A precedes make code and E0 AA follows break code.
-+ * We do our own book-keeping, so we will just ignore these.
-+ */
-+ /*
-+ * For my keyboard there is no caps lock mode, but there are
-+ * both Shift-L and Shift-R modes. The former mode generates
-+ * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
-+ * So, we should also ignore the latter. - aeb@cwi.nl
-+ */
-+ if (scancode == 0x2a || scancode == 0x36)
-+ return 0;
-+
-+ if (e0_keys[scancode])
-+ *keycode = e0_keys[scancode];
-+ else {
-+#ifdef KBD_REPORT_UNKN
-+ if (!raw_mode)
-+ printk(KERN_INFO
-+ "keyboard: unknown scancode e0 %02x\n",
-+ scancode);
-+#endif
-+ return 0;
-+ }
-+ }
-+ } else if (scancode >= SC_LIM) {
-+ /* This happens with the FOCUS 9000 keyboard
-+ Its keys PF1..PF12 are reported to generate
-+ 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
-+ Moreover, unless repeated, they do not generate
-+ key-down events, so we have to zero up_flag below */
-+ /* Also, Japanese 86/106 keyboards are reported to
-+ generate 0x73 and 0x7d for \ - and \ | respectively. */
-+ /* Also, some Brazilian keyboard is reported to produce
-+ 0x73 and 0x7e for \ ? and KP-dot, respectively. */
-+
-+ *keycode = high_keys[scancode - SC_LIM];
-+
-+ if (!*keycode) {
-+ if (!raw_mode) {
-+#ifdef KBD_REPORT_UNKN
-+ printk(KERN_INFO
-+ "keyboard: unrecognized scancode (%02x)"
-+ " - ignored\n", scancode);
-+#endif
-+ }
-+ return 0;
-+ }
-+ } else
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+char sa1111_unexpected_up(unsigned char keycode)
-+{
-+ /* unexpected, but this can happen: maybe this was a key release for a
-+ FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
-+ if (keycode >= SC_LIM || keycode == 85)
-+ return 0;
-+ else
-+ return 0200;
-+}
-+
-+static unsigned char kbd_exists = 1;
-+
-+static inline void handle_keyboard_event(unsigned char scancode)
-+{
-+#ifdef CONFIG_VT
-+ kbd_exists = 1;
-+ if (do_acknowledge(scancode))
-+ handle_scancode(scancode, !(scancode & 0x80));
-+#endif
-+ tasklet_schedule(&keyboard_tasklet);
-+}
-+
-+/*
-+ * This reads the keyboard status port, and does the
-+ * appropriate action.
-+ *
-+ * It requires that we hold the keyboard controller
-+ * spinlock.
-+ */
-+static void handle_kbd_event(void)
-+{
-+ unsigned int status = KBDSTAT;
-+ unsigned int work = 10000;
-+ unsigned char scancode;
-+
-+ while (status & KBD_STAT_RXF) {
-+ while (status & KBD_STAT_RXF) {
-+ scancode = KBDDATA & 0xff;
-+ if (!(status & KBD_STAT_STP))
-+ handle_keyboard_event(scancode);
-+ if (!--work) {
-+ printk(KERN_ERR
-+ "pc_keyb: keyboard controller jammed (0x%02X).\n",
-+ status);
-+ return;
-+ }
-+ status = KBDSTAT;
-+ }
-+ work = 10000;
-+ }
-+
-+ if (status & KBD_STAT_STP)
-+ KBDSTAT = KBD_STAT_STP;
-+}
-+
-+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long flags;
-+
-+#ifdef CONFIG_VT
-+ kbd_pt_regs = regs;
-+#endif
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ handle_kbd_event();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * send_data sends a character to the keyboard and waits
-+ * for an acknowledge, possibly retrying if asked to. Returns
-+ * the success status.
-+ *
-+ * Don't use 'jiffies', so that we don't depend on interrupts
-+ */
-+static int send_data(unsigned char data)
-+{
-+ int retries = 3;
-+
-+ do {
-+ unsigned long timeout = KBD_TIMEOUT;
-+
-+ acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
-+ resend = 0;
-+ reply_expected = 1;
-+ kbd_write_output_w(data);
-+ for (;;) {
-+ if (acknowledge)
-+ return 1;
-+ if (resend)
-+ break;
-+ mdelay(1);
-+ if (!--timeout) {
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING
-+ "keyboard: Timeout - AT keyboard not present?\n");
-+#endif
-+ return 0;
-+ }
-+ }
-+ }
-+ while (retries-- > 0);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING
-+ "keyboard: Too many NACKs -- noisy kbd cable?\n");
-+#endif
-+ return 0;
-+}
-+
-+void sa1111_leds(unsigned char leds)
-+{
-+ if (kbd_exists
-+ && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {
-+ send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */
-+ kbd_exists = 0;
-+ }
-+}
-+
-+#define KBD_NO_DATA (-1) /* No data */
-+#define KBD_BAD_DATA (-2) /* Parity or other error */
-+
-+static int __init kbd_read_data(void)
-+{
-+ int retval = KBD_NO_DATA;
-+ unsigned int status;
-+
-+ status = KBDSTAT;
-+ if (status & KBD_STAT_RXF) {
-+ unsigned char data = KBDDATA;
-+
-+ retval = data;
-+ if (status & KBD_STAT_STP)
-+ retval = KBD_BAD_DATA;
-+ }
-+ return retval;
-+}
-+
-+static void __init kbd_clear_input(void)
-+{
-+ int maxread = 100; /* Random number */
-+
-+ do {
-+ if (kbd_read_data() == KBD_NO_DATA)
-+ break;
-+ }
-+ while (--maxread);
-+}
-+
-+static int __init kbd_wait_for_input(void)
-+{
-+ long timeout = KBD_INIT_TIMEOUT;
-+
-+ do {
-+ int retval = kbd_read_data();
-+ if (retval >= 0)
-+ return retval;
-+ mdelay(1);
-+ }
-+ while (--timeout);
-+ return -1;
-+}
-+
-+#if 0
-+static void kbd_write_command_w(int data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ kb_wait();
-+ kbd_write_command(data);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+#endif
-+
-+static void kbd_write_output_w(int data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ kb_wait();
-+ KBDDATA = data & 0xff;
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Test the keyboard interface. We basically check to make sure that
-+ * we can drive each line to the keyboard independently of each other.
-+ */
-+static int kbdif_test(void)
-+{
-+ int ret = 0;
-+
-+ KBDCR = KBDCR_ENA | KBDCR_FKC;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBD) {
-+ printk("Keyboard interface test failed[1]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ KBDCR = KBDCR_ENA;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != (KBDSTAT_KBC | KBDSTAT_KBD)) {
-+ printk("Keyboard interface test failed[2]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ KBDCR = KBDCR_ENA | KBDCR_FKD;
-+ udelay(2);
-+ if ((KBDSTAT & (KBDSTAT_KBC | KBDSTAT_KBD)) != KBDSTAT_KBC) {
-+ printk("Keyboard interface test failed[3]: %02x\n",
-+ KBDSTAT);
-+ ret = -ENODEV;
-+ }
-+
-+ return ret;
-+}
-+
-+static char *__init initialize_kbd(void)
-+{
-+ int status;
-+
-+ /*
-+ * Test the keyboard interface.
-+ */
-+ kbdif_test();
-+
-+ /*
-+ * Ok, drop the force low bits, and wait a while,
-+ * and clear the stop bit error flag.
-+ */
-+ KBDCR = KBDCR_ENA;
-+ udelay(4);
-+ KBDSTAT = KBD_STAT_STP;
-+
-+ /*
-+ * Ok, we're now ready to talk to the keyboard. Reset
-+ * it, just to make sure we're starting in a sane state.
-+ *
-+ * Set up to try again if the keyboard asks for RESEND.
-+ */
-+ do {
-+ KBDDATA = KBD_CMD_RESET;
-+ status = kbd_wait_for_input();
-+ if (status == KBD_REPLY_ACK)
-+ break;
-+ if (status != KBD_REPLY_RESEND)
-+ return "Keyboard reset failed, no ACK";
-+ } while (1);
-+
-+ if (kbd_wait_for_input() != KBD_REPLY_POR)
-+ return "Keyboard reset failed, no POR";
-+
-+ /*
-+ * Set keyboard controller mode. During this, the keyboard should be
-+ * in the disabled state.
-+ *
-+ * Set up to try again if the keyboard asks for RESEND.
-+ */
-+ do {
-+ kbd_write_output_w(KBD_CMD_DISABLE);
-+ status = kbd_wait_for_input();
-+ if (status == KBD_REPLY_ACK)
-+ break;
-+ if (status != KBD_REPLY_RESEND)
-+ return "Disable keyboard: no ACK";
-+ } while (1);
-+
-+#if 0 /*@@@ */
-+ kbd_write_command_w(KBD_CCMD_WRITE_MODE);
-+ kbd_write_output_w(KBD_MODE_KBD_INT
-+ | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE |
-+ KBD_MODE_KCC);
-+
-+ /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
-+ kbd_write_command_w(KBD_CCMD_READ_MODE);
-+ if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
-+ /*
-+ * If the controller does not support conversion,
-+ * Set the keyboard to scan-code set 1.
-+ */
-+ kbd_write_output_w(0xF0);
-+ kbd_wait_for_input();
-+ kbd_write_output_w(0x01);
-+ kbd_wait_for_input();
-+ }
-+#else
-+ kbd_write_output_w(0xf0);
-+ kbd_wait_for_input();
-+ kbd_write_output_w(0x01);
-+ kbd_wait_for_input();
-+#endif
-+
-+
-+ kbd_write_output_w(KBD_CMD_ENABLE);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Enable keyboard: no ACK";
-+
-+ /*
-+ * Finally, set the typematic rate to maximum.
-+ */
-+ kbd_write_output_w(KBD_CMD_SET_RATE);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Set rate: no ACK";
-+ kbd_write_output_w(0x00);
-+ if (kbd_wait_for_input() != KBD_REPLY_ACK)
-+ return "Set rate: no ACK";
-+
-+ return NULL;
-+}
-+
-+int __init sa1111_kbd_init_hw(void)
-+{
-+ char *msg;
-+ int ret;
-+
-+ if (!request_mem_region(_KBDCR, 512, "keyboard"))
-+ return -EBUSY;
-+
-+ SKPCR |= SKPCR_PTCLKEN;
-+ KBDCLKDIV = 0;
-+ KBDPRECNT = 127;
-+
-+ /* Flush any pending input. */
-+ kbd_clear_input();
-+
-+ msg = initialize_kbd();
-+ if (msg)
-+ printk(KERN_WARNING "initialize_kbd: %s\n", msg);
-+
-+#if defined CONFIG_PSMOUSE
-+ psaux_init();
-+#endif
-+
-+ k_setkeycode = sa1111_setkeycode;
-+ k_getkeycode = sa1111_getkeycode;
-+ k_translate = sa1111_translate;
-+ k_unexpected_up = sa1111_unexpected_up;
-+ k_leds = sa1111_leds;
-+#ifdef CONFIG_MAGIC_SYSRQ
-+ k_sysrq_xlate = sa1111_sysrq_xlate;
-+ k_sysrq_key = 0x54;
-+#endif
-+
-+ /* Ok, finally allocate the IRQ, and off we go.. */
-+ ret = request_irq(IRQ_TPRXINT, keyboard_interrupt, 0, "keyboard", NULL);
-+ if (ret)
-+ release_mem_region(_KBDCR, 512);
-+
-+ return ret;
-+}
-+
-+#if defined CONFIG_PSMOUSE
-+
-+static inline void handle_mouse_event(unsigned char scancode)
-+{
-+ if (mouse_reply_expected) {
-+ if (scancode == AUX_ACK) {
-+ mouse_reply_expected--;
-+ return;
-+ }
-+ mouse_reply_expected = 0;
-+ }
-+
-+ add_mouse_randomness(scancode);
-+ if (aux_count) {
-+ int head = queue->head;
-+
-+ queue->buf[head] = scancode;
-+ head = (head + 1) & (AUX_BUF_SIZE - 1);
-+ if (head != queue->tail) {
-+ queue->head = head;
-+ if (queue->fasync)
-+ kill_fasync(&queue->fasync, SIGIO,
-+ POLL_IN);
-+ wake_up_interruptible(&queue->proc_list);
-+ }
-+ }
-+}
-+
-+static void handle_mse_event(void)
-+{
-+ unsigned int msests = MSESTAT;
-+ unsigned int work = 10000;
-+ unsigned char scancode;
-+
-+ while (msests & MSE_STAT_RXF) {
-+ while (msests & MSE_STAT_RXF) {
-+ scancode = MSEDATA & 0xff;
-+ if (!(msests & MSE_STAT_STP))
-+ handle_mouse_event(scancode);
-+ if (!--work) {
-+ printk(KERN_ERR
-+ "pc_keyb: mouse controller jammed (0x%02X).\n",
-+ msests);
-+ return;
-+ /*XXX*/}
-+ msests = MSESTAT;
-+ }
-+ work = 10000;
-+ }
-+}
-+
-+static void ms_wait(void)
-+{
-+ unsigned long timeout = KBC_TIMEOUT;
-+
-+ do {
-+ /*
-+ * "handle_kbd_event()" will handle any incoming events
-+ * while we wait - keypresses or mouse movement.
-+ */
-+ handle_mse_event();
-+ if (MSESTAT & MSE_STAT_TXE)
-+ return;
-+ mdelay(1);
-+ timeout--;
-+ }
-+ while (timeout);
-+#ifdef KBD_REPORT_TIMEOUTS
-+ printk(KERN_WARNING "Mouse timed out[1]\n");
-+#endif
-+}
-+
-+static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ handle_mse_event();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Check if this is a dual port controller.
-+ */
-+static int __init detect_auxiliary_port(void)
-+{
-+ unsigned long flags;
-+ int loops = 10;
-+ int retval = 0;
-+
-+ /* Check if the BIOS detected a device on the auxiliary port. */
-+ if (aux_device_present == 0xaa)
-+ return 1;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+
-+ /* Put the value 0x5A in the output buffer using the "Write
-+ * Auxiliary Device Output Buffer" command (0xD3). Poll the
-+ * Status Register for a while to see if the value really
-+ * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
-+ * bit is also set to 1 in the Status Register, we assume this
-+ * controller has an Auxiliary Port (a.k.a. Mouse Port).
-+ */
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
-+
-+ SKPCR |= SKPCR_PMCLKEN;
-+
-+ MSECLKDIV = 0;
-+ MSEPRECNT = 127;
-+ MSECR = MSECR_ENA;
-+ mdelay(50);
-+ MSEDATA = 0xf4;
-+ mdelay(50);
-+
-+ do {
-+ unsigned int msests = MSESTAT;
-+
-+ if (msests & MSE_STAT_RXF) {
-+ do {
-+ msests = MSEDATA; /* dummy read */
-+ mdelay(50);
-+ msests = MSESTAT;
-+ }
-+ while (msests & MSE_STAT_RXF);
-+ printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
-+ retval = 1;
-+ break;
-+ }
-+ mdelay(1);
-+ }
-+ while (--loops);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+
-+ return retval;
-+}
-+
-+/*
-+ * Send a byte to the mouse.
-+ */
-+static void aux_write_dev(int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
-+ ms_wait();
-+ MSEDATA = val;
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+/*
-+ * Send a byte to the mouse & handle returned ack
-+ */
-+static void aux_write_ack(int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ // kb_wait();
-+ // kbd_write_command(KBD_CCMD_WRITE_MOUSE);
-+ ms_wait();
-+ MSEDATA = val;
-+ /* we expect an ACK in response. */
-+ mouse_reply_expected++;
-+ ms_wait();
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+}
-+
-+static unsigned char get_from_queue(void)
-+{
-+ unsigned char result;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&kbd_controller_lock, flags);
-+ result = queue->buf[queue->tail];
-+ queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);
-+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
-+ return result;
-+}
-+
-+
-+static inline int queue_empty(void)
-+{
-+ return queue->head == queue->tail;
-+}
-+
-+static int fasync_aux(int fd, struct file *filp, int on)
-+{
-+ int retval;
-+
-+ retval = fasync_helper(fd, filp, on, &queue->fasync);
-+ if (retval < 0)
-+ return retval;
-+ return 0;
-+}
-+
-+
-+/*
-+ * Random magic cookie for the aux device
-+ */
-+#define AUX_DEV ((void *)queue)
-+
-+static int release_aux(struct inode *inode, struct file *file)
-+{
-+ fasync_aux(-1, file, 0);
-+ if (--aux_count)
-+ return 0;
-+ // kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
-+ // kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
-+ aux_write_ack(AUX_DISABLE_DEV); /* Disable aux device */
-+ MSECR &= ~MSECR_ENA;
-+ free_irq(IRQ_MSRXINT, AUX_DEV);
-+ return 0;
-+}
-+
-+/*
-+ * Install interrupt handler.
-+ * Enable auxiliary device.
-+ */
-+
-+static int open_aux(struct inode *inode, struct file *file)
-+{
-+ if (aux_count++) {
-+ return 0;
-+ }
-+ queue->head = queue->tail = 0; /* Flush input queue */
-+ /* Don't enable the mouse controller until we've registered IRQ handler */
-+ if (request_irq(IRQ_MSRXINT, mouse_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
-+ aux_count--;
-+ return -EBUSY;
-+ }
-+ MSECLKDIV = 0;
-+ MSEPRECNT = 127;
-+ MSECR &= ~MSECR_ENA;
-+ mdelay(50);
-+ MSECR = MSECR_ENA;
-+ mdelay(50);
-+ MSEDATA = 0xf4;
-+ mdelay(50);
-+ if (MSESTAT & 0x0100) {
-+ MSESTAT = 0x0100; /* clear IRQ status */
-+ }
-+/* kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); *//* Enable the
-+ auxiliary port on
-+ controller. */
-+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
-+ // kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
-+
-+ // send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
-+
-+ return 0;
-+}
-+
-+/*
-+ * Put bytes from input queue to buffer.
-+ */
-+
-+static ssize_t
-+read_aux(struct file *file, char *buffer, size_t count, loff_t * ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ ssize_t i = count;
-+ unsigned char c;
-+
-+ if (queue_empty()) {
-+ if (file->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+ add_wait_queue(&queue->proc_list, &wait);
-+ repeat:
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (queue_empty() && !signal_pending(current)) {
-+ schedule();
-+ goto repeat;
-+ }
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&queue->proc_list, &wait);
-+ }
-+ while (i > 0 && !queue_empty()) {
-+ c = get_from_queue();
-+ put_user(c, buffer++);
-+ i--;
-+ }
-+ if (count - i) {
-+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-+ return count - i;
-+ }
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+ return 0;
-+}
-+
-+/*
-+ * Write to the aux device.
-+ */
-+
-+static ssize_t
-+write_aux(struct file *file, const char *buffer, size_t count,
-+ loff_t * ppos)
-+{
-+ ssize_t retval = 0;
-+
-+ if (count) {
-+ ssize_t written = 0;
-+
-+ if (count > 32)
-+ count = 32; /* Limit to 32 bytes. */
-+ do {
-+ char c;
-+ get_user(c, buffer++);
-+ aux_write_dev(c);
-+ written++;
-+ }
-+ while (--count);
-+ retval = -EIO;
-+ if (written) {
-+ retval = written;
-+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+static unsigned int aux_poll(struct file *file, poll_table * wait)
-+{
-+ poll_wait(file, &queue->proc_list, wait);
-+ if (!queue_empty())
-+ return POLLIN | POLLRDNORM;
-+ return 0;
-+}
-+
-+struct file_operations psaux_fops = {
-+ read: read_aux,
-+ write: write_aux,
-+ poll: aux_poll,
-+ open: open_aux,
-+ release: release_aux,
-+ fasync: fasync_aux,
-+};
-+
-+/*
-+ * Initialize driver.
-+ */
-+static struct miscdevice psaux_mouse = {
-+ PSMOUSE_MINOR, "psaux", &psaux_fops
-+};
-+
-+
-+static int __init psaux_init(void)
-+{
-+ int ret;
-+
-+ if (!request_mem_region(_MSECR, 512, "psaux"))
-+ return -EBUSY;
-+
-+ if (!detect_auxiliary_port()) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ misc_register(&psaux_mouse);
-+ queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-+ memset(queue, 0, sizeof(*queue));
-+ queue->head = queue->tail = 0;
-+ init_waitqueue_head(&queue->proc_list);
-+
-+#ifdef CONFIG_PSMOUSE
-+ aux_write_ack(AUX_SET_SAMPLE);
-+ aux_write_ack(100); /* 100 samples/sec */
-+ aux_write_ack(AUX_SET_RES);
-+ aux_write_ack(3); /* 8 counts per mm */
-+ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
-+#endif
-+ ret = 0;
-+
-+ out:
-+ if (ret)
-+ release_mem_region(_MSECR, 512);
-+ return ret;
-+}
-+
-+#endif /* CONFIG_PSMOUSE */
---- linux-2.4.27/drivers/char/serial.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/serial.c
-@@ -4527,6 +4527,14 @@
- }
-
- /*
-+ * If there is exactly one port of 8 bytes, use it.
-+ */
-+ if (num_port == 1 && pci_resource_len(dev, first_port) == 8) {
-+ board->flags = first_port;
-+ return 0;
-+ }
-+
-+ /*
- * If there is 1 or 0 iomem regions, and exactly one port, use
- * it.
- */
---- linux-2.4.27/drivers/char/serial_21285.c
-+++ /dev/null
-@@ -1,498 +0,0 @@
--/*
-- * linux/drivers/char/serial_21285.c
-- *
-- * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
-- *
-- * Based on drivers/char/serial.c
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/errno.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/interrupt.h>
--#include <linux/tty.h>
--#include <linux/tty_flip.h>
--#include <linux/serial.h>
--#include <linux/major.h>
--#include <linux/ptrace.h>
--#include <linux/ioport.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/init.h>
--#include <linux/console.h>
--
--#include <asm/io.h>
--#include <asm/irq.h>
--#include <asm/uaccess.h>
--#include <asm/dec21285.h>
--#include <asm/hardware.h>
--
--#define BAUD_BASE (mem_fclk_21285/64)
--
--#define SERIAL_21285_NAME "ttyFB"
--#define SERIAL_21285_MAJOR 204
--#define SERIAL_21285_MINOR 4
--
--#define SERIAL_21285_AUXNAME "cuafb"
--#define SERIAL_21285_AUXMAJOR 205
--#define SERIAL_21285_AUXMINOR 4
--
--static struct tty_driver rs285_driver, callout_driver;
--static int rs285_refcount;
--static struct tty_struct *rs285_table[1];
--
--static struct termios *rs285_termios[1];
--static struct termios *rs285_termios_locked[1];
--
--static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
--static struct tty_struct *rs285_tty;
--static int rs285_use_count;
--
--static int rs285_write_room(struct tty_struct *tty)
--{
-- return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
--}
--
--static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- if (!rs285_tty) {
-- disable_irq(IRQ_CONRX);
-- return;
-- }
-- while (!(*CSR_UARTFLG & 0x10)) {
-- int ch, flag;
-- ch = *CSR_UARTDR;
-- flag = *CSR_RXSTAT;
-- if (flag & 4)
-- tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
-- if (flag & 2)
-- flag = TTY_PARITY;
-- else if (flag & 1)
-- flag = TTY_FRAME;
-- tty_insert_flip_char(rs285_tty, ch, flag);
-- }
-- tty_flip_buffer_push(rs285_tty);
--}
--
--static void rs285_send_xchar(struct tty_struct *tty, char ch)
--{
-- x_char = ch;
-- enable_irq(IRQ_CONTX);
--}
--
--static void rs285_throttle(struct tty_struct *tty)
--{
-- if (I_IXOFF(tty))
-- rs285_send_xchar(tty, STOP_CHAR(tty));
--}
--
--static void rs285_unthrottle(struct tty_struct *tty)
--{
-- if (I_IXOFF(tty)) {
-- if (x_char)
-- x_char = 0;
-- else
-- rs285_send_xchar(tty, START_CHAR(tty));
-- }
--}
--
--static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- while (!(*CSR_UARTFLG & 0x20)) {
-- if (x_char) {
-- *CSR_UARTDR = x_char;
-- x_char = 0;
-- continue;
-- }
-- if (putp == getp) {
-- disable_irq(IRQ_CONTX);
-- break;
-- }
-- *CSR_UARTDR = *getp;
-- if (++getp >= wbuf + sizeof(wbuf))
-- getp = wbuf;
-- }
-- if (rs285_tty)
-- wake_up_interruptible(&rs285_tty->write_wait);
--}
--
--static inline int rs285_xmit(int ch)
--{
-- if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
-- return 0;
-- *putp = ch;
-- if (++putp >= wbuf + sizeof(wbuf))
-- putp = wbuf;
-- enable_irq(IRQ_CONTX);
-- return 1;
--}
--
--static int rs285_write(struct tty_struct *tty, int from_user,
-- const u_char * buf, int count)
--{
-- int i;
--
-- if (from_user && verify_area(VERIFY_READ, buf, count))
-- return -EINVAL;
--
-- for (i = 0; i < count; i++) {
-- char ch;
-- if (from_user)
-- __get_user(ch, buf + i);
-- else
-- ch = buf[i];
-- if (!rs285_xmit(ch))
-- break;
-- }
-- return i;
--}
--
--static void rs285_put_char(struct tty_struct *tty, u_char ch)
--{
-- rs285_xmit(ch);
--}
--
--static int rs285_chars_in_buffer(struct tty_struct *tty)
--{
-- return sizeof(wbuf) - rs285_write_room(tty);
--}
--
--static void rs285_flush_buffer(struct tty_struct *tty)
--{
-- disable_irq(IRQ_CONTX);
-- putp = getp = wbuf;
-- if (x_char)
-- enable_irq(IRQ_CONTX);
--}
--
--static inline void rs285_set_cflag(int cflag)
--{
-- int h_lcr, baud, quot;
--
-- switch (cflag & CSIZE) {
-- case CS5:
-- h_lcr = 0x10;
-- break;
-- case CS6:
-- h_lcr = 0x30;
-- break;
-- case CS7:
-- h_lcr = 0x50;
-- break;
-- default: /* CS8 */
-- h_lcr = 0x70;
-- break;
--
-- }
-- if (cflag & CSTOPB)
-- h_lcr |= 0x08;
-- if (cflag & PARENB)
-- h_lcr |= 0x02;
-- if (!(cflag & PARODD))
-- h_lcr |= 0x04;
--
-- switch (cflag & CBAUD) {
-- case B200: baud = 200; break;
-- case B300: baud = 300; break;
-- case B1200: baud = 1200; break;
-- case B1800: baud = 1800; break;
-- case B2400: baud = 2400; break;
-- case B4800: baud = 4800; break;
-- default:
-- case B9600: baud = 9600; break;
-- case B19200: baud = 19200; break;
-- case B38400: baud = 38400; break;
-- case B57600: baud = 57600; break;
-- case B115200: baud = 115200; break;
-- }
--
-- /*
-- * The documented expression for selecting the divisor is:
-- * BAUD_BASE / baud - 1
-- * However, typically BAUD_BASE is not divisible by baud, so
-- * we want to select the divisor that gives us the minimum
-- * error. Therefore, we want:
-- * int(BAUD_BASE / baud - 0.5) ->
-- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
-- * int((BAUD_BASE - (baud >> 1)) / baud)
-- */
-- quot = (BAUD_BASE - (baud >> 1)) / baud;
--
-- *CSR_UARTCON = 0;
-- *CSR_L_UBRLCR = quot & 0xff;
-- *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
-- *CSR_H_UBRLCR = h_lcr;
-- *CSR_UARTCON = 1;
--}
--
--static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
--{
-- if (old && tty->termios->c_cflag == old->c_cflag)
-- return;
-- rs285_set_cflag(tty->termios->c_cflag);
--}
--
--
--static void rs285_stop(struct tty_struct *tty)
--{
-- disable_irq(IRQ_CONTX);
--}
--
--static void rs285_start(struct tty_struct *tty)
--{
-- enable_irq(IRQ_CONTX);
--}
--
--static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
--{
-- int orig_jiffies = jiffies;
-- while (*CSR_UARTFLG & 8) {
-- current->state = TASK_INTERRUPTIBLE;
-- schedule_timeout(1);
-- if (signal_pending(current))
-- break;
-- if (timeout && time_after(jiffies, orig_jiffies + timeout))
-- break;
-- }
-- current->state = TASK_RUNNING;
--}
--
--static int rs285_open(struct tty_struct *tty, struct file *filp)
--{
-- int line;
--
-- MOD_INC_USE_COUNT;
-- line = MINOR(tty->device) - tty->driver.minor_start;
-- if (line) {
-- MOD_DEC_USE_COUNT;
-- return -ENODEV;
-- }
--
-- tty->driver_data = NULL;
-- if (!rs285_tty)
-- rs285_tty = tty;
--
-- enable_irq(IRQ_CONRX);
-- rs285_use_count++;
-- return 0;
--}
--
--static void rs285_close(struct tty_struct *tty, struct file *filp)
--{
-- if (!--rs285_use_count) {
-- rs285_wait_until_sent(tty, 0);
-- disable_irq(IRQ_CONRX);
-- disable_irq(IRQ_CONTX);
-- rs285_tty = NULL;
-- }
-- MOD_DEC_USE_COUNT;
--}
--
--static int __init rs285_init(void)
--{
-- int baud = B9600;
--
-- if (machine_is_personal_server())
-- baud = B57600;
--
-- rs285_driver.magic = TTY_DRIVER_MAGIC;
-- rs285_driver.driver_name = "serial_21285";
-- rs285_driver.name = SERIAL_21285_NAME;
-- rs285_driver.major = SERIAL_21285_MAJOR;
-- rs285_driver.minor_start = SERIAL_21285_MINOR;
-- rs285_driver.num = 1;
-- rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
-- rs285_driver.subtype = SERIAL_TYPE_NORMAL;
-- rs285_driver.init_termios = tty_std_termios;
-- rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
-- rs285_driver.flags = TTY_DRIVER_REAL_RAW;
-- rs285_driver.refcount = &rs285_refcount;
-- rs285_driver.table = rs285_table;
-- rs285_driver.termios = rs285_termios;
-- rs285_driver.termios_locked = rs285_termios_locked;
--
-- rs285_driver.open = rs285_open;
-- rs285_driver.close = rs285_close;
-- rs285_driver.write = rs285_write;
-- rs285_driver.put_char = rs285_put_char;
-- rs285_driver.write_room = rs285_write_room;
-- rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
-- rs285_driver.flush_buffer = rs285_flush_buffer;
-- rs285_driver.throttle = rs285_throttle;
-- rs285_driver.unthrottle = rs285_unthrottle;
-- rs285_driver.send_xchar = rs285_send_xchar;
-- rs285_driver.set_termios = rs285_set_termios;
-- rs285_driver.stop = rs285_stop;
-- rs285_driver.start = rs285_start;
-- rs285_driver.wait_until_sent = rs285_wait_until_sent;
--
-- callout_driver = rs285_driver;
-- callout_driver.name = SERIAL_21285_AUXNAME;
-- callout_driver.major = SERIAL_21285_AUXMAJOR;
-- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
--
-- if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
-- panic("Couldn't get rx irq for rs285");
--
-- if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
-- panic("Couldn't get tx irq for rs285");
--
-- if (tty_register_driver(&rs285_driver))
-- printk(KERN_ERR "Couldn't register 21285 serial driver\n");
-- if (tty_register_driver(&callout_driver))
-- printk(KERN_ERR "Couldn't register 21285 callout driver\n");
--
-- return 0;
--}
--
--static void __exit rs285_fini(void)
--{
-- unsigned long flags;
-- int ret;
--
-- save_flags(flags);
-- cli();
-- ret = tty_unregister_driver(&callout_driver);
-- if (ret)
-- printk(KERN_ERR "Unable to unregister 21285 callout driver "
-- "(%d)\n", ret);
-- ret = tty_unregister_driver(&rs285_driver);
-- if (ret)
-- printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
-- ret);
-- free_irq(IRQ_CONTX, NULL);
-- free_irq(IRQ_CONRX, NULL);
-- restore_flags(flags);
--}
--
--module_init(rs285_init);
--module_exit(rs285_fini);
--
--#ifdef CONFIG_SERIAL_21285_CONSOLE
--/************** console driver *****************/
--
--static void rs285_console_write(struct console *co, const char *s, u_int count)
--{
-- int i;
--
-- disable_irq(IRQ_CONTX);
-- for (i = 0; i < count; i++) {
-- while (*CSR_UARTFLG & 0x20);
-- *CSR_UARTDR = s[i];
-- if (s[i] == '\n') {
-- while (*CSR_UARTFLG & 0x20);
-- *CSR_UARTDR = '\r';
-- }
-- }
-- enable_irq(IRQ_CONTX);
--}
--
--static kdev_t rs285_console_device(struct console *c)
--{
-- return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
--}
--
--static int __init rs285_console_setup(struct console *co, char *options)
--{
-- int baud = 9600;
-- int bits = 8;
-- int parity = 'n';
-- int cflag = CREAD | HUPCL | CLOCAL;
--
-- if (machine_is_personal_server())
-- baud = 57600;
--
-- if (options) {
-- char *s = options;
-- baud = simple_strtoul(options, NULL, 10);
-- while (*s >= '0' && *s <= '9')
-- s++;
-- if (*s)
-- parity = *s++;
-- if (*s)
-- bits = *s - '0';
-- }
--
-- /*
-- * Now construct a cflag setting.
-- */
-- switch (baud) {
-- case 1200:
-- cflag |= B1200;
-- break;
-- case 2400:
-- cflag |= B2400;
-- break;
-- case 4800:
-- cflag |= B4800;
-- break;
-- case 9600:
-- cflag |= B9600;
-- break;
-- case 19200:
-- cflag |= B19200;
-- break;
-- case 38400:
-- cflag |= B38400;
-- break;
-- case 57600:
-- cflag |= B57600;
-- break;
-- case 115200:
-- cflag |= B115200;
-- break;
-- default:
-- cflag |= B9600;
-- break;
-- }
-- switch (bits) {
-- case 7:
-- cflag |= CS7;
-- break;
-- default:
-- cflag |= CS8;
-- break;
-- }
-- switch (parity) {
-- case 'o':
-- case 'O':
-- cflag |= PARODD;
-- break;
-- case 'e':
-- case 'E':
-- cflag |= PARENB;
-- break;
-- }
-- co->cflag = cflag;
-- rs285_set_cflag(cflag);
-- rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
-- if (options)
-- rs285_console_write(NULL, options, strlen(options));
-- else
-- rs285_console_write(NULL, "no options", 10);
-- rs285_console_write(NULL, "\n", 1);
--
-- return 0;
--}
--
--static struct console rs285_cons =
--{
-- name: SERIAL_21285_NAME,
-- write: rs285_console_write,
-- device: rs285_console_device,
-- setup: rs285_console_setup,
-- flags: CON_PRINTBUFFER,
-- index: -1,
--};
--
--void __init rs285_console_init(void)
--{
-- register_console(&rs285_cons);
--}
--
--#endif /* CONFIG_SERIAL_21285_CONSOLE */
--
--MODULE_LICENSE("GPL");
--EXPORT_NO_SYMBOLS;
---- linux-2.4.27/drivers/char/serial_amba.c
-+++ /dev/null
-@@ -1,2015 +0,0 @@
--/*
-- * linux/drivers/char/serial_amba.c
-- *
-- * Driver for AMBA serial ports
-- *
-- * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-- *
-- * Copyright 1999 ARM Limited
-- * Copyright (C) 2000 Deep Blue Solutions Ltd.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- *
-- *
-- * This is a generic driver for ARM AMBA-type serial ports. They
-- * have a lot of 16550-like features, but are not register compatable.
-- * Note that although they do have CTS, DCD and DSR inputs, they do
-- * not have an RI input, nor do they have DTR or RTS outputs. If
-- * required, these have to be supplied via some other means (eg, GPIO)
-- * and hooked into this driver.
-- *
-- * This could very easily become a generic serial driver for dumb UARTs
-- * (eg, {82,16x}50, 21285, SA1100).
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/errno.h>
--#include <linux/signal.h>
--#include <linux/sched.h>
--#include <linux/interrupt.h>
--#include <linux/tty.h>
--#include <linux/tty_flip.h>
--#include <linux/major.h>
--#include <linux/string.h>
--#include <linux/fcntl.h>
--#include <linux/ptrace.h>
--#include <linux/ioport.h>
--#include <linux/mm.h>
--#include <linux/slab.h>
--#include <linux/init.h>
--#include <linux/circ_buf.h>
--#include <linux/serial.h>
--#include <linux/console.h>
--#include <linux/sysrq.h>
--
--#include <asm/system.h>
--#include <asm/io.h>
--#include <asm/irq.h>
--#include <asm/uaccess.h>
--#include <asm/bitops.h>
--
--#include <asm/hardware/serial_amba.h>
--
--#define SERIAL_AMBA_NAME "ttyAM"
--#define SERIAL_AMBA_MAJOR 204
--#define SERIAL_AMBA_MINOR 16
--#define SERIAL_AMBA_NR 2
--
--#define CALLOUT_AMBA_NAME "cuaam"
--#define CALLOUT_AMBA_MAJOR 205
--#define CALLOUT_AMBA_MINOR 16
--#define CALLOUT_AMBA_NR SERIAL_AMBA_NR
--
--#ifndef TRUE
--#define TRUE 1
--#endif
--#ifndef FALSE
--#define FALSE 0
--#endif
--
--#define DEBUG 0
--#define DEBUG_LEDS 0
--
--#if DEBUG_LEDS
--extern int get_leds(void);
--extern int set_leds(int);
--#endif
--
--/*
-- * Access routines for the AMBA UARTs
-- */
--#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR)
--#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR)
--#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR)
--#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c))
--#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR)
--#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR)
--#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c))
--#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L)
--#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c))
--#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M)
--#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c))
--#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H)
--#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c))
--#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
--#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
--#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
--
--#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE)
--#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS)
--
--/*
-- * Things needed by tty driver
-- */
--static struct tty_driver ambanormal_driver, ambacallout_driver;
--static int ambauart_refcount;
--static struct tty_struct *ambauart_table[SERIAL_AMBA_NR];
--static struct termios *ambauart_termios[SERIAL_AMBA_NR];
--static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR];
--
--#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
--#define SUPPORT_SYSRQ
--#endif
--
--/*
-- * Things needed internally to this driver
-- */
--
--/*
-- * tmp_buf is used as a temporary buffer by serial_write. We need to
-- * lock it in case the copy_from_user blocks while swapping in a page,
-- * and some other program tries to do a serial write at the same time.
-- * Since the lock will only come under contention when the system is
-- * swapping and available memory is low, it makes sense to share one
-- * buffer across all the serial ports, since it significantly saves
-- * memory if large numbers of serial ports are open.
-- */
--static u_char *tmp_buf;
--static DECLARE_MUTEX(tmp_buf_sem);
--
--#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
--
--/* number of characters left in xmit buffer before we ask for more */
--#define WAKEUP_CHARS 256
--#define AMBA_ISR_PASS_LIMIT 256
--
--#define EVT_WRITE_WAKEUP 0
--
--struct amba_icount {
-- __u32 cts;
-- __u32 dsr;
-- __u32 rng;
-- __u32 dcd;
-- __u32 rx;
-- __u32 tx;
-- __u32 frame;
-- __u32 overrun;
-- __u32 parity;
-- __u32 brk;
-- __u32 buf_overrun;
--};
--
--/*
-- * Static information about the port
-- */
--struct amba_port {
-- unsigned int uart_base;
-- unsigned int irq;
-- unsigned int uartclk;
-- unsigned int fifosize;
-- unsigned int tiocm_support;
-- void (*set_mctrl)(struct amba_port *, u_int mctrl);
--};
--
--/*
-- * This is the state information which is persistent across opens
-- */
--struct amba_state {
-- struct amba_icount icount;
-- unsigned int line;
-- unsigned int close_delay;
-- unsigned int closing_wait;
-- unsigned int custom_divisor;
-- unsigned int flags;
-- struct termios normal_termios;
-- struct termios callout_termios;
--
-- int count;
-- struct amba_info *info;
--};
--
--#define AMBA_XMIT_SIZE 1024
--/*
-- * This is the state information which is only valid when the port is open.
-- */
--struct amba_info {
-- struct amba_port *port;
-- struct amba_state *state;
-- struct tty_struct *tty;
-- unsigned char x_char;
-- unsigned char old_status;
-- unsigned char read_status_mask;
-- unsigned char ignore_status_mask;
-- struct circ_buf xmit;
-- unsigned int flags;
--#ifdef SUPPORT_SYSRQ
-- unsigned long sysrq;
--#endif
--
-- unsigned int event;
-- unsigned int timeout;
-- unsigned int lcr_h;
-- unsigned int mctrl;
-- int blocked_open;
-- pid_t session;
-- pid_t pgrp;
--
-- struct tasklet_struct tlet;
--
-- wait_queue_head_t open_wait;
-- wait_queue_head_t close_wait;
-- wait_queue_head_t delta_msr_wait;
--};
--
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
--static struct console ambauart_cons;
--#endif
--static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios);
--static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout);
--
--#if 1 //def CONFIG_SERIAL_INTEGRATOR
--static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl)
--{
--}
--
--static struct amba_port amba_ports[SERIAL_AMBA_NR] = {
-- {
-- uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE),
-- irq: IRQ_UARTINT0,
-- uartclk: 14745600,
-- fifosize: 8,
-- set_mctrl: amba_set_mctrl_null,
-- },
-- {
-- uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE),
-- irq: IRQ_UARTINT1,
-- uartclk: 14745600,
-- fifosize: 8,
-- set_mctrl: amba_set_mctrl_null,
-- }
--};
--#endif
--
--static struct amba_state amba_state[SERIAL_AMBA_NR];
--
--static void ambauart_enable_rx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_disable_rx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_enable_tx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr |= AMBA_UARTCR_TIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_disable_tx_interrupt(struct amba_info *info)
--{
-- unsigned int cr;
--
-- cr = UART_GET_CR(info->port);
-- cr &= ~AMBA_UARTCR_TIE;
-- UART_PUT_CR(info->port, cr);
--}
--
--static void ambauart_stop(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- ambauart_disable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--static void ambauart_start(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- if (info->xmit.head != info->xmit.tail
-- && info->xmit.buf)
-- ambauart_enable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--
--/*
-- * This routine is used by the interrupt handler to schedule
-- * processing in the software interrupt portion of the driver.
-- */
--static void ambauart_event(struct amba_info *info, int event)
--{
-- info->event |= 1 << event;
-- tasklet_schedule(&info->tlet);
--}
--
--static void
--#ifdef SUPPORT_SYSRQ
--ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs)
--#else
--ambauart_rx_chars(struct amba_info *info)
--#endif
--{
-- struct tty_struct *tty = info->tty;
-- unsigned int status, ch, rsr, flg, ignored = 0;
-- struct amba_icount *icount = &info->state->icount;
-- struct amba_port *port = info->port;
--
-- status = UART_GET_FR(port);
-- while (UART_RX_DATA(status)) {
-- ch = UART_GET_CHAR(port);
--
-- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-- goto ignore_char;
-- icount->rx++;
--
-- flg = TTY_NORMAL;
--
-- /*
-- * Note that the error handling code is
-- * out of the main execution path
-- */
-- rsr = UART_GET_RSR(port);
-- if (rsr & AMBA_UARTRSR_ANY)
-- goto handle_error;
--#ifdef SUPPORT_SYSRQ
-- if (info->sysrq) {
-- if (ch && time_before(jiffies, info->sysrq)) {
-- handle_sysrq(ch, regs, NULL, NULL);
-- info->sysrq = 0;
-- goto ignore_char;
-- }
-- info->sysrq = 0;
-- }
--#endif
-- error_return:
-- *tty->flip.flag_buf_ptr++ = flg;
-- *tty->flip.char_buf_ptr++ = ch;
-- tty->flip.count++;
-- ignore_char:
-- status = UART_GET_FR(port);
-- }
--out:
-- tty_flip_buffer_push(tty);
-- return;
--
--handle_error:
-- if (rsr & AMBA_UARTRSR_BE) {
-- rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
-- icount->brk++;
--
--#ifdef SUPPORT_SYSRQ
-- if (info->state->line == ambauart_cons.index) {
-- if (!info->sysrq) {
-- info->sysrq = jiffies + HZ*5;
-- goto ignore_char;
-- }
-- }
--#endif
-- } else if (rsr & AMBA_UARTRSR_PE)
-- icount->parity++;
-- else if (rsr & AMBA_UARTRSR_FE)
-- icount->frame++;
-- if (rsr & AMBA_UARTRSR_OE)
-- icount->overrun++;
--
-- if (rsr & info->ignore_status_mask) {
-- if (++ignored > 100)
-- goto out;
-- goto ignore_char;
-- }
-- rsr &= info->read_status_mask;
--
-- if (rsr & AMBA_UARTRSR_BE)
-- flg = TTY_BREAK;
-- else if (rsr & AMBA_UARTRSR_PE)
-- flg = TTY_PARITY;
-- else if (rsr & AMBA_UARTRSR_FE)
-- flg = TTY_FRAME;
--
-- if (rsr & AMBA_UARTRSR_OE) {
-- /*
-- * CHECK: does overrun affect the current character?
-- * ASSUMPTION: it does not.
-- */
-- *tty->flip.flag_buf_ptr++ = flg;
-- *tty->flip.char_buf_ptr++ = ch;
-- tty->flip.count++;
-- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-- goto ignore_char;
-- ch = 0;
-- flg = TTY_OVERRUN;
-- }
--#ifdef SUPPORT_SYSRQ
-- info->sysrq = 0;
--#endif
-- goto error_return;
--}
--
--static void ambauart_tx_chars(struct amba_info *info)
--{
-- struct amba_port *port = info->port;
-- int count;
--
-- if (info->x_char) {
-- UART_PUT_CHAR(port, info->x_char);
-- info->state->icount.tx++;
-- info->x_char = 0;
-- return;
-- }
-- if (info->xmit.head == info->xmit.tail
-- || info->tty->stopped
-- || info->tty->hw_stopped) {
-- ambauart_disable_tx_interrupt(info);
-- return;
-- }
--
-- count = port->fifosize;
-- do {
-- UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-- info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1);
-- info->state->icount.tx++;
-- if (info->xmit.head == info->xmit.tail)
-- break;
-- } while (--count > 0);
--
-- if (CIRC_CNT(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE) < WAKEUP_CHARS)
-- ambauart_event(info, EVT_WRITE_WAKEUP);
--
-- if (info->xmit.head == info->xmit.tail) {
-- ambauart_disable_tx_interrupt(info);
-- }
--}
--
--static void ambauart_modem_status(struct amba_info *info)
--{
-- unsigned int status, delta;
-- struct amba_icount *icount = &info->state->icount;
--
-- status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
--
-- delta = status ^ info->old_status;
-- info->old_status = status;
--
-- if (!delta)
-- return;
--
-- if (delta & AMBA_UARTFR_DCD) {
-- icount->dcd++;
--#ifdef CONFIG_HARD_PPS
-- if ((info->flags & ASYNC_HARDPPS_CD) &&
-- (status & AMBA_UARTFR_DCD)
-- hardpps();
--#endif
-- if (info->flags & ASYNC_CHECK_CD) {
-- if (status & AMBA_UARTFR_DCD)
-- wake_up_interruptible(&info->open_wait);
-- else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_CALLOUT_NOHUP))) {
-- if (info->tty)
-- tty_hangup(info->tty);
-- }
-- }
-- }
--
-- if (delta & AMBA_UARTFR_DSR)
-- icount->dsr++;
--
-- if (delta & AMBA_UARTFR_CTS) {
-- icount->cts++;
--
-- if (info->flags & ASYNC_CTS_FLOW) {
-- status &= AMBA_UARTFR_CTS;
--
-- if (info->tty->hw_stopped) {
-- if (status) {
-- info->tty->hw_stopped = 0;
-- ambauart_enable_tx_interrupt(info);
-- ambauart_event(info, EVT_WRITE_WAKEUP);
-- }
-- } else {
-- if (!status) {
-- info->tty->hw_stopped = 1;
-- ambauart_disable_tx_interrupt(info);
-- }
-- }
-- }
-- }
-- wake_up_interruptible(&info->delta_msr_wait);
--
--}
--
--static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
--{
-- struct amba_info *info = dev_id;
-- unsigned int status, pass_counter = 0;
--
--#if DEBUG_LEDS
-- // tell the world
-- set_leds(get_leds() | RED_LED);
--#endif
--
-- status = UART_GET_INT_STATUS(info->port);
-- do {
-- /*
-- * FIXME: what about clearing the interrupts?
-- */
--
-- if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
--#ifdef SUPPORT_SYSRQ
-- ambauart_rx_chars(info, regs);
--#else
-- ambauart_rx_chars(info);
--#endif
-- if (status & AMBA_UARTIIR_TIS)
-- ambauart_tx_chars(info);
-- if (status & AMBA_UARTIIR_MIS)
-- ambauart_modem_status(info);
-- if (pass_counter++ > AMBA_ISR_PASS_LIMIT)
-- break;
--
-- status = UART_GET_INT_STATUS(info->port);
-- } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS));
--
--#if DEBUG_LEDS
-- // tell the world
-- set_leds(get_leds() & ~RED_LED);
--#endif
--}
--
--static void ambauart_tasklet_action(unsigned long data)
--{
-- struct amba_info *info = (struct amba_info *)data;
-- struct tty_struct *tty;
--
-- tty = info->tty;
-- if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event))
-- return;
--
-- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-- tty->ldisc.write_wakeup)
-- (tty->ldisc.write_wakeup)(tty);
-- wake_up_interruptible(&tty->write_wait);
--}
--
--static int ambauart_startup(struct amba_info *info)
--{
-- unsigned long flags;
-- unsigned long page;
-- int retval = 0;
--
-- page = get_zeroed_page(GFP_KERNEL);
-- if (!page)
-- return -ENOMEM;
--
-- save_flags(flags); cli();
--
-- if (info->flags & ASYNC_INITIALIZED) {
-- free_page(page);
-- goto errout;
-- }
--
-- if (info->xmit.buf)
-- free_page(page);
-- else
-- info->xmit.buf = (unsigned char *) page;
--
-- /*
-- * Allocate the IRQ
-- */
-- retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info);
-- if (retval) {
-- if (capable(CAP_SYS_ADMIN)) {
-- if (info->tty)
-- set_bit(TTY_IO_ERROR, &info->tty->flags);
-- retval = 0;
-- }
-- goto errout;
-- }
--
-- info->mctrl = 0;
-- if (info->tty->termios->c_cflag & CBAUD)
-- info->mctrl = TIOCM_RTS | TIOCM_DTR;
-- info->port->set_mctrl(info->port, info->mctrl);
--
-- /*
-- * initialise the old status of the modem signals
-- */
-- info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY;
--
-- /*
-- * Finally, enable interrupts
-- */
-- ambauart_enable_rx_interrupt(info);
--
-- if (info->tty)
-- clear_bit(TTY_IO_ERROR, &info->tty->flags);
-- info->xmit.head = info->xmit.tail = 0;
--
-- /*
-- * Set up the tty->alt_speed kludge
-- */
-- if (info->tty) {
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-- info->tty->alt_speed = 57600;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-- info->tty->alt_speed = 115200;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-- info->tty->alt_speed = 230400;
-- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-- info->tty->alt_speed = 460800;
-- }
--
-- /*
-- * and set the speed of the serial port
-- */
-- ambauart_change_speed(info, 0);
--
-- info->flags |= ASYNC_INITIALIZED;
-- restore_flags(flags);
-- return 0;
--
--errout:
-- restore_flags(flags);
-- return retval;
--}
--
--/*
-- * This routine will shutdown a serial port; interrupts are disabled, and
-- * DTR is dropped if the hangup on close termio flag is on.
-- */
--static void ambauart_shutdown(struct amba_info *info)
--{
-- unsigned long flags;
--
-- if (!(info->flags & ASYNC_INITIALIZED))
-- return;
--
-- save_flags(flags); cli(); /* Disable interrupts */
--
-- /*
-- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-- * here so the queue might never be woken up
-- */
-- wake_up_interruptible(&info->delta_msr_wait);
--
-- /*
-- * Free the IRQ
-- */
-- free_irq(info->port->irq, info);
--
-- if (info->xmit.buf) {
-- unsigned long pg = (unsigned long) info->xmit.buf;
-- info->xmit.buf = NULL;
-- free_page(pg);
-- }
--
-- /*
-- * disable all interrupts, disable the port
-- */
-- UART_PUT_CR(info->port, 0);
--
-- /* disable break condition and fifos */
-- UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) &
-- ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
--
-- if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-- info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS);
-- info->port->set_mctrl(info->port, info->mctrl);
--
-- /* kill off our tasklet */
-- tasklet_kill(&info->tlet);
-- if (info->tty)
-- set_bit(TTY_IO_ERROR, &info->tty->flags);
--
-- info->flags &= ~ASYNC_INITIALIZED;
-- restore_flags(flags);
--}
--
--static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios)
--{
-- unsigned int lcr_h, baud, quot, cflag, old_cr, bits;
-- unsigned long flags;
--
-- if (!info->tty || !info->tty->termios)
-- return;
--
-- cflag = info->tty->termios->c_cflag;
--
--#if DEBUG
-- printk("ambauart_set_cflag(0x%x) called\n", cflag);
--#endif
-- /* byte size and parity */
-- switch (cflag & CSIZE) {
-- case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break;
-- case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break;
-- case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break;
-- default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8
-- }
-- if (cflag & CSTOPB) {
-- lcr_h |= AMBA_UARTLCR_H_STP2;
-- bits ++;
-- }
-- if (cflag & PARENB) {
-- lcr_h |= AMBA_UARTLCR_H_PEN;
-- bits++;
-- if (!(cflag & PARODD))
-- lcr_h |= AMBA_UARTLCR_H_EPS;
-- }
-- if (info->port->fifosize > 1)
-- lcr_h |= AMBA_UARTLCR_H_FEN;
--
-- do {
-- /* Determine divisor based on baud rate */
-- baud = tty_get_baud_rate(info->tty);
-- if (!baud)
-- baud = 9600;
--
-- if (baud == 38400 &&
-- ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-- quot = info->state->custom_divisor;
-- else
-- quot = (info->port->uartclk / (16 * baud)) - 1;
--
-- if (!quot && old_termios) {
-- info->tty->termios->c_cflag &= ~CBAUD;
-- info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
-- old_termios = NULL;
-- }
-- } while (quot == 0 && old_termios);
--
-- /* As a last resort, if the quotient is zero, default to 9600 bps */
-- if (!quot)
-- quot = (info->port->uartclk / (16 * 9600)) - 1;
--
-- info->timeout = (info->port->fifosize * HZ * bits * quot) /
-- (info->port->uartclk / 16);
-- info->timeout += HZ/50; /* Add .02 seconds of slop */
--
-- if (cflag & CRTSCTS)
-- info->flags |= ASYNC_CTS_FLOW;
-- else
-- info->flags &= ~ASYNC_CTS_FLOW;
-- if (cflag & CLOCAL)
-- info->flags &= ~ASYNC_CHECK_CD;
-- else
-- info->flags |= ASYNC_CHECK_CD;
--
-- /*
-- * Set up parity check flag
-- */
--#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
--
-- info->read_status_mask = AMBA_UARTRSR_OE;
-- if (I_INPCK(info->tty))
-- info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-- if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-- info->read_status_mask |= AMBA_UARTRSR_BE;
--
-- /*
-- * Characters to ignore
-- */
-- info->ignore_status_mask = 0;
-- if (I_IGNPAR(info->tty))
-- info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-- if (I_IGNBRK(info->tty)) {
-- info->ignore_status_mask |= AMBA_UARTRSR_BE;
-- /*
-- * If we're ignoring parity and break indicators,
-- * ignore overruns to (for real raw support).
-- */
-- if (I_IGNPAR(info->tty))
-- info->ignore_status_mask |= AMBA_UARTRSR_OE;
-- }
--
-- /* first, disable everything */
-- save_flags(flags); cli();
-- old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE;
--
-- if ((info->flags & ASYNC_HARDPPS_CD) ||
-- (cflag & CRTSCTS) ||
-- !(cflag & CLOCAL))
-- old_cr |= AMBA_UARTCR_MSIE;
--
-- UART_PUT_CR(info->port, 0);
-- restore_flags(flags);
--
-- /* Set baud rate */
-- UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8));
-- UART_PUT_LCRL(info->port, (quot & 0xff));
--
-- /*
-- * ----------v----------v----------v----------v-----
-- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
-- * ----------^----------^----------^----------^-----
-- */
-- UART_PUT_LCRH(info->port, lcr_h);
-- UART_PUT_CR(info->port, old_cr);
--}
--
--static void ambauart_put_char(struct tty_struct *tty, u_char ch)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (!tty || !info->xmit.buf)
-- return;
--
-- save_flags(flags); cli();
-- if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) {
-- info->xmit.buf[info->xmit.head] = ch;
-- info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1);
-- }
-- restore_flags(flags);
--}
--
--static void ambauart_flush_chars(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (info->xmit.head == info->xmit.tail
-- || tty->stopped
-- || tty->hw_stopped
-- || !info->xmit.buf)
-- return;
--
-- save_flags(flags); cli();
-- ambauart_enable_tx_interrupt(info);
-- restore_flags(flags);
--}
--
--static int ambauart_write(struct tty_struct *tty, int from_user,
-- const u_char * buf, int count)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- int c, ret = 0;
--
-- if (!tty || !info->xmit.buf || !tmp_buf)
-- return 0;
--
-- save_flags(flags);
-- if (from_user) {
-- down(&tmp_buf_sem);
-- while (1) {
-- int c1;
-- c = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (count < c)
-- c = count;
-- if (c <= 0)
-- break;
--
-- c -= copy_from_user(tmp_buf, buf, c);
-- if (!c) {
-- if (!ret)
-- ret = -EFAULT;
-- break;
-- }
-- cli();
-- c1 = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (c1 < c)
-- c = c1;
-- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
-- info->xmit.head = (info->xmit.head + c) &
-- (AMBA_XMIT_SIZE - 1);
-- restore_flags(flags);
-- buf += c;
-- count -= c;
-- ret += c;
-- }
-- up(&tmp_buf_sem);
-- } else {
-- cli();
-- while (1) {
-- c = CIRC_SPACE_TO_END(info->xmit.head,
-- info->xmit.tail,
-- AMBA_XMIT_SIZE);
-- if (count < c)
-- c = count;
-- if (c <= 0)
-- break;
-- memcpy(info->xmit.buf + info->xmit.head, buf, c);
-- info->xmit.head = (info->xmit.head + c) &
-- (AMBA_XMIT_SIZE - 1);
-- buf += c;
-- count -= c;
-- ret += c;
-- }
-- restore_flags(flags);
-- }
-- if (info->xmit.head != info->xmit.tail
-- && !tty->stopped
-- && !tty->hw_stopped)
-- ambauart_enable_tx_interrupt(info);
-- return ret;
--}
--
--static int ambauart_write_room(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
--
-- return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
--}
--
--static int ambauart_chars_in_buffer(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
--
-- return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE);
--}
--
--static void ambauart_flush_buffer(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
--#if DEBUG
-- printk("ambauart_flush_buffer(%d) called\n",
-- MINOR(tty->device) - tty->driver.minor_start);
--#endif
-- save_flags(flags); cli();
-- info->xmit.head = info->xmit.tail = 0;
-- restore_flags(flags);
-- wake_up_interruptible(&tty->write_wait);
-- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-- tty->ldisc.write_wakeup)
-- (tty->ldisc.write_wakeup)(tty);
--}
--
--/*
-- * This function is used to send a high-priority XON/XOFF character to
-- * the device
-- */
--static void ambauart_send_xchar(struct tty_struct *tty, char ch)
--{
-- struct amba_info *info = tty->driver_data;
--
-- info->x_char = ch;
-- if (ch)
-- ambauart_enable_tx_interrupt(info);
--}
--
--static void ambauart_throttle(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
--
-- if (I_IXOFF(tty))
-- ambauart_send_xchar(tty, STOP_CHAR(tty));
--
-- if (tty->termios->c_cflag & CRTSCTS) {
-- save_flags(flags); cli();
-- info->mctrl &= ~TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--}
--
--static void ambauart_unthrottle(struct tty_struct *tty)
--{
-- struct amba_info *info = (struct amba_info *) tty->driver_data;
-- unsigned long flags;
--
-- if (I_IXOFF(tty)) {
-- if (info->x_char)
-- info->x_char = 0;
-- else
-- ambauart_send_xchar(tty, START_CHAR(tty));
-- }
--
-- if (tty->termios->c_cflag & CRTSCTS) {
-- save_flags(flags); cli();
-- info->mctrl |= TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--}
--
--static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo)
--{
-- struct amba_state *state = info->state;
-- struct amba_port *port = info->port;
-- struct serial_struct tmp;
--
-- memset(&tmp, 0, sizeof(tmp));
-- tmp.type = 0;
-- tmp.line = state->line;
-- tmp.port = port->uart_base;
-- if (HIGH_BITS_OFFSET)
-- tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET;
-- tmp.irq = port->irq;
-- tmp.flags = 0;
-- tmp.xmit_fifo_size = port->fifosize;
-- tmp.baud_base = port->uartclk / 16;
-- tmp.close_delay = state->close_delay;
-- tmp.closing_wait = state->closing_wait;
-- tmp.custom_divisor = state->custom_divisor;
--
-- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-- return -EFAULT;
-- return 0;
--}
--
--static int set_serial_info(struct amba_info *info,
-- struct serial_struct *newinfo)
--{
-- struct serial_struct new_serial;
-- struct amba_state *state, old_state;
-- struct amba_port *port;
-- unsigned long new_port;
-- unsigned int i, change_irq, change_port;
-- int retval = 0;
--
-- if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-- return -EFAULT;
--
-- state = info->state;
-- old_state = *state;
-- port = info->port;
--
-- new_port = new_serial.port;
-- if (HIGH_BITS_OFFSET)
-- new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
--
-- change_irq = new_serial.irq != port->irq;
-- change_port = new_port != port->uart_base;
--
-- if (!capable(CAP_SYS_ADMIN)) {
-- if (change_irq || change_port ||
-- (new_serial.baud_base != port->uartclk / 16) ||
-- (new_serial.close_delay != state->close_delay) ||
-- (new_serial.xmit_fifo_size != port->fifosize) ||
-- ((new_serial.flags & ~ASYNC_USR_MASK) !=
-- (state->flags & ~ASYNC_USR_MASK)))
-- return -EPERM;
-- state->flags = ((state->flags & ~ASYNC_USR_MASK) |
-- (new_serial.flags & ASYNC_USR_MASK));
-- info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-- (new_serial.flags & ASYNC_USR_MASK));
-- state->custom_divisor = new_serial.custom_divisor;
-- goto check_and_exit;
-- }
--
-- if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-- (new_serial.baud_base < 9600))
-- return -EINVAL;
--
-- if (new_serial.type && change_port) {
-- for (i = 0; i < SERIAL_AMBA_NR; i++)
-- if ((port != amba_ports + i) &&
-- amba_ports[i].uart_base != new_port)
-- return -EADDRINUSE;
-- }
--
-- if ((change_port || change_irq) && (state->count > 1))
-- return -EBUSY;
--
-- /*
-- * OK, past this point, all the error checking has been done.
-- * At this point, we start making changes.....
-- */
-- port->uartclk = new_serial.baud_base * 16;
-- state->flags = ((state->flags & ~ASYNC_FLAGS) |
-- (new_serial.flags & ASYNC_FLAGS));
-- info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
-- (info->flags & ASYNC_INTERNAL_FLAGS));
-- state->custom_divisor = new_serial.custom_divisor;
-- state->close_delay = new_serial.close_delay * HZ / 100;
-- state->closing_wait = new_serial.closing_wait * HZ / 100;
-- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-- port->fifosize = new_serial.xmit_fifo_size;
--
-- if (change_port || change_irq) {
-- /*
-- * We need to shutdown the serial port at the old
-- * port/irq combination.
-- */
-- ambauart_shutdown(info);
-- port->irq = new_serial.irq;
-- port->uart_base = new_port;
-- }
--
--check_and_exit:
-- if (!port->uart_base)
-- return 0;
-- if (info->flags & ASYNC_INITIALIZED) {
-- if ((old_state.flags & ASYNC_SPD_MASK) !=
-- (state->flags & ASYNC_SPD_MASK) ||
-- (old_state.custom_divisor != state->custom_divisor)) {
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-- info->tty->alt_speed = 57600;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-- info->tty->alt_speed = 115200;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-- info->tty->alt_speed = 230400;
-- if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-- info->tty->alt_speed = 460800;
-- ambauart_change_speed(info, NULL);
-- }
-- } else
-- retval = ambauart_startup(info);
-- return retval;
--}
--
--
--/*
-- * get_lsr_info - get line status register info
-- */
--static int get_lsr_info(struct amba_info *info, unsigned int *value)
--{
-- unsigned int result, status;
-- unsigned long flags;
--
-- save_flags(flags); cli();
-- status = UART_GET_FR(info->port);
-- restore_flags(flags);
-- result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0;
--
-- /*
-- * If we're about to load something into the transmit
-- * register, we'll pretend the transmitter isn't empty to
-- * avoid a race condition (depending on when the transmit
-- * interrupt happens).
-- */
-- if (info->x_char ||
-- ((CIRC_CNT(info->xmit.head, info->xmit.tail,
-- AMBA_XMIT_SIZE) > 0) &&
-- !info->tty->stopped && !info->tty->hw_stopped))
-- result &= TIOCSER_TEMT;
--
-- return put_user(result, value);
--}
--
--static int get_modem_info(struct amba_info *info, unsigned int *value)
--{
-- unsigned int result = info->mctrl;
-- unsigned int status;
--
-- status = UART_GET_FR(info->port);
-- if (status & AMBA_UARTFR_DCD)
-- result |= TIOCM_CAR;
-- if (status & AMBA_UARTFR_DSR)
-- result |= TIOCM_DSR;
-- if (status & AMBA_UARTFR_CTS)
-- result |= TIOCM_CTS;
--
-- return put_user(result, value);
--}
--
--static int set_modem_info(struct amba_info *info, unsigned int cmd,
-- unsigned int *value)
--{
-- unsigned int arg, old;
-- unsigned long flags;
--
-- if (get_user(arg, value))
-- return -EFAULT;
--
-- old = info->mctrl;
-- switch (cmd) {
-- case TIOCMBIS:
-- info->mctrl |= arg;
-- break;
--
-- case TIOCMBIC:
-- info->mctrl &= ~arg;
-- break;
--
-- case TIOCMSET:
-- info->mctrl = arg;
-- break;
--
-- default:
-- return -EINVAL;
-- }
-- save_flags(flags); cli();
-- if (old != info->mctrl)
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- return 0;
--}
--
--static void ambauart_break_ctl(struct tty_struct *tty, int break_state)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- unsigned int lcr_h;
--
-- save_flags(flags); cli();
-- lcr_h = UART_GET_LCRH(info->port);
-- if (break_state == -1)
-- lcr_h |= AMBA_UARTLCR_H_BRK;
-- else
-- lcr_h &= ~AMBA_UARTLCR_H_BRK;
-- UART_PUT_LCRH(info->port, lcr_h);
-- restore_flags(flags);
--}
--
--static int ambauart_ioctl(struct tty_struct *tty, struct file *file,
-- unsigned int cmd, unsigned long arg)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_icount cprev, cnow;
-- struct serial_icounter_struct icount;
-- unsigned long flags;
--
-- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-- if (tty->flags & (1 << TTY_IO_ERROR))
-- return -EIO;
-- }
--
-- switch (cmd) {
-- case TIOCMGET:
-- return get_modem_info(info, (unsigned int *)arg);
-- case TIOCMBIS:
-- case TIOCMBIC:
-- case TIOCMSET:
-- return set_modem_info(info, cmd, (unsigned int *)arg);
-- case TIOCGSERIAL:
-- return get_serial_info(info,
-- (struct serial_struct *)arg);
-- case TIOCSSERIAL:
-- return set_serial_info(info,
-- (struct serial_struct *)arg);
-- case TIOCSERGETLSR: /* Get line status register */
-- return get_lsr_info(info, (unsigned int *)arg);
-- /*
-- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-- * - mask passed in arg for lines of interest
-- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-- * Caller should use TIOCGICOUNT to see which one it was
-- */
-- case TIOCMIWAIT:
-- save_flags(flags); cli();
-- /* note the counters on entry */
-- cprev = info->state->icount;
-- /* Force modem status interrupts on */
-- UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE);
-- restore_flags(flags);
-- while (1) {
-- interruptible_sleep_on(&info->delta_msr_wait);
-- /* see if a signal did it */
-- if (signal_pending(current))
-- return -ERESTARTSYS;
-- save_flags(flags); cli();
-- cnow = info->state->icount; /* atomic copy */
-- restore_flags(flags);
-- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-- return -EIO; /* no change => error */
-- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-- return 0;
-- }
-- cprev = cnow;
-- }
-- /* NOTREACHED */
--
-- /*
-- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-- * Return: write counters to the user passed counter struct
-- * NB: both 1->0 and 0->1 transitions are counted except for
-- * RI where only 0->1 is counted.
-- */
-- case TIOCGICOUNT:
-- save_flags(flags); cli();
-- cnow = info->state->icount;
-- restore_flags(flags);
-- icount.cts = cnow.cts;
-- icount.dsr = cnow.dsr;
-- icount.rng = cnow.rng;
-- icount.dcd = cnow.dcd;
-- icount.rx = cnow.rx;
-- icount.tx = cnow.tx;
-- icount.frame = cnow.frame;
-- icount.overrun = cnow.overrun;
-- icount.parity = cnow.parity;
-- icount.brk = cnow.brk;
-- icount.buf_overrun = cnow.buf_overrun;
--
-- return copy_to_user((void *)arg, &icount, sizeof(icount))
-- ? -EFAULT : 0;
--
-- default:
-- return -ENOIOCTLCMD;
-- }
-- return 0;
--}
--
--static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios)
--{
-- struct amba_info *info = tty->driver_data;
-- unsigned long flags;
-- unsigned int cflag = tty->termios->c_cflag;
--
-- if ((cflag ^ old_termios->c_cflag) == 0 &&
-- RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
-- return;
--
-- ambauart_change_speed(info, old_termios);
--
-- /* Handle transition to B0 status */
-- if ((old_termios->c_cflag & CBAUD) &&
-- !(cflag & CBAUD)) {
-- save_flags(flags); cli();
-- info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--
-- /* Handle transition away from B0 status */
-- if (!(old_termios->c_cflag & CBAUD) &&
-- (cflag & CBAUD)) {
-- save_flags(flags); cli();
-- info->mctrl |= TIOCM_DTR;
-- if (!(cflag & CRTSCTS) ||
-- !test_bit(TTY_THROTTLED, &tty->flags))
-- info->mctrl |= TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- restore_flags(flags);
-- }
--
-- /* Handle turning off CRTSCTS */
-- if ((old_termios->c_cflag & CRTSCTS) &&
-- !(cflag & CRTSCTS)) {
-- tty->hw_stopped = 0;
-- ambauart_start(tty);
-- }
--
--#if 0
-- /*
-- * No need to wake up processes in open wait, since they
-- * sample the CLOCAL flag once, and don't recheck it.
-- * XXX It's not clear whether the current behavior is correct
-- * or not. Hence, this may change.....
-- */
-- if (!(old_termios->c_cflag & CLOCAL) &&
-- (tty->termios->c_cflag & CLOCAL))
-- wake_up_interruptible(&info->open_wait);
--#endif
--}
--
--static void ambauart_close(struct tty_struct *tty, struct file *filp)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_state *state;
-- unsigned long flags;
--
-- if (!info)
-- return;
--
-- state = info->state;
--
--#if DEBUG
-- printk("ambauart_close() called\n");
--#endif
--
-- save_flags(flags); cli();
--
-- if (tty_hung_up_p(filp)) {
-- MOD_DEC_USE_COUNT;
-- restore_flags(flags);
-- return;
-- }
--
-- if ((tty->count == 1) && (state->count != 1)) {
-- /*
-- * Uh, oh. tty->count is 1, which means that the tty
-- * structure will be freed. state->count should always
-- * be one in these conditions. If it's greater than
-- * one, we've got real problems, since it means the
-- * serial port won't be shutdown.
-- */
-- printk("ambauart_close: bad serial port count; tty->count is 1, "
-- "state->count is %d\n", state->count);
-- state->count = 1;
-- }
-- if (--state->count < 0) {
-- printk("rs_close: bad serial port count for %s%d: %d\n",
-- tty->driver.name, info->state->line, state->count);
-- state->count = 0;
-- }
-- if (state->count) {
-- MOD_DEC_USE_COUNT;
-- restore_flags(flags);
-- return;
-- }
-- info->flags |= ASYNC_CLOSING;
-- restore_flags(flags);
-- /*
-- * Save the termios structure, since this port may have
-- * separate termios for callout and dialin.
-- */
-- if (info->flags & ASYNC_NORMAL_ACTIVE)
-- info->state->normal_termios = *tty->termios;
-- if (info->flags & ASYNC_CALLOUT_ACTIVE)
-- info->state->callout_termios = *tty->termios;
-- /*
-- * Now we wait for the transmit buffer to clear; and we notify
-- * the line discipline to only process XON/XOFF characters.
-- */
-- tty->closing = 1;
-- if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-- tty_wait_until_sent(tty, info->state->closing_wait);
-- /*
-- * At this point, we stop accepting input. To do this, we
-- * disable the receive line status interrupts.
-- */
-- if (info->flags & ASYNC_INITIALIZED) {
-- ambauart_disable_rx_interrupt(info);
-- /*
-- * Before we drop DTR, make sure the UART transmitter
-- * has completely drained; this is especially
-- * important if there is a transmit FIFO!
-- */
-- ambauart_wait_until_sent(tty, info->timeout);
-- }
-- ambauart_shutdown(info);
-- if (tty->driver.flush_buffer)
-- tty->driver.flush_buffer(tty);
-- if (tty->ldisc.flush_buffer)
-- tty->ldisc.flush_buffer(tty);
-- tty->closing = 0;
-- info->event = 0;
-- info->tty = NULL;
-- if (info->blocked_open) {
-- if (info->state->close_delay) {
-- set_current_state(TASK_INTERRUPTIBLE);
-- schedule_timeout(info->state->close_delay);
-- }
-- wake_up_interruptible(&info->open_wait);
-- }
-- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
-- ASYNC_CLOSING);
-- wake_up_interruptible(&info->close_wait);
-- MOD_DEC_USE_COUNT;
--}
--
--static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout)
--{
-- struct amba_info *info = (struct amba_info *) tty->driver_data;
-- unsigned long char_time, expire;
-- unsigned int status;
--
-- if (info->port->fifosize == 0)
-- return;
--
-- /*
-- * Set the check interval to be 1/5 of the estimated time to
-- * send a single character, and make it at least 1. The check
-- * interval should also be less than the timeout.
-- *
-- * Note: we have to use pretty tight timings here to satisfy
-- * the NIST-PCTS.
-- */
-- char_time = (info->timeout - HZ/50) / info->port->fifosize;
-- char_time = char_time / 5;
-- if (char_time == 0)
-- char_time = 1;
-- if (timeout && timeout < char_time)
-- char_time = timeout;
-- /*
-- * If the transmitter hasn't cleared in twice the approximate
-- * amount of time to send the entire FIFO, it probably won't
-- * ever clear. This assumes the UART isn't doing flow
-- * control, which is currently the case. Hence, if it ever
-- * takes longer than info->timeout, this is probably due to a
-- * UART bug of some kind. So, we clamp the timeout parameter at
-- * 2*info->timeout.
-- */
-- if (!timeout || timeout > 2 * info->timeout)
-- timeout = 2 * info->timeout;
--
-- expire = jiffies + timeout;
--#if DEBUG
-- printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n",
-- MINOR(tty->device) - tty->driver.minor_start, jiffies,
-- expire);
--#endif
-- while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) {
-- set_current_state(TASK_INTERRUPTIBLE);
-- schedule_timeout(char_time);
-- if (signal_pending(current))
-- break;
-- if (timeout && time_after(jiffies, expire))
-- break;
-- status = UART_GET_FR(info->port);
-- }
-- set_current_state(TASK_RUNNING);
--}
--
--static void ambauart_hangup(struct tty_struct *tty)
--{
-- struct amba_info *info = tty->driver_data;
-- struct amba_state *state = info->state;
--
-- ambauart_flush_buffer(tty);
-- if (info->flags & ASYNC_CLOSING)
-- return;
-- ambauart_shutdown(info);
-- info->event = 0;
-- state->count = 0;
-- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
-- info->tty = NULL;
-- wake_up_interruptible(&info->open_wait);
--}
--
--static int block_til_ready(struct tty_struct *tty, struct file *filp,
-- struct amba_info *info)
--{
-- DECLARE_WAITQUEUE(wait, current);
-- struct amba_state *state = info->state;
-- unsigned long flags;
-- int do_clocal = 0, extra_count = 0, retval;
--
-- /*
-- * If the device is in the middle of being closed, then block
-- * until it's done, and then try again.
-- */
-- if (tty_hung_up_p(filp) ||
-- (info->flags & ASYNC_CLOSING)) {
-- if (info->flags & ASYNC_CLOSING)
-- interruptible_sleep_on(&info->close_wait);
-- return (info->flags & ASYNC_HUP_NOTIFY) ?
-- -EAGAIN : -ERESTARTSYS;
-- }
--
-- /*
-- * If this is a callout device, then just make sure the normal
-- * device isn't being used.
-- */
-- if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-- if (info->flags & ASYNC_NORMAL_ACTIVE)
-- return -EBUSY;
-- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_SESSION_LOCKOUT) &&
-- (info->session != current->session))
-- return -EBUSY;
-- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (info->flags & ASYNC_PGRP_LOCKOUT) &&
-- (info->pgrp != current->pgrp))
-- return -EBUSY;
-- info->flags |= ASYNC_CALLOUT_ACTIVE;
-- return 0;
-- }
--
-- /*
-- * If non-blocking mode is set, or the port is not enabled,
-- * then make the check up front and then exit.
-- */
-- if ((filp->f_flags & O_NONBLOCK) ||
-- (tty->flags & (1 << TTY_IO_ERROR))) {
-- if (info->flags & ASYNC_CALLOUT_ACTIVE)
-- return -EBUSY;
-- info->flags |= ASYNC_NORMAL_ACTIVE;
-- return 0;
-- }
--
-- if (info->flags & ASYNC_CALLOUT_ACTIVE) {
-- if (state->normal_termios.c_cflag & CLOCAL)
-- do_clocal = 1;
-- } else {
-- if (tty->termios->c_cflag & CLOCAL)
-- do_clocal = 1;
-- }
--
-- /*
-- * Block waiting for the carrier detect and the line to become
-- * free (i.e., not in use by the callout). While we are in
-- * this loop, state->count is dropped by one, so that
-- * rs_close() knows when to free things. We restore it upon
-- * exit, either normal or abnormal.
-- */
-- retval = 0;
-- add_wait_queue(&info->open_wait, &wait);
-- save_flags(flags); cli();
-- if (!tty_hung_up_p(filp)) {
-- extra_count = 1;
-- state->count--;
-- }
-- restore_flags(flags);
-- info->blocked_open++;
-- while (1) {
-- save_flags(flags); cli();
-- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- (tty->termios->c_cflag & CBAUD)) {
-- info->mctrl = TIOCM_DTR | TIOCM_RTS;
-- info->port->set_mctrl(info->port, info->mctrl);
-- }
-- restore_flags(flags);
-- set_current_state(TASK_INTERRUPTIBLE);
-- if (tty_hung_up_p(filp) ||
-- !(info->flags & ASYNC_INITIALIZED)) {
-- if (info->flags & ASYNC_HUP_NOTIFY)
-- retval = -EAGAIN;
-- else
-- retval = -ERESTARTSYS;
-- break;
-- }
-- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-- !(info->flags & ASYNC_CLOSING) &&
-- (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD)))
-- break;
-- if (signal_pending(current)) {
-- retval = -ERESTARTSYS;
-- break;
-- }
-- schedule();
-- }
-- set_current_state(TASK_RUNNING);
-- remove_wait_queue(&info->open_wait, &wait);
-- if (extra_count)
-- state->count++;
-- info->blocked_open--;
-- if (retval)
-- return retval;
-- info->flags |= ASYNC_NORMAL_ACTIVE;
-- return 0;
--}
--
--static struct amba_info *ambauart_get(int line)
--{
-- struct amba_info *info;
-- struct amba_state *state = amba_state + line;
--
-- state->count++;
-- if (state->info)
-- return state->info;
-- info = kmalloc(sizeof(struct amba_info), GFP_KERNEL);
-- if (info) {
-- memset(info, 0, sizeof(struct amba_info));
-- init_waitqueue_head(&info->open_wait);
-- init_waitqueue_head(&info->close_wait);
-- init_waitqueue_head(&info->delta_msr_wait);
-- info->flags = state->flags;
-- info->state = state;
-- info->port = amba_ports + line;
-- tasklet_init(&info->tlet, ambauart_tasklet_action,
-- (unsigned long)info);
-- }
-- if (state->info) {
-- kfree(info);
-- return state->info;
-- }
-- state->info = info;
-- return info;
--}
--
--static int ambauart_open(struct tty_struct *tty, struct file *filp)
--{
-- struct amba_info *info;
-- int retval, line = MINOR(tty->device) - tty->driver.minor_start;
--
--#if DEBUG
-- printk("ambauart_open(%d) called\n", line);
--#endif
--
-- // is this a line that we've got?
-- MOD_INC_USE_COUNT;
-- if (line >= SERIAL_AMBA_NR) {
-- MOD_DEC_USE_COUNT;
-- return -ENODEV;
-- }
--
-- info = ambauart_get(line);
-- if (!info)
-- return -ENOMEM;
--
-- tty->driver_data = info;
-- info->tty = tty;
-- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
--
-- /*
-- * Make sure we have the temporary buffer allocated
-- */
-- if (!tmp_buf) {
-- unsigned long page = get_zeroed_page(GFP_KERNEL);
-- if (tmp_buf)
-- free_page(page);
-- else if (!page) {
-- MOD_DEC_USE_COUNT;
-- return -ENOMEM;
-- }
-- tmp_buf = (u_char *)page;
-- }
--
-- /*
-- * If the port is in the middle of closing, bail out now.
-- */
-- if (tty_hung_up_p(filp) ||
-- (info->flags & ASYNC_CLOSING)) {
-- if (info->flags & ASYNC_CLOSING)
-- interruptible_sleep_on(&info->close_wait);
-- MOD_DEC_USE_COUNT;
-- return -EAGAIN;
-- }
--
-- /*
-- * Start up the serial port
-- */
-- retval = ambauart_startup(info);
-- if (retval) {
-- MOD_DEC_USE_COUNT;
-- return retval;
-- }
--
-- retval = block_til_ready(tty, filp, info);
-- if (retval) {
-- MOD_DEC_USE_COUNT;
-- return retval;
-- }
--
-- if ((info->state->count == 1) &&
-- (info->flags & ASYNC_SPLIT_TERMIOS)) {
-- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-- *tty->termios = info->state->normal_termios;
-- else
-- *tty->termios = info->state->callout_termios;
-- }
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-- if (ambauart_cons.cflag && ambauart_cons.index == line) {
-- tty->termios->c_cflag = ambauart_cons.cflag;
-- ambauart_cons.cflag = 0;
-- }
--#endif
-- ambauart_change_speed(info, NULL);
-- info->session = current->session;
-- info->pgrp = current->pgrp;
-- return 0;
--}
--
--int __init ambauart_init(void)
--{
-- int i;
--
-- ambanormal_driver.magic = TTY_DRIVER_MAGIC;
-- ambanormal_driver.driver_name = "serial_amba";
-- ambanormal_driver.name = SERIAL_AMBA_NAME;
-- ambanormal_driver.major = SERIAL_AMBA_MAJOR;
-- ambanormal_driver.minor_start = SERIAL_AMBA_MINOR;
-- ambanormal_driver.num = SERIAL_AMBA_NR;
-- ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
-- ambanormal_driver.subtype = SERIAL_TYPE_NORMAL;
-- ambanormal_driver.init_termios = tty_std_termios;
-- ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
-- ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-- ambanormal_driver.refcount = &ambauart_refcount;
-- ambanormal_driver.table = ambauart_table;
-- ambanormal_driver.termios = ambauart_termios;
-- ambanormal_driver.termios_locked = ambauart_termios_locked;
--
-- ambanormal_driver.open = ambauart_open;
-- ambanormal_driver.close = ambauart_close;
-- ambanormal_driver.write = ambauart_write;
-- ambanormal_driver.put_char = ambauart_put_char;
-- ambanormal_driver.flush_chars = ambauart_flush_chars;
-- ambanormal_driver.write_room = ambauart_write_room;
-- ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer;
-- ambanormal_driver.flush_buffer = ambauart_flush_buffer;
-- ambanormal_driver.ioctl = ambauart_ioctl;
-- ambanormal_driver.throttle = ambauart_throttle;
-- ambanormal_driver.unthrottle = ambauart_unthrottle;
-- ambanormal_driver.send_xchar = ambauart_send_xchar;
-- ambanormal_driver.set_termios = ambauart_set_termios;
-- ambanormal_driver.stop = ambauart_stop;
-- ambanormal_driver.start = ambauart_start;
-- ambanormal_driver.hangup = ambauart_hangup;
-- ambanormal_driver.break_ctl = ambauart_break_ctl;
-- ambanormal_driver.wait_until_sent = ambauart_wait_until_sent;
-- ambanormal_driver.read_proc = NULL;
--
-- /*
-- * The callout device is just like the normal device except for
-- * the major number and the subtype code.
-- */
-- ambacallout_driver = ambanormal_driver;
-- ambacallout_driver.name = CALLOUT_AMBA_NAME;
-- ambacallout_driver.major = CALLOUT_AMBA_MAJOR;
-- ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT;
-- ambacallout_driver.read_proc = NULL;
-- ambacallout_driver.proc_entry = NULL;
--
-- if (tty_register_driver(&ambanormal_driver))
-- panic("Couldn't register AMBA serial driver\n");
-- if (tty_register_driver(&ambacallout_driver))
-- panic("Couldn't register AMBA callout driver\n");
--
-- for (i = 0; i < SERIAL_AMBA_NR; i++) {
-- struct amba_state *state = amba_state + i;
-- state->line = i;
-- state->close_delay = 5 * HZ / 10;
-- state->closing_wait = 30 * HZ;
-- state->callout_termios = ambacallout_driver.init_termios;
-- state->normal_termios = ambanormal_driver.init_termios;
-- }
--
-- return 0;
--}
--
--__initcall(ambauart_init);
--
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
--/************** console driver *****************/
--
--/*
-- * This code is currently never used; console->read is never called.
-- * Therefore, although we have an implementation, we don't use it.
-- * FIXME: the "const char *s" should be fixed to "char *s" some day.
-- * (when the definition in include/linux/console.h is also fixed)
-- */
--#ifdef used_and_not_const_char_pointer
--static int ambauart_console_read(struct console *co, const char *s, u_int count)
--{
-- struct amba_port *port = &amba_ports[co->index];
-- unsigned int status;
-- char *w;
-- int c;
--#if DEBUG
-- printk("ambauart_console_read() called\n");
--#endif
--
-- c = 0;
-- w = s;
-- while (c < count) {
-- status = UART_GET_FR(port);
-- if (UART_RX_DATA(status)) {
-- *w++ = UART_GET_CHAR(port);
-- c++;
-- } else {
-- // nothing more to get, return
-- return c;
-- }
-- }
-- // return the count
-- return c;
--}
--#endif
--
--/*
-- * Print a string to the serial port trying not to disturb
-- * any possible real use of the port...
-- *
-- * The console must be locked when we get here.
-- */
--static void ambauart_console_write(struct console *co, const char *s, u_int count)
--{
-- struct amba_port *port = &amba_ports[co->index];
-- unsigned int status, old_cr;
-- int i;
--
-- /*
-- * First save the CR then disable the interrupts
-- */
-- old_cr = UART_GET_CR(port);
-- UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
--
-- /*
-- * Now, do each character
-- */
-- for (i = 0; i < count; i++) {
-- do {
-- status = UART_GET_FR(port);
-- } while (!UART_TX_READY(status));
-- UART_PUT_CHAR(port, s[i]);
-- if (s[i] == '\n') {
-- do {
-- status = UART_GET_FR(port);
-- } while (!UART_TX_READY(status));
-- UART_PUT_CHAR(port, '\r');
-- }
-- }
--
-- /*
-- * Finally, wait for transmitter to become empty
-- * and restore the TCR
-- */
-- do {
-- status = UART_GET_FR(port);
-- } while (status & AMBA_UARTFR_BUSY);
-- UART_PUT_CR(port, old_cr);
--}
--
--static kdev_t ambauart_console_device(struct console *c)
--{
-- return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
--}
--
--static int __init ambauart_console_setup(struct console *co, char *options)
--{
-- struct amba_port *port;
-- int baud = 38400;
-- int bits = 8;
-- int parity = 'n';
-- u_int cflag = CREAD | HUPCL | CLOCAL;
-- u_int lcr_h, quot;
--
-- if (co->index >= SERIAL_AMBA_NR)
-- co->index = 0;
--
-- port = &amba_ports[co->index];
--
-- if (options) {
-- char *s = options;
-- baud = simple_strtoul(s, NULL, 10);
-- while (*s >= '0' && *s <= '9')
-- s++;
-- if (*s) parity = *s++;
-- if (*s) bits = *s - '0';
-- }
--
-- /*
-- * Now construct a cflag setting.
-- */
-- switch (baud) {
-- case 1200: cflag |= B1200; break;
-- case 2400: cflag |= B2400; break;
-- case 4800: cflag |= B4800; break;
-- default: cflag |= B9600; baud = 9600; break;
-- case 19200: cflag |= B19200; break;
-- case 38400: cflag |= B38400; break;
-- case 57600: cflag |= B57600; break;
-- case 115200: cflag |= B115200; break;
-- }
-- switch (bits) {
-- case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break;
-- default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break;
-- }
-- switch (parity) {
-- case 'o':
-- case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break;
-- case 'e':
-- case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN |
-- AMBA_UARTLCR_H_EPS; break;
-- }
--
-- co->cflag = cflag;
--
-- if (port->fifosize > 1)
-- lcr_h |= AMBA_UARTLCR_H_FEN;
--
-- quot = (port->uartclk / (16 * baud)) - 1;
--
-- UART_PUT_LCRL(port, (quot & 0xff));
-- UART_PUT_LCRM(port, (quot >> 8));
-- UART_PUT_LCRH(port, lcr_h);
--
-- /* we will enable the port as we need it */
-- UART_PUT_CR(port, 0);
--
-- return 0;
--}
--
--static struct console ambauart_cons =
--{
-- name: SERIAL_AMBA_NAME,
-- write: ambauart_console_write,
--#ifdef used_and_not_const_char_pointer
-- read: ambauart_console_read,
--#endif
-- device: ambauart_console_device,
-- setup: ambauart_console_setup,
-- flags: CON_PRINTBUFFER,
-- index: -1,
--};
--
--void __init ambauart_console_init(void)
--{
-- register_console(&ambauart_cons);
--}
--
--#endif /* CONFIG_SERIAL_AMBA_CONSOLE */
--
--MODULE_LICENSE("GPL");
--EXPORT_NO_SYMBOLS;
---- linux-2.4.27/drivers/char/tty_io.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/tty_io.c
-@@ -19,7 +19,7 @@
- * Also restructured routines so that there is more of a separation
- * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
- * the low-level tty routines (serial.c, pty.c, console.c). This
-- * makes for cleaner and more compact code. -TYT, 9/17/92
-+ * makes for cleaner and more compact code. -TYT, 9/17/92
- *
- * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
- * which can be dynamically activated and de-activated by the line
-@@ -41,7 +41,7 @@
- *
- * New TIOCLINUX variants added.
- * -- mj@k332.feld.cvut.cz, 19-Nov-95
-- *
-+ *
- * Restrict vt switching via ioctl()
- * -- grif@cs.ucr.edu, 5-Dec-95
- *
-@@ -151,8 +151,7 @@
- extern void tty3215_init(void);
- extern void tub3270_con_init(void);
- extern void tub3270_init(void);
--extern void rs285_console_init(void);
--extern void sa1100_rs_console_init(void);
-+extern void uart_console_init(void);
- extern void sgi_serial_console_init(void);
- extern void sn_sal_serial_console_init(void);
- extern void sci_console_init(void);
-@@ -164,6 +163,7 @@
- extern void txx9_serial_console_init(void);
- extern void sb1250_serial_console_init(void);
- extern void arc_console_init(void);
-+extern void rs285_console_init(void);
- extern int hvc_console_init(void);
-
- #ifndef MIN
-@@ -201,7 +201,7 @@
- else
- sprintf(buf, name,
- idx + tty->driver.name_base);
--
-+
- return buf;
- }
-
-@@ -239,7 +239,7 @@
- #ifdef CHECK_TTY_COUNT
- struct list_head *p;
- int count = 0;
--
-+
- file_list_lock();
- for(p = tty->tty_files.next; p != &tty->tty_files; p = p->next) {
- if(list_entry(p, struct file, f_list)->private_data == tty)
-@@ -255,7 +255,7 @@
- "!= #fd's(%d) in %s\n",
- kdevname(tty->device), tty->count, count, routine);
- return count;
-- }
-+ }
- #endif
- return 0;
- }
-@@ -264,14 +264,14 @@
- {
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
--
-+
- if (new_ldisc) {
- ldiscs[disc] = *new_ldisc;
- ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
- ldiscs[disc].num = disc;
- } else
- memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
--
-+
- return 0;
- }
-
-@@ -301,7 +301,7 @@
- o_ldisc = tty->ldisc;
-
- tty_wait_until_sent(tty, 0);
--
-+
- /* Shutdown the current discipline. */
- if (tty->ldisc.close)
- (tty->ldisc.close)(tty);
-@@ -339,7 +339,7 @@
- {
- int major, minor;
- struct tty_driver *p;
--
-+
- minor = MINOR(device);
- major = MAJOR(device);
-
-@@ -456,7 +456,7 @@
- redirect = NULL;
- }
- spin_unlock(&redirect_lock);
--
-+
- check_tty_count(tty, "do_tty_hangup");
- file_list_lock();
- for (l = tty->tty_files.next; l != &tty->tty_files; l = l->next) {
-@@ -473,7 +473,7 @@
- filp->f_op = &hung_up_tty_fops;
- }
- file_list_unlock();
--
-+
- /* FIXME! What are the locking issues here? This may me overdoing things.. */
- {
- unsigned long flags;
-@@ -510,7 +510,7 @@
- "error %d\n", -i);
- }
- }
--
-+
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if ((tty->session > 0) && (p->session == tty->session) &&
-@@ -550,7 +550,7 @@
- {
- #ifdef TTY_DEBUG_HANGUP
- char buf[64];
--
-+
- printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
- #endif
- schedule_task(&tty->tq_hangup);
-@@ -650,7 +650,7 @@
- wake_up_interruptible(&tty->write_wait);
- }
-
--static ssize_t tty_read(struct file * file, char * buf, size_t count,
-+static ssize_t tty_read(struct file * file, char * buf, size_t count,
- loff_t *ppos)
- {
- int i;
-@@ -707,7 +707,7 @@
- size_t count)
- {
- ssize_t ret = 0, written = 0;
--
-+
- if (file->f_flags & O_NONBLOCK) {
- if (down_trylock(&tty->atomic_write))
- return -EAGAIN;
-@@ -835,7 +835,7 @@
- struct tty_struct *tty, *o_tty;
- struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
- struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
-- struct tty_driver *driver;
-+ struct tty_driver *driver;
- int retval=0;
- int idx;
-
-@@ -845,7 +845,7 @@
-
- idx = MINOR(device) - driver->minor_start;
-
-- /*
-+ /*
- * Check whether we need to acquire the tty semaphore to avoid
- * race conditions. For now, play it safe.
- */
-@@ -859,7 +859,7 @@
- * First time open is complex, especially for PTY devices.
- * This code guarantees that either everything succeeds and the
- * TTY is ready for operation, or else the table slots are vacated
-- * and the allocated memory released. (Except that the termios
-+ * and the allocated memory released. (Except that the termios
- * and locked termios may be retained.)
- */
-
-@@ -938,13 +938,13 @@
- o_tty->link = tty;
- }
-
-- /*
-+ /*
- * All structures have been allocated, so now we install them.
-- * Failures after this point use release_mem to clean up, so
-+ * Failures after this point use release_mem to clean up, so
- * there's no need to null out the local pointers.
- */
- driver->table[idx] = tty;
--
-+
- if (!*tp_loc)
- *tp_loc = tp;
- if (!*ltp_loc)
-@@ -954,7 +954,7 @@
- (*driver->refcount)++;
- tty->count++;
-
-- /*
-+ /*
- * Structures all installed ... call the ldisc open routines.
- * If we fail here just call release_mem to clean up. No need
- * to decrement the use counts, as release_mem doesn't care.
-@@ -988,7 +988,7 @@
- if (driver->type == TTY_DRIVER_TYPE_PTY &&
- driver->subtype == PTY_TYPE_MASTER) {
- /*
-- * special case for PTY masters: only one open permitted,
-+ * special case for PTY masters: only one open permitted,
- * and the slave side open count is incremented as well.
- */
- if (tty->count) {
-@@ -1002,7 +1002,7 @@
-
- success:
- *ret_tty = tty;
--
-+
- /* All paths come through here to release the semaphore */
- end_init:
- up_tty_sem(idx);
-@@ -1080,7 +1080,7 @@
- int pty_master, tty_closing, o_tty_closing, do_sleep;
- int idx;
- char buf[64];
--
-+
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "release_dev"))
- return;
-@@ -1138,7 +1138,7 @@
- idx, kdevname(tty->device));
- return;
- }
-- if (o_tty->termios_locked !=
-+ if (o_tty->termios_locked !=
- tty->driver.other->termios_locked[idx]) {
- printk(KERN_DEBUG "release_dev: other->termios_locked["
- "%d] not o_termios_locked for (%s)\n",
-@@ -1204,11 +1204,11 @@
- printk(KERN_WARNING "release_dev: %s: read/write wait queue "
- "active!\n", tty_name(tty, buf));
- schedule();
-- }
-+ }
-
- /*
-- * The closing flags are now consistent with the open counts on
-- * both sides, and we've completed the last operation that could
-+ * The closing flags are now consistent with the open counts on
-+ * both sides, and we've completed the last operation that could
- * block, so it's safe to proceed with closing.
- */
- if (pty_master) {
-@@ -1266,7 +1266,7 @@
- /* check whether both sides are closing ... */
- if (!tty_closing || (o_tty && !o_tty_closing))
- return;
--
-+
- #ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "freeing tty structure...");
- #endif
-@@ -1284,14 +1284,14 @@
- (o_tty->ldisc.close)(o_tty);
- o_tty->ldisc = ldiscs[N_TTY];
- }
--
-+
- /*
-- * Make sure that the tty's task queue isn't activated.
-+ * Make sure that the tty's task queue isn't activated.
- */
- run_task_queue(&tq_timer);
- flush_scheduled_tasks();
-
-- /*
-+ /*
- * The release_mem function takes care of the details of clearing
- * the slots and preserving the termios structure.
- */
-@@ -1482,7 +1482,7 @@
- tty = (struct tty_struct *)filp->private_data;
- if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
- return 0;
--
-+
- retval = fasync_helper(fd, filp, on, &tty->fasync);
- if (retval <= 0)
- return retval;
-@@ -1697,7 +1697,7 @@
-
- static int tty_generic_brk(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
- {
-- if (cmd == TCSBRK && arg)
-+ if (cmd == TCSBRK && arg)
- {
- /* tcdrain case */
- int retval = tty_check_change(tty);
-@@ -1718,7 +1718,7 @@
- {
- struct tty_struct *tty, *real_tty;
- int retval;
--
-+
- tty = (struct tty_struct *)file->private_data;
- if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
- return -EINVAL;
-@@ -1738,7 +1738,7 @@
- if (tty->driver.ioctl)
- return tty->driver.ioctl(tty, file, cmd, arg);
- return -EINVAL;
--
-+
- /* These two ioctl's always return success; even if */
- /* the driver doesn't support them. */
- case TCSBRK:
-@@ -1761,7 +1761,7 @@
- case TIOCSBRK:
- case TIOCCBRK:
- case TCSBRK:
-- case TCSBRKP:
-+ case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
-@@ -1824,7 +1824,7 @@
- case TIOCSBRK: /* Turn break on, unconditionally */
- tty->driver.break_ctl(tty, -1);
- return 0;
--
-+
- case TIOCCBRK: /* Turn break off, unconditionally */
- tty->driver.break_ctl(tty, 0);
- return 0;
-@@ -1837,7 +1837,7 @@
- if (!arg)
- return send_break(tty, HZ/4);
- return 0;
-- case TCSBRKP: /* support for POSIX tcsendbreak() */
-+ case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
- }
- if (tty->driver.ioctl) {
-@@ -1859,7 +1859,7 @@
- * prevent trojan horses by killing all processes associated with this
- * tty when the user hits the "Secure Attention Key". Required for
- * super-paranoid applications --- see the Orange Book for more details.
-- *
-+ *
- * This code could be nicer; ideally it should send a HUP, wait a few
- * seconds, then send a INT, and then a KILL signal. But you then
- * have to coordinate with the init process, since all processes associated
-@@ -1883,7 +1883,7 @@
- int session;
- int i;
- struct file *filp;
--
-+
- if (!tty)
- return;
- session = tty->session;
-@@ -1968,7 +1968,7 @@
- count = tty->flip.count;
- tty->flip.count = 0;
- restore_flags(flags);
--
-+
- tty->ldisc.receive_buf(tty, cp, fp, count);
- }
-
-@@ -2000,7 +2000,7 @@
- i = cflag & CBAUD;
- if (i & CBAUDEX) {
- i &= ~CBAUDEX;
-- if (i < 1 || i+15 >= n_baud_table)
-+ if (i < 1 || i+15 >= n_baud_table)
- tty->termios->c_cflag &= ~CBAUDEX;
- else
- i += 15;
-@@ -2013,7 +2013,7 @@
- }
- return(tty->alt_speed);
- }
--
-+
- return baud_table[i];
- }
-
-@@ -2079,7 +2079,7 @@
- mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- break;
- }
-- if ( (minor < driver->minor_start) ||
-+ if ( (minor < driver->minor_start) ||
- (minor >= driver->minor_start + driver->num) ) {
- printk(KERN_ERR "Attempt to register invalid minor number "
- "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
-@@ -2132,12 +2132,12 @@
-
- if (!driver->put_char)
- driver->put_char = tty_default_put_char;
--
-+
- driver->prev = 0;
- driver->next = tty_drivers;
- if (tty_drivers) tty_drivers->prev = driver;
- tty_drivers = driver;
--
-+
- if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
- for(i = 0; i < driver->num; i++)
- tty_register_devfs(driver, 0, driver->minor_start + i);
-@@ -2156,7 +2156,7 @@
- int i, found = 0;
- struct termios *tp;
- const char *othername = NULL;
--
-+
- if (*driver->refcount)
- return -EBUSY;
-
-@@ -2166,7 +2166,7 @@
- else if (p->major == driver->major)
- othername = p->name;
- }
--
-+
- if (!found)
- return -ENOENT;
-
-@@ -2181,7 +2181,7 @@
- driver->prev->next = driver->next;
- else
- tty_drivers = driver->next;
--
-+
- if (driver->next)
- driver->next->prev = driver->prev;
-
-@@ -2221,7 +2221,7 @@
- (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
-
- /*
-- * Set up the standard termios. Individual tty drivers may
-+ * Set up the standard termios. Individual tty drivers may
- * deviate from this; this is used as a template.
- */
- memset(&tty_std_termios, 0, sizeof(struct termios));
-@@ -2233,11 +2233,11 @@
- ECHOCTL | ECHOKE | IEXTEN;
-
- /*
-- * set up the console device so that later boot sequences can
-+ * set up the console device so that later boot sequences can
- * inform about problems etc..
- */
- #ifdef CONFIG_EARLY_PRINTK
-- disable_early_printk();
-+ disable_early_printk();
- #endif
- #ifdef CONFIG_HVC_CONSOLE
- hvc_console_init();
-@@ -2288,18 +2288,12 @@
- #ifdef CONFIG_STDIO_CONSOLE
- stdio_console_init();
- #endif
--#ifdef CONFIG_SERIAL_21285_CONSOLE
-- rs285_console_init();
--#endif
--#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-- sa1100_rs_console_init();
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+ uart_console_init();
- #endif
- #ifdef CONFIG_ARC_CONSOLE
- arc_console_init();
- #endif
--#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-- ambauart_console_init();
--#endif
- #ifdef CONFIG_SERIAL_TX3912_CONSOLE
- tx3912_console_init();
- #endif
-@@ -2315,6 +2309,9 @@
- #ifdef CONFIG_IP22_SERIAL
- sgi_serial_console_init();
- #endif
-+#ifdef CONFIG_SERIAL_21285_CONSOLE
-+ rs285_console_init();
-+#endif
- }
-
- static struct tty_driver dev_tty_driver, dev_syscons_driver;
-@@ -2347,7 +2344,7 @@
- dev_tty_driver.num = 1;
- dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
- dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
--
-+
- if (tty_register_driver(&dev_tty_driver))
- panic("Couldn't register /dev/tty driver\n");
-
-@@ -2363,7 +2360,7 @@
- panic("Couldn't register /dev/console driver\n");
-
- /* console calls tty_register_driver() before kmalloc() works.
-- * Thus, we can't devfs_register() then. Do so now, instead.
-+ * Thus, we can't devfs_register() then. Do so now, instead.
- */
- #ifdef CONFIG_VT
- con_init_devfs();
-@@ -2381,7 +2378,7 @@
- if (tty_register_driver(&dev_ptmx_driver))
- panic("Couldn't register /dev/ptmx driver\n");
- #endif
--
-+
- #ifdef CONFIG_VT
- dev_console_driver = dev_tty_driver;
- dev_console_driver.driver_name = "/dev/vc/0";
-@@ -2441,10 +2438,10 @@
- pty_init();
- #ifdef CONFIG_MOXA_SMARTIO
- mxser_init();
--#endif
-+#endif
- #ifdef CONFIG_MOXA_INTELLIO
- moxa_init();
--#endif
-+#endif
- #ifdef CONFIG_VT
- vcs_init();
- #endif
---- linux-2.4.27/drivers/char/wdt285.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/wdt285.c
-@@ -151,7 +151,7 @@
- if (get_user(new_margin, (int *)arg))
- return -EFAULT;
- /* Arbitrary, can't find the card's limits */
-- if ((new_marg < 0) || (new_margin > 60))
-+ if ((new_margin < 0) || (new_margin > 60))
- return -EINVAL;
- soft_margin = new_margin;
- watchdog_ping();
---- linux-2.4.27/drivers/char/wdt977.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/char/wdt977.c
-@@ -27,6 +27,7 @@
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-
- #define WATCHDOG_MINOR 130
-
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/Kconfig
-@@ -0,0 +1,38 @@
-+config CPU_FREQ_PROC_INTF
-+ tristate "/proc/cpufreq interface (deprecated)"
-+ depends on CPU_FREQ && PROC_FS
-+ help
-+ This enables the /proc/cpufreq interface for controlling
-+ CPUFreq. Please note that it is recommended to use the sysfs
-+ interface instead (which is built automatically).
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say N.
-+
-+config CPU_FREQ_GOV_USERSPACE
-+ tristate "'userspace' governor for userspace frequency scaling"
-+ depends on CPU_FREQ
-+ help
-+ Enable this cpufreq governor when you either want to set the
-+ CPU frequency manually or when an userspace programm shall
-+ be able to set the CPU dynamically, like on LART
-+ ( http://www.lart.tudelft.nl/ )
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say Y.
-+
-+config CPU_FREQ_24_API
-+ bool "/proc/sys/cpu/ interface (2.4. / OLD)"
-+ depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
-+ help
-+ This enables the /proc/sys/cpu/ sysctl interface for controlling
-+ the CPUFreq,"userspace" governor. This is the same interface
-+ as known from the.4.-kernel patches for CPUFreq, and offers
-+ the same functionality as long as "userspace" is the
-+ selected governor for the specified CPU.
-+
-+ For details, take a look at linux/Documentation/cpufreq.
-+
-+ If in doubt, say N.
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/Makefile
-@@ -0,0 +1,4 @@
-+#CPUfreq governors and cross-arch helpers
-+obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
-+obj-$(CONFIG_CPU_FREQ_PROC_INTF) += proc_intf.o
-+obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/cpufreq.c
-@@ -0,0 +1,720 @@
-+/*
-+ * linux/kernel/cpufreq.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+
-+#include <asm/semaphore.h>
-+/**
-+ * The "cpufreq driver" - the arch- or hardware-dependend low
-+ * level driver of CPUFreq support, and its spinlock. This lock
-+ * also protects the cpufreq_cpu_data array.
-+ */
-+static struct cpufreq_driver *cpufreq_driver;
-+static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
-+static spinlock_t cpufreq_driver_lock = SPIN_LOCK_UNLOCKED;
-+
-+/* internal prototype */
-+static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
-+
-+
-+/**
-+ * Two notifier lists: the "policy" list is involved in the
-+ * validation process for a new CPU frequency policy; the
-+ * "transition" list for kernel code that needs to handle
-+ * changes to devices when the CPU clock speed changes.
-+ * The mutex locks both lists.
-+ */
-+static struct notifier_block *cpufreq_policy_notifier_list;
-+static struct notifier_block *cpufreq_transition_notifier_list;
-+static DECLARE_RWSEM (cpufreq_notifier_rwsem);
-+
-+
-+static LIST_HEAD(cpufreq_governor_list);
-+static DECLARE_MUTEX (cpufreq_governor_sem);
-+
-+/*
-+ * backport info:
-+ * we don't have a kobj we can use for ref-counting, so use a
-+ * "unsigned int policy->use_count" and an "unload_sem" [idea from
-+ * Pat Mochel's struct driver unload_sem] for proper reference counting.
-+ */
-+
-+static struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
-+{
-+ struct cpufreq_policy *data;
-+ unsigned long flags;
-+
-+ if (cpu >= NR_CPUS)
-+ goto err_out;
-+
-+ /* get the cpufreq driver */
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+
-+ if (!cpufreq_driver)
-+ goto err_out_unlock;
-+
-+ /* get the CPU */
-+ data = cpufreq_cpu_data[cpu];
-+
-+ if (!data)
-+ goto err_out_unlock;
-+
-+ if (!data->use_count)
-+ goto err_out_unlock;
-+
-+ data->use_count += 1;
-+
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ return data;
-+
-+ err_out_unlock:
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ err_out:
-+ return NULL;
-+}
-+
-+static void cpufreq_cpu_put(struct cpufreq_policy *data)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ data->use_count -= 1;
-+ if (!data->use_count) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ up(&data->unload_sem);
-+ return;
-+ }
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+}
-+
-+/*********************************************************************
-+ * SYSFS INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_parse_governor - parse a governor string
-+ */
-+int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
-+ struct cpufreq_governor **governor)
-+{
-+ if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
-+ *policy = CPUFREQ_POLICY_PERFORMANCE;
-+ return 0;
-+ } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
-+ *policy = CPUFREQ_POLICY_POWERSAVE;
-+ return 0;
-+ } else {
-+ struct cpufreq_governor *t;
-+ down(&cpufreq_governor_sem);
-+ if (!cpufreq_driver || !cpufreq_driver->target)
-+ goto out;
-+ list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-+ if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
-+ *governor = t;
-+ *policy = CPUFREQ_POLICY_GOVERNOR;
-+ up(&cpufreq_governor_sem);
-+ return 0;
-+ }
-+ }
-+ out:
-+ up(&cpufreq_governor_sem);
-+ }
-+ return -EINVAL;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
-+
-+
-+/* backport info:
-+ * all the sysfs stuff is missing -- of course
-+ */
-+
-+/**
-+ * cpufreq_add_dev - add a CPU device
-+ *
-+ * Adds the cpufreq interface for a CPU device.
-+ */
-+static int cpufreq_add_dev (unsigned int cpu)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy new_policy;
-+ struct cpufreq_policy *policy;
-+ unsigned long flags;
-+
-+ policy = kmalloc(sizeof(struct cpufreq_policy), GFP_KERNEL);
-+ if (!policy)
-+ return -ENOMEM;
-+ memset(policy, 0, sizeof(struct cpufreq_policy));
-+
-+ policy->cpu = cpu;
-+ policy->use_count = 1;
-+ init_MUTEX_LOCKED(&policy->lock);
-+ init_MUTEX_LOCKED(&policy->unload_sem);
-+
-+ /* call driver. From then on the cpufreq must be able
-+ * to accept all calls to ->verify and ->setpolicy for this CPU
-+ */
-+ ret = cpufreq_driver->init(policy);
-+ if (ret)
-+ goto err_out;
-+
-+ memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_cpu_data[cpu] = policy;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ up(&policy->lock);
-+
-+ /* set default policy */
-+ ret = cpufreq_set_policy(&new_policy);
-+ if (ret)
-+ goto err_out_unregister;
-+
-+ return 0;
-+
-+
-+ err_out_unregister:
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_cpu_data[cpu] = NULL;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ err_out:
-+ kfree(policy);
-+ return ret;
-+}
-+
-+
-+/**
-+ * cpufreq_remove_dev - remove a CPU device
-+ *
-+ * Removes the cpufreq interface for a CPU device.
-+ */
-+static int cpufreq_remove_dev (unsigned int cpu)
-+{
-+ unsigned long flags;
-+ struct cpufreq_policy *data;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ data = cpufreq_cpu_data[cpu];
-+ if (!data) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ return -EINVAL;
-+ }
-+ cpufreq_cpu_data[cpu] = NULL;
-+
-+ data->use_count -= 1;
-+ if (!data->use_count) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ up(&data->unload_sem);
-+ } else {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ /* this will sleep until data->use_count gets to zero */
-+ down(&data->unload_sem);
-+ up(&data->unload_sem);
-+ }
-+
-+ if (cpufreq_driver->target)
-+ __cpufreq_governor(data, CPUFREQ_GOV_STOP);
-+
-+ if (cpufreq_driver->exit)
-+ cpufreq_driver->exit(data);
-+
-+ kfree(data);
-+
-+ return 0;
-+}
-+
-+
-+/*********************************************************************
-+ * NOTIFIER LISTS INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_register_notifier - register a driver with cpufreq
-+ * @nb: notifier function to register
-+ * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
-+ *
-+ * Add a driver to one of two lists: either a list of drivers that
-+ * are notified about clock rate changes (once before and once after
-+ * the transition), or a list of drivers that are notified about
-+ * changes in cpufreq policy.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_register.
-+ */
-+int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
-+{
-+ int ret;
-+
-+ down_write(&cpufreq_notifier_rwsem);
-+ switch (list) {
-+ case CPUFREQ_TRANSITION_NOTIFIER:
-+ ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
-+ break;
-+ case CPUFREQ_POLICY_NOTIFIER:
-+ ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+ up_write(&cpufreq_notifier_rwsem);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_register_notifier);
-+
-+
-+/**
-+ * cpufreq_unregister_notifier - unregister a driver with cpufreq
-+ * @nb: notifier block to be unregistered
-+ * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
-+ *
-+ * Remove a driver from the CPU frequency notifier list.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_unregister.
-+ */
-+int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
-+{
-+ int ret;
-+
-+ down_write(&cpufreq_notifier_rwsem);
-+ switch (list) {
-+ case CPUFREQ_TRANSITION_NOTIFIER:
-+ ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
-+ break;
-+ case CPUFREQ_POLICY_NOTIFIER:
-+ ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+ up_write(&cpufreq_notifier_rwsem);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_unregister_notifier);
-+
-+
-+/*********************************************************************
-+ * GOVERNORS *
-+ *********************************************************************/
-+
-+
-+int __cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation)
-+{
-+ return cpufreq_driver->target(policy, target_freq, relation);
-+}
-+EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
-+
-+
-+int cpufreq_driver_target(struct cpufreq_policy *policy,
-+ unsigned int target_freq,
-+ unsigned int relation)
-+{
-+ unsigned int ret;
-+
-+ policy = cpufreq_cpu_get(policy->cpu);
-+ if (!policy)
-+ return -EINVAL;
-+
-+ down(&policy->lock);
-+
-+ ret = __cpufreq_driver_target(policy, target_freq, relation);
-+
-+ up(&policy->lock);
-+
-+ cpufreq_cpu_put(policy);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_driver_target);
-+
-+
-+static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
-+{
-+ int ret = 0;
-+
-+ switch (policy->policy) {
-+ case CPUFREQ_POLICY_POWERSAVE:
-+ if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
-+ ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
-+ }
-+ break;
-+ case CPUFREQ_POLICY_PERFORMANCE:
-+ if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
-+ ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
-+ }
-+ break;
-+ case CPUFREQ_POLICY_GOVERNOR:
-+ ret = policy->governor->governor(policy, event);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+int cpufreq_governor(unsigned int cpu, unsigned int event)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ down(&policy->lock);
-+ ret = __cpufreq_governor(policy, event);
-+ up(&policy->lock);
-+
-+ cpufreq_cpu_put(policy);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_governor);
-+
-+
-+int cpufreq_register_governor(struct cpufreq_governor *governor)
-+{
-+ struct cpufreq_governor *t;
-+
-+ if (!governor)
-+ return -EINVAL;
-+
-+ if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN))
-+ return -EBUSY;
-+ if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
-+ return -EBUSY;
-+
-+ down(&cpufreq_governor_sem);
-+
-+ list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-+ if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-+ up(&cpufreq_governor_sem);
-+ return -EBUSY;
-+ }
-+ }
-+ list_add(&governor->governor_list, &cpufreq_governor_list);
-+
-+ up(&cpufreq_governor_sem);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_register_governor);
-+
-+
-+void cpufreq_unregister_governor(struct cpufreq_governor *governor)
-+{
-+ /* backport info:
-+ * As the module usage count isn't assured in 2.4., check for removal
-+ * of running cpufreq governor
-+ */
-+ unsigned int i;
-+
-+ if (!governor)
-+ return;
-+
-+ down(&cpufreq_governor_sem);
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(i);
-+ if (!policy)
-+ goto done;
-+ down(&policy->lock);
-+
-+ if (policy->policy != CPUFREQ_POLICY_GOVERNOR)
-+ goto unlock_done;
-+ if (policy->governor != governor)
-+ goto unlock_done;
-+
-+ /* stop old one, start performance [always present] */
-+ __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-+ __cpufreq_governor(policy, CPUFREQ_GOV_START);
-+
-+ unlock_done:
-+ up(&policy->lock);
-+ done:
-+ cpufreq_cpu_put(policy);
-+ }
-+ list_del(&governor->governor_list);
-+ up(&cpufreq_governor_sem);
-+ return;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
-+
-+
-+
-+/*********************************************************************
-+ * POLICY INTERFACE *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_get_policy - get the current cpufreq_policy
-+ * @policy: struct cpufreq_policy into which the current cpufreq_policy is written
-+ *
-+ * Reads the current cpufreq policy.
-+ */
-+int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
-+{
-+ struct cpufreq_policy *cpu_policy;
-+ if (!policy)
-+ return -EINVAL;
-+
-+ cpu_policy = cpufreq_cpu_get(cpu);
-+ if (!cpu_policy)
-+ return -EINVAL;
-+
-+ down(&cpu_policy->lock);
-+ memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
-+ up(&cpu_policy->lock);
-+
-+ cpufreq_cpu_put(cpu_policy);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(cpufreq_get_policy);
-+
-+
-+/**
-+ * cpufreq_set_policy - set a new CPUFreq policy
-+ * @policy: policy to be set.
-+ *
-+ * Sets a new CPU frequency and voltage scaling policy.
-+ */
-+int cpufreq_set_policy(struct cpufreq_policy *policy)
-+{
-+ int ret = 0;
-+ struct cpufreq_policy *data;
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ data = cpufreq_cpu_get(policy->cpu);
-+ if (!data)
-+ return -EINVAL;
-+
-+ /* lock this CPU */
-+ down(&data->lock);
-+
-+ memcpy(&policy->cpuinfo,
-+ &data->cpuinfo,
-+ sizeof(struct cpufreq_cpuinfo));
-+
-+ /* verify the cpu speed can be set within this limit */
-+ ret = cpufreq_driver->verify(policy);
-+ if (ret)
-+ goto error_out;
-+
-+ down_read(&cpufreq_notifier_rwsem);
-+
-+ /* adjust if necessary - all reasons */
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
-+ policy);
-+
-+ /* adjust if necessary - hardware incompatibility*/
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE,
-+ policy);
-+
-+ /* verify the cpu speed can be set within this limit,
-+ which might be different to the first one */
-+ ret = cpufreq_driver->verify(policy);
-+ if (ret) {
-+ up_read(&cpufreq_notifier_rwsem);
-+ goto error_out;
-+ }
-+
-+ /* notification of the new policy */
-+ notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
-+ policy);
-+
-+ up_read(&cpufreq_notifier_rwsem);
-+
-+ data->min = policy->min;
-+ data->max = policy->max;
-+
-+ if (cpufreq_driver->setpolicy) {
-+ data->policy = policy->policy;
-+ ret = cpufreq_driver->setpolicy(policy);
-+ } else {
-+ if ((policy->policy != data->policy) ||
-+ ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) {
-+ /* save old, working values */
-+ unsigned int old_pol = data->policy;
-+ struct cpufreq_governor *old_gov = data->governor;
-+
-+ /* end old governor */
-+ __cpufreq_governor(data, CPUFREQ_GOV_STOP);
-+
-+ /* start new governor */
-+ data->policy = policy->policy;
-+ data->governor = policy->governor;
-+ if (__cpufreq_governor(data, CPUFREQ_GOV_START)) {
-+ /* new governor failed, so re-start old one */
-+ data->policy = old_pol;
-+ data->governor = old_gov;
-+ __cpufreq_governor(data, CPUFREQ_GOV_START);
-+ }
-+ /* might be a policy change, too, so fall through */
-+ }
-+ __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
-+ }
-+
-+ error_out:
-+ up(&data->lock);
-+ cpufreq_cpu_put(data);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(cpufreq_set_policy);
-+
-+
-+
-+/*********************************************************************
-+ * EXTERNALLY AFFECTING FREQUENCY CHANGES *
-+ *********************************************************************/
-+
-+/**
-+ * adjust_jiffies - adjust the system "loops_per_jiffy"
-+ *
-+ * This function alters the system "loops_per_jiffy" for the clock
-+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
-+ * systems as each CPU might be scaled differently. So, use the arch
-+ * per-CPU loops_per_jiffy value wherever possible.
-+ */
-+#ifndef CONFIG_SMP
-+static unsigned long l_p_j_ref = 0;
-+static unsigned int l_p_j_ref_freq = 0;
-+
-+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
-+{
-+ if (!l_p_j_ref_freq) {
-+ l_p_j_ref = loops_per_jiffy;
-+ l_p_j_ref_freq = ci->old;
-+ }
-+ if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
-+ (val == CPUFREQ_POSTCHANGE && ci->old > ci->new))
-+ loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
-+}
-+#else
-+#define adjust_jiffies(x...) do {} while (0)
-+#endif
-+
-+
-+/**
-+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
-+ *
-+ * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
-+ * twice on all CPU frequency changes that have external effects.
-+ */
-+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
-+{
-+ down_read(&cpufreq_notifier_rwsem);
-+ switch (state) {
-+ case CPUFREQ_PRECHANGE:
-+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
-+ adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
-+ break;
-+ case CPUFREQ_POSTCHANGE:
-+ adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-+ notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
-+ cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
-+ break;
-+ }
-+ up_read(&cpufreq_notifier_rwsem);
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
-+
-+
-+
-+/*********************************************************************
-+ * REGISTER / UNREGISTER CPUFREQ DRIVER *
-+ *********************************************************************/
-+
-+/**
-+ * cpufreq_register_driver - register a CPU Frequency driver
-+ * @driver_data: A struct cpufreq_driver containing the values#
-+ * submitted by the CPU Frequency driver.
-+ *
-+ * Registers a CPU Frequency driver to this core code. This code
-+ * returns zero on success, -EBUSY when another driver got here first
-+ * (and isn't unregistered in the meantime).
-+ *
-+ */
-+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
-+{
-+ unsigned long flags;
-+ unsigned int i;
-+
-+ if (!driver_data || !driver_data->verify || !driver_data->init ||
-+ ((!driver_data->setpolicy) && (!driver_data->target)))
-+ return -EINVAL;
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ if (cpufreq_driver) {
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+ return -EBUSY;
-+ }
-+ cpufreq_driver = driver_data;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ if (cpu_online(i))
-+ cpufreq_add_dev(i);
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_register_driver);
-+
-+
-+/**
-+ * cpufreq_unregister_driver - unregister the current CPUFreq driver
-+ *
-+ * Unregister the current CPUFreq driver. Only call this if you have
-+ * the right to do so, i.e. if you have succeeded in initialising before!
-+ * Returns zero if successful, and -EINVAL if the cpufreq_driver is
-+ * currently not initialised.
-+ */
-+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
-+{
-+ unsigned long flags;
-+ unsigned int i;
-+
-+ if (!cpufreq_driver || (driver != cpufreq_driver))
-+ return -EINVAL;
-+
-+ for (i=0; i<NR_CPUS; i++) {
-+ if (cpu_online(i))
-+ cpufreq_remove_dev(i);
-+ }
-+
-+ spin_lock_irqsave(&cpufreq_driver_lock, flags);
-+ cpufreq_driver = NULL;
-+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/freq_table.c
-@@ -0,0 +1,203 @@
-+/*
-+ * linux/drivers/cpufreq/freq_table.c
-+ *
-+ * Copyright (C) 2002 - 2003 Dominik Brodowski
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+
-+/*********************************************************************
-+ * FREQUENCY TABLE HELPERS *
-+ *********************************************************************/
-+
-+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table)
-+{
-+ unsigned int min_freq = ~0;
-+ unsigned int max_freq = 0;
-+ unsigned int i = 0;
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if (freq < min_freq)
-+ min_freq = freq;
-+ if (freq > max_freq)
-+ max_freq = freq;
-+ }
-+
-+ policy->min = policy->cpuinfo.min_freq = min_freq;
-+ policy->max = policy->cpuinfo.max_freq = max_freq;
-+
-+ if (policy->min == ~0)
-+ return -EINVAL;
-+ else
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
-+
-+
-+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table)
-+{
-+ unsigned int next_larger = ~0;
-+ unsigned int i = 0;
-+ unsigned int count = 0;
-+
-+ if (!cpu_online(policy->cpu))
-+ return -EINVAL;
-+
-+ cpufreq_verify_within_limits(policy,
-+ policy->cpuinfo.min_freq,
-+ policy->cpuinfo.max_freq);
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if ((freq >= policy->min) && (freq <= policy->max))
-+ count++;
-+ else if ((next_larger > freq) && (freq > policy->max))
-+ next_larger = freq;
-+ }
-+
-+ if (!count)
-+ policy->max = next_larger;
-+
-+ cpufreq_verify_within_limits(policy,
-+ policy->cpuinfo.min_freq,
-+ policy->cpuinfo.max_freq);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
-+
-+
-+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
-+ struct cpufreq_frequency_table *table,
-+ unsigned int target_freq,
-+ unsigned int relation,
-+ unsigned int *index)
-+{
-+ struct cpufreq_frequency_table optimal = { .index = ~0, };
-+ struct cpufreq_frequency_table suboptimal = { .index = ~0, };
-+ unsigned int i;
-+
-+ switch (relation) {
-+ case CPUFREQ_RELATION_H:
-+ optimal.frequency = 0;
-+ suboptimal.frequency = ~0;
-+ break;
-+ case CPUFREQ_RELATION_L:
-+ optimal.frequency = ~0;
-+ suboptimal.frequency = 0;
-+ break;
-+ }
-+
-+ if (!cpu_online(policy->cpu))
-+ return -EINVAL;
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ unsigned int freq = table[i].frequency;
-+ if (freq == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ if ((freq < policy->min) || (freq > policy->max))
-+ continue;
-+ switch(relation) {
-+ case CPUFREQ_RELATION_H:
-+ if (freq <= target_freq) {
-+ if (freq >= optimal.frequency) {
-+ optimal.frequency = freq;
-+ optimal.index = i;
-+ }
-+ } else {
-+ if (freq <= suboptimal.frequency) {
-+ suboptimal.frequency = freq;
-+ suboptimal.index = i;
-+ }
-+ }
-+ break;
-+ case CPUFREQ_RELATION_L:
-+ if (freq >= target_freq) {
-+ if (freq <= optimal.frequency) {
-+ optimal.frequency = freq;
-+ optimal.index = i;
-+ }
-+ } else {
-+ if (freq >= suboptimal.frequency) {
-+ suboptimal.frequency = freq;
-+ suboptimal.index = i;
-+ }
-+ }
-+ break;
-+ }
-+ }
-+ if (optimal.index > i) {
-+ if (suboptimal.index > i)
-+ return -EINVAL;
-+ *index = suboptimal.index;
-+ } else
-+ *index = optimal.index;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
-+
-+static struct cpufreq_frequency_table *show_table[NR_CPUS];
-+/**
-+ * show_scaling_governor - show the current policy for the specified CPU
-+ */
-+static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
-+{
-+ unsigned int i = 0;
-+ unsigned int cpu = policy->cpu;
-+ ssize_t count = 0;
-+ struct cpufreq_frequency_table *table;
-+
-+ if (!show_table[cpu])
-+ return -ENODEV;
-+
-+ table = show_table[cpu];
-+
-+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-+ if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
-+ continue;
-+ count += sprintf(&buf[count], "%d ", table[i].frequency);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+
-+}
-+
-+struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
-+ .attr = { .name = "scaling_available_frequencies", .mode = 0444 },
-+ .show = show_available_freqs,
-+};
-+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
-+
-+/*
-+ * if you use these, you must assure that the frequency table is valid
-+ * all the time between get_attr and put_attr!
-+ */
-+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
-+ unsigned int cpu)
-+{
-+ show_table[cpu] = table;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
-+
-+void cpufreq_frequency_table_put_attr(unsigned int cpu)
-+{
-+ show_table[cpu] = NULL;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
-+
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-+MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
-+MODULE_LICENSE ("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/proc_intf.c
-@@ -0,0 +1,244 @@
-+/*
-+ * linux/drivers/cpufreq/proc_intf.c
-+ *
-+ * Copyright (C) 2002 - 2003 Dominik Brodowski
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/cpufreq.h>
-+#include <linux/ctype.h>
-+#include <linux/proc_fs.h>
-+#include <asm/uaccess.h>
-+
-+
-+/**
-+ * cpufreq_parse_policy - parse a policy string
-+ * @input_string: the string to parse.
-+ * @policy: the policy written inside input_string
-+ *
-+ * This function parses a "policy string" - something the user echo'es into
-+ * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
-+ * If there are invalid/missing entries, they are replaced with current
-+ * cpufreq policy.
-+ */
-+static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
-+{
-+ unsigned int min = 0;
-+ unsigned int max = 0;
-+ unsigned int cpu = 0;
-+ char str_governor[16];
-+ struct cpufreq_policy current_policy;
-+ unsigned int result = -EFAULT;
-+
-+ if (!policy)
-+ return -EINVAL;
-+
-+ policy->min = 0;
-+ policy->max = 0;
-+ policy->policy = 0;
-+ policy->cpu = CPUFREQ_ALL_CPUS;
-+
-+ if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4)
-+ {
-+ policy->min = min;
-+ policy->max = max;
-+ policy->cpu = cpu;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
-+ {
-+ if (!cpufreq_get_policy(&current_policy, cpu)) {
-+ policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-+ policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-+ policy->cpu = cpu;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ }
-+
-+ if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3)
-+ {
-+ policy->min = min;
-+ policy->max = max;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+
-+ if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
-+ {
-+ if (!cpufreq_get_policy(&current_policy, cpu)) {
-+ policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-+ policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-+ result = 0;
-+ goto scan_policy;
-+ }
-+ }
-+
-+ return -EINVAL;
-+
-+scan_policy:
-+ result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
-+
-+ return result;
-+}
-+
-+/**
-+ * cpufreq_proc_read - read /proc/cpufreq
-+ *
-+ * This function prints out the current cpufreq policy.
-+ */
-+static int cpufreq_proc_read (
-+ char *page,
-+ char **start,
-+ off_t off,
-+ int count,
-+ int *eof,
-+ void *data)
-+{
-+ char *p = page;
-+ int len = 0;
-+ struct cpufreq_policy policy;
-+ unsigned int min_pctg = 0;
-+ unsigned int max_pctg = 0;
-+ unsigned int i = 0;
-+
-+ if (off != 0)
-+ goto end;
-+
-+ p += sprintf(p, " minimum CPU frequency - maximum CPU frequency - policy\n");
-+ for (i=0;i<NR_CPUS;i++) {
-+ if (!cpu_online(i))
-+ continue;
-+
-+ if (cpufreq_get_policy(&policy, i))
-+ continue;
-+
-+ if (!policy.cpuinfo.max_freq)
-+ continue;
-+
-+ min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
-+ max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
-+
-+ p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ",
-+ i , policy.min, min_pctg, policy.max, max_pctg);
-+ switch (policy.policy) {
-+ case CPUFREQ_POLICY_POWERSAVE:
-+ p += sprintf(p, "powersave\n");
-+ break;
-+ case CPUFREQ_POLICY_PERFORMANCE:
-+ p += sprintf(p, "performance\n");
-+ break;
-+ case CPUFREQ_POLICY_GOVERNOR:
-+ p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
-+ break;
-+ default:
-+ p += sprintf(p, "INVALID\n");
-+ break;
-+ }
-+ }
-+end:
-+ len = (p - page);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len>count)
-+ len = count;
-+ if (len<0)
-+ len = 0;
-+
-+ return len;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_write - handles writing into /proc/cpufreq
-+ *
-+ * This function calls the parsing script and then sets the policy
-+ * accordingly.
-+ */
-+static int cpufreq_proc_write (
-+ struct file *file,
-+ const char *buffer,
-+ unsigned long count,
-+ void *data)
-+{
-+ int result = 0;
-+ char proc_string[42] = {'\0'};
-+ struct cpufreq_policy policy;
-+ unsigned int i = 0;
-+
-+
-+ if ((count > sizeof(proc_string) - 1))
-+ return -EINVAL;
-+
-+ if (copy_from_user(proc_string, buffer, count))
-+ return -EFAULT;
-+
-+ proc_string[count] = '\0';
-+
-+ result = cpufreq_parse_policy(proc_string, &policy);
-+ if (result)
-+ return -EFAULT;
-+
-+ if (policy.cpu == CPUFREQ_ALL_CPUS)
-+ {
-+ for (i=0; i<NR_CPUS; i++)
-+ {
-+ policy.cpu = i;
-+ if (cpu_online(i))
-+ cpufreq_set_policy(&policy);
-+ }
-+ }
-+ else
-+ cpufreq_set_policy(&policy);
-+
-+ return count;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_init - add "cpufreq" to the /proc root directory
-+ *
-+ * This function adds "cpufreq" to the /proc root directory.
-+ */
-+static int __init cpufreq_proc_init (void)
-+{
-+ struct proc_dir_entry *entry = NULL;
-+
-+ /* are these acceptable values? */
-+ entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR,
-+ &proc_root);
-+
-+ if (!entry) {
-+ printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
-+ return -EIO;
-+ } else {
-+ entry->read_proc = cpufreq_proc_read;
-+ entry->write_proc = cpufreq_proc_write;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+/**
-+ * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
-+ *
-+ * This function removes "cpufreq" from the /proc root directory.
-+ */
-+static void __exit cpufreq_proc_exit (void)
-+{
-+ remove_proc_entry("cpufreq", &proc_root);
-+ return;
-+}
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
-+MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
-+MODULE_LICENSE ("GPL");
-+
-+module_init(cpufreq_proc_init);
-+module_exit(cpufreq_proc_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/cpufreq/userspace.c
-@@ -0,0 +1,591 @@
-+/*
-+ * drivers/cpufreq/userspace.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
-+ *
-+ * $Id: userspace.c,v 1.4 2003/03/07 10:30:20 db Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/smp.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/interrupt.h>
-+#include <linux/ctype.h>
-+#include <linux/cpufreq.h>
-+#include <linux/sysctl.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/sysfs.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define CTL_CPU_VARS_SPEED_MAX(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ_MAX, \
-+ .data = &cpu_max_freq[cpunr], \
-+ .procname = "speed-max", \
-+ .maxlen = sizeof(cpu_max_freq[cpunr]),\
-+ .mode = 0444, \
-+ .proc_handler = proc_dointvec, }
-+
-+#define CTL_CPU_VARS_SPEED_MIN(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ_MIN, \
-+ .data = &cpu_min_freq[cpunr], \
-+ .procname = "speed-min", \
-+ .maxlen = sizeof(cpu_min_freq[cpunr]),\
-+ .mode = 0444, \
-+ .proc_handler = proc_dointvec, }
-+
-+#define CTL_CPU_VARS_SPEED(cpunr) { \
-+ .ctl_name = CPU_NR_FREQ, \
-+ .procname = "speed", \
-+ .mode = 0644, \
-+ .proc_handler = cpufreq_procctl, \
-+ .strategy = cpufreq_sysctl, \
-+ .extra1 = (void*) (cpunr), }
-+
-+#define CTL_TABLE_CPU_VARS(cpunr) static ctl_table ctl_cpu_vars_##cpunr[] = {\
-+ CTL_CPU_VARS_SPEED_MAX(cpunr), \
-+ CTL_CPU_VARS_SPEED_MIN(cpunr), \
-+ CTL_CPU_VARS_SPEED(cpunr), \
-+ { .ctl_name = 0, }, }
-+
-+/* the ctl_table entry for each CPU */
-+#define CPU_ENUM(s) { \
-+ .ctl_name = (CPU_NR + s), \
-+ .procname = #s, \
-+ .mode = 0555, \
-+ .child = ctl_cpu_vars_##s }
-+
-+/**
-+ * A few values needed by the userspace governor
-+ */
-+static unsigned int cpu_max_freq[NR_CPUS];
-+static unsigned int cpu_min_freq[NR_CPUS];
-+static unsigned int cpu_cur_freq[NR_CPUS];
-+static unsigned int cpu_is_managed[NR_CPUS];
-+static struct cpufreq_policy current_policy[NR_CPUS];
-+
-+static DECLARE_MUTEX (userspace_sem);
-+
-+
-+/* keep track of frequency transitions */
-+static int
-+userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-+ void *data)
-+{
-+ struct cpufreq_freqs *freq = data;
-+
-+ cpu_cur_freq[freq->cpu] = freq->new;
-+
-+ return 0;
-+}
-+
-+static struct notifier_block userspace_cpufreq_notifier_block = {
-+ .notifier_call = userspace_cpufreq_notifier
-+};
-+
-+
-+/**
-+ * cpufreq_set - set the CPU frequency
-+ * @freq: target frequency in kHz
-+ * @cpu: CPU for which the frequency is to be set
-+ *
-+ * Sets the CPU frequency to freq.
-+ */
-+int cpufreq_set(unsigned int freq, unsigned int cpu)
-+{
-+ int ret = -EINVAL;
-+
-+ down(&userspace_sem);
-+ if (!cpu_is_managed[cpu])
-+ goto err;
-+
-+ if (freq < cpu_min_freq[cpu])
-+ freq = cpu_min_freq[cpu];
-+ if (freq > cpu_max_freq[cpu])
-+ freq = cpu_max_freq[cpu];
-+
-+ ret = cpufreq_driver_target(&current_policy[cpu], freq,
-+ CPUFREQ_RELATION_L);
-+
-+ err:
-+ up(&userspace_sem);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_set);
-+
-+
-+/**
-+ * cpufreq_setmax - set the CPU to the maximum frequency
-+ * @cpu - affected cpu;
-+ *
-+ * Sets the CPU frequency to the maximum frequency supported by
-+ * this CPU.
-+ */
-+int cpufreq_setmax(unsigned int cpu)
-+{
-+ if (!cpu_is_managed[cpu] || !cpu_online(cpu))
-+ return -EINVAL;
-+ return cpufreq_set(cpu_max_freq[cpu], cpu);
-+}
-+EXPORT_SYMBOL_GPL(cpufreq_setmax);
-+
-+
-+/**
-+ * cpufreq_get - get the current CPU frequency (in kHz)
-+ * @cpu: CPU number
-+ *
-+ * Get the CPU current (static) CPU frequency
-+ */
-+unsigned int cpufreq_get(unsigned int cpu)
-+{
-+ return cpu_cur_freq[cpu];
-+}
-+EXPORT_SYMBOL(cpufreq_get);
-+
-+
-+#ifdef CONFIG_CPU_FREQ_24_API
-+
-+
-+/*********************** cpufreq_sysctl interface ********************/
-+static int
-+cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ char buf[16], *p;
-+ int cpu = (int) ctl->extra1;
-+ int len, left = *lenp;
-+
-+ if (!left || (filp->f_pos && !write) || !cpu_online(cpu)) {
-+ *lenp = 0;
-+ return 0;
-+ }
-+
-+ if (write) {
-+ unsigned int freq;
-+
-+ len = left;
-+ if (left > sizeof(buf))
-+ left = sizeof(buf);
-+ if (copy_from_user(buf, buffer, left))
-+ return -EFAULT;
-+ buf[sizeof(buf) - 1] = '\0';
-+
-+ freq = simple_strtoul(buf, &p, 0);
-+ cpufreq_set(freq, cpu);
-+ } else {
-+ len = sprintf(buf, "%d\n", cpufreq_get(cpu));
-+ if (len > left)
-+ len = left;
-+ if (copy_to_user(buffer, buf, len))
-+ return -EFAULT;
-+ }
-+
-+ *lenp = len;
-+ filp->f_pos += len;
-+ return 0;
-+}
-+
-+static int
-+cpufreq_sysctl(ctl_table *table, int *name, int nlen,
-+ void *oldval, size_t *oldlenp,
-+ void *newval, size_t newlen, void **context)
-+{
-+ int cpu = (int) table->extra1;
-+
-+ if (!cpu_online(cpu))
-+ return -EINVAL;
-+
-+ if (oldval && oldlenp) {
-+ size_t oldlen;
-+
-+ if (get_user(oldlen, oldlenp))
-+ return -EFAULT;
-+
-+ if (oldlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
-+ put_user(sizeof(unsigned int), oldlenp))
-+ return -EFAULT;
-+ }
-+ if (newval && newlen) {
-+ unsigned int freq;
-+
-+ if (newlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (get_user(freq, (unsigned int *)newval))
-+ return -EFAULT;
-+
-+ cpufreq_set(freq, cpu);
-+ }
-+ return 1;
-+}
-+
-+/* ctl_table ctl_cpu_vars_{0,1,...,(NR_CPUS-1)} */
-+/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
-+ CTL_TABLE_CPU_VARS(0);
-+#if NR_CPUS > 1
-+ CTL_TABLE_CPU_VARS(1);
-+#endif
-+#if NR_CPUS > 2
-+ CTL_TABLE_CPU_VARS(2);
-+#endif
-+#if NR_CPUS > 3
-+ CTL_TABLE_CPU_VARS(3);
-+#endif
-+#if NR_CPUS > 4
-+ CTL_TABLE_CPU_VARS(4);
-+#endif
-+#if NR_CPUS > 5
-+ CTL_TABLE_CPU_VARS(5);
-+#endif
-+#if NR_CPUS > 6
-+ CTL_TABLE_CPU_VARS(6);
-+#endif
-+#if NR_CPUS > 7
-+ CTL_TABLE_CPU_VARS(7);
-+#endif
-+#if NR_CPUS > 8
-+ CTL_TABLE_CPU_VARS(8);
-+#endif
-+#if NR_CPUS > 9
-+ CTL_TABLE_CPU_VARS(9);
-+#endif
-+#if NR_CPUS > 10
-+ CTL_TABLE_CPU_VARS(10);
-+#endif
-+#if NR_CPUS > 11
-+ CTL_TABLE_CPU_VARS(11);
-+#endif
-+#if NR_CPUS > 12
-+ CTL_TABLE_CPU_VARS(12);
-+#endif
-+#if NR_CPUS > 13
-+ CTL_TABLE_CPU_VARS(13);
-+#endif
-+#if NR_CPUS > 14
-+ CTL_TABLE_CPU_VARS(14);
-+#endif
-+#if NR_CPUS > 15
-+ CTL_TABLE_CPU_VARS(15);
-+#endif
-+#if NR_CPUS > 16
-+ CTL_TABLE_CPU_VARS(16);
-+#endif
-+#if NR_CPUS > 17
-+ CTL_TABLE_CPU_VARS(17);
-+#endif
-+#if NR_CPUS > 18
-+ CTL_TABLE_CPU_VARS(18);
-+#endif
-+#if NR_CPUS > 19
-+ CTL_TABLE_CPU_VARS(19);
-+#endif
-+#if NR_CPUS > 20
-+ CTL_TABLE_CPU_VARS(20);
-+#endif
-+#if NR_CPUS > 21
-+ CTL_TABLE_CPU_VARS(21);
-+#endif
-+#if NR_CPUS > 22
-+ CTL_TABLE_CPU_VARS(22);
-+#endif
-+#if NR_CPUS > 23
-+ CTL_TABLE_CPU_VARS(23);
-+#endif
-+#if NR_CPUS > 24
-+ CTL_TABLE_CPU_VARS(24);
-+#endif
-+#if NR_CPUS > 25
-+ CTL_TABLE_CPU_VARS(25);
-+#endif
-+#if NR_CPUS > 26
-+ CTL_TABLE_CPU_VARS(26);
-+#endif
-+#if NR_CPUS > 27
-+ CTL_TABLE_CPU_VARS(27);
-+#endif
-+#if NR_CPUS > 28
-+ CTL_TABLE_CPU_VARS(28);
-+#endif
-+#if NR_CPUS > 29
-+ CTL_TABLE_CPU_VARS(29);
-+#endif
-+#if NR_CPUS > 30
-+ CTL_TABLE_CPU_VARS(30);
-+#endif
-+#if NR_CPUS > 31
-+ CTL_TABLE_CPU_VARS(31);
-+#endif
-+#if NR_CPUS > 32
-+#error please extend CPU enumeration
-+#endif
-+
-+/* due to NR_CPUS tweaking, a lot of if/endifs are required, sorry */
-+static ctl_table ctl_cpu_table[NR_CPUS + 1] = {
-+ CPU_ENUM(0),
-+#if NR_CPUS > 1
-+ CPU_ENUM(1),
-+#endif
-+#if NR_CPUS > 2
-+ CPU_ENUM(2),
-+#endif
-+#if NR_CPUS > 3
-+ CPU_ENUM(3),
-+#endif
-+#if NR_CPUS > 4
-+ CPU_ENUM(4),
-+#endif
-+#if NR_CPUS > 5
-+ CPU_ENUM(5),
-+#endif
-+#if NR_CPUS > 6
-+ CPU_ENUM(6),
-+#endif
-+#if NR_CPUS > 7
-+ CPU_ENUM(7),
-+#endif
-+#if NR_CPUS > 8
-+ CPU_ENUM(8),
-+#endif
-+#if NR_CPUS > 9
-+ CPU_ENUM(9),
-+#endif
-+#if NR_CPUS > 10
-+ CPU_ENUM(10),
-+#endif
-+#if NR_CPUS > 11
-+ CPU_ENUM(11),
-+#endif
-+#if NR_CPUS > 12
-+ CPU_ENUM(12),
-+#endif
-+#if NR_CPUS > 13
-+ CPU_ENUM(13),
-+#endif
-+#if NR_CPUS > 14
-+ CPU_ENUM(14),
-+#endif
-+#if NR_CPUS > 15
-+ CPU_ENUM(15),
-+#endif
-+#if NR_CPUS > 16
-+ CPU_ENUM(16),
-+#endif
-+#if NR_CPUS > 17
-+ CPU_ENUM(17),
-+#endif
-+#if NR_CPUS > 18
-+ CPU_ENUM(18),
-+#endif
-+#if NR_CPUS > 19
-+ CPU_ENUM(19),
-+#endif
-+#if NR_CPUS > 20
-+ CPU_ENUM(20),
-+#endif
-+#if NR_CPUS > 21
-+ CPU_ENUM(21),
-+#endif
-+#if NR_CPUS > 22
-+ CPU_ENUM(22),
-+#endif
-+#if NR_CPUS > 23
-+ CPU_ENUM(23),
-+#endif
-+#if NR_CPUS > 24
-+ CPU_ENUM(24),
-+#endif
-+#if NR_CPUS > 25
-+ CPU_ENUM(25),
-+#endif
-+#if NR_CPUS > 26
-+ CPU_ENUM(26),
-+#endif
-+#if NR_CPUS > 27
-+ CPU_ENUM(27),
-+#endif
-+#if NR_CPUS > 28
-+ CPU_ENUM(28),
-+#endif
-+#if NR_CPUS > 29
-+ CPU_ENUM(29),
-+#endif
-+#if NR_CPUS > 30
-+ CPU_ENUM(30),
-+#endif
-+#if NR_CPUS > 31
-+ CPU_ENUM(31),
-+#endif
-+#if NR_CPUS > 32
-+#error please extend CPU enumeration
-+#endif
-+ {
-+ .ctl_name = 0,
-+ }
-+};
-+
-+static ctl_table ctl_cpu[2] = {
-+ {
-+ .ctl_name = CTL_CPU,
-+ .procname = "cpu",
-+ .mode = 0555,
-+ .child = ctl_cpu_table,
-+ },
-+ {
-+ .ctl_name = 0,
-+ }
-+};
-+
-+struct ctl_table_header *cpufreq_sysctl_table;
-+
-+static inline void cpufreq_sysctl_init(void)
-+{
-+ cpufreq_sysctl_table = register_sysctl_table(ctl_cpu, 0);
-+}
-+
-+static inline void cpufreq_sysctl_exit(void)
-+{
-+ unregister_sysctl_table(cpufreq_sysctl_table);
-+}
-+
-+#else
-+#define cpufreq_sysctl_init() do {} while(0)
-+#define cpufreq_sysctl_exit() do {} while(0)
-+#endif /* CONFIG_CPU_FREQ_24API */
-+
-+
-+/************************** sysfs interface ************************/
-+static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
-+{
-+ return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
-+}
-+
-+static ssize_t
-+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
-+{
-+ unsigned int freq = 0;
-+ unsigned int ret;
-+
-+ ret = sscanf (buf, "%u", &freq);
-+ if (ret != 1)
-+ return -EINVAL;
-+
-+ cpufreq_set(freq, policy->cpu);
-+
-+ return count;
-+}
-+
-+static struct freq_attr freq_attr_scaling_setspeed = {
-+ .attr = { .name = "scaling_setspeed", .mode = 0644 },
-+ .show = show_speed,
-+ .store = store_speed,
-+};
-+
-+static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
-+ unsigned int event)
-+{
-+ unsigned int cpu = policy->cpu;
-+ switch (event) {
-+ case CPUFREQ_GOV_START:
-+ if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) ||
-+ !policy->cur)
-+ return -EINVAL;
-+ down(&userspace_sem);
-+ cpu_is_managed[cpu] = 1;
-+ cpu_min_freq[cpu] = policy->min;
-+ cpu_max_freq[cpu] = policy->max;
-+ cpu_cur_freq[cpu] = policy->cur;
-+ sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
-+ memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
-+ up(&userspace_sem);
-+ break;
-+ case CPUFREQ_GOV_STOP:
-+ down(&userspace_sem);
-+ cpu_is_managed[cpu] = 0;
-+ cpu_min_freq[cpu] = 0;
-+ cpu_max_freq[cpu] = 0;
-+ sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
-+ up(&userspace_sem);
-+ module_put(THIS_MODULE);
-+ break;
-+ case CPUFREQ_GOV_LIMITS:
-+ down(&userspace_sem);
-+ cpu_min_freq[cpu] = policy->min;
-+ cpu_max_freq[cpu] = policy->max;
-+ if (policy->max < cpu_cur_freq[cpu])
-+ cpufreq_driver_target(&current_policy[cpu], policy->max,
-+ CPUFREQ_RELATION_H);
-+ else if (policy->min > cpu_cur_freq[cpu])
-+ cpufreq_driver_target(&current_policy[cpu], policy->min,
-+ CPUFREQ_RELATION_L);
-+ memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
-+ up(&userspace_sem);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+/* on ARM SA1100 we need to rely on the values of cpufreq_get() - because
-+ * of this, cpu_cur_freq[] needs to be set early.
-+ */
-+#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_SA1100)
-+extern unsigned int sa11x0_getspeed(void);
-+
-+static void cpufreq_sa11x0_compat(void)
-+{
-+ cpu_cur_freq[0] = sa11x0_getspeed();
-+}
-+#else
-+#define cpufreq_sa11x0_compat() do {} while(0)
-+#endif
-+
-+
-+static struct cpufreq_governor cpufreq_gov_userspace = {
-+ .name = "userspace",
-+ .governor = cpufreq_governor_userspace,
-+ .owner = THIS_MODULE,
-+};
-+EXPORT_SYMBOL(cpufreq_gov_userspace);
-+
-+static int already_init = 0;
-+
-+int cpufreq_gov_userspace_init(void)
-+{
-+ if (!already_init) {
-+ down(&userspace_sem);
-+ cpufreq_sa11x0_compat();
-+ cpufreq_sysctl_init();
-+ cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-+ already_init = 1;
-+ up(&userspace_sem);
-+ }
-+ return cpufreq_register_governor(&cpufreq_gov_userspace);
-+}
-+EXPORT_SYMBOL(cpufreq_gov_userspace_init);
-+
-+
-+static void __exit cpufreq_gov_userspace_exit(void)
-+{
-+ cpufreq_unregister_governor(&cpufreq_gov_userspace);
-+ cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-+ cpufreq_sysctl_exit();
-+}
-+
-+
-+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
-+MODULE_LICENSE ("GPL");
-+
-+module_init(cpufreq_gov_userspace_init);
-+module_exit(cpufreq_gov_userspace_exit);
---- linux-2.4.27/drivers/i2c/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/Config.in
-@@ -17,6 +17,15 @@
- int ' GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
- int ' GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
- fi
-+
-+ dep_tristate ' Guide GPIO adapter' CONFIG_I2C_GUIDE $CONFIG_I2C_ALGOBIT
-+ if [ "$CONFIG_ARCH_OMAHA" = "y" ]; then
-+ dep_tristate ' Omaha I2C interface' CONFIG_I2C_OMAHA $CONFIG_I2C
-+ fi
-+ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ dep_tristate ' Frodo I2C adapter' CONFIG_I2C_FRODO $CONFIG_I2C_ALGOBIT
-+ dep_tristate ' SA1100 I2C GPIO adapter' CONFIG_I2C_BIT_SA1100_GPIO $CONFIG_I2C_ALGOBIT
-+ fi
- fi
-
- dep_tristate 'NatSemi SCx200 ACCESS.bus' CONFIG_SCx200_ACB $CONFIG_I2C
-@@ -49,6 +58,10 @@
- dep_tristate 'Keywest I2C interface in Apple Core99 machines' CONFIG_I2C_KEYWEST $CONFIG_I2C
- fi
-
-+ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ] ; then
-+ dep_tristate 'Atmel AT91RM9200 I2C Two-Wire interface (TWI)' CONFIG_I2C_AT91 $CONFIG_I2C
-+ fi
-+
- if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
- dep_tristate 'SiByte SMBus interface' CONFIG_I2C_ALGO_SIBYTE $CONFIG_I2C
- dep_tristate ' MAX1617 Temperature Sensor' CONFIG_I2C_MAX1617 $CONFIG_I2C_ALGO_SIBYTE
---- linux-2.4.27/drivers/i2c/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/Makefile
-@@ -8,12 +8,21 @@
- i2c-algo-ite.o i2c-algo-sibyte.o i2c-algo-sgi.o \
- i2c-proc.o
-
-+# Init order: core, chardev, bit adapters, pcf adapters
-+
- obj-$(CONFIG_I2C) += i2c-core.o
- obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
-+
-+# Bit adapters
- obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
- obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o
- obj-$(CONFIG_I2C_ELV) += i2c-elv.o
- obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o
-+obj-$(CONFIG_I2C_GUIDE) += i2c-guide.o
-+obj-$(CONFIG_I2C_FRODO) += i2c-frodo.o
-+obj-$(CONFIG_I2C_OMAHA) += i2c-omaha.o
-+
-+# PCF adapters
- obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
- obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
- obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o
-@@ -30,4 +39,3 @@
- # This is needed for automatic patch generation: sensors code ends here
-
- include $(TOPDIR)/Rules.make
--
---- linux-2.4.27/drivers/i2c/i2c-algo-bit.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-algo-bit.c
-@@ -169,7 +169,14 @@
- * 1 if the device acknowledged
- * 0 if the device did not ack
- * -ETIMEDOUT if an error occurred (while raising the scl line)
-- */
-+
-+ * tsong@iders.ca: an instruction to disable any timeconsuming interrupt
-+ here except the heart beat of timer2 should be added before setsda(adap, sb).
-+ because when interrupt occurs during
-+ scl is set high, the interrupt service routine is served and may take long,
-+ after the interrupt returns, sda could be sampled by the device(slave)
-+ more than once, and this cause error problem.
-+*/
- static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
- {
- int i;
-@@ -582,9 +589,7 @@
- printk("\n");
- }
-
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- i2c_add_adapter(adap);
-
- return 0;
-@@ -600,15 +605,13 @@
-
- DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name));
-
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- return 0;
- }
-
--int __init i2c_algo_bit_init (void)
-+static int __init i2c_algo_bit_init (void)
- {
-- printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module\n");
-+ printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n");
- return 0;
- }
-
-@@ -617,7 +620,6 @@
- EXPORT_SYMBOL(i2c_bit_add_bus);
- EXPORT_SYMBOL(i2c_bit_del_bus);
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
- MODULE_LICENSE("GPL");
-@@ -631,12 +633,4 @@
- MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
-
--int init_module(void)
--{
-- return i2c_algo_bit_init();
--}
--
--void cleanup_module(void)
--{
--}
--#endif
-+module_init(i2c_algo_bit_init);
---- linux-2.4.27/drivers/i2c/i2c-algo-pcf.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-algo-pcf.c
-@@ -475,9 +475,7 @@
- return i;
- }
-
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
-
- i2c_add_adapter(adap);
-
-@@ -515,13 +513,11 @@
- return res;
- DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name));
-
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- return 0;
- }
-
--int __init i2c_algo_pcf_init (void)
-+static int __init i2c_algo_pcf_init (void)
- {
- printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
- return 0;
-@@ -531,7 +527,6 @@
- EXPORT_SYMBOL(i2c_pcf_add_bus);
- EXPORT_SYMBOL(i2c_pcf_del_bus);
-
--#ifdef MODULE
- MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
- MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
- MODULE_LICENSE("GPL");
-@@ -543,13 +538,4 @@
- MODULE_PARM_DESC(i2c_debug,
- "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
-
--
--int init_module(void)
--{
-- return i2c_algo_pcf_init();
--}
--
--void cleanup_module(void)
--{
--}
--#endif
-+module_init(i2c_algo_pcf_init);
---- linux-2.4.27/drivers/i2c/i2c-core.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-core.c
-@@ -41,7 +41,7 @@
-
- /* exclusive access to the bus */
- #define I2C_LOCK(adap) down(&adap->lock)
--#define I2C_UNLOCK(adap) up(&adap->lock)
-+#define I2C_UNLOCK(adap) up(&adap->lock)
-
- #define ADAP_LOCK() down(&adap_lock)
- #define ADAP_UNLOCK() up(&adap_lock)
-@@ -67,7 +67,7 @@
- static int driver_count;
-
- /**** debug level */
--static int i2c_debug=1;
-+static int i2c_debug = 0;
-
- /* ---------------------------------------------------
- * /proc entry declarations
-@@ -77,14 +77,14 @@
- #ifdef CONFIG_PROC_FS
-
- static int i2cproc_init(void);
--static int i2cproc_cleanup(void);
-+static void i2cproc_cleanup(void);
-
--static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
-+static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
- loff_t *ppos);
- static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
- int *eof , void *private);
-
--/* To implement the dynamic /proc/bus/i2c-? files, we need our own
-+/* To implement the dynamic /proc/bus/i2c-? files, we need our own
- implementation of the read hook */
- static struct file_operations i2cproc_operations = {
- read: i2cproc_bus_read,
-@@ -101,8 +101,8 @@
-
-
- /* ---------------------------------------------------
-- * registering functions
-- * ---------------------------------------------------
-+ * registering functions
-+ * ---------------------------------------------------
- */
-
- /* -----
-@@ -119,7 +119,7 @@
- if (NULL == adapters[i])
- break;
- if (I2C_ADAP_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n",
- adap->name);
- res = -ENOMEM;
-@@ -129,7 +129,7 @@
- adapters[i] = adap;
- adap_count++;
- ADAP_UNLOCK();
--
-+
- /* init data types */
- init_MUTEX(&adap->lock);
-
-@@ -157,18 +157,18 @@
- #endif /* def CONFIG_PROC_FS */
-
- /* inform drivers of new adapters */
-- DRV_LOCK();
-+ DRV_LOCK();
- for (j=0;j<I2C_DRIVER_MAX;j++)
-- if (drivers[j]!=NULL &&
-+ if (drivers[j]!=NULL &&
- (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY)))
- /* We ignore the return code; if it fails, too bad */
- drivers[j]->attach_adapter(adap);
- DRV_UNLOCK();
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
- adap->name,i));
-
-- return 0;
-+ return 0;
-
-
- ERROR1:
-@@ -203,13 +203,13 @@
- * this or hell will break loose...
- */
- DRV_LOCK();
-- for (j = 0; j < I2C_DRIVER_MAX; j++)
-+ for (j = 0; j < I2C_DRIVER_MAX; j++)
- if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
- if ((res = drivers[j]->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
- "while detaching driver %s: driver not "
- "detached!",adap->name,drivers[j]->name);
-- goto ERROR1;
-+ goto ERROR1;
- }
- DRV_UNLOCK();
-
-@@ -241,8 +241,8 @@
-
- adapters[i] = NULL;
- adap_count--;
--
-- ADAP_UNLOCK();
-+
-+ ADAP_UNLOCK();
- DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
- return 0;
-
-@@ -269,7 +269,7 @@
- if (NULL == drivers[i])
- break;
- if (I2C_DRIVER_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: register_driver(%s) "
- "- enlarge I2C_DRIVER_MAX.\n",
- driver->name);
-@@ -279,11 +279,11 @@
-
- drivers[i] = driver;
- driver_count++;
--
-+
- DRV_UNLOCK(); /* driver was successfully added */
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
--
-+
- ADAP_LOCK();
-
- /* now look for instances of driver on our adapters
-@@ -314,11 +314,11 @@
- return -ENODEV;
- }
- /* Have a look at each adapter, if clients of this driver are still
-- * attached. If so, detach them to be able to kill the driver
-+ * attached. If so, detach them to be able to kill the driver
- * afterwards.
- */
- DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n"));
-- /* removing clients does not depend on the notify flag, else
-+ /* removing clients does not depend on the notify flag, else
- * invalid operation might (will!) result, when using stale client
- * pointers.
- */
-@@ -333,7 +333,7 @@
- /* DUMMY drivers do not register their clients, so we have to
- * use a trick here: we call driver->attach_adapter to
- * *detach* it! Of course, each dummy driver should know about
-- * this or hell will break loose...
-+ * this or hell will break loose...
- */
- if ((res = driver->attach_adapter(adap))) {
- printk(KERN_WARNING "i2c-core.o: while unregistering "
-@@ -345,9 +345,9 @@
- return res;
- }
- } else {
-- for (j=0;j<I2C_CLIENT_MAX;j++) {
-+ for (j=0;j<I2C_CLIENT_MAX;j++) {
- struct i2c_client *client = adap->clients[j];
-- if (client != NULL &&
-+ if (client != NULL &&
- client->driver == driver) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: "
- "detaching client %s:\n",
-@@ -376,7 +376,7 @@
- drivers[i] = NULL;
- driver_count--;
- DRV_UNLOCK();
--
-+
- DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
- return 0;
- }
-@@ -384,7 +384,7 @@
- int i2c_check_addr (struct i2c_adapter *adapter, int addr)
- {
- int i;
-- for (i = 0; i < I2C_CLIENT_MAX ; i++)
-+ for (i = 0; i < I2C_CLIENT_MAX ; i++)
- if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
- return -EBUSY;
- return 0;
-@@ -402,7 +402,7 @@
- if (NULL == adapter->clients[i])
- break;
- if (I2C_CLIENT_MAX == i) {
-- printk(KERN_WARNING
-+ printk(KERN_WARNING
- " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n",
- client->name);
- return -ENOMEM;
-@@ -410,9 +410,9 @@
-
- adapter->clients[i] = client;
- adapter->client_count++;
--
-- if (adapter->client_register)
-- if (adapter->client_register(client))
-+
-+ if (adapter->client_register)
-+ if (adapter->client_register(client))
- printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
- "to have failed for client %02x at adapter %s\n",
- client->addr,adapter->name);
-@@ -421,7 +421,7 @@
-
- if(client->flags & I2C_CLIENT_ALLOW_USE)
- client->usage_count = 0;
--
-+
- return 0;
- }
-
-@@ -440,12 +440,12 @@
- client->name);
- return -ENODEV;
- }
--
-- if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
-+
-+ if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
- (client->usage_count>0))
- return -EBUSY;
--
-- if (adapter->client_unregister != NULL)
-+
-+ if (adapter->client_unregister != NULL)
- if ((res = adapter->client_unregister(client))) {
- printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
- "client not detached",client->name);
-@@ -471,7 +471,7 @@
-
- void i2c_dec_use_client(struct i2c_client *client)
- {
--
-+
- if (client->driver->dec_use != NULL)
- client->driver->dec_use(client);
-
-@@ -479,65 +479,65 @@
- client->adapter->dec_use(client->adapter);
- }
-
--struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
-+struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
- struct i2c_client *prev)
- {
- int i,j;
--
-+
- /* Will iterate through the list of clients in each adapter of adapters-list
-- in search for a client that matches the search criteria. driver_id or
-- adapter_id are ignored if set to 0. If both are ignored this returns
-+ in search for a client that matches the search criteria. driver_id or
-+ adapter_id are ignored if set to 0. If both are ignored this returns
- first client found. */
--
-- i = j = 0;
--
-- /* set starting point */
-+
-+ i = j = 0;
-+
-+ /* set starting point */
- if(prev)
- {
- if(!(prev->adapter))
- return (struct i2c_client *) -EINVAL;
--
-+
- for(j=0; j < I2C_ADAP_MAX; j++)
- if(prev->adapter == adapters[j])
- break;
--
-+
- /* invalid starting point? */
- if (I2C_ADAP_MAX == j) {
- printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n",
- prev->name);
- return (struct i2c_client *) -ENODEV;
-- }
--
-+ }
-+
- for(i=0; i < I2C_CLIENT_MAX; i++)
- if(prev == adapters[j]->clients[i])
- break;
--
-+
- /* invalid starting point? */
- if (I2C_CLIENT_MAX == i) {
- printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n",
- prev->name);
- return (struct i2c_client *) -ENODEV;
-- }
--
-+ }
-+
- i++; /* start from one after prev */
- }
--
-+
- for(; j < I2C_ADAP_MAX; j++)
- {
- if(!adapters[j])
- continue;
--
-+
- if(adapter_id && (adapters[j]->id != adapter_id))
- continue;
--
-+
- for(; i < I2C_CLIENT_MAX; i++)
- {
- if(!adapters[j]->clients[i])
- continue;
--
-+
- if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
- continue;
-- if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
-+ if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
- return adapters[j]->clients[i];
- }
- i = 0;
-@@ -549,12 +549,12 @@
- int i2c_use_client(struct i2c_client *client)
- {
- if(client->flags & I2C_CLIENT_ALLOW_USE) {
-- if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
-+ if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
- client->usage_count++;
- else {
-- if(client->usage_count > 0)
-+ if(client->usage_count > 0)
- return -EBUSY;
-- else
-+ else
- client->usage_count++;
- }
- }
-@@ -575,9 +575,9 @@
- return -EPERM;
- }
- }
--
-+
- i2c_dec_use_client(client);
--
-+
- return 0;
- }
-
-@@ -589,7 +589,7 @@
- #ifdef CONFIG_PROC_FS
-
- /* This function generates the output for /proc/bus/i2c */
--int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
-+int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
- void *private)
- {
- int i;
-@@ -615,7 +615,7 @@
- }
-
- /* This function generates the output for /proc/bus/i2c-? */
--ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
-+ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
- loff_t *ppos)
- {
- struct inode * inode = file->f_dentry->d_inode;
-@@ -626,7 +626,7 @@
- int order[I2C_CLIENT_MAX];
-
- if (count > 4000)
-- return -EINVAL;
-+ return -EINVAL;
- len_total = file->f_pos + count;
- /* Too bad if this gets longer (unlikely) */
- if (len_total > 4000)
-@@ -641,12 +641,12 @@
- sorted by address */
- order_nr=0;
- for (j = 0; j < I2C_CLIENT_MAX; j++) {
-- if ((client = adapters[i]->clients[j]) &&
-+ if ((client = adapters[i]->clients[j]) &&
- (client->driver->id != I2C_DRIVERID_I2CDEV)) {
-- for(k = order_nr;
-- (k > 0) &&
-+ for(k = order_nr;
-+ (k > 0) &&
- adapters[i]->clients[order[k-1]]->
-- addr > client->addr;
-+ addr > client->addr;
- k--)
- order[k] = order[k-1];
- order[k] = j;
-@@ -665,7 +665,7 @@
- len = len - file->f_pos;
- if (len > count)
- len = count;
-- if (len < 0)
-+ if (len < 0)
- len = 0;
- if (copy_to_user (buf,kbuf+file->f_pos, len)) {
- kfree(kbuf);
-@@ -689,7 +689,7 @@
- printk("i2c-core.o: /proc/bus/ does not exist");
- i2cproc_cleanup();
- return -ENOENT;
-- }
-+ }
- proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
- if (!proc_bus_i2c) {
- printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
-@@ -702,14 +702,13 @@
- return 0;
- }
-
--int i2cproc_cleanup(void)
-+static void i2cproc_cleanup(void)
- {
-
- if (i2cproc_initialized >= 1) {
- remove_proc_entry("i2c",proc_bus);
- i2cproc_initialized -= 2;
- }
-- return 0;
- }
-
-
-@@ -751,10 +750,10 @@
- msg.flags = client->flags & I2C_M_TEN;
- msg.len = count;
- (const char *)msg.buf = buf;
--
-+
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
- count,client->adapter->name));
--
-+
- I2C_LOCK(adap);
- ret = adap->algo->master_xfer(adap,&msg,1);
- I2C_UNLOCK(adap);
-@@ -784,14 +783,14 @@
-
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
- count,client->adapter->name));
--
-+
- I2C_LOCK(adap);
- ret = adap->algo->master_xfer(adap,&msg,1);
- I2C_UNLOCK(adap);
--
-+
- DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
- ret, count, client->addr));
--
-+
- /* if everything went ok (i.e. 1 msg transmitted), return #bytes
- * transmitted, else error code.
- */
-@@ -852,7 +851,7 @@
- found = 0;
-
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
-- if (((adap_id == address_data->force[i]) ||
-+ if (((adap_id == address_data->force[i]) ||
- (address_data->force[i] == ANY_I2C_BUS)) &&
- (addr == address_data->force[i+1])) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",
-@@ -862,7 +861,7 @@
- found = 1;
- }
- }
-- if (found)
-+ if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about
-@@ -870,7 +869,7 @@
- for (i = 0;
- !found && (address_data->ignore[i] != I2C_CLIENT_END);
- i += 2) {
-- if (((adap_id == address_data->ignore[i]) ||
-+ if (((adap_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == ANY_I2C_BUS))) &&
- (addr == address_data->ignore[i+1])) {
- DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "
-@@ -890,11 +889,11 @@
- found = 1;
- }
- }
-- if (found)
-+ if (found)
- continue;
-
-- /* Now, we will do a detection, but only if it is in the normal or
-- probe entries */
-+ /* Now, we will do a detection, but only if it is in the normal or
-+ probe entries */
- for (i = 0;
- !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
- i += 1) {
-@@ -939,7 +938,7 @@
- "addr %04x\n", adap_id,addr));
- }
- }
-- if (!found)
-+ if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
-@@ -1087,11 +1086,11 @@
- I2C_SMBUS_I2C_BLOCK_DATA,&data);
- }
-
--/* Simulate a SMBus command using the i2c protocol
-+/* Simulate a SMBus command using the i2c protocol
- No checking of parameters is done! */
--static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
-+static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
- unsigned short flags,
-- char read_write, u8 command, int size,
-+ char read_write, u8 command, int size,
- union i2c_smbus_data * data)
- {
- /* So we need to generate a series of msgs. In the case of writing, we
-@@ -1101,7 +1100,7 @@
- unsigned char msgbuf0[34];
- unsigned char msgbuf1[34];
- int num = read_write == I2C_SMBUS_READ?2:1;
-- struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
-+ struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
- { addr, flags | I2C_M_RD, 0, msgbuf1 }
- };
- int i;
-@@ -1179,7 +1178,7 @@
- case I2C_SMBUS_BYTE_DATA:
- data->byte = msgbuf1[0];
- break;
-- case I2C_SMBUS_WORD_DATA:
-+ case I2C_SMBUS_WORD_DATA:
- case I2C_SMBUS_PROC_CALL:
- data->word = msgbuf1[0] | (msgbuf1[1] << 8);
- break;
-@@ -1189,7 +1188,7 @@
-
-
- s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
-- char read_write, u8 command, int size,
-+ char read_write, u8 command, int size,
- union i2c_smbus_data * data)
- {
- s32 res;
-@@ -1207,7 +1206,7 @@
-
-
- /* You should always define `functionality'; the 'else' is just for
-- backward compatibility. */
-+ backward compatibility. */
- u32 i2c_get_functionality (struct i2c_adapter *adap)
- {
- if (adap->algo->functionality)
-@@ -1233,122 +1232,12 @@
-
- init_MUTEX(&adap_lock);
- init_MUTEX(&driver_lock);
--
-- i2cproc_init();
--
-- return 0;
--}
--
--#ifndef MODULE
--#ifdef CONFIG_I2C_CHARDEV
-- extern int i2c_dev_init(void);
--#endif
--#ifdef CONFIG_I2C_ALGOBIT
-- extern int i2c_algo_bit_init(void);
--#endif
--#ifdef CONFIG_I2C_PHILIPSPAR
-- extern int i2c_bitlp_init(void);
--#endif
--#ifdef CONFIG_I2C_ELV
-- extern int i2c_bitelv_init(void);
--#endif
--#ifdef CONFIG_I2C_VELLEMAN
-- extern int i2c_bitvelle_init(void);
--#endif
--#ifdef CONFIG_I2C_BITVIA
-- extern int i2c_bitvia_init(void);
--#endif
-
--#ifdef CONFIG_I2C_ALGOPCF
-- extern int i2c_algo_pcf_init(void);
--#endif
--#ifdef CONFIG_I2C_ELEKTOR
-- extern int i2c_pcfisa_init(void);
--#endif
--
--#ifdef CONFIG_I2C_ALGO8XX
-- extern int i2c_algo_8xx_init(void);
--#endif
--#ifdef CONFIG_I2C_RPXLITE
-- extern int i2c_rpx_init(void);
--#endif
--
--#ifdef CONFIG_I2C_ALGO_SIBYTE
-- extern int i2c_algo_sibyte_init(void);
-- extern int i2c_sibyte_init(void);
--#endif
--#ifdef CONFIG_I2C_MAX1617
-- extern int i2c_max1617_init(void);
--#endif
--
--#ifdef CONFIG_I2C_PROC
-- extern int sensors_init(void);
--#endif
--
--/* This is needed for automatic patch generation: sensors code starts here */
--/* This is needed for automatic patch generation: sensors code ends here */
--
--int __init i2c_init_all(void)
--{
-- /* --------------------- global ----- */
-- i2c_init();
--
--#ifdef CONFIG_I2C_CHARDEV
-- i2c_dev_init();
--#endif
-- /* --------------------- bit -------- */
--#ifdef CONFIG_I2C_ALGOBIT
-- i2c_algo_bit_init();
--#endif
--#ifdef CONFIG_I2C_PHILIPSPAR
-- i2c_bitlp_init();
--#endif
--#ifdef CONFIG_I2C_ELV
-- i2c_bitelv_init();
--#endif
--#ifdef CONFIG_I2C_VELLEMAN
-- i2c_bitvelle_init();
--#endif
--
-- /* --------------------- pcf -------- */
--#ifdef CONFIG_I2C_ALGOPCF
-- i2c_algo_pcf_init();
--#endif
--#ifdef CONFIG_I2C_ELEKTOR
-- i2c_pcfisa_init();
--#endif
--
-- /* --------------------- 8xx -------- */
--#ifdef CONFIG_I2C_ALGO8XX
-- i2c_algo_8xx_init();
--#endif
--#ifdef CONFIG_I2C_RPXLITE
-- i2c_rpx_init();
--#endif
--
-- /* --------------------- SiByte -------- */
--#ifdef CONFIG_I2C_ALGO_SIBYTE
-- i2c_algo_sibyte_init();
-- i2c_sibyte_init();
--#endif
--#ifdef CONFIG_I2C_MAX1617
-- i2c_max1617_init();
--#endif
--
-- /* -------------- proc interface ---- */
--#ifdef CONFIG_I2C_PROC
-- sensors_init();
--#endif
--/* This is needed for automatic patch generation: sensors code starts here */
--/* This is needed for automatic patch generation: sensors code ends here */
-+ i2cproc_init();
-
- return 0;
- }
-
--#endif
--
--
--
- EXPORT_SYMBOL(i2c_add_adapter);
- EXPORT_SYMBOL(i2c_del_adapter);
- EXPORT_SYMBOL(i2c_add_driver);
-@@ -1385,7 +1274,6 @@
- EXPORT_SYMBOL(i2c_get_functionality);
- EXPORT_SYMBOL(i2c_check_functionality);
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus main module");
- MODULE_LICENSE("GPL");
-@@ -1393,13 +1281,5 @@
- MODULE_PARM(i2c_debug, "i");
- MODULE_PARM_DESC(i2c_debug,"debug level");
-
--int init_module(void)
--{
-- return i2c_init();
--}
--
--void cleanup_module(void)
--{
-- i2cproc_cleanup();
--}
--#endif
-+module_init(i2c_init);
-+module_exit(i2cproc_cleanup);
---- linux-2.4.27/drivers/i2c/i2c-dev.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-dev.c
-@@ -1,5 +1,5 @@
- /*
-- i2c-dev.c - i2c-bus driver, char device interface
-+ i2c-dev.c - i2c-bus driver, char device interface
-
- Copyright (C) 1995-97 Simon G. Vogl
- Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
-@@ -25,7 +25,7 @@
-
- /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-
--/* The devfs code is contributed by Philipp Matthias Hahn
-+/* The devfs code is contributed by Philipp Matthias Hahn
- <pmhahn@titan.lahn.de> */
-
- /* $Id: i2c-dev.c,v 1.40 2001/08/25 01:28:01 mds Exp $ */
-@@ -50,19 +50,14 @@
- #include <linux/i2c.h>
- #include <linux/i2c-dev.h>
-
--#ifdef MODULE
--extern int init_module(void);
--extern int cleanup_module(void);
--#endif /* def MODULE */
--
- /* struct file_operations changed too often in the 2.1 series for nice code */
-
--static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
-+static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
- loff_t *offset);
--static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
-+static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
- loff_t *offset);
-
--static int i2cdev_ioctl (struct inode *inode, struct file *file,
-+static int i2cdev_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
- static int i2cdev_open (struct inode *inode, struct file *file);
-
-@@ -73,13 +68,8 @@
- static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
-
--#ifdef MODULE
--static
--#else
--extern
--#endif
-- int __init i2c_dev_init(void);
--static int i2cdev_cleanup(void);
-+static int __init i2c_dev_init(void);
-+static void i2cdev_cleanup(void);
-
- static struct file_operations i2cdev_fops = {
- owner: THIS_MODULE,
-@@ -185,7 +175,7 @@
- return ret;
- }
-
--int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-+int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
- {
- struct i2c_client *client = (struct i2c_client *)file->private_data;
-@@ -198,14 +188,14 @@
- unsigned long funcs;
-
- #ifdef DEBUG
-- printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
-+ printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
- MINOR(inode->i_rdev),cmd, arg);
- #endif /* DEBUG */
-
- switch ( cmd ) {
- case I2C_SLAVE:
- case I2C_SLAVE_FORCE:
-- if ((arg > 0x3ff) ||
-+ if ((arg > 0x3ff) ||
- (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
- return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
-@@ -224,8 +214,8 @@
- sizeof(unsigned long)))?-EFAULT:0;
-
- case I2C_RDWR:
-- if (copy_from_user(&rdwr_arg,
-- (struct i2c_rdwr_ioctl_data *)arg,
-+ if (copy_from_user(&rdwr_arg,
-+ (struct i2c_rdwr_ioctl_data *)arg,
- sizeof(rdwr_arg)))
- return -EFAULT;
-
-@@ -233,9 +223,9 @@
- * be sent at once */
- if (rdwr_arg.nmsgs > 42)
- return -EINVAL;
--
-+
- rdwr_pa = (struct i2c_msg *)
-- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
-+ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
- GFP_KERNEL);
-
- if (rdwr_pa == NULL) return -ENOMEM;
-@@ -312,9 +302,9 @@
- (struct i2c_smbus_ioctl_data *) arg,
- sizeof(struct i2c_smbus_ioctl_data)))
- return -EFAULT;
-- if ((data_arg.size != I2C_SMBUS_BYTE) &&
-+ if ((data_arg.size != I2C_SMBUS_BYTE) &&
- (data_arg.size != I2C_SMBUS_QUICK) &&
-- (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
-+ (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
- (data_arg.size != I2C_SMBUS_WORD_DATA) &&
- (data_arg.size != I2C_SMBUS_PROC_CALL) &&
- (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
-@@ -325,9 +315,9 @@
- #endif
- return -EINVAL;
- }
-- /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
-+ /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
- so the check is valid if size==I2C_SMBUS_QUICK too. */
-- if ((data_arg.read_write != I2C_SMBUS_READ) &&
-+ if ((data_arg.read_write != I2C_SMBUS_READ) &&
- (data_arg.read_write != I2C_SMBUS_WRITE)) {
- #ifdef DEBUG
- printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
-@@ -339,7 +329,7 @@
- /* Note that command values are always valid! */
-
- if ((data_arg.size == I2C_SMBUS_QUICK) ||
-- ((data_arg.size == I2C_SMBUS_BYTE) &&
-+ ((data_arg.size == I2C_SMBUS_BYTE) &&
- (data_arg.read_write == I2C_SMBUS_WRITE)))
- /* These are special: we do not use data */
- return i2c_smbus_xfer(client->adapter, client->addr,
-@@ -358,13 +348,13 @@
- if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
- (data_arg.size == I2C_SMBUS_BYTE))
- datasize = sizeof(data_arg.data->byte);
-- else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
-+ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
- (data_arg.size == I2C_SMBUS_PROC_CALL))
- datasize = sizeof(data_arg.data->word);
- else /* size == I2C_SMBUS_BLOCK_DATA */
- datasize = sizeof(data_arg.data->block);
-
-- if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-+ if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_WRITE)) {
- if (copy_from_user(&temp, data_arg.data, datasize))
- return -EFAULT;
-@@ -372,7 +362,7 @@
- res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- data_arg.read_write,
- data_arg.command,data_arg.size,&temp);
-- if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
-+ if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_READ))) {
- if (copy_to_user(data_arg.data, &temp, datasize))
- return -EFAULT;
-@@ -479,7 +469,7 @@
- return -1;
- }
-
--int __init i2c_dev_init(void)
-+static int __init i2c_dev_init(void)
- {
- int res;
-
-@@ -509,7 +499,7 @@
- return 0;
- }
-
--int i2cdev_cleanup(void)
-+static void i2cdev_cleanup(void)
- {
- int res;
-
-@@ -517,9 +507,9 @@
- if ((res = i2c_del_driver(&i2cdev_driver))) {
- printk("i2c-dev.o: Driver deregistration failed, "
- "module not removed.\n");
-- return res;
-+ return;
- }
-- i2cdev_initialized --;
-+ i2cdev_initialized --;
- }
-
- if (i2cdev_initialized >= 1) {
-@@ -531,30 +521,17 @@
- #endif
- printk("i2c-dev.o: unable to release major %d for i2c bus\n",
- I2C_MAJOR);
-- return res;
-+ return;
- }
- i2cdev_initialized --;
- }
-- return 0;
- }
-
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
--
- MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C /dev entries driver");
- MODULE_LICENSE("GPL");
-
--int init_module(void)
--{
-- return i2c_dev_init();
--}
--
--int cleanup_module(void)
--{
-- return i2cdev_cleanup();
--}
--
--#endif /* def MODULE */
--
-+module_init(i2c_dev_init);
-+module_exit(i2cdev_cleanup);
---- linux-2.4.27/drivers/i2c/i2c-elektor.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-elektor.c
-@@ -181,16 +181,12 @@
-
- static void pcf_isa_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void pcf_isa_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
-
-@@ -219,7 +215,7 @@
- pcf_isa_unreg,
- };
-
--int __init i2c_pcfisa_init(void)
-+static int __init i2c_pcfisa_init(void)
- {
- #ifdef __alpha__
- /* check to see we have memory mapped PCF8584 connected to the
-@@ -289,10 +285,14 @@
- return 0;
- }
-
-+static void i2c_pcfisa_exit(void)
-+{
-+ i2c_pcf_del_bus(&pcf_isa_ops);
-+ pcf_isa_exit();
-+}
-
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
- MODULE_LICENSE("GPL");
-@@ -304,15 +304,5 @@
- MODULE_PARM(mmapped, "i");
- MODULE_PARM(i2c_debug, "i");
-
--int init_module(void)
--{
-- return i2c_pcfisa_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_pcf_del_bus(&pcf_isa_ops);
-- pcf_isa_exit();
--}
--
--#endif
-+module_init(i2c_pcfisa_init);
-+module_exit(i2c_pcfisa_exit);
---- linux-2.4.27/drivers/i2c/i2c-elv.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-elv.c
-@@ -75,7 +75,7 @@
- PortData |=2;
- }
- outb(PortData, DATA);
--}
-+}
-
- static int bit_elv_getscl(void *data)
- {
-@@ -90,7 +90,7 @@
- static int bit_elv_init(void)
- {
- if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
-- return -ENODEV;
-+ return -ENODEV;
- } else {
- /* test for ELV adap. */
- if (inb(base+1) & 0x80) { /* BUSY should be high */
-@@ -131,16 +131,12 @@
-
- static void bit_elv_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void bit_elv_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
- /* ------------------------------------------------------------------------
-@@ -164,10 +160,10 @@
- bit_elv_inc_use,
- bit_elv_dec_use,
- bit_elv_reg,
-- bit_elv_unreg,
-+ bit_elv_unreg,
- };
-
--int __init i2c_bitelv_init(void)
-+static int __init i2c_bitelv_init(void)
- {
- printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (base==0) {
-@@ -194,24 +190,19 @@
- }
-
-
-+static void __exit i2c_bitelv_exit(void)
-+{
-+ i2c_bit_del_bus(&bit_elv_ops);
-+ bit_elv_exit();
-+}
-+
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
- MODULE_LICENSE("GPL");
-
- MODULE_PARM(base, "i");
-
--int init_module(void)
--{
-- return i2c_bitelv_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bit_del_bus(&bit_elv_ops);
-- bit_elv_exit();
--}
--
--#endif
-+module_init(i2c_bitelv_init);
-+module_exit(i2c_bitelv_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-frodo.c
-@@ -0,0 +1,114 @@
-+
-+/*
-+ * linux/drivers/i2c/i2c-frodo.c
-+ *
-+ * Author: Abraham van der Merwe <abraham@2d3d.co.za>
-+ *
-+ * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
-+ * Development board (Frodo).
-+ *
-+ * This source code is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * version 2 as published by the Free Software Foundation.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/version.h>
-+#include <linux/module.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+
-+#include <asm/hardware.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+static void frodo_setsda (void *data,int state)
-+{
-+ if (state)
-+ frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
-+ else
-+ frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SDA_OUT);
-+}
-+
-+static void frodo_setscl (void *data,int state)
-+{
-+ if (state)
-+ frodo_cpld_set (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
-+ else
-+ frodo_cpld_clear (FRODO_CPLD_I2C,FRODO_I2C_SCL_OUT);
-+}
-+
-+static int frodo_getsda (void *data)
-+{
-+ return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SDA_IN) != 0);
-+}
-+
-+static int frodo_getscl (void *data)
-+{
-+ return ((frodo_cpld_read (FRODO_CPLD_I2C) & FRODO_I2C_SCL_IN) != 0);
-+}
-+
-+static struct i2c_algo_bit_data bit_frodo_data = {
-+ setsda: frodo_setsda,
-+ setscl: frodo_setscl,
-+ getsda: frodo_getsda,
-+ getscl: frodo_getscl,
-+ udelay: 80,
-+ mdelay: 80,
-+ timeout: 100
-+};
-+
-+static int frodo_client_register (struct i2c_client *client)
-+{
-+ return (0);
-+}
-+
-+static int frodo_client_unregister (struct i2c_client *client)
-+{
-+ return (0);
-+}
-+
-+static void frodo_inc_use (struct i2c_adapter *adapter)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void frodo_dec_use (struct i2c_adapter *adapter)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static struct i2c_adapter frodo_ops = {
-+ name: "Frodo adapter driver",
-+ id: I2C_HW_B_FRODO,
-+ algo: NULL,
-+ algo_data: &bit_frodo_data,
-+ inc_use: frodo_inc_use,
-+ dec_use: frodo_dec_use,
-+ client_register: frodo_client_register,
-+ client_unregister: frodo_client_unregister
-+};
-+
-+static int __init i2c_frodo_init (void)
-+{
-+ return (i2c_bit_add_bus (&frodo_ops));
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+static void __exit i2c_frodo_exit (void)
-+{
-+ i2c_bit_del_bus (&frodo_ops);
-+}
-+
-+MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
-+MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
-+MODULE_LICENSE ("GPL");
-+EXPORT_NO_SYMBOLS;
-+
-+module_init (i2c_frodo_init);
-+module_exit (i2c_frodo_exit);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-guide.c
-@@ -0,0 +1,199 @@
-+/************************************************************************************\
-+Copyright : Copyright (C) 1995-2000 Simon G. Vogl
-+ Copyright 2002 IDERs Incorporated
-+File Name : i2c-guide.c
-+Description : this i2c driver uses the GPIO port B pin 0 and pin 1 on the cs89712.
-+Notes : To change the bit rate, change the structure i2c_algo_bit_data
-+ : to 10 10 100
-+Contact : tsong@iders.ca
-+License : This source code is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License
-+ version 2 as published by the Free Software Foundation.
-+\************************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <linux/ioport.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/string.h> /* for 2.0 kernels to get NULL */
-+#include <asm/errno.h> /* for 2.0 kernels to get ENODEV */
-+#include <asm/io.h>
-+
-+#include <asm/hardware/cs89712.h> // io operation ep_writel()
-+#include <asm/hardware/clps7111.h> // io operation clps_writel()
-+#include <asm/arch-clps711x/hardware.h> // io operation clps_writel()
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+/* ----- global defines ----------------------------------------------- */
-+
-+#define DEB(x) /* should be reasonable open, close &c. */
-+#define DEB2(x) /* low level debugging - very slow */
-+#define DEBE(x) x /* error messages */
-+ /* Pin Port Inverted name */
-+#define I2C_SDA 0x08 /* port B ctrl pin 3 (inv) */
-+#define I2C_SCL 0x04 /* port B ctrl pin 2 (inv) */
-+
-+#define I2C_SDAIN 0x08 /* use the same pin with output */
-+#define I2C_SCLIN 0x04 /* use the same pin with output */
-+
-+#define I2C_DMASK 0xf7 /* inverse of I2C_SDA */
-+#define I2C_CMASK 0xfb /* inverse of I2c_SCL */
-+
-+#define PORTB_PIN0_SDA_OUTPUT 0x08 /* pin 3 direction of port B output */
-+#define PORTB_PIN0_SDA_INPUT 0xf7 /* pin 3 direction of port B input */
-+
-+#define PORTB_PIN1_SCL_OUTPUT 0x04 /* pin 2 direction of port B output */
-+#define PORTB_PIN1_SCL_INPUT 0xfb /* pin 2 direction of port B input */
-+
-+int base = 0;
-+#define DEFAULT_BASE PBDR
-+
-+/* ----- local functions --------------------------------------------------- */
-+
-+static void bit_guide_setscl(void* data, int state)
-+{
-+ if (state) {
-+ // set port B pin2 input
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN1_SCL_INPUT, PBDDR);
-+ }
-+ else {
-+ // clear
-+ clps_writeb((clps_readb(PBDR)) & I2C_CMASK, PBDR);
-+ // set port B pin2 output
-+ clps_writeb((clps_readb(PBDDR)) | PORTB_PIN1_SCL_OUTPUT, PBDDR);
-+ }
-+}
-+
-+static void bit_guide_setsda(void* data, int state)
-+{
-+ if (state) {
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
-+ // float pin 0 (actually drive high by pull up resistor)
-+ // clps_writeb((clps_readb(PBDR)) | I2C_SDA, PBDR); // set Jan4 ori: eff
-+ // printk("set sda high, state=%i\n",state);
-+ }
-+ else {
-+ // clear
-+ clps_writeb((clps_readb(PBDR)) & I2C_DMASK, PBDR);
-+ // set port B pin 0 output
-+ clps_writeb((clps_readb(PBDDR)) | PORTB_PIN0_SDA_OUTPUT, PBDDR);
-+ }
-+}
-+
-+static int bit_guide_getscl(void *data)
-+{
-+ return ( 0 != ( (clps_readb(PBDR)) & I2C_SCLIN ) );
-+}
-+
-+static int bit_guide_getsda(void *data)
-+{
-+ // set port B pin 0 input Jan4 ori eff
-+ clps_writeb((clps_readb(PBDDR)) & PORTB_PIN0_SDA_INPUT, PBDDR);
-+ return ( 0 != ( (clps_readb(PBDR) ) & I2C_SDAIN ) );
-+}
-+
-+static int bit_guide_init(void)
-+{
-+ bit_guide_setsda((void*)base,1);
-+ bit_guide_setscl((void*)base,1);
-+ return 0;
-+}
-+
-+static int bit_guide_reg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static int bit_guide_unreg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static void bit_guide_inc_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_INC_USE_COUNT;
-+#endif
-+}
-+
-+static void bit_guide_dec_use(struct i2c_adapter *adap)
-+{
-+#ifdef MODULE
-+ MOD_DEC_USE_COUNT;
-+#endif
-+}
-+
-+/* ------------------------------------------------------------------------
-+ * Encapsulate the above functions in the correct operations structure.
-+ * This is only done when more than one hardware adapter is supported.
-+ */
-+
-+/* last line (us, ms, timout)
-+ * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps)
-+ * 10ms not known
-+ * 100ms timeout
-+ */
-+static struct i2c_algo_bit_data bit_guide_data = {
-+ NULL,
-+ bit_guide_setsda,
-+ bit_guide_setscl,
-+ bit_guide_getsda,
-+ bit_guide_getscl,
-+ 50, 10, 100, /* orginal (non-guide) value 10, 10, 100 */
-+};
-+
-+static struct i2c_adapter bit_guide_ops = {
-+ "Guide Port B: PIN2-SCL/PIN3-SDA",
-+ I2C_HW_B_GUIDE,
-+ NULL,
-+ &bit_guide_data,
-+ bit_guide_inc_use,
-+ bit_guide_dec_use,
-+ bit_guide_reg,
-+ bit_guide_unreg,
-+};
-+
-+static int __init i2c_bitguide_init(void)
-+{
-+ printk("i2c-guide.o: Guide i2c port B adapter module.\n");
-+ clps_writeb((clps_readb(PBDDR)) & 0xfd, PBDDR); // set service reuest pb1 as input
-+ if (base==0) {
-+ /* probe some values */
-+ base=DEFAULT_BASE;
-+ bit_guide_data.data=(void*)DEFAULT_BASE;
-+ if (bit_guide_init()==0) {
-+ if(i2c_bit_add_bus(&bit_guide_ops) < 0)
-+ return -ENODEV;
-+ } else {
-+ return -ENODEV;
-+ }
-+ } else {
-+ bit_guide_data.data=(void*)base;
-+ if (bit_guide_init()==0) {
-+ if(i2c_bit_add_bus(&bit_guide_ops) < 0)
-+ return -ENODEV;
-+ } else {
-+ return -ENODEV;
-+ }
-+ }
-+ printk("i2c-guide.o: found device at %#x.\n",base);
-+ return 0;
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("T. C. Song <tsong@iders.ca>");
-+MODULE_DESCRIPTION("I2C-Bus adapter routines for Guide (cs89712) GPIO port B");
-+MODULE_LICENSE("GPL");
-+
-+MODULE_PARM(base, "i");
-+
-+module_init(i2c_bitguide_init);
-+/* for completeness, we should have a module_exit() function, but the
-+ GUIDE requires this to always be loaded. If it is unloaded, the
-+ operation of the GUIDE is undefined.
-+ Nobody has written the i2c_bitguide_exit() routine yet, so it is not included.
-+module_exit(i2c_bitguide_exit);
-+*/
---- /dev/null
-+++ linux-2.4.27/drivers/i2c/i2c-omaha.c
-@@ -0,0 +1,276 @@
-+/* ------------------------------------------------------------------------- *
-+ Copyright ARM Limited 2002. All rights reserved.
-+
-+ i2c driver for Omaha
-+
-+ Notes:Based on i2c-elv.c
-+
-+ The S3C2400X01 has better support for I2C, but bit oriented operations
-+ are directly supported by the other I2C layers, so we use that method
-+ of performing I2C operations.
-+
-+ Copyright (C) 1995-2000 Simon G. Vogl
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-+/* ------------------------------------------------------------------------- */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <linux/ioport.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+
-+/* ----- global defines ----------------------------------------------- */
-+#define DEB(x) if (i2c_debug>=1) x;
-+#define DEB2(x) if (i2c_debug>=2) x;
-+#define DEB3(x) if (i2c_debug>=3) x
-+#define DEBE(x) x // error messages
-+#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
-+#define DEBPROTO(x) if (i2c_debug>=9) { x; }
-+ /* debug the protocol by showing transferred bits */
-+
-+/* Register and bitdefs for Omaha */
-+
-+// Port G control registers
-+static volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
-+static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT);
-+
-+static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR);
-+
-+static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);
-+
-+// Open drain control registers
-+#define OPC_CMD BIT2
-+#define OPC_DAT BIT3
-+
-+// data bits in GPIO Port G data register
-+#define OMAHA_SDA BIT5
-+#define OMAHA_SCL BIT6
-+#define IIC_WP BIT3 // Write Protect for EEPROM
-+
-+// input/out select bits in GPIO G control register
-+#define IIC_BITS (BIT12|BIT10|BIT6);
-+
-+
-+/* ----- local functions ---------------------------------------------- */
-+
-+
-+static void bit_omaha_setscl(void *data, int state)
-+{
-+ unsigned int tmp;
-+
-+ if (state)
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp |= OMAHA_SCL;
-+ __raw_writel(tmp,pgdat);
-+ }
-+ else
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp &= ~OMAHA_SCL;
-+ __raw_writel(tmp,pgdat);
-+ }
-+}
-+
-+static void bit_omaha_setsda(void *data, int state)
-+{
-+ unsigned int tmp;
-+
-+ // ensure that sda is an output at the moment
-+ tmp = __raw_readl(pgcon);
-+ tmp = tmp | BIT10;
-+ __raw_writel(tmp,pgcon);
-+
-+ if (state)
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp |= OMAHA_SDA;
-+ __raw_writel(tmp,pgdat);
-+ }
-+ else
-+ {
-+ tmp = __raw_readl(pgdat);
-+ tmp &= ~OMAHA_SDA;
-+ __raw_writel(tmp,pgdat);
-+ }
-+}
-+
-+static int bit_omaha_getscl(void *data)
-+{
-+ if (__raw_readl(pgdat) & OMAHA_SCL)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int bit_omaha_getsda(void *data)
-+{
-+ unsigned int tmp;
-+
-+ // ensure that sda is an output at the moment
-+ tmp = __raw_readl(pgcon);
-+ tmp = tmp & ~BIT10;
-+ __raw_writel(tmp,pgcon);
-+
-+ if (__raw_readl(pgdat) & OMAHA_SDA)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int bit_omaha_init(void)
-+{
-+ // Have we got some mmapped space?
-+ if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 )
-+ {
-+ printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base);
-+ return -ENODEV;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int bit_omaha_reg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+
-+static int bit_omaha_unreg(struct i2c_client *client)
-+{
-+ return 0;
-+}
-+
-+static void bit_omaha_inc_use(struct i2c_adapter *adap)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void bit_omaha_dec_use(struct i2c_adapter *adap)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+
-+
-+/* ------------------------------------------------------------------------
-+ * Encapsulate the above functions in the correct operations structure.
-+ * This is only done when more than one hardware adapter is supported.
-+ */
-+static struct i2c_algo_bit_data bit_omaha_data = {
-+ NULL,
-+ bit_omaha_setsda,
-+ bit_omaha_setscl,
-+ bit_omaha_getsda,
-+ bit_omaha_getscl,
-+ 10, 10, 20, /* waits, timeout */
-+};
-+
-+static struct i2c_adapter bit_omaha_ops = {
-+ "BIT-Type Omaha I2C adapter",
-+ I2C_HW_B_OMAHA,
-+ NULL,
-+ &bit_omaha_data,
-+ bit_omaha_inc_use,
-+ bit_omaha_dec_use,
-+ bit_omaha_reg,
-+ bit_omaha_unreg,
-+};
-+
-+static int __init i2c_omaha_init (void)
-+{
-+ unsigned int tmp;
-+
-+ printk("i2c-omaha.o: i2c omaha adapter module\n");
-+
-+ if (bit_omaha_init() == 0) {
-+ if(i2c_bit_add_bus(&bit_omaha_ops) < 0)
-+ {
-+ printk("Could not add bus!\n");
-+ return -ENODEV;
-+ }
-+ } else {
-+ printk("Could not pcf_omaha_init\n");
-+ return -ENODEV;
-+ }
-+
-+ // Program Port G bits to output function
-+ tmp = __raw_readl(pgcon);
-+ tmp |= IIC_BITS;
-+ __raw_writel(tmp,pgcon);
-+
-+ // Ensure SDA and SCL are open-drain
-+ tmp = __raw_readl(opencr);
-+ tmp = tmp | OPC_CMD | OPC_DAT;
-+ __raw_writel(tmp,opencr);
-+
-+ bit_omaha_setsda((void*)base,1);
-+ bit_omaha_setscl((void*)base,1);
-+
-+ // Disable WP
-+ tmp = __raw_readl(pgdat);
-+ tmp = tmp & ~IIC_WP;
-+ __raw_writel(tmp,pgdat);
-+
-+ return 0;
-+}
-+
-+static void bit_omaha_exit(void)
-+{
-+ release_region(base , 2);
-+}
-+
-+static void i2c_omaha_exit(void)
-+{
-+
-+ i2c_bit_del_bus(&bit_omaha_ops);
-+
-+ bit_omaha_exit();
-+
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("ARM Limited <support@arm.com>");
-+MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha");
-+MODULE_LICENSE("GPL");
-+
-+MODULE_PARM(base, "i");
-+MODULE_PARM(irq, "i");
-+MODULE_PARM(clock, "i");
-+MODULE_PARM(own, "i");
-+MODULE_PARM(mmapped, "i");
-+MODULE_PARM(i2c_debug, "i");
-+
-+
-+module_init(i2c_omaha_init);
-+module_exit(i2c_omaha_exit);
-+
-+
---- linux-2.4.27/drivers/i2c/i2c-philips-par.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-philips-par.c
-@@ -16,7 +16,7 @@
- You 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. */
--/* ------------------------------------------------------------------------- */
-+/* ------------------------------------------------------------------------- */
-
- /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
- Frodo Looijaard <frodol@dds.nl> */
-@@ -72,7 +72,7 @@
-
- static void bit_lp_setscl(void *data, int state)
- {
-- /*be cautious about state of the control register -
-+ /*be cautious about state of the control register -
- touch only the one bit needed*/
- if (state) {
- parport_write_control((struct parport *) data,
-@@ -126,7 +126,7 @@
-
- static int bit_lp_getsda2(void *data)
- {
-- return (parport_read_status((struct parport *) data) &
-+ return (parport_read_status((struct parport *) data) &
- PARPORT_STATUS_BUSY) ? 0 : 1;
- }
-
-@@ -154,7 +154,7 @@
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
--
-+
- static struct i2c_algo_bit_data bit_lp_data = {
- NULL,
- bit_lp_setsda,
-@@ -162,7 +162,7 @@
- bit_lp_getsda,
- bit_lp_getscl,
- 80, 80, 100, /* waits, timeout */
--};
-+};
-
- static struct i2c_algo_bit_data bit_lp_data2 = {
- NULL,
-@@ -171,7 +171,7 @@
- bit_lp_getsda2,
- NULL,
- 80, 80, 100, /* waits, timeout */
--};
-+};
-
- static struct i2c_adapter bit_lp_ops = {
- "Philips Parallel port adapter",
-@@ -197,7 +197,7 @@
- printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name);
-
- adapter->pdev = parport_register_device(port, "i2c-philips-par",
-- NULL, NULL, NULL,
-+ NULL, NULL, NULL,
- PARPORT_FLAG_EXCL,
- NULL);
- if (!adapter->pdev) {
-@@ -257,16 +257,16 @@
- NULL
- };
-
--int __init i2c_bitlp_init(void)
-+static int __init i2c_bitlp_init(void)
- {
- printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
-
- parport_register_driver(&i2c_driver);
--
-+
- return 0;
- }
-
--void __exit i2c_bitlp_exit(void)
-+static void __exit i2c_bitlp_exit(void)
- {
- parport_unregister_driver(&i2c_driver);
- }
-@@ -279,14 +279,5 @@
-
- MODULE_PARM(type, "i");
-
--#ifdef MODULE
--int init_module(void)
--{
-- return i2c_bitlp_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bitlp_exit();
--}
--#endif
-+module_init(i2c_bitlp_init);
-+module_exit(i2c_bitlp_exit);
---- linux-2.4.27/drivers/i2c/i2c-velleman.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/i2c/i2c-velleman.c
-@@ -65,7 +65,7 @@
- } else {
- outb(inb(CTRL) | I2C_SCL, CTRL);
- }
--
-+
- }
-
- static void bit_velle_setsda(void *data, int state)
-@@ -75,8 +75,8 @@
- } else {
- outb(inb(CTRL) | I2C_SDA, CTRL);
- }
--
--}
-+
-+}
-
- static int bit_velle_getscl(void *data)
- {
-@@ -95,7 +95,7 @@
- base));
- return -ENODEV;
- } else {
-- request_region(base, (base == 0x3bc)? 3 : 8,
-+ request_region(base, (base == 0x3bc)? 3 : 8,
- "i2c (Vellemann adapter)");
- bit_velle_setsda((void*)base,1);
- bit_velle_setscl((void*)base,1);
-@@ -104,7 +104,7 @@
- }
-
- static void __exit bit_velle_exit(void)
--{
-+{
- release_region( base , (base == 0x3bc)? 3 : 8 );
- }
-
-@@ -121,16 +121,12 @@
-
- static void bit_velle_inc_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_INC_USE_COUNT;
--#endif
- }
-
- static void bit_velle_dec_use(struct i2c_adapter *adap)
- {
--#ifdef MODULE
- MOD_DEC_USE_COUNT;
--#endif
- }
-
- /* ------------------------------------------------------------------------
-@@ -158,7 +154,7 @@
- bit_velle_unreg,
- };
-
--int __init i2c_bitvelle_init(void)
-+static int __init i2c_bitvelle_init(void)
- {
- printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- if (base==0) {
-@@ -184,24 +180,19 @@
- return 0;
- }
-
-+static void __exit i2c_bitvelle_exit(void)
-+{
-+ i2c_bit_del_bus(&bit_velle_ops);
-+ bit_velle_exit();
-+}
-+
- EXPORT_NO_SYMBOLS;
-
--#ifdef MODULE
- MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
- MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
- MODULE_LICENSE("GPL");
-
- MODULE_PARM(base, "i");
-
--int init_module(void)
--{
-- return i2c_bitvelle_init();
--}
--
--void cleanup_module(void)
--{
-- i2c_bit_del_bus(&bit_velle_ops);
-- bit_velle_exit();
--}
--
--#endif
-+module_init(i2c_bitvelle_init);
-+module_exit(i2c_bitvelle_exit);
---- linux-2.4.27/drivers/ide/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/Config.in
-@@ -107,6 +107,9 @@
- define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS
- dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN
- fi
-+ if [ "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
-+ dep_bool ' RiscStation IDE' CONFIG_BLK_DEV_IDE_RISCSTATION $CONFIG_ARCH_RISCSTATION
-+ fi
- if [ "$CONFIG_AMIGA" = "y" ]; then
- dep_bool ' Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE $CONFIG_AMIGA
- dep_mbool ' Amiga IDE Doubler support (EXPERIMENTAL)' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE $CONFIG_EXPERIMENTAL
---- linux-2.4.27/drivers/ide/arm/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/arm/Makefile
-@@ -6,6 +6,7 @@
-
- obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
- obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
-+obj-$(CONFIG_BLK_DEV_IDE_RISCSTATION) += rstation-ide.o
-
- EXTRA_CFLAGS := -I../
-
---- linux-2.4.27/drivers/ide/arm/icside.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/arm/icside.c
-@@ -1,7 +1,7 @@
- /*
- * linux/drivers/ide/arm/icside.c
- *
-- * Copyright (c) 1996,1997 Russell King.
-+ * Copyright (c) 1996-2003 Russell King.
- *
- * Changelog:
- * 08-Jun-1996 RMK Created
-@@ -26,24 +26,6 @@
- #include <asm/ecard.h>
- #include <asm/io.h>
-
--#include "ide-noise.h"
--
--/*
-- * FIXME: We want to drop the the MACRO CRAP!
-- *
-- * ec->iops->in{b/w/l}
-- * ec->iops->in{b/w/l}_p
-- * ec->iops->out{b/w/l}
-- * ec->iops->out{b/w/l}_p
-- *
-- * the new core supports clean MMIO calls and other goodies
-- */
--
--/*
-- * Maximum number of interfaces per card
-- */
--#define MAX_IFS 2
--
- #define ICS_IDENT_OFFSET 0x8a0
-
- #define ICS_ARCIN_V5_INTRSTAT 0x000
-@@ -86,17 +68,20 @@
- ICS_ARCIN_V6_IDESTEPPING
- };
-
--static const card_ids icside_cids[] = {
-- { MANU_ICS, PROD_ICS_IDE },
-- { MANU_ICS2, PROD_ICS2_IDE },
-- { 0xffff, 0xffff }
-+struct icside_state {
-+ unsigned int channel;
-+ unsigned int enabled;
-+ unsigned long irq_port;
-+ unsigned long slot_port;
-+ unsigned int type;
-+ ide_hwif_t *hwif[2];
- };
-
--typedef enum {
-- ics_if_unknown,
-- ics_if_arcin_v5,
-- ics_if_arcin_v6
--} iftype_t;
-+#define ICS_TYPE_A3IN 0
-+#define ICS_TYPE_A3USER 1
-+#define ICS_TYPE_V6 3
-+#define ICS_TYPE_V5 15
-+#define ICS_TYPE_NOTYPE ((unsigned int)-1)
-
- /* ---------------- Version 5 PCB Support Functions --------------------- */
- /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
-@@ -104,8 +89,10 @@
- */
- static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int memc_port = (unsigned int)ec->irq_data;
-- outb(0, memc_port + ICS_ARCIN_V5_INTROFFSET);
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-+
-+ outb(0, base + ICS_ARCIN_V5_INTROFFSET);
- }
-
- /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
-@@ -113,17 +100,15 @@
- */
- static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int memc_port = (unsigned int)ec->irq_data;
-- inb(memc_port + ICS_ARCIN_V5_INTROFFSET);
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-+
-+ inb(base + ICS_ARCIN_V5_INTROFFSET);
- }
-
- static const expansioncard_ops_t icside_ops_arcin_v5 = {
-- icside_irqenable_arcin_v5,
-- icside_irqdisable_arcin_v5,
-- NULL,
-- NULL,
-- NULL,
-- NULL
-+ .irqenable = icside_irqenable_arcin_v5,
-+ .irqdisable = icside_irqdisable_arcin_v5,
- };
-
-
-@@ -133,10 +118,21 @@
- */
- static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-+ unsigned int base = state->irq_port;
-
-- outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
-- outb(0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ state->enabled = 1;
-+
-+ switch (state->channel) {
-+ case 0:
-+ outb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(base + ICS_ARCIN_V6_INTROFFSET_2);
-+ break;
-+ case 1:
-+ outb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(base + ICS_ARCIN_V6_INTROFFSET_1);
-+ break;
-+ }
- }
-
- /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
-@@ -144,10 +140,12 @@
- */
- static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-
-- inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_1);
-- inb(ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ state->enabled = 0;
-+
-+ inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
- }
-
- /* Prototype: icside_irqprobe(struct expansion_card *ec)
-@@ -155,70 +153,49 @@
- */
- static int icside_irqpending_arcin_v6(struct expansion_card *ec)
- {
-- unsigned int ide_base_port = (unsigned int)ec->irq_data;
-+ struct icside_state *state = ec->irq_data;
-
-- return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-- inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
-+ return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-+ inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
- }
-
- static const expansioncard_ops_t icside_ops_arcin_v6 = {
-- icside_irqenable_arcin_v6,
-- icside_irqdisable_arcin_v6,
-- icside_irqpending_arcin_v6,
-- NULL,
-- NULL,
-- NULL
-+ .irqenable = icside_irqenable_arcin_v6,
-+ .irqdisable = icside_irqdisable_arcin_v6,
-+ .irqpending = icside_irqpending_arcin_v6,
- };
-
--/* Prototype: icside_identifyif (struct expansion_card *ec)
-- * Purpose : identify IDE interface type
-- * Notes : checks the description string
-+/*
-+ * Handle routing of interrupts. This is called before
-+ * we write the command to the drive.
- */
--static iftype_t __init icside_identifyif (struct expansion_card *ec)
-+static void icside_maskproc(ide_drive_t *drive, int mask)
- {
-- unsigned int addr;
-- iftype_t iftype;
-- int id = 0;
--
-- iftype = ics_if_unknown;
--
-- addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
--
-- id = inb(addr) & 1;
-- id |= (inb(addr + 1) & 1) << 1;
-- id |= (inb(addr + 2) & 1) << 2;
-- id |= (inb(addr + 3) & 1) << 3;
--
-- switch (id) {
-- case 0: /* A3IN */
-- printk("icside: A3IN unsupported\n");
-- break;
--
-- case 1: /* A3USER */
-- printk("icside: A3USER unsupported\n");
-- break;
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct icside_state *state = hwif->hwif_data;
-+ unsigned long flags;
-
-- case 3: /* ARCIN V6 */
-- printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no);
-- iftype = ics_if_arcin_v6;
-- break;
-+ local_irq_save(flags);
-
-- case 15:/* ARCIN V5 (no id) */
-- printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no);
-- iftype = ics_if_arcin_v5;
-- break;
-+ state->channel = hwif->channel;
-
-- default:/* we don't know - complain very loudly */
-- printk("icside: ***********************************\n");
-- printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id);
-- printk("icside: ***********************************\n");
-- printk("icside: please report this to linux@arm.linux.org.uk\n");
-- printk("icside: defaulting to ARCIN V5\n");
-- iftype = ics_if_arcin_v5;
-- break;
-+ if (state->enabled && !mask) {
-+ switch (hwif->channel) {
-+ case 0:
-+ outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ break;
-+ case 1:
-+ outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ break;
-+ }
-+ } else {
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
- }
-
-- return iftype;
-+ local_irq_restore(flags);
- }
-
- #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-@@ -234,125 +211,138 @@
- #define NR_ENTRIES 256
- #define TABLE_SIZE (NR_ENTRIES * 8)
-
--static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
-+static void ide_build_sglist(ide_drive_t *drive, struct request *rq)
- {
-- struct buffer_head *bh;
-+ ide_hwif_t *hwif = HWIF(drive);
- struct scatterlist *sg = hwif->sg_table;
-+ struct buffer_head *bh;
- int nents = 0;
-
-- if (rq->cmd == READ)
-- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-- else
-- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-- bh = rq->bh;
-- do {
-- unsigned char *virt_addr = bh->b_data;
-- unsigned int size = bh->b_size;
-+ BUG_ON(hwif->sg_dma_active);
-
-- while ((bh = bh->b_reqnext) != NULL) {
-- if ((virt_addr + size) != (unsigned char *)bh->b_data)
-- break;
-- size += bh->b_size;
-- }
-- memset(&sg[nents], 0, sizeof(*sg));
-- sg[nents].address = virt_addr;
-- sg[nents].length = size;
-- nents++;
-- } while (bh != NULL);
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-
-- return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
--}
-+ if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+ else
-+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
--static int
--icside_build_dmatable(ide_drive_t *drive, int ddir)
--{
-- return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir);
--}
-+ memset(sg, 0, sizeof(*sg));
-+ sg->address = rq->buffer;
-+ sg->length = rq->nr_sectors * SECTOR_SIZE;
-+ nents = 1;
-+ } else {
-+ if (rq->cmd == READ)
-+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+ else
-+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
--/* Teardown mappings after DMA has completed. */
--static void icside_destroy_dmatable(ide_drive_t *drive)
--{
-- struct scatterlist *sg = HWIF(drive)->sg_table;
-- int nents = HWIF(drive)->sg_nents;
-+ bh = rq->bh;
-+ do {
-+ unsigned long lastend;
-
-- pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
-+ memset(sg, 0, sizeof(*sg));
-+ sg->page = bh->b_page;
-+ lastend = bh_phys(bh);
-+
-+ do {
-+ lastend += bh->b_size;
-+ sg->length += bh->b_size;
-+
-+ bh = bh->b_reqnext;
-+ if (bh == NULL)
-+ break;
-+ } while (lastend == bh_phys(bh));
-+
-+ sg++;
-+ nents++;
-+ } while (bh != NULL);
-+ }
-+
-+ nents = pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
-+
-+ hwif->sg_nents = nents;
- }
-
--static int
--icside_config_if(ide_drive_t *drive, int xfer_mode)
-+
-+/*
-+ * Configure the IOMD to give the appropriate timings for the transfer
-+ * mode being requested. We take the advice of the ATA standards, and
-+ * calculate the cycle time based on the transfer mode, and the EIDE
-+ * MW DMA specs that the drive provides in the IDENTIFY command.
-+ *
-+ * We have the following IOMD DMA modes to choose from:
-+ *
-+ * Type Active Recovery Cycle
-+ * A 250 (250) 312 (550) 562 (800)
-+ * B 187 250 437
-+ * C 125 (125) 125 (375) 250 (500)
-+ * D 62 125 187
-+ *
-+ * (figures in brackets are actual measured timings)
-+ *
-+ * However, we also need to take care of the read/write active and
-+ * recovery timings:
-+ *
-+ * Read Write
-+ * Mode Active -- Recovery -- Cycle IOMD type
-+ * MW0 215 50 215 480 A
-+ * MW1 80 50 50 150 C
-+ * MW2 70 25 25 120 C
-+ */
-+static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
- {
-- int func = ide_dma_off;
-+ int on = 0, cycle_time = 0, use_dma_info = 0;
-+
-+ /*
-+ * Limit the transfer speed to MW_DMA_2.
-+ */
-+ if (xfer_mode > XFER_MW_DMA_2)
-+ xfer_mode = XFER_MW_DMA_2;
-
- switch (xfer_mode) {
- case XFER_MW_DMA_2:
-- /*
-- * The cycle time is limited to 250ns by the r/w
-- * pulse width (90ns), however we should still
-- * have a maximum burst transfer rate of 8MB/s.
-- */
-- drive->drive_data = 250;
-+ cycle_time = 250;
-+ use_dma_info = 1;
- break;
-
- case XFER_MW_DMA_1:
-- drive->drive_data = 250;
-+ cycle_time = 250;
-+ use_dma_info = 1;
- break;
-
- case XFER_MW_DMA_0:
-- drive->drive_data = 480;
-+ cycle_time = 480;
- break;
-
-- default:
-- drive->drive_data = 0;
-+ case XFER_SW_DMA_2:
-+ case XFER_SW_DMA_1:
-+ case XFER_SW_DMA_0:
-+ cycle_time = 480;
- break;
- }
-
-- if (!drive->init_speed)
-- drive->init_speed = (u8) xfer_mode;
-+ /*
-+ * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
-+ * take care to note the values in the ID...
-+ */
-+ if (use_dma_info && drive->id->eide_dma_time > cycle_time)
-+ cycle_time = drive->id->eide_dma_time;
-
-- if (drive->drive_data &&
-- ide_config_drive_speed(drive, (u8) xfer_mode) == 0)
-- func = ide_dma_on;
-+ drive->drive_data = cycle_time;
-+
-+ if (cycle_time && ide_config_drive_speed(drive, xfer_mode) == 0)
-+ on = 1;
- else
- drive->drive_data = 480;
-
- printk("%s: %s selected (peak %dMB/s)\n", drive->name,
- ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
-
-- drive->current_speed = (u8) xfer_mode;
--
-- return func;
--}
--
--static int
--icside_set_speed(ide_drive_t *drive, u8 speed)
--{
-- return icside_config_if(drive, speed);
--}
--
--/*
-- * dma_intr() is the handler for disk read/write DMA interrupts
-- */
--static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
--{
-- u8 dma_stat = HWIF(drive)->ide_dma_end(drive);
-- /* get drive status */
-- u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
-- int i;
-+ drive->current_speed = xfer_mode;
-
-- if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
-- if (!dma_stat) {
-- struct request *rq = HWGROUP(drive)->rq;
-- rq = HWGROUP(drive)->rq;
-- for (i = rq->nr_sectors; i > 0;) {
-- i -= rq->current_nr_sectors;
-- DRIVER(drive)->end_request(drive, 1);
-- }
-- return ide_stopped;
-- }
-- printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
-- drive->name, dma_stat);
-- }
-- return DRIVER(drive)->error(drive, "dma_intr", stat);
-+ return on;
- }
-
- /*
-@@ -361,19 +351,19 @@
- * This should be defined in one place only.
- */
- struct drive_list_entry {
-- char * id_model;
-- char * id_firmware;
-+ const char * id_model;
-+ const char * id_firmware;
- };
-
--static struct drive_list_entry drive_whitelist [] = {
-+static const struct drive_list_entry drive_whitelist [] = {
- { "Micropolis 2112A", "ALL" },
- { "CONNER CTMA 4000", "ALL" },
- { "CONNER CTT8000-A", "ALL" },
- { "ST34342A", "ALL" },
-- { NULL, 0 }
-+ { NULL, NULL }
- };
-
--static struct drive_list_entry drive_blacklist [] = {
-+static const struct drive_list_entry drive_blacklist [] = {
- { "WDC AC11000H", "ALL" },
- { "WDC AC22100H", "ALL" },
- { "WDC AC32500H", "ALL" },
-@@ -407,10 +397,11 @@
- { "PLEXTOR CD-R PX-W8432T", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
-- { NULL, 0 }
-+ { NULL, NULL }
- };
-
--static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
-+static int
-+in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
- {
- for ( ; drive_table->id_model ; drive_table++)
- if ((!strcmp(drive_table->id_model, id->model)) &&
-@@ -420,41 +411,52 @@
- return 0;
- }
-
--/*
-- * For both Blacklisted and Whitelisted drives.
-- * This is setup to be called as an extern for future support
-- * to other special driver code.
-- */
--int check_drive_good_lists (ide_drive_t *drive)
-+static int icside_dma_host_off(ide_drive_t *drive)
- {
-- struct hd_driveid *id = drive->id;
-- return in_drive_list(id, drive_whitelist);
-+ return 0;
- }
-
--int check_drive_bad_lists (ide_drive_t *drive)
-+static int icside_dma_off_quietly(ide_drive_t *drive)
- {
-- struct hd_driveid *id = drive->id;
-- int blacklist = in_drive_list(id, drive_blacklist);
-- if (blacklist)
-- printk("%s: Disabling DMA for %s\n", drive->name, id->model);
-- return(blacklist);
-+ drive->using_dma = 0;
-+ return icside_dma_host_off(drive);
- }
-
--int icside_dma_check(ide_drive_t *drive)
-+static int icside_dma_off(ide_drive_t *drive)
-+{
-+ printk("%s: DMA disabled\n", drive->name);
-+ return icside_dma_off_quietly(drive);
-+}
-+
-+static int icside_dma_host_on(ide_drive_t *drive)
-+{
-+ return 0;
-+}
-+
-+static int icside_dma_on(ide_drive_t *drive)
-+{
-+ drive->using_dma = 1;
-+ return icside_dma_host_on(drive);
-+}
-+
-+static int icside_dma_check(ide_drive_t *drive)
- {
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
-- int autodma = hwif->autodma;
- int xfer_mode = XFER_PIO_2;
-+ int on;
-
-- if (!id || !(id->capability & 1) || !autodma)
-- return hwif->ide_dma_off_quietly(drive);
-+ if (!id || !(id->capability & 1) || !hwif->autodma)
-+ goto out;
-
- /*
- * Consult the list of known "bad" drives
- */
-- if (check_drive_bad_lists(drive))
-- return hwif->ide_dma_off(drive);
-+ if (in_drive_list(id, drive_blacklist)) {
-+ printk("%s: Disabling DMA for %s (blacklisted)\n",
-+ drive->name, id->model);
-+ goto out;
-+ }
-
- /*
- * Enable DMA on any drive that has multiword DMA
-@@ -473,192 +475,241 @@
- /*
- * Consult the list of known "good" drives
- */
-- if (check_drive_good_lists(drive)) {
-+ if (in_drive_list(id, drive_whitelist)) {
- if (id->eide_dma_time > 150)
- goto out;
- xfer_mode = XFER_MW_DMA_1;
- }
-
- out:
-- if (icside_config_if(drive, xfer_mode))
-- return hwif->ide_dma_on(drive);
-- return hwif->ide_dma_off(drive);
--}
-+ on = icside_set_speed(drive, xfer_mode);
-
--int icside_dma_verbose(ide_drive_t *drive)
--{
-- printk(", DMA");
-- return 1;
-+ if (on)
-+ return icside_dma_on(drive);
-+ else
-+ return icside_dma_off(drive);
- }
-
--int icside_dma_test_irq(ide_drive_t *drive)
-+static int icside_dma_end(ide_drive_t *drive)
- {
- ide_hwif_t *hwif = HWIF(drive);
-- return inb((unsigned long)hwif->hw.priv) & 1;
--}
-
--int icside_dma_host_off(ide_drive_t *drive)
--{
-- return 0;
--}
-+ drive->waiting_for_dma = 0;
-
--int icside_dma_off_quietly(ide_drive_t *drive)
--{
-- drive->using_dma = 0;
-- return icside_dma_host_off(drive);
--}
-+ disable_dma(hwif->hw.dma);
-
--int icside_dma_off(ide_drive_t *drive)
--{
-- printk("%s: DMA disabled\n", drive->name);
-- return icside_dma_off_quietly(drive);
--}
-+ /* Teardown mappings after DMA has completed. */
-+ pci_unmap_sg(NULL, hwif->sg_table, hwif->sg_nents,
-+ hwif->sg_dma_direction);
-
--int icside_dma_host_on(ide_drive_t *drive)
--{
-- return 0;
--}
-+ hwif->sg_dma_active = 0;
-
--int icside_dma_on(ide_drive_t *drive)
--{
-- drive->using_dma = 1;
-- return icside_dma_host_on(drive);
-+ return get_dma_residue(hwif->hw.dma) != 0;
- }
-
--int icside_dma_begin(ide_drive_t *drive)
-+static int icside_dma_begin(ide_drive_t *drive)
- {
- ide_hwif_t *hwif = HWIF(drive);
-
-+ /* We can not enable DMA on both channels simultaneously. */
-+ BUG_ON(dma_channel_active(hwif->hw.dma));
- enable_dma(hwif->hw.dma);
- return 0;
- }
-
--int icside_dma_end(ide_drive_t *drive)
-+static int icside_dma_count(ide_drive_t *drive)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--
-- drive->waiting_for_dma = 0;
-- disable_dma(hwif->hw.dma);
-- icside_destroy_dmatable(drive);
-- return get_dma_residue(hwif->hw.dma) != 0;
-+ return icside_dma_begin(drive);
- }
-
--int icside_dma_count (ide_drive_t *drive)
-+/*
-+ * dma_intr() is the handler for disk read/write DMA interrupts
-+ */
-+static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
- {
-- return icside_dma_begin(drive);
-+ unsigned int stat;
-+ int dma_stat;
-+
-+ dma_stat = icside_dma_end(drive);
-+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
-+ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
-+ if (!dma_stat) {
-+ struct request *rq = HWGROUP(drive)->rq;
-+ int i;
-+
-+ for (i = rq->nr_sectors; i > 0; ) {
-+ i -= rq->current_nr_sectors;
-+ DRIVER(drive)->end_request(drive, 1);
-+ }
-+
-+ return ide_stopped;
-+ }
-+ printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",
-+ drive->name, dma_stat);
-+ }
-+
-+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
- }
-
--int icside_dma_read(ide_drive_t *drive)
-+static int
-+icside_dma_common(ide_drive_t *drive, struct request *rq,
-+ unsigned int dma_mode)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--// ide_task_t *args = HWGROUP(drive)->rq->special;
-- int count = 0;
-- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-- task_ioreg_t command = WIN_NOP;
-+ ide_hwif_t *hwif = HWIF(drive);
-
-- count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE);
-- if (!count)
-- return 1;
-- disable_dma(hwif->hw.dma);
-+ /*
-+ * We can not enable DMA on both channels.
-+ */
-+ BUG_ON(hwif->sg_dma_active);
-+ BUG_ON(dma_channel_active(hwif->hw.dma));
-
-- /* Route the DMA signals to
-- * to the correct interface.
-+ ide_build_sglist(drive, rq);
-+
-+ /*
-+ * Ensure that we have the right interrupt routed.
- */
-- HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
-+ icside_maskproc(drive, 0);
-
-- /* Select the correct timing
-- * for this drive
-+ /*
-+ * Route the DMA signals to the correct interface.
-+ */
-+ outb(hwif->select_data, hwif->config_data);
-+
-+ /*
-+ * Select the correct timing for this drive.
- */
- set_dma_speed(hwif->hw.dma, drive->drive_data);
-
-- set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
-- set_dma_mode(hwif->hw.dma, DMA_MODE_READ);
-+ /*
-+ * Tell the DMA engine about the SG table and
-+ * data direction.
-+ */
-+ set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents);
-+ set_dma_mode(hwif->hw.dma, dma_mode);
-+
-+ return 0;
-+}
-+
-+static int icside_dma_read(ide_drive_t *drive)
-+{
-+ struct request *rq = HWGROUP(drive)->rq;
-+ task_ioreg_t cmd;
-+
-+ if (icside_dma_common(drive, rq, DMA_MODE_READ))
-+ return 1;
-
- drive->waiting_for_dma = 1;
-+
- if (drive->media != ide_disk)
- return 0;
-
-- if (HWGROUP(drive)->handler != NULL) /* paranoia check */
-- BUG();
-- ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
- /*
- * FIX ME to use only ACB ide_task_t args Struct
- */
- #if 0
- {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
- }
- #else
-- command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
-- if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-+ } else if (drive->addressing == 1) {
-+ cmd = WIN_READDMA_EXT;
-+ } else {
-+ cmd = WIN_READDMA;
- }
- #endif
-- /* issue cmd to drive */
-- HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
-
-- return icside_dma_count(drive);
-+ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-+
-+ return icside_dma_begin(drive);
- }
-
--int icside_dma_write(ide_drive_t *drive)
-+static int icside_dma_write(ide_drive_t *drive)
- {
-- ide_hwif_t *hwif = HWIF(drive);
--// ide_task_t *args = HWGROUP(drive)->rq->special;
-- int count = 0;
-- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-- task_ioreg_t command = WIN_NOP;
-+ struct request *rq = HWGROUP(drive)->rq;
-+ task_ioreg_t cmd;
-
-- count = icside_build_dmatable(drive, PCI_DMA_TODEVICE);
-- if (!count)
-+ if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
- return 1;
-- disable_dma(hwif->hw.dma);
--
-- /* Route the DMA signals to
-- * to the correct interface.
-- */
-- HWIF(drive)->OUTB(hwif->select_data, hwif->config_data);
--
-- /* Select the correct timing
-- * for this drive
-- */
-- set_dma_speed(hwif->hw.dma, drive->drive_data);
--
-- set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
-- set_dma_mode(hwif->hw.dma, DMA_MODE_WRITE);
-
- drive->waiting_for_dma = 1;
-+
- if (drive->media != ide_disk)
- return 0;
-
-- if (HWGROUP(drive)->handler != NULL)
-- BUG();
-- ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
- /*
- * FIX ME to use only ACB ide_task_t args Struct
- */
- #if 0
- {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
- }
- #else
-- command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
-- if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-- ide_task_t *args = HWGROUP(drive)->rq->special;
-- command = args->tfRegister[IDE_COMMAND_OFFSET];
-+ if (rq->cmd == IDE_DRIVE_TASKFILE) {
-+ ide_task_t *args = rq->special;
-+ cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-+ } else if (drive->addressing == 1) {
-+ cmd = WIN_WRITEDMA_EXT;
-+ } else {
-+ cmd = WIN_WRITEDMA;
- }
- #endif
-- /* issue cmd to drive */
-- HWIF(drive)->OUTB(command, IDE_COMMAND_REG);
-
-- return icside_dma_count(drive);
-+ ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-+
-+ return icside_dma_begin(drive);
- }
-
--static int
--icside_setup_dma(ide_hwif_t *hwif, int autodma)
-+static int icside_dma_test_irq(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct icside_state *state = hwif->hwif_data;
-+
-+ return inb(state->irq_port +
-+ (hwif->channel ?
-+ ICS_ARCIN_V6_INTRSTAT_2 :
-+ ICS_ARCIN_V6_INTRSTAT_1)) & 1;
-+}
-+
-+static int icside_dma_verbose(ide_drive_t *drive)
-+{
-+ printk(", %s (peak %dMB/s)",
-+ ide_xfer_verbose(drive->current_speed),
-+ 2000 / drive->drive_data);
-+ return 1;
-+}
-+
-+static int icside_dma_timeout(ide_drive_t *drive)
- {
-+ printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-+
-+ if (icside_dma_test_irq(drive))
-+ return 0;
-+
-+ ide_dump_status(drive, "DMA timeout",
-+ HWIF(drive)->INB(IDE_STATUS_REG));
-+
-+ return icside_dma_end(drive);
-+}
-+
-+static int icside_dma_lostirq(ide_drive_t *drive)
-+{
-+ printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-+ return 1;
-+}
-+
-+static int icside_dma_init(ide_hwif_t *hwif)
-+{
-+ int autodma = 0;
-+
-+#ifdef CONFIG_IDEDMA_ICS_AUTO
-+ autodma = 1;
-+#endif
-+
- printk(" %s: SG-DMA", hwif->name);
-
- hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
-@@ -666,40 +717,53 @@
- if (!hwif->sg_table)
- goto failed;
-
-- hwif->dmatable_cpu = NULL;
-- hwif->dmatable_dma = 0;
-- hwif->speedproc = icside_set_speed;
-- hwif->autodma = autodma;
-+ hwif->atapi_dma = 1;
-+ hwif->mwdma_mask = 7; /* MW0..2 */
-+ hwif->swdma_mask = 7; /* SW0..2 */
-
-- hwif->ide_dma_check = icside_dma_check;
-- hwif->ide_dma_host_off = icside_dma_host_off;
-+ hwif->dmatable_cpu = NULL;
-+ hwif->dmatable_dma = 0;
-+ hwif->speedproc = icside_set_speed;
-+ hwif->autodma = autodma;
-+
-+ hwif->ide_dma_check = icside_dma_check;
-+ hwif->ide_dma_host_off = icside_dma_host_off;
- hwif->ide_dma_off_quietly = icside_dma_off_quietly;
-- hwif->ide_dma_off = icside_dma_off;
-- hwif->ide_dma_host_on = icside_dma_host_on;
-- hwif->ide_dma_on = icside_dma_on;
-- hwif->ide_dma_read = icside_dma_read;
-- hwif->ide_dma_write = icside_dma_write;
-- hwif->ide_dma_count = icside_dma_count;
-- hwif->ide_dma_begin = icside_dma_begin;
-- hwif->ide_dma_end = icside_dma_end;
-- hwif->ide_dma_verbose = icside_dma_verbose;
-- hwif->ide_dma_bad_drive = check_drive_bad_lists;
-- hwif->ide_dma_good_drive = check_drive_good_lists;
-- hwif->ide_dma_test_irq = icside_dma_test_irq;
-+ hwif->ide_dma_off = icside_dma_off;
-+ hwif->ide_dma_host_on = icside_dma_host_on;
-+ hwif->ide_dma_on = icside_dma_on;
-+ hwif->ide_dma_read = icside_dma_read;
-+ hwif->ide_dma_write = icside_dma_write;
-+ hwif->ide_dma_count = icside_dma_count;
-+ hwif->ide_dma_begin = icside_dma_begin;
-+ hwif->ide_dma_end = icside_dma_end;
-+ hwif->ide_dma_test_irq = icside_dma_test_irq;
-+ hwif->ide_dma_verbose = icside_dma_verbose;
-+ hwif->ide_dma_timeout = icside_dma_timeout;
-+ hwif->ide_dma_lostirq = icside_dma_lostirq;
-
-- printk(" capable%s\n", autodma ?
-- ", auto-enable" : "");
-+ printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
-
- return 1;
-
- failed:
-- printk(" -- ERROR, unable to allocate DMA table\n");
-+ printk(" disabled, unable to allocate DMA table\n");
- return 0;
- }
-+
-+static void icside_dma_exit(ide_hwif_t *hwif)
-+{
-+ if (hwif->sg_table) {
-+ kfree(hwif->sg_table);
-+ hwif->sg_table = NULL;
-+ }
-+}
-+#else
-+#define icside_dma_init(hwif) (0)
-+#define icside_dma_exit(hwif) do { } while (0)
- #endif
-
--static ide_hwif_t *
--icside_find_hwif(unsigned long dataport)
-+static ide_hwif_t *icside_find_hwif(unsigned long dataport)
- {
- ide_hwif_t *hwif;
- int index;
-@@ -716,13 +780,13 @@
- goto found;
- }
-
-- return NULL;
-+ hwif = NULL;
- found:
- return hwif;
- }
-
- static ide_hwif_t *
--icside_setup(unsigned long base, struct cardinfo *info, int irq)
-+icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec)
- {
- unsigned long port = base + info->dataoffset;
- ide_hwif_t *hwif;
-@@ -740,8 +804,8 @@
- }
- hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
- hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
-- hwif->hw.irq = irq;
-- hwif->irq = irq;
-+ hwif->hw.irq = ec->irq;
-+ hwif->irq = ec->irq;
- hwif->hw.dma = NO_DMA;
- hwif->noprobe = 0;
- hwif->chipset = ide_acorn;
-@@ -750,33 +814,39 @@
- return hwif;
- }
-
--static int __init icside_register_v5(struct expansion_card *ec, int autodma)
-+static int __init
-+icside_register_v5(struct icside_state *state, struct expansion_card *ec)
- {
- unsigned long slot_port;
- ide_hwif_t *hwif;
-
- slot_port = ecard_address(ec, ECARD_MEMC, 0);
-
-+ state->irq_port = slot_port;
-+
- ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
- ec->irqmask = 1;
-- ec->irq_data = (void *)slot_port;
-- ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
-+ ec->irq_data = state;
-+ ec->ops = &icside_ops_arcin_v5;
-
- /*
- * Be on the safe side - disable interrupts
- */
- inb(slot_port + ICS_ARCIN_V5_INTROFFSET);
-
-- hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq);
-+ hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);
-
-- return hwif ? 0 : -1;
-+ state->hwif[0] = hwif;
-+
-+ return hwif ? 0 : -ENODEV;
- }
-
--static int __init icside_register_v6(struct expansion_card *ec, int autodma)
-+static int __init
-+icside_register_v6(struct icside_state *state, struct expansion_card *ec)
- {
- unsigned long slot_port, port;
- ide_hwif_t *hwif, *mate;
-- int sel = 0;
-+ unsigned int sel = 0;
-
- slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
- port = ecard_address(ec, ECARD_EASI, ECARD_FAST);
-@@ -788,88 +858,185 @@
-
- outb(sel, slot_port);
-
-- ec->irq_data = (void *)port;
-- ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
--
- /*
- * Be on the safe side - disable interrupts
- */
- inb(port + ICS_ARCIN_V6_INTROFFSET_1);
- inb(port + ICS_ARCIN_V6_INTROFFSET_2);
-
-- hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq);
-- mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq);
-+ /*
-+ * Find and register the interfaces.
-+ */
-+ hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
-+ mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
-
--#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
-- if (ec->dma != NO_DMA) {
-- if (request_dma(ec->dma, hwif->name))
-- goto no_dma;
-+ if (!hwif || !mate)
-+ return -ENODEV;
-
-- if (hwif) {
-- hwif->config_data = slot_port;
-- hwif->select_data = sel;
-- hwif->hw.dma = ec->dma;
-- hwif->hw.priv = (void *)
-- (port + ICS_ARCIN_V6_INTRSTAT_1);
-- hwif->channel = 0;
-- icside_setup_dma(hwif, autodma);
-- hwif->drives[0].autodma = autodma;
-- hwif->drives[1].autodma = autodma;
-- }
-- if (mate) {
-- mate->config_data = slot_port;
-- mate->select_data = sel | 1;
-- mate->hw.dma = ec->dma;
-- mate->hw.priv = (void *)
-- (port + ICS_ARCIN_V6_INTRSTAT_2);
-- mate->channel = 1;
-- icside_setup_dma(mate, autodma);
-- mate->drives[0].autodma = autodma;
-- mate->drives[1].autodma = autodma;
-- }
-+ state->irq_port = port;
-+ state->slot_port = slot_port;
-+ state->hwif[0] = hwif;
-+ state->hwif[1] = mate;
-+
-+ ec->irq_data = state;
-+ ec->ops = &icside_ops_arcin_v6;
-+
-+ hwif->maskproc = icside_maskproc;
-+ hwif->channel = 0;
-+ hwif->hwif_data = state;
-+ hwif->mate = mate;
-+ hwif->serialized = 1;
-+ hwif->config_data = slot_port;
-+ hwif->select_data = sel;
-+ hwif->hw.dma = ec->dma;
-+
-+ mate->maskproc = icside_maskproc;
-+ mate->channel = 1;
-+ mate->hwif_data = state;
-+ mate->mate = hwif;
-+ mate->serialized = 1;
-+ mate->config_data = slot_port;
-+ mate->select_data = sel | 1;
-+ mate->hw.dma = ec->dma;
-+
-+ if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
-+ icside_dma_init(hwif);
-+ icside_dma_init(mate);
- }
--no_dma:
--#endif
-- return hwif || mate ? 0 : -1;
-+ return 0;
- }
-
--int __init icside_init(void)
-+static int __init icside_probe(struct expansion_card *ec, const struct ecard_id *id)
- {
-- int autodma = 0;
-+ struct icside_state *state;
-+ int ret;
-
--#ifdef CONFIG_IDEDMA_ICS_AUTO
-- autodma = 1;
--#endif
-+ state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);
-+ if (!state) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-
-- ecard_startfind ();
-+ memset(state, 0, sizeof(struct icside_state));
-+ state->type = ICS_TYPE_NOTYPE;
-
-- do {
-- struct expansion_card *ec;
-- int result;
-+ {
-+ unsigned int addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET;
-+ unsigned int type;
-
-- ec = ecard_find(0, icside_cids);
-- if (ec == NULL)
-- break;
-+ type = inb(addr) & 1;
-+ type |= (inb(addr + 1) & 1) << 1;
-+ type |= (inb(addr + 2) & 1) << 2;
-+ type |= (inb(addr + 3) & 1) << 3;
-
-- ecard_claim(ec);
-+ state->type = type;
-+ }
-
-- switch (icside_identifyif(ec)) {
-- case ics_if_arcin_v5:
-- result = icside_register_v5(ec, autodma);
-- break;
-+ switch (state->type) {
-+ case ICS_TYPE_A3IN:
-+ printk(KERN_WARNING "icside: A3IN unsupported\n");
-+ ret = -ENODEV;
-+ break;
-
-- case ics_if_arcin_v6:
-- result = icside_register_v6(ec, autodma);
-- break;
-+ case ICS_TYPE_A3USER:
-+ printk(KERN_WARNING "icside: A3USER unsupported\n");
-+ ret = -ENODEV;
-+ break;
-
-- default:
-- result = -1;
-- break;
-- }
-+ case ICS_TYPE_V5:
-+ ret = icside_register_v5(state, ec);
-+ break;
-
-- if (result)
-- ecard_release(ec);
-- } while (1);
-+ case ICS_TYPE_V6:
-+ ret = icside_register_v6(state, ec);
-+ break;
-
-- return 0;
-+ default:
-+ printk(KERN_WARNING "icside: unknown interface type\n");
-+ ret = -ENODEV;
-+ break;
-+ }
-+
-+ if (ret == 0) {
-+ ecard_set_drvdata(ec, state);
-+ } else {
-+ kfree(state);
-+ }
-+ out:
-+ return ret;
-+}
-+
-+static void __devexit icside_remove(struct expansion_card *ec)
-+{
-+ struct icside_state *state = ecard_get_drvdata(ec);
-+
-+ switch (state->type) {
-+ case ICS_TYPE_V5:
-+ /* FIXME: tell IDE to stop using the interface */
-+
-+ /* Disable interrupts */
-+ inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
-+ break;
-+
-+ case ICS_TYPE_V6:
-+ /* FIXME: tell IDE to stop using the interface */
-+ icside_dma_exit(state->hwif[1]);
-+ icside_dma_exit(state->hwif[0]);
-+
-+ if (ec->dma != NO_DMA)
-+ free_dma(ec->dma);
-+
-+ /* Disable interrupts */
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+
-+ /* Reset the ROM pointer/EASI selection */
-+ outb(0, state->slot_port);
-+ break;
-+ }
-+
-+ ecard_set_drvdata(ec, NULL);
-+ ec->ops = NULL;
-+ ec->irq_data = NULL;
-+
-+ kfree(state);
-+}
-+
-+static void icside_shutdown(struct expansion_card *ec)
-+{
-+ struct icside_state *state = ecard_get_drvdata(ec);
-+
-+ switch (state->type) {
-+ case ICS_TYPE_V5:
-+ /* Disable interrupts */
-+ inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
-+ break;
-+
-+ case ICS_TYPE_V6:
-+ /* Disable interrupts */
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-+ inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-+
-+ /* Reset the ROM pointer/EASI selection */
-+ outb(0, state->slot_port);
-+ break;
-+ }
-+}
-+
-+static const struct ecard_id icside_ids[] = {
-+ { MANU_ICS, PROD_ICS_IDE },
-+ { MANU_ICS2, PROD_ICS2_IDE },
-+ { 0xffff, 0xffff }
-+};
-+
-+static struct ecard_driver icside_driver = {
-+ .probe = icside_probe,
-+ .remove = __devexit_p(icside_remove),
-+ .shutdown = icside_shutdown,
-+ .id_table = icside_ids,
-+};
-+
-+int __init icside_init(void)
-+{
-+ return ecard_register_driver(&icside_driver);
- }
---- /dev/null
-+++ linux-2.4.27/drivers/ide/arm/rstation-ide.c
-@@ -0,0 +1,78 @@
-+/*
-+ * linux/drivers/ide/rs-ide.c
-+ *
-+ * Copyright (c) 2002 Ben Dooks
-+ * Copyright (c) 2002 Simtec Electronics
-+ *
-+ * Simple RiscStation IDE support
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/blkdev.h>
-+#include <linux/errno.h>
-+#include <linux/ide.h>
-+#include <linux/init.h>
-+
-+#include <asm/hardware/iomd.h>
-+#include <asm/mach-types.h>
-+#include <asm/io.h>
-+
-+#ifndef CONFIG_ARCH_RISCSTATION
-+#error "compiling this code for non-riscstation hardware is dangerous!"
-+#endif
-+
-+#define DRV_PREFIX "ide-rs"
-+
-+#define IRQ_PRI (40+3)
-+#define IRQ_SEC (40+4)
-+
-+#define PORT_BASE ((0x2b800 - 0x10000) >> 2)
-+#define SEC_OFF (0x400 >> 2)
-+
-+int __init rside_reg(unsigned long base, unsigned int irq);
-+
-+int __init rside_init(void)
-+{
-+ int iotcr;
-+
-+ if (!machine_is_riscstation()) {
-+ printk(DRV_PREFIX ": hardware is not a RiscStation!\n");
-+ return 0;
-+ }
-+
-+ /* select correct area cycle time */
-+
-+ iotcr = inb(IOMD_IOTCR);
-+ outb((iotcr & ~3) | 1, IOMD_IOTCR);
-+
-+ /* register h/w */
-+
-+ rside_reg(PORT_BASE, IRQ_PRI);
-+ rside_reg(PORT_BASE + SEC_OFF, IRQ_SEC);
-+
-+ return 0;
-+}
-+
-+
-+int __init rside_reg(unsigned long port, unsigned int irq)
-+{
-+ unsigned long addr, i;
-+ hw_regs_t hw;
-+
-+ hw.irq = irq;
-+
-+ addr = port;
-+
-+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-+ hw.io_ports[i] = (ide_ioreg_t)addr;
-+ addr += 0x40 >> 2;
-+ }
-+
-+ hw.io_ports[IDE_CONTROL_OFFSET] = port + ((0xb80 - 0x800) >> 2);
-+
-+ printk(DRV_PREFIX ": registering channel at %08lx, %08lx, irq %d\n",
-+ port, hw.io_ports[IDE_CONTROL_OFFSET], irq);
-+
-+ return ide_register_hw(&hw, NULL);
-+}
---- linux-2.4.27/drivers/ide/ide-probe.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/ide-probe.c
-@@ -1297,11 +1297,11 @@
- hwif->name, hwif->major);
- return (hwif->present = 0);
- }
--
-+
- if (init_irq(hwif)) {
- int i = hwif->irq;
- /*
-- * It failed to initialise. Find the default IRQ for
-+ * It failed to initialise. Find the default IRQ for
- * this port and try that.
- */
- if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
-@@ -1319,7 +1319,7 @@
- printk("%s: probed IRQ %d failed, using default.\n",
- hwif->name, hwif->irq);
- }
--
-+
- init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].queue = ide_get_queue;
---- linux-2.4.27/drivers/ide/ide-proc.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/ide-proc.c
-@@ -425,6 +425,7 @@
- case ide_cy82c693: name = "cy82c693"; break;
- case ide_4drives: name = "4drives"; break;
- case ide_pmac: name = "pmac"; break;
-+ case ide_acorn: name = "acorn"; break;
- default: name = "(unknown)"; break;
- }
- len = sprintf(page, "%s\n", name);
---- linux-2.4.27/drivers/ide/ide.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/ide.c
-@@ -218,23 +218,14 @@
- static void init_hwif_data (unsigned int index)
- {
- unsigned int unit;
-- hw_regs_t hw;
- ide_hwif_t *hwif = &ide_hwifs[index];
-
- /* bulk initialize hwif & drive info with zeros */
- memset(hwif, 0, sizeof(ide_hwif_t));
-- memset(&hw, 0, sizeof(hw_regs_t));
-
- /* fill in any non-zero initial values */
- hwif->index = index;
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
-- memcpy(&hwif->hw, &hw, sizeof(hw));
-- memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
-- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
--#ifdef CONFIG_BLK_DEV_HD
-- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
-- hwif->noprobe = 1; /* may be overridden by ide_setup() */
--#endif /* CONFIG_BLK_DEV_HD */
-+ hwif->noprobe = 1;
- hwif->major = ide_hwif_to_major[index];
- hwif->name[0] = 'i';
- hwif->name[1] = 'd';
-@@ -276,6 +267,28 @@
- }
-
- /*
-+ * Old compatability function - initialise ports using ide_default_io_base
-+ */
-+static void ide_old_init_default_hwifs(void)
-+{
-+ unsigned int index;
-+ ide_ioreg_t base;
-+ ide_hwif_t *hwif;
-+
-+ for (index = 0; index < MAX_HWIFS; index++) {
-+ hwif = &ide_hwifs[index];
-+
-+ base = ide_default_io_base(index);
-+
-+ if (base) {
-+ ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->hw.irq);
-+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
-+ hwif->noprobe = 0;
-+ }
-+ }
-+}
-+
-+/*
- * init_ide_data() sets reasonable default values into all fields
- * of all instances of the hwifs and drives, but only on the first call.
- * Subsequent calls have no effect (they don't wipe out anything).
-@@ -307,6 +320,7 @@
- init_hwif_data(index);
-
- /* Add default hw interfaces */
-+ ide_old_init_default_hwifs();
- ide_init_default_hwifs();
-
- idebus_parameter = 0;
-@@ -2530,6 +2544,12 @@
- rapide_init();
- }
- #endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
-+#ifdef CONFIG_BLK_DEV_IDE_RISCSTATION
-+ {
-+ extern void rside_init(void);
-+ rside_init();
-+ }
-+#endif /* CONFIG_BLK_DEV_IDE_RISCSTATION */
- #ifdef CONFIG_BLK_DEV_GAYLE
- {
- extern void gayle_init(void);
---- linux-2.4.27/drivers/ide/pci/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/pci/Makefile
-@@ -16,7 +16,6 @@
- obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
- obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
- #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o
--obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
- obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
- obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
- obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
---- linux-2.4.27/drivers/ide/pci/sl82c105.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/ide/pci/sl82c105.c
-@@ -37,7 +37,7 @@
- #ifdef DEBUG
- #define DBG(arg) printk arg
- #else
--#define DBG(fmt,...)
-+#define DBG(fmt...)
- #endif
- /*
- * SL82C105 PCI config register 0x40 bits.
---- /dev/null
-+++ linux-2.4.27/drivers/ide/pci/sl82c105.c.2419
-@@ -0,0 +1,380 @@
-+/*
-+ * linux/drivers/ide/sl82c105.c
-+ *
-+ * SL82C105/Winbond 553 IDE driver
-+ *
-+ * Maintainer unknown.
-+ *
-+ * Changelog:
-+ *
-+ * 15/11/1998 RMK Drive tuning added from Rebel.com's kernel
-+ * sources
-+ * 30/03/2002 RMK Add fixes specified in W83C553F errata.
-+ * (with special thanks to Todd Inglett)
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/timer.h>
-+#include <linux/mm.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/blkdev.h>
-+#include <linux/hdreg.h>
-+#include <linux/pci.h>
-+#include <linux/ide.h>
-+
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+
-+#include "ide_modes.h"
-+
-+extern char *ide_xfer_verbose (byte xfer_rate);
-+
-+/*
-+ * SL82C105 PCI config register 0x40 bits.
-+ */
-+#define CTRL_IDE_IRQB (1 << 30)
-+#define CTRL_IDE_IRQA (1 << 28)
-+#define CTRL_LEGIRQ (1 << 11)
-+#define CTRL_P1F16 (1 << 5)
-+#define CTRL_P1EN (1 << 4)
-+#define CTRL_P0F16 (1 << 1)
-+#define CTRL_P0EN (1 << 0)
-+
-+/*
-+ * Convert a PIO mode and cycle time to the required on/off
-+ * times for the interface. This has protection against run-away
-+ * timings.
-+ */
-+static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
-+{
-+ unsigned int cmd_on;
-+ unsigned int cmd_off;
-+
-+ cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
-+ cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
-+
-+ if (cmd_on > 32)
-+ cmd_on = 32;
-+ if (cmd_on == 0)
-+ cmd_on = 1;
-+
-+ if (cmd_off > 32)
-+ cmd_off = 32;
-+ if (cmd_off == 0)
-+ cmd_off = 1;
-+
-+ return (cmd_on - 1) << 8 | (cmd_off - 1) | (p->use_iordy ? 0x40 : 0x00);
-+}
-+
-+/*
-+ * Configure the drive and chipset for PIO
-+ */
-+static void config_for_pio(ide_drive_t *drive, int pio, int report)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ ide_pio_data_t p;
-+ unsigned short drv_ctrl = 0x909;
-+ unsigned int xfer_mode, reg;
-+
-+ reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-+
-+ pio = ide_get_best_pio_mode(drive, pio, 5, &p);
-+
-+ switch (pio) {
-+ default:
-+ case 0: xfer_mode = XFER_PIO_0; break;
-+ case 1: xfer_mode = XFER_PIO_1; break;
-+ case 2: xfer_mode = XFER_PIO_2; break;
-+ case 3: xfer_mode = XFER_PIO_3; break;
-+ case 4: xfer_mode = XFER_PIO_4; break;
-+ }
-+
-+ if (ide_config_drive_speed(drive, xfer_mode) == 0)
-+ drv_ctrl = get_timing_sl82c105(&p);
-+
-+ if (drive->using_dma == 0) {
-+ /*
-+ * If we are actually using MW DMA, then we can not
-+ * reprogram the interface drive control register.
-+ */
-+ pci_write_config_word(dev, reg, drv_ctrl);
-+ pci_read_config_word(dev, reg, &drv_ctrl);
-+
-+ if (report) {
-+ printk("%s: selected %s (%dns) (%04X)\n", drive->name,
-+ ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
-+ }
-+ }
-+}
-+
-+/*
-+ * Configure the drive and the chipset for DMA
-+ */
-+static int config_for_dma(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ unsigned short drv_ctrl = 0x909;
-+ unsigned int reg;
-+
-+ reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-+
-+ if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
-+ drv_ctrl = 0x0240;
-+
-+ pci_write_config_word(dev, reg, drv_ctrl);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Check to see if the drive and
-+ * chipset is capable of DMA mode
-+ */
-+static int sl82c105_check_drive(ide_drive_t *drive)
-+{
-+ ide_dma_action_t dma_func = ide_dma_off_quietly;
-+
-+ do {
-+ struct hd_driveid *id = drive->id;
-+ ide_hwif_t *hwif = HWIF(drive);
-+
-+ if (!hwif->autodma)
-+ break;
-+
-+ if (!id || !(id->capability & 1))
-+ break;
-+
-+ /* Consult the list of known "bad" drives */
-+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-+ dma_func = ide_dma_off;
-+ break;
-+ }
-+
-+ if (id->field_valid & 2) {
-+ if (id->dma_mword & 7 || id->dma_1word & 7)
-+ dma_func = ide_dma_on;
-+ break;
-+ }
-+
-+ if (ide_dmaproc(ide_dma_good_drive, drive)) {
-+ dma_func = ide_dma_on;
-+ break;
-+ }
-+ } while (0);
-+
-+ return HWIF(drive)->dmaproc(dma_func, drive);
-+}
-+
-+/*
-+ * The SL82C105 holds off all IDE interrupts while in DMA mode until
-+ * all DMA activity is completed. Sometimes this causes problems (eg,
-+ * when the drive wants to report an error condition).
-+ *
-+ * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller
-+ * state machine. We need to kick this to work around various bugs.
-+ */
-+static inline void sl82c105_reset_host(struct pci_dev *dev)
-+{
-+ u16 val;
-+
-+ pci_read_config_word(dev, 0x7e, &val);
-+ pci_write_config_word(dev, 0x7e, val | (1 << 2));
-+ pci_write_config_word(dev, 0x7e, val & ~(1 << 2));
-+}
-+
-+/*
-+ * If we get an IRQ timeout, it might be that the DMA state machine
-+ * got confused. Fix from Todd Inglett. Details from Winbond.
-+ *
-+ * This function is called when the IDE timer expires, the drive
-+ * indicates that it is READY, and we were waiting for DMA to complete.
-+ */
-+static int sl82c105_lostirq(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+ u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
-+ unsigned long dma_base = hwif->dma_base;
-+
-+ printk("sl82c105: lost IRQ: resetting host\n");
-+
-+ /*
-+ * Check the raw interrupt from the drive.
-+ */
-+ pci_read_config_dword(dev, 0x40, &val);
-+ if (val & mask)
-+ printk("sl82c105: drive was requesting IRQ, but host lost it\n");
-+
-+ /*
-+ * Was DMA enabled? If so, disable it - we're resetting the
-+ * host. The IDE layer will be handling the drive for us.
-+ */
-+ val = inb(dma_base);
-+ if (val & 1) {
-+ outb(val & ~1, dma_base);
-+ printk("sl82c105: DMA was enabled\n");
-+ }
-+
-+ sl82c105_reset_host(dev);
-+
-+ /* ide_dmaproc would return 1, so we do as well */
-+ return 1;
-+}
-+
-+/*
-+ * ATAPI devices can cause the SL82C105 DMA state machine to go gaga.
-+ * Winbond recommend that the DMA state machine is reset prior to
-+ * setting the bus master DMA enable bit.
-+ *
-+ * The generic IDE core will have disabled the BMEN bit before this
-+ * function is called.
-+ */
-+static void sl82c105_before_bm_enable(ide_drive_t *drive)
-+{
-+ ide_hwif_t *hwif = HWIF(drive);
-+ struct pci_dev *dev = hwif->pci_dev;
-+
-+ sl82c105_reset_host(dev);
-+}
-+
-+/*
-+ * Our very own dmaproc. We need to intercept various calls
-+ * to fix up the SL82C105 specific behaviour.
-+ */
-+static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-+{
-+ switch (func) {
-+ case ide_dma_check:
-+ return sl82c105_check_drive(drive);
-+
-+ case ide_dma_on:
-+ if (config_for_dma(drive))
-+ func = ide_dma_off;
-+ /* fall through */
-+
-+ case ide_dma_off_quietly:
-+ case ide_dma_off:
-+ config_for_pio(drive, 4, 0);
-+ break;
-+
-+ case ide_dma_read:
-+ case ide_dma_write:
-+ case ide_dma_begin:
-+ case ide_dma_timeout:
-+ sl82c105_before_bm_enable(drive);
-+ break;
-+
-+ case ide_dma_lostirq:
-+ return sl82c105_lostirq(drive);
-+
-+ default:
-+ break;
-+ }
-+ return ide_dmaproc(func, drive);
-+}
-+
-+/*
-+ * We only deal with PIO mode here - DMA mode 'using_dma' is not
-+ * initialised at the point that this function is called.
-+ */
-+static void tune_sl82c105(ide_drive_t *drive, byte pio)
-+{
-+ config_for_pio(drive, pio, 1);
-+
-+ /*
-+ * We support 32-bit I/O on this interface, and it
-+ * doesn't have problems with interrupts.
-+ */
-+ drive->io_32bit = 1;
-+ drive->unmask = 1;
-+}
-+
-+/*
-+ * Return the revision of the Winbond bridge
-+ * which this function is part of.
-+ */
-+static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
-+{
-+ struct pci_dev *bridge;
-+ unsigned char rev;
-+
-+ /*
-+ * The bridge should be part of the same device, but function 0.
-+ */
-+ bridge = pci_find_slot(dev->bus->number,
-+ PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
-+ if (!bridge)
-+ return -1;
-+
-+ /*
-+ * Make sure it is a Winbond 553 and is an ISA bridge.
-+ */
-+ if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
-+ bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
-+ bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA)
-+ return -1;
-+
-+ /*
-+ * We need to find function 0's revision, not function 1
-+ */
-+ pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
-+
-+ return rev;
-+}
-+
-+/*
-+ * Enable the PCI device
-+ */
-+unsigned int __init pci_init_sl82c105(struct pci_dev *dev, const char *msg)
-+{
-+ u32 val;
-+
-+ pci_read_config_dword(dev, 0x40, &val);
-+ val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1EN | CTRL_P1F16;
-+ pci_write_config_dword(dev, 0x40, val);
-+
-+ return dev->irq;
-+}
-+
-+void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
-+{
-+ unsigned int bridge_rev;
-+ byte dma_state;
-+
-+ dma_state = inb(dma_base + 2);
-+ bridge_rev = sl82c105_bridge_revision(hwif->pci_dev);
-+ if (bridge_rev <= 5) {
-+ hwif->autodma = 0;
-+ hwif->drives[0].autotune = 1;
-+ hwif->drives[1].autotune = 1;
-+ printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
-+ hwif->name, bridge_rev);
-+ dma_state &= ~0x60;
-+ } else {
-+ dma_state |= 0x60;
-+ hwif->autodma = 1;
-+ }
-+ outb(dma_state, dma_base + 2);
-+
-+ ide_setup_dma(hwif, dma_base, 8);
-+
-+ if (bridge_rev <= 5)
-+ hwif->dmaproc = NULL;
-+ else
-+ hwif->dmaproc = sl82c105_dmaproc;
-+}
-+
-+/*
-+ * Initialise the chip
-+ */
-+void __init ide_init_sl82c105(ide_hwif_t *hwif)
-+{
-+ hwif->tuneproc = tune_sl82c105;
-+}
-+
---- linux-2.4.27/drivers/input/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/input/Config.in
-@@ -15,5 +15,6 @@
- dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_INPUT
- dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_INPUT
- dep_tristate ' User level driver support' CONFIG_INPUT_UINPUT $CONFIG_INPUT
-+dep_tristate ' MX1 touchscreen support' CONFIG_INPUT_MX1TS $CONFIG_INPUT_MOUSEDEV $CONFIG_ARCH_MX1ADS
-
- endmenu
---- linux-2.4.27/drivers/input/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/input/Makefile
-@@ -24,6 +24,7 @@
- obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
- obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
- obj-$(CONFIG_INPUT_EVDEV) += evdev.o
-+obj-$(CONFIG_INPUT_MX1TS) += mx1ts.o
- obj-$(CONFIG_INPUT_UINPUT) += uinput.o
-
- # The global Rules.make.
---- /dev/null
-+++ linux-2.4.27/drivers/input/mx1ts.c
-@@ -0,0 +1,508 @@
-+/*
-+ * linux/drivers/misc/mx1ts.c
-+ *
-+ * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * Cloned from ucb1x00_ts.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/smp_lock.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+
-+#include <linux/input.h>
-+
-+#include "mx1ts.h"
-+
-+#define DEV_IRQ_ID "mx1-ts"
-+
-+struct mx1_ts {
-+ struct input_dev idev;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pmdev;
-+#endif
-+
-+ wait_queue_head_t irq_wait;
-+ struct completion init_exit;
-+ int use_count;
-+ u16 x_res;
-+ u16 y_res;
-+
-+ int restart:1;
-+};
-+
-+static struct mx1_ts mx1ts;
-+static u8 mx1_performing_auto_calibration = 0;
-+static u16 mx1_cal_auto_zero = 0;
-+static u16 mx1_cal_range_x = 0;
-+static u16 mx1_cal_range_y = 0;
-+
-+static int mx1_ts_startup(struct mx1_ts *ts);
-+static void mx1_ts_shutdown(struct mx1_ts *ts);
-+
-+static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs);
-+static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs);
-+static void mx1_ts_compare_int(int irq, void *dev_id, struct pt_regs *regs);
-+
-+static void mx1_ts_enable_pen_touch_interrupt(void);
-+static void mx1_ts_disable_pen_touch_interrupt(void);
-+static void mx1_ts_enable_pen_up_interrupt(void);
-+static void mx1_ts_disable_pen_up_interrupt(void);
-+static void mx1_ts_enable_auto_sample(void);
-+static void mx1_ts_disable_auto_sample(void);
-+static void mx1_ts_start_auto_calibration(void);
-+
-+static inline void mx1_reg_write(unsigned int reg, unsigned int val)
-+{
-+ *((volatile unsigned int *)reg) = val;
-+}
-+
-+static inline unsigned int mx1_reg_read(unsigned int reg)
-+{
-+ return *((volatile unsigned int *)reg);
-+}
-+
-+static inline void mx1_reg_clear_bit(unsigned int reg, unsigned int bit)
-+{
-+ *((volatile unsigned int *)reg) &= ~bit;
-+}
-+
-+static inline void mx1_reg_set_bit(unsigned int reg, unsigned int bit)
-+{
-+ *((volatile unsigned int *)reg) |= bit;
-+}
-+
-+static inline void mx1_ts_evt_add(struct mx1_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ input_report_abs(&ts->idev, ABS_X, (int)x - 32768);
-+ input_report_abs(&ts->idev, ABS_Y, (int)y - 32768);
-+ input_report_abs(&ts->idev, ABS_PRESSURE, (int)pressure);
-+}
-+
-+static inline void mx1_ts_flush_fifo(void)
-+{
-+ int i;
-+ for (i = 0; i < 12; i++)
-+ if (mx1_reg_read(ASP_ISTATR) & (ASP_PFF | ASP_PDR))
-+ mx1_reg_read(ASP_PADFIFO);
-+}
-+
-+static int mx1_ts_open(struct input_dev *idev)
-+{
-+ struct mx1_ts *ts = (struct mx1_ts *)idev;
-+
-+ mx1_performing_auto_calibration = 0;
-+ return mx1_ts_startup(ts);
-+}
-+
-+static void mx1_ts_close(struct input_dev *idev)
-+{
-+ struct mx1_ts *ts = (struct mx1_ts *)idev;
-+
-+ mx1_ts_shutdown(ts);
-+}
-+
-+static inline int mx1_ts_enable_irqs(void)
-+{
-+ int result;
-+
-+ result = request_irq(ASP_PENDATA_IRQ,
-+ mx1_ts_pendata_int,
-+ SA_INTERRUPT,
-+ DEV_IRQ_ID,
-+ DEV_IRQ_ID);
-+ if (result) {
-+ printk("Couldn't request pen data IRQ.\n");
-+ return result;
-+ }
-+
-+ result = request_irq(ASP_TOUCH_IRQ,
-+ mx1_ts_touch_int,
-+ SA_INTERRUPT,
-+ DEV_IRQ_ID,
-+ DEV_IRQ_ID);
-+ if (result) {
-+ printk("Couldn't request pen touch IRQ.\n");
-+ free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
-+ return result;
-+ }
-+
-+ return result;
-+}
-+
-+static inline int mx1_ts_disable_irqs(void)
-+{
-+ free_irq(ASP_PENDATA_IRQ, DEV_IRQ_ID);
-+ free_irq(ASP_TOUCH_IRQ, DEV_IRQ_ID);
-+
-+ return 0;
-+}
-+
-+static inline int mx1_ts_register(struct mx1_ts *ts)
-+{
-+ ts->idev.name = "Touchscreen panel";
-+ ts->idev.open = mx1_ts_open;
-+ ts->idev.close = mx1_ts_close;
-+
-+ __set_bit(EV_ABS, ts->idev.evbit);
-+ __set_bit(ABS_X, ts->idev.absbit);
-+ __set_bit(ABS_Y, ts->idev.absbit);
-+ __set_bit(ABS_PRESSURE, ts->idev.absbit);
-+
-+ ts->idev.absmin[ABS_X] = 0;
-+ ts->idev.absmax[ABS_X] = (u32)0x0000FFFF;
-+ ts->idev.absfuzz[ABS_X] = 50;
-+ ts->idev.absflat[ABS_X] = 0;
-+
-+ ts->idev.absmin[ABS_Y] = 0;
-+ ts->idev.absmax[ABS_Y] = (u32)0x0000FFFF;
-+ ts->idev.absfuzz[ABS_Y] = 50;
-+ ts->idev.absflat[ABS_Y] = 0;
-+
-+ input_register_device(&ts->idev);
-+
-+ return 0;
-+}
-+
-+static inline void mx1_ts_deregister(struct mx1_ts *ts)
-+{
-+ input_unregister_device(&ts->idev);
-+}
-+
-+/*
-+ * Handle the touch interrupt, generated when the pen is pressed/
-+ * released.
-+ */
-+static void mx1_ts_touch_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ /* Clear the interrupt. */
-+ mx1_reg_set_bit(ASP_ISTATR, ASP_PEN);
-+
-+ mx1_ts_disable_pen_touch_interrupt();
-+ mx1_ts_start_auto_calibration();
-+ mx1_ts_enable_pen_up_interrupt();
-+}
-+
-+/*
-+ * Handle the pen data ready interrupt, generated when pen data is
-+ * in the FIFO.
-+ */
-+static void mx1_ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ static unsigned int auto_zero, pen_x, pen_y, pen_u;
-+
-+ if (mx1_reg_read(ASP_ISTATR) & 0x400) {
-+ mx1_reg_set_bit(ASP_ISTATR, 0x400);
-+
-+ mx1_ts_disable_auto_sample();
-+ mx1_ts_disable_pen_up_interrupt();
-+ mx1_ts_enable_pen_touch_interrupt();
-+
-+ mx1_ts_evt_add(&mx1ts, 0, pen_x, pen_y);
-+
-+ mx1_ts_flush_fifo();
-+
-+ return;
-+ }
-+
-+ if (mx1_performing_auto_calibration) {
-+ unsigned int value;
-+
-+ mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+ mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+ mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
-+
-+ if ((mx1_cal_auto_zero >= mx1_cal_range_x) ||
-+ (mx1_cal_auto_zero >= mx1_cal_range_y)) {
-+ /* Invalid data. */
-+ mx1_ts_start_auto_calibration();
-+ return;
-+ }
-+
-+ mx1_cal_range_x -= mx1_cal_auto_zero;
-+ mx1_cal_range_y -= mx1_cal_auto_zero;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+ value &= ~0x04000000; /* XXX Undocumented. */
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ mx1_performing_auto_calibration = 0;
-+
-+ mx1_ts_enable_auto_sample();
-+ } else {
-+ /* There could be more than one sample in the FIFO, but we're
-+ * only going to read one per call. The interrupt will be
-+ * generated as long as there is data in the FIFO. */
-+
-+ if ((mx1_reg_read(ASP_ISTATR) & ASP_PDR) != ASP_PDR) {
-+ return;
-+ }
-+
-+ auto_zero = mx1_reg_read(ASP_PADFIFO);
-+ if (auto_zero > (mx1_cal_auto_zero + 0x200)) {
-+ return;
-+ }
-+
-+ pen_x = mx1_reg_read(ASP_PADFIFO);
-+ pen_y = mx1_reg_read(ASP_PADFIFO);
-+ pen_u = mx1_reg_read(ASP_PADFIFO);
-+
-+ pen_x = (u32)(((pen_x - mx1_cal_auto_zero) << 16) /
-+ mx1_cal_range_x);
-+ pen_y = (u32)(((pen_y - mx1_cal_auto_zero) << 16) /
-+ mx1_cal_range_y);
-+
-+ mx1_ts_evt_add(&mx1ts, pen_u, pen_x, pen_y);
-+ }
-+}
-+
-+static void mx1_ts_reset_asp(void)
-+{
-+ unsigned int value;
-+
-+ mx1_ts_flush_fifo();
-+
-+ /* Soft reset the ASP module */
-+ mx1_reg_write(ASP_ACNTLCR, ASP_SWRST);
-+
-+ /* Read back the reset value of the control register */
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Enable the clock and wait for a short while */
-+ value |= ASP_CLKEN;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+ udelay(100);
-+
-+ /* Set the value of the conrtol register. */
-+ value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Set the clock divide ratio to 2. */
-+ mx1_reg_write(ASP_CLKDIV, 0x01);
-+
-+ /* Set the sample rate control register. These values should yield
-+ * about 150 samples per second, which seems to give good smooth
-+ * lines. */
-+ value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */
-+ (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */
-+ (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */
-+ mx1_reg_write(ASP_PSMPLRG, value);
-+
-+ /* Disable the compare function. */
-+ mx1_reg_write(ASP_CMPCNTL, 0);
-+}
-+
-+static void mx1_ts_enable_auto_sample(void)
-+{
-+ unsigned int value;
-+
-+ mx1_ts_flush_fifo();
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to X then Y */
-+ value &= ~ASP_MODE_MASK;
-+ value |= ASP_MODE_ONLY_Y;
-+
-+ /* Enable auto zero. */
-+ value |= ASP_AZE;
-+
-+ /* Enable auto sample. */
-+ value |= ASP_AUTO;
-+
-+ /* Enable pen A/D. */
-+ value |= ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Enable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PFFE | ASP_PDRE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_auto_sample(void)
-+{
-+ unsigned int value;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to none */
-+ value &= ~ASP_MODE_MASK;
-+
-+ /* Disable auto zero. */
-+ value &= ~ASP_AZE;
-+
-+ /* Disable auto sample. */
-+ value &= ~ASP_AUTO;
-+
-+ /* Disable pen A/D. */
-+ value &= ~ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Disable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~(ASP_PFFE | ASP_PDRE);
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_enable_pen_touch_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen touch interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_EDGE | ASP_PIRQE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_pen_touch_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen touch interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~ASP_PIRQE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_enable_pen_up_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen up interrupt. XXX: This feature is undocumented. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_disable_pen_up_interrupt(void)
-+{
-+ unsigned int value;
-+
-+ /* Enable pen up interrupt. XXX: This feature is undocumented. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value &= ~ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static void mx1_ts_start_auto_calibration(void)
-+{
-+ unsigned int value;
-+
-+ mx1_performing_auto_calibration = 1;
-+
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+
-+ /* Set the mode to X then Y */
-+ value &= ~ASP_MODE_MASK;
-+ value |= ASP_MODE_ONLY_X;
-+
-+ /* Enable auto zero. */
-+ value |= ASP_AZE;
-+
-+ /* Enable auto calibrate. XXX: Undocumented bitfield. */
-+ value |= 0x04000000;
-+
-+ /* Enable auto sample. */
-+ value |= ASP_AUTO;
-+
-+ /* Enable pen A/D. */
-+ value |= ASP_PADE;
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+
-+ /* Enable pen data ready and full interrupt. */
-+ value = mx1_reg_read(ASP_ICNTLR);
-+ value |= ASP_PFFE | ASP_PDRE | ASP_PUPE;
-+ mx1_reg_write(ASP_ICNTLR, value);
-+}
-+
-+static int mx1_ts_startup(struct mx1_ts *ts)
-+{
-+ int ret = 0;
-+
-+ if (ts->use_count++ != 0)
-+ goto out;
-+
-+ /*
-+ * Reset the ASP.
-+ */
-+ mx1_ts_reset_asp();
-+
-+
-+ /*
-+ * XXX: Figure out if we need this...
-+ * If we do this at all, we should allow the user to
-+ * measure and read the X and Y resistance at any time.
-+ */
-+ //ts->x_res = mx1_ts_read_xres(ts);
-+ //ts->y_res = mx1_ts_read_yres(ts);
-+
-+ mx1_ts_enable_pen_touch_interrupt();
-+
-+ out:
-+ if (ret)
-+ ts->use_count--;
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static void mx1_ts_shutdown(struct mx1_ts *ts)
-+{
-+ if (--ts->use_count == 0) {
-+ unsigned int value;
-+
-+ /* Turn off the ADC and associated circuitry. */
-+ value = mx1_reg_read(ASP_ACNTLCR);
-+ value &= !(ASP_CLKEN | ASP_PADE | ASP_BGE);
-+ mx1_reg_write(ASP_ACNTLCR, value);
-+ }
-+}
-+
-+/*
-+ * Initialization.
-+ */
-+static int __init mx1_ts_init(void)
-+{
-+ int ret = 0;
-+ struct mx1_ts *ts = &mx1ts;
-+
-+ mx1_ts_reset_asp();
-+
-+ /*
-+ * Enable the IRQ's
-+ */
-+ if ((ret = mx1_ts_enable_irqs()))
-+ return ret;
-+
-+ return mx1_ts_register(ts);
-+}
-+
-+static void __exit mx1_ts_exit(void)
-+{
-+ struct mx1_ts *ts = &mx1ts;
-+
-+ mx1_ts_disable_irqs();
-+ mx1_ts_deregister(ts);
-+}
-+
-+module_init(mx1_ts_init);
-+module_exit(mx1_ts_exit);
-+
-+MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
-+MODULE_DESCRIPTION("MX1 touchscreen driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/input/mx1ts.h
-@@ -0,0 +1,108 @@
-+/*
-+ * linux/drivers/misc/mx1ts.h
-+ *
-+ * Copyright (C) 2003 Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+/* Interrupt numbers */
-+#define ASP_COMPARE_IRQ 5
-+#define ASP_PENDATA_IRQ 33
-+#define ASP_TOUCH_IRQ 46
-+
-+/* Analog signal processor (ASP) control registers */
-+#define ASP_ACNTLCR 0xF0215010 /* Control register */
-+#define ASP_PSMPLRG 0xF0215014 /* Pen A/D sampe rate control */
-+#define ASP_CMPCNTL 0xF0215030 /* Compare control register */
-+#define ASP_ICNTLR 0xF0215018 /* Interrupt control register */
-+#define ASP_ISTATR 0xF021501C /* Interrupt status register */
-+#define ASP_PADFIFO 0xF0215000 /* Pen sample FIFO */
-+#define ASP_CLKDIV 0xF021502C /* Clock divide register */
-+
-+/* ASP control register bits */
-+#define ASP_CLKEN (1 << 25) /* Clock enable */
-+#define ASP_SWRST (1 << 23) /* Software reset */
-+#define ASP_U_SEL (1 << 21) /* U-channel resistor select */
-+#define ASP_AZ_SEL (1 << 20) /* Auto-zero position select */
-+#define ASP_LVM (1 << 19) /* Low voltage output */
-+#define ASP_NM (1 << 18) /* Normal voltage output */
-+#define ASP_HPM (1 << 17) /* High voltage output */
-+#define ASP_GLO (1 << 16) /* Low gain enable */
-+#define ASP_AZE (1 << 15) /* Auto-zero enable */
-+#define ASP_AUTO (1 << 14) /* Auto sampling */
-+#define ASP_SW8 (1 << 11) /* Switch control 8 */
-+#define ASP_SW7 (1 << 10)
-+#define ASP_SW6 (1 << 9)
-+#define ASP_SW5 (1 << 8)
-+#define ASP_SW4 (1 << 7)
-+#define ASP_SW3 (1 << 6)
-+#define ASP_SW2 (1 << 5)
-+#define ASP_SW1 (1 << 4) /* Switch control 1 */
-+#define ASP_VDAE (1 << 3) /* Voice D/A enable */
-+#define ASP_VADE (1 << 2) /* Voice A/D enable */
-+#define ASP_PADE (1 << 1) /* Pen A/D enable */
-+#define ASP_BGE (1 << 0) /* Bandgap enable */
-+
-+#define ASP_MODE_MASK 0x00003000
-+#define ASP_MODE_NONE 0x00000000
-+#define ASP_MODE_ONLY_X 0x00001000
-+#define ASP_MODE_ONLY_Y 0x00002000
-+#define ASP_MODE_ONLY_U 0x00003000
-+
-+/* ASP Pen A/D sample rate control register */
-+#define ASP_DMCNT_MASK (0x00007000) /* Decimation ratio count */
-+#define ASP_DMCNT_SCALE (12)
-+#define ASP_BIT_SELECT_MASK (0x00000C00) /* Bit select */
-+#define ASP_BIT_SELECT_SCALE (10)
-+#define ASP_IDLECNT_MASK (0x000003F0) /* Idle count */
-+#define ASP_IDLECNT_SCALE (4)
-+#define ASP_DSCNT_MASK (0x0000000F) /* Data setup count */
-+#define ASP_DSCNT_SCALE (0)
-+
-+/* ASP compare control register */
-+#define ASP_INT (1 << 19) /* Interrupt status */
-+#define ASP_CC (1 << 18) /* Trigger on greater than */
-+#define ASP_INSEL_MASK (0x00030000)
-+#define ASP_INSEL_DISABLE (0x00000000)
-+#define ASP_INSEL_X (0x00010000)
-+#define ASP_INSEL_Y (0x00020000)
-+#define ASP_INSEL_U (0x00030000)
-+#define ASP_COMPARE_VAL_MASK (0x0000FFFF)
-+#define ASP_COMPARE_VAL_SCALE (0)
-+
-+/* ASP interrupt control register bits */
-+#define ASP_PUPE (1 << 10) /* Pen up XXX undocumented */
-+#define ASP_VDDMAE (1 << 8) /* VDAC FIFO empty DMA */
-+#define ASP_VADMAE (1 << 7) /* VADC FIFO full DMA */
-+#define ASP_POL (1 << 6) /* Pen interrupt polarity */
-+#define ASP_EDGE (1 << 5) /* Edge trigger enable */
-+#define ASP_PIRQE (1 << 4) /* Pen interrupt enable */
-+#define ASP_VDAFEE (1 << 3) /* VDAC FIFO empty interrupt */
-+#define ASP_VADFFE (1 << 2) /* VADC FIFO full interrupt */
-+#define ASP_PFFE (1 << 1) /* Pen FIFO full interrupt */
-+#define ASP_PDRE (1 << 0) /* Pen data ready interrupt */
-+
-+/* ASP interrupt/error status register bits */
-+#define ASP_PUP (1 << 10) /* Pen up XXX undocumented */
-+#define ASP_BGR (1 << 9) /* Bandgap ready */
-+#define ASP_VOV (1 << 8) /* Voice sample data overflow */
-+#define ASP_POV (1 << 7) /* Pen sample data overflow */
-+#define ASP_PEN (1 << 6) /* Pen interrupt */
-+#define ASP_VDAFF (1 << 5) /* VDAC FIFO full */
-+#define ASP_VDAFE (1 << 4) /* VDAC FIFO empty */
-+#define ASP_VADFF (1 << 3) /* VADC FIFO full */
-+#define ASP_VADDR (1 << 2) /* VADC data ready */
-+#define ASP_PFF (1 << 1) /* Pen sample FIFO full */
-+#define ASP_PDR (1 << 0) /* Pen data ready */
-+
-+/* ASP Clock divide register */
-+#define ASP_PADC_CLK_MASK (0x0000001F)
-+#define ASP_PADC_CLK_SCALE (0)
-+#define ASP_VADC_CLK_MASK (0x000003E0)
-+#define ASP_VADC_CLK_SCALE (5)
-+#define ASP_VDAC_CLK_MASK (0x00003C00)
-+#define ASP_VDAC_CLK_SCALE (10)
---- /dev/null
-+++ linux-2.4.27/drivers/l3/Config.in
-@@ -0,0 +1,21 @@
-+#
-+# L3 bus configuration
-+#
-+mainmenu_option next_comment
-+comment 'L3 serial bus support'
-+
-+tristate 'L3 support' CONFIG_L3
-+dep_bool ' L3 bit-banging interfaces' CONFIG_L3_ALGOBIT $CONFIG_L3
-+dep_bool ' SA11x0 GPIO adapter' CONFIG_L3_BIT_SA1100_GPIO $CONFIG_L3_ALGOBIT $CONFIG_ARCH_SA1100
-+
-+comment 'Other L3 adapters'
-+dep_bool ' SA1111 adapter' CONFIG_L3_SA1111 $CONFIG_L3
-+endmenu
-+
-+# i2c must come before this
-+if [ "$CONFIG_L3_BIT_SA1100_GPIO" = "y" -o \
-+ "$CONFIG_I2C_BIT_SA1100_GPIO" = "y" ]; then
-+ define_bool CONFIG_BIT_SA1100_GPIO y
-+else
-+ define_bool CONFIG_BIT_SA1100_GPIO n
-+fi
---- /dev/null
-+++ linux-2.4.27/drivers/l3/Makefile
-@@ -0,0 +1,23 @@
-+#
-+# Makefile for the L3 bus driver.
-+#
-+
-+O_TARGET := l3.o
-+
-+export-objs := l3-core.o l3-algo-bit.o
-+l3-y :=
-+l3-n :=
-+l3-drv-y :=
-+l3-drv-n :=
-+
-+# Link order:
-+# (core, adapters, algorithms, drivers) then clients
-+
-+l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o
-+l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o
-+l3-$(CONFIG_L3_SA1111) += l3-sa1111.o
-+
-+obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y)
-+
-+include $(TOPDIR)/Rules.make
-+
---- /dev/null
-+++ linux-2.4.27/drivers/l3/l3-algo-bit.c
-@@ -0,0 +1,175 @@
-+/*
-+ * L3 bus algorithm module.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Note that L3 buses can share the same pins as I2C buses, so we must
-+ * _not_ generate an I2C start condition. An I2C start condition is
-+ * defined as a high-to-low transition of the data line while the clock
-+ * is high. Therefore, we must only change the data line while the
-+ * clock is low.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/algo-bit.h>
-+
-+#define setdat(adap,val) adap->setdat(adap->data, val)
-+#define setclk(adap,val) adap->setclk(adap->data, val)
-+#define setmode(adap,val) adap->setmode(adap->data, val)
-+#define setdatin(adap) adap->setdir(adap->data, 1)
-+#define setdatout(adap) adap->setdir(adap->data, 0)
-+#define getdat(adap) adap->getdat(adap->data)
-+
-+/*
-+ * Send one byte of data to the chip. Data is latched into the chip on
-+ * the rising edge of the clock.
-+ */
-+static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte)
-+{
-+ int i;
-+
-+ for (i = 0; i < 8; i++) {
-+ setclk(adap, 0);
-+ udelay(adap->data_hold);
-+ setdat(adap, byte & 1);
-+ udelay(adap->data_setup);
-+ setclk(adap, 1);
-+ udelay(adap->clock_high);
-+ byte >>= 1;
-+ }
-+}
-+
-+/*
-+ * Send a set of bytes to the chip. We need to pulse the MODE line
-+ * between each byte, but never at the start nor at the end of the
-+ * transfer.
-+ */
-+static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ if (i) {
-+ udelay(adap->mode_hold);
-+ setmode(adap, 0);
-+ udelay(adap->mode);
-+ }
-+ setmode(adap, 1);
-+ udelay(adap->mode_setup);
-+ sendbyte(adap, buf[i]);
-+ }
-+}
-+
-+/*
-+ * Read one byte of data from the chip. Data is latched into the chip on
-+ * the rising edge of the clock.
-+ */
-+static unsigned int readbyte(struct l3_algo_bit_data *adap)
-+{
-+ unsigned int byte = 0;
-+ int i;
-+
-+ for (i = 0; i < 8; i++) {
-+ setclk(adap, 0);
-+ udelay(adap->data_hold + adap->data_setup);
-+ setclk(adap, 1);
-+ if (getdat(adap))
-+ byte |= 1 << i;
-+ udelay(adap->clock_high);
-+ }
-+
-+ return byte;
-+}
-+
-+/*
-+ * Read a set of bytes from the chip. We need to pulse the MODE line
-+ * between each byte, but never at the start nor at the end of the
-+ * transfer.
-+ */
-+static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ if (i) {
-+ udelay(adap->mode_hold);
-+ setmode(adap, 0);
-+ }
-+ setmode(adap, 1);
-+ udelay(adap->mode_setup);
-+ buf[i] = readbyte(adap);
-+ }
-+}
-+
-+static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num)
-+{
-+ struct l3_algo_bit_data *adap = l3_adap->algo_data;
-+ int i;
-+
-+ /*
-+ * If we share an I2C bus, ensure that it is in STOP mode
-+ */
-+ setclk(adap, 1);
-+ setdat(adap, 1);
-+ setmode(adap, 1);
-+ setdatout(adap);
-+ udelay(adap->mode);
-+
-+ for (i = 0; i < num; i++) {
-+ struct l3_msg *pmsg = &msgs[i];
-+
-+ if (!(pmsg->flags & L3_M_NOADDR)) {
-+ setmode(adap, 0);
-+ udelay(adap->mode_setup);
-+ sendbyte(adap, pmsg->addr);
-+ udelay(adap->mode_hold);
-+ }
-+
-+ if (pmsg->flags & L3_M_RD) {
-+ setdatin(adap);
-+ readbytes(adap, pmsg->buf, pmsg->len);
-+ } else {
-+ setdatout(adap);
-+ sendbytes(adap, pmsg->buf, pmsg->len);
-+ }
-+ }
-+
-+ /*
-+ * Ensure that we leave the bus in I2C stop mode.
-+ */
-+ setclk(adap, 1);
-+ setdat(adap, 1);
-+ setmode(adap, 0);
-+ setdatin(adap);
-+
-+ return num;
-+}
-+
-+static struct l3_algorithm l3_bit_algo = {
-+ name: "L3 bit-shift algorithm",
-+ xfer: l3_xfer,
-+};
-+
-+int l3_bit_add_bus(struct l3_adapter *adap)
-+{
-+ adap->algo = &l3_bit_algo;
-+ return l3_add_adapter(adap);
-+}
-+
-+int l3_bit_del_bus(struct l3_adapter *adap)
-+{
-+ return l3_del_adapter(adap);
-+}
-+
-+EXPORT_SYMBOL(l3_bit_add_bus);
-+EXPORT_SYMBOL(l3_bit_del_bus);
---- /dev/null
-+++ linux-2.4.27/drivers/l3/l3-bit-sa1100.c
-@@ -0,0 +1,277 @@
-+/*
-+ * linux/drivers/l3/l3-bit-sa1100.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * This is a combined I2C and L3 bus driver.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/ioport.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/i2c-algo-bit.h>
-+#include <linux/l3/algo-bit.h>
-+
-+#include <asm/system.h>
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/assabet.h>
-+
-+#define NAME "l3-bit-sa1100-gpio"
-+
-+struct bit_data {
-+ unsigned int sda;
-+ unsigned int scl;
-+ unsigned int l3_mode;
-+};
-+
-+static int getsda(void *data)
-+{
-+ struct bit_data *bits = data;
-+
-+ return GPLR & bits->sda;
-+}
-+
-+#ifdef CONFIG_I2C_BIT_SA1100_GPIO
-+static void i2c_setsda(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPDR &= ~bits->sda;
-+ else {
-+ GPCR = bits->sda;
-+ GPDR |= bits->sda;
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+static void i2c_setscl(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPDR &= ~bits->scl;
-+ else {
-+ GPCR = bits->scl;
-+ GPDR |= bits->scl;
-+ }
-+ local_irq_restore(flags);
-+}
-+
-+static int i2c_getscl(void *data)
-+{
-+ struct bit_data *bits = data;
-+
-+ return GPLR & bits->scl;
-+}
-+
-+static struct i2c_algo_bit_data i2c_bit_data = {
-+ setsda: i2c_setsda,
-+ setscl: i2c_setscl,
-+ getsda: getsda,
-+ getscl: i2c_getscl,
-+ udelay: 10,
-+ mdelay: 10,
-+ timeout: 100,
-+};
-+
-+static struct i2c_adapter i2c_adapter = {
-+ name: NAME,
-+ algo_data: &i2c_bit_data,
-+// inc_use: i2c_inc_use,
-+// dec_use: i2c_dec_use,
-+};
-+
-+#define LOCK &i2c_adapter.lock
-+
-+static int __init i2c_init(struct bit_data *bits)
-+{
-+ i2c_bit_data.data = bits;
-+ return i2c_bit_add_bus(&i2c_adapter);
-+}
-+
-+static void i2c_exit(void)
-+{
-+ i2c_bit_del_bus(&i2c_adapter);
-+}
-+
-+#else
-+static DECLARE_MUTEX(l3_lock);
-+#define LOCK &l3_lock
-+#define i2c_init(bits) (0)
-+#define i2c_exit() do { } while (0)
-+#endif
-+
-+#ifdef CONFIG_L3_BIT_SA1100_GPIO
-+/*
-+ * iPAQs need the clock line driven hard high and low.
-+ */
-+static void l3_setscl(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (state)
-+ GPSR = bits->scl;
-+ else
-+ GPCR = bits->scl;
-+ GPDR |= bits->scl;
-+ local_irq_restore(flags);
-+}
-+
-+static void l3_setsda(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+
-+ if (state)
-+ GPSR = bits->sda;
-+ else
-+ GPCR = bits->sda;
-+}
-+
-+static void l3_setdir(void *data, int in)
-+{
-+ struct bit_data *bits = data;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ if (in)
-+ GPDR &= ~bits->sda;
-+ else
-+ GPDR |= bits->sda;
-+ local_irq_restore(flags);
-+}
-+
-+static void l3_setmode(void *data, int state)
-+{
-+ struct bit_data *bits = data;
-+
-+ if (state)
-+ GPSR = bits->l3_mode;
-+ else
-+ GPCR = bits->l3_mode;
-+}
-+
-+static struct l3_algo_bit_data l3_bit_data = {
-+ data: NULL,
-+ setdat: l3_setsda,
-+ setclk: l3_setscl,
-+ setmode: l3_setmode,
-+ setdir: l3_setdir,
-+ getdat: getsda,
-+ data_hold: 1,
-+ data_setup: 1,
-+ clock_high: 1,
-+ mode_hold: 1,
-+ mode_setup: 1,
-+};
-+
-+static struct l3_adapter l3_adapter = {
-+ owner: THIS_MODULE,
-+ name: NAME,
-+ algo_data: &l3_bit_data,
-+ lock: LOCK,
-+};
-+
-+static int __init l3_init(struct bit_data *bits)
-+{
-+ l3_bit_data.data = bits;
-+ return l3_bit_add_bus(&l3_adapter);
-+}
-+
-+static void __exit l3_exit(void)
-+{
-+ l3_bit_del_bus(&l3_adapter);
-+}
-+#else
-+#define l3_init(bits) (0)
-+#define l3_exit() do { } while (0)
-+#endif
-+
-+static struct bit_data bit_data;
-+
-+static int __init bus_init(void)
-+{
-+ struct bit_data *bit = &bit_data;
-+ unsigned long flags;
-+ int ret;
-+
-+ if (machine_is_assabet() || machine_is_pangolin()) {
-+ bit->sda = GPIO_GPIO15;
-+ bit->scl = GPIO_GPIO18;
-+ bit->l3_mode = GPIO_GPIO17;
-+ }
-+
-+#if defined(CONFIG_SA1100_H3600) || defined(CONFIG_SA1100_H3100)
-+ if (machine_is_h3600() || machine_is_h3100()) {
-+ bit->sda = GPIO_H3600_L3_DATA;
-+ bit->scl = GPIO_H3600_L3_CLOCK;
-+ bit->l3_mode = GPIO_H3600_L3_MODE;
-+ }
-+#endif
-+
-+#ifdef CONFIG_SA1100_STORK
-+ if (machine_is_stork()) {
-+ bit->sda = GPIO_STORK_L3_I2C_SDA;
-+ bit->scl = GPIO_STORK_L3_I2C_SCL;
-+ bit->l3_mode = GPIO_STORK_L3_MODE;
-+ }
-+#endif
-+
-+ if (!bit->sda)
-+ return -ENODEV;
-+
-+ /*
-+ * Default level for L3 mode is low.
-+ * We set SCL and SDA high (i2c idle state).
-+ */
-+ local_irq_save(flags);
-+ GPDR &= ~(bit->scl | bit->sda);
-+ GPCR = bit->l3_mode | bit->scl | bit->sda;
-+ GPDR |= bit->l3_mode;
-+ local_irq_restore(flags);
-+
-+ if (machine_is_assabet()) {
-+ /*
-+ * Release reset on UCB1300, ADI7171 and UDA1341. We
-+ * need to do this here so that we can communicate on
-+ * the I2C/L3 buses.
-+ */
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ mdelay(1);
-+ ASSABET_BCR_clear(ASSABET_BCR_CODEC_RST);
-+ mdelay(1);
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ }
-+
-+ ret = i2c_init(bit);
-+ if (ret == 0 && bit->l3_mode) {
-+ ret = l3_init(bit);
-+ if (ret)
-+ i2c_exit();
-+ }
-+
-+ return ret;
-+}
-+
-+static void __exit bus_exit(void)
-+{
-+ l3_exit();
-+ i2c_exit();
-+}
-+
-+module_init(bus_init);
-+module_exit(bus_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/l3/l3-core.c
-@@ -0,0 +1,377 @@
-+/*
-+ * linux/drivers/l3/l3-core.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * General structure taken from i2c-core.c by Simon G. Vogl
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * See linux/Documentation/l3 for further documentation.
-+ */
-+#include <linux/module.h>
-+#include <linux/config.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/proc_fs.h>
-+#include <linux/kmod.h>
-+#include <linux/init.h>
-+#include <linux/l3/l3.h>
-+
-+static DECLARE_MUTEX(adapter_lock);
-+static LIST_HEAD(adapter_list);
-+
-+static DECLARE_MUTEX(driver_lock);
-+static LIST_HEAD(driver_list);
-+
-+/**
-+ * l3_add_adapter - register a new L3 bus adapter
-+ * @adap: l3_adapter structure for the registering adapter
-+ *
-+ * Make the adapter available for use by clients using name adap->name.
-+ * The adap->adapters list is initialised by this function.
-+ *
-+ * Returns 0;
-+ */
-+int l3_add_adapter(struct l3_adapter *adap)
-+{
-+ INIT_LIST_HEAD(&adap->clients);
-+ down(&adapter_lock);
-+ list_add(&adap->adapters, &adapter_list);
-+ up(&adapter_lock);
-+ return 0;
-+}
-+
-+/**
-+ * l3_del_adapter - unregister a L3 bus adapter
-+ * @adap: l3_adapter structure to unregister
-+ *
-+ * Remove an adapter from the list of available L3 Bus adapters.
-+ *
-+ * Returns 0;
-+ */
-+int l3_del_adapter(struct l3_adapter *adap)
-+{
-+ down(&adapter_lock);
-+ list_del(&adap->adapters);
-+ up(&adapter_lock);
-+ return 0;
-+}
-+
-+static struct l3_adapter *__l3_get_adapter(const char *name)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &adapter_list) {
-+ struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
-+
-+ if (strcmp(adap->name, name) == 0)
-+ return adap;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * l3_get_adapter - get a reference to an adapter
-+ * @name: driver name
-+ *
-+ * Obtain a l3_adapter structure for the specified adapter. If the adapter
-+ * is not currently load, then load it. The adapter will be locked in core
-+ * until all references are released via l3_put_adapter.
-+ */
-+struct l3_adapter *l3_get_adapter(const char *name)
-+{
-+ struct l3_adapter *adap;
-+ int try;
-+
-+ for (try = 0; try < 2; try ++) {
-+ down(&adapter_lock);
-+ adap = __l3_get_adapter(name);
-+ if (adap && !try_inc_mod_count(adap->owner))
-+ adap = NULL;
-+ up(&adapter_lock);
-+
-+ if (adap)
-+ break;
-+
-+ if (try == 0)
-+ request_module(name);
-+ }
-+
-+ return adap;
-+}
-+
-+/**
-+ * l3_put_adapter - release a reference to an adapter
-+ * @adap: driver to release reference
-+ *
-+ * Indicate to the L3 core that you no longer require the adapter reference.
-+ * The adapter module may be unloaded when there are no references to its
-+ * data structure.
-+ *
-+ * You must not use the reference after calling this function.
-+ */
-+void l3_put_adapter(struct l3_adapter *adap)
-+{
-+ if (adap && adap->owner)
-+ __MOD_DEC_USE_COUNT(adap->owner);
-+}
-+
-+/**
-+ * l3_add_driver - register a new L3 device driver
-+ * @driver - driver structure to make available
-+ *
-+ * Make the driver available for use by clients using name driver->name.
-+ * The driver->drivers list is initialised by this function.
-+ *
-+ * Returns 0;
-+ */
-+int l3_add_driver(struct l3_driver *driver)
-+{
-+ down(&driver_lock);
-+ list_add(&driver->drivers, &driver_list);
-+ up(&driver_lock);
-+ return 0;
-+}
-+
-+/**
-+ * l3_del_driver - unregister a L3 device driver
-+ * @driver: driver to remove
-+ *
-+ * Remove an driver from the list of available L3 Bus device drivers.
-+ *
-+ * Returns 0;
-+ */
-+int l3_del_driver(struct l3_driver *driver)
-+{
-+ down(&driver_lock);
-+ list_del(&driver->drivers);
-+ up(&driver_lock);
-+ return 0;
-+}
-+
-+static struct l3_driver *__l3_get_driver(const char *name)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &driver_list) {
-+ struct l3_driver *drv = list_entry(l, struct l3_driver, drivers);
-+
-+ if (strcmp(drv->name, name) == 0)
-+ return drv;
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * l3_get_driver - get a reference to a driver
-+ * @name: driver name
-+ *
-+ * Obtain a l3_driver structure for the specified driver. If the driver is
-+ * not currently load, then load it. The driver will be locked in core
-+ * until all references are released via l3_put_driver.
-+ */
-+struct l3_driver *l3_get_driver(const char *name)
-+{
-+ struct l3_driver *drv;
-+ int try;
-+
-+ for (try = 0; try < 2; try ++) {
-+ down(&adapter_lock);
-+ drv = __l3_get_driver(name);
-+ if (drv && !try_inc_mod_count(drv->owner))
-+ drv = NULL;
-+ up(&adapter_lock);
-+
-+ if (drv)
-+ break;
-+
-+ if (try == 0)
-+ request_module(name);
-+ }
-+
-+ return drv;
-+}
-+
-+/**
-+ * l3_put_driver - release a reference to a driver
-+ * @drv: driver to release reference
-+ *
-+ * Indicate to the L3 core that you no longer require the driver reference.
-+ * The driver module may be unloaded when there are no references to its
-+ * data structure.
-+ *
-+ * You must not use the reference after calling this function.
-+ */
-+void l3_put_driver(struct l3_driver *drv)
-+{
-+ if (drv && drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+}
-+
-+/**
-+ * l3_attach_client - attach a client to an adapter and driver
-+ * @client: client structure to attach
-+ * @adap: adapter (module) name
-+ * @drv: driver (module) name
-+ *
-+ * Attempt to attach a client (a user of a device driver) to a particular
-+ * driver and adapter. If the specified driver or adapter aren't registered,
-+ * request_module is used to load the relevant modules.
-+ *
-+ * Returns 0 on success, or negative error code.
-+ */
-+int l3_attach_client(struct l3_client *client, const char *adap, const char *drv)
-+{
-+ struct l3_adapter *adapter = l3_get_adapter(adap);
-+ struct l3_driver *driver = l3_get_driver(drv);
-+ int ret = -ENOENT;
-+
-+ if (!adapter)
-+ printk(KERN_ERR "%s: unable to get adapter: %s\n",
-+ __FUNCTION__, adap);
-+ if (!driver)
-+ printk(KERN_ERR "%s: unable to get driver: %s\n",
-+ __FUNCTION__, drv);
-+
-+ if (adapter && driver) {
-+ ret = 0;
-+
-+ client->adapter = adapter;
-+ client->driver = driver;
-+
-+ list_add(&client->__adap, &adapter->clients);
-+
-+ if (driver->attach_client)
-+ ret = driver->attach_client(client);
-+ }
-+
-+ if (ret) {
-+ l3_put_driver(driver);
-+ l3_put_adapter(adapter);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * l3_detach_client - detach a client from an adapter and driver
-+ * @client: client structure to detach
-+ *
-+ * Detach the client from the adapter and driver.
-+ */
-+int l3_detach_client(struct l3_client *client)
-+{
-+ struct l3_adapter *adapter = client->adapter;
-+ struct l3_driver *driver = client->driver;
-+
-+ driver->detach_client(client);
-+
-+ client->adapter = NULL;
-+ client->driver = NULL;
-+
-+ l3_put_driver(driver);
-+ l3_put_adapter(adapter);
-+
-+ list_del(&client->__adap);
-+
-+ return 0;
-+}
-+
-+/**
-+ * l3_transfer - transfer information on an L3 bus
-+ * @adap: adapter structure to perform transfer on
-+ * @msgs: array of l3_msg structures describing transfer
-+ * @num: number of l3_msg structures
-+ *
-+ * Transfer the specified messages to/from a device on the L3 bus.
-+ *
-+ * Returns number of messages successfully transferred, otherwise negative
-+ * error code.
-+ */
-+int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
-+{
-+ int ret = -ENOSYS;
-+
-+ if (adap->algo->xfer) {
-+ down(adap->lock);
-+ ret = adap->algo->xfer(adap, msgs, num);
-+ up(adap->lock);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * l3_write - send data to a device on an L3 bus
-+ * @client: registered client structure
-+ * @addr: L3 bus address
-+ * @buf: buffer for bytes to send
-+ * @len: number of bytes to send
-+ *
-+ * Send len bytes pointed to by buf to device address addr on the L3 bus
-+ * described by client.
-+ *
-+ * Returns the number of bytes transferred, or negative error code.
-+ */
-+int l3_write(struct l3_client *client, int addr, const char *buf, int len)
-+{
-+ struct l3_adapter *adap = client->adapter;
-+ struct l3_msg msg;
-+ int ret;
-+
-+ msg.addr = addr;
-+ msg.flags = 0;
-+ msg.buf = (char *)buf;
-+ msg.len = len;
-+
-+ ret = l3_transfer(adap, &msg, 1);
-+ return ret == 1 ? len : ret;
-+}
-+
-+/**
-+ * l3_read - receive data from a device on an L3 bus
-+ * @client: registered client structure
-+ * @addr: L3 bus address
-+ * @buf: buffer for bytes to receive
-+ * @len: number of bytes to receive
-+ *
-+ * Receive len bytes from device address addr on the L3 bus described by
-+ * client to a buffer pointed to by buf.
-+ *
-+ * Returns the number of bytes transferred, or negative error code.
-+ */
-+int l3_read(struct l3_client *client, int addr, char *buf, int len)
-+{
-+ struct l3_adapter *adap = client->adapter;
-+ struct l3_msg msg;
-+ int ret;
-+
-+ msg.addr = addr;
-+ msg.flags = L3_M_RD;
-+ msg.buf = buf;
-+ msg.len = len;
-+
-+ ret = l3_transfer(adap, &msg, 1);
-+ return ret == 1 ? len : ret;
-+}
-+
-+EXPORT_SYMBOL(l3_add_adapter);
-+EXPORT_SYMBOL(l3_del_adapter);
-+EXPORT_SYMBOL(l3_get_adapter);
-+EXPORT_SYMBOL(l3_put_adapter);
-+
-+EXPORT_SYMBOL(l3_add_driver);
-+EXPORT_SYMBOL(l3_del_driver);
-+EXPORT_SYMBOL(l3_get_driver);
-+EXPORT_SYMBOL(l3_put_driver);
-+
-+EXPORT_SYMBOL(l3_attach_client);
-+EXPORT_SYMBOL(l3_detach_client);
-+
-+EXPORT_SYMBOL(l3_transfer);
-+EXPORT_SYMBOL(l3_write);
-+EXPORT_SYMBOL(l3_read);
---- /dev/null
-+++ linux-2.4.27/drivers/l3/l3-sa1111.c
-@@ -0,0 +1,118 @@
-+/*
-+ * L3 SA1111 algorithm/adapter module.
-+ *
-+ * By Russell King,
-+ * gratuitously ripped from sa1111-uda1341.c by John Dorsey.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/errno.h>
-+#include <linux/l3/l3.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/hardware/sa1111.h>
-+
-+static inline unsigned char l3_sa1111_recv_byte(unsigned char addr)
-+{
-+ unsigned char dat;
-+
-+ L3_CAR = addr;
-+ while ((SASR0 & SASR0_L3RD) == 0)
-+ mdelay(1);
-+ dat = L3_CDR;
-+ SASCR = SASCR_RDD;
-+ return dat;
-+}
-+
-+static void l3_sa1111_recv_msg(struct l3_msg *msg)
-+{
-+ int len = msg->len;
-+ char *p = msg->buf;
-+
-+ if (len > 1) {
-+ SACR1 |= SACR1_L3MB;
-+ while ((len--) > 1)
-+ *p++ = l3_sa1111_recv_byte(msg->addr);
-+ }
-+ SACR1 &= ~SACR1_L3MB;
-+ *p = l3_sa1111_recv_byte(msg->addr);
-+}
-+
-+static inline void l3_sa1111_send_byte(unsigned char addr, unsigned char dat)
-+{
-+ L3_CAR = addr;
-+ L3_CDR = dat;
-+ while ((SASR0 & SASR0_L3WD) == 0)
-+ mdelay(1);
-+ SASCR = SASCR_DTS;
-+}
-+
-+static void l3_sa1111_send_msg(struct l3_msg *msg)
-+{
-+ int len = msg->len;
-+ char *p = msg->buf;
-+
-+ if (len > 1) {
-+ SACR1 |= SACR1_L3MB;
-+ while ((len--) > 1)
-+ l3_sa1111_send_byte(msg->addr, *p++);
-+ }
-+ SACR1 &= ~SACR1_L3MB;
-+ l3_sa1111_send_byte(msg->addr, *p);
-+}
-+
-+static int l3_sa1111_xfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
-+{
-+ int i;
-+
-+ for (i = 0; i < num; i++) {
-+ struct l3_msg *pmsg = &msgs[i];
-+
-+ if (pmsg->flags & L3_M_RD)
-+ l3_sa1111_recv_msg(pmsg);
-+ else
-+ l3_sa1111_send_msg(pmsg);
-+ }
-+
-+ return num;
-+}
-+
-+static struct l3_algorithm l3_sa1111_algo = {
-+ name: "L3 SA1111 algorithm",
-+ xfer: l3_sa1111_xfer,
-+};
-+
-+static DECLARE_MUTEX(sa1111_lock);
-+
-+static struct l3_adapter l3_sa1111_adapter = {
-+ owner: THIS_MODULE,
-+ name: "l3-sa1111",
-+ algo: &l3_sa1111_algo,
-+ lock: &sa1111_lock,
-+};
-+
-+static int __init l3_sa1111_init(void)
-+{
-+ int ret = -ENODEV;
-+ if ((machine_is_assabet() && machine_has_neponset()) ||
-+ machine_is_jornada720() || machine_is_accelent_sa() ||
-+ machine_is_badge4())
-+ ret = l3_add_adapter(&l3_sa1111_adapter);
-+ return ret;
-+}
-+
-+static void __exit l3_sa1111_exit(void)
-+{
-+ l3_del_adapter(&l3_sa1111_adapter);
-+}
-+
-+module_init(l3_sa1111_init);
-+module_exit(l3_sa1111_exit);
---- linux-2.4.27/drivers/media/video/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/media/video/Config.in
-@@ -52,5 +52,8 @@
- if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HIGHMEM64G" != "y" ]; then
- dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
- fi
-+# unfortunately, this depends on having CONFIG_FB_CYBER2000
-+# set as well - we hook off of the VGA driver
-+dep_tristate ' NetWinder Video for Linux (EXPERIMENTAL)' CONFIG_VIDEO_CYBERPRO $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL $CONFIG_ARCH_NETWINDER
-
- endmenu
---- linux-2.4.27/drivers/media/video/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/media/video/Makefile
-@@ -16,7 +16,7 @@
- obj-n :=
- obj- :=
-
--SUB_DIRS :=
-+SUB_DIRS :=
- MOD_SUB_DIRS := $(SUB_DIRS)
- ALL_SUB_DIRS := $(SUB_DIRS)
-
-@@ -47,7 +47,8 @@
- obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
- obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
- obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
--obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
-+obj-$(CONFIG_VIDEO_CYBERPRO) += cyberpro.o i2c-old.o saa7111.o
-+obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
- obj-$(CONFIG_VIDEO_PMS) += pms.o
- obj-$(CONFIG_VIDEO_PLANB) += planb.o
- obj-$(CONFIG_VIDEO_VINO) += saa7191.o indycam.o vino.o
---- /dev/null
-+++ linux-2.4.27/drivers/media/video/cyberpro.c
-@@ -0,0 +1,2091 @@
-+/*
-+ * CyberPro 2000 video capture driver for the Rebel.com NetWinder
-+ *
-+ * (C) 1999-2000 Russell King
-+ *
-+ * Re-written from Rebel.com's vidcap driver.
-+ *
-+ * Architecture
-+ * ------------
-+ * The NetWinder video capture consists of a SAA7111 video decoder chip
-+ * connected to the CyberPro feature bus. The video data is captured to
-+ * the VGA memory, where the CyberPro can overlay (by chromakeying) the
-+ * data onto the VGA display.
-+ *
-+ * The CyberPro also has some nifty features, including a second overlay
-+ * and picture in picture mode. We do not currently use these features.
-+ *
-+ * Power Saving
-+ * ------------
-+ * Please note that rev.5 NetWinders have the ability to hold the SAA7111
-+ * decoder chip into reset, which saves power. The only time at which
-+ * this is done is when the driver is unloaded, which implies that this
-+ * is compiled as a module.
-+ *
-+ * In this case, you will want the kernel to automatically load this
-+ * driver when required. Place the following line in /etc/modules.conf
-+ * to enable this:
-+ *
-+ * alias char-major-81-0 cyberpro
-+ *
-+ * The relevant modules will be automatically loaded by modprobe on a
-+ * as and when needed basis.
-+ *
-+ * Capture resolution
-+ * ------------------
-+ * The maximum useful capture resolution is:
-+ * 625-line UK: 716x576
-+ * 525-line US: ?
-+ *
-+ * Bugs
-+ * ----
-+ * 1. The CyberPro chip seems to be prone to randomly scribbling over VGA
-+ * memory [hopefully fixed with new capture enable/freeze stuff]
-+ * 2. read()ing pauses video capture, and sometimes triggers bug 1.
-+ * 3. mmap() is not supported (requires BM-DMA - see bug 4)
-+ * 4. Really, we want to do scatter BM-DMA. Is the CyberPro capable of this?
-+ * The Cyberpro seems to randomly scribble to various PCI addresses if you
-+ * transfer >16 words.
-+ * 5. We shouldn't ignore O_NONBLOCK when reading a frame.
-+ * 6. The incoming stream on the NetWinder is CCIR656, which is YUV422.
-+ * CyberPro docs also call the format we capture and overlay "YUV422",
-+ * but we actually seem to have Y, U, Y, V bytes (is this YUYV format?)
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/videodev.h>
-+#include <linux/video_decoder.h>
-+#include <linux/mm.h>
-+#include <linux/i2c-old.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/kmod.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/pgtable.h>
-+#include <asm/pgalloc.h>
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("CyberPro v4l video grabber");
-+MODULE_LICENSE("GPL");
-+
-+#include "../../video/cyber2000fb.h"
-+
-+/*
-+ * These enable various experimental features. Most of these
-+ * are just plain broken or just don't work at the moment.
-+ */
-+/*
-+ * Enable this if you want mmap() access. (see bug 4)
-+ */
-+#undef USE_MMAP
-+
-+/*
-+ * Enable this if you want mmio access. (slow)
-+ */
-+#define USE_MMIO
-+
-+/*
-+ * The V4L API is unclear whether VIDIOCSCAPTURE call is allowed while
-+ * capture is running. The default is to disallow the call.
-+ *
-+ * Define this if you do want to allow the call while capture is active.
-+ */
-+#undef ALLOW_SCAPTURE_WHILE_CAP
-+
-+/*
-+ * We capture two frames
-+ */
-+#define NR_FRAMES 2
-+
-+/*
-+ * One frame of video is 202 pages, assuming YUV422 format, 716x576
-+ */
-+#define NR_PAGES 202
-+
-+struct src_info {
-+ unsigned int offset; /* offset of source data */
-+ unsigned int x; /* source x */
-+ unsigned int y; /* source y */
-+ unsigned int width; /* source width */
-+ unsigned int height; /* source height */
-+ unsigned int format; /* source format */
-+};
-+
-+struct dst_info {
-+ unsigned int x; /* destination x */
-+ unsigned int y; /* destination y */
-+ unsigned int width; /* destination width */
-+ unsigned int height; /* destination height */
-+ unsigned int chromakey; /* chromakey */
-+ unsigned int flags; /* flags (eg, chromakey enable) */
-+};
-+
-+struct cyberpro_vidinfo;
-+
-+struct win_info {
-+ void (*init)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*set_src)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*set_win)(struct cyberpro_vidinfo *dp, struct win_info *wi);
-+ void (*ctl)(struct cyberpro_vidinfo *dp, struct win_info *wi, int on_off);
-+
-+ /* public */
-+ struct src_info src;
-+ struct dst_info dst;
-+
-+ /* private */
-+ unsigned short vid_fifo_ctl;
-+ unsigned char vid_fmt;
-+ unsigned char vid_disp_ctl1;
-+ unsigned char vid_fifo_ctl1;
-+ unsigned char vid_misc_ctl1;
-+};
-+
-+struct framebuf {
-+ unsigned int offset; /* mmap offset for this frame */
-+ unsigned int status;
-+#define FRAME_FREE 0
-+#define FRAME_DONE 1
-+#define FRAME_WAITING 2
-+#define FRAME_GRABBING 3
-+
-+ /*
-+ * Bus-Master DMA stuff. Note that we should
-+ * probably use the kiovec stuff instead.
-+ */
-+ unsigned long bus_addr[NR_PAGES]; /* list of pages */
-+ struct page *pages[NR_PAGES];
-+ void *buffer;
-+ int dbg;
-+};
-+
-+struct cyberpro_vidinfo {
-+ struct video_device *dev;
-+ struct i2c_bus *bus;
-+ struct cyberpro_info info; /* host information */
-+ unsigned char *regs;
-+ unsigned int irq; /* PCI interrupt number */
-+
-+ /* hardware configuration */
-+ unsigned int stream_fmt; /* format of stream from decoder*/
-+
-+ /* software settings */
-+ unsigned int decoder:1; /* decoder loaded */
-+ unsigned int interlace:1; /* interlace */
-+ unsigned int buf_set:1; /* VIDIOCSFBUF has been issued */
-+ unsigned int win_set:1; /* VIDIOCSWIN has been issued */
-+ unsigned int cap_active:1; /* capture is active */
-+ unsigned int ovl_active:1; /* overlay is active */
-+ unsigned int mmaped:1; /* buffer is mmap()d */
-+ unsigned int unused:25;
-+
-+ unsigned int users; /* number of users */
-+ unsigned long cap_mem_offset; /* capture framebuffer offset */
-+ void * buffer; /* kernel capture buffer */
-+ unsigned int norm; /* video standard */
-+
-+ struct video_capability cap; /* capabilities */
-+ struct video_picture pic; /* current picture settings */
-+ struct video_buffer buf; /* display parameters */
-+ struct video_capture capt; /* video capture params */
-+
-+ struct win_info *ovl; /* overlay window set */
-+ struct win_info ext; /* "Extended" window info */
-+ struct win_info v2; /* "V2" window info */
-+ struct win_info x2; /* "X2" window info */
-+
-+ unsigned int bm_offset; /* Cap memory bus master offset */
-+ unsigned int bm_index; /* Cap page index */
-+
-+#ifdef USE_MMAP
-+ unsigned int frame_idx; /* currently grabbing frame */
-+ unsigned int frame_size;
-+ struct framebuf frame[NR_FRAMES];
-+ wait_queue_head_t frame_wait;
-+#endif
-+
-+ wait_queue_head_t vbl_wait;
-+
-+ /*
-+ * cyberpro registers
-+ */
-+ unsigned char cap_mode1;
-+ unsigned char cap_mode2;
-+ unsigned char cap_miscctl;
-+ unsigned char vfac1;
-+ unsigned char vfac3;
-+};
-+
-+/*
-+ * Our access methods.
-+ */
-+#define cyberpro_writel(val,reg,dp) writel(val, (dp)->regs + (reg))
-+#define cyberpro_writew(val,reg,dp) writew(val, (dp)->regs + (reg))
-+#define cyberpro_writeb(val,reg,dp) writeb(val, (dp)->regs + (reg))
-+
-+#define cyberpro_readb(reg,dp) readb((dp)->regs + (reg))
-+
-+static inline void
-+cyberpro_grphw(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_writew((reg & 255) | val << 8, 0x3ce, dp);
-+}
-+
-+static void cyberpro_grphw8(unsigned int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+}
-+
-+static unsigned char cyberpro_grphr8(int reg, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_writeb(reg, 0x3ce, dp);
-+ return cyberpro_readb(0x3cf, dp);
-+}
-+
-+static void cyberpro_grphw16(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+ cyberpro_grphw(reg + 1, val >> 8, dp);
-+}
-+
-+static void cyberpro_grphw24(int reg, unsigned int val, struct cyberpro_vidinfo *dp)
-+{
-+ cyberpro_grphw(reg, val, dp);
-+ cyberpro_grphw(reg + 1, val >> 8, dp);
-+ cyberpro_grphw(reg + 2, val >> 16, dp);
-+}
-+
-+#if 0
-+static void
-+cyberpro_dbg_dump(void)
-+{
-+ int i;
-+ unsigned char idx[] =
-+ { 0x30, 0x3e, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
-+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad };
-+ printk(KERN_DEBUG);
-+ for (i = 0; i < sizeof(idx); i++)
-+ printk("%02x ", idx[i]);
-+ printk("\n" KERN_DEBUG);
-+ for (i = 0; i < sizeof(idx); i++)
-+ printk("%02x ", cyberpro_grphr8(idx[i]));
-+ printk("\n");
-+}
-+#endif
-+
-+/*
-+ * On the NetWinder, we can put the SAA7111 to sleep by holding
-+ * it in reset.
-+ *
-+ * Note: once we have initialised the SAA7111, we can't put it back to
-+ * sleep and expect it to keep its settings. Maybe a better solution
-+ * is to register/de-register the i2c bus in open/release?
-+ */
-+static void
-+decoder_sleep(int sleep)
-+{
-+#ifdef CONFIG_ARCH_NETWINDER
-+ extern spinlock_t gpio_lock;
-+
-+ spin_lock_irq(&gpio_lock);
-+ cpld_modify(CPLD_7111_DISABLE, sleep ? CPLD_7111_DISABLE : 0);
-+ spin_unlock_irq(&gpio_lock);
-+
-+ if (!sleep) {
-+ /*
-+ * wait 20ms for device to wake up
-+ */
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ / 50);
-+ }
-+#endif
-+}
-+
-+/* -------------------------------- I2C support ---------------------------- */
-+
-+#define I2C_DELAY 100
-+
-+static void
-+cyberpro_i2c_setlines(struct i2c_bus *bus, int ctrl, int data)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ int v;
-+
-+ v = (ctrl ? EXT_LATCH2_I2C_CLKEN : 0x00) | (data ? EXT_LATCH2_I2C_DATEN : 0x00);
-+ cyberpro_grphw8(EXT_LATCH2, v, dp);
-+
-+ udelay(I2C_DELAY);
-+}
-+
-+static int
-+cyberpro_i2c_getdataline(struct i2c_bus *bus)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ unsigned long flags;
-+ int v;
-+
-+ save_flags(flags);
-+ cli();
-+
-+ v = cyberpro_grphr8(EXT_LATCH2, dp);
-+
-+ restore_flags(flags);
-+
-+ return v & EXT_LATCH2_I2C_DAT ? 1 : 0;
-+}
-+
-+static void
-+cyberpro_i2c_attach(struct i2c_bus *bus, int id)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+ int zero = 0;
-+
-+ if (id == I2C_DRIVERID_VIDEODECODER) {
-+ __u16 norm = dp->norm;
-+ i2c_control_device(bus, id, DECODER_SET_NORM, &norm);
-+ i2c_control_device(bus, id, DECODER_SET_PICTURE, &dp->pic);
-+ i2c_control_device(bus, id, DECODER_ENABLE_OUTPUT, &zero);
-+
-+ dp->decoder = 1;
-+ }
-+}
-+
-+static void
-+cyberpro_i2c_detach(struct i2c_bus *bus, int id)
-+{
-+ struct cyberpro_vidinfo *dp = bus->data;
-+
-+ if (id == I2C_DRIVERID_VIDEODECODER)
-+ dp->decoder = 0;
-+}
-+
-+static struct i2c_bus cyberpro_i2c_bus = {
-+ name: "",
-+ id: I2C_BUSID_CYBER2000,
-+ bus_lock: SPIN_LOCK_UNLOCKED,
-+ attach_inform: cyberpro_i2c_attach,
-+ detach_inform: cyberpro_i2c_detach,
-+ i2c_setlines: cyberpro_i2c_setlines,
-+ i2c_getdataline: cyberpro_i2c_getdataline,
-+};
-+
-+/*------------------------- Extended Overlay Window -------------------------
-+ * Initialise 1st overlay window (works)
-+ */
-+static void
-+cyberpro_ext_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fifo_ctl = 0xf87c;
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
-+ EXT_VID_DISP_CTL1_NOCLIP;
-+ wi->vid_fifo_ctl1 = EXT_VID_FIFO_CTL1_INTERLEAVE |
-+ EXT_VID_FIFO_CTL1_OE_HIGH;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8 (EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ cyberpro_grphw16(EXT_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(EXT_DDA_Y_INIT, 0x0800, dp);
-+ cyberpro_grphw16(EXT_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
-+ cyberpro_grphw8 (EXT_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the extended window
-+ */
-+static void
-+cyberpro_ext_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw24(EXT_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(EXT_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (EXT_SRC_WIN_WIDTH, phase, dp);
-+ cyberpro_grphw8 (EXT_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set overlay1 window
-+ */
-+static void
-+cyberpro_ext_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = wi->src.width;
-+
-+ if (wi->dst.width >= wi->src.width * 2) {
-+ wi->vid_fmt |= EXT_VID_FMT_DBL_H_PIX;
-+ xscale *= 2;
-+ } else {
-+ wi->vid_fmt &= ~EXT_VID_FMT_DBL_H_PIX;
-+ }
-+
-+ xscale = ((xscale - /*2*/0) * 4096) / wi->dst.width;
-+ yscale = ((wi->src.height - /*2*/0) * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw16(EXT_X_START, xoff, dp);
-+ cyberpro_grphw16(EXT_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(EXT_Y_START, yoff, dp);
-+ cyberpro_grphw16(EXT_Y_END, yoff + wi->dst.height, dp);
-+ cyberpro_grphw24(EXT_COLOUR_COMPARE, wi->dst.chromakey, dp);
-+ cyberpro_grphw16(EXT_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(EXT_DDA_Y_INC, yscale, dp);
-+ cyberpro_grphw8(EXT_VID_FMT, wi->vid_fmt, dp);
-+
-+ if (wi->dst.flags & VIDEO_WINDOW_CHROMAKEY)
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_IGNORE_CCOMP;
-+ else
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_IGNORE_CCOMP;
-+}
-+
-+/*
-+ * Enable or disable the 1st overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_ext_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(EXT_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/*------------------------------- V2 Overlay Window -------------------------
-+ * Initialise 2nd overlay window (guesswork)
-+ */
-+static void
-+cyberpro_v2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fifo_ctl = 0xf87c;
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = EXT_VID_DISP_CTL1_VINTERPOL_OFF |
-+ EXT_VID_DISP_CTL1_NOCLIP;
-+ wi->vid_fifo_ctl1 = 0x06;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8 (Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ /* No DDA init values */
-+ cyberpro_grphw16(Y_V2_VID_FIFO_CTL, wi->vid_fifo_ctl, dp);
-+ cyberpro_grphw8 (Y_V2_VID_FIFO_CTL1, wi->vid_fifo_ctl1, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the v2 window
-+ */
-+static void
-+cyberpro_v2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
-+ cyberpro_grphw24(X_V2_VID_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(X_V2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (X_V2_VID_SRC_WIN_WIDTH, phase, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(Y_V2_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set v2 window
-+ */
-+static void
-+cyberpro_v2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = (wi->src.width * 4096) / wi->dst.width;
-+ yscale = (wi->src.height * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_X, dp);
-+ cyberpro_grphw16(X_V2_X_START, xoff, dp);
-+ cyberpro_grphw16(X_V2_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(X_V2_Y_START, yoff, dp);
-+ cyberpro_grphw16(X_V2_Y_END, yoff + wi->dst.height, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw16(Y_V2_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(Y_V2_DDA_Y_INC, yscale, dp);
-+}
-+
-+/*
-+ * Enable or disable the 2nd overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_v2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(Y_V2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/*--------------------------- X2 Overlay Window -----------------------------
-+ * Initialise 3rd overlay window (guesswork)
-+ */
-+static void
-+cyberpro_x2_init(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ wi->vid_fmt = EXT_VID_FMT_YUV422;
-+ wi->vid_disp_ctl1 = 0x40;
-+ wi->vid_misc_ctl1 = 0;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8 (K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+ cyberpro_grphw16(K_X2_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(K_X2_DDA_Y_INIT, 0x0800, dp);
-+}
-+
-+/*
-+ * Set the source parameters for the x2 window
-+ */
-+static void
-+cyberpro_x2_set_src(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int phase, pitch;
-+
-+ pitch = (wi->src.width >> 2) & 0x0fff;
-+ phase = (wi->src.width + 3) >> 2;
-+
-+ wi->vid_fmt &= ~7;
-+ switch (wi->src.format) {
-+ case VIDEO_PALETTE_RGB565: wi->vid_fmt |= EXT_VID_FMT_RGB565; break;
-+ case VIDEO_PALETTE_RGB24: wi->vid_fmt |= EXT_VID_FMT_RGB888_24; break;
-+ case VIDEO_PALETTE_RGB32: wi->vid_fmt |= EXT_VID_FMT_RGB888_32; break;
-+ case VIDEO_PALETTE_RGB555: wi->vid_fmt |= EXT_VID_FMT_RGB555; break;
-+ case VIDEO_PALETTE_YUV422: wi->vid_fmt |= EXT_VID_FMT_YUV422; break;
-+ }
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
-+ cyberpro_grphw24(J_X2_VID_MEM_START, wi->src.offset, dp);
-+ cyberpro_grphw16(J_X2_VID_SRC_WIDTH, pitch | ((phase << 4) & 0xf000), dp);
-+ cyberpro_grphw8 (J_X2_VID_SRC_WIN_WIDTH, phase, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8(K_X2_VID_FMT, wi->vid_fmt, dp);
-+}
-+
-+/*
-+ * Set x2 window
-+ */
-+static void
-+cyberpro_x2_set_win(struct cyberpro_vidinfo *dp, struct win_info *wi)
-+{
-+ unsigned int xscale, yscale;
-+ unsigned int xoff, yoff;
-+
-+ /*
-+ * Note: the offset does not appear to be influenced by
-+ * hardware scrolling.
-+ */
-+ xoff = yoff = 0;
-+
-+ xoff += wi->dst.x;
-+ yoff += wi->dst.y;
-+
-+ xscale = (wi->src.width * 4096) / wi->dst.width;
-+ yscale = (wi->src.height * 4096) / wi->dst.height;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_J, dp);
-+ cyberpro_grphw16(J_X2_X_START, xoff, dp);
-+ cyberpro_grphw16(J_X2_X_END, xoff + wi->dst.width, dp);
-+ cyberpro_grphw16(J_X2_Y_START, yoff, dp);
-+ cyberpro_grphw16(J_X2_Y_END, yoff + wi->dst.height, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw16(K_X2_DDA_X_INC, xscale, dp);
-+ cyberpro_grphw16(K_X2_DDA_Y_INC, yscale, dp);
-+}
-+
-+/*
-+ * Enable or disable the 3rd overlay window. Note that for anything
-+ * useful to be displayed, we must have capture enabled.
-+ */
-+static void
-+cyberpro_x2_ctl(struct cyberpro_vidinfo *dp, struct win_info *wi, int on)
-+{
-+ if (on)
-+ wi->vid_disp_ctl1 |= EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+ else
-+ wi->vid_disp_ctl1 &= ~EXT_VID_DISP_CTL1_ENABLE_WINDOW;
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_K, dp);
-+ cyberpro_grphw8(K_X2_VID_DISP_CTL1, wi->vid_disp_ctl1, dp);
-+}
-+
-+/* ------------------------------------------------------------------------- */
-+
-+#if 0
-+static void reset_seq(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char ext_mem_ctl = cyberpro_grphr8(0x70, dp);
-+
-+ cyberpro_grphw8(ext_mem_ctl | 0x80, 0x70, dp);
-+ cyberpro_grphw8(ext_mem_ctl, 0x70, dp);
-+}
-+#endif
-+
-+#ifdef USE_MMAP
-+/*
-+ * Buffer support
-+ */
-+static int
-+cyberpro_alloc_frame_buffer(struct cyberpro_vidinfo *dp,
-+ struct framebuf *frame)
-+{
-+ unsigned long addr;
-+ void *buffer;
-+ int pgidx;
-+
-+ if (frame->buffer)
-+ return 0;
-+
-+ /*
-+ * Allocate frame buffer
-+ */
-+ buffer = vmalloc(NR_PAGES * PAGE_SIZE);
-+
-+ if (frame->buffer) {
-+ vfree(buffer);
-+ return 0;
-+ }
-+
-+ if (!buffer)
-+ return -ENOMEM;
-+
-+ printk("Buffer allocated @ %p [", buffer);
-+
-+ frame->buffer = buffer;
-+ frame->dbg = 1;
-+
-+ /*
-+ * Don't leak information from the kernel.
-+ */
-+ memset(buffer, 0x5a, NR_PAGES * PAGE_SIZE);
-+
-+ /*
-+ * Now, reserve all the pages, and calculate
-+ * each pages' bus address.
-+ */
-+ addr = (unsigned long)buffer;
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++, addr += PAGE_SIZE) {
-+ struct page *page;
-+ pgd_t *pgd;
-+ pmd_t *pmd;
-+ pte_t *pte;
-+
-+ /*
-+ * The page should be present. If not,
-+ * vmalloc has gone nuts.
-+ */
-+ pgd = pgd_offset_k(addr);
-+ if (pgd_none(*pgd))
-+ BUG();
-+ pmd = pmd_offset(pgd, addr);
-+ if (pmd_none(*pmd))
-+ BUG();
-+ pte = pte_offset(pmd, addr);
-+ if (!pte_present(*pte))
-+ BUG();
-+
-+ page = pte_page(*pte);
-+
-+ frame->bus_addr[pgidx] = virt_to_bus((void *)page_address(page));
-+ frame->pages[pgidx] = page;
-+ SetPageReserved(page);
-+
-+ printk("%08lx (%08lx) ", page_address(page), frame->bus_addr[pgidx]);
-+ }
-+ printk("\n");
-+
-+ return 0;
-+}
-+
-+static void
-+cyberpro_frames_free_one(struct cyberpro_vidinfo *dp, struct framebuf *frame)
-+{
-+ void *buffer;
-+ int pgidx;
-+
-+ frame->status = FRAME_FREE;
-+ buffer = frame->buffer;
-+ frame->buffer = NULL;
-+
-+ if (buffer) {
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
-+ frame->bus_addr[pgidx] = 0;
-+ ClearPageReserved(frame->pages[pgidx]);
-+ frame->pages[pgidx] = NULL;
-+ }
-+ vfree(buffer);
-+ }
-+}
-+
-+static void
-+cyberpro_busmaster_frame(struct cyberpro_vidinfo *dp, struct framebuf *frame)
-+{
-+ unsigned long bus_addr;
-+
-+ bus_addr = frame->bus_addr[dp->bm_index];
-+
-+ if (frame->dbg) {
-+ printk("Frame%d: %06x -> %08lx\n",
-+ dp->frame_idx,
-+ dp->bm_offset,
-+ bus_addr);
-+ }
-+
-+ cyber2000_outw(dp->bm_offset, BM_VID_ADDR_LOW);
-+ cyber2000_outw(dp->bm_offset >> 16, BM_VID_ADDR_HIGH);
-+
-+ cyber2000_outw(bus_addr, BM_ADDRESS_LOW);
-+ cyber2000_outw(bus_addr >> 16, BM_ADDRESS_HIGH);
-+
-+ /*
-+ * One page-full only
-+ */
-+ cyber2000_outw(1023, BM_LENGTH);
-+
-+ /*
-+ * Load length
-+ */
-+ cyber2000_outw(BM_CONTROL_INIT, BM_CONTROL);
-+
-+ /*
-+ * Enable transfer
-+ */
-+ cyber2000_outw(BM_CONTROL_ENABLE|BM_CONTROL_IRQEN, BM_CONTROL);
-+
-+ dp->bm_offset += 1024;
-+ dp->bm_index += 1;
-+}
-+
-+static void cyberpro_busmaster_interrupt(struct cyberpro_vidinfo *dp)
-+{
-+ struct framebuf *frame = dp->frame + dp->frame_idx;
-+
-+ /*
-+ * Disable Busmaster operations
-+ */
-+ cyber2000_outw(0, BM_CONTROL);
-+
-+ if (frame->status == FRAME_GRABBING) {
-+ /*
-+ * We are still grabbing this frame to system
-+ * memory. Transfer next page if there are
-+ * more, or else flag this frame as complete.
-+ */
-+ if (dp->bm_index < NR_PAGES)
-+ cyberpro_busmaster_frame(dp);
-+ else {
-+ unsigned int idx;
-+
-+ frame->status = FRAME_DONE;
-+ frame->dbg = 0;
-+
-+ idx = dp->frame_idx + 1;
-+ if (idx >= NR_FRAMES)
-+ idx = 0;
-+
-+ dp->frame_idx = idx;
-+
-+ wake_up(&dp->frame_wait);
-+ }
-+ }
-+}
-+
-+static void cyberpro_frames_vbl(struct cyberpro_vidinfo *dp, unsigned int stat)
-+{
-+ struct framebuf *frame = dp->frame + dp->frame_idx;
-+
-+ /*
-+ * No point capturing frames if the grabber isn't active.
-+ */
-+ if (stat & EXT_ROM_UCB4GH_FREEZE)
-+ return;
-+
-+ /*
-+ * If the next buffer is ready for grabbing,
-+ * set up the bus master registers for the
-+ * transfer.
-+ */
-+ if (frame->status == FRAME_WAITING) {
-+ frame->status = FRAME_GRABBING;
-+
-+ dp->bm_offset = dp->cap_mem_offset;
-+ dp->bm_index = 0;
-+
-+ cyberpro_busmaster_frame(dp, frame);
-+ }
-+}
-+
-+static void __init cyberpro_frames_init(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned int offset, maxsize;
-+ int i;
-+
-+ init_waitqueue_head(&dp->frame_wait);
-+
-+ maxsize = 2 * dp->cap.maxwidth * dp->cap.maxheight;
-+ dp->frame_size = PAGE_ALIGN(maxsize);
-+ dp->frame_idx = 0;
-+
-+ for (i = offset = 0; i < NR_FRAMES; i++) {
-+ dp->frame[i].offset = offset;
-+ dp->frame[i].status = FRAME_FREE;
-+ offset += dp->frame_size;
-+ }
-+}
-+
-+static void cyberpro_frames_free(struct cyberpro_vidinfo *dp)
-+{
-+ int i;
-+
-+ dp->mmaped = 0;
-+
-+ /*
-+ * Free all frame buffers
-+ */
-+ for (i = 0; i < NR_FRAMES; i++)
-+ cyberpro_frames_free_one(dp, dp->frame + i);
-+}
-+
-+#else
-+#define cyberpro_frames_vbl(dp,stat) do { } while (0)
-+#define cyberpro_frames_init(dp) do { } while (0)
-+#define cyberpro_frames_free(dp) do { } while (0)
-+#endif
-+
-+/*
-+ * CyberPro Interrupts
-+ * -------------------
-+ *
-+ * We don't really know how to signal an IRQ clear to the chip. However,
-+ * disabling and re-enabling the capture interrupt enable seems to do what
-+ * we want.
-+ */
-+static void cyberpro_interrupt(int nr, void *dev_id, struct pt_regs *regs)
-+{
-+ struct cyberpro_vidinfo *dp = dev_id;
-+ unsigned char old_grphidx;
-+ unsigned int status;
-+
-+ /*
-+ * Save old graphics index register
-+ */
-+ old_grphidx = cyberpro_readb(0x3ce, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ /*
-+ * Was it due to the Capture VSYNC?
-+ */
-+ if (status & EXT_ROM_UCB4GH_INTSTAT) {
-+ /*
-+ * Frob the IRQ enable bit to drop the request.
-+ */
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3 & ~VFAC_CTL3_CAP_IRQ, dp);
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+
-+ cyberpro_frames_vbl(dp, status);
-+ wake_up(&dp->vbl_wait);
-+ }
-+
-+ /*
-+ * Restore graphics controller index
-+ */
-+ cyberpro_writeb(old_grphidx, 0x3ce, dp);
-+
-+#ifdef USE_MMAP
-+ /*
-+ * Do Bus-Master IRQ stuff
-+ */
-+ if (cyber2000_inb(BM_CONTROL) & (1 << 7))
-+ cyberpro_busmaster_interrupt(dp);
-+#endif
-+}
-+
-+static void cyberpro_capture(struct cyberpro_vidinfo *dp, int on)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ unsigned int status;
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ add_wait_queue(&dp->vbl_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ if (!!on ^ !(status & EXT_ROM_UCB4GH_FREEZE)) {
-+ if (on) {
-+ schedule_timeout(40 * HZ / 1000);
-+ dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ } else {
-+ dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ if (!(status & EXT_ROM_UCB4GH_FREEZE))
-+ schedule_timeout(40 * HZ / 1000);
-+ }
-+ }
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&dp->vbl_wait, &wait);
-+}
-+
-+static void cyberpro_capture_one(struct cyberpro_vidinfo *dp)
-+{
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ unsigned int status;
-+ unsigned long policy, rt_priority;
-+
-+ policy = tsk->policy;
-+ rt_priority = tsk->rt_priority;
-+
-+ tsk->policy = SCHED_FIFO;
-+ tsk->rt_priority = 1;
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ add_wait_queue(&dp->vbl_wait, &wait);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ schedule_timeout(40 * HZ / 1000);
-+ dp->vfac1 &= ~(VFAC_CTL1_FREEZE_CAPTURE|VFAC_CTL1_FREEZE_CAPTURE_SYNC);
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(40 * HZ / 1000);
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(40 * HZ / 1000);
-+
-+ dp->vfac1 |= VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ status = cyberpro_grphr8(EXT_ROM_UCB4GH, dp);
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&dp->vbl_wait, &wait);
-+
-+ tsk->policy = policy;
-+ tsk->rt_priority = rt_priority;
-+}
-+
-+static void cyberpro_capture_set_win(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned int xstart, xend, ystart, yend;
-+
-+ xstart = 4 + dp->capt.x;
-+ xend = xstart + dp->capt.width;
-+
-+ if (dp->cap_mode1 & EXT_CAP_MODE1_8BIT) {
-+ /* 8-bit capture */
-+ xstart *= 2;
-+ xend *= 2;
-+ }
-+
-+ xstart -= 1;
-+ xend -= 1;
-+
-+ ystart = 18 + dp->capt.y;
-+ yend = ystart + dp->capt.height / 2;
-+
-+ cyberpro_grphw16(CAP_X_START, xstart, dp);
-+ cyberpro_grphw16(CAP_X_END, xend + 1, dp);
-+ cyberpro_grphw16(CAP_Y_START, ystart, dp);
-+ cyberpro_grphw16(CAP_Y_END, yend + 2, dp);
-+
-+ /*
-+ * This should take account of capt.decimation
-+ */
-+ cyberpro_grphw16(CAP_DDA_X_INIT, 0x0800, dp);
-+ cyberpro_grphw16(CAP_DDA_X_INC, 0x1000, dp);
-+ cyberpro_grphw16(CAP_DDA_Y_INIT, 0x0800, dp);
-+ cyberpro_grphw16(CAP_DDA_Y_INC, 0x1000, dp);
-+
-+ cyberpro_grphw8(CAP_PITCH, dp->capt.width >> 2, dp);
-+}
-+
-+static void cyberpro_set_interlace(struct cyberpro_vidinfo *dp)
-+{
-+ /*
-+ * set interlace mode
-+ */
-+ if (dp->interlace) {
-+ dp->vfac3 |= VFAC_CTL3_CAP_INTERLACE;
-+ dp->cap_miscctl &= ~CAP_CTL_MISC_ODDEVEN;
-+ dp->ovl->src.height = dp->capt.height;
-+ } else {
-+ dp->vfac3 &= ~VFAC_CTL3_CAP_INTERLACE;
-+ dp->cap_miscctl |= CAP_CTL_MISC_ODDEVEN;
-+ dp->ovl->src.height = dp->capt.height / 2;
-+ }
-+
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+ cyberpro_grphw8(CAP_CTL_MISC, dp->cap_miscctl, dp);
-+
-+ dp->ovl->set_src(dp, dp->ovl);
-+
-+ if (dp->win_set)
-+ dp->ovl->set_win(dp, dp->ovl);
-+}
-+
-+/*
-+ * Calculate and set the address of the capture buffer. Note we
-+ * also update the extended memory buffer for the overlay window.
-+ *
-+ * base: phys base address of display
-+ * width: pixel width of display
-+ * height: height of display
-+ * depth: depth of display (8/16/24)
-+ * bytesperline: number of bytes on a line
-+ *
-+ * We place the capture buffer 16K after the screen.
-+ */
-+static int
-+cyberpro_set_buffer(struct cyberpro_vidinfo *dp, struct video_buffer *b)
-+{
-+ unsigned long screensize, maxbufsz;
-+
-+ if (b->height <= 0 || b->width <= 0 || b->bytesperline <= 0)
-+ return -EINVAL;
-+
-+ maxbufsz = dp->cap.maxwidth * dp->cap.maxheight * 2;
-+ screensize = b->height * b->bytesperline + 16384;
-+
-+ if ((screensize + maxbufsz) >= dp->info.fb_size)
-+ return -EINVAL;
-+
-+ dp->buf.base = b->base;
-+ dp->buf.width = b->width;
-+ dp->buf.height = b->height;
-+ dp->buf.depth = b->depth;
-+ dp->buf.bytesperline = b->bytesperline;
-+ dp->cap_mem_offset = screensize >> 2;
-+
-+ cyberpro_grphw24(CAP_MEM_START, dp->cap_mem_offset, dp);
-+
-+ /*
-+ * Setup the overlay source information.
-+ */
-+ dp->ovl->src.offset = dp->cap_mem_offset;
-+ dp->ovl->set_src(dp, dp->ovl);
-+
-+ return 0;
-+}
-+
-+static void cyberpro_hw_init(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char old;
-+
-+ /*
-+ * Enable access to bus-master registers
-+ */
-+ dp->info.enable_extregs(dp->info.info);
-+
-+ dp->vfac1 = VFAC_CTL1_PHILIPS |
-+ VFAC_CTL1_FREEZE_CAPTURE |
-+ VFAC_CTL1_FREEZE_CAPTURE_SYNC;
-+ dp->vfac3 = VFAC_CTL3_CAP_IRQ;
-+
-+ dp->cap_miscctl = CAP_CTL_MISC_DISPUSED |
-+ CAP_CTL_MISC_SYNCTZOR |
-+ CAP_CTL_MISC_SYNCTZHIGH;
-+
-+ /*
-+ * Setup bus-master mode
-+ */
-+ cyberpro_grphw8(BM_CTRL1, 0x88, dp);
-+ cyberpro_grphw8(PCI_BM_CTL, PCI_BM_CTL_ENABLE, dp);
-+ cyberpro_grphw8(BM_CTRL0, 0x44, dp);
-+ cyberpro_grphw8(BM_CTRL1, 0x84, dp);
-+
-+ cyberpro_grphw24(CAP_MEM_START, 0, dp);
-+
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+ cyberpro_grphw8(VFAC_CTL2, 0, dp);
-+
-+ cyberpro_grphw8(REG_BANK, REG_BANK_Y, dp);
-+ cyberpro_grphw8(EXT_TV_CTL, 0x80, dp);
-+
-+ cyberpro_grphw8(EXT_CAP_CTL1, 0x3f, dp); /* disable PIP */
-+ cyberpro_grphw8(EXT_CAP_CTL2, 0xc0 | EXT_CAP_CTL2_ODDFRAMEIRQ, dp);
-+
-+ /*
-+ * Configure capture mode to match the
-+ * external video processor format
-+ */
-+ cyberpro_grphw8(EXT_CAP_MODE1, dp->cap_mode1, dp);
-+ cyberpro_grphw8(EXT_CAP_MODE2, dp->cap_mode2, dp);
-+
-+ /* setup overlay */
-+ cyberpro_grphw16(EXT_FIFO_CTL, 0x1010, dp);
-+// cyberpro_grphw16(EXT_FIFO_CTL, 0x1b0f, dp);
-+
-+ /*
-+ * Always reset the capture parameters on each open.
-+ */
-+ dp->capt.x = 0;
-+ dp->capt.y = 0;
-+ dp->capt.width = dp->cap.maxwidth;
-+ dp->capt.height = dp->cap.maxheight;
-+ dp->capt.decimation = 0;
-+ dp->capt.flags = 0;
-+
-+ cyberpro_capture_set_win(dp);
-+
-+ /*
-+ * Enable VAFC
-+ */
-+ old = cyberpro_grphr8(EXT_LATCH1, dp);
-+ cyberpro_grphw8(EXT_LATCH1, old | EXT_LATCH1_VAFC_EN, dp);
-+
-+ /*
-+ * Enable capture (we hope that VSYNC=1)
-+ */
-+ dp->vfac1 |= VFAC_CTL1_CAPTURE;
-+ cyberpro_grphw8(VFAC_CTL1, dp->vfac1, dp);
-+
-+ /*
-+ * The overlay source format is always the
-+ * same as the capture stream format.
-+ */
-+ dp->ovl->src.width = dp->capt.width;
-+ dp->ovl->src.height = dp->capt.height;
-+ dp->ovl->src.format = dp->stream_fmt;
-+
-+ /*
-+ * Initialise the overlay windows
-+ */
-+ dp->ext.init(dp, &dp->ext);
-+ dp->v2.init(dp, &dp->v2);
-+ dp->x2.init(dp, &dp->x2);
-+}
-+
-+static void cyberpro_deinit(struct cyberpro_vidinfo *dp)
-+{
-+ unsigned char old;
-+
-+ /*
-+ * Stop any bus-master activity
-+ */
-+ cyberpro_writew(0, BM_CONTROL, dp);
-+
-+ /*
-+ * Shut down overlay
-+ */
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+ dp->ovl_active = 0;
-+
-+ /*
-+ * Shut down capture
-+ */
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+ dp->cap_active = 0;
-+
-+ /*
-+ * Disable all capture
-+ */
-+ cyberpro_grphw8(VFAC_CTL1, 0, dp);
-+
-+ /*
-+ * Disable VAFC
-+ */
-+ old = cyberpro_grphr8(EXT_LATCH1, dp);
-+ cyberpro_grphw8(EXT_LATCH1, old & ~EXT_LATCH1_VAFC_EN, dp);
-+
-+ /*
-+ * Disable interrupt (this allows it to float)
-+ */
-+ dp->vfac3 &= ~VFAC_CTL3_CAP_IRQ;
-+ cyberpro_grphw8(VFAC_CTL3, dp->vfac3, dp);
-+
-+ /*
-+ * Switch off bus-master mode
-+ */
-+ cyberpro_grphw8(PCI_BM_CTL, 0, dp);
-+
-+ /*
-+ * Disable access to bus-master registers
-+ */
-+ dp->info.disable_extregs(dp->info.info);
-+}
-+
-+static int cyberpro_grabber_open(struct video_device *dev, int flags)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ int ret, one = 1;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ ret = -EBUSY;
-+ if (flags || dp->users)
-+ goto out;
-+
-+ dp->users += 1;
-+
-+ if (dp->users == 1) {
-+ ret = request_irq(dp->irq, cyberpro_interrupt, SA_SHIRQ,
-+ dp->info.dev_name, dp);
-+
-+ if (ret) {
-+ dp->users -= 1;
-+ goto out;
-+ }
-+
-+ /*
-+ * Initialise the VGA chip
-+ */
-+ cyberpro_hw_init(dp);
-+
-+ /*
-+ * Enable the IRQ. This allows the IRQ to work as expected
-+ * even if the IRQ line is missing the pull-up resistor.
-+ */
-+ enable_irq(dp->irq);
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_ENABLE_OUTPUT, &one);
-+ }
-+
-+ ret = 0;
-+out:
-+ if (ret)
-+ MOD_DEC_USE_COUNT;
-+ return ret;
-+}
-+
-+static void cyberpro_grabber_close(struct video_device *dev)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+
-+ if (dp->users == 1) {
-+ int zero = 0;
-+
-+ /*
-+ * Disable the IRQ. This prevents problems with missing
-+ * pull-up resistors on the PCI interrupt line.
-+ */
-+ disable_irq(dp->irq);
-+
-+ cyberpro_frames_free(dp);
-+
-+ /*
-+ * Turn off the SAA7111 decoder
-+ */
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_ENABLE_OUTPUT, &zero);
-+
-+ /*
-+ * Disable grabber
-+ */
-+ cyberpro_deinit(dp);
-+
-+ free_irq(dp->irq, dp);
-+ }
-+
-+ dp->users -= 1;
-+
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+/*
-+ * Our general plan here is:
-+ * 1. Set the CyberPro to perform a BM-DMA of one frame to this memory
-+ * 2. Copy the frame to the userspace
-+ *
-+ * However, BM-DMA seems to be unreliable at the moment, especially on
-+ * rev. 4 NetWinders.
-+ */
-+static long
-+cyberpro_grabber_read(struct video_device *dev, char *buf,
-+ unsigned long count, int noblock)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ int ret = -EINVAL;
-+
-+#ifdef USE_MMIO
-+ unsigned long maxbufsz = dp->capt.width * dp->capt.height * 2;
-+ char *disp = dp->info.fb + (dp->cap_mem_offset << 2);
-+
-+ /*
-+ * If the buffer is mmap()'d, we shouldn't be using read()
-+ */
-+ if (dp->mmaped)
-+ return -EINVAL;
-+
-+ if (count > maxbufsz)
-+ count = maxbufsz;
-+
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+ else
-+ cyberpro_capture_one(dp);
-+
-+ ret = (int)count;
-+ if (copy_to_user(buf, disp, count))
-+ ret = -EFAULT;
-+
-+ /*
-+ * unfreeze capture
-+ */
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 1);
-+#endif
-+
-+ return ret;
-+}
-+
-+/*
-+ * We don't support writing to the grabber
-+ * (In theory, we could allow writing to a separate region of VGA memory,
-+ * and display this using the second overlay window. This would allow us
-+ * to do video conferencing for example).
-+ */
-+static long
-+cyberpro_grabber_write(struct video_device *dev, const char *buf,
-+ unsigned long count, int noblock)
-+{
-+ return -EINVAL;
-+}
-+
-+static int
-+cyberpro_grabber_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+
-+ switch (cmd) {
-+ case VIDIOCGCAP:
-+ return copy_to_user(arg, &dp->cap, sizeof(dp->cap))
-+ ? -EFAULT : 0;
-+
-+ case VIDIOCGCHAN:
-+ {
-+ struct video_channel chan;
-+
-+ chan.channel = 0;
-+ strcpy(chan.name, "Composite");
-+ chan.tuners = 0;
-+ chan.flags = 0;
-+ chan.type = VIDEO_TYPE_CAMERA;
-+ chan.norm = dp->norm;
-+
-+ return copy_to_user(arg, &chan, sizeof(chan)) ? -EFAULT : 0;
-+ }
-+
-+ case VIDIOCGPICT:
-+ return copy_to_user(arg, &dp->pic, sizeof(dp->pic))
-+ ? -EINVAL : 0;
-+
-+ case VIDIOCGWIN:
-+ {
-+ struct video_window win;
-+
-+ win.x = dp->ovl->dst.x;
-+ win.y = dp->ovl->dst.y;
-+ win.width = dp->ovl->dst.width;
-+ win.height = dp->ovl->dst.height;
-+ win.chromakey = dp->ovl->dst.chromakey;
-+ win.flags = VIDEO_WINDOW_CHROMAKEY |
-+ (dp->interlace ? VIDEO_WINDOW_INTERLACE : 0);
-+ win.clips = NULL;
-+ win.clipcount = 0;
-+
-+ return copy_to_user(arg, &win, sizeof(win))
-+ ? -EINVAL : 0;
-+ }
-+
-+ case VIDIOCGFBUF:
-+ return copy_to_user(arg, &dp->buf, sizeof(dp->buf))
-+ ? -EINVAL : 0;
-+
-+ case VIDIOCGUNIT:
-+ {
-+ struct video_unit unit;
-+
-+ unit.video = dev->minor;
-+ unit.vbi = VIDEO_NO_UNIT;
-+ unit.radio = VIDEO_NO_UNIT;
-+ unit.audio = VIDEO_NO_UNIT;
-+ unit.teletext = VIDEO_NO_UNIT;
-+
-+ return copy_to_user(arg, &unit, sizeof(unit))
-+ ? -EINVAL : 0;
-+ }
-+
-+ case VIDIOCGCAPTURE:
-+ return copy_to_user(arg, &dp->capt, sizeof(dp->capt))
-+ ? -EFAULT : 0;
-+
-+ case VIDIOCSCHAN:
-+ {
-+ struct video_decoder_capability vdc;
-+ struct video_channel v;
-+ int ok;
-+
-+ if (copy_from_user(&v, arg, sizeof(v)))
-+ return -EFAULT;
-+
-+ if (v.channel != 0)
-+ return -EINVAL;
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_GET_CAPABILITIES, &vdc);
-+
-+ switch (v.norm) {
-+ case VIDEO_MODE_PAL:
-+ ok = vdc.flags & VIDEO_DECODER_PAL;
-+ break;
-+ case VIDEO_MODE_NTSC:
-+ ok = vdc.flags & VIDEO_DECODER_NTSC;
-+ break;
-+ case VIDEO_MODE_AUTO:
-+ ok = vdc.flags & VIDEO_DECODER_AUTO;
-+ break;
-+ default:
-+ ok = 0;
-+ }
-+ if (!ok)
-+ return -EINVAL;
-+
-+ dp->norm = v.norm;
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_SET_NORM, &v.norm);
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSPICT:
-+ {
-+ struct video_picture p;
-+
-+ if (copy_from_user(&p, arg, sizeof(p)))
-+ return -EFAULT;
-+
-+ if (p.palette != dp->stream_fmt ||
-+ p.depth != 8)
-+ return -EINVAL;
-+
-+ dp->pic = p;
-+
-+ /* p.depth sets the capture depth */
-+ /* p.palette sets the capture palette */
-+
-+ i2c_control_device(dp->bus, I2C_DRIVERID_VIDEODECODER,
-+ DECODER_SET_PICTURE, &p);
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSWIN: /* set the size & position of the overlay window */
-+ {
-+ struct video_window w;
-+ int diff;
-+
-+ if (!dp->buf_set)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&w, arg, sizeof(w)))
-+ return -EFAULT;
-+
-+ if (w.clipcount)
-+ return -EINVAL;
-+
-+ /*
-+ * Bound the overlay window by the size of the screen
-+ */
-+ if (w.x < 0)
-+ w.x = 0;
-+ if (w.y < 0)
-+ w.y = 0;
-+
-+ if (w.x > dp->buf.width)
-+ w.x = dp->buf.width;
-+ if (w.y > dp->buf.height)
-+ w.y = dp->buf.height;
-+
-+ if (w.width < dp->capt.width)
-+ w.width = dp->capt.width;
-+ if (w.height < dp->capt.height)
-+ w.height = dp->capt.height;
-+
-+ if (w.x + w.width > dp->buf.width)
-+ w.width = dp->buf.width - w.x;
-+ if (w.y + w.height > dp->buf.height)
-+ w.height = dp->buf.height - w.y;
-+
-+ /*
-+ * We've tried to make the values fit, but
-+ * they just won't.
-+ */
-+ if (w.width < dp->capt.width || w.height < dp->capt.height)
-+ return -EINVAL;
-+
-+ diff = dp->ovl->dst.x != w.x ||
-+ dp->ovl->dst.y != w.y ||
-+ dp->ovl->dst.width != w.width ||
-+ dp->ovl->dst.height != w.height ||
-+ dp->ovl->dst.chromakey != w.chromakey ||
-+ dp->ovl->dst.flags != w.flags;
-+
-+ if (!dp->win_set || diff) {
-+ dp->ovl->dst.x = w.x;
-+ dp->ovl->dst.y = w.y;
-+ dp->ovl->dst.width = w.width;
-+ dp->ovl->dst.height = w.height;
-+ dp->ovl->dst.chromakey = w.chromakey;
-+ dp->ovl->dst.flags = w.flags;
-+
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+
-+ dp->ovl->set_win(dp, dp->ovl);
-+
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 1);
-+
-+ diff = w.flags & VIDEO_WINDOW_INTERLACE ? 1 : 0;
-+ if (!dp->win_set || dp->interlace != diff) {
-+ dp->interlace = diff;
-+ cyberpro_set_interlace(dp);
-+ }
-+ }
-+
-+ dp->win_set = 1;
-+
-+ return 0;
-+ }
-+
-+ case VIDIOCSFBUF: /* set frame buffer info */
-+ {
-+ struct video_buffer b;
-+ int ret;
-+
-+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-+ return -EPERM;
-+
-+ if (dp->cap_active)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&b, arg, sizeof(b)))
-+ return -EFAULT;
-+
-+ ret = cyberpro_set_buffer(dp, &b);
-+ if (ret == 0) {
-+ dp->buf_set = 1;
-+ dp->win_set = 0;
-+ }
-+
-+ return ret;
-+ }
-+
-+ case VIDIOCCAPTURE:
-+ {
-+ int on;
-+
-+ if (get_user(on, (int *)arg))
-+ return -EFAULT;
-+
-+ if (( on && dp->ovl_active) ||
-+ (!on && !dp->ovl_active))
-+ return 0;
-+
-+ if (on && (!dp->buf_set || !dp->win_set))
-+ return -EINVAL;
-+
-+ cyberpro_capture(dp, on);
-+ dp->cap_active = on;
-+ dp->ovl->ctl(dp, dp->ovl, on);
-+ dp->ovl_active = on;
-+
-+ return 0;
-+ }
-+
-+#ifdef USE_MMAP
-+ case VIDIOCSYNC:
-+ {
-+ DECLARE_WAITQUEUE(wait, current);
-+ int buf;
-+
-+ /*
-+ * The buffer must have been mmaped
-+ * for this call to work.
-+ */
-+ if (!dp->mmaped)
-+ return -EINVAL;
-+
-+ if (get_user(buf, (int *)arg))
-+ return -EFAULT;
-+
-+ if (buf < 0 || buf >= NR_FRAMES)
-+ return -EINVAL;
-+
-+ switch (dp->frame[buf].status) {
-+ case FRAME_FREE:
-+ return -EINVAL;
-+
-+ case FRAME_WAITING:
-+ case FRAME_GRABBING:
-+ add_wait_queue(&dp->frame_wait, &wait);
-+ while (1) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (signal_pending(current))
-+ break;
-+ if (dp->frame[buf].status == FRAME_DONE)
-+ break;
-+ schedule();
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&dp->frame_wait, &wait);
-+ if (signal_pending(current))
-+ return -EINTR;
-+ /*FALLTHROUGH*/
-+ case FRAME_DONE:
-+ dp->frame[buf].status = FRAME_FREE;
-+ break;
-+ }
-+ return 0;
-+ }
-+
-+ case VIDIOCMCAPTURE:
-+ {
-+ struct video_mmap vmap;
-+
-+ /*
-+ * The buffer must have been mmaped
-+ * for this call to work.
-+ */
-+ if (!dp->mmaped)
-+ return -EINVAL;
-+
-+ if (copy_from_user(&vmap, arg, sizeof(vmap)))
-+ return -EFAULT;
-+
-+ /*
-+ * We can only capture in our source format/size.
-+ */
-+ if (vmap.frame >= NR_FRAMES ||
-+ vmap.format != dp->stream_fmt ||
-+ vmap.width != dp->capt.width ||
-+ vmap.height != dp->capt.height)
-+ return -EINVAL;
-+
-+ if (dp->frame[vmap.frame].status == FRAME_WAITING ||
-+ dp->frame[vmap.frame].status == FRAME_GRABBING)
-+ return -EBUSY;
-+
-+ dp->frame[vmap.frame].status = FRAME_WAITING;
-+ return 0;
-+ }
-+
-+ case VIDIOCGMBUF:
-+ {
-+ struct video_mbuf vmb;
-+ unsigned int i;
-+
-+ vmb.frames = NR_FRAMES;
-+ vmb.size = dp->frame_size * NR_FRAMES;
-+
-+ for (i = 0; i < NR_FRAMES; i++)
-+ vmb.offsets[i] = dp->frame[i].offset;
-+
-+ return copy_to_user(arg, &vmb, sizeof(vmb)) ? -EFAULT : 0;
-+ }
-+#endif
-+
-+ case VIDIOCSCAPTURE:
-+ {
-+ struct video_capture capt;
-+
-+#ifndef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->cap_active)
-+ return -EINVAL;
-+#endif
-+
-+ if (copy_from_user(&capt, arg, sizeof(capt)))
-+ return -EFAULT;
-+
-+ if (capt.x < 0 || capt.width < 0 ||
-+ capt.y < 0 || capt.height < 0 ||
-+ capt.x + capt.width > dp->cap.maxwidth ||
-+ capt.y + capt.height > dp->cap.maxheight)
-+ return -EINVAL;
-+
-+ /*
-+ * The capture width must be a multiple of 4
-+ */
-+ if (dp->capt.width & 3)
-+ return -EINVAL;
-+
-+ dp->capt.x = capt.x;
-+ dp->capt.y = capt.y;
-+ dp->capt.width = capt.width;
-+ dp->capt.height = capt.height;
-+#ifdef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 0);
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 0);
-+#endif
-+ cyberpro_capture_set_win(dp);
-+
-+ /*
-+ * Update the overlay window information
-+ */
-+ dp->ovl->src.width = capt.width;
-+ dp->ovl->src.height = capt.height;
-+
-+ dp->ovl->set_src(dp, dp->ovl);
-+ if (dp->win_set)
-+ dp->ovl->set_win(dp, dp->ovl);
-+
-+#ifdef ALLOW_SCAPTURE_WHILE_CAP
-+ if (dp->cap_active)
-+ cyberpro_capture(dp, 1);
-+ if (dp->ovl_active)
-+ dp->ovl->ctl(dp, dp->ovl, 1);
-+#endif
-+ return 0;
-+ }
-+
-+ case VIDIOCGTUNER: /* no tuner */
-+ case VIDIOCSTUNER:
-+ return -EINVAL;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+#ifdef USE_MMAP
-+static int
-+cyberpro_grabber_mmap(struct video_device *dev, const char *addr, unsigned long size)
-+{
-+ struct cyberpro_vidinfo *dp = dev->priv;
-+ unsigned long vaddr = (unsigned long)addr;
-+ pgprot_t prot;
-+ int frame_idx, ret = -EINVAL;
-+
-+#if defined(__arm__)
-+ prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_USER | L_PTE_WRITE | L_PTE_DIRTY);
-+#elif defined(__i386__)
-+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED);
-+ if (boot_cpu_data.x86 > 3)
-+ pgprot_val(prot) |= _PAGE_PCD;
-+#else
-+#error "Unsupported architecture"
-+#endif
-+
-+ /*
-+ * The mmap() request must have the correct size.
-+ */
-+ if (size != NR_FRAMES * dp->frame_size)
-+ goto out;
-+
-+ /*
-+ * If it's already mapped, don't re-do
-+ */
-+ if (dp->mmaped)
-+ goto out;
-+ dp->mmaped = 1;
-+
-+ /*
-+ * Map in each frame
-+ */
-+ for (frame_idx = 0; frame_idx < NR_FRAMES; frame_idx++) {
-+ struct framebuf *frame;
-+ int pgidx;
-+
-+ frame = dp->frame + frame_idx;
-+
-+ ret = cyberpro_alloc_frame_buffer(dp, frame);
-+
-+ /*
-+ * If an error occurs, we can be lazy and leave what we've
-+ * been able to do. Our release function will free any
-+ * allocated buffers, and do_mmap_pgoff() will zap any
-+ * inserted mappings.
-+ */
-+ if (ret)
-+ goto out2;
-+
-+ /*
-+ * Map in each page on a page by page basis. This is just
-+ * a little on the inefficient side, but it's only run once.
-+ */
-+ for (pgidx = 0; pgidx < NR_PAGES; pgidx++) {
-+ unsigned long virt;
-+
-+ virt = page_address(frame->pages[pgidx]);
-+
-+ ret = remap_page_range(vaddr, virt_to_phys((void *)virt),
-+ PAGE_SIZE, prot);
-+
-+ if (ret)
-+ goto out2;
-+
-+ vaddr += PAGE_SIZE;
-+ }
-+ }
-+
-+ out2:
-+ if (ret)
-+ dp->mmaped = 0;
-+ out:
-+ return ret;
-+}
-+#endif
-+
-+static int __init cyberpro_grabber_init_done(struct video_device *dev)
-+{
-+ struct cyberpro_vidinfo *dp;
-+ struct cyberpro_info *info = dev->priv;
-+ int ret;
-+
-+ dp = kmalloc(sizeof(*dp), GFP_KERNEL);
-+ if (!dp)
-+ return -ENOMEM;
-+
-+ memset(dp, 0, sizeof(*dp));
-+
-+ dev->priv = dp;
-+ dp->info = *info;
-+ dp->dev = dev;
-+ dp->bus = &cyberpro_i2c_bus;
-+ dp->regs = info->regs;
-+ dp->irq = info->dev->irq;
-+
-+ strcpy(dp->cap.name, dev->name);
-+ dp->cap.type = dev->type;
-+ dp->cap.channels = 1;
-+ dp->cap.audios = 0;
-+ dp->cap.minwidth = 32;
-+ dp->cap.maxwidth = 716;
-+ dp->cap.minheight = 32;
-+ dp->cap.maxheight = 576;
-+
-+ dp->pic.brightness = 32768;
-+ dp->pic.hue = 32768;
-+ dp->pic.colour = 32768;
-+ dp->pic.contrast = 32768;
-+ dp->pic.whiteness = 0;
-+ dp->pic.depth = 8;
-+ dp->pic.palette = VIDEO_PALETTE_YUV422;
-+
-+ /* dp->buf is setup by the user */
-+ /* dp->cap_mem_offset setup by dp->buf */
-+
-+ dp->norm = VIDEO_MODE_AUTO;
-+
-+ /*
-+ * The extended overlay window
-+ */
-+ dp->ext.init = cyberpro_ext_init;
-+ dp->ext.set_src = cyberpro_ext_set_src;
-+ dp->ext.set_win = cyberpro_ext_set_win;
-+ dp->ext.ctl = cyberpro_ext_ctl;
-+
-+ /*
-+ * The V2 overlay window
-+ */
-+ dp->v2.init = cyberpro_v2_init;
-+ dp->v2.set_src = cyberpro_v2_set_src;
-+ dp->v2.set_win = cyberpro_v2_set_win;
-+ dp->v2.ctl = cyberpro_v2_ctl;
-+
-+ /*
-+ * The X2 overlay window
-+ */
-+ dp->x2.init = cyberpro_x2_init;
-+ dp->x2.set_src = cyberpro_x2_set_src;
-+ dp->x2.set_win = cyberpro_x2_set_win;
-+ dp->x2.ctl = cyberpro_x2_ctl;
-+
-+ /*
-+ * Set the overlay window which we shall be using
-+ */
-+ dp->ovl = &dp->ext;
-+
-+ dp->cap_mode1 = EXT_CAP_MODE1_ALTFIFO;
-+
-+ /*
-+ * Initialise hardware specific values.
-+ * - CCIR656 8bit mode (YUV422 data)
-+ * - Ignore Hgood signal
-+ * - Invert Odd/Even field signal
-+ */
-+ dp->cap_mode1 |= EXT_CAP_MODE1_CCIR656 | EXT_CAP_MODE1_8BIT;
-+ dp->cap_mode2 = EXT_CAP_MODE2_FIXSONY | EXT_CAP_MODE2_DATEND |
-+ EXT_CAP_MODE2_CCIRINVOE;
-+ dp->stream_fmt = VIDEO_PALETTE_YUV422;
-+
-+
-+ init_waitqueue_head(&dp->vbl_wait);
-+ cyberpro_frames_init(dp);
-+
-+ /*
-+ * wake up the decoder
-+ */
-+ decoder_sleep(0);
-+
-+ dp->bus->data = dp;
-+ strncpy(dp->bus->name, dev->name, sizeof(dp->bus->name));
-+
-+ pci_set_master(dp->info.dev);
-+
-+ ret = i2c_register_bus(dp->bus);
-+
-+ /*
-+ * If we successfully registered the bus, but didn't initialise
-+ * the decoder (because its driver is not present), request
-+ * that it is loaded.
-+ */
-+ if (ret == 0 && !dp->decoder)
-+ request_module("saa7111");
-+
-+ /*
-+ * If that didn't work, then we're out of luck.
-+ */
-+ if (ret == 0 && !dp->decoder) {
-+ i2c_unregister_bus(dp->bus);
-+ ret = -ENXIO;
-+ }
-+
-+ if (ret) {
-+ kfree(dp);
-+
-+ /*
-+ * put the decoder back to sleep
-+ */
-+ decoder_sleep(1);
-+ }
-+
-+ return ret;
-+}
-+
-+static struct video_device cyberpro_grabber = {
-+ name: "",
-+ type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
-+ VID_TYPE_CHROMAKEY | VID_TYPE_SCALES |
-+ VID_TYPE_SUBCAPTURE,
-+ hardware: 0,
-+ open: cyberpro_grabber_open,
-+ close: cyberpro_grabber_close,
-+ read: cyberpro_grabber_read,
-+ write: cyberpro_grabber_write,
-+ ioctl: cyberpro_grabber_ioctl,
-+#ifdef USE_MMAP
-+ mmap: cyberpro_grabber_mmap,
-+#endif
-+ initialize: cyberpro_grabber_init_done,
-+};
-+
-+int init_cyber2000fb_viddev(void)
-+{
-+ struct cyberpro_info info;
-+
-+ if (!cyber2000fb_attach(&info, 0))
-+ return -ENXIO;
-+
-+ strncpy(cyberpro_grabber.name, info.dev_name, sizeof(cyberpro_grabber.name));
-+
-+ cyberpro_grabber.priv = &info;
-+
-+ return video_register_device(&cyberpro_grabber, VFL_TYPE_GRABBER, -1);
-+}
-+
-+/*
-+ * This can be cleaned up when the SAA7111 code is fixed.
-+ */
-+#ifdef MODULE
-+static int __init cyberpro_init(void)
-+{
-+ disable_irq(35);
-+ return init_cyber2000fb_viddev();
-+}
-+
-+static void __exit cyberpro_exit(void)
-+{
-+ video_unregister_device(&cyberpro_grabber);
-+ kfree(cyberpro_grabber.priv);
-+ i2c_unregister_bus(&cyberpro_i2c_bus);
-+
-+ /*
-+ * put the decoder back to sleep
-+ */
-+ decoder_sleep(1);
-+
-+ cyber2000fb_detach(0);
-+}
-+
-+module_init(cyberpro_init);
-+module_exit(cyberpro_exit);
-+#endif
---- linux-2.4.27/drivers/media/video/i2c-old.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/media/video/i2c-old.c
-@@ -36,11 +36,20 @@
- static struct i2c_driver *drivers[I2C_DRIVER_MAX];
- static int bus_count = 0, driver_count = 0;
-
-+extern int saa7111_init(void);
-+extern int saa7185_init(void);
-+extern int bt819_init(void);
-+extern int bt856_init(void);
-+
- int i2c_init(void)
- {
- printk(KERN_INFO "i2c: initialized%s\n",
- scan ? " (i2c bus scan enabled)" : "");
-
-+#if defined(CONFIG_VIDEO_CYBERPRO)
-+ saa7111_init();
-+#endif
-+
- return 0;
- }
-
-@@ -52,10 +61,10 @@
- int i,j,ack=1;
- unsigned char addr;
- LOCK_FLAGS;
--
-+
- /* probe for device */
- LOCK_I2C_BUS(bus);
-- for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
-+ for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2)
- {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,addr,0);
-@@ -87,8 +96,8 @@
- device->addr = addr;
-
- /* Attach */
--
-- if (driver->attach(device)!=0)
-+
-+ if (driver->attach(device)!=0)
- {
- kfree(device);
- return;
-@@ -114,7 +123,7 @@
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->driver->devices[i])
- break;
-- if (I2C_DEVICE_MAX == i)
-+ if (I2C_DEVICE_MAX == i)
- {
- printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
- device->name);
-@@ -126,7 +135,7 @@
- for (i = 0; i < I2C_DEVICE_MAX; i++)
- if (device == device->bus->devices[i])
- break;
-- if (I2C_DEVICE_MAX == i)
-+ if (I2C_DEVICE_MAX == i)
- {
- printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
- device->name);
-@@ -158,19 +167,19 @@
- busses[i] = bus;
- bus_count++;
- REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
--
-+
- MOD_INC_USE_COUNT;
-
-- if (scan)
-+ if (scan)
- {
- /* scan whole i2c bus */
- LOCK_I2C_BUS(bus);
-- for (i = 0; i < 256; i+=2)
-+ for (i = 0; i < 256; i+=2)
- {
- i2c_start(bus);
- ack = i2c_sendbyte(bus,i,0);
- i2c_stop(bus);
-- if (!ack)
-+ if (!ack)
- {
- printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
- bus->name,i);
-@@ -198,20 +207,20 @@
- for (i = 0; i < I2C_BUS_MAX; i++)
- if (bus == busses[i])
- break;
-- if (I2C_BUS_MAX == i)
-+ if (I2C_BUS_MAX == i)
- {
- printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
- bus->name);
- return -ENODEV;
- }
--
-+
- MOD_DEC_USE_COUNT;
--
-+
- busses[i] = NULL;
- bus_count--;
- REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
-
-- return 0;
-+ return 0;
- }
-
- /* ----------------------------------------------------------------------- */
-@@ -231,9 +240,9 @@
-
- drivers[i] = driver;
- driver_count++;
--
-+
- MOD_INC_USE_COUNT;
--
-+
- REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
-
- /* Probe available busses */
-@@ -256,7 +265,7 @@
- for (i = 0; i < I2C_DRIVER_MAX; i++)
- if (driver == drivers[i])
- break;
-- if (I2C_DRIVER_MAX == i)
-+ if (I2C_DRIVER_MAX == i)
- {
- printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
- driver->name);
-@@ -264,7 +273,7 @@
- }
-
- MOD_DEC_USE_COUNT;
--
-+
- drivers[i] = NULL;
- driver_count--;
- REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
-@@ -328,7 +337,7 @@
- int i2c_ack(struct i2c_bus *bus)
- {
- int ack;
--
-+
- I2C_SET(bus,0,1);
- I2C_SET(bus,1,1);
- ack = I2C_GET(bus);
-@@ -339,7 +348,7 @@
- int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
- {
- int i, ack;
--
-+
- I2C_SET(bus,0,0);
- for (i=7; i>=0; i--)
- (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
-@@ -354,9 +363,9 @@
- {
- int i;
- unsigned char data=0;
--
-+
- I2C_SET(bus,0,1);
-- for (i=7; i>=0; i--)
-+ for (i=7; i>=0; i--)
- {
- I2C_SET(bus,1,1);
- if (I2C_GET(bus))
-@@ -373,7 +382,7 @@
- int i2c_read(struct i2c_bus *bus, unsigned char addr)
- {
- int ret;
--
-+
- if (bus->i2c_read)
- return bus->i2c_read(bus, addr);
-
---- linux-2.4.27/drivers/media/video/saa7111.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/media/video/saa7111.c
-@@ -20,9 +20,9 @@
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
--
--#include <linux/module.h>
-+#include <linux/config.h>
- #include <linux/init.h>
-+#include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
-@@ -149,7 +149,11 @@
- 0x0d, 0x00, /* 0d - HUE=0 */
- 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
- 0x0f, 0x00, /* 0f - reserved */
-+#ifndef CONFIG_ARCH_NETWINDER
- 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
-+#else
-+ 0x10, 0xc8, /* 10 - OFTS=YUV-CCIR656, HDEL=0, VLRN=1, YDEL=0 */
-+#endif
- 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
- 0x12, 0x00, /* 12 - output control 2 */
- 0x13, 0x00, /* 13 - output control 3 */
---- linux-2.4.27/drivers/message/i2o/i2o_core.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/message/i2o/i2o_core.c
-@@ -1665,14 +1665,14 @@
- }
- memset(status, 0, 4);
-
-- msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
-- msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
-- msg[2]=core_context;
-- msg[3]=0;
-- msg[4]=0;
-- msg[5]=0;
-- msg[6]=virt_to_bus(status);
-- msg[7]=0; /* 64bit host FIXME */
-+ writel(EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
-+ writel(I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0, msg + 3);
-+ writel(0, msg + 4);
-+ writel(0, msg + 5);
-+ writel(virt_to_bus(status), msg + 6);
-+ writel(0, msg + 7); /* 64bit host FIXME */
-
- i2o_post_message(c,m);
-
-@@ -1781,15 +1781,15 @@
- return -ETIMEDOUT;
- msg=(u32 *)(c->mem_offset+m);
-
-- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-- msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-- msg[2]=core_context;
-- msg[3]=0;
-- msg[4]=0;
-- msg[5]=0;
-- msg[6]=virt_to_bus(c->status_block);
-- msg[7]=0; /* 64bit host FIXME */
-- msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
-+ writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, msg + 0);
-+ writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0, msg + 3);
-+ writel(0, msg + 4);
-+ writel(0, msg + 5);
-+ writel(virt_to_bus(c->status_block), msg + 6);
-+ writel(0, msg + 7); /* 64bit host FIXME */
-+ writel(sizeof(i2o_status_block), msg + 8); /* always 88 bytes */
-
- i2o_post_message(c,m);
-
-@@ -2193,15 +2193,15 @@
- }
- memset(status, 0, 4);
-
-- msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
-- msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
-- msg[2]= core_context;
-- msg[3]= 0x0106; /* Transaction context */
-- msg[4]= 4096; /* Host page frame size */
-+ writel(EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6, msg + 0);
-+ writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, msg + 1);
-+ writel(core_context, msg + 2);
-+ writel(0x0106, msg + 3); /* Transaction context */
-+ writel(PAGE_SIZE, msg + 4); /* Host page frame size */
- /* Frame size is in words. 256 bytes a frame for now */
-- msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size in words and Initcode */
-- msg[6]= 0xD0000004; /* Simple SG LE, EOB */
-- msg[7]= virt_to_bus(status);
-+ writel(MSG_FRAME_SIZE<<16|0x80, msg + 5);/* Outbound msg frame size in words and Initcode */
-+ writel(0xD0000004, msg + 6); /* Simple SG LE, EOB */
-+ writel(virt_to_bus(status), msg + 7);
-
- i2o_post_message(c,m);
-
---- linux-2.4.27/drivers/message/i2o/i2o_pci.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/message/i2o/i2o_pci.c
-@@ -390,4 +390,4 @@
- MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
- module_init(i2o_pci_core_attach);
- module_exit(i2o_pci_core_detach);
--
-\ No newline at end of file
-+
---- linux-2.4.27/drivers/misc/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/misc/Config.in
-@@ -1,7 +1,17 @@
- #
--# Misc strange devices
-+# MCP drivers
- #
- mainmenu_option next_comment
--comment 'Misc devices'
-+comment 'Multimedia Capabilities Port drivers'
-+
-+bool 'Multimedia drivers' CONFIG_MCP
-+
-+# Interface drivers
-+dep_bool 'Support SA1100 MCP interface' CONFIG_MCP_SA1100 $CONFIG_MCP $CONFIG_ARCH_SA1100
-+
-+# Chip drivers
-+dep_tristate 'Support for UCB1200 / UCB1300' CONFIG_MCP_UCB1200 $CONFIG_MCP
-+dep_tristate ' Audio / Telephony interface support' CONFIG_MCP_UCB1200_AUDIO $CONFIG_MCP_UCB1200 $CONFIG_SOUND
-+dep_tristate ' Touchscreen interface support' CONFIG_MCP_UCB1200_TS $CONFIG_MCP_UCB1200
-
- endmenu
---- linux-2.4.27/drivers/misc/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/misc/Makefile
-@@ -11,6 +11,14 @@
-
- O_TARGET := misc.o
-
-+export-objs := mcp-core.o mcp-sa1100.o ucb1x00-core.o
-+
-+obj-$(CONFIG_MCP) += mcp-core.o
-+obj-$(CONFIG_MCP_SA1100) += mcp-sa1100.o
-+obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
-+obj-$(CONFIG_MCP_UCB1200_AUDIO) += ucb1x00-audio.o
-+obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-+
- include $(TOPDIR)/Rules.make
-
- fastdep:
---- /dev/null
-+++ linux-2.4.27/drivers/misc/mcp-core.c
-@@ -0,0 +1,155 @@
-+/*
-+ * linux/drivers/misc/mcp-core.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * Generic MCP (Multimedia Communications Port) layer. All MCP locking
-+ * is solely held within this file.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/smp.h>
-+
-+#include <asm/dma.h>
-+#include <asm/system.h>
-+
-+#include "mcp.h"
-+
-+/**
-+ * mcp_set_telecom_divisor - set the telecom divisor
-+ * @mcp: MCP interface structure
-+ * @div: SIB clock divisor
-+ *
-+ * Set the telecom divisor on the MCP interface. The resulting
-+ * sample rate is SIBCLOCK/div.
-+ */
-+void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ mcp->set_telecom_divisor(mcp, div);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_set_audio_divisor - set the audio divisor
-+ * @mcp: MCP interface structure
-+ * @div: SIB clock divisor
-+ *
-+ * Set the audio divisor on the MCP interface.
-+ */
-+void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ mcp->set_audio_divisor(mcp, div);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_reg_write - write a device register
-+ * @mcp: MCP interface structure
-+ * @reg: 4-bit register index
-+ * @val: 16-bit data value
-+ *
-+ * Write a device register. The MCP interface must be enabled
-+ * to prevent this function hanging.
-+ */
-+void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ mcp->reg_write(mcp, reg, val);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+}
-+
-+/**
-+ * mcp_reg_read - read a device register
-+ * @mcp: MCP interface structure
-+ * @reg: 4-bit register index
-+ *
-+ * Read a device register and return its value. The MCP interface
-+ * must be enabled to prevent this function hanging.
-+ */
-+unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
-+{
-+ unsigned long flags;
-+ unsigned int val;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ val = mcp->reg_read(mcp, reg);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+
-+ return val;
-+}
-+
-+/**
-+ * mcp_enable - enable the MCP interface
-+ * @mcp: MCP interface to enable
-+ *
-+ * Enable the MCP interface. Each call to mcp_enable will need
-+ * a corresponding call to mcp_disable to disable the interface.
-+ */
-+void mcp_enable(struct mcp *mcp)
-+{
-+ spin_lock_irq(&mcp->lock);
-+ if (mcp->use_count++ == 0)
-+ mcp->enable(mcp);
-+ spin_unlock_irq(&mcp->lock);
-+}
-+
-+/**
-+ * mcp_disable - disable the MCP interface
-+ * @mcp: MCP interface to disable
-+ *
-+ * Disable the MCP interface. The MCP interface will only be
-+ * disabled once the number of calls to mcp_enable matches the
-+ * number of calls to mcp_disable.
-+ */
-+void mcp_disable(struct mcp *mcp)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&mcp->lock, flags);
-+ if (--mcp->use_count == 0)
-+ mcp->disable(mcp);
-+ spin_unlock_irqrestore(&mcp->lock, flags);
-+}
-+
-+
-+/*
-+ * This needs re-working
-+ */
-+static struct mcp *mcp_if;
-+
-+struct mcp *mcp_get(void)
-+{
-+ return mcp_if;
-+}
-+
-+int mcp_register(struct mcp *mcp)
-+{
-+ if (mcp_if)
-+ return -EBUSY;
-+ if (mcp->owner)
-+ __MOD_INC_USE_COUNT(mcp->owner);
-+ mcp_if = mcp;
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(mcp_set_telecom_divisor);
-+EXPORT_SYMBOL(mcp_set_audio_divisor);
-+EXPORT_SYMBOL(mcp_reg_write);
-+EXPORT_SYMBOL(mcp_reg_read);
-+EXPORT_SYMBOL(mcp_enable);
-+EXPORT_SYMBOL(mcp_disable);
-+EXPORT_SYMBOL(mcp_get);
-+EXPORT_SYMBOL(mcp_register);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Core multimedia communications port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/misc/mcp-sa1100.c
-@@ -0,0 +1,180 @@
-+/*
-+ * linux/drivers/misc/mcp-sa1100.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * SA1100 MCP (Multimedia Communications Port) driver.
-+ *
-+ * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/spinlock.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+
-+#include "mcp.h"
-+
-+static void
-+mcp_sa1100_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
-+{
-+ unsigned int mccr0;
-+
-+ divisor /= 32;
-+
-+ mccr0 = Ser4MCCR0 & ~0x00007f00;
-+ mccr0 |= divisor << 8;
-+ Ser4MCCR0 = mccr0;
-+}
-+
-+static void
-+mcp_sa1100_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
-+{
-+ unsigned int mccr0;
-+
-+ divisor /= 32;
-+
-+ mccr0 = Ser4MCCR0 & ~0x0000007f;
-+ mccr0 |= divisor;
-+ Ser4MCCR0 = mccr0;
-+}
-+
-+/*
-+ * Write data to the device. The bit should be set after 3 subframe
-+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
-+ * We really should try doing something more productive while we
-+ * wait.
-+ */
-+static void
-+mcp_sa1100_write(struct mcp *mcp, unsigned int reg, unsigned int val)
-+{
-+ int ret = -ETIME;
-+ int i;
-+
-+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
-+
-+ for (i = 0; i < 2; i++) {
-+ udelay(mcp->rw_timeout);
-+ if (Ser4MCSR & MCSR_CWC) {
-+ ret = 0;
-+ break;
-+ }
-+ }
-+
-+ if (ret < 0)
-+ printk(KERN_WARNING "mcp: write timed out\n");
-+}
-+
-+/*
-+ * Read data from the device. The bit should be set after 3 subframe
-+ * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
-+ * We really should try doing something more productive while we
-+ * wait.
-+ */
-+static unsigned int
-+mcp_sa1100_read(struct mcp *mcp, unsigned int reg)
-+{
-+ int ret = -ETIME;
-+ int i;
-+
-+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
-+
-+ for (i = 0; i < 2; i++) {
-+ udelay(mcp->rw_timeout);
-+ if (Ser4MCSR & MCSR_CRC) {
-+ ret = Ser4MCDR2 & 0xffff;
-+ break;
-+ }
-+ }
-+
-+ if (ret < 0)
-+ printk(KERN_WARNING "mcp: read timed out\n");
-+
-+ return ret;
-+}
-+
-+static void mcp_sa1100_enable(struct mcp *mcp)
-+{
-+ Ser4MCSR = -1;
-+ Ser4MCCR0 |= MCCR0_MCE;
-+}
-+
-+static void mcp_sa1100_disable(struct mcp *mcp)
-+{
-+ Ser4MCCR0 &= ~MCCR0_MCE;
-+}
-+
-+struct mcp mcp_sa1100 = {
-+ owner: THIS_MODULE,
-+ lock: SPIN_LOCK_UNLOCKED,
-+ sclk_rate: 11981000,
-+ dma_audio_rd: DMA_Ser4MCP0Rd,
-+ dma_audio_wr: DMA_Ser4MCP0Wr,
-+ dma_telco_rd: DMA_Ser4MCP1Rd,
-+ dma_telco_wr: DMA_Ser4MCP1Wr,
-+ set_telecom_divisor: mcp_sa1100_set_telecom_divisor,
-+ set_audio_divisor: mcp_sa1100_set_audio_divisor,
-+ reg_write: mcp_sa1100_write,
-+ reg_read: mcp_sa1100_read,
-+ enable: mcp_sa1100_enable,
-+ disable: mcp_sa1100_disable,
-+};
-+
-+/*
-+ * This needs re-working
-+ */
-+static int mcp_sa1100_init(void)
-+{
-+ struct mcp *mcp = &mcp_sa1100;
-+ int ret = -ENODEV;
-+
-+ if (machine_is_accelent_sa() ||
-+ machine_is_adsbitsy() || machine_is_assabet() ||
-+ machine_is_cerf() || machine_is_flexanet() ||
-+ machine_is_freebird() || machine_is_graphicsclient() ||
-+ machine_is_graphicsmaster() || machine_is_lart() ||
-+ machine_is_omnimeter() || machine_is_pfs168() ||
-+ machine_is_shannon() || machine_is_simpad() ||
-+ machine_is_simputer() || machine_is_yopy()) {
-+ /*
-+ * Setup the PPC unit correctly.
-+ */
-+ PPDR &= ~PPC_RXD4;
-+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
-+ PSDR |= PPC_RXD4;
-+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-+
-+ Ser4MCSR = -1;
-+ Ser4MCCR1 = 0;
-+ Ser4MCCR0 = 0x00007f7f | MCCR0_ADM;
-+
-+ /*
-+ * Calculate the read/write timeout (us) from the bit clock
-+ * rate. This is the period for 3 64-bit frames. Always
-+ * round this time up.
-+ */
-+ mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
-+ mcp->sclk_rate;
-+
-+ ret = mcp_register(mcp);
-+ }
-+
-+ return ret;
-+}
-+
-+module_init(mcp_sa1100_init);
-+EXPORT_SYMBOL(mcp_sa1100_init);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/misc/mcp.h
-@@ -0,0 +1,44 @@
-+/*
-+ * linux/drivers/misc/mcp.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef MCP_H
-+#define MCP_H
-+
-+struct mcp {
-+ struct module *owner;
-+ spinlock_t lock;
-+ int use_count;
-+ unsigned int sclk_rate;
-+ unsigned int rw_timeout;
-+ dma_device_t dma_audio_rd;
-+ dma_device_t dma_audio_wr;
-+ dma_device_t dma_telco_rd;
-+ dma_device_t dma_telco_wr;
-+ void (*set_telecom_divisor)(struct mcp *, unsigned int);
-+ void (*set_audio_divisor)(struct mcp *, unsigned int);
-+ void (*reg_write)(struct mcp *, unsigned int, unsigned int);
-+ unsigned int (*reg_read)(struct mcp *, unsigned int);
-+ void (*enable)(struct mcp *);
-+ void (*disable)(struct mcp *);
-+};
-+
-+void mcp_set_telecom_divisor(struct mcp *, unsigned int);
-+void mcp_set_audio_divisor(struct mcp *, unsigned int);
-+void mcp_reg_write(struct mcp *, unsigned int, unsigned int);
-+unsigned int mcp_reg_read(struct mcp *, unsigned int);
-+void mcp_enable(struct mcp *);
-+void mcp_disable(struct mcp *);
-+
-+/* noddy implementation alert! */
-+struct mcp *mcp_get(void);
-+int mcp_register(struct mcp *);
-+
-+#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00-audio.c
-@@ -0,0 +1,378 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-audio.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/list.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+
-+#include "ucb1x00.h"
-+
-+#include "../drivers/sound/sa1100-audio.h"
-+
-+#define MAGIC 0x41544154
-+
-+struct ucb1x00_audio {
-+ struct file_operations fops;
-+ struct file_operations mops;
-+ struct ucb1x00 *ucb;
-+ audio_stream_t output_stream;
-+ audio_stream_t input_stream;
-+ audio_state_t state;
-+ unsigned int rate;
-+ int dev_id;
-+ int mix_id;
-+ unsigned int daa_oh_bit;
-+ unsigned int telecom;
-+ unsigned int magic;
-+ unsigned int ctrl_a;
-+ unsigned int ctrl_b;
-+
-+ /* mixer info */
-+ unsigned int mod_cnt;
-+ unsigned short output_level;
-+ unsigned short input_level;
-+};
-+
-+#define REC_MASK (SOUND_MASK_VOLUME | SOUND_MASK_MIC)
-+#define DEV_MASK REC_MASK
-+
-+static int
-+ucb1x00_mixer_ioctl(struct inode *ino, struct file *filp, uint cmd, ulong arg)
-+{
-+ struct ucb1x00_audio *ucba;
-+ unsigned int val, gain;
-+ int ret = 0;
-+
-+ ucba = list_entry(filp->f_op, struct ucb1x00_audio, mops);
-+
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ if (cmd == SOUND_MIXER_INFO) {
-+ struct mixer_info mi;
-+
-+ strncpy(mi.id, "UCB1x00", sizeof(mi.id));
-+ strncpy(mi.name, "Philips UCB1x00", sizeof(mi.name));
-+ mi.modify_counter = ucba->mod_cnt;
-+ return copy_to_user((void *)arg, &mi, sizeof(mi)) ? -EFAULT : 0;
-+ }
-+
-+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
-+ unsigned int left, right;
-+
-+ ret = get_user(val, (unsigned int *)arg);
-+ if (ret)
-+ goto out;
-+
-+ left = val & 255;
-+ right = val >> 8;
-+
-+ if (left > 100)
-+ left = 100;
-+ if (right > 100)
-+ right = 100;
-+
-+ gain = (left + right) / 2;
-+
-+ ret = -EINVAL;
-+ if (!ucba->telecom) {
-+ switch(_IOC_NR(cmd)) {
-+ case SOUND_MIXER_VOLUME:
-+ ucba->output_level = gain | gain << 8;
-+ ucba->mod_cnt++;
-+ ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
-+ ((gain * 31) / 100);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
-+ ucba->ctrl_b);
-+ ret = 0;
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ ucba->input_level = gain | gain << 8;
-+ ucba->mod_cnt++;
-+ ucba->ctrl_a = (ucba->ctrl_a & 0x7f) |
-+ (((gain * 31) / 100) << 7);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A,
-+ ucba->ctrl_a);
-+ ret = 0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
-+ switch (_IOC_NR(cmd)) {
-+ case SOUND_MIXER_VOLUME:
-+ val = ucba->output_level;
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ val = ucba->input_level;
-+ break;
-+
-+ case SOUND_MIXER_RECSRC:
-+ case SOUND_MIXER_RECMASK:
-+ val = ucba->telecom ? 0 : REC_MASK;
-+ break;
-+
-+ case SOUND_MIXER_DEVMASK:
-+ val = ucba->telecom ? 0 : DEV_MASK;
-+ break;
-+
-+ case SOUND_MIXER_CAPS:
-+ case SOUND_MIXER_STEREODEVS:
-+ val = 0;
-+ break;
-+
-+ default:
-+ val = 0;
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ if (ret == 0)
-+ ret = put_user(val, (int *)arg);
-+ }
-+ out:
-+ return ret;
-+}
-+
-+static int ucb1x00_audio_setrate(struct ucb1x00_audio *ucba, int rate)
-+{
-+ unsigned int div_rate = ucb1x00_clkrate(ucba->ucb) / 32;
-+ unsigned int div;
-+
-+ div = (div_rate + (rate / 2)) / rate;
-+ if (div < 6)
-+ div = 6;
-+ if (div > 127)
-+ div = 127;
-+
-+ ucba->ctrl_a = (ucba->ctrl_a & ~0x7f) | div;
-+
-+ if (ucba->telecom) {
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, 0);
-+ ucb1x00_set_telecom_divisor(ucba->ucb, div * 32);
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_A, ucba->ctrl_a);
-+ ucb1x00_reg_write(ucba->ucb, UCB_TC_B, ucba->ctrl_b);
-+ } else {
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, 0);
-+ ucb1x00_set_audio_divisor(ucba->ucb, div * 32);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_A, ucba->ctrl_a);
-+ ucb1x00_reg_write(ucba->ucb, UCB_AC_B, ucba->ctrl_b);
-+ }
-+
-+ ucba->rate = div_rate / div;
-+
-+ return ucba->rate;
-+}
-+
-+static int ucb1x00_audio_getrate(struct ucb1x00_audio *ucba)
-+{
-+ return ucba->rate;
-+}
-+
-+static void ucb1x00_audio_startup(void *data)
-+{
-+ struct ucb1x00_audio *ucba = data;
-+
-+ ucb1x00_enable(ucba->ucb);
-+ ucb1x00_audio_setrate(ucba, ucba->rate);
-+
-+ ucb1x00_reg_write(ucba->ucb, UCB_MODE, UCB_MODE_DYN_VFLAG_ENA);
-+
-+ /*
-+ * Take off-hook
-+ */
-+ if (ucba->daa_oh_bit)
-+ ucb1x00_io_write(ucba->ucb, 0, ucba->daa_oh_bit);
-+}
-+
-+static void ucb1x00_audio_shutdown(void *data)
-+{
-+ struct ucb1x00_audio *ucba = data;
-+
-+ /*
-+ * Place on-hook
-+ */
-+ if (ucba->daa_oh_bit)
-+ ucb1x00_io_write(ucba->ucb, ucba->daa_oh_bit, 0);
-+
-+ ucb1x00_reg_write(ucba->ucb, ucba->telecom ? UCB_TC_B : UCB_AC_B, 0);
-+ ucb1x00_disable(ucba->ucb);
-+}
-+
-+static int
-+ucb1x00_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ struct ucb1x00_audio *ucba;
-+ int val, ret = 0;
-+
-+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
-+
-+ /*
-+ * Make sure we have our magic number
-+ */
-+ if (ucba->magic != MAGIC)
-+ return -ENODEV;
-+
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ if (val != 0)
-+ return -EINVAL;
-+ val = 0;
-+ break;
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ val = 1;
-+ break;
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ return ret;
-+ val = ucb1x00_audio_setrate(ucba, val);
-+ break;
-+
-+ case SOUND_PCM_READ_RATE:
-+ val = ucb1x00_audio_getrate(ucba);
-+ break;
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ val = AFMT_S16_LE;
-+ break;
-+
-+ default:
-+ return ucb1x00_mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return put_user(val, (int *)arg);
-+}
-+
-+static int ucb1x00_audio_open(struct inode *inode, struct file *file)
-+{
-+ struct ucb1x00_audio *ucba;
-+
-+ ucba = list_entry(file->f_op, struct ucb1x00_audio, fops);
-+
-+ return sa1100_audio_attach(inode, file, &ucba->state);
-+}
-+
-+static struct ucb1x00_audio *ucb1x00_audio_alloc(struct ucb1x00 *ucb)
-+{
-+ struct ucb1x00_audio *ucba;
-+
-+ ucba = kmalloc(sizeof(*ucba), GFP_KERNEL);
-+ if (ucba) {
-+ memset(ucba, 0, sizeof(*ucba));
-+
-+ ucba->magic = MAGIC;
-+ ucba->ucb = ucb;
-+ ucba->fops.owner = THIS_MODULE;
-+ ucba->fops.open = ucb1x00_audio_open;
-+ ucba->mops.owner = THIS_MODULE;
-+ ucba->mops.ioctl = ucb1x00_mixer_ioctl;
-+ ucba->state.output_stream = &ucba->output_stream;
-+ ucba->state.input_stream = &ucba->input_stream;
-+ ucba->state.data = ucba;
-+ ucba->state.hw_init = ucb1x00_audio_startup;
-+ ucba->state.hw_shutdown = ucb1x00_audio_shutdown;
-+ ucba->state.client_ioctl = ucb1x00_audio_ioctl;
-+
-+ /* There is a bug in the StrongARM causes corrupt MCP data to be sent to
-+ * the codec when the FIFOs are empty and writes are made to the OS timer
-+ * match register 0. To avoid this we must make sure that data is always
-+ * sent to the codec.
-+ */
-+ ucba->state.need_tx_for_rx = 1;
-+
-+ init_MUTEX(&ucba->state.sem);
-+ ucba->rate = 8000;
-+ }
-+ return ucba;
-+}
-+
-+static struct ucb1x00_audio *audio, *telecom;
-+
-+static int __init ucb1x00_audio_init(void)
-+{
-+ struct ucb1x00 *ucb = ucb1x00_get();
-+ struct ucb1x00_audio *a;
-+
-+ if (!ucb)
-+ return -ENODEV;
-+
-+ a = ucb1x00_audio_alloc(ucb);
-+ if (a) {
-+ a->state.input_dma = ucb->mcp->dma_audio_rd;
-+ a->state.input_id = "UCB1x00 audio in";
-+ a->state.output_dma = ucb->mcp->dma_audio_wr;
-+ a->state.output_id = "UCB1x00 audio out";
-+ a->dev_id = register_sound_dsp(&a->fops, -1);
-+ a->mix_id = register_sound_mixer(&a->mops, -1);
-+ a->ctrl_a = 0;
-+ a->ctrl_b = UCB_AC_B_IN_ENA|UCB_AC_B_OUT_ENA;
-+ audio = a;
-+ }
-+
-+ a = ucb1x00_audio_alloc(ucb);
-+ if (a) {
-+#if 0
-+ a->daa_oh_bit = UCB_IO_8;
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_io_write(ucb, a->daa_oh_bit, 0);
-+ ucb1x00_io_set_dir(ucb, UCB_IO_7 | UCB_IO_6, a->daa_oh_bit);
-+ ucb1x00_disable(ucb);
-+#endif
-+
-+ a->telecom = 1;
-+ a->state.input_dma = ucb->mcp->dma_telco_rd;
-+ a->state.input_id = "UCB1x00 telco in";
-+ a->state.output_dma = ucb->mcp->dma_telco_wr;
-+ a->state.output_id = "UCB1x00 telco out";
-+ a->dev_id = register_sound_dsp(&a->fops, -1);
-+ a->mix_id = register_sound_mixer(&a->mops, -1);
-+ a->ctrl_a = 0;
-+ a->ctrl_b = UCB_TC_B_IN_ENA|UCB_TC_B_OUT_ENA;
-+ telecom = a;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit ucb1x00_audio_exit(void)
-+{
-+ unregister_sound_dsp(telecom->dev_id);
-+ unregister_sound_dsp(audio->dev_id);
-+ unregister_sound_mixer(telecom->mix_id);
-+ unregister_sound_mixer(audio->mix_id);
-+}
-+
-+module_init(ucb1x00_audio_init);
-+module_exit(ucb1x00_audio_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 telecom/audio driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00-core.c
-@@ -0,0 +1,651 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-core.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * The UCB1x00 core driver provides basic services for handling IO,
-+ * the ADC, interrupts, and accessing registers. It is designed
-+ * such that everything goes through this layer, thereby providing
-+ * a consistent locking methodology, as well as allowing the drivers
-+ * to be used on other non-MCP-enabled hardware platforms.
-+ *
-+ * Note that all locks are private to this file. Nothing else may
-+ * touch them.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/arch/shannon.h>
-+
-+#include "ucb1x00.h"
-+
-+/**
-+ * ucb1x00_io_set_dir - set IO direction
-+ * @ucb: UCB1x00 structure describing chip
-+ * @in: bitfield of IO pins to be set as inputs
-+ * @out: bitfield of IO pins to be set as outputs
-+ *
-+ * Set the IO direction of the ten general purpose IO pins on
-+ * the UCB1x00 chip. The @in bitfield has priority over the
-+ * @out bitfield, in that if you specify a pin as both input
-+ * and output, it will end up as an input.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function takes a spinlock, disabling interrupts.
-+ */
-+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ucb->io_lock, flags);
-+ ucb->io_dir |= out;
-+ ucb->io_dir &= ~in;
-+
-+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
-+ spin_unlock_irqrestore(&ucb->io_lock, flags);
-+}
-+
-+/**
-+ * ucb1x00_io_write - set or clear IO outputs
-+ * @ucb: UCB1x00 structure describing chip
-+ * @set: bitfield of IO pins to set to logic '1'
-+ * @clear: bitfield of IO pins to set to logic '0'
-+ *
-+ * Set the IO output state of the specified IO pins. The value
-+ * is retained if the pins are subsequently configured as inputs.
-+ * The @clear bitfield has priority over the @set bitfield -
-+ * outputs will be cleared.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function takes a spinlock, disabling interrupts.
-+ */
-+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ucb->io_lock, flags);
-+ ucb->io_out |= set;
-+ ucb->io_out &= ~clear;
-+
-+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
-+ spin_unlock_irqrestore(&ucb->io_lock, flags);
-+}
-+
-+/**
-+ * ucb1x00_io_read - read the current state of the IO pins
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return a bitfield describing the logic state of the ten
-+ * general purpose IO pins.
-+ *
-+ * ucb1x00_enable must have been called to enable the comms
-+ * before using this function.
-+ *
-+ * This function does not take any semaphores or spinlocks.
-+ */
-+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
-+{
-+ return ucb1x00_reg_read(ucb, UCB_IO_DATA);
-+}
-+
-+/*
-+ * UCB1300 data sheet says we must:
-+ * 1. enable ADC => 5us (including reference startup time)
-+ * 2. select input => 51*tsibclk => 4.3us
-+ * 3. start conversion => 102*tsibclk => 8.5us
-+ * (tsibclk = 1/11981000)
-+ * Period between SIB 128-bit frames = 10.7us
-+ */
-+
-+/**
-+ * ucb1x00_adc_enable - enable the ADC converter
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
-+ * Any code wishing to use the ADC converter must call this
-+ * function prior to using it.
-+ *
-+ * This function takes the ADC semaphore to prevent two or more
-+ * concurrent uses, and therefore may sleep. As a result, it
-+ * can only be called from process context, not interrupt
-+ * context.
-+ *
-+ * You should release the ADC as soon as possible using
-+ * ucb1x00_adc_disable.
-+ */
-+void ucb1x00_adc_enable(struct ucb1x00 *ucb)
-+{
-+ down(&ucb->adc_sem);
-+
-+ ucb->adc_cr |= UCB_ADC_ENA;
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
-+}
-+
-+/**
-+ * ucb1x00_adc_read - read the specified ADC channel
-+ * @ucb: UCB1x00 structure describing chip
-+ * @adc_channel: ADC channel mask
-+ * @sync: wait for syncronisation pulse.
-+ *
-+ * Start an ADC conversion and wait for the result. Note that
-+ * synchronised ADC conversions (via the ADCSYNC pin) must wait
-+ * until the trigger is asserted and the conversion is finished.
-+ *
-+ * This function currently spins waiting for the conversion to
-+ * complete (2 frames max without sync).
-+ *
-+ * If called for a synchronised ADC conversion, it may sleep
-+ * with the ADC semaphore held.
-+ */
-+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
-+{
-+ unsigned int val;
-+
-+ if (sync)
-+ adc_channel |= UCB_ADC_SYNC_ENA;
-+
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
-+
-+ for (;;) {
-+ val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
-+ if (val & UCB_ADC_DAT_VAL)
-+ break;
-+ /* yield to other processes */
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ }
-+
-+ return UCB_ADC_DAT(val);
-+}
-+
-+/**
-+ * ucb1x00_adc_disable - disable the ADC converter
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Disable the ADC converter and release the ADC semaphore.
-+ */
-+void ucb1x00_adc_disable(struct ucb1x00 *ucb)
-+{
-+ ucb->adc_cr &= ~UCB_ADC_ENA;
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
-+ ucb1x00_disable(ucb);
-+
-+ up(&ucb->adc_sem);
-+}
-+
-+#ifdef CONFIG_PM
-+static int ucb1x00_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data;
-+ unsigned int isr;
-+
-+ if (rqst == PM_RESUME) {
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+ ucb1x00_disable(ucb);
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * UCB1x00 Interrupt handling.
-+ *
-+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
-+ * Since we need to read an internal register, we must re-enable
-+ * SIBCLK to talk to the chip. We leave the clock running until
-+ * we have finished processing all interrupts from the chip.
-+ */
-+static void ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
-+{
-+ struct ucb1x00 *ucb = devid;
-+ struct ucb1x00_irq *irq;
-+ unsigned int isr, i;
-+
-+ ucb1x00_enable(ucb);
-+ isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
-+ if (isr & 1 && irq->fn)
-+ irq->fn(i, irq->devid);
-+ ucb1x00_disable(ucb);
-+}
-+
-+/**
-+ * ucb1x00_hook_irq - hook a UCB1x00 interrupt
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @fn: function to call when interrupt is triggered
-+ * @devid: device id to pass to interrupt handler
-+ *
-+ * Hook the specified interrupt. You can only register one handler
-+ * for each interrupt source. The interrupt source is not enabled
-+ * by this function; use ucb1x00_enable_irq instead.
-+ *
-+ * Interrupt handlers will be called with other interrupts enabled.
-+ *
-+ * Returns zero on success, or one of the following errors:
-+ * -EINVAL if the interrupt index is invalid
-+ * -EBUSY if the interrupt has already been hooked
-+ */
-+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
-+{
-+ struct ucb1x00_irq *irq;
-+ int ret = -EINVAL;
-+
-+ if (idx < 16) {
-+ irq = ucb->irq_handler + idx;
-+ ret = -EBUSY;
-+
-+ spin_lock_irq(&ucb->lock);
-+ if (irq->fn == NULL) {
-+ irq->devid = devid;
-+ irq->fn = fn;
-+ ret = 0;
-+ }
-+ spin_unlock_irq(&ucb->lock);
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * ucb1x00_enable_irq - enable an UCB1x00 interrupt source
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @edges: interrupt edges to enable
-+ *
-+ * Enable the specified interrupt to trigger on %UCB_RISING,
-+ * %UCB_FALLING or both edges. The interrupt should have been
-+ * hooked by ucb1x00_hook_irq.
-+ */
-+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
-+{
-+ unsigned long flags;
-+
-+ if (idx < 16) {
-+ spin_lock_irqsave(&ucb->lock, flags);
-+
-+ ucb1x00_enable(ucb);
-+ if (edges & UCB_RISING) {
-+ ucb->irq_ris_enbl |= 1 << idx;
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ }
-+ if (edges & UCB_FALLING) {
-+ ucb->irq_fal_enbl |= 1 << idx;
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ }
-+ ucb1x00_disable(ucb);
-+ spin_unlock_irqrestore(&ucb->lock, flags);
-+ }
-+}
-+
-+/**
-+ * ucb1x00_disable_irq - disable an UCB1x00 interrupt source
-+ * @ucb: UCB1x00 structure describing chip
-+ * @edges: interrupt edges to disable
-+ *
-+ * Disable the specified interrupt triggering on the specified
-+ * (%UCB_RISING, %UCB_FALLING or both) edges.
-+ */
-+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
-+{
-+ unsigned long flags;
-+
-+ if (idx < 16) {
-+ spin_lock_irqsave(&ucb->lock, flags);
-+
-+ ucb1x00_enable(ucb);
-+ if (edges & UCB_RISING) {
-+ ucb->irq_ris_enbl &= ~(1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ }
-+ if (edges & UCB_FALLING) {
-+ ucb->irq_fal_enbl &= ~(1 << idx);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ }
-+ ucb1x00_disable(ucb);
-+ spin_unlock_irqrestore(&ucb->lock, flags);
-+ }
-+}
-+
-+/**
-+ * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
-+ * @ucb: UCB1x00 structure describing chip
-+ * @idx: interrupt index
-+ * @devid: device id.
-+ *
-+ * Disable the interrupt source and remove the handler. devid must
-+ * match the devid passed when hooking the interrupt.
-+ *
-+ * Returns zero on success, or one of the following errors:
-+ * -EINVAL if the interrupt index is invalid
-+ * -ENOENT if devid does not match
-+ */
-+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
-+{
-+ struct ucb1x00_irq *irq;
-+ int ret;
-+
-+ if (idx >= 16)
-+ goto bad;
-+
-+ irq = ucb->irq_handler + idx;
-+ ret = -ENOENT;
-+
-+ spin_lock_irq(&ucb->lock);
-+ if (irq->devid == devid) {
-+ ucb->irq_ris_enbl &= ~(1 << idx);
-+ ucb->irq_fal_enbl &= ~(1 << idx);
-+
-+ ucb1x00_enable(ucb);
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
-+ ucb1x00_disable(ucb);
-+
-+ irq->fn = NULL;
-+ irq->devid = NULL;
-+ ret = 0;
-+ }
-+ spin_unlock_irq(&ucb->lock);
-+ return ret;
-+
-+bad:
-+ printk(KERN_ERR "%s: freeing bad irq %d\n", __FUNCTION__, idx);
-+ return -EINVAL;
-+}
-+
-+/*
-+ * Try to probe our interrupt, rather than relying on lots of
-+ * hard-coded machine dependencies. For reference, the expected
-+ * IRQ mappings are:
-+ *
-+ * Machine Default IRQ
-+ * adsbitsy IRQ_GPCIN4
-+ * cerf IRQ_GPIO_UCB1200_IRQ
-+ * flexanet IRQ_GPIO_GUI
-+ * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ
-+ * graphicsclient IRQ_GRAPHICSCLIENT_UCB1200
-+ * graphicsmaster IRQ_GRAPHICSMASTER_UCB1200
-+ * lart LART_IRQ_UCB1200
-+ * omnimeter IRQ_GPIO23
-+ * pfs168 IRQ_GPIO_UCB1300_IRQ
-+ * simpad IRQ_GPIO_UCB1300_IRQ
-+ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC
-+ * yopy IRQ_GPIO_UCB1200_IRQ
-+ */
-+static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb)
-+{
-+ unsigned long mask;
-+
-+ mask = probe_irq_on();
-+ if (!mask)
-+ return NO_IRQ;
-+
-+ /*
-+ * Enable the ADC interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ /*
-+ * Cause an ADC interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
-+
-+ /*
-+ * Wait for the conversion to complete.
-+ */
-+ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
-+ ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
-+
-+ /*
-+ * Disable and clear interrupt.
-+ */
-+ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
-+ ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
-+ ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
-+
-+ /*
-+ * Read triggered interrupt.
-+ */
-+ return probe_irq_off(mask);
-+}
-+
-+/*
-+ * This configures the UCB1x00 layer depending on the machine type
-+ * we're running on. The UCB1x00 drivers should not contain any
-+ * machine dependencies.
-+ *
-+ * We can get rid of some of these dependencies by using existing
-+ * facilities provided by the kernel - namely IRQ probing. The
-+ * machine specific files are expected to setup the IRQ levels on
-+ * initialisation. With any luck, we'll get rid of all the
-+ * machine dependencies here.
-+ */
-+static int __init ucb1x00_configure(struct ucb1x00 *ucb)
-+{
-+ unsigned int irq_gpio_pin = 0;
-+ int irq, default_irq = NO_IRQ;
-+
-+ if (machine_is_adsbitsy())
-+ default_irq = IRQ_GPCIN4;
-+
-+// if (machine_is_assabet())
-+// default_irq = IRQ_GPIO23;
-+
-+#ifdef CONFIG_SA1100_CERF
-+ if (machine_is_cerf())
-+ default_irq = IRQ_GPIO_UCB1200_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_FREEBIRD
-+ if (machine_is_freebird())
-+ default_irq = IRQ_GPIO_FREEBIRD_UCB1300_IRQ;
-+#endif
-+#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
-+// if (machine_is_graphicsclient())
-+// default_irq = IRQ_GRAPHICSCLIENT_UCB1200;
-+#endif
-+#if defined(CONFIG_SA1100_GRAPICSMASTER)
-+ if (machine_is_graphicsmaster())
-+ default_irq = IRQ_GRAPHICSMASTER_UCB1200;
-+#endif
-+#ifdef CONFIG_SA1100_LART
-+ if (machine_is_lart()) {
-+ default_irq = LART_IRQ_UCB1200;
-+ irq_gpio_pin = LART_GPIO_UCB1200;
-+ }
-+#endif
-+ if (machine_is_omnimeter())
-+ default_irq = IRQ_GPIO23;
-+
-+#ifdef CONFIG_SA1100_PFS168
-+ if (machine_is_pfs168())
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (machine_is_simpad())
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ default_irq = IRQ_GPIO_UCB1300_IRQ;
-+ irq_gpio_pin = GPIO_UCB1300_IRQ;
-+ }
-+#endif
-+ if (machine_is_shannon())
-+ default_irq = SHANNON_IRQ_GPIO_IRQ_CODEC;
-+#ifdef CONFIG_SA1100_YOPY
-+ if (machine_is_yopy())
-+ default_irq = IRQ_GPIO_UCB1200_IRQ;
-+#endif
-+#ifdef CONFIG_SA1100_ACCELENT
-+ if (machine_is_accelent_sa()) {
-+ ucb->irq = IRQ_GPIO_UCB1200_IRQ;
-+ irq_gpio_pin = GPIO_UCB1200_IRQ;
-+ }
-+#endif
-+
-+ /*
-+ * Eventually, this will disappear.
-+ */
-+ if (irq_gpio_pin)
-+ set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
-+
-+ irq = ucb1x00_detect_irq(ucb);
-+ if (irq != NO_IRQ) {
-+ if (default_irq != NO_IRQ && irq != default_irq)
-+ printk(KERN_ERR "UCB1x00: probed IRQ%d != default IRQ%d\n",
-+ irq, default_irq);
-+ if (irq == default_irq)
-+ printk(KERN_ERR "UCB1x00: probed IRQ%d correctly. "
-+ "Please remove machine dependencies from "
-+ "ucb1x00-core.c\n", irq);
-+ ucb->irq = irq;
-+ } else {
-+ printk(KERN_ERR "UCB1x00: IRQ probe failed, using IRQ%d\n",
-+ default_irq);
-+ ucb->irq = default_irq;
-+ }
-+
-+ return ucb->irq == NO_IRQ ? -ENODEV : 0;
-+}
-+
-+struct ucb1x00 *my_ucb;
-+
-+/**
-+ * ucb1x00_get - get the UCB1x00 structure describing a chip
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the UCB1x00 structure describing a chip.
-+ *
-+ * FIXME: Currently very noddy indeed, which currently doesn't
-+ * matter since we only support one chip.
-+ */
-+struct ucb1x00 *ucb1x00_get(void)
-+{
-+ return my_ucb;
-+}
-+
-+static int __init ucb1x00_init(void)
-+{
-+ struct mcp *mcp;
-+ unsigned int id;
-+ int ret = -ENODEV;
-+
-+ mcp = mcp_get();
-+ if (!mcp)
-+ goto no_mcp;
-+
-+ mcp_enable(mcp);
-+ id = mcp_reg_read(mcp, UCB_ID);
-+
-+ if (id != UCB_ID_1200 && id != UCB_ID_1300) {
-+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
-+ goto out;
-+ }
-+
-+ my_ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
-+ ret = -ENOMEM;
-+ if (!my_ucb)
-+ goto out;
-+
-+ if (machine_is_shannon()) {
-+ /* reset the codec */
-+ GPDR |= SHANNON_GPIO_CODEC_RESET;
-+ GPCR = SHANNON_GPIO_CODEC_RESET;
-+ GPSR = SHANNON_GPIO_CODEC_RESET;
-+
-+ }
-+
-+ memset(my_ucb, 0, sizeof(struct ucb1x00));
-+
-+ spin_lock_init(&my_ucb->lock);
-+ spin_lock_init(&my_ucb->io_lock);
-+ sema_init(&my_ucb->adc_sem, 1);
-+
-+ my_ucb->id = id;
-+ my_ucb->mcp = mcp;
-+
-+ ret = ucb1x00_configure(my_ucb);
-+ if (ret)
-+ goto out;
-+
-+ ret = request_irq(my_ucb->irq, ucb1x00_irq, 0, "UCB1x00", my_ucb);
-+ if (ret) {
-+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
-+ my_ucb->irq, ret);
-+ kfree(my_ucb);
-+ my_ucb = NULL;
-+ goto out;
-+ }
-+
-+#ifdef CONFIG_PM
-+ my_ucb->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_pm);
-+ if (my_ucb->pmdev == NULL)
-+ printk("ucb1x00: unable to register in PM.\n");
-+ else
-+ my_ucb->pmdev->data = my_ucb;
-+#endif
-+
-+out:
-+ mcp_disable(mcp);
-+no_mcp:
-+ return ret;
-+}
-+
-+static void __exit ucb1x00_exit(void)
-+{
-+ free_irq(my_ucb->irq, my_ucb);
-+ kfree(my_ucb);
-+}
-+
-+module_init(ucb1x00_init);
-+module_exit(ucb1x00_exit);
-+
-+EXPORT_SYMBOL(ucb1x00_get);
-+
-+EXPORT_SYMBOL(ucb1x00_io_set_dir);
-+EXPORT_SYMBOL(ucb1x00_io_write);
-+EXPORT_SYMBOL(ucb1x00_io_read);
-+
-+EXPORT_SYMBOL(ucb1x00_adc_enable);
-+EXPORT_SYMBOL(ucb1x00_adc_read);
-+EXPORT_SYMBOL(ucb1x00_adc_disable);
-+
-+EXPORT_SYMBOL(ucb1x00_hook_irq);
-+EXPORT_SYMBOL(ucb1x00_free_irq);
-+EXPORT_SYMBOL(ucb1x00_enable_irq);
-+EXPORT_SYMBOL(ucb1x00_disable_irq);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 core driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00-ts.c
-@@ -0,0 +1,664 @@
-+/*
-+ * linux/drivers/misc/ucb1x00-ts.c
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * 21-Jan-2002 <jco@ict.es> :
-+ *
-+ * Added support for synchronous A/D mode. This mode is useful to
-+ * avoid noise induced in the touchpanel by the LCD, provided that
-+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
-+ * It is important to note that the signal connected to the ADCSYNC
-+ * pin should provide pulses even when the LCD is blanked, otherwise
-+ * a pen touch needed to unblank the LCD will never be read.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/smp_lock.h>
-+#include <linux/sched.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/string.h>
-+#include <linux/pm.h>
-+
-+#include <asm/dma.h>
-+#include <asm/semaphore.h>
-+
-+#include "ucb1x00.h"
-+
-+/*
-+ * Define this if you want the UCB1x00 stuff to talk to the input layer
-+ */
-+#undef USE_INPUT
-+
-+#ifndef USE_INPUT
-+
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/poll.h>
-+
-+/*
-+ * This structure is nonsense - millisecs is not very useful
-+ * since the field size is too small. Also, we SHOULD NOT
-+ * be exposing jiffies to user space directly.
-+ */
-+struct ts_event {
-+ u16 pressure;
-+ u16 x;
-+ u16 y;
-+ u16 pad;
-+ struct timeval stamp;
-+};
-+
-+#define NR_EVENTS 16
-+
-+#else
-+
-+#include <linux/input.h>
-+
-+#endif
-+
-+struct ucb1x00_ts {
-+#ifdef USE_INPUT
-+ struct input_dev idev;
-+#endif
-+ struct ucb1x00 *ucb;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pmdev;
-+#endif
-+
-+ wait_queue_head_t irq_wait;
-+ struct semaphore sem;
-+ struct completion init_exit;
-+ struct task_struct *rtask;
-+ int use_count;
-+ u16 x_res;
-+ u16 y_res;
-+
-+#ifndef USE_INPUT
-+ struct fasync_struct *fasync;
-+ wait_queue_head_t read_wait;
-+ u8 evt_head;
-+ u8 evt_tail;
-+ struct ts_event events[NR_EVENTS];
-+#endif
-+ int restart:1;
-+ int adcsync:1;
-+};
-+
-+static struct ucb1x00_ts ucbts;
-+static int adcsync = UCB_NOSYNC;
-+
-+static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);
-+static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);
-+
-+#ifndef USE_INPUT
-+
-+#define ucb1x00_ts_evt_pending(ts) ((volatile u8)(ts)->evt_head != (ts)->evt_tail)
-+#define ucb1x00_ts_evt_get(ts) ((ts)->events + (ts)->evt_tail)
-+#define ucb1x00_ts_evt_pull(ts) ((ts)->evt_tail = ((ts)->evt_tail + 1) & (NR_EVENTS - 1))
-+#define ucb1x00_ts_evt_clear(ts) ((ts)->evt_head = (ts)->evt_tail = 0)
-+
-+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ int next_head;
-+
-+ next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);
-+ if (next_head != ts->evt_tail) {
-+ ts->events[ts->evt_head].pressure = pressure;
-+ ts->events[ts->evt_head].x = x;
-+ ts->events[ts->evt_head].y = y;
-+ do_gettimeofday(&ts->events[ts->evt_head].stamp);
-+ ts->evt_head = next_head;
-+
-+ if (ts->fasync)
-+ kill_fasync(&ts->fasync, SIGIO, POLL_IN);
-+ wake_up_interruptible(&ts->read_wait);
-+ }
-+}
-+
-+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_ts_evt_add(ts, 0, 0, 0);
-+}
-+
-+/*
-+ * User space driver interface.
-+ */
-+static ssize_t
-+ucb1x00_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct ucb1x00_ts *ts = filp->private_data;
-+ char *ptr = buffer;
-+ int err = 0;
-+
-+ add_wait_queue(&ts->read_wait, &wait);
-+ while (count >= sizeof(struct ts_event)) {
-+ err = -ERESTARTSYS;
-+ if (signal_pending(current))
-+ break;
-+
-+ if (ucb1x00_ts_evt_pending(ts)) {
-+ struct ts_event *evt = ucb1x00_ts_evt_get(ts);
-+
-+ err = copy_to_user(ptr, evt, sizeof(struct ts_event));
-+ ucb1x00_ts_evt_pull(ts);
-+
-+ if (err)
-+ break;
-+
-+ ptr += sizeof(struct ts_event);
-+ count -= sizeof(struct ts_event);
-+ continue;
-+ }
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ err = -EAGAIN;
-+ if (filp->f_flags & O_NONBLOCK)
-+ break;
-+ schedule();
-+ }
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&ts->read_wait, &wait);
-+
-+ return ptr == buffer ? err : ptr - buffer;
-+}
-+
-+static unsigned int ucb1x00_ts_poll(struct file *filp, poll_table *wait)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+ int ret = 0;
-+
-+ poll_wait(filp, &ts->read_wait, wait);
-+ if (ucb1x00_ts_evt_pending(ts))
-+ ret = POLLIN | POLLRDNORM;
-+
-+ return ret;
-+}
-+
-+static int ucb1x00_ts_fasync(int fd, struct file *filp, int on)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+
-+ return fasync_helper(fd, filp, on, &ts->fasync);
-+}
-+
-+static int ucb1x00_ts_open(struct inode *inode, struct file *filp)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+ int ret = 0;
-+
-+ ret = ucb1x00_ts_startup(ts);
-+ if (ret == 0)
-+ filp->private_data = ts;
-+
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static int ucb1x00_ts_release(struct inode *inode, struct file *filp)
-+{
-+ struct ucb1x00_ts *ts = filp->private_data;
-+
-+ down(&ts->sem);
-+ ucb1x00_ts_fasync(-1, filp, 0);
-+ ucb1x00_ts_shutdown(ts);
-+ up(&ts->sem);
-+
-+ return 0;
-+}
-+
-+static struct file_operations ucb1x00_fops = {
-+ owner: THIS_MODULE,
-+ read: ucb1x00_ts_read,
-+ poll: ucb1x00_ts_poll,
-+ open: ucb1x00_ts_open,
-+ release: ucb1x00_ts_release,
-+ fasync: ucb1x00_ts_fasync,
-+};
-+
-+/*
-+ * The official UCB1x00 touchscreen is a miscdevice:
-+ * 10 char Non-serial mice, misc features
-+ * 14 = /dev/touchscreen/ucb1x00 UCB 1x00 touchscreen
-+ */
-+static struct miscdevice ucb1x00_ts_dev = {
-+ minor: 14,
-+ name: "touchscreen/ucb1x00",
-+ fops: &ucb1x00_fops,
-+};
-+
-+static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
-+{
-+ init_waitqueue_head(&ts->read_wait);
-+ return misc_register(&ucb1x00_ts_dev);
-+}
-+
-+static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
-+{
-+ misc_deregister(&ucb1x00_ts_dev);
-+}
-+
-+#else
-+
-+#define ucb1x00_ts_evt_clear(ts) do { } while (0)
-+
-+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
-+{
-+ input_report_abs(&ts->idev, ABS_X, x);
-+ input_report_abs(&ts->idev, ABS_Y, y);
-+ input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
-+}
-+
-+static int ucb1x00_ts_open(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-+
-+ return ucb1x00_ts_startup(ts);
-+}
-+
-+static void ucb1x00_ts_close(struct input_dev *idev)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
-+
-+ down(&ts->sem);
-+ ucb1x00_ts_shutdown(ts);
-+ up(&ts->sem);
-+}
-+
-+static inline int ucb1x00_ts_register(struct ucb1x00_ts *ts)
-+{
-+ ts->idev.name = "Touchscreen panel";
-+ ts->idev.idproduct = ts->ucb->id;
-+ ts->idev.open = ucb1x00_ts_open;
-+ ts->idev.close = ucb1x00_ts_close;
-+
-+ __set_bit(EV_ABS, ts->idev.evbit);
-+ __set_bit(ABS_X, ts->idev.absbit);
-+ __set_bit(ABS_Y, ts->idev.absbit);
-+ __set_bit(ABS_PRESSURE, ts->idev.absbit);
-+
-+ input_register_device(&ts->idev);
-+
-+ return 0;
-+}
-+
-+static inline void ucb1x00_ts_deregister(struct ucb1x00_ts *ts)
-+{
-+ input_unregister_device(&ts->idev);
-+}
-+
-+#endif
-+
-+/*
-+ * Switch to interrupt mode.
-+ */
-+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_INT);
-+}
-+
-+/*
-+ * Switch to pressure mode, and read pressure. We don't need to wait
-+ * here, since both plates are being driven.
-+ */
-+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to X position mode and measure Y plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y position mode and measure X plate. We switch the plate
-+ * configuration in pressure mode, then switch to position mode. This
-+ * gives a faster response time. Even so, we need to wait about 55us
-+ * for things to stabilise.
-+ */
-+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
-+
-+ udelay(55);
-+
-+ return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to X plate resistance mode. Set MX to ground, PX to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+/*
-+ * Switch to Y plate resistance mode. Set MY to ground, PY to
-+ * supply. Measure current.
-+ */
-+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
-+{
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
-+ UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
-+ UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
-+ return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
-+}
-+
-+/*
-+ * This is a RT kernel thread that handles the ADC accesses
-+ * (mainly so we can use semaphores in the UCB1200 core code
-+ * to serialise accesses to the ADC).
-+ */
-+static int ucb1x00_thread(void *_ts)
-+{
-+ struct ucb1x00_ts *ts = _ts;
-+ struct task_struct *tsk = current;
-+ DECLARE_WAITQUEUE(wait, tsk);
-+ int valid;
-+
-+ ts->rtask = tsk;
-+
-+ daemonize();
-+ reparent_to_init();
-+ strcpy(tsk->comm, "ktsd");
-+ tsk->tty = NULL;
-+ /*
-+ * We could run as a real-time thread. However, thus far
-+ * this doesn't seem to be necessary.
-+ */
-+// tsk->policy = SCHED_FIFO;
-+// tsk->rt_priority = 1;
-+
-+ /* only want to receive SIGKILL */
-+ spin_lock_irq(&tsk->sigmask_lock);
-+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-+ recalc_sigpending(tsk);
-+ spin_unlock_irq(&tsk->sigmask_lock);
-+
-+ complete(&ts->init_exit);
-+
-+ valid = 0;
-+
-+ add_wait_queue(&ts->irq_wait, &wait);
-+ for (;;) {
-+ unsigned int x, y, p, val;
-+ signed long timeout;
-+
-+ ts->restart = 0;
-+
-+ ucb1x00_adc_enable(ts->ucb);
-+
-+ x = ucb1x00_ts_read_xpos(ts);
-+ y = ucb1x00_ts_read_ypos(ts);
-+ p = ucb1x00_ts_read_pressure(ts);
-+
-+ /*
-+ * Switch back to interrupt mode.
-+ */
-+ ucb1x00_ts_mode_int(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ / 100);
-+ if (signal_pending(tsk))
-+ break;
-+
-+ ucb1x00_enable(ts->ucb);
-+ val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
-+
-+ if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+
-+ ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * If we spat out a valid sample set last time,
-+ * spit out a "pen off" sample here.
-+ */
-+ if (valid) {
-+ ucb1x00_ts_event_release(ts);
-+ valid = 0;
-+ }
-+
-+ timeout = MAX_SCHEDULE_TIMEOUT;
-+ } else {
-+ ucb1x00_disable(ts->ucb);
-+
-+ /*
-+ * Filtering is policy. Policy belongs in user
-+ * space. We therefore leave it to user space
-+ * to do any filtering they please.
-+ */
-+ if (!ts->restart) {
-+ ucb1x00_ts_evt_add(ts, p, x, y);
-+ valid = 1;
-+ }
-+
-+ set_task_state(tsk, TASK_INTERRUPTIBLE);
-+ timeout = HZ / 100;
-+ }
-+
-+ schedule_timeout(timeout);
-+ if (signal_pending(tsk))
-+ break;
-+ }
-+
-+ remove_wait_queue(&ts->irq_wait, &wait);
-+
-+ ts->rtask = NULL;
-+ ucb1x00_ts_evt_clear(ts);
-+ complete_and_exit(&ts->init_exit, 0);
-+}
-+
-+/*
-+ * We only detect touch screen _touches_ with this interrupt
-+ * handler, and even then we just schedule our task.
-+ */
-+static void ucb1x00_ts_irq(int idx, void *id)
-+{
-+ struct ucb1x00_ts *ts = id;
-+ ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
-+ wake_up(&ts->irq_wait);
-+}
-+
-+static int ucb1x00_ts_startup(struct ucb1x00_ts *ts)
-+{
-+ int ret = 0;
-+
-+ if (down_interruptible(&ts->sem))
-+ return -EINTR;
-+
-+ if (ts->use_count++ != 0)
-+ goto out;
-+
-+ if (ts->rtask)
-+ panic("ucb1x00: rtask running?");
-+
-+ init_waitqueue_head(&ts->irq_wait);
-+ ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
-+ if (ret < 0)
-+ goto out;
-+
-+ /*
-+ * If we do this at all, we should allow the user to
-+ * measure and read the X and Y resistance at any time.
-+ */
-+ ucb1x00_adc_enable(ts->ucb);
-+ ts->x_res = ucb1x00_ts_read_xres(ts);
-+ ts->y_res = ucb1x00_ts_read_yres(ts);
-+ ucb1x00_adc_disable(ts->ucb);
-+
-+ init_completion(&ts->init_exit);
-+ ret = kernel_thread(ucb1x00_thread, ts, 0);
-+ if (ret >= 0) {
-+ wait_for_completion(&ts->init_exit);
-+ ret = 0;
-+ } else {
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ }
-+
-+ out:
-+ if (ret)
-+ ts->use_count--;
-+ up(&ts->sem);
-+ return ret;
-+}
-+
-+/*
-+ * Release touchscreen resources. Disable IRQs.
-+ */
-+static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts)
-+{
-+ if (--ts->use_count == 0) {
-+ if (ts->rtask) {
-+ send_sig(SIGKILL, ts->rtask, 1);
-+ wait_for_completion(&ts->init_exit);
-+ }
-+
-+ ucb1x00_enable(ts->ucb);
-+ ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
-+ ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
-+ ucb1x00_disable(ts->ucb);
-+ }
-+}
-+
-+#ifdef CONFIG_PM
-+static int ucb1x00_ts_pm (struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct ucb1x00_ts *ts = (struct ucb1x00_ts *) (dev->data);
-+
-+ if (rqst == PM_RESUME && ts->rtask != NULL) {
-+ /*
-+ * Restart the TS thread to ensure the
-+ * TS interrupt mode is set up again
-+ * after sleep.
-+ */
-+ ts->restart = 1;
-+ wake_up(&ts->irq_wait);
-+ }
-+ return 0;
-+}
-+#endif
-+
-+
-+/*
-+ * Initialisation.
-+ */
-+static int __init ucb1x00_ts_init(void)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+
-+ ts->ucb = ucb1x00_get();
-+ if (!ts->ucb)
-+ return -ENODEV;
-+
-+ ts->adcsync = adcsync;
-+ init_MUTEX(&ts->sem);
-+
-+#ifdef CONFIG_PM
-+ ts->pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ucb1x00_ts_pm);
-+ if (ts->pmdev == NULL)
-+ printk("ucb1x00_ts: unable to register in PM.\n");
-+ else
-+ ts->pmdev->data = ts;
-+#endif
-+ return ucb1x00_ts_register(ts);
-+}
-+
-+static void __exit ucb1x00_ts_exit(void)
-+{
-+ struct ucb1x00_ts *ts = &ucbts;
-+
-+ ucb1x00_ts_deregister(ts);
-+
-+#ifdef CONFIG_PM
-+ if (ts->pmdev)
-+ pm_unregister(ts->pmdev);
-+#endif
-+}
-+
-+#ifndef MODULE
-+
-+/*
-+ * Parse kernel command-line options.
-+ *
-+ * syntax : ucbts=[sync|nosync],...
-+ */
-+static int __init ucb1x00_ts_setup(char *str)
-+{
-+ char *p;
-+
-+ while ((p = strsep(&str, ",")) != NULL) {
-+ if (strcmp(p, "sync") == 0)
-+ adcsync = UCB_SYNC;
-+ }
-+
-+ return 1;
-+}
-+
-+__setup("ucbts=", ucb1x00_ts_setup);
-+
-+#else
-+
-+MODULE_PARM(adcsync, "i");
-+MODULE_PARM_DESC(adcsync, "Enable use of ADCSYNC signal");
-+
-+#endif
-+
-+module_init(ucb1x00_ts_init);
-+module_exit(ucb1x00_ts_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/misc/ucb1x00.h
-@@ -0,0 +1,232 @@
-+/*
-+ * linux/drivers/misc/ucb1x00.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ */
-+#ifndef UCB1200_H
-+#define UCB1200_H
-+
-+#define UCB_IO_DATA 0x00
-+#define UCB_IO_DIR 0x01
-+
-+#define UCB_IO_0 (1 << 0)
-+#define UCB_IO_1 (1 << 1)
-+#define UCB_IO_2 (1 << 2)
-+#define UCB_IO_3 (1 << 3)
-+#define UCB_IO_4 (1 << 4)
-+#define UCB_IO_5 (1 << 5)
-+#define UCB_IO_6 (1 << 6)
-+#define UCB_IO_7 (1 << 7)
-+#define UCB_IO_8 (1 << 8)
-+#define UCB_IO_9 (1 << 9)
-+
-+#define UCB_IE_RIS 0x02
-+#define UCB_IE_FAL 0x03
-+#define UCB_IE_STATUS 0x04
-+#define UCB_IE_CLEAR 0x04
-+#define UCB_IE_ADC (1 << 11)
-+#define UCB_IE_TSPX (1 << 12)
-+#define UCB_IE_TSMX (1 << 13)
-+#define UCB_IE_TCLIP (1 << 14)
-+#define UCB_IE_ACLIP (1 << 15)
-+
-+#define UCB_IRQ_TSPX 12
-+
-+#define UCB_TC_A 0x05
-+#define UCB_TC_A_LOOP (1 << 7) /* UCB1200 */
-+#define UCB_TC_A_AMPL (1 << 7) /* UCB1300 */
-+
-+#define UCB_TC_B 0x06
-+#define UCB_TC_B_VOICE_ENA (1 << 3)
-+#define UCB_TC_B_CLIP (1 << 4)
-+#define UCB_TC_B_ATT (1 << 6)
-+#define UCB_TC_B_SIDE_ENA (1 << 11)
-+#define UCB_TC_B_MUTE (1 << 13)
-+#define UCB_TC_B_IN_ENA (1 << 14)
-+#define UCB_TC_B_OUT_ENA (1 << 15)
-+
-+#define UCB_AC_A 0x07
-+#define UCB_AC_B 0x08
-+#define UCB_AC_B_LOOP (1 << 8)
-+#define UCB_AC_B_MUTE (1 << 13)
-+#define UCB_AC_B_IN_ENA (1 << 14)
-+#define UCB_AC_B_OUT_ENA (1 << 15)
-+
-+#define UCB_TS_CR 0x09
-+#define UCB_TS_CR_TSMX_POW (1 << 0)
-+#define UCB_TS_CR_TSPX_POW (1 << 1)
-+#define UCB_TS_CR_TSMY_POW (1 << 2)
-+#define UCB_TS_CR_TSPY_POW (1 << 3)
-+#define UCB_TS_CR_TSMX_GND (1 << 4)
-+#define UCB_TS_CR_TSPX_GND (1 << 5)
-+#define UCB_TS_CR_TSMY_GND (1 << 6)
-+#define UCB_TS_CR_TSPY_GND (1 << 7)
-+#define UCB_TS_CR_MODE_INT (0 << 8)
-+#define UCB_TS_CR_MODE_PRES (1 << 8)
-+#define UCB_TS_CR_MODE_POS (2 << 8)
-+#define UCB_TS_CR_BIAS_ENA (1 << 11)
-+#define UCB_TS_CR_TSPX_LOW (1 << 12)
-+#define UCB_TS_CR_TSMX_LOW (1 << 13)
-+
-+#define UCB_ADC_CR 0x0a
-+#define UCB_ADC_SYNC_ENA (1 << 0)
-+#define UCB_ADC_VREFBYP_CON (1 << 1)
-+#define UCB_ADC_INP_TSPX (0 << 2)
-+#define UCB_ADC_INP_TSMX (1 << 2)
-+#define UCB_ADC_INP_TSPY (2 << 2)
-+#define UCB_ADC_INP_TSMY (3 << 2)
-+#define UCB_ADC_INP_AD0 (4 << 2)
-+#define UCB_ADC_INP_AD1 (5 << 2)
-+#define UCB_ADC_INP_AD2 (6 << 2)
-+#define UCB_ADC_INP_AD3 (7 << 2)
-+#define UCB_ADC_EXT_REF (1 << 5)
-+#define UCB_ADC_START (1 << 7)
-+#define UCB_ADC_ENA (1 << 15)
-+
-+#define UCB_ADC_DATA 0x0b
-+#define UCB_ADC_DAT_VAL (1 << 15)
-+#define UCB_ADC_DAT(x) (((x) & 0x7fe0) >> 5)
-+
-+#define UCB_ID 0x0c
-+#define UCB_ID_1200 0x1004
-+#define UCB_ID_1300 0x1005
-+
-+#define UCB_MODE 0x0d
-+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
-+#define UCB_MODE_AUD_OFF_CAN (1 << 13)
-+
-+#include "mcp.h"
-+
-+struct ucb1x00;
-+
-+struct ucb1x00_irq {
-+ void *devid;
-+ void (*fn)(int, void *);
-+};
-+
-+struct ucb1x00 {
-+ spinlock_t lock;
-+ struct mcp *mcp;
-+ struct pm_dev *pmdev;
-+ unsigned int irq;
-+ struct semaphore adc_sem;
-+ spinlock_t io_lock;
-+ u16 id;
-+ u16 io_dir;
-+ u16 io_out;
-+ u16 adc_cr;
-+ u16 irq_fal_enbl;
-+ u16 irq_ris_enbl;
-+ struct ucb1x00_irq irq_handler[16];
-+};
-+
-+/**
-+ * ucb1x00_clkrate - return the UCB1x00 SIB clock rate
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Return the SIB clock rate in Hz.
-+ */
-+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
-+{
-+ return mcp_get_sclk_rate(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_enable - enable the UCB1x00 SIB clock
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Enable the SIB clock. This can be called multiple times.
-+ */
-+static inline void ucb1x00_enable(struct ucb1x00 *ucb)
-+{
-+ mcp_enable(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_disable - disable the UCB1x00 SIB clock
-+ * @ucb: UCB1x00 structure describing chip
-+ *
-+ * Disable the SIB clock. The SIB clock will only be disabled
-+ * when the number of ucb1x00_enable calls match the number of
-+ * ucb1x00_disable calls.
-+ */
-+static inline void ucb1x00_disable(struct ucb1x00 *ucb)
-+{
-+ mcp_disable(ucb->mcp);
-+}
-+
-+/**
-+ * ucb1x00_reg_write - write a UCB1x00 register
-+ * @ucb: UCB1x00 structure describing chip
-+ * @reg: UCB1x00 4-bit register index to write
-+ * @val: UCB1x00 16-bit value to write
-+ *
-+ * Write the UCB1x00 register @reg with value @val. The SIB
-+ * clock must be running for this function to return.
-+ */
-+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
-+{
-+ mcp_reg_write(ucb->mcp, reg, val);
-+}
-+
-+/**
-+ * ucb1x00_reg_read - read a UCB1x00 register
-+ * @ucb: UCB1x00 structure describing chip
-+ * @reg: UCB1x00 4-bit register index to write
-+ *
-+ * Read the UCB1x00 register @reg and return its value. The SIB
-+ * clock must be running for this function to return.
-+ */
-+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
-+{
-+ return mcp_reg_read(ucb->mcp, reg);
-+}
-+/**
-+ * ucb1x00_set_audio_divisor -
-+ * @ucb: UCB1x00 structure describing chip
-+ * @div: SIB clock divisor
-+ */
-+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
-+{
-+ mcp_set_audio_divisor(ucb->mcp, div);
-+}
-+
-+/**
-+ * ucb1x00_set_telecom_divisor -
-+ * @ucb: UCB1x00 structure describing chip
-+ * @div: SIB clock divisor
-+ */
-+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
-+{
-+ mcp_set_telecom_divisor(ucb->mcp, div);
-+}
-+
-+struct ucb1x00 *ucb1x00_get(void);
-+
-+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
-+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
-+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
-+
-+#define UCB_NOSYNC (0)
-+#define UCB_SYNC (1)
-+
-+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
-+void ucb1x00_adc_enable(struct ucb1x00 *ucb);
-+void ucb1x00_adc_disable(struct ucb1x00 *ucb);
-+
-+/*
-+ * Which edges of the IRQ do you want to control today?
-+ */
-+#define UCB_RISING (1 << 0)
-+#define UCB_FALLING (1 << 1)
-+
-+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
-+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
-+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
-+
-+#endif
---- linux-2.4.27/drivers/mtd/chips/cfi_probe.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/chips/cfi_probe.c
-@@ -65,6 +65,10 @@
- return 0;
- }
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-+
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
- cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
- if (!qry_present(map,base,cfi))
-@@ -84,6 +88,8 @@
- /* Eep. This chip also had the QRY marker.
- * Is it an alias for the new one? */
- cfi_send_gen_cmd(0xF0, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, chips[i].start, map, cfi, cfi->device_type, NULL);
-
- /* If the QRY marker goes away, it's an alias */
- if (!qry_present(map, chips[i].start, cfi)) {
-@@ -96,7 +102,8 @@
- * too and if it's the same, assume it's an alias. */
- /* FIXME: Use other modes to do a proper check */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
--
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
- if (qry_present(map, base, cfi)) {
- printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
- map->name, base, chips[i].start);
-@@ -119,6 +126,10 @@
- /* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
-+
- printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit mode\n",
- map->name, cfi->interleave, cfi->device_type*8, base,
- map->buswidth*8);
-@@ -165,6 +176,20 @@
- cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
- cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
-
-+ /*
-+ * ST screwed up the CFI interface for buffer writes on their parts,
-+ * so this needs to be fixed up by hand here.
-+ *
-+ * A possible enhancment is that instead of just reverting back
-+ * to word write (as this does), we could use the ST specific double
-+ * word write instead.
-+ */
-+
-+ if (cfi_read_query(map,base) == 0x20){
-+ cfi->cfiq->BufWriteTimeoutTyp = 0;
-+ cfi->cfiq->BufWriteTimeoutMax = 0;
-+ }
-+
- #ifdef DEBUG_CFI
- /* Dump the information therein */
- print_cfi_ident(cfi->cfiq);
-@@ -182,6 +207,9 @@
- /* Put it back into Read Mode */
- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-
-+ /* some devices don't respond to 0xF0, so send 0xFF to be sure */
-+ cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-+
- return 1;
- }
-
---- linux-2.4.27/drivers/mtd/chips/jedec_probe.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/chips/jedec_probe.c
-@@ -100,6 +100,8 @@
- #define M29W040B 0x00E3
-
- /* SST */
-+#define SST29EE020 0x0010
-+#define SST29LE020 0x0012
- #define SST29EE512 0x005d
- #define SST29LE512 0x003d
- #define SST39LF800 0x2781
-@@ -839,6 +841,24 @@
- }
- }, {
- mfr_id: MANUFACTURER_SST,
-+ dev_id: SST29EE020,
-+ name: "SST 29EE020",
-+ DevSize: SIZE_256KiB,
-+ CmdSet: P_ID_SST_PAGE,
-+ NumEraseRegions: 1,
-+ regions: {ERASEINFO(0x01000,64),
-+ }
-+ }, {
-+ mfr_id: MANUFACTURER_SST,
-+ dev_id: SST29LE020,
-+ name: "SST 29LE020",
-+ DevSize: SIZE_256KiB,
-+ CmdSet: P_ID_SST_PAGE,
-+ NumEraseRegions: 1,
-+ regions: {ERASEINFO(0x01000,64),
-+ }
-+ }, {
-+ mfr_id: MANUFACTURER_SST,
- dev_id: SST39LF020,
- name: "SST 39LF020",
- DevSize: SIZE_256KiB,
-@@ -937,7 +957,20 @@
- struct cfi_private *cfi)
- {
- /* Reset */
-- cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-+
-+ /* after checking the datasheets for SST, MACRONIX and ATMEL
-+ * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
-+ * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
-+ * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
-+ * as they will ignore the writes and dont care what address
-+ * the F0 is written to */
-+ if(cfi->addr_unlock1) {
-+ /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
-+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-+ }
-+
-+ cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
- /* Some misdesigned intel chips do not respond for 0xF0 for a reset,
- * so ensure we're in read mode. Send both the Intel and the AMD command
- * for this. Intel uses 0xff for this, AMD uses 0xff for NOP, so
---- linux-2.4.27/drivers/mtd/devices/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/devices/Config.in
-@@ -17,6 +17,15 @@
- if [ "$CONFIG_SA1100_LART" = "y" ]; then
- dep_tristate ' 28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD
- fi
-+if [ "$CONFIG_ARCH_MX1ADS" = "y" ]; then
-+ dep_tristate ' SyncFlash driver for MX1ADS' CONFIG_MTD_SYNCFLASH $CONFIG_MTD
-+fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ dep_tristate ' AT91RM9200 DataFlash support' CONFIG_MTD_AT91_DATAFLASH $CONFIG_MTD
-+ if [ "$CONFIG_MTD_AT91_DATAFLASH" = "y" -o "$CONFIG_MTD_AT91_DATAFLASH" = "m" ]; then
-+ bool ' Enable DataFlash card? ' CONFIG_MTD_AT91_DATAFLASH_CARD
-+ fi
-+fi
- dep_tristate ' Test driver using RAM' CONFIG_MTD_MTDRAM $CONFIG_MTD
- if [ "$CONFIG_MTD_MTDRAM" = "y" -o "$CONFIG_MTD_MTDRAM" = "m" ]; then
- int 'MTDRAM device size in KiB' CONFIG_MTDRAM_TOTAL_SIZE 4096
---- linux-2.4.27/drivers/mtd/devices/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/devices/Makefile
-@@ -21,6 +21,7 @@
- obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
- obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
- obj-$(CONFIG_MTD_LART) += lart.o
-+obj-$(CONFIG_MTD_SYNCFLASH) += syncflash.o
- obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
-
- include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/devices/syncflash.c
-@@ -0,0 +1,615 @@
-+/*
-+ * MTD driver for Micron SyncFlash flash memory.
-+ *
-+ * Author: Jon McClintock <jonm@bluemug.com>
-+ *
-+ * Based loosely upon the LART flash driver, authored by Abraham vd Merwe
-+ * <abraham@2d3d.co.za>.
-+ *
-+ * Copyright 2003, Blue Mug, Inc. for Motorola, Inc.
-+ *
-+ * This code is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * References:
-+ *
-+ * [1] Micron SyncFlash homepage
-+ * - http://www.syncflash.com/
-+ *
-+ * [2] MT28S4M16LC -- 4Mx16 SyncFlash memory datasheet
-+ * - http://syncflash.com/pdfs/datasheets/mt28s4m16lc_6.pdf
-+ *
-+ * [3] MTD internal API documentation
-+ * - http://www.linux-mtd.infradead.org/tech/
-+ *
-+ * Limitations:
-+ *
-+ * Even though this driver is written for Micron SyncFlash, it is quite
-+ * specific to the Motorola MX1 ADS development board.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/version.h>
-+#include <linux/errno.h>
-+#include <linux/mtd/mtd.h>
-+#include <asm/io.h>
-+
-+/* partition support */
-+#define HAVE_PARTITIONS
-+#ifdef HAVE_PARTITIONS
-+#include <linux/mtd/partitions.h>
-+#endif
-+
-+#ifndef CONFIG_ARCH_MX1ADS
-+#error The SyncFlash driver currently only supports the MX1 ADS platform.
-+#endif
-+
-+/*
-+ * General flash configuration parameters.
-+ */
-+#define BUSWIDTH 4
-+#define FLASH_BLOCKSIZE (256 * 1024 * BUSWIDTH)
-+#define FLASH_NUMBLOCKS 16
-+
-+#define BUSWIDTH 4
-+#define FLASH_ADDRESS IO_ADDRESS(MX1ADS_FLASH_BASE)
-+
-+#define FLASH_MANUFACTURER 0x002C002C
-+#define FLASH_DEVICE_ID 0x00D300D3
-+
-+/*
-+ * The size and extent of the bootloader in flash.
-+ */
-+#define NUM_BOOTLOADER_BLOCKS 1
-+#define BOOTLOADER_START 0x00000000
-+#define BOOTLOADER_LEN (NUM_BOOTLOADER_BLOCKS * FLASH_BLOCKSIZE)
-+
-+/*
-+ * The size and extent of the kernel in flash.
-+ */
-+#define NUM_KERNEL_BLOCKS 1
-+#define KERNEL_START (BOOTLOADER_START + BOOTLOADER_LEN)
-+#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE)
-+
-+/* File system */
-+#define NUM_FILESYSTEM_BLOCKS 14
-+#define FILESYSTEM_START (KERNEL_START + KERNEL_LEN)
-+#define FILESYSTEM_LEN (NUM_FILESYSTEM_BLOCKS * FLASH_BLOCKSIZE)
-+
-+
-+/*
-+ * SDRAM controller register location and values. These are very specific
-+ * to the MX1.
-+ */
-+#define SDRAMC_REGISTER IO_ADDRESS(0x00221004)
-+
-+/*
-+ * This the mask we use to get the start of a block from a given address.
-+ */
-+#define BLOCK_MASK (0xFFF00000)
-+
-+/*
-+ * This is the A10 address line of the SyncFlash; it's used to initiate
-+ * a precharge command.
-+ */
-+#define SYNCFLASH_A10 (0x00100000)
-+
-+/*
-+ * SDRAM controller MODE settings.
-+ */
-+#define CMD_NORMAL (0x81020300) /* Normal Mode */
-+#define CMD_PREC (CMD_NORMAL + 0x10000000) /* Precharge command */
-+#define CMD_AUTO (CMD_NORMAL + 0x20000000) /* Auto refresh */
-+#define CMD_LMR (CMD_NORMAL + 0x30000000) /* Load Mode Register */
-+#define CMD_LCR (CMD_NORMAL + 0x60000000) /* LCR Command */
-+#define CMD_PROGRAM (CMD_NORMAL + 0x70000000) /* SyncFlash Program */
-+
-+/*
-+ * SyncFlash LCR Commands adjusted for the DBMX1 AHB internal address bus .
-+ */
-+#define LCR_READ_STATUS (0x0001C000) /* 0x70 */
-+#define LCR_READ_CONFIG (0x00024000) /* 0x90 */
-+#define LCR_ERASE_CONFIRM (0x00008000) /* 0x20 */
-+#define LCR_ERASE_NVMODE (0x0000C000) /* 0x30 */
-+#define LCR_PROG_NVMODE (0x00028000) /* 0xA0 */
-+#define LCR_SR_CLEAR (0x00014000) /* 0x50 */
-+
-+/*
-+ * Status register bits
-+ */
-+#define SR_VPS_ERROR (1 << 8) /* Power-Up status error */
-+#define SR_ISM_READY (1 << 7) /* State machine isn't busy */
-+#define SR_ERASE_ERROR (1 << 5) /* Erase/Unprotect error */
-+#define SR_PROGRAM_ERROR (1 << 4) /* Program/Protect error */
-+#define SR_DEVICE_PROTECTED (1 << 3) /* Device is protected */
-+#define SR_ISM_STATUS_H (1 << 2) /* Bank ISM status, high bit */
-+#define SR_ISM_STATUS_L (1 << 1) /* Bank ISM status, low bit */
-+#define SR_DEVICE_ISM_STATUS (1 << 0) /* ISM is device-level */
-+
-+#define SR_ERROR (SR_VPS_ERROR|SR_ERASE_ERROR|SR_PROGRAM_ERROR|SR_DEVICE_PROTECTED)
-+
-+#define STATUS_VALUE(a) ((a) | ((a) << 16))
-+
-+/*
-+ * Device configuration register offsets
-+ */
-+#define DC_MANUFACTURER (0 * BUSWIDTH)
-+#define DC_DEVICE_ID (1 * BUSWIDTH)
-+#define DC_BLOCK_PROTECT (2 * BUSWIDTH)
-+#define DC_DEVICE_PROTECT (3 * BUSWIDTH)
-+
-+#define FL_WORD(addr) (*(volatile unsigned long*)(addr))
-+
-+static char module_name[] = "syncflash";
-+
-+inline __u8 read8 (__u32 offset)
-+{
-+ return *(volatile __u8 *) (FLASH_ADDRESS + offset);
-+}
-+
-+inline __u32 read32 (__u32 offset)
-+{
-+ return *(volatile __u32 *) (FLASH_ADDRESS + offset);
-+}
-+
-+inline void write32 (__u32 x,__u32 offset)
-+{
-+ *(volatile __u32 *) (FLASH_ADDRESS + offset) = x;
-+}
-+
-+static __u32 read_device_configuration_register(__u32 reg_number)
-+{
-+ __u32 tmp;
-+
-+ /* Setup the SDRAM controller to issue an LCR command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+
-+ /* Perform a read to issue the Read Device Configuration Command. */
-+ tmp = read32(LCR_READ_CONFIG);
-+
-+ /* Return the SDRAM controller to normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+
-+ /* Return the value of the specified register. */
-+ tmp = read32(reg_number);
-+
-+ return tmp;
-+}
-+
-+/*
-+ * Get the status of the flash devices.
-+ */
-+static __u32 flash_read_status()
-+{
-+ __u32 status, tmp;
-+
-+ /* Enter the SyncFlash Program READ/WRITE mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
-+
-+ /* Read the status register. */
-+ status = read32(LCR_READ_STATUS);
-+
-+ /* Clear the status register. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+ tmp = read32(LCR_SR_CLEAR);
-+
-+ /* Return to Normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+
-+ return status;
-+}
-+
-+/*
-+ * Loop until both write state machines are ready.
-+ */
-+static __u32 flash_status_wait()
-+{
-+ __u32 status;
-+ do {
-+ status = flash_read_status();
-+ } while ((status & STATUS_VALUE(SR_ISM_READY)) !=
-+ STATUS_VALUE(SR_ISM_READY));
-+ return status;
-+}
-+
-+/*
-+ * Loop until the Write State machine is ready, then do a full error
-+ * check. Clear status and leave the flash in Read Array mode; return
-+ * 0 for no error, -1 for error.
-+ */
-+static int flash_status_full_check()
-+{
-+ __u32 status;
-+
-+ status = flash_status_wait() & STATUS_VALUE(SR_ERROR);
-+ return status ? -EIO : 0;
-+}
-+
-+/*
-+ * Return the flash to the normal mode.
-+ */
-+static void flash_normal_mode()
-+{
-+ __u32 tmp;
-+
-+ /* First issue a precharge all command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(SYNCFLASH_A10);
-+
-+ /* Now place the SDRAM controller in Normal mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+}
-+
-+/*
-+ * Probe for SyncFlash memory on MX1ADS board.
-+ *
-+ * Returns 1 if we found SyncFlash memory, 0 otherwise.
-+ */
-+static int flash_probe (void)
-+{
-+ __u32 manufacturer, device_id;
-+
-+ /* For some reason, the first read doesn't work, so we do it
-+ * twice. */
-+ manufacturer = read_device_configuration_register(DC_MANUFACTURER);
-+ manufacturer = read_device_configuration_register(DC_MANUFACTURER);
-+ device_id = read_device_configuration_register(DC_DEVICE_ID);
-+
-+ printk("SyncFlash probe: manufacturer 0x%08lx, device_id 0x%08lx\n",
-+ manufacturer, device_id);
-+ return (manufacturer == FLASH_MANUFACTURER &&
-+ device_id == FLASH_DEVICE_ID);
-+}
-+
-+/*
-+ * Erase one block of flash memory at offset ``offset'' which is any
-+ * address within the block which should be erased.
-+ *
-+ * Returns 0 if successful, -1 otherwise.
-+ */
-+static inline int erase_block (__u32 offset)
-+{
-+ __u32 tmp;
-+
-+ /* Mask off the lower bits of the address to get the first address
-+ * in the flash block. */
-+ offset &= (__u32)BLOCK_MASK;
-+
-+ /* Perform a read and precharge of the bank before the LCR|ACT|WRIT
-+ * sequence to avoid the inadvertent precharge command occurring
-+ * during the LCR_ACT_WRIT sequence. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+ tmp = read32(offset);
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(offset);
-+
-+ /* Now start the actual erase. */
-+
-+ /* LCR|ACT|WRIT sequence */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_LCR;
-+ write32(0, offset + LCR_ERASE_CONFIRM);
-+
-+ /* Return to normal mode to issue the erase confirm. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_NORMAL;
-+ write32(0xD0D0D0D0, offset);
-+
-+ if (flash_status_full_check()) {
-+ printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",
-+ module_name, offset);
-+ return (-1);
-+ }
-+
-+ flash_normal_mode();
-+
-+ return 0;
-+}
-+
-+static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
-+{
-+ __u32 addr,len;
-+ int i,first;
-+
-+ /* sanity checks */
-+ if (instr->addr + instr->len > mtd->size) return (-EINVAL);
-+
-+ /*
-+ * check that both start and end of the requested erase are
-+ * aligned with the erasesize at the appropriate addresses.
-+ *
-+ * skip all erase regions which are ended before the start of
-+ * the requested erase. Actually, to save on the calculations,
-+ * we skip to the first erase region which starts after the
-+ * start of the requested erase, and then go back one.
-+ */
-+ for (i = 0; (i < mtd->numeraseregions) &&
-+ (instr->addr >= mtd->eraseregions[i].offset); i++) ;
-+ i--;
-+
-+ /*
-+ * ok, now i is pointing at the erase region in which this
-+ * erase request starts. Check the start of the requested
-+ * erase range is aligned with the erase size which is in
-+ * effect here.
-+ */
-+ if (instr->addr & (mtd->eraseregions[i].erasesize - 1))
-+ return (-EINVAL);
-+
-+ /* Remember the erase region we start on */
-+ first = i;
-+
-+ /*
-+ * next, check that the end of the requested erase is aligned
-+ * with the erase region at that address.
-+ *
-+ * as before, drop back one to point at the region in which
-+ * the address actually falls
-+ */
-+ for (;
-+ (i < mtd->numeraseregions) &&
-+ ((instr->addr + instr->len) >= mtd->eraseregions[i].offset) ;
-+ i++) ;
-+ i--;
-+
-+ /* is the end aligned on a block boundary? */
-+ if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1))
-+ return (-EINVAL);
-+
-+ addr = instr->addr;
-+ len = instr->len;
-+
-+ i = first;
-+
-+ /* now erase those blocks */
-+ while (len)
-+ {
-+ if (erase_block (addr))
-+ {
-+ instr->state = MTD_ERASE_FAILED;
-+ return (-EIO);
-+ }
-+
-+ addr += mtd->eraseregions[i].erasesize;
-+ len -= mtd->eraseregions[i].erasesize;
-+
-+ if (addr == (mtd->eraseregions[i].offset +
-+ (mtd->eraseregions[i].erasesize *
-+ mtd->eraseregions[i].numblocks)))
-+ i++;
-+ }
-+
-+ instr->state = MTD_ERASE_DONE;
-+ if (instr->callback) instr->callback (instr);
-+
-+ return (0);
-+}
-+
-+static int flash_read (struct mtd_info *mtd, loff_t from,
-+ size_t len, size_t *retlen, u_char *buf)
-+{
-+ /* Sanity checks. */
-+ if (!len) return (0);
-+ if (from + len > mtd->size) return (-EINVAL);
-+
-+ /* Ensure that we are in normal mode. */
-+ flash_normal_mode();
-+
-+ /* We always read len bytes. */
-+ *retlen = len;
-+
-+ /* first, we read bytes until we reach a dword boundary */
-+ if (from & (BUSWIDTH - 1))
-+ {
-+ int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
-+ while (len && gap--) *buf++ = read8(from++), len--;
-+ }
-+
-+ /* now we read dwords until we reach a non-dword boundary */
-+ while (len >= BUSWIDTH)
-+ {
-+ *((__u32 *) buf) = read32(from);
-+
-+ buf += BUSWIDTH;
-+ from += BUSWIDTH;
-+ len -= BUSWIDTH;
-+ }
-+
-+ /* top up the last unaligned bytes */
-+ if (len & (BUSWIDTH - 1))
-+ while (len--) *buf++ = read8(from++);
-+
-+ return (0);
-+}
-+
-+/*
-+ * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
-+ * must be 32 bits, i.e. it must be on a dword boundary.
-+ *
-+ * Returns 0 if successful, -1 otherwise.
-+ */
-+static int flash_write_dword(__u32 offset, __u32 x)
-+{
-+ __u32 tmp;
-+
-+ /* First issue a precharge all command. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PREC;
-+ tmp = read32(SYNCFLASH_A10);
-+
-+ /* Enter the SyncFlash programming mode. */
-+ FL_WORD(SDRAMC_REGISTER) = CMD_PROGRAM;
-+ write32(x, offset);
-+
-+ /* Wait for the write to complete. */
-+ flash_status_wait();
-+
-+ /* Return to normal mode. */
-+ flash_normal_mode();
-+
-+ return 0;
-+}
-+
-+static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
-+{
-+ __u8 tmp[4];
-+ int i,n;
-+
-+ *retlen = 0;
-+
-+ /* Sanity checks */
-+ if (!len) return (0);
-+ if (to + len > mtd->size) return (-EINVAL);
-+
-+ /* First, we write a 0xFF.... padded byte until we reach a
-+ * dword boundary. */
-+ if (to & (BUSWIDTH - 1))
-+ {
-+ __u32 aligned = to & ~(BUSWIDTH - 1);
-+ int gap = to - aligned;
-+
-+ i = n = 0;
-+
-+ while (gap--) tmp[i++] = 0xFF;
-+ while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
-+ while (i < BUSWIDTH) tmp[i++] = 0xFF;
-+
-+ if (flash_write_dword(aligned, *((__u32 *) tmp)))
-+ return (-EIO);
-+
-+ to += n;
-+ buf += n;
-+ *retlen += n;
-+ }
-+
-+ /* Now we write dwords until we reach a non-dword boundary. */
-+ while (len >= BUSWIDTH)
-+ {
-+ if (flash_write_dword (to,*((__u32 *) buf))) return (-EIO);
-+
-+ to += BUSWIDTH;
-+ buf += BUSWIDTH;
-+ *retlen += BUSWIDTH;
-+ len -= BUSWIDTH;
-+ }
-+
-+ /* Top up the last unaligned bytes, padded with 0xFF.... */
-+ if (len & (BUSWIDTH - 1))
-+ {
-+ i = n = 0;
-+
-+ while (len--) tmp[i++] = buf[n++];
-+ while (i < BUSWIDTH) tmp[i++] = 0xFF;
-+
-+ if (flash_write_dword (to,*((__u32 *) tmp))) return (-EIO);
-+
-+ *retlen += n;
-+ }
-+
-+ return flash_status_full_check();
-+}
-+
-+
-+
-+#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
-+
-+static struct mtd_info mtd;
-+
-+static struct mtd_erase_region_info erase_regions[] =
-+{
-+ /* flash blocks */
-+ {
-+ offset: 0x00000000,
-+ erasesize: FLASH_BLOCKSIZE,
-+ numblocks: FLASH_NUMBLOCKS
-+ },
-+};
-+
-+#ifdef HAVE_PARTITIONS
-+static struct mtd_partition syncflash_partitions[] =
-+{
-+ /* bootloader */
-+ {
-+ name: "bootloader",
-+ offset: BOOTLOADER_START,
-+ size: BOOTLOADER_LEN,
-+ mask_flags: 0
-+ },
-+ /* Kernel */
-+ {
-+ name: "kernel",
-+ offset: KERNEL_START, /* MTDPART_OFS_APPEND */
-+ size: KERNEL_LEN,
-+ mask_flags: 0
-+ },
-+ /* file system */
-+ {
-+ name: "file system",
-+ offset: FILESYSTEM_START, /* MTDPART_OFS_APPEND */
-+ size: FILESYSTEM_LEN, /* MTDPART_SIZ_FULL */
-+ mask_flags: 0
-+ }
-+};
-+#endif
-+
-+int __init syncflash_init (void)
-+{
-+ int result;
-+
-+ memset (&mtd,0,sizeof (mtd));
-+
-+ printk ("MTD driver for Micron SyncFlash.\n");
-+ printk ("%s: Probing for SyncFlash on MX1ADS...\n",module_name);
-+
-+ if (!flash_probe ())
-+ {
-+ printk (KERN_WARNING "%s: Found no SyncFlash devices\n",
-+ module_name);
-+ return (-ENXIO);
-+ }
-+
-+ printk ("%s: Found a SyncFlash device.\n",module_name);
-+
-+ mtd.name = module_name;
-+ mtd.type = MTD_NORFLASH;
-+ mtd.flags = MTD_CAP_NORFLASH;
-+ mtd.size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS;
-+
-+ mtd.erasesize = FLASH_BLOCKSIZE;
-+ mtd.numeraseregions = NB_OF(erase_regions);
-+ mtd.eraseregions = erase_regions;
-+
-+ mtd.module = THIS_MODULE;
-+
-+ mtd.erase = flash_erase;
-+ mtd.read = flash_read;
-+ mtd.write = flash_write;
-+
-+#ifndef HAVE_PARTITIONS
-+ result = add_mtd_device(&mtd);
-+#else
-+ result = add_mtd_partitions(&mtd,
-+ syncflash_partitions,
-+ NB_OF(syncflash_partitions));
-+#endif
-+
-+ return (result);
-+}
-+
-+void __exit syncflash_exit (void)
-+{
-+#ifndef HAVE_PARTITIONS
-+ del_mtd_device (&mtd);
-+#else
-+ del_mtd_partitions (&mtd);
-+#endif
-+}
-+
-+module_init (syncflash_init);
-+module_exit (syncflash_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
-+MODULE_DESCRIPTION("MTD driver for Micron MT28S4M16LC SyncFlash on MX1ADS board");
-+
-+
---- linux-2.4.27/drivers/mtd/maps/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/maps/Config.in
-@@ -81,10 +81,10 @@
- dep_tristate ' CFI Flash device mapped on StrongARM SA11x0' CONFIG_MTD_SA1100 $CONFIG_MTD_CFI $CONFIG_ARCH_SA1100 $CONFIG_MTD_PARTITIONS
- dep_tristate ' CFI Flash device mapped on DC21285 Footbridge' CONFIG_MTD_DC21285 $CONFIG_MTD_CFI $CONFIG_ARCH_FOOTBRIDGE
- dep_tristate ' CFI Flash device mapped on the XScale IQ80310 board' CONFIG_MTD_IQ80310 $CONFIG_MTD_CFI $CONFIG_ARCH_IQ80310
-- dep_tristate ' CFI Flash device mapped on Epxa10db' CONFIG_MTD_EPXA10DB $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
-- dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_SA1100_FORTUNET
-+ dep_tristate ' CFI Flash device mapped on the FortuNet board' CONFIG_MTD_FORTUNET $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_FORTUNET
-+ dep_tristate ' CFI Flash device mapped on Epxa' CONFIG_MTD_EPXA $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS $CONFIG_ARCH_CAMELOT
- dep_tristate ' NV-RAM mapping AUTCPU12 board' CONFIG_MTD_AUTCPU12 $CONFIG_ARCH_AUTCPU12
-- dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_MTD_CFI
-+ dep_tristate ' CFI Flash device mapped on EDB7312' CONFIG_MTD_EDB7312 $CONFIG_ARCH_EDB7212 $CONFIG_MTD_CFI
- dep_tristate ' JEDEC Flash device mapped on impA7' CONFIG_MTD_IMPA7 $CONFIG_MTD_JEDECPROBE
- dep_tristate ' JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame' CONFIG_MTD_CEIVA $CONFIG_MTD_JEDECPROBE $CONFIG_ARCH_CEIVA
- fi
---- linux-2.4.27/drivers/mtd/maps/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/maps/Makefile
-@@ -3,11 +3,7 @@
- #
- # $Id: Makefile,v 1.37 2003/01/24 14:26:38 dwmw2 Exp $
-
--BELOW25 := $(shell echo $(PATCHLEVEL) | sed s/[1234]/y/)
--
--ifeq ($(BELOW25),y)
- O_TARGET := mapslink.o
--endif
-
- # Chip mappings
- obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
-@@ -17,7 +13,7 @@
- obj-$(CONFIG_MTD_DC21285) += dc21285.o
- obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
- obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
--obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
-+obj-$(CONFIG_MTD_EPXA) += epxa-flash.o
- obj-$(CONFIG_MTD_IQ80310) += iq80310.o
- obj-$(CONFIG_MTD_L440GX) += l440gx.o
- obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
-@@ -29,9 +25,9 @@
- obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
- ifneq ($(CONFIG_MTD_PHYSMAP),n)
- ifeq ($(CONFIG_MTD_PHYSMAP_BUSWIDTH),8)
-- obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
-+ obj-$(CONFIG_MTD_PHYSMAP) += physmap64.o
- else
-- obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
-+ obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
- endif
- endif
- obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
-@@ -39,6 +35,9 @@
- obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
- obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
- obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
-+ifeq ($(CONFIG_ASSABET_NEPONSET),y)
-+ obj-$(CONFIG_MTD_SA1100) += neponset-flash.o
-+endif
- obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
- obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
- obj-$(CONFIG_MTD_NETSC520) += netsc520.o
---- linux-2.4.27/drivers/mtd/maps/dc21285.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/maps/dc21285.c
-@@ -11,6 +11,7 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
-+#include <linux/delay.h>
-
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/map.h>
-@@ -18,9 +19,9 @@
-
- #include <asm/io.h>
- #include <asm/hardware/dec21285.h>
-+#include <asm/mach-types.h>
-
--
--static struct mtd_info *mymtd;
-+static struct mtd_info *dc21285_mtd;
-
- __u8 dc21285_read8(struct map_info *map, unsigned long ofs)
- {
-@@ -44,6 +45,9 @@
-
- void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr)
- {
-+ if(machine_is_netwinder()) {
-+ nw_en_write();
-+ }
- *CSR_ROMWRITEREG = adr & 3;
- adr &= ~3;
- *(__u8*)(map->map_priv_1 + adr) = d;
-@@ -51,6 +55,9 @@
-
- void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr)
- {
-+ if(machine_is_netwinder()) {
-+ nw_en_write();
-+ }
- *CSR_ROMWRITEREG = adr & 3;
- adr &= ~3;
- *(__u16*)(map->map_priv_1 + adr) = d;
-@@ -58,6 +65,9 @@
-
- void dc21285_write32(struct map_info *map, __u32 d, unsigned long adr)
- {
-+ if(machine_is_netwinder()) {
-+ nw_en_write();
-+ }
- *(__u32*)(map->map_priv_1 + adr) = d;
- }
-
-@@ -105,6 +115,27 @@
- };
-
-
-+static void
-+nw_en_write(void) {
-+#ifdef CONFIG_ARCH_NETWINDER
-+ extern spinlock_t gpio_lock;
-+ unsigned long flags;
-+
-+ /*
-+ * we want to write a bit pattern XXX1 to Xilinx to enable
-+ * the write gate, which will be open for about the next 2ms.
-+ */
-+ spin_lock_irqsave(&gpio_lock, flags);
-+ cpld_modify(1, 1);
-+ spin_unlock_irqrestore(&gpio_lock, flags);
-+
-+ /*
-+ * let the ISA bus to catch on...
-+ */
-+ udelay(25);
-+#endif
-+}
-+
- /* Partition stuff */
- static struct mtd_partition *dc21285_parts;
-
-@@ -112,6 +143,9 @@
-
- int __init init_dc21285(void)
- {
-+ int nr_parts = 0;
-+ char *part_type = "none";
-+
- /* Determine buswidth */
- switch (*CSR_SA110_CNTL & (3<<14)) {
- case SA110_CNTL_ROMWIDTH_8:
-@@ -137,24 +171,64 @@
- return -EIO;
- }
-
-- mymtd = do_map_probe("cfi_probe", &dc21285_map);
-- if (mymtd) {
-- int nrparts = 0;
-+ if(machine_is_ebsa285()) {
-+ dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
-+ } else {
-+ dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
-+ }
-
-- mymtd->module = THIS_MODULE;
-+ if (!dc21285_mtd) {
-+ /* no recognised device so unmap and exit */
-+ iounmap((void *)dc21285_map.map_priv_1);
-+ return -ENXIO;
-+ }
-
-- /* partition fixup */
-+ dc21285_mtd->module = THIS_MODULE;
-
-+ /*
-+ * Dynamic partition selection stuff (might override the static ones)
-+ */
- #ifdef CONFIG_MTD_REDBOOT_PARTS
-- nrparts = parse_redboot_partitions(mymtd, &dc21285_parts);
-+ if (nr_parts == 0) {
-+ int ret = parse_redboot_partitions(dc21285_mtd, &dc21285_parts);
-+
-+ if (ret > 0) {
-+ part_type = "RedBoot";
-+ nr_parts = ret;
-+ }
-+ else
-+ {
-+ dc21285_parts=NULL; /* ensure partition table remains clear */
-+ }
-+ }
- #endif
-- if (nrparts > 0) {
-- add_mtd_partitions(mymtd, dc21285_parts, nrparts);
-- } else if (nrparts == 0) {
-- printk(KERN_NOTICE "RedBoot partition table failed\n");
-- add_mtd_device(mymtd);
-+#ifdef CONFIG_MTD_CMDLINE_PARTS
-+ if (nr_parts == 0) {
-+ int ret = parse_cmdline_partitions(dc21285_mtd, &dc21285_parts, "sa1100");
-+ if (ret > 0) {
-+ part_type = "Command Line";
-+ nr_parts = ret;
-+ }
-+ else
-+ {
-+ dc21285_parts=NULL; /* ensure partition table remains clear */
- }
-+ }
-+#endif
-+
-+ if (nr_parts == 0) {
-+ printk(KERN_NOTICE "DC21285 Flash: no partition info available, registering whole flash at once\n");
-+ add_mtd_device(dc21285_mtd);
-+ }
-+#ifdef CONFIG_MTD_PARTITIONS
-+ else
-+ {
-+ printk(KERN_NOTICE "DC21285 Flash: Using %s partition definition\n", part_type);
-+ add_mtd_partitions(dc21285_mtd, &dc21285_parts, nr_parts);
-+ }
-+#endif
-
-+ if(machine_is_ebsa285()) {
- /*
- * Flash timing is determined with bits 19-16 of the
- * CSR_SA110_CNTL. The value is the number of wait cycles, or
-@@ -167,20 +241,15 @@
- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
- /* tristate time */
- *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
--
-- return 0;
- }
--
-- iounmap((void *)dc21285_map.map_priv_1);
-- return -ENXIO;
- }
-
- static void __exit cleanup_dc21285(void)
- {
-- if (mymtd) {
-- del_mtd_device(mymtd);
-- map_destroy(mymtd);
-- mymtd = NULL;
-+ if (dc21285_mtd) {
-+ del_mtd_device(dc21285_mtd);
-+ map_destroy(dc21285_mtd);
-+ dc21285_mtd = NULL;
- }
- if (dc21285_map.map_priv_1) {
- iounmap((void *)dc21285_map.map_priv_1);
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/maps/epxa-flash.c
-@@ -0,0 +1,234 @@
-+/*
-+ * Flash memory access on EPXA based devices
-+ *
-+ * (C) 2000 Nicolas Pitre <nico@cam.org>
-+ * Copyright (C) 2001 Altera Corporation
-+ * Copyright (C) 2001 Red Hat, Inc.
-+ *
-+ * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#ifdef CONFIG_EPXA10DB
-+#define BOARD_NAME "EPXA10DB"
-+#else
-+#define BOARD_NAME "EPXA1DB"
-+#endif
-+
-+static int nr_parts = 0;
-+static struct mtd_partition *parts;
-+
-+static struct mtd_info *mymtd;
-+
-+extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
-+static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
-+{
-+ return __raw_readl(map->map_priv_1 + ofs);
-+}
-+
-+static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + from, len);
-+}
-+
-+static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ __raw_writeb(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ __raw_writew(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ __raw_writel(d, map->map_priv_1 + adr);
-+ mb();
-+}
-+
-+static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy_toio(map->map_priv_1 + to, from, len);
-+}
-+
-+static struct map_info epxa_map = {
-+ .name = "EPXA flash",
-+ .size = FLASH_SIZE,
-+ .buswidth = 2,
-+ .read8 = epxa_read8,
-+ .read16 = epxa_read16,
-+ .read32 = epxa_read32,
-+ .copy_from = epxa_copy_from,
-+ .write8 = epxa_write8,
-+ .write16 = epxa_write16,
-+ .write32 = epxa_write32,
-+ .copy_to = epxa_copy_to
-+};
-+
-+static int __init epxa_mtd_init(void)
-+{
-+ int i;
-+
-+ printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-+ epxa_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_START, FLASH_SIZE);
-+ if (!epxa_map.map_priv_1) {
-+ printk("Failed to ioremap %s flash\n",BOARD_NAME);
-+ return -EIO;
-+ }
-+
-+ mymtd = do_map_probe("cfi_probe", &epxa_map);
-+ if (!mymtd) {
-+ iounmap((void *)epxa_map.map_priv_1);
-+ return -ENXIO;
-+ }
-+
-+ mymtd->module = THIS_MODULE;
-+
-+ /* Unlock the flash device. */
-+ if(mymtd->unlock){
-+ for (i=0; i<mymtd->numeraseregions;i++){
-+ int j;
-+ for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
-+ mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
-+ }
-+ }
-+ }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+ nr_parts = parse_redboot_partitions(mymtd, &parts);
-+
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+#endif
-+#ifdef CONFIG_MTD_AFS_PARTS
-+ nr_parts = parse_afs_partitions(mymtd, &parts);
-+
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+#endif
-+
-+ /* No recognised partitioning schemes found - use defaults */
-+ nr_parts = epxa_default_partitions(mymtd, &parts);
-+ if (nr_parts > 0) {
-+ add_mtd_partitions(mymtd, parts, nr_parts);
-+ return 0;
-+ }
-+
-+ /* If all else fails... */
-+ add_mtd_device(mymtd);
-+ return 0;
-+}
-+
-+static void __exit epxa_mtd_cleanup(void)
-+{
-+ if (mymtd) {
-+ if (nr_parts)
-+ del_mtd_partitions(mymtd);
-+ else
-+ del_mtd_device(mymtd);
-+ map_destroy(mymtd);
-+ }
-+ if (epxa_map.map_priv_1) {
-+ iounmap((void *)epxa_map.map_priv_1);
-+ epxa_map.map_priv_1 = 0;
-+ }
-+}
-+
-+
-+/*
-+ * This will do for now, once we decide which bootldr we're finally
-+ * going to use then we'll remove this function and do it properly
-+ *
-+ * Partions are currently (as offsets from base of flash):
-+ * 0x00000000 - 0x003FFFFF - bootloader (!)
-+ * 0x00400000 - 0x00FFFFFF - Flashdisk
-+ */
-+
-+static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
-+{
-+ struct mtd_partition *parts;
-+ int ret;
-+ int npartitions = 0;
-+ char *names;
-+ const char *name = "jffs";
-+
-+ printk("Using default partitions for %s\n",BOARD_NAME);
-+ npartitions=1;
-+ parts = kmalloc(npartitions*sizeof(*parts)+strlen(name)+1, GFP_KERNEL);
-+ if (!parts) {
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ memzero(parts,npartitions*sizeof(*parts)+strlen(name));
-+
-+ names = (char *)&parts[npartitions];
-+ parts[0].name = names;
-+ names += strlen(name) + 1;
-+ strcpy(parts[0].name, name);
-+
-+#ifdef CONFIG_EPXA10DB_R2
-+ parts[0].size = FLASH_SIZE-0x00400000;
-+ parts[0].offset = 0x00400000;
-+#elif defined CONFIG_EPXA10DB_R3
-+ parts[0].size = 0x00800000;
-+ parts[0].offset = 0x00800000;
-+#else
-+ parts[0].size = FLASH_SIZE-0x00180000;
-+ parts[0].offset = 0x00180000;
-+#endif
-+ ret = npartitions;
-+
-+ out:
-+ *pparts = parts;
-+ return ret;
-+}
-+
-+
-+module_init(epxa_mtd_init);
-+module_exit(epxa_mtd_cleanup);
-+
-+MODULE_AUTHOR("Clive Davies");
-+MODULE_DESCRIPTION("Altera epxa mtd flash map");
-+MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/mtd/maps/epxa10db-flash.c
-+++ /dev/null
-@@ -1,233 +0,0 @@
--/*
-- * Flash memory access on EPXA based devices
-- *
-- * (C) 2000 Nicolas Pitre <nico@cam.org>
-- * Copyright (C) 2001 Altera Corporation
-- * Copyright (C) 2001 Red Hat, Inc.
-- *
-- * $Id: epxa10db-flash.c,v 1.4 2002/08/22 10:46:19 cdavies Exp $
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--
--#include <linux/config.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/kernel.h>
--#include <asm/io.h>
--#include <linux/mtd/mtd.h>
--#include <linux/mtd/map.h>
--#include <linux/mtd/partitions.h>
--
--#include <asm/hardware.h>
--#ifdef CONFIG_EPXA10DB
--#define BOARD_NAME "EPXA10DB"
--#else
--#define BOARD_NAME "EPXA1DB"
--#endif
--
--static int nr_parts = 0;
--static struct mtd_partition *parts;
--
--static struct mtd_info *mymtd;
--
--extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
--static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
--
--static __u8 epxa_read8(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readb(map->map_priv_1 + ofs);
--}
--
--static __u16 epxa_read16(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readw(map->map_priv_1 + ofs);
--}
--
--static __u32 epxa_read32(struct map_info *map, unsigned long ofs)
--{
-- return __raw_readl(map->map_priv_1 + ofs);
--}
--
--static void epxa_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
--{
-- memcpy_fromio(to, (void *)(map->map_priv_1 + from), len);
--}
--
--static void epxa_write8(struct map_info *map, __u8 d, unsigned long adr)
--{
-- __raw_writeb(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_write16(struct map_info *map, __u16 d, unsigned long adr)
--{
-- __raw_writew(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_write32(struct map_info *map, __u32 d, unsigned long adr)
--{
-- __raw_writel(d, map->map_priv_1 + adr);
-- mb();
--}
--
--static void epxa_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
--{
-- memcpy_toio((void *)(map->map_priv_1 + to), from, len);
--}
--
--
--
--static struct map_info epxa_map = {
-- name: "EPXA flash",
-- size: FLASH_SIZE,
-- buswidth: 2,
-- read8: epxa_read8,
-- read16: epxa_read16,
-- read32: epxa_read32,
-- copy_from: epxa_copy_from,
-- write8: epxa_write8,
-- write16: epxa_write16,
-- write32: epxa_write32,
-- copy_to: epxa_copy_to
--};
--
--
--static int __init epxa_mtd_init(void)
--{
-- int i;
--
-- printk(KERN_NOTICE "%s flash device: %x at %x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-- epxa_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
-- if (!epxa_map.map_priv_1) {
-- printk("Failed to ioremap %s flash\n",BOARD_NAME);
-- return -EIO;
-- }
--
-- mymtd = do_map_probe("cfi_probe", &epxa_map);
-- if (!mymtd) {
-- iounmap((void *)epxa_map.map_priv_1);
-- return -ENXIO;
-- }
--
-- mymtd->module = THIS_MODULE;
--
-- /* Unlock the flash device. */
-- if(mymtd->unlock){
-- for (i=0; i<mymtd->numeraseregions;i++){
-- int j;
-- for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
-- mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
-- }
-- }
-- }
--
--#ifdef CONFIG_MTD_REDBOOT_PARTS
-- nr_parts = parse_redboot_partitions(mymtd, &parts);
--
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--#endif
--#ifdef CONFIG_MTD_AFS_PARTS
-- nr_parts = parse_afs_partitions(mymtd, &parts);
--
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--#endif
--
-- /* No recognised partitioning schemes found - use defaults */
-- nr_parts = epxa_default_partitions(mymtd, &parts);
-- if (nr_parts > 0) {
-- add_mtd_partitions(mymtd, parts, nr_parts);
-- return 0;
-- }
--
-- /* If all else fails... */
-- add_mtd_device(mymtd);
-- return 0;
--}
--
--static void __exit epxa_mtd_cleanup(void)
--{
-- if (mymtd) {
-- if (nr_parts)
-- del_mtd_partitions(mymtd);
-- else
-- del_mtd_device(mymtd);
-- map_destroy(mymtd);
-- }
-- if (epxa_map.map_priv_1) {
-- iounmap((void *)epxa_map.map_priv_1);
-- epxa_map.map_priv_1 = 0;
-- }
--}
--
--
--/*
-- * This will do for now, once we decide which bootldr we're finally
-- * going to use then we'll remove this function and do it properly
-- *
-- * Partions are currently (as offsets from base of flash):
-- * 0x00000000 - 0x003FFFFF - bootloader (!)
-- * 0x00400000 - 0x00FFFFFF - Flashdisk
-- */
--
--static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
--{
-- struct mtd_partition *parts;
-- int ret, i;
-- int npartitions = 0;
-- char *names;
-- const char *name = "jffs";
--
-- printk("Using default partitions for %s\n",BOARD_NAME);
-- npartitions=1;
-- parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
-- memzero(parts,npartitions*sizeof(*parts)+strlen(name));
-- if (!parts) {
-- ret = -ENOMEM;
-- goto out;
-- }
-- i=0;
-- names = (char *)&parts[npartitions];
-- parts[i].name = names;
-- names += strlen(name) + 1;
-- strcpy(parts[i].name, name);
--
--#ifdef CONFIG_EPXA10DB
-- parts[i].size = FLASH_SIZE-0x00400000;
-- parts[i].offset = 0x00400000;
--#else
-- parts[i].size = FLASH_SIZE-0x00180000;
-- parts[i].offset = 0x00180000;
--#endif
--
-- out:
-- *pparts = parts;
-- return npartitions;
--}
--
--
--module_init(epxa_mtd_init);
--module_exit(epxa_mtd_cleanup);
--
--MODULE_AUTHOR("Clive Davies");
--MODULE_DESCRIPTION("Altera epxa mtd flash map");
--MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/mtd/maps/neponset-flash.c
-@@ -0,0 +1,109 @@
-+/*
-+ * Flash memory access on SA11x0 based devices
-+ *
-+ * (C) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * $Id: neponset-flash.c,v 1.18 2001/07/14 00:59:17 thockin Exp $
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/arch/assabet.h>
-+
-+static __u8 read8(struct map_info *map, unsigned long ofs)
-+{
-+ return readb(map->map_priv_1 + ofs);
-+}
-+
-+static __u16 read16(struct map_info *map, unsigned long ofs)
-+{
-+ return readw(map->map_priv_1 + ofs);
-+}
-+
-+static __u32 read32(struct map_info *map, unsigned long ofs)
-+{
-+ return readl(map->map_priv_1 + ofs);
-+}
-+
-+static void copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-+{
-+ memcpy_fromio(to, map->map_priv_1 + from, len);
-+}
-+
-+static void write8(struct map_info *map, __u8 d, unsigned long adr)
-+{
-+ writeb(d, map->map_priv_1 + adr);
-+}
-+
-+static void write16(struct map_info *map, __u16 d, unsigned long adr)
-+{
-+ writew(d, map->map_priv_1 + adr);
-+}
-+
-+static void write32(struct map_info *map, __u32 d, unsigned long adr)
-+{
-+ writel(d, map->map_priv_1 + adr);
-+}
-+
-+static void copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-+{
-+ memcpy_toio(map->map_priv_1 + to, from, len);
-+}
-+
-+#define MAX_SZ (32 * 1024 * 1024)
-+
-+static struct map_info neponset_map = {
-+ name: "Neponset",
-+ size: MAX_SZ,
-+ buswidth: 4,
-+ read8: read8,
-+ read16: read16,
-+ read32: read32,
-+ copy_from: copy_from,
-+ write8: write8,
-+ write16: write16,
-+ write32: write32,
-+ copy_to: copy_to,
-+};
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+static struct mtd_info *neponset_mtd;
-+
-+int __init neponset_mtd_init(void)
-+{
-+ if (!machine_is_assabet() || !machine_has_neponset())
-+ return -ENODEV;
-+
-+ neponset_map.map_priv_1 = (unsigned int)ioremap(0x08000000, MAX_SZ);
-+ if (!neponset_map.map_priv_1)
-+ return -ENOMEM;
-+
-+ neponset_mtd = do_map_probe("cfi_probe", &neponset_map);
-+ if (!neponset_mtd)
-+ return -ENXIO;
-+ neponset_mtd->module = THIS_MODULE;
-+ add_mtd_device(neponset_mtd);
-+ return 0;
-+}
-+
-+static void __exit neponset_mtd_cleanup(void)
-+{
-+ if (neponset_mtd)
-+ map_destroy(neponset_mtd);
-+ if (neponset_map.map_priv_1)
-+ iounmap((void *)neponset_map.map_priv_1);
-+}
-+
-+module_init(neponset_mtd_init);
-+module_exit(neponset_mtd_cleanup);
---- linux-2.4.27/drivers/mtd/maps/sa1100-flash.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/maps/sa1100-flash.c
-@@ -97,6 +97,32 @@
- * entries. Thanks.
- */
-
-+#ifdef CONFIG_SA1100_ADSAGC
-+#define ADSAGC_FLASH_SIZE 0x02000000
-+static struct mtd_partition adsagc_partitions[] = {
-+ {
-+ name: "bootROM",
-+ size: 0x80000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "zImage",
-+ size: 0x100000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "ramdisk.gz",
-+ size: 0x300000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "User FS",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_ADSBITSY
- #define ADSBITSY_FLASH_SIZE 0x02000000
- static struct mtd_partition adsbitsy_partitions[] = {
-@@ -123,6 +149,32 @@
- };
- #endif
-
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+#define ADSBITSYPLUS_FLASH_SIZE 0x02000000
-+static struct mtd_partition adsbitsyplus_partitions[] = {
-+ {
-+ name: "bootROM",
-+ size: 0x80000,
-+ offset: 0,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "zImage",
-+ size: 0x100000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "ramdisk.gz",
-+ size: 0x300000,
-+ offset: MTDPART_OFS_APPEND,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "User FS",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_ASSABET
- /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
- #define ASSABET4_FLASH_SIZE 0x00400000
-@@ -438,7 +490,7 @@
- #endif
-
- #ifdef CONFIG_SA1100_GRAPHICSMASTER
--#define GRAPHICSMASTER_FLASH_SIZE 0x01000000
-+#define GRAPHICSMASTER_FLASH_SIZE 0x02000000
- static struct mtd_partition graphicsmaster_partitions[] = {
- {
- name: "zImage",
-@@ -507,6 +559,38 @@
- }
- #endif
-
-+#ifdef CONFIG_SA1100_HACKKIT
-+#define HACKKIT_FLASH_SIZE 0x01000000
-+static struct mtd_partition hackkit_partitions[] = {
-+ {
-+ name: "BLOB",
-+ size: 0x00040000,
-+ offset: 0x00000000,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ }, {
-+ name: "config",
-+ size: 0x00040000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "kernel",
-+ size: 0x00100000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "initrd",
-+ size: 0x00180000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "rootfs",
-+ size: 0x700000,
-+ offset: MTDPART_OFS_APPEND,
-+ }, {
-+ name: "data",
-+ size: MTDPART_SIZ_FULL,
-+ offset: MTDPART_OFS_APPEND,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- #define HUW_WEBPANEL_FLASH_SIZE 0x01000000
- static struct mtd_partition huw_webpanel_partitions[] = {
-@@ -555,12 +639,12 @@
- offset: 0x00540000,
- }, {
- name: "JORNADA720 usr local",
-- size: 0 /* will expand to the end of the flash */
-+ size: 0, /* will expand to the end of the flash */
- offset: 0x00d00000,
- }
- };
-
--static void jornada720_set_vpp(int vpp)
-+static void jornada720_set_vpp(struct map_info *map, int vpp)
- {
- if (vpp)
- PPSR |= 0x80;
-@@ -571,6 +655,27 @@
-
- #endif
-
-+#ifdef CONFIG_SA1100_NANOENGINE
-+/* nanoEngine has one 28F320B3B Flash part in bank 0: */
-+#define NANOENGINE_FLASH_SIZE 0x00400000
-+static struct mtd_partition nanoengine_partitions[] = {
-+ {
-+ name: "nanoEngine boot firmware and parameter table",
-+ size: 0x00010000, /* 32K */
-+ offset: 0x00000000,
-+ mask_flags: MTD_WRITEABLE, /* force read-only */
-+ },{
-+ name: "kernel/initrd reserved",
-+ size: 0x002f0000,
-+ offset: 0x00010000,
-+ },{
-+ name: "experimental filesystem allocation",
-+ size: 0x00100000,
-+ offset: 0x00300000,
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_PANGOLIN
- #define PANGOLIN_FLASH_SIZE 0x04000000
- static struct mtd_partition pangolin_partitions[] = {
-@@ -699,6 +804,32 @@
- };
- #endif /* CONFIG_SA1100_SIMPAD */
-
-+#ifdef CONFIG_SA1100_SIMPUTER
-+#define SIMPUTER_FLASH_SIZE 0x02000000
-+static struct mtd_partition simputer_partitions[] = {
-+ {
-+ name: "blob+logo",
-+ offset: 0,
-+ size: 0x00040000
-+ },
-+ {
-+ name: "kernel",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x000C0000
-+ },
-+ {
-+ name: "/(cramfs)",
-+ offset: MTDPART_OFS_APPEND,
-+ size: 0x00200000
-+ },
-+ {
-+ name: "/usr/local(jffs2)",
-+ offset: MTDPART_OFS_APPEND,
-+ size: MTDPART_SIZ_FULL /* expand till the end */
-+ }
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_STORK
- #define STORK_FLASH_SIZE 0x02000000
- static struct mtd_partition stork_partitions[] = {
-@@ -766,7 +897,7 @@
- #endif
-
- extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
--extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
-
- static struct mtd_partition *parsed_parts;
- static struct mtd_info *mymtd;
-@@ -787,6 +918,14 @@
- */
- part_type = "static";
-
-+#ifdef CONFIG_SA1100_ADSAGC
-+ if (machine_is_adsagc()) {
-+ parts = adsagc_partitions;
-+ nb_parts = ARRAY_SIZE(adsagc_partitions);
-+ sa1100_map.size = ADSAGC_FLASH_SIZE;
-+ sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_ADSBITSY
- if (machine_is_adsbitsy()) {
- parts = adsbitsy_partitions;
-@@ -795,6 +934,14 @@
- sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
- }
- #endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ parts = adsbitsyplus_partitions;
-+ nb_parts = ARRAY_SIZE(adsbitsyplus_partitions);
-+ sa1100_map.size = ADSBITSYPLUS_FLASH_SIZE;
-+ sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_ASSABET
- if (machine_is_assabet()) {
- parts = assabet_partitions;
-@@ -869,6 +1016,13 @@
- sa1100_map.set_vpp = h3600_set_vpp;
- }
- #endif
-+#ifdef CONFIG_SA1100_HACKKIT
-+ if (machine_is_hackkit()) {
-+ parts = hackkit_partitions;
-+ nb_parts = ARRAY_SIZE(hackkit_partitions);
-+ sa1100_map.size = HACKKIT_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- if (machine_is_huw_webpanel()) {
- parts = huw_webpanel_partitions;
-@@ -884,6 +1038,13 @@
- sa1100_map.set_vpp = jornada720_set_vpp;
- }
- #endif
-+#ifdef CONFIG_SA1100_NANOENGINE
-+ if (machine_is_nanoengine()) {
-+ parts = nanoengine_partitions;
-+ nb_parts = ARRAY_SIZE(nanoengine_partitions);
-+ sa1100_map.size = NANOENGINE_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_PANGOLIN
- if (machine_is_pangolin()) {
- parts = pangolin_partitions;
-@@ -919,6 +1080,13 @@
- sa1100_map.size = SIMPAD_FLASH_SIZE;
- }
- #endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ parts = simputer_partitions;
-+ nb_parts = ARRAY_SIZE(simputer_partitions);
-+ sa1100_map.size = SIMPUTER_FLASH_SIZE;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- parts = stork_partitions;
-@@ -953,7 +1121,9 @@
- * specific machine settings might have been set above.
- */
- printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
-- mymtd = do_map_probe("cfi_probe", &sa1100_map);
-+ mymtd = do_map_probe("jedec_probe", &sa1100_map);
-+ if (!mymtd)
-+ mymtd = do_map_probe("cfi_probe", &sa1100_map);
- ret = -ENXIO;
- if (!mymtd)
- goto out_err;
---- linux-2.4.27/drivers/mtd/nand/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/mtd/nand/Config.in
-@@ -33,4 +33,8 @@
- fi
- fi
-
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ dep_tristate ' SmartMedia Card on Atmel AT91RM9200' CONFIG_MTD_AT91_SMARTMEDIA $CONFIG_MTD_NAND
-+fi
-+
- endmenu
---- linux-2.4.27/drivers/net/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/Config.in
-@@ -30,9 +30,15 @@
- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
- source drivers/acorn/net/Config.in
- fi
-+ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate ' AT91RM9200 Ethernet support' CONFIG_AT91_ETHER
-+ if [ "$CONFIG_AT91_ETHER" = "y" -o "$CONFIG_AT91_ETHER" = "m" ]; then
-+ bool ' RMII interface? ' CONFIG_AT91_ETHER_RMII
-+ fi
-+ fi
- fi
- if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
-- tristate ' Altera Ether00 support' CONFIG_ETHER00
-+ tristate ' Altera Ether00 support' CONFIG_ETHER00
- fi
- if [ "$CONFIG_PPC" = "y" ]; then
- dep_tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE $CONFIG_ALL_PPC
---- linux-2.4.27/drivers/net/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/Makefile
-@@ -244,6 +244,7 @@
- # non-drivers/net drivers who want mii lib
- obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
- obj-$(CONFIG_USB_USBNET) += mii.o
-+obj-$(CONFIG_AT91_ETHER) += mii.o
-
- obj-$(CONFIG_IBMVETH) += ibmveth.o
-
-@@ -270,4 +271,3 @@
-
- rcpci.o: $(rcpci-objs)
- $(LD) -r -o $@ $(rcpci-objs)
--
---- linux-2.4.27/drivers/net/am79c961a.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/am79c961a.c
-@@ -54,25 +54,36 @@
- #ifdef __arm__
- static void write_rreg(u_long base, u_int reg, u_int val)
- {
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- str%?h %0, [%2, #-4] @ NET_RDP
-- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "str%?h %0, [%2, #-4] @ NET_RDP"
-+ : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
- }
-
- static inline unsigned short read_rreg(u_long base_addr, u_int reg)
- {
- unsigned short v;
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- ldr%?h %0, [%2, #-4] @ NET_RDP
-- " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "ldr%?h %0, [%2, #-4] @ NET_RDP"
-+ : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
- return v;
- }
-
- static inline void write_ireg(u_long base, u_int reg, u_int val)
- {
-- __asm__("str%?h %1, [%2] @ NET_RAP
-- str%?h %0, [%2, #8] @ NET_IDP
-- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ __asm__("str%?h %1, [%2] @ NET_RAP\n\t"
-+ "str%?h %0, [%2, #8] @ NET_IDP"
-+ : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+}
-+
-+static inline unsigned short read_ireg(u_long base_addr, u_int reg)
-+{
-+ u_short v;
-+ __asm__(
-+ "str%?h %1, [%2] @ NAT_RAP\n\t"
-+ "str%?h %0, [%2, #8] @ NET_IDP\n\t"
-+ : "=r" (v)
-+ : "r" (reg), "r" (ISAIO_BASE + 0x0464));
-+ return v;
- }
-
- #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
-@@ -91,16 +102,16 @@
- }
- while (length > 8) {
- unsigned int tmp, tmp2;
-- __asm__ __volatile__("
-- ldm%?ia %1!, {%2, %3}
-- str%?h %2, [%0], #4
-- mov%? %2, %2, lsr #16
-- str%?h %2, [%0], #4
-- str%?h %3, [%0], #4
-- mov%? %3, %3, lsr #16
-- str%?h %3, [%0], #4
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
-- : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldm%?ia %1!, {%2, %3}\n\t"
-+ "str%?h %2, [%0], #4\n\t"
-+ "mov%? %2, %2, lsr #16\n\t"
-+ "str%?h %2, [%0], #4\n\t"
-+ "str%?h %3, [%0], #4\n\t"
-+ "mov%? %3, %3, lsr #16\n\t"
-+ "str%?h %3, [%0], #4"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
-+ : "0" (offset), "1" (buf));
- length -= 8;
- }
- while (length > 0) {
-@@ -118,36 +129,36 @@
- length = (length + 1) & ~1;
- if ((int)buf & 2) {
- unsigned int tmp;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- str%?b %2, [%1], #1
-- mov%? %2, %2, lsr #8
-- str%?b %2, [%1], #1
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "str%?b %2, [%1], #1\n\t"
-+ "mov%? %2, %2, lsr #8\n\t"
-+ "str%?b %2, [%1], #1"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
- length -= 2;
- }
- while (length > 8) {
- unsigned int tmp, tmp2, tmp3;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- ldr%?h %3, [%0], #4
-- orr%? %2, %2, %3, lsl #16
-- ldr%?h %3, [%0], #4
-- ldr%?h %4, [%0], #4
-- orr%? %3, %3, %4, lsl #16
-- stm%?ia %1!, {%2, %3}
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
-- : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "ldr%?h %3, [%0], #4\n\t"
-+ "orr%? %2, %2, %3, lsl #16\n\t"
-+ "ldr%?h %3, [%0], #4\n\t"
-+ "ldr%?h %4, [%0], #4\n\t"
-+ "orr%? %3, %3, %4, lsl #16\n\t"
-+ "stm%?ia %1!, {%2, %3}"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
-+ : "0" (offset), "1" (buf));
- length -= 8;
- }
- while (length > 0) {
- unsigned int tmp;
-- __asm__ __volatile__("
-- ldr%?h %2, [%0], #4
-- str%?b %2, [%1], #1
-- mov%? %2, %2, lsr #8
-- str%?b %2, [%1], #1
-- " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
-+ __asm__ __volatile__(
-+ "ldr%?h %2, [%0], #4\n\t"
-+ "str%?b %2, [%1], #1\n\t"
-+ "mov%? %2, %2, lsr #8\n\t"
-+ "str%?b %2, [%1], #1"
-+ : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
- length -= 2;
- }
- }
-@@ -254,9 +265,27 @@
- write_rreg (dev->base_addr, BASERXH, 0);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
-+ write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
- write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
- }
-
-+static void am79c961_timer(unsigned long data)
-+{
-+ struct net_device *dev = (struct net_device *)data;
-+ struct dev_priv *priv = (struct dev_priv *)dev->priv;
-+ unsigned int lnkstat, carrier;
-+
-+ lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
-+ carrier = netif_carrier_ok(dev);
-+
-+ if (lnkstat && !carrier)
-+ netif_carrier_on(dev);
-+ else if (!lnkstat && carrier)
-+ netif_carrier_off(dev);
-+
-+ mod_timer(&priv->timer, jiffies + 5*HZ);
-+}
-+
- /*
- * Open/initialize the board.
- */
-@@ -274,6 +303,11 @@
-
- am79c961_init_for_open(dev);
-
-+ netif_carrier_off(dev);
-+
-+ priv->timer.expires = jiffies;
-+ add_timer(&priv->timer);
-+
- netif_start_queue(dev);
-
- return 0;
-@@ -288,7 +322,10 @@
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
- unsigned long flags;
-
-+ del_timer_sync(&priv->timer);
-+
- netif_stop_queue(dev);
-+ netif_carrier_off(dev);
-
- spin_lock_irqsave(priv->chip_lock, flags);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-@@ -413,15 +450,6 @@
- unsigned int hdraddr, bufaddr;
- unsigned int head;
- unsigned long flags;
--
-- /* FIXME: I thought the 79c961 could do padding - RMK ??? */
-- if(length < ETH_ZLEN)
-- {
-- skb = skb_padto(skb, ETH_ZLEN);
-- if(skb == NULL)
-- return 0;
-- length = ETH_ZLEN;
-- }
-
- head = priv->txhead;
- hdraddr = priv->txhdr + (head << 3);
-@@ -431,7 +459,7 @@
- head = 0;
-
- am_writebuffer (dev, bufaddr, skb->data, length);
-- am_writeword (dev, hdraddr + 4, -length);
-+ am_writeword (dev, hdraddr + 4, -skb->len);
- am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
- priv->txhead = head;
-
-@@ -448,6 +476,8 @@
- if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
- netif_stop_queue(dev);
-
-+ priv->stats.tx_bytes += skb->len;
-+
- dev_kfree_skb(skb);
-
- return 0;
-@@ -520,6 +550,7 @@
- am79c961_tx(struct net_device *dev, struct dev_priv *priv)
- {
- do {
-+ signed short len;
- u_int hdraddr;
- u_int status;
-
-@@ -555,6 +586,8 @@
- continue;
- }
- priv->stats.tx_packets ++;
-+ len = am_readword (dev, hdraddr + 4);
-+ priv->stats.tx_bytes += -len;
- } while (priv->txtail != priv->txhead);
-
- netif_wake_queue(dev);
-@@ -565,17 +598,23 @@
- {
- struct net_device *dev = (struct net_device *)dev_id;
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
-- u_int status;
-+ u_int status, n = 100;
-
-- status = read_rreg(dev->base_addr, CSR0);
-- write_rreg(dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
-+ do {
-+ status = read_rreg(dev->base_addr, CSR0);
-+ write_rreg(dev->base_addr, CSR0, status &
-+ (CSR0_IENA|CSR0_TINT|CSR0_RINT|
-+ CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
-
-- if (status & CSR0_RINT)
-- am79c961_rx(dev, priv);
-- if (status & CSR0_TINT)
-- am79c961_tx(dev, priv);
-- if (status & CSR0_MISS)
-- priv->stats.rx_dropped ++;
-+ if (status & CSR0_RINT)
-+ am79c961_rx(dev, priv);
-+ if (status & CSR0_TINT)
-+ am79c961_tx(dev, priv);
-+ if (status & CSR0_MISS)
-+ priv->stats.rx_dropped ++;
-+ if (status & CSR0_CERR)
-+ mod_timer(&priv->timer, jiffies);
-+ } while (--n && status & (CSR0_RINT | CSR0_TINT));
- }
-
- /*
-@@ -587,10 +626,10 @@
- {
- struct dev_priv *priv = (struct dev_priv *)dev->priv;
-
-- spin_lock_irq(priv->chip_lock);
-+ spin_lock_irq(&priv->chip_lock);
- write_rreg (dev->base_addr, CSR0, CSR0_STOP);
- write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
-- spin_unlock_irq(priv->chip_lock);
-+ spin_unlock_irq(&priv->chip_lock);
-
- am79c961_ramtest(dev, 0x66);
- am79c961_ramtest(dev, 0x99);
-@@ -655,6 +694,11 @@
- printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
- }
-
-+ spin_lock_init(&priv->chip_lock);
-+ init_timer(&priv->timer);
-+ priv->timer.data = (unsigned long)dev;
-+ priv->timer.function = am79c961_timer;
-+
- if (am79c961_hw_init(dev))
- goto release;
-
---- linux-2.4.27/drivers/net/am79c961a.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/am79c961a.h
-@@ -58,6 +58,18 @@
- #define CSR3_BABLM 0x4000
- #define CSR3_MASKALL 0x5F00
-
-+#define CSR4 4
-+#define CSR4_JABM 0x0001
-+#define CSR4_JAB 0x0002
-+#define CSR4_TXSTRTM 0x0004
-+#define CSR4_TXSTRT 0x0008
-+#define CSR4_RCVCCOM 0x0010
-+#define CSR4_RCVCCO 0x0020
-+#define CSR4_MFCOM 0x0100
-+#define CSR4_MFCO 0x0200
-+#define CSR4_ASTRP_RCV 0x0400
-+#define CSR4_APAD_XMIT 0x0800
-+
- #define CTRL1 5
- #define CTRL1_SPND 0x0001
-
-@@ -93,6 +105,8 @@
- #define SIZERXR 76
- #define SIZETXR 78
-
-+#define CSR_MFC 112
-+
- #define RMD_ENP 0x0100
- #define RMD_STP 0x0200
- #define RMD_CRC 0x0800
-@@ -112,6 +126,9 @@
- #define TST_UFLO 0x4000
- #define TST_BUFF 0x8000
-
-+#define ISALED0 0x0004
-+#define ISALED0_LNKST 0x8000
-+
- struct dev_priv {
- struct net_device_stats stats;
- unsigned long rxbuffer[RX_BUFFERS];
-@@ -123,6 +140,7 @@
- unsigned long rxhdr;
- unsigned long txhdr;
- spinlock_t chip_lock;
-+ struct timer_list timer;
- };
-
- extern int am79c961_probe (struct net_device *dev);
---- linux-2.4.27/drivers/net/cirrus.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/cirrus.c
-@@ -75,6 +75,7 @@
- typedef struct {
- struct net_device_stats stats;
- u16 txlen;
-+ u16 txafter; /* Default is After5 (0) */
- } cirrus_t;
-
- typedef struct {
-@@ -230,13 +231,19 @@
- cirrus_t *priv = (cirrus_t *) dev->priv;
- u16 status;
-
-+ /* Tx start must be done with irq disabled
-+ * else status can be wrong */
-+ disable_irq (dev->irq);
-+
- netif_stop_queue (dev);
-
-- cirrus_write (dev,PP_TxCMD,TxStart (After5));
-+ cirrus_write (dev,PP_TxCMD,TxStart (priv->txafter));
- cirrus_write (dev,PP_TxLength,skb->len);
-
- status = cirrus_read (dev,PP_BusST);
-
-+ enable_irq (dev->irq);
-+
- if ((status & TxBidErr)) {
- printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
- priv->stats.tx_errors++;
-@@ -249,7 +256,6 @@
- printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
- priv->stats.tx_errors++;
- priv->txlen = 0;
-- /* FIXME: store skb and send it in interrupt handler */
- return (1);
- }
-
-@@ -310,11 +316,18 @@
- }
- if ((RegContent (status) & TxUnderrun)) {
- priv->stats.tx_errors++;
-- priv->stats.tx_fifo_errors++;
-+ /* Shift start tx, if underruns come too often */
-+ switch (priv->stats.tx_fifo_errors++) {
-+ case 3: priv->txafter = After381; break;
-+ case 6: priv->txafter = After1021; break;
-+ case 9: priv->txafter = AfterAll; break;
-+ }
-+ }
-+ /* Wakeup only for tx events ! */
-+ if ((RegContent (status) & (TxUnderrun | Rdy4Tx))) {
-+ priv->txlen = 0;
-+ netif_wake_queue (dev);
- }
-- /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
-- priv->txlen = 0;
-- netif_wake_queue (dev);
- break;
-
- case TxCOL:
-@@ -428,7 +441,7 @@
- else
- cirrus_clear (dev,PP_RxCTL,PromiscuousA);
-
-- if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
-+ if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
- cirrus_set (dev,PP_RxCTL,MulticastA);
- else
- cirrus_clear (dev,PP_RxCTL,MulticastA);
---- linux-2.4.27/drivers/net/cs89x0.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/cs89x0.c
-@@ -115,6 +115,7 @@
-
- */
-
-+#include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/types.h>
-@@ -427,18 +428,18 @@
- /* if they give us an odd I/O address, then do ONE write to
- the address port, to get it back to address zero, where we
- expect to find the EISA signature word. An IO with a base of 0x3
-- will skip the test for the ADD_PORT. */
-+ will skip the test for the ADD_PORT. */
- if (ioaddr & 1) {
- if (net_debug > 1)
- printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
-- if ((ioaddr & 2) != 2)
-+ if ((ioaddr & 2) != 2)
- if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
- printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, inw((ioaddr & ~3)+ ADD_PORT));
- retval = -ENODEV;
- goto out2;
- }
-- ioaddr &= ~3;
-+ ioaddr &= ~3;
- outw(PP_ChipID, ioaddr + ADD_PORT);
- }
- printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
-@@ -446,7 +447,7 @@
- if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
- printk(KERN_ERR "%s: incorrect signature 0x%x\n",
- dev->name, inw(ioaddr + DATA_PORT));
-- retval = -ENODEV;
-+ retval = -ENODEV;
- goto out2;
- }
-
-@@ -477,7 +478,7 @@
- dev->base_addr);
-
- reset_chip(dev);
--
-+
- /* Here we read the current configuration of the chip. If there
- is no Extended EEPROM then the idea is to not disturb the chip
- configuration, it should have been correctly setup by automatic
---- linux-2.4.27/drivers/net/ether00.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/ether00.c
-@@ -38,6 +38,7 @@
- #include <asm/arch/ether00.h>
- #include <asm/arch/tdkphy.h>
-
-+static int ether00_get_ethernet_address(struct net_device* dev);
-
- MODULE_AUTHOR("Clive Davies");
- MODULE_DESCRIPTION("Altera Ether00 IP core driver");
-@@ -734,8 +735,11 @@
- int result,tmp;
- struct net_priv* priv;
-
-- if (!is_valid_ether_addr(dev->dev_addr))
-- return -EINVAL;
-+ if (!ether00_get_ethernet_address(dev)){
-+ printk("%s: Invalid ethernet MAC address. Please set using "
-+ "ifconfig\n", dev->name);
-+ return -EINVAL;
-+ }
-
- dev->base_addr=(unsigned int)ioremap_nocache(base,SZ_4K);
-
-@@ -906,10 +910,9 @@
- }
-
-
--static void ether00_get_ethernet_address(struct net_device* dev)
-+static int ether00_get_ethernet_address(struct net_device* dev)
- {
- struct mtd_info *mymtd=NULL;
-- int i;
- size_t retlen;
-
- /*
-@@ -926,11 +929,7 @@
- #ifdef CONFIG_ARCH_CAMELOT
- #ifdef CONFIG_MTD
- /* get the mtd_info structure for the first mtd device*/
-- for(i=0;i<MAX_MTD_DEVICES;i++){
-- mymtd=get_mtd_device(NULL,i);
-- if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
-- break;
-- }
-+ mymtd=get_mtd_device(NULL,0);
-
- if(!mymtd || !mymtd->read_user_prot_reg){
- printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
-@@ -947,9 +946,7 @@
- #endif
- #endif
-
-- if (!is_valid_ether_addr(dev->dev_addr))
-- printk("%s: Invalid ethernet MAC address. Please set using "
-- "ifconfig\n", dev->name);
-+ return (is_valid_ether_addr(dev->dev_addr));
-
- }
-
-@@ -966,8 +963,6 @@
- dev->tx_timeout=ether00_tx_timeout;
- dev->watchdog_timeo=TX_TIMEOUT;
-
-- ether00_get_ethernet_address(dev);
--
- SET_MODULE_OWNER(dev);
- return 0;
- }
---- linux-2.4.27/drivers/net/irda/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/irda/Config.in
-@@ -40,7 +40,7 @@
- dep_tristate 'VIA IrCC (Experimental)' CONFIG_VIA_IRCC_FIR $CONFIG_IRDA
- fi
- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA
-+ dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA $CONFIG_EXPERIMENTAL
- fi
-
- endmenu
---- linux-2.4.27/drivers/net/irda/sa1100_ir.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/irda/sa1100_ir.c
-@@ -38,11 +38,7 @@
-
- #include <asm/arch/assabet.h>
-
--#ifndef CONFIG_SA1100_H3600
--#define clr_h3600_egpio(x) do { } while (0)
--#define set_h3600_egpio(x) do { } while (0)
--#endif
--
-+/* Yopy wants fixing */
- #ifndef GPIO_IRDA_FIR
- #define GPIO_IRDA_FIR (0)
- #endif
-@@ -174,8 +170,8 @@
-
- if (machine_is_assabet())
- ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
-- if (machine_is_h3600())
-- clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
-+ if (machine_is_h3xxx())
-+ clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
- if (machine_is_yopy())
- PPSR &= ~GPIO_IRDA_FIR;
-
-@@ -199,8 +195,8 @@
-
- if (machine_is_assabet())
- ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
-- if (machine_is_h3600())
-- set_h3600_egpio(EGPIO_H3600_IR_FSEL);
-+ if (machine_is_h3xxx())
-+ set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
- if (machine_is_yopy())
- PPSR |= GPIO_IRDA_FIR;
-
-@@ -246,10 +242,7 @@
- static inline int
- sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state)
- {
-- if (state)
-- set_h3600_egpio(EGPIO_H3600_IR_ON);
-- else
-- clr_h3600_egpio(EGPIO_H3600_IR_ON);
-+ assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
- return 0;
- }
-
-@@ -283,7 +276,7 @@
-
- if (machine_is_assabet())
- ret = sa1100_irda_set_power_assabet(si, state);
-- if (machine_is_h3600())
-+ if (machine_is_h3xxx())
- ret = sa1100_irda_set_power_h3600(si, state);
- if (machine_is_yopy())
- ret = sa1100_irda_set_power_yopy(si, state);
-@@ -727,11 +720,6 @@
- netif_wake_queue(dev);
- }
-
--/*
-- * Note that we will never build up a backlog of frames; the protocol is a
-- * half duplex protocol which basically means we transmit a frame, we
-- * receive a frame, we transmit the next frame etc.
-- */
- static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- struct sa1100_irda *si = dev->priv;
-@@ -758,6 +746,8 @@
- }
-
- if (!IS_FIR(si)) {
-+ netif_stop_queue(dev);
-+
- si->tx_buff.data = si->tx_buff.head;
- si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data,
- si->tx_buff.truesize);
---- linux-2.4.27/drivers/net/irda/w83977af_ir.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/irda/w83977af_ir.c
-@@ -205,7 +205,7 @@
-
- /* FIXME: The HP HDLS-1100 does not support 1152000! */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
-- IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-+ IR_115200/*|IR_576000|IR_1152000|(IR_4000000 << 8)*/;
-
- /* The HP HDLS-1100 needs 1 ms according to the specs */
- self->qos.min_turn_time.bits = qos_mtt_bits;
-@@ -1341,7 +1341,7 @@
- case SIOCSBANDWIDTH: /* Set bandwidth */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
-- goto out;
-+ break;
- }
- w83977af_change_speed(self, irq->ifr_baudrate);
- break;
---- linux-2.4.27/drivers/net/smc9194.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/smc9194.c
-@@ -12,8 +12,8 @@
- . AUI/TP selection ( mine has 10Base2/10BaseT select )
- .
- . Arguments:
-- . io = for the base address
-- . irq = for the IRQ
-+ . io = for the base address
-+ . irq = for the IRQ
- . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 )
- .
- . author:
-@@ -51,12 +51,21 @@
- . allocation
- . 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet
- . 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ"
-+ . 06/23/01 Russell King Separate out IO functions for different bus
-+ . types.
-+ . Use dev->name instead of CARDNAME for printk
-+ . Add ethtool support, full duplex support
-+ . Add LAN91C96 support.
- . 11/08/01 Matt Domsch Use common crc32 function
- ----------------------------------------------------------------------------*/
-
-+#define DRV_NAME "smc9194"
-+#define DRV_VERSION "0.15"
-+
- static const char version[] =
-- "smc9194.c:v0.14 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
-+ DRV_NAME ".c:v" DRV_VERSION " 12/15/00 by Erik Stahlman (erik@vt.edu)\n";
-
-+#include <linux/config.h>
- #include <linux/module.h>
- #include <linux/version.h>
- #include <linux/kernel.h>
-@@ -69,16 +78,26 @@
- #include <linux/in.h>
- #include <linux/slab.h>
- #include <linux/string.h>
-+#include <linux/delay.h>
- #include <linux/init.h>
- #include <linux/crc32.h>
--#include <asm/bitops.h>
--#include <asm/io.h>
- #include <linux/errno.h>
-+#include <linux/ethtool.h>
-
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
-
-+#include <asm/bitops.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+
-+#ifdef CONFIG_ARCH_SA1100
-+#include <asm/hardware.h>
-+#include <asm/arch/assabet.h>
-+#endif
-+
- #include "smc9194.h"
- /*------------------------------------------------------------------------
- .
-@@ -152,29 +171,27 @@
- -------------------------------------------------------------------------*/
- #define CARDNAME "SMC9194"
-
-+static const char *chip_ids[15] = {
-+ NULL,
-+ NULL,
-+ NULL,
-+ "SMC91C90/91C92", /* 3 */
-+ "SMC91C94/91C96", /* 4 */
-+ "SMC91C95", /* 5 */
-+ NULL,
-+ "SMC91C100", /* 7 */
-+ "SMC91C100FD", /* 8 */
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL,
-+ NULL
-+};
-
--/* store this information for the driver.. */
--struct smc_local {
-- /*
-- these are things that the kernel wants me to keep, so users
-- can find out semi-useless statistics of how well the card is
-- performing
-- */
-- struct net_device_stats stats;
--
-- /*
-- If I have to wait until memory is available to send
-- a packet, I will store the skbuff here, until I get the
-- desired memory. Then, I'll send it out and free it.
-- */
-- struct sk_buff * saved_skb;
--
-- /*
-- . This keeps track of how many packets that I have
-- . sent out. When an TX_EMPTY interrupt comes, I know
-- . that all of these have been sent.
-- */
-- int packets_waiting;
-+static const char * interfaces[2] = {
-+ "TP",
-+ "AUI"
- };
-
-
-@@ -202,6 +219,11 @@
- static int smc_open(struct net_device *dev);
-
- /*
-+ . This handles the ethtool interface
-+*/
-+static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-+
-+/*
- . Our watchdog timed out. Called by the networking layer
- */
- static void smc_timeout(struct net_device *dev);
-@@ -217,11 +239,11 @@
- . This routine allows the proc file system to query the driver's
- . statistics.
- */
--static struct net_device_stats * smc_query_statistics( struct net_device *dev);
-+static struct net_device_stats * smc_query_statistics(struct net_device *dev);
-
- /*
-- . Finally, a call to set promiscuous mode ( for TCPDUMP and related
-- . programs ) and multicast modes.
-+ . Finally, a call to set promiscuous mode (for TCPDUMP and related
-+ . programs) and multicast modes.
- */
- static void smc_set_multicast_list(struct net_device *dev);
-
-@@ -240,12 +262,12 @@
- . This is a separate procedure to handle the receipt of a packet, to
- . leave the interrupt code looking slightly cleaner
- */
--static inline void smc_rcv( struct net_device *dev );
-+static inline void smc_rcv(struct net_device *dev);
- /*
- . This handles a TX interrupt, which is only called when an error
- . relating to a packet is sent.
- */
--static inline void smc_tx( struct net_device * dev );
-+static inline void smc_tx(struct net_device * dev);
-
- /*
- ------------------------------------------------------------
-@@ -261,39 +283,287 @@
- */
- static int smc_probe(struct net_device *dev, int ioaddr);
-
--/*
-- . A rather simple routine to print out a packet for debugging purposes.
--*/
--#if SMC_DEBUG > 2
--static void print_packet( byte *, int );
--#endif
--
--#define tx_done(dev) 1
--
- /* this is called to actually send the packet to the chip */
--static void smc_hardware_send_packet( struct net_device * dev );
-+static void smc_hardware_send_packet(struct net_device * dev);
-
- /* Since I am not sure if I will have enough room in the chip's ram
- . to store the packet, I call this routine, which either sends it
- . now, or generates an interrupt when the card is ready for the
- . packet */
--static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
-+static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *dev);
-
- /* this does a soft reset on the device */
--static void smc_reset( int ioaddr );
-+static void smc_reset(struct net_device *dev);
-
- /* Enable Interrupts, Receive, and Transmit */
--static void smc_enable( int ioaddr );
-+static void smc_enable(struct net_device *dev);
-
- /* this puts the device in an inactive state */
--static void smc_shutdown( int ioaddr );
-+static void smc_shutdown(struct net_device *dev);
-
- /* This routine will find the IRQ of the driver if one is not
- . specified in the input to the device. */
--static int smc_findirq( int ioaddr );
-+static int smc_findirq(struct net_device *dev);
-
-+#ifndef CONFIG_ASSABET_NEPONSET
- /*
-- . Function: smc_reset( int ioaddr )
-+ * These functions allow us to handle IO addressing as we wish - this
-+ * ethernet controller can be connected to a variety of busses. Some
-+ * busses do not support 16 bit or 32 bit transfers. --rmk
-+ */
-+static inline u8 smc_inb(u_int base, u_int reg)
-+{
-+ return inb(base + reg);
-+}
-+
-+static inline u16 smc_inw(u_int base, u_int reg)
-+{
-+ return inw(base + reg);
-+}
-+
-+static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ /* QUESTION: Like in the TX routine, do I want
-+ to send the DWORDs or the bytes first, or some
-+ mixture. A mixture might improve already slow PIO
-+ performance */
-+ PRINTK3((" Reading %d dwords (and %d bytes) \n",
-+ len >> 2, len & 3));
-+ insl(port, data, len >> 2);
-+ /* read the left over bytes */
-+ insb(port, data + (len & ~3), len & 3);
-+#else
-+ PRINTK3((" Reading %d words and %d byte(s) \n",
-+ len >> 1, len & 1));
-+ insw(port, data, len >> 1);
-+ if (len & 1) {
-+ data += len & ~1;
-+ *data = inb(port);
-+ }
-+#endif
-+}
-+
-+static inline void smc_outb(u8 val, u_int base, u_int reg)
-+{
-+ outb(val, base + reg);
-+}
-+
-+static inline void smc_outw(u16 val, u_int base, u_int reg)
-+{
-+ outw(val, base + reg);
-+}
-+
-+static inline void smc_outl(u32 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ outl(val, port);
-+#else
-+ outw(val, port);
-+ outw(val >> 16, port);
-+#endif
-+}
-+
-+static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg;
-+#ifdef USE_32_BIT
-+ if (len & 2) {
-+ outsl(port, data, len >> 2);
-+ outw(*((word *)(data + (len & ~3))), port);
-+ }
-+ else
-+ outsl(port, data, len >> 2);
-+#else
-+ outsw(port, data, len >> 1);
-+#endif
-+}
-+
-+
-+/*-------------------------------------------------------------------------
-+ . I define some macros to make it easier to do somewhat common
-+ . or slightly complicated, repeated tasks.
-+ --------------------------------------------------------------------------*/
-+
-+/* select a register bank, 0 to 3 */
-+
-+#define SMC_SELECT_BANK(x) \
-+ { \
-+ smc_outw(x, ioaddr, BANK_SELECT); \
-+ }
-+
-+/* define a small delay for the reset */
-+#define SMC_DELAY() \
-+ { \
-+ smc_inw(ioaddr, RCR); \
-+ smc_inw(ioaddr, RCR); \
-+ smc_inw(ioaddr, RCR); \
-+ }
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) \
-+ { \
-+ byte mask; \
-+ mask = smc_inb(ioaddr, INT_MASK); \
-+ mask |= (x); \
-+ smc_outb(mask, ioaddr, INT_MASK); \
-+ }
-+
-+/* this sets the absolutel interrupt mask */
-+#define SMC_SET_INT(x) \
-+ { \
-+ smc_outw((x), INT_MASK); \
-+ }
-+
-+#else
-+
-+#undef SMC_IO_EXTENT
-+#define SMC_IO_EXTENT (16 << 2)
-+
-+/*
-+ * These functions allow us to handle IO addressing as we wish - this
-+ * ethernet controller can be connected to a variety of busses. Some
-+ * busses do not support 16 bit or 32 bit transfers. --rmk
-+ */
-+static inline u8 smc_inb(u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ return readb(port);
-+}
-+
-+static inline u16 smc_inw(u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ return readb(port) | readb(port + 4) << 8;
-+}
-+
-+static inline void smc_ins(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg * 4;
-+
-+ insb(port, data, len);
-+}
-+
-+static inline void smc_outb(u8 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+}
-+
-+static inline void smc_outw(u16 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+ writeb(val >> 8, port + 4);
-+}
-+
-+static inline void smc_outl(u32 val, u_int base, u_int reg)
-+{
-+ u_int port = base + reg * 4;
-+
-+ writeb(val, port);
-+ writeb(val >> 8, port + 4);
-+ writeb(val >> 16, port + 8);
-+ writeb(val >> 24, port + 12);
-+}
-+
-+static inline void smc_outs(u_int base, u_int reg, u8 *data, u_int len)
-+{
-+ u_int port = base + reg * 4;
-+
-+ outsb(port, data, len & ~1);
-+}
-+
-+/*-------------------------------------------------------------------------
-+ . I define some macros to make it easier to do somewhat common
-+ . or slightly complicated, repeated tasks.
-+ --------------------------------------------------------------------------*/
-+
-+/* select a register bank, 0 to 3 */
-+
-+#define SMC_SELECT_BANK(x) \
-+ { \
-+ smc_outb(x, ioaddr, BANK_SELECT); \
-+ }
-+
-+/* define a small delay for the reset */
-+#define SMC_DELAY() \
-+ { \
-+ smc_inb(ioaddr, RCR); \
-+ smc_inb(ioaddr, RCR); \
-+ smc_inb(ioaddr, RCR); \
-+ }
-+
-+/* this enables an interrupt in the interrupt mask register */
-+#define SMC_ENABLE_INT(x) \
-+ { \
-+ byte mask; \
-+ mask = smc_inb(ioaddr, INT_MASK); \
-+ mask |= (x); \
-+ smc_outb(mask, ioaddr, INT_MASK); \
-+ }
-+
-+/* this sets the absolutel interrupt mask */
-+#define SMC_SET_INT(x) \
-+ { \
-+ smc_outb((x), ioaddr, INT_MASK); \
-+ }
-+
-+#endif
-+
-+/*
-+ . A rather simple routine to print out a packet for debugging purposes.
-+*/
-+#if SMC_DEBUG > 2
-+static void print_packet(byte * buf, int length)
-+{
-+ int i;
-+ int remainder;
-+ int lines;
-+
-+ printk("Packet of length %d \n", length);
-+ lines = length / 16;
-+ remainder = length % 16;
-+
-+ for (i = 0; i < lines ; i ++) {
-+ int cur;
-+
-+ for (cur = 0; cur < 8; cur ++) {
-+ byte a, b;
-+
-+ a = *(buf ++);
-+ b = *(buf ++);
-+ printk("%02x%02x ", a, b);
-+ }
-+ printk("\n");
-+ }
-+ for (i = 0; i < remainder/2 ; i++) {
-+ byte a, b;
-+
-+ a = *(buf ++);
-+ b = *(buf ++);
-+ printk("%02x%02x ", a, b);
-+ }
-+ if (remainder & 1) {
-+ byte a;
-+
-+ a = *buf++;
-+ printk("%02x", a);
-+ }
-+ printk("\n");
-+}
-+#else
-+#define print_packet(buf,len) do { } while (0)
-+#endif
-+
-+/*
-+ . Function: smc_reset(struct net_device *dev)
- . Purpose:
- . This sets the SMC91xx chip to its normal state, hopefully from whatever
- . mess that any other DOS driver has put it in.
-@@ -309,36 +579,37 @@
- . 5. clear all interrupts
- .
- */
--static void smc_reset( int ioaddr )
-+static void smc_reset(struct net_device *dev)
- {
-+ u_int ioaddr = dev->base_addr;
-+
- /* This resets the registers mostly to defaults, but doesn't
- affect EEPROM. That seems unnecessary */
-- SMC_SELECT_BANK( 0 );
-- outw( RCR_SOFTRESET, ioaddr + RCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outw(RCR_SOFTRESET, ioaddr, RCR);
-
- /* this should pause enough for the chip to be happy */
-- SMC_DELAY( );
-+ SMC_DELAY();
-
- /* Set the transmit and receive configuration registers to
- default values */
-- outw( RCR_CLEAR, ioaddr + RCR );
-- outw( TCR_CLEAR, ioaddr + TCR );
-+ smc_outw(RCR_CLEAR, ioaddr, RCR);
-+ smc_outw(TCR_CLEAR, ioaddr, TCR);
-
- /* set the control register to automatically
- release successfully transmitted packets, to make the best
- use out of our limited memory */
-- SMC_SELECT_BANK( 1 );
-- outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL );
-+ SMC_SELECT_BANK(1);
-+ smc_outw(smc_inw(ioaddr, CONTROL) | CTL_AUTO_RELEASE, ioaddr, CONTROL);
-
- /* Reset the MMU */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_RESET, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_RESET, ioaddr, MMU_CMD);
-
- /* Note: It doesn't seem that waiting for the MMU busy is needed here,
- but this is a place where future chipsets _COULD_ break. Be wary
- of issuing another MMU command right after this */
--
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
- }
-
- /*
-@@ -349,20 +620,21 @@
- . 2. Enable the receiver
- . 3. Enable interrupts
- */
--static void smc_enable( int ioaddr )
-+static void smc_enable(struct net_device *dev)
- {
-- SMC_SELECT_BANK( 0 );
-+ u_int ioaddr = dev->base_addr;
-+ SMC_SELECT_BANK(0);
- /* see the header file for options in TCR/RCR NORMAL*/
-- outw( TCR_NORMAL, ioaddr + TCR );
-- outw( RCR_NORMAL, ioaddr + RCR );
-+ smc_outw(TCR_NORMAL, ioaddr, TCR);
-+ smc_outw(RCR_NORMAL, ioaddr, RCR);
-
- /* now, enable interrupts */
-- SMC_SELECT_BANK( 2 );
-- outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(SMC_INTERRUPT_MASK);
- }
-
- /*
-- . Function: smc_shutdown
-+ . Function: smc_shutdown(struct net_device *dev)
- . Purpose: closes down the SMC91xxx chip.
- . Method:
- . 1. zero the interrupt mask
-@@ -375,26 +647,28 @@
- . the manual says that it will wake up in response to any I/O requests
- . in the register space. Empirical results do not show this working.
- */
--static void smc_shutdown( int ioaddr )
-+static void smc_shutdown(struct net_device *dev)
- {
-+ u_int ioaddr = dev->base_addr;
-+
- /* no more interrupts for me */
-- SMC_SELECT_BANK( 2 );
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(0);
-
- /* and tell the card to stay away from that nasty outside world */
-- SMC_SELECT_BANK( 0 );
-- outb( RCR_CLEAR, ioaddr + RCR );
-- outb( TCR_CLEAR, ioaddr + TCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outb(RCR_CLEAR, ioaddr, RCR);
-+ smc_outb(TCR_CLEAR, ioaddr, TCR);
- #if 0
- /* finally, shut the chip down */
-- SMC_SELECT_BANK( 1 );
-- outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL );
-+ SMC_SELECT_BANK(1);
-+ smc_outw(smc_inw(ioaddr, CONTROL), CTL_POWERDOWN, ioaddr, CONTROL);
- #endif
- }
-
-
- /*
-- . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
-+ . Function: smc_setmulticast(int ioaddr, int count, dev_mc_list * adds)
- . Purpose:
- . This sets the internal hardware table to filter out unwanted multicast
- . packets before they take up memory.
-@@ -411,26 +685,28 @@
- */
-
-
--static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) {
-+static void smc_setmulticast(struct net_device *dev, int count, struct dev_mc_list * addrs)
-+{
-+ u_int ioaddr = dev->base_addr;
- int i;
-- unsigned char multicast_table[ 8 ];
-+ unsigned char multicast_table[8];
- struct dev_mc_list * cur_addr;
- /* table for flipping the order of 3 bits */
- unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
-
- /* start with a table of all zeros: reject all */
-- memset( multicast_table, 0, sizeof( multicast_table ) );
-+ memset(multicast_table, 0, sizeof(multicast_table));
-
- cur_addr = addrs;
-- for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) {
-+ for (i = 0; i < count ; i ++, cur_addr = cur_addr->next) {
- int position;
-
- /* do we have a pointer here? */
-- if ( !cur_addr )
-+ if (!cur_addr)
- break;
- /* make sure this is a multicast address - shouldn't this
- be a given if we have it here ? */
-- if ( !( *cur_addr->dmi_addr & 1 ) )
-+ if (!(*cur_addr->dmi_addr & 1))
- continue;
-
- /* only use the low order bits */
-@@ -442,15 +718,15 @@
-
- }
- /* now, the table can be loaded into the chipset */
-- SMC_SELECT_BANK( 3 );
-+ SMC_SELECT_BANK(3);
-
-- for ( i = 0; i < 8 ; i++ ) {
-- outb( multicast_table[i], ioaddr + MULTICAST1 + i );
-+ for (i = 0; i < 8 ; i++) {
-+ smc_outb(multicast_table[i], ioaddr, MULTICAST1 + i);
- }
- }
-
- /*
-- . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
-+ . Function: smc_wait_to_send_packet(struct sk_buff * skb, struct net_device *)
- . Purpose:
- . Attempt to allocate memory for a packet, if chip-memory is not
- . available, then tell the card to generate an interrupt when it
-@@ -465,10 +741,10 @@
- . o (NO): Enable interrupts and let the interrupt handler deal with it.
- . o (YES):Send it now.
- */
--static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
-+static int smc_wait_to_send_packet(struct sk_buff * skb, struct net_device * dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- unsigned short ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- word length;
- unsigned short numPages;
- word time_out;
-@@ -477,15 +753,16 @@
- /* Well, I want to send the packet.. but I don't know
- if I can send it right now... */
-
-- if ( lp->saved_skb) {
-+ if (lp->saved_skb) {
- /* THIS SHOULD NEVER HAPPEN. */
- lp->stats.tx_aborted_errors++;
-- printk(CARDNAME": Bad Craziness - sent packet while busy.\n" );
-+ printk("%s: Bad Craziness - sent packet while busy.\n",
-+ dev->name);
- return 1;
- }
-
- length = skb->len;
--
-+
- if(length < ETH_ZLEN)
- {
- skb = skb_padto(skb, ETH_ZLEN);
-@@ -497,18 +774,18 @@
- length = ETH_ZLEN;
- }
- lp->saved_skb = skb;
--
-+
- /*
- ** The MMU wants the number of pages to be the number of 256 bytes
-- ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
-+ ** 'pages', minus 1 (since a packet can't ever have 0 pages :))
- **
- ** Pkt size for allocating is data length +6 (for additional status words,
- ** length and ctl!) If odd size last byte is included in this header.
- */
-- numPages = ((length & 0xfffe) + 6) / 256;
-+ numPages = ((length & 0xfffe) + 6) / 256;
-
-- if (numPages > 7 ) {
-- printk(CARDNAME": Far too big packet error. \n");
-+ if (numPages > 7) {
-+ printk("%s: Far too big packet error.\n", dev->name);
- /* freeing the packet is a good thing here... but should
- . any packets of this size get down here? */
- dev_kfree_skb (skb);
-@@ -517,12 +794,13 @@
- netif_wake_queue(dev);
- return 0;
- }
-+
- /* either way, a packet is waiting now */
- lp->packets_waiting++;
-
- /* now, try to allocate the memory */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_ALLOC | numPages, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_ALLOC | numPages, ioaddr, MMU_CMD);
- /*
- . Performance Hack
- .
-@@ -539,21 +817,21 @@
- do {
- word status;
-
-- status = inb( ioaddr + INTERRUPT );
-- if ( status & IM_ALLOC_INT ) {
-+ status = smc_inb(ioaddr, INTERRUPT);
-+ if (status & IM_ALLOC_INT) {
- /* acknowledge the interrupt */
-- outb( IM_ALLOC_INT, ioaddr + INTERRUPT );
-- break;
-+ smc_outb(IM_ALLOC_INT, ioaddr, INTERRUPT);
-+ break;
- }
-- } while ( -- time_out );
-+ } while (-- time_out);
-
-- if ( !time_out ) {
-+ if (!time_out) {
- /* oh well, wait until the chip finds memory later */
-- SMC_ENABLE_INT( IM_ALLOC_INT );
-- PRINTK2((CARDNAME": memory allocation deferred. \n"));
-+ SMC_ENABLE_INT(IM_ALLOC_INT);
-+ PRINTK2(("%s: memory allocation deferred.\n", dev->name));
- /* it's deferred, but I'll handle it later */
-- return 0;
-- }
-+ return 0;
-+ }
- /* or YES! I can send the packet now.. */
- smc_hardware_send_packet(dev);
- netif_wake_queue(dev);
-@@ -561,46 +839,46 @@
- }
-
- /*
-- . Function: smc_hardware_send_packet(struct net_device * )
-+ . Function: smc_hardware_send_packet(struct net_device *)
- . Purpose:
- . This sends the actual packet to the SMC9xxx chip.
- .
- . Algorithm:
- . First, see if a saved_skb is available.
-- . ( this should NOT be called if there is no 'saved_skb'
-+ . (this should NOT be called if there is no 'saved_skb'
- . Now, find the packet number that the chip allocated
- . Point the data pointers at it in memory
- . Set the length word in the chip's memory
- . Dump the packet to chip memory
-- . Check if a last byte is needed ( odd length packet )
-+ . Check if a last byte is needed (odd length packet)
- . if so, set the control flag right
- . Tell the card to send it
- . Enable the transmit interrupt, so I know if it failed
- . Free the kernel data if I actually sent it.
- */
--static void smc_hardware_send_packet( struct net_device * dev )
-+static void smc_hardware_send_packet(struct net_device *dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- byte packet_no;
-- struct sk_buff * skb = lp->saved_skb;
-- word length;
-- unsigned short ioaddr;
-- byte * buf;
--
-- ioaddr = dev->base_addr;
-+ struct sk_buff *skb = lp->saved_skb;
-+ word length, lastword;
-+ u_int ioaddr = dev->base_addr;
-+ byte packet_no;
-+ byte *buf;
-
-- if ( !skb ) {
-- PRINTK((CARDNAME": In XMIT with no packet to send \n"));
-+ if (!skb) {
-+ PRINTK(("%s: In XMIT with no packet to send\n", dev->name));
- return;
- }
-+
- length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- buf = skb->data;
-
- /* If I get here, I _know_ there is a packet slot waiting for me */
-- packet_no = inb( ioaddr + PNR_ARR + 1 );
-- if ( packet_no & 0x80 ) {
-+ packet_no = smc_inb(ioaddr, PNR_ARR + 1);
-+ if (packet_no & 0x80) {
- /* or isn't there? BAD CHIP! */
-- printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
-+ printk(KERN_DEBUG "%s: Memory allocation failed.\n",
-+ dev->name);
- dev_kfree_skb_any(skb);
- lp->saved_skb = NULL;
- netif_wake_queue(dev);
-@@ -608,26 +886,19 @@
- }
-
- /* we have a packet address, so tell the card to use it */
-- outb( packet_no, ioaddr + PNR_ARR );
-+ smc_outb(packet_no, ioaddr, PNR_ARR);
-
- /* point to the beginning of the packet */
-- outw( PTR_AUTOINC , ioaddr + POINTER );
-+ smc_outw(PTR_AUTOINC, ioaddr, POINTER);
-
-- PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length ));
--#if SMC_DEBUG > 2
-- print_packet( buf, length );
--#endif
-+ PRINTK3(("%s: Trying to xmit packet of length %x\n",
-+ dev->name, length));
-
-- /* send the packet length ( +6 for status, length and ctl byte )
-- and the status word ( set to zeros ) */
--#ifdef USE_32_BIT
-- outl( (length +6 ) << 16 , ioaddr + DATA_1 );
--#else
-- outw( 0, ioaddr + DATA_1 );
-- /* send the packet length ( +6 for status words, length, and ctl*/
-- outb( (length+6) & 0xFF,ioaddr + DATA_1 );
-- outb( (length+6) >> 8 , ioaddr + DATA_1 );
--#endif
-+ print_packet(buf, length);
-+
-+ /* send the packet length (+6 for status, length and ctl byte)
-+ and the status word (set to zeros) */
-+ smc_outl((length + 6) << 16, ioaddr, DATA_1);
-
- /* send the actual data
- . I _think_ it's faster to send the longs first, and then
-@@ -636,32 +907,22 @@
- . a good idea to check which is optimal? But that could take
- . almost as much time as is saved?
- */
--#ifdef USE_32_BIT
-- if ( length & 0x2 ) {
-- outsl(ioaddr + DATA_1, buf, length >> 2 );
-- outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-- }
-- else
-- outsl(ioaddr + DATA_1, buf, length >> 2 );
--#else
-- outsw(ioaddr + DATA_1 , buf, (length ) >> 1);
--#endif
-- /* Send the last byte, if there is one. */
-+ smc_outs(ioaddr, DATA_1, buf, length);
-
-- if ( (length & 1) == 0 ) {
-- outw( 0, ioaddr + DATA_1 );
-- } else {
-- outb( buf[length -1 ], ioaddr + DATA_1 );
-- outb( 0x20, ioaddr + DATA_1);
-- }
-+ /* Send the last byte, if there is one. */
-+ if ((length & 1) == 0)
-+ lastword = 0;
-+ else
-+ lastword = 0x2000 | buf[length - 1];
-+ smc_outw(lastword, ioaddr, DATA_1);
-
- /* enable the interrupts */
-- SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
-+ SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
-
- /* and let the chipset deal with it */
-- outw( MC_ENQUEUE , ioaddr + MMU_CMD );
-+ smc_outw(MC_ENQUEUE, ioaddr, MMU_CMD);
-
-- PRINTK2((CARDNAME": Sent packet of length %d \n",length));
-+ PRINTK2(("%s: Sent packet of length %d\n", dev->name, length));
-
- lp->saved_skb = NULL;
- dev_kfree_skb_any (skb);
-@@ -676,7 +937,7 @@
-
- /*-------------------------------------------------------------------------
- |
-- | smc_init( struct net_device * dev )
-+ | smc_init(struct net_device * dev)
- | Input parameters:
- | dev->base_addr == 0, try to find all possible locations
- | dev->base_addr == 1, return failure code
-@@ -691,6 +952,65 @@
- */
- int __init smc_init(struct net_device *dev)
- {
-+ int ret = -ENODEV;
-+#if defined(CONFIG_ASSABET_NEPONSET)
-+ if (machine_is_assabet() && machine_has_neponset()) {
-+ unsigned int *addr;
-+ unsigned char ecor;
-+ unsigned long flags;
-+
-+ NCR_0 |= NCR_ENET_OSC_EN;
-+ dev->irq = IRQ_NEPONSET_SMC9196;
-+
-+ /*
-+ * Map the attribute space. This is overkill, but clean.
-+ */
-+ addr = ioremap(0x18000000 + (1 << 25), 64 * 1024 * 4);
-+ if (!addr)
-+ return -ENOMEM;
-+
-+ /*
-+ * Reset the device. We must disable IRQs around this.
-+ */
-+ local_irq_save(flags);
-+ ecor = readl(addr + ECOR) & ~ECOR_RESET;
-+ writel(ecor | ECOR_RESET, addr + ECOR);
-+ udelay(100);
-+
-+ /*
-+ * The device will ignore all writes to the enable bit while
-+ * reset is asserted, even if the reset bit is cleared in the
-+ * same write. Must clear reset first, then enable the device.
-+ */
-+ writel(ecor, addr + ECOR);
-+ writel(ecor | ECOR_ENABLE, addr + ECOR);
-+
-+ /*
-+ * Force byte mode.
-+ */
-+ writel(readl(addr + ECSR) | ECSR_IOIS8, addr + ECSR);
-+ local_irq_restore(flags);
-+
-+ iounmap(addr);
-+
-+ /*
-+ * Wait for the chip to wake up.
-+ */
-+ mdelay(1);
-+
-+ /*
-+ * Map the real registers.
-+ */
-+ addr = ioremap(0x18000000, 8 * 1024);
-+ if (!addr)
-+ return -ENOMEM;
-+
-+ ret = smc_probe(dev, (int)addr);
-+ if (ret)
-+ iounmap(addr);
-+ }
-+
-+#elif defined(CONFIG_ISA)
- int i;
- int base_addr = dev->base_addr;
-
-@@ -708,7 +1028,8 @@
- return 0;
-
- /* couldn't find anything */
-- return -ENODEV;
-+#endif
-+ return ret;
- }
-
- /*----------------------------------------------------------------------
-@@ -718,10 +1039,11 @@
- . interrupt, so an auto-detect routine can detect it, and find the IRQ,
- ------------------------------------------------------------------------
- */
--int __init smc_findirq( int ioaddr )
-+int __init smc_findirq(struct net_device *dev)
- {
- int timeout = 20;
- unsigned long cookie;
-+ u_int ioaddr = dev->base_addr;
-
-
- /* I have to do a STI() here, because this is called from
-@@ -737,26 +1059,25 @@
- * when done.
- */
-
--
-+ /* enable ALLOCation interrupts ONLY. */
- SMC_SELECT_BANK(2);
-- /* enable ALLOCation interrupts ONLY */
-- outb( IM_ALLOC_INT, ioaddr + INT_MASK );
-+ SMC_SET_INT(IM_ALLOC_INT);
-
- /*
- . Allocate 512 bytes of memory. Note that the chip was just
- . reset so all the memory is available
- */
-- outw( MC_ALLOC | 1, ioaddr + MMU_CMD );
-+ smc_outw(MC_ALLOC | 1, ioaddr, MMU_CMD);
-
- /*
- . Wait until positive that the interrupt has been generated
- */
-- while ( timeout ) {
-+ while (timeout) {
- byte int_status;
-
-- int_status = inb( ioaddr + INTERRUPT );
-+ int_status = smc_inb(ioaddr, INTERRUPT);
-
-- if ( int_status & IM_ALLOC_INT )
-+ if (int_status & IM_ALLOC_INT)
- break; /* got the interrupt */
- timeout--;
- }
-@@ -775,7 +1096,7 @@
- SMC_DELAY();
-
- /* and disable all interrupts again */
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
-
- /* clear hardware interrupts again, because that's how it
- was when I was called... */
-@@ -785,8 +1106,87 @@
- return probe_irq_off(cookie);
- }
-
-+static int __init smc_probe_chip(struct net_device *dev, int ioaddr)
-+{
-+ unsigned int temp;
-+
-+ /* First, see if the high byte is 0x33 */
-+ temp = smc_inw(ioaddr, BANK_SELECT);
-+ if ((temp & 0xFF00) != 0x3300)
-+ return -ENODEV;
-+
-+ /* The above MIGHT indicate a device, but I need to write to further
-+ test this. */
-+ smc_outw(0, ioaddr, BANK_SELECT);
-+ temp = smc_inw(ioaddr, BANK_SELECT);
-+ if ((temp & 0xFF00) != 0x3300)
-+ return -ENODEV;
-+
-+#ifndef CONFIG_ASSABET_NEPONSET
-+ /* well, we've already written once, so hopefully another time won't
-+ hurt. This time, I need to switch the bank register to bank 1,
-+ so I can access the base address register */
-+ SMC_SELECT_BANK(1);
-+ temp = smc_inw(ioaddr, BASE);
-+ if (ioaddr != (temp >> 3 & 0x3E0)) {
-+ printk("%s: IOADDR %x doesn't match configuration (%x)."
-+ "Probably not a SMC chip\n", dev->name,
-+ ioaddr, (base_address_register >> 3) & 0x3E0);
-+ /* well, the base address register didn't match. Must not have
-+ been a SMC chip after all. */
-+ return -ENODEV;
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+/*
-+ . If dev->irq is 0, then the device has to be banged on to see
-+ . what the IRQ is.
-+ .
-+ . This banging doesn't always detect the IRQ, for unknown reasons.
-+ . a workaround is to reset the chip and try again.
-+ .
-+ . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-+ . be what is requested on the command line. I don't do that, mostly
-+ . because the card that I have uses a non-standard method of accessing
-+ . the IRQs, and because this _should_ work in most configurations.
-+ .
-+ . Specifying an IRQ is done with the assumption that the user knows
-+ . what (s)he is doing. No checking is done!!!!
-+ .
-+*/
-+static int __init smc_probe_irq(struct net_device *dev)
-+{
-+ if (dev->irq < 2) {
-+ int trials;
-+
-+ trials = 3;
-+ while (trials--) {
-+ dev->irq = smc_findirq(dev);
-+ if (dev->irq)
-+ break;
-+ /* kick the card and try again */
-+ smc_reset(dev);
-+ }
-+ }
-+ if (dev->irq == 0) {
-+ printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
-+ dev->name);
-+ return -ENODEV;
-+ }
-+
-+ /*
-+ * Some machines (eg, PCs) need to cannonicalize their IRQs.
-+ */
-+ dev->irq = irq_cannonicalize(dev->irq);
-+
-+ return 0;
-+}
-+
- /*----------------------------------------------------------------------
-- . Function: smc_probe( int ioaddr )
-+ . Function: smc_probe(struct net_device *dev, int ioaddr)
- .
- . Purpose:
- . Tests to see if a given ioaddr points to an SMC9xxx chip.
-@@ -816,16 +1216,14 @@
- */
- static int __init smc_probe(struct net_device *dev, int ioaddr)
- {
-+ struct smc_local *smc;
- int i, memory, retval;
- static unsigned version_printed;
-- unsigned int bank;
-
- const char *version_string;
-- const char *if_string;
-
- /* registers */
- word revision_register;
-- word base_address_register;
- word configuration_register;
- word memory_info_register;
- word memory_cfg_register;
-@@ -834,44 +1232,24 @@
- if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
- return -EBUSY;
-
-- /* First, see if the high byte is 0x33 */
-- bank = inw( ioaddr + BANK_SELECT );
-- if ( (bank & 0xFF00) != 0x3300 ) {
-- retval = -ENODEV;
-- goto err_out;
-- }
-- /* The above MIGHT indicate a device, but I need to write to further
-- test this. */
-- outw( 0x0, ioaddr + BANK_SELECT );
-- bank = inw( ioaddr + BANK_SELECT );
-- if ( (bank & 0xFF00 ) != 0x3300 ) {
-- retval = -ENODEV;
-- goto err_out;
-- }
-- /* well, we've already written once, so hopefully another time won't
-- hurt. This time, I need to switch the bank register to bank 1,
-- so I can access the base address register */
-- SMC_SELECT_BANK(1);
-- base_address_register = inw( ioaddr + BASE );
-- if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) {
-- printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)."
-- "Probably not a SMC chip\n",
-- ioaddr, base_address_register >> 3 & 0x3E0 );
-- /* well, the base address register didn't match. Must not have
-- been a SMC chip after all. */
-- retval = -ENODEV;
-+ /*
-+ * Do the basic probes.
-+ */
-+ retval = smc_probe_chip(dev, ioaddr);
-+ if (retval)
- goto err_out;
-- }
-
- /* check if the revision register is something that I recognize.
- These might need to be added to later, as future revisions
- could be added. */
- SMC_SELECT_BANK(3);
-- revision_register = inw( ioaddr + REVISION );
-- if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) {
-+ revision_register = smc_inw(ioaddr, REVISION);
-+ version_string = chip_ids[(revision_register >> 4) & 15];
-+ if (!version_string) {
- /* I don't recognize this chip, so... */
-- printk(CARDNAME ": IO %x: Unrecognized revision register:"
-- " %x, Contact author. \n", ioaddr, revision_register );
-+ printk("%s: IO %x: unrecognized revision register: %x, "
-+ "contact author.\n", dev->name, ioaddr,
-+ revision_register);
-
- retval = -ENODEV;
- goto err_out;
-@@ -882,138 +1260,122 @@
- against the hardware address, or do some other tests. */
-
- if (version_printed++ == 0)
-- printk("%s", version);
-+ printk(KERN_INFO "%s", version);
-
- /* fill in some of the fields */
- dev->base_addr = ioaddr;
-
- /*
-- . Get the MAC address ( bank 1, regs 4 - 9 )
-+ . Get the MAC address (bank 1, regs 4 - 9)
- */
-- SMC_SELECT_BANK( 1 );
-- for ( i = 0; i < 6; i += 2 ) {
-+ SMC_SELECT_BANK(1);
-+ for (i = 0; i < 6; i += 2) {
- word address;
-
-- address = inw( ioaddr + ADDR0 + i );
-- dev->dev_addr[ i + 1] = address >> 8;
-- dev->dev_addr[ i ] = address & 0xFF;
-+ address = smc_inw(ioaddr, ADDR0 + i);
-+ dev->dev_addr[i + 1] = address >> 8;
-+ dev->dev_addr[i] = address & 0xFF;
- }
-
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ printk("%s: Invalid ethernet MAC address. Please set using "
-+ "ifconfig\n", dev->name);
-+
- /* get the memory information */
-
-- SMC_SELECT_BANK( 0 );
-- memory_info_register = inw( ioaddr + MIR );
-- memory_cfg_register = inw( ioaddr + MCR );
-- memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */
-- memory *= 256 * ( memory_info_register & 0xFF );
-+ SMC_SELECT_BANK(0);
-+ memory_info_register = smc_inw(ioaddr, MIR);
-+ memory_cfg_register = smc_inw(ioaddr, MCR);
-+ memory = (memory_cfg_register >> 9) & 0x7; /* multiplier */
-+ memory *= 256 * (memory_info_register & 0xFF);
-+
-+ /* now, reset the chip, and put it into a known state */
-+ smc_reset(dev);
-
- /*
-- Now, I want to find out more about the chip. This is sort of
-- redundant, but it's cleaner to have it in both, rather than having
-- one VERY long probe procedure.
-- */
-- SMC_SELECT_BANK(3);
-- revision_register = inw( ioaddr + REVISION );
-- version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ];
-- if ( !version_string ) {
-- /* I shouldn't get here because this call was done before.... */
-- retval = -ENODEV;
-+ * Ok, now that we have everything in a
-+ * sane state, probe for the interrupt.
-+ */
-+ retval = smc_probe_irq(dev);
-+ if (retval)
- goto err_out;
-- }
-
-- /* is it using AUI or 10BaseT ? */
-- if ( dev->if_port == 0 ) {
-- SMC_SELECT_BANK(1);
-- configuration_register = inw( ioaddr + CONFIG );
-- if ( configuration_register & CFG_AUI_SELECT )
-- dev->if_port = 2;
-- else
-- dev->if_port = 1;
-+ /* Initialize the private structure. */
-+ if (dev->priv == NULL) {
-+ dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
-+ if (dev->priv == NULL) {
-+ retval = -ENOMEM;
-+ goto err_out;
-+ }
- }
-- if_string = interfaces[ dev->if_port - 1 ];
-
-- /* now, reset the chip, and put it into a known state */
-- smc_reset( ioaddr );
-+ smc = dev->priv;
-+
-+ /* set the private data to zero by default */
-+ memset(smc, 0, sizeof(struct smc_local));
-
- /*
-- . If dev->irq is 0, then the device has to be banged on to see
-- . what the IRQ is.
-- .
-- . This banging doesn't always detect the IRQ, for unknown reasons.
-- . a workaround is to reset the chip and try again.
-- .
-- . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
-- . be what is requested on the command line. I don't do that, mostly
-- . because the card that I have uses a non-standard method of accessing
-- . the IRQs, and because this _should_ work in most configurations.
-- .
-- . Specifying an IRQ is done with the assumption that the user knows
-- . what (s)he is doing. No checking is done!!!!
-- .
-- */
-- if ( dev->irq < 2 ) {
-- int trials;
-+ * Get the interface characteristics.
-+ * is it using AUI or 10BaseT ?
-+ */
-+ switch (dev->if_port) {
-+ case IF_PORT_10BASET:
-+ smc->port = PORT_TP;
-+ break;
-
-- trials = 3;
-- while ( trials-- ) {
-- dev->irq = smc_findirq( ioaddr );
-- if ( dev->irq )
-- break;
-- /* kick the card and try again */
-- smc_reset( ioaddr );
-+ case IF_PORT_AUI:
-+ smc->port = PORT_AUI;
-+ break;
-+
-+ default:
-+ SMC_SELECT_BANK(1);
-+ configuration_register = smc_inw(ioaddr, CONFIG);
-+ if (configuration_register & CFG_AUI_SELECT) {
-+ dev->if_port = IF_PORT_AUI;
-+ smc->port = PORT_AUI;
-+ } else {
-+ dev->if_port = IF_PORT_10BASET;
-+ smc->port = PORT_TP;
- }
-- }
-- if (dev->irq == 0 ) {
-- printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
-- retval = -ENODEV;
-- goto err_out;
-+ break;
- }
-
-- /* now, print out the card info, in a short format.. */
-+ /* all interfaces are half-duplex by default */
-+ smc->duplex = DUPLEX_HALF;
-
-- printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
-- version_string, revision_register & 0xF, ioaddr, dev->irq,
-- if_string, memory );
-+ /* now, print out the card info, in a short format.. */
-+ printk("%s: %s (rev %d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name,
-+ version_string, revision_register & 15, ioaddr, dev->irq,
-+ interfaces[smc->port], memory);
- /*
- . Print the Ethernet address
- */
- printk("ADDR: ");
- for (i = 0; i < 5; i++)
-- printk("%2.2x:", dev->dev_addr[i] );
-- printk("%2.2x \n", dev->dev_addr[5] );
--
--
-- /* Initialize the private structure. */
-- if (dev->priv == NULL) {
-- dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
-- if (dev->priv == NULL) {
-- retval = -ENOMEM;
-- goto err_out;
-- }
-- }
-- /* set the private data to zero by default */
-- memset(dev->priv, 0, sizeof(struct smc_local));
-+ printk("%2.2x:", dev->dev_addr[i]);
-+ printk("%2.2x\n", dev->dev_addr[5]);
-
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
-
- /* Grab the IRQ */
-- retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-- if (retval) {
-+ retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
-+ if (retval) {
- printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
- dev->irq, retval);
- kfree(dev->priv);
- dev->priv = NULL;
-- goto err_out;
-- }
-+ goto err_out;
-+ }
-
-- dev->open = smc_open;
-- dev->stop = smc_close;
-- dev->hard_start_xmit = smc_wait_to_send_packet;
-- dev->tx_timeout = smc_timeout;
-- dev->watchdog_timeo = HZ/20;
-- dev->get_stats = smc_query_statistics;
-- dev->set_multicast_list = smc_set_multicast_list;
-+ dev->open = smc_open;
-+ dev->stop = smc_close;
-+ dev->hard_start_xmit = smc_wait_to_send_packet;
-+ dev->tx_timeout = smc_timeout;
-+ dev->watchdog_timeo = HZ/20;
-+ dev->get_stats = smc_query_statistics;
-+ dev->set_multicast_list = smc_set_multicast_list;
-+ dev->do_ioctl = smc_ioctl;
-
- return 0;
-
-@@ -1022,42 +1384,43 @@
- return retval;
- }
-
--#if SMC_DEBUG > 2
--static void print_packet( byte * buf, int length )
-+/*
-+ * This is responsible for setting the chip appropriately
-+ * for the interface type. This should only be called while
-+ * the interface is up and running.
-+ */
-+static void smc_set_port(struct net_device *dev)
- {
--#if 0
-- int i;
-- int remainder;
-- int lines;
--
-- printk("Packet of length %d \n", length );
-- lines = length / 16;
-- remainder = length % 16;
--
-- for ( i = 0; i < lines ; i ++ ) {
-- int cur;
-+ struct smc_local *smc = dev->priv;
-+ u_int ioaddr = dev->base_addr;
-+ u_int val;
-
-- for ( cur = 0; cur < 8; cur ++ ) {
-- byte a, b;
-+ SMC_SELECT_BANK(1);
-+ val = smc_inw(ioaddr, CONFIG);
-+ switch (smc->port) {
-+ case PORT_TP:
-+ val &= ~CFG_AUI_SELECT;
-+ break;
-
-- a = *(buf ++ );
-- b = *(buf ++ );
-- printk("%02x%02x ", a, b );
-- }
-- printk("\n");
-+ case PORT_AUI:
-+ val |= CFG_AUI_SELECT;
-+ break;
- }
-- for ( i = 0; i < remainder/2 ; i++ ) {
-- byte a, b;
-+ smc_outw(val, ioaddr, CONFIG);
-
-- a = *(buf ++ );
-- b = *(buf ++ );
-- printk("%02x%02x ", a, b );
-+ SMC_SELECT_BANK(0);
-+ val = smc_inw(ioaddr, TCR);
-+ switch (smc->duplex) {
-+ case DUPLEX_HALF:
-+ val &= ~TCR_FDSE;
-+ break;
-+
-+ case DUPLEX_FULL:
-+ val |= TCR_FDSE;
-+ break;
- }
-- printk("\n");
--#endif
-+ smc_outw(val, ioaddr, TCR);
- }
--#endif
--
-
- /*
- * Open and Initialize the board
-@@ -1067,48 +1430,141 @@
- */
- static int smc_open(struct net_device *dev)
- {
-- int ioaddr = dev->base_addr;
-+ struct smc_local *smc = dev->priv;
-+ u_int ioaddr = dev->base_addr;
-+ int i;
-
-- int i; /* used to set hw ethernet address */
-+ /*
-+ * Check that the address is valid. If its not, refuse
-+ * to bring the device up. The user must specify an
-+ * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-+ */
-+ if (!is_valid_ether_addr(dev->dev_addr))
-+ return -EINVAL;
-
- /* clear out all the junk that was put here before... */
-- memset(dev->priv, 0, sizeof(struct smc_local));
-+ smc->saved_skb = NULL;
-+ smc->packets_waiting = 0;
-
- /* reset the hardware */
--
-- smc_reset( ioaddr );
-- smc_enable( ioaddr );
-+ smc_reset(dev);
-+ smc_enable(dev);
-
- /* Select which interface to use */
--
-- SMC_SELECT_BANK( 1 );
-- if ( dev->if_port == 1 ) {
-- outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT,
-- ioaddr + CONFIG );
-- }
-- else if ( dev->if_port == 2 ) {
-- outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT,
-- ioaddr + CONFIG );
-- }
-+ smc_set_port(dev);
-
- /*
-- According to Becker, I have to set the hardware address
-+ According to Becker, I have to set the hardware address
- at this point, because the (l)user can set it with an
- ioctl. Easily done...
- */
-- SMC_SELECT_BANK( 1 );
-- for ( i = 0; i < 6; i += 2 ) {
-+ SMC_SELECT_BANK(1);
-+ for (i = 0; i < 6; i += 2) {
- word address;
-
-- address = dev->dev_addr[ i + 1 ] << 8 ;
-- address |= dev->dev_addr[ i ];
-- outw( address, ioaddr + ADDR0 + i );
-+ address = dev->dev_addr[i + 1] << 8 ;
-+ address |= dev->dev_addr[i];
-+ smc_outw(address, ioaddr, ADDR0 + i);
- }
-
- netif_start_queue(dev);
- return 0;
- }
-
-+/*
-+ * This is our template. Fill the rest in at run-time
-+ */
-+static const struct ethtool_cmd ecmd_template = {
-+ supported: SUPPORTED_10baseT_Half |
-+ SUPPORTED_10baseT_Full |
-+ SUPPORTED_TP |
-+ SUPPORTED_AUI,
-+ speed: SPEED_10,
-+ autoneg: AUTONEG_DISABLE,
-+ maxtxpkt: 1,
-+ maxrxpkt: 1,
-+ transceiver: XCVR_INTERNAL,
-+};
-+
-+static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-+{
-+ struct smc_local *smc = dev->priv;
-+ u32 etcmd;
-+ int ret = -EINVAL;
-+
-+ if (cmd != SIOCETHTOOL)
-+ return -EOPNOTSUPP;
-+
-+ if (get_user(etcmd, (u32 *)rq->ifr_data))
-+ return -EFAULT;
-+
-+ switch (etcmd) {
-+ case ETHTOOL_GSET: {
-+ struct ethtool_cmd ecmd = ecmd_template;
-+
-+ ecmd.cmd = etcmd;
-+ ecmd.port = smc->port;
-+ ecmd.duplex = smc->duplex;
-+
-+ ret = copy_to_user(rq->ifr_data, &ecmd, sizeof(ecmd))
-+ ? -EFAULT : 0;
-+ break;
-+ }
-+
-+ case ETHTOOL_SSET: {
-+ struct ethtool_cmd ecmd;
-+
-+ ret = -EPERM;
-+ if (!capable(CAP_NET_ADMIN))
-+ break;
-+
-+ ret = -EFAULT;
-+ if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
-+ break;
-+
-+ /*
-+ * Sanity-check the arguments.
-+ */
-+ ret = -EINVAL;
-+ if (ecmd.autoneg != AUTONEG_DISABLE)
-+ break;
-+ if (ecmd.speed != SPEED_10)
-+ break;
-+ if (ecmd.duplex != DUPLEX_HALF && ecmd.duplex != DUPLEX_FULL)
-+ break;
-+ if (ecmd.port != PORT_TP && ecmd.port != PORT_AUI)
-+ break;
-+
-+ smc->port = ecmd.port;
-+ smc->duplex = ecmd.duplex;
-+
-+ if (netif_running(dev))
-+ smc_set_port(dev);
-+
-+ ret = 0;
-+ break;
-+ }
-+
-+ case ETHTOOL_GDRVINFO: {
-+ struct ethtool_drvinfo edrv;
-+
-+ memset(&edrv, 0, sizeof(edrv));
-+
-+ edrv.cmd = etcmd;
-+ strcpy(edrv.driver, DRV_NAME);
-+ strcpy(edrv.version, DRV_VERSION);
-+ sprintf(edrv.bus_info, "ISA:%8.8lx:%d",
-+ dev->base_addr, dev->irq);
-+
-+ ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv))
-+ ? -EFAULT : 0;
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
- /*--------------------------------------------------------
- . Called by the kernel to send a packet out into the void
- . of the net. This routine is largely based on
-@@ -1120,12 +1576,10 @@
- {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
-- printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
-- tx_done(dev) ? "IRQ conflict" :
-- "network cable problem");
-+ printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
- /* "kick" the adaptor */
-- smc_reset( dev->base_addr );
-- smc_enable( dev->base_addr );
-+ smc_reset(dev);
-+ smc_enable(dev);
- dev->trans_start = jiffies;
- /* clear anything saved */
- ((struct smc_local *)dev->priv)->saved_skb = NULL;
-@@ -1145,10 +1599,10 @@
- .
- ---------------------------------------------------------------------*/
-
--static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-+static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
- {
- struct net_device *dev = dev_id;
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
-
- byte status;
-@@ -1161,45 +1615,45 @@
-
-
-
-- PRINTK3((CARDNAME": SMC interrupt started \n"));
-+ PRINTK3(("%s: SMC interrupt started\n", dev->name));
-
-- saved_bank = inw( ioaddr + BANK_SELECT );
-+ saved_bank = smc_inw(ioaddr, BANK_SELECT);
-
- SMC_SELECT_BANK(2);
-- saved_pointer = inw( ioaddr + POINTER );
-+ saved_pointer = smc_inw(ioaddr, POINTER);
-
-- mask = inb( ioaddr + INT_MASK );
-+ mask = smc_inb(ioaddr, INT_MASK);
- /* clear all interrupts */
-- outb( 0, ioaddr + INT_MASK );
-+ SMC_SET_INT(0);
-
-
- /* set a timeout value, so I don't stay here forever */
- timeout = 4;
-
-- PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
-+ PRINTK2((KERN_WARNING "%s: MASK IS %x\n", dev->name, mask));
- do {
- /* read the status flag, and mask it */
-- status = inb( ioaddr + INTERRUPT ) & mask;
-- if (!status )
-+ status = smc_inb(ioaddr, INTERRUPT) & mask;
-+ if (!status)
- break;
-
-- PRINTK3((KERN_WARNING CARDNAME
-- ": Handling interrupt status %x \n", status ));
-+ PRINTK3((KERN_WARNING "%s: handling interrupt status %x\n",
-+ dev->name, status));
-
- if (status & IM_RCV_INT) {
- /* Got a packet(s). */
-- PRINTK2((KERN_WARNING CARDNAME
-- ": Receive Interrupt\n"));
-+ PRINTK2((KERN_WARNING "%s: receive interrupt\n",
-+ dev->name));
- smc_rcv(dev);
-- } else if (status & IM_TX_INT ) {
-- PRINTK2((KERN_WARNING CARDNAME
-- ": TX ERROR handled\n"));
-+ } else if (status & IM_TX_INT) {
-+ PRINTK2((KERN_WARNING "%s: TX ERROR handled\n",
-+ dev->name));
- smc_tx(dev);
-- outb(IM_TX_INT, ioaddr + INTERRUPT );
-- } else if (status & IM_TX_EMPTY_INT ) {
-+ smc_outb(IM_TX_INT, ioaddr, INTERRUPT);
-+ } else if (status & IM_TX_EMPTY_INT) {
- /* update stats */
-- SMC_SELECT_BANK( 0 );
-- card_stats = inw( ioaddr + COUNTER );
-+ SMC_SELECT_BANK(0);
-+ card_stats = smc_inw(ioaddr, COUNTER);
- /* single collisions */
- lp->stats.collisions += card_stats & 0xF;
- card_stats >>= 4;
-@@ -1208,60 +1662,63 @@
-
- /* these are for when linux supports these statistics */
-
-- SMC_SELECT_BANK( 2 );
-- PRINTK2((KERN_WARNING CARDNAME
-- ": TX_BUFFER_EMPTY handled\n"));
-- outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
-+ SMC_SELECT_BANK(2);
-+ PRINTK2((KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
-+ dev->name));
-+ smc_outb(IM_TX_EMPTY_INT, ioaddr, INTERRUPT);
- mask &= ~IM_TX_EMPTY_INT;
- lp->stats.tx_packets += lp->packets_waiting;
- lp->packets_waiting = 0;
-
-- } else if (status & IM_ALLOC_INT ) {
-- PRINTK2((KERN_DEBUG CARDNAME
-- ": Allocation interrupt \n"));
-+ } else if (status & IM_ALLOC_INT) {
-+ PRINTK2((KERN_DEBUG "%s: Allocation interrupt\n",
-+ dev->name));
- /* clear this interrupt so it doesn't happen again */
- mask &= ~IM_ALLOC_INT;
-
-- smc_hardware_send_packet( dev );
-+ smc_hardware_send_packet(dev);
-
- /* enable xmit interrupts based on this */
-- mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
-+ mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
-
- /* and let the card send more packets to me */
- netif_wake_queue(dev);
-
-- PRINTK2((CARDNAME": Handoff done successfully.\n"));
-- } else if (status & IM_RX_OVRN_INT ) {
-+ PRINTK2(("%s: Handoff done successfully.\n",
-+ dev->name));
-+ } else if (status & IM_RX_OVRN_INT) {
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
-- outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
-- } else if (status & IM_EPH_INT ) {
-- PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
-- } else if (status & IM_ERCV_INT ) {
-- PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
-- outb( IM_ERCV_INT, ioaddr + INTERRUPT );
-+ smc_outb(IM_RX_OVRN_INT, ioaddr, INTERRUPT);
-+ } else if (status & IM_EPH_INT) {
-+ PRINTK(("%s: UNSUPPORTED: EPH INTERRUPT\n",
-+ dev->name));
-+ } else if (status & IM_ERCV_INT) {
-+ PRINTK(("%s: UNSUPPORTED: ERCV INTERRUPT\n",
-+ dev->name));
-+ smc_outb(IM_ERCV_INT, ioaddr, INTERRUPT);
- }
-- } while ( timeout -- );
-+ } while (timeout --);
-
-
- /* restore state register */
-- SMC_SELECT_BANK( 2 );
-- outb( mask, ioaddr + INT_MASK );
-+ SMC_SELECT_BANK(2);
-+ SMC_SET_INT(mask);
-
-- PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
-- outw( saved_pointer, ioaddr + POINTER );
-+ PRINTK3((KERN_WARNING "%s: MASK is now %x\n", dev->name, mask));
-+ smc_outw(saved_pointer, ioaddr, POINTER);
-
-- SMC_SELECT_BANK( saved_bank );
-+ SMC_SELECT_BANK(saved_bank);
-
-- PRINTK3((CARDNAME ": Interrupt done\n"));
-+ PRINTK3(("%s: Interrupt done\n", dev->name));
- return;
- }
-
- /*-------------------------------------------------------------
- .
-- . smc_rcv - receive a packet from the card
-+ . smc_rcv - receive a packet from the card
- .
-- . There is ( at least ) a packet waiting to be read from
-+ . There is (at least) a packet waiting to be read from
- . chip-memory.
- .
- . o Read the status
-@@ -1272,55 +1729,57 @@
- static void smc_rcv(struct net_device *dev)
- {
- struct smc_local *lp = (struct smc_local *)dev->priv;
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- int packet_number;
- word status;
- word packet_length;
-
- /* assume bank 2 */
-
-- packet_number = inw( ioaddr + FIFO_PORTS );
-+ packet_number = smc_inw(ioaddr, FIFO_PORTS);
-
-- if ( packet_number & FP_RXEMPTY ) {
-+ if (packet_number & FP_RXEMPTY) {
- /* we got called , but nothing was on the FIFO */
-- PRINTK((CARDNAME ": WARNING: smc_rcv with nothing on FIFO. \n"));
-+ PRINTK(("%s: WARNING: smc_rcv with nothing on FIFO.\n",
-+ dev->name));
- /* don't need to restore anything */
- return;
- }
-
- /* start reading from the start of the packet */
-- outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );
-+ smc_outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr, POINTER);
-
- /* First two words are status and packet_length */
-- status = inw( ioaddr + DATA_1 );
-- packet_length = inw( ioaddr + DATA_1 );
-+ status = smc_inw(ioaddr, DATA_1);
-+ packet_length = smc_inw(ioaddr, DATA_1);
-
- packet_length &= 0x07ff; /* mask off top bits */
-
-- PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ));
-+ PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length));
- /*
- . the packet length contains 3 extra words :
- . status, length, and an extra word with an odd byte .
- */
- packet_length -= 6;
-
-- if ( !(status & RS_ERRORS ) ){
-+ if (!(status & RS_ERRORS)){
- /* do stuff to make a new packet */
- struct sk_buff * skb;
- byte * data;
-
- /* read one extra byte */
-- if ( status & RS_ODDFRAME )
-+ if (status & RS_ODDFRAME)
- packet_length++;
-
- /* set multicast stats */
-- if ( status & RS_MULTICAST )
-+ if (status & RS_MULTICAST)
- lp->stats.multicast++;
-
-- skb = dev_alloc_skb( packet_length + 5);
-+ skb = dev_alloc_skb(packet_length + 5);
-
-- if ( skb == NULL ) {
-- printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n");
-+ if (skb == NULL) {
-+ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
-+ dev->name);
- lp->stats.rx_dropped++;
- goto done;
- }
-@@ -1330,36 +1789,15 @@
- ! in the worse case
- */
-
-- skb_reserve( skb, 2 ); /* 16 bit alignment */
-+ skb_reserve(skb, 2); /* 16 bit alignment */
-
- skb->dev = dev;
-- data = skb_put( skb, packet_length);
-+ data = skb_put(skb, packet_length);
-
--#ifdef USE_32_BIT
-- /* QUESTION: Like in the TX routine, do I want
-- to send the DWORDs or the bytes first, or some
-- mixture. A mixture might improve already slow PIO
-- performance */
-- PRINTK3((" Reading %d dwords (and %d bytes) \n",
-- packet_length >> 2, packet_length & 3 ));
-- insl(ioaddr + DATA_1 , data, packet_length >> 2 );
-- /* read the left over bytes */
-- insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC),
-- packet_length & 0x3 );
--#else
-- PRINTK3((" Reading %d words and %d byte(s) \n",
-- (packet_length >> 1 ), packet_length & 1 ));
-- insw(ioaddr + DATA_1 , data, packet_length >> 1);
-- if ( packet_length & 1 ) {
-- data += packet_length & ~1;
-- *(data++) = inb( ioaddr + DATA_1 );
-- }
--#endif
--#if SMC_DEBUG > 2
-- print_packet( data, packet_length );
--#endif
-+ smc_ins(ioaddr, DATA_1, data, packet_length);
-+ print_packet(data, packet_length);
-
-- skb->protocol = eth_type_trans(skb, dev );
-+ skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
-@@ -1368,15 +1806,17 @@
- /* error ... */
- lp->stats.rx_errors++;
-
-- if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++;
-- if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
-+ if (status & RS_ALGNERR)
-+ lp->stats.rx_frame_errors++;
-+ if (status & (RS_TOOSHORT | RS_TOOLONG))
- lp->stats.rx_length_errors++;
-- if ( status & RS_BADCRC) lp->stats.rx_crc_errors++;
-+ if (status & RS_BADCRC)
-+ lp->stats.rx_crc_errors++;
- }
-
- done:
- /* error or good, tell the card to get rid of this packet */
-- outw( MC_RELEASE, ioaddr + MMU_CMD );
-+ smc_outw(MC_RELEASE, ioaddr, MMU_CMD);
- }
-
-
-@@ -1389,62 +1829,64 @@
- . Algorithm:
- . Save pointer and packet no
- . Get the packet no from the top of the queue
-- . check if it's valid ( if not, is this an error??? )
-+ . check if it's valid (if not, is this an error???)
- . read the status word
- . record the error
-- . ( resend? Not really, since we don't want old packets around )
-+ . (resend? Not really, since we don't want old packets around)
- . Restore saved values
- ************************************************************************/
--static void smc_tx( struct net_device * dev )
-+static void smc_tx(struct net_device * dev)
- {
-- int ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
- struct smc_local *lp = (struct smc_local *)dev->priv;
- byte saved_packet;
- byte packet_no;
- word tx_status;
-
-
-- /* assume bank 2 */
-+ /* assume bank 2 */
-
-- saved_packet = inb( ioaddr + PNR_ARR );
-- packet_no = inw( ioaddr + FIFO_PORTS );
-+ saved_packet = smc_inb(ioaddr, PNR_ARR);
-+ packet_no = smc_inw(ioaddr, FIFO_PORTS);
- packet_no &= 0x7F;
-
- /* select this as the packet to read from */
-- outb( packet_no, ioaddr + PNR_ARR );
-+ smc_outb(packet_no, ioaddr, PNR_ARR);
-
- /* read the first word from this packet */
-- outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER );
-+ smc_outw(PTR_AUTOINC | PTR_READ, ioaddr, POINTER);
-
-- tx_status = inw( ioaddr + DATA_1 );
-- PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status ));
-+ tx_status = smc_inw(ioaddr, DATA_1);
-+ PRINTK3(("%s: TX DONE STATUS: %4x\n", dev->name, tx_status));
-
- lp->stats.tx_errors++;
-- if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++;
-- if ( tx_status & TS_LATCOL ) {
-- printk(KERN_DEBUG CARDNAME
-- ": Late collision occurred on last xmit.\n");
-+ if (tx_status & TS_LOSTCAR)
-+ lp->stats.tx_carrier_errors++;
-+ if (tx_status & TS_LATCOL) {
-+ printk(KERN_DEBUG "%s: Late collision occurred on "
-+ "last xmit.\n", dev->name);
- lp->stats.tx_window_errors++;
- }
- #if 0
-- if ( tx_status & TS_16COL ) { ... }
-+ if (tx_status & TS_16COL) { ... }
- #endif
-
-- if ( tx_status & TS_SUCCESS ) {
-- printk(CARDNAME": Successful packet caused interrupt \n");
-+ if (tx_status & TS_SUCCESS) {
-+ printk("%s: Successful packet caused interrupt\n",
-+ dev->name);
- }
- /* re-enable transmit */
-- SMC_SELECT_BANK( 0 );
-- outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR );
-+ SMC_SELECT_BANK(0);
-+ smc_outw(smc_inw(ioaddr, TCR) | TCR_ENABLE, ioaddr, TCR);
-
- /* kill the packet */
-- SMC_SELECT_BANK( 2 );
-- outw( MC_FREEPKT, ioaddr + MMU_CMD );
-+ SMC_SELECT_BANK(2);
-+ smc_outw(MC_FREEPKT, ioaddr, MMU_CMD);
-
- /* one less packet waiting for me */
- lp->packets_waiting--;
-
-- outb( saved_packet, ioaddr + PNR_ARR );
-+ smc_outb(saved_packet, ioaddr, PNR_ARR);
- return;
- }
-
-@@ -1460,7 +1902,7 @@
- {
- netif_stop_queue(dev);
- /* clear everything */
-- smc_shutdown( dev->base_addr );
-+ smc_shutdown(dev);
-
- /* Update the statistics here. */
- return 0;
-@@ -1481,16 +1923,16 @@
- .
- . This routine will, depending on the values passed to it,
- . either make it accept multicast packets, go into
-- . promiscuous mode ( for TCPDUMP and cousins ) or accept
-+ . promiscuous mode (for TCPDUMP and cousins) or accept
- . a select set of multicast packets
- */
- static void smc_set_multicast_list(struct net_device *dev)
- {
-- short ioaddr = dev->base_addr;
-+ u_int ioaddr = dev->base_addr;
-
- SMC_SELECT_BANK(0);
-- if ( dev->flags & IFF_PROMISC )
-- outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
-+ if (dev->flags & IFF_PROMISC)
-+ smc_outw(smc_inw(ioaddr, RCR) | RCR_PROMISC, ioaddr, RCR);
-
- /* BUG? I never disable promiscuous mode if multicasting was turned on.
- Now, I turn off promiscuous mode, but I don't do anything to multicasting
-@@ -1502,34 +1944,34 @@
- checked before the table is
- */
- else if (dev->flags & IFF_ALLMULTI)
-- outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
-+ smc_outw(smc_inw(ioaddr, RCR) | RCR_ALMUL, ioaddr, RCR);
-
- /* We just get all multicast packets even if we only want them
- . from one source. This will be changed at some future
- . point. */
-- else if (dev->mc_count ) {
-+ else if (dev->mc_count) {
- /* support hardware multicasting */
-
- /* be sure I get rid of flags I might have set */
-- outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
-- ioaddr + RCR );
-+ smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
-+ ioaddr, RCR);
- /* NOTE: this has to set the bank, so make sure it is the
- last thing called. The bank is set to zero at the top */
-- smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
-+ smc_setmulticast(dev, dev->mc_count, dev->mc_list);
- }
-- else {
-- outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
-- ioaddr + RCR );
-+ else {
-+ smc_outw(smc_inw(ioaddr, RCR) & ~(RCR_PROMISC | RCR_ALMUL),
-+ ioaddr, RCR);
-
- /*
- since I'm disabling all multicast entirely, I need to
- clear the multicast list
- */
-- SMC_SELECT_BANK( 3 );
-- outw( 0, ioaddr + MULTICAST1 );
-- outw( 0, ioaddr + MULTICAST2 );
-- outw( 0, ioaddr + MULTICAST3 );
-- outw( 0, ioaddr + MULTICAST4 );
-+ SMC_SELECT_BANK(3);
-+ smc_outw(0, ioaddr, MULTICAST1);
-+ smc_outw(0, ioaddr, MULTICAST2);
-+ smc_outw(0, ioaddr, MULTICAST3);
-+ smc_outw(0, ioaddr, MULTICAST4);
- }
- }
-
-@@ -1550,21 +1992,26 @@
-
- int init_module(void)
- {
-- int result;
--
- if (io == 0)
-- printk(KERN_WARNING
-- CARDNAME": You shouldn't use auto-probing with insmod!\n" );
-+ printk(KERN_WARNING CARDNAME
-+ ": You shouldn't use auto-probing with insmod!\n");
-+
-+ /*
-+ * Note: dev->if_port has changed to be 2.4 compliant.
-+ * We keep the ifport insmod parameter the same though.
-+ */
-+ switch (ifport) {
-+ case 1: devSMC9194.if_port = IF_PORT_10BASET; break;
-+ case 2: devSMC9194.if_port = IF_PORT_AUI; break;
-+ default: devSMC9194.if_port = 0; break;
-+ }
-
- /* copy the parameters from insmod into the device structure */
- devSMC9194.base_addr = io;
- devSMC9194.irq = irq;
-- devSMC9194.if_port = ifport;
-- devSMC9194.init = smc_init;
-- if ((result = register_netdev(&devSMC9194)) != 0)
-- return result;
-+ devSMC9194.init = smc_init;
-
-- return 0;
-+ return register_netdev(&devSMC9194);
- }
-
- void cleanup_module(void)
---- linux-2.4.27/drivers/net/smc9194.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/net/smc9194.h
-@@ -63,10 +63,11 @@
-
- #define TCR 0 /* transmit control register */
- #define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
-+#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
-+#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
- #define TCR_FDUPLX 0x0800 /* receive packets sent out */
- #define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
--#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
--#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
-+#define TCR_FDSE 0x8000 /* full duplex, switched ethernet */
-
- #define TCR_CLEAR 0 /* do NOTHING */
- /* the normal settings for the TCR register : */
-@@ -107,7 +108,10 @@
- #define CTL_CR_ENABLE 0x40
- #define CTL_TE_ENABLE 0x0020
- #define CTL_AUTO_RELEASE 0x0800
--#define CTL_EPROM_ACCESS 0x0003 /* high if Eprom is being read */
-+#define CTL_EPROM_SELECT 0x0004
-+#define CTL_EPROM_RELOAD 0x0002
-+#define CTL_EPROM_STORE 0x0001
-+#define CTL_EPROM_ACCESS (CTL_EPROM_RELOAD | CTL_EPROM_STORE) /* high if Eprom is being read */
-
- /* BANK 2 */
- #define MMU_CMD 0
-@@ -130,7 +134,6 @@
- #define PTR_READ 0x2000
- #define PTR_RCV 0x8000
- #define PTR_AUTOINC 0x4000
--#define PTR_AUTO_INC 0x0040
-
- #define DATA_1 8
- #define DATA_2 10
-@@ -162,17 +165,6 @@
- #define CHIP_9195 5
- #define CHIP_91100 7
-
--static const char * chip_ids[ 15 ] = {
-- NULL, NULL, NULL,
-- /* 3 */ "SMC91C90/91C92",
-- /* 4 */ "SMC91C94",
-- /* 5 */ "SMC91C95",
-- NULL,
-- /* 7 */ "SMC91C100",
-- /* 8 */ "SMC91C100FD",
-- NULL, NULL, NULL,
-- NULL, NULL, NULL};
--
- /*
- . Transmit status bits
- */
-@@ -192,40 +184,20 @@
- #define RS_MULTICAST 0x0001
- #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
-
--static const char * interfaces[ 2 ] = { "TP", "AUI" };
--
--/*-------------------------------------------------------------------------
-- . I define some macros to make it easier to do somewhat common
-- . or slightly complicated, repeated tasks.
-- --------------------------------------------------------------------------*/
--
--/* select a register bank, 0 to 3 */
--
--#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); }
--
--/* define a small delay for the reset */
--#define SMC_DELAY() { inw( ioaddr + RCR );\
-- inw( ioaddr + RCR );\
-- inw( ioaddr + RCR ); }
--
--/* this enables an interrupt in the interrupt mask register */
--#define SMC_ENABLE_INT(x) {\
-- unsigned char mask;\
-- SMC_SELECT_BANK(2);\
-- mask = inb( ioaddr + INT_MASK );\
-- mask |= (x);\
-- outb( mask, ioaddr + INT_MASK ); \
--}
--
--/* this disables an interrupt from the interrupt mask register */
-+/*
-+ * SMC91C96 ethernet config and status registers.
-+ * These are in the "attribute" space.
-+ */
-+#define ECOR 0x8000
-+#define ECOR_RESET 0x80
-+#define ECOR_LEVEL_IRQ 0x40
-+#define ECOR_WR_ATTRIB 0x04
-+#define ECOR_ENABLE 0x01
-
--#define SMC_DISABLE_INT(x) {\
-- unsigned char mask;\
-- SMC_SELECT_BANK(2);\
-- mask = inb( ioaddr + INT_MASK );\
-- mask &= ~(x);\
-- outb( mask, ioaddr + INT_MASK ); \
--}
-+#define ECSR 0x8002
-+#define ECSR_IOIS8 0x20
-+#define ECSR_PWRDWN 0x04
-+#define ECSR_INT 0x02
-
- /*----------------------------------------------------------------------
- . Define the interrupts that I want to receive from the card
-@@ -237,5 +209,36 @@
- --------------------------------------------------------------------------*/
- #define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT)
-
-+/* store this information for the driver.. */
-+struct smc_local {
-+ /*
-+ these are things that the kernel wants me to keep, so users
-+ can find out semi-useless statistics of how well the card is
-+ performing
-+ */
-+ struct net_device_stats stats;
-+
-+ /*
-+ If I have to wait until memory is available to send
-+ a packet, I will store the skbuff here, until I get the
-+ desired memory. Then, I'll send it out and free it.
-+ */
-+ struct sk_buff * saved_skb;
-+
-+ /*
-+ . This keeps track of how many packets that I have
-+ . sent out. When an TX_EMPTY interrupt comes, I know
-+ . that all of these have been sent.
-+ */
-+ int packets_waiting;
-+
-+ /*
-+ . Interface status. These correspond to the parameters
-+ . in the ethtool_cmd structure.
-+ */
-+ u8 duplex;
-+ u8 port;
-+};
-+
- #endif /* _SMC_9194_H_ */
-
---- linux-2.4.27/drivers/parport/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/parport/Config.in
-@@ -27,7 +27,8 @@
- dep_tristate ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA $CONFIG_PCMCIA $CONFIG_PARPORT_PC $CONFIG_HOTPLUG
- fi
- if [ "$CONFIG_ARM" = "y" ]; then
-- dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
-+ dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT $CONFIG_ARCH_ARC
-+ dep_tristate ' Accelent SA1110 IDP' CONFIG_PARPORT_IDP $CONFIG_PARPORT $CONFIG_SA1100_ACCELENT
- fi
- if [ "$CONFIG_AMIGA" = "y" ]; then
- dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
---- linux-2.4.27/drivers/parport/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/parport/Makefile
-@@ -28,6 +28,7 @@
- obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
- obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
- obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
-+obj-$(CONFIG_PARPORT_IDP) += parport_idp.o
- obj-$(CONFIG_PARPORT_IP22) += parport_ip22.o
-
- include $(TOPDIR)/Rules.make
---- linux-2.4.27/drivers/parport/init.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/parport/init.c
-@@ -164,6 +164,9 @@
- #ifdef CONFIG_PARPORT_SUNBPP
- parport_sunbpp_init();
- #endif
-+#ifdef CONFIG_PARPORT_IDP
-+ parport_idp_init();
-+#endif
- return 0;
- }
-
---- /dev/null
-+++ linux-2.4.27/drivers/parport/parport_idp.c
-@@ -0,0 +1,247 @@
-+/* Low-level polled-mode parallel port routines for the Accelent IDP
-+ *
-+ * Author: Rich Dulabahn <rich@accelent.com>
-+ *
-+ * Inspiration taken from parport_amiga.c and parport_atari.c.
-+ *
-+ * To use, under menuconfig:
-+ * 1) Turn on <*> Accelent IDP under Parallel port setup
-+ * 2) Turn on <*> Parallel printer support under Character devices
-+ *
-+ * This will give you parport0 configured as /dev/lp0
-+ *
-+ * To make the correct /dev/lp* entries, enter /dev and type this:
-+ *
-+ * mknod lp0 c 6 0
-+ * mknod lp1 c 6 1
-+ * mknod lp2 c 6 2
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/parport.h>
-+#include <asm/hardware.h>
-+
-+/*
-+ * Parallel data port is port H, data
-+ * Parallel data direction is port H, direction
-+ * Control port is port I, data, lowest 4 bits
-+ * Status port is port G, data, upper 5 bits
-+ */
-+
-+#define INPUTPOWERHANDLER 0
-+/* masks */
-+#define CONTROL_MASK 0x0f
-+#define STATUS_MASK 0xf8
-+
-+#undef DEBUG
-+
-+#ifdef DEBUG
-+#define DPRINTK printk
-+#else
-+#define DPRINTK(stuff...)
-+#endif
-+
-+static struct parport *this_port = NULL;
-+
-+static unsigned char
-+parport_idp_read_data(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTH_DATA;
-+ DPRINTK("read_data:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_write_data(struct parport *p, unsigned char data)
-+{
-+ IDP_FPGA_PORTH_DATA = data;
-+ DPRINTK("write_data:0x%x\n",data);
-+}
-+
-+static unsigned char
-+parport_idp_read_control(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTI_DATA & CONTROL_MASK;
-+ DPRINTK("read_control:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_write_control(struct parport *p, unsigned char control)
-+{
-+ unsigned int temp;
-+
-+ temp = IDP_FPGA_PORTH_DATA;
-+ temp &= ~CONTROL_MASK;
-+ IDP_FPGA_PORTI_DATA = (temp | (control & CONTROL_MASK));
-+DPRINTK("write_control:0x%x\n",control);
-+}
-+
-+static unsigned char
-+parport_idp_frob_control(struct parport *p, unsigned char mask,
-+ unsigned char val)
-+{
-+ unsigned char c;
-+
-+/* From the parport-lowlevel.txt file...*/
-+/* This is equivalent to reading from the control register, masking out
-+the bits in mask, exclusive-or'ing with the bits in val, and writing
-+the result to the control register. */
-+
-+/* Easy enough, right? */
-+
-+ c = parport_idp_read_control(p);
-+ parport_idp_write_control(p, (c & ~mask) ^ val);
-+ DPRINTK("frob_control:0x%x\n",c);
-+ return c;
-+}
-+
-+static unsigned char
-+parport_idp_read_status(struct parport *p)
-+{
-+ unsigned char c;
-+
-+ c = IDP_FPGA_PORTG_DATA & STATUS_MASK;
-+ c ^= 0x80; /* toggle S7 bit, active low */
-+ DPRINTK("read_status:0x%x\n",c);
-+ return c;
-+}
-+
-+static void
-+parport_idp_init_state(struct pardevice *d, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_save_state(struct parport *p, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_restore_state(struct parport *p, struct parport_state *s)
-+{
-+}
-+
-+static void
-+parport_idp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+}
-+
-+static void
-+parport_idp_enable_irq(struct parport *p)
-+{
-+}
-+
-+static void
-+parport_idp_disable_irq(struct parport *p)
-+{
-+}
-+
-+static void
-+parport_idp_data_forward(struct parport *p)
-+{
-+ IDP_FPGA_PORTH_DIR = 0x00; /* 0 sets to output */
-+ DPRINTK("data_forward:0x%x\n",0);
-+}
-+
-+static void
-+parport_idp_data_reverse(struct parport *p)
-+{
-+ IDP_FPGA_PORTH_DIR = 0xff; /* and 1 sets to input */
-+ DPRINTK("data_reverse:0x%x\n",0xff);
-+}
-+
-+static void
-+parport_idp_inc_use_count(void)
-+{
-+ MOD_INC_USE_COUNT;
-+}
-+
-+static void
-+parport_idp_dec_use_count(void)
-+{
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static struct parport_operations parport_idp_ops = {
-+ parport_idp_write_data,
-+ parport_idp_read_data,
-+
-+ parport_idp_write_control,
-+ parport_idp_read_control,
-+ parport_idp_frob_control,
-+
-+ parport_idp_read_status,
-+
-+ parport_idp_enable_irq,
-+ parport_idp_disable_irq,
-+
-+ parport_idp_data_forward,
-+ parport_idp_data_reverse,
-+
-+ parport_idp_init_state,
-+ parport_idp_save_state,
-+ parport_idp_restore_state,
-+
-+ parport_idp_inc_use_count,
-+ parport_idp_dec_use_count,
-+
-+ parport_ieee1284_epp_write_data,
-+ parport_ieee1284_epp_read_data,
-+ parport_ieee1284_epp_write_addr,
-+ parport_ieee1284_epp_read_addr,
-+
-+ parport_ieee1284_ecp_write_data,
-+ parport_ieee1284_ecp_read_data,
-+ parport_ieee1284_ecp_write_addr,
-+
-+ parport_ieee1284_write_compat,
-+ parport_ieee1284_read_nibble,
-+ parport_ieee1284_read_byte,
-+};
-+
-+
-+int __init
-+parport_idp_init(void)
-+{
-+ struct parport *p;
-+
-+ p = parport_register_port((unsigned long)0,PARPORT_IRQ_NONE,PARPORT_DMA_NONE,&parport_idp_ops);
-+
-+ if (!p) return 0; /* return 0 on failure */
-+
-+ this_port=p;
-+ printk("%s: Accelent IDP parallel port registered.\n", p->name);
-+ parport_proc_register(p);
-+ parport_announce_port(p);
-+
-+ return 1;
-+}
-+
-+#ifdef MODULE
-+
-+MODULE_AUTHOR("Rich Dulabahn");
-+MODULE_DESCRIPTION("Parport Driver for Accelent IDP");
-+MODULE_SUPPORTED_DEVICE("Accelent IDP builtin Parallel Port");
-+MODULE_LICENSE("GPL");
-+
-+int
-+init_module(void)
-+{
-+ return parport_idp_init() ? 0 : -ENODEV;
-+}
-+
-+void
-+cleanup_module(void)
-+{
-+ parport_proc_unregister(this_port);
-+ parport_unregister_port(this_port);
-+}
-+#endif
-+
---- linux-2.4.27/drivers/pci/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pci/Makefile
-@@ -13,7 +13,7 @@
-
- export-objs := pci.o
-
--obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
-+obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o bridge.o
- obj-$(CONFIG_PROC_FS) += proc.o
-
- ifndef CONFIG_SPARC64
---- /dev/null
-+++ linux-2.4.27/drivers/pci/bridge.c
-@@ -0,0 +1,149 @@
-+
-+/*
-+ * Copyright (c) 2001 Red Hat, Inc. All rights reserved.
-+ *
-+ * This software may be freely redistributed under the terms
-+ * of the GNU public license.
-+ *
-+ * You 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.
-+ *
-+ * Author: Arjan van de Ven <arjanv@redhat.com>
-+ *
-+ */
-+
-+
-+/*
-+ * Generic PCI driver for PCI bridges for powermanagement purposes
-+ *
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+
-+static struct pci_device_id bridge_pci_table[] __devinitdata = {
-+ {/* handle all PCI bridges */
-+ class: ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00),
-+ class_mask: ~0,
-+ vendor: PCI_ANY_ID,
-+ device: PCI_ANY_ID,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+ },
-+ {0,},
-+};
-+
-+static int bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force);
-+int pci_generic_resume_compare(struct pci_dev *pdev);
-+
-+int pci_bridge_force_restore = 0;
-+
-+
-+
-+
-+static int __init bridge_setup(char *str)
-+{
-+ if (!strcmp(str,"force"))
-+ pci_bridge_force_restore = 1;
-+ else if (!strcmp(str,"noforce"))
-+ pci_bridge_force_restore = 0;
-+ return 0;
-+}
-+
-+__setup("resume=",bridge_setup);
-+
-+
-+static int pci_bridge_save_state_bus(struct pci_bus *bus, int force)
-+{
-+ struct list_head *list;
-+ int error = 0;
-+
-+ list_for_each(list, &bus->children) {
-+ error = pci_bridge_save_state_bus(pci_bus_b(list),force);
-+ if (error) return error;
-+ }
-+ list_for_each(list, &bus->devices) {
-+ pci_generic_suspend_save(pci_dev_b(list),0);
-+ }
-+ return 0;
-+}
-+
-+
-+static int pci_bridge_restore_state_bus(struct pci_bus *bus, int force)
-+{
-+ struct list_head *list;
-+ int error = 0;
-+ static int printed_warning=0;
-+
-+ list_for_each(list, &bus->children) {
-+ error = pci_bridge_restore_state_bus(pci_bus_b(list),force);
-+ if (error) return error;
-+ }
-+ list_for_each(list, &bus->devices) {
-+ if (force)
-+ pci_generic_resume_restore(pci_dev_b(list));
-+ else {
-+ error = pci_generic_resume_compare(pci_dev_b(list));
-+ if (error && !printed_warning++) {
-+ printk(KERN_WARNING "resume warning: bios doesn't restore PCI state properly\n");
-+ printk(KERN_WARNING "resume warning: if resume failed, try booting with resume=force\n");
-+ }
-+ if (error)
-+ return error;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int bridge_suspend(struct pci_dev *dev, u32 force)
-+{
-+ pci_generic_suspend_save(dev,force);
-+ if (dev->subordinate)
-+ pci_bridge_save_state_bus(dev->subordinate,force);
-+ return 0;
-+}
-+
-+static int bridge_resume(struct pci_dev *dev)
-+{
-+
-+ pci_generic_resume_restore(dev);
-+ if (dev->subordinate)
-+ pci_bridge_restore_state_bus(dev->subordinate,pci_bridge_force_restore);
-+ return 0;
-+}
-+
-+
-+MODULE_DEVICE_TABLE(pci, bridge_pci_table);
-+static struct pci_driver bridge_ops = {
-+ name: "PCI Bridge",
-+ id_table: bridge_pci_table,
-+ probe: bridge_probe,
-+ suspend: bridge_suspend,
-+ resume: bridge_resume
-+};
-+
-+static int __devinit bridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-+{
-+ return 0;
-+}
-+
-+static int __init bridge_init(void)
-+{
-+ pci_register_driver(&bridge_ops);
-+ return 0;
-+}
-+
-+static void __exit bridge_exit(void)
-+{
-+ pci_unregister_driver(&bridge_ops);
-+}
-+
-+
-+module_init(bridge_init)
-+module_exit(bridge_exit)
-+
---- linux-2.4.27/drivers/pci/pci.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pci/pci.c
-@@ -359,6 +359,48 @@
- return 0;
- }
-
-+int
-+pci_compare_state(struct pci_dev *dev, u32 *buffer)
-+{
-+ int i;
-+ unsigned int temp;
-+
-+ if (buffer) {
-+ for (i = 0; i < 16; i++) {
-+ pci_read_config_dword(dev,i*4,&temp);
-+ if (temp!=buffer[i])
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state)
-+{
-+ if (pdev)
-+ pci_save_state(pdev,pdev->saved_state);
-+ return 0;
-+}
-+
-+int pci_generic_resume_restore(struct pci_dev *pdev)
-+{
-+ if (pdev)
-+ pci_restore_state(pdev,pdev->saved_state);
-+ return 0;
-+}
-+
-+int pci_generic_resume_compare(struct pci_dev *pdev)
-+{
-+ int retval=0;
-+ if (pdev)
-+ retval = pci_compare_state(pdev,pdev->saved_state);
-+ return retval;
-+}
-+
-+EXPORT_SYMBOL(pci_generic_suspend_save);
-+EXPORT_SYMBOL(pci_generic_resume_restore);
-+EXPORT_SYMBOL(pci_generic_resume_compare);
-+
- /**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
---- linux-2.4.27/drivers/pci/setup-bus.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pci/setup-bus.c
-@@ -12,6 +12,8 @@
- /*
- * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
- * PCI-PCI bridges cleanup, sorted resource allocation.
-+ * May 2001, Russell King <rmk@arm.linux.org.uk>
-+ * Allocate prefetchable memory regions where available.
- * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
- * Converted to allocation in 3 passes, which gives
- * tighter packing. Prefetchable range support.
-@@ -160,8 +162,10 @@
- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
-
- /* Check if we have VGA behind the bridge.
-- Enable ISA in either case (FIXME!). */
-- l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
-+ Enable ISA in either case. */
-+ l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ?
-+ PCI_BRIDGE_CTL_VGA | PCI_BRIDGE_CTL_NO_ISA :
-+ PCI_BRIDGE_CTL_NO_ISA;
- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
- }
-
---- linux-2.4.27/drivers/pcmcia/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/Config.in
-@@ -14,21 +14,19 @@
-
- tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA
- if [ "$CONFIG_PCMCIA" != "n" ]; then
-+ # yes, I really mean the following...
-+ if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ define_bool CONFIG_PCMCIA_PROBE y
-+ fi
- if [ "$CONFIG_PCI" != "n" ]; then
- bool ' CardBus support' CONFIG_CARDBUS
- fi
-+ dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
-+ bool ' i82365 compatible bridge support' CONFIG_I82365
- bool ' Databook TCIC host bridge support' CONFIG_TCIC
- if [ "$CONFIG_HD64465" = "y" ]; then
- dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
- fi
-- dep_bool ' i82092 compatible bridge support' CONFIG_I82092 $CONFIG_PCI
-- bool ' i82365 compatible bridge support' CONFIG_I82365
-- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_PCMCIA
-- fi
-- if [ "$CONFIG_8xx" = "y" ]; then
-- dep_tristate ' M8xx support' CONFIG_PCMCIA_M8XX $CONFIG_PCMCIA
-- fi
- if [ "$CONFIG_SOC_AU1X00" = "y" ]; then
- dep_tristate ' Au1x00 PCMCIA support' CONFIG_PCMCIA_AU1X00 $CONFIG_PCMCIA
- if [ "$CONFIG_PCMCIA_AU1X00" != "n" ]; then
-@@ -44,5 +42,9 @@
- dep_tristate ' NEC VRC4173 CARDU support' CONFIG_PCMCIA_VRC4173 $CONFIG_PCMCIA
- fi
- fi
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ dep_tristate ' CLPS6700 support' CONFIG_PCMCIA_CLPS6700 $CONFIG_ARCH_CLPS711X $CONFIG_PCMCIA
-+ dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
-+fi
-
- endmenu
---- linux-2.4.27/drivers/pcmcia/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/Makefile
-@@ -65,15 +65,18 @@
- au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o
- au1000_ss-objs-$(CONFIG_PCMCIA_XXS1500) += au1000_xxs1500.o
-
-+obj-$(CONFIG_PCMCIA_CLPS6700) += clps6700.o
- obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
--obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
- obj-$(CONFIG_PCMCIA_SIBYTE) += sibyte_generic.o
-
- sa1100_cs-objs-y := sa1100_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_ADSAGC) += sa1100_graphicsmaster.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSYPLUS) += sa1100_adsbitsyplus.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
- sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
-+sa1100_cs-objs-$(CONFIG_SA1100_CONSUS) += sa1100_neponset.o sa1111_generic.o
- sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
- sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
- sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
---- linux-2.4.27/drivers/pcmcia/cistpl.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/cistpl.c
-@@ -286,7 +286,7 @@
- s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
- if (!(s->cap.features & SS_CAP_STATIC_MAP))
-- release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
-+ release_mem_resource(s->cis_mem.sys_start, s->cap.map_size);
- bus_iounmap(s->cap.bus, s->cis_virt);
- s->cis_mem.sys_start = 0;
- s->cis_virt = NULL;
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/clps6700.c
-@@ -0,0 +1,498 @@
-+/*
-+ * linux/drivers/pcmcia/clps6700.c
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/proc_fs.h>
-+#include <linux/spinlock.h>
-+#include <linux/init.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/page.h>
-+
-+#include <asm/arch/syspld.h>
-+#include <asm/hardware/clps7111.h>
-+
-+#include <pcmcia/version.h>
-+#include <pcmcia/cs_types.h>
-+#include <pcmcia/ss.h>
-+
-+#include "clps6700.h"
-+
-+#define DEBUG
-+
-+MODULE_AUTHOR("Russell King");
-+MODULE_DESCRIPTION("CL-PS6700 PCMCIA socket driver");
-+
-+#define NR_CLPS6700 2
-+
-+struct clps6700_skt {
-+ u_int nr;
-+ u_int physbase;
-+ u_int regbase;
-+ u_int pmr;
-+ u_int cpcr;
-+ u_int cpcr_3v3;
-+ u_int cpcr_5v0;
-+ u_int cur_pmr;
-+ u_int cur_cicr;
-+ u_int cur_pcimr;
-+ u_int cur_cpcr;
-+ void (*handler)(void *, u_int);
-+ void *handler_info;
-+
-+ u_int ev_pending;
-+ spinlock_t ev_lock;
-+};
-+
-+static struct clps6700_skt *skts[NR_CLPS6700];
-+
-+static int clps6700_sock_init(u_int sock)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+ skt->cur_cicr = 0;
-+ skt->cur_pmr = skt->pmr;
-+ skt->cur_pcimr = 0;
-+ skt->cur_cpcr = skt->cpcr;
-+
-+#ifdef DEBUG
-+ printk("skt%d: sock_init()\n", sock);
-+#endif
-+
-+ __raw_writel(skt->cur_pmr, skt->regbase + PMR);
-+ __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
-+ __raw_writel(0x01f8, skt->regbase + SICR);
-+ __raw_writel(0x0000, skt->regbase + DMACR);
-+ __raw_writel(skt->cur_cicr, skt->regbase + CICR);
-+ __raw_writel(0x1f00, skt->regbase + CITR0A);
-+ __raw_writel(0x0000, skt->regbase + CITR0B);
-+ __raw_writel(0x1f00, skt->regbase + CITR1A);
-+ __raw_writel(0x0000, skt->regbase + CITR1B);
-+ __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
-+
-+ /*
-+ * Enable Auto Idle Mode in PM register
-+ */
-+ __raw_writel(-1, skt->regbase + PCIRR1);
-+ __raw_writel(-1, skt->regbase + PCIRR2);
-+ __raw_writel(-1, skt->regbase + PCIRR3);
-+
-+ return 0;
-+}
-+
-+static int clps6700_suspend(u_int sock)
-+{
-+ return 0;
-+}
-+
-+static int clps6700_register_callback(u_int sock, void (*handler)(void *, u_int), void *info)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+#ifdef DEBUG
-+ printk("skt%d: register_callback: %p (%p)\n", sock, handler, info);
-+#endif
-+
-+ skt->handler_info = info;
-+ skt->handler = handler;
-+
-+ return 0;
-+}
-+
-+static int clps6700_inquire_socket(u_int sock, socket_cap_t *cap)
-+{
-+ cap->features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN;
-+ cap->irq_mask = 0; /* available IRQs for this socket */
-+ cap->map_size = PAGE_SIZE; /* minimum mapping size */
-+ cap->pci_irq = 0; /* PCI interrupt number */
-+ cap->cb_dev = NULL;
-+ cap->bus = NULL;
-+ return 0;
-+}
-+
-+static int __clps6700_get_status(struct clps6700_skt *skt)
-+{
-+ unsigned int v, val;
-+
-+ v = __raw_readl(skt->regbase + PCIILR);
-+ val = 0;
-+ if ((v & (PCM_CD1 | PCM_CD2)) == 0)
-+ val |= SS_DETECT;
-+ if ((v & (PCM_BVD2 | PCM_BVD1)) == PCM_BVD1)
-+ val |= SS_BATWARN;
-+ if ((v & PCM_BVD2) == 0)
-+ val |= SS_BATDEAD;
-+
-+ if (v & PCM_RDYL)
-+ val |= SS_READY;
-+ if (v & PCM_VS1)
-+ val |= SS_3VCARD;
-+ if (v & PCM_VS2)
-+ val |= SS_XVCARD;
-+
-+#ifdef DEBUG
-+ printk("skt%d: PCIILR: %08x -> (%s %s %s %s %s %s)\n",
-+ skt->nr, v,
-+ val & SS_READY ? "rdy" : "---",
-+ val & SS_DETECT ? "det" : "---",
-+ val & SS_BATWARN ? "bw" : "--",
-+ val & SS_BATDEAD ? "bd" : "--",
-+ val & SS_3VCARD ? "3v" : "--",
-+ val & SS_XVCARD ? "xv" : "--");
-+#endif
-+ return val;
-+}
-+
-+static int clps6700_get_status(u_int sock, u_int *valp)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+
-+ *valp = __clps6700_get_status(skt);
-+
-+ return 0; /* not used! */
-+}
-+
-+static int clps6700_get_socket(u_int sock, socket_state_t *state)
-+{
-+ return -EINVAL;
-+}
-+
-+static int clps6700_set_socket(u_int sock, socket_state_t *state)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+ unsigned long flags;
-+ u_int cpcr = skt->cur_cpcr, pmr = skt->cur_pmr, cicr = skt->cur_cicr;
-+ u_int pcimr = 0;
-+
-+ cicr &= ~(CICR_ENABLE | CICR_RESET | CICR_IOMODE);
-+
-+ if (state->flags & SS_PWR_AUTO)
-+ pmr |= PMR_DCAR | PMR_PDCR;
-+
-+ /*
-+ * Note! We must NOT assert the Card Enable bit until reset has
-+ * been de-asserted. Some cards indicate not ready, which then
-+ * hangs our next access. (Bug in CLPS6700?)
-+ */
-+ if (state->flags & SS_RESET)
-+ cicr |= CICR_RESET | CICR_RESETOE;
-+ else if (state->flags & SS_OUTPUT_ENA)
-+ cicr |= CICR_ENABLE;
-+
-+ if (state->flags & SS_IOCARD) {
-+ cicr |= CICR_IOMODE;
-+
-+/* if (state->csc_mask & SS_STSCHG)*/
-+ } else {
-+ if (state->csc_mask & SS_BATDEAD)
-+ pcimr |= PCM_BVD2;
-+ if (state->csc_mask & SS_BATWARN)
-+ pcimr |= PCM_BVD1;
-+ if (state->csc_mask & SS_READY)
-+ pcimr |= PCM_RDYL;
-+ }
-+
-+ if (state->csc_mask & SS_DETECT)
-+ pcimr |= PCM_CD1 | PCM_CD2;
-+
-+ switch (state->Vcc) {
-+ case 0: break;
-+ case 33: cpcr |= skt->cpcr_3v3; pmr |= PMR_CPE; break;
-+ case 50: cpcr |= skt->cpcr_5v0; pmr |= PMR_CPE; break;
-+ default: return -EINVAL;
-+ }
-+
-+#ifdef DEBUG
-+ printk("skt%d: PMR: %04x, CPCR: %04x, CICR: %04x PCIMR: %04x "
-+ "(Vcc = %d, flags = %c%c%c%c, csc = %c%c%c%c%c)\n",
-+ sock, pmr, cpcr, cicr, pcimr, state->Vcc,
-+ state->flags & SS_RESET ? 'r' : '-',
-+ state->flags & SS_PWR_AUTO ? 'p' : '-',
-+ state->flags & SS_IOCARD ? 'i' : '-',
-+ state->flags & SS_OUTPUT_ENA ? 'o' : '-',
-+ state->csc_mask & SS_STSCHG ? 's' : '-',
-+ state->csc_mask & SS_BATDEAD ? 'd' : '-',
-+ state->csc_mask & SS_BATWARN ? 'w' : '-',
-+ state->csc_mask & SS_READY ? 'r' : '-',
-+ state->csc_mask & SS_DETECT ? 'c' : '-');
-+#endif
-+
-+ save_flags_cli(flags);
-+
-+ if (skt->cur_cpcr != cpcr) {
-+ skt->cur_cpcr = cpcr;
-+ __raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
-+ }
-+
-+ if (skt->cur_pmr != pmr) {
-+ skt->cur_pmr = pmr;
-+ __raw_writel(skt->cur_pmr, skt->regbase + PMR);
-+ }
-+ if (skt->cur_pcimr != pcimr) {
-+ skt->cur_pcimr = pcimr;
-+ __raw_writel(skt->cur_pcimr, skt->regbase + PCIMR);
-+ }
-+ if (skt->cur_cicr != cicr) {
-+ skt->cur_cicr = cicr;
-+ __raw_writel(skt->cur_cicr, skt->regbase + CICR);
-+ }
-+
-+ restore_flags(flags);
-+
-+ return 0;
-+}
-+
-+static int clps6700_get_io_map(u_int sock, struct pccard_io_map *io)
-+{
-+ return -EINVAL;
-+}
-+
-+static int clps6700_set_io_map(u_int sock, struct pccard_io_map *io)
-+{
-+ printk("skt%d: iomap: %d: speed %d, flags %X start %X stop %X\n",
-+ sock, io->map, io->speed, io->flags, io->start, io->stop);
-+ return 0;
-+}
-+
-+static int clps6700_get_mem_map(u_int sock, struct pccard_mem_map *mem)
-+{
-+ return -EINVAL;
-+}
-+
-+/*
-+ * Set the memory map attributes for this socket. (ie, mem->speed)
-+ * Note that since we have SS_CAP_STATIC_MAP set, we don't need to do
-+ * any mapping here at all; we just need to return the address (suitable
-+ * for ioremap) to map the requested space in mem->sys_start.
-+ *
-+ * flags & MAP_ATTRIB indicates whether we want attribute space.
-+ */
-+static int clps6700_set_mem_map(u_int sock, struct pccard_mem_map *mem)
-+{
-+ struct clps6700_skt *skt = skts[sock];
-+ u_int off;
-+
-+ printk("skt%d: memmap: %d: speed %d, flags %X start %lX stop %lX card %X\n",
-+ sock, mem->map, mem->speed, mem->flags, mem->sys_start,
-+ mem->sys_stop, mem->card_start);
-+
-+ if (mem->flags & MAP_ATTRIB)
-+ off = CLPS6700_ATTRIB_BASE;
-+ else
-+ off = CLPS6700_MEM_BASE;
-+
-+ mem->sys_start = skt->physbase + off;
-+ mem->sys_start += mem->card_start;
-+
-+ return 0;
-+}
-+
-+static void clps6700_proc_setup(u_int sock, struct proc_dir_entry *base)
-+{
-+}
-+
-+static struct pccard_operations clps6700_operations = {
-+ init: clps6700_sock_init,
-+ suspend: clps6700_suspend,
-+ register_callback: clps6700_register_callback,
-+ inquire_socket: clps6700_inquire_socket,
-+ get_status: clps6700_get_status,
-+ get_socket: clps6700_get_socket,
-+ set_socket: clps6700_set_socket,
-+ get_io_map: clps6700_get_io_map,
-+ set_io_map: clps6700_set_io_map,
-+ get_mem_map: clps6700_get_mem_map,
-+ set_mem_map: clps6700_set_mem_map,
-+ proc_setup: clps6700_proc_setup
-+};
-+
-+static void clps6700_bh(void *dummy)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_CLPS6700; i++) {
-+ struct clps6700_skt *skt = skts[i];
-+ unsigned long flags;
-+ u_int events;
-+
-+ if (!skt)
-+ continue;
-+
-+ /*
-+ * Note! We must read the pending event state
-+ * with interrupts disabled, otherwise we race
-+ * with our own interrupt routine!
-+ */
-+ spin_lock_irqsave(&skt->ev_lock, flags);
-+ events = skt->ev_pending;
-+ skt->ev_pending = 0;
-+ spin_unlock_irqrestore(&skt->ev_lock, flags);
-+
-+ if (skt->handler && events)
-+ skt->handler(skt->handler_info, events);
-+ }
-+}
-+
-+static struct tq_struct clps6700_task = {
-+ routine: clps6700_bh
-+};
-+
-+static void clps6700_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct clps6700_skt *skt = dev_id;
-+ u_int val, events;
-+
-+ val = __raw_readl(skt->regbase + PCISR);
-+ if (!val)
-+ return;
-+
-+ __raw_writel(val, skt->regbase + PCICR);
-+
-+ events = 0;
-+ if (val & (PCM_CD1 | PCM_CD2))
-+ events |= SS_DETECT;
-+ if (val & PCM_BVD1)
-+ events |= SS_BATWARN;
-+ if (val & PCM_BVD2)
-+ events |= SS_BATDEAD;
-+ if (val & PCM_RDYL)
-+ events |= SS_READY;
-+
-+ spin_lock(&skt->ev_lock);
-+ skt->ev_pending |= events;
-+ spin_unlock(&skt->ev_lock);
-+ schedule_task(&clps6700_task);
-+}
-+
-+static int __init clps6700_init_skt(int nr)
-+{
-+ struct clps6700_skt *skt;
-+ int ret;
-+
-+ skt = kmalloc(sizeof(struct clps6700_skt), GFP_KERNEL);
-+ if (!skt)
-+ return -ENOMEM;
-+
-+ memset(skt, 0, sizeof(struct clps6700_skt));
-+
-+ spin_lock_init(&skt->ev_lock);
-+
-+ skt->nr = nr;
-+ skt->physbase = nr ? CS5_PHYS_BASE : CS4_PHYS_BASE;
-+ skt->pmr = PMR_AUTOIDLE | PMR_MCPE | PMR_CDWEAK;
-+ skt->cpcr = CPCR_PDIR(PCTL1|PCTL0);
-+ skt->cpcr_3v3 = CPCR_PON(PCTL0);
-+ skt->cpcr_5v0 = CPCR_PON(PCTL0); /* we only do 3v3 */
-+
-+ skt->cur_pmr = skt->pmr;
-+
-+ skt->regbase = (u_int)ioremap(skt->physbase + CLPS6700_REG_BASE,
-+ CLPS6700_REG_SIZE);
-+ ret = -ENOMEM;
-+ if (!skt->regbase)
-+ goto err_free;
-+
-+ skts[nr] = skt;
-+
-+ ret = request_irq(IRQ_EINT3, clps6700_interrupt,
-+ SA_SHIRQ, "pcmcia", skt);
-+
-+ if (ret) {
-+ printk(KERN_ERR "clps6700: unable to grab irq%d (%d)\n",
-+ IRQ_EINT3, ret);
-+ goto err_unmap;
-+ }
-+ return 0;
-+
-+err_unmap:
-+ iounmap((void *)skt->regbase);
-+err_free:
-+ kfree(skt);
-+ skts[nr] = NULL;
-+ return ret;
-+}
-+
-+static void clps6700_free_resources(void)
-+{
-+ int i;
-+
-+ for (i = NR_CLPS6700; i >= 0; i--) {
-+ struct clps6700_skt *skt = skts[i];
-+
-+ skts[i] = NULL;
-+ if (skt == NULL)
-+ continue;
-+
-+ free_irq(IRQ_EINT3, skt);
-+ if (skt->regbase) {
-+ __raw_writel(skt->pmr, skt->regbase + PMR);
-+ __raw_writel(skt->cpcr, skt->regbase + CPCR);
-+ __raw_writel(0, skt->regbase + CICR);
-+ __raw_writel(0, skt->regbase + PCIMR);
-+ }
-+ iounmap((void *)skt->regbase);
-+ kfree(skt);
-+ }
-+}
-+
-+static int __init clps6700_init(void)
-+{
-+ unsigned int v;
-+ int err, nr;
-+
-+ PLD_CF = 0;
-+ v = clps_readl(SYSCON2) | SYSCON2_PCCARD1 | SYSCON2_PCCARD2;
-+ clps_writel(v, SYSCON2);
-+ v = clps_readl(SYSCON1) | SYSCON1_EXCKEN;
-+ clps_writel(v, SYSCON1);
-+
-+ for (nr = 0; nr < NR_CLPS6700; nr++) {
-+ err = clps6700_init_skt(nr);
-+ if (err)
-+ goto free;
-+ }
-+
-+ err = register_ss_entry(nr, &clps6700_operations);
-+ if (err)
-+ goto free;
-+
-+ return 0;
-+
-+free:
-+ clps6700_free_resources();
-+ /*
-+ * An error occurred. Unmap and free all CLPS6700
-+ */
-+ return err;
-+}
-+
-+static void __exit clps6700_exit(void)
-+{
-+ unregister_ss_entry(&clps6700_operations);
-+ clps6700_free_resources();
-+}
-+
-+module_init(clps6700_init);
-+module_exit(clps6700_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/clps6700.h
-@@ -0,0 +1,85 @@
-+#define PCISR 0x0000 /* PC Card Interrupt Status Register */
-+#define PCIMR 0x0400 /* PC Card Interrupt Mask Register */
-+#define PCICR 0x0800 /* PC Card Interrupt Clear Register */
-+#define PCIOSR 0x0c00 /* PC Card Interrupt Output Select Regsiter */
-+#define PCIRR1 0x1000 /* PC Card Interrupt Reserved Register 1 */
-+#define PCIRR2 0x1400 /* PC Card Interrupt Reserved Register 2 */
-+#define PCIRR3 0x1800 /* PC Card Interrupt Reserved Register 3 */
-+#define PCIILR 0x1c00 /* PC Card Interrupt Input Level Register */
-+#define SICR 0x2000 /* System Interface Configuration Register */
-+#define CICR 0x2400 /* Card Interface Configuration Register */
-+#define PMR 0x2800 /* Power Management Register */
-+#define CPCR 0x2c00 /* Card Power Control Register */
-+#define CITR0A 0x3000 /* Card Interface Timing Register 0A */
-+#define CITR0B 0x3400 /* Card Interface Timing Register 0B */
-+#define CITR1A 0x3800 /* Card Interface Timing Register 1A */
-+#define CITR1B 0x3c00 /* Card Interface Timing Register 1B */
-+#define DMACR 0x4000 /* DMA Control Register */
-+#define DIR 0x4400 /* Device Information Register */
-+
-+#define CLPS6700_ATTRIB_BASE 0x00000000
-+#define CLPS6700_IO_BASE 0x04000000
-+#define CLPS6700_MEM_BASE 0x08000000
-+#define CLPS6700_REG_BASE 0x0c000000
-+#define CLPS6700_REG_SIZE 0x00005000
-+
-+
-+#define PMR_AUTOIDLE (1 << 0) /* auto idle mode */
-+#define PMR_FORCEIDLE (1 << 1) /* force idle mode */
-+#define PMR_PDCS (1 << 2) /* Power down card on standby */
-+#define PMR_PDCR (1 << 3) /* Power down card on removal */
-+#define PMR_DCAR (1 << 4) /* Disable card access on removal */
-+#define PMR_CPE (1 << 5) /* Card power enable */
-+#define PMR_MCPE (1 << 6) /* Monitor card power enable */
-+#define PMR_PDREQLSEL (1 << 7) /* If set, PDREQL is a GPIO pin */
-+#define PMR_DISSTBY (1 << 8) /* Disable standby */
-+#define PMR_ACCSTBY (1 << 9) /* Complete card accesses before standby*/
-+#define PMR_CDUNPROT (0 << 10) /* Card detect inputs unprotected */
-+#define PMR_CDPROT (1 << 10) /* Card detect inputs protected */
-+#define PMR_CDWEAK (2 << 10) /* Weak pullup except in standby */
-+#define PMR_CDWEAKAL (3 << 10) /* Weak pullup */
-+
-+#define CPCR_PON(x) ((x)&7) /* PCTL[2:0] value when PMR_CPE = 1 */
-+#define CPCR_POFF(x) (((x)&7)<<3) /* PCTL[2:0] value when PMR_CPE = 0 */
-+#define CPCR_PDIR(x) (((x)&7)<<6) /* PCTL[2:0] direction */
-+#define CPCR_CON(x) (((x)&1)<<9) /* GPIO value when PMR_CPE = 1 */
-+#define CPCR_COFF(x) (((x)&1)<<10) /* GPIO value when PMR_CPE = 0 */
-+#define CPCR_CDIR(x) (((x)&1)<<11) /* GPIO direction (PMR_PDREQLSEL = 1) */
-+#define CPCR_VS(x) (((x)&3)<<12) /* VS[2:1] output value */
-+#define CPCR_VSDIR(x) (((x)&3)<<14) /* VS[2:1] direction */
-+
-+#define PCTL0 (1 << 0)
-+#define PCTL1 (1 << 1)
-+#define PCTL2 (1 << 2)
-+
-+#define CICR_ASRTMR1 (1 << 0) /* Timer 1 select for attribute read */
-+#define CICR_ASWTMR1 (1 << 1) /* Timer 1 select for attribute write */
-+#define CICR_IOSRTMR1 (1 << 2) /* Timer 1 select for IO read */
-+#define CICR_IOSWTMR1 (1 << 3) /* Timer 1 select for IO write */
-+#define CICR_MEMSRTMR1 (1 << 4) /* Timer 1 select for memory read */
-+#define CICR_MEMSWTMR1 (1 << 5) /* Timer 1 select for memory write */
-+#define CICR_AUTOIOSZ (1 << 6) /* Auto size I/O accesses */
-+#define CICR_CAW (1 << 7) /* Card access width */
-+#define CICR_IOMODE (1 << 8) /* IO mode select */
-+#define CICR_ENABLE (1 << 10) /* Card enable */
-+#define CICR_RESETOE (1 << 11) /* Card reset output enable */
-+#define CICR_RESET (1 << 12) /* Card reset */
-+
-+
-+#define RD_FAIL (1 << 14)
-+#define WR_FAIL (1 << 13)
-+#define IDLE (1 << 12)
-+
-+#define FFOTHLD (1 << 11)
-+#define PCM_RDYL (1 << 10)
-+#define PCM_WP (1 << 9)
-+#define PCTL (1 << 8)
-+
-+#define PDREQ_L (1 << 6)
-+#define PCM_VS2 (1 << 5)
-+#define PCM_VS1 (1 << 4)
-+
-+#define PCM_CD2 (1 << 3)
-+#define PCM_CD1 (1 << 2)
-+#define PCM_BVD2 (1 << 1)
-+#define PCM_BVD1 (1 << 0)
---- linux-2.4.27/drivers/pcmcia/cs.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/cs.c
-@@ -3,7 +3,7 @@
- Kernel Card Services -- core services
-
- cs.c 1.271 2000/10/02 20:27:49
--
-+
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #include <linux/module.h>
-@@ -92,7 +92,7 @@
- MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
- MODULE_DESCRIPTION("Linux Kernel Card Services " CS_RELEASE
- "\n options:" OPTIONS);
--MODULE_LICENSE("Dual MPL/GPL");
-+MODULE_LICENSE("Dual MPL/GPL");
-
- #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
-@@ -123,7 +123,7 @@
- static const char *version =
- "cs.c 1.279 2001/10/13 00:08:28 (David Hinds)";
- #endif
--
-+
- /*====================================================================*/
-
- socket_state_t dead_socket = {
-@@ -299,7 +299,7 @@
-
- Low-level PC Card interface drivers need to register with Card
- Services using these calls.
--
-+
- ======================================================================*/
-
- static int setup_socket(socket_info_t *);
-@@ -331,7 +331,7 @@
- s->use_bus_pm = use_bus_pm;
- s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
- spin_lock_init(&s->lock);
--
-+
- for (i = 0; i < sockets; i++)
- if (socket_table[i] == NULL) break;
- socket_table[i] = s;
-@@ -365,7 +365,7 @@
- for (ns = 0; ns < nsock; ns++) {
- pcmcia_register_socket (ns, ss_entry, 0);
- }
--
-+
- return 0;
- } /* register_ss_entry */
-
-@@ -457,7 +457,7 @@
- static void shutdown_socket(socket_info_t *s)
- {
- client_t **c;
--
-+
- DEBUG(1, "cs: shutdown_socket(%p)\n", s);
-
- /* Blank out the socket state */
-@@ -561,7 +561,7 @@
- have several causes: card insertion, a call to reset_socket, or
- recovery from a suspend/resume cycle. Unreset_socket() sends
- a CS event that matches the cause of the reset.
--
-+
- ======================================================================*/
-
- static void reset_socket(socket_info_t *s)
-@@ -616,7 +616,7 @@
- s->state &= ~SOCKET_SETUP_PENDING;
- } else {
- send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
-- if (s->reset_handle) {
-+ if (s->reset_handle) {
- s->reset_handle->event_callback_args.info = NULL;
- EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,
- CS_EVENT_PRI_LOW);
-@@ -631,7 +631,7 @@
- valid clients. Parse_events() interprets the event bits from
- a card status change report. Do_shutdown() handles the high
- priority stuff associated with a card removal.
--
-+
- ======================================================================*/
-
- static int send_event(socket_info_t *s, event_t event, int priority)
-@@ -641,7 +641,7 @@
- DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",
- s->sock, event, priority);
- ret = 0;
-- for (; client; client = client->next) {
-+ for (; client; client = client->next) {
- if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))
- continue;
- if (client->EventMask & event) {
-@@ -675,10 +675,17 @@
- static void parse_events(void *info, u_int events)
- {
- socket_info_t *s = info;
-+
- if (events & SS_DETECT) {
- int status;
-
- get_socket_status(s, &status);
-+
-+ /*
-+ * If our socket state indicates that a card is present and
-+ * either the socket has not been suspended (for some reason)
-+ * or the card has been removed, shut down the socket first.
-+ */
- if ((s->state & SOCKET_PRESENT) &&
- (!(s->state & SOCKET_SUSPEND) ||
- !(status & SS_DETECT)))
-@@ -716,7 +723,7 @@
-
- This does not comply with the latest PC Card spec for handling
- power management events.
--
-+
- ======================================================================*/
-
- void pcmcia_suspend_socket (socket_info_t *s)
-@@ -773,7 +780,7 @@
- /*======================================================================
-
- Special stuff for managing IO windows, because they are scarce.
--
-+
- ======================================================================*/
-
- static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
-@@ -862,7 +869,7 @@
- Access_configuration_register() reads and writes configuration
- registers in attribute memory. Memory window 0 is reserved for
- this and the tuple reading services.
--
-+
- ======================================================================*/
-
- int pcmcia_access_configuration_register(client_handle_t handle,
-@@ -872,7 +879,7 @@
- config_t *c;
- int addr;
- u_char val;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -890,7 +897,7 @@
- return CS_CONFIGURATION_LOCKED;
-
- addr = (c->ConfigBase + reg->Offset) >> 1;
--
-+
- switch (reg->Action) {
- case CS_READ:
- read_cis_mem(s, 1, addr, 1, &val);
-@@ -913,7 +920,7 @@
- It is normally called by Driver Services after it has identified
- a newly inserted card. An instance of that driver will then be
- eligible to register as a client of this socket.
--
-+
- ======================================================================*/
-
- int pcmcia_bind_device(bind_req_t *req)
-@@ -949,23 +956,23 @@
- region. It is normally called by Driver Services after it has
- identified a memory device type. An instance of the corresponding
- driver will then be able to register to control this region.
--
-+
- ======================================================================*/
-
- int pcmcia_bind_mtd(mtd_bind_t *req)
- {
- socket_info_t *s;
- memory_handle_t region;
--
-+
- if (CHECK_SOCKET(req->Socket))
- return CS_BAD_SOCKET;
- s = SOCKET(req);
--
-+
- if (req->Attributes & REGION_TYPE_AM)
- region = s->a_region;
- else
- region = s->c_region;
--
-+
- while (region) {
- if (region->info.CardOffset == req->CardOffset) break;
- region = region->info.next;
-@@ -973,7 +980,7 @@
- if (!region || (region->mtd != NULL))
- return CS_BAD_OFFSET;
- strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
--
-+
- DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n",
- req->Attributes, req->CardOffset, (char *)req->dev_info);
- return CS_SUCCESS;
-@@ -988,7 +995,7 @@
- memory_handle_t region;
- u_long flags;
- int i, sn;
--
-+
- DEBUG(1, "cs: deregister_client(%p)\n", handle);
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-@@ -1007,7 +1014,7 @@
- for (region = s->c_region; region; region = region->info.next)
- if (region->mtd == handle) region->mtd = NULL;
- }
--
-+
- sn = handle->Socket; s = socket_table[sn];
-
- if ((handle->state & CLIENT_STALE) ||
-@@ -1032,7 +1039,7 @@
-
- if (--s->real_clients == 0)
- register_callback(s, NULL, NULL);
--
-+
- return CS_SUCCESS;
- } /* deregister_client */
-
-@@ -1043,7 +1050,7 @@
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1055,7 +1062,7 @@
- return CS_BAD_ARGS;
- } else
- config->Function = handle->Function;
--
-+
- #ifdef CONFIG_CARDBUS
- if (s->state & SOCKET_CARDBUS) {
- u_char fn = config->Function;
-@@ -1076,16 +1083,16 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- c = (s->config != NULL) ? &s->config[config->Function] : NULL;
--
-+
- if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
- config->Attributes = 0;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- return CS_SUCCESS;
- }
--
-+
- /* !!! This is a hack !!! */
- memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
- config->Attributes |= CONF_VALID_CLIENT;
-@@ -1099,14 +1106,14 @@
- config->NumPorts2 = c->io.NumPorts2;
- config->Attributes2 = c->io.Attributes2;
- config->IOAddrLines = c->io.IOAddrLines;
--
-+
- return CS_SUCCESS;
- } /* get_configuration_info */
-
- /*======================================================================
-
- Return information about this version of Card Services.
--
-+
- ======================================================================*/
-
- int pcmcia_get_card_services_info(servinfo_t *info)
-@@ -1124,7 +1131,7 @@
-
- Note that get_first_client() *does* recognize the Socket field
- in the request structure.
--
-+
- ======================================================================*/
-
- int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
-@@ -1239,7 +1246,7 @@
-
- Get the current socket state bits. We don't support the latched
- SocketState yet: I haven't seen any point for it.
--
-+
- ======================================================================*/
-
- int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
-@@ -1247,7 +1254,7 @@
- socket_info_t *s;
- config_t *c;
- int val;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1263,7 +1270,7 @@
- return CS_NO_CARD;
- if (s->state & SOCKET_SETUP_PENDING)
- status->CardState |= CS_EVENT_CARD_INSERTION;
--
-+
- /* Get info from the PRR, if necessary */
- if (handle->Function == BIND_FN_ALL) {
- if (status->Function && (status->Function >= s->functions))
-@@ -1309,7 +1316,7 @@
- /*======================================================================
-
- Change the card address of an already open memory window.
--
-+
- ======================================================================*/
-
- int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
-@@ -1338,7 +1345,7 @@
- /*======================================================================
-
- Modify a locked socket configuration
--
-+
- ======================================================================*/
-
- int pcmcia_modify_configuration(client_handle_t handle,
-@@ -1346,7 +1353,7 @@
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle); c = CONFIG(handle);
-@@ -1354,7 +1361,7 @@
- return CS_NO_CARD;
- if (!(c->state & CONFIG_LOCKED))
- return CS_CONFIGURATION_LOCKED;
--
-+
- if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
- if (mod->Attributes & CONF_ENABLE_IRQ) {
- c->Attributes |= CONF_ENABLE_IRQ;
-@@ -1406,7 +1413,7 @@
- win->ctl.flags |= MAP_USE_WAIT;
- win->ctl.speed = req->AccessSpeed;
- set_mem_map(win->sock, &win->ctl);
--
-+
- return CS_SUCCESS;
- } /* modify_window */
-
-@@ -1416,7 +1423,7 @@
- caller with a socket. The driver must have already been bound
- to a socket with bind_device() -- in fact, bind_device()
- allocates the client structure that will be used.
--
-+
- ======================================================================*/
-
- int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
-@@ -1424,7 +1431,7 @@
- client_t *client;
- socket_info_t *s;
- socket_t ns;
--
-+
- /* Look for unbound client with matching dev_info */
- client = NULL;
- for (ns = 0; ns < sockets; ns++) {
-@@ -1464,7 +1471,7 @@
-
- if (s->state & SOCKET_CARDBUS)
- client->state |= CLIENT_CARDBUS;
--
-+
- if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
- (client->Function != BIND_FN_ALL)) {
- cistpl_longlink_mfc_t mfc;
-@@ -1479,7 +1486,7 @@
- return CS_OUT_OF_RESOURCE;
- memset(s->config, 0, sizeof(config_t) * s->functions);
- }
--
-+
- DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n",
- client, client->Socket, client->dev_info);
- if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
-@@ -1501,13 +1508,13 @@
- pccard_io_map io = { 0, 0, 0, 0, 1 };
- socket_info_t *s;
- int i;
--
-+
- if (CHECK_HANDLE(handle) ||
- !(handle->state & CLIENT_CONFIG_LOCKED))
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_CONFIG_LOCKED;
- s = SOCKET(handle);
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- cb_disable(s);
-@@ -1515,7 +1522,7 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (--(s->lock_count) == 0) {
-@@ -1536,7 +1543,7 @@
- }
- c->state &= ~CONFIG_LOCKED;
- }
--
-+
- return CS_SUCCESS;
- } /* release_configuration */
-
-@@ -1547,25 +1554,25 @@
- the actual socket configuration, so if the client is "stale", we
- don't bother checking the port ranges against the current socket
- values.
--
-+
- ======================================================================*/
-
- int pcmcia_release_io(client_handle_t handle, io_req_t *req)
- {
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_IO_REQ;
- s = SOCKET(handle);
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- cb_release(s);
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (c->state & CONFIG_LOCKED)
-@@ -1581,7 +1588,7 @@
- release_io_space(s, req->BasePort1, req->NumPorts1);
- if (req->NumPorts2)
- release_io_space(s, req->BasePort2, req->NumPorts2);
--
-+
- return CS_SUCCESS;
- } /* release_io */
-
-@@ -1594,7 +1601,7 @@
- return CS_BAD_HANDLE;
- handle->state &= ~CLIENT_IRQ_REQ;
- s = SOCKET(handle);
--
-+
- if (!(handle->state & CLIENT_STALE)) {
- config_t *c = CONFIG(handle);
- if (c->state & CONFIG_LOCKED)
-@@ -1608,16 +1615,16 @@
- s->irq.AssignedIRQ = 0;
- }
- }
--
-+
- if (req->Attributes & IRQ_HANDLE_PRESENT) {
- bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance);
- }
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (req->AssignedIRQ != s->cap.pci_irq)
- undo_irq(req->Attributes, req->AssignedIRQ);
- #endif
--
-+
- return CS_SUCCESS;
- } /* cs_release_irq */
-
-@@ -1626,7 +1633,7 @@
- int pcmcia_release_window(window_handle_t win)
- {
- socket_info_t *s;
--
-+
- if ((win == NULL) || (win->magic != WINDOW_MAGIC))
- return CS_BAD_HANDLE;
- s = win->sock;
-@@ -1640,11 +1647,11 @@
-
- /* Release system memory */
- if(!(s->cap.features & SS_CAP_STATIC_MAP))
-- release_mem_region(win->base, win->size);
-+ release_mem_resource(win->base, win->size);
- win->handle->state &= ~CLIENT_WIN_REQ(win->index);
-
- win->magic = 0;
--
-+
- return CS_SUCCESS;
- } /* release_window */
-
-@@ -1658,13 +1665,13 @@
- socket_info_t *s;
- config_t *c;
- pccard_io_map iomap;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
- if (!(s->state & SOCKET_PRESENT))
- return CS_NO_CARD;
--
-+
- #ifdef CONFIG_CARDBUS
- if (handle->state & CLIENT_CARDBUS) {
- if (!(req->IntType & INT_CARDBUS))
-@@ -1677,7 +1684,7 @@
- return CS_SUCCESS;
- }
- #endif
--
-+
- if (req->IntType & INT_CARDBUS)
- return CS_UNSUPPORTED_MODE;
- c = CONFIG(handle);
-@@ -1692,9 +1699,9 @@
- s->socket.Vpp = req->Vpp1;
- if (set_socket(s, &s->socket))
- return CS_BAD_VPP;
--
-+
- c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
--
-+
- /* Pick memory or I/O card, DMA mode, interrupt */
- c->IntType = req->IntType;
- c->Attributes = req->Attributes;
-@@ -1712,7 +1719,7 @@
- s->socket.io_irq = 0;
- set_socket(s, &s->socket);
- s->lock_count++;
--
-+
- /* Set up CIS configuration registers */
- base = c->ConfigBase = req->ConfigBase;
- c->Present = c->CardValues = req->Present;
-@@ -1757,7 +1764,7 @@
- u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
- write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
- }
--
-+
- /* Configure I/O windows */
- if (c->state & CONFIG_IO_REQ) {
- iomap.speed = io_speed;
-@@ -1779,24 +1786,24 @@
- s->io[i].Config++;
- }
- }
--
-+
- c->state |= CONFIG_LOCKED;
- handle->state |= CLIENT_CONFIG_LOCKED;
- return CS_SUCCESS;
- } /* request_configuration */
-
- /*======================================================================
--
-+
- Request_io() reserves ranges of port addresses for a socket.
- I have not implemented range sharing or alias addressing.
--
-+
- ======================================================================*/
-
- int pcmcia_request_io(client_handle_t handle, io_req_t *req)
- {
- socket_info_t *s;
- config_t *c;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1855,7 +1862,7 @@
- hooked, we don't guarantee that an irq will still be available
- when the configuration is locked. Now that I think about it,
- there might be a way to fix this using a dummy handler.
--
-+
- ======================================================================*/
-
- int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
-@@ -1863,7 +1870,7 @@
- socket_info_t *s;
- config_t *c;
- int ret = CS_IN_USE, irq = 0;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- s = SOCKET(handle);
-@@ -1875,7 +1882,7 @@
- if (c->state & CONFIG_IRQ_REQ)
- return CS_IN_USE;
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (s->irq.AssignedIRQ != 0) {
- /* If the interrupt is already assigned, it must match */
- irq = s->irq.AssignedIRQ;
-@@ -1909,7 +1916,7 @@
-
- if (req->Attributes & IRQ_HANDLE_PRESENT) {
- if (bus_request_irq(s->cap.bus, irq, req->Handler,
-- ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
-+ ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
- (s->functions > 1) ||
- (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
- handle->dev_info, req->Instance))
-@@ -1919,7 +1926,7 @@
- c->irq.Attributes = req->Attributes;
- s->irq.AssignedIRQ = req->AssignedIRQ = irq;
- s->irq.Config++;
--
-+
- c->state |= CONFIG_IRQ_REQ;
- handle->state |= CLIENT_IRQ_REQ;
- return CS_SUCCESS;
-@@ -1938,7 +1945,7 @@
- window_t *win;
- u_long align;
- int w;
--
-+
- if (CHECK_HANDLE(*handle))
- return CS_BAD_HANDLE;
- s = SOCKET(*handle);
-@@ -2005,7 +2012,7 @@
- /* Return window handle */
- req->Base = win->ctl.sys_start;
- *wh = win;
--
-+
- return CS_SUCCESS;
- } /* request_window */
-
-@@ -2014,14 +2021,14 @@
- I'm not sure which "reset" function this is supposed to use,
- but for now, it uses the low-level interface's reset, not the
- CIS register.
--
-+
- ======================================================================*/
-
- int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
- {
- int i, ret;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2049,14 +2056,14 @@
-
- These shut down or wake up a socket. They are sort of user
- initiated versions of the APM suspend and resume actions.
--
-+
- ======================================================================*/
-
- int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
- {
- int i;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2077,7 +2084,7 @@
- {
- int i;
- socket_info_t *s;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2095,7 +2102,7 @@
- /*======================================================================
-
- These handle user requests to eject or insert a card.
--
-+
- ======================================================================*/
-
- int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
-@@ -2103,7 +2110,7 @@
- int i, ret;
- socket_info_t *s;
- u_long flags;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2119,9 +2126,9 @@
- spin_lock_irqsave(&s->lock, flags);
- do_shutdown(s);
- spin_unlock_irqrestore(&s->lock, flags);
--
-+
- return CS_SUCCESS;
--
-+
- } /* eject_card */
-
- int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
-@@ -2129,7 +2136,7 @@
- int i, status;
- socket_info_t *s;
- u_long flags;
--
-+
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
- i = handle->Socket; s = socket_table[i];
-@@ -2157,7 +2164,7 @@
-
- Maybe this should send a CS_EVENT_CARD_INSERTION event if we
- haven't sent one to this client yet?
--
-+
- ======================================================================*/
-
- int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask)
-@@ -2189,7 +2196,7 @@
- printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", handle->dev_info);
--
-+
- for (i = 0; i < SERVICE_COUNT; i++)
- if (service_table[i].key == err->func) break;
- if (i < SERVICE_COUNT)
-@@ -2347,13 +2354,13 @@
- default:
- return CS_UNSUPPORTED_FUNCTION; break;
- }
--
-+
- } /* CardServices */
-
- /*======================================================================
-
- OS-specific module glue goes here
--
-+
- ======================================================================*/
- /* in alpha order */
- EXPORT_SYMBOL(pcmcia_access_configuration_register);
-@@ -2450,4 +2457,3 @@
- module_exit(exit_pcmcia_cs);
-
- /*====================================================================*/
--
---- linux-2.4.27/drivers/pcmcia/ds.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/ds.c
-@@ -55,6 +55,7 @@
- #include <pcmcia/bulkmem.h>
- #include <pcmcia/cistpl.h>
- #include <pcmcia/ds.h>
-+#include <linux/devfs_fs_kernel.h>
-
- /*====================================================================*/
-
-@@ -880,6 +881,8 @@
- EXPORT_SYMBOL(register_pccard_driver);
- EXPORT_SYMBOL(unregister_pccard_driver);
-
-+static devfs_handle_t devfs_handle;
-+
- /*====================================================================*/
-
- int __init init_pcmcia_ds(void)
-@@ -957,8 +960,13 @@
- if (i == -EBUSY)
- printk(KERN_NOTICE "unable to find a free device # for "
- "Driver Services\n");
-- else
-+ else {
- major_dev = i;
-+ devfs_handle = devfs_register(NULL, "pcmcia", DEVFS_FL_DEFAULT,
-+ major_dev, 0,
-+ S_IFCHR | S_IRUSR | S_IWUSR,
-+ &ds_fops, NULL);
-+ }
-
- #ifdef CONFIG_PROC_FS
- if (proc_pccard)
-@@ -983,7 +991,9 @@
- remove_proc_entry("drivers", proc_pccard);
- #endif
- if (major_dev != -1)
-- unregister_chrdev(major_dev, "pcmcia");
-+ devfs_unregister_chrdev(major_dev, "pcmcia");
-+ devfs_unregister(devfs_handle);
-+
- for (i = 0; i < sockets; i++)
- pcmcia_deregister_client(socket_table[i].handle);
- sockets = 0;
---- linux-2.4.27/drivers/pcmcia/i82365.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/i82365.c
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #include <linux/module.h>
-@@ -65,6 +65,15 @@
- #include "ricoh.h"
- #include "o2micro.h"
-
-+#ifdef CONFIG_ARCH_EBSA110
-+#define I365_MASK (1 << 6)
-+#define SOCKIRQ2REG(sock,irq) ((irq) ? ((sock) ? 3 : 4) : 0)
-+#define REG2SOCKIRQ(sock,reg) (6)
-+#else
-+#define SOCKIRQ2REG(sock,irq) (irq)
-+#define REG2SOCKIRQ(sock,reg) (reg)
-+#endif
-+
- #ifdef PCMCIA_DEBUG
- static int pc_debug = PCMCIA_DEBUG;
- MODULE_PARM(pc_debug, "i");
-@@ -173,13 +182,15 @@
- } socket_info_t;
-
- /* Where we keep track of our sockets... */
--static int sockets = 0;
--static socket_info_t socket[8] = {
-- { 0, }, /* ... */
--};
-+static int sockets /* = 0 */;
-+static socket_info_t socket[8] /* = {
-+ { 0, },
-+} */;
-
- /* Default ISA interrupt mask */
-+#ifndef I365_MASK
- #define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
-+#endif
-
- static int grab_irq;
- static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
-@@ -303,7 +314,7 @@
-
- The VIA controllers also use these routines, as they are mostly
- Cirrus lookalikes, without the timing registers.
--
-+
- ======================================================================*/
-
- #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
-@@ -389,7 +400,7 @@
- Code to save and restore global state information for Vadem VG468
- and VG469 controllers, and to set and report global configuration
- options.
--
-+
- ======================================================================*/
-
- static void vg46x_get_state(u_short s)
-@@ -411,7 +422,7 @@
- static u_int __init vg46x_set_opts(u_short s, char *buf)
- {
- vg46x_state_t *p = &socket[s].state.vg46x;
--
-+
- flip(p->ctl, VG468_CTL_ASYNC, async_clock);
- flip(p->ema, VG469_MODE_CABLE, cable_mode);
- if (p->ctl & VG468_CTL_ASYNC)
-@@ -436,7 +447,7 @@
- /*======================================================================
-
- Generic routines to get and set controller options
--
-+
- ======================================================================*/
-
- static void get_bridge_state(u_short s)
-@@ -489,7 +500,7 @@
- /*======================================================================
-
- Interrupt testing code, for ISA and PCI interrupts
--
-+
- ======================================================================*/
-
- static volatile u_int irq_hits;
-@@ -517,7 +528,7 @@
- }
-
- /* Generate one interrupt */
-- i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
-+ i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (SOCKIRQ2REG(sock, irq) << 4));
- i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
- udelay(1000);
-
-@@ -526,7 +537,7 @@
- /* mask all interrupts */
- i365_set(sock, I365_CSCINT, 0);
- DEBUG(2, " hits = %d\n", irq_hits);
--
-+
- return (irq_hits != 1);
- }
-
-@@ -540,7 +551,7 @@
- /* Don't probe level-triggered interrupts -- reserved for PCI */
- mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
- #endif
--
-+
- if (do_scan) {
- set_bridge_state(sock);
- i365_set(sock, I365_CSCINT, 0);
-@@ -551,7 +562,7 @@
- if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
- mask1 ^= (1 << i);
- }
--
-+
- printk(KERN_INFO " ISA irqs (");
- if (mask1) {
- printk("scanned");
-@@ -565,12 +576,12 @@
- if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
- }
- printk(") = ");
--
-+
- for (i = 0; i < 16; i++)
- if (mask1 & (1<<i))
- printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
- if (mask1 == 0) printk("none!");
--
-+
- return mask1;
- }
-
-@@ -598,14 +609,14 @@
- /* Use the next free entry in the socket table */
- socket[sockets].ioaddr = port;
- socket[sockets].psock = sock;
--
-+
- /* Wake up a sleepy Cirrus controller */
- if (wakeup) {
- i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
- /* Pause at least 50 ms */
- mdelay(50);
- }
--
-+
- if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
- return -1;
- switch (val) {
-@@ -618,7 +629,7 @@
- case 0x88: case 0x89: case 0x8a:
- type = IS_IBM; break;
- }
--
-+
- /* Check for Vadem VG-468 chips */
- outb(0x0e, port);
- outb(0x37, port);
-@@ -633,7 +644,7 @@
- val = i365_get(sockets, RF5C_CHIP_ID);
- if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
- type = IS_RF5Cx96;
--
-+
- /* Check for Cirrus CL-PD67xx chips */
- i365_set(sockets, PD67_CHIP_INFO, 0);
- val = i365_get(sockets, PD67_CHIP_INFO);
-@@ -655,14 +666,14 @@
- bound to a (non PC Card) Linux driver. We leave these alone.
-
- We make an exception for cards that seem to be serial devices.
--
-+
- ======================================================================*/
-
- static int __init is_alive(u_short sock)
- {
- u_char stat;
- u_short start, stop;
--
-+
- stat = i365_get(sock, I365_STATUS);
- start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
- stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
-@@ -697,7 +708,7 @@
-
- base = sockets-ns;
- if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
--
-+
- if (base == 0) printk("\n");
- printk(KERN_INFO " %s", pcic[type].name);
- printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
-@@ -713,7 +724,7 @@
- mask &= I365_MASK & set_bridge_opts(base, ns);
- /* Scan for ISA interrupts */
- mask = isa_scan(base, mask);
--
-+
- /* Poll if only two interrupts available */
- if (!poll_interval) {
- u_int tmp = (mask & 0xff20);
-@@ -735,15 +746,15 @@
- printk(" status change on irq %d\n", cs_irq);
- }
- }
--
-+
- if (!isa_irq) {
- if (poll_interval == 0)
- poll_interval = HZ;
- printk(" polling interval = %d ms\n",
- poll_interval * 1000 / HZ);
--
-+
- }
--
-+
- /* Update socket interrupt information, capabilities */
- for (i = 0; i < ns; i++) {
- t[i].cap.features |= SS_CAP_PCCARD;
-@@ -866,12 +877,12 @@
- events = pending_events[i];
- pending_events[i] = 0;
- spin_unlock_irq(&pending_event_lock);
-- /*
-- SS_DETECT events need a small delay here. The reason for this is that
-+ /*
-+ SS_DETECT events need a small delay here. The reason for this is that
- the "is there a card" electronics need time to see the card after the
-- "we have a card coming in" electronics have seen it.
-+ "we have a card coming in" electronics have seen it.
- */
-- if (events & SS_DETECT)
-+ if (events & SS_DETECT)
- mdelay(4);
- if (socket[i].handler)
- socket[i].handler(socket[i].info, events);
-@@ -890,7 +901,7 @@
- int i, j, csc;
- u_int events, active;
- u_long flags = 0;
--
-+
- DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
-
- for (j = 0; j < 20; j++) {
-@@ -906,20 +917,20 @@
- continue;
- }
- events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
--
--
-+
-+
- /* Several sockets will send multiple "new card detected"
-- events in rapid succession. However, the rest of the pcmcia expects
-+ events in rapid succession. However, the rest of the pcmcia expects
- only one such event. We just ignore these events by having a
- timeout */
-
- if (events) {
-- if ((jiffies - last_detect_jiffies)<(HZ/20))
-+ if ((jiffies - last_detect_jiffies)<(HZ/20))
- events = 0;
- last_detect_jiffies = jiffies;
--
-+
- }
--
-+
- if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
- events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
- else {
-@@ -980,11 +991,11 @@
- static int i365_get_status(u_short sock, u_int *value)
- {
- u_int status;
--
-+
- status = i365_get(sock, I365_STATUS);
- *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
- ? SS_DETECT : 0;
--
-+
- if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
- *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
- else {
-@@ -1005,7 +1016,7 @@
- *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
- }
- }
--
-+
- DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
- return 0;
- } /* i365_get_status */
-@@ -1016,7 +1027,7 @@
- {
- socket_info_t *t = &socket[sock];
- u_char reg, vcc, vpp;
--
-+
- reg = i365_get(sock, I365_POWER);
- state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
- state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-@@ -1057,14 +1068,14 @@
- reg = i365_get(sock, I365_INTCTL);
- state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
- if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-- state->io_irq = reg & I365_IRQ_MASK;
--
-+ state->io_irq = REG2SOCKIRQ(sock, reg & I365_IRQ_MASK);
-+
- /* speaker control */
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
- state->flags |= SS_SPKR_ENA;
- }
--
-+
- /* Card status change mask */
- reg = i365_get(sock, I365_CSCINT);
- state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
-@@ -1075,7 +1086,7 @@
- state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
- state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
- }
--
-+
- DEBUG(1, "i82365: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-@@ -1088,21 +1099,21 @@
- {
- socket_info_t *t = &socket[sock];
- u_char reg;
--
-+
- DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
--
-+
- /* First set global controller options */
- set_bridge_state(sock);
--
-+
- /* IO card, RESET flag, IO interrupt */
- reg = t->intr;
-- reg |= state->io_irq;
-+ reg |= SOCKIRQ2REG(sock, state->io_irq);
- reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
- reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
- i365_set(sock, I365_INTCTL, reg);
--
-+
- reg = I365_PWR_NORESET;
- if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
- if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
-@@ -1165,7 +1176,7 @@
- default: return -EINVAL;
- }
- }
--
-+
- if (reg != i365_get(sock, I365_POWER))
- i365_set(sock, I365_POWER, reg);
-
-@@ -1175,9 +1186,9 @@
- i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
- state->flags & SS_SPKR_ENA);
- }
--
-+
- /* Card status change interrupt mask */
-- reg = t->cs_irq << 4;
-+ reg = SOCKIRQ2REG(sock, t->cs_irq) << 4;
- if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
- if (state->flags & SS_IOCARD) {
- if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
-@@ -1188,7 +1199,7 @@
- }
- i365_set(sock, I365_CSCINT, reg);
- i365_get(sock, I365_CSC);
--
-+
- return 0;
- } /* i365_set_socket */
-
-@@ -1197,7 +1208,7 @@
- static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
- {
- u_char map, ioctl, addr;
--
-+
- map = io->map;
- if (map > 1) return -EINVAL;
- io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
-@@ -1220,7 +1231,7 @@
- static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
- {
- u_char map, ioctl;
--
-+
- DEBUG(1, "i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
- io->speed, io->start, io->stop);
-@@ -1250,30 +1261,30 @@
- {
- u_short base, i;
- u_char map, addr;
--
-+
- map = mem->map;
- if (map > 4) return -EINVAL;
- addr = i365_get(sock, I365_ADDRWIN);
- mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
- base = I365_MEM(map);
--
-+
- i = i365_get_pair(sock, base+I365_W_START);
- mem->flags |= (i & I365_MEM_16BIT) ? MAP_16BIT : 0;
- mem->flags |= (i & I365_MEM_0WS) ? MAP_0WS : 0;
- mem->sys_start = ((u_long)(i & 0x0fff) << 12);
--
-+
- i = i365_get_pair(sock, base+I365_W_STOP);
- mem->speed = (i & I365_MEM_WS0) ? 1 : 0;
- mem->speed += (i & I365_MEM_WS1) ? 2 : 0;
- mem->speed = to_ns(mem->speed);
- mem->sys_stop = ((u_long)(i & 0x0fff) << 12) + 0x0fff;
--
-+
- i = i365_get_pair(sock, base+I365_W_OFF);
- mem->flags |= (i & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
- mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
- mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
- mem->card_start &= 0x3ffffff;
--
-+
- DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
- "5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
- mem->sys_start, mem->sys_stop, mem->card_start);
-@@ -1281,12 +1292,12 @@
- } /* i365_get_mem_map */
-
- /*====================================================================*/
--
-+
- static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
- {
- u_short base, i;
- u_char map;
--
-+
- DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
- "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
- mem->sys_start, mem->sys_stop, mem->card_start);
-@@ -1297,17 +1308,17 @@
- return -EINVAL;
- if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
- return -EINVAL;
--
-+
- /* Turn off the window before changing anything */
- if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
- i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
--
-+
- base = I365_MEM(map);
- i = (mem->sys_start >> 12) & 0x0fff;
- if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
- if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
- i365_set_pair(sock, base+I365_W_START, i);
--
-+
- i = (mem->sys_stop >> 12) & 0x0fff;
- switch (to_cycles(mem->speed)) {
- case 0: break;
-@@ -1316,12 +1327,12 @@
- default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
- }
- i365_set_pair(sock, base+I365_W_STOP, i);
--
-+
- i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
- if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
- if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
- i365_set_pair(sock, base+I365_W_OFF, i);
--
-+
- /* Turn on the window if necessary */
- if (mem->flags & MAP_ACTIVE)
- i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
-@@ -1332,7 +1343,7 @@
-
- Routines for accessing socket information and register dumps via
- /proc/bus/pccard/...
--
-+
- ======================================================================*/
-
- #ifdef CONFIG_PROC_FS
-@@ -1353,7 +1364,7 @@
- u_short sock = (socket_info_t *)data - socket;
- char *p = buf;
- int i, top;
--
-+
- u_long flags = 0;
- ISA_LOCK(sock, flags);
- top = 0x40;
-@@ -1399,7 +1410,7 @@
-
- /*====================================================================*/
-
--/* this is horribly ugly... proper locking needs to be done here at
-+/* this is horribly ugly... proper locking needs to be done here at
- * some time... */
- #define LOCKED(x) do { \
- int retval; \
-@@ -1532,7 +1543,7 @@
- /* Set up interrupt handler(s) */
- if (grab_irq != 0)
- request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
--
-+
- if (register_ss_entry(sockets, &pcic_operations) != 0)
- printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
-
-@@ -1544,9 +1555,9 @@
- poll_timer.expires = jiffies + poll_interval;
- add_timer(&poll_timer);
- }
--
-+
- return 0;
--
-+
- } /* init_i82365 */
-
- static void __exit exit_i82365(void)
---- linux-2.4.27/drivers/pcmcia/rsrc_mgr.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/rsrc_mgr.c
-@@ -28,7 +28,7 @@
- and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this
- file under either the MPL or the GPL.
--
-+
- ======================================================================*/
-
- #define __NO_VERSION__
-@@ -55,6 +55,10 @@
- #include <pcmcia/cistpl.h>
- #include "cs_internal.h"
-
-+#ifndef ISAMEM_PHYS
-+#define ISAMEM_PHYS 0
-+#endif
-+
- /*====================================================================*/
-
- /* Parameters that can be set with 'insmod' */
-@@ -62,7 +66,7 @@
- #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
- INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
- INT_MODULE_PARM(mem_limit, 0x10000);
- #endif
-@@ -85,7 +89,7 @@
- /* IO port resource database */
- static resource_map_t io_db = { 0, 0, &io_db };
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- typedef struct irq_info_t {
- u_int Attributes;
-@@ -133,6 +137,7 @@
- static inline int check_mem_resource(unsigned long b, unsigned long n,
- struct pci_dev *dev)
- {
-+ b += ISAMEM_PHYS;
- return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
- }
-
-@@ -169,10 +174,15 @@
- static int request_mem_resource(unsigned long b, unsigned long n,
- char *name, struct pci_dev *dev)
- {
-- struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
-- struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
-+ struct resource *res;
-+ struct resource *pr;
- int err = -ENOMEM;
-
-+ b += ISAMEM_PHYS;
-+
-+ res = make_resource(b, n, IORESOURCE_MEM, name);
-+ pr = resource_parent(b, n, IORESOURCE_MEM, dev);
-+
- if (res) {
- err = request_resource(pr, res);
- if (err)
-@@ -181,10 +191,16 @@
- return err;
- }
-
-+void release_mem_resource(unsigned long b, unsigned long n)
-+{
-+ b += ISAMEM_PHYS;
-+ release_mem_region(b, n);
-+}
-+
- /*======================================================================
-
- These manage the internal databases of available resources.
--
-+
- ======================================================================*/
-
- static int add_interval(resource_map_t *map, u_long base, u_long num)
-@@ -248,25 +264,25 @@
-
- These routines examine a region of IO or memory addresses to
- determine what ranges might be genuinely available.
--
-+
- ======================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- static void do_io_probe(ioaddr_t base, ioaddr_t num)
- {
--
-+
- ioaddr_t i, j, bad, any;
- u_char *b, hole, most;
--
-+
- printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
- base, base+num-1);
--
-+
- /* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
- if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
- return;
-- }
-+ }
- memset(b, 0, 256);
- for (i = base, most = 0; i < base+num; i += 8) {
- if (check_io_resource(i, 8, NULL))
-@@ -308,7 +324,7 @@
- printk(" %#04x-%#04x", bad, i-1);
- }
- }
--
-+
- printk(any ? "\n" : " clean.\n");
- }
- #endif
-@@ -318,7 +334,7 @@
- The memory probe. If the memory list includes a 64K-aligned block
- below 1MB, we probe in 64K chunks, and as soon as we accumulate at
- least mem_limit free space, we quit.
--
-+
- ======================================================================*/
-
- static int do_mem_probe(u_long base, u_long num,
-@@ -332,7 +348,7 @@
- bad = fail = 0;
- step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
- for (i = j = base; i < base+num; i = j + step) {
-- if (!fail) {
-+ if (!fail) {
- for (j = i; j < base+num; j += step)
- if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
- is_valid(j))
-@@ -356,7 +372,7 @@
- return (num - bad);
- }
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- static u_long inv_probe(int (*is_valid)(u_long),
- int (*do_cksum)(u_long),
-@@ -383,7 +399,7 @@
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- static int hi = 0, lo = 0;
- u_long b, i, ok = 0;
--
-+
- if (!probe_mem) return;
- /* We do up to four passes through the list */
- if (!force_low) {
-@@ -414,14 +430,14 @@
- }
- }
-
--#else /* CONFIG_ISA */
-+#else /* CONFIG_PCMCIA_PROBE */
-
- void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
- int force_low, socket_info_t *s)
- {
- resource_map_t *m, *n;
- static int done = 0;
--
-+
- if (!probe_mem || done++)
- return;
-
-@@ -432,7 +448,7 @@
- }
- }
-
--#endif /* CONFIG_ISA */
-+#endif /* CONFIG_PCMCIA_PROBE */
-
- /*======================================================================
-
-@@ -444,7 +460,7 @@
- should be a power of two, greater than or equal to 'num'. A value
- of 0 means that all bits of *base are significant. *base should
- also be strictly less than 'align'.
--
-+
- ======================================================================*/
-
- int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
-@@ -452,7 +468,7 @@
- {
- ioaddr_t try;
- resource_map_t *m;
--
-+
- for (m = io_db.next; m != &io_db; m = m->next) {
- try = (m->base & ~(align-1)) + *base;
- for (try = (try >= m->base) ? try : try+align;
-@@ -500,10 +516,10 @@
- This checks to see if an interrupt is available, with support
- for interrupt sharing. We don't support reserving interrupts
- yet. If the interrupt is available, we allocate it.
--
-+
- ======================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- static void fake_irq(int i, void *d, struct pt_regs *r) { }
- static inline int check_irq(int irq)
-@@ -570,7 +586,7 @@
-
- /*====================================================================*/
-
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
-
- void undo_irq(u_int Attributes, int irq)
- {
-@@ -600,7 +616,7 @@
-
- The various adjust_* calls form the external interface to the
- resource database.
--
-+
- ======================================================================*/
-
- static int adjust_memory(adjust_t *adj)
-@@ -632,7 +648,7 @@
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- }
--
-+
- return ret;
- }
-
-@@ -641,7 +657,7 @@
- static int adjust_io(adjust_t *adj)
- {
- int base, num;
--
-+
- base = adj->resource.io.BasePort;
- num = adj->resource.io.NumPorts;
- if ((base < 0) || (base > 0xffff))
-@@ -653,7 +669,7 @@
- case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0)
- return CS_IN_USE;
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- if (probe_io)
- do_io_probe(base, num);
- #endif
-@@ -673,15 +689,15 @@
-
- static int adjust_irq(adjust_t *adj)
- {
--#ifdef CONFIG_ISA
-+#ifdef CONFIG_PCMCIA_PROBE
- int irq;
- irq_info_t *info;
--
-+
- irq = adj->resource.irq.IRQ;
- if ((irq < 0) || (irq > 15))
- return CS_BAD_IRQ;
- info = &irq_table[irq];
--
-+
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (info->Attributes & RES_REMOVED)
-@@ -716,7 +732,7 @@
- {
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
--
-+
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- return adjust_memory(adj);
-@@ -736,7 +752,7 @@
- void release_resource_db(void)
- {
- resource_map_t *p, *q;
--
-+
- for (p = mem_db.next; p != &mem_db; p = q) {
- q = p->next;
- kfree(p);
---- linux-2.4.27/drivers/pcmcia/sa1100.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100.h
-@@ -204,7 +204,9 @@
- extern struct pcmcia_low_level flexanet_pcmcia_ops;
- extern struct pcmcia_low_level simpad_pcmcia_ops;
- extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
-+extern struct pcmcia_low_level adsagc_pcmcia_ops;
- extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
-+extern struct pcmcia_low_level adsbitsyplus_pcmcia_ops;
- extern struct pcmcia_low_level stork_pcmcia_ops;
- extern struct pcmcia_low_level badge4_pcmcia_ops;
-
---- linux-2.4.27/drivers/pcmcia/sa1100_adsbitsy.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_adsbitsy.c
-@@ -11,28 +11,156 @@
- */
- #include <linux/kernel.h>
- #include <linux/sched.h>
-+#include <linux/ioport.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-+#include <asm/irq.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-
-+int adsbitsy_smc91111_present(void);
-+
-+#ifndef CONFIG_SMC91111
-+#define adsbitsy_smc91111_present() 0
-+#endif
-+
-+static struct irqs {
-+ int irq;
-+ const char *str;
-+} irqs[] = {
-+ { S0_CD_VALID, "SA1111 PCMCIA card detect" },
-+ { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
-+ { S1_CD_VALID, "SA1111 CF card detect" },
-+ { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
-+};
-+
- static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
- {
-- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
-- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+ int ret=0;
-+ int nirq = 0;
-+ int slots = 0;
-+ int i;
-
-- /* Disable Power 3.3V/5V for PCMCIA/CF */
-- PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
-+ /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
-+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
-
-- /* Why? */
-- MECR = 0x09430943;
-+ /* Disable Power 3.3V/5V for PCMCIA */
-+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
-
-- return sa1111_pcmcia_init(init);
-+ if (!request_mem_region(_PCCR, 512, "PCMCIA"))
-+ return -1;
-+
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
-+
-+ nirq = 2;
-+ slots = 1;
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ /* If the SMC91111 is used CF cannot be used */
-+ /* Set GPIO_A<3:2> to be outputs for CF power controller: */
-+ PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
-+
-+ /* Disable Power 3.3V/5V for CF */
-+ PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+ nirq = 4;
-+ slots = 2;
-+ }
-+
-+ for (i = ret = 0; i < nirq; i++) {
-+ ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (ret)
-+ break;
-+ }
-+
-+ if (i < nirq) {
-+ printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
-+ irqs[i].irq, ret);
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ release_mem_region(_PCCR, 16);
-+ }
-+
-+ return ret ? -1 : slots;
- }
-
--static int
--adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
-+static int adsbitsy_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state)
-+{
-+ unsigned long status;
-+
-+ if (adsbitsy_smc91111_present()) {
-+ if(state->size<1) return -1;
-+ }
-+ else
-+ if(state->size<2) return -1;
-+
-+ memset(state->state, 0,
-+ (state->size)*sizeof(struct pcmcia_state));
-+
-+ status = PCSR;
-+
-+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
-+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
-+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
-+ state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
-+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
-+ state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
-+ state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
-+
-+ if (state->size > 1) {
-+ if (adsbitsy_smc91111_present()) {
-+ // If there is SMC91111 on ADS Bitsy connector board
-+ // it returns not detect/ready/...
-+ state->state[1].detect = 0;
-+ state->state[1].ready = 0;
-+ state->state[1].bvd1 = 0;
-+ state->state[1].bvd2 = 0;
-+ state->state[1].wrprot = 0;
-+ state->state[1].vs_3v = 0;
-+ state->state[1].vs_Xv = 0;
-+ }
-+ else {
-+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
-+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
-+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
-+ state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
-+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
-+ state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
-+ state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
-+ }
-+ }
-+ return 1;
-+}
-+
-+static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
- {
- unsigned int pa_dwr_mask, pa_dwr_set;
- int ret;
-@@ -54,10 +182,11 @@
-
- switch (conf->vcc) {
- default:
-- case 0: pa_dwr_set = 0; break;
-+ case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
- case 33: pa_dwr_set = GPIO_GPIO2; break;
- case 50: pa_dwr_set = GPIO_GPIO3; break;
- }
-+ break;
-
- default:
- return -1;
-@@ -83,8 +212,8 @@
-
- struct pcmcia_low_level adsbitsy_pcmcia_ops = {
- init: adsbitsy_pcmcia_init,
-- shutdown: sa1111_pcmcia_shutdown,
-- socket_state: sa1111_pcmcia_socket_state,
-+ shutdown: adsbitsy_pcmcia_shutdown,
-+ socket_state: adsbitsy_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: adsbitsy_pcmcia_configure_socket,
-
---- /dev/null
-+++ linux-2.4.27/drivers/pcmcia/sa1100_adsbitsyplus.c
-@@ -0,0 +1,236 @@
-+/*
-+ * drivers/pcmcia/sa1100_adsbitsyplus.c
-+ *
-+ * PCMCIA implementation routines for ADS Bitsy Plus
-+ *
-+ * Created Feb 7, 2003 by Robert Whaley <rwhaley@applieddata.net>
-+ *
-+ * This file comes from sa1100_adsbitsy.c of Woojung Huh <whuh@applieddata.net>
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-+#include <asm/irq.h>
-+
-+#include "sa1100_generic.h"
-+#include "sa1111_generic.h"
-+
-+int adsbitsy_smc91111_present(void);
-+
-+#ifndef CONFIG_SMC91111
-+#define adsbitsy_smc91111_present() 0
-+#endif
-+
-+static struct irqs {
-+ int irq;
-+ const char *str;
-+} irqs[] = {
-+ { S0_CD_VALID, "SA1111 PCMCIA card detect" },
-+ { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
-+ { S1_CD_VALID, "SA1111 CF card detect" },
-+ { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
-+};
-+
-+#define sock0_3_3_reverse_logic() ((ADS_CPLD_IO2 & ADS_IO2_CPLD_REV_MASK) >= ADS_IO2_CPLD_REV_5_MAGIC)
-+
-+static int adsbitsyplus_pcmcia_init(struct pcmcia_init *init)
-+{
-+ int ret=0;
-+ int nirq = 0;
-+ int slots = 0;
-+ int i;
-+
-+ /* Set GPIO_A<1:0> to be outputs for PCMCIA power controller: */
-+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1);
-+
-+ /* Disable Power 3.3V/5V for PCMCIA */
-+ if (sock0_3_3_reverse_logic())
-+ PA_DWR = (PA_DWR & ~GPIO_GPIO0) | GPIO_GPIO1;
-+ else
-+ PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1;
-+
-+ if (!request_mem_region(_PCCR, 512, "PCMCIA"))
-+ return -1;
-+
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
-+ SA1111_IRQMASK_HI(S0_CD_VALID) |
-+ SA1111_IRQMASK_HI(S0_BVD1_STSCHG);
-+
-+ nirq = 2;
-+ slots = 1;
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ /* If the SMC91111 is used CF cannot be used */
-+ /* Set GPIO_A<3:2> to be outputs for CF power controller: */
-+ PA_DDR &= ~(GPIO_GPIO2 | GPIO_GPIO3);
-+
-+ /* Disable Power 3.3V/5V for CF */
-+ PA_DWR |= GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ INTPOL1 |= SA1111_IRQMASK_HI(S1_READY_NINT) |
-+ SA1111_IRQMASK_HI(S1_CD_VALID) |
-+ SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
-+
-+ nirq = 4;
-+ slots = 2;
-+ }
-+
-+ for (i = ret = 0; i < nirq; i++) {
-+ ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
-+ irqs[i].str, NULL);
-+ if (ret)
-+ break;
-+ }
-+
-+ if (i < nirq) {
-+ printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
-+ irqs[i].irq, ret);
-+ while (i--)
-+ free_irq(irqs[i].irq, NULL);
-+
-+ release_mem_region(_PCCR, 16);
-+ }
-+
-+ return ret ? -1 : slots;
-+}
-+
-+static int adsbitsyplus_pcmcia_shutdown(void)
-+{
-+
-+ free_irq(S0_CD_VALID, NULL);
-+ free_irq(S0_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) | SA1111_IRQMASK_HI(S0_BVD1_STSCHG));
-+
-+ if (!adsbitsy_smc91111_present()) {
-+ free_irq(S1_CD_VALID, NULL);
-+ free_irq(S1_BVD1_STSCHG, NULL);
-+ INTPOL1 &= ~(SA1111_IRQMASK_HI(S1_CD_VALID) | SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int adsbitsyplus_pcmcia_socket_state(struct pcmcia_state_array *state)
-+{
-+ unsigned long status;
-+
-+ if (adsbitsy_smc91111_present()) {
-+ if(state->size<1) return -1;
-+ }
-+ else
-+ if(state->size<2) return -1;
-+
-+ memset(state->state, 0,
-+ (state->size)*sizeof(struct pcmcia_state));
-+
-+ status = PCSR;
-+
-+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
-+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
-+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
-+ state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
-+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
-+ state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
-+ state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
-+
-+ if (state->size > 1) {
-+ if (adsbitsy_smc91111_present()) {
-+ // If there is SMC91111 on ADS Bitsy connector board
-+ // it returns not detect/ready/...
-+ state->state[1].detect = 0;
-+ state->state[1].ready = 0;
-+ state->state[1].bvd1 = 0;
-+ state->state[1].bvd2 = 0;
-+ state->state[1].wrprot = 0;
-+ state->state[1].vs_3v = 0;
-+ state->state[1].vs_Xv = 0;
-+ }
-+ else {
-+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
-+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
-+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
-+ state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
-+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
-+ state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
-+ state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
-+ }
-+ }
-+ return 1;
-+}
-+
-+static int adsbitsyplus_pcmcia_configure_socket(const struct pcmcia_configure *conf)
-+{
-+ unsigned int pa_dwr_mask, pa_dwr_set;
-+ int ret;
-+
-+ switch (conf->sock) {
-+ case 0:
-+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
-+
-+ if (sock0_3_3_reverse_logic()) {
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO1; break;
-+ case 33: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
-+ case 50: pa_dwr_set = 0; break;
-+ }
-+ } else {
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
-+ case 33: pa_dwr_set = GPIO_GPIO1; break;
-+ case 50: pa_dwr_set = GPIO_GPIO0; break;
-+ }
-+ }
-+ break;
-+
-+ case 1:
-+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
-+
-+ switch (conf->vcc) {
-+ default:
-+ case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
-+ case 33: pa_dwr_set = GPIO_GPIO2; break;
-+ case 50: pa_dwr_set = GPIO_GPIO3; break;
-+ }
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
-+ printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
-+ __FUNCTION__, conf->vpp);
-+ return -1;
-+ }
-+
-+ ret = sa1111_pcmcia_configure_socket(conf);
-+ if (ret == 0) {
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
-+ local_irq_restore(flags);
-+ }
-+
-+ return ret;
-+}
-+
-+struct pcmcia_low_level adsbitsyplus_pcmcia_ops = {
-+ init: adsbitsyplus_pcmcia_init,
-+ shutdown: adsbitsyplus_pcmcia_shutdown,
-+ socket_state: adsbitsyplus_pcmcia_socket_state,
-+ get_irq_info: sa1111_pcmcia_get_irq_info,
-+ configure_socket: adsbitsyplus_pcmcia_configure_socket,
-+
-+ socket_init: sa1111_pcmcia_socket_init,
-+ socket_suspend: sa1111_pcmcia_socket_suspend,
-+};
-+
---- linux-2.4.27/drivers/pcmcia/sa1100_freebird.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_freebird.c
-@@ -67,9 +67,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels = LINKUP_PRS;
- //printk("LINKUP_PRS=%x \n",levels);
-
---- linux-2.4.27/drivers/pcmcia/sa1100_generic.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_generic.c
-@@ -992,10 +992,18 @@
- if(machine_is_graphicsmaster())
- pcmcia_low_level = &graphicsmaster_pcmcia_ops;
- #endif
-+#ifdef CONFIG_SA1100_ADSAGC
-+ if(machine_is_adsagc())
-+ pcmcia_low_level = &graphicsmaster_pcmcia_ops;
-+#endif
- #ifdef CONFIG_SA1100_ADSBITSY
- if(machine_is_adsbitsy())
- pcmcia_low_level = &adsbitsy_pcmcia_ops;
- #endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if(machine_is_adsbitsyplus())
-+ pcmcia_low_level = &adsbitsyplus_pcmcia_ops;
-+#endif
- #ifdef CONFIG_SA1100_STORK
- if(machine_is_stork())
- pcmcia_low_level = &stork_pcmcia_ops;
-@@ -1067,7 +1075,7 @@
- * We initialize the MECR to default values here, because we are
- * not guaranteed to see a SetIOMap operation at runtime.
- */
-- mecr = 0;
-+ mecr = MECR;
-
- clock = cpufreq_get(0);
-
---- linux-2.4.27/drivers/pcmcia/sa1100_graphicsclient.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_graphicsclient.c
-@@ -3,6 +3,8 @@
- *
- * PCMCIA implementation routines for Graphics Client Plus
- *
-+ * Nov/14/01 Woojung
-+ * Set MECR at initializing time
- * 9/12/01 Woojung
- * Turn power OFF at startup
- * 1/31/2001 Woojung Huh
-@@ -19,11 +21,6 @@
- #include <asm/irq.h>
- #include "sa1100_generic.h"
-
--#error This is broken!
--
--#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
--#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
--
- static volatile unsigned long *PCMCIA_Status =
- ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS));
-
-@@ -46,20 +43,23 @@
- *PCMCIA_Power &= ~0x03;
-
- /* Register interrupts */
-- irq = S0_CD_IRQ;
-+ irq = IRQ_GRAPHICSCLIENT_S0_CD;
- res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
- if (res < 0) {
-- printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
-+ printk(KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq);
- return -1;
- }
-
-+ // Nov/14/01 WH
-+ MECR = 0x00000943;
-+
- return 1; // 1 PCMCIA Slot
- }
-
- static int gcplus_pcmcia_shutdown(void)
- {
- /* disable IRQs */
-- free_irq( S0_CD_IRQ, NULL);
-+ free_irq( IRQ_GRAPHICSCLIENT_S0_CD, NULL);
-
- /* Shutdown PCMCIA power */
- mdelay(2); // 2msec
-@@ -74,9 +74,6 @@
-
- if(state_array->size<1) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=*PCMCIA_Status;
-
- state_array->state[0].detect=(levels & ADS_CS_ST_A_CD)?1:0;
-@@ -96,7 +93,7 @@
- return -1;
-
- if (info->sock == 0)
-- info->irq = S0_STS_IRQ;
-+ info->irq = IRQ_GRAPHICSCLIENT_S0_STS;
-
- return 0;
- }
-@@ -143,6 +140,11 @@
-
- restore_flags(flags);
-
-+ if (configure->irq)
-+ enable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
-+ else
-+ disable_irq(IRQ_GRAPHICSCLIENT_S0_STS);
-+
- return 0;
- }
-
---- linux-2.4.27/drivers/pcmcia/sa1100_graphicsmaster.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_graphicsmaster.c
-@@ -12,13 +12,13 @@
- #include <linux/sched.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-
- static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
- {
-- int return_val=0;
-
- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-@@ -26,9 +26,6 @@
- /* Disable Power 3.3V/5V for PCMCIA/CF */
- PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
-
-- /* why? */
-- MECR = 0x09430943;
--
- return sa1111_pcmcia_init(init);
- }
-
-@@ -59,6 +56,10 @@
- case 33: pa_dwr_set = GPIO_GPIO3; break;
- case 50: pa_dwr_set = GPIO_GPIO2; break;
- }
-+ break;
-+
-+ default:
-+ return -1;
- }
-
- if (conf->vpp != conf->vcc && conf->vpp != 0) {
---- linux-2.4.27/drivers/pcmcia/sa1100_h3600.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_h3600.c
-@@ -29,6 +29,9 @@
- set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_IRQ0 | GPIO_H3600_PCMCIA_IRQ1,
- GPIO_FALLING_EDGE);
-
-+ set_GPIO_IRQ_edge(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1,
-+ GPIO_NO_EDGES);
-+
- /*
- * Register interrupts
- */
---- linux-2.4.27/drivers/pcmcia/sa1100_jornada720.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_jornada720.c
-@@ -8,6 +8,7 @@
- #include <linux/sched.h>
-
- #include <asm/hardware.h>
-+#include <asm/hardware/sa1111.h>
-
- #include "sa1100_generic.h"
- #include "sa1111_generic.h"
-@@ -88,7 +89,7 @@
-
- local_irq_save(flags);
- PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
-- locla_irq_restore(flags);
-+ local_irq_restore(flags);
- }
-
- return ret;
---- linux-2.4.27/drivers/pcmcia/sa1100_pangolin.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_pangolin.c
-@@ -53,9 +53,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
- #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
- state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
---- linux-2.4.27/drivers/pcmcia/sa1100_shannon.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_shannon.c
-@@ -53,9 +53,6 @@
- {
- unsigned long levels;
-
-- memset(state_array->state, 0,
-- state_array->size * sizeof(struct pcmcia_state));
--
- levels = GPLR;
-
- state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
---- linux-2.4.27/drivers/pcmcia/sa1100_simpad.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_simpad.c
-@@ -63,9 +63,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
-
- state_array->state[1].detect=((levels & GPIO_CF_CD)==0)?1:0;
---- linux-2.4.27/drivers/pcmcia/sa1100_stork.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_stork.c
-@@ -79,9 +79,6 @@
-
- if(state_array->size<2) return -1;
-
-- memset(state_array->state, 0,
-- (state_array->size)*sizeof(struct pcmcia_state));
--
- levels=GPLR;
-
- if (debug > 1)
---- linux-2.4.27/drivers/pcmcia/sa1100_yopy.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/pcmcia/sa1100_yopy.c
-@@ -73,9 +73,6 @@
- if (state_array->size != 1)
- return -1;
-
-- memset(state_array->state, 0,
-- state_array->size * sizeof(struct pcmcia_state));
--
- levels = GPLR;
-
- state_array->state[0].detect = (levels & GPIO_CF_CD) ? 0 : 1;
---- /dev/null
-+++ linux-2.4.27/drivers/pld/Makefile
-@@ -0,0 +1,28 @@
-+#
-+# Makefile for the kernel pld device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definitions are now inherited from the
-+# parent makes..
-+#
-+# $Id: $
-+#
-+
-+O_TARGET := pld.o
-+
-+export-objs := pld_hotswap.o
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+obj-$(CONFIG_PLD) += pld_epxa.o
-+obj-$(CONFIG_PLD_HOTSWAP) += pld_hotswap.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastdep:
-+
---- /dev/null
-+++ linux-2.4.27/drivers/pld/pld_epxa.c
-@@ -0,0 +1,375 @@
-+
-+/*
-+ * drivers/char/epxapld.c
-+ *
-+ * Copyright (C) 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/module.h>
-+#include <asm/io.h>
-+#include <asm/uaccess.h>
-+#include <asm/arch/excalibur.h>
-+#include <asm/arch/hardware.h>
-+#define PLD_CONF00_TYPE (volatile unsigned int *)
-+#define MODE_CTRL00_TYPE (volatile unsigned int *)
-+//#define DEBUG(x) x
-+#define DEBUG(x)
-+
-+#include <asm/arch/mode_ctrl00.h>
-+#include <asm/arch/pld_conf00.h>
-+#ifdef CONFIG_PLD_HOTSWAP
-+#include <linux/pld/pld_hotswap.h>
-+#endif
-+#include <linux/pld/pld_epxa.h>
-+
-+/*
-+ * Macros
-+ */
-+
-+
-+#define PLD_BASE (IO_ADDRESS(EXC_PLD_CONFIG00_BASE))
-+#define CLOCK_DIV_RATIO ((1 + EXC_AHB2_CLK_FREQUENCY/32000000) & CONFIG_CONTROL_CLOCK_RATIO_MSK)
-+/*
-+ * STRUCTURES
-+ */
-+
-+
-+struct pld_sbihdr{
-+ unsigned int fpos;
-+ unsigned int temp;
-+};
-+
-+static DECLARE_MUTEX(pld_sem);
-+
-+
-+static void lock_pld (void)
-+{
-+ /* Lock the pld i/f */
-+ unsigned int tmp;
-+
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ tmp |= CONFIG_CONTROL_LK_MSK;
-+
-+ writel(tmp,CONFIG_CONTROL(PLD_BASE));
-+}
-+
-+static void unlock_excalibur_pld (void)
-+{
-+ /* Unlock the pld i/f */
-+
-+ if (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK ){
-+ writel(CONFIG_UNLOCK_MAGIC, CONFIG_UNLOCK(PLD_BASE));
-+ while (readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_LK_MSK);
-+ }
-+}
-+
-+
-+static int place_pld_into_configure_mode (void)
-+{
-+ unsigned int tmp;
-+
-+
-+ if( readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK ){
-+ /*
-+ * Already being configured!!!
-+ */
-+ printk(KERN_WARNING "pld0: Device already being configured!\n");
-+ return -EBUSY;
-+ }
-+
-+ /* Set up the config clock */
-+
-+ writel(CLOCK_DIV_RATIO,CONFIG_CONTROL_CLOCK(PLD_BASE));
-+ while(readl(CONFIG_CONTROL_CLOCK(PLD_BASE))
-+ !=CLOCK_DIV_RATIO);
-+ /* Tell the device we wish to configure it */
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ tmp |= CONFIG_CONTROL_CO_MSK;
-+ writel(tmp,CONFIG_CONTROL(PLD_BASE));
-+
-+
-+ /*
-+ * Wait for the busy bit to clear then check for errors.
-+ */
-+
-+ while((tmp=readl(CONFIG_CONTROL(PLD_BASE))&CONFIG_CONTROL_B_MSK ));
-+
-+ if ( tmp & CONFIG_CONTROL_E_MSK ){
-+ if ( tmp & CONFIG_CONTROL_ES_0_MSK ){
-+ /* Already being programmed via JTAG */
-+ printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
-+ return -EBUSY;
-+
-+ }
-+ if ( tmp & CONFIG_CONTROL_ES_1_MSK ){
-+ /* No config clock configured */
-+ printk(KERN_ERR "pld0:No config clock!\n");
-+ BUG();
-+ return -EBUSY;
-+ }
-+ if ( tmp & CONFIG_CONTROL_ES_2_MSK ){
-+ /* Already being programmed via External device */
-+ printk(KERN_WARNING "pld0:JTAG configuration alreay in progress\n");
-+ return -EBUSY;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int write_pld_data_word(unsigned int config_data)
-+{
-+ unsigned int tmp;
-+
-+ do{
-+ tmp = readl(CONFIG_CONTROL(PLD_BASE));
-+ }
-+ while ( ( tmp & CONFIG_CONTROL_B_MSK ) &&
-+ !( tmp & CONFIG_CONTROL_E_MSK ));
-+
-+ if ( tmp & CONFIG_CONTROL_E_MSK ){
-+ printk("pld0: Error writing pld data, CONFIG_CONTROL=%#x\n",tmp);
-+
-+ return -EILSEQ;
-+ }
-+
-+ writel(config_data,CONFIG_CONTROL_DATA(PLD_BASE));
-+ return 0;
-+
-+}
-+
-+
-+static int wait_for_device_to_configure (void)
-+{
-+ int i=0x10000;
-+
-+ while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
-+
-+ /*
-+ * Wait for the config bit (CO) to go low, indicating that everything
-+ * is Ok. If it doesn't, assume that is screwed up somehow and
-+ * clear the CO bit to abort the configuration.
-+ */
-+
-+ while(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_B_MSK);
-+
-+ while (i&&(readl(CONFIG_CONTROL(PLD_BASE)) & CONFIG_CONTROL_CO_MSK)){
-+ i--;
-+ }
-+
-+ if (!i){
-+ writel(0,CONFIG_CONTROL(PLD_BASE));
-+ printk(KERN_WARNING "pld0: Invalid PLD config data\n");
-+ return -EILSEQ;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+static int pld_open(struct inode* inode, struct file *filep)
-+{
-+
-+ struct pld_sbihdr* sbihdr;
-+
-+ /* Check the device minor number */
-+ if(minor(inode->i_rdev)){
-+ DEBUG(printk("pld0: minor=%d",minor(inode->i_rdev));)
-+ return -ENODEV;
-+ }
-+
-+ /* Create our private data and link it to the file structure */
-+ sbihdr=kmalloc(sizeof(struct pld_sbihdr),GFP_KERNEL);
-+
-+ if(!sbihdr)
-+ return -ENOMEM;
-+
-+ filep->private_data=sbihdr;
-+
-+ sbihdr->fpos=0;
-+ sbihdr->temp=0;
-+ return 0;
-+}
-+
-+static int pld_release(struct inode* inode, struct file *filep){
-+ int ret_code;
-+
-+ kfree(filep->private_data);
-+ ret_code=wait_for_device_to_configure();
-+ lock_pld();
-+ return ret_code;
-+}
-+
-+static ssize_t pld_write(struct file* filep, const char* data, size_t count, loff_t* ppos){
-+
-+ struct pld_sbihdr* sbihdr=filep->private_data;
-+ int bytes_left=count;
-+ int result;
-+ DEBUG(int i=0);
-+
-+
-+ /* Can't seek (pwrite) on pld. */
-+ if (ppos != &filep->f_pos)
-+ return -ESPIPE;
-+
-+
-+ /* Check access to the whole are in one go */
-+ if(!access_ok(VERIFY_READ,(const void*)data, count)){
-+ return -EFAULT;
-+ }
-+
-+ /*
-+ * We now lock against writes.
-+ */
-+ if (down_interruptible(&pld_sem))
-+ return -ERESTARTSYS;
-+
-+ if(!sbihdr->fpos){
-+ /*
-+ * unlock the pld and place in configure mode
-+ */
-+ unlock_excalibur_pld();
-+ result=place_pld_into_configure_mode();
-+ if(result)
-+ return result;
-+ }
-+ DEBUG(printk("data= %#x count=%#x 0ffset=%#x\n",*data, count, *ppos));
-+
-+ while(bytes_left){
-+ char tmp;
-+ __get_user(tmp,data);
-+ /* read our header ! */
-+ sbihdr->temp|=tmp << (8*(sbihdr->fpos&3));
-+ if((sbihdr->fpos&3)==3){
-+ if(write_pld_data_word(sbihdr->temp))
-+ {
-+ DEBUG(printk("pos=%d\n",sbihdr->fpos);)
-+ return -EILSEQ;
-+ }
-+ DEBUG(if(i<10){)
-+ DEBUG(printk("fpos2 :%#x data=%#x\n",sbihdr->fpos,sbihdr->temp));
-+ DEBUG(i++);
-+ DEBUG(});
-+ sbihdr->temp=0;
-+ DEBUG(words_written++);
-+ }
-+ sbihdr->fpos++;
-+ data++;
-+ bytes_left--;
-+ }
-+
-+ up(&pld_sem);
-+ return (count);
-+}
-+
-+int pld_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
-+{
-+
-+ switch(cmd){
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+ case PLD_IOC_ADD_PLD_DEV:
-+ {
-+ struct pldhs_dev_desc desc;
-+ struct pldhs_dev_info info;
-+ char *name;
-+ void *data;
-+ int result=0;
-+
-+ result=copy_from_user(&desc,(const void*)arg,sizeof(struct pldhs_dev_desc));
-+ if(result)
-+ return -EFAULT;
-+ result=copy_from_user(&info,(const void*)desc.info,sizeof(struct pldhs_dev_info));
-+ if(result)
-+ return -EFAULT;
-+ name=kmalloc(info.nsize,GFP_KERNEL);
-+ if(!name)
-+ return -ENOMEM;
-+
-+ result=copy_from_user(name,(const void*)desc.name,info.nsize);
-+ if(result){
-+ result=-EFAULT;
-+ goto ioctl_out;
-+ }
-+
-+ data=kmalloc(info.pssize,GFP_KERNEL);
-+ if(!data){
-+ result=-ENOMEM;
-+ goto ioctl_out;
-+ }
-+
-+ result=copy_from_user(data,(const void*)desc.data,info.pssize);
-+ if(result){
-+ result=-EFAULT;
-+ goto ioctl_out1;
-+ }
-+ result=pldhs_add_device(&info,name,data);
-+
-+ ioctl_out1:
-+ kfree(data);
-+ ioctl_out:
-+ kfree(name);
-+ return result;
-+
-+ }
-+
-+ case PLD_IOC_REMOVE_PLD_DEVS:
-+ pldhs_remove_devices();
-+ return 0;
-+
-+ case PLD_IOC_SET_INT_MODE:
-+ if(cmd==3){
-+ printk(KERN_INFO "Interrupt mode set to 3 (Six individual interrupts)\n");
-+ return 0;
-+ }else{
-+ printk(KERN_INFO "There is no interrupt handler available for this mode (%d). You will need to add one\n to implement whatever scheme you require\n");
-+ return -EACCES;
-+ }
-+#endif
-+ default:
-+ return -ENOTTY;
-+ }
-+}
-+
-+
-+static struct file_operations pld_fops={
-+ write: pld_write,
-+ ioctl: pld_ioctl,
-+ open: pld_open,
-+ release: pld_release
-+};
-+
-+static int __init pld_init(void){
-+ int major;
-+ major=register_chrdev(0,"pld",&pld_fops);
-+ printk(KERN_INFO "Using PLD major num=%d\n",major);
-+ if (major<0){
-+ return major;
-+ }
-+ return 0;
-+}
-+
-+__initcall(pld_init);
---- /dev/null
-+++ linux-2.4.27/drivers/pld/pld_hotswap.c
-@@ -0,0 +1,188 @@
-+/*
-+ * linux/drivers/pld/pld_hotswap.c
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ *
-+ * Copyright 2001 Altera Corporation (cdavies@altera.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+
-+/*
-+ * pld_hotswap ops contains the basic operation required for adding
-+ * and removing devices from the system.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/pagemap.h>
-+#include <linux/slab.h>
-+#include <linux/smp_lock.h>
-+#include <linux/init.h>
-+#include <linux/kmod.h>
-+#include <linux/proc_fs.h>
-+#include <linux/list.h>
-+#include <asm/uaccess.h>
-+#include <linux/pld/pld_hotswap.h>
-+
-+
-+static struct pld_hotswap_ops pldhs_driver_list={
-+ list: LIST_HEAD_INIT(pldhs_driver_list.list),
-+ name: "",
-+};
-+
-+static spinlock_t list_lock=SPIN_LOCK_UNLOCKED;
-+
-+
-+
-+static struct pld_hotswap_ops * pldhs_find_driver(char* name)
-+{
-+ struct pld_hotswap_ops * ptr;
-+ struct list_head *list_pos;
-+
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(!strcmp(name, ptr->name)){
-+ spin_unlock(&list_lock);
-+ return ptr;
-+
-+ }
-+ }
-+ spin_unlock(&list_lock);
-+ return 0;
-+}
-+
-+
-+
-+int pldhs_register_driver(struct pld_hotswap_ops *drv)
-+{
-+
-+ /* Check that the device is not already on the list
-+ * if so, do nothing */
-+ if(pldhs_find_driver(drv->name)){
-+ return 0;
-+ }
-+
-+ printk(KERN_INFO "PLD: Registering hotswap driver %s\n",drv->name);
-+ /* Add this at the start of the list */
-+ spin_lock(&list_lock);
-+ list_add((struct list_head*)drv,&pldhs_driver_list.list);
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+int pldhs_unregister_driver(char *name)
-+{
-+ struct pld_hotswap_ops *ptr;
-+
-+ ptr=pldhs_find_driver(name);
-+ if(!ptr){
-+ return -ENODEV;
-+ }
-+
-+ printk(KERN_INFO "PLD: Unregistering hotswap driver%s\n",name);
-+ spin_lock(&list_lock);
-+ list_del((struct list_head*)ptr);
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data)
-+{
-+ struct pld_hotswap_ops * ptr;
-+
-+ ptr=pldhs_find_driver(drv_name);
-+
-+ if(!ptr){
-+ /* try requesting this module*/
-+ request_module(drv_name);
-+ /* is the driver there now? */
-+ ptr=pldhs_find_driver(drv_name);
-+ if(!ptr){
-+ printk("pld hotswap: Failed to load a driver for %s\n",drv_name);
-+ return -ENODEV;
-+ }
-+ }
-+
-+ if(!ptr->add_device){
-+ printk(KERN_WARNING "pldhs: no add_device() function for driver %s\n",drv_name);
-+ return 0;
-+ }
-+
-+ return ptr->add_device(dev_info,dev_ps_data);
-+}
-+
-+int pldhs_remove_devices(void)
-+{
-+ struct list_head *list_pos;
-+ struct pld_hotswap_ops * ptr;
-+
-+
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(ptr->remove_devices)
-+ ptr->remove_devices();
-+
-+ }
-+ spin_unlock(&list_lock);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+int pldhs_read_proc(char* buf,char** start,off_t offset,int count,int *eof,void *data){
-+
-+
-+ struct list_head *list_pos;
-+ struct pld_hotswap_ops * ptr;
-+ int i,len=0;
-+
-+ *start=buf;
-+ spin_lock(&list_lock);
-+ list_for_each(list_pos,&pldhs_driver_list.list){
-+ ptr=(struct pld_hotswap_ops *)list_pos;
-+ if(ptr->proc_read){
-+ i=ptr->proc_read(buf,start,offset,count,eof,data);
-+ count-=i;
-+ len+=i;
-+ *start+=i;
-+ }
-+ }
-+ spin_unlock(&list_lock);
-+
-+ *start=NULL;
-+ *eof=1;
-+ return len;
-+}
-+
-+void __init pldhs_init(void){
-+ create_proc_read_entry("pld",0,NULL,pldhs_read_proc,NULL);
-+}
-+
-+__initcall(pldhs_init);
-+#endif
-+
-+EXPORT_SYMBOL(pldhs_register_driver);
-+EXPORT_SYMBOL(pldhs_unregister_driver);
---- linux-2.4.27/drivers/scsi/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/Makefile
-@@ -21,7 +21,7 @@
-
- O_TARGET := scsidrv.o
-
--export-objs := scsi_syms.o 53c700.o libata-core.o
-+export-objs := scsi_syms.o 53c700.o scsi_error.o libata-core.o
- mod-subdirs := pcmcia ../acorn/scsi
-
-
---- linux-2.4.27/drivers/scsi/scsi.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi.c
-@@ -1334,14 +1334,10 @@
- */
- int scsi_retry_command(Scsi_Cmnd * SCpnt)
- {
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ /*
-+ * Restore the SCSI command state.
-+ */
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Zero the sense information from the last time we tried
---- linux-2.4.27/drivers/scsi/scsi.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi.h
-@@ -465,6 +465,7 @@
- int sectors);
- extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
- extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
-+extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
- extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
- extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
- int block_sectors);
-@@ -588,6 +589,7 @@
- unsigned changed:1; /* Data invalid due to media change */
- unsigned busy:1; /* Used to prevent races */
- unsigned lockable:1; /* Able to prevent media removal */
-+ unsigned locked:1; /* Media removal disabled */
- unsigned borken:1; /* Tell the Seagate driver to be
- * painfully slow on this device */
- unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
---- linux-2.4.27/drivers/scsi/scsi_dma.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi_dma.c
-@@ -30,6 +30,15 @@
- typedef unsigned char FreeSectorBitmap;
- #elif SECTORS_PER_PAGE <= 32
- typedef unsigned int FreeSectorBitmap;
-+#elif SECTORS_PER_PAGE <= 64
-+#if 0
-+typedef unsigned long long FreeSectorBitmap;
-+#else
-+typedef struct {
-+ unsigned long l,h;
-+} FreeSectorBitmap;
-+#define LARGE_MALLOC
-+#endif
- #else
- #error You lose.
- #endif
-@@ -69,6 +78,7 @@
- * to allocate more memory in order to be able to write the
- * data to disk, you would wedge the system.
- */
-+#ifndef LARGE_MALLOC
- void *scsi_malloc(unsigned int len)
- {
- unsigned int nbits, mask;
-@@ -167,6 +177,97 @@
- panic("scsi_free:Bad offset");
- }
-
-+#else
-+
-+void *scsi_malloc(unsigned int len)
-+{
-+ unsigned int nbits;
-+ unsigned long maskl, maskh, flags;
-+ FreeSectorBitmap *fsb;
-+ int i;
-+
-+ if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
-+ return NULL;
-+
-+ save_flags_cli (flags);
-+ nbits = len >> 9;
-+ if (nbits < 32) {
-+ maskl = (1 << nbits) - 1;
-+ maskh = 0;
-+ } else {
-+ maskl = (unsigned long)-1;
-+ maskh = (1 << (nbits - 32)) - 1;
-+ }
-+
-+ fsb = dma_malloc_freelist;
-+
-+ for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) {
-+ unsigned long mml, mmh;
-+ int j;
-+ mml = maskl;
-+ mmh = maskh;
-+ j = 0;
-+ do {
-+ if ((fsb->l & mml) == 0 && (fsb->h & mmh) == 0) {
-+ fsb->h |= mmh;
-+ fsb->l |= mml;
-+ restore_flags (flags);
-+ scsi_dma_free_sectors -= nbits;
-+#ifdef DEBUG
-+ printk("SMalloc: %d %p\n",len, dma_malloc_pages[i] + (j << 9));
-+#endif
-+ return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
-+ }
-+ mmh = (mmh << 1) | (mml >> 31);
-+ mml <<= 1;
-+ j++;
-+ } while (!(mmh & (1 << 31)));
-+ fsb ++;
-+ }
-+ return NULL; /* Nope. No more */
-+}
-+
-+int scsi_free(void *obj, unsigned int len)
-+{
-+ unsigned int page, sector, nbits;
-+ unsigned long maskl, maskh, flags;
-+
-+#ifdef DEBUG
-+ printk("scsi_free %p %d\n",obj, len);
-+#endif
-+
-+ for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
-+ unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
-+ if ((unsigned long) obj >= page_addr &&
-+ (unsigned long) obj < page_addr + PAGE_SIZE) {
-+ sector = (((unsigned long) obj) - page_addr) >> 9;
-+ nbits = len >> 9;
-+ if (nbits < 32) {
-+ maskl = (1 << nbits) - 1;
-+ maskh = 0;
-+ } else {
-+ maskl = (unsigned long)-1;
-+ maskh = (1 << (nbits - 32)) - 1;
-+ }
-+ if ((sector + nbits) > SECTORS_PER_PAGE)
-+ panic ("scsi_free:Bad memory alignment");
-+ maskh = (maskh << sector) | (maskl >> (32 - sector));
-+ maskl = maskl << sector;
-+ save_flags_cli(flags);
-+ if (((dma_malloc_freelist[page].l & maskl) != maskl) ||
-+ ((dma_malloc_freelist[page].h & maskh) != maskh))
-+ panic("scsi_free:Trying to free unused memory");
-+ scsi_dma_free_sectors += nbits;
-+ dma_malloc_freelist[page].l &= ~maskl;
-+ dma_malloc_freelist[page].h &= ~maskh;
-+ restore_flags(flags);
-+ return 0;
-+ }
-+ }
-+ panic("scsi_free:Bad offset");
-+}
-+#endif
-+
-
- /*
- * Function: scsi_resize_dma_pool
---- linux-2.4.27/drivers/scsi/scsi_error.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi_error.c
-@@ -35,6 +35,8 @@
- #include "hosts.h"
- #include "constants.h"
-
-+#include <scsi/scsi_ioctl.h> /* grr */
-+
- /*
- * We must always allow SHUTDOWN_SIGS. Even if we are not a module,
- * the host drivers that we are using may be loaded as modules, and
-@@ -49,6 +51,13 @@
- */
- #define SHUTDOWN_SIGS (sigmask(SIGHUP))
-
-+/*
-+ * The number of times we retry a REQUEST SENSE and TEST UNIT READY
-+ * respectively. This is arbitary.
-+ */
-+#define SENSE_RETRIES 5
-+#define TUR_RETRIES 5
-+
- #ifdef DEBUG
- #define SENSE_TIMEOUT SCSI_TIMEOUT
- #define ABORT_TIMEOUT SCSI_TIMEOUT
-@@ -373,16 +382,12 @@
- */
- STATIC int scsi_eh_retry_command(Scsi_Cmnd * SCpnt)
- {
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ int tries = 0;
-
-- scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
-+ do {
-+ scsi_setup_cmd_retry(SCpnt);
-+ scsi_send_eh_cmnd(SCpnt, SCpnt->timeout_per_command);
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SCpnt->allowed);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -409,16 +414,10 @@
- static unsigned char generic_sense[6] =
- {REQUEST_SENSE, 0, 0, 0, 255, 0};
- unsigned char scsi_result0[256], *scsi_result = NULL;
-- int saved_result;
-+ int saved_result, tries;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
-- memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
-- sizeof(generic_sense));
--
-- if (SCpnt->device->scsi_level <= SCSI_2)
-- SCpnt->cmnd[1] = SCpnt->lun << 5;
--
- scsi_result = (!SCpnt->host->hostt->unchecked_isa_dma)
- ? &scsi_result0[0] : kmalloc(512, GFP_ATOMIC | GFP_DMA);
-
-@@ -426,24 +425,41 @@
- printk("cannot allocate scsi_result in scsi_request_sense.\n");
- return FAILED;
- }
-- /*
-- * Zero the sense buffer. Some host adapters automatically always request
-- * sense, so it is not a good idea that SCpnt->request_buffer and
-- * SCpnt->sense_buffer point to the same address (DB).
-- * 0 is not a valid sense code.
-- */
-- memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-- memset((void *) scsi_result, 0, 256);
-
- saved_result = SCpnt->result;
-- SCpnt->request_buffer = scsi_result;
-- SCpnt->request_bufflen = 256;
-- SCpnt->use_sg = 0;
-- SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-- SCpnt->sc_data_direction = SCSI_DATA_READ;
-- SCpnt->underflow = 0;
-
-- scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ tries = 0;
-+ do {
-+ memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
-+ sizeof(generic_sense));
-+
-+ if (SCpnt->device->scsi_level <= SCSI_2)
-+ SCpnt->cmnd[1] = SCpnt->lun << 5;
-+
-+ /*
-+ * Zero the sense buffer. Some host adapters automatically
-+ * always request sense, so it is not a good idea that
-+ * SCpnt->request_buffer and SCpnt->sense_buffer point to
-+ * the same address (DB). 0 is not a valid sense code.
-+ */
-+ memset((void *) SCpnt->sense_buffer, 0,
-+ sizeof(SCpnt->sense_buffer));
-+ memset((void *) scsi_result, 0, 256);
-+
-+ SCpnt->request_buffer = scsi_result;
-+ SCpnt->request_bufflen = 256;
-+ SCpnt->use_sg = 0;
-+ SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-+ SCpnt->sc_data_direction = SCSI_DATA_READ;
-+ SCpnt->underflow = 0;
-+
-+ scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ /*
-+ * If the SCSI device responded with "logical unit
-+ * is in process of becoming ready", we need to
-+ * retry this command.
-+ */
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < SENSE_RETRIES);
-
- /* Last chance to have valid sense data */
- if (!scsi_sense_valid(SCpnt))
-@@ -458,15 +474,8 @@
- * When we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (DB)
- */
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
- SCpnt->result = saved_result;
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -484,40 +493,42 @@
- {
- static unsigned char tur_command[6] =
- {TEST_UNIT_READY, 0, 0, 0, 0, 0};
-+ int tries = 0;
-
-- memcpy((void *) SCpnt->cmnd, (void *) tur_command,
-- sizeof(tur_command));
-+ do {
-+ memcpy((void *) SCpnt->cmnd, (void *) tur_command,
-+ sizeof(tur_command));
-
-- if (SCpnt->device->scsi_level <= SCSI_2)
-- SCpnt->cmnd[1] = SCpnt->lun << 5;
-+ if (SCpnt->device->scsi_level <= SCSI_2)
-+ SCpnt->cmnd[1] = SCpnt->lun << 5;
-
-- /*
-- * Zero the sense buffer. The SCSI spec mandates that any
-- * untransferred sense data should be interpreted as being zero.
-- */
-- memset((void *) SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-+ /*
-+ * Zero the sense buffer. The SCSI spec mandates that any
-+ * untransferred sense data should be interpreted as being zero.
-+ */
-+ memset((void *) SCpnt->sense_buffer, 0,
-+ sizeof(SCpnt->sense_buffer));
-
-- SCpnt->request_buffer = NULL;
-- SCpnt->request_bufflen = 0;
-- SCpnt->use_sg = 0;
-- SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-- SCpnt->underflow = 0;
-- SCpnt->sc_data_direction = SCSI_DATA_NONE;
-+ SCpnt->request_buffer = NULL;
-+ SCpnt->request_bufflen = 0;
-+ SCpnt->use_sg = 0;
-+ SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-+ SCpnt->underflow = 0;
-+ SCpnt->sc_data_direction = SCSI_DATA_NONE;
-
-- scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ scsi_send_eh_cmnd(SCpnt, SENSE_TIMEOUT);
-+ /*
-+ * If the SCSI device responded with "logical unit
-+ * is in process of becoming ready", we need to
-+ * retry this command.
-+ */
-+ } while (SCpnt->eh_state == NEEDS_RETRY && tries++ < TUR_RETRIES);
-
- /*
- * When we eventually call scsi_finish, we really wish to complete
- * the original request, so let's restore the original data. (DB)
- */
-- memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-- sizeof(SCpnt->data_cmnd));
-- SCpnt->request_buffer = SCpnt->buffer;
-- SCpnt->request_bufflen = SCpnt->bufflen;
-- SCpnt->use_sg = SCpnt->old_use_sg;
-- SCpnt->cmd_len = SCpnt->old_cmd_len;
-- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-- SCpnt->underflow = SCpnt->old_underflow;
-+ scsi_setup_cmd_retry(SCpnt);
-
- /*
- * Hey, we are done. Let's look to see what happened.
-@@ -577,7 +588,6 @@
-
- host = SCpnt->host;
-
-- retry:
- /*
- * We will use a queued command if possible, otherwise we will emulate the
- * queuing and calling of completion function ourselves.
-@@ -660,14 +670,13 @@
- SCSI_LOG_ERROR_RECOVERY(3,
- printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", ret));
- switch (ret) {
-- case SUCCESS:
-- SCpnt->eh_state = SUCCESS;
-- break;
-- case NEEDS_RETRY:
-- goto retry;
-- case FAILED:
- default:
-- SCpnt->eh_state = FAILED;
-+ ret = FAILED;
-+ /*FALLTHROUGH*/
-+ case FAILED:
-+ case NEEDS_RETRY:
-+ case SUCCESS:
-+ SCpnt->eh_state = ret;
- break;
- }
- } else {
-@@ -1208,6 +1217,82 @@
-
-
- /*
-+ * Function: scsi_eh_lock_done
-+ *
-+ * Purpose: free the command and request structures associated
-+ * with the error handlers door lock request
-+ *
-+ * Arguments: SCpnt - the SCSI command block for the door lock request.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: We completed the asynchronous door lock request, and
-+ * it has either locked the door or failed. We must free
-+ * the command structures associated with this request.
-+ */
-+static void scsi_eh_lock_done(struct scsi_cmnd *SCpnt)
-+{
-+ struct scsi_request *SRpnt = SCpnt->sc_request;
-+
-+ SCpnt->sc_request = NULL;
-+ SRpnt->sr_command = NULL;
-+
-+ scsi_release_command(SCpnt);
-+ scsi_release_request(SRpnt);
-+}
-+
-+
-+/*
-+ * Function: scsi_eh_lock_door
-+ *
-+ * Purpose: Prevent medium removal for the specified device
-+ *
-+ * Arguments: dev - SCSI device to prevent medium removal
-+ *
-+ * Locking: We must be called from process context;
-+ * scsi_allocate_request() may sleep.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request
-+ * on the head of the devices request queue, and continue.
-+ *
-+ * Bugs: scsi_allocate_request() may sleep waiting for existing
-+ * requests to be processed. However, since we haven't
-+ * kicked off any request processing for this host, this
-+ * may deadlock.
-+ *
-+ * If scsi_allocate_request() fails for what ever reason,
-+ * we completely forget to lock the door.
-+ */
-+STATIC void scsi_eh_lock_door(struct scsi_device *dev)
-+{
-+ struct scsi_request *SRpnt = scsi_allocate_request(dev);
-+
-+ if (SRpnt == NULL) {
-+ /* what now? */
-+ return;
-+ }
-+
-+ SRpnt->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-+ SRpnt->sr_cmnd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
-+ SRpnt->sr_cmnd[2] = 0;
-+ SRpnt->sr_cmnd[3] = 0;
-+ SRpnt->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
-+ SRpnt->sr_cmnd[5] = 0;
-+ SRpnt->sr_data_direction = SCSI_DATA_NONE;
-+ SRpnt->sr_bufflen = 0;
-+ SRpnt->sr_buffer = NULL;
-+ SRpnt->sr_allowed = 5;
-+ SRpnt->sr_done = scsi_eh_lock_done;
-+ SRpnt->sr_timeout_per_command = 10 * HZ;
-+ SRpnt->sr_cmd_len = COMMAND_SIZE(SRpnt->sr_cmnd[0]);
-+
-+ scsi_insert_special_req(SRpnt, 1);
-+}
-+
-+
-+/*
- * Function: scsi_restart_operations
- *
- * Purpose: Restart IO operations to the specified host.
-@@ -1229,6 +1314,15 @@
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
-+ * If the door was locked, we need to insert a door lock request
-+ * onto the head of the SCSI request queue for the device. There
-+ * is no point trying to lock the door of an off-line device.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ if (SDpnt->online && SDpnt->locked)
-+ scsi_eh_lock_door(SDpnt);
-+
-+ /*
- * Next free up anything directly waiting upon the host. This will be
- * requests for character device operations, and also for ioctls to queued
- * block devices.
-@@ -1248,8 +1342,7 @@
- request_queue_t *q;
- if ((host->can_queue > 0 && (host->host_busy >= host->can_queue))
- || (host->host_blocked)
-- || (host->host_self_blocked)
-- || (SDpnt->device_blocked)) {
-+ || (host->host_self_blocked)) {
- break;
- }
- q = &SDpnt->request_queue;
-@@ -1259,136 +1352,202 @@
- }
-
- /*
-- * Function: scsi_unjam_host
-+ * Function: scsi_eh_find_failed_command
- *
-- * Purpose: Attempt to fix a host which has a command that failed for
-- * some reason.
-+ * Purpose: Find a failed Scsi_Cmnd structure on a device.
- *
-- * Arguments: host - host that needs unjamming.
-- *
-- * Returns: Nothing
-+ * Arguments: SDpnt - Scsi_Device structure
- *
-- * Notes: When we come in here, we *know* that all commands on the
-- * bus have either completed, failed or timed out. We also
-- * know that no further commands are being sent to the host,
-- * so things are relatively quiet and we have freedom to
-- * fiddle with things as we wish.
-+ * Returns: Pointer to Scsi_Cmnd structure, or NULL on failure
-+ */
-+STATIC Scsi_Cmnd *scsi_eh_find_failed_command(Scsi_Device *SDpnt)
-+{
-+ Scsi_Cmnd *SCpnt;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
-+ if (SCpnt->state == SCSI_STATE_FAILED ||
-+ SCpnt->state == SCSI_STATE_TIMEOUT)
-+ return SCpnt;
-+
-+ return NULL;
-+}
-+
-+
-+/*
-+ * Function: scsi_eh_test_and_retry
- *
-- * Additional note: This is only the *default* implementation. It is possible
-- * for individual drivers to supply their own version of this
-- * function, and if the maintainer wishes to do this, it is
-- * strongly suggested that this function be taken as a template
-- * and modified. This function was designed to correctly handle
-- * problems for about 95% of the different cases out there, and
-- * it should always provide at least a reasonable amount of error
-- * recovery.
-+ * Purpose: Try to retry a failed command.
- *
-- * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
-- * have scsi_finish_command() called for it. We do all of
-- * the retry stuff here, so when we restart the host after we
-- * return it should have an empty queue.
-+ * Arguments: SCpnt - scsi command structure
-+ * done - list of commands that have been successfully
-+ * completed.
-+ *
-+ * Returns: SUCCESS or FAILED
-+ *
-+ * Note: If the TEST UNIT READY command successfully executes,
-+ * but returns some form of "device not ready", we wait
-+ * a while, and retry 3 times. The device could be still
-+ * re-initialising.
- */
--STATIC int scsi_unjam_host(struct Scsi_Host *host)
-+STATIC int scsi_eh_test_and_retry(Scsi_Cmnd *SCpnt, Scsi_Cmnd **done)
- {
-- int devices_failed;
-- int numfailed;
-- int ourrtn;
-- int rtn = FALSE;
-- int result;
-- Scsi_Cmnd *SCloop;
-- Scsi_Cmnd *SCpnt;
-- Scsi_Device *SDpnt;
-- Scsi_Device *SDloop;
-- Scsi_Cmnd *SCdone;
-- int timed_out;
-+ int rtn, tries = 3;
-
-- ASSERT_LOCK(&io_request_lock, 0);
-+ do {
-+ rtn = scsi_test_unit_ready(SCpnt);
-+ if (rtn != SUCCESS)
-+ return rtn;
-
-- SCdone = NULL;
-+ if (scsi_unit_is_ready(SCpnt))
-+ break;
-+
-+ if (tries-- == 0)
-+ return FAILED;
-+
-+ scsi_sleep(5 * HZ);
-+ } while (1);
-+
-+ rtn = scsi_eh_retry_command(SCpnt);
-+ if (rtn == SUCCESS) {
-+ SCpnt->host->host_failed--;
-+ scsi_eh_finish_command(done, SCpnt);
-+ }
-+
-+ return rtn;
-+}
-
-- /*
-- * First, protect against any sort of race condition. If any of the outstanding
-- * commands are in states that indicate that we are not yet blocked (i.e. we are
-- * not in a quiet state) then we got woken up in error. If we ever end up here,
-- * we need to re-examine some of the assumptions.
-- */
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state == SCSI_STATE_FAILED
-- || SCpnt->state == SCSI_STATE_TIMEOUT
-- || SCpnt->state == SCSI_STATE_INITIALIZING
-- || SCpnt->state == SCSI_STATE_UNUSED) {
-- continue;
-- }
-- /*
-- * Rats. Something is still floating around out there. This could
-- * be the result of the fact that the upper level drivers are still frobbing
-- * commands that might have succeeded. There are two outcomes. One is that
-- * the command block will eventually be freed, and the other one is that
-- * the command will be queued and will be finished along the way.
-- */
-- SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
-
- /*
-- * panic("SCSI Error handler woken too early\n");
-+ * Function: scsi_eh_restart_device
- *
-- * This is no longer a problem, since now the code cares only about
-- * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
-- * Other states are useful only to release active commands when devices are
-- * set offline. If (host->host_active == host->host_busy) we can safely assume
-- * that there are no commands in state other then TIMEOUT od FAILED. (DB)
-+ * Purpose: Retry all failed or timed out commands for a device
- *
-- * FIXME:
-- * It is not easy to release correctly commands according to their state when
-- * devices are set offline, when the state is neither TIMEOUT nor FAILED.
-- * When a device is set offline, we can have some command with
-- * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
-- * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
-- * (DB, 17 May 1998)
-+ * Arguments: SDpnt - SCSI device to retry
-+ * done - list of commands that have been successfully
-+ * completed.
-+ *
-+ * Returns: SUCCESS or failure code
- */
-+STATIC int scsi_eh_restart_device(Scsi_Device *SDpnt, Scsi_Cmnd **done)
-+{
-+ Scsi_Cmnd *SCpnt, *SCnext;
-+ int rtn = SUCCESS;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
-+ SCnext = SCpnt->next;
-+
-+ if (SCpnt->state == SCSI_STATE_FAILED ||
-+ SCpnt->state == SCSI_STATE_TIMEOUT) {
-+ rtn = scsi_eh_test_and_retry(SCpnt, done);
-+ if (rtn != SUCCESS)
-+ break;
-+ }
-+ }
-+
-+ return rtn;
-+}
-+
-+/*
-+ * Function: scsi_eh_set_device_offline
-+ *
-+ * Purpose: set a device off line
-+ *
-+ * Arguments: SDpnt - SCSI device to take off line
-+ * done - list of commands that have been successfully
-+ * completed.
-+ * reason - text string describing why the device is off-line
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: In addition, we complete each failed or timed out command
-+ * attached to this device.
-+ */
-+STATIC void scsi_eh_set_device_offline(Scsi_Device *SDpnt, Scsi_Cmnd **done,
-+ const char *reason)
-+{
-+ Scsi_Cmnd *SCpnt, *SCnext;
-+
-+ printk(KERN_ERR "scsi: device set offline - %s: "
-+ "host %d channel %d id %d lun %d\n",
-+ reason, SDpnt->host->host_no, SDpnt->channel,
-+ SDpnt->id, SDpnt->lun);
-+
-+ SDpnt->online = FALSE;
-+
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCnext) {
-+ SCnext = SCpnt->next;
-+
-+ switch (SCpnt->state) {
-+ case SCSI_STATE_TIMEOUT:
-+ SCpnt->result |= DRIVER_TIMEOUT;
-+ /*FALLTHROUGH*/
-+
-+ case SCSI_STATE_FAILED:
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("Finishing command for device %d %x\n",
-+ SDpnt->id, SCpnt->result));
-+
-+ SDpnt->host->host_failed--;
-+ scsi_eh_finish_command(done, SCpnt);
-+ break;
-+
-+ default:
-+ break;
- }
- }
-+}
-+
-+static void scsi_unjam_request_sense(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ int rtn;
-+ int result;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Device *SDpnt;
-
- /*
- * Next, see if we need to request sense information. if so,
- * then get it now, so we have a better idea of what to do.
-- * FIXME(eric) this has the unfortunate side effect that if a host
-- * adapter does not automatically request sense information, that we end
-- * up shutting it down before we request it. All hosts should be doing this
-- * anyways, so for now all I have to say is tough noogies if you end up in here.
-- * On second thought, this is probably a good idea. We *really* want to give
-- * authors an incentive to automatically request this.
-+ * FIXME(eric) this has the unfortunate side effect that if a
-+ * host adapter does not automatically request sense information,
-+ * that we end up shutting it down before we request it. All
-+ * hosts should be doing this anyways, so for now all I have
-+ * to say is tough noogies if you end up in here. On second
-+ * thought, this is probably a good idea. We *really* want
-+ * to give authors an incentive to automatically request this.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we need to request sense\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt)) {
-+ if (SCpnt->state != SCSI_STATE_FAILED || scsi_sense_valid(SCpnt))
- continue;
-- }
-- SCSI_LOG_ERROR_RECOVERY(2, printk("scsi_unjam_host: Requesting sense for %d\n",
-- SCpnt->target));
-+
-+ SCSI_LOG_ERROR_RECOVERY(2,
-+ printk("scsi_unjam_host: Requesting sense for %d\n",
-+ SCpnt->target));
- rtn = scsi_request_sense(SCpnt);
-- if (rtn != SUCCESS) {
-+ if (rtn != SUCCESS)
- continue;
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("Sense requested for %p - result %x\n",
-- SCpnt, SCpnt->result));
-+
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("Sense requested for %p - result %x\n",
-+ SCpnt, SCpnt->result));
- SCSI_LOG_ERROR_RECOVERY(3, print_sense("bh", SCpnt));
-
- result = scsi_decide_disposition(SCpnt);
-
- /*
-- * If the result was normal, then just pass it along to the
-- * upper level.
-+ * If the result was normal, then just pass
-+ * it along to the upper level.
- */
- if (result == SUCCESS) {
- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCpnt);
-+ scsi_eh_finish_command(done, SCpnt);
- }
-- if (result != NEEDS_RETRY) {
-+ if (result != NEEDS_RETRY)
- continue;
-- }
-+
- /*
- * We only come in here if we want to retry a
- * command. The test to see whether the command
-@@ -1398,20 +1557,29 @@
- */
- SCpnt->state = NEEDS_RETRY;
- rtn = scsi_eh_retry_command(SCpnt);
-- if (rtn != SUCCESS) {
-+ if (rtn != SUCCESS)
- continue;
-- }
-+
- /*
- * We eventually hand this one back to the top level.
- */
- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCpnt);
-+ scsi_eh_finish_command(done, SCpnt);
- }
- }
-+}
-+
-+static void scsi_unjam_count(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int devices_failed;
-+ int numfailed;
-+ int timed_out;
-
- /*
-- * Go through the list of commands and figure out where we stand and how bad things
-- * really are.
-+ * Go through the list of commands and figure out where we
-+ * stand and how bad things really are.
- */
- numfailed = 0;
- timed_out = 0;
-@@ -1421,359 +1589,478 @@
-
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
- if (SCpnt->state == SCSI_STATE_FAILED) {
-- SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d failed\n",
-- SCpnt->target));
-+ SCSI_LOG_ERROR_RECOVERY(5,
-+ printk("Command to ID %d failed\n",
-+ SCpnt->target));
- numfailed++;
- device_error++;
- }
- if (SCpnt->state == SCSI_STATE_TIMEOUT) {
-- SCSI_LOG_ERROR_RECOVERY(5, printk("Command to ID %d timedout\n",
-- SCpnt->target));
-+ SCSI_LOG_ERROR_RECOVERY(5,
-+ printk("Command to ID %d timedout\n",
-+ SCpnt->target));
- timed_out++;
- device_error++;
- }
- }
-- if (device_error > 0) {
-+ if (device_error > 0)
- devices_failed++;
-- }
- }
-
-- SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d+%d commands on %d devices require eh work\n",
-- numfailed, timed_out, devices_failed));
-+ SCSI_LOG_ERROR_RECOVERY(2,
-+ printk("Total of %d+%d commands on %d devices require eh work\n",
-+ numfailed, timed_out, devices_failed));
-+}
-+
-+static void scsi_unjam_abort(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn;
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * Next, try and see whether or not it makes sense to try and abort
-- * the running command. This only works out to be the case if we have
-- * one command that has timed out. If the command simply failed, it
-- * makes no sense to try and abort the command, since as far as the
-- * host adapter is concerned, it isn't running.
-+ * Next, try and see whether or not it makes sense to try and
-+ * abort the running command. This only works out to be the
-+ * case if we have one command that has timed out. If the
-+ * command simply failed, it makes no sense to try and abort
-+ * the command, since as far as the host adapter is concerned,
-+ * it isn't running.
- */
-
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we want to try abort\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state != SCSI_STATE_TIMEOUT) {
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-+ if (SCpnt->state != SCSI_STATE_TIMEOUT)
- continue;
-- }
-- rtn = scsi_try_to_abort_command(SCloop, ABORT_TIMEOUT);
-- if (rtn == SUCCESS) {
-- rtn = scsi_test_unit_ready(SCloop);
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
--
-- if (rtn == SUCCESS) {
-- SCloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-+ rtn = scsi_try_to_abort_command(SCpnt, ABORT_TIMEOUT);
-+ if (rtn == SUCCESS)
-+ scsi_eh_test_and_retry(SCpnt, done);
- }
- }
-+}
-+
-+static void scsi_unjam_device_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn;
-
-- /*
-- * If we have corrected all of the problems, then we are done.
-- */
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
- * Either the abort wasn't appropriate, or it didn't succeed.
-- * Now try a bus device reset. Still, look to see whether we have
-- * multiple devices that are jammed or not - if we have multiple devices,
-- * it makes no sense to try BUS_DEVICE_RESET - we really would need
-- * to try a BUS_RESET instead.
-+ * Now try a bus device reset. Still, look to see whether we
-+ * have multiple devices that are jammed or not - if we have
-+ * multiple devices, it makes no sense to try BUS_DEVICE_RESET
-+ * - we really would need to try a BUS_RESET instead.
- *
-- * Does this make sense - should we try BDR on each device individually?
-- * Yes, definitely.
-+ * Does this make sense - should we try BDR on each device
-+ * individually? Yes, definitely.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Checking to see if we want to try BDR\n"));
-
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state == SCSI_STATE_FAILED
-- || SCloop->state == SCSI_STATE_TIMEOUT) {
-- break;
-- }
-- }
--
-- if (SCloop == NULL) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt == NULL)
- continue;
-- }
-+
- /*
-- * OK, we have a device that is having problems. Try and send
-- * a bus device reset to it.
-- *
-- * FIXME(eric) - make sure we handle the case where multiple
-- * commands to the same device have failed. They all must
-- * get properly restarted.
-+ * OK, we have a device that is having problems.
-+ * Try and send a bus device reset to it.
- */
-- rtn = scsi_try_bus_device_reset(SCloop, RESET_TIMEOUT);
-+ rtn = scsi_try_bus_device_reset(SCpnt, RESET_TIMEOUT);
-
-- if (rtn == SUCCESS) {
-- rtn = scsi_test_unit_ready(SCloop);
-+ /*
-+ * A successful bus device reset causes all commands
-+ * currently executing on the device to terminate.
-+ * We expect the HBA driver to "forget" all commands
-+ * associated with this device.
-+ *
-+ * Retry each failed or timed out command currently
-+ * outstanding for this device.
-+ *
-+ * If any command fails, bail out. We will try a
-+ * bus reset instead.
-+ */
-+ if (rtn == SUCCESS)
-+ scsi_eh_restart_device(SDpnt, done);
-+ }
-+}
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+static void scsi_unjam_bus_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ int rtn, channel, max_channel = 0;
-
-- if (rtn == SUCCESS) {
-- SCloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-- }
-+ /*
-+ * If we ended up here, we have serious problems. The only thing
-+ * left to try is a full bus reset. If someone has grabbed the
-+ * bus and isn't letting go, then perhaps this will help.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try hard bus reset\n"));
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * If we ended up here, we have serious problems. The only thing left
-- * to try is a full bus reset. If someone has grabbed the bus and isn't
-- * letting go, then perhaps this will help.
-+ * Find the maximum channel number for this host.
- */
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard bus reset\n"));
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ if (SDpnt->channel > max_channel)
-+ max_channel = SDpnt->channel;
-
-- /*
-- * We really want to loop over the various channels, and do this on
-- * a channel by channel basis. We should also check to see if any
-- * of the failed commands are on soft_reset devices, and if so, skip
-- * the reset.
-+ /*
-+ * Loop over each channel, and see if it any device on
-+ * each channel has failed.
- */
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- next_device:
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED
-- && SCpnt->state != SCSI_STATE_TIMEOUT) {
-+ for (channel = 0; channel <= max_channel; channel++) {
-+ Scsi_Cmnd *failed_command;
-+ int soft_reset;
-+
-+ try_again:
-+ failed_command = NULL;
-+ soft_reset = 0;
-+
-+ /*
-+ * Loop over each device on this channel locating any
-+ * failed command. We need a Scsi_Cmnd structure to
-+ * call the bus reset function.
-+ *
-+ * We also need to check if any of the failed commands
-+ * are on soft_reset devices, and if so, skip the reset.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ if (SDpnt->channel != channel)
- continue;
-- }
-- /*
-- * We have a failed command. Make sure there are no other failed
-- * commands on the same channel that are timed out and implement a
-- * soft reset.
-- */
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->channel != SCpnt->channel) {
-- continue;
-- }
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- if (SDloop->soft_reset && SCloop->state == SCSI_STATE_TIMEOUT) {
-- /*
-- * If this device uses the soft reset option, and this
-- * is one of the devices acting up, then our only
-- * option is to wait a bit, since the command is
-- * supposedly still running.
-- *
-- * FIXME(eric) - right now we will just end up falling
-- * through to the 'take device offline' case.
-- *
-- * FIXME(eric) - It is possible that the command completed
-- * *after* the error recovery procedure started, and if this
-- * is the case, we are worrying about nothing here.
-- */
-
-- scsi_sleep(1 * HZ);
-- goto next_device;
-- }
-- }
-- }
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt)
-+ failed_command = SCpnt;
-
- /*
-- * We now know that we are able to perform a reset for the
-- * bus that SCpnt points to. There are no soft-reset devices
-- * with outstanding timed out commands.
-+ * If this device has timed out or failed commands,
-+ * and uses the soft_reset option.
- */
-- rtn = scsi_try_bus_reset(SCpnt);
-- if (rtn == SUCCESS) {
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->channel != SCpnt->channel) {
-- continue;
-- }
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- rtn = scsi_test_unit_ready(SCloop);
-+ if (SCpnt && SDpnt->soft_reset)
-+ soft_reset = 1;
-+ }
-
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+ /*
-+ * If this channel hasn't failed, we
-+ * don't need to reset it.
-+ */
-+ if (!failed_command)
-+ continue;
-
-- if (rtn == SUCCESS) {
-- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- /*
-- * If the bus reset worked, but we are still unable to
-- * talk to the device, take it offline.
-- * FIXME(eric) - is this really the correct thing to do?
-- */
-- if (rtn != SUCCESS) {
-- printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after bus reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-+ /*
-+ * If this device uses the soft reset option, and this
-+ * is one of the devices acting up, then our only
-+ * option is to wait a bit, since the command is
-+ * supposedly still running.
-+ *
-+ * FIXME(eric) - right now we will just end up falling
-+ * through to the 'take device offline' case.
-+ *
-+ * FIXME(eric) - It is possible that the command completed
-+ * *after* the error recovery procedure started, and if
-+ * this is the case, we are worrying about nothing here.
-+ *
-+ * FIXME(rmk) - This should be bounded; we shouldn't wait
-+ * for an infinite amount of time for any device.
-+ */
-+ if (soft_reset) {
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: unable to try bus "
-+ "reset for host %d channel %d\n",
-+ host->host_no, channel));
-+ scsi_sleep(1 * HZ);
-+ goto try_again;
-+ }
-
-- SDloop->online = FALSE;
-- SDloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-+ /*
-+ * We now know that we are able to perform a reset for the
-+ * bus that SCpnt points to. There are no soft-reset devices
-+ * with outstanding timed out commands.
-+ */
-+ rtn = scsi_try_bus_reset(failed_command);
-+
-+ /*
-+ * If we failed to reset the bus, move on to the next bus.
-+ */
-+ if (rtn != SUCCESS)
-+ continue;
-+
-+ /*
-+ * We succeeded. Retry each failed command.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ if (SDpnt->channel != channel)
-+ continue;
-+
-+ rtn = scsi_eh_restart_device(SDpnt, done);
-+
-+ if (rtn != SUCCESS) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+
-+ /*
-+ * This device failed again. Since a bus
-+ * reset freed it up, chances are we've
-+ * hit the same problem, so try the same
-+ * solution. We also need to ensure that
-+ * the SCSI bus is in the BUS FREE state
-+ * so we can try to talk to other devices.
-+ */
-+ scsi_try_bus_reset(SCpnt);
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "not ready or command retry "
-+ "failed after bus reset");
- }
- }
- }
-+}
-+
-+static void scsi_unjam_host_reset(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Cmnd *failed_command = NULL;
-+ int rtn, soft_reset;
-
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
- /*
-- * If we ended up here, we have serious problems. The only thing left
-- * to try is a full host reset - perhaps the firmware on the device
-- * crashed, or something like that.
-+ * If we ended up here, we have serious problems. The only thing
-+ * left to try is a full host reset - perhaps the firmware on the
-+ * device crashed, or something like that.
- *
-- * It is assumed that a succesful host reset will cause *all* information
-- * about the command to be flushed from both the host adapter *and* the
-- * device.
-+ * It is assumed that a succesful host reset will cause *all*
-+ * information about the command to be flushed from both the host
-+ * adapter *and* the device.
- *
-- * FIXME(eric) - it isn't clear that devices that implement the soft reset
-- * option can ever be cleared except via cycling the power. The problem is
-- * that sending the host reset command will cause the host to forget
-- * about the pending command, but the device won't forget. For now, we
-- * skip the host reset option if any of the failed devices are configured
-- * to use the soft reset option.
-+ * FIXME(eric) - it isn't clear that devices that implement the
-+ * soft reset option can ever be cleared except via cycling the
-+ * power. The problem is that sending the host reset command will
-+ * cause the host to forget about the pending command, but the
-+ * device won't forget. For now, we skip the host reset option
-+ * if any of the failed devices are configured to use the soft
-+ * reset option.
- */
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try host reset\n"));
-+
-+ try_again:
-+ failed_command = NULL;
-+ soft_reset = 0;
-+
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- next_device2:
-- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-- if (SCpnt->state != SCSI_STATE_FAILED
-- && SCpnt->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- if (SDpnt->soft_reset && SCpnt->state == SCSI_STATE_TIMEOUT) {
-- /*
-- * If this device uses the soft reset option, and this
-- * is one of the devices acting up, then our only
-- * option is to wait a bit, since the command is
-- * supposedly still running.
-- *
-- * FIXME(eric) - right now we will just end up falling
-- * through to the 'take device offline' case.
-- */
-- SCSI_LOG_ERROR_RECOVERY(3,
-- printk("scsi_unjam_host: Unable to try hard host reset\n"));
-+ /*
-+ * Locate any failed commands for this device.
-+ */
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-+ if (SCpnt)
-+ failed_command = SCpnt;
-
-- /*
-- * Due to the spinlock, we will never get out of this
-- * loop without a proper wait. (DB)
-- */
-- scsi_sleep(1 * HZ);
-+ /*
-+ * If this device has timed out or failed commands,
-+ * and uses the soft_reset option.
-+ */
-+ if (SCpnt && SDpnt->soft_reset)
-+ soft_reset = 1;
-+ }
-
-- goto next_device2;
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Try hard host reset\n"));
-+ /*
-+ * If this device uses the soft reset option, and this
-+ * is one of the devices acting up, then our only
-+ * option is to wait a bit, since the command is
-+ * supposedly still running.
-+ *
-+ * FIXME(eric) - right now we will just end up falling
-+ * through to the 'take device offline' case.
-+ *
-+ * FIXME(rmk) - This should be bounded; we shouldn't wait
-+ * for an infinite amount of time for any device.
-+ */
-+ if (soft_reset) {
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: unable to try "
-+ "hard host reset\n"));
-
- /*
-- * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
-+ * Due to the spinlock, we will never get out of this
-+ * loop without a proper wait. (DB)
- */
-- rtn = scsi_try_host_reset(SCpnt);
-- if (rtn == SUCCESS) {
-- /*
-- * FIXME(eric) we assume that all commands are flushed from the
-- * controller. We should get a DID_RESET for all of the commands
-- * that were pending. We should ignore these so that we can
-- * guarantee that we are in a consistent state.
-- *
-- * I believe this to be the case right now, but this needs to be
-- * tested.
-- */
-- for (SDloop = host->host_queue; SDloop; SDloop = SDloop->next) {
-- for (SCloop = SDloop->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state != SCSI_STATE_FAILED
-- && SCloop->state != SCSI_STATE_TIMEOUT) {
-- continue;
-- }
-- rtn = scsi_test_unit_ready(SCloop);
--
-- if (rtn == SUCCESS && scsi_unit_is_ready(SCloop)) {
-- rtn = scsi_eh_retry_command(SCloop);
-+ scsi_sleep(1 * HZ);
-
-- if (rtn == SUCCESS) {
-- SCpnt->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- if (rtn != SUCCESS) {
-- printk(KERN_INFO "scsi: device set offline - not ready or command retry failed after host reset: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-- SDloop->online = FALSE;
-- SDloop->host->host_failed--;
-- scsi_eh_finish_command(&SCdone, SCloop);
-- }
-- }
-- }
-- }
-- }
-+ goto try_again;
- }
-
-+ SCSI_LOG_ERROR_RECOVERY(3,
-+ printk("scsi_unjam_host: Try hard host reset\n"));
-+
- /*
-- * If we solved all of the problems, then let's rev up the engines again.
-- */
-- if (host->host_failed == 0) {
-- ourrtn = TRUE;
-- goto leave;
-- }
-- /*
-- * If the HOST RESET failed, then for now we assume that the entire host
-- * adapter is too hosed to be of any use. For our purposes, however, it is
-- * easier to simply take the devices offline that correspond to commands
-- * that failed.
-+ * FIXME(eric) - we need to obtain a valid SCpnt to perform this call.
- */
-- SCSI_LOG_ERROR_RECOVERY(1, printk("scsi_unjam_host: Take device offline\n"));
-+ rtn = scsi_try_host_reset(failed_command);
-+ if (rtn == SUCCESS) {
-+ /*
-+ * FIXME(eric) we assume that all commands are flushed from
-+ * the controller. We should get a DID_RESET for all of the
-+ * commands that were pending. We should ignore these so
-+ * that we can guarantee that we are in a consistent state.
-+ *
-+ * I believe this to be the case right now, but this needs
-+ * to be tested.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ rtn = scsi_eh_restart_device(SDpnt, done);
-
-- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-- for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
-- if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == SCSI_STATE_TIMEOUT) {
-- SDloop = SCloop->device;
-- if (SDloop->online == TRUE) {
-- printk(KERN_INFO "scsi: device set offline - command error recover failed: host %d channel %d id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
-- SDloop->online = FALSE;
-- }
-+ if (rtn != SUCCESS) {
-+ SCpnt = scsi_eh_find_failed_command(SDpnt);
-
- /*
-- * This should pass the failure up to the top level driver, and
-- * it will have to try and do something intelligent with it.
-+ * This device failed again. Since a host
-+ * reset freed it up, chances are we've
-+ * hit the same problem, so try the same
-+ * solution. We also need to ensure that
-+ * the SCSI bus is in the BUS FREE state
-+ * so we can try to talk to other devices.
- */
-- SCloop->host->host_failed--;
--
-- if (SCloop->state == SCSI_STATE_TIMEOUT) {
-- SCloop->result |= (DRIVER_TIMEOUT << 24);
-- }
-- SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command for device %d %x\n",
-- SDloop->id, SCloop->result));
--
-- scsi_eh_finish_command(&SCdone, SCloop);
-+ scsi_try_host_reset(SCpnt);
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "not ready or command retry "
-+ "failed after host reset");
- }
- }
- }
-+}
-
-- if (host->host_failed != 0) {
-+static void scsi_unjam_failure(struct Scsi_Host *host, Scsi_Cmnd **done)
-+{
-+ Scsi_Device *SDpnt;
-+
-+ /*
-+ * If the HOST RESET failed, then for now we assume that the
-+ * entire host adapter is too hosed to be of any use. For our
-+ * purposes, however, it is easier to simply take the devices
-+ * offline that correspond to commands that failed.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(1,
-+ printk("scsi_unjam_host: Take device offline\n"));
-+
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
-+ scsi_eh_set_device_offline(SDpnt, done,
-+ "command error recover failed");
-+
-+ if (host->host_failed != 0)
- panic("scsi_unjam_host: Miscount of number of failed commands.\n");
-- }
-+
- SCSI_LOG_ERROR_RECOVERY(3, printk("scsi_unjam_host: Returning\n"));
-+}
-
-- ourrtn = FALSE;
-+static void (*unjam_method[])(struct Scsi_Host *, Scsi_Cmnd **) = {
-+ scsi_unjam_request_sense,
-+ scsi_unjam_count,
-+ scsi_unjam_abort,
-+ scsi_unjam_device_reset,
-+ scsi_unjam_bus_reset,
-+ scsi_unjam_host_reset,
-+ scsi_unjam_failure,
-+};
-
-- leave:
-+/*
-+ * Function: scsi_unjam_host
-+ *
-+ * Purpose: Attempt to fix a host which has a command that failed for
-+ * some reason.
-+ *
-+ * Arguments: host - host that needs unjamming.
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: When we come in here, we *know* that all commands on the
-+ * bus have either completed, failed or timed out. We also
-+ * know that no further commands are being sent to the host,
-+ * so things are relatively quiet and we have freedom to
-+ * fiddle with things as we wish.
-+ *
-+ * Additional note: This is only the *default* implementation. It is possible
-+ * for individual drivers to supply their own version of this
-+ * function, and if the maintainer wishes to do this, it is
-+ * strongly suggested that this function be taken as a template
-+ * and modified. This function was designed to correctly handle
-+ * problems for about 95% of the different cases out there, and
-+ * it should always provide at least a reasonable amount of error
-+ * recovery.
-+ *
-+ * Note3: Any command marked 'FAILED' or 'TIMEOUT' must eventually
-+ * have scsi_finish_command() called for it. We do all of
-+ * the retry stuff here, so when we restart the host after we
-+ * return it should have an empty queue.
-+ */
-+STATIC int scsi_unjam_host(struct Scsi_Host *host)
-+{
-+ Scsi_Cmnd *SCdone = NULL;
-+ Scsi_Cmnd *SCpnt;
-+ Scsi_Device *SDpnt;
-+ int ourrtn = FALSE;
-+ int i;
-+
-+ ASSERT_LOCK(&io_request_lock, 0);
-+
-+ /*
-+ * First, protect against any sort of race condition. If any of the outstanding
-+ * commands are in states that indicate that we are not yet blocked (i.e. we are
-+ * not in a quiet state) then we got woken up in error. If we ever end up here,
-+ * we need to re-examine some of the assumptions.
-+ */
-+ for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-+ for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
-+ if (SCpnt->state == SCSI_STATE_FAILED
-+ || SCpnt->state == SCSI_STATE_TIMEOUT
-+ || SCpnt->state == SCSI_STATE_INITIALIZING
-+ || SCpnt->state == SCSI_STATE_UNUSED) {
-+ continue;
-+ }
-+ /*
-+ * Rats. Something is still floating around out there. This could
-+ * be the result of the fact that the upper level drivers are still frobbing
-+ * commands that might have succeeded. There are two outcomes. One is that
-+ * the command block will eventually be freed, and the other one is that
-+ * the command will be queued and will be finished along the way.
-+ */
-+ SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler prematurely woken - commands still active (%p %x %d)\n", SCpnt, SCpnt->state, SCpnt->target));
-+
-+/*
-+ * panic("SCSI Error handler woken too early\n");
-+ *
-+ * This is no longer a problem, since now the code cares only about
-+ * SCSI_STATE_TIMEOUT and SCSI_STATE_FAILED.
-+ * Other states are useful only to release active commands when devices are
-+ * set offline. If (host->host_active == host->host_busy) we can safely assume
-+ * that there are no commands in state other then TIMEOUT od FAILED. (DB)
-+ *
-+ * FIXME:
-+ * It is not easy to release correctly commands according to their state when
-+ * devices are set offline, when the state is neither TIMEOUT nor FAILED.
-+ * When a device is set offline, we can have some command with
-+ * rq_status=RQ_SCSY_BUSY, owner=SCSI_STATE_HIGHLEVEL,
-+ * state=SCSI_STATE_INITIALIZING and the driver module cannot be released.
-+ * (DB, 17 May 1998)
-+ */
-+ }
-+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(unjam_method); i++) {
-+ unjam_method[i](host, &SCdone);
-+
-+ /*
-+ * If we solved all of the problems, then
-+ * let's rev up the engines again.
-+ */
-+ if (host->host_failed == 0) {
-+ ourrtn = TRUE;
-+ break;
-+ }
-+ }
-
- /*
- * We should have a list of commands that we 'finished' during the course of
-@@ -2013,3 +2300,17 @@
- * tab-width: 8
- * End:
- */
-+
-+EXPORT_SYMBOL(scsi_eh_times_out);
-+EXPORT_SYMBOL(scsi_eh_retry_command);
-+EXPORT_SYMBOL(scsi_request_sense);
-+EXPORT_SYMBOL(scsi_test_unit_ready);
-+EXPORT_SYMBOL(scsi_unit_is_ready);
-+EXPORT_SYMBOL(scsi_eh_finish_command);
-+EXPORT_SYMBOL(scsi_try_to_abort_command);
-+EXPORT_SYMBOL(scsi_try_bus_device_reset);
-+EXPORT_SYMBOL(scsi_try_bus_reset);
-+EXPORT_SYMBOL(scsi_try_host_reset);
-+EXPORT_SYMBOL(scsi_sense_valid);
-+EXPORT_SYMBOL(scsi_done);
-+EXPORT_SYMBOL(scsi_decide_disposition);
---- linux-2.4.27/drivers/scsi/scsi_ioctl.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi_ioctl.c
-@@ -153,6 +153,29 @@
- return result;
- }
-
-+int scsi_set_medium_removal(Scsi_Device *dev, char state)
-+{
-+ char scsi_cmd[MAX_COMMAND_SIZE];
-+ int ret;
-+
-+ if (!dev->removable || !dev->lockable)
-+ return 0;
-+
-+ scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-+ scsi_cmd[1] = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
-+ scsi_cmd[2] = 0;
-+ scsi_cmd[3] = 0;
-+ scsi_cmd[4] = state;
-+ scsi_cmd[5] = 0;
-+
-+ ret = ioctl_internal_command(dev, scsi_cmd, IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-+
-+ if (ret == 0)
-+ dev->locked = state == SCSI_REMOVAL_PREVENT;
-+
-+ return ret;
-+}
-+
- /*
- * This interface is depreciated - users should use the scsi generic (sg)
- * interface instead, as this is a more flexible approach to performing
-@@ -450,24 +473,9 @@
- return scsi_ioctl_send_command((Scsi_Device *) dev,
- (Scsi_Ioctl_Command *) arg);
- case SCSI_IOCTL_DOORLOCK:
-- if (!dev->removable || !dev->lockable)
-- return 0;
-- scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-- scsi_cmd[1] = cmd_byte1;
-- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-- scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
-- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-- IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-- break;
-+ return scsi_set_medium_removal(dev, SCSI_REMOVAL_PREVENT);
- case SCSI_IOCTL_DOORUNLOCK:
-- if (!dev->removable || !dev->lockable)
-- return 0;
-- scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
-- scsi_cmd[1] = cmd_byte1;
-- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-- scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
-- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
-- IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
-+ return scsi_set_medium_removal(dev, SCSI_REMOVAL_ALLOW);
- case SCSI_IOCTL_TEST_UNIT_READY:
- scsi_cmd[0] = TEST_UNIT_READY;
- scsi_cmd[1] = cmd_byte1;
---- linux-2.4.27/drivers/scsi/scsi_lib.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi_lib.c
-@@ -208,6 +208,30 @@
- }
-
- /*
-+ * Function: scsi_setup_cmd_retry()
-+ *
-+ * Purpose: Restore the command state for a retry
-+ *
-+ * Arguments: SCpnt - command to be restored
-+ *
-+ * Returns: Nothing
-+ *
-+ * Notes: Immediately prior to retrying a command, we need
-+ * to restore certain fields that we saved above.
-+ */
-+void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt)
-+{
-+ memcpy((void *) SCpnt->cmnd, (void *) SCpnt->data_cmnd,
-+ sizeof(SCpnt->data_cmnd));
-+ SCpnt->request_buffer = SCpnt->buffer;
-+ SCpnt->request_bufflen = SCpnt->bufflen;
-+ SCpnt->use_sg = SCpnt->old_use_sg;
-+ SCpnt->cmd_len = SCpnt->old_cmd_len;
-+ SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-+ SCpnt->underflow = SCpnt->old_underflow;
-+}
-+
-+/*
- * Function: scsi_queue_next_request()
- *
- * Purpose: Handle post-processing of completed commands.
-@@ -731,7 +755,7 @@
- printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",
- SCpnt->host->host_no, (int) SCpnt->channel,
- (int) SCpnt->target, (int) SCpnt->lun);
-- print_command(SCpnt->cmnd);
-+ print_command(SCpnt->data_cmnd);
- print_sense("sd", SCpnt);
- SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
- return;
-@@ -906,8 +930,17 @@
- * space. Technically the error handling thread should be
- * doing this crap, but the error handler isn't used by
- * most hosts.
-+ *
-+ * (rmk)
-+ * Trying to lock the door can cause deadlocks. We therefore
-+ * only use this for old hosts; our door locking is now done
-+ * by the error handler in scsi_restart_operations for new
-+ * eh hosts.
-+ *
-+ * Note that we don't clear was_reset here; this is used by
-+ * st.c, and either one or other has to die.
- */
-- if (SDpnt->was_reset) {
-+ if (SHpnt->hostt->use_new_eh_code == 0 && SDpnt->was_reset) {
- /*
- * We need to relock the door, but we might
- * be in an interrupt handler. Only do this
-@@ -918,7 +951,7 @@
- * this work.
- */
- SDpnt->was_reset = 0;
-- if (SDpnt->removable && !in_interrupt()) {
-+ if (SDpnt->removable && SDpnt->locked && !in_interrupt()) {
- spin_unlock_irq(&io_request_lock);
- scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
- spin_lock_irq(&io_request_lock);
---- linux-2.4.27/drivers/scsi/scsi_syms.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/scsi_syms.c
-@@ -104,3 +104,6 @@
- extern int scsi_delete_timer(Scsi_Cmnd *);
- EXPORT_SYMBOL(scsi_add_timer);
- EXPORT_SYMBOL(scsi_delete_timer);
-+
-+extern int scsi_set_medium_removal(Scsi_Device *dev, char state);
-+EXPORT_SYMBOL(scsi_set_medium_removal);
---- linux-2.4.27/drivers/scsi/sd.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/sd.c
-@@ -399,6 +399,7 @@
- this_count = 0xffff;
-
- SCpnt->cmnd[0] += READ_10 - READ_6;
-+ SCpnt->cmnd[1] |= 1 << 3; /* Set FUA --rmk */
- SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
- SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
- SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
-@@ -524,7 +525,7 @@
- if (SDev->removable)
- if (SDev->access_count==1)
- if (scsi_block_when_processing_errors(SDev))
-- scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
-+ scsi_set_medium_removal(SDev, SCSI_REMOVAL_PREVENT);
-
-
- return 0;
-@@ -553,7 +554,7 @@
- if (SDev->removable) {
- if (!SDev->access_count)
- if (scsi_block_when_processing_errors(SDev))
-- scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);
-+ scsi_set_medium_removal(SDev, SCSI_REMOVAL_ALLOW);
- }
- if (SDev->host->hostt->module)
- __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
---- linux-2.4.27/drivers/scsi/sr_ioctl.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/scsi/sr_ioctl.c
-@@ -214,9 +214,8 @@
-
- int sr_lock_door(struct cdrom_device_info *cdi, int lock)
- {
-- return scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
-- lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
-- 0);
-+ return scsi_set_medium_removal(scsi_CDs[MINOR(cdi->dev)].device,
-+ lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
- }
-
- int sr_drive_status(struct cdrom_device_info *cdi, int slot)
---- /dev/null
-+++ linux-2.4.27/drivers/serial/21285.c
-@@ -0,0 +1,599 @@
-+/*
-+ * linux/drivers/char/serial_21285.c
-+ *
-+ * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
-+ *
-+ * Based on drivers/char/serial.c
-+ *
-+ * $Id: 21285.c,v 1.4.2.1 2002/10/24 09:53:23 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/serial.h>
-+#include <linux/major.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware/dec21285.h>
-+#include <asm/hardware.h>
-+
-+#define BAUD_BASE (mem_fclk_21285/64)
-+
-+#ifdef CONFIG_DEVFS_FS
-+#define SERIAL_21285_NAME "tts/FB%d"
-+#define SERIAL_21285_AUXNAME "cua/FB%d"
-+#else
-+#define SERIAL_21285_NAME "ttyFB"
-+#define SERIAL_21285_AUXNAME "cuafb"
-+#endif
-+
-+#define SERIAL_21285_MAJOR 204
-+#define SERIAL_21285_MINOR 4
-+
-+#define SERIAL_21285_AUXMAJOR 205
-+#define SERIAL_21285_AUXMINOR 4
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+#include <asm/mach-types.h>
-+/*
-+ * Compatability with a mistake made a long time ago.
-+ * Note - the use of "ttyI", "/dev/ttyS0" and major/minor 5,64
-+ * is HIGHLY DEPRECIATED, and will be removed in the 2.5
-+ * kernel series.
-+ * -- rmk 15/04/2000
-+ */
-+#define SERIAL_21285_OLD_NAME "ttyI"
-+#define SERIAL_21285_OLD_MAJOR TTY_MAJOR
-+#define SERIAL_21285_OLD_MINOR 64
-+
-+static struct tty_driver rs285_old_driver;
-+#endif
-+
-+static struct tty_driver rs285_driver, callout_driver;
-+static int rs285_refcount;
-+static struct tty_struct *rs285_table[1];
-+
-+static struct termios *rs285_termios[1];
-+static struct termios *rs285_termios_locked[1];
-+
-+static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
-+static struct tty_struct *rs285_tty;
-+static DECLARE_MUTEX(rs285_sem);
-+static int rs285_use_count;
-+static unsigned long rs285_irq_enabled;
-+
-+#define TX_IRQ_BIT (0)
-+#define RX_IRQ_BIT (1)
-+
-+static void rs285_stop_tx(void)
-+{
-+ if (test_and_clear_bit(TX_IRQ_BIT, &rs285_irq_enabled))
-+ disable_irq(IRQ_CONTX);
-+}
-+
-+static void rs285_start_tx(void)
-+{
-+ if (!test_and_set_bit(TX_IRQ_BIT, &rs285_irq_enabled))
-+ enable_irq(IRQ_CONTX);
-+}
-+
-+static void rs285_stop_rx(void)
-+{
-+ if (test_and_clear_bit(RX_IRQ_BIT, &rs285_irq_enabled))
-+ disable_irq(IRQ_CONRX);
-+}
-+
-+static void rs285_start_rx(void)
-+{
-+ if (!test_and_set_bit(RX_IRQ_BIT, &rs285_irq_enabled))
-+ enable_irq(IRQ_CONRX);
-+}
-+
-+static int rs285_write_room(struct tty_struct *tty)
-+{
-+ return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
-+}
-+
-+static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ if (!rs285_tty) {
-+ rs285_stop_rx();
-+ return;
-+ }
-+ while (!(*CSR_UARTFLG & 0x10)) {
-+ int ch, flag;
-+ ch = *CSR_UARTDR;
-+ flag = *CSR_RXSTAT;
-+ if (flag & 4)
-+ tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
-+ if (flag & 2)
-+ flag = TTY_PARITY;
-+ else if (flag & 1)
-+ flag = TTY_FRAME;
-+ tty_insert_flip_char(rs285_tty, ch, flag);
-+ }
-+ tty_flip_buffer_push(rs285_tty);
-+}
-+
-+static void rs285_send_xchar(struct tty_struct *tty, char ch)
-+{
-+ x_char = ch;
-+ rs285_start_tx();
-+}
-+
-+static void rs285_throttle(struct tty_struct *tty)
-+{
-+ if (I_IXOFF(tty))
-+ rs285_send_xchar(tty, STOP_CHAR(tty));
-+}
-+
-+static void rs285_unthrottle(struct tty_struct *tty)
-+{
-+ if (I_IXOFF(tty)) {
-+ if (x_char)
-+ x_char = 0;
-+ else
-+ rs285_send_xchar(tty, START_CHAR(tty));
-+ }
-+}
-+
-+static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ while (!(*CSR_UARTFLG & 0x20)) {
-+ if (x_char) {
-+ *CSR_UARTDR = x_char;
-+ x_char = 0;
-+ continue;
-+ }
-+ if (putp == getp) {
-+ rs285_stop_tx();
-+ break;
-+ }
-+ *CSR_UARTDR = *getp;
-+ if (++getp >= wbuf + sizeof(wbuf))
-+ getp = wbuf;
-+ }
-+ if (rs285_tty)
-+ wake_up_interruptible(&rs285_tty->write_wait);
-+}
-+
-+static inline int rs285_xmit(int ch)
-+{
-+ if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
-+ return 0;
-+ *putp = ch;
-+ if (++putp >= wbuf + sizeof(wbuf))
-+ putp = wbuf;
-+ rs285_start_tx();
-+ return 1;
-+}
-+
-+static int rs285_write(struct tty_struct *tty, int from_user,
-+ const u_char * buf, int count)
-+{
-+ int i;
-+
-+ if (from_user && verify_area(VERIFY_READ, buf, count))
-+ return -EINVAL;
-+
-+ for (i = 0; i < count; i++) {
-+ char ch;
-+ if (from_user)
-+ __get_user(ch, buf + i);
-+ else
-+ ch = buf[i];
-+ if (!rs285_xmit(ch))
-+ break;
-+ }
-+ return i;
-+}
-+
-+static void rs285_put_char(struct tty_struct *tty, u_char ch)
-+{
-+ rs285_xmit(ch);
-+}
-+
-+static int rs285_chars_in_buffer(struct tty_struct *tty)
-+{
-+ return sizeof(wbuf) - rs285_write_room(tty);
-+}
-+
-+static void rs285_flush_buffer(struct tty_struct *tty)
-+{
-+ rs285_stop_tx();
-+ putp = getp = wbuf;
-+ if (x_char)
-+ rs285_start_tx();
-+}
-+
-+static inline void rs285_set_cflag(int cflag)
-+{
-+ int h_lcr, baud, quot;
-+
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ h_lcr = 0x10;
-+ break;
-+ case CS6:
-+ h_lcr = 0x30;
-+ break;
-+ case CS7:
-+ h_lcr = 0x50;
-+ break;
-+ default: /* CS8 */
-+ h_lcr = 0x70;
-+ break;
-+
-+ }
-+ if (cflag & CSTOPB)
-+ h_lcr |= 0x08;
-+ if (cflag & PARENB)
-+ h_lcr |= 0x02;
-+ if (!(cflag & PARODD))
-+ h_lcr |= 0x04;
-+
-+ switch (cflag & CBAUD) {
-+ case B200: baud = 200; break;
-+ case B300: baud = 300; break;
-+ case B1200: baud = 1200; break;
-+ case B1800: baud = 1800; break;
-+ case B2400: baud = 2400; break;
-+ case B4800: baud = 4800; break;
-+ default:
-+ case B9600: baud = 9600; break;
-+ case B19200: baud = 19200; break;
-+ case B38400: baud = 38400; break;
-+ case B57600: baud = 57600; break;
-+ case B115200: baud = 115200; break;
-+ }
-+
-+ /*
-+ * The documented expression for selecting the divisor is:
-+ * BAUD_BASE / baud - 1
-+ * However, typically BAUD_BASE is not divisible by baud, so
-+ * we want to select the divisor that gives us the minimum
-+ * error. Therefore, we want:
-+ * int(BAUD_BASE / baud - 0.5) ->
-+ * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
-+ * int((BAUD_BASE - (baud >> 1)) / baud)
-+ */
-+ quot = (BAUD_BASE - (baud >> 1)) / baud;
-+
-+ *CSR_UARTCON = 0;
-+ *CSR_L_UBRLCR = quot & 0xff;
-+ *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
-+ *CSR_H_UBRLCR = h_lcr;
-+ *CSR_UARTCON = 1;
-+}
-+
-+static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
-+{
-+ if (old && tty->termios->c_cflag == old->c_cflag)
-+ return;
-+ rs285_set_cflag(tty->termios->c_cflag);
-+}
-+
-+
-+static void rs285_stop(struct tty_struct *tty)
-+{
-+ rs285_stop_tx();
-+}
-+
-+static void rs285_start(struct tty_struct *tty)
-+{
-+ rs285_start_tx();
-+}
-+
-+static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
-+{
-+ int orig_jiffies = jiffies;
-+ while (*CSR_UARTFLG & 8) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(1);
-+ if (signal_pending(current))
-+ break;
-+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING);
-+}
-+
-+static int rs285_open(struct tty_struct *tty, struct file *filp)
-+{
-+ int line, ret;
-+
-+ MOD_INC_USE_COUNT;
-+
-+ line = MINOR(tty->device) - tty->driver.minor_start;
-+ if (line)
-+ return -ENODEV;
-+
-+ ret = down_interruptible(&rs285_sem);
-+ if (ret)
-+ return ret;
-+
-+ tty->driver_data = NULL;
-+ rs285_tty = tty;
-+
-+ if (rs285_use_count == 0) {
-+ rs285_irq_enabled = 3;
-+ ret = request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL);
-+ if (ret == 0) {
-+ ret = request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285",
-+ NULL);
-+ if (ret)
-+ free_irq(IRQ_CONRX, NULL);
-+ }
-+ }
-+
-+ if (ret == 0)
-+ rs285_use_count++;
-+
-+ up(&rs285_sem);
-+
-+ return ret;
-+}
-+
-+static void rs285_close(struct tty_struct *tty, struct file *filp)
-+{
-+ down(&rs285_sem);
-+ if (!--rs285_use_count) {
-+ rs285_wait_until_sent(tty, 0);
-+ rs285_stop_rx();
-+ rs285_stop_tx();
-+ rs285_tty = NULL;
-+ free_irq(IRQ_CONTX, NULL);
-+ free_irq(IRQ_CONRX, NULL);
-+ }
-+ up(&rs285_sem);
-+ MOD_DEC_USE_COUNT;
-+}
-+
-+static int __init rs285_init(void)
-+{
-+ int baud = B9600;
-+
-+ if (machine_is_personal_server())
-+ baud = B57600;
-+
-+ rs285_driver.magic = TTY_DRIVER_MAGIC;
-+ rs285_driver.driver_name = "serial_21285";
-+ rs285_driver.name = SERIAL_21285_NAME;
-+ rs285_driver.major = SERIAL_21285_MAJOR;
-+ rs285_driver.minor_start = SERIAL_21285_MINOR;
-+ rs285_driver.num = 1;
-+ rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
-+ rs285_driver.subtype = SERIAL_TYPE_NORMAL;
-+ rs285_driver.init_termios = tty_std_termios;
-+ rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
-+ rs285_driver.flags = TTY_DRIVER_REAL_RAW;
-+ rs285_driver.refcount = &rs285_refcount;
-+ rs285_driver.table = rs285_table;
-+ rs285_driver.termios = rs285_termios;
-+ rs285_driver.termios_locked = rs285_termios_locked;
-+
-+ rs285_driver.open = rs285_open;
-+ rs285_driver.close = rs285_close;
-+ rs285_driver.write = rs285_write;
-+ rs285_driver.put_char = rs285_put_char;
-+ rs285_driver.write_room = rs285_write_room;
-+ rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
-+ rs285_driver.flush_buffer = rs285_flush_buffer;
-+ rs285_driver.throttle = rs285_throttle;
-+ rs285_driver.unthrottle = rs285_unthrottle;
-+ rs285_driver.send_xchar = rs285_send_xchar;
-+ rs285_driver.set_termios = rs285_set_termios;
-+ rs285_driver.stop = rs285_stop;
-+ rs285_driver.start = rs285_start;
-+ rs285_driver.wait_until_sent = rs285_wait_until_sent;
-+
-+ callout_driver = rs285_driver;
-+ callout_driver.name = SERIAL_21285_AUXNAME;
-+ callout_driver.major = SERIAL_21285_AUXMAJOR;
-+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder()) {
-+ rs285_old_driver = rs285_driver;
-+ rs285_old_driver.name = SERIAL_21285_OLD_NAME;
-+ rs285_old_driver.major = SERIAL_21285_OLD_MAJOR;
-+ rs285_old_driver.minor_start = SERIAL_21285_OLD_MINOR;
-+
-+ if (tty_register_driver(&rs285_old_driver))
-+ printk(KERN_ERR "Couldn't register old 21285 serial driver\n");
-+ }
-+#endif
-+
-+ if (tty_register_driver(&rs285_driver))
-+ printk(KERN_ERR "Couldn't register 21285 serial driver\n");
-+ if (tty_register_driver(&callout_driver))
-+ printk(KERN_ERR "Couldn't register 21285 callout driver\n");
-+
-+ return 0;
-+}
-+
-+static void __exit rs285_fini(void)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ save_flags(flags);
-+ cli();
-+ ret = tty_unregister_driver(&callout_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister 21285 callout driver "
-+ "(%d)\n", ret);
-+ ret = tty_unregister_driver(&rs285_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
-+ ret);
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder()) {
-+ ret = tty_unregister_driver(&rs285_old_driver);
-+ if (ret)
-+ printk(KERN_ERR "Unable to unregister old 21285 "
-+ "driver (%d)\n", ret);
-+ }
-+#endif
-+ free_irq(IRQ_CONTX, NULL);
-+ free_irq(IRQ_CONRX, NULL);
-+ restore_flags(flags);
-+}
-+
-+module_init(rs285_init);
-+module_exit(rs285_fini);
-+
-+#ifdef CONFIG_SERIAL_21285_CONSOLE
-+/************** console driver *****************/
-+
-+static void rs285_console_write(struct console *co, const char *s, u_int count)
-+{
-+ int i;
-+
-+ rs285_stop_tx();
-+ for (i = 0; i < count; i++) {
-+ while (*CSR_UARTFLG & 0x20);
-+ *CSR_UARTDR = s[i];
-+ if (s[i] == '\n') {
-+ while (*CSR_UARTFLG & 0x20);
-+ *CSR_UARTDR = '\r';
-+ }
-+ }
-+ rs285_start_tx();
-+}
-+
-+static kdev_t rs285_console_device(struct console *c)
-+{
-+ return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
-+}
-+
-+static int __init rs285_console_setup(struct console *co, char *options)
-+{
-+ int baud = 9600;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow;
-+ int cflag = CREAD | HUPCL | CLOCAL;
-+
-+ if (machine_is_personal_server())
-+ baud = 57600;
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+
-+ /*
-+ * Now construct a cflag setting.
-+ */
-+ switch (baud) {
-+ case 1200:
-+ cflag |= B1200;
-+ break;
-+ case 2400:
-+ cflag |= B2400;
-+ break;
-+ case 4800:
-+ cflag |= B4800;
-+ break;
-+ case 9600:
-+ cflag |= B9600;
-+ break;
-+ case 19200:
-+ cflag |= B19200;
-+ break;
-+ case 38400:
-+ cflag |= B38400;
-+ break;
-+ case 57600:
-+ cflag |= B57600;
-+ break;
-+ case 115200:
-+ cflag |= B115200;
-+ break;
-+ default:
-+ cflag |= B9600;
-+ break;
-+ }
-+ switch (bits) {
-+ case 7:
-+ cflag |= CS7;
-+ break;
-+ default:
-+ cflag |= CS8;
-+ break;
-+ }
-+ switch (parity) {
-+ case 'o':
-+ case 'O':
-+ cflag |= PARODD;
-+ break;
-+ case 'e':
-+ case 'E':
-+ cflag |= PARENB;
-+ break;
-+ }
-+ co->cflag = cflag;
-+ rs285_set_cflag(cflag);
-+ rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
-+ if (options)
-+ rs285_console_write(NULL, options, strlen(options));
-+ else
-+ rs285_console_write(NULL, "no options", 10);
-+ rs285_console_write(NULL, "\n", 1);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SERIAL_21285_OLD
-+static struct console rs285_old_cons =
-+{
-+ SERIAL_21285_OLD_NAME,
-+ rs285_console_write,
-+ NULL,
-+ rs285_console_device,
-+ NULL,
-+ rs285_console_setup,
-+ CON_PRINTBUFFER,
-+ -1,
-+ 0,
-+ NULL
-+};
-+#endif
-+
-+static struct console rs285_cons =
-+{
-+ name: SERIAL_21285_NAME,
-+ write: rs285_console_write,
-+ device: rs285_console_device,
-+ setup: rs285_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+void __init rs285_console_init(void)
-+{
-+#ifdef CONFIG_SERIAL_21285_OLD
-+ if (!machine_is_ebsa285() && !machine_is_netwinder())
-+ register_console(&rs285_old_cons);
-+#endif
-+ register_console(&rs285_cons);
-+}
-+
-+#endif /* CONFIG_SERIAL_21285_CONSOLE */
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
---- /dev/null
-+++ linux-2.4.27/drivers/serial/8250.c
-@@ -0,0 +1,2170 @@
-+/*
-+ * linux/drivers/serial/8250.c
-+ *
-+ * Driver for 8250/16550-type serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * $Id: 8250.c,v 1.14.2.8 2002/10/24 14:31:31 rmk Exp $
-+ *
-+ * A note about mapbase / membase
-+ *
-+ * mapbase is the physical address of the IO port. Currently, we don't
-+ * support this very well, and it may well be dropped from this driver
-+ * in future. As such, mapbase should be NULL.
-+ *
-+ * membase is an 'ioremapped' cookie. This is compatible with the old
-+ * serial.c driver, and is currently the preferred form.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/serial_reg.h>
-+#include <linux/serialP.h>
-+#include <linux/delay.h>
-+#include <linux/serial_core.h>
-+#include <linux/kmod.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#include "8250.h"
-+
-+/*
-+ * Configuration:
-+ * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option
-+ * is unsafe when used on edge-triggered interrupts.
-+ */
-+unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
-+
-+/*
-+ * Debugging.
-+ */
-+#if 0
-+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-+#else
-+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-+#endif
-+
-+#if 0
-+#define DEBUG_INTR(fmt...) printk(fmt)
-+#else
-+#define DEBUG_INTR(fmt...) do { } while (0)
-+#endif
-+
-+#define PASS_LIMIT 256
-+
-+/*
-+ * We default to IRQ0 for the "no irq" hack. Some
-+ * machine types want others as well - they're free
-+ * to redefine this in their header file.
-+ */
-+#define is_real_interrupt(irq) ((irq) != 0)
-+
-+/*
-+ * This converts from our new CONFIG_ symbols to the symbols
-+ * that asm/serial.h expects. You _NEED_ to comment out the
-+ * linux/config.h include contained inside asm/serial.h for
-+ * this to work.
-+ */
-+#undef CONFIG_SERIAL_MANY_PORTS
-+#undef CONFIG_SERIAL_DETECT_IRQ
-+#undef CONFIG_SERIAL_MULTIPORT
-+#undef CONFIG_HUB6
-+
-+#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
-+#define CONFIG_SERIAL_DETECT_IRQ 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_MULTIPORT
-+#define CONFIG_SERIAL_MULTIPORT 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+#define CONFIG_HUB6 1
-+#endif
-+#ifdef CONFIG_SERIAL_8250_MANY_PORTS
-+#define CONFIG_SERIAL_MANY_PORTS 1
-+#endif
-+
-+#include <asm/serial.h>
-+
-+static struct old_serial_port old_serial_port[] = {
-+ SERIAL_PORT_DFNS /* defined in asm/serial.h */
-+};
-+
-+#define UART_NR ARRAY_SIZE(old_serial_port)
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *serial8250_table[UART_NR];
-+static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+
-+#define PORT_RSA_MAX 4
-+static int probe_rsa[PORT_RSA_MAX];
-+static int force_rsa[PORT_RSA_MAX];
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
-+struct uart_8250_port {
-+ struct uart_port port;
-+ struct timer_list timer; /* "no irq" timer */
-+ struct list_head list; /* ports on this IRQ */
-+ unsigned int capabilities; /* port capabilities */
-+ unsigned char acr;
-+ unsigned char ier;
-+ unsigned short rev;
-+ unsigned char lcr;
-+ unsigned char mcr;
-+ unsigned char mcr_mask; /* mask of user bits */
-+ unsigned char mcr_force; /* mask of forced bits */
-+ unsigned char efr;
-+ unsigned int lsr_break_flag;
-+
-+ /*
-+ * We provide a per-port pm hook.
-+ */
-+ void (*pm)(struct uart_port *port,
-+ unsigned int state, unsigned int old);
-+};
-+
-+struct irq_info {
-+ spinlock_t lock;
-+ struct list_head *head;
-+};
-+
-+static struct irq_info irq_lists[NR_IRQS];
-+
-+/*
-+ * Here we define the default xmit fifo size used for each type of UART.
-+ */
-+static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
-+ { "unknown", 1, 0 },
-+ { "8250", 1, 0 },
-+ { "16450", 1, 0 },
-+ { "16550", 1, 0 },
-+ { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "Cirrus", 1, 0 },
-+ { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
-+ { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "Startech", 1, 0 },
-+ { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO },
-+ { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-+ { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }
-+};
-+
-+static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
-+{
-+ offset <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+ case SERIAL_IO_HUB6:
-+ outb(up->port.hub6 - 1 + offset, up->port.iobase);
-+ return inb(up->port.iobase + 1);
-+#endif
-+
-+ case SERIAL_IO_MEM:
-+ return readb(up->port.membase + offset);
-+
-+ default:
-+ return inb(up->port.iobase + offset);
-+ }
-+}
-+
-+static _INLINE_ void
-+serial_out(struct uart_8250_port *up, int offset, int value)
-+{
-+ offset <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+#ifdef CONFIG_SERIAL_8250_HUB6
-+ case SERIAL_IO_HUB6:
-+ outb(up->port.hub6 - 1 + offset, up->port.iobase);
-+ outb(value, up->port.iobase + 1);
-+ break;
-+#endif
-+
-+ case SERIAL_IO_MEM:
-+ writeb(value, up->port.membase + offset);
-+ break;
-+
-+ default:
-+ outb(value, up->port.iobase + offset);
-+ }
-+}
-+
-+/*
-+ * We used to support using pause I/O for certain machines. We
-+ * haven't supported this for a while, but just in case it's badly
-+ * needed for certain old 386 machines, I've left these #define's
-+ * in....
-+ */
-+#define serial_inp(up, offset) serial_in(up, offset)
-+#define serial_outp(up, offset, value) serial_out(up, offset, value)
-+
-+
-+/*
-+ * For the 16C950
-+ */
-+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-+{
-+ serial_out(up, UART_SCR, offset);
-+ serial_out(up, UART_ICR, value);
-+}
-+
-+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-+{
-+ unsigned int value;
-+
-+ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
-+ serial_out(up, UART_SCR, offset);
-+ value = serial_in(up, UART_ICR);
-+ serial_icr_write(up, UART_ACR, up->acr);
-+
-+ return value;
-+}
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+/*
-+ * Attempts to turn on the RSA FIFO. Returns zero on failure.
-+ * We set the port uart clock rate if we succeed.
-+ */
-+static int __enable_rsa(struct uart_8250_port *up)
-+{
-+ unsigned char mode;
-+ int result;
-+
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = mode & UART_RSA_MSR_FIFO;
-+
-+ if (!result) {
-+ serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = mode & UART_RSA_MSR_FIFO;
-+ }
-+
-+ if (result)
-+ up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-+
-+ return result;
-+}
-+
-+static void enable_rsa(struct uart_8250_port *up)
-+{
-+ if (up->port.type == PORT_RSA) {
-+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
-+ spin_lock_irq(&up->port.lock);
-+ __enable_rsa(up);
-+ spin_unlock_irq(&up->port.lock);
-+ }
-+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
-+ serial_outp(up, UART_RSA_FRR, 0);
-+ }
-+}
-+
-+/*
-+ * Attempts to turn off the RSA FIFO. Returns zero on failure.
-+ * It is unknown why interrupts were disabled in here. However,
-+ * the caller is expected to preserve this behaviour by grabbing
-+ * the spinlock before calling this function.
-+ */
-+static void disable_rsa(struct uart_8250_port *up)
-+{
-+ unsigned char mode;
-+ int result;
-+
-+ if (up->port.type == PORT_RSA &&
-+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
-+ spin_lock_irq(&up->port.lock);
-+
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = !(mode & UART_RSA_MSR_FIFO);
-+
-+ if (!result) {
-+ serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
-+ mode = serial_inp(up, UART_RSA_MSR);
-+ result = !(mode & UART_RSA_MSR_FIFO);
-+ }
-+
-+ if (result)
-+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
-+ spin_unlock_irq(&up->port.lock);
-+ }
-+}
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
-+/*
-+ * This is a quickie test to see how big the FIFO is.
-+ * It doesn't work at all the time, more's the pity.
-+ */
-+static int size_fifo(struct uart_8250_port *up)
-+{
-+ unsigned char old_fcr, old_mcr, old_dll, old_dlm;
-+ int count;
-+
-+ old_fcr = serial_inp(up, UART_FCR);
-+ old_mcr = serial_inp(up, UART_MCR);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_MCR, UART_MCR_LOOP);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ old_dll = serial_inp(up, UART_DLL);
-+ old_dlm = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, 0x01);
-+ serial_outp(up, UART_DLM, 0x00);
-+ serial_outp(up, UART_LCR, 0x03);
-+ for (count = 0; count < 256; count++)
-+ serial_outp(up, UART_TX, count);
-+ mdelay(20);/* FIXME - schedule_timeout */
-+ for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
-+ (count < 256); count++)
-+ serial_inp(up, UART_RX);
-+ serial_outp(up, UART_FCR, old_fcr);
-+ serial_outp(up, UART_MCR, old_mcr);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ serial_outp(up, UART_DLL, old_dll);
-+ serial_outp(up, UART_DLM, old_dlm);
-+
-+ return count;
-+}
-+
-+/*
-+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
-+ * When this function is called we know it is at least a StarTech
-+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
-+ * its clones. (We treat the broken original StarTech 16650 V1 as a
-+ * 16550, and why not? Startech doesn't seem to even acknowledge its
-+ * existence.)
-+ *
-+ * What evil have men's minds wrought...
-+ */
-+static void autoconfig_has_efr(struct uart_8250_port *up)
-+{
-+ unsigned char id1, id2, id3, rev, saved_dll, saved_dlm;
-+
-+ /*
-+ * First we check to see if it's an Oxford Semiconductor UART.
-+ *
-+ * If we have to do this here because some non-National
-+ * Semiconductor clone chips lock up if you try writing to the
-+ * LSR register (which serial_icr_read does)
-+ */
-+
-+ /*
-+ * Check for Oxford Semiconductor 16C950.
-+ *
-+ * EFR [4] must be set else this test fails.
-+ *
-+ * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
-+ * claims that it's needed for 952 dual UART's (which are not
-+ * recommended for new designs).
-+ */
-+ up->acr = 0;
-+ serial_out(up, UART_LCR, 0xBF);
-+ serial_out(up, UART_EFR, 0x10);
-+ serial_out(up, UART_LCR, 0x00);
-+ id1 = serial_icr_read(up, UART_ID1);
-+ id2 = serial_icr_read(up, UART_ID2);
-+ id3 = serial_icr_read(up, UART_ID3);
-+ rev = serial_icr_read(up, UART_REV);
-+
-+ DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-+
-+ if (id1 == 0x16 && id2 == 0xC9 &&
-+ (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
-+ up->port.type = PORT_16C950;
-+ up->rev = rev | (id3 << 8);
-+ return;
-+ }
-+
-+ /*
-+ * We check for a XR16C850 by setting DLL and DLM to 0, and then
-+ * reading back DLL and DLM. The chip type depends on the DLM
-+ * value read back:
-+ * 0x10 - XR16C850 and the DLL contains the chip revision.
-+ * 0x12 - XR16C2850.
-+ * 0x14 - XR16C854.
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ saved_dll = serial_inp(up, UART_DLL);
-+ saved_dlm = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, 0);
-+ serial_outp(up, UART_DLM, 0);
-+ id2 = serial_inp(up, UART_DLL);
-+ id1 = serial_inp(up, UART_DLM);
-+ serial_outp(up, UART_DLL, saved_dll);
-+ serial_outp(up, UART_DLM, saved_dlm);
-+
-+ DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
-+
-+ if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
-+ if (id1 == 0x10)
-+ up->rev = id2;
-+ up->port.type = PORT_16850;
-+ return;
-+ }
-+
-+ /*
-+ * It wasn't an XR16C850.
-+ *
-+ * We distinguish between the '654 and the '650 by counting
-+ * how many bytes are in the FIFO. I'm using this for now,
-+ * since that's the technique that was sent to me in the
-+ * serial driver update, but I'm not convinced this works.
-+ * I've had problems doing this in the past. -TYT
-+ */
-+ if (size_fifo(up) == 64)
-+ up->port.type = PORT_16654;
-+ else
-+ up->port.type = PORT_16650V2;
-+}
-+
-+/*
-+ * We detected a chip without a FIFO. Only two fall into
-+ * this category - the original 8250 and the 16450. The
-+ * 16450 has a scratch register (accessible with LCR=0)
-+ */
-+static void autoconfig_8250(struct uart_8250_port *up)
-+{
-+ unsigned char scratch, status1, status2;
-+
-+ up->port.type = PORT_8250;
-+
-+ scratch = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, 0xa5);
-+ status1 = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, 0x5a);
-+ status2 = serial_in(up, UART_SCR);
-+ serial_outp(up, UART_SCR, scratch);
-+
-+ if (status1 == 0xa5 && status2 == 0x5a)
-+ up->port.type = PORT_16450;
-+}
-+
-+/*
-+ * We know that the chip has FIFOs. Does it have an EFR? The
-+ * EFR is located in the same register position as the IIR and
-+ * we know the top two bits of the IIR are currently set. The
-+ * EFR should contain zero. Try to read the EFR.
-+ */
-+static void autoconfig_16550a(struct uart_8250_port *up)
-+{
-+ unsigned char status1, status2;
-+
-+ up->port.type = PORT_16550A;
-+
-+ /*
-+ * Check for presence of the EFR when DLAB is set.
-+ * Only ST16C650V1 UARTs pass this test.
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ if (serial_in(up, UART_EFR) == 0) {
-+ DEBUG_AUTOCONF("EFRv1 ");
-+ up->port.type = PORT_16650;
-+ return;
-+ }
-+
-+ /*
-+ * Maybe it requires 0xbf to be written to the LCR.
-+ * (other ST16C650V2 UARTs, TI16C752A, etc)
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ if (serial_in(up, UART_EFR) == 0) {
-+ DEBUG_AUTOCONF("EFRv2 ");
-+ autoconfig_has_efr(up);
-+ return;
-+ }
-+
-+ /*
-+ * Check for a National Semiconductor SuperIO chip.
-+ * Attempt to switch to bank 2, read the value of the LOOP bit
-+ * from EXCR1. Switch back to bank 0, change it in MCR. Then
-+ * switch back to bank 2, read it from EXCR1 again and check
-+ * it's changed. If so, set baud_base in EXCR2 to 921600.
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ status1 = serial_in(up, UART_MCR);
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status2 = serial_in(up, 0x02); /* EXCR1 */
-+
-+ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status2 = serial_in(up, 0x02); /* EXCR1 */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_MCR, status1);
-+
-+ if ((status2 ^ status1) & UART_MCR_LOOP) {
-+ serial_outp(up, UART_LCR, 0xE0);
-+ status1 = serial_in(up, 0x04); /* EXCR1 */
-+ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-+ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
-+ serial_outp(up, 0x04, status1);
-+ serial_outp(up, UART_LCR, 0);
-+
-+ up->port.type = PORT_NS16550A;
-+ up->port.uartclk = 921600*16;
-+ return;
-+ }
-+ }
-+
-+ /*
-+ * No EFR. Try to detect a TI16750, which only sets bit 5 of
-+ * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
-+ * Try setting it with and without DLAB set. Cheap clones
-+ * set bit 5 without DLAB set.
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-+ status1 = serial_in(up, UART_IIR) >> 5;
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
-+ status2 = serial_in(up, UART_IIR) >> 5;
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+
-+ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-+
-+ if (status1 == 6 && status2 == 7) {
-+ up->port.type = PORT_16750;
-+ return;
-+ }
-+}
-+
-+/*
-+ * This routine is called by rs_init() to initialize a specific serial
-+ * port. It determines what type of UART chip this serial port is
-+ * using: 8250, 16450, 16550, 16550A. The important question is
-+ * whether or not this UART is a 16550A or not, since this will
-+ * determine whether or not we can use its FIFO features or not.
-+ */
-+static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
-+{
-+ unsigned char status1, scratch, scratch2, scratch3;
-+ unsigned char save_lcr, save_mcr;
-+ unsigned long flags;
-+
-+ if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
-+ return;
-+
-+ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
-+ up->port.line, up->port.iobase, up->port.membase);
-+
-+ /*
-+ * We really do need global IRQs disabled here - we're going to
-+ * be frobbing the chips IRQ enable register to see if it exists.
-+ */
-+ spin_lock_irqsave(&up->port.lock, flags);
-+
-+ if (!(up->port.flags & UPF_BUGGY_UART)) {
-+ /*
-+ * Do a simple existence test first; if we fail this,
-+ * there's no point trying anything else.
-+ *
-+ * 0x80 is used as a nonsense port to prevent against
-+ * false positives due to ISA bus float. The
-+ * assumption is that 0x80 is a non-existent port;
-+ * which should be safe since include/asm/io.h also
-+ * makes this assumption.
-+ *
-+ * Note: this is safe as long as MCR bit 4 is clear
-+ * and the device is in "PC" mode.
-+ */
-+ scratch = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, 0);
-+#ifdef __i386__
-+ outb(0xff, 0x080);
-+#endif
-+ scratch2 = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, 0x0F);
-+#ifdef __i386__
-+ outb(0, 0x080);
-+#endif
-+ scratch3 = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_IER, scratch);
-+ if (scratch2 != 0 || scratch3 != 0x0F) {
-+ /*
-+ * We failed; there's nothing here
-+ */
-+ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
-+ scratch2, scratch3);
-+ goto out;
-+ }
-+ }
-+
-+ save_mcr = serial_in(up, UART_MCR);
-+ save_lcr = serial_in(up, UART_LCR);
-+
-+ /*
-+ * Check to see if a UART is really there. Certain broken
-+ * internal modems based on the Rockwell chipset fail this
-+ * test, because they apparently don't implement the loopback
-+ * test mode. So this test is skipped on the COM 1 through
-+ * COM 4 ports. This *should* be safe, since no board
-+ * manufacturer would be stupid enough to design a board
-+ * that conflicts with COM 1-4 --- we hope!
-+ */
-+ if (!(up->port.flags & UPF_SKIP_TEST)) {
-+ serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
-+ status1 = serial_inp(up, UART_MSR) & 0xF0;
-+ serial_outp(up, UART_MCR, save_mcr);
-+ if (status1 != 0x90) {
-+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
-+ status1);
-+ goto out;
-+ }
-+ }
-+
-+ /*
-+ * We're pretty sure there's a port here. Lets find out what
-+ * type of port it is. The IIR top two bits allows us to find
-+ * out if its 8250 or 16450, 16550, 16550A or later. This
-+ * determines what we test for next.
-+ *
-+ * We also initialise the EFR (if any) to zero for later. The
-+ * EFR occupies the same register location as the FCR and IIR.
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ serial_outp(up, UART_LCR, 0);
-+
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ scratch = serial_in(up, UART_IIR) >> 6;
-+
-+ DEBUG_AUTOCONF("iir=%d ", scratch);
-+
-+ switch (scratch) {
-+ case 0:
-+ autoconfig_8250(up);
-+ break;
-+ case 1:
-+ up->port.type = PORT_UNKNOWN;
-+ break;
-+ case 2:
-+ up->port.type = PORT_16550;
-+ break;
-+ case 3:
-+ autoconfig_16550a(up);
-+ break;
-+ }
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+ /*
-+ * Only probe for RSA ports if we got the region.
-+ */
-+ if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
-+ int i;
-+
-+ for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
-+ if (!probe_rsa[i] && !force_rsa[i])
-+ break;
-+ if (((probe_rsa[i] != up->port.iobase) ||
-+ check_region(up->port.iobase + UART_RSA_BASE, 16)) &&
-+ (force_rsa[i] != up->port.iobase))
-+ continue;
-+ if (__enable_rsa(up)) {
-+ up->port.type = PORT_RSA;
-+ break;
-+ }
-+ }
-+ }
-+#endif
-+ serial_outp(up, UART_LCR, save_lcr);
-+
-+ up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
-+ up->capabilities = uart_config[up->port.type].flags;
-+
-+ if (up->port.type == PORT_UNKNOWN)
-+ goto out;
-+
-+ /*
-+ * Reset the UART.
-+ */
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ if (up->port.type == PORT_RSA)
-+ serial_outp(up, UART_RSA_FRR, 0);
-+#endif
-+ serial_outp(up, UART_MCR, save_mcr);
-+ serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR |
-+ UART_FCR_CLEAR_XMIT));
-+ serial_outp(up, UART_FCR, 0);
-+ (void)serial_in(up, UART_RX);
-+ serial_outp(up, UART_IER, 0);
-+
-+ out:
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ if (up->port.iobase && up->port.type == PORT_RSA) {
-+ release_region(up->port.iobase, 8);
-+ request_region(up->port.iobase + UART_RSA_BASE, 16,
-+ "serial_rsa");
-+ }
-+#endif
-+ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
-+}
-+
-+static void autoconfig_irq(struct uart_8250_port *up)
-+{
-+ unsigned char save_mcr, save_ier;
-+ unsigned char save_ICP = 0;
-+ unsigned int ICP = 0;
-+ unsigned long irqs;
-+ int irq;
-+
-+ if (up->port.flags & UPF_FOURPORT) {
-+ ICP = (up->port.iobase & 0xfe0) | 0x1f;
-+ save_ICP = inb_p(ICP);
-+ outb_p(0x80, ICP);
-+ (void) inb_p(ICP);
-+ }
-+
-+ /* forget possible initially masked and pending IRQ */
-+ probe_irq_off(probe_irq_on());
-+ save_mcr = serial_inp(up, UART_MCR);
-+ save_ier = serial_inp(up, UART_IER);
-+ serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-+
-+ irqs = probe_irq_on();
-+ serial_outp(up, UART_MCR, 0);
-+ udelay (10);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ serial_outp(up, UART_MCR,
-+ UART_MCR_DTR | UART_MCR_RTS);
-+ } else {
-+ serial_outp(up, UART_MCR,
-+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
-+ }
-+ serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
-+ (void)serial_inp(up, UART_LSR);
-+ (void)serial_inp(up, UART_RX);
-+ (void)serial_inp(up, UART_IIR);
-+ (void)serial_inp(up, UART_MSR);
-+ serial_outp(up, UART_TX, 0xFF);
-+ udelay (20);
-+ irq = probe_irq_off(irqs);
-+
-+ serial_outp(up, UART_MCR, save_mcr);
-+ serial_outp(up, UART_IER, save_ier);
-+
-+ if (up->port.flags & UPF_FOURPORT)
-+ outb_p(save_ICP, ICP);
-+
-+ up->port.irq = (irq > 0) ? irq : 0;
-+}
-+
-+static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ if (up->ier & UART_IER_THRI) {
-+ up->ier &= ~UART_IER_THRI;
-+ serial_out(up, UART_IER, up->ier);
-+ }
-+ if (up->port.type == PORT_16C950 && tty_stop) {
-+ up->acr |= UART_ACR_TXDIS;
-+ serial_icr_write(up, UART_ACR, up->acr);
-+ }
-+}
-+
-+static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ if (!(up->ier & UART_IER_THRI)) {
-+ up->ier |= UART_IER_THRI;
-+ serial_out(up, UART_IER, up->ier);
-+ }
-+ /*
-+ * We only do this from uart_start
-+ */
-+ if (tty_start && up->port.type == PORT_16C950) {
-+ up->acr &= ~UART_ACR_TXDIS;
-+ serial_icr_write(up, UART_ACR, up->acr);
-+ }
-+}
-+
-+static void serial8250_stop_rx(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ up->ier &= ~UART_IER_RLSI;
-+ up->port.read_status_mask &= ~UART_LSR_DR;
-+ serial_out(up, UART_IER, up->ier);
-+}
-+
-+static void serial8250_enable_ms(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+
-+ up->ier |= UART_IER_MSI;
-+ serial_out(up, UART_IER, up->ier);
-+}
-+
-+static _INLINE_ void
-+receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
-+{
-+ struct tty_struct *tty = up->port.info->tty;
-+ unsigned char ch;
-+ int max_count = 256;
-+
-+ do {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ /*
-+ * FIXME: Deadlock can happen here if we're a
-+ * low-latency port. We're holding the per-port
-+ * spinlock, and we call flush_to_ldisc->
-+ * n_tty_receive_buf->n_tty_receive_char->
-+ * opost->uart_put_char.
-+ */
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ return; // if TTY_DONT_FLIP is set
-+ }
-+ ch = serial_inp(up, UART_RX);
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ up->port.icount.rx++;
-+
-+ if (*status & (UART_LSR_BI | UART_LSR_PE |
-+ UART_LSR_FE | UART_LSR_OE)) {
-+ /*
-+ * For statistics only
-+ */
-+ if (*status & UART_LSR_BI) {
-+ *status &= ~(UART_LSR_FE | UART_LSR_PE);
-+ up->port.icount.brk++;
-+ /*
-+ * We do the SysRQ and SAK checking
-+ * here because otherwise the break
-+ * may get masked by ignore_status_mask
-+ * or read_status_mask.
-+ */
-+ if (uart_handle_break(&up->port))
-+ goto ignore_char;
-+ } else if (*status & UART_LSR_PE)
-+ up->port.icount.parity++;
-+ else if (*status & UART_LSR_FE)
-+ up->port.icount.frame++;
-+ if (*status & UART_LSR_OE)
-+ up->port.icount.overrun++;
-+
-+ /*
-+ * Mask off conditions which should be ingored.
-+ */
-+ *status &= up->port.read_status_mask;
-+
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+ if (up->port.line == up->port.cons->index) {
-+ /* Recover the break flag from console xmit */
-+ *status |= up->lsr_break_flag;
-+ up->lsr_break_flag = 0;
-+ }
-+#endif
-+ if (*status & UART_LSR_BI) {
-+ DEBUG_INTR("handling break....");
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ } else if (*status & UART_LSR_PE)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (*status & UART_LSR_FE)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+ if (uart_handle_sysrq_char(&up->port, ch, regs))
-+ goto ignore_char;
-+ if ((*status & up->port.ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((*status & UART_LSR_OE) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character.
-+ */
-+ *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ *status = serial_inp(up, UART_LSR);
-+ } while ((*status & UART_LSR_DR) && (max_count-- > 0));
-+ tty_flip_buffer_push(tty);
-+}
-+
-+static _INLINE_ void transmit_chars(struct uart_8250_port *up)
-+{
-+ struct circ_buf *xmit = &up->port.info->xmit;
-+ int count;
-+
-+ if (up->port.x_char) {
-+ serial_outp(up, UART_TX, up->port.x_char);
-+ up->port.icount.tx++;
-+ up->port.x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-+ serial8250_stop_tx(&up->port, 0);
-+ return;
-+ }
-+
-+ count = up->port.fifosize;
-+ do {
-+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ up->port.icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&up->port);
-+
-+ DEBUG_INTR("THRE...");
-+
-+ if (uart_circ_empty(xmit))
-+ serial8250_stop_tx(&up->port, 0);
-+}
-+
-+static _INLINE_ void check_modem_status(struct uart_8250_port *up)
-+{
-+ int status;
-+
-+ status = serial_in(up, UART_MSR);
-+
-+ if ((status & UART_MSR_ANY_DELTA) == 0)
-+ return;
-+
-+ if (status & UART_MSR_TERI)
-+ up->port.icount.rng++;
-+ if (status & UART_MSR_DDSR)
-+ up->port.icount.dsr++;
-+ if (status & UART_MSR_DDCD)
-+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-+ if (status & UART_MSR_DCTS)
-+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-+
-+ wake_up_interruptible(&up->port.info->delta_msr_wait);
-+}
-+
-+/*
-+ * This handles the interrupt from one port.
-+ */
-+static inline void
-+serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
-+{
-+ unsigned int status = serial_inp(up, UART_LSR);
-+
-+ DEBUG_INTR("status = %x...", status);
-+
-+ if (status & UART_LSR_DR)
-+ receive_chars(up, &status, regs);
-+ check_modem_status(up);
-+ if (status & UART_LSR_THRE)
-+ transmit_chars(up);
-+}
-+
-+/*
-+ * This is the serial driver's interrupt routine.
-+ *
-+ * Arjan thinks the old way was overly complex, so it got simplified.
-+ * Alan disagrees, saying that need the complexity to handle the weird
-+ * nature of ISA shared interrupts. (This is a special exception.)
-+ *
-+ * In order to handle ISA shared interrupts properly, we need to check
-+ * that all ports have been serviced, and therefore the ISA interrupt
-+ * line has been de-asserted.
-+ *
-+ * This means we need to loop through all ports. checking that they
-+ * don't have an interrupt pending.
-+ */
-+static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct irq_info *i = dev_id;
-+ struct list_head *l, *end = NULL;
-+ int pass_counter = 0;
-+
-+ DEBUG_INTR("serial8250_interrupt(%d)...", irq);
-+
-+ spin_lock(&i->lock);
-+
-+ l = i->head;
-+ do {
-+ struct uart_8250_port *up;
-+ unsigned int iir;
-+
-+ up = list_entry(l, struct uart_8250_port, list);
-+
-+ iir = serial_in(up, UART_IIR);
-+ if (!(iir & UART_IIR_NO_INT)) {
-+ spin_lock(&up->port.lock);
-+ serial8250_handle_port(up, regs);
-+ spin_unlock(&up->port.lock);
-+
-+ end = NULL;
-+ } else if (end == NULL)
-+ end = l;
-+
-+ l = l->next;
-+
-+ if (l == i->head && pass_counter++ > PASS_LIMIT) {
-+ /* If we hit this, we're dead. */
-+ printk(KERN_ERR "serial8250: too much work for "
-+ "irq%d\n", irq);
-+ break;
-+ }
-+ } while (l != end);
-+
-+ spin_unlock(&i->lock);
-+
-+ DEBUG_INTR("end.\n");
-+}
-+
-+/*
-+ * To support ISA shared interrupts, we need to have one interrupt
-+ * handler that ensures that the IRQ line has been deasserted
-+ * before returning. Failing to do this will result in the IRQ
-+ * line being stuck active, and, since ISA irqs are edge triggered,
-+ * no more IRQs will be seen.
-+ */
-+static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
-+{
-+ spin_lock_irq(&i->lock);
-+
-+ if (!list_empty(i->head)) {
-+ if (i->head == &up->list)
-+ i->head = i->head->next;
-+ list_del(&up->list);
-+ } else {
-+ BUG_ON(i->head != &up->list);
-+ i->head = NULL;
-+ }
-+
-+ spin_unlock_irq(&i->lock);
-+}
-+
-+static int serial_link_irq_chain(struct uart_8250_port *up)
-+{
-+ struct irq_info *i = irq_lists + up->port.irq;
-+ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0;
-+
-+ spin_lock_irq(&i->lock);
-+
-+ if (i->head) {
-+ list_add(&up->list, i->head);
-+ spin_unlock_irq(&i->lock);
-+
-+ ret = 0;
-+ } else {
-+ INIT_LIST_HEAD(&up->list);
-+ i->head = &up->list;
-+ spin_unlock_irq(&i->lock);
-+
-+ ret = request_irq(up->port.irq, serial8250_interrupt,
-+ irq_flags, "serial", i);
-+ if (ret < 0)
-+ serial_do_unlink(i, up);
-+ }
-+
-+ return ret;
-+}
-+
-+static void serial_unlink_irq_chain(struct uart_8250_port *up)
-+{
-+ struct irq_info *i = irq_lists + up->port.irq;
-+
-+ BUG_ON(i->head == NULL);
-+
-+ if (list_empty(i->head))
-+ free_irq(up->port.irq, i);
-+
-+ serial_do_unlink(i, up);
-+}
-+
-+/*
-+ * This function is used to handle ports that do not have an
-+ * interrupt. This doesn't work very well for 16450's, but gives
-+ * barely passable results for a 16550A. (Although at the expense
-+ * of much CPU overhead).
-+ */
-+static void serial8250_timeout(unsigned long data)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)data;
-+ unsigned int timeout;
-+ unsigned int iir;
-+
-+ iir = serial_in(up, UART_IIR);
-+ if (!(iir & UART_IIR_NO_INT)) {
-+ spin_lock(&up->port.lock);
-+ serial8250_handle_port(up, NULL);
-+ spin_unlock(&up->port.lock);
-+ }
-+
-+ timeout = up->port.timeout;
-+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-+ mod_timer(&up->timer, jiffies + timeout);
-+}
-+
-+static unsigned int serial8250_tx_empty(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ return ret;
-+}
-+
-+static unsigned int serial8250_get_mctrl(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned char status;
-+ unsigned int ret;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ status = serial_in(up, UART_MSR);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ ret = 0;
-+ if (status & UART_MSR_DCD)
-+ ret |= TIOCM_CAR;
-+ if (status & UART_MSR_RI)
-+ ret |= TIOCM_RNG;
-+ if (status & UART_MSR_DSR)
-+ ret |= TIOCM_DSR;
-+ if (status & UART_MSR_CTS)
-+ ret |= TIOCM_CTS;
-+ return ret;
-+}
-+
-+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned char mcr = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ mcr |= UART_MCR_RTS;
-+ if (mctrl & TIOCM_DTR)
-+ mcr |= UART_MCR_DTR;
-+ if (mctrl & TIOCM_OUT1)
-+ mcr |= UART_MCR_OUT1;
-+ if (mctrl & TIOCM_OUT2)
-+ mcr |= UART_MCR_OUT2;
-+ if (mctrl & TIOCM_LOOP)
-+ mcr |= UART_MCR_LOOP;
-+
-+ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-+
-+ serial_out(up, UART_MCR, mcr);
-+}
-+
-+static void serial8250_break_ctl(struct uart_port *port, int break_state)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (break_state == -1)
-+ up->lcr |= UART_LCR_SBC;
-+ else
-+ up->lcr &= ~UART_LCR_SBC;
-+ serial_out(up, UART_LCR, up->lcr);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+static int serial8250_startup(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+ unsigned char lsr, iir;
-+ int retval;
-+
-+ up->capabilities = uart_config[up->port.type].flags;
-+ up->mcr = 0;
-+ up->efr = 0;
-+ up->ier = 0;
-+
-+ if (up->port.type == PORT_16C950) {
-+ /* Wake up and initialize UART */
-+ up->acr = 0;
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_IER, 0);
-+ serial_outp(up, UART_LCR, 0);
-+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ /*
-+ * If this is an RSA port, see if we can kick it up to the
-+ * higher speed clock.
-+ */
-+ enable_rsa(up);
-+#endif
-+
-+ /*
-+ * Clear the FIFO buffers and disable them.
-+ * (they will be reeanbled in change_speed())
-+ */
-+ if (up->capabilities & UART_CLEAR_FIFO) {
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_FCR, 0);
-+ }
-+
-+ /*
-+ * Clear the interrupt registers.
-+ */
-+ (void) serial_inp(up, UART_LSR);
-+ (void) serial_inp(up, UART_RX);
-+ (void) serial_inp(up, UART_IIR);
-+ (void) serial_inp(up, UART_MSR);
-+
-+ /*
-+ * At this point, there's no way the LSR could still be 0xff;
-+ * if it is, then bail out, because there's likely no UART
-+ * here.
-+ */
-+ if (!(up->port.flags & UPF_BUGGY_UART) &&
-+ (serial_inp(up, UART_LSR) == 0xff)) {
-+ printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
-+ return -ENODEV;
-+ }
-+
-+ /*
-+ * If the "interrupt" for this port doesn't correspond with any
-+ * hardware interrupt, we use a timer-based system. The original
-+ * driver used to do this with IRQ0.
-+ */
-+ if (!is_real_interrupt(up->port.irq)) {
-+ unsigned int timeout = up->port.timeout;
-+
-+ timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-+
-+ up->timer.data = (unsigned long)up;
-+ mod_timer(&up->timer, jiffies + timeout);
-+ } else {
-+ retval = serial_link_irq_chain(up);
-+ if (retval)
-+ return retval;
-+ }
-+
-+ /*
-+ * Now, initialize the UART
-+ */
-+ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ if (!is_real_interrupt(up->port.irq))
-+ up->port.mctrl |= TIOCM_OUT1;
-+ } else
-+ /*
-+ * Most PC uarts need OUT2 raised to enable interrupts.
-+ */
-+ if (is_real_interrupt(up->port.irq))
-+ up->port.mctrl |= TIOCM_OUT2;
-+
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+
-+ /*
-+ * Do a quick test to see if we receive an
-+ * interrupt when we enable the TX irq.
-+ */
-+ serial_outp(up, UART_IER, UART_IER_THRI);
-+ lsr = serial_in(up, UART_LSR);
-+ iir = serial_in(up, UART_IIR);
-+ serial_outp(up, UART_IER, 0);
-+
-+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
-+ up->capabilities |= UART_BAD_TX_ENABLE;
-+ printk("ttyS%d - enabling bad tx status workarounds\n",
-+ port->line);
-+ }
-+
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ /*
-+ * Finally, enable interrupts. Note: Modem status interrupts
-+ * are set via change_speed(), which will be occuring imminently
-+ * anyway, so we don't enable them here.
-+ */
-+ up->ier = UART_IER_RLSI | UART_IER_RDI;
-+ serial_outp(up, UART_IER, up->ier);
-+
-+ if (up->port.flags & UPF_FOURPORT) {
-+ unsigned int icp;
-+ /*
-+ * Enable interrupts on the AST Fourport board
-+ */
-+ icp = (up->port.iobase & 0xfe0) | 0x01f;
-+ outb_p(0x80, icp);
-+ (void) inb_p(icp);
-+ }
-+
-+ /*
-+ * And clear the interrupt registers again for luck.
-+ */
-+ (void) serial_inp(up, UART_LSR);
-+ (void) serial_inp(up, UART_RX);
-+ (void) serial_inp(up, UART_IIR);
-+ (void) serial_inp(up, UART_MSR);
-+
-+ return 0;
-+}
-+
-+static void serial8250_shutdown(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long flags;
-+
-+ /*
-+ * Disable interrupts from this port
-+ */
-+ up->ier = 0;
-+ serial_outp(up, UART_IER, 0);
-+
-+ spin_lock_irqsave(&up->port.lock, flags);
-+ if (up->port.flags & UPF_FOURPORT) {
-+ /* reset interrupts on the AST Fourport board */
-+ inb((up->port.iobase & 0xfe0) | 0x1f);
-+ up->port.mctrl |= TIOCM_OUT1;
-+ } else
-+ up->port.mctrl &= ~TIOCM_OUT2;
-+
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+
-+ /*
-+ * Disable break condition and FIFOs
-+ */
-+ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-+ UART_FCR_CLEAR_RCVR |
-+ UART_FCR_CLEAR_XMIT);
-+ serial_outp(up, UART_FCR, 0);
-+
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ /*
-+ * Reset the RSA board back to 115kbps compat mode.
-+ */
-+ disable_rsa(up);
-+#endif
-+
-+ /*
-+ * Read data port to reset things, and then unlink from
-+ * the IRQ chain.
-+ */
-+ (void) serial_in(up, UART_RX);
-+
-+ if (!is_real_interrupt(up->port.irq))
-+ del_timer_sync(&up->timer);
-+ else
-+ serial_unlink_irq_chain(up);
-+}
-+
-+static void serial8250_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned char cval, fcr = 0;
-+ unsigned long flags;
-+
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ cval = 0x00;
-+ break;
-+ case CS6:
-+ cval = 0x01;
-+ break;
-+ case CS7:
-+ cval = 0x02;
-+ break;
-+ default:
-+ case CS8:
-+ cval = 0x03;
-+ break;
-+ }
-+
-+ if (cflag & CSTOPB)
-+ cval |= 0x04;
-+ if (cflag & PARENB)
-+ cval |= UART_LCR_PARITY;
-+ if (!(cflag & PARODD))
-+ cval |= UART_LCR_EPAR;
-+#ifdef CMSPAR
-+ if (cflag & CMSPAR)
-+ cval |= UART_LCR_SPAR;
-+#endif
-+
-+ /*
-+ * Work around a bug in the Oxford Semiconductor 952 rev B
-+ * chip which causes it to seriously miscalculate baud rates
-+ * when DLL is 0.
-+ */
-+ if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
-+ up->rev == 0x5201)
-+ quot ++;
-+
-+ if (up->capabilities & UART_USE_FIFO) {
-+ if ((up->port.uartclk / quot) < (2400 * 16))
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-+#ifdef CONFIG_SERIAL_8250_RSA
-+ else if (up->port.type == PORT_RSA)
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
-+#endif
-+ else
-+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
-+ }
-+ if (up->port.type == PORT_16750)
-+ fcr |= UART_FCR7_64BYTE;
-+
-+ /*
-+ * Ok, we're now changing the port state. Do it with
-+ * interrupts disabled.
-+ */
-+ spin_lock_irqsave(&up->port.lock, flags);
-+
-+ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-+ if (iflag & IGNPAR)
-+ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-+ if (iflag & (BRKINT | PARMRK))
-+ up->port.read_status_mask |= UART_LSR_BI;
-+
-+ /*
-+ * Characteres to ignore
-+ */
-+ up->port.ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-+ if (iflag & IGNBRK) {
-+ up->port.ignore_status_mask |= UART_LSR_BI;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ up->port.ignore_status_mask |= UART_LSR_OE;
-+ }
-+
-+ /*
-+ * ignore all characters if CREAD is not set
-+ */
-+ if ((cflag & CREAD) == 0)
-+ up->port.ignore_status_mask |= UART_LSR_DR;
-+
-+ /*
-+ * CTS flow control flag and modem status interrupts
-+ */
-+ up->ier &= ~UART_IER_MSI;
-+ if (UART_ENABLE_MS(&up->port, cflag))
-+ up->ier |= UART_IER_MSI;
-+
-+ serial_out(up, UART_IER, up->ier);
-+
-+ if (up->capabilities & UART_MCRAFE) {
-+ /*
-+ * TI16C750 hardware flow control
-+ */
-+ up->mcr &= ~UART_MCR_AFE;
-+ if (cflag & CRTSCTS)
-+ up->mcr |= UART_MCR_AFE;
-+ }
-+ if (up->capabilities & UART_EFRAFE) {
-+ /*
-+ * TI16C752/Startech hardware flow control
-+ * FIXME:
-+ * - TI16C752 requires control thresholds
-+ * to be set for auto-RTS.
-+ * - We only enable auto-CTS here.
-+ * Note: ST16C654 does not allow MCR bit 1
-+ * to override RTS when UART_EFR_RTS is set.
-+ */
-+ up->efr &= ~UART_EFR_CTS;
-+ if (cflag & CRTSCTS)
-+ up->efr |= UART_EFR_CTS;
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, up->efr);
-+ }
-+
-+ if (up->capabilities & UART_NATSEMI) {
-+ /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
-+ serial_outp(up, UART_LCR, 0xe0);
-+ } else {
-+ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
-+ }
-+ serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */
-+ serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */
-+ if (up->port.type == PORT_16750)
-+ serial_outp(up, UART_FCR, fcr); /* set fcr */
-+ serial_outp(up, UART_LCR, cval); /* reset DLAB */
-+ up->lcr = cval; /* Save LCR */
-+ if (up->port.type != PORT_16750) {
-+ if (fcr & UART_FCR_ENABLE_FIFO) {
-+ /* emulated UARTs (Lucent Venus 167x) need two steps */
-+ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-+ }
-+ serial_outp(up, UART_FCR, fcr); /* set fcr */
-+ }
-+ serial8250_set_mctrl(&up->port, up->port.mctrl);
-+ spin_unlock_irqrestore(&up->port.lock, flags);
-+}
-+
-+static void
-+serial8250_pm(struct uart_port *port, unsigned int state,
-+ unsigned int oldstate)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ if (state) {
-+ /* sleep */
-+ if (up->capabilities & UART_STARTECH) {
-+ /* Arrange to enter sleep mode */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_IER, UART_IERX_SLEEP);
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+ if (up->port.type == PORT_16750) {
-+ /* Arrange to enter sleep mode */
-+ serial_outp(up, UART_IER, UART_IERX_SLEEP);
-+ }
-+ } else {
-+ /* wake */
-+ if (up->capabilities & UART_STARTECH) {
-+ /* Wake up UART */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, UART_EFR_ECB);
-+ /*
-+ * Turn off LCR == 0xBF so we actually set the IER
-+ * register on the XR16C850
-+ */
-+ serial_outp(up, UART_LCR, 0);
-+ serial_outp(up, UART_IER, 0);
-+ /*
-+ * Now reset LCR so we can turn off the ECB bit
-+ */
-+ serial_outp(up, UART_LCR, 0xBF);
-+ serial_outp(up, UART_EFR, 0);
-+ /*
-+ * For a XR16C850, we need to set the trigger levels
-+ */
-+ if (up->port.type == PORT_16850) {
-+ unsigned char fctr;
-+
-+ fctr = serial_inp(up, UART_FCTR) &
-+ ~(UART_FCTR_RX | UART_FCTR_TX);
-+ serial_outp(up, UART_FCTR, fctr |
-+ UART_FCTR_TRGD |
-+ UART_FCTR_RX);
-+ serial_outp(up, UART_TRG, UART_TRG_96);
-+ serial_outp(up, UART_FCTR, fctr |
-+ UART_FCTR_TRGD |
-+ UART_FCTR_TX);
-+ serial_outp(up, UART_TRG, UART_TRG_96);
-+ }
-+ serial_outp(up, UART_LCR, 0);
-+ }
-+
-+ if (up->port.type == PORT_16750) {
-+ /* Wake up UART */
-+ serial_outp(up, UART_IER, 0);
-+ }
-+ }
-+}
-+
-+/*
-+ * Resource handling. This is complicated by the fact that resources
-+ * depend on the port type. Maybe we should be claiming the standard
-+ * 8250 ports, and then trying to get other resources as necessary?
-+ */
-+static int
-+serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res)
-+{
-+ unsigned int size = 8 << up->port.regshift;
-+ int ret = 0;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ *res = request_mem_region(up->port.mapbase, size, "serial");
-+ if (!*res)
-+ ret = -EBUSY;
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ *res = request_region(up->port.iobase, size, "serial");
-+ if (!*res)
-+ ret = -EBUSY;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int
-+serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res)
-+{
-+ unsigned int size = 8 << up->port.regshift;
-+ unsigned long start;
-+ int ret = 0;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ start = up->port.mapbase;
-+ start += UART_RSA_BASE << up->port.regshift;
-+ *res = request_mem_region(start, size, "serial-rsa");
-+ if (!*res)
-+ ret = -EBUSY;
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ start = up->port.iobase;
-+ start += UART_RSA_BASE << up->port.regshift;
-+ *res = request_region(start, size, "serial-rsa");
-+ if (!*res)
-+ ret = -EBUSY;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static void serial8250_release_port(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ unsigned long start, offset = 0, size = 0;
-+
-+ if (up->port.type == PORT_RSA) {
-+ offset = UART_RSA_BASE << up->port.regshift;
-+ size = 8;
-+ }
-+
-+ size <<= up->port.regshift;
-+
-+ switch (up->port.iotype) {
-+ case SERIAL_IO_MEM:
-+ if (up->port.mapbase) {
-+ /*
-+ * Unmap the area.
-+ */
-+ if (up->port.flags & UPF_IOREMAP) {
-+ iounmap(up->port.membase);
-+ up->port.membase = NULL;
-+ }
-+
-+ start = up->port.mapbase;
-+
-+ if (size)
-+ release_mem_region(start + offset, size);
-+ release_mem_region(start, 8 << up->port.regshift);
-+ }
-+ break;
-+
-+ case SERIAL_IO_HUB6:
-+ case SERIAL_IO_PORT:
-+ start = up->port.iobase;
-+
-+ if (size)
-+ release_region(start + offset, size);
-+ release_region(start + offset, 8 << up->port.regshift);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+}
-+
-+static int serial8250_request_port(struct uart_port *port)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ struct resource *res = NULL, *res_rsa = NULL;
-+ int ret = 0;
-+
-+ if (up->port.flags & UPF_RESOURCES) {
-+ if (up->port.type == PORT_RSA) {
-+ ret = serial8250_request_rsa_resource(up, &res_rsa);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ ret = serial8250_request_std_resource(up, &res);
-+ }
-+
-+ /*
-+ * If we have a mapbase, then request that as well.
-+ */
-+ if (ret == 0 && up->port.flags & UPF_IOREMAP) {
-+ int size = res->end - res->start + 1;
-+
-+ up->port.membase = ioremap(up->port.mapbase, size);
-+ if (!up->port.membase)
-+ ret = -ENOMEM;
-+ }
-+
-+ if (ret < 0) {
-+ if (res_rsa)
-+ release_resource(res_rsa);
-+ if (res)
-+ release_resource(res);
-+ }
-+ return ret;
-+}
-+
-+static void serial8250_config_port(struct uart_port *port, int flags)
-+{
-+ struct uart_8250_port *up = (struct uart_8250_port *)port;
-+ struct resource *res_std = NULL, *res_rsa = NULL;
-+ int probeflags = PROBE_ANY;
-+ int ret;
-+
-+#ifdef CONFIG_MCA
-+ /*
-+ * Don't probe for MCA ports on non-MCA machines.
-+ */
-+ if (up->port.flags & UPF_BOOT_ONLYMCA && !MCA_bus)
-+ return;
-+#endif
-+
-+ /*
-+ * Find the region that we can probe for. This in turn
-+ * tells us whether we can probe for the type of port.
-+ */
-+ if (up->port.flags & UPF_RESOURCES) {
-+ ret = serial8250_request_std_resource(up, &res_std);
-+ if (ret < 0)
-+ return;
-+
-+ ret = serial8250_request_rsa_resource(up, &res_rsa);
-+ if (ret < 0)
-+ probeflags &= ~PROBE_RSA;
-+ } else {
-+ probeflags &= ~PROBE_RSA;
-+ }
-+
-+ if (flags & UART_CONFIG_TYPE)
-+ autoconfig(up, probeflags);
-+ if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
-+ autoconfig_irq(up);
-+
-+ /*
-+ * If the port wasn't an RSA port, release the resource.
-+ */
-+ if (up->port.type != PORT_RSA && res_rsa)
-+ release_resource(res_rsa);
-+
-+ if (up->port.type == PORT_UNKNOWN && res_std)
-+ release_resource(res_std);
-+}
-+
-+static int
-+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ if (ser->irq >= NR_IRQS || ser->irq < 0 ||
-+ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
-+ ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS ||
-+ ser->type == PORT_STARTECH)
-+ return -EINVAL;
-+ return 0;
-+}
-+
-+static const char *
-+serial8250_type(struct uart_port *port)
-+{
-+ int type = port->type;
-+
-+ if (type >= ARRAY_SIZE(uart_config))
-+ type = 0;
-+ return uart_config[type].name;
-+}
-+
-+static struct uart_ops serial8250_pops = {
-+ .tx_empty = serial8250_tx_empty,
-+ .set_mctrl = serial8250_set_mctrl,
-+ .get_mctrl = serial8250_get_mctrl,
-+ .stop_tx = serial8250_stop_tx,
-+ .start_tx = serial8250_start_tx,
-+ .stop_rx = serial8250_stop_rx,
-+ .enable_ms = serial8250_enable_ms,
-+ .break_ctl = serial8250_break_ctl,
-+ .startup = serial8250_startup,
-+ .shutdown = serial8250_shutdown,
-+ .change_speed = serial8250_change_speed,
-+ .pm = serial8250_pm,
-+ .type = serial8250_type,
-+ .release_port = serial8250_release_port,
-+ .request_port = serial8250_request_port,
-+ .config_port = serial8250_config_port,
-+ .verify_port = serial8250_verify_port,
-+};
-+
-+static struct uart_8250_port serial8250_ports[UART_NR];
-+
-+static void __init serial8250_isa_init_ports(void)
-+{
-+ struct uart_8250_port *up;
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
-+ i++, up++) {
-+ up->port.iobase = old_serial_port[i].port;
-+ up->port.irq = irq_cannonicalize(old_serial_port[i].irq);
-+ up->port.uartclk = old_serial_port[i].baud_base * 16;
-+ up->port.flags = old_serial_port[i].flags |
-+ UPF_RESOURCES;
-+ up->port.hub6 = old_serial_port[i].hub6;
-+ up->port.membase = old_serial_port[i].iomem_base;
-+ up->port.iotype = old_serial_port[i].io_type;
-+ up->port.regshift = old_serial_port[i].iomem_reg_shift;
-+ up->port.ops = &serial8250_pops;
-+
-+ if (up->port.iotype == UPIO_MEM && up->port.mapbase)
-+ up->port.flags |= UPF_IOREMAP;
-+
-+ if (share_irqs)
-+ up->port.flags |= UPF_SHARE_IRQ;
-+ }
-+}
-+
-+static void __init serial8250_register_ports(struct uart_driver *drv)
-+{
-+ int i;
-+
-+ serial8250_isa_init_ports();
-+
-+ for (i = 0; i < UART_NR; i++) {
-+ struct uart_8250_port *up = &serial8250_ports[i];
-+
-+ up->port.line = i;
-+ up->port.ops = &serial8250_pops;
-+ init_timer(&up->timer);
-+ up->timer.function = serial8250_timeout;
-+
-+ /*
-+ * ALPHA_KLUDGE_MCR needs to be killed.
-+ */
-+ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
-+ up->mcr_force = ALPHA_KLUDGE_MCR;
-+
-+ uart_add_one_port(drv, &up->port);
-+ }
-+}
-+
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+
-+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-+
-+/*
-+ * Wait for transmitter & holding register to empty
-+ */
-+static inline void wait_for_xmitr(struct uart_8250_port *up)
-+{
-+ unsigned int status, tmout = 10000;
-+
-+ /* Wait up to 10ms for the character(s) to be sent. */
-+ do {
-+ status = serial_in(up, UART_LSR);
-+
-+ if (status & UART_LSR_BI)
-+ up->lsr_break_flag = UART_LSR_BI;
-+
-+ if (--tmout == 0)
-+ break;
-+ udelay(1);
-+ } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
-+
-+ /* Wait up to 1s for flow control if necessary */
-+ if (up->port.flags & UPF_CONS_FLOW) {
-+ tmout = 1000000;
-+ while (--tmout &&
-+ ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-+ udelay(1);
-+ }
-+}
-+
-+/*
-+ * Print a string to the serial port trying not to disturb
-+ * any possible real use of the port...
-+ *
-+ * The console_lock must be held when we get here.
-+ */
-+static void
-+serial8250_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct uart_8250_port *up = &serial8250_ports[co->index];
-+ unsigned int ier;
-+ int i;
-+
-+ /*
-+ * First save the UER then disable the interrupts
-+ */
-+ ier = serial_in(up, UART_IER);
-+ serial_out(up, UART_IER, 0);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++, s++) {
-+ wait_for_xmitr(up);
-+
-+ /*
-+ * Send the character out.
-+ * If a LF, also do CR...
-+ */
-+ serial_out(up, UART_TX, *s);
-+ if (*s == 10) {
-+ wait_for_xmitr(up);
-+ serial_out(up, UART_TX, 13);
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the IER
-+ */
-+ wait_for_xmitr(up);
-+ serial_out(up, UART_IER, ier);
-+}
-+
-+static kdev_t serial8250_console_device(struct console *co)
-+{
-+ return MKDEV(TTY_MAJOR, 64 + co->index);
-+}
-+
-+static int __init serial8250_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 9600;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index >= UART_NR)
-+ co->index = 0;
-+ port = &serial8250_ports[co->index].port;
-+
-+ /*
-+ * Temporary fix.
-+ */
-+ spin_lock_init(&port->lock);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console serial8250_console = {
-+ .name = "ttyS",
-+ .write = serial8250_console_write,
-+ .device = serial8250_console_device,
-+ .setup = serial8250_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init serial8250_console_init(void)
-+{
-+ serial8250_isa_init_ports();
-+ register_console(&serial8250_console);
-+}
-+
-+#define SERIAL8250_CONSOLE &serial8250_console
-+#else
-+#define SERIAL8250_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver serial8250_reg = {
-+ .owner = THIS_MODULE,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "tts/%d",
-+ .callout_name = "cua/%d",
-+#else
-+ .normal_name = "ttyS",
-+ .callout_name = "cua",
-+#endif
-+ .normal_major = TTY_MAJOR,
-+ .callout_major = TTYAUX_MAJOR,
-+ .normal_driver = &normal,
-+ .callout_driver = &callout,
-+ .table = serial8250_table,
-+ .termios = serial8250_termios,
-+ .termios_locked = serial8250_termios_locked,
-+ .minor = 64,
-+ .nr = UART_NR,
-+ .cons = SERIAL8250_CONSOLE,
-+};
-+
-+/*
-+ * register_serial and unregister_serial allows for 16x50 serial ports to be
-+ * configured at run-time, to support PCMCIA modems.
-+ */
-+
-+static int __register_serial(struct serial_struct *req, int line)
-+{
-+ struct uart_port port;
-+
-+ port.iobase = req->port;
-+ port.membase = req->iomem_base;
-+ port.irq = req->irq;
-+ port.uartclk = req->baud_base * 16;
-+ port.fifosize = req->xmit_fifo_size;
-+ port.regshift = req->iomem_reg_shift;
-+ port.iotype = req->io_type;
-+ port.flags = req->flags | UPF_BOOT_AUTOCONF;
-+ port.mapbase = req->iomap_base;
-+ port.line = line;
-+
-+ if (share_irqs)
-+ port.flags |= UPF_SHARE_IRQ;
-+
-+ if (HIGH_BITS_OFFSET)
-+ port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-+
-+ /*
-+ * If a clock rate wasn't specified by the low level
-+ * driver, then default to the standard clock rate.
-+ */
-+ if (port.uartclk == 0)
-+ port.uartclk = BASE_BAUD * 16;
-+
-+ return uart_register_port(&serial8250_reg, &port);
-+}
-+
-+/**
-+ * register_serial - configure a 16x50 serial port at runtime
-+ * @req: request structure
-+ *
-+ * Configure the serial port specified by the request. If the
-+ * port exists and is in use an error is returned. If the port
-+ * is not currently in the table it is added.
-+ *
-+ * The port is then probed and if necessary the IRQ is autodetected
-+ * If this fails an error is returned.
-+ *
-+ * On success the port is ready to use and the line number is returned.
-+ */
-+int register_serial(struct serial_struct *req)
-+{
-+ return __register_serial(req, -1);
-+}
-+
-+/**
-+ * unregister_serial - remove a 16x50 serial port at runtime
-+ * @line: serial line number
-+ *
-+ * Remove one serial port. This may be called from interrupt
-+ * context.
-+ */
-+void unregister_serial(int line)
-+{
-+ uart_unregister_port(&serial8250_reg, line);
-+}
-+
-+/*
-+ * This is for ISAPNP only.
-+ */
-+void serial8250_get_irq_map(unsigned int *map)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++) {
-+ if (serial8250_ports[i].port.type != PORT_UNKNOWN &&
-+ serial8250_ports[i].port.irq < 16)
-+ *map |= 1 << serial8250_ports[i].port.irq;
-+ }
-+}
-+
-+static int __init serial8250_init(void)
-+{
-+ int ret, i;
-+
-+ for (i = 0; i < NR_IRQS; i++)
-+ spin_lock_init(&irq_lists[i].lock);
-+
-+ ret = uart_register_driver(&serial8250_reg);
-+ if (ret >= 0)
-+ serial8250_register_ports(&serial8250_reg);
-+
-+ return ret;
-+}
-+
-+static void __exit serial8250_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port);
-+
-+ uart_unregister_driver(&serial8250_reg);
-+}
-+
-+module_init(serial8250_init);
-+module_exit(serial8250_exit);
-+
-+EXPORT_SYMBOL(register_serial);
-+EXPORT_SYMBOL(unregister_serial);
-+EXPORT_SYMBOL(serial8250_get_irq_map);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-+
-+MODULE_PARM(share_irqs, "i");
-+MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
-+ " (unsafe)");
-+
-+#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE)
-+MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
-+MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
-+MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
-+MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
-+#endif /* CONFIG_SERIAL_8250_RSA */
-+
---- /dev/null
-+++ linux-2.4.27/drivers/serial/8250.h
-@@ -0,0 +1,88 @@
-+/*
-+ * linux/drivers/serial/8250.h
-+ *
-+ * Driver for 8250/16550-type serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * $Id: 8250.h,v 1.1.1.1.2.1 2002/10/24 09:53:24 rmk Exp $
-+ */
-+
-+#include <linux/config.h>
-+
-+struct serial8250_probe {
-+ struct module *owner;
-+ int (*pci_init_one)(struct pci_dev *dev);
-+ void (*pci_remove_one)(struct pci_dev *dev);
-+ void (*pnp_init)(void);
-+};
-+
-+int serial8250_register_probe(struct serial8250_probe *probe);
-+void serial8250_unregister_probe(struct serial8250_probe *probe);
-+void serial8250_get_irq_map(unsigned int *map);
-+
-+struct old_serial_port {
-+ unsigned int uart;
-+ unsigned int baud_base;
-+ unsigned int port;
-+ unsigned int irq;
-+ unsigned int flags;
-+ unsigned char hub6;
-+ unsigned char io_type;
-+ unsigned char *iomem_base;
-+ unsigned short iomem_reg_shift;
-+};
-+
-+struct serial8250_config {
-+ const char *name;
-+ unsigned int dfl_xmit_fifo_size;
-+ unsigned int flags;
-+};
-+
-+#define UART_CLEAR_FIFO 0x01
-+#define UART_USE_FIFO 0x02
-+#define UART_STARTECH 0x04
-+#define UART_NATSEMI 0x08
-+#define UART_MCRAFE 0x10 /* TI16C750-style auto-flow */
-+#define UART_EFRAFE 0x20 /* TI16C752/startech auto-flow */
-+
-+#define UART_BAD_TX_ENABLE 0x80000000
-+
-+#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-+#define SERIAL_INLINE
-+#endif
-+
-+#ifdef SERIAL_INLINE
-+#define _INLINE_ inline
-+#else
-+#define _INLINE_
-+#endif
-+
-+#define PROBE_RSA (1 << 0)
-+#define PROBE_ANY (~0)
-+
-+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-+
-+#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-+#define SERIAL8250_SHARE_IRQS 1
-+#else
-+#define SERIAL8250_SHARE_IRQS 0
-+#endif
-+
-+#if defined(__alpha__) && !defined(CONFIG_PCI)
-+/*
-+ * Digital did something really horribly wrong with the OUT1 and OUT2
-+ * lines on at least some ALPHA's. The failure mode is that if either
-+ * is cleared, the machine locks up with endless interrupts.
-+ */
-+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
-+#else
-+#define ALPHA_KLUDGE_MCR 0
-+#endif
---- /dev/null
-+++ linux-2.4.27/drivers/serial/8250_pci.c
-@@ -0,0 +1,1080 @@
-+/*
-+ * linux/drivers/char/serial_8250_pci.c
-+ *
-+ * Probe module for 8250/16550-type PCI serial ports.
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * $Id: 8250_pci.c,v 1.8.2.1 2002/10/24 09:53:24 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/sched.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/serial.h>
-+
-+/* 2.4.6 compatibility cruft ;( */
-+#define pci_board __pci_board
-+#include <linux/serialP.h>
-+#undef pci_board
-+
-+#include <asm/bitops.h>
-+#include <asm/byteorder.h>
-+#include <asm/serial.h>
-+
-+#include "8250.h"
-+
-+#ifndef IS_PCI_REGION_IOPORT
-+#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
-+ IORESOURCE_IO)
-+#endif
-+#ifndef IS_PCI_REGION_IOMEM
-+#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
-+ IORESOURCE_MEM)
-+#endif
-+#ifndef PCI_IRQ_RESOURCE
-+#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
-+#endif
-+
-+#ifndef pci_get_subvendor
-+#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
-+#define pci_get_subdevice(dev) ((dev)->subsystem_device)
-+#endif
-+
-+struct serial_private {
-+ unsigned int nr;
-+ struct pci_board *board;
-+ int line[0];
-+};
-+
-+struct pci_board {
-+ int flags;
-+ int num_ports;
-+ int base_baud;
-+ int uart_offset;
-+ int reg_shift;
-+ int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
-+ int enable);
-+ int first_uart_offset;
-+};
-+
-+static int
-+get_pci_port(struct pci_dev *dev, struct pci_board *board,
-+ struct serial_struct *req, int idx)
-+{
-+ unsigned long port;
-+ int base_idx;
-+ int max_port;
-+ int offset;
-+
-+ base_idx = SPCI_FL_GET_BASE(board->flags);
-+ if (board->flags & SPCI_FL_BASE_TABLE)
-+ base_idx += idx;
-+
-+ if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-+ max_port = pci_resource_len(dev, base_idx) / 8;
-+ if (idx >= max_port)
-+ return 1;
-+ }
-+
-+ offset = board->first_uart_offset;
-+
-+ /* Timedia/SUNIX uses a mixture of BARs and offsets */
-+ /* Ugh, this is ugly as all hell --- TYT */
-+ if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
-+ switch(idx) {
-+ case 0: base_idx=0;
-+ break;
-+ case 1: base_idx=0; offset=8;
-+ break;
-+ case 2: base_idx=1;
-+ break;
-+ case 3: base_idx=1; offset=8;
-+ break;
-+ case 4: /* BAR 2*/
-+ case 5: /* BAR 3 */
-+ case 6: /* BAR 4*/
-+ case 7: base_idx=idx-2; /* BAR 5*/
-+ }
-+
-+ /* Some Titan cards are also a little weird */
-+ if (dev->vendor == PCI_VENDOR_ID_TITAN &&
-+ (dev->device == PCI_DEVICE_ID_TITAN_400L ||
-+ dev->device == PCI_DEVICE_ID_TITAN_800L)) {
-+ switch (idx) {
-+ case 0: base_idx = 1;
-+ break;
-+ case 1: base_idx = 2;
-+ break;
-+ default:
-+ base_idx = 4;
-+ offset = 8 * (idx - 2);
-+ }
-+ }
-+
-+ port = pci_resource_start(dev, base_idx) + offset;
-+
-+ if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-+ port += idx * (board->uart_offset ? board->uart_offset : 8);
-+
-+ if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
-+ req->port = port;
-+ if (HIGH_BITS_OFFSET)
-+ req->port_high = port >> HIGH_BITS_OFFSET;
-+ else
-+ req->port_high = 0;
-+ return 0;
-+ }
-+ req->io_type = SERIAL_IO_MEM;
-+ req->iomem_base = ioremap(port, board->uart_offset);
-+ req->iomem_reg_shift = board->reg_shift;
-+ req->port = 0;
-+ return 0;
-+}
-+
-+static _INLINE_ int get_pci_irq(struct pci_dev *dev,
-+ struct pci_board *board,
-+ int idx)
-+{
-+ int base_idx;
-+
-+ if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
-+ return dev->irq;
-+
-+ base_idx = SPCI_FL_GET_IRQBASE(board->flags);
-+ if (board->flags & SPCI_FL_IRQ_TABLE)
-+ base_idx += idx;
-+
-+ return PCI_IRQ_RESOURCE(dev, base_idx);
-+}
-+
-+/*
-+ * Some PCI serial cards using the PLX 9050 PCI interface chip require
-+ * that the card interrupt be explicitly enabled or disabled. This
-+ * seems to be mainly needed on card using the PLX which also use I/O
-+ * mapped memory.
-+ */
-+static int __devinit
-+pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u8 data, *p, irq_config;
-+ int pci_config;
-+
-+ irq_config = 0x41;
-+ pci_config = PCI_COMMAND_MEMORY;
-+ if (dev->vendor == PCI_VENDOR_ID_PANACOM)
-+ irq_config = 0x43;
-+ if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
-+ (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
-+ /*
-+ * As the megawolf cards have the int pins active
-+ * high, and have 2 UART chips, both ints must be
-+ * enabled on the 9050. Also, the UARTS are set in
-+ * 16450 mode by default, so we have to enable the
-+ * 16C950 'enhanced' mode so that we can use the deep
-+ * FIFOs
-+ */
-+ irq_config = 0x5b;
-+ pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
-+ }
-+
-+ pci_read_config_byte(dev, PCI_COMMAND, &data);
-+
-+ if (enable)
-+ pci_write_config_byte(dev, PCI_COMMAND,
-+ data | pci_config);
-+
-+ /* enable/disable interrupts */
-+ p = ioremap(pci_resource_start(dev, 0), 0x80);
-+ writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
-+ iounmap(p);
-+
-+ if (!enable)
-+ pci_write_config_byte(dev, PCI_COMMAND,
-+ data & ~pci_config);
-+ return 0;
-+}
-+
-+
-+/*
-+ * SIIG serial cards have an PCI interface chip which also controls
-+ * the UART clocking frequency. Each UART can be clocked independently
-+ * (except cards equiped with 4 UARTs) and initial clocking settings
-+ * are stored in the EEPROM chip. It can cause problems because this
-+ * version of serial driver doesn't support differently clocked UART's
-+ * on single PCI card. To prevent this, initialization functions set
-+ * high frequency clocking for all UART's on given card. It is safe (I
-+ * hope) because it doesn't touch EEPROM settings to prevent conflicts
-+ * with other OSes (like M$ DOS).
-+ *
-+ * SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
-+ *
-+ * There is two family of SIIG serial cards with different PCI
-+ * interface chip and different configuration methods:
-+ * - 10x cards have control registers in IO and/or memory space;
-+ * - 20x cards have control registers in standard PCI configuration space.
-+ */
-+
-+#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
-+#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
-+
-+static int __devinit
-+pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u16 data, *p;
-+
-+ if (!enable) return 0;
-+
-+ p = ioremap(pci_resource_start(dev, 0), 0x80);
-+
-+ switch (dev->device & 0xfff8) {
-+ case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
-+ data = 0xffdf;
-+ break;
-+ case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
-+ data = 0xf7ff;
-+ break;
-+ default: /* 1S1P, 4S */
-+ data = 0xfffb;
-+ break;
-+ }
-+
-+ writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
-+ iounmap(p);
-+ return 0;
-+}
-+
-+#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
-+#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
-+
-+static int __devinit
-+pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ u8 data;
-+
-+ if (!enable) return 0;
-+
-+ /* Change clock frequency for the first UART. */
-+ pci_read_config_byte(dev, 0x6f, &data);
-+ pci_write_config_byte(dev, 0x6f, data & 0xef);
-+
-+ /* If this card has 2 UART, we have to do the same with second UART. */
-+ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
-+ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
-+ pci_read_config_byte(dev, 0x73, &data);
-+ pci_write_config_byte(dev, 0x73, data & 0xef);
-+ }
-+ return 0;
-+}
-+
-+/* Added for EKF Intel i960 serial boards */
-+static int __devinit
-+pci_inteli960ni_fn(struct pci_dev *dev,
-+ struct pci_board *board,
-+ int enable)
-+{
-+ unsigned long oldval;
-+
-+ if (!(pci_get_subdevice(dev) & 0x1000))
-+ return(-1);
-+
-+ if (!enable) /* is there something to deinit? */
-+ return(0);
-+
-+ /* is firmware started? */
-+ pci_read_config_dword(dev, 0x44, (void*) &oldval);
-+ if (oldval == 0x00001000L) { /* RESET value */
-+ printk(KERN_DEBUG "Local i960 firmware missing");
-+ return(-1);
-+ }
-+ return(0);
-+}
-+
-+/*
-+ * Timedia has an explosion of boards, and to avoid the PCI table from
-+ * growing *huge*, we use this function to collapse some 70 entries
-+ * in the PCI table into one, for sanity's and compactness's sake.
-+ */
-+static unsigned short timedia_single_port[] = {
-+ 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
-+static unsigned short timedia_dual_port[] = {
-+ 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
-+ 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
-+ 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
-+ 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
-+ 0xD079, 0 };
-+static unsigned short timedia_quad_port[] = {
-+ 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
-+ 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
-+ 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
-+ 0xB157, 0 };
-+static unsigned short timedia_eight_port[] = {
-+ 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
-+ 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
-+static struct timedia_struct {
-+ int num;
-+ unsigned short *ids;
-+} timedia_data[] = {
-+ { 1, timedia_single_port },
-+ { 2, timedia_dual_port },
-+ { 4, timedia_quad_port },
-+ { 8, timedia_eight_port },
-+ { 0, 0 }
-+};
-+
-+static int __devinit
-+pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ int i, j;
-+ unsigned short *ids;
-+
-+ if (!enable)
-+ return 0;
-+
-+ for (i=0; timedia_data[i].num; i++) {
-+ ids = timedia_data[i].ids;
-+ for (j=0; ids[j]; j++) {
-+ if (pci_get_subdevice(dev) == ids[j]) {
-+ board->num_ports = timedia_data[i].num;
-+ return 0;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+static int __devinit
-+pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
-+{
-+ __set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(HZ/10);
-+ return 0;
-+}
-+
-+/*
-+ * This is the configuration table for all of the PCI serial boards
-+ * which we support. It is directly indexed by the pci_board_num_t enum
-+ * value, which is encoded in the pci_device_id PCI probe table's
-+ * driver_data member.
-+ */
-+enum pci_board_num_t {
-+ pbn_b0_1_115200,
-+ pbn_default = 0,
-+
-+ pbn_b0_2_115200,
-+ pbn_b0_4_115200,
-+
-+ pbn_b0_1_921600,
-+ pbn_b0_2_921600,
-+ pbn_b0_4_921600,
-+
-+ pbn_b0_bt_1_115200,
-+ pbn_b0_bt_2_115200,
-+ pbn_b0_bt_1_460800,
-+ pbn_b0_bt_2_460800,
-+
-+ pbn_b1_1_115200,
-+ pbn_b1_2_115200,
-+ pbn_b1_4_115200,
-+ pbn_b1_8_115200,
-+
-+ pbn_b1_2_921600,
-+ pbn_b1_4_921600,
-+ pbn_b1_8_921600,
-+
-+ pbn_b1_2_1382400,
-+ pbn_b1_4_1382400,
-+ pbn_b1_8_1382400,
-+
-+ pbn_b2_8_115200,
-+ pbn_b2_4_460800,
-+ pbn_b2_8_460800,
-+ pbn_b2_16_460800,
-+ pbn_b2_4_921600,
-+ pbn_b2_8_921600,
-+
-+ pbn_b2_bt_1_115200,
-+ pbn_b2_bt_2_115200,
-+ pbn_b2_bt_4_115200,
-+ pbn_b2_bt_2_921600,
-+
-+ pbn_panacom,
-+ pbn_panacom2,
-+ pbn_panacom4,
-+ pbn_plx_romulus,
-+ pbn_oxsemi,
-+ pbn_timedia,
-+ pbn_intel_i960,
-+ pbn_sgi_ioc3,
-+#ifdef CONFIG_DDB5074
-+ pbn_nec_nile4,
-+#endif
-+#if 0
-+ pbn_dci_pccom8,
-+#endif
-+ pbn_xircom_combo,
-+
-+ pbn_siig10x_0,
-+ pbn_siig10x_1,
-+ pbn_siig10x_2,
-+ pbn_siig10x_4,
-+ pbn_siig20x_0,
-+ pbn_siig20x_2,
-+ pbn_siig20x_4,
-+
-+ pbn_computone_4,
-+ pbn_computone_6,
-+ pbn_computone_8,
-+};
-+
-+static struct pci_board pci_boards[] __devinitdata = {
-+ /*
-+ * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-+ * Offset to get to next UART's registers,
-+ * Register shift to use for memory-mapped I/O,
-+ * Initialization function, first UART offset
-+ */
-+
-+ /* Generic serial board, pbn_b0_1_115200, pbn_default */
-+ { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
-+ pbn_default */
-+
-+ { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
-+ { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
-+
-+ { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
-+ { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
-+ { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
-+
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
-+
-+ { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
-+ { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
-+ { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
-+ { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
-+
-+ { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
-+ { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
-+ { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
-+
-+ { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
-+ { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
-+ { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
-+
-+ { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
-+ { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
-+ { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
-+ { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
-+ { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
-+ { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
-+
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
-+
-+ { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
-+ 0x400, 7, pci_plx9050_fn },
-+ { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
-+ 0x20, 2, pci_plx9050_fn, 0x03 },
-+ /* This board uses the size of PCI Base region 0 to
-+ * signal now many ports are available */
-+ { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
-+ { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
-+ 0, 0, pci_timedia_fn },
-+ /* EKF addition for i960 Boards form EKF with serial port */
-+ { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
-+ 8<<2, 2, pci_inteli960ni_fn, 0x10000},
-+ { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
-+ 1, 458333, 0, 0, 0, 0x20178 },
-+#ifdef CONFIG_DDB5074
-+ /*
-+ * NEC Vrc-5074 (Nile 4) builtin UART.
-+ * Conditionally compiled in since this is a motherboard device.
-+ */
-+ { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
-+ 64, 3, NULL, 0x300 },
-+#endif
-+#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */
-+ { SPCI_FL_BASE3, 8, 115200, 8 },
-+#endif
-+ { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
-+ 0, 0, pci_xircom_fn },
-+
-+ { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
-+ 0, 0, pci_siig10x_fn },
-+ { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
-+ 0, 0, pci_siig20x_fn },
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
-+ 0, 0, pci_siig20x_fn },
-+ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
-+ 0, 0, pci_siig20x_fn },
-+
-+ { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
-+ 0x40, 2, NULL, 0x200 },
-+ { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
-+ 0x40, 2, NULL, 0x200 },
-+ { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
-+ 0x40, 2, NULL, 0x200 },
-+};
-+
-+/*
-+ * Given a complete unknown PCI device, try to use some heuristics to
-+ * guess what the configuration might be, based on the pitiful PCI
-+ * serial specs. Returns 0 on success, 1 on failure.
-+ */
-+static int __devinit serial_pci_guess_board(struct pci_dev *dev,
-+ struct pci_board *board)
-+{
-+ int num_iomem = 0, num_port = 0, first_port = -1;
-+ int i;
-+
-+ /*
-+ * If it is not a communications device or the programming
-+ * interface is greater than 6, give up.
-+ *
-+ * (Should we try to make guesses for multiport serial devices
-+ * later?)
-+ */
-+ if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
-+ ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
-+ (dev->class & 0xff) > 6)
-+ return 1;
-+
-+ for (i=0; i < 6; i++) {
-+ if (IS_PCI_REGION_IOPORT(dev, i)) {
-+ num_port++;
-+ if (first_port == -1)
-+ first_port = i;
-+ }
-+ if (IS_PCI_REGION_IOMEM(dev, i))
-+ num_iomem++;
-+ }
-+
-+ /*
-+ * If there is 1 or 0 iomem regions, and exactly one port, use
-+ * it.
-+ */
-+ if (num_iomem <= 1 && num_port == 1) {
-+ board->flags = first_port;
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+/*
-+ * return -1 to refuse
-+ */
-+static int pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
-+{
-+ struct serial_private *priv;
-+ struct pci_board *board, tmp;
-+ struct serial_struct serial_req;
-+ int base_baud, rc, k;
-+
-+ board = &pci_boards[ent->driver_data];
-+
-+ rc = pci_enable_device(dev);
-+ if (rc)
-+ return rc;
-+
-+ if (ent->driver_data == pbn_default &&
-+ serial_pci_guess_board(dev, board))
-+ return -ENODEV;
-+ else if (serial_pci_guess_board(dev, &tmp) == 0) {
-+ printk(KERN_INFO "Redundant entry in serial pci_table. "
-+ "Please send the output of\n"
-+ "lspci -vv, this message (%d,%d,%d,%d)\n"
-+ "and the manufacturer and name of "
-+ "serial board or modem board\n"
-+ "to serial-pci-info@lists.sourceforge.net.\n",
-+ dev->vendor, dev->device,
-+ pci_get_subvendor(dev), pci_get_subdevice(dev));
-+ }
-+
-+
-+ priv = kmalloc(sizeof(struct serial_private) +
-+ sizeof(unsigned int) * board->num_ports,
-+ GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ /*
-+ * Run the initialization function, if any
-+ */
-+ if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) {
-+ kfree(priv);
-+ return -ENODEV;
-+ }
-+
-+ base_baud = board->base_baud;
-+ if (!base_baud)
-+ base_baud = BASE_BAUD;
-+ memset(&serial_req, 0, sizeof(serial_req));
-+ for (k=0; k < board->num_ports; k++) {
-+ serial_req.irq = get_pci_irq(dev, board, k);
-+ if (get_pci_port(dev, board, &serial_req, k))
-+ break;
-+#ifdef SERIAL_DEBUG_PCI
-+ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
-+ serial_req.port, serial_req.irq, serial_req.io_type);
-+#endif
-+ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-+ serial_req.baud_base = base_baud;
-+ priv->line[k] = register_serial(&serial_req);
-+ if (priv->line[k] < 0)
-+ break;
-+ }
-+
-+ priv->board = board;
-+ priv->nr = k;
-+
-+ pci_set_drvdata(dev, priv);
-+
-+ return 0;
-+}
-+
-+static void pci_remove_one(struct pci_dev *dev)
-+{
-+ struct serial_private *priv = pci_get_drvdata(dev);
-+ int i;
-+
-+ pci_set_drvdata(dev, NULL);
-+
-+ for (i = 0; i < priv->nr; i++)
-+ unregister_serial(priv->line[i]);
-+
-+ priv->board->init_fn(dev, priv->board, 0);
-+
-+ kfree(priv);
-+}
-+
-+static struct pci_device_id serial_pci_tbl[] __devinitdata = {
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-+ pbn_b1_8_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-+ pbn_b1_4_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-+ pbn_b1_2_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
-+ pbn_b1_8_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
-+ pbn_b1_4_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
-+ pbn_b1_2_1382400 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
-+ pbn_b1_4_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
-+ pbn_b1_4_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
-+ pbn_b1_2_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
-+ pbn_b1_8_921600 },
-+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
-+ PCI_SUBVENDOR_ID_CONNECT_TECH,
-+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
-+ pbn_b1_4_921600 },
-+
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_1_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_4_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_4_115200 },
-+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_8_115200 },
-+
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_921600 },
-+ /* VScom SPCOM800, from sl@s.pl */
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_8_921600 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_4_921600 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_KEYSPAN,
-+ PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
-+ pbn_panacom },
-+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_panacom4 },
-+ { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_panacom2 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
-+ pbn_b2_4_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
-+ pbn_b2_8_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
-+ pbn_b2_16_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
-+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
-+ pbn_b2_16_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-+ PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
-+ pbn_b2_4_460800 },
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
-+ PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
-+ pbn_b2_8_460800 },
-+ /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
-+ /* (Exoray@isys.ca) */
-+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
-+ 0x10b5, 0x106a, 0, 0,
-+ pbn_plx_romulus },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_4_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_2_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_8_115200 },
-+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_8_115200 },
-+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
-+ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_115200 },
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_2_115200 },
-+
-+ /* Digitan DS560-558, from jimd@esoft.com */
-+ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b1_1_115200 },
-+
-+ /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
-+ { PCI_VENDOR_ID_USR, 0x1008,
-+ PCI_ANY_ID, PCI_ANY_ID, },
-+
-+ /* Titan Electronic cards */
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_1_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_2_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_4_921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE1, 1, 921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-+ /* The 400L and 800L have a custom hack in get_pci_port */
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE_TABLE, 4, 921600 },
-+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
-+ PCI_ANY_ID, PCI_ANY_ID,
-+ SPCI_FL_BASE_TABLE, 8, 921600 },
-+
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_1 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig10x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_0 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_2 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_siig20x_4 },
-+
-+ /* Computone devices submitted by Doug McNash dmcnash@computone.com */
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
-+ 0, 0, pbn_computone_4 },
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
-+ 0, 0, pbn_computone_8 },
-+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
-+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
-+ 0, 0, pbn_computone_6 },
-+
-+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
-+ { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
-+ PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
-+
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_2_460800 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_1_115200 },
-+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b0_bt_1_460800 },
-+
-+ /* RAStel 2 port modem, gerg@moreton.com.au */
-+ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_b2_bt_2_115200 },
-+
-+ /* EKF addition for i960 Boards form EKF with serial port */
-+ { PCI_VENDOR_ID_INTEL, 0x1960,
-+ 0xE4BF, PCI_ANY_ID, 0, 0,
-+ pbn_intel_i960 },
-+
-+ /* Xircom Cardbus/Ethernet combos */
-+ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_xircom_combo },
-+
-+ /*
-+ * Untested PCI modems, sent in from various folks...
-+ */
-+
-+ /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
-+ { PCI_VENDOR_ID_ROCKWELL, 0x1004,
-+ 0x1048, 0x1500, 0, 0,
-+ pbn_b1_1_115200 },
-+
-+ { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-+ 0xFF00, 0, 0, 0,
-+ pbn_sgi_ioc3 },
-+
-+#ifdef CONFIG_DDB5074
-+ /*
-+ * NEC Vrc-5074 (Nile 4) builtin UART.
-+ * Conditionally compiled in since this is a motherboard device.
-+ */
-+ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_nec_nile4 },
-+#endif
-+
-+#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */
-+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-+ pbn_dci_pccom8 },
-+#endif
-+
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
-+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, },
-+ { 0, }
-+};
-+
-+static struct pci_driver serial_pci_driver = {
-+ name: "serial",
-+ probe: pci_init_one,
-+ remove: pci_remove_one,
-+ id_table: serial_pci_tbl,
-+};
-+
-+static int __init serial8250_pci_init(void)
-+{
-+ return pci_module_init(&serial_pci_driver);
-+}
-+
-+static void __exit serial8250_pci_exit(void)
-+{
-+ pci_unregister_driver(&serial_pci_driver);
-+}
-+
-+module_init(serial8250_pci_init);
-+module_exit(serial8250_pci_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-+MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
---- /dev/null
-+++ linux-2.4.27/drivers/serial/8250_pnp.c
-@@ -0,0 +1,553 @@
-+/*
-+ * linux/drivers/char/serial_8250_pnp.c
-+ *
-+ * Probe module for 8250/16550-type ISAPNP serial ports.
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * $Id: 8250_pnp.c,v 1.3.2.1 2002/10/24 09:53:25 rmk Exp $
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/isapnp.h>
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/serial.h>
-+#include <linux/serialP.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/byteorder.h>
-+#include <asm/serial.h>
-+
-+#include "8250.h"
-+
-+static struct serial_state rs_table[] = { };
-+#define NR_PORTS 0
-+
-+struct pnpbios_device_id
-+{
-+ char id[8];
-+ unsigned long driver_data;
-+};
-+
-+static const struct pnpbios_device_id pnp_dev_table[] = {
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "AAC000F", 0 },
-+ /* Anchor Datacomm BV */
-+ /* SXPro 144 External Data Fax Modem Plug & Play */
-+ { "ADC0001", 0 },
-+ /* SXPro 288 External Data Fax Modem Plug & Play */
-+ { "ADC0002", 0 },
-+ /* Rockwell 56K ACF II Fax+Data+Voice Modem */
-+ { "AKY1021", SPCI_FL_NO_SHIRQ },
-+ /* AZT3005 PnP SOUND DEVICE */
-+ { "AZT4001", 0 },
-+ /* Best Data Products Inc. Smart One 336F PnP Modem */
-+ { "BDP3336", 0 },
-+ /* Boca Research */
-+ /* Boca Complete Ofc Communicator 14.4 Data-FAX */
-+ { "BRI0A49", 0 },
-+ /* Boca Research 33,600 ACF Modem */
-+ { "BRI1400", 0 },
-+ /* Boca 33.6 Kbps Internal FD34FSVD */
-+ { "BRI3400", 0 },
-+ /* Boca 33.6 Kbps Internal FD34FSVD */
-+ { "BRI0A49", 0 },
-+ /* Best Data Products Inc. Smart One 336F PnP Modem */
-+ { "BDP3336", 0 },
-+ /* Computer Peripherals Inc */
-+ /* EuroViVa CommCenter-33.6 SP PnP */
-+ { "CPI4050", 0 },
-+ /* Creative Labs */
-+ /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
-+ { "CTL3001", 0 },
-+ /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
-+ { "CTL3011", 0 },
-+ /* Creative */
-+ /* Creative Modem Blaster Flash56 DI5601-1 */
-+ { "DMB1032", 0 },
-+ /* Creative Modem Blaster V.90 DI5660 */
-+ { "DMB2001", 0 },
-+ /* FUJITSU */
-+ /* Fujitsu 33600 PnP-I2 R Plug & Play */
-+ { "FUJ0202", 0 },
-+ /* Fujitsu FMV-FX431 Plug & Play */
-+ { "FUJ0205", 0 },
-+ /* Fujitsu 33600 PnP-I4 R Plug & Play */
-+ { "FUJ0206", 0 },
-+ /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
-+ { "FUJ0209", 0 },
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "GVC000F", 0 },
-+ /* Hayes */
-+ /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
-+ { "HAY0001", 0 },
-+ /* Hayes Optima 336 V.34 + FAX + Voice PnP */
-+ { "HAY000C", 0 },
-+ /* Hayes Optima 336B V.34 + FAX + Voice PnP */
-+ { "HAY000D", 0 },
-+ /* Hayes Accura 56K Ext Fax Modem PnP */
-+ { "HAY5670", 0 },
-+ /* Hayes Accura 56K Ext Fax Modem PnP */
-+ { "HAY5674", 0 },
-+ /* Hayes Accura 56K Fax Modem PnP */
-+ { "HAY5675", 0 },
-+ /* Hayes 288, V.34 + FAX */
-+ { "HAYF000", 0 },
-+ /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
-+ { "HAYF001", 0 },
-+ /* IBM */
-+ /* IBM Thinkpad 701 Internal Modem Voice */
-+ { "IBM0033", 0 },
-+ /* Intertex */
-+ /* Intertex 28k8 33k6 Voice EXT PnP */
-+ { "IXDC801", 0 },
-+ /* Intertex 33k6 56k Voice EXT PnP */
-+ { "IXDC901", 0 },
-+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
-+ { "IXDD801", 0 },
-+ /* Intertex 33k6 56k Voice SP EXT PnP */
-+ { "IXDD901", 0 },
-+ /* Intertex 28k8 33k6 Voice SP INT PnP */
-+ { "IXDF401", 0 },
-+ /* Intertex 28k8 33k6 Voice SP EXT PnP */
-+ { "IXDF801", 0 },
-+ /* Intertex 33k6 56k Voice SP EXT PnP */
-+ { "IXDF901", 0 },
-+ /* Kortex International */
-+ /* KORTEX 28800 Externe PnP */
-+ { "KOR4522", 0 },
-+ /* KXPro 33.6 Vocal ASVD PnP */
-+ { "KORF661", 0 },
-+ /* Lasat */
-+ /* LASAT Internet 33600 PnP */
-+ { "LAS4040", 0 },
-+ /* Lasat Safire 560 PnP */
-+ { "LAS4540", 0 },
-+ /* Lasat Safire 336 PnP */
-+ { "LAS5440", 0 },
-+ /* Microcom, Inc. */
-+ /* Microcom TravelPorte FAST V.34 Plug & Play */
-+ { "MNP0281", 0 },
-+ /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
-+ { "MNP0336", 0 },
-+ /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
-+ { "MNP0339", 0 },
-+ /* Microcom DeskPorte 28.8P Plug & Play */
-+ { "MNP0342", 0 },
-+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-+ { "MNP0500", 0 },
-+ /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
-+ { "MNP0501", 0 },
-+ /* Microcom DeskPorte 28.8S Internal Plug & Play */
-+ { "MNP0502", 0 },
-+ /* Motorola */
-+ /* Motorola BitSURFR Plug & Play */
-+ { "MOT1105", 0 },
-+ /* Motorola TA210 Plug & Play */
-+ { "MOT1111", 0 },
-+ /* Motorola HMTA 200 (ISDN) Plug & Play */
-+ { "MOT1114", 0 },
-+ /* Motorola BitSURFR Plug & Play */
-+ { "MOT1115", 0 },
-+ /* Motorola Lifestyle 28.8 Internal */
-+ { "MOT1190", 0 },
-+ /* Motorola V.3400 Plug & Play */
-+ { "MOT1501", 0 },
-+ /* Motorola Lifestyle 28.8 V.34 Plug & Play */
-+ { "MOT1502", 0 },
-+ /* Motorola Power 28.8 V.34 Plug & Play */
-+ { "MOT1505", 0 },
-+ /* Motorola ModemSURFR External 28.8 Plug & Play */
-+ { "MOT1509", 0 },
-+ /* Motorola Premier 33.6 Desktop Plug & Play */
-+ { "MOT150A", 0 },
-+ /* Motorola VoiceSURFR 56K External PnP */
-+ { "MOT150F", 0 },
-+ /* Motorola ModemSURFR 56K External PnP */
-+ { "MOT1510", 0 },
-+ /* Motorola ModemSURFR 56K Internal PnP */
-+ { "MOT1550", 0 },
-+ /* Motorola ModemSURFR Internal 28.8 Plug & Play */
-+ { "MOT1560", 0 },
-+ /* Motorola Premier 33.6 Internal Plug & Play */
-+ { "MOT1580", 0 },
-+ /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
-+ { "MOT15B0", 0 },
-+ /* Motorola VoiceSURFR 56K Internal PnP */
-+ { "MOT15F0", 0 },
-+ /* Com 1 */
-+ /* Deskline K56 Phone System PnP */
-+ { "MVX00A1", 0 },
-+ /* PC Rider K56 Phone System PnP */
-+ { "MVX00F2", 0 },
-+ /* Pace 56 Voice Internal Plug & Play Modem */
-+ { "PMC2430", 0 },
-+ /* Generic */
-+ /* Generic standard PC COM port */
-+ { "PNP0500", 0 },
-+ /* Generic 16550A-compatible COM port */
-+ { "PNP0501", 0 },
-+ /* Compaq 14400 Modem */
-+ { "PNPC000", 0 },
-+ /* Compaq 2400/9600 Modem */
-+ { "PNPC001", 0 },
-+ /* Dial-Up Networking Serial Cable between 2 PCs */
-+ { "PNPC031", 0 },
-+ /* Dial-Up Networking Parallel Cable between 2 PCs */
-+ { "PNPC032", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC100", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC101", 0 },
-+ /* Standard 28800 bps Modem*/
-+ { "PNPC102", 0 },
-+ /* Standard Modem*/
-+ { "PNPC103", 0 },
-+ /* Standard 9600 bps Modem*/
-+ { "PNPC104", 0 },
-+ /* Standard 14400 bps Modem*/
-+ { "PNPC105", 0 },
-+ /* Standard 28800 bps Modem*/
-+ { "PNPC106", 0 },
-+ /* Standard Modem */
-+ { "PNPC107", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC108", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC109", 0 },
-+ /* Standard 28800 bps Modem */
-+ { "PNPC10A", 0 },
-+ /* Standard Modem */
-+ { "PNPC10B", 0 },
-+ /* Standard 9600 bps Modem */
-+ { "PNPC10C", 0 },
-+ /* Standard 14400 bps Modem */
-+ { "PNPC10D", 0 },
-+ /* Standard 28800 bps Modem */
-+ { "PNPC10E", 0 },
-+ /* Standard Modem */
-+ { "PNPC10F", 0 },
-+ /* Standard PCMCIA Card Modem */
-+ { "PNP2000", 0 },
-+ /* Rockwell */
-+ /* Modular Technology */
-+ /* Rockwell 33.6 DPF Internal PnP */
-+ /* Modular Technology 33.6 Internal PnP */
-+ { "ROK0030", 0 },
-+ /* Kortex International */
-+ /* KORTEX 14400 Externe PnP */
-+ { "ROK0100", 0 },
-+ /* Viking Components, Inc */
-+ /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
-+ { "ROK4920", 0 },
-+ /* Rockwell */
-+ /* British Telecom */
-+ /* Modular Technology */
-+ /* Rockwell 33.6 DPF External PnP */
-+ /* BT Prologue 33.6 External PnP */
-+ /* Modular Technology 33.6 External PnP */
-+ { "RSS00A0", 0 },
-+ /* Viking 56K FAX INT */
-+ { "RSS0262", 0 },
-+ /* SupraExpress 28.8 Data/Fax PnP modem */
-+ { "SUP1310", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1421", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1590", 0 },
-+ /* SupraExpress 33.6 Data/Fax PnP modem */
-+ { "SUP1760", 0 },
-+ /* Phoebe Micro */
-+ /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
-+ { "TEX0011", 0 },
-+ /* Archtek America Corp. */
-+ /* Archtek SmartLink Modem 3334BT Plug & Play */
-+ { "UAC000F", 0 },
-+ /* 3Com Corp. */
-+ /* Gateway Telepath IIvi 33.6 */
-+ { "USR0000", 0 },
-+ /* Sportster Vi 14.4 PnP FAX Voicemail */
-+ { "USR0004", 0 },
-+ /* U.S. Robotics 33.6K Voice INT PnP */
-+ { "USR0006", 0 },
-+ /* U.S. Robotics 33.6K Voice EXT PnP */
-+ { "USR0007", 0 },
-+ /* U.S. Robotics 33.6K Voice INT PnP */
-+ { "USR2002", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR2070", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP */
-+ { "USR2080", 0 },
-+ /* U.S. Robotics 56K FAX INT */
-+ { "USR3031", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR3070", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP */
-+ { "USR3080", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP */
-+ { "USR3090", 0 },
-+ /* U.S. Robotics 56K Message */
-+ { "USR9100", 0 },
-+ /* U.S. Robotics 56K FAX EXT PnP*/
-+ { "USR9160", 0 },
-+ /* U.S. Robotics 56K FAX INT PnP*/
-+ { "USR9170", 0 },
-+ /* U.S. Robotics 56K Voice EXT PnP*/
-+ { "USR9180", 0 },
-+ /* U.S. Robotics 56K Voice INT PnP*/
-+ { "USR9190", 0 },
-+ { "", 0 }
-+};
-+
-+static void inline avoid_irq_share(struct pci_dev *dev)
-+{
-+ int i, map = 0x1FF8;
-+ struct serial_state *state = rs_table;
-+ struct isapnp_irq *irq;
-+ struct isapnp_resources *res = dev->sysdata;
-+
-+ for (i = 0; i < NR_PORTS; i++) {
-+ if (state->type != PORT_UNKNOWN)
-+ clear_bit(state->irq, &map);
-+ state++;
-+ }
-+
-+ for ( ; res; res = res->alt)
-+ for(irq = res->irq; irq; irq = irq->next)
-+ irq->map = map;
-+}
-+
-+static char *modem_names[] __devinitdata = {
-+ "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
-+ "56K", "56k", "K56", "33.6", "28.8", "14.4",
-+ "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
-+ "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
-+};
-+
-+static int __devinit check_name(char *name)
-+{
-+ char **tmp;
-+
-+ for (tmp = modem_names; *tmp; tmp++)
-+ if (strstr(name, *tmp))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static int inline check_compatible_id(struct pci_dev *dev)
-+{
-+ int i;
-+ for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
-+ if ((dev->vendor_compatible[i] ==
-+ ISAPNP_VENDOR('P', 'N', 'P')) &&
-+ (swab16(dev->device_compatible[i]) >= 0xc000) &&
-+ (swab16(dev->device_compatible[i]) <= 0xdfff))
-+ return 0;
-+ return 1;
-+}
-+
-+/*
-+ * Given a complete unknown ISA PnP device, try to use some heuristics to
-+ * detect modems. Currently use such heuristic set:
-+ * - dev->name or dev->bus->name must contain "modem" substring;
-+ * - device must have only one IO region (8 byte long) with base adress
-+ * 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
-+ *
-+ * Such detection looks very ugly, but can detect at least some of numerous
-+ * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
-+ * table.
-+ */
-+static int serial_pnp_guess_board(struct pci_dev *dev, int *flags)
-+{
-+ struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
-+ struct isapnp_resources *resa;
-+
-+ if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
-+ !(check_compatible_id(dev)))
-+ return -ENODEV;
-+
-+ if (!res || res->next)
-+ return -ENODEV;
-+
-+ for (resa = res->alt; resa; resa = resa->alt) {
-+ struct isapnp_port *port;
-+ for (port = res->port; port; port = port->next)
-+ if ((port->size == 8) &&
-+ ((port->min == 0x2f8) ||
-+ (port->min == 0x3f8) ||
-+ (port->min == 0x2e8) ||
-+ (port->min == 0x3e8)))
-+ return 0;
-+ }
-+
-+ return -ENODEV;
-+}
-+
-+static int
-+pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent,
-+ char *slot_name)
-+{
-+ struct serial_struct serial_req;
-+ int ret, line, flags = ent ? ent->driver_data : 0;
-+
-+ if (!ent) {
-+ ret = serial_pnp_guess_board(dev, &flags);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (dev->prepare(dev) < 0) {
-+ printk("serial: PNP device '%s' prepare failed\n",
-+ slot_name);
-+ return -ENODEV;
-+ }
-+
-+ if (dev->active)
-+ return -ENODEV;
-+
-+ if (flags & SPCI_FL_NO_SHIRQ)
-+ avoid_irq_share(dev);
-+
-+ if (dev->activate(dev) < 0) {
-+ printk("serial: PNP device '%s' activate failed\n",
-+ slot_name);
-+ return -ENODEV;
-+ }
-+
-+ memset(&serial_req, 0, sizeof(serial_req));
-+ serial_req.irq = dev->irq_resource[0].start;
-+ serial_req.port = pci_resource_start(dev, 0);
-+ if (HIGH_BITS_OFFSET)
-+ serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET;
-+
-+#ifdef SERIAL_DEBUG_PCI
-+ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
-+ serial_req.port, serial_req.irq, serial_req.io_type);
-+#endif
-+
-+ serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-+ serial_req.baud_base = 115200;
-+ line = register_serial(&serial_req);
-+
-+ if (line >= 0) {
-+ pci_set_drvdata(dev, (void *)(line + 1));
-+
-+ /*
-+ * Public health warning: remove this once the 2.5
-+ * pnpbios_module_init() stuff is incorporated.
-+ */
-+ dev->driver = (void *)pnp_dev_table;
-+ } else
-+ dev->deactivate(dev);
-+
-+ return line >= 0 ? 0 : -ENODEV;
-+}
-+
-+static void pnp_remove_one(struct pci_dev *dev)
-+{
-+ int line = (int)pci_get_drvdata(dev);
-+
-+ if (line) {
-+ pci_set_drvdata(dev, NULL);
-+
-+ unregister_serial(line - 1);
-+
-+ dev->deactivate(dev);
-+ }
-+}
-+
-+static char hex[] = "0123456789ABCDEF";
-+
-+/*
-+ * This function should vanish when 2.5 comes around and
-+ * we have pnpbios_module_init()
-+ */
-+static void pnp_init(void)
-+{
-+ const struct pnpbios_device_id *id;
-+ struct pci_dev *dev = NULL;
-+
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Entered probe_serial_pnp()\n");
-+#endif
-+
-+ isapnp_for_each_dev(dev) {
-+ char slot_name[8];
-+ u32 pnpid;
-+
-+ if (dev->active)
-+ continue;
-+
-+ pnpid = dev->vendor << 16 | dev->device;
-+ pnpid = cpu_to_le32(pnpid);
-+
-+#define HEX(id,a) hex[((id)>>a) & 15]
-+#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-+ slot_name[0] = CHAR(pnpid, 26);
-+ slot_name[1] = CHAR(pnpid, 21);
-+ slot_name[2] = CHAR(pnpid, 16);
-+ slot_name[3] = HEX(pnpid, 12);
-+ slot_name[4] = HEX(pnpid, 8);
-+ slot_name[5] = HEX(pnpid, 4);
-+ slot_name[6] = HEX(pnpid, 0);
-+ slot_name[7] = '\0';
-+
-+ for (id = pnp_dev_table; id->id[0]; id++)
-+ if (memcmp(id->id, slot_name, 7) == 0)
-+ break;
-+
-+ if (id->id[0])
-+ pnp_init_one(dev, id, slot_name);
-+ else
-+ pnp_init_one(dev, NULL, slot_name);
-+ }
-+
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Leaving probe_serial_pnp() (probe finished)\n");
-+#endif
-+}
-+
-+static int __init serial8250_pnp_init(void)
-+{
-+ if (!isapnp_present()) {
-+#ifdef SERIAL_DEBUG_PNP
-+ printk("Leaving probe_serial_pnp() (no isapnp)\n");
-+#endif
-+ return -ENODEV;
-+ }
-+ pnp_init();
-+ return 0;
-+}
-+
-+static void __exit serial8250_pnp_exit(void)
-+{
-+ struct pci_dev *dev = NULL;
-+
-+ isapnp_for_each_dev(dev) {
-+ if (dev->driver != (void *)pnp_dev_table)
-+ continue;
-+ pnp_remove_one(dev);
-+ }
-+}
-+
-+module_init(serial8250_pnp_init);
-+module_exit(serial8250_pnp_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
-+MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/serial/Config.in
-@@ -0,0 +1,91 @@
-+#
-+# Serial device configuration
-+#
-+# $Id: Config.in,v 1.4 2001/10/12 15:46:58 rmk Exp $
-+#
-+mainmenu_option next_comment
-+comment 'Serial drivers'
-+
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ # I don't have this in my tree yet.
-+ dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN
-+ dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN
-+ if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then
-+ int ' Default Anakin serial baudrate' CONFIG_ANAKIN_DEFAULT_BAUDRATE 9600
-+ fi
-+
-+ dep_tristate 'ARM AMBA serial port support' CONFIG_SERIAL_AMBA $CONFIG_ARCH_INTEGRATOR
-+ dep_bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE $CONFIG_SERIAL_AMBA
-+ if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then
-+ define_bool CONFIG_SERIAL_INTEGRATOR y
-+ fi
-+
-+ dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X
-+ dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X
-+
-+ dep_bool 'DC21285 serial port support' CONFIG_SERIAL_21285 $CONFIG_FOOTBRIDGE
-+ dep_bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD $CONFIG_SERIAL_21285 $CONFIG_OBSOLETE
-+ dep_bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE $CONFIG_SERIAL_21285
-+
-+ dep_bool 'Excalibur serial port (uart00) support' CONFIG_SERIAL_UART00 $CONFIG_ARCH_CAMELOT
-+ dep_bool ' Support for console on Excalibur serial port' CONFIG_SERIAL_UART00_CONSOLE $CONFIG_SERIAL_UART00
-+
-+
-+ dep_bool 'SA1100 serial port support' CONFIG_SERIAL_SA1100 $CONFIG_ARCH_SA1100
-+ dep_bool ' Console on SA1100 serial port' CONFIG_SERIAL_SA1100_CONSOLE $CONFIG_SERIAL_SA1100
-+ if [ "$CONFIG_SERIAL_SA1100" = "y" ]; then
-+ int ' Default SA1100 serial baudrate' CONFIG_SA1100_DEFAULT_BAUDRATE 9600
-+ fi
-+
-+ dep_tristate 'ARM Omaha serial port support' CONFIG_SERIAL_OMAHA $CONFIG_ARCH_OMAHA
-+ dep_bool ' Support for console on Omaha serial port' CONFIG_SERIAL_OMAHA_CONSOLE $CONFIG_SERIAL_OMAHA
-+
-+ dep_tristate 'AT91RM9200 serial port support' CONFIG_SERIAL_AT91 $CONFIG_ARCH_AT91RM9200
-+ dep_bool ' Console on AT91RM9200 serial port' CONFIG_SERIAL_AT91_CONSOLE $CONFIG_SERIAL_AT91
-+
-+fi
-+#
-+# The new 8250/16550 serial drivers
-+dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
-+dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL
-+
-+dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250
-+dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support for sharing serial interrupts' CONFIG_SERIAL_8250_SHARE_IRQ $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_8250_DETECT_IRQ $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support special multiport boards' CONFIG_SERIAL_8250_MULTIPORT $CONFIG_SERIAL_8250_EXTENDED
-+dep_bool ' Support Bell Technologies HUB6 card' CONFIG_SERIAL_8250_HUB6 $CONFIG_SERIAL_8250_EXTENDED
-+
-+if [ "$CONFIG_SERIAL_AMBA" = "y" -o \
-+ "$CONFIG_SERIAL_CLPS711X" = "y" -o \
-+ "$CONFIG_SERIAL_SA1100" = "y" -o \
-+ "$CONFIG_SERIAL_ANAKIN" = "y" -o \
-+ "$CONFIG_SERIAL_UART00" = "y" -o \
-+ "$CONFIG_SERIAL_8250" = "y" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "y" -o \
-+ "$CONFIG_SERIAL_AT91" = "y" ]; then
-+ define_bool CONFIG_SERIAL_CORE y
-+else
-+ if [ "$CONFIG_SERIAL_AMBA" = "m" -o \
-+ "$CONFIG_SERIAL_CLPS711X" = "m" -o \
-+ "$CONFIG_SERIAL_SA1100" = "m" -o \
-+ "$CONFIG_SERIAL_ANAKIN" = "m" -o \
-+ "$CONFIG_SERIAL_UART00" = "m" -o \
-+ "$CONFIG_SERIAL_8250" = "m" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "m" -o \
-+ "$CONFIG_SERIAL_AT91" = "m" ]; then
-+ define_bool CONFIG_SERIAL_CORE m
-+ fi
-+fi
-+if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_UART00_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_8250_CONSOLE" = "y" -o \
-+ "$CONFIG_SERIAL_OMAHA" = "y" -o \
-+ "$CONFIG_SERIAL_AT91_CONSOLE" = "y" ]; then
-+ define_bool CONFIG_SERIAL_CORE_CONSOLE y
-+fi
-+
-+endmenu
---- /dev/null
-+++ linux-2.4.27/drivers/serial/Makefile
-@@ -0,0 +1,39 @@
-+#
-+# Makefile for the kernel serial device drivers.
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definitions are now inherited from the
-+# parent makes..
-+#
-+# $Id: Makefile,v 1.2 2001/10/12 15:46:58 rmk Exp $
-+#
-+
-+O_TARGET := serial.o
-+
-+export-objs := core.o 8250.o
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+serial-8250-y :=
-+serial-8250-$(CONFIG_PCI) += 8250_pci.o
-+serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o
-+obj-$(CONFIG_SERIAL_CORE) += core.o
-+obj-$(CONFIG_SERIAL_21285) += 21285.o
-+obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
-+obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
-+obj-$(CONFIG_SERIAL_AMBA) += amba.o
-+obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
-+obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
-+obj-$(CONFIG_SERIAL_UART00) += uart00.o
-+obj-$(CONFIG_SERIAL_OMAHA) += omaha.o
-+obj-$(CONFIG_SERIAL_AT91US3) += at91us3.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+fastdep:
-+
---- /dev/null
-+++ linux-2.4.27/drivers/serial/amba.c
-@@ -0,0 +1,770 @@
-+/*
-+ * linux/drivers/char/serial_amba.c
-+ *
-+ * Driver for AMBA serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: amba.c,v 1.9.2.2 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ * This is a generic driver for ARM AMBA-type serial ports. They
-+ * have a lot of 16550-like features, but are not register compatable.
-+ * Note that although they do have CTS, DCD and DSR inputs, they do
-+ * not have an RI input, nor do they have DTR or RTS outputs. If
-+ * required, these have to be supplied via some other means (eg, GPIO)
-+ * and hooked into this driver.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/serial_amba.h>
-+
-+#define UART_NR 2
-+
-+#define SERIAL_AMBA_MAJOR 204
-+#define SERIAL_AMBA_MINOR 16
-+#define SERIAL_AMBA_NR UART_NR
-+
-+#define CALLOUT_AMBA_NAME "cuaam"
-+#define CALLOUT_AMBA_MAJOR 205
-+#define CALLOUT_AMBA_MINOR 16
-+#define CALLOUT_AMBA_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *amba_table[UART_NR];
-+static struct termios *amba_termios[UART_NR], *amba_termios_locked[UART_NR];
-+#ifdef SUPPORT_SYSRQ
-+static struct console amba_console;
-+#endif
-+
-+#define AMBA_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the AMBA UARTs
-+ */
-+#define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR)
-+#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR)
-+#define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR)
-+#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR)
-+#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR)
-+#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR)
-+#define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR)
-+#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR)
-+#define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L)
-+#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L)
-+#define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M)
-+#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M)
-+#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H)
-+#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H)
-+#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0)
-+#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0)
-+#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0)
-+
-+#define UART_DUMMY_RSR_RX 256
-+#define UART_PORT_SIZE 64
-+
-+/*
-+ * On the Integrator platform, the port RTS and DTR are provided by
-+ * bits in the following SC_CTRLS register bits:
-+ * RTS DTR
-+ * UART0 7 6
-+ * UART1 5 4
-+ */
-+#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
-+#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
-+
-+/*
-+ * We wrap our port structure around the generic uart_port.
-+ */
-+struct uart_amba_port {
-+ struct uart_port port;
-+ unsigned int dtr_mask;
-+ unsigned int rts_mask;
-+ unsigned int old_status;
-+};
-+
-+static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr &= ~AMBA_UARTCR_TIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr |= AMBA_UARTCR_TIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_stop_rx(struct uart_port *port)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void ambauart_enable_ms(struct uart_port *port)
-+{
-+ unsigned int cr;
-+
-+ cr = UART_GET_CR(port);
-+ cr |= AMBA_UARTCR_MSIE;
-+ UART_PUT_CR(port, cr);
-+}
-+
-+static void
-+#ifdef SUPPORT_SYSRQ
-+ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+#else
-+ambauart_rx_chars(struct uart_port *port)
-+#endif
-+{
-+ struct tty_struct *tty = port->info->tty;
-+ unsigned int status, ch, rsr, max_count = 256;
-+
-+ status = UART_GET_FR(port);
-+ while (UART_RX_DATA(status) && max_count--) {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-+ return;
-+ }
-+ }
-+
-+ ch = UART_GET_CHAR(port);
-+
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ port->icount.rx++;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
-+ if (rsr & AMBA_UARTRSR_ANY) {
-+ if (rsr & AMBA_UARTRSR_BE) {
-+ rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
-+ port->icount.brk++;
-+ if (uart_handle_break(port))
-+ goto ignore_char;
-+ } else if (rsr & AMBA_UARTRSR_PE)
-+ port->icount.parity++;
-+ else if (rsr & AMBA_UARTRSR_FE)
-+ port->icount.frame++;
-+ if (rsr & AMBA_UARTRSR_OE)
-+ port->icount.overrun++;
-+
-+ rsr &= port->read_status_mask;
-+
-+ if (rsr & AMBA_UARTRSR_BE)
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ else if (rsr & AMBA_UARTRSR_PE)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (rsr & AMBA_UARTRSR_FE)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ if ((rsr & port->ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((rsr & AMBA_UARTRSR_OE) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character
-+ */
-+ *tty->flip.char_buf_ptr++ = 0;
-+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ status = UART_GET_FR(port);
-+ }
-+ tty_flip_buffer_push(tty);
-+ return;
-+}
-+
-+static void ambauart_tx_chars(struct uart_port *port)
-+{
-+ struct circ_buf *xmit = &port->info->xmit;
-+ int count;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ ambauart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ ambauart_stop_tx(port, 0);
-+}
-+
-+static void ambauart_modem_status(struct uart_port *port)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ unsigned int status, delta;
-+
-+ UART_PUT_ICR(&uap->port, 0);
-+
-+ status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
-+
-+ delta = status ^ uap->old_status;
-+ uap->old_status = status;
-+
-+ if (!delta)
-+ return;
-+
-+ if (delta & AMBA_UARTFR_DCD)
-+ uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD);
-+
-+ if (delta & AMBA_UARTFR_DSR)
-+ uap->port.icount.dsr++;
-+
-+ if (delta & AMBA_UARTFR_CTS)
-+ uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS);
-+
-+ wake_up_interruptible(&uap->port.info->delta_msr_wait);
-+}
-+
-+static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ do {
-+ if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS))
-+#ifdef SUPPORT_SYSRQ
-+ ambauart_rx_chars(port, regs);
-+#else
-+ ambauart_rx_chars(port);
-+#endif
-+ if (status & AMBA_UARTIIR_TIS)
-+ ambauart_tx_chars(port);
-+ if (status & AMBA_UARTIIR_MIS)
-+ ambauart_modem_status(port);
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS |
-+ AMBA_UARTIIR_TIS));
-+}
-+
-+static unsigned int ambauart_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int ambauart_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ status = UART_GET_FR(port);
-+ if (status & AMBA_UARTFR_DCD)
-+ result |= TIOCM_CAR;
-+ if (status & AMBA_UARTFR_DSR)
-+ result |= TIOCM_DSR;
-+ if (status & AMBA_UARTFR_CTS)
-+ result |= TIOCM_CTS;
-+
-+ return result;
-+}
-+
-+static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ unsigned int ctrls = 0, ctrlc = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ ctrlc |= uap->rts_mask;
-+ else
-+ ctrls |= uap->rts_mask;
-+
-+ if (mctrl & TIOCM_DTR)
-+ ctrlc |= uap->dtr_mask;
-+ else
-+ ctrls |= uap->dtr_mask;
-+
-+ __raw_writel(ctrls, SC_CTRLS);
-+ __raw_writel(ctrlc, SC_CTRLC);
-+}
-+
-+static void ambauart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned long flags;
-+ unsigned int lcr_h;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ lcr_h = UART_GET_LCRH(port);
-+ if (break_state == -1)
-+ lcr_h |= AMBA_UARTLCR_H_BRK;
-+ else
-+ lcr_h &= ~AMBA_UARTLCR_H_BRK;
-+ UART_PUT_LCRH(port, lcr_h);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static int ambauart_startup(struct uart_port *port)
-+{
-+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, ambauart_int, 0, "amba", port);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
-+
-+ /*
-+ * Finally, enable interrupts
-+ */
-+ UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE |
-+ AMBA_UARTCR_RTIE);
-+
-+ return 0;
-+}
-+
-+static void ambauart_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ UART_PUT_CR(port, 0);
-+
-+ /* disable break condition and fifos */
-+ UART_PUT_LCRH(port, UART_GET_LCRH(port) &
-+ ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN));
-+}
-+
-+static void ambauart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ unsigned int lcr_h, old_cr;
-+ unsigned long flags;
-+
-+#if DEBUG
-+ printk("ambauart_set_cflag(0x%x) called\n", cflag);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_5;
-+ break;
-+ case CS6:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_6;
-+ break;
-+ case CS7:
-+ lcr_h = AMBA_UARTLCR_H_WLEN_7;
-+ break;
-+ default: // CS8
-+ lcr_h = AMBA_UARTLCR_H_WLEN_8;
-+ break;
-+ }
-+ if (cflag & CSTOPB)
-+ lcr_h |= AMBA_UARTLCR_H_STP2;
-+ if (cflag & PARENB) {
-+ lcr_h |= AMBA_UARTLCR_H_PEN;
-+ if (!(cflag & PARODD))
-+ lcr_h |= AMBA_UARTLCR_H_EPS;
-+ }
-+ if (port->fifosize > 1)
-+ lcr_h |= AMBA_UARTLCR_H_FEN;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+
-+ port->read_status_mask = AMBA_UARTRSR_OE;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= AMBA_UARTRSR_BE;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE;
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= AMBA_UARTRSR_BE;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= AMBA_UARTRSR_OE;
-+ }
-+
-+ /*
-+ * Ignore all characters if CREAD is not set.
-+ */
-+ if ((cflag & CREAD) == 0)
-+ port->ignore_status_mask |= UART_DUMMY_RSR_RX;
-+
-+ old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE;
-+
-+ if (UART_ENABLE_MS(port, cflag))
-+ old_cr |= AMBA_UARTCR_MSIE;
-+
-+ UART_PUT_CR(port, 0);
-+
-+ /* Set baud rate */
-+ quot -= 1;
-+ UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
-+ UART_PUT_LCRL(port, (quot & 0xff));
-+
-+ /*
-+ * ----------v----------v----------v----------v-----
-+ * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
-+ * ----------^----------^----------^----------^-----
-+ */
-+ UART_PUT_LCRH(port, lcr_h);
-+ UART_PUT_CR(port, old_cr);
-+
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static const char *ambauart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_AMBA ? "AMBA" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void ambauart_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int ambauart_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba")
-+ != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void ambauart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_AMBA;
-+ ambauart_request_port(port);
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops amba_pops = {
-+ .tx_empty = ambauart_tx_empty,
-+ .set_mctrl = ambauart_set_mctrl,
-+ .get_mctrl = ambauart_get_mctrl,
-+ .stop_tx = ambauart_stop_tx,
-+ .start_tx = ambauart_start_tx,
-+ .stop_rx = ambauart_stop_rx,
-+ .enable_ms = ambauart_enable_ms,
-+ .break_ctl = ambauart_break_ctl,
-+ .startup = ambauart_startup,
-+ .shutdown = ambauart_shutdown,
-+ .change_speed = ambauart_change_speed,
-+ .type = ambauart_type,
-+ .release_port = ambauart_release_port,
-+ .request_port = ambauart_request_port,
-+ .config_port = ambauart_config_port,
-+ .verify_port = ambauart_verify_port,
-+};
-+
-+static struct uart_amba_port amba_ports[UART_NR] = {
-+ {
-+ .port = {
-+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
-+ .mapbase = INTEGRATOR_UART0_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UARTINT0,
-+ .uartclk = 14745600,
-+ .fifosize = 16,
-+ .ops = &amba_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ .line = 0,
-+ },
-+ .dtr_mask = 1 << 5,
-+ .rts_mask = 1 << 4,
-+ },
-+ {
-+ .port = {
-+ .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
-+ .mapbase = INTEGRATOR_UART1_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UARTINT1,
-+ .uartclk = 14745600,
-+ .fifosize = 16,
-+ .ops = &amba_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ .line = 1,
-+ },
-+ .dtr_mask = 1 << 7,
-+ .rts_mask = 1 << 6,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-+
-+static void ambauart_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct uart_port *port = &amba_ports[co->index].port;
-+ unsigned int status, old_cr;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+ old_cr = UART_GET_CR(port);
-+ UART_PUT_CR(port, AMBA_UARTCR_UARTEN);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the TCR
-+ */
-+ do {
-+ status = UART_GET_FR(port);
-+ } while (status & AMBA_UARTFR_BUSY);
-+ UART_PUT_CR(port, old_cr);
-+}
-+
-+static kdev_t ambauart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index);
-+}
-+
-+static void __init
-+ambauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) {
-+ unsigned int lcr_h, quot;
-+ lcr_h = UART_GET_LCRH(port);
-+
-+ *parity = 'n';
-+ if (lcr_h & AMBA_UARTLCR_H_PEN) {
-+ if (lcr_h & AMBA_UARTLCR_H_EPS)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7)
-+ *bits = 7;
-+ else
-+ *bits = 8;
-+
-+ quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
-+ *baud = port->uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init ambauart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index >= UART_NR)
-+ co->index = 0;
-+ port = &amba_ports[co->index].port;
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ ambauart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console amba_console = {
-+ .name = "ttyAM",
-+ .write = ambauart_console_write,
-+ .device = ambauart_console_device,
-+ .setup = ambauart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init ambauart_console_init(void)
-+{
-+ register_console(&amba_console);
-+}
-+
-+#define AMBA_CONSOLE &amba_console
-+#else
-+#define AMBA_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver amba_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_AMBA_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttyAM%d",
-+ .callout_name = "cuaam%d",
-+#else
-+ .normal_name = "ttyAM",
-+ .callout_name = "cuaam",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_AMBA_MAJOR,
-+ .callout_driver = &callout,
-+ .table = amba_table,
-+ .termios = amba_termios,
-+ .termios_locked = amba_termios_locked,
-+ .minor = SERIAL_AMBA_MINOR,
-+ .nr = UART_NR,
-+ .cons = AMBA_CONSOLE,
-+};
-+
-+static int __init ambauart_init(void)
-+{
-+ int ret;
-+
-+ ret = uart_register_driver(&amba_reg);
-+ if (ret == 0) {
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_add_one_port(&amba_reg, &amba_ports[i].port);
-+ }
-+ return ret;
-+}
-+
-+static void __exit ambauart_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&amba_reg, &amba_ports[i].port);
-+
-+ uart_unregister_driver(&amba_reg);
-+}
-+
-+module_init(ambauart_init);
-+module_exit(ambauart_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("ARM AMBA serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/serial/anakin.c
-@@ -0,0 +1,545 @@
-+/*
-+ * linux/drivers/char/serial_anakin.c
-+ *
-+ * Based on driver for AMBA serial ports, by ARM Limited,
-+ * Deep Blue Solutions Ltd., Linus Torvalds and Theodore Ts'o.
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * Copyright (C) 2001 Blue Mug, Inc. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 20-Apr-2001 TTC Created
-+ * 05-May-2001 W/TTC Updated for serial_core.c
-+ * 27-Jun-2001 jonm Minor changes; add mctrl support, switch to
-+ * SA_INTERRUPT. Works reliably now. No longer requires
-+ * changes to the serial_core API.
-+ *
-+ * $Id: anakin.c,v 1.5.2.2 2002/10/24 09:53:25 rmk Exp $
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/arch/serial_reg.h>
-+
-+#define UART_NR 5
-+
-+#define SERIAL_ANAKIN_NAME "ttyAN"
-+#define SERIAL_ANAKIN_MAJOR 204
-+#define SERIAL_ANAKIN_MINOR 32
-+
-+#define CALLOUT_ANAKIN_NAME "cuaan"
-+#define CALLOUT_ANAKIN_MAJOR 205
-+#define CALLOUT_ANAKIN_MINOR 32
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *anakin_table[UART_NR];
-+static struct termios *anakin_termios[UART_NR], *anakin_termios_locked[UART_NR];
-+static struct uart_state anakin_state[UART_NR];
-+static u_int txenable[NR_IRQS]; /* Software interrupt register */
-+
-+static inline unsigned int
-+anakin_in(struct uart_port *port, u_int offset)
-+{
-+ return __raw_readl(port->base + offset);
-+}
-+
-+static inline void
-+anakin_out(struct uart_port *port, u_int offset, unsigned int value)
-+{
-+ __raw_writel(value, port->base + offset);
-+}
-+
-+static void
-+anakin_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ txenable[port->irq] = 0;
-+}
-+
-+static inline void
-+anakin_transmit_buffer(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x14, info->xmit.buf[info->xmit.tail]);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE-1);
-+ info->state->icount.tx++;
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ anakin_stop_tx(port, 0);
-+}
-+
-+static inline void
-+anakin_transmit_x_char(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+
-+ anakin_out(port, 0x14, info->x_char);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+ info->state->icount.tx++;
-+ info->x_char = 0;
-+}
-+
-+static void
-+anakin_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
-+{
-+ unsigned int flags;
-+
-+ save_flags_cli(flags);
-+
-+ // is it this... or below: if (nonempty
-+ if (!txenable[port->irq]) {
-+ txenable[port->irq] = TXENABLE;
-+
-+ if ((anakin_in(port, 0x10) & TXEMPTY) && nonempty) {
-+ anakin_transmit_buffer((struct uart_info*)port->unused);
-+ }
-+ }
-+
-+ restore_flags(flags);
-+}
-+
-+static void
-+anakin_stop_rx(struct uart_port *port)
-+{
-+ unsigned long flags;
-+
-+ save_flags_cli(flags);
-+ while (anakin_in(port, 0x10) & RXRELEASE)
-+ anakin_in(port, 0x14);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX);
-+ restore_flags(flags);
-+}
-+
-+static void
-+anakin_enable_ms(struct uart_port *port)
-+{
-+}
-+
-+static inline void
-+anakin_rx_chars(struct uart_info *info)
-+{
-+ unsigned int ch;
-+ struct tty_struct *tty = info->tty;
-+
-+ if (!(anakin_in(info->port, 0x10) & RXRELEASE))
-+ return;
-+
-+ ch = anakin_in(info->port, 0x14) & 0xff;
-+
-+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ *tty->flip.char_buf_ptr++ = ch;
-+ *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-+ info->state->icount.rx++;
-+ tty->flip.count++;
-+ }
-+ tty_flip_buffer_push(tty);
-+}
-+
-+static inline void
-+anakin_overrun_chars(struct uart_info *info)
-+{
-+ unsigned int ch;
-+
-+ ch = anakin_in(info->port, 0x14);
-+ info->state->icount.overrun++;
-+}
-+
-+static inline void
-+anakin_tx_chars(struct uart_info *info)
-+{
-+ if (info->x_char) {
-+ anakin_transmit_x_char(info);
-+ return;
-+ }
-+
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ anakin_stop_tx(info->port, 0);
-+ return;
-+ }
-+
-+ anakin_transmit_buffer(info);
-+
-+ if (CIRC_CNT(info->xmit.head,
-+ info->xmit.tail,
-+ UART_XMIT_SIZE) < WAKEUP_CHARS)
-+ uart_event(info, EVT_WRITE_WAKEUP);
-+}
-+
-+static void
-+anakin_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int status;
-+ struct uart_info *info = dev_id;
-+
-+ status = anakin_in(info->port, 0x1c);
-+
-+ if (status & RX)
-+ anakin_rx_chars(info);
-+
-+ if (status & OVERRUN)
-+ anakin_overrun_chars(info);
-+
-+ if (txenable[info->port->irq] && (status & TX))
-+ anakin_tx_chars(info);
-+}
-+
-+static u_int
-+anakin_tx_empty(struct uart_port *port)
-+{
-+ return anakin_in(port, 0x10) & TXEMPTY ? TIOCSER_TEMT : 0;
-+}
-+
-+static u_int
-+anakin_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int status = 0;
-+
-+ status |= (anakin_in(port, 0x10) & CTS ? TIOCM_CTS : 0);
-+ status |= (anakin_in(port, 0x18) & DCD ? TIOCM_CAR : 0);
-+ status |= (anakin_in(port, 0x18) & DTR ? TIOCM_DTR : 0);
-+ status |= (anakin_in(port, 0x18) & RTS ? TIOCM_RTS : 0);
-+
-+ return status;
-+}
-+
-+static void
-+anakin_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned int status;
-+
-+ status = anakin_in(port, 0x18);
-+
-+ if (mctrl & TIOCM_RTS)
-+ status |= RTS;
-+ else
-+ status &= ~RTS;
-+
-+ if (mctrl & TIOCM_CAR)
-+ status |= DCD;
-+ else
-+ status &= ~DCD;
-+
-+ anakin_out(port, 0x18, status);
-+}
-+
-+static void
-+anakin_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned int status;
-+
-+ status = anakin_in(port, 0x20);
-+
-+ if (break_state == -1)
-+ status |= SETBREAK;
-+ else
-+ status &= ~SETBREAK;
-+
-+ anakin_out(port, 0x20, status);
-+}
-+
-+static int
-+anakin_startup(struct uart_port *port, struct uart_info *info)
-+{
-+ int retval;
-+ unsigned int read,write;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, anakin_int, SA_INTERRUPT, "serial_anakin", info);
-+ if (retval)
-+ return retval;
-+
-+ port->ops->set_mctrl(port, info->mctrl);
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ port->old_status = 0;
-+
-+ /*
-+ * Finally, disable IRQ and softIRQs for first byte)
-+ */
-+ txenable[port->irq] = 0;
-+ read = anakin_in(port, 0x18);
-+ write = (read & ~(RTS | DTR | BLOCKRX)) | IRQENABLE;
-+ anakin_out(port, 0x18, write);
-+
-+ /* Store the uart_info pointer so we can reference it in
-+ * anakin_start_tx() */
-+ port->unused = (u_int)info;
-+
-+ return 0;
-+}
-+
-+static void
-+anakin_shutdown(struct uart_port *port, struct uart_info *info)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, info);
-+
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) & ~IRQENABLE);
-+}
-+
-+static void
-+anakin_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ unsigned int flags;
-+
-+ save_flags_cli(flags);
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x10, (anakin_in(port, 0x10) & ~PRESCALER)
-+ | (quot << 3));
-+
-+ //parity always set to none
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) & ~PARITY);
-+ restore_flags(flags);
-+}
-+
-+static const char *anakin_type(struct port *port)
-+{
-+ return port->type == PORT_ANAKIN ? "ANAKIN" : NULL;
-+}
-+
-+static struct uart_ops anakin_pops = {
-+ tx_empty: anakin_tx_empty,
-+ set_mctrl: anakin_set_mctrl,
-+ get_mctrl: anakin_get_mctrl,
-+ stop_tx: anakin_stop_tx,
-+ start_tx: anakin_start_tx,
-+ stop_rx: anakin_stop_rx,
-+ enable_ms: anakin_enable_ms,
-+ break_ctl: anakin_break_ctl,
-+ startup: anakin_startup,
-+ shutdown: anakin_shutdown,
-+ change_speed: anakin_change_speed,
-+ type: anakin_type,
-+};
-+
-+static struct uart_port anakin_ports[UART_NR] = {
-+ {
-+ base: IO_BASE + UART0,
-+ irq: IRQ_UART0,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART1,
-+ irq: IRQ_UART1,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART2,
-+ irq: IRQ_UART2,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART3,
-+ irq: IRQ_UART3,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+ {
-+ base: IO_BASE + UART4,
-+ irq: IRQ_UART4,
-+ uartclk: 3686400,
-+ fifosize: 0,
-+ ops: &anakin_pops,
-+ },
-+};
-+
-+
-+#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-+
-+static void
-+anakin_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = anakin_ports + co->index;
-+ unsigned int flags, status, i;
-+
-+ /*
-+ * First save the status then disable the interrupts
-+ */
-+ save_flags_cli(flags);
-+ status = anakin_in(port, 0x18);
-+ anakin_out(port, 0x18, status & ~IRQENABLE);
-+ restore_flags(flags);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++, s++) {
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+
-+ /*
-+ * Send the character out.
-+ * If a LF, also do CR...
-+ */
-+ anakin_out(port, 0x14, *s);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST);
-+
-+ if (*s == 10) {
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+ anakin_out(port, 0x14, 13);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18)
-+ | SENDREQUEST);
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the interrupts
-+ */
-+ while (!(anakin_in(port, 0x10) & TXEMPTY));
-+
-+ if (status & IRQENABLE)
-+ save_flags_cli(flags);
-+ anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE);
-+ restore_flags(flags);
-+}
-+
-+static kdev_t
-+anakin_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR + co->index);
-+}
-+
-+/*
-+ * Read the current UART setup.
-+ */
-+static void __init
-+anakin_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ int paritycode;
-+
-+ *baud = GETBAUD (anakin_in(port, 0x10) & PRESCALER);
-+ paritycode = GETPARITY(anakin_in(port, 0x18) & PARITY);
-+ switch (paritycode) {
-+ case NONEPARITY: *parity = 'n'; break;
-+ case ODDPARITY: *parity = 'o'; break;
-+ case EVENPARITY: *parity = 'e'; break;
-+ }
-+ *bits = 8;
-+}
-+
-+static int __init
-+anakin_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = CONFIG_ANAKIN_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(anakin_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits);
-+ else
-+ anakin_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits);
-+}
-+
-+static struct console anakin_console = {
-+ name: SERIAL_ANAKIN_NAME,
-+ write: anakin_console_write,
-+ device: anakin_console_device,
-+ setup: anakin_console_setup,
-+ flags: CON_PRINTBUFFER,
-+ index: -1,
-+};
-+
-+void __init
-+anakin_console_init(void)
-+{
-+ register_console(&anakin_console);
-+}
-+
-+#define ANAKIN_CONSOLE &anakin_console
-+#else
-+#define ANAKIN_CONSOLE NULL
-+#endif
-+
-+static struct uart_register anakin_reg = {
-+ normal_major: SERIAL_ANAKIN_MAJOR,
-+ normal_name: SERIAL_ANAKIN_NAME,
-+ normal_driver: &normal,
-+ callout_major: CALLOUT_ANAKIN_MAJOR,
-+ callout_name: CALLOUT_ANAKIN_NAME,
-+ callout_driver: &callout,
-+ table: anakin_table,
-+ termios: anakin_termios,
-+ termios_locked: anakin_termios_locked,
-+ minor: SERIAL_ANAKIN_MINOR,
-+ nr: UART_NR,
-+ state: anakin_state,
-+ port: anakin_ports,
-+ cons: ANAKIN_CONSOLE,
-+};
-+
-+static int __init
-+anakin_init(void)
-+{
-+ return uart_register_port(&anakin_reg);
-+}
-+
-+__initcall(anakin_init);
-+
-+MODULE_DESCRIPTION("Anakin serial driver");
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_SUPPORTED_DEVICE("ttyAN");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/serial/clps711x.c
-@@ -0,0 +1,635 @@
-+/*
-+ * linux/drivers/char/serial_clps711x.c
-+ *
-+ * Driver for CLPS711x serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: clps711x.c,v 1.12.2.2 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/bitops.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/clps7111.h>
-+
-+#define UART_NR 2
-+
-+#define SERIAL_CLPS711X_NAME "ttyAM"
-+#define SERIAL_CLPS711X_MAJOR 204
-+#define SERIAL_CLPS711X_MINOR 16
-+#define SERIAL_CLPS711X_NR UART_NR
-+
-+#define CALLOUT_CLPS711X_NAME "cuaam"
-+#define CALLOUT_CLPS711X_MAJOR 205
-+#define CALLOUT_CLPS711X_MINOR 16
-+#define CALLOUT_CLPS711X_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *clps711x_table[UART_NR];
-+static struct termios *clps711x_termios[UART_NR], *clps711x_termios_locked[UART_NR];
-+
-+/*
-+ * We use the relevant SYSCON register as a base address for these ports.
-+ */
-+#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
-+#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
-+#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
-+#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
-+
-+#define TX_IRQ(port) ((port)->irq)
-+#define RX_IRQ(port) ((port)->irq + 1)
-+
-+#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
-+
-+#define tx_enabled(port) ((port)->unused[0])
-+
-+static void
-+clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ if (tx_enabled(port)) {
-+ disable_irq(TX_IRQ(port));
-+ tx_enabled(port) = 0;
-+ }
-+}
-+
-+static void
-+clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ if (!tx_enabled(port)) {
-+ enable_irq(TX_IRQ(port));
-+ tx_enabled(port) = 1;
-+ }
-+}
-+
-+static void clps711xuart_stop_rx(struct uart_port *port)
-+{
-+ disable_irq(RX_IRQ(port));
-+}
-+
-+static void clps711xuart_enable_ms(struct uart_port *port)
-+{
-+}
-+
-+static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ struct tty_struct *tty = port->info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = clps_readl(SYSFLG(port));
-+ while (!(status & SYSFLG_URXFE)) {
-+ ch = clps_readl(UARTDR(port));
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ port->icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (ch & UART_ANY_ERR)
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = clps_readl(SYSFLG(port));
-+ }
-+ out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+ handle_error:
-+ if (ch & UARTDR_PARERR)
-+ port->icount.parity++;
-+ else if (ch & UARTDR_FRMERR)
-+ port->icount.frame++;
-+ if (ch & UARTDR_OVERR)
-+ port->icount.overrun++;
-+
-+ if (ch & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+ ch &= port->read_status_mask;
-+
-+ if (ch & UARTDR_PARERR)
-+ flg = TTY_PARITY;
-+ else if (ch & UARTDR_FRMERR)
-+ flg = TTY_FRAME;
-+
-+ if (ch & UARTDR_OVERR) {
-+ /*
-+ * CHECK: does overrun affect the current character?
-+ * ASSUMPTION: it does not.
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ struct circ_buf *xmit = &port->info->xmit;
-+ int count;
-+
-+ if (port->x_char) {
-+ clps_writel(port->x_char, UARTDR(port));
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-+ clps711xuart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ clps_writel(xmit->buf[xmit->tail], UARTDR(port));
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ } while (--count > 0);
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (uart_circ_empty(xmit))
-+ clps711xuart_stop_tx(port, 0);
-+}
-+
-+static unsigned int clps711xuart_tx_empty(struct uart_port *port)
-+{
-+ unsigned int status = clps_readl(SYSFLG(port));
-+ return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int port_addr;
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ port_addr = SYSFLG(port);
-+ if (port_addr == SYSFLG1) {
-+ status = clps_readl(SYSFLG1);
-+ if (status & SYSFLG1_DCD)
-+ result |= TIOCM_CAR;
-+ if (status & SYSFLG1_DSR)
-+ result |= TIOCM_DSR;
-+ if (status & SYSFLG1_CTS)
-+ result |= TIOCM_CTS;
-+ }
-+
-+ return result;
-+}
-+
-+static void
-+clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
-+{
-+}
-+
-+static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned long flags;
-+ unsigned int ubrlcr;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ ubrlcr = clps_readl(UBRLCR(port));
-+ if (break_state == -1)
-+ ubrlcr |= UBRLCR_BREAK;
-+ else
-+ ubrlcr &= ~UBRLCR_BREAK;
-+ clps_writel(ubrlcr, UBRLCR(port));
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static int clps711xuart_startup(struct uart_port *port)
-+{
-+ unsigned int syscon;
-+ int retval;
-+
-+ tx_enabled(port) = 1;
-+
-+ /*
-+ * Allocate the IRQs
-+ */
-+ retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
-+ "clps711xuart_tx", port);
-+ if (retval)
-+ return retval;
-+
-+ retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
-+ "clps711xuart_rx", port);
-+ if (retval) {
-+ free_irq(TX_IRQ(port), port);
-+ return retval;
-+ }
-+
-+ /*
-+ * enable the port
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ syscon |= SYSCON_UARTEN;
-+ clps_writel(syscon, SYSCON(port));
-+
-+ return 0;
-+}
-+
-+static void clps711xuart_shutdown(struct uart_port *port)
-+{
-+ unsigned int ubrlcr, syscon;
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(TX_IRQ(port), port); /* TX interrupt */
-+ free_irq(RX_IRQ(port), port); /* RX interrupt */
-+
-+ /*
-+ * disable the port
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ syscon &= ~SYSCON_UARTEN;
-+ clps_writel(syscon, SYSCON(port));
-+
-+ /*
-+ * disable break condition and fifos
-+ */
-+ ubrlcr = clps_readl(UBRLCR(port));
-+ ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
-+ clps_writel(ubrlcr, UBRLCR(port));
-+}
-+
-+static void clps711xuart_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ unsigned int ubrlcr;
-+ unsigned long flags;
-+
-+#if DEBUG
-+ printk("clps711xuart_change_speed(cflag=0x%x, iflag=0x%x, quot=%d) called\n",
-+ cflag, iflag, quot);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ ubrlcr = UBRLCR_WRDLEN5;
-+ break;
-+ case CS6:
-+ ubrlcr = UBRLCR_WRDLEN6;
-+ break;
-+ case CS7:
-+ ubrlcr = UBRLCR_WRDLEN7;
-+ break;
-+ default: // CS8
-+ ubrlcr = UBRLCR_WRDLEN8;
-+ break;
-+ }
-+ if (cflag & CSTOPB)
-+ ubrlcr |= UBRLCR_XSTOP;
-+ if (cflag & PARENB) {
-+ ubrlcr |= UBRLCR_PRTEN;
-+ if (!(cflag & PARODD))
-+ ubrlcr |= UBRLCR_EVENPRT;
-+ }
-+ if (port->fifosize > 1)
-+ ubrlcr |= UBRLCR_FIFOEN;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+
-+ port->read_status_mask = UARTDR_OVERR;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
-+ if (iflag & IGNBRK) {
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns to (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UARTDR_OVERR;
-+ }
-+
-+ quot -= 1;
-+
-+ clps_writel(ubrlcr | quot, UBRLCR(port));
-+
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static const char *clps711xuart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void clps711xuart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE)
-+ port->type = PORT_CLPS711X;
-+}
-+
-+static void clps711xuart_release_port(struct uart_port *port)
-+{
-+}
-+
-+static int clps711xuart_request_port(struct uart_port *port)
-+{
-+ return 0;
-+}
-+
-+static struct uart_ops clps711x_pops = {
-+ .tx_empty = clps711xuart_tx_empty,
-+ .set_mctrl = clps711xuart_set_mctrl_null,
-+ .get_mctrl = clps711xuart_get_mctrl,
-+ .stop_tx = clps711xuart_stop_tx,
-+ .start_tx = clps711xuart_start_tx,
-+ .stop_rx = clps711xuart_stop_rx,
-+ .enable_ms = clps711xuart_enable_ms,
-+ .break_ctl = clps711xuart_break_ctl,
-+ .startup = clps711xuart_startup,
-+ .shutdown = clps711xuart_shutdown,
-+ .change_speed = clps711xuart_change_speed,
-+ .type = clps711xuart_type,
-+ .config_port = clps711xuart_config_port,
-+ .release_port = clps711xuart_release_port,
-+ .request_port = clps711xuart_request_port,
-+};
-+
-+static struct uart_port clps711x_ports[UART_NR] = {
-+ {
-+ .iobase = SYSCON1,
-+ .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
-+ .uartclk = 3686400,
-+ .fifosize = 16,
-+ .ops = &clps711x_pops,
-+ .line = 0,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ },
-+ {
-+ .iobase = SYSCON2,
-+ .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
-+ .uartclk = 3686400,
-+ .fifosize = 16,
-+ .ops = &clps711x_pops,
-+ .line = 1,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-+/*
-+ * Print a string to the serial port trying not to disturb
-+ * any possible real use of the port...
-+ *
-+ * The console_lock must be held when we get here.
-+ *
-+ * Note that this is called with interrupts already disabled
-+ */
-+static void
-+clps711xuart_console_write(struct console *co, const char *s,
-+ unsigned int count)
-+{
-+ struct uart_port *port = clps711x_ports + co->index;
-+ unsigned int status, syscon;
-+ int i;
-+
-+ /*
-+ * Ensure that the port is enabled.
-+ */
-+ syscon = clps_readl(SYSCON(port));
-+ clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UTXFF);
-+ clps_writel(s[i], UARTDR(port));
-+ if (s[i] == '\n') {
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UTXFF);
-+ clps_writel('\r', UARTDR(port));
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the uart state.
-+ */
-+ do {
-+ status = clps_readl(SYSFLG(port));
-+ } while (status & SYSFLG_UBUSY);
-+
-+ clps_writel(syscon, SYSCON(port));
-+}
-+
-+static kdev_t clps711xuart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index);
-+}
-+
-+static void __init
-+clps711xuart_console_get_options(struct uart_port *port, int *baud,
-+ int *parity, int *bits)
-+{
-+ if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
-+ unsigned int ubrlcr, quot;
-+
-+ ubrlcr = clps_readl(UBRLCR(port));
-+
-+ *parity = 'n';
-+ if (ubrlcr & UBRLCR_PRTEN) {
-+ if (ubrlcr & UBRLCR_EVENPRT)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
-+ *bits = 7;
-+ else
-+ *bits = 8;
-+
-+ quot = ubrlcr & UBRLCR_BAUD_MASK;
-+ *baud = port->uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init clps711xuart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(clps711x_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ clps711xuart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console clps711x_console = {
-+ .name = SERIAL_CLPS711X_NAME,
-+ .write = clps711xuart_console_write,
-+ .device = clps711xuart_console_device,
-+ .setup = clps711xuart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init clps711xuart_console_init(void)
-+{
-+ register_console(&clps711x_console);
-+}
-+
-+#define CLPS711X_CONSOLE &clps711x_console
-+#else
-+#define CLPS711X_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver clps711x_reg = {
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = SERIAL_CLPS711X_NAME,
-+ .callout_name = CALLOUT_CLPS711X_NAME,
-+#else
-+ .normal_name = SERIAL_CLPS711X_NAME,
-+ .callout_name = CALLOUT_CLPS711X_NAME,
-+#endif
-+
-+ .normal_major = SERIAL_CLPS711X_MAJOR,
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_CLPS711X_MAJOR,
-+ .callout_driver = &callout,
-+
-+ .table = clps711x_table,
-+ .termios = clps711x_termios,
-+ .termios_locked = clps711x_termios_locked,
-+
-+ .minor = SERIAL_CLPS711X_MINOR,
-+ .nr = UART_NR,
-+
-+ .cons = CLPS711X_CONSOLE,
-+};
-+
-+static int __init clps711xuart_init(void)
-+{
-+ int ret, i;
-+
-+ printk(KERN_INFO "Serial: CLPS711x driver\n");
-+
-+ ret = uart_register_driver(&clps711x_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
-+
-+ return 0;
-+}
-+
-+static void __exit clps711xuart_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < UART_NR; i++)
-+ uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
-+
-+ uart_unregister_driver(&clps711x_reg);
-+}
-+
-+module_init(clps711xuart_init);
-+module_exit(clps711xuart_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("CLPS-711x generic serial driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/serial/core.c
-@@ -0,0 +1,2584 @@
-+/*
-+ * linux/drivers/serial/core.c
-+ *
-+ * Driver core for serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999 ARM Limited
-+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: core.c,v 1.20.2.5 2002/03/13 15:22:26 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/tty.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/pm.h>
-+#include <linux/serial_core.h>
-+#include <linux/smp_lock.h>
-+
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK(x...) printk(x)
-+#else
-+#define DPRINTK(x...) do { } while (0)
-+#endif
-+
-+#ifndef CONFIG_PM
-+#define pm_access(pm) do { } while (0)
-+#define pm_unregister(pm) do { } while (0)
-+#endif
-+
-+/*
-+ * This is used to lock changes in serial line configuration.
-+ */
-+static DECLARE_MUTEX(port_sem);
-+
-+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-+
-+#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
-+
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
-+#else
-+#define uart_console(port) (0)
-+#endif
-+
-+static void uart_change_speed(struct uart_state *state, struct termios *old_termios);
-+static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
-+static void uart_change_pm(struct uart_state *state, int pm_state);
-+
-+/*
-+ * This routine is used by the interrupt handler to schedule processing in
-+ * the software interrupt portion of the driver.
-+ */
-+void uart_write_wakeup(struct uart_port *port)
-+{
-+ struct uart_info *info = port->info;
-+ tasklet_schedule(&info->tlet);
-+}
-+
-+static void uart_stop(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->stop_tx(port, 1);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void __uart_start(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
-+ !tty->stopped && !tty->hw_stopped)
-+ port->ops->start_tx(port, 1);
-+}
-+
-+static void uart_start(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ pm_access(state->pm);
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ __uart_start(tty);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void uart_tasklet_action(unsigned long data)
-+{
-+ struct uart_state *state = (struct uart_state *)data;
-+ struct tty_struct *tty;
-+
-+ tty = state->info->tty;
-+ if (tty) {
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-+ tty->ldisc.write_wakeup)
-+ tty->ldisc.write_wakeup(tty);
-+ wake_up_interruptible(&tty->write_wait);
-+ }
-+}
-+
-+static inline void
-+uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
-+{
-+ unsigned long flags;
-+ unsigned int old;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ old = port->mctrl;
-+ port->mctrl = (old & ~clear) | set;
-+ if (old != port->mctrl)
-+ port->ops->set_mctrl(port, port->mctrl);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0)
-+#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear)
-+
-+static inline unsigned int uart_get_altspeed(struct uart_port *port)
-+{
-+ unsigned int flags = port->flags & UPF_SPD_MASK;
-+ unsigned int altbaud = 0;
-+
-+ if (flags == ASYNC_SPD_HI)
-+ altbaud = 57600;
-+ if (flags == ASYNC_SPD_VHI)
-+ altbaud = 115200;
-+ if (flags == ASYNC_SPD_SHI)
-+ altbaud = 230400;
-+ if (flags == ASYNC_SPD_WARP)
-+ altbaud = 460800;
-+
-+ return altbaud;
-+}
-+
-+/*
-+ * Startup the port. This will be called once per open. All calls
-+ * will be serialised by the per-port semaphore.
-+ */
-+static int uart_startup(struct uart_state *state, int init_hw)
-+{
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+ unsigned long page;
-+ int retval = 0;
-+
-+ if (info->flags & UIF_INITIALIZED)
-+ return 0;
-+
-+ /*
-+ * Set the TTY IO error marker - we will only clear this
-+ * once we have successfully opened the port. Also set
-+ * up the tty->alt_speed kludge
-+ */
-+ if (info->tty)
-+ set_bit(TTY_IO_ERROR, &info->tty->flags);
-+
-+ if (port->type == PORT_UNKNOWN)
-+ return 0;
-+
-+ /*
-+ * Initialise and allocate the transmit and temporary
-+ * buffer.
-+ */
-+ if (!info->xmit.buf) {
-+ page = get_zeroed_page(GFP_KERNEL);
-+ if (!page)
-+ return -ENOMEM;
-+
-+ info->xmit.buf = (unsigned char *) page;
-+ info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE;
-+ init_MUTEX(&info->tmpbuf_sem);
-+ uart_circ_clear(&info->xmit);
-+ }
-+
-+ port->mctrl = 0;
-+
-+ retval = port->ops->startup(port);
-+ if (retval == 0) {
-+ if (init_hw) {
-+ /*
-+ * Initialise the hardware port settings.
-+ */
-+ uart_change_speed(state, NULL);
-+
-+ /*
-+ * Setup the RTS and DTR signals once the
-+ * port is open and ready to respond.
-+ */
-+ if (info->tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-+ }
-+
-+ info->flags |= UIF_INITIALIZED;
-+
-+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
-+ }
-+
-+ if (retval && capable(CAP_SYS_ADMIN))
-+ retval = 0;
-+
-+ return retval;
-+}
-+
-+/*
-+ * This routine will shutdown a serial port; interrupts are disabled, and
-+ * DTR is dropped if the hangup on close termio flag is on. Calls to
-+ * uart_shutdown are serialised by the per-port semaphore.
-+ */
-+static void uart_shutdown(struct uart_state *state)
-+{
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+
-+ if (!(info->flags & UIF_INITIALIZED))
-+ return;
-+
-+ /*
-+ * Turn off DTR and RTS early.
-+ */
-+ if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-+ uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-+
-+ /*
-+ * clear delta_msr_wait queue to avoid mem leaks: we may free
-+ * the irq here so the queue might never be woken up. Note
-+ * that we won't end up waiting on delta_msr_wait again since
-+ * any outstanding file descriptors should be pointing at
-+ * hung_up_tty_fops now.
-+ */
-+ wake_up_interruptible(&info->delta_msr_wait);
-+
-+ /*
-+ * Free the IRQ and disable the port.
-+ */
-+ port->ops->shutdown(port);
-+
-+ /*
-+ * Free the transmit buffer page.
-+ */
-+ if (info->xmit.buf) {
-+ free_page((unsigned long)info->xmit.buf);
-+ info->xmit.buf = NULL;
-+ info->tmpbuf = NULL;
-+ }
-+
-+ /*
-+ * kill off our tasklet
-+ */
-+ tasklet_kill(&info->tlet);
-+ if (info->tty)
-+ set_bit(TTY_IO_ERROR, &info->tty->flags);
-+
-+ info->flags &= ~UIF_INITIALIZED;
-+}
-+
-+/**
-+ * uart_update_timeout - update per-port FIFO timeout.
-+ * @port: uart_port structure describing the port.
-+ * @cflag: termios cflag value
-+ * @quot: uart clock divisor quotient
-+ *
-+ * Set the port FIFO timeout value. The @cflag value should
-+ * reflect the actual hardware settings.
-+ */
-+void
-+uart_update_timeout(struct uart_port *port, unsigned int cflag,
-+ unsigned int baud)
-+{
-+ unsigned int bits;
-+
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5:
-+ bits = 7;
-+ break;
-+ case CS6:
-+ bits = 8;
-+ break;
-+ case CS7:
-+ bits = 9;
-+ break;
-+ default:
-+ bits = 10;
-+ break; // CS8
-+ }
-+
-+ if (cflag & CSTOPB)
-+ bits++;
-+ if (cflag & PARENB)
-+ bits++;
-+
-+ /*
-+ * The total number of bits to be transmitted in the fifo.
-+ */
-+ bits = bits * port->fifosize;
-+
-+ /*
-+ * Figure the timeout to send the above number of bits.
-+ * Add .02 seconds of slop
-+ */
-+ port->timeout = (HZ * bits) / baud + HZ/50;
-+}
-+
-+EXPORT_SYMBOL(uart_update_timeout);
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+ u_int quot;
-+
-+ /* Special case: B0 rate */
-+ if (!baud)
-+ baud = 9600;
-+
-+ /* Old HI/VHI/custom speed handling */
-+ if (baud == 38400 &&
-+ ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-+ quot = port->custom_divisor;
-+ else
-+ quot = port->uartclk / (16 * baud);
-+
-+ return quot;
-+}
-+
-+static void
-+uart_change_speed(struct uart_state *state, struct termios *old_termios)
-+{
-+ struct tty_struct *tty = state->info->tty;
-+ struct uart_port *port = state->port;
-+ struct termios *termios;
-+ unsigned int quot, baud, cflag, try;
-+
-+ /*
-+ * If we have no tty, termios, or the port does not exist,
-+ * then we can't set the parameters for this port.
-+ */
-+ if (!tty || !tty->termios || port->type == PORT_UNKNOWN)
-+ return;
-+
-+ termios = tty->termios;
-+
-+ cflag = termios->c_cflag;
-+
-+ for (try = 0; try < 2; try ++) {
-+ /* Determine divisor based on baud rate */
-+ baud = tty_get_baud_rate(tty);
-+ quot = uart_calculate_quot(port, baud);
-+ if (quot)
-+ break;
-+
-+ /*
-+ * Oops, the quotient was zero. Try again with
-+ * the old baud rate if possible.
-+ */
-+ termios->c_cflag &= ~CBAUD;
-+ if (old_termios) {
-+ termios->c_cflag |=
-+ (old_termios->c_cflag & CBAUD);
-+ old_termios = NULL;
-+ continue;
-+ }
-+
-+ /*
-+ * As a last resort, if the quotient is zero,
-+ * default to 9600 bps
-+ */
-+ termios->c_cflag |= B9600;
-+ }
-+
-+ uart_update_timeout(port, cflag, port->uartclk / (16 * quot));
-+
-+ if (termios->c_cflag & CRTSCTS)
-+ state->info->flags |= UIF_CTS_FLOW;
-+ else
-+ state->info->flags &= ~UIF_CTS_FLOW;
-+ if (termios->c_cflag & CLOCAL)
-+ state->info->flags &= ~UIF_CHECK_CD;
-+ else
-+ state->info->flags |= UIF_CHECK_CD;
-+
-+ /*
-+ * Set up parity check flag
-+ */
-+ pm_access(state->pm);
-+
-+ port->ops->change_speed(port, cflag, termios->c_iflag, quot);
-+}
-+
-+static inline void
-+__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
-+{
-+ unsigned long flags;
-+
-+ if (!circ->buf)
-+ return;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ if (uart_circ_chars_free(circ) != 0) {
-+ circ->buf[circ->head] = c;
-+ circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
-+ }
-+ spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static inline int
-+__uart_user_write(struct uart_port *port, struct circ_buf *circ,
-+ const unsigned char *buf, int count)
-+{
-+ unsigned long flags;
-+ int c, ret = 0;
-+
-+ if (down_interruptible(&port->info->tmpbuf_sem))
-+ return -EINTR;
-+
-+ while (1) {
-+ int c1;
-+ c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+
-+ c -= copy_from_user(port->info->tmpbuf, buf, c);
-+ if (!c) {
-+ if (!ret)
-+ ret = -EFAULT;
-+ break;
-+ }
-+ spin_lock_irqsave(&port->lock, flags);
-+ c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (c1 < c)
-+ c = c1;
-+ memcpy(circ->buf + circ->head, port->info->tmpbuf, c);
-+ circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ buf += c;
-+ count -= c;
-+ ret += c;
-+ }
-+ up(&port->info->tmpbuf_sem);
-+
-+ return ret;
-+}
-+
-+static inline int
-+__uart_kern_write(struct uart_port *port, struct circ_buf *circ,
-+ const unsigned char *buf, int count)
-+{
-+ unsigned long flags;
-+ int c, ret = 0;
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ while (1) {
-+ c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+ memcpy(circ->buf + circ->head, buf, c);
-+ circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-+ buf += c;
-+ count -= c;
-+ ret += c;
-+ }
-+ spin_unlock_irqrestore(&port->lock, flags);
-+
-+ return ret;
-+}
-+
-+static void uart_put_char(struct tty_struct *tty, unsigned char ch)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ __uart_put_char(state->port, &state->info->xmit, ch);
-+}
-+
-+static void uart_flush_chars(struct tty_struct *tty)
-+{
-+ uart_start(tty);
-+}
-+
-+static int
-+uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf,
-+ int count)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ int ret;
-+
-+ if (!state->info->xmit.buf)
-+ return 0;
-+
-+ if (from_user)
-+ ret = __uart_user_write(state->port, &state->info->xmit, buf, count);
-+ else
-+ ret = __uart_kern_write(state->port, &state->info->xmit, buf, count);
-+
-+ uart_start(tty);
-+ return ret;
-+}
-+
-+static int uart_write_room(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ return uart_circ_chars_free(&state->info->xmit);
-+}
-+
-+static int uart_chars_in_buffer(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ return uart_circ_chars_pending(&state->info->xmit);
-+}
-+
-+static void uart_flush_buffer(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ DPRINTK("uart_flush_buffer(%d) called\n",
-+ MINOR(tty->device) - tty->driver.minor_start);
-+
-+ spin_lock_irqsave(&port->lock, flags);
-+ uart_circ_clear(&state->info->xmit);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ wake_up_interruptible(&tty->write_wait);
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-+ tty->ldisc.write_wakeup)
-+ (tty->ldisc.write_wakeup)(tty);
-+}
-+
-+/*
-+ * This function is used to send a high-priority XON/XOFF character to
-+ * the device
-+ */
-+static void uart_send_xchar(struct tty_struct *tty, char ch)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long flags;
-+
-+ if (port->ops->send_xchar)
-+ port->ops->send_xchar(port, ch);
-+ else {
-+ port->x_char = ch;
-+ if (ch) {
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->start_tx(port, 0);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ }
-+ }
-+}
-+
-+static void uart_throttle(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ if (I_IXOFF(tty))
-+ uart_send_xchar(tty, STOP_CHAR(tty));
-+
-+ if (tty->termios->c_cflag & CRTSCTS)
-+ uart_clear_mctrl(state->port, TIOCM_RTS);
-+}
-+
-+static void uart_unthrottle(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ if (I_IXOFF(tty)) {
-+ if (port->x_char)
-+ port->x_char = 0;
-+ else
-+ uart_send_xchar(tty, START_CHAR(tty));
-+ }
-+
-+ if (tty->termios->c_cflag & CRTSCTS)
-+ uart_set_mctrl(port, TIOCM_RTS);
-+}
-+
-+static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo)
-+{
-+ struct uart_port *port = state->port;
-+ struct serial_struct tmp;
-+
-+ memset(&tmp, 0, sizeof(tmp));
-+ tmp.type = port->type;
-+ tmp.line = port->line;
-+ tmp.port = port->iobase;
-+ if (HIGH_BITS_OFFSET)
-+ tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET;
-+ tmp.irq = port->irq;
-+ tmp.flags = port->flags;
-+ tmp.xmit_fifo_size = port->fifosize;
-+ tmp.baud_base = port->uartclk / 16;
-+ tmp.close_delay = state->close_delay;
-+ tmp.closing_wait = state->closing_wait;
-+ tmp.custom_divisor = port->custom_divisor;
-+ tmp.hub6 = port->hub6;
-+ tmp.io_type = port->iotype;
-+ tmp.iomem_reg_shift = port->regshift;
-+ tmp.iomem_base = (void *)port->mapbase;
-+
-+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-+ return -EFAULT;
-+ return 0;
-+}
-+
-+static int
-+uart_set_info(struct uart_state *state, struct serial_struct *newinfo)
-+{
-+ struct serial_struct new_serial;
-+ struct uart_port *port = state->port;
-+ unsigned long new_port;
-+ unsigned int change_irq, change_port, old_flags;
-+ unsigned int old_custom_divisor;
-+ int retval = 0;
-+
-+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
-+ return -EFAULT;
-+
-+ new_port = new_serial.port;
-+ if (HIGH_BITS_OFFSET)
-+ new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
-+
-+ new_serial.irq = irq_cannonicalize(new_serial.irq);
-+
-+ /*
-+ * This semaphore protects state->count. It is also
-+ * very useful to prevent opens. Also, take the
-+ * port configuration semaphore to make sure that a
-+ * module insertion/removal doesn't change anything
-+ * under us.
-+ */
-+ down(&state->sem);
-+
-+ change_irq = new_serial.irq != port->irq;
-+
-+ /*
-+ * Since changing the 'type' of the port changes its resource
-+ * allocations, we should treat type changes the same as
-+ * IO port changes.
-+ */
-+ change_port = new_port != port->iobase ||
-+ (unsigned long)new_serial.iomem_base != port->mapbase ||
-+ new_serial.hub6 != port->hub6 ||
-+ new_serial.io_type != port->iotype ||
-+ new_serial.iomem_reg_shift != port->regshift ||
-+ new_serial.type != port->type;
-+
-+ old_flags = port->flags;
-+ old_custom_divisor = port->custom_divisor;
-+
-+ if (!capable(CAP_SYS_ADMIN)) {
-+ retval = -EPERM;
-+ if (change_irq || change_port ||
-+ (new_serial.baud_base != port->uartclk / 16) ||
-+ (new_serial.close_delay != state->close_delay) ||
-+ (new_serial.closing_wait != state->closing_wait) ||
-+ (new_serial.xmit_fifo_size != port->fifosize) ||
-+ (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0))
-+ goto exit;
-+ port->flags = ((port->flags & ~UPF_USR_MASK) |
-+ (new_serial.flags & UPF_USR_MASK));
-+ port->custom_divisor = new_serial.custom_divisor;
-+ goto check_and_exit;
-+ }
-+
-+ /*
-+ * Ask the low level driver to verify the settings.
-+ */
-+ if (port->ops->verify_port)
-+ retval = port->ops->verify_port(port, &new_serial);
-+
-+ if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
-+ (new_serial.baud_base < 9600))
-+ retval = -EINVAL;
-+
-+ if (retval)
-+ goto exit;
-+
-+ if (change_port || change_irq) {
-+ retval = -EBUSY;
-+
-+ /*
-+ * Make sure that we are the sole user of this port.
-+ */
-+ if (uart_users(state) > 1)
-+ goto exit;
-+
-+ /*
-+ * We need to shutdown the serial port at the old
-+ * port/type/irq combination.
-+ */
-+ uart_shutdown(state);
-+ }
-+
-+ if (change_port) {
-+ unsigned long old_iobase, old_mapbase;
-+ unsigned int old_type, old_iotype, old_hub6, old_shift;
-+
-+ old_iobase = port->iobase;
-+ old_mapbase = port->mapbase;
-+ old_type = port->type;
-+ old_hub6 = port->hub6;
-+ old_iotype = port->iotype;
-+ old_shift = port->regshift;
-+
-+ /*
-+ * Free and release old regions
-+ */
-+ if (old_type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ port->iobase = new_port;
-+ port->type = new_serial.type;
-+ port->hub6 = new_serial.hub6;
-+ port->iotype = new_serial.io_type;
-+ port->regshift = new_serial.iomem_reg_shift;
-+ port->mapbase = (unsigned long)new_serial.iomem_base;
-+
-+ /*
-+ * Claim and map the new regions
-+ */
-+ if (port->type != PORT_UNKNOWN) {
-+ retval = port->ops->request_port(port);
-+ } else {
-+ /* Always success - Jean II */
-+ retval = 0;
-+ }
-+
-+ /*
-+ * If we fail to request resources for the
-+ * new port, try to restore the old settings.
-+ */
-+ if (retval && old_type != PORT_UNKNOWN) {
-+ port->iobase = old_iobase;
-+ port->type = old_type;
-+ port->hub6 = old_hub6;
-+ port->iotype = old_iotype;
-+ port->regshift = old_shift;
-+ port->mapbase = old_mapbase;
-+ retval = port->ops->request_port(port);
-+ /*
-+ * If we failed to restore the old settings,
-+ * we fail like this.
-+ */
-+ if (retval)
-+ port->type = PORT_UNKNOWN;
-+
-+ /*
-+ * We failed anyway.
-+ */
-+ retval = -EBUSY;
-+ }
-+ }
-+
-+ port->irq = new_serial.irq;
-+ port->uartclk = new_serial.baud_base * 16;
-+ port->flags = (port->flags & ~UPF_CHANGE_MASK) |
-+ (new_serial.flags & UPF_CHANGE_MASK);
-+ port->custom_divisor = new_serial.custom_divisor;
-+ state->close_delay = new_serial.close_delay * HZ / 100;
-+ state->closing_wait = new_serial.closing_wait * HZ / 100;
-+ port->fifosize = new_serial.xmit_fifo_size;
-+ if (state->info->tty)
-+ state->info->tty->low_latency =
-+ (port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-+
-+ check_and_exit:
-+ retval = 0;
-+ if (port->type == PORT_UNKNOWN)
-+ goto exit;
-+ if (state->info->flags & UIF_INITIALIZED) {
-+ if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
-+ old_custom_divisor != port->custom_divisor) {
-+ state->info->tty->alt_speed = uart_get_altspeed(port);
-+ uart_change_speed(state, NULL);
-+ }
-+ } else
-+ retval = uart_startup(state, 1);
-+ exit:
-+ up(&state->sem);
-+ return retval;
-+}
-+
-+
-+/*
-+ * uart_get_lsr_info - get line status register info.
-+ * Note: uart_ioctl protects us against hangups.
-+ */
-+static int uart_get_lsr_info(struct uart_state *state, unsigned int *value)
-+{
-+ struct uart_port *port = state->port;
-+ unsigned int result;
-+
-+ result = port->ops->tx_empty(port);
-+
-+ /*
-+ * If we're about to load something into the transmit
-+ * register, we'll pretend the transmitter isn't empty to
-+ * avoid a race condition (depending on when the transmit
-+ * interrupt happens).
-+ */
-+ if (port->x_char ||
-+ ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
-+ !state->info->tty->stopped && !state->info->tty->hw_stopped))
-+ result &= ~TIOCSER_TEMT;
-+
-+ return put_user(result, value);
-+}
-+
-+static int uart_tiocmget(struct tty_struct *tty, struct file *file)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ int result = -EIO;
-+
-+ down(&state->sem);
-+ if ((!file || !tty_hung_up_p(file)) &&
-+ !(tty->flags & (1 << TTY_IO_ERROR))) {
-+ result = port->mctrl;
-+ result |= port->ops->get_mctrl(port);
-+ }
-+ up(&state->sem);
-+
-+ return result;
-+}
-+
-+static int
-+uart_tiocmset(struct tty_struct *tty, struct file *file,
-+ unsigned int set, unsigned int clear)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ int ret = -EIO;
-+
-+ down(&state->sem);
-+ if ((!file || !tty_hung_up_p(file)) &&
-+ !(tty->flags & (1 << TTY_IO_ERROR))) {
-+ uart_update_mctrl(port, set, clear);
-+ ret = 0;
-+ }
-+ up(&state->sem);
-+ return ret;
-+}
-+
-+static void uart_break_ctl(struct tty_struct *tty, int break_state)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ down(&state->sem);
-+
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->break_ctl(port, break_state);
-+
-+ up(&state->sem);
-+}
-+
-+static int uart_do_autoconfig(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+ int flags, ret;
-+
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ /*
-+ * Take the per-port semaphore. This prevents count from
-+ * changing, and hence any extra opens of the port while
-+ * we're auto-configuring.
-+ */
-+ if (down_interruptible(&state->sem))
-+ return -ERESTARTSYS;
-+
-+ ret = -EBUSY;
-+ if (uart_users(state) == 1) {
-+ uart_shutdown(state);
-+
-+ /*
-+ * If we already have a port type configured,
-+ * we must release its resources.
-+ */
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ flags = UART_CONFIG_TYPE;
-+ if (port->flags & UPF_AUTO_IRQ)
-+ flags |= UART_CONFIG_IRQ;
-+
-+ /*
-+ * This will claim the ports resources if
-+ * a port is found.
-+ */
-+ port->ops->config_port(port, flags);
-+
-+ ret = uart_startup(state, 1);
-+ }
-+ up(&state->sem);
-+ return ret;
-+}
-+
-+/*
-+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-+ * - mask passed in arg for lines of interest
-+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-+ * Caller should use TIOCGICOUNT to see which one it was
-+ */
-+static int
-+uart_wait_modem_status(struct uart_state *state, unsigned long arg)
-+{
-+ struct uart_port *port = state->port;
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct uart_icount cprev, cnow;
-+ int ret;
-+
-+ /*
-+ * note the counters on entry
-+ */
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cprev, &port->icount, sizeof(struct uart_icount));
-+
-+ /*
-+ * Force modem status interrupts on
-+ */
-+ port->ops->enable_ms(port);
-+ spin_unlock_irq(&port->lock);
-+
-+ add_wait_queue(&state->info->delta_msr_wait, &wait);
-+ for (;;) {
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
-+ spin_unlock_irq(&port->lock);
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-+ ret = 0;
-+ break;
-+ }
-+
-+ schedule();
-+
-+ /* see if a signal did it */
-+ if (signal_pending(current)) {
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-+
-+ cprev = cnow;
-+ }
-+
-+ current->state = TASK_RUNNING;
-+ remove_wait_queue(&state->info->delta_msr_wait, &wait);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-+ * Return: write counters to the user passed counter struct
-+ * NB: both 1->0 and 0->1 transitions are counted except for
-+ * RI where only 0->1 is counted.
-+ */
-+static int
-+uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt)
-+{
-+ struct serial_icounter_struct icount;
-+ struct uart_icount cnow;
-+ struct uart_port *port = state->port;
-+
-+ spin_lock_irq(&port->lock);
-+ memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
-+ spin_unlock_irq(&port->lock);
-+
-+ icount.cts = cnow.cts;
-+ icount.dsr = cnow.dsr;
-+ icount.rng = cnow.rng;
-+ icount.dcd = cnow.dcd;
-+ icount.rx = cnow.rx;
-+ icount.tx = cnow.tx;
-+ icount.frame = cnow.frame;
-+ icount.overrun = cnow.overrun;
-+ icount.parity = cnow.parity;
-+ icount.brk = cnow.brk;
-+ icount.buf_overrun = cnow.buf_overrun;
-+
-+ return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
-+}
-+
-+/*
-+ * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here.
-+ */
-+static int
-+uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ int ret = -ENOIOCTLCMD;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ /*
-+ * These ioctls don't rely on the hardware to be present.
-+ */
-+ switch (cmd) {
-+ case TIOCGSERIAL:
-+ ret = uart_get_info(state, (struct serial_struct *)arg);
-+ break;
-+
-+ case TIOCSSERIAL:
-+ ret = uart_set_info(state, (struct serial_struct *)arg);
-+ break;
-+
-+ case TIOCSERCONFIG:
-+ ret = uart_do_autoconfig(state);
-+ break;
-+
-+ case TIOCSERGWILD: /* obsolete */
-+ case TIOCSERSWILD: /* obsolete */
-+ ret = 0;
-+ break;
-+ }
-+
-+ if (ret != -ENOIOCTLCMD)
-+ goto out;
-+
-+ if (tty->flags & (1 << TTY_IO_ERROR)) {
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ /*
-+ * The following should only be used when hardware is present.
-+ */
-+ switch (cmd) {
-+ case TIOCMIWAIT:
-+ ret = uart_wait_modem_status(state, arg);
-+ break;
-+
-+ case TIOCGICOUNT:
-+ ret = uart_get_count(state, (struct serial_icounter_struct *)arg);
-+ break;
-+
-+ case TIOCMGET:
-+ {
-+ int val;
-+ val = uart_tiocmget(tty, filp);
-+ if (val >= 0) {
-+ ret = put_user(val, (int *)arg);
-+ } else {
-+ ret = val;
-+ }
-+ }
-+ break;
-+
-+ case TIOCMBIS:
-+ case TIOCMBIC:
-+ case TIOCMSET:
-+ {
-+ int val, set = 0, clear = 0;
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ break;
-+
-+ switch (cmd) {
-+ case TIOCMBIS:
-+ set = val;
-+ break;
-+ case TIOCMBIC:
-+ clear = val;
-+ break;
-+ case TIOCMSET:
-+ set = val;
-+ clear = ~val;
-+ break;
-+ }
-+
-+ set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
-+ clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
-+
-+ ret = uart_tiocmset(tty, filp, set, clear);
-+ }
-+ break;
-+ }
-+
-+ if (ret != -ENOIOCTLCMD)
-+ goto out;
-+
-+ down(&state->sem);
-+
-+ if (tty_hung_up_p(filp)) {
-+ ret = -EIO;
-+ goto out_up;
-+ }
-+
-+ /*
-+ * All these rely on hardware being present and need to be
-+ * protected against the tty being hung up.
-+ */
-+ switch (cmd) {
-+ case TIOCSERGETLSR: /* Get line status register */
-+ ret = uart_get_lsr_info(state, (unsigned int *)arg);
-+ break;
-+
-+ default: {
-+ struct uart_port *port = state->port;
-+ if (port->ops->ioctl)
-+ ret = port->ops->ioctl(port, cmd, arg);
-+ break;
-+ }
-+ }
-+ out_up:
-+ up(&state->sem);
-+ out:
-+ return ret;
-+}
-+
-+static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ unsigned long flags;
-+ unsigned int cflag = tty->termios->c_cflag;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ /*
-+ * These are the bits that are used to setup various
-+ * flags in the low level driver.
-+ */
-+#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-+
-+ if ((cflag ^ old_termios->c_cflag) == 0 &&
-+ RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
-+ return;
-+
-+ uart_change_speed(state, old_termios);
-+
-+ /* Handle transition to B0 status */
-+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-+ uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR);
-+
-+ /* Handle transition away from B0 status */
-+ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-+ unsigned int mask = TIOCM_DTR;
-+ if (!(cflag & CRTSCTS) ||
-+ !test_bit(TTY_THROTTLED, &tty->flags))
-+ mask |= TIOCM_RTS;
-+ uart_set_mctrl(state->port, mask);
-+ }
-+
-+ /* Handle turning off CRTSCTS */
-+ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-+ spin_lock_irqsave(&state->port->lock, flags);
-+ tty->hw_stopped = 0;
-+ __uart_start(tty);
-+ spin_unlock_irqrestore(&state->port->lock, flags);
-+ }
-+
-+#if 0
-+ /*
-+ * No need to wake up processes in open wait, since they
-+ * sample the CLOCAL flag once, and don't recheck it.
-+ * XXX It's not clear whether the current behavior is correct
-+ * or not. Hence, this may change.....
-+ */
-+ if (!(old_termios->c_cflag & CLOCAL) &&
-+ (tty->termios->c_cflag & CLOCAL))
-+ wake_up_interruptible(&state->info->open_wait);
-+#endif
-+}
-+
-+/*
-+ * In 2.4.5, calls to this will be serialized via the BKL in
-+ * linux/drivers/char/tty_io.c:tty_release()
-+ * linux/drivers/char/tty_io.c:do_tty_handup()
-+ */
-+static void uart_close(struct tty_struct *tty, struct file *filp)
-+{
-+ struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ if (!state || !state->port)
-+ return;
-+
-+ port = state->port;
-+
-+ DPRINTK("uart_close(%d) called\n", port->line);
-+
-+ down(&state->sem);
-+
-+ if (tty_hung_up_p(filp))
-+ goto done;
-+
-+ if ((tty->count == 1) && (state->count != 1)) {
-+ /*
-+ * Uh, oh. tty->count is 1, which means that the tty
-+ * structure will be freed. state->count should always
-+ * be one in these conditions. If it's greater than
-+ * one, we've got real problems, since it means the
-+ * serial port won't be shutdown.
-+ */
-+ printk("uart_close: bad serial port count; tty->count is 1, "
-+ "state->count is %d\n", state->count);
-+ state->count = 1;
-+ }
-+ if (--state->count < 0) {
-+ printk("rs_close: bad serial port count for %s%d: %d\n",
-+ tty->driver.name, port->line, state->count);
-+ state->count = 0;
-+ }
-+ if (state->count)
-+ goto done;
-+
-+ /*
-+ * Save the termios structure, since this port may have
-+ * separate termios for callout and dialin.
-+ */
-+ if (state->info->flags & UIF_NORMAL_ACTIVE)
-+ state->normal_termios = *tty->termios;
-+ if (state->info->flags & UIF_CALLOUT_ACTIVE)
-+ state->callout_termios = *tty->termios;
-+
-+ /*
-+ * Now we wait for the transmit buffer to clear; and we notify
-+ * the line discipline to only process XON/XOFF characters by
-+ * setting tty->closing.
-+ */
-+ tty->closing = 1;
-+
-+ if (state->closing_wait != USF_CLOSING_WAIT_NONE)
-+ tty_wait_until_sent(tty, state->closing_wait);
-+
-+ /*
-+ * At this point, we stop accepting input. To do this, we
-+ * disable the receive line status interrupts.
-+ */
-+ if (state->info->flags & UIF_INITIALIZED) {
-+ unsigned long flags;
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->stop_rx(port);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+ /*
-+ * Before we drop DTR, make sure the UART transmitter
-+ * has completely drained; this is especially
-+ * important if there is a transmit FIFO!
-+ */
-+ uart_wait_until_sent(tty, port->timeout);
-+ }
-+
-+ uart_shutdown(state);
-+ uart_flush_buffer(tty);
-+ if (tty->ldisc.flush_buffer)
-+ tty->ldisc.flush_buffer(tty);
-+ tty->closing = 0;
-+ state->info->tty = NULL;
-+
-+ if (state->info->blocked_open) {
-+ if (state->close_delay) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(state->close_delay);
-+ set_current_state(TASK_RUNNING);
-+ }
-+ } else if (!uart_console(port)) {
-+ uart_change_pm(state, 3);
-+ }
-+
-+ /*
-+ * Wake up anyone trying to open this port.
-+ */
-+ state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
-+ wake_up_interruptible(&state->info->open_wait);
-+
-+ done:
-+ up(&state->sem);
-+ if (drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+}
-+
-+static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
-+{
-+ struct uart_state *state = tty->driver_data;
-+ struct uart_port *port = state->port;
-+ unsigned long char_time, expire;
-+
-+ BUG_ON(!kernel_locked());
-+
-+ if (port->type == PORT_UNKNOWN || port->fifosize == 0)
-+ return;
-+
-+ /*
-+ * Set the check interval to be 1/5 of the estimated time to
-+ * send a single character, and make it at least 1. The check
-+ * interval should also be less than the timeout.
-+ *
-+ * Note: we have to use pretty tight timings here to satisfy
-+ * the NIST-PCTS.
-+ */
-+ char_time = (port->timeout - HZ/50) / port->fifosize;
-+ char_time = char_time / 5;
-+ if (char_time == 0)
-+ char_time = 1;
-+ if (timeout && timeout < char_time)
-+ char_time = timeout;
-+
-+ /*
-+ * If the transmitter hasn't cleared in twice the approximate
-+ * amount of time to send the entire FIFO, it probably won't
-+ * ever clear. This assumes the UART isn't doing flow
-+ * control, which is currently the case. Hence, if it ever
-+ * takes longer than port->timeout, this is probably due to a
-+ * UART bug of some kind. So, we clamp the timeout parameter at
-+ * 2*port->timeout.
-+ */
-+ if (timeout == 0 || timeout > 2 * port->timeout)
-+ timeout = 2 * port->timeout;
-+
-+ expire = jiffies + timeout;
-+
-+ DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n",
-+ port->line, jiffies, expire);
-+
-+ /*
-+ * Check whether the transmitter is empty every 'char_time'.
-+ * 'timeout' / 'expire' give us the maximum amount of time
-+ * we wait.
-+ */
-+ while (!port->ops->tx_empty(port)) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(char_time);
-+ if (signal_pending(current))
-+ break;
-+ if (time_after(jiffies, expire))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING); /* might not be needed */
-+}
-+
-+/*
-+ * This is called with the BKL held in
-+ * linux/drivers/char/tty_io.c:do_tty_hangup()
-+ * We're called from the eventd thread, so we can sleep for
-+ * a _short_ time only.
-+ */
-+static void uart_hangup(struct tty_struct *tty)
-+{
-+ struct uart_state *state = tty->driver_data;
-+
-+ BUG_ON(!kernel_locked());
-+ DPRINTK("uart_hangup(%d)\n", state->port->line);
-+
-+ down(&state->sem);
-+ if (state->info && state->info->flags & (UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE)) {
-+ uart_flush_buffer(tty);
-+ uart_shutdown(state);
-+ state->count = 0;
-+ state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CALLOUT_ACTIVE);
-+ state->info->tty = NULL;
-+ wake_up_interruptible(&state->info->open_wait);
-+ wake_up_interruptible(&state->info->delta_msr_wait);
-+ }
-+ up(&state->sem);
-+}
-+
-+/*
-+ * Copy across the serial console cflag setting into the termios settings
-+ * for the initial open of the port. This allows continuity between the
-+ * kernel settings, and the settings init adopts when it opens the port
-+ * for the first time.
-+ */
-+static void uart_update_termios(struct uart_state *state)
-+{
-+ struct tty_struct *tty = state->info->tty;
-+ struct uart_port *port = state->port;
-+
-+ if (uart_console(port) && port->cons->cflag) {
-+ tty->termios->c_cflag = port->cons->cflag;
-+ port->cons->cflag = 0;
-+ }
-+
-+ /*
-+ * If the device failed to grab its irq resources,
-+ * or some other error occurred, don't try to talk
-+ * to the port hardware.
-+ */
-+ if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-+ /*
-+ * Make termios settings take effect.
-+ */
-+ uart_change_speed(state, NULL);
-+
-+ /*
-+ * And finally enable the RTS and DTR signals.
-+ */
-+ if (tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-+ }
-+}
-+
-+/*
-+ * Block the open until the port is ready. We must be called with
-+ * the per-port semaphore held.
-+ */
-+static int
-+uart_block_til_ready(struct file *filp, struct uart_state *state)
-+{
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct uart_info *info = state->info;
-+ struct uart_port *port = state->port;
-+ struct termios *termios;
-+
-+ /*
-+ * If this is a callout device, then just make sure the normal
-+ * device isn't being used.
-+ */
-+ if (info->tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-+ if (info->flags & UIF_NORMAL_ACTIVE)
-+ return -EBUSY;
-+ if ((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (info->flags & ASYNC_SESSION_LOCKOUT) &&
-+ (info->session != current->session))
-+ return -EBUSY;
-+ if ((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (info->flags & ASYNC_PGRP_LOCKOUT) &&
-+ (info->pgrp != current->pgrp))
-+ return -EBUSY;
-+ info->flags |= UIF_CALLOUT_ACTIVE;
-+ return 0;
-+ }
-+
-+ if (info->flags & UIF_CALLOUT_ACTIVE) {
-+ termios = &state->normal_termios;
-+ } else {
-+ termios = state->info->tty->termios;
-+ }
-+
-+ info->blocked_open++;
-+ state->count--;
-+
-+ add_wait_queue(&info->open_wait, &wait);
-+ while (1) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ /*
-+ * If we have been hung up, tell userspace/restart open.
-+ */
-+ if (tty_hung_up_p(filp) || info->tty == NULL)
-+ break;
-+
-+ /*
-+ * If the port has been closed, tell userspace/restart open.
-+ */
-+ if (!(info->flags & UIF_INITIALIZED))
-+ break;
-+
-+ /*
-+ * If non-blocking mode is set, or CLOCAL mode is set,
-+ * we don't want to wait for the modem status lines to
-+ * indicate that the port is ready.
-+ *
-+ * Also, if the port is not enabled/configured, we want
-+ * to allow the open to succeed here. Note that we will
-+ * have set TTY_IO_ERROR for a non-existant port.
-+ */
-+ if ((filp->f_flags & O_NONBLOCK) ||
-+ (termios->c_cflag & CLOCAL) ||
-+ (info->tty->flags & (1 << TTY_IO_ERROR))) {
-+ break;
-+ }
-+
-+ if (!(info->flags & UIF_CALLOUT_ACTIVE)) {
-+ /*
-+ * Set DTR to allow modem to know we're waiting. Do
-+ * not set RTS here - we want to make sure we catch
-+ * the data from the modem.
-+ */
-+ if (info->tty->termios->c_cflag & CBAUD)
-+ uart_set_mctrl(port, TIOCM_DTR);
-+
-+ /*
-+ * and wait for the carrier to indicate that the
-+ * modem is ready for us.
-+ */
-+ if (port->ops->get_mctrl(port) & TIOCM_CAR)
-+ break;
-+ }
-+
-+ up(&state->sem);
-+ schedule();
-+ down(&state->sem);
-+
-+ if (signal_pending(current))
-+ break;
-+ }
-+ set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&info->open_wait, &wait);
-+
-+ state->count++;
-+ info->blocked_open--;
-+
-+ info->flags |= UIF_NORMAL_ACTIVE;
-+
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+
-+ if (!info->tty || tty_hung_up_p(filp))
-+ return -EAGAIN;
-+
-+ return 0;
-+}
-+
-+static struct uart_state *uart_get(struct uart_driver *drv, int line)
-+{
-+ struct uart_state *state;
-+
-+ down(&port_sem);
-+ state = drv->state + line;
-+ if (down_interruptible(&state->sem)) {
-+ state = ERR_PTR(-ERESTARTSYS);
-+ goto out;
-+ }
-+
-+ state->count++;
-+ if (!state->port) {
-+ state->count--;
-+ up(&state->sem);
-+ state = ERR_PTR(-ENXIO);
-+ goto out;
-+ }
-+
-+ if (!state->info) {
-+ state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
-+ if (state->info) {
-+ memset(state->info, 0, sizeof(struct uart_info));
-+ init_waitqueue_head(&state->info->open_wait);
-+ init_waitqueue_head(&state->info->delta_msr_wait);
-+
-+ /*
-+ * Link the info into the other structures.
-+ */
-+ state->port->info = state->info;
-+
-+ tasklet_init(&state->info->tlet, uart_tasklet_action,
-+ (unsigned long)state);
-+ } else {
-+ state->count--;
-+ up(&state->sem);
-+ state = ERR_PTR(-ENOMEM);
-+ }
-+ }
-+
-+ out:
-+ up(&port_sem);
-+ return state;
-+}
-+
-+/*
-+ * In 2.4.5, calls to uart_open are serialised by the BKL in
-+ * linux/fs/devices.c:chrdev_open()
-+ * Note that if this fails, then uart_close() _will_ be called.
-+ */
-+static int uart_open(struct tty_struct *tty, struct file *filp)
-+{
-+ struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state;
-+ struct uart_state *state;
-+ int retval, line = MINOR(tty->device) - tty->driver.minor_start;
-+
-+ BUG_ON(!kernel_locked());
-+ DPRINTK("uart_open(%d) called\n", line);
-+
-+ /*
-+ * tty->driver->num won't change, so we won't fail here with
-+ * tty->driver_data set to something non-NULL (and therefore
-+ * we won't get caught by uart_close()).
-+ */
-+ retval = -ENODEV;
-+ if (line >= tty->driver.num)
-+ goto fail;
-+
-+ if (!try_inc_mod_count(drv->owner))
-+ goto fail;
-+
-+ /*
-+ * We take the semaphore inside uart_get to guarantee that we won't
-+ * be re-entered while allocating the info structure, or while we
-+ * request any IRQs that the driver may need. This also has the nice
-+ * side-effect that it delays the action of uart_hangup, so we can
-+ * guarantee that info->tty will always contain something reasonable.
-+ */
-+ state = uart_get(drv, line);
-+ if (IS_ERR(state)) {
-+ retval = PTR_ERR(state);
-+ if (!tty->driver_data)
-+ goto out;
-+ else
-+ goto fail;
-+ }
-+
-+ /*
-+ * Once we set tty->driver_data here, we are guaranteed that
-+ * uart_close() will decrement the driver module use count.
-+ * Any failures from here onwards should not touch the count.
-+ */
-+ tty->driver_data = state;
-+ tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
-+ tty->alt_speed = uart_get_altspeed(state->port);
-+ state->info->tty = tty;
-+
-+ /*
-+ * If the port is in the middle of closing, bail out now.
-+ */
-+ if (tty_hung_up_p(filp)) {
-+ retval = -EAGAIN;
-+ state->count--;
-+ up(&state->sem);
-+ goto fail;
-+ }
-+
-+ /*
-+ * Make sure the device is in D0 state.
-+ */
-+ if (state->count == 1)
-+ uart_change_pm(state, 0);
-+
-+ /*
-+ * Start up the serial port.
-+ */
-+ retval = uart_startup(state, 0);
-+
-+ /*
-+ * If we succeeded, wait until the port is ready.
-+ */
-+ if (retval == 0)
-+ retval = uart_block_til_ready(filp, state);
-+
-+ /*
-+ * If this is the first open to succeed, adjust things to suit.
-+ */
-+ if (retval == 0 && state->count == 1) {
-+ if (state->port->flags & UPF_SPLIT_TERMIOS) {
-+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-+ *tty->termios = state->normal_termios;
-+ else
-+ *tty->termios = state->callout_termios;
-+ }
-+
-+ uart_update_termios(state);
-+
-+ state->info->session = current->session;
-+ state->info->pgrp = current->pgrp;
-+ }
-+ up(&state->sem);
-+
-+ return 0;
-+
-+ out:
-+ if (drv->owner)
-+ __MOD_DEC_USE_COUNT(drv->owner);
-+ fail:
-+ return retval;
-+}
-+
-+static const char *uart_type(struct uart_port *port)
-+{
-+ const char *str = NULL;
-+
-+ if (port->ops->type)
-+ str = port->ops->type(port);
-+
-+ if (!str)
-+ str = "unknown";
-+
-+ return str;
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+
-+static int uart_line_info(char *buf, struct uart_driver *drv, int i)
-+{
-+ struct uart_state *state = drv->state + i;
-+ struct uart_port *port = state->port;
-+ char stat_buf[32];
-+ unsigned int status;
-+ int ret;
-+
-+ if (!port)
-+ return 0;
-+
-+ ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d",
-+ port->line, uart_type(port),
-+ port->iobase, port->irq);
-+
-+ if (port->type == PORT_UNKNOWN) {
-+ strcat(buf, "\n");
-+ return ret + 1;
-+ }
-+
-+ status = port->ops->get_mctrl(port);
-+
-+ ret += sprintf(buf + ret, " tx:%d rx:%d",
-+ port->icount.tx, port->icount.rx);
-+ if (port->icount.frame)
-+ ret += sprintf(buf + ret, " fe:%d",
-+ port->icount.frame);
-+ if (port->icount.parity)
-+ ret += sprintf(buf + ret, " pe:%d",
-+ port->icount.parity);
-+ if (port->icount.brk)
-+ ret += sprintf(buf + ret, " brk:%d",
-+ port->icount.brk);
-+ if (port->icount.overrun)
-+ ret += sprintf(buf + ret, " oe:%d",
-+ port->icount.overrun);
-+
-+#define INFOBIT(bit,str) \
-+ if (port->mctrl & (bit)) \
-+ strcat(stat_buf, (str))
-+#define STATBIT(bit,str) \
-+ if (status & (bit)) \
-+ strcat(stat_buf, (str))
-+
-+ stat_buf[0] = '\0';
-+ stat_buf[1] = '\0';
-+ INFOBIT(TIOCM_RTS, "|RTS");
-+ STATBIT(TIOCM_CTS, "|CTS");
-+ INFOBIT(TIOCM_DTR, "|DTR");
-+ STATBIT(TIOCM_DSR, "|DSR");
-+ STATBIT(TIOCM_CAR, "|CD");
-+ STATBIT(TIOCM_RNG, "|RI");
-+ if (stat_buf[0])
-+ stat_buf[0] = ' ';
-+ strcat(stat_buf, "\n");
-+
-+ ret += sprintf(buf + ret, stat_buf);
-+ return ret;
-+}
-+
-+static int uart_read_proc(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ struct tty_driver *ttydrv = data;
-+ struct uart_driver *drv = ttydrv->driver_state;
-+ int i, len = 0, l;
-+ off_t begin = 0;
-+
-+ len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
-+ "", "", "");
-+ for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) {
-+ l = uart_line_info(page + len, drv, i);
-+ len += l;
-+ if (len + begin > off + count)
-+ goto done;
-+ if (len + begin < off) {
-+ begin += len;
-+ len = 0;
-+ }
-+ }
-+ *eof = 1;
-+ done:
-+ if (off >= len + begin)
-+ return 0;
-+ *start = page + (off - begin);
-+ return (count < begin + len - off) ? count : (begin + len - off);
-+}
-+#endif
-+
-+#ifdef CONFIG_SERIAL_CORE_CONSOLE
-+/*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+struct uart_port * __init
-+uart_get_console(struct uart_port *ports, int nr, struct console *co)
-+{
-+ int idx = co->index;
-+
-+ if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
-+ ports[idx].membase == NULL))
-+ for (idx = 0; idx < nr; idx++)
-+ if (ports[idx].iobase != 0 ||
-+ ports[idx].membase != NULL)
-+ break;
-+
-+ co->index = idx;
-+
-+ return ports + idx;
-+}
-+
-+/**
-+ * uart_parse_options - Parse serial port baud/parity/bits/flow contro.
-+ * @options: pointer to option string
-+ * @baud: pointer to an 'int' variable for the baud rate.
-+ * @parity: pointer to an 'int' variable for the parity.
-+ * @bits: pointer to an 'int' variable for the number of data bits.
-+ * @flow: pointer to an 'int' variable for the flow control character.
-+ *
-+ * uart_parse_options decodes a string containing the serial console
-+ * options. The format of the string is <baud><parity><bits><flow>,
-+ * eg: 115200n8r
-+ */
-+void __init
-+uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
-+{
-+ char *s = options;
-+
-+ *baud = simple_strtoul(s, NULL, 10);
-+ while (*s >= '0' && *s <= '9')
-+ s++;
-+ if (*s)
-+ *parity = *s++;
-+ if (*s)
-+ *bits = *s++ - '0';
-+ if (*s)
-+ *flow = *s;
-+}
-+
-+struct baud_rates {
-+ unsigned int rate;
-+ unsigned int cflag;
-+};
-+
-+static struct baud_rates baud_rates[] = {
-+ { 921600, B921600 },
-+ { 460800, B460800 },
-+ { 230400, B230400 },
-+ { 115200, B115200 },
-+ { 57600, B57600 },
-+ { 38400, B38400 },
-+ { 19200, B19200 },
-+ { 9600, B9600 },
-+ { 4800, B4800 },
-+ { 2400, B2400 },
-+ { 1200, B1200 },
-+ { 0, B38400 }
-+};
-+
-+/**
-+ * uart_set_options - setup the serial console parameters
-+ * @port: pointer to the serial ports uart_port structure
-+ * @co: console pointer
-+ * @baud: baud rate
-+ * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
-+ * @bits: number of data bits
-+ * @flow: flow control character - 'r' (rts)
-+ */
-+int __init
-+uart_set_options(struct uart_port *port, struct console *co,
-+ int baud, int parity, int bits, int flow)
-+{
-+ struct termios termios;
-+ unsigned int quot;
-+ int i;
-+
-+ memset(&termios, 0, sizeof(struct termios));
-+
-+ termios.c_cflag = CREAD | HUPCL | CLOCAL;
-+
-+ /*
-+ * Construct a cflag setting.
-+ */
-+ for (i = 0; baud_rates[i].rate; i++)
-+ if (baud_rates[i].rate <= baud)
-+ break;
-+
-+ termios.c_cflag |= baud_rates[i].cflag;
-+ baud = baud_rates[i].rate;
-+ if (baud == 0)
-+ baud = 38400;
-+
-+ if (bits == 7)
-+ termios.c_cflag |= CS7;
-+ else
-+ termios.c_cflag |= CS8;
-+
-+ switch (parity) {
-+ case 'o': case 'O':
-+ termios.c_cflag |= PARODD;
-+ /*fall through*/
-+ case 'e': case 'E':
-+ termios.c_cflag |= PARENB;
-+ break;
-+ }
-+
-+ if (flow == 'r')
-+ termios.c_cflag |= CRTSCTS;
-+
-+ quot = (port->uartclk / (16 * baud));
-+ port->ops->change_speed(port, termios.c_cflag, 0, quot);
-+ co->cflag = termios.c_cflag;
-+
-+ return 0;
-+}
-+
-+extern void ambauart_console_init(void);
-+extern void anakin_console_init(void);
-+extern void clps711xuart_console_init(void);
-+extern void sa1100_rs_console_init(void);
-+extern void serial8250_console_init(void);
-+extern void at91_console_init(void);
-+
-+/*
-+ * Central "initialise all serial consoles" container. Needs to be killed.
-+ */
-+void __init uart_console_init(void)
-+{
-+#ifdef CONFIG_SERIAL_AMBA_CONSOLE
-+ ambauart_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE
-+ anakin_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
-+ clps711xuart_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-+ sa1100_rs_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_AT91_CONSOLE
-+ at91_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_8250_CONSOLE
-+ serial8250_console_init();
-+#endif
-+#ifdef CONFIG_SERIAL_UART00_CONSOLE
-+ uart00_console_init();
-+#endif
-+}
-+#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-+
-+static void uart_change_pm(struct uart_state *state, int pm_state)
-+{
-+ struct uart_port *port = state->port;
-+ if (port->ops->pm)
-+ port->ops->pm(port, pm_state, 0);
-+}
-+
-+#ifdef CONFIG_PM
-+int uart_suspend_port(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+
-+ down(&state->sem);
-+ if (port) {
-+ /*
-+ * Disable the console device before suspending.
-+ */
-+ if (uart_console(port))
-+ port->cons->flags &= ~CON_ENABLED;
-+
-+ if (state->info && state->info->flags & UIF_INITIALIZED) {
-+ struct uart_ops *ops = port->ops;
-+
-+ spin_lock_irq(&port->lock);
-+ ops->stop_tx(port, 0);
-+ ops->set_mctrl(port, 0);
-+ ops->stop_rx(port);
-+ spin_unlock_irq(&port->lock);
-+
-+ /*
-+ * Wait for the transmitter to empty.
-+ */
-+ while (!ops->tx_empty(port)) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(10*HZ/1000);
-+ }
-+ set_current_state(TASK_RUNNING);
-+
-+ ops->shutdown(port);
-+ }
-+
-+ uart_change_pm(state, 3);
-+ }
-+
-+ up(&state->sem);
-+
-+ return 0;
-+}
-+
-+int uart_resume_port(struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+
-+ down(&state->sem);
-+ if (port) {
-+ uart_change_pm(state, 0);
-+
-+ /*
-+ * Re-enable the console device after suspending.
-+ */
-+ if (uart_console(port)) {
-+ uart_change_speed(state, NULL);
-+ port->cons->flags |= CON_ENABLED;
-+ }
-+
-+ if (state->info && state->info->flags & UIF_INITIALIZED) {
-+ struct uart_ops *ops = port->ops;
-+
-+ ops->set_mctrl(port, 0);
-+ ops->startup(port);
-+ uart_change_speed(state, NULL);
-+ spin_lock_irq(&port->lock);
-+ ops->set_mctrl(port, port->mctrl);
-+ ops->start_tx(port, 0);
-+ spin_unlock_irq(&port->lock);
-+ }
-+ }
-+
-+ up(&state->sem);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Wakeup support.
-+ */
-+static int uart_pm_set_wakeup(struct uart_state *state, int data)
-+{
-+ int err = 0;
-+
-+ if (state->port->ops->set_wake)
-+ err = state->port->ops->set_wake(state->port, data);
-+
-+ return err;
-+}
-+
-+static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ struct uart_state *state = dev->data;
-+ int err = 0;
-+
-+ if (state->port && state->port->type == PORT_UNKNOWN)
-+ return 0;
-+
-+ switch (rqst) {
-+ case PM_SUSPEND:
-+ err = uart_suspend_port(state);
-+ break;
-+
-+ case PM_RESUME:
-+ err = uart_resume_port(state);
-+ break;
-+
-+ case PM_SET_WAKEUP:
-+ err = uart_pm_set_wakeup(state, (int)data);
-+ break;
-+ }
-+ return err;
-+}
-+#endif
-+
-+static inline void
-+uart_report_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ printk("%s%d at ", drv->normal_name, port->line);
-+ switch (port->iotype) {
-+ case UPIO_PORT:
-+ printk("I/O 0x%x", port->iobase);
-+ break;
-+ case UPIO_HUB6:
-+ printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
-+ break;
-+ case UPIO_MEM:
-+ printk("MMIO 0x%lx", port->mapbase);
-+ break;
-+ }
-+ printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
-+}
-+
-+static void
-+uart_configure_port(struct uart_driver *drv, struct uart_state *state,
-+ struct uart_port *port)
-+{
-+ unsigned int flags;
-+
-+ /*
-+ * If there isn't a port here, don't do anything further.
-+ */
-+ if (!port->iobase && !port->mapbase && !port->membase)
-+ return;
-+
-+ /*
-+ * Now do the auto configuration stuff. Note that config_port
-+ * is expected to claim the resources and map the port for us.
-+ */
-+ flags = UART_CONFIG_TYPE;
-+ if (port->flags & UPF_AUTO_IRQ)
-+ flags |= UART_CONFIG_IRQ;
-+ if (port->flags & UPF_BOOT_AUTOCONF) {
-+ port->type = PORT_UNKNOWN;
-+ port->ops->config_port(port, flags);
-+ }
-+
-+ if (port->type != PORT_UNKNOWN) {
-+ unsigned long flags;
-+
-+ uart_report_port(drv, port);
-+
-+ /*
-+ * Ensure that the modem control lines are de-activated.
-+ * We probably don't need a spinlock around this, but
-+ */
-+ spin_lock_irqsave(&port->lock, flags);
-+ port->ops->set_mctrl(port, 0);
-+ spin_unlock_irqrestore(&port->lock, flags);
-+
-+ /*
-+ * Power down all ports by default, except the
-+ * console if we have one.
-+ */
-+ if (!uart_console(port))
-+ uart_change_pm(state, 3);
-+ }
-+}
-+
-+/*
-+ * This reverses the effects of uart_configure_port, hanging up the
-+ * port before removal.
-+ */
-+static void
-+uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
-+{
-+ struct uart_port *port = state->port;
-+ struct uart_info *info = state->info;
-+
-+ if (info && info->tty)
-+ tty_vhangup(info->tty);
-+
-+ down(&state->sem);
-+
-+ state->info = NULL;
-+
-+ /*
-+ * Free the port IO and memory resources, if any.
-+ */
-+ if (port->type != PORT_UNKNOWN)
-+ port->ops->release_port(port);
-+
-+ /*
-+ * Indicate that there isn't a port here anymore.
-+ */
-+ port->type = PORT_UNKNOWN;
-+
-+ /*
-+ * Kill the tasklet, and free resources.
-+ */
-+ if (info) {
-+ tasklet_kill(&info->tlet);
-+ kfree(info);
-+ }
-+
-+ up(&state->sem);
-+}
-+
-+/**
-+ * uart_register_driver - register a driver with the uart core layer
-+ * @drv: low level driver structure
-+ *
-+ * Register a uart driver with the core driver. We in turn register
-+ * with the tty layer, and initialise the core driver per-port state.
-+ *
-+ * We have a proc file in /proc/tty/driver which is named after the
-+ * normal driver.
-+ *
-+ * drv->port should be NULL, and the per-port structures should be
-+ * registered using uart_add_one_port after this call has succeeded.
-+ */
-+int uart_register_driver(struct uart_driver *drv)
-+{
-+ struct tty_driver *normal, *callout;
-+ int i, retval;
-+
-+ BUG_ON(drv->state);
-+
-+ /*
-+ * Maybe we should be using a slab cache for this, especially if
-+ * we have a large number of ports to handle. Note that we also
-+ * allocate space for an integer for reference counting.
-+ */
-+ drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +
-+ sizeof(int), GFP_KERNEL);
-+ retval = -ENOMEM;
-+ if (!drv->state)
-+ goto out;
-+
-+ memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
-+ sizeof(int));
-+
-+ normal = drv->normal_driver;
-+ callout = drv->callout_driver;
-+
-+ normal->magic = TTY_DRIVER_MAGIC;
-+ normal->driver_name = drv->normal_name;
-+ normal->name = drv->normal_name;
-+ normal->major = drv->normal_major;
-+ normal->minor_start = drv->minor;
-+ normal->num = drv->nr;
-+ normal->type = TTY_DRIVER_TYPE_SERIAL;
-+ normal->subtype = SERIAL_TYPE_NORMAL;
-+ normal->init_termios = tty_std_termios;
-+ normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-+ normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-+ normal->refcount = (int *)(drv->state + drv->nr);
-+ normal->table = drv->table;
-+ normal->termios = drv->termios;
-+ normal->termios_locked = drv->termios_locked;
-+ normal->driver_state = drv;
-+
-+ normal->open = uart_open;
-+ normal->close = uart_close;
-+ normal->write = uart_write;
-+ normal->put_char = uart_put_char;
-+ normal->flush_chars = uart_flush_chars;
-+ normal->write_room = uart_write_room;
-+ normal->chars_in_buffer = uart_chars_in_buffer;
-+ normal->flush_buffer = uart_flush_buffer;
-+ normal->ioctl = uart_ioctl;
-+ normal->throttle = uart_throttle;
-+ normal->unthrottle = uart_unthrottle;
-+ normal->send_xchar = uart_send_xchar;
-+ normal->set_termios = uart_set_termios;
-+ normal->stop = uart_stop;
-+ normal->start = uart_start;
-+ normal->hangup = uart_hangup;
-+ normal->break_ctl = uart_break_ctl;
-+ normal->wait_until_sent = uart_wait_until_sent;
-+#ifdef CONFIG_PROC_FS
-+ normal->read_proc = uart_read_proc;
-+#endif
-+
-+ /*
-+ * The callout device is just like the normal device except for
-+ * the major number and the subtype code.
-+ */
-+ *callout = *normal;
-+ callout->name = drv->callout_name;
-+ callout->major = drv->callout_major;
-+ callout->subtype = SERIAL_TYPE_CALLOUT;
-+ callout->read_proc = NULL;
-+ callout->proc_entry = NULL;
-+
-+ /*
-+ * Initialise the UART state(s).
-+ */
-+ for (i = 0; i < drv->nr; i++) {
-+ struct uart_state *state = drv->state + i;
-+
-+ state->callout_termios = callout->init_termios;
-+ state->normal_termios = normal->init_termios;
-+ state->close_delay = 5 * HZ / 10;
-+ state->closing_wait = 30 * HZ;
-+
-+ init_MUTEX(&state->sem);
-+ }
-+
-+ retval = tty_register_driver(normal);
-+ if (retval)
-+ goto out;
-+
-+ retval = tty_register_driver(callout);
-+ if (retval)
-+ tty_unregister_driver(normal);
-+
-+ out:
-+ if (retval < 0) {
-+ kfree(drv->state);
-+ }
-+ return retval;
-+}
-+
-+/**
-+ * uart_unregister_driver - remove a driver from the uart core layer
-+ * @drv: low level driver structure
-+ *
-+ * Remove all references to a driver from the core driver. The low
-+ * level driver must have removed all its ports via the
-+ * uart_remove_one_port() if it registered them with uart_add_one_port().
-+ * (ie, drv->port == NULL)
-+ */
-+void uart_unregister_driver(struct uart_driver *drv)
-+{
-+ tty_unregister_driver(drv->normal_driver);
-+ tty_unregister_driver(drv->callout_driver);
-+
-+ kfree(drv->state);
-+ drv->state = NULL;
-+}
-+
-+/**
-+ * uart_add_one_port - attach a driver-defined port structure
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure to use for this port.
-+ *
-+ * This allows the driver to register its own uart_port structure
-+ * with the core driver. The main purpose is to allow the low
-+ * level uart drivers to expand uart_port, rather than having yet
-+ * more levels of structures.
-+ */
-+int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state;
-+ int ret = 0;
-+
-+ BUG_ON(in_interrupt());
-+
-+ if (port->line >= drv->nr)
-+ return -EINVAL;
-+
-+ state = drv->state + port->line;
-+
-+ down(&port_sem);
-+ if (state->port) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ state->port = port;
-+
-+ spin_lock_init(&port->lock);
-+ port->cons = drv->cons;
-+ port->info = state->info;
-+
-+ uart_configure_port(drv, state, port);
-+
-+ /*
-+ * Register the port whether it's detected or not. This allows
-+ * setserial to be used to alter this ports parameters.
-+ */
-+ tty_register_devfs(drv->normal_driver, 0, drv->minor + port->line);
-+ tty_register_devfs(drv->callout_driver, 0, drv->minor + port->line);
-+
-+#ifdef CONFIG_PM
-+ port->cons = drv->cons;
-+ state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
-+ if (state->pm)
-+ state->pm->data = state;
-+#endif
-+
-+ out:
-+ up(&port_sem);
-+
-+ return ret;
-+}
-+
-+/**
-+ * uart_remove_one_port - detach a driver defined port structure
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure for this port
-+ *
-+ * This unhooks (and hangs up) the specified port structure from the
-+ * core driver. No further calls will be made to the low-level code
-+ * for this port.
-+ */
-+int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state = drv->state + port->line;
-+
-+ BUG_ON(in_interrupt());
-+
-+ if (state->port != port)
-+ printk(KERN_ALERT "Removing wrong port: %p != %p\n",
-+ state->port, port);
-+
-+ down(&port_sem);
-+
-+ pm_unregister(state->pm);
-+
-+ /*
-+ * Remove the devices from devfs
-+ */
-+ tty_unregister_devfs(drv->normal_driver, drv->minor + port->line);
-+ tty_unregister_devfs(drv->callout_driver, drv->minor + port->line);
-+
-+ uart_unconfigure_port(drv, state);
-+ state->port = NULL;
-+ up(&port_sem);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Are the two ports equivalent?
-+ */
-+static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
-+{
-+ if (port1->iotype != port2->iotype)
-+ return 0;
-+
-+ switch (port1->iotype) {
-+ case UPIO_PORT:
-+ return (port1->iobase == port2->iobase);
-+ case UPIO_HUB6:
-+ return (port1->iobase == port2->iobase) &&
-+ (port1->hub6 == port2->hub6);
-+ case UPIO_MEM:
-+ return (port1->membase == port2->membase);
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Try to find an unused uart_state slot for a port.
-+ */
-+static struct uart_state *
-+uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port)
-+{
-+ int i;
-+
-+ /*
-+ * First, find a port entry which matches. Note: if we do
-+ * find a matching entry, and it has a non-zero use count,
-+ * then we can't register the port.
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (uart_match_port(drv->state[i].port, port))
-+ return &drv->state[i];
-+
-+ /*
-+ * We didn't find a matching entry, so look for the first
-+ * free entry. We look for one which hasn't been previously
-+ * used (indicated by zero iobase).
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (drv->state[i].port->type == PORT_UNKNOWN &&
-+ drv->state[i].port->iobase == 0 &&
-+ drv->state[i].count == 0)
-+ return &drv->state[i];
-+
-+ /*
-+ * That also failed. Last resort is to find any currently
-+ * entry which doesn't have a real port associated with it.
-+ */
-+ for (i = 0; i < drv->nr; i++)
-+ if (drv->state[i].port->type == PORT_UNKNOWN &&
-+ drv->state[i].count == 0)
-+ return &drv->state[i];
-+
-+ return NULL;
-+}
-+
-+/**
-+ * uart_register_port: register uart settings with a port
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @port: uart port structure describing the port
-+ *
-+ * Register UART settings with the specified low level driver. Detect
-+ * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the
-+ * IRQ if UPF_AUTO_IRQ is set.
-+ *
-+ * We try to pick the same port for the same IO base address, so that
-+ * when a modem is plugged in, unplugged and plugged back in, it gets
-+ * allocated the same port.
-+ *
-+ * Returns negative error, or positive line number.
-+ */
-+int uart_register_port(struct uart_driver *drv, struct uart_port *port)
-+{
-+ struct uart_state *state;
-+ int ret;
-+
-+ down(&port_sem);
-+
-+ state = uart_find_match_or_unused(drv, port);
-+
-+ if (state) {
-+ /*
-+ * Ok, we've found a line that we can use.
-+ *
-+ * If we find a port that matches this one, and it appears
-+ * to be in-use (even if it doesn't have a type) we shouldn't
-+ * alter it underneath itself - the port may be open and
-+ * trying to do useful work.
-+ */
-+ if (uart_users(state) != 0) {
-+ ret = -EBUSY;
-+ goto out;
-+ }
-+
-+ /*
-+ * If the port is already initialised, don't touch it.
-+ */
-+ if (state->port->type == PORT_UNKNOWN) {
-+ state->port->iobase = port->iobase;
-+ state->port->membase = port->membase;
-+ state->port->irq = port->irq;
-+ state->port->uartclk = port->uartclk;
-+ state->port->fifosize = port->fifosize;
-+ state->port->regshift = port->regshift;
-+ state->port->iotype = port->iotype;
-+ state->port->flags = port->flags;
-+ state->port->line = state - drv->state;
-+ state->port->mapbase = port->mapbase;
-+
-+ uart_configure_port(drv, state, state->port);
-+ }
-+
-+ ret = state->port->line;
-+ } else
-+ ret = -ENOSPC;
-+ out:
-+ up(&port_sem);
-+ return ret;
-+}
-+
-+/**
-+ * uart_unregister_port - de-allocate a port
-+ * @drv: pointer to the uart low level driver structure for this port
-+ * @line: line index previously returned from uart_register_port()
-+ *
-+ * Hang up the specified line associated with the low level driver,
-+ * and mark the port as unused.
-+ */
-+void uart_unregister_port(struct uart_driver *drv, int line)
-+{
-+ struct uart_state *state;
-+
-+ if (line < 0 || line >= drv->nr) {
-+ printk(KERN_ERR "Attempt to unregister %s%d\n",
-+ drv->normal_name, line);
-+ return;
-+ }
-+
-+ state = drv->state + line;
-+
-+ down(&port_sem);
-+ uart_unconfigure_port(drv, state);
-+ up(&port_sem);
-+}
-+
-+EXPORT_SYMBOL(uart_write_wakeup);
-+EXPORT_SYMBOL(uart_register_driver);
-+EXPORT_SYMBOL(uart_unregister_driver);
-+EXPORT_SYMBOL(uart_register_port);
-+EXPORT_SYMBOL(uart_unregister_port);
-+EXPORT_SYMBOL(uart_add_one_port);
-+EXPORT_SYMBOL(uart_remove_one_port);
-+
-+MODULE_DESCRIPTION("Serial driver core");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/serial/omaha.c
-@@ -0,0 +1,584 @@
-+/*
-+ * linux/drivers/char/omaha.c
-+ *
-+ * Driver for Omaha serial port
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright 1999-2002 ARM Limited
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: serial_amba.c,v 1.4 2001/07/17 20:34:27 rmk Exp $
-+ *
-+ * This is a generic driver for ARM AMBA-type serial ports. They
-+ * have a lot of 16550-like features, but are not register compatable.
-+ * Note that although they do have CTS, DCD and DSR inputs, they do
-+ * not have an RI input, nor do they have DTR or RTS outputs. If
-+ * required, these have to be supplied via some other means (eg, GPIO)
-+ * and hooked into this driver.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+
-+#if defined(CONFIG_SERIAL_OMAHA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+#include <asm/hardware/serial_omaha.h>
-+
-+#define UART_NR 1
-+
-+#define SERIAL_OMAHA_MAJOR 204
-+#define SERIAL_OMAHA_MINOR 32
-+#define SERIAL_OMAHA_NR UART_NR
-+
-+#define CALLOUT_OMAHA_NAME "cuaom"
-+#define CALLOUT_OMAHA_MAJOR 205
-+#define CALLOUT_OMAHA_MINOR 32
-+#define CALLOUT_OMAHA_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *omaha_table[UART_NR];
-+static struct termios *omaha_termios[UART_NR], *omaha_termios_locked[UART_NR];
-+#ifdef SUPPORT_SYSRQ
-+static struct console omaha_console;
-+#endif
-+
-+#define OMAHA_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the Omaha UARTs
-+ */
-+
-+#define UART_GET_FR(p) readb((p)->membase + OMAHA_UTRSTAT)
-+#define UART_GET_CHAR(p) readb((p)->membase + OMAHA_URXH)
-+#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + OMAHA_UTXH)
-+#define UART_GET_RSR(p) readb((p)->membase + OMAHA_UERSTAT)
-+#define UART_FIFO_STATUS(p) (readl((p)->membase + OMAHA_UFSTAT))
-+#define UART_RX_DATA(s) (((s) & OMAHA_RXFF_CNT) != 0)
-+#define UART_TX_DATA(s) (!((s) & OMAHA_TXFF))
-+#define UART_TX_READY(s) (((s) & OMAHA_UTX_EMPTY))
-+#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & OMAHA_UTXEMPTY) != 0)
-+
-+#define UART_DUMMY_RSR_RX 256
-+#define UART_PORT_SIZE 64
-+
-+#define RX_IRQ(port) ((port)->irq)
-+#define TX_IRQ(port) ((port)->irq + 5)
-+
-+/*
-+ * Our private driver data mappings.
-+ */
-+#define drv_old_status driver_priv
-+
-+static void omahauart_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+ disable_irq(TX_IRQ(port));
-+}
-+
-+static void omahauart_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
-+{
-+ if (nonempty)
-+ enable_irq(TX_IRQ(port));
-+}
-+
-+static void omahauart_stop_rx(struct uart_port *port)
-+{
-+ disable_irq(RX_IRQ(port));
-+}
-+
-+static void omahauart_enable_ms(struct uart_port *port)
-+{
-+ // Do nothing...
-+}
-+
-+static void
-+#ifdef SUPPORT_SYSRQ
-+omahauart_rx_chars(struct uart_info *info, struct pt_regs *regs)
-+#else
-+omahauart_rx_chars(struct uart_info *info)
-+#endif
-+{
-+ struct tty_struct *tty = info->tty;
-+ volatile unsigned int status, data, ch, rsr, max_count = 256;
-+ struct uart_port *port = info->port;
-+
-+ status = UART_FIFO_STATUS(port);
-+ while (UART_RX_DATA(status) && max_count--) {
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ tty->flip.tqueue.routine((void *)tty);
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-+ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
-+ return;
-+ }
-+ }
-+
-+ ch = UART_GET_CHAR(port);
-+
-+ *tty->flip.char_buf_ptr = ch;
-+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
-+ port->icount.rx++;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
-+ if (rsr & 0xf) {
-+ if (rsr & OMAHA_UART_BREAK) {
-+ rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY);
-+ port->icount.brk++;
-+ if (uart_handle_break(info, &omaha_console))
-+ goto ignore_char;
-+ } else if (rsr & OMAHA_UART_PARITY)
-+ port->icount.parity++;
-+ else if (rsr & OMAHA_UART_FRAME)
-+ port->icount.frame++;
-+ if (rsr & OMAHA_UART_OVERRUN)
-+ port->icount.overrun++;
-+
-+ rsr &= port->read_status_mask;
-+
-+ if (rsr & OMAHA_UART_BREAK)
-+ *tty->flip.flag_buf_ptr = TTY_BREAK;
-+ else if (rsr & OMAHA_UART_PARITY)
-+ *tty->flip.flag_buf_ptr = TTY_PARITY;
-+ else if (rsr & OMAHA_UART_FRAME)
-+ *tty->flip.flag_buf_ptr = TTY_FRAME;
-+ }
-+
-+ if (uart_handle_sysrq_char(info, ch, regs))
-+ goto ignore_char;
-+
-+ if ((rsr & port->ignore_status_mask) == 0) {
-+ tty->flip.flag_buf_ptr++;
-+ tty->flip.char_buf_ptr++;
-+ tty->flip.count++;
-+ }
-+ if ((rsr & OMAHA_UART_OVERRUN) &&
-+ tty->flip.count < TTY_FLIPBUF_SIZE) {
-+ /*
-+ * Overrun is special, since it's reported
-+ * immediately, and doesn't affect the current
-+ * character
-+ */
-+ *tty->flip.char_buf_ptr++ = 0;
-+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-+ tty->flip.count++;
-+ }
-+ ignore_char:
-+ status = UART_FIFO_STATUS(port);
-+ }
-+ tty_flip_buffer_push(tty);
-+ return;
-+}
-+
-+static void omahauart_tx_chars(struct uart_info *info)
-+{
-+ struct uart_port *port = info->port;
-+ volatile unsigned int status;
-+
-+ if (port->x_char) {
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+ return;
-+ }
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ omahauart_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ status = UART_FIFO_STATUS(info->port);
-+
-+ // FIll FIFO as far as possible
-+ while(UART_TX_DATA(UART_FIFO_STATUS(info->port)))
-+ {
-+ UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (info->xmit.head == info->xmit.tail)
-+ break;
-+ }
-+
-+ if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
-+ WAKEUP_CHARS)
-+ uart_event(info, EVT_WRITE_WAKEUP);
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ omahauart_stop_tx(info->port, 0);
-+}
-+
-+static void omahauart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_info *info = dev_id;
-+ volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ do {
-+ // TX if FIFO not full
-+ if (UART_TX_DATA(status))
-+ omahauart_tx_chars(info);
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ } while (UART_TX_DATA(status));
-+}
-+
-+static void omahauart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_info *info = dev_id;
-+ volatile unsigned int status, pass_counter = OMAHA_ISR_PASS_LIMIT;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ do {
-+ if (UART_RX_DATA(status))
-+#ifdef SUPPORT_SYSRQ
-+ omahauart_rx_chars(info, regs);
-+#else
-+ omahauart_rx_chars(info);
-+#endif
-+
-+ if (pass_counter-- == 0)
-+ break;
-+
-+ status = UART_FIFO_STATUS(info->port);
-+ } while (UART_RX_DATA(status));
-+}
-+
-+static u_int omahauart_tx_empty(struct uart_port *port)
-+{
-+ return UART_FIFO_STATUS(port) ? 0 : TIOCSER_TEMT;
-+}
-+
-+static int omahauart_get_mctrl(struct uart_port *port)
-+{
-+ // Report no errors.
-+
-+ return 0;
-+}
-+
-+static void omahauart_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ // Do nothing.
-+}
-+
-+static void omahauart_break_ctl(struct uart_port *port, int break_state)
-+{
-+ // Do nothing.
-+}
-+
-+static int omahauart_startup(struct uart_port *port, struct uart_info *info)
-+{
-+ unsigned int tmp;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQs
-+ */
-+ retval = request_irq(TX_IRQ(port), omahauart_int_tx, 0, "omaha_uart_tx", info);
-+ if (retval)
-+ return retval;
-+
-+ retval = request_irq(RX_IRQ(port), omahauart_int_rx, 0, "omaha_uart_rx", info);
-+
-+ if (retval)
-+ {
-+ free_irq(TX_IRQ(port), info);
-+ return retval;
-+ }
-+
-+ /*
-+ * initialise the old status of the modem signals
-+ */
-+ info->drv_old_status = 0;
-+
-+ // Clear all errors
-+ writel(0, port->membase + OMAHA_UERSTAT);
-+
-+ // Enable FIFO, 16-byte watermark, also do reset (auto-clearing)
-+ writel(0xF7, port->membase + OMAHA_UFCON);
-+
-+ // Level driven TX/RX ints, with rx timeout enabled
-+ tmp = readl(port->membase + OMAHA_UCON);
-+ tmp |= 0x280; // rx is pulse driven...
-+ writel(tmp, port->membase + OMAHA_UCON);
-+
-+ return 0;
-+}
-+
-+static void omahauart_shutdown(struct uart_port *port, struct uart_info *info)
-+{
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(TX_IRQ(port), info); /* TX interrupt */
-+ free_irq(RX_IRQ(port), info); /* RX interrupt */
-+
-+}
-+
-+static void omahauart_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ // Do nothing.
-+}
-+
-+static const char *omahauart_type(struct uart_port *port)
-+{
-+ return port->type == PORT_OMAHA ? "OMAHA" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void omahauart_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int omahauart_request_port(struct uart_port *port)
-+{
-+ return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_omaha")
-+ != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void omahauart_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ port->type = PORT_OMAHA;
-+ omahauart_request_port(port);
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int omahauart_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_OMAHA)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops omaha_pops = {
-+ .tx_empty = omahauart_tx_empty,
-+ .set_mctrl = omahauart_set_mctrl,
-+ .get_mctrl = omahauart_get_mctrl,
-+ .stop_tx = omahauart_stop_tx,
-+ .start_tx = omahauart_start_tx,
-+ .stop_rx = omahauart_stop_rx,
-+ .enable_ms = omahauart_enable_ms,
-+ .break_ctl = omahauart_break_ctl,
-+ .startup = omahauart_startup,
-+ .shutdown = omahauart_shutdown,
-+ .change_speed = omahauart_change_speed,
-+ .type = omahauart_type,
-+ .release_port = omahauart_release_port,
-+ .request_port = omahauart_request_port,
-+ .config_port = omahauart_config_port,
-+ .verify_port = omahauart_verify_port,
-+};
-+
-+static struct uart_port omaha_ports[UART_NR] = {
-+ {
-+ .membase = (void *)IO_ADDRESS(OMAHA_UART0_BASE),
-+ .mapbase = OMAHA_UART0_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = OMAHA_INT_URXD0,
-+ .uartclk = 10000000,
-+ .fifosize = 8,
-+ .unused = { 4, 5 }, /*Udriver_priv: PORT_CTRLS(5, 4), */
-+ .ops = &omaha_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+ }
-+};
-+
-+#ifdef CONFIG_SERIAL_OMAHA_CONSOLE
-+static void omahauart_console_write(struct console *co, const char *s, u_int count)
-+{
-+ struct uart_port *port = omaha_ports + co->index;
-+ unsigned int status;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the TCR
-+ */
-+ do {
-+ status = UART_GET_FR(port);
-+ } while ((status & OMAHA_UTX_EMPTY) == 0);
-+}
-+
-+static kdev_t omahauart_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_OMAHA_MAJOR, SERIAL_OMAHA_MINOR + co->index);
-+}
-+
-+static int omahauart_console_wait_key(struct console *co)
-+{
-+ struct uart_port *port = omaha_ports + co->index;
-+ unsigned int status;
-+
-+ do {
-+ status = UART_FIFO_STATUS(port);
-+ } while (!UART_RX_DATA(status));
-+ return UART_GET_CHAR(port);
-+}
-+
-+static void __init
-+omahauart_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ // Do nothing.
-+}
-+
-+static int __init omahauart_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = uart_get_console(omaha_ports, UART_NR, co);
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ omahauart_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console omaha_console = {
-+ .write = omahauart_console_write,
-+ .device = omahauart_console_device,
-+ .wait_key = omahauart_console_wait_key,
-+ .setup = omahauart_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init omahauart_console_init(void)
-+{
-+ register_console(&omaha_console);
-+}
-+
-+#define OMAHA_CONSOLE &omaha_console
-+#else
-+#define OMAHA_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver omaha_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_OMAHA_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttyOM%d",
-+ .callout_name = "cuaom%d",
-+#else
-+ .normal_name = "ttyOM",
-+ .callout_name = "cuaom",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_OMAHA_MAJOR,
-+ .callout_driver = &callout,
-+ .table = omaha_table,
-+ .termios = omaha_termios,
-+ .termios_locked = omaha_termios_locked,
-+ .minor = SERIAL_OMAHA_MINOR,
-+ .nr = UART_NR,
-+ .port = omaha_ports,
-+ .cons = OMAHA_CONSOLE,
-+};
-+
-+static int __init omahauart_init(void)
-+{
-+ return uart_register_driver(&omaha_reg);
-+}
-+
-+static void __exit omahauart_exit(void)
-+{
-+ uart_unregister_driver(&omaha_reg);
-+}
-+
-+module_init(omahauart_init);
-+module_exit(omahauart_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/serial/sa1100.c
-@@ -0,0 +1,904 @@
-+/*
-+ * linux/drivers/char/serial_sa1100.c
-+ *
-+ * Driver for SA11x0 serial ports
-+ *
-+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: sa1100.c,v 1.14.2.4 2002/10/24 09:53:25 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/tty.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/hardware.h>
-+#include <asm/mach/serial_sa1100.h>
-+
-+#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+
-+/* We've been assigned a range on the "Low-density serial ports" major */
-+#define SERIAL_SA1100_MAJOR 204
-+#define CALLOUT_SA1100_MAJOR 205
-+#define MINOR_START 5
-+
-+#define NR_PORTS 3
-+
-+#define SA1100_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Convert from ignore_status_mask or read_status_mask to UTSR[01]
-+ */
-+#define SM_TO_UTSR0(x) ((x) & 0xff)
-+#define SM_TO_UTSR1(x) ((x) >> 8)
-+#define UTSR0_TO_SM(x) ((x))
-+#define UTSR1_TO_SM(x) ((x) << 8)
-+
-+#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
-+#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
-+#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
-+#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
-+#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
-+#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
-+#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
-+
-+#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
-+#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
-+#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
-+#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
-+#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
-+#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
-+#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
-+
-+/*
-+ * This is the size of our serial port register set.
-+ */
-+#define UART_PORT_SIZE 0x24
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *sa1100_table[NR_PORTS];
-+static struct termios *sa1100_termios[NR_PORTS], *sa1100_termios_locked[NR_PORTS];
-+static int (*sa1100_open)(struct uart_port *);
-+static void (*sa1100_close)(struct uart_port *);
-+#ifdef SUPPORT_SYSRQ
-+static struct console sa1100_console;
-+#endif
-+
-+/*
-+ * This determines how often we check the modem status signals
-+ * for any change. They generally aren't connected to an IRQ
-+ * so we have to poll them. We also check immediately before
-+ * filling the TX fifo incase CTS has been dropped.
-+ */
-+#define MCTRL_TIMEOUT (250*HZ/1000)
-+
-+struct sa1100_port {
-+ struct uart_port port;
-+ struct timer_list timer;
-+ unsigned int old_status;
-+};
-+
-+/*
-+ * Handle any change of modem status signal since we were last called.
-+ */
-+static void sa1100_mctrl_check(struct sa1100_port *sport)
-+{
-+ unsigned int status, changed;
-+
-+ status = sport->port.ops->get_mctrl(&sport->port);
-+ changed = status ^ sport->old_status;
-+
-+ if (changed == 0)
-+ return;
-+
-+ sport->old_status = status;
-+
-+ if (changed & TIOCM_RI)
-+ sport->port.icount.rng++;
-+ if (changed & TIOCM_DSR)
-+ sport->port.icount.dsr++;
-+ if (changed & TIOCM_CAR)
-+ uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
-+ if (changed & TIOCM_CTS)
-+ uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
-+
-+ wake_up_interruptible(&sport->port.info->delta_msr_wait);
-+}
-+
-+/*
-+ * This is our per-port timeout handler, for checking the
-+ * modem status signals.
-+ */
-+static void sa1100_timeout(unsigned long data)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)data;
-+ unsigned long flags;
-+
-+ if (sport->port.info) {
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ sa1100_mctrl_check(sport);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+
-+ mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
-+ }
-+}
-+
-+/*
-+ * interrupts disabled on entry
-+ */
-+static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ u32 utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
-+ sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
-+}
-+
-+/*
-+ * interrupts may not be disabled on entry
-+ */
-+static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ u32 utcr3;
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ utcr3 = UART_GET_UTCR3(sport);
-+ sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
-+ UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+/*
-+ * Interrupts enabled
-+ */
-+static void sa1100_stop_rx(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ u32 utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
-+}
-+
-+/*
-+ * Set the modem control timer to fire immediately.
-+ */
-+static void sa1100_enable_ms(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ mod_timer(&sport->timer, jiffies);
-+}
-+
-+static void
-+sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
-+{
-+ struct tty_struct *tty = sport->port.info->tty;
-+ unsigned int status, ch, flg, ignored = 0;
-+
-+ status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
-+ UTSR0_TO_SM(UART_GET_UTSR0(sport));
-+ while (status & UTSR1_TO_SM(UTSR1_RNE)) {
-+ ch = UART_GET_CHAR(sport);
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ sport->port.icount.rx++;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
-+ goto handle_error;
-+
-+ if (uart_handle_sysrq_char(&sport->port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
-+ UTSR0_TO_SM(UART_GET_UTSR0(sport));
-+ }
-+ out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+ handle_error:
-+ if (status & UTSR1_TO_SM(UTSR1_PRE))
-+ sport->port.icount.parity++;
-+ else if (status & UTSR1_TO_SM(UTSR1_FRE))
-+ sport->port.icount.frame++;
-+ if (status & UTSR1_TO_SM(UTSR1_ROR))
-+ sport->port.icount.overrun++;
-+
-+ if (status & sport->port.ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+
-+ status &= sport->port.read_status_mask;
-+
-+ if (status & UTSR1_TO_SM(UTSR1_PRE))
-+ flg = TTY_PARITY;
-+ else if (status & UTSR1_TO_SM(UTSR1_FRE))
-+ flg = TTY_FRAME;
-+
-+ if (status & UTSR1_TO_SM(UTSR1_ROR)) {
-+ /*
-+ * overrun does *not* affect the character
-+ * we read from the FIFO
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ sport->port.sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void sa1100_tx_chars(struct sa1100_port *sport)
-+{
-+ struct circ_buf *xmit = &sport->port.info->xmit;
-+
-+ if (sport->port.x_char) {
-+ UART_PUT_CHAR(sport, sport->port.x_char);
-+ sport->port.icount.tx++;
-+ sport->port.x_char = 0;
-+ return;
-+ }
-+
-+ /*
-+ * Check the modem control lines before
-+ * transmitting anything.
-+ */
-+ sa1100_mctrl_check(sport);
-+
-+ if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-+ sa1100_stop_tx(&sport->port, 0);
-+ return;
-+ }
-+
-+ /*
-+ * Tried using FIFO (not checking TNF) for fifo fill:
-+ * still had the '4 bytes repeated' problem.
-+ */
-+ while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
-+ UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
-+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-+ sport->port.icount.tx++;
-+ if (uart_circ_empty(xmit))
-+ break;
-+ }
-+
-+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-+ uart_write_wakeup(&sport->port);
-+
-+ if (uart_circ_empty(xmit))
-+ sa1100_stop_tx(&sport->port, 0);
-+}
-+
-+static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct sa1100_port *sport = dev_id;
-+ unsigned int status, pass_counter = 0;
-+
-+ spin_lock(&sport->port.lock);
-+ status = UART_GET_UTSR0(sport);
-+ status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
-+ do {
-+ if (status & (UTSR0_RFS | UTSR0_RID)) {
-+ /* Clear the receiver idle bit, if set */
-+ if (status & UTSR0_RID)
-+ UART_PUT_UTSR0(sport, UTSR0_RID);
-+ sa1100_rx_chars(sport, regs);
-+ }
-+
-+ /* Clear the relevant break bits */
-+ if (status & (UTSR0_RBB | UTSR0_REB))
-+ UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
-+
-+ if (status & UTSR0_RBB)
-+ sport->port.icount.brk++;
-+
-+ if (status & UTSR0_REB)
-+ uart_handle_break(&sport->port);
-+
-+ if (status & UTSR0_TFS)
-+ sa1100_tx_chars(sport);
-+ if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
-+ break;
-+ status = UART_GET_UTSR0(sport);
-+ status &= SM_TO_UTSR0(sport->port.read_status_mask) |
-+ ~UTSR0_TFS;
-+ } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
-+ spin_unlock(&sport->port.lock);
-+}
-+
-+/*
-+ * Return TIOCSER_TEMT when transmitter is not busy.
-+ */
-+static unsigned int sa1100_tx_empty(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
-+}
-+
-+static unsigned int sa1100_get_mctrl(struct uart_port *port)
-+{
-+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
-+}
-+
-+static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
-+{
-+}
-+
-+/*
-+ * Interrupts always disabled.
-+ */
-+static void sa1100_break_ctl(struct uart_port *port, int break_state)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ unsigned int utcr3;
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+ utcr3 = UART_GET_UTCR3(sport);
-+ if (break_state == -1)
-+ utcr3 |= UTCR3_BRK;
-+ else
-+ utcr3 &= ~UTCR3_BRK;
-+ UART_PUT_UTCR3(sport, utcr3);
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+static int sa1100_startup(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(sport->port.irq, sa1100_int, 0,
-+ "sa11x0-uart", sport);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * If there is a specific "open" function
-+ * (to register control line interrupts)
-+ */
-+ if (sa1100_open) {
-+ retval = sa1100_open(port);
-+ if (retval) {
-+ free_irq(sport->port.irq, sport);
-+ return retval;
-+ }
-+ }
-+
-+ /*
-+ * Finally, clear and enable interrupts
-+ */
-+ UART_PUT_UTSR0(sport, -1);
-+ UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
-+
-+ return 0;
-+}
-+
-+static void sa1100_shutdown(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ /*
-+ * Stop our timer.
-+ */
-+ del_timer_sync(&sport->timer);
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(sport->port.irq, sport);
-+
-+ /*
-+ * If there is a specific "close" function (to unregister
-+ * control line interrupts)
-+ */
-+ if (sa1100_close)
-+ sa1100_close(port);
-+
-+ /*
-+ * Disable all interrupts, port and break condition.
-+ */
-+ UART_PUT_UTCR3(sport, 0);
-+}
-+
-+static void sa1100_change_speed(struct uart_port *port, unsigned int cflag, unsigned int iflag, unsigned int quot)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ unsigned long flags;
-+ unsigned int utcr0, old_utcr3;
-+
-+ if ((cflag & CSIZE) == CS8)
-+ utcr0 = UTCR0_DSS;
-+ else
-+ utcr0 = 0;
-+
-+ if (cflag & CSTOPB)
-+ utcr0 |= UTCR0_SBS;
-+ if (cflag & PARENB) {
-+ utcr0 |= UTCR0_PE;
-+ if (!(cflag & PARODD))
-+ utcr0 |= UTCR0_OES;
-+ }
-+
-+ spin_lock_irqsave(&sport->port.lock, flags);
-+
-+ sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
-+ sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
-+ if (iflag & INPCK)
-+ sport->port.read_status_mask |=
-+ UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-+ if (iflag & (BRKINT | PARMRK))
-+ sport->port.read_status_mask |=
-+ UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ sport->port.ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ sport->port.ignore_status_mask |=
-+ UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
-+ if (iflag & IGNBRK) {
-+ sport->port.ignore_status_mask |=
-+ UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns too (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ sport->port.ignore_status_mask |=
-+ UTSR1_TO_SM(UTSR1_ROR);
-+ }
-+
-+ del_timer_sync(&sport->timer);
-+
-+ /*
-+ * disable interrupts and drain transmitter
-+ */
-+ old_utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
-+
-+ while (UART_GET_UTSR1(sport) & UTSR1_TBY)
-+ barrier();
-+
-+ /* then, disable everything */
-+ UART_PUT_UTCR3(sport, 0);
-+
-+ /* set the parity, stop bits and data size */
-+ UART_PUT_UTCR0(sport, utcr0);
-+
-+ /* set the baud rate */
-+ quot -= 1;
-+ UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
-+ UART_PUT_UTCR2(sport, (quot & 0xff));
-+
-+ UART_PUT_UTSR0(sport, -1);
-+
-+ UART_PUT_UTCR3(sport, old_utcr3);
-+
-+ if (UART_ENABLE_MS(&sport->port, cflag))
-+ sa1100_enable_ms(&sport->port);
-+
-+ spin_unlock_irqrestore(&sport->port.lock, flags);
-+}
-+
-+static const char *sa1100_type(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'.
-+ */
-+static void sa1100_release_port(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'.
-+ */
-+static int sa1100_request_port(struct uart_port *port)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
-+ "sa11x0-uart") != NULL ? 0 : -EBUSY;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void sa1100_config_port(struct uart_port *port, int flags)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+
-+ if (flags & UART_CONFIG_TYPE &&
-+ sa1100_request_port(&sport->port) == 0)
-+ sport->port.type = PORT_SA1100;
-+}
-+
-+/*
-+ * Verify the new serial_struct (for TIOCSSERIAL).
-+ * The only change we allow are to the flags and type, and
-+ * even then only between PORT_SA1100 and PORT_UNKNOWN
-+ */
-+static int sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ struct sa1100_port *sport = (struct sa1100_port *)port;
-+ int ret = 0;
-+
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
-+ ret = -EINVAL;
-+ if (sport->port.irq != ser->irq)
-+ ret = -EINVAL;
-+ if (ser->io_type != SERIAL_IO_MEM)
-+ ret = -EINVAL;
-+ if (sport->port.uartclk / 16 != ser->baud_base)
-+ ret = -EINVAL;
-+ if ((void *)sport->port.mapbase != ser->iomem_base)
-+ ret = -EINVAL;
-+ if (sport->port.iobase != ser->port)
-+ ret = -EINVAL;
-+ if (ser->hub6 != 0)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops sa1100_pops = {
-+ .tx_empty = sa1100_tx_empty,
-+ .set_mctrl = sa1100_set_mctrl,
-+ .get_mctrl = sa1100_get_mctrl,
-+ .stop_tx = sa1100_stop_tx,
-+ .start_tx = sa1100_start_tx,
-+ .stop_rx = sa1100_stop_rx,
-+ .enable_ms = sa1100_enable_ms,
-+ .break_ctl = sa1100_break_ctl,
-+ .startup = sa1100_startup,
-+ .shutdown = sa1100_shutdown,
-+ .change_speed = sa1100_change_speed,
-+ .type = sa1100_type,
-+ .release_port = sa1100_release_port,
-+ .request_port = sa1100_request_port,
-+ .config_port = sa1100_config_port,
-+ .verify_port = sa1100_verify_port,
-+};
-+
-+static struct sa1100_port sa1100_ports[NR_PORTS];
-+
-+/*
-+ * Setup the SA1100 serial ports. Note that we don't include the IrDA
-+ * port here since we have our own SIR/FIR driver (see drivers/net/irda)
-+ *
-+ * Note also that we support "console=ttySAx" where "x" is either 0 or 1.
-+ * Which serial port this ends up being depends on the machine you're
-+ * running this kernel on. I'm not convinced that this is a good idea,
-+ * but that's the way it traditionally works.
-+ *
-+ * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
-+ * used here.
-+ */
-+static void __init sa1100_init_ports(void)
-+{
-+ static int first = 1;
-+ int i;
-+
-+ if (!first)
-+ return;
-+ first = 0;
-+
-+ for (i = 0; i < NR_PORTS; i++) {
-+ sa1100_ports[i].port.uartclk = 3686400;
-+ sa1100_ports[i].port.ops = &sa1100_pops;
-+ sa1100_ports[i].port.fifosize = 8;
-+ sa1100_ports[i].port.line = i;
-+ sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
-+ init_timer(&sa1100_ports[i].timer);
-+ sa1100_ports[i].timer.function = sa1100_timeout;
-+ sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
-+ }
-+
-+ /*
-+ * make transmit lines outputs, so that when the port
-+ * is closed, the output is in the MARK state.
-+ */
-+ PPDR |= PPC_TXD1 | PPC_TXD3;
-+ PPSR |= PPC_TXD1 | PPC_TXD3;
-+}
-+
-+void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
-+{
-+ if (fns->enable_ms)
-+ sa1100_pops.enable_ms = fns->enable_ms;
-+ if (fns->get_mctrl)
-+ sa1100_pops.get_mctrl = fns->get_mctrl;
-+ if (fns->set_mctrl)
-+ sa1100_pops.set_mctrl = fns->set_mctrl;
-+ sa1100_open = fns->open;
-+ sa1100_close = fns->close;
-+ sa1100_pops.pm = fns->pm;
-+ sa1100_pops.set_wake = fns->set_wake;
-+}
-+
-+void __init sa1100_register_uart(int idx, int port)
-+{
-+ if (idx >= NR_PORTS) {
-+ printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
-+ return;
-+ }
-+
-+ switch (port) {
-+ case 1:
-+ sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser1UART;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ case 2:
-+ sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ case 3:
-+ sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
-+ sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
-+ sa1100_ports[idx].port.irq = IRQ_Ser3UART;
-+ sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
-+ break;
-+
-+ default:
-+ printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
-+ }
-+}
-+
-+
-+#ifdef CONFIG_SERIAL_SA1100_CONSOLE
-+
-+/*
-+ * Interrupts are disabled on entering
-+ */
-+static void
-+sa1100_console_write(struct console *co, const char *s, unsigned int count)
-+{
-+ struct sa1100_port *sport = &sa1100_ports[co->index];
-+ unsigned int old_utcr3, status, i;
-+
-+ /*
-+ * First, save UTCR3 and then disable interrupts
-+ */
-+ old_utcr3 = UART_GET_UTCR3(sport);
-+ UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
-+ UTCR3_TXE);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (!(status & UTSR1_TNF));
-+ UART_PUT_CHAR(sport, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (!(status & UTSR1_TNF));
-+ UART_PUT_CHAR(sport, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore UTCR3
-+ */
-+ do {
-+ status = UART_GET_UTSR1(sport);
-+ } while (status & UTSR1_TBY);
-+ UART_PUT_UTCR3(sport, old_utcr3);
-+}
-+
-+static kdev_t sa1100_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_SA1100_MAJOR, MINOR_START + co->index);
-+}
-+
-+/*
-+ * If the port was already initialised (eg, by a boot loader), try to determine
-+ * the current setup.
-+ */
-+static void __init
-+sa1100_console_get_options(struct sa1100_port *sport, int *baud,
-+ int *parity, int *bits)
-+{
-+ unsigned int utcr3;
-+
-+ utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
-+ if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
-+ /* ok, the port was enabled */
-+ unsigned int utcr0, quot;
-+
-+ utcr0 = UART_GET_UTCR0(sport);
-+
-+ *parity = 'n';
-+ if (utcr0 & UTCR0_PE) {
-+ if (utcr0 & UTCR0_OES)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ if (utcr0 & UTCR0_DSS)
-+ *bits = 8;
-+ else
-+ *bits = 7;
-+
-+ quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
-+ quot &= 0xfff;
-+ *baud = sport->port.uartclk / (16 * (quot + 1));
-+ }
-+}
-+
-+static int __init
-+sa1100_console_setup(struct console *co, char *options)
-+{
-+ struct sa1100_port *sport;
-+ int baud = CONFIG_SA1100_DEFAULT_BAUDRATE;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow = 'n';
-+
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ if (co->index == -1 || co->index >= NR_PORTS)
-+ co->index = 0;
-+ sport = &sa1100_ports[co->index];
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ sa1100_console_get_options(sport, &baud, &parity, &bits);
-+
-+ return uart_set_options(&sport->port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console sa1100_console = {
-+ .name = "ttySA",
-+ .write = sa1100_console_write,
-+ .device = sa1100_console_device,
-+ .setup = sa1100_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = -1,
-+};
-+
-+void __init sa1100_rs_console_init(void)
-+{
-+ sa1100_init_ports();
-+ register_console(&sa1100_console);
-+}
-+
-+#define SA1100_CONSOLE &sa1100_console
-+#else
-+#define SA1100_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver sa1100_reg = {
-+ .owner = THIS_MODULE,
-+ .normal_major = SERIAL_SA1100_MAJOR,
-+#ifdef CONFIG_DEVFS_FS
-+ .normal_name = "ttySA%d",
-+ .callout_name = "cusa%d",
-+#else
-+ .normal_name = "ttySA",
-+ .callout_name = "cusa",
-+#endif
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_SA1100_MAJOR,
-+ .callout_driver = &callout,
-+ .table = sa1100_table,
-+ .termios = sa1100_termios,
-+ .termios_locked = sa1100_termios_locked,
-+ .minor = MINOR_START,
-+ .nr = NR_PORTS,
-+ .cons = SA1100_CONSOLE,
-+};
-+
-+static int __init sa1100_serial_init(void)
-+{
-+ int i, ret;
-+
-+ sa1100_init_ports();
-+
-+ ret = uart_register_driver(&sa1100_reg);
-+ if (ret)
-+ return ret;
-+
-+ for (i = 0; i < NR_PORTS; i++)
-+ uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
-+
-+ return 0;
-+}
-+
-+static void __exit sa1100_serial_exit(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NR_PORTS; i++)
-+ uart_remove_one_port(&sa1100_reg, &sa1100_ports[i].port);
-+
-+ uart_unregister_driver(&sa1100_reg);
-+}
-+
-+module_init(sa1100_serial_init);
-+module_exit(sa1100_serial_exit);
-+
-+EXPORT_NO_SYMBOLS;
-+
-+MODULE_AUTHOR("Deep Blue Solutions Ltd");
-+MODULE_DESCRIPTION("SA1100 generic serial port driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/serial/uart00.c
-@@ -0,0 +1,903 @@
-+/*
-+ * linux/drivers/serial/uart00.c
-+ *
-+ * Driver for UART00 serial ports
-+ *
-+ * Based on drivers/char/serial_amba.c, by ARM Limited &
-+ * Deep Blue Solutions Ltd.
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: uart00.c,v 1.3.2.5 2002/10/24 09:53:26 rmk Exp $
-+ *
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+#include <linux/ioport.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/console.h>
-+#include <linux/sysrq.h>
-+#include <linux/pld/pld_hotswap.h>
-+#include <linux/proc_fs.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
-+#include <asm/sizes.h>
-+
-+#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-+#define SUPPORT_SYSRQ
-+#endif
-+
-+#include <linux/serial_core.h>
-+#include <asm/arch/excalibur.h>
-+#define UART00_TYPE (volatile unsigned int*)
-+#include <asm/arch/uart00.h>
-+#include <asm/arch/int_ctrl00.h>
-+
-+#undef DEBUG
-+#define UART_NR 2
-+
-+#define SERIAL_UART00_NAME "ttyUA"
-+#define SERIAL_UART00_MAJOR 204
-+#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
-+#define SERIAL_UART00_NR UART_NR
-+#define UART_PORT_SIZE 0x50
-+
-+#define CALLOUT_UART00_NAME "cuaua"
-+#define CALLOUT_UART00_MAJOR 205
-+#define CALLOUT_UART00_MINOR 16 /* Temporary - will change in future */
-+#define CALLOUT_UART00_NR UART_NR
-+
-+static struct tty_driver normal, callout;
-+static struct tty_struct *uart00_table[UART_NR];
-+static struct termios *uart00_termios[UART_NR], *uart00_termios_locked[UART_NR];
-+static struct console uart00_console;
-+static struct uart_driver uart00_reg;
-+
-+
-+#define UART00_ISR_PASS_LIMIT 256
-+
-+/*
-+ * Access macros for the UART00 UARTs
-+ */
-+#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
-+#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
-+#define UART_GET_IES(p) inl(UART_IES((p)->membase))
-+#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
-+#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
-+#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
-+#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
-+#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
-+#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
-+#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
-+#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
-+#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
-+#define UART_GET_MC(p) inl(UART_MC((p)->membase))
-+#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
-+#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
-+#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
-+#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
-+#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
-+#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
-+#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
-+#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
-+//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
-+
-+static void uart00_stop_tx(struct uart_port *port, u_int from_tty)
-+{
-+
-+ UART_PUT_IEC(port, UART_IEC_TIE_MSK);
-+}
-+
-+static void uart00_stop_rx(struct uart_port *port)
-+{
-+
-+ UART_PUT_IEC(port, UART_IEC_RE_MSK);
-+}
-+
-+static void uart00_enable_ms(struct uart_port *port)
-+{
-+
-+ UART_PUT_IES(port, UART_IES_ME_MSK);
-+}
-+
-+static void
-+uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+ unsigned int status, ch, rds, flg, ignored = 0;
-+
-+
-+ status = UART_GET_RSR(port);
-+ while (UART_RX_DATA(status)) {
-+
-+ /*
-+ * We need to read rds before reading the
-+ * character from the fifo
-+ */
-+ rds = UART_GET_RDS(port);
-+ ch = UART_GET_CHAR(port);
-+ port->icount.rx++;
-+
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+
-+ flg = TTY_NORMAL;
-+
-+ /*
-+ * Note that the error handling code is
-+ * out of the main execution path
-+ */
-+ if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|UART_RDS_PE_MSK))
-+ goto handle_error;
-+ if (uart_handle_sysrq_char(port, ch, regs))
-+ goto ignore_char;
-+
-+ error_return:
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ ignore_char:
-+ status = UART_GET_RSR(port);
-+ }
-+out:
-+ tty_flip_buffer_push(tty);
-+ return;
-+
-+handle_error:
-+ if (rds & UART_RDS_BI_MSK) {
-+ status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
-+ port->icount.brk++;
-+
-+#ifdef SUPPORT_SYSRQ
-+ if (uart_handle_break(port))
-+ goto ignore_char;
-+#endif
-+ } else if (rds & UART_RDS_PE_MSK)
-+ port->icount.parity++;
-+ else if (rds & UART_RDS_FE_MSK)
-+ port->icount.frame++;
-+ if (rds & UART_RDS_OE_MSK)
-+ port->icount.overrun++;
-+
-+ if (rds & port->ignore_status_mask) {
-+ if (++ignored > 100)
-+ goto out;
-+ goto ignore_char;
-+ }
-+ rds &= port->read_status_mask;
-+
-+ if (rds & UART_RDS_BI_MSK)
-+ flg = TTY_BREAK;
-+ else if (rds & UART_RDS_PE_MSK)
-+ flg = TTY_PARITY;
-+ else if (rds & UART_RDS_FE_MSK)
-+ flg = TTY_FRAME;
-+
-+ if (rds & UART_RDS_OE_MSK) {
-+ /*
-+ * CHECK: does overrun affect the current character?
-+ * ASSUMPTION: it does not.
-+ */
-+ *tty->flip.flag_buf_ptr++ = flg;
-+ *tty->flip.char_buf_ptr++ = ch;
-+ tty->flip.count++;
-+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-+ goto ignore_char;
-+ ch = 0;
-+ flg = TTY_OVERRUN;
-+ }
-+#ifdef SUPPORT_SYSRQ
-+ port->sysrq = 0;
-+#endif
-+ goto error_return;
-+}
-+
-+static void uart00_tx_chars(struct uart_port *port)
-+{
-+ int count;
-+ struct uart_info *info = port->info;
-+
-+ if (port->x_char) {
-+ while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
-+ UART_PUT_CHAR(port, port->x_char);
-+ port->icount.tx++;
-+ port->x_char = 0;
-+
-+ return;
-+ }
-+ if (info->xmit.head == info->xmit.tail
-+ || info->tty->stopped
-+ || info->tty->hw_stopped) {
-+ uart00_stop_tx(port, 0);
-+ return;
-+ }
-+
-+ count = port->fifosize >> 1;
-+ do {
-+ while((UART_GET_TSR(port)& UART_TSR_TX_LEVEL_MSK)==15);
-+ UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]);
-+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
-+ port->icount.tx++;
-+ if (info->xmit.head == info->xmit.tail)
-+ break;
-+ } while (--count > 0);
-+
-+ if (CIRC_CNT(info->xmit.head,
-+ info->xmit.tail,
-+ UART_XMIT_SIZE) < WAKEUP_CHARS)
-+ uart_write_wakeup(port);
-+
-+ if (info->xmit.head == info->xmit.tail)
-+ uart00_stop_tx(port, 0);
-+}
-+
-+static void uart00_start_tx(struct uart_port *port, u_int from_tty)
-+{
-+ UART_PUT_IES(port,UART_IES_TIE_MSK );
-+ uart00_tx_chars(port);
-+}
-+
-+static void uart00_modem_status(struct uart_port *port)
-+{
-+ unsigned int status;
-+ struct uart_icount *icount = &port->icount;
-+ struct uart_info *info = port->info;
-+
-+ status = UART_GET_MSR(port);
-+
-+ if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
-+ UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))
-+ return;
-+
-+ if (status & UART_MSR_DDCD_MSK) {
-+ icount->dcd++;
-+#ifdef CONFIG_HARD_PPS
-+ if ((port->flags & ASYNC_HARDPPS_CD) &&
-+ (status & UART_MSR_DCD_MSK))
-+ hardpps();
-+#endif
-+ if (info->flags & ASYNC_CHECK_CD) {
-+ if (status & UART_MSR_DCD_MSK)
-+ wake_up_interruptible(&info->open_wait);
-+ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-+ (port->flags & ASYNC_CALLOUT_NOHUP))) {
-+ if (info->tty)
-+ tty_hangup(info->tty);
-+ }
-+ }
-+ }
-+
-+ if (status & UART_MSR_DDSR_MSK)
-+ icount->dsr++;
-+
-+ if (status & UART_MSR_DCTS_MSK) {
-+ icount->cts++;
-+
-+ if (info->flags & ASYNC_CTS_FLOW) {
-+ status &= UART_MSR_CTS_MSK;
-+
-+ if (info->tty->hw_stopped) {
-+ if (status) {
-+ info->tty->hw_stopped = 0;
-+ port->ops->start_tx(port, 0);
-+ uart_write_wakeup(port);
-+ }
-+ } else {
-+ if (!status) {
-+ info->tty->hw_stopped = 1;
-+ port->ops->stop_tx(port, 0);
-+ }
-+ }
-+ }
-+ }
-+ wake_up_interruptible(&info->delta_msr_wait);
-+
-+}
-+
-+static void uart00_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ unsigned int status, pass_counter = 0;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ do {
-+
-+ if (status & UART_ISR_RI_MSK)
-+ uart00_rx_chars(port, regs);
-+ if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
-+ uart00_tx_chars(port);
-+ if (status & UART_ISR_MI_MSK)
-+ uart00_modem_status(port);
-+ if (pass_counter++ > UART00_ISR_PASS_LIMIT)
-+ break;
-+
-+ status = UART_GET_INT_STATUS(port);
-+ } while (status);
-+}
-+
-+static u_int uart00_tx_empty(struct uart_port *port)
-+{
-+ return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
-+}
-+
-+static u_int uart00_get_mctrl(struct uart_port *port)
-+{
-+ unsigned int result = 0;
-+ unsigned int status;
-+
-+ status = UART_GET_MSR(port);
-+ if (status & UART_MSR_DCD_MSK)
-+ result |= TIOCM_CAR;
-+ if (status & UART_MSR_DSR_MSK)
-+ result |= TIOCM_DSR;
-+ if (status & UART_MSR_CTS_MSK)
-+ result |= TIOCM_CTS;
-+ if (status & UART_MCR_RI_MSK)
-+ result |= TIOCM_RNG;
-+
-+ return result;
-+}
-+
-+static void uart00_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ unsigned char mcr = 0;
-+
-+ if (mctrl & TIOCM_RTS)
-+ mcr |= UART_MCR_RTS_MSK;
-+ if (mctrl & TIOCM_DTR)
-+ mcr |= UART_MCR_DTR_MSK;
-+ if (mctrl & TIOCM_LOOP)
-+ mcr |= UART_MCR_LB_MSK;
-+
-+ UART_PUT_MCR(port, mcr);
-+}
-+
-+static void uart00_break_ctl(struct uart_port *port, int break_state)
-+{
-+ unsigned int mcr;
-+
-+ mcr = UART_GET_MCR(port);
-+ if (break_state == -1)
-+ mcr |= UART_MCR_BR_MSK;
-+ else
-+ mcr &= ~UART_MCR_BR_MSK;
-+ UART_PUT_MCR(port, mcr);
-+}
-+
-+static inline u_int uart_calculate_quot(struct uart_port *port, u_int baud)
-+{
-+ u_int quot;
-+
-+ /* Special case: B0 rate */
-+ if (!baud)
-+ baud = 9600;
-+
-+ quot = (port->uartclk / (16 * baud)-1) ;
-+
-+ return quot;
-+}
-+static void uart00_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
-+{
-+ u_int uart_mc=0, old_ies;
-+ unsigned long flags;
-+
-+#ifdef DEBUG
-+ printk("uart00_set_cflag(0x%x) called\n", cflag);
-+#endif
-+ /* byte size and parity */
-+ switch (cflag & CSIZE) {
-+ case CS5: uart_mc = UART_MC_CLS_CHARLEN_5; break;
-+ case CS6: uart_mc = UART_MC_CLS_CHARLEN_6; break;
-+ case CS7: uart_mc = UART_MC_CLS_CHARLEN_7; break;
-+ default: uart_mc = UART_MC_CLS_CHARLEN_8; break; // CS8
-+ }
-+ if (cflag & CSTOPB)
-+ uart_mc|= UART_MC_ST_TWO;
-+ if (cflag & PARENB) {
-+ uart_mc |= UART_MC_PE_MSK;
-+ if (!(cflag & PARODD))
-+ uart_mc |= UART_MC_EP_MSK;
-+ }
-+
-+ port->read_status_mask = UART_RDS_OE_MSK;
-+ if (iflag & INPCK)
-+ port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
-+ if (iflag & (BRKINT | PARMRK))
-+ port->read_status_mask |= UART_RDS_BI_MSK;
-+
-+ /*
-+ * Characters to ignore
-+ */
-+ port->ignore_status_mask = 0;
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
-+ if (iflag & IGNBRK) {
-+ port->ignore_status_mask |= UART_RDS_BI_MSK;
-+ /*
-+ * If we're ignoring parity and break indicators,
-+ * ignore overruns to (for real raw support).
-+ */
-+ if (iflag & IGNPAR)
-+ port->ignore_status_mask |= UART_RDS_OE_MSK;
-+ }
-+
-+ /* first, disable everything */
-+ save_flags(flags); cli();
-+ old_ies = UART_GET_IES(port);
-+
-+ if ((port->flags & ASYNC_HARDPPS_CD) ||
-+ (cflag & CRTSCTS) || !(cflag & CLOCAL))
-+ old_ies |= UART_IES_ME_MSK;
-+
-+
-+ /* Set baud rate */
-+ UART_PUT_DIV_LO(port, (quot & 0xff));
-+ UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-+
-+
-+ UART_PUT_MC(port, uart_mc);
-+ UART_PUT_IES(port, old_ies);
-+
-+ restore_flags(flags);
-+}
-+
-+static int uart00_startup(struct uart_port *port)
-+{
-+ int retval;
-+
-+ /*
-+ * Allocate the IRQ
-+ */
-+ retval = request_irq(port->irq, uart00_int, 0, "uart00", port);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * Finally, enable interrupts. Use the TII interrupt to minimise
-+ * the number of interrupts generated. If higher performance is
-+ * needed, consider using the TI interrupt with a suitable FIFO
-+ * threshold
-+ */
-+ UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
-+
-+ return 0;
-+}
-+
-+static void uart00_shutdown(struct uart_port *port)
-+{
-+ /*
-+ * disable all interrupts, disable the port
-+ */
-+ UART_PUT_IEC(port, 0xff);
-+
-+ /* disable break condition and fifos */
-+ UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
-+
-+ /*
-+ * Free the interrupt
-+ */
-+ free_irq(port->irq, port);
-+}
-+
-+static const char *uart00_type(struct uart_port *port)
-+{
-+ return port->type == PORT_UART00 ? "Altera UART00" : NULL;
-+}
-+
-+/*
-+ * Release the memory region(s) being used by 'port'
-+ */
-+static void uart00_release_port(struct uart_port *port)
-+{
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+ if(port->membase!=(void*)IO_ADDRESS(EXC_UART00_BASE)){
-+ iounmap(port->membase);
-+ }
-+#endif
-+}
-+
-+/*
-+ * Request the memory region(s) being used by 'port'
-+ */
-+static int uart00_request_port(struct uart_port *port)
-+{
-+ int result;
-+
-+ result = request_mem_region(port->mapbase, UART_PORT_SIZE,
-+ "serial_uart00") != NULL ? 0 : -EBUSY;
-+ if (result)
-+ return result;
-+
-+ port->membase = ioremap(port->mapbase, SZ_4K);
-+ if (!port->membase) {
-+ printk(KERN_ERR "serial00: cannot map io memory\n");
-+ release_mem_region(port->mapbase, UART_PORT_SIZE);
-+ }
-+
-+ return port->membase ? 0 : -ENOMEM;
-+}
-+
-+/*
-+ * Configure/autoconfigure the port.
-+ */
-+static void uart00_config_port(struct uart_port *port, int flags)
-+{
-+ if (flags & UART_CONFIG_TYPE) {
-+ if (uart00_request_port(port) == 0)
-+ port->type = PORT_UART00;
-+ }
-+}
-+
-+/*
-+ * verify the new serial_struct (for TIOCSSERIAL).
-+ */
-+static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
-+{
-+ int ret = 0;
-+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
-+ ret = -EINVAL;
-+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
-+ ret = -EINVAL;
-+ if (ser->baud_base < 9600)
-+ ret = -EINVAL;
-+ return ret;
-+}
-+
-+static struct uart_ops uart00_pops = {
-+ tx_empty: uart00_tx_empty,
-+ set_mctrl: uart00_set_mctrl,
-+ get_mctrl: uart00_get_mctrl,
-+ stop_tx: uart00_stop_tx,
-+ start_tx: uart00_start_tx,
-+ stop_rx: uart00_stop_rx,
-+ enable_ms: uart00_enable_ms,
-+ break_ctl: uart00_break_ctl,
-+ startup: uart00_startup,
-+ shutdown: uart00_shutdown,
-+ change_speed: uart00_change_speed,
-+ type: uart00_type,
-+ release_port: uart00_release_port,
-+ request_port: uart00_request_port,
-+ config_port: uart00_config_port,
-+ verify_port: uart00_verify_port,
-+};
-+
-+static struct uart_port uart00_ports[UART_NR] = {
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+{
-+ .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
-+ .mapbase = EXC_UART00_BASE,
-+ .iotype = SERIAL_IO_MEM,
-+ .irq = IRQ_UART,
-+ .uartclk = EXC_AHB2_CLK_FREQUENCY,
-+ .fifosize = 16,
-+ .ops = &uart00_pops,
-+ .flags = ASYNC_BOOT_AUTOCONF,
-+}
-+#endif
-+};
-+
-+#ifdef CONFIG_SERIAL_UART00_CONSOLE
-+static void uart00_console_write(struct console *co, const char *s, unsigned count)
-+{
-+#ifdef CONFIG_ARCH_CAMELOT
-+ struct uart_port *port = &uart00_ports[0];
-+ unsigned int status, old_ies;
-+ int i;
-+
-+ /*
-+ * First save the CR then disable the interrupts
-+ */
-+ old_ies = UART_GET_IES(port);
-+ UART_PUT_IEC(port,0xff);
-+
-+ /*
-+ * Now, do each character
-+ */
-+ for (i = 0; i < count; i++) {
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, s[i]);
-+ if (s[i] == '\n') {
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (!UART_TX_READY(status));
-+ UART_PUT_CHAR(port, '\r');
-+ }
-+ }
-+
-+ /*
-+ * Finally, wait for transmitter to become empty
-+ * and restore the IES
-+ */
-+ do {
-+ status = UART_GET_TSR(port);
-+ } while (status & UART_TSR_TX_LEVEL_MSK);
-+ UART_PUT_IES(port, old_ies);
-+#endif
-+}
-+
-+static kdev_t uart00_console_device(struct console *co)
-+{
-+ return MKDEV(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index);
-+}
-+
-+static void /*__init*/ uart00_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
-+{
-+ u_int uart_mc, quot;
-+ uart_mc= UART_GET_MC(port);
-+
-+ *parity = 'n';
-+ if (uart_mc & UART_MC_PE_MSK) {
-+ if (uart_mc & UART_MC_EP_MSK)
-+ *parity = 'e';
-+ else
-+ *parity = 'o';
-+ }
-+
-+ switch (uart_mc & UART_MC_CLS_MSK){
-+
-+ case UART_MC_CLS_CHARLEN_5:
-+ *bits = 5;
-+ break;
-+ case UART_MC_CLS_CHARLEN_6:
-+ *bits = 6;
-+ break;
-+ case UART_MC_CLS_CHARLEN_7:
-+ *bits = 7;
-+ break;
-+ case UART_MC_CLS_CHARLEN_8:
-+ *bits = 8;
-+ break;
-+ }
-+ quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
-+ *baud = port->uartclk / (16 *quot );
-+}
-+
-+static int __init uart00_console_setup(struct console *co, char *options)
-+{
-+ struct uart_port *port;
-+ int baud = 38400;
-+ int bits = 8;
-+ int parity = 'n';
-+ int flow= 'n';
-+
-+#ifdef CONFIG_ARCH_CAMELOT
-+ /*
-+ * Check whether an invalid uart number has been specified, and
-+ * if so, search for the first available port that does have
-+ * console support.
-+ */
-+ port = &uart00_ports[0];
-+ co->index = 0;
-+#else
-+ return -ENODEV;
-+#endif
-+
-+ if (options)
-+ uart_parse_options(options, &baud, &parity, &bits, &flow);
-+ else
-+ uart00_console_get_options(port, &baud, &parity, &bits);
-+
-+ return uart_set_options(port, co, baud, parity, bits, flow);
-+}
-+
-+static struct console uart00_console = {
-+ .name = SERIAL_UART00_NAME,
-+ .write = uart00_console_write,
-+ .device = uart00_console_device,
-+ .setup = uart00_console_setup,
-+ .flags = CON_PRINTBUFFER,
-+ .index = 0,
-+};
-+
-+void __init uart00_console_init(void)
-+{
-+ register_console(&uart00_console);
-+}
-+
-+#define UART00_CONSOLE &uart00_console
-+#else
-+#define UART00_CONSOLE NULL
-+#endif
-+
-+static struct uart_driver uart00_reg = {
-+ .owner = NULL,
-+ .normal_major = SERIAL_UART00_MAJOR,
-+ .normal_name = SERIAL_UART00_NAME,
-+ .normal_driver = &normal,
-+ .callout_major = CALLOUT_UART00_MAJOR,
-+ .callout_name = CALLOUT_UART00_NAME,
-+ .callout_driver = &callout,
-+ .table = uart00_table,
-+ .termios = uart00_termios,
-+ .termios_locked = uart00_termios_locked,
-+ .minor = SERIAL_UART00_MINOR,
-+ .nr = UART_NR,
-+ .state = NULL,
-+ .cons = UART00_CONSOLE,
-+};
-+
-+struct dev_port_entry{
-+ struct uart_port *port;
-+};
-+
-+static struct dev_port_entry dev_port_map[UART_NR];
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+/*
-+ * Keep a mapping of dev_info addresses -> port lines to use when
-+ * removing ports dev==NULL indicates unused entry
-+ */
-+
-+struct uart00_ps_data{
-+ unsigned int clk;
-+ unsigned int fifosize;
-+};
-+
-+int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
-+{
-+ struct uart00_ps_data* dev_ps=dev_ps_data;
-+ struct uart_port * port;
-+ int i,result;
-+
-+ i=0;
-+ while(dev_port_map[i].port)
-+ i++;
-+
-+ if(i==UART_NR){
-+ printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
-+ return 0;
-+ }
-+
-+ port=&uart00_ports[i];
-+
-+ printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
-+ port->membase=0;
-+ port->mapbase=dev_info->base_addr;
-+ port->iotype=SERIAL_IO_MEM;
-+ port->irq=dev_info->irq;
-+ port->uartclk=dev_ps->clk;
-+ port->fifosize=dev_ps->fifosize;
-+ port->ops=&uart00_pops;
-+ port->line=i;
-+ port->flags=ASYNC_BOOT_AUTOCONF;
-+
-+ result=uart_register_port(&uart00_reg, port);
-+ if(result<0){
-+ printk("uart_register_port returned %d\n",result);
-+ return result;
-+ }
-+ dev_port_map[i].port=port;
-+ printk("uart00: added device at %lx as ttyUA%d\n",dev_port_map[i].port->mapbase,i);
-+ return 0;
-+
-+}
-+
-+int uart00_remove_devices(void)
-+{
-+ int i,result;
-+
-+
-+ result=0;
-+ for(i=1;i<UART_NR;i++){
-+ if(dev_port_map[i].port){
-+ uart_unregister_port(&uart00_reg,i);
-+ dev_port_map[i].port=NULL;
-+ }
-+ }
-+ return 0;
-+
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+
-+
-+int uart00_proc_read(char* buf,char** start,off_t offset,int count,int *eof,void *data){
-+
-+ int i,len=0;
-+ struct uart_port *port;
-+ int limit = count - 80;
-+ char ps_data[80];
-+ if(*start)
-+ buf=*start;
-+ for(i=0;(i<UART_NR)&&(len<limit);i++){
-+ if(dev_port_map[i].port){
-+ port=dev_port_map[i].port;
-+ sprintf(ps_data,"clk, %dHz, fifo size, %dbytes",
-+ port->uartclk,port->fifosize);
-+ len+=PLDHS_READ_PROC_DATA(buf+len,"uart00",i,
-+ port->mapbase,port->irq,ps_data);
-+
-+ }
-+ }
-+ *eof=1;
-+ return len;
-+}
-+
-+
-+
-+#endif
-+struct pld_hotswap_ops uart00_pldhs_ops={
-+ .name = "uart00",
-+ .add_device = uart00_add_device,
-+ .remove_devices = uart00_remove_devices,
-+ .proc_read = uart00_proc_read
-+};
-+
-+#endif
-+
-+static int __init uart00_init(void)
-+{
-+ int ret;
-+ int i;
-+
-+ ret = uart_register_driver(&uart00_reg);
-+ if (ret) {
-+ printk(KERN_ERR "uart00: Couldn't register driver\n");
-+ return ret;
-+ }
-+
-+ unregister_console(&uart00_console);
-+
-+ for(i=0;i<UART_NR;i++){
-+ uart00_ports[i].ops=&uart00_pops;
-+ }
-+
-+ printk(KERN_WARNING "uart00:Using temporary major/minor pairs - these WILL change in the future\n");
-+
-+#ifdef CONFIG_PLD_HOTSWAP
-+ pldhs_register_driver(&uart00_pldhs_ops);
-+#endif
-+ for (i=0; i<UART_NR; i++)
-+ uart_add_one_port(&uart00_reg,&uart00_ports[i]);
-+
-+ uart00_console.flags = 0;
-+ register_console(&uart00_console);
-+#ifdef CONFIG_ARCH_CAMELOT
-+ dev_port_map[0].port=uart00_ports;
-+#endif
-+ return ret;
-+}
-+
-+
-+__initcall(uart00_init);
-+
-+
---- linux-2.4.27/drivers/sound/.version
-+++ /dev/null
-@@ -1,2 +0,0 @@
--3.8s
--0x030804
---- linux-2.4.27/drivers/sound/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/sound/Config.in
-@@ -131,6 +131,17 @@
- dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI
- dep_mbool ' VIA 82C686 MIDI' CONFIG_MIDI_VIA82CXXX $CONFIG_SOUND_VIA82CXXX
-
-+if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-+ dep_tristate ' StrongARM-11x0 Sound Drivers' CONFIG_SOUND_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_SOUND
-+ dep_tristate ' UDA1341 Stereo Codec' CONFIG_SOUND_UDA1341 $CONFIG_L3 $CONFIG_SOUND_SA1100 $CONFIG_SOUND
-+ dep_tristate ' Assabet audio support' CONFIG_SOUND_ASSABET_UDA1341 $CONFIG_SA1100_ASSABET $CONFIG_SOUND_UDA1341
-+ dep_tristate ' Compaq iPAQ audio support' CONFIG_SOUND_H3600_UDA1341 $CONFIG_SA1100_H3600 $CONFIG_SOUND_UDA1341
-+ dep_tristate ' Pangolin audio support' CONFIG_SOUND_PANGOLIN_UDA1341 $CONFIG_SA1100_PANGOLIN $CONFIG_SOUND_UDA1341
-+ dep_tristate ' SA1111 audio support' CONFIG_SOUND_SA1111_UDA1341 $CONFIG_SA1111 $CONFIG_SOUND_UDA1341
-+ dep_tristate ' SA1111 AC97 Sound' CONFIG_SOUND_SA1111_AC97 $CONFIG_SA1111 $CONFIG_SOUND_SA1100
-+ dep_tristate ' Generic DAC on the SA11x0 SSP port' CONFIG_SOUND_SA1100SSP $CONFIG_SOUND_SA1100
-+fi
-+
- dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
-
- if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
-@@ -220,14 +231,14 @@
- bool ' Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
- fi
- fi
-+
-+fi
-
-- if [ "$CONFIG_ARM" = "y" ]; then
-- if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
-- dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
-- fi
-- dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
-+if [ "$CONFIG_ARM" = "y" ]; then
-+ if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" -o "$CONFIG_ARCH_RISCSTATION" ]; then
-+ dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
- fi
--
-+ dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
- fi
-
- dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
---- linux-2.4.27/drivers/sound/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/sound/Makefile
-@@ -10,7 +10,8 @@
- export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
- msnd.o opl3.o sb_common.o sequencer_syms.o \
- sound_core.o sound_syms.o uart401.o \
-- nm256_audio.o ac97.o ac97_codec.o aci.o
-+ nm256_audio.o ac97.o ac97_codec.o aci.o \
-+ sa1100-audio.o
-
- # Each configuration option enables a list of files.
-
-@@ -76,6 +77,14 @@
- obj-$(CONFIG_SOUND_FORTE) += forte.o ac97_codec.o
- obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
- obj-$(CONFIG_SOUND_HARMONY) += harmony.o
-+obj-$(CONFIG_SOUND_SA1100) += sa1100-audio.o
-+obj-$(CONFIG_SOUND_UDA1341) += uda1341.o
-+obj-$(CONFIG_SOUND_ASSABET_UDA1341) += assabet-uda1341.o
-+obj-$(CONFIG_SOUND_PANGOLIN_UDA1341) += pangolin-uda1341.o
-+obj-$(CONFIG_SOUND_H3600_UDA1341) += h3600-uda1341.o
-+obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o
-+obj-$(CONFIG_SOUND_SA1111_AC97) += sa1111-ac97.o ac97_codec.o
-+obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o
- obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o
- obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
- obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o
-@@ -105,7 +114,6 @@
- obj-y += dmasound/dmasound.o
- endif
-
--
- # Declare multi-part drivers.
-
- list-multi := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
---- /dev/null
-+++ linux-2.4.27/drivers/sound/assabet-uda1341.c
-@@ -0,0 +1,404 @@
-+/*
-+ * Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Assabet/UDA1341 support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
-+ *
-+ * 2001-08-03 Russell King Fix left/right channel swap.
-+ * Attempt to reduce power consumption when idle.
-+ *
-+ * 2001-09-23 Russell King Remove old L3 bus driver.
-+ *
-+ * Please note that fiddling too much with MDREFR results in oopses, so we don't
-+ * touch MDREFR unnecessarily, which means we don't touch it on close.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/cpufreq.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/arch/assabet.h>
-+
-+#include "sa1100-audio.h"
-+
-+/*
-+ * Define this to fix the power drain on early Assabets
-+ */
-+#define FIX_POWER_DRAIN
-+
-+/*
-+ * Debugging?
-+ */
-+#undef DEBUG
-+
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+/*
-+ * Mixer (UDA1341) interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations assabet_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+/*
-+ * FIXME: what about SFRM going high when SSP is disabled?
-+ */
-+static void assabet_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ u_int clk_ref, clk_div;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * Our clock source is derived from the CPLD on which we don't have
-+ * much control unfortunately. This was intended for a fixed 48000 Hz
-+ * samplerate assuming a core clock of 221.2 MHz. The CPLD appears
-+ * to divide the memory clock so there is a ratio of 4608 between
-+ * the core clock and the resulting samplerate (obtained by
-+ * measurements, the CPLD equations should confirm that).
-+ *
-+ * Still we can play with the SA1110's clock divisor for the SSP port
-+ * to get half the samplerate as well.
-+ *
-+ * Apparently the clock sent to the SA1110 for the SSP port is further
-+ * more divided from the clock sent to the UDA1341 (some people tried
-+ * to be too clever in their design, or simply failed to read the
-+ * SA1110 manual). If it was the same clock we would have been able
-+ * to support a third samplerate with the UDA1341's 384FS mode.
-+ *
-+ * At least it would have been a minimum acceptable solution to be
-+ * able to set the CPLD divisor by software. The iPAQ design is
-+ * certainly a better example to follow for a new design.
-+ */
-+ clk_ref = cpufreq_get(0) * 1000 / 4608;
-+ if (val > clk_ref*4/7) {
-+ audio_samplerate = clk_ref;
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(2);
-+ } else {
-+ audio_samplerate = clk_ref/2;
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(4);
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+}
-+
-+/*
-+ * Initialise the Assabet audio driver.
-+ *
-+ * Note that we have to be careful with the order that we do things here;
-+ * there is a D-type flip flop which is clocked from the SFRM line which
-+ * indicates whether the same is for the left or right channel to the
-+ * UDA1341.
-+ *
-+ * When you disable the SSP (by clearing SSCR0_SSE) it appears that the
-+ * SFRM signal can float high. When you re-enable the SSP, you clock the
-+ * flip flop once, and end up swapping the left and right channels.
-+ *
-+ * The ASSABET_BCR_CODEC_RST line will force this flip flop into a known
-+ * state, but this line resets other devices as well!
-+ *
-+ * In addition to the above, it appears that powering down the UDA1341 on
-+ * early Assabets leaves the UDA_WS actively driving a logic '1' into the
-+ * chip, wasting power! (you can tell this by D11 being half-on). We
-+ * attempt to correct this by kicking the flip flop on init/open/close.
-+ * We should probably do this on PM resume as well.
-+ *
-+ * (Note the ordering of ASSABET_BCR_AUDIO_ON, SFRM and ASSABET_BCR_CODEC_RST
-+ * is important).
-+ */
-+static void assabet_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+ unsigned int mdrefr;
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ * Enable the power for the UDA1341 before driving any signals.
-+ * We leave the audio amp (LM4880) disabled for now.
-+ */
-+ ASSABET_BCR_set(ASSABET_BCR_AUDIO_ON);
-+
-+#ifdef FIX_POWER_DRAIN
-+ GPSR = GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+#endif
-+
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ ASSABET_BCR_clear(ASSABET_BCR_STEREO_LB);
-+
-+ /*
-+ * Setup the SSP uart.
-+ */
-+ PPAR |= PPAR_SPR;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK;
-+ GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
-+ GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ /*
-+ * Only give SFRM to the SSP after it has been enabled.
-+ */
-+ GAFR |= GPIO_SSP_SFRM;
-+
-+ /*
-+ * The assabet board uses the SDRAM clock as the source clock for
-+ * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
-+ * At 206MHz we need to run the audio clock (SDRAM bank 2)
-+ * at half speed. This clock will scale with core frequency so
-+ * the audio sample rate will also scale. The CPLD on Assabet
-+ * will need to be programmed to match the core frequency.
-+ */
-+ mdrefr = MDREFR;
-+ if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
-+ MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
-+ mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
-+ mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
-+ MDREFR = mdrefr;
-+ (void) MDREFR;
-+ }
-+ local_irq_restore(flags);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ mdelay(1);
-+
-+ l3_open(&uda1341);
-+
-+ assabet_set_samplerate(audio_samplerate);
-+
-+ /* Enable the audio power */
-+ ASSABET_BCR_clear(ASSABET_BCR_QMUTE | ASSABET_BCR_SPK_OFF);
-+}
-+
-+/*
-+ * Shutdown the Assabet audio driver.
-+ *
-+ * We have to be careful about the SFRM line here for the same reasons
-+ * described in the initialisation comments above. This basically means
-+ * that we must hand the SSP pins back to the GPIO module before disabling
-+ * the SSP.
-+ *
-+ * In addition, to reduce power drain, we toggle the SFRM line once so
-+ * that the UDA_WS line is at logic 0.
-+ *
-+ * We can't clear ASSABET_BCR_CODEC_RST without knowing if the UCB1300 or
-+ * ADV7171 driver is still active. If it is, then we still need to play
-+ * games, so we might as well leave ASSABET_BCR_CODEC_RST set.
-+ */
-+static void assabet_audio_shutdown(void *dummy)
-+{
-+ ASSABET_BCR_set(ASSABET_BCR_STEREO_LB | ASSABET_BCR_QMUTE |
-+ ASSABET_BCR_SPK_OFF);
-+
-+ l3_close(&uda1341);
-+
-+ GAFR &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
-+ Ser4SSCR0 = 0;
-+
-+#ifdef FIX_POWER_DRAIN
-+ GPSR = GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+#endif
-+
-+ /* disable the audio power */
-+ ASSABET_BCR_clear(ASSABET_BCR_AUDIO_ON);
-+}
-+
-+static int assabet_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ assabet_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do signed 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Assabet UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "Assabet UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: assabet_audio_init,
-+ hw_shutdown: assabet_audio_shutdown,
-+ client_ioctl: assabet_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int assabet_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations assabet_audio_fops = {
-+ open: assabet_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init assabet_uda1341_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_assabet())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&assabet_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&assabet_mixer_fops, -1);
-+
-+#ifdef FIX_POWER_DRAIN
-+ {
-+ unsigned long flags;
-+ local_irq_save(flags);
-+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
-+ GPSR = GPIO_SSP_SFRM;
-+ GPDR |= GPIO_SSP_SFRM;
-+ GPCR = GPIO_SSP_SFRM;
-+ local_irq_restore(flags);
-+ }
-+#endif
-+
-+ printk(KERN_INFO "Sound: Assabet UDA1341: dsp id %d mixer id %d\n",
-+ audio_dev_id, mixer_dev_id);
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit assabet_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(assabet_uda1341_init);
-+module_exit(assabet_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1110 Assabet board & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/h3600-uda1341.c
-@@ -0,0 +1,352 @@
-+/*
-+ * Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Compaq iPAQ (aka Bitsy) support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release.
-+ *
-+ * 2000-07-?? George France Bitsy support.
-+ *
-+ * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+//#include <asm/arch/h3600_hal.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "Bitsy_UDA1341"
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations h3600_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+/*
-+ * Stop-gap solution until rest of hh.org HAL stuff is merged.
-+ */
-+#define GPIO_H3600_CLK_SET0 GPIO_GPIO (12)
-+#define GPIO_H3600_CLK_SET1 GPIO_GPIO (13)
-+static void h3600_set_audio_clock(long val)
-+{
-+ switch (val) {
-+ case 24000: case 32000: case 48000: /* 00: 12.288 MHz */
-+ GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 22050: case 29400: case 44100: /* 01: 11.2896 MHz */
-+ GPSR = GPIO_H3600_CLK_SET0;
-+ GPCR = GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 8000: case 10666: case 16000: /* 10: 4.096 MHz */
-+ GPCR = GPIO_H3600_CLK_SET0;
-+ GPSR = GPIO_H3600_CLK_SET1;
-+ break;
-+
-+ case 10985: case 14647: case 21970: /* 11: 5.6245 MHz */
-+ GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-+ break;
-+ }
-+}
-+
-+static void h3600_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ int clk_div = 0;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * We have the following clock sources:
-+ * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
-+ * Those can be divided either by 256, 384 or 512.
-+ * This makes up 12 combinations for the following samplerates...
-+ */
-+ if (val >= 48000)
-+ val = 48000;
-+ else if (val >= 44100)
-+ val = 44100;
-+ else if (val >= 32000)
-+ val = 32000;
-+ else if (val >= 29400)
-+ val = 29400;
-+ else if (val >= 24000)
-+ val = 24000;
-+ else if (val >= 22050)
-+ val = 22050;
-+ else if (val >= 21970)
-+ val = 21970;
-+ else if (val >= 16000)
-+ val = 16000;
-+ else if (val >= 14647)
-+ val = 14647;
-+ else if (val >= 10985)
-+ val = 10985;
-+ else if (val >= 10666)
-+ val = 10666;
-+ else
-+ val = 8000;
-+
-+ /* Set the external clock generator */
-+ h3600_set_audio_clock(val);
-+
-+ /* Select the clock divisor */
-+ switch (val) {
-+ case 8000:
-+ case 10985:
-+ case 22050:
-+ case 24000:
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(16);
-+ break;
-+ case 16000:
-+ case 21970:
-+ case 44100:
-+ case 48000:
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(8);
-+ break;
-+ case 10666:
-+ case 14647:
-+ case 29400:
-+ case 32000:
-+ cfg.fs = 384;
-+ clk_div = SSCR0_SerClkDiv(12);
-+ break;
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+ audio_samplerate = val;
-+}
-+
-+static void h3600_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+
-+ /* Setup the uarts */
-+ local_irq_save(flags);
-+ GAFR |= (GPIO_SSP_CLK);
-+ GPDR &= ~(GPIO_SSP_CLK);
-+ Ser4SSCR0 = 0;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ /* Enable the audio power */
-+
-+ clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ set_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
-+ set_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+ local_irq_restore(flags);
-+
-+ /* external clock configuration */
-+ h3600_set_samplerate(audio_samplerate);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ set_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ mdelay(1);
-+
-+ /* make the left and right channels unswapped (flip the WS latch ) */
-+ Ser4SSDR = 0;
-+
-+ /* Initialize the UDA1341 internal state */
-+ l3_open(&uda1341);
-+
-+ clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+}
-+
-+static void h3600_audio_shutdown(void *dummy)
-+{
-+ /* disable the audio power and all signals leading to the audio chip */
-+ l3_close(&uda1341);
-+ Ser4SSCR0 = 0;
-+ clr_h3600_egpio(IPAQ_EGPIO_CODEC_NRESET);
-+ clr_h3600_egpio(IPAQ_EGPIO_AUDIO_ON);
-+ clr_h3600_egpio(IPAQ_EGPIO_QMUTE);
-+}
-+
-+static int h3600_audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ h3600_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: h3600_audio_init,
-+ hw_shutdown: h3600_audio_shutdown,
-+ client_ioctl: h3600_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int h3600_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations h3600_audio_fops = {
-+ open: h3600_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init h3600_uda1341_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_h3xxx())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&h3600_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&h3600_mixer_fops, -1);
-+
-+ printk( KERN_INFO "iPAQ audio support initialized\n" );
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit h3600_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(h3600_uda1341_init);
-+module_exit(h3600_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre, George France");
-+MODULE_DESCRIPTION("Glue audio driver for the Compaq iPAQ H3600 & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/pangolin-uda1341.c
-@@ -0,0 +1,322 @@
-+/*
-+ * Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This is the machine specific part of the Pangolin/UDA1341 support.
-+ * This driver makes use of the UDA1341 and the sa1100-audio modules.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-17 Nicolas Pitre Supports 44100Hz and 22050Hz samplerate now.
-+ *
-+ * 2001-08-06 Richard Fan Pangolin Support
-+ *
-+ * 2001-09-23 Russell King Update inline with Assabet driver
-+ * Remove old L3 bus driver
-+ *
-+ * Note: this should probably be merged with the Assabet audio driver,
-+ * and become the "SDRAM-clock driven" SA1100 audio driver.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+/*
-+ * Debugging?
-+ */
-+#undef DEBUG
-+
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_RATE_DEFAULT 44100
-+
-+#define QmutePin GPIO_GPIO(4)
-+#define SpeakerOffPin GPIO_GPIO(5)
-+
-+/*
-+ * Mixer (UDA1341) interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations pangolin_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+static long audio_samplerate = AUDIO_RATE_DEFAULT;
-+
-+static void pangolin_set_samplerate(long val)
-+{
-+ struct uda1341_cfg cfg;
-+ int clk_div;
-+
-+ /* We don't want to mess with clocks when frames are in flight */
-+ Ser4SSCR0 &= ~SSCR0_SSE;
-+ /* wait for any frame to complete */
-+ udelay(125);
-+
-+ /*
-+ * Our clock source is derived from the CPLD on which we don't have
-+ * much control unfortunately. This was intended for a fixed 44100Hz
-+ * samplerate assuming a core clock of 206 MHz. Still we can play
-+ * with the SA1110's clock divisor for the SSP port to get a 22050Hz
-+ * samplerate.
-+ *
-+ * Apparently the clock sent to the SA1110 for the SSP port is
-+ * divided from the clock sent to the UDA1341 (some people tried to
-+ * be too clever in their design, or simply failed to read the SA1110
-+ * manual). If it was the same source we would have been able to
-+ * support a third samplerate.
-+ *
-+ * At least it would have been a minimum acceptable solution to be
-+ * able to set the CPLD divisor by software. The iPAQ design is
-+ * certainly a better example to follow for a new design.
-+ */
-+ if (val >= 44100) {
-+ audio_samplerate = 44100;
-+ cfg.fs = 256;
-+ clk_div = SSCR0_SerClkDiv(2);
-+ } else {
-+ audio_samplerate = 22050;
-+ cfg.fs = 512;
-+ clk_div = SSCR0_SerClkDiv(4);
-+ }
-+
-+ cfg.format = FMT_LSB16;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-+}
-+
-+static void pangolin_audio_init(void *dummy)
-+{
-+ unsigned long flags;
-+ unsigned int mdrefr;
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ * Setup the SSP uart.
-+ */
-+ PPAR |= PPAR_SPR;
-+ Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(2);
-+ Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-+ GAFR |= GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_CLK |
-+ GPIO_SSP_SFRM;
-+ GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
-+ GPDR &= ~(GPIO_SSP_RXD | GPIO_SSP_CLK);
-+ Ser4SSCR0 |= SSCR0_SSE;
-+
-+ GAFR &= ~(SpeakerOffPin | QmutePin);
-+ GPDR |= (SpeakerOffPin | QmutePin);
-+ GPCR = SpeakerOffPin;
-+
-+ /*
-+ * The assabet board uses the SDRAM clock as the source clock for
-+ * audio. This is supplied to the SA11x0 from the CPLD on pin 19.
-+ * At 206MHz we need to run the audio clock (SDRAM bank 2)
-+ * at half speed. This clock will scale with core frequency so
-+ * the audio sample rate will also scale. The CPLD on Assabet
-+ * will need to be programmed to match the core frequency.
-+ */
-+ mdrefr = MDREFR;
-+ if ((mdrefr & (MDREFR_K2DB2 | MDREFR_K2RUN | MDREFR_EAPD |
-+ MDREFR_KAPD)) != (MDREFR_K2DB2 | MDREFR_K2RUN)) {
-+ mdrefr |= MDREFR_K2DB2 | MDREFR_K2RUN;
-+ mdrefr &= ~(MDREFR_EAPD | MDREFR_KAPD);
-+ MDREFR = mdrefr;
-+ (void) MDREFR;
-+ }
-+ local_irq_restore(flags);
-+
-+ /* Wait for the UDA1341 to wake up */
-+ mdelay(100);
-+
-+ l3_open(&uda1341);
-+
-+ pangolin_set_samplerate(audio_samplerate);
-+
-+ GPCR = QmutePin;
-+}
-+
-+static void pangolin_audio_shutdown(void *dummy)
-+{
-+ GPSR = QmutePin;
-+
-+ l3_close(&uda1341);
-+
-+ Ser4SSCR0 = 0;
-+ MDREFR &= ~(MDREFR_K2DB2 | MDREFR_K2RUN);
-+}
-+
-+static int pangolin_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ pangolin_set_samplerate(val);
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(audio_samplerate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do signed 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Pangolin UDA1341 out",
-+ input_stream: &input_stream,
-+ input_dma: DMA_Ser4SSPRd,
-+ input_id: "Pangolin UDA1341 in",
-+ need_tx_for_rx: 1,
-+ hw_init: pangolin_audio_init,
-+ hw_shutdown: pangolin_audio_shutdown,
-+ client_ioctl: pangolin_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int pangolin_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations pangolin_audio_fops = {
-+ open: pangolin_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init pangolin_uda1341_init(void)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ if (!machine_is_pangolin())
-+ return -ENODEV;
-+
-+ ret = l3_attach_client(&uda1341, "l3-bit-sa1100-gpio", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&pangolin_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&pangolin_mixer_fops, -1);
-+
-+ local_irq_save(flags);
-+ GAFR &= ~(SpeakerOffPin | QmutePin);
-+ GPDR |= (SpeakerOffPin | QmutePin);
-+ local_irq_restore(flags);
-+
-+ printk(KERN_INFO "Pangolin UDA1341 audio driver initialized\n");
-+ return 0;
-+
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ return ret;
-+}
-+
-+static void __exit pangolin_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ l3_detach_client(&uda1341);
-+}
-+
-+module_init(pangolin_uda1341_init);
-+module_exit(pangolin_uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1110 Pangolin board & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/sa1100-audio.c
-@@ -0,0 +1,976 @@
-+/*
-+ * Common audio handling for the SA11x0 processor
-+ *
-+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ *
-+ * This module handles the generic buffering/DMA/mmap audio interface for
-+ * codecs connected to the SA1100 chip. All features depending on specific
-+ * hardware implementations like supported audio formats or samplerates are
-+ * relegated to separate specific modules.
-+ *
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2000-06-10 Erik Bunce Add initial poll support.
-+ *
-+ * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the
-+ * generic SA1100 DMA interface.
-+ *
-+ * 2000-11-30 Nicolas Pitre - Validation of opened instances;
-+ * - Power handling at open/release time instead
-+ * of driver load/unload;
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-07-22 Nicolas Pitre - added mmap() and realtime support
-+ * - corrected many details to better comply
-+ * with the OSS API
-+ *
-+ * 2001-10-19 Nicolas Pitre - brought DMA registration processing
-+ * into this module for better ressource
-+ * management. This also fixes a bug
-+ * with the suspend/resume logic.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/poll.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/sysrq.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/semaphore.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+/* #define DEBUG 1 */
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "sa1100-audio"
-+#define AUDIO_NBFRAGS_DEFAULT 8
-+#define AUDIO_FRAGSIZE_DEFAULT 8192
-+
-+#define NEXT_BUF(_s_,_b_) { \
-+ (_s_)->_b_##_idx++; \
-+ (_s_)->_b_##_idx %= (_s_)->nbfrags; \
-+ (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; }
-+
-+#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
-+
-+/*
-+ * This function frees all buffers
-+ */
-+
-+static void audio_clear_buf(audio_stream_t * s)
-+{
-+ DPRINTK("audio_clear_buf\n");
-+
-+ /* ensure DMA won't run anymore */
-+ s->active = 0;
-+ s->stopped = 0;
-+ sa1100_dma_flush_all(s->dma_ch);
-+
-+ if (s->buffers) {
-+ int frag;
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ if (!s->buffers[frag].master)
-+ continue;
-+ consistent_free(s->buffers[frag].start,
-+ s->buffers[frag].master,
-+ s->buffers[frag].dma_addr);
-+ }
-+ kfree(s->buffers);
-+ s->buffers = NULL;
-+ }
-+
-+ s->buf_idx = 0;
-+ s->buf = NULL;
-+}
-+
-+
-+/*
-+ * This function allocates the buffer structure array and buffer data space
-+ * according to the current number of fragments and fragment size.
-+ */
-+
-+static int audio_setup_buf(audio_stream_t * s)
-+{
-+ int frag;
-+ int dmasize = 0;
-+ char *dmabuf = NULL;
-+ dma_addr_t dmaphys = 0;
-+
-+ if (s->buffers)
-+ return -EBUSY;
-+
-+ s->buffers = (audio_buf_t *)
-+ kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
-+ if (!s->buffers)
-+ goto err;
-+ memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
-+
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+
-+ /*
-+ * Let's allocate non-cached memory for DMA buffers.
-+ * We try to allocate all memory at once.
-+ * If this fails (a common reason is memory fragmentation),
-+ * then we allocate more smaller buffers.
-+ */
-+ if (!dmasize) {
-+ dmasize = (s->nbfrags - frag) * s->fragsize;
-+ do {
-+ dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
-+ dmasize,
-+ &dmaphys);
-+ if (!dmabuf)
-+ dmasize -= s->fragsize;
-+ } while (!dmabuf && dmasize);
-+ if (!dmabuf)
-+ goto err;
-+ b->master = dmasize;
-+ memzero(dmabuf, dmasize);
-+ }
-+
-+ b->start = dmabuf;
-+ b->dma_addr = dmaphys;
-+ b->stream = s;
-+ sema_init(&b->sem, 1);
-+ DPRINTK("buf %d: start %p dma %p\n", frag, b->start,
-+ b->dma_addr);
-+
-+ dmabuf += s->fragsize;
-+ dmaphys += s->fragsize;
-+ dmasize -= s->fragsize;
-+ }
-+
-+ s->buf_idx = 0;
-+ s->buf = &s->buffers[0];
-+ s->bytecount = 0;
-+ s->getptrCount = 0;
-+ s->fragcount = 0;
-+
-+ return 0;
-+
-+err:
-+ printk(AUDIO_NAME ": unable to allocate audio memory\n ");
-+ audio_clear_buf(s);
-+ return -ENOMEM;
-+}
-+
-+
-+/*
-+ * This function yanks all buffers from the DMA code's control and
-+ * resets them ready to be used again.
-+ */
-+
-+static void audio_reset_buf(audio_stream_t * s)
-+{
-+ int frag;
-+
-+ s->active = 0;
-+ s->stopped = 0;
-+ sa1100_dma_flush_all(s->dma_ch);
-+ if (s->buffers) {
-+ for (frag = 0; frag < s->nbfrags; frag++) {
-+ audio_buf_t *b = &s->buffers[frag];
-+ b->size = 0;
-+ sema_init(&b->sem, 1);
-+ }
-+ }
-+ s->bytecount = 0;
-+ s->getptrCount = 0;
-+ s->fragcount = 0;
-+}
-+
-+
-+/*
-+ * DMA callback functions
-+ */
-+
-+static void audio_dmaout_done_callback(void *buf_id, int size)
-+{
-+ audio_buf_t *b = (audio_buf_t *) buf_id;
-+ audio_stream_t *s = b->stream;
-+
-+ /* Accounting */
-+ s->bytecount += size;
-+ s->fragcount++;
-+
-+ /* Recycle buffer */
-+ if (s->mapped)
-+ sa1100_dma_queue_buffer(s->dma_ch, buf_id,
-+ b->dma_addr, s->fragsize);
-+ else
-+ up(&b->sem);
-+
-+ /* And any process polling on write. */
-+ wake_up(&s->wq);
-+}
-+
-+static void audio_dmain_done_callback(void *buf_id, int size)
-+{
-+ audio_buf_t *b = (audio_buf_t *) buf_id;
-+ audio_stream_t *s = b->stream;
-+
-+ /* Accounting */
-+ s->bytecount += size;
-+ s->fragcount++;
-+
-+ /* Recycle buffer */
-+ if (s->mapped) {
-+ sa1100_dma_queue_buffer(s->dma_ch, buf_id,
-+ b->dma_addr, s->fragsize);
-+ } else {
-+ b->size = size;
-+ up(&b->sem);
-+ }
-+
-+ /* And any process polling on write. */
-+ wake_up(&s->wq);
-+}
-+
-+static int audio_sync(struct file *file)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ audio_buf_t *b;
-+
-+ DPRINTK("audio_sync\n");
-+
-+ if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped)
-+ return 0;
-+
-+ /*
-+ * Send current buffer if it contains data. Be sure to send
-+ * a full sample count.
-+ */
-+ b = s->buf;
-+ if (b->size &= ~3) {
-+ down(&b->sem);
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, b->size);
-+ b->size = 0;
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ /*
-+ * Let's wait for the last buffer we sent i.e. the one before the
-+ * current buf_idx. When we acquire the semaphore, this means either:
-+ * - DMA on the buffer completed or
-+ * - the buffer was already free thus nothing else to sync.
-+ */
-+ b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags);
-+ if (down_interruptible(&b->sem))
-+ return -EINTR;
-+ up(&b->sem);
-+ return 0;
-+}
-+
-+
-+static int audio_write(struct file *file, const char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ const char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->output_stream;
-+ int chunksize, ret = 0;
-+
-+ DPRINTK("audio_write: count=%d\n", count);
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+
-+ while (count > 0) {
-+ audio_buf_t *b = s->buf;
-+
-+ /* Wait for a buffer to become free */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&b->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&b->sem))
-+ break;
-+ }
-+
-+ /* Feed the current buffer */
-+ chunksize = s->fragsize - b->size;
-+ if (chunksize > count)
-+ chunksize = count;
-+ DPRINTK("write %d to %d\n", chunksize, s->buf_idx);
-+ if (copy_from_user(b->start + b->size, buffer, chunksize)) {
-+ up(&b->sem);
-+ return -EFAULT;
-+ }
-+ b->size += chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->size < s->fragsize) {
-+ up(&b->sem);
-+ break;
-+ }
-+
-+ /* Send current buffer to dma */
-+ s->active = 1;
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, b->size);
-+ b->size = 0; /* indicate that the buffer has been sent */
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ DPRINTK("audio_write: return=%d\n", ret);
-+ return ret;
-+}
-+
-+
-+static inline void audio_check_tx_spin(audio_state_t *state)
-+{
-+ /*
-+ * With some codecs like the Philips UDA1341 we must ensure
-+ * there is an output stream at any time while recording since
-+ * this is how the UDA1341 gets its clock from the SA1100.
-+ * So while there is no playback data to send, the output DMA
-+ * will spin with all zeroes. We use the cache flush special
-+ * area for that.
-+ */
-+ if (state->need_tx_for_rx && !state->tx_spinning) {
-+ sa1100_dma_set_spin(state->output_stream->dma_ch,
-+ (dma_addr_t)FLUSH_BASE_PHYS, 2048);
-+ state->tx_spinning = 1;
-+ }
-+}
-+
-+
-+static void audio_prime_dma(audio_stream_t *s)
-+{
-+ int i;
-+
-+ s->active = 1;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *b = s->buf;
-+ down(&b->sem);
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, s->fragsize);
-+ NEXT_BUF(s, buf);
-+ }
-+}
-+
-+
-+static int audio_read(struct file *file, char *buffer,
-+ size_t count, loff_t * ppos)
-+{
-+ char *buffer0 = buffer;
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s = state->input_stream;
-+ int chunksize, ret = 0;
-+
-+ DPRINTK("audio_read: count=%d\n", count);
-+
-+ if (ppos != &file->f_pos)
-+ return -ESPIPE;
-+ if (s->mapped)
-+ return -ENXIO;
-+
-+ if (!s->active) {
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ audio_check_tx_spin(state);
-+ audio_prime_dma(s);
-+ }
-+
-+ while (count > 0) {
-+ audio_buf_t *b = s->buf;
-+
-+ /* Wait for a buffer to become full */
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ if (down_trylock(&b->sem))
-+ break;
-+ } else {
-+ ret = -ERESTARTSYS;
-+ if (down_interruptible(&b->sem))
-+ break;
-+ }
-+
-+ /* Grab data from the current buffer */
-+ chunksize = b->size;
-+ if (chunksize > count)
-+ chunksize = count;
-+ DPRINTK("read %d from %d\n", chunksize, s->buf_idx);
-+ if (copy_to_user(buffer,
-+ b->start + s->fragsize - b->size,
-+ chunksize)) {
-+ up(&b->sem);
-+ return -EFAULT;
-+ }
-+ b->size -= chunksize;
-+ buffer += chunksize;
-+ count -= chunksize;
-+ if (b->size > 0) {
-+ up(&b->sem);
-+ break;
-+ }
-+
-+ /* Make current buffer available for DMA again */
-+ sa1100_dma_queue_buffer(s->dma_ch, (void *) b,
-+ b->dma_addr, s->fragsize);
-+ NEXT_BUF(s, buf);
-+ }
-+
-+ if ((buffer - buffer0))
-+ ret = buffer - buffer0;
-+ DPRINTK("audio_read: return=%d\n", ret);
-+ return ret;
-+}
-+
-+
-+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *s;
-+ unsigned long size, vma_addr;
-+ int i, ret;
-+
-+ if (vma->vm_pgoff != 0)
-+ return -EINVAL;
-+
-+ if (vma->vm_flags & VM_WRITE) {
-+ if (!state->wr_ref)
-+ return -EINVAL;;
-+ s = state->output_stream;
-+ } else if (vma->vm_flags & VM_READ) {
-+ if (!state->rd_ref)
-+ return -EINVAL;
-+ s = state->input_stream;
-+ } else return -EINVAL;
-+
-+ if (s->mapped)
-+ return -EINVAL;
-+ size = vma->vm_end - vma->vm_start;
-+ if (size != s->fragsize * s->nbfrags)
-+ return -EINVAL;
-+ if (!s->buffers && audio_setup_buf(s))
-+ return -ENOMEM;
-+ vma_addr = vma->vm_start;
-+ for (i = 0; i < s->nbfrags; i++) {
-+ audio_buf_t *buf = &s->buffers[i];
-+ if (!buf->master)
-+ continue;
-+ ret = remap_page_range(vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);
-+ if (ret)
-+ return ret;
-+ vma_addr += buf->master;
-+ }
-+ s->mapped = 1;
-+
-+ return 0;
-+}
-+
-+
-+static unsigned int audio_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *is = state->input_stream;
-+ audio_stream_t *os = state->output_stream;
-+ unsigned int mask = 0;
-+ int i;
-+
-+ DPRINTK("audio_poll(): mode=%s%s\n",
-+ (file->f_mode & FMODE_READ) ? "r" : "",
-+ (file->f_mode & FMODE_WRITE) ? "w" : "");
-+
-+ if (file->f_mode & FMODE_READ) {
-+ /* Start audio input if not already active */
-+ if (!is->active) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ audio_check_tx_spin(state);
-+ audio_prime_dma(is);
-+ }
-+ poll_wait(file, &is->wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ poll_wait(file, &os->wq, wait);
-+ }
-+
-+ if (file->f_mode & FMODE_READ) {
-+ if (is->mapped) {
-+/* if the buffer is mapped assume we care that there are more bytes available than
-+ when we last asked using SNDCTL_DSP_GETxPTR */
-+ if (is->bytecount != is->getptrCount)
-+ mask |= POLLIN | POLLRDNORM;
-+ } else {
-+ for (i = 0; i < is->nbfrags; i++) {
-+ if (atomic_read(&is->buffers[i].sem.count) > 0) {
-+ mask |= POLLIN | POLLRDNORM;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (os->mapped) {
-+ if (os->bytecount != os->getptrCount)
-+ mask |= POLLOUT | POLLWRNORM;
-+ } else {
-+ for (i = 0; i < os->nbfrags; i++) {
-+ if (atomic_read(&os->buffers[i].sem.count) > 0) {
-+ mask |= POLLOUT | POLLWRNORM;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+ DPRINTK("audio_poll() returned mask of %s%s\n",
-+ (mask & POLLIN) ? "r" : "",
-+ (mask & POLLOUT) ? "w" : "");
-+
-+ return mask;
-+}
-+
-+
-+static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
-+{
-+ return -ESPIPE;
-+}
-+
-+
-+static int audio_set_fragments(audio_stream_t *s, int val)
-+{
-+ if (s->active)
-+ return -EBUSY;
-+ if (s->buffers)
-+ audio_clear_buf(s);
-+ s->nbfrags = (val >> 16) & 0x7FFF;
-+ val &= 0xffff;
-+ if (val < 4)
-+ val = 4;
-+ if (val > 15)
-+ val = 15;
-+ s->fragsize = 1 << val;
-+ if (s->nbfrags < 2)
-+ s->nbfrags = 2;
-+ if (s->nbfrags * s->fragsize > 128 * 1024)
-+ s->nbfrags = 128 * 1024 / s->fragsize;
-+ if (audio_setup_buf(s))
-+ return -ENOMEM;
-+ return val|(s->nbfrags << 16);
-+}
-+
-+static int audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ audio_stream_t *os = state->output_stream;
-+ audio_stream_t *is = state->input_stream;
-+ long val;
-+
-+ /* dispatch based on command */
-+ switch (cmd) {
-+ case OSS_GETVERSION:
-+ return put_user(SOUND_VERSION, (int *)arg);
-+
-+ case SNDCTL_DSP_GETBLKSIZE:
-+ if (file->f_mode & FMODE_WRITE)
-+ return put_user(os->fragsize, (int *)arg);
-+ else
-+ return put_user(is->fragsize, (int *)arg);
-+
-+ case SNDCTL_DSP_GETCAPS:
-+ val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
-+ if (is && os)
-+ val |= DSP_CAP_DUPLEX;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETFRAGMENT:
-+ if (get_user(val, (long *) arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ int ret = audio_set_fragments(is, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ int ret = audio_set_fragments(os, val);
-+ if (ret < 0)
-+ return ret;
-+ ret = put_user(ret, (int *)arg);
-+ if (ret)
-+ return ret;
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_SYNC:
-+ return audio_sync(file);
-+
-+ case SNDCTL_DSP_SETDUPLEX:
-+ return 0;
-+
-+ case SNDCTL_DSP_POST:
-+ return 0;
-+
-+ case SNDCTL_DSP_GETTRIGGER:
-+ val = 0;
-+ if (file->f_mode & FMODE_READ && is->active && !is->stopped)
-+ val |= PCM_ENABLE_INPUT;
-+ if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
-+ val |= PCM_ENABLE_OUTPUT;
-+ return put_user(val, (int *)arg);
-+
-+ case SNDCTL_DSP_SETTRIGGER:
-+ if (get_user(val, (int *)arg))
-+ return -EFAULT;
-+ if (file->f_mode & FMODE_READ) {
-+ if (val & PCM_ENABLE_INPUT) {
-+ if (!is->active) {
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ audio_prime_dma(is);
-+ }
-+ audio_check_tx_spin(state);
-+ if (is->stopped) {
-+ is->stopped = 0;
-+ sa1100_dma_resume(is->dma_ch);
-+ }
-+ } else {
-+ sa1100_dma_stop(is->dma_ch);
-+ is->stopped = 1;
-+ }
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ if (val & PCM_ENABLE_OUTPUT) {
-+ if (!os->active) {
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ if (os->mapped)
-+ audio_prime_dma(os);
-+ }
-+ if (os->stopped) {
-+ os->stopped = 0;
-+ sa1100_dma_resume(os->dma_ch);
-+ }
-+ } else {
-+ sa1100_dma_stop(os->dma_ch);
-+ os->stopped = 1;
-+ }
-+ }
-+ return 0;
-+
-+ case SNDCTL_DSP_GETOPTR:
-+ case SNDCTL_DSP_GETIPTR:
-+ {
-+ count_info inf = { 0, };
-+ audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
-+ audio_buf_t *b;
-+ dma_addr_t ptr;
-+ int bytecount, offset, flags;
-+
-+ if ((s == is && !(file->f_mode & FMODE_READ)) ||
-+ (s == os && !(file->f_mode & FMODE_WRITE)))
-+ return -EINVAL;
-+ if (s->active) {
-+ save_flags_cli(flags);
-+ if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
-+ offset = ptr - b->dma_addr;
-+ inf.ptr = (b - s->buffers) * s->fragsize + offset;
-+ } else offset = 0;
-+ bytecount = s->bytecount + offset;
-+ s->getptrCount = s->bytecount; /* so poll can tell if it changes */
-+ inf.blocks = s->fragcount;
-+ s->fragcount = 0;
-+ restore_flags(flags);
-+ if (bytecount < 0)
-+ bytecount = 0;
-+ inf.bytes = bytecount;
-+ }
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETOSPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ int i;
-+
-+ if (!(file->f_mode & FMODE_WRITE))
-+ return -EINVAL;
-+ if (!os->buffers && audio_setup_buf(os))
-+ return -ENOMEM;
-+ for (i = 0; i < os->nbfrags; i++) {
-+ if (atomic_read(&os->buffers[i].sem.count) > 0) {
-+ if (os->buffers[i].size == 0)
-+ inf.fragments++;
-+ inf.bytes += os->fragsize - os->buffers[i].size;
-+ }
-+ }
-+ inf.fragstotal = os->nbfrags;
-+ inf.fragsize = os->fragsize;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_GETISPACE:
-+ {
-+ audio_buf_info inf = { 0, };
-+ int i;
-+
-+ if (!(file->f_mode & FMODE_READ))
-+ return -EINVAL;
-+ if (!is->buffers && audio_setup_buf(is))
-+ return -ENOMEM;
-+ for (i = 0; i < is->nbfrags; i++) {
-+ if (atomic_read(&is->buffers[i].sem.count) > 0) {
-+ if (is->buffers[i].size == is->fragsize)
-+ inf.fragments++;
-+ inf.bytes += is->buffers[i].size;
-+ }
-+ }
-+ inf.fragstotal = is->nbfrags;
-+ inf.fragsize = is->fragsize;
-+ return copy_to_user((void *)arg, &inf, sizeof(inf));
-+ }
-+
-+ case SNDCTL_DSP_NONBLOCK:
-+ file->f_flags |= O_NONBLOCK;
-+ return 0;
-+
-+ case SNDCTL_DSP_RESET:
-+ if (file->f_mode & FMODE_READ) {
-+ if (state->tx_spinning) {
-+ sa1100_dma_set_spin(os->dma_ch, 0, 0);
-+ state->tx_spinning = 0;
-+ }
-+ audio_reset_buf(is);
-+ }
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_reset_buf(os);
-+ }
-+ return 0;
-+
-+ default:
-+ /*
-+ * Let the client of this module handle the
-+ * non generic ioctls
-+ */
-+ return state->client_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int audio_release(struct inode *inode, struct file *file)
-+{
-+ audio_state_t *state = (audio_state_t *)file->private_data;
-+ DPRINTK("audio_release\n");
-+
-+ down(&state->sem);
-+
-+ if (file->f_mode & FMODE_READ) {
-+ if (state->tx_spinning) {
-+ sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0);
-+ state->tx_spinning = 0;
-+ }
-+ audio_clear_buf(state->input_stream);
-+ if (!state->skip_dma_init) {
-+ sa1100_free_dma(state->input_stream->dma_ch);
-+ if (state->need_tx_for_rx && !state->wr_ref)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ }
-+ state->rd_ref = 0;
-+ }
-+
-+ if (file->f_mode & FMODE_WRITE) {
-+ audio_sync(file);
-+ audio_clear_buf(state->output_stream);
-+ if (!state->skip_dma_init)
-+ if (!state->need_tx_for_rx || !state->rd_ref)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ state->wr_ref = 0;
-+ }
-+
-+ if (!AUDIO_ACTIVE(state)) {
-+ if (state->hw_shutdown)
-+ state->hw_shutdown(state->data);
-+#ifdef CONFIG_PM
-+ pm_unregister(state->pm_dev);
-+#endif
-+ }
-+
-+ up(&state->sem);
-+ return 0;
-+}
-+
-+
-+#ifdef CONFIG_PM
-+
-+static int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
-+{
-+ audio_state_t *state = (audio_state_t *)pm_dev->data;
-+
-+ switch (req) {
-+ case PM_SUSPEND: /* enter D1-D3 */
-+ if (state->output_stream)
-+ sa1100_dma_sleep(state->output_stream->dma_ch);
-+ if (state->input_stream)
-+ sa1100_dma_sleep(state->input_stream->dma_ch);
-+ if (AUDIO_ACTIVE(state) && state->hw_shutdown)
-+ state->hw_shutdown(state->data);
-+ break;
-+ case PM_RESUME: /* enter D0 */
-+ if (AUDIO_ACTIVE(state) && state->hw_init)
-+ state->hw_init(state->data);
-+ if (state->input_stream)
-+ sa1100_dma_wakeup(state->input_stream->dma_ch);
-+ if (state->output_stream)
-+ sa1100_dma_wakeup(state->output_stream->dma_ch);
-+ break;
-+ }
-+ return 0;
-+}
-+
-+#endif
-+
-+
-+int sa1100_audio_attach(struct inode *inode, struct file *file,
-+ audio_state_t *state)
-+{
-+ int err, need_tx_dma;
-+
-+ DPRINTK("audio_open\n");
-+
-+ down(&state->sem);
-+
-+ /* access control */
-+ err = -ENODEV;
-+ if ((file->f_mode & FMODE_WRITE) && !state->output_stream)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && !state->input_stream)
-+ goto out;
-+ err = -EBUSY;
-+ if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
-+ goto out;
-+ if ((file->f_mode & FMODE_READ) && state->rd_ref)
-+ goto out;
-+ err = -EINVAL;
-+ if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)
-+ goto out;
-+
-+ /* request DMA channels */
-+ if (state->skip_dma_init)
-+ goto skip_dma;
-+ need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
-+ ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
-+ if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
-+ need_tx_dma = 0;
-+ if (need_tx_dma) {
-+ err = sa1100_request_dma(&state->output_stream->dma_ch,
-+ state->output_id,
-+ state->output_dma);
-+ if (err)
-+ goto out;
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ err = sa1100_request_dma(&state->input_stream->dma_ch,
-+ state->input_id,
-+ state->input_dma);
-+ if (err) {
-+ if (need_tx_dma)
-+ sa1100_free_dma(state->output_stream->dma_ch);
-+ goto out;
-+ }
-+ }
-+skip_dma:
-+
-+ /* now complete initialisation */
-+ if (!AUDIO_ACTIVE(state)) {
-+ if (state->hw_init)
-+ state->hw_init(state->data);
-+#ifdef CONFIG_PM
-+ state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);
-+ if (state->pm_dev)
-+ state->pm_dev->data = state;
-+#endif
-+ }
-+
-+ if ((file->f_mode & FMODE_WRITE)) {
-+ state->wr_ref = 1;
-+ audio_clear_buf(state->output_stream);
-+ state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ state->output_stream->mapped = 0;
-+ sa1100_dma_set_callback(state->output_stream->dma_ch,
-+ audio_dmaout_done_callback);
-+ init_waitqueue_head(&state->output_stream->wq);
-+ }
-+ if (file->f_mode & FMODE_READ) {
-+ state->rd_ref = 1;
-+ audio_clear_buf(state->input_stream);
-+ state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
-+ state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
-+ state->input_stream->mapped = 0;
-+ sa1100_dma_set_callback(state->input_stream->dma_ch,
-+ audio_dmain_done_callback);
-+ init_waitqueue_head(&state->input_stream->wq);
-+ }
-+
-+ file->private_data = state;
-+ file->f_op->release = audio_release;
-+ file->f_op->write = audio_write;
-+ file->f_op->read = audio_read;
-+ file->f_op->mmap = audio_mmap;
-+ file->f_op->poll = audio_poll;
-+ file->f_op->ioctl = audio_ioctl;
-+ file->f_op->llseek = audio_llseek;
-+ err = 0;
-+
-+out:
-+ up(&state->sem);
-+ return err;
-+}
-+
-+EXPORT_SYMBOL(sa1100_audio_attach);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Common audio handling for the SA11x0 processor");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ linux-2.4.27/drivers/sound/sa1100-audio.h
-@@ -0,0 +1,68 @@
-+/*
-+ * Common audio handling for the SA11x0
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+
-+/*
-+ * Buffer Management
-+ */
-+
-+typedef struct {
-+ int size; /* buffer size */
-+ char *start; /* points to actual buffer */
-+ dma_addr_t dma_addr; /* physical buffer address */
-+ struct semaphore sem; /* down before touching the buffer */
-+ int master; /* owner for buffer allocation, contain size when true */
-+ struct audio_stream_s *stream; /* owning stream */
-+} audio_buf_t;
-+
-+typedef struct audio_stream_s {
-+ audio_buf_t *buffers; /* pointer to audio buffer structures */
-+ audio_buf_t *buf; /* current buffer used by read/write */
-+ u_int buf_idx; /* index for the pointer above... */
-+ u_int fragsize; /* fragment i.e. buffer size */
-+ u_int nbfrags; /* nbr of fragments i.e. buffers */
-+ int bytecount; /* nbr of processed bytes */
-+ int getptrCount; /* value of bytecount last time anyone asked via GETxPTR */
-+ int fragcount; /* nbr of fragment transitions */
-+ dmach_t dma_ch; /* DMA channel ID */
-+ wait_queue_head_t wq; /* for poll */
-+ int mapped:1; /* mmap()'ed buffers */
-+ int active:1; /* actually in progress */
-+ int stopped:1; /* might be active but stopped */
-+} audio_stream_t;
-+
-+/*
-+ * State structure for one instance
-+ */
-+
-+typedef struct {
-+ audio_stream_t *output_stream;
-+ audio_stream_t *input_stream;
-+ dma_device_t output_dma;
-+ dma_device_t input_dma;
-+ char *output_id;
-+ char *input_id;
-+ int rd_ref:1; /* open reference for recording */
-+ int wr_ref:1; /* open reference for playback */
-+ int need_tx_for_rx:1; /* if data must be sent while receiving */
-+ int tx_spinning:1; /* tx spinning active */
-+ int skip_dma_init:1; /* hack for the SA1111 */
-+ void *data;
-+ void (*hw_init)(void *);
-+ void (*hw_shutdown)(void *);
-+ int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
-+ struct pm_dev *pm_dev;
-+ struct semaphore sem; /* to protect against races in attach() */
-+} audio_state_t;
-+
-+/*
-+ * Functions exported by this module
-+ */
-+extern int sa1100_audio_attach( struct inode *inode, struct file *file,
-+ audio_state_t *state);
---- /dev/null
-+++ linux-2.4.27/drivers/sound/sa1100ssp.c
-@@ -0,0 +1,182 @@
-+/*
-+ * Glue audio driver for a simple DAC on the SA1100's SSP port
-+ *
-+ * Copyright (c) 2001 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-06-04 Nicolas Pitre Initial release.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+
-+#include "sa1100-audio.h"
-+
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+#define AUDIO_NAME "SA1100 SSP audio"
-+
-+#define AUDIO_FMT AFMT_S16_LE
-+#define AUDIO_CHANNELS 2
-+
-+static int sample_rate = 44100;
-+
-+
-+static void ssp_audio_init(void)
-+{
-+ if (machine_is_lart()) {
-+ unsigned long flags;
-+ local_irq_save(flags);
-+
-+ /* LART has the SSP port rewired to GPIO 10-13, 19 */
-+ /* alternate functions for the GPIOs */
-+ GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK |
-+ GPIO_SSP_SFRM | GPIO_SSP_CLK );
-+
-+ /* Set the direction: 10, 12, 13 output; 11, 19 input */
-+ GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM );
-+ GPDR &= ~( GPIO_SSP_RXD | GPIO_SSP_CLK );
-+
-+ /* enable SSP pin swap */
-+ PPAR |= PPAR_SPR;
-+
-+ local_irq_restore(flags);
-+ }
-+
-+ /* turn on the SSP */
-+ Ser4SSCR0 = 0;
-+ Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2) |
-+ SSCR0_SSE);
-+ Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk);
-+}
-+
-+static void ssp_audio_shutdown(void)
-+{
-+ Ser4SSCR0 = 0;
-+}
-+
-+static int ssp_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* Simple standard DACs are stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* Simple standard DACs are stereo only */
-+ return put_user(AUDIO_CHANNELS, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ case SOUND_PCM_READ_RATE:
-+ /* We assume the clock doesn't change */
-+ return put_user(sample_rate, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* Simple standard DACs are 16-bit only */
-+ return put_user(AUDIO_FMT, (long *) arg);
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ output_dma: DMA_Ser4SSPWr,
-+ output_id: "Generic SSP sound",
-+ hw_init: ssp_audio_init,
-+ hw_shutdown: ssp_audio_shutdown,
-+ client_ioctl: ssp_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int ssp_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations ssp_audio_fops = {
-+ open: ssp_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+static int audio_dev_id;
-+
-+static int __init sa1100ssp_audio_init(void)
-+{
-+ int ret;
-+
-+ if (!machine_is_lart()) {
-+ printk(KERN_ERR AUDIO_NAME ": no support for this SA-1100 design!\n");
-+ /* look at ssp_audio_init() for specific initialisations */
-+ return -ENODEV;
-+ }
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&ssp_audio_fops, -1);
-+
-+ printk( KERN_INFO AUDIO_NAME " initialized\n" );
-+ return 0;
-+}
-+
-+static void __exit sa1100ssp_audio_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+}
-+
-+module_init(sa1100ssp_audio_init);
-+module_exit(sa1100ssp_audio_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for a simple DAC on the SA1100's SSP port");
-+
-+MODULE_PARM(sample_rate, "i");
-+MODULE_PARM_DESC(sample_rate, "Sample rate of the audio DAC, default is 44100");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/sa1111-ac97.c
-@@ -0,0 +1,518 @@
-+/*
-+ * Glue audio driver for the CS4205 and CS4201 AC'97 codecs.
-+ * largely based on the framework provided by sa1111-uda1341.c.
-+ *
-+ * Copyright (c) 2002 Bertrik Sikken (bertrik.sikken@technolution.nl)
-+ * Copyright (c) 2002 Robert Whaley (rwhaley@applieddata.net)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * This driver makes use of the ac97_codec module (for mixer registers)
-+ * and the sa1100-audio module (for DMA).
-+ *
-+ * History:
-+ *
-+ * 2002-04-04 Initial version.
-+ * 2002-04-10 Updated mtd_audio_init to improve choppy sound
-+ * and hanging sound issue.
-+ * 2002-05-16 Updated for ADS Bitsy+ Robert Whaley
-+ * 2002-06-28 Cleanup and added retry for read register timeouts
-+ * 2002-08-14 Updated for ADS AGC Robert Whaley
-+ * 2002-12-26 Cleanup, remove CONFIG_PM (it's handled by sa1100-audio.c)
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+#include <linux/errno.h>
-+#include <linux/proc_fs.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ac97_codec.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+#include <asm/dma.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "sa1100-audio.h"
-+
-+/* SAC FIFO depth, low nibble is transmit fifo, high nibble is receive FIFO */
-+#define SAC_FIFO_DEPTH 0x77
-+
-+// #define DEBUG
-+
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+/*
-+ Our codec data
-+*/
-+static struct ac97_codec ac97codec;
-+static int audio_dev_id, mixer_dev_id;
-+static audio_stream_t output_stream, input_stream;
-+
-+/* proc info */
-+
-+struct proc_dir_entry *ac97_ps;
-+
-+static int sa1111_ac97_set_adc_rate(long rate);
-+static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val);
-+static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg);
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M') {
-+ return -EINVAL;
-+ }
-+
-+ /* pass the ioctl to the ac97 mixer */
-+ return ac97codec.mixer_ioctl(&ac97codec, cmd, arg);
-+}
-+
-+
-+static struct file_operations sa1111_ac97_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+static void sa1111_ac97_power_off(void *dummy)
-+{
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ /* turn off audio and audio amp */
-+ ADS_CPLD_PCON |= (ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
-+
-+ /* make GPIO11 high impeadence */
-+ GPDR &= ~GPIO_GPIO11;
-+
-+ /* disable SACR0 so we can make these pins high impeadence */
-+ SACR0 &= ~SACR0_ENB;
-+
-+ /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
-+ PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSAGC
-+ /* turn off audio and audio amp */
-+ ADS_CR1 &= ~(ADS_CR1_CODEC | ADS_CR1_AMP);
-+
-+ /* disable SACR0 so we can make these pins high impeadence */
-+ SACR0 &= ~SACR0_ENB;
-+
-+ /* make BIT_CLK, SDATA_OUT, and SYNC high impeadence */
-+ PC_DDR |= (GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-+
-+#endif
-+}
-+
-+
-+static void sa1111_ac97_power_on(void *dummy)
-+{
-+ int ret, i;
-+
-+ /* disable L3 */
-+ SACR1 = 0;
-+
-+ SKPCR |= (SKPCR_ACCLKEN); /* enable ac97 clock */
-+ udelay(50);
-+
-+ /* BIT_CLK is input to SA1111, DMA thresholds 9 (both dirs) */
-+ SACR0 |= SACR0_BCKD | (SAC_FIFO_DEPTH << 8);
-+
-+ /* reset SAC registers */
-+ SACR0 &= ~SACR0_RST;
-+ udelay(50);
-+ SACR0 |= SACR0_RST;
-+ udelay(50);
-+ SACR0 &= ~SACR0_RST;
-+
-+ /* setup SA1111 to use AC'97 */
-+ SBI_SKCR |= SKCR_SELAC; /* select ac97 */
-+ udelay(50);
-+
-+ /* issue a cold AC97 reset */
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+
-+ /* initialize reset line */
-+ GAFR &= ~GPIO_GPIO11;
-+ GPDR |= GPIO_GPIO11;
-+ GPSR = GPIO_GPIO11;
-+
-+ /* turn on audio and audio amp */
-+ ADS_CPLD_PCON &= ~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON);
-+ mdelay(5);
-+
-+ /* reset by lowering the reset pin momentarily */
-+ DPRINTK("reseting codec via GPIO11\n");
-+ GPCR = GPIO_GPIO11;
-+ udelay(5);
-+ GPSR = GPIO_GPIO11;
-+ udelay(10);
-+
-+#endif
-+#ifdef CONFIG_SA1100_ADSAGC
-+
-+ /* turn on audio and audio amp */
-+ DPRINTK("before turning on power. ADS_CR1: %x\n", ADS_CR1);
-+ ADS_CR1 |= (ADS_CR1_AMP | ADS_CR1_CODEC);
-+ DPRINTK("after turnning on power. ADS_CR1: %x\n", ADS_CR1);
-+ mdelay(5);
-+
-+ /* reset by lowering the reset pin momentarily */
-+ DPRINTK("reseting codec via CPLD\n");
-+ ADS_CR1 |= ADS_CR1_AUDIO_RST;
-+ DPRINTK("after reset1. ADS_CR1: %x\n", ADS_CR1);
-+ udelay(5);
-+ ADS_CR1 &= ~ADS_CR1_AUDIO_RST;
-+ DPRINTK("after reset2. ADS_CR1: %x\n", ADS_CR1);
-+ udelay(10);
-+
-+#endif
-+ SACR2 = 0;
-+ udelay(50);
-+
-+ DPRINTK("before SW reset: SACR2: %x\n", SACR2);
-+ SACR2 = SACR2_RESET;
-+ DPRINTK("after SW reset: SACR2: %x\n", SACR2);
-+ udelay(50);
-+
-+ /* set AC97 slot 3 and 4 (PCM out) to valid */
-+ SACR2 = (SACR2_RESET | SACR2_TS3V | SACR2_TS4V);
-+
-+ /* enable SAC */
-+ SACR0 |= SACR0_ENB;
-+
-+ i = 100;
-+ while (!(SASR1 & SASR1_CRDY)) {
-+ if (!i--) {
-+ printk("Didn't get CRDY. SASR1=%x SKID=%x\n", SASR1, SBI_SKID);
-+ break;
-+ }
-+ udelay(50);
-+ }
-+
-+ if (!(ret = ac97_probe_codec(&ac97codec))) {
-+ printk("ac97_probe_codec failed (%d)\n", ret);
-+ return;
-+ }
-+
-+ /* mic ADC on, disable VRA, disable VRM */
-+ sa1111_ac97_write_reg(&ac97codec, AC97_EXTENDED_STATUS, 0x0200);
-+}
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+
-+static int sa1111_ac97_audio_ioctl(struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ DPRINTK("sa1111_ac97_audio_ioctl\n");
-+
-+ /*
-+ * These are platform dependent ioctls which are not handled by the
-+ * generic sa1100-audio module.
-+ */
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret) {
-+ return ret;
-+ }
-+ /* the cs42xx is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the cs42xx is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+#define SA1100_AC97_IOCTL_EXTRAS
-+
-+#ifdef SA1100_AC97_IOCTL_EXTRAS
-+
-+#define SNDCTL_DSP_AC97_CMD _SIOWR('P', 99, int)
-+#define SNDCTL_DSP_INPUT_SPEED _SIOWR('P', 98, int)
-+#define SOUND_PCM_READ_INPUT_RATE _SIOWR('P', 97, int)
-+
-+ case SNDCTL_DSP_AC97_CMD:
-+
-+ ret = get_user(val, (long *) arg);
-+ if (ret) {
-+ break;
-+ }
-+ sa1111_ac97_write_reg(&ac97codec, (u8) ((val & 0xff000000) >> 24), (u16) (val & 0xffff));
-+ return 0;
-+
-+
-+ case SNDCTL_DSP_INPUT_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ // acc code here to set the speed
-+ if (ret) {
-+ break;
-+ }
-+ // note that this only changes the ADC rate, not the
-+ // rate of the DAC.
-+ ret = sa1111_ac97_set_adc_rate(val);
-+ if (ret)
-+ break;
-+ return put_user(val, (long *) arg);
-+
-+ case SOUND_PCM_READ_INPUT_RATE:
-+
-+ return put_user((long) sa1111_ac97_read_reg(&ac97codec, 0x32), (long *) arg);
-+
-+
-+#endif
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) {
-+ break;
-+ }
-+
-+ case SOUND_PCM_READ_RATE:
-+ /* only 48 kHz playback is supported by the SA1111 */
-+ return put_user(48000L, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (As per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ input_stream: &input_stream,
-+ skip_dma_init: 1, /* done locally */
-+ hw_init: sa1111_ac97_power_on,
-+ hw_shutdown: sa1111_ac97_power_off,
-+ client_ioctl: sa1111_ac97_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+
-+static int sa1111_ac97_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations sa1111_ac97_audio_fops = {
-+ open: sa1111_ac97_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+
-+static void sa1111_ac97_write_reg(struct ac97_codec *dev, u8 reg, u16 val)
-+{
-+ int i;
-+
-+ /* reset status bits */
-+ SASCR = SASCR_DTS;
-+
-+ /* write command and data registers */
-+ ACCAR = reg << 12;
-+ ACCDR = val << 4;
-+
-+ /* wait for data to be transmitted */
-+ i = 0;
-+ while ((SASR1 & SASR1_CADT) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("sa1111_ac97_write_reg failed (data not transmitted. SASR1: %x)\n", SASR1);
-+ break;
-+ }
-+ }
-+
-+ DPRINTK("<%03d> sa1111_ac97_write_reg, [%02X]=%04X\n", i, reg, val);
-+}
-+
-+
-+static u16 sa1111_ac97_read_reg(struct ac97_codec *dev, u8 reg)
-+{
-+ u16 val;
-+ int i;
-+ int retry = 10;
-+
-+ do {
-+ /* reset status bits */
-+ SASCR = SASCR_RDD | SASCR_STO;
-+
-+ /* write command register */
-+ ACCAR = (reg | 0x80) << 12;
-+ ACCDR = 0;
-+
-+ /* wait for SADR bit in SASR1 */
-+ i = 0;
-+ while ((SASR1 & SASR1_SADR) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("<---> sa1111_ac97_read_reg failed\n");
-+ retry--;
-+ break;
-+ }
-+ if ((SASR1 & SASR1_RSTO) != 0) {
-+ DPRINTK("sa1111_ac97_read_reg *timeout*\n");
-+ retry--;
-+ break;
-+ }
-+ }
-+
-+ } while ((SASR1 & SASR1_SADR) == 0 && retry > 0);
-+
-+ val = ACSDR >> 4;
-+
-+ DPRINTK("<%03d> sa1111_ac97_read_reg, [%02X]=%04X\n", i, reg, val);
-+ return val;
-+}
-+
-+
-+/* wait for codec ready */
-+static void sa1111_ac97_ready(struct ac97_codec *dev)
-+{
-+ int i;
-+ u16 val;
-+
-+ i = 0;
-+ while ((SASR1 & SASR1_CRDY) == 0) {
-+ udelay(50);
-+ if (++i > 10) {
-+ DPRINTK("sa1111_ac97_ready failed\n");
-+ return;
-+ }
-+ }
-+ DPRINTK("codec_ready bit took %d cycles\n", i);
-+
-+ /* Wait for analog parts of codec to initialise */
-+ i = 0;
-+ do {
-+ val = sa1111_ac97_read_reg(&ac97codec, AC97_POWER_CONTROL);
-+ if (++i > 100) {
-+ break;
-+ }
-+ mdelay(10);
-+ } while ((val & 0xF) != 0xF || val == 0xFFFF);
-+
-+ /* the cs42xx typically takes 150 ms to initialise */
-+
-+ DPRINTK("analog init took %d cycles\n", i);
-+}
-+
-+
-+static int __init sa1111_ac97_init(void)
-+{
-+ int ret;
-+
-+ // SBI_SKCR |= SKCR_RCLKEN;
-+
-+ DPRINTK("sa1111_ac97_init\n");
-+
-+ /* install the ac97 mixer module */
-+ ac97codec.codec_read = sa1111_ac97_read_reg;
-+ ac97codec.codec_write = sa1111_ac97_write_reg;
-+ ac97codec.codec_wait = sa1111_ac97_ready;
-+
-+ /* Acquire and initialize DMA */
-+ ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
-+ SA1111_SAC_XMT_CHANNEL);
-+ if (ret < 0) {
-+ printk("DMA request for SAC output failed\n");
-+ return ret;
-+ }
-+
-+ ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
-+ SA1111_SAC_RCV_CHANNEL);
-+ if (ret < 0) {
-+ printk("DMA request for SAC input failed\n");
-+ sa1100_free_dma(output_stream.dma_ch);
-+ return ret;
-+ }
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&sa1111_ac97_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&sa1111_ac97_mixer_fops, -1);
-+
-+
-+ /* setup proc entry */
-+ ac97_ps = create_proc_read_entry ("driver/sa1111-ac97", 0, NULL,
-+ ac97_read_proc, &ac97codec);
-+
-+ return 0;
-+}
-+
-+
-+static void __exit sa1111_ac97_exit(void)
-+{
-+ SKPCR &= ~SKPCR_ACCLKEN; /* disable ac97 clock */
-+ SBI_SKCR &= ~SKCR_SELAC; /* deselect ac97 */
-+
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ sa1100_free_dma(output_stream.dma_ch);
-+ sa1100_free_dma(input_stream.dma_ch);
-+}
-+
-+static int sa1111_ac97_set_adc_rate(long rate)
-+{
-+
-+ // note this only changes the rate of the ADC, the DAC is fixed at 48K.
-+ // this is due to limitations of the SA1111 chip
-+
-+ u16 code = rate;
-+
-+ switch (rate) {
-+ case 8000:
-+ case 11025:
-+ case 16000:
-+ case 22050:
-+ case 32000:
-+ case 44100:
-+ case 48000:
-+ break;
-+ default:
-+ return -1;
-+ }
-+ sa1111_ac97_write_reg(&ac97codec, 0x2A, 0x0001);
-+ sa1111_ac97_write_reg(&ac97codec, 0x32, code);
-+ return 0;
-+}
-+
-+module_init(sa1111_ac97_init);
-+module_exit(sa1111_ac97_exit);
-+
-+MODULE_AUTHOR("Bertrik Sikken, Technolution B.V., Netherlands");
-+MODULE_DESCRIPTION("Glue audio driver for AC'97 codec");
-+MODULE_LICENSE("GPL");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/sa1111-uda1341.c
-@@ -0,0 +1,282 @@
-+/*
-+ * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.
-+ *
-+ * Copyright (c) 2000 John Dorsey
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2000-09-04 John Dorsey SA-1111 Serial Audio Controller support
-+ * was initially added to the sa1100-uda1341.c
-+ * driver.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-09-23 Russell King Remove old L3 bus driver.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/sound.h>
-+#include <linux/soundcard.h>
-+#include <linux/ioport.h>
-+#include <linux/pm.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/dma.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "sa1100-audio.h"
-+
-+#undef DEBUG
-+#ifdef DEBUG
-+#define DPRINTK( x... ) printk( ##x )
-+#else
-+#define DPRINTK( x... )
-+#endif
-+
-+
-+/*
-+ * Definitions
-+ */
-+
-+#define AUDIO_RATE_DEFAULT 22050
-+
-+#define AUDIO_CLK_BASE 561600
-+
-+
-+
-+/*
-+ * Mixer interface
-+ */
-+
-+static struct l3_client uda1341;
-+
-+static int
-+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
-+{
-+ /*
-+ * We only accept mixer (type 'M') ioctls.
-+ */
-+ if (_IOC_TYPE(cmd) != 'M')
-+ return -EINVAL;
-+
-+ return l3_command(&uda1341, cmd, (void *)arg);
-+}
-+
-+static struct file_operations uda1341_mixer_fops = {
-+ ioctl: mixer_ioctl,
-+ owner: THIS_MODULE
-+};
-+
-+
-+/*
-+ * Audio interface
-+ */
-+
-+static int audio_clk_div = (AUDIO_CLK_BASE + AUDIO_RATE_DEFAULT/2)/AUDIO_RATE_DEFAULT;
-+
-+static void sa1111_audio_init(void *dummy)
-+{
-+#ifdef CONFIG_ASSABET_NEPONSET
-+ if (machine_is_assabet()) {
-+ /* Select I2S audio (instead of AC-Link) */
-+ AUD_CTL = AUD_SEL_1341;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_JORNADA720
-+ if (machine_is_jornada720()) {
-+ /* LDD4 is speaker, LDD3 is microphone */
-+ PPSR &= ~(PPC_LDD3 | PPC_LDD4);
-+ PPDR |= PPC_LDD3 | PPC_LDD4;
-+ PPSR |= PPC_LDD4; /* enable speaker */
-+ PPSR |= PPC_LDD3; /* enable microphone */
-+ }
-+#endif
-+
-+ SBI_SKCR &= ~SKCR_SELAC;
-+
-+ /* Enable the I2S clock and L3 bus clock: */
-+ SKPCR |= (SKPCR_I2SCLKEN | SKPCR_L3CLKEN);
-+
-+ /* Activate and reset the Serial Audio Controller */
-+ SACR0 |= (SACR0_ENB | SACR0_RST);
-+ mdelay(5);
-+ SACR0 &= ~SACR0_RST;
-+
-+ /* For I2S, BIT_CLK is supplied internally. The "SA-1111
-+ * Specification Update" mentions that the BCKD bit should
-+ * be interpreted as "0 = output". Default clock divider
-+ * is 22.05kHz.
-+ *
-+ * Select I2S, L3 bus. "Recording" and "Replaying"
-+ * (receive and transmit) are enabled.
-+ */
-+ SACR1 = SACR1_L3EN;
-+ SKAUD = audio_clk_div - 1;
-+
-+ /* Initialize the UDA1341 internal state */
-+ l3_open(&uda1341);
-+}
-+
-+static void sa1111_audio_shutdown(void *dummy)
-+{
-+ l3_close(&uda1341);
-+ SACR0 &= ~SACR0_ENB;
-+}
-+
-+static int sa1111_audio_ioctl( struct inode *inode, struct file *file,
-+ uint cmd, ulong arg)
-+{
-+ long val;
-+ int ret = 0;
-+
-+ switch (cmd) {
-+ case SNDCTL_DSP_STEREO:
-+ ret = get_user(val, (int *) arg);
-+ if (ret)
-+ return ret;
-+ /* the UDA1341 is stereo only */
-+ ret = (val == 0) ? -EINVAL : 1;
-+ return put_user(ret, (int *) arg);
-+
-+ case SNDCTL_DSP_CHANNELS:
-+ case SOUND_PCM_READ_CHANNELS:
-+ /* the UDA1341 is stereo only */
-+ return put_user(2, (long *) arg);
-+
-+ case SNDCTL_DSP_SPEED:
-+ ret = get_user(val, (long *) arg);
-+ if (ret) break;
-+ if (val < 8000) val = 8000;
-+ if (val > 48000) val = 48000;
-+ audio_clk_div = (AUDIO_CLK_BASE + val/2)/val;
-+ SKAUD = audio_clk_div - 1;
-+ /* fall through */
-+
-+ case SOUND_PCM_READ_RATE:
-+ return put_user(AUDIO_CLK_BASE/audio_clk_div, (long *) arg);
-+
-+ case SNDCTL_DSP_SETFMT:
-+ case SNDCTL_DSP_GETFMTS:
-+ /* we can do 16-bit only */
-+ return put_user(AFMT_S16_LE, (long *) arg);
-+
-+ default:
-+ /* Maybe this is meant for the mixer (as per OSS Docs) */
-+ return mixer_ioctl(inode, file, cmd, arg);
-+ }
-+
-+ return ret;
-+}
-+
-+static audio_stream_t output_stream, input_stream;
-+
-+static audio_state_t audio_state = {
-+ output_stream: &output_stream,
-+ input_stream: &input_stream,
-+ skip_dma_init: 1, /* done locally */
-+ hw_init: sa1111_audio_init,
-+ hw_shutdown: sa1111_audio_shutdown,
-+ client_ioctl: sa1111_audio_ioctl,
-+ sem: __MUTEX_INITIALIZER(audio_state.sem),
-+};
-+
-+static int sa1111_audio_open(struct inode *inode, struct file *file)
-+{
-+ return sa1100_audio_attach(inode, file, &audio_state);
-+}
-+
-+/*
-+ * Missing fields of this structure will be patched with the call
-+ * to sa1100_audio_attach().
-+ */
-+static struct file_operations sa1111_audio_fops = {
-+ open: sa1111_audio_open,
-+ owner: THIS_MODULE
-+};
-+
-+static int audio_dev_id, mixer_dev_id;
-+
-+static int __init sa1111_uda1341_init(void)
-+{
-+ struct uda1341_cfg cfg;
-+ int ret;
-+
-+ if ( !( (machine_is_assabet() && machine_has_neponset()) ||
-+ machine_is_jornada720() ||
-+ machine_is_badge4() ))
-+ return -ENODEV;
-+
-+ if (!request_mem_region(_SACR0, 512, "sound"))
-+ return -EBUSY;
-+
-+ ret = l3_attach_client(&uda1341, "l3-sa1111", "uda1341");
-+ if (ret)
-+ goto out;
-+
-+ /* Acquire and initialize DMA */
-+ ret = sa1111_sac_request_dma(&output_stream.dma_ch, "SA1111 audio out",
-+ SA1111_SAC_XMT_CHANNEL);
-+ if (ret < 0)
-+ goto release_l3;
-+
-+ ret = sa1111_sac_request_dma(&input_stream.dma_ch, "SA1111 audio in",
-+ SA1111_SAC_RCV_CHANNEL);
-+ if (ret < 0)
-+ goto release_dma;
-+
-+ cfg.fs = 256;
-+ cfg.format = FMT_I2S;
-+ l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);
-+
-+ /* register devices */
-+ audio_dev_id = register_sound_dsp(&sa1111_audio_fops, -1);
-+ mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1);
-+
-+ printk(KERN_INFO "Sound: SA1111 UDA1341: dsp id %d mixer id %d\n",
-+ audio_dev_id, mixer_dev_id);
-+ return 0;
-+
-+release_dma:
-+ sa1100_free_dma(output_stream.dma_ch);
-+release_l3:
-+ l3_detach_client(&uda1341);
-+out:
-+ release_mem_region(_SACR0, 512);
-+ return ret;
-+}
-+
-+static void __exit sa1111_uda1341_exit(void)
-+{
-+ unregister_sound_dsp(audio_dev_id);
-+ unregister_sound_mixer(mixer_dev_id);
-+ sa1100_free_dma(output_stream.dma_ch);
-+ sa1100_free_dma(input_stream.dma_ch);
-+ l3_detach_client(&uda1341);
-+
-+ release_mem_region(_SACR0, 512);
-+}
-+
-+module_init(sa1111_uda1341_init);
-+module_exit(sa1111_uda1341_exit);
-+
-+MODULE_AUTHOR("John Dorsey, Nicolas Pitre");
-+MODULE_DESCRIPTION("Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.");
-+
-+EXPORT_NO_SYMBOLS;
---- /dev/null
-+++ linux-2.4.27/drivers/sound/uda1341.c
-@@ -0,0 +1,511 @@
-+/*
-+ * Philips UDA1341 mixer device driver
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * Portions are Copyright (C) 2000 Lernout & Hauspie Speech Products, N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2000-05-21 Nicolas Pitre Initial release.
-+ *
-+ * 2000-08-19 Erik Bunce More inline w/ OSS API and UDA1341 docs
-+ * including fixed AGC and audio source handling
-+ *
-+ * 2000-11-30 Nicolas Pitre - More mixer functionalities.
-+ *
-+ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
-+ * the former sa1100-uda1341.c driver.
-+ *
-+ * 2001-08-13 Russell King Re-written as part of the L3 interface
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include <linux/ioctl.h>
-+#include <linux/soundcard.h>
-+#include <linux/l3/l3.h>
-+#include <linux/l3/uda1341.h>
-+
-+#include <asm/uaccess.h>
-+
-+#define DEF_VOLUME 65
-+
-+/*
-+ * UDA1341 L3 address and command types
-+ */
-+#define UDA1341_L3ADDR 5
-+#define UDA1341_DATA0 (UDA1341_L3ADDR << 2 | 0)
-+#define UDA1341_DATA1 (UDA1341_L3ADDR << 2 | 1)
-+#define UDA1341_STATUS (UDA1341_L3ADDR << 2 | 2)
-+
-+struct uda1341_regs {
-+ unsigned char stat0;
-+#define STAT0 0x00
-+#define STAT0_RST (1 << 6)
-+#define STAT0_SC_MASK (3 << 4)
-+#define STAT0_SC_512FS (0 << 4)
-+#define STAT0_SC_384FS (1 << 4)
-+#define STAT0_SC_256FS (2 << 4)
-+#define STAT0_IF_MASK (7 << 1)
-+#define STAT0_IF_I2S (0 << 1)
-+#define STAT0_IF_LSB16 (1 << 1)
-+#define STAT0_IF_LSB18 (2 << 1)
-+#define STAT0_IF_LSB20 (3 << 1)
-+#define STAT0_IF_MSB (4 << 1)
-+#define STAT0_IF_LSB16MSB (5 << 1)
-+#define STAT0_IF_LSB18MSB (6 << 1)
-+#define STAT0_IF_LSB20MSB (7 << 1)
-+#define STAT0_DC_FILTER (1 << 0)
-+
-+ unsigned char stat1;
-+#define STAT1 0x80
-+#define STAT1_DAC_GAIN (1 << 6) /* gain of DAC */
-+#define STAT1_ADC_GAIN (1 << 5) /* gain of ADC */
-+#define STAT1_ADC_POL (1 << 4) /* polarity of ADC */
-+#define STAT1_DAC_POL (1 << 3) /* polarity of DAC */
-+#define STAT1_DBL_SPD (1 << 2) /* double speed playback */
-+#define STAT1_ADC_ON (1 << 1) /* ADC powered */
-+#define STAT1_DAC_ON (1 << 0) /* DAC powered */
-+
-+ unsigned char data0_0;
-+#define DATA0 0x00
-+#define DATA0_VOLUME_MASK 0x3f
-+#define DATA0_VOLUME(x) (x)
-+
-+ unsigned char data0_1;
-+#define DATA1 0x40
-+#define DATA1_BASS(x) ((x) << 2)
-+#define DATA1_BASS_MASK (15 << 2)
-+#define DATA1_TREBLE(x) ((x))
-+#define DATA1_TREBLE_MASK (3)
-+
-+ unsigned char data0_2;
-+#define DATA2 0x80
-+#define DATA2_PEAKAFTER (1 << 5)
-+#define DATA2_DEEMP_NONE (0 << 3)
-+#define DATA2_DEEMP_32KHz (1 << 3)
-+#define DATA2_DEEMP_44KHz (2 << 3)
-+#define DATA2_DEEMP_48KHz (3 << 3)
-+#define DATA2_MUTE (1 << 2)
-+#define DATA2_FILTER_FLAT (0 << 0)
-+#define DATA2_FILTER_MIN (1 << 0)
-+#define DATA2_FILTER_MAX (3 << 0)
-+
-+#define EXTADDR(n) (0xc0 | (n))
-+#define EXTDATA(d) (0xe0 | (d))
-+
-+ unsigned char ext0;
-+#define EXT0 0
-+#define EXT0_CH1_GAIN(x) (x)
-+
-+ unsigned char ext1;
-+#define EXT1 1
-+#define EXT1_CH2_GAIN(x) (x)
-+
-+ unsigned char ext2;
-+#define EXT2 2
-+#define EXT2_MIC_GAIN_MASK (7 << 2)
-+#define EXT2_MIC_GAIN(x) ((x) << 2)
-+#define EXT2_MIXMODE_DOUBLEDIFF (0)
-+#define EXT2_MIXMODE_CH1 (1)
-+#define EXT2_MIXMODE_CH2 (2)
-+#define EXT2_MIXMODE_MIX (3)
-+
-+ unsigned char ext4;
-+#define EXT4 4
-+#define EXT4_AGC_ENABLE (1 << 4)
-+#define EXT4_INPUT_GAIN_MASK (3)
-+#define EXT4_INPUT_GAIN(x) ((x) & 3)
-+
-+ unsigned char ext5;
-+#define EXT5 5
-+#define EXT5_INPUT_GAIN(x) ((x) >> 2)
-+
-+ unsigned char ext6;
-+#define EXT6 6
-+#define EXT6_AGC_CONSTANT_MASK (7 << 2)
-+#define EXT6_AGC_CONSTANT(x) ((x) << 2)
-+#define EXT6_AGC_LEVEL_MASK (3)
-+#define EXT6_AGC_LEVEL(x) (x)
-+};
-+
-+#define REC_MASK (SOUND_MASK_LINE | SOUND_MASK_MIC)
-+#define DEV_MASK (REC_MASK | SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
-+
-+struct uda1341 {
-+ struct uda1341_regs regs;
-+ int active;
-+ unsigned short volume;
-+ unsigned short bass;
-+ unsigned short treble;
-+ unsigned short line;
-+ unsigned short mic;
-+ int mod_cnt;
-+};
-+
-+#define ADD_FIELD(reg,field) \
-+ *p++ = reg | uda->regs.field
-+
-+#define ADD_EXTFIELD(reg,field) \
-+ *p++ = EXTADDR(reg); \
-+ *p++ = EXTDATA(uda->regs.field);
-+
-+static void uda1341_sync(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ char buf[24], *p = buf;
-+
-+ ADD_FIELD(STAT0, stat0);
-+ ADD_FIELD(STAT1, stat1);
-+
-+ if (p != buf)
-+ l3_write(clnt, UDA1341_STATUS, buf, p - buf);
-+
-+ p = buf;
-+ ADD_FIELD(DATA0, data0_0);
-+ ADD_FIELD(DATA1, data0_1);
-+ ADD_FIELD(DATA2, data0_2);
-+ ADD_EXTFIELD(EXT0, ext0);
-+ ADD_EXTFIELD(EXT1, ext1);
-+ ADD_EXTFIELD(EXT2, ext2);
-+ ADD_EXTFIELD(EXT4, ext4);
-+ ADD_EXTFIELD(EXT5, ext5);
-+ ADD_EXTFIELD(EXT6, ext6);
-+
-+ if (p != buf)
-+ l3_write(clnt, UDA1341_DATA0, buf, p - buf);
-+}
-+
-+static void uda1341_cmd_init(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ char buf[2];
-+
-+ uda->active = 1;
-+
-+ buf[0] = uda->regs.stat0 | STAT0_RST;
-+ buf[1] = uda->regs.stat0;
-+
-+ l3_write(clnt, UDA1341_STATUS, buf, 2);
-+
-+ /* resend all parameters */
-+ uda1341_sync(clnt);
-+}
-+
-+static int uda1341_configure(struct l3_client *clnt, struct uda1341_cfg *conf)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ int ret = 0;
-+
-+ uda->regs.stat0 &= ~(STAT0_SC_MASK | STAT0_IF_MASK);
-+
-+ switch (conf->fs) {
-+ case 512: uda->regs.stat0 |= STAT0_SC_512FS; break;
-+ case 384: uda->regs.stat0 |= STAT0_SC_384FS; break;
-+ case 256: uda->regs.stat0 |= STAT0_SC_256FS; break;
-+ default: ret = -EINVAL; break;
-+ }
-+
-+ switch (conf->format) {
-+ case FMT_I2S: uda->regs.stat0 |= STAT0_IF_I2S; break;
-+ case FMT_LSB16: uda->regs.stat0 |= STAT0_IF_LSB16; break;
-+ case FMT_LSB18: uda->regs.stat0 |= STAT0_IF_LSB18; break;
-+ case FMT_LSB20: uda->regs.stat0 |= STAT0_IF_LSB20; break;
-+ case FMT_MSB: uda->regs.stat0 |= STAT0_IF_MSB; break;
-+ case FMT_LSB16MSB: uda->regs.stat0 |= STAT0_IF_LSB16MSB; break;
-+ case FMT_LSB18MSB: uda->regs.stat0 |= STAT0_IF_LSB18MSB; break;
-+ case FMT_LSB20MSB: uda->regs.stat0 |= STAT0_IF_LSB20MSB; break;
-+ }
-+
-+ if (ret == 0 && uda->active) {
-+ char buf = uda->regs.stat0 | STAT0;
-+ l3_write(clnt, UDA1341_STATUS, &buf, 1);
-+ }
-+ return ret;
-+}
-+
-+static int uda1341_update_direct(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain *v = arg;
-+ char newreg;
-+ int val;
-+
-+ switch (cmd) {
-+ case L3_SET_VOLUME: /* set volume. val = 0 to 100 => 62 to 1 */
-+ uda->regs.data0_0 = DATA0_VOLUME(62 - ((v->left * 61) / 100));
-+ newreg = uda->regs.data0_0 | DATA0;
-+ break;
-+
-+ case L3_SET_BASS: /* set bass. val = 50 to 100 => 0 to 12 */
-+ val = v->left - 50;
-+ if (val < 0)
-+ val = 0;
-+ uda->regs.data0_1 &= ~DATA1_BASS_MASK;
-+ uda->regs.data0_1 |= DATA1_BASS((val * 12) / 50);
-+ newreg = uda->regs.data0_1 | DATA1;
-+ break;
-+
-+ case L3_SET_TREBLE: /* set treble. val = 50 to 100 => 0 to 3 */
-+ val = v->left - 50;
-+ if (val < 0)
-+ val = 0;
-+ uda->regs.data0_1 &= ~DATA1_TREBLE_MASK;
-+ uda->regs.data0_1 |= DATA1_TREBLE((val * 3) / 50);
-+ newreg = uda->regs.data0_1 | DATA1;
-+ break;
-+
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ if (uda->active)
-+ l3_write(clnt, UDA1341_DATA0, &newreg, 1);
-+ return 0;
-+}
-+
-+static int uda1341_update_indirect(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain *gain = arg;
-+ struct l3_agc *agc = arg;
-+ char buf[8], *p = buf;
-+ int val, ret = 0;
-+
-+ switch (cmd) {
-+ case L3_SET_GAIN:
-+ val = 31 - (gain->left * 31 / 100);
-+ switch (gain->channel) {
-+ case 1:
-+ uda->regs.ext0 = EXT0_CH1_GAIN(val);
-+ ADD_EXTFIELD(EXT0, ext0);
-+ break;
-+
-+ case 2:
-+ uda->regs.ext1 = EXT1_CH2_GAIN(val);
-+ ADD_EXTFIELD(EXT1, ext1);
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ }
-+ break;
-+
-+ case L3_INPUT_AGC:
-+ if (agc->channel == 2) {
-+ if (agc->enable)
-+ uda->regs.ext4 |= EXT4_AGC_ENABLE;
-+ else
-+ uda->regs.ext4 &= ~EXT4_AGC_ENABLE;
-+#if 0
-+ agc->level
-+ agc->attack
-+ agc->decay
-+#endif
-+ ADD_EXTFIELD(EXT4, ext4);
-+ } else
-+ ret = -EINVAL;
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ if (ret == 0 && uda->active)
-+ l3_write(clnt, UDA1341_DATA0, buf, p - buf);
-+
-+ return ret;
-+}
-+
-+static int uda1341_mixer_ioctl(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ struct l3_gain gain;
-+ int val, nr = _IOC_NR(cmd), ret = 0;
-+
-+ if (cmd == SOUND_MIXER_INFO) {
-+ struct mixer_info mi;
-+
-+ strncpy(mi.id, "UDA1341", sizeof(mi.id));
-+ strncpy(mi.name, "Philips UDA1341", sizeof(mi.name));
-+ mi.modify_counter = uda->mod_cnt;
-+ return copy_to_user(arg, &mi, sizeof(mi));
-+ }
-+
-+ if (_IOC_DIR(cmd) & _IOC_WRITE) {
-+ ret = get_user(val, (int *)arg);
-+ if (ret)
-+ goto out;
-+
-+ gain.left = val & 255;
-+ gain.right = val >> 8;
-+ gain.channel = 0;
-+
-+ switch (nr) {
-+ case SOUND_MIXER_VOLUME:
-+ uda->volume = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_VOLUME, &gain);
-+ break;
-+
-+ case SOUND_MIXER_BASS:
-+ uda->bass = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_BASS, &gain);
-+ break;
-+
-+ case SOUND_MIXER_TREBLE:
-+ uda->treble = val;
-+ uda->mod_cnt++;
-+ uda1341_update_direct(clnt, L3_SET_TREBLE, &gain);
-+ break;
-+
-+ case SOUND_MIXER_LINE:
-+ uda->line = val;
-+ gain.channel = 1;
-+ uda->mod_cnt++;
-+ uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
-+ break;
-+
-+ case SOUND_MIXER_MIC:
-+ uda->mic = val;
-+ gain.channel = 2;
-+ uda->mod_cnt++;
-+ uda1341_update_indirect(clnt, L3_SET_GAIN, &gain);
-+ break;
-+
-+ case SOUND_MIXER_RECSRC:
-+ break;
-+
-+ default:
-+ ret = -EINVAL;
-+ }
-+ }
-+
-+ if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
-+ int nr = _IOC_NR(cmd);
-+ ret = 0;
-+
-+ switch (nr) {
-+ case SOUND_MIXER_VOLUME: val = uda->volume; break;
-+ case SOUND_MIXER_BASS: val = uda->bass; break;
-+ case SOUND_MIXER_TREBLE: val = uda->treble; break;
-+ case SOUND_MIXER_LINE: val = uda->line; break;
-+ case SOUND_MIXER_MIC: val = uda->mic; break;
-+ case SOUND_MIXER_RECSRC: val = REC_MASK; break;
-+ case SOUND_MIXER_RECMASK: val = REC_MASK; break;
-+ case SOUND_MIXER_DEVMASK: val = DEV_MASK; break;
-+ case SOUND_MIXER_CAPS: val = 0; break;
-+ case SOUND_MIXER_STEREODEVS: val = 0; break;
-+ default: val = 0; ret = -EINVAL; break;
-+ }
-+
-+ if (ret == 0)
-+ ret = put_user(val, (int *)arg);
-+ }
-+out:
-+ return ret;
-+}
-+
-+static int uda1341_attach(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda;
-+
-+ uda = kmalloc(sizeof(*uda), GFP_KERNEL);
-+ if (!uda)
-+ return -ENOMEM;
-+
-+ memset(uda, 0, sizeof(*uda));
-+
-+ uda->volume = DEF_VOLUME | DEF_VOLUME << 8;
-+ uda->bass = 50 | 50 << 8;
-+ uda->treble = 50 | 50 << 8;
-+ uda->line = 88 | 88 << 8;
-+ uda->mic = 88 | 88 << 8;
-+
-+ uda->regs.stat0 = STAT0_SC_256FS | STAT0_IF_LSB16;
-+ uda->regs.stat1 = STAT1_DAC_GAIN | STAT1_ADC_GAIN |
-+ STAT1_ADC_ON | STAT1_DAC_ON;
-+ uda->regs.data0_0 = DATA0_VOLUME(62 - ((DEF_VOLUME * 61) / 100));
-+ uda->regs.data0_1 = DATA1_BASS(0) | DATA1_TREBLE(0);
-+ uda->regs.data0_2 = DATA2_PEAKAFTER | DATA2_DEEMP_NONE |
-+ DATA2_FILTER_MAX;
-+ uda->regs.ext0 = EXT0_CH1_GAIN(4);
-+ uda->regs.ext1 = EXT1_CH2_GAIN(4);
-+ uda->regs.ext2 = EXT2_MIXMODE_MIX | EXT2_MIC_GAIN(4);
-+ uda->regs.ext4 = EXT4_AGC_ENABLE | EXT4_INPUT_GAIN(0);
-+ uda->regs.ext5 = EXT5_INPUT_GAIN(0);
-+ uda->regs.ext6 = EXT6_AGC_CONSTANT(3) | EXT6_AGC_LEVEL(0);
-+
-+ clnt->driver_data = uda;
-+
-+ return 0;
-+}
-+
-+static void uda1341_detach(struct l3_client *clnt)
-+{
-+ kfree(clnt->driver_data);
-+}
-+
-+static int
-+uda1341_command(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ int ret = -EINVAL;
-+
-+ if (_IOC_TYPE(cmd) == 'M')
-+ ret = uda1341_mixer_ioctl(clnt, cmd, arg);
-+ else if (cmd == L3_UDA1341_CONFIGURE)
-+ ret = uda1341_configure(clnt, arg);
-+
-+ return ret;
-+}
-+
-+static int uda1341_open(struct l3_client *clnt)
-+{
-+ uda1341_cmd_init(clnt);
-+ return 0;
-+}
-+
-+static void uda1341_close(struct l3_client *clnt)
-+{
-+ struct uda1341 *uda = clnt->driver_data;
-+ uda->active = 0;
-+}
-+
-+static struct l3_ops uda1341_ops = {
-+ open: uda1341_open,
-+ command: uda1341_command,
-+ close: uda1341_close,
-+};
-+
-+static struct l3_driver uda1341 = {
-+ name: UDA1341_NAME,
-+ attach_client: uda1341_attach,
-+ detach_client: uda1341_detach,
-+ ops: &uda1341_ops,
-+ owner: THIS_MODULE,
-+};
-+
-+static int __init uda1341_init(void)
-+{
-+ return l3_add_driver(&uda1341);
-+}
-+
-+static void __exit uda1341_exit(void)
-+{
-+ l3_del_driver(&uda1341);
-+}
-+
-+module_init(uda1341_init);
-+module_exit(uda1341_exit);
-+
-+MODULE_AUTHOR("Nicolas Pitre");
-+MODULE_DESCRIPTION("Philips UDA1341 CODEC driver");
---- linux-2.4.27/drivers/sound/vidc.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/sound/vidc.c
-@@ -40,6 +40,7 @@
- #endif
-
- #define VIDC_SOUND_CLOCK (250000)
-+#define VIDC_SOUND_CLOCK_EXT (176400)
-
- /*
- * When using SERIAL SOUND mode (external DAC), the number of physical
-@@ -192,28 +193,43 @@
- return vidc_audio_format;
- }
-
-+#define my_abs(i) ((i)<0 ? -(i) : (i))
-+
- static int vidc_audio_set_speed(int dev, int rate)
- {
- if (rate) {
-- unsigned int hwctrl, hwrate;
-+ unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext;
- unsigned int newsize, new2size;
-
-- /*
-- * If we have selected 44.1kHz, use the DAC clock.
-- */
-- if (0 && rate == 44100) {
-- hwctrl = 0x00000002;
-+ hwctrl = 0x00000003;
-+
-+ /* Using internal clock */
-+ hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
-+ if (hwrate < 3)
- hwrate = 3;
-- } else {
-- hwctrl = 0x00000003;
-+ if (hwrate > 255)
-+ hwrate = 255;
-
-- hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1;
-- if (hwrate < 3)
-- hwrate = 3;
-- if (hwrate > 255)
-- hwrate = 255;
-+ /* Using exernal clock */
-+ hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1;
-+ if (hwrate_ext < 3)
-+ hwrate_ext = 3;
-+ if (hwrate_ext > 255)
-+ hwrate_ext = 255;
-
-- rate = VIDC_SOUND_CLOCK / hwrate;
-+ rate_int = VIDC_SOUND_CLOCK / hwrate;
-+ rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext;
-+
-+ /* Chose between external and internal clock */
-+ if (my_abs(rate_ext-rate) < my_abs(rate_int-rate)) {
-+ /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/
-+ hwrate=hwrate_ext;
-+ hwctrl=0x00000002;
-+ rate=rate_ext;
-+ } else {
-+ /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/
-+ hwctrl=0x00000003;
-+ rate=rate_int;
- }
-
- vidc_writel(0xb0000000 | (hwrate - 2));
-@@ -225,13 +241,14 @@
- if (newsize > 4096)
- newsize = 4096;
- for (new2size = 128; new2size < newsize; new2size <<= 1);
-- if (new2size - newsize > newsize - (new2size >> 1))
-- new2size >>= 1;
-+ if (new2size - newsize > newsize - (new2size >> 1))
-+ new2size >>= 1;
- if (new2size > 4096) {
- printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n",
- newsize, new2size);
- new2size = 4096;
- }
-+ /*printk("VIDC: dma size %d\n", new2size);*/
- dma_bufsize = new2size;
- vidc_audio_rate = rate;
- }
---- linux-2.4.27/drivers/sound/waveartist.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/sound/waveartist.c
-@@ -247,17 +247,15 @@
- printk("\n");
- }
-
-- if (inb(io_base + STATR) & CMD_RF) {
-- int old_data;
--
-- /* flush the port
-- */
-+ /*
-+ * flush any stale command data from the port.
-+ */
-+ while (inb(io_base + STATR) & CMD_RF) {
-+ unsigned int old_data;
-
- old_data = inw(io_base + CMDR);
--
-- if (debug_flg & DEBUG_CMD)
-- printk("flushed %04X...", old_data);
--
-+ printk("waveartist: flushing stale command data: 0x%04x pc=%p\n",
-+ old_data, __builtin_return_address(0));
- udelay(10);
- }
-
-@@ -287,16 +285,19 @@
- resp[i] = inw(io_base + CMDR);
- }
-
-- if (debug_flg & DEBUG_CMD) {
-- if (!timed_out) {
-- printk("waveartist_cmd: resp=");
-+ if (debug_flg & DEBUG_CMD && !timed_out) {
-+ printk("waveartist_cmd: resp=");
-
-- for (i = 0; i < nr_resp; i++)
-- printk("%04X ", resp[i]);
-+ for (i = 0; i < nr_resp; i++)
-+ printk("%04X ", resp[i]);
-+ printk("\n");
-+ }
-
-- printk("\n");
-- } else
-- printk("waveartist_cmd: timed out\n");
-+ if (timed_out) {
-+ printk(KERN_ERR "waveartist_cmd: command timed out:");
-+ for (i = 0; i < nr_cmd; i++)
-+ printk(" %04x", cmd[i]);
-+ printk("\n");
- }
-
- return timed_out ? 1 : 0;
-@@ -495,7 +496,6 @@
- audio_devs[dev]->flags & DMA_AUTOMODE &&
- intrflag &&
- count == devc->xfer_count) {
-- devc->audio_mode |= PCM_ENABLE_INPUT;
- return; /*
- * Auto DMA mode on. No need to react
- */
-@@ -571,9 +571,6 @@
- wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
- unsigned int speed, bits;
-
-- if (devc->audio_mode)
-- return 0;
--
- speed = waveartist_get_speed(portc);
- bits = waveartist_get_bits(portc);
-
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/Config.in
-@@ -0,0 +1,11 @@
-+
-+mainmenu_option next_comment
-+comment 'Synchronous Serial Interface'
-+tristate 'Synchronous Serial Interface Support' CONFIG_SSI
-+
-+comment 'SSI Bus Drivers'
-+dep_tristate ' CLPS711X SSI support' CONFIG_SSI_CLPS711X $CONFIG_SSI $CONFIG_ARCH_CLPS711X
-+
-+comment 'SSI Device Drivers'
-+dep_tristate ' JUNO keyboard support' CONFIG_SSI_JUNO $CONFIG_SSI
-+endmenu
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/Makefile
-@@ -0,0 +1,50 @@
-+#
-+# Makefile for the SSI drivers
-+#
-+# Note! Dependencies are done automagically by 'make dep', which also
-+# removes any old dependencies. DON'T put your own dependencies here
-+# unless it's something special (ie not a .c file).
-+#
-+# Note 2! The CFLAGS definition is now inherited from the
-+# parent makefile.
-+#
-+
-+O_TARGET := ssi.o
-+
-+obj-y :=
-+obj-m :=
-+obj-n :=
-+obj- :=
-+
-+export-objs :=
-+list-multi :=
-+
-+obj-$(CONFIG_SSI) += ssi_core.o
-+obj-$(CONFIG_SSI_CLPS711X) += clps711x_ssi1.o
-+obj-y += juno.o
-+
-+# Extract lists of the multi-part drivers.
-+# The 'int-*' lists are intermediate files used to build the multi's.
-+
-+multi-y := $(filter $(list-multi), $(obj-y))
-+multi-m := $(filter $(list-multi), $(obj-m))
-+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-+
-+# Files that are both resident and modular; remove from modular.
-+
-+obj-m := $(filter-out $(obj-y), $(obj-m))
-+int-m := $(filter-out $(int-y), $(int-m))
-+
-+# Take multi-part drivers out of obj-y and put components in.
-+
-+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
-+
-+# Translate to Rules.make lists.
-+
-+O_OBJS := $(filter-out $(export-objs), $(obj-y))
-+OX_OBJS := $(filter $(export-objs), $(obj-y))
-+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-+
-+include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/README
-@@ -0,0 +1,86 @@
-+ Synchronous Serial Interface bus driver
-+ ---------------------------------------
-+
-+ EEEEE X X PPPP EEEEE RRRR IIIII M M EEEEE N N TTTTT AAA L
-+ E X X P P E R R I MM MM E NN N T A A L
-+ EEEE X PPPP EEEE RRRR I M M M EEEE N N N T AAAAA L
-+ E X X P E R R I M M E N NN T A A L
-+ EEEEE X X P EEEEE R R IIIII M M EEEEE N N T A A LLLLL
-+
-+This directory holds the SSI bus drivers. Basically, a SSI bus consists
-+of the following signals:
-+
-+ stxd Transmit data
-+ srxd Receive data
-+ sclk Clock
-+ sfrm Frame
-+ Chip selects (1 - n)
-+
-+There may be more than one device on a SSI bus, and each device can
-+have different timing requirements. There are several frame formats:
-+
-+1. Texas Instruments Synchronous Serial Frame format
-+
-+ sclk ____~_~_~_~_~_~_~_~____
-+ sfrm ____~~_________________
-+ stxd ------bn..........b0---
-+ srxd ------bn..........b0---
-+
-+ - data latched in on the falling edge of the clock
-+ - data shifted out on the rising edge of the clock
-+
-+2. Motorola SPI frame format
-+
-+ sclk ______~_~_~_~_~_~_~____
-+ sfrm ~~~~________________~~~
-+ stxd -----bn..........b0----
-+ srxd ----.bn..........b0----
-+
-+ - data latched in on the rising edge of the clock
-+ - data shifted out on the falling edge of the clock, or falling edge
-+ of sfrm
-+
-+3. National Microwire format
-+
-+ sclk ______~_~_~_~_~_~_~_~_~_~_~_~_~_____
-+ sfrm ~~~~_____________________________~~~
-+ stxd -----bn......b0---------------------
-+ srxd -----------------bn..........b0.----
-+
-+ - data latched in on the rising edge of the clock
-+ - data shifted out on the falling edge of the clock
-+ - half duplex, one clock between transmission and reception
-+
-+Types of devices
-+----------------
-+
-+The following types of devices can be found on a SSP bus:
-+
-+ Sound chips
-+ Keyboard devices
-+ Touch screen devices
-+
-+Keyboard
-+--------
-+
-+TX:
-+0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
-+1. select device
-+2. keyboard responds asserting key_atn
-+3. wait 0.1ms to 5ms
-+4. transmit data byte
-+5. wait >= 150us
-+6. repeat step 4 until all data sent
-+7. deselect device
-+8. keyboard responds de-asserting key_atn
-+9. wait >= 120us
-+
-+RX:
-+0. Format: cfglen = 8, framelen = 8, clkpol = 1, clk < 250kHz
-+1. keyboard asserts key_atn
-+2. select device after 0.1ms < 5ms
-+3. read data byte
-+4. wait 150us
-+5. if key_atn still asserted, goto 3
-+6. deselect device
-+7. wait >= 120us
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/clps711x_ssi1.c
-@@ -0,0 +1,237 @@
-+/*
-+ * linux/drivers/ssi/clps711x_ssi1.c
-+ *
-+ * SSI bus driver for the CLPS711x SSI1 bus. We support EP7212
-+ * extensions as well.
-+ *
-+ * Frame sizes can be between 4 and 24 bits.
-+ * Config sizes can be between 4 and 16 bits.
-+ */
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/mach-types.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#include <asm/hardware/ep7212.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+#define EP7212
-+
-+/*
-+ * Port E on the P720T is used for the SPI bus chip selects
-+ * 0 - Keyboard
-+ * 1 - Touch screen
-+ * 2 - CS4224 ADC/DAC
-+ * 7 - idle
-+ */
-+
-+#if 0
-+/*
-+ * we place in the transmit buffer:
-+ * <control>
-+ * received data (binary):
-+ * 0xxxxxxxxxxxx000
-+ * where 'x' is the value
-+ */
-+struct ssi_dev ads7846_dev = {
-+ name: "ADS7846",
-+ id: 1,
-+ proto: SSI_SPI,
-+ cfglen: 8,
-+ framelen: 24,
-+ clkpol: 0,
-+ clkfreq: 2500000,
-+};
-+
-+/*
-+ * we place in the transmit buffer:
-+ * write: <20> <map> <data>...
-+ * received data discarded
-+ */
-+struct ssi_dev cs4224_dev = {
-+ name: "CS4224",
-+ id: 2,
-+ proto: SSI_SPI,
-+ cfglen: 8,
-+ framelen: 8,
-+ clkpol: 0,
-+ clkfreq: 6000000,
-+};
-+#endif
-+
-+/*
-+ * Supplement with whatever method your board requires
-+ */
-+static void ssi1_select_id(int id)
-+{
-+ if (machine_is_p720t()) {
-+ clps_writel(7, PEDDR);
-+ clps_writel(id, PEDR);
-+ }
-+}
-+
-+/*
-+ * Select the specified device. The upper layers will have already
-+ * checked that the bus transmit queue is idle. We need to make sure
-+ * that the interface itself is idle.
-+ */
-+static int ssi1_select(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ u_int id = dev ? dev->id : 7;
-+ u_int val;
-+
-+ /*
-+ * Make sure that the interface is idle
-+ */
-+ do {
-+ val = clps_readl(SYSFLG1);
-+ } while (val & SYSFLG1_SSIBUSY);
-+
-+ ssi1_select_id(7);
-+
-+ if (dev) {
-+ /*
-+ * Select clock frequency. This is very rough,
-+ * and assumes that we're operating in PLL mode.
-+ */
-+ val = clps_readl(SYSCON1) & ~SYSCON1_ADCKSEL_MASK;
-+// if (dev->clkfreq <= 16000) /* <16kHz */
-+// val |= SYSCON1_ADCKSEL(0);
-+// else if (dev->clkfreq < 64000) /* <64kHz */
-+// val |= SYSCON1_ADCKSEL(1);
-+// else if (dev->clkfreq < 128000) /* <128kHz */
-+ val |= SYSCON1_ADCKSEL(2);
-+// else /* >= 128kHz */
-+// val |= SYSCON1_ADCKSEL(3);
-+ clps_writel(val, SYSCON1);
-+
-+ bus->cfglen = dev->cfglen;
-+ bus->framelen = dev->framelen;
-+ bus->clkpol = dev->clkpol;
-+ bus->proto = dev->proto;
-+
-+#ifdef EP7212
-+ /*
-+ * Set the clock edge according to the device.
-+ * (set clkpol if the device reads data on the
-+ * falling edge of the clock signal).
-+ */
-+ val = ep_readl(SYSCON3) & ~SYSCON3_ADCCKNSEN;
-+ if (bus->clkpol && dev->proto != SSI_USAR)
-+ val |= SYSCON3_ADCCKNSEN;
-+ ep_writel(val, SYSCON3);
-+#endif
-+
-+ /*
-+ * Select the device
-+ */
-+ ssi1_select_id(id);
-+
-+#ifdef EP7212
-+ /*
-+ * If we are doing USAR, wait 30us, then set
-+ * the clock line low.
-+ */
-+ if (dev->proto == SSI_USAR) {
-+ udelay(150);
-+
-+ val |= SYSCON3_ADCCKNSEN;
-+ ep_writel(val, SYSCON3);
-+ }
-+#endif
-+ }
-+
-+ return 0;
-+}
-+
-+static void ssi1_int(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct ssi_bus *bus = (struct ssi_bus *)dev_id;
-+
-+ /*
-+ * Read the data word and queue it.
-+ */
-+ ssi_core_rcv(bus, clps_readl(SYNCIO));
-+}
-+
-+/*
-+ * Enable transmission and/or of some bytes
-+ */
-+static int ssi1_trans(struct ssi_bus *bus, u_int data)
-+{
-+ u_int syncio;
-+
-+#ifdef EP7212
-+ data <<= 32 - bus->cfglen;
-+ syncio = bus->cfglen | bus->framelen << 7 | data;
-+#else
-+ syncio = data | bus->framelen << 8;
-+#endif
-+
-+ clps_writel(syncio, SYNCIO);
-+ clps_writel(syncio | SYNCIO_TXFRMEN, SYNCIO);
-+ return 0;
-+}
-+
-+/*
-+ * Initialise the SSI bus.
-+ */
-+static int ssi1_bus_init(struct ssi_bus *bus)
-+{
-+ int retval, val;
-+
-+ retval = request_irq(IRQ_SSEOTI, ssi1_int, 0, "ssi1", bus);
-+ if (retval)
-+ return retval;
-+
-+#ifdef EP7212
-+ /*
-+ * EP7212 only! Set the configuration command length.
-+ * On the CLPS711x chips, it is fixed at 8 bits.
-+ */
-+ val = ep_readl(SYSCON3);
-+ val |= SYSCON3_ADCCON;
-+ ep_writel(val, SYSCON3);
-+#endif
-+
-+ ssi1_select(bus, NULL);
-+
-+ PLD_SPI |= PLD_SPI_EN;
-+
-+ return 0;
-+}
-+
-+static void ssi1_bus_exit(struct ssi_bus *bus)
-+{
-+ ssi1_select(bus, NULL);
-+
-+ PLD_SPI &= ~PLD_SPI_EN;
-+
-+ free_irq(IRQ_SSEOTI, bus);
-+}
-+
-+struct ssi_bus clps711x_ssi1_bus = {
-+ name: "clps711x_ssi1",
-+ init: ssi1_bus_init,
-+ exit: ssi1_bus_exit,
-+ select: ssi1_select,
-+ trans: ssi1_trans,
-+};
-+
-+static int __init clps711x_ssi1_init(void)
-+{
-+ return ssi_register_bus(&clps711x_ssi1_bus);
-+}
-+
-+static void __exit clps711x_ssi1_exit(void)
-+{
-+ ssi_unregister_bus(&clps711x_ssi1_bus);
-+}
-+
-+module_init(clps711x_ssi1_init);
-+module_exit(clps711x_ssi1_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/juno.c
-@@ -0,0 +1,131 @@
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+
-+#include <asm/arch/syspld.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+extern struct ssi_bus clps711x_ssi1_bus;
-+
-+static u_int recvbuf[16];
-+static volatile u_int ptr, rxed;
-+
-+static inline void juno_enable_irq(void)
-+{
-+ enable_irq(IRQ_EINT1);
-+}
-+
-+static inline void juno_disable_irq(void)
-+{
-+ disable_irq(IRQ_EINT1);
-+}
-+
-+static void juno_rcv(struct ssi_dev *dev, u_int data)
-+{
-+ if (ptr < 16) {
-+ recvbuf[ptr] = data;
-+ ptr++;
-+ } else
-+ printk("juno_rcv: %04x\n", data);
-+ rxed = 1;
-+}
-+
-+static void juno_irq(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct ssi_dev *dev = dev_id;
-+
-+ printk("juno_irq\n");
-+
-+ ssi_select_device(dev->bus, dev);
-+
-+ ptr = 0;
-+ do {
-+ rxed = 0;
-+ ssi_transmit_data(dev, 0xff);
-+ while (rxed == 0);
-+ udelay(150);
-+ } while (PLD_INT & PLD_INT_KBD_ATN);
-+
-+ ssi_select_device(dev->bus, NULL);
-+
-+ { int i;
-+ printk("juno_rcv: ");
-+ for (i = 0; i < ptr; i++)
-+ printk("%04x ", recvbuf[i]);
-+ printk("\n");
-+ }
-+}
-+
-+static void juno_command(struct ssi_dev *dev, int cmd, int data)
-+{
-+ ssi_transmit_data(dev, cmd);
-+ mdelay(1);
-+ ssi_transmit_data(dev, data);
-+ mdelay(1);
-+ ssi_transmit_data(dev, 0xa0 ^ 0xc0);
-+ mdelay(1);
-+}
-+
-+static int juno_dev_init(struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+ PLD_KBD |= PLD_KBD_EN;
-+ ptr = 16;
-+
-+ mdelay(20);
-+
-+ retval = request_irq(IRQ_EINT1, juno_irq, 0, dev->name, dev);
-+ if (retval)
-+ return retval;
-+
-+ juno_disable_irq();
-+
-+ if (ssi_select_device(dev->bus, dev) != 0) {
-+ printk("juno: ssi_select_dev failed\n");
-+ return -EBUSY;
-+ }
-+
-+ mdelay(1);
-+
-+ juno_command(dev, 0x80, 0x20);
-+
-+ ssi_select_device(dev->bus, NULL);
-+
-+ juno_enable_irq();
-+
-+ return 0;
-+}
-+
-+static struct ssi_dev juno_dev = {
-+ name: "Juno",
-+ id: 0,
-+ proto: SSI_USAR,
-+ cfglen: 8,
-+ framelen: 8,
-+ clkpol: 1,
-+ clkfreq: 250000,
-+ rcv: juno_rcv,
-+ init: juno_dev_init,
-+};
-+
-+static int __init juno_init(void)
-+{
-+ return ssi_register_device(&clps711x_ssi1_bus, &juno_dev);
-+}
-+
-+static void __exit juno_exit(void)
-+{
-+ ssi_unregister_device(&juno_dev);
-+}
-+
-+module_init(juno_init);
-+module_exit(juno_exit);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/ssi_bus.h
-@@ -0,0 +1,21 @@
-+#include <linux/circ_buf.h>
-+
-+struct ssi_dev;
-+
-+struct ssi_bus {
-+ u_char cfglen;
-+ u_char framelen;
-+ u_char clkpol;
-+ u_char proto;
-+ struct ssi_dev *dev; /* current device */
-+ int (*select)(struct ssi_bus *, struct ssi_dev *);
-+ int (*trans)(struct ssi_bus *, u_int data);
-+ int (*init)(struct ssi_bus *);
-+ void (*exit)(struct ssi_bus *);
-+ char *name;
-+ u_int devices;
-+};
-+
-+extern int ssi_core_rcv(struct ssi_bus *bus, u_int data);
-+extern int ssi_register_bus(struct ssi_bus *bus);
-+extern int ssi_unregister_bus(struct ssi_bus *bus);
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/ssi_core.c
-@@ -0,0 +1,175 @@
-+/*
-+ * linux/drivers/ssi/ssi_core.c
-+ *
-+ * This file provides a common framework to allow multiple SSI devices
-+ * to work together on a single SSI bus.
-+ *
-+ * You can use this in two ways:
-+ * 1. select the device, queue up data, flush the data to the device,
-+ * (optionally) purge the received data, deselect the device.
-+ * 2. select the device, queue up one data word, flush to the device
-+ * read data word, queue up next data word, flush to the device...
-+ * deselect the device.
-+ */
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/malloc.h>
-+#include <linux/init.h>
-+
-+#include <asm/errno.h>
-+
-+#include "ssi_bus.h"
-+#include "ssi_dev.h"
-+
-+#define DEBUG
-+
-+/**
-+ * ssi_core_rcv - pass received SSI data to the device
-+ * @bus: the bus that the data was received from
-+ * @data: the data word that was received
-+ *
-+ * This function is intended to be called by SSI bus device
-+ * drivers to pass received data to the device driver.
-+ */
-+int ssi_core_rcv(struct ssi_bus *bus, u_int data)
-+{
-+ struct ssi_dev *dev = bus->dev;
-+
-+ if (dev && dev->rcv)
-+ dev->rcv(dev, data);
-+
-+ return 0;
-+}
-+
-+/**
-+ * ssi_transmit_data - queue SSI data for later transmission
-+ * @dev: device requesting data to be transmitted
-+ * @data: data word to be transmitted.
-+ *
-+ * Queue one data word of SSI data for later transmission.
-+ */
-+int ssi_transmit_data(struct ssi_dev *dev, u_int data)
-+{
-+ struct ssi_bus *bus = dev->bus;
-+
-+ /*
-+ * Make sure that we currently own the bus
-+ */
-+ if (bus->dev != dev)
-+ BUG();
-+
-+ bus->trans(bus, data);
-+ return 0;
-+}
-+
-+/**
-+ * ssi_select_device - select a SSI device for later transactions
-+ * @dev: device to be selected
-+ */
-+int ssi_select_device(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+#ifdef DEBUG
-+ printk("SSI: selecting device %s on bus %s\n",
-+ dev ? dev->name : "<none>", bus->name);
-+#endif
-+
-+ /*
-+ * Select the device if it wasn't already selected.
-+ */
-+ retval = 0;
-+ if (bus->dev != dev) {
-+ retval = bus->select(bus, dev);
-+ bus->dev = dev;
-+ }
-+
-+ return retval;
-+}
-+
-+/**
-+ * ssi_register_device - register a SSI device with a SSI bus
-+ * @bus: bus
-+ * @dev: SSI device
-+ */
-+int ssi_register_device(struct ssi_bus *bus, struct ssi_dev *dev)
-+{
-+ int retval;
-+
-+ dev->bus = bus;
-+ bus->devices++;
-+ retval = dev->init(dev);
-+ if (retval != 0) {
-+ dev->bus = NULL;
-+ bus->devices--;
-+ } else {
-+#ifdef DEBUG
-+ printk("SSI: registered new device %s on bus %s\n", dev->name, bus->name);
-+#endif
-+ }
-+ return retval;
-+}
-+
-+/**
-+ * ssi_unregister_device - unregister a SSI device from a SSI bus
-+ * @dev: SSI device
-+ */
-+int ssi_unregister_device(struct ssi_dev *dev)
-+{
-+ struct ssi_bus *bus = dev->bus;
-+
-+ if (bus->dev == dev)
-+ bus->dev = NULL;
-+
-+ dev->bus = NULL;
-+ bus->devices--;
-+#ifdef DEBUG
-+ printk("SSI: unregistered device %s on bus %s\n", dev->name, bus->name);
-+#endif
-+ return 0;
-+}
-+
-+/**
-+ * ssi_register_bus - register a SSI bus driver
-+ * @bus: bus
-+ */
-+int ssi_register_bus(struct ssi_bus *bus)
-+{
-+ int retval;
-+
-+ retval = bus->init(bus);
-+ if (retval == 0) {
-+ bus->devices = 0;
-+#ifdef DEBUG
-+ printk("SSI: registered new bus %s\n", bus->name);
-+#endif
-+ }
-+
-+ return retval;
-+}
-+
-+/**
-+ * ssi_unregister_bus - unregister a SSI bus driver
-+ * @bus: bus
-+ */
-+int ssi_unregister_bus(struct ssi_bus *bus)
-+{
-+ int retval = -EBUSY;
-+ if (bus->devices == 0) {
-+ retval = 0;
-+ }
-+ return retval;
-+}
-+
-+static int __init ssi_init(void)
-+{
-+ return 0;
-+}
-+
-+static void __exit ssi_exit(void)
-+{
-+}
-+
-+module_init(ssi_init);
-+module_exit(ssi_exit);
---- /dev/null
-+++ linux-2.4.27/drivers/ssi/ssi_dev.h
-@@ -0,0 +1,21 @@
-+struct ssi_bus;
-+
-+#define SSI_SPI 1
-+#define SSI_MICROWIRE 2
-+#define SSI_TISSF 3
-+#define SSI_USAR 4
-+
-+struct ssi_dev {
-+ char *name;
-+ u_int id;
-+ u_int clkfreq;
-+ u_char cfglen;
-+ u_char framelen;
-+ u_char clkpol;
-+ u_char proto;
-+ void (*rcv)(struct ssi_dev *, u_int);
-+ int (*init)(struct ssi_dev *);
-+ struct ssi_bus *bus;
-+};
-+
-+
---- linux-2.4.27/drivers/usb/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/Config.in
-@@ -4,7 +4,13 @@
- mainmenu_option next_comment
- comment 'USB support'
-
--dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
-+# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
-+if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ tristate 'Support for USB' CONFIG_USB
-+else
-+ define_bool CONFIG_USB n
-+fi
-+
- if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
- bool ' USB verbose debug messages' CONFIG_USB_DEBUG
-
---- linux-2.4.27/drivers/usb/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/Makefile
-@@ -74,6 +74,14 @@
-
- subdir-$(CONFIG_USB_OHCI) += host
- ifeq ($(CONFIG_USB_OHCI),y)
-+ obj-y += host/usb-ohci.o host/usb-ohci-pci.o
-+endif
-+subdir-$(CONFIG_USB_OHCI_SA1111)+= host
-+ifeq ($(CONFIG_USB_OHCI),y)
-+ obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o
-+endif
-+subdir-$(CONFIG_USB_OHCI_AT91) += host
-+ifeq ($(CONFIG_USB_OHCI_AT91),y)
- obj-y += host/usb-ohci.o
- endif
-
-@@ -85,8 +93,6 @@
- obj-$(CONFIG_USB_KBD) += usbkbd.o
- obj-$(CONFIG_USB_AIPTEK) += aiptek.o
- obj-$(CONFIG_USB_WACOM) += wacom.o
--obj-$(CONFIG_USB_KBTAB) += kbtab.o
--obj-$(CONFIG_USB_POWERMATE) += powermate.o
-
- obj-$(CONFIG_USB_SCANNER) += scanner.o
- obj-$(CONFIG_USB_ACM) += acm.o
---- linux-2.4.27/drivers/usb/hcd.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/hcd.c
-@@ -96,7 +96,7 @@
- /* used when updating hcd data */
- static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
-
--static struct usb_operations hcd_operations;
-+/*static*/ struct usb_operations hcd_operations;
-
- /*-------------------------------------------------------------------------*/
-
-@@ -1208,13 +1208,21 @@
- } else {
- if (usb_pipecontrol (urb->pipe))
- urb->setup_dma = pci_map_single (
-+#ifdef CONFIG_PCI
- hcd->pdev,
-+#else
-+ NULL,
-+#endif
- urb->setup_packet,
- sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
- if (urb->transfer_buffer_length != 0)
- urb->transfer_dma = pci_map_single (
-+#ifdef CONFIG_PCI
- hcd->pdev,
-+#else
-+ NULL,
-+#endif
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
-@@ -1424,7 +1432,7 @@
- return 0;
- }
-
--static struct usb_operations hcd_operations = {
-+/*static*/ struct usb_operations hcd_operations = {
- allocate: hcd_alloc_dev,
- get_frame_number: hcd_get_frame_number,
- submit_urb: hcd_submit_urb,
-@@ -1434,7 +1442,7 @@
-
- /*-------------------------------------------------------------------------*/
-
--static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
-+/*static*/ void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
- {
- struct usb_hcd *hcd = __hcd;
- int start = hcd->state;
-@@ -1490,12 +1498,24 @@
-
- /* For 2.4, don't unmap bounce buffer if it's a root hub operation. */
- if (usb_pipecontrol (urb->pipe) && !is_root_hub_operation)
-- pci_unmap_single (hcd->pdev, urb->setup_dma,
-+ pci_unmap_single (
-+#ifdef CONFIG_PCI
-+ hcd->pdev,
-+#else
-+ NULL,
-+#endif
-+ urb->setup_dma,
- sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
-
- if ((urb->transfer_buffer_length != 0) && !is_root_hub_operation)
-- pci_unmap_single (hcd->pdev, urb->transfer_dma,
-+ pci_unmap_single (
-+#ifdef CONFIG_PCI
-+ hcd->pdev,
-+#else
-+ NULL,
-+#endif
-+ urb->transfer_dma,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
- ? PCI_DMA_FROMDEVICE
---- linux-2.4.27/drivers/usb/host/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/host/Config.in
-@@ -12,8 +12,13 @@
- define_bool CONFIG_USB_UHCI_ALT n
- fi
- dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
-+dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
- if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" -a "$CONFIG_X86_64" != "y" ]; then
- # Cypress embedded USB controller on StrongARM or on x86 in PC/104
- dep_tristate ' SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
- dep_tristate ' SL811HS (x86, StrongARM) support, old driver' CONFIG_USB_SL811HS $CONFIG_USB $CONFIG_EXPERIMENTAL
- fi
-+if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
-+ dep_tristate ' AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB
-+fi
-+
---- linux-2.4.27/drivers/usb/host/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/host/Makefile
-@@ -8,9 +8,11 @@
- obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
- obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
- obj-$(CONFIG_USB_UHCI) += usb-uhci.o
--obj-$(CONFIG_USB_OHCI) += usb-ohci.o
-+obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o
- obj-$(CONFIG_USB_SL811HS_ALT) += sl811.o
- obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
-+obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o
-+obj-$(CONFIG_USB_OHCI_AT91) += usb-ohci.o
-
- # Extract lists of the multi-part drivers.
- # The 'int-*' lists are the intermediate files used to build the multi's.
---- /dev/null
-+++ linux-2.4.27/drivers/usb/host/usb-ohci-pci.c
-@@ -0,0 +1,436 @@
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h> /* for in_interrupt() */
-+#undef DEBUG
-+#include <linux/usb.h>
-+
-+#include "usb-ohci.h"
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+#include <asm/machdep.h>
-+#include <asm/pmac_feature.h>
-+#include <asm/pci-bridge.h>
-+#ifndef CONFIG_PM
-+#define CONFIG_PM
-+#endif
-+#endif
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* Increment the module usage count, start the control thread and
-+ * return success. */
-+
-+static struct pci_driver ohci_pci_driver;
-+extern spinlock_t usb_ed_lock;
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
-+ const char *name, const char *slot_name);
-+extern void hc_remove_ohci(ohci_t *ohci);
-+
-+static int __devinit
-+hc_found_ohci (struct pci_dev *dev, int irq,
-+ void *mem_base, const struct pci_device_id *id)
-+{
-+ unsigned long flags = id->driver_data;
-+
-+ printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
-+
-+ /* Check for NSC87560. We have to look at the bridge (fn1) to identify
-+ the USB (fn2). This quirk might apply to more or even all NSC stuff
-+ I don't know.. */
-+
-+ if(dev->vendor == PCI_VENDOR_ID_NS)
-+ {
-+ struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
-+ if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
-+ flags |= OHCI_QUIRK_SUCKYIO;
-+
-+ }
-+
-+ if (flags & OHCI_QUIRK_SUCKYIO)
-+ printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
-+ if (flags & OHCI_QUIRK_AMD756)
-+ printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
-+
-+ return hc_add_ohci(dev, irq, mem_base, flags,
-+ ohci_pci_driver.name, dev->slot_name);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+#ifdef CONFIG_PM
-+
-+/* controller died; cleanup debris, then restart */
-+/* must not be called from interrupt context */
-+
-+static void hc_restart (ohci_t *ohci)
-+{
-+ int temp;
-+ int i;
-+
-+ if (ohci->pci_latency)
-+ pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
-+
-+ ohci->disabled = 1;
-+ ohci->sleeping = 0;
-+ if (ohci->bus->root_hub)
-+ usb_disconnect (&ohci->bus->root_hub);
-+
-+ /* empty the interrupt branches */
-+ for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-+ for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
-+
-+ /* no EDs to remove */
-+ ohci->ed_rm_list [0] = NULL;
-+ ohci->ed_rm_list [1] = NULL;
-+
-+ /* empty control and bulk lists */
-+ ohci->ed_isotail = NULL;
-+ ohci->ed_controltail = NULL;
-+ ohci->ed_bulktail = NULL;
-+
-+ if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-+ err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
-+ } else
-+ dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
-+}
-+
-+#endif /* CONFIG_PM */
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* configured so that an OHCI device is always provided */
-+/* always called with process context; sleeping is OK */
-+
-+static int __devinit
-+ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-+{
-+ unsigned long mem_resource, mem_len;
-+ void *mem_base;
-+ int status;
-+
-+ if (pci_enable_device(dev) < 0)
-+ return -ENODEV;
-+
-+ if (!dev->irq) {
-+ err("found OHCI device with no IRQ assigned. check BIOS settings!");
-+ pci_disable_device (dev);
-+ return -ENODEV;
-+ }
-+
-+ /* we read its hardware registers as memory */
-+ mem_resource = pci_resource_start(dev, 0);
-+ mem_len = pci_resource_len(dev, 0);
-+ if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-+ dbg ("controller already in use");
-+ pci_disable_device (dev);
-+ return -EBUSY;
-+ }
-+
-+ mem_base = ioremap_nocache (mem_resource, mem_len);
-+ if (!mem_base) {
-+ err("Error mapping OHCI memory");
-+ release_mem_region (mem_resource, mem_len);
-+ pci_disable_device (dev);
-+ return -EFAULT;
-+ }
-+
-+ /* controller writes into our memory */
-+ pci_set_master (dev);
-+
-+ status = hc_found_ohci (dev, dev->irq, mem_base, id);
-+ if (status < 0) {
-+ iounmap (mem_base);
-+ release_mem_region (mem_resource, mem_len);
-+ pci_disable_device (dev);
-+ }
-+ return status;
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* may be called from interrupt context [interface spec] */
-+/* may be called without controller present */
-+/* may be called with controller, bus, and devices active */
-+
-+static void __devexit
-+ohci_pci_remove (struct pci_dev *dev)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+
-+ dbg ("remove %s controller usb-%s%s%s",
-+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-+ dev->slot_name,
-+ ohci->disabled ? " (disabled)" : "",
-+ in_interrupt () ? " in interrupt" : ""
-+ );
-+
-+ hc_remove_ohci(ohci);
-+
-+ release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-+ pci_disable_device (dev);
-+}
-+
-+
-+#ifdef CONFIG_PM
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int
-+ohci_pci_suspend (struct pci_dev *dev, u32 state)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+ unsigned long flags;
-+ u16 cmd;
-+
-+ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-+ dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-+ hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-+ return -EIO;
-+ }
-+
-+ /* act as if usb suspend can always be used */
-+ info ("USB suspend: usb-%s", dev->slot_name);
-+ ohci->sleeping = 1;
-+
-+ /* First stop processing */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-+ (void) readl (&ohci->regs->intrstatus);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+
-+ /* Wait a frame or two */
-+ mdelay(1);
-+ if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-+ mdelay (1);
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+ if (_machine == _MACH_Pmac)
-+ disable_irq (ohci->irq);
-+ /* else, 2.4 assumes shared irqs -- don't disable */
-+#endif
-+ /* Enable remote wakeup */
-+ writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
-+
-+ /* Suspend chip and let things settle down a bit */
-+ ohci->hc_control = OHCI_USB_SUSPEND;
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (500); /* No schedule here ! */
-+ switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-+ case OHCI_USB_RESET:
-+ dbg("Bus in reset phase ???");
-+ break;
-+ case OHCI_USB_RESUME:
-+ dbg("Bus in resume phase ???");
-+ break;
-+ case OHCI_USB_OPER:
-+ dbg("Bus in operational phase ???");
-+ break;
-+ case OHCI_USB_SUSPEND:
-+ dbg("Bus suspended");
-+ break;
-+ }
-+ /* In some rare situations, Apple's OHCI have happily trashed
-+ * memory during sleep. We disable it's bus master bit during
-+ * suspend
-+ */
-+ pci_read_config_word (dev, PCI_COMMAND, &cmd);
-+ cmd &= ~PCI_COMMAND_MASTER;
-+ pci_write_config_word (dev, PCI_COMMAND, cmd);
-+#ifdef CONFIG_PMAC_PBOOK
-+ {
-+ struct device_node *of_node;
-+
-+ /* Disable USB PAD & cell clock */
-+ of_node = pci_device_to_OF_node (ohci->ohci_dev);
-+ if (of_node)
-+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-+ }
-+#endif
-+ return 0;
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int
-+ohci_pci_resume (struct pci_dev *dev)
-+{
-+ ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev);
-+ int temp;
-+ unsigned long flags;
-+
-+ /* guard against multiple resumes */
-+ atomic_inc (&ohci->resume_count);
-+ if (atomic_read (&ohci->resume_count) != 1) {
-+ err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-+ atomic_dec (&ohci->resume_count);
-+ return 0;
-+ }
-+
-+#ifdef CONFIG_PMAC_PBOOK
-+ {
-+ struct device_node *of_node;
-+
-+ /* Re-enable USB PAD & cell clock */
-+ of_node = pci_device_to_OF_node (ohci->ohci_dev);
-+ if (of_node)
-+ pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-+ }
-+#endif
-+
-+ /* did we suspend, or were we powered off? */
-+ ohci->hc_control = readl (&ohci->regs->control);
-+ temp = ohci->hc_control & OHCI_CTRL_HCFS;
-+
-+#ifdef DEBUG
-+ /* the registers may look crazy here */
-+ ohci_dump_status (ohci);
-+#endif
-+
-+ /* Re-enable bus mastering */
-+ pci_set_master(ohci->ohci_dev);
-+
-+ switch (temp) {
-+
-+ case OHCI_USB_RESET: // lost power
-+ info ("USB restart: usb-%s", dev->slot_name);
-+ hc_restart (ohci);
-+ break;
-+
-+ case OHCI_USB_SUSPEND: // host wakeup
-+ case OHCI_USB_RESUME: // remote wakeup
-+ info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
-+ (temp == OHCI_USB_SUSPEND)
-+ ? "host" : "remote");
-+ ohci->hc_control = OHCI_USB_RESUME;
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (20); /* no schedule here ! */
-+ /* Some controllers (lucent) need a longer delay here */
-+ mdelay (15);
-+ temp = readl (&ohci->regs->control);
-+ temp = ohci->hc_control & OHCI_CTRL_HCFS;
-+ if (temp != OHCI_USB_RESUME) {
-+ err ("controller usb-%s won't resume", dev->slot_name);
-+ ohci->disabled = 1;
-+ return -EIO;
-+ }
-+
-+ /* Some chips likes being resumed first */
-+ writel (OHCI_USB_OPER, &ohci->regs->control);
-+ (void) readl (&ohci->regs->control);
-+ mdelay (3);
-+
-+ /* Then re-enable operations */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ ohci->disabled = 0;
-+ ohci->sleeping = 0;
-+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-+ if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-+ if (ohci->ed_controltail)
-+ ohci->hc_control |= OHCI_CTRL_CLE;
-+ if (ohci->ed_bulktail)
-+ ohci->hc_control |= OHCI_CTRL_BLE;
-+ }
-+ writel (ohci->hc_control, &ohci->regs->control);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-+ writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-+ /* Check for a pending done list */
-+ writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
-+ (void) readl (&ohci->regs->intrdisable);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+#ifdef CONFIG_PMAC_PBOOK
-+ if (_machine == _MACH_Pmac)
-+ enable_irq (ohci->irq);
-+#endif
-+ if (ohci->hcca->done_head)
-+ dl_done_list (ohci, dl_reverse_done_list (ohci));
-+ writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
-+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-+ break;
-+
-+ default:
-+ warn ("odd PCI resume for usb-%s", dev->slot_name);
-+ }
-+
-+ /* controller is operational, extra resumes are harmless */
-+ atomic_dec (&ohci->resume_count);
-+
-+ return 0;
-+}
-+
-+#endif /* CONFIG_PM */
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
-+
-+ /*
-+ * AMD-756 [Viper] USB has a serious erratum when used with
-+ * lowspeed devices like mice.
-+ */
-+ vendor: 0x1022,
-+ device: 0x740c,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+
-+ driver_data: OHCI_QUIRK_AMD756,
-+
-+} , {
-+
-+ /* handle any USB OHCI controller */
-+ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-+ class_mask: ~0,
-+
-+ /* no matter who makes it */
-+ vendor: PCI_ANY_ID,
-+ device: PCI_ANY_ID,
-+ subvendor: PCI_ANY_ID,
-+ subdevice: PCI_ANY_ID,
-+
-+ }, { /* end: all zeroes */ }
-+};
-+
-+MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
-+
-+static struct pci_driver ohci_pci_driver = {
-+ name: "usb-ohci",
-+ id_table: &ohci_pci_ids [0],
-+
-+ probe: ohci_pci_probe,
-+ remove: __devexit_p(ohci_pci_remove),
-+
-+#ifdef CONFIG_PM
-+ suspend: ohci_pci_suspend,
-+ resume: ohci_pci_resume,
-+#endif /* PM */
-+};
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static int __init ohci_hcd_init (void)
-+{
-+ return pci_module_init (&ohci_pci_driver);
-+}
-+
-+/*-------------------------------------------------------------------------*/
-+
-+static void __exit ohci_hcd_cleanup (void)
-+{
-+ pci_unregister_driver (&ohci_pci_driver);
-+}
-+
-+module_init (ohci_hcd_init);
-+module_exit (ohci_hcd_cleanup);
-+
---- /dev/null
-+++ linux-2.4.27/drivers/usb/host/usb-ohci-sa1111.c
-@@ -0,0 +1,118 @@
-+/*
-+ * linux/drivers/usb/usb-ohci-sa1111.c
-+ *
-+ * The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
-+ * original OHCI driver modifications, and reworked into a cleaner form
-+ * by Russell King <rmk@arm.linux.org.uk>.
-+ */
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/usb.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/io.h>
-+#include <asm/pci.h>
-+#include <asm/arch/assabet.h>
-+#include <asm/arch/badge4.h>
-+#include <asm/hardware/sa1111.h>
-+
-+#include "usb-ohci.h"
-+
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
-+ const char *name, const char *slot_name);
-+extern void hc_remove_ohci(ohci_t *ohci);
-+
-+static ohci_t *sa1111_ohci;
-+
-+static void __init sa1111_ohci_configure(void)
-+{
-+ unsigned int usb_rst = 0;
-+
-+ if (machine_is_xp860() ||
-+ machine_has_neponset() ||
-+ machine_is_accelent_sa() ||
-+ machine_is_pfs168() ||
-+ machine_is_badge4())
-+ usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
-+
-+ /*
-+ * Configure the power sense and control lines. Place the USB
-+ * host controller in reset.
-+ */
-+ USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
-+
-+ /*
-+ * Now, carefully enable the USB clock, and take
-+ * the USB host controller out of reset.
-+ */
-+ SKPCR |= SKPCR_UCLKEN;
-+ udelay(11);
-+ USB_RESET = usb_rst;
-+}
-+
-+static int __init sa1111_ohci_init(void)
-+{
-+ int ret;
-+
-+ /*
-+ * Request memory resources.
-+ */
-+// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci"))
-+// return -EBUSY;
-+
-+ sa1111_ohci_configure();
-+
-+ /*
-+ * Initialise the generic OHCI driver.
-+ */
-+ ret = hc_add_ohci(SA1111_FAKE_PCIDEV, NIRQHCIM,
-+ (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci,
-+ "usb-ohci", "sa1111");
-+
-+// if (ret)
-+// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
-+
-+#ifdef CONFIG_SA1100_BADGE4
-+ if (machine_is_badge4() && (!ret)) {
-+ /* found the controller, so now power the bus */
-+ badge4_set_5V(BADGE4_5V_USB, 1);
-+ }
-+#endif
-+
-+ return ret;
-+}
-+
-+static void __exit sa1111_ohci_exit(void)
-+{
-+ hc_remove_ohci(sa1111_ohci);
-+
-+ /*
-+ * Put the USB host controller into reset.
-+ */
-+ USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
-+
-+ /*
-+ * Stop the USB clock.
-+ */
-+ SKPCR &= ~SKPCR_UCLKEN;
-+
-+ /*
-+ * Release memory resources.
-+ */
-+// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
-+
-+#ifdef CONFIG_SA1100_BADGE4
-+ if (machine_is_badge4()) {
-+ badge4_set_5V(BADGE4_5V_USB, 0);
-+ }
-+#endif
-+}
-+
-+module_init(sa1111_ohci_init);
-+module_exit(sa1111_ohci_exit);
---- linux-2.4.27/drivers/usb/host/usb-ohci.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/host/usb-ohci.c
-@@ -12,7 +12,6 @@
- *
- * History:
- *
-- * 2002/10/22 OHCI_USB_OPER for ALi lockup in IBM i1200 (ALEX <thchou@ali>)
- * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
- * load failure (Matthew Frederickson)
- * 2002/01/20 async unlink fixes: return -EINPROGRESS (per spec) and
-@@ -81,16 +80,6 @@
-
- #include "../hcd.h"
-
--#ifdef CONFIG_PMAC_PBOOK
--#include <asm/machdep.h>
--#include <asm/pmac_feature.h>
--#include <asm/pci-bridge.h>
--#ifndef CONFIG_PM
--#define CONFIG_PM
--#endif
--#endif
--
--
- /*
- * Version Information
- */
-@@ -98,12 +87,12 @@
- #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
- #define DRIVER_DESC "USB OHCI Host Controller Driver"
-
--/* For initializing controller (mask in an HCFS mode too) */
--#define OHCI_CONTROL_INIT \
-- (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
--
- #define OHCI_UNLINK_TIMEOUT (HZ / 10)
-
-+static LIST_HEAD (ohci_hcd_list);
-+spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-+
-+
- /*-------------------------------------------------------------------------*/
-
- /* AMD-756 (D2 rev) reports corrupt register contents in some cases.
-@@ -130,57 +119,6 @@
- /*-------------------------------------------------------------------------*
- * URB support functions
- *-------------------------------------------------------------------------*/
--
--static void ohci_complete_add(struct ohci *ohci, struct urb *urb)
--{
--
-- if (urb->hcpriv != NULL) {
-- printk("completing with non-null priv!\n");
-- return;
-- }
--
-- if (ohci->complete_tail == NULL) {
-- ohci->complete_head = urb;
-- ohci->complete_tail = urb;
-- } else {
-- ohci->complete_head->hcpriv = urb;
-- ohci->complete_tail = urb;
-- }
--}
--
--static inline struct urb *ohci_complete_get(struct ohci *ohci)
--{
-- struct urb *urb;
--
-- if ((urb = ohci->complete_head) == NULL)
-- return NULL;
-- if (urb == ohci->complete_tail) {
-- ohci->complete_tail = NULL;
-- ohci->complete_head = NULL;
-- } else {
-- ohci->complete_head = urb->hcpriv;
-- }
-- urb->hcpriv = NULL;
-- return urb;
--}
--
--static inline void ohci_complete(struct ohci *ohci)
--{
-- struct urb *urb;
--
-- spin_lock(&ohci->ohci_lock);
-- while ((urb = ohci_complete_get(ohci)) != NULL) {
-- spin_unlock(&ohci->ohci_lock);
-- if (urb->dev) {
-- usb_dec_dev_use (urb->dev);
-- urb->dev = NULL;
-- }
-- if (urb->complete)
-- (*urb->complete)(urb);
-- spin_lock(&ohci->ohci_lock);
-- }
-- spin_unlock(&ohci->ohci_lock);
--}
-
- /* free HCD-private data associated with this URB */
-
-@@ -256,14 +194,20 @@
- }
-
- urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
-- } else {
-- if (urb->dev != NULL) {
-- err ("Non-null dev at rm_priv time");
-- // urb->dev = NULL;
-- }
-+ usb_dec_dev_use (urb->dev);
-+ urb->dev = NULL;
- }
- }
-
-+static void urb_rm_priv (struct urb * urb)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ urb_rm_priv_locked (urb);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+}
-+
- /*-------------------------------------------------------------------------*/
-
- #ifdef DEBUG
-@@ -484,7 +428,7 @@
-
- static void ohci_dump (ohci_t *controller, int verbose)
- {
-- dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
-+ dbg ("OHCI controller usb-%s state", controller->slot_name);
-
- // dumps some of the state we know about
- ohci_dump_status (controller);
-@@ -507,6 +451,7 @@
- {
- urb_priv_t * urb_priv = urb->hcpriv;
- struct urb * urbt;
-+ unsigned long flags;
- int i;
-
- if (!urb_priv)
-@@ -514,8 +459,7 @@
-
- /* just to be sure */
- if (!urb->complete) {
-- urb_rm_priv_locked (urb);
-- ohci_complete_add(hc, urb); /* Just usb_dec_dev_use */
-+ urb_rm_priv (urb);
- return -1;
- }
-
-@@ -531,18 +475,20 @@
- usb_pipeout (urb->pipe)
- ? PCI_DMA_TODEVICE
- : PCI_DMA_FROMDEVICE);
-+
- if (urb->interval) {
- urb->complete (urb);
--
-+
- /* implicitly requeued */
- urb->actual_length = 0;
- urb->status = -EINPROGRESS;
- td_submit_urb (urb);
- } else {
-- urb_rm_priv_locked (urb);
-- ohci_complete_add(hc, urb);
-+ urb_rm_priv(urb);
-+ urb->complete (urb);
- }
-- break;
-+ break;
-+
-
- case PIPE_ISOCHRONOUS:
- for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
-@@ -554,6 +500,7 @@
- ? PCI_DMA_TODEVICE
- : PCI_DMA_FROMDEVICE);
- urb->complete (urb);
-+ spin_lock_irqsave (&usb_ed_lock, flags);
- urb->actual_length = 0;
- urb->status = USB_ST_URB_PENDING;
- urb->start_frame = urb_priv->ed->last_iso + 1;
-@@ -564,17 +511,18 @@
- }
- td_submit_urb (urb);
- }
--
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-+
- } else { /* unlink URB, call complete */
-- urb_rm_priv_locked (urb);
-- ohci_complete_add(hc, urb);
-+ urb_rm_priv (urb);
-+ urb->complete (urb);
- }
- break;
-
- case PIPE_BULK:
- case PIPE_CONTROL: /* unlink URB, call complete */
-- urb_rm_priv_locked (urb);
-- ohci_complete_add(hc, urb);
-+ urb_rm_priv (urb);
-+ urb->complete (urb);
- break;
- }
- return 0;
-@@ -594,7 +542,7 @@
- int i, size = 0;
- unsigned long flags;
- int bustime = 0;
-- int mem_flags = GFP_ATOMIC;
-+ int mem_flags = ALLOC_FLAGS;
-
- if (!urb->dev || !urb->dev->bus)
- return -ENODEV;
-@@ -611,24 +559,20 @@
- #ifdef DEBUG
- urb_print (urb, "SUB", usb_pipein (pipe));
- #endif
--
-+
- /* handle a request to the virtual root hub */
- if (usb_pipedevice (pipe) == ohci->rh.devnum)
- return rh_submit_urb (urb);
--
-- spin_lock_irqsave(&ohci->ohci_lock, flags);
--
-+
- /* when controller's hung, permit only roothub cleanup attempts
- * such as powering down ports */
- if (ohci->disabled) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -ESHUTDOWN;
- }
-
- /* every endpoint has a ed, locate and fill it */
- if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -ENOMEM;
- }
-@@ -650,7 +594,6 @@
- case PIPE_ISOCHRONOUS: /* number of packets from URB */
- size = urb->number_of_packets;
- if (size <= 0) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -EINVAL;
- }
-@@ -670,9 +613,8 @@
-
- /* allocate the private part of the URB */
- urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *),
-- GFP_ATOMIC);
-+ in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
- if (!urb_priv) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -ENOMEM;
- }
-@@ -683,12 +625,13 @@
- urb_priv->ed = ed;
-
- /* allocate the TDs (updating hash chains) */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
- for (i = 0; i < size; i++) {
- urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
- if (!urb_priv->td[i]) {
- urb_priv->length = i;
- urb_free_priv (ohci, urb_priv);
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -ENOMEM;
- }
-@@ -696,7 +639,7 @@
-
- if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
- urb_free_priv (ohci, urb_priv);
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- usb_dec_dev_use (urb->dev);
- return -EINVAL;
- }
-@@ -718,7 +661,7 @@
- }
- if (bustime < 0) {
- urb_free_priv (ohci, urb_priv);
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- usb_dec_dev_use (urb->dev);
- return bustime;
- }
-@@ -744,6 +687,9 @@
- if (urb->timeout) {
- struct list_head *entry;
-
-+ // FIXME: usb-uhci uses relative timeouts (like this),
-+ // while uhci uses absolute ones (probably better).
-+ // Pick one solution and change the affected drivers.
- urb->timeout += jiffies;
-
- list_for_each (entry, &ohci->timeout_list) {
-@@ -757,11 +703,10 @@
-
- /* drive timeouts by SF (messy, but works) */
- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- #endif
-
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-
- return 0;
- }
-@@ -792,7 +737,6 @@
- if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
- return rh_unlink_urb (urb);
-
-- spin_lock_irqsave(&ohci->ohci_lock, flags);
- if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) {
- if (!ohci->disabled) {
- urb_priv_t * urb_priv;
-@@ -802,7 +746,6 @@
- */
- if (!(urb->transfer_flags & USB_ASYNC_UNLINK)
- && in_interrupt ()) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- err ("bug in call from %p; use async!",
- __builtin_return_address(0));
- return -EWOULDBLOCK;
-@@ -811,10 +754,11 @@
- /* flag the urb and its TDs for deletion in some
- * upcoming SF interrupt delete list processing
- */
-+ spin_lock_irqsave (&usb_ed_lock, flags);
- urb_priv = urb->hcpriv;
-
- if (!urb_priv || (urb_priv->state == URB_DEL)) {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return 0;
- }
-
-@@ -829,36 +773,26 @@
-
- add_wait_queue (&unlink_wakeup, &wait);
- urb_priv->wait = &unlink_wakeup;
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-
- /* wait until all TDs are deleted */
- set_current_state(TASK_UNINTERRUPTIBLE);
-- while (timeout && (urb->status == USB_ST_URB_PENDING)) {
-+ while (timeout && (urb->status == USB_ST_URB_PENDING))
- timeout = schedule_timeout (timeout);
-- set_current_state(TASK_UNINTERRUPTIBLE);
-- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue (&unlink_wakeup, &wait);
- if (urb->status == USB_ST_URB_PENDING) {
- err ("unlink URB timeout");
- return -ETIMEDOUT;
- }
--
-- usb_dec_dev_use (urb->dev);
-- urb->dev = NULL;
-- if (urb->complete)
-- urb->complete (urb);
- } else {
- /* usb_dec_dev_use done in dl_del_list() */
- urb->status = -EINPROGRESS;
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return -EINPROGRESS;
- }
- } else {
-- urb_rm_priv_locked (urb);
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-- usb_dec_dev_use (urb->dev);
-- urb->dev = NULL;
-+ urb_rm_priv (urb);
- if (urb->transfer_flags & USB_ASYNC_UNLINK) {
- urb->status = -ECONNRESET;
- if (urb->complete)
-@@ -866,8 +800,6 @@
- } else
- urb->status = -ENOENT;
- }
-- } else {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- }
- return 0;
- }
-@@ -910,14 +842,14 @@
- * (freeing all the TDs, unlinking EDs) but we need
- * to defend against bugs that prevent that.
- */
-- spin_lock_irqsave(&ohci->ohci_lock, flags);
-+ spin_lock_irqsave (&usb_ed_lock, flags);
- for(i = 0; i < NUM_EDS; i++) {
- ed = &(dev->ed[i]);
- if (ed->state != ED_NEW) {
- if (ed->state == ED_OPER) {
- /* driver on that interface didn't unlink an urb */
- dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
-- ohci->ohci_dev->slot_name, usb_dev->devnum, i);
-+ ohci->slot_name, usb_dev->devnum, i);
- ep_unlink (ohci, ed);
- }
- ep_rm_ed (usb_dev, ed);
-@@ -925,7 +857,7 @@
- cnt++;
- }
- }
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-
- /* if the controller is running, tds for those unlinked
- * urbs get freed by dl_del_list at the next SF interrupt
-@@ -962,7 +894,7 @@
- } else {
- /* likely some interface's driver has a refcount bug */
- err ("bus %s devnum %d deletion in interrupt",
-- ohci->ohci_dev->slot_name, usb_dev->devnum);
-+ ohci->slot_name, usb_dev->devnum);
- BUG ();
- }
- }
-@@ -1259,12 +1191,17 @@
- td_t * td;
- ed_t * ed_ret;
- volatile ed_t * ed;
-+ unsigned long flags;
-+
-+
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-
- ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) |
- (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
-
- if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
- /* pending delete request */
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return NULL;
- }
-
-@@ -1277,6 +1214,7 @@
- /* out of memory */
- if (td)
- td_free(ohci, td);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return NULL;
- }
- ed->hwTailP = cpu_to_le32 (td->td_dma);
-@@ -1299,7 +1237,8 @@
- ed->int_period = interval;
- ed->int_load = load;
- }
--
-+
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return ed_ret;
- }
-
-@@ -1340,7 +1279,6 @@
- /* enable SOF interrupt */
- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- }
-
-@@ -1362,7 +1300,11 @@
- err("internal OHCI error: TD index > length");
- return;
- }
--
-+#ifdef CONFIG_SA1111
-+ if (data & (1 << 20))
-+ panic("td_fill: A20 = 1: %08x\n", data);
-+#endif
-+
- /* use this td as the next dummy */
- td_pt = urb_priv->td [index];
- td_pt->hwNextTD = 0;
-@@ -1461,7 +1403,6 @@
- if (!ohci->sleeping) {
- wmb();
- writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- break;
-
-@@ -1490,7 +1431,6 @@
- if (!ohci->sleeping) {
- wmb();
- writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- }
- break;
-
-@@ -1558,7 +1498,7 @@
-
- /* handle an urb that is being unlinked */
-
--static void dl_del_urb (ohci_t *ohci, struct urb * urb)
-+static void dl_del_urb (struct urb * urb)
- {
- wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
-
-@@ -1566,9 +1506,12 @@
-
- if (urb->transfer_flags & USB_ASYNC_UNLINK) {
- urb->status = -ECONNRESET;
-- ohci_complete_add(ohci, urb);
-+ if (urb->complete)
-+ urb->complete (urb);
- } else {
- urb->status = -ENOENT;
-+ if (urb->complete)
-+ urb->complete (urb);
-
- /* unblock sohci_unlink_urb */
- if (wait_head)
-@@ -1587,7 +1530,10 @@
- td_t * td_rev = NULL;
- td_t * td_list = NULL;
- urb_priv_t * urb_priv = NULL;
--
-+ unsigned long flags;
-+
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+
- td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
- ohci->hcca->done_head = 0;
-
-@@ -1613,6 +1559,7 @@
- td_rev = td_list;
- td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;
- }
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- return td_list;
- }
-
-@@ -1624,6 +1571,7 @@
-
- static void dl_del_list (ohci_t * ohci, unsigned int frame)
- {
-+ unsigned long flags;
- ed_t * ed;
- __u32 edINFO;
- __u32 tdINFO;
-@@ -1631,6 +1579,8 @@
- __u32 * td_p;
- int ctrl = 0, bulk = 0;
-
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+
- for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
-
- tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
-@@ -1651,7 +1601,7 @@
-
- /* URB is done; clean up */
- if (++(urb_priv->td_cnt) == urb_priv->length)
-- dl_del_urb (ohci, urb);
-+ dl_del_urb (urb);
- } else {
- td_p = &td->hwNextTD;
- }
-@@ -1708,6 +1658,7 @@
- }
-
- ohci->ed_rm_list[frame] = NULL;
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- }
-
-
-@@ -1724,7 +1675,9 @@
- struct urb * urb;
- urb_priv_t * urb_priv;
- __u32 tdINFO, edHeadP, edTailP;
--
-+
-+ unsigned long flags;
-+
- while (td_list) {
- td_list_next = td_list->next_dl_td;
-
-@@ -1753,10 +1706,13 @@
- urb->status = cc_to_error[cc];
- sohci_return_urb (ohci, urb);
- } else {
-- dl_del_urb (ohci, urb);
-+ spin_lock_irqsave (&usb_ed_lock, flags);
-+ dl_del_urb (urb);
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
- }
- }
-
-+ spin_lock_irqsave (&usb_ed_lock, flags);
- if (ed->state != ED_NEW) {
- edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
- edTailP = le32_to_cpup (&ed->hwTailP);
-@@ -1765,6 +1721,7 @@
- if ((edHeadP == edTailP) && (ed->state == ED_OPER))
- ep_unlink (ohci, ed);
- }
-+ spin_unlock_irqrestore (&usb_ed_lock, flags);
-
- td_list = td_list_next;
- }
-@@ -1855,7 +1812,7 @@
- num_ports = roothub_a (ohci) & RH_A_NDP;
- if (num_ports > MAX_ROOT_PORTS) {
- err ("bogus NDP=%d for OHCI usb-%s", num_ports,
-- ohci->ohci_dev->slot_name);
-+ ohci->slot_name);
- err ("rereads as NDP=%d",
- readl (&ohci->regs->roothub.a) & RH_A_NDP);
- /* retry later; "should not happen" */
-@@ -1955,8 +1912,7 @@
- int leni = urb->transfer_buffer_length;
- int len = 0;
- int status = TD_CC_NOERROR;
-- unsigned long flags;
--
-+
- __u32 datab[4];
- __u8 * data_buf = (__u8 *) datab;
-
-@@ -1965,16 +1921,13 @@
- __u16 wIndex;
- __u16 wLength;
-
-- spin_lock_irqsave(&ohci->ohci_lock, flags);
--
- if (usb_pipeint(pipe)) {
- ohci->rh.urb = urb;
- ohci->rh.send = 1;
- ohci->rh.interval = urb->interval;
- rh_init_int_timer(urb);
- urb->status = cc_to_error [TD_CC_NOERROR];
--
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
-+
- return 0;
- }
-
-@@ -2146,7 +2099,6 @@
- #endif
-
- urb->hcpriv = NULL;
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use (usb_dev);
- urb->dev = NULL;
- if (urb->complete)
-@@ -2159,16 +2111,13 @@
- static int rh_unlink_urb (struct urb * urb)
- {
- ohci_t * ohci = urb->dev->bus->hcpriv;
-- unsigned int flags;
-
-- spin_lock_irqsave(&ohci->ohci_lock, flags);
- if (ohci->rh.urb == urb) {
- ohci->rh.send = 0;
- del_timer (&ohci->rh.rh_int_timer);
- ohci->rh.urb = NULL;
-
- urb->hcpriv = NULL;
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- usb_dec_dev_use(urb->dev);
- urb->dev = NULL;
- if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-@@ -2177,8 +2126,6 @@
- urb->complete (urb);
- } else
- urb->status = -ENOENT;
-- } else {
-- spin_unlock_irqrestore(&ohci->ohci_lock, flags);
- }
- return 0;
- }
-@@ -2213,16 +2160,12 @@
- writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
-
- dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
-- ohci->ohci_dev->slot_name,
-+ ohci->slot_name,
- readl (&ohci->regs->control));
-
- /* Reset USB (needed by some controllers) */
- writel (0, &ohci->regs->control);
--
-- /* Force a state change from USBRESET to USBOPERATIONAL for ALi */
-- (void) readl (&ohci->regs->control); /* PCI posting */
-- writel (ohci->hc_control = OHCI_USB_OPER, &ohci->regs->control);
--
-+
- /* HC Reset requires max 10 ms delay */
- writel (OHCI_HCR, &ohci->regs->cmdstatus);
- while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
-@@ -2291,8 +2234,6 @@
- writel (RH_HS_LPSC, &ohci->regs->roothub.status);
- #endif /* OHCI_USE_NPS */
-
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
--
- // POTPGT delay is bits 24-31, in 2 ms units.
- mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
-
-@@ -2322,7 +2263,7 @@
-
- static void check_timeouts (struct ohci *ohci)
- {
-- spin_lock (&ohci->ohci_lock);
-+ spin_lock (&usb_ed_lock);
- while (!list_empty (&ohci->timeout_list)) {
- struct urb *urb;
-
-@@ -2335,15 +2276,15 @@
- continue;
-
- urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
-- spin_unlock (&ohci->ohci_lock);
-+ spin_unlock (&usb_ed_lock);
-
- // outside the interrupt handler (in a timer...)
- // this reference would race interrupts
- sohci_unlink_urb (urb);
-
-- spin_lock (&ohci->ohci_lock);
-+ spin_lock (&usb_ed_lock);
- }
-- spin_unlock (&ohci->ohci_lock);
-+ spin_unlock (&usb_ed_lock);
- }
-
-
-@@ -2357,8 +2298,6 @@
- struct ohci_regs * regs = ohci->regs;
- int ints;
-
-- spin_lock (&ohci->ohci_lock);
--
- /* avoid (slow) readl if only WDH happened */
- if ((ohci->hcca->done_head != 0)
- && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
-@@ -2367,22 +2306,20 @@
- /* cardbus/... hardware gone before remove() */
- } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
- ohci->disabled++;
-- spin_unlock (&ohci->ohci_lock);
- err ("%s device removed!", ohci->ohci_dev->slot_name);
- return;
-
- /* interrupt for some other device? */
- } else if ((ints &= readl (&regs->intrenable)) == 0) {
-- spin_unlock (&ohci->ohci_lock);
- return;
-- }
-+ }
-
- // dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
-
- if (ints & OHCI_INTR_UE) {
- ohci->disabled++;
- err ("OHCI Unrecoverable Error, controller usb-%s disabled",
-- ohci->ohci_dev->slot_name);
-+ ohci->slot_name);
- // e.g. due to PCI Master/Target Abort
-
- #ifdef DEBUG
-@@ -2398,39 +2335,26 @@
-
- if (ints & OHCI_INTR_WDH) {
- writel (OHCI_INTR_WDH, &regs->intrdisable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- dl_done_list (ohci, dl_reverse_done_list (ohci));
- writel (OHCI_INTR_WDH, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- }
-
- if (ints & OHCI_INTR_SO) {
- dbg("USB Schedule overrun");
- writel (OHCI_INTR_SO, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- }
-
- // FIXME: this assumes SOF (1/ms) interrupts don't get lost...
- if (ints & OHCI_INTR_SF) {
- unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
- writel (OHCI_INTR_SF, &regs->intrdisable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
- if (ohci->ed_rm_list[!frame] != NULL) {
- dl_del_list (ohci, !frame);
- }
-- if (ohci->ed_rm_list[frame] != NULL) {
-+ if (ohci->ed_rm_list[frame] != NULL)
- writel (OHCI_INTR_SF, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
-- }
- }
-
-- /*
-- * Finally, we are done with trashing about our hardware lists
-- * and other CPUs are allowed in. The festive flipping of the lock
-- * ensues as we struggle with the check_timeouts disaster.
-- */
-- spin_unlock (&ohci->ohci_lock);
--
- if (!list_empty (&ohci->timeout_list)) {
- check_timeouts (ohci);
- // FIXME: enable SF as needed in a timer;
-@@ -2442,9 +2366,6 @@
-
- writel (ints, &regs->intrstatus);
- writel (OHCI_INTR_MIE, &regs->intrenable);
-- (void)readl (&regs->intrdisable); /* PCI posting flush */
--
-- ohci_complete(ohci);
- }
-
- /*-------------------------------------------------------------------------*/
-@@ -2475,10 +2396,14 @@
- ohci->regs = mem_base;
-
- ohci->ohci_dev = dev;
-+#ifdef CONFIG_PCI
- pci_set_drvdata(dev, ohci);
-+#endif
-
-+ INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-+ list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
-+
- INIT_LIST_HEAD (&ohci->timeout_list);
-- spin_lock_init(&ohci->ohci_lock);
-
- ohci->bus = usb_alloc_bus (&sohci_device_operations);
- if (!ohci->bus) {
-@@ -2501,7 +2426,7 @@
-
- static void hc_release_ohci (ohci_t * ohci)
- {
-- dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
-+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
-
- /* disconnect all devices */
- if (ohci->bus->root_hub)
-@@ -2514,7 +2439,9 @@
- free_irq (ohci->irq, ohci);
- ohci->irq = -1;
- }
-- pci_set_drvdata(ohci->ohci_dev, NULL);
-+#ifdef CONFIG_PCI
-+ pci_set_drvdata(ohci->ohci_dev, 0);
-+#endif
- if (ohci->bus) {
- if (ohci->bus->busnum != -1)
- usb_deregister_bus (ohci->bus);
-@@ -2522,6 +2449,9 @@
- usb_free_bus (ohci->bus);
- }
-
-+ list_del (&ohci->ohci_hcd_list);
-+ INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-+
- ohci_mem_cleanup (ohci);
-
- /* unmap the IO address space */
-@@ -2534,17 +2464,15 @@
-
- /*-------------------------------------------------------------------------*/
-
--/* Increment the module usage count, start the control thread and
-- * return success. */
--
--static struct pci_driver ohci_pci_driver;
--
--static int __devinit
--hc_found_ohci (struct pci_dev *dev, int irq,
-- void *mem_base, const struct pci_device_id *id)
-+/*
-+ * Host bus independent add one OHCI host controller.
-+ */
-+int __devinit
-+hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags,
-+ const char *name, const char *slot_name)
- {
-- ohci_t * ohci;
- char buf[8], *bufp = buf;
-+ ohci_t * ohci;
- int ret;
-
- #ifndef __sparc__
-@@ -2554,34 +2482,17 @@
- #endif
- printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
- (unsigned long) mem_base, bufp);
-- printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
--
-+
- ohci = hc_alloc_ohci (dev, mem_base);
- if (!ohci) {
- return -ENOMEM;
- }
-+ ohci->slot_name = slot_name;
- if ((ret = ohci_mem_init (ohci)) < 0) {
- hc_release_ohci (ohci);
- return ret;
- }
-- ohci->flags = id->driver_data;
--
-- /* Check for NSC87560. We have to look at the bridge (fn1) to identify
-- the USB (fn2). This quirk might apply to more or even all NSC stuff
-- I don't know.. */
--
-- if(dev->vendor == PCI_VENDOR_ID_NS)
-- {
-- struct pci_dev *fn1 = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
-- if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
-- ohci->flags |= OHCI_QUIRK_SUCKYIO;
--
-- }
--
-- if (ohci->flags & OHCI_QUIRK_SUCKYIO)
-- printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n");
-- if (ohci->flags & OHCI_QUIRK_AMD756)
-- printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
-+ ohci->flags = flags;
-
- if (hc_reset (ohci) < 0) {
- hc_release_ohci (ohci);
-@@ -2590,13 +2501,11 @@
-
- /* FIXME this is a second HC reset; why?? */
- writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
-- (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */
- wait_ms (10);
-
- usb_register_bus (ohci->bus);
-
-- if (request_irq (irq, hc_interrupt, SA_SHIRQ,
-- ohci_pci_driver.name, ohci) != 0) {
-+ if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) {
- err ("request interrupt %s failed", bufp);
- hc_release_ohci (ohci);
- return -EBUSY;
-@@ -2604,7 +2513,7 @@
- ohci->irq = irq;
-
- if (hc_start (ohci) < 0) {
-- err ("can't start usb-%s", dev->slot_name);
-+ err ("can't start usb-%s", ohci->slot_name);
- hc_release_ohci (ohci);
- return -EBUSY;
- }
-@@ -2615,114 +2524,11 @@
- return 0;
- }
-
--/*-------------------------------------------------------------------------*/
--
--#ifdef CONFIG_PM
--
--/* controller died; cleanup debris, then restart */
--/* must not be called from interrupt context */
--
--static void hc_restart (ohci_t *ohci)
--{
-- int temp;
-- int i;
--
-- if (ohci->pci_latency)
-- pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
--
-- ohci->disabled = 1;
-- ohci->sleeping = 0;
-- if (ohci->bus->root_hub)
-- usb_disconnect (&ohci->bus->root_hub);
--
-- /* empty the interrupt branches */
-- for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-- for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
--
-- /* no EDs to remove */
-- ohci->ed_rm_list [0] = NULL;
-- ohci->ed_rm_list [1] = NULL;
--
-- /* empty control and bulk lists */
-- ohci->ed_isotail = NULL;
-- ohci->ed_controltail = NULL;
-- ohci->ed_bulktail = NULL;
--
-- if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-- err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
-- } else
-- dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
--}
--
--#endif /* CONFIG_PM */
--
--/*-------------------------------------------------------------------------*/
--
--/* configured so that an OHCI device is always provided */
--/* always called with process context; sleeping is OK */
--
--static int __devinit
--ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
--{
-- unsigned long mem_resource, mem_len;
-- void *mem_base;
-- int status;
--
-- if (pci_enable_device(dev) < 0)
-- return -ENODEV;
--
-- if (!dev->irq) {
-- err("found OHCI device with no IRQ assigned. check BIOS settings!");
-- pci_disable_device (dev);
-- return -ENODEV;
-- }
--
-- /* we read its hardware registers as memory */
-- mem_resource = pci_resource_start(dev, 0);
-- mem_len = pci_resource_len(dev, 0);
-- if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-- dbg ("controller already in use");
-- pci_disable_device (dev);
-- return -EBUSY;
-- }
--
-- mem_base = ioremap_nocache (mem_resource, mem_len);
-- if (!mem_base) {
-- err("Error mapping OHCI memory");
-- release_mem_region (mem_resource, mem_len);
-- pci_disable_device (dev);
-- return -EFAULT;
-- }
--
-- /* controller writes into our memory */
-- pci_set_master (dev);
--
-- status = hc_found_ohci (dev, dev->irq, mem_base, id);
-- if (status < 0) {
-- iounmap (mem_base);
-- release_mem_region (mem_resource, mem_len);
-- pci_disable_device (dev);
-- }
-- return status;
--}
--
--/*-------------------------------------------------------------------------*/
--
--/* may be called from interrupt context [interface spec] */
--/* may be called without controller present */
--/* may be called with controller, bus, and devices active */
--
--static void __devexit
--ohci_pci_remove (struct pci_dev *dev)
-+/*
-+ * Host bus independent remove one OHCI host controller.
-+ */
-+void __devexit hc_remove_ohci(ohci_t *ohci)
- {
-- ohci_t *ohci = pci_get_drvdata(dev);
--
-- dbg ("remove %s controller usb-%s%s%s",
-- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-- dev->slot_name,
-- ohci->disabled ? " (disabled)" : "",
-- in_interrupt () ? " in interrupt" : ""
-- );
- #ifdef DEBUG
- ohci_dump (ohci, 1);
- #endif
-@@ -2739,270 +2545,8 @@
- &ohci->regs->control);
-
- hc_release_ohci (ohci);
--
-- release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-- pci_disable_device (dev);
- }
-
--
--#ifdef CONFIG_PM
--
--/*-------------------------------------------------------------------------*/
--
--static int
--ohci_pci_suspend (struct pci_dev *dev, u32 state)
--{
-- ohci_t *ohci = pci_get_drvdata(dev);
-- unsigned long flags;
-- u16 cmd;
--
-- if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-- dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-- return -EIO;
-- }
--
-- /* act as if usb suspend can always be used */
-- info ("USB suspend: usb-%s", dev->slot_name);
-- ohci->sleeping = 1;
--
-- /* First stop processing */
-- spin_lock_irqsave (&ohci->ohci_lock, flags);
-- ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-- writel (ohci->hc_control, &ohci->regs->control);
-- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-- (void) readl (&ohci->regs->intrstatus);
-- spin_unlock_irqrestore (&ohci->ohci_lock, flags);
--
-- /* Wait a frame or two */
-- mdelay(1);
-- if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-- mdelay (1);
--
--#ifdef CONFIG_PMAC_PBOOK
-- if (_machine == _MACH_Pmac)
-- disable_irq (ohci->irq);
-- /* else, 2.4 assumes shared irqs -- don't disable */
--#endif
-- /* Enable remote wakeup */
-- writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
--
-- /* Suspend chip and let things settle down a bit */
-- ohci->hc_control = OHCI_USB_SUSPEND;
-- writel (ohci->hc_control, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (500); /* No schedule here ! */
-- switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-- case OHCI_USB_RESET:
-- dbg("Bus in reset phase ???");
-- break;
-- case OHCI_USB_RESUME:
-- dbg("Bus in resume phase ???");
-- break;
-- case OHCI_USB_OPER:
-- dbg("Bus in operational phase ???");
-- break;
-- case OHCI_USB_SUSPEND:
-- dbg("Bus suspended");
-- break;
-- }
-- /* In some rare situations, Apple's OHCI have happily trashed
-- * memory during sleep. We disable it's bus master bit during
-- * suspend
-- */
-- pci_read_config_word (dev, PCI_COMMAND, &cmd);
-- cmd &= ~PCI_COMMAND_MASTER;
-- pci_write_config_word (dev, PCI_COMMAND, cmd);
--#ifdef CONFIG_PMAC_PBOOK
-- {
-- struct device_node *of_node;
--
-- /* Disable USB PAD & cell clock */
-- of_node = pci_device_to_OF_node (ohci->ohci_dev);
-- if (of_node)
-- pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-- }
--#endif
-- return 0;
--}
--
--/*-------------------------------------------------------------------------*/
--
--static int
--ohci_pci_resume (struct pci_dev *dev)
--{
-- ohci_t *ohci = pci_get_drvdata(dev);
-- int temp;
-- unsigned long flags;
--
-- /* guard against multiple resumes */
-- atomic_inc (&ohci->resume_count);
-- if (atomic_read (&ohci->resume_count) != 1) {
-- err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-- atomic_dec (&ohci->resume_count);
-- return 0;
-- }
--
--#ifdef CONFIG_PMAC_PBOOK
-- {
-- struct device_node *of_node;
--
-- /* Re-enable USB PAD & cell clock */
-- of_node = pci_device_to_OF_node (ohci->ohci_dev);
-- if (of_node)
-- pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-- }
--#endif
--
-- /* did we suspend, or were we powered off? */
-- ohci->hc_control = readl (&ohci->regs->control);
-- temp = ohci->hc_control & OHCI_CTRL_HCFS;
--
--#ifdef DEBUG
-- /* the registers may look crazy here */
-- ohci_dump_status (ohci);
--#endif
--
-- /* Re-enable bus mastering */
-- pci_set_master(ohci->ohci_dev);
--
-- switch (temp) {
--
-- case OHCI_USB_RESET: // lost power
-- info ("USB restart: usb-%s", dev->slot_name);
-- hc_restart (ohci);
-- break;
--
-- case OHCI_USB_SUSPEND: // host wakeup
-- case OHCI_USB_RESUME: // remote wakeup
-- info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
-- (temp == OHCI_USB_SUSPEND)
-- ? "host" : "remote");
-- ohci->hc_control = OHCI_USB_RESUME;
-- writel (ohci->hc_control, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (20); /* no schedule here ! */
-- /* Some controllers (lucent) need a longer delay here */
-- mdelay (15);
-- temp = readl (&ohci->regs->control);
-- temp = ohci->hc_control & OHCI_CTRL_HCFS;
-- if (temp != OHCI_USB_RESUME) {
-- err ("controller usb-%s won't resume", dev->slot_name);
-- ohci->disabled = 1;
-- return -EIO;
-- }
--
-- /* Some chips likes being resumed first */
-- writel (OHCI_USB_OPER, &ohci->regs->control);
-- (void) readl (&ohci->regs->control);
-- mdelay (3);
--
-- /* Then re-enable operations */
-- spin_lock_irqsave (&ohci->ohci_lock, flags);
-- ohci->disabled = 0;
-- ohci->sleeping = 0;
-- ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-- if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-- if (ohci->ed_controltail)
-- ohci->hc_control |= OHCI_CTRL_CLE;
-- if (ohci->ed_bulktail)
-- ohci->hc_control |= OHCI_CTRL_BLE;
-- }
-- writel (ohci->hc_control, &ohci->regs->control);
-- writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-- writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-- /* Check for a pending done list */
-- writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
-- (void) readl (&ohci->regs->intrdisable);
--#ifdef CONFIG_PMAC_PBOOK
-- if (_machine == _MACH_Pmac)
-- enable_irq (ohci->irq);
--#endif
-- if (ohci->hcca->done_head)
-- dl_done_list (ohci, dl_reverse_done_list (ohci));
-- writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
-- writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-- writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-- spin_unlock_irqrestore (&ohci->ohci_lock, flags);
-- break;
--
-- default:
-- warn ("odd PCI resume for usb-%s", dev->slot_name);
-- }
--
-- /* controller is operational, extra resumes are harmless */
-- atomic_dec (&ohci->resume_count);
--
-- return 0;
--}
--
--#endif /* CONFIG_PM */
--
--
--/*-------------------------------------------------------------------------*/
--
--static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
--
-- /*
-- * AMD-756 [Viper] USB has a serious erratum when used with
-- * lowspeed devices like mice.
-- */
-- vendor: 0x1022,
-- device: 0x740c,
-- subvendor: PCI_ANY_ID,
-- subdevice: PCI_ANY_ID,
--
-- driver_data: OHCI_QUIRK_AMD756,
--
--} , {
--
-- /* handle any USB OHCI controller */
-- class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-- class_mask: ~0,
--
-- /* no matter who makes it */
-- vendor: PCI_ANY_ID,
-- device: PCI_ANY_ID,
-- subvendor: PCI_ANY_ID,
-- subdevice: PCI_ANY_ID,
--
-- }, { /* end: all zeroes */ }
--};
--
--MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
--
--static struct pci_driver ohci_pci_driver = {
-- name: "usb-ohci",
-- id_table: &ohci_pci_ids [0],
--
-- probe: ohci_pci_probe,
-- remove: __devexit_p(ohci_pci_remove),
--
--#ifdef CONFIG_PM
-- suspend: ohci_pci_suspend,
-- resume: ohci_pci_resume,
--#endif /* PM */
--};
--
--
--/*-------------------------------------------------------------------------*/
--
--static int __init ohci_hcd_init (void)
--{
-- return pci_module_init (&ohci_pci_driver);
--}
--
--/*-------------------------------------------------------------------------*/
--
--static void __exit ohci_hcd_cleanup (void)
--{
-- pci_unregister_driver (&ohci_pci_driver);
--}
--
--module_init (ohci_hcd_init);
--module_exit (ohci_hcd_cleanup);
--
--
- MODULE_AUTHOR( DRIVER_AUTHOR );
- MODULE_DESCRIPTION( DRIVER_DESC );
- MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/usb/host/usb-ohci.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/usb/host/usb-ohci.h
-@@ -384,12 +384,13 @@
- #define OHCI_QUIRK_SUCKYIO 0x02 /* NSC superio */
-
- struct ohci_regs * regs; /* OHCI controller's memory */
-+ struct list_head ohci_hcd_list; /* list of all ohci_hcd */
-
-+ struct ohci * next; // chain of ohci device contexts
- struct list_head timeout_list;
- // struct list_head urb_list; // list of all pending urbs
-- spinlock_t ohci_lock; /* Covers all fields up & down */
-- struct urb *complete_head, *complete_tail;
--
-+ // spinlock_t urb_list_lock; // lock to keep consistency
-+
- int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/
- ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */
- ed_t * ed_bulktail; /* last endpoint of bulk list */
-@@ -403,6 +404,7 @@
-
- /* PCI device handle, settings, ... */
- struct pci_dev *ohci_dev;
-+ const char *slot_name;
- u8 pci_latency;
- struct pci_pool *td_cache;
- struct pci_pool *dev_cache;
-@@ -448,7 +450,7 @@
- #endif
-
- #ifndef CONFIG_PCI
--# error "usb-ohci currently requires PCI-based controllers"
-+//# error "usb-ohci currently requires PCI-based controllers"
- /* to support non-PCI OHCIs, you need custom bus/mem/... glue */
- #endif
-
-@@ -641,3 +643,6 @@
- pci_pool_free (hc->dev_cache, dev, dev->dma);
- }
-
-+/* For initializing controller (mask in an HCFS mode too) */
-+#define OHCI_CONTROL_INIT \
-+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
---- linux-2.4.27/drivers/video/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/Config.in
-@@ -30,13 +30,28 @@
- tristate ' Permedia3 support (EXPERIMENTAL)' CONFIG_FB_PM3
- fi
- fi
-- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-- bool ' Acorn VIDC support' CONFIG_FB_ACORN
-- fi
-- dep_tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
-- if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-- bool ' SA-1100 LCD support' CONFIG_FB_SA1100
-+ if [ "$CONFIG_ARM" = "y" ]; then
-+ if [ "$CONFIG_ARCH_ACORN" -o "$CONFIG_ARCH_RISCSTATION" ]; then
-+ bool ' Acorn VIDC support' CONFIG_FB_ACORN
-+ else
-+ define_bool CONFIG_FB_ACORN n
-+ fi
-+ dep_bool ' Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
-+ dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
-+ dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
-+ dep_bool ' MX1ADS LCD support' CONFIG_FB_DBMX1 $CONFIG_ARCH_MX1ADS
-+ if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
-+ choice 'CerfBoard LCD Display Size' \
-+ "3.8_Color CONFIG_CERF_LCD_38_A \
-+ 3.8_Mono CONFIG_CERF_LCD_38_B \
-+ 5.7 CONFIG_CERF_LCD_57_A \
-+ 7.2 CONFIG_CERF_LCD_72_A" 5.7
-+ fi
-+ if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
-+ bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
-+ fi
- fi
-+ dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
- if [ "$CONFIG_APOLLO" = "y" ]; then
- define_bool CONFIG_FB_APOLLO y
- fi
-@@ -265,7 +280,7 @@
- "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \
- "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
- "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
-- "$CONFIG_FB_TX3912" = "y" ]; then
-+ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" ]; then
- define_tristate CONFIG_FBCON_MFB y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \
-@@ -273,19 +288,20 @@
- "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \
- "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
- "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
-- "$CONFIG_FB_TX3912" = "m" ]; then
-+ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
- define_tristate CONFIG_FBCON_MFB m
- fi
- fi
- if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
- "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
-- "$CONFIG_FB_TX3912" = "y" ]; then
-+ "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB2 y
- define_tristate CONFIG_FBCON_CFB4 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
- "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
-- "$CONFIG_FB_TX3912" = "m" ]; then
-+ "$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_CLPS711X" = "m" ]; then
- define_tristate CONFIG_FBCON_CFB2 m
- define_tristate CONFIG_FBCON_CFB4 m
- fi
-@@ -312,7 +328,8 @@
- "$CONFIG_FB_TX3912" = "y" -o \
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
- "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \
-- "$CONFIG_FB_INTEL" = "y" ]; then
-+ "$CONFIG_FB_INTEL" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB8 y
- else
- if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
-@@ -354,7 +371,9 @@
- "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
- "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
- "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
-- "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" ]; then
-+ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \
-+ "$CONFIG_FB_ANAKIN" = "y" -o \
-+ "$CONFIG_FB_DBMX1" = "y" ]; then
- define_tristate CONFIG_FBCON_CFB16 y
- else
- if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
-@@ -509,6 +528,9 @@
- if [ "$CONFIG_AMIGA" = "y" ]; then
- define_bool CONFIG_FONT_PEARL_8x8 y
- fi
-+ if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_RISCSTATION" = "y" ]; then
-+ define_bool CONFIG_FONT_ACORN_8x8 y
-+ fi
- if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
- define_bool CONFIG_FONT_ACORN_8x8 y
- fi
---- linux-2.4.27/drivers/video/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/Makefile
-@@ -55,6 +55,7 @@
- obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
- obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
- obj-$(CONFIG_FB_CT65550) += chipsfb.o
-+obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
- obj-$(CONFIG_FB_CYBER) += cyberfb.o
- obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
- obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
-@@ -68,7 +69,7 @@
- obj-$(CONFIG_FB_TRIDENT) += tridentfb.o fbgen.o
- obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
- obj-$(CONFIG_FB_TGA) += tgafb.o fbgen.o
--obj-$(CONFIG_FB_VESA) += vesafb.o
-+obj-$(CONFIG_FB_VESA) += vesafb.o
- obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
- obj-$(CONFIG_FB_VIRGE) += virgefb.o
- obj-$(CONFIG_FB_G364) += g364fb.o
-@@ -126,14 +127,16 @@
-
- obj-$(CONFIG_FB_SUN3) += sun3fb.o
- obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
--obj-$(CONFIG_FB_HGA) += hgafb.o
-+obj-$(CONFIG_FB_HGA) += hgafb.o
- obj-$(CONFIG_FB_SA1100) += sa1100fb.o
--obj-$(CONFIG_FB_VIRTUAL) += vfb.o
-+obj-$(CONFIG_FB_DBMX1) += dbmx1fb.o
-+obj-$(CONFIG_FB_VIRTUAL) += vfb.o
- obj-$(CONFIG_FB_HIT) += hitfb.o fbgen.o
- obj-$(CONFIG_FB_E1355) += epson1355fb.o fbgen.o
- obj-$(CONFIG_FB_E1356) += epson1356fb.o
- obj-$(CONFIG_FB_PVR2) += pvr2fb.o
- obj-$(CONFIG_FB_VOODOO1) += sstfb.o
-+obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
-
- # Generic Low Level Drivers
-
-@@ -169,4 +172,3 @@
- -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
-
- promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h
--
---- linux-2.4.27/drivers/video/acornfb.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/acornfb.c
-@@ -752,11 +752,12 @@
- }
- #endif
- #ifdef FBCON_HAS_CFB16
-- if (bpp == 16 && regno < 16) {
-+ if (bpp == 16) {
- int i;
-
-- current_par.cmap.cfb16[regno] =
-- regno | regno << 5 | regno << 10;
-+ if (regno < 16)
-+ current_par.cmap.cfb16[regno] =
-+ regno | regno << 5 | regno << 10;
-
- pal.p = 0;
- vidc_writel(0x10000000);
-@@ -1215,7 +1216,7 @@
- p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
- p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
- }
-- acornfb_palette_write(i, current_par.palette[i]);
-+ acornfb_palette_write(i, p);
- }
- } else
- #endif
---- /dev/null
-+++ linux-2.4.27/drivers/video/anakinfb.c
-@@ -0,0 +1,221 @@
-+/*
-+ * linux/drivers/video/anakinfb.c
-+ *
-+ * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 23-Apr-2001 TTC Created
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/string.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+
-+#include <asm/io.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-cfb16.h>
-+
-+static u16 colreg[16];
-+static int currcon = 0;
-+static struct fb_info fb_info;
-+static struct display display;
-+
-+static int
-+anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-+ u_int *transp, struct fb_info *info)
-+{
-+ if (regno > 15)
-+ return 1;
-+
-+ *red = colreg[regno] & 0xf800;
-+ *green = colreg[regno] & 0x7e0 << 5;
-+ *blue = colreg[regno] & 0x1f << 11;
-+ *transp = 0;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ if (regno > 15)
-+ return 1;
-+
-+ colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
-+ (blue & 0xf800 >> 11);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, "AnakinFB");
-+ fix->smem_start = VGA_START;
-+ fix->smem_len = VGA_SIZE;
-+ fix->type = FB_TYPE_PACKED_PIXELS;
-+ fix->type_aux = 0;
-+ fix->visual = FB_VISUAL_TRUECOLOR;
-+ fix->xpanstep = 0;
-+ fix->ypanstep = 0;
-+ fix->ywrapstep = 0;
-+ fix->line_length = 400 * 2;
-+ fix->accel = FB_ACCEL_NONE;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ memset(var, 0, sizeof(struct fb_var_screeninfo));
-+ var->xres = 400;
-+ var->yres = 234;
-+ var->xres_virtual = 400;
-+ var->yres_virtual = 234;
-+ var->xoffset = 0;
-+ var->yoffset = 0;
-+ var->bits_per_pixel = 16;
-+ var->grayscale = 0;
-+ 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;
-+ var->nonstd = 0;
-+ var->activate = FB_ACTIVATE_NOW;
-+ var->height = -1;
-+ var->width = -1;
-+ var->pixclock = 0;
-+ var->left_margin = 0;
-+ var->right_margin = 0;
-+ var->upper_margin = 0;
-+ var->lower_margin = 0;
-+ var->hsync_len = 0;
-+ var->vsync_len = 0;
-+ var->sync = 0;
-+ var->vmode = FB_VMODE_NONINTERLACED;
-+ return 0;
-+}
-+
-+static int
-+anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+static int
-+anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ if (con == currcon)
-+ return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
-+ else if (fb_display[con].cmap.len)
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err;
-+
-+ if (!fb_display[con].cmap.len) {
-+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
-+ return err;
-+ }
-+ if (con == currcon)
-+ return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
-+ else
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ return 0;
-+}
-+
-+static int
-+anakinfb_switch_con(int con, struct fb_info *info)
-+{
-+ currcon = con;
-+ return 0;
-+
-+}
-+
-+static int
-+anakinfb_updatevar(int con, struct fb_info *info)
-+{
-+ return 0;
-+}
-+
-+static void
-+anakinfb_blank(int blank, struct fb_info *info)
-+{
-+ /*
-+ * TODO: use I2C to blank/unblank the screen
-+ */
-+}
-+
-+static struct fb_ops anakinfb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: anakinfb_get_fix,
-+ fb_get_var: anakinfb_get_var,
-+ fb_set_var: anakinfb_set_var,
-+ fb_get_cmap: anakinfb_get_cmap,
-+ fb_set_cmap: anakinfb_set_cmap,
-+};
-+
-+int __init
-+anakinfb_init(void)
-+{
-+ memset(&fb_info, 0, sizeof(struct fb_info));
-+ strcpy(fb_info.modename, "AnakinFB");
-+ fb_info.node = -1;
-+ fb_info.flags = FBINFO_FLAG_DEFAULT;
-+ fb_info.fbops = &anakinfb_ops;
-+ fb_info.disp = &display;
-+ strcpy(fb_info.fontname, "VGA8x16");
-+ fb_info.changevar = NULL;
-+ fb_info.switch_con = &anakinfb_switch_con;
-+ fb_info.updatevar = &anakinfb_updatevar;
-+ fb_info.blank = &anakinfb_blank;
-+
-+ memset(&display, 0, sizeof(struct display));
-+ anakinfb_get_var(&display.var, 0, &fb_info);
-+ display.screen_base = ioremap(VGA_START, VGA_SIZE);
-+ display.visual = FB_VISUAL_TRUECOLOR;
-+ display.type = FB_TYPE_PACKED_PIXELS;
-+ display.type_aux = 0;
-+ display.ypanstep = 0;
-+ display.ywrapstep = 0;
-+ display.line_length = 400 * 2;
-+ display.can_soft_blank = 1;
-+ display.inverse = 0;
-+
-+#ifdef FBCON_HAS_CFB16
-+ display.dispsw = &fbcon_cfb16;
-+ display.dispsw_data = colreg;
-+#else
-+ display.dispsw = &fbcon_dummy;
-+#endif
-+
-+ if (register_framebuffer(&fb_info) < 0)
-+ return -EINVAL;
-+
-+ MOD_INC_USE_COUNT;
-+ return 0;
-+}
-+
-+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
-+MODULE_DESCRIPTION("Anakin framebuffer driver");
-+MODULE_SUPPORTED_DEVICE("fb");
---- /dev/null
-+++ linux-2.4.27/drivers/video/clps711xfb.c
-@@ -0,0 +1,677 @@
-+/*
-+ * linux/drivers/video/clps711xfb.c
-+ *
-+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Framebuffer driver for the CLPS7111 and EP7212 processors.
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/fb.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/delay.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb2.h>
-+#include <video/fbcon-mfb.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+
-+#include <asm/hardware/clps7111.h>
-+#include <asm/arch/syspld.h>
-+
-+static struct clps7111fb_info {
-+ struct fb_info fb;
-+ int currcon;
-+} *cfb;
-+
-+#define CMAP_MAX_SIZE 16
-+
-+/* The /proc entry for the backlight. */
-+static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
-+
-+static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data);
-+static int clps7111fb_proc_backlight_write(struct file *file,
-+ const char *buffer, unsigned long count, void *data);
-+
-+/*
-+ * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
-+ * This determines how many clocks + 1 of CL1 before the M signal toggles.
-+ * The number of lines on the display must not be divisible by this number.
-+ */
-+static unsigned int lcd_ac_prescale = 13;
-+
-+/*
-+ * Set a single color register. Return != 0 for invalid regno.
-+ */
-+static int
-+clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
-+{
-+ unsigned int level, mask, shift, pal;
-+
-+ if (regno >= (1 << info->var.bits_per_pixel))
-+ return 1;
-+
-+ /* gray = 0.30*R + 0.58*G + 0.11*B */
-+ level = (red * 77 + green * 151 + blue * 28) >> 20;
-+
-+ /*
-+ * On an LCD, a high value is dark, while a low value is light.
-+ * So we invert the level.
-+ *
-+ * This isn't true on all machines, so we only do it on EDB7211.
-+ * --rmk
-+ */
-+ if (machine_is_edb7211() || machine_is_guidea07()) {
-+ level = 15 - level;
-+ }
-+
-+ shift = 4 * (regno & 7);
-+ level <<= shift;
-+ mask = 15 << shift;
-+ level &= mask;
-+
-+ regno = regno < 8 ? PALLSW : PALMSW;
-+
-+ pal = clps_readl(regno);
-+ pal = (pal & ~mask) | level;
-+ clps_writel(pal, regno);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Set the colormap
-+ */
-+static int
-+clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
-+ struct fb_cmap *dcmap = &fb_display[con].cmap;
-+ int err = 0;
-+
-+ /* no colormap allocated? */
-+ if (!dcmap->len)
-+ err = fb_alloc_cmap(dcmap, CMAP_MAX_SIZE, 0);
-+
-+ if (!err && con == cfb->currcon) {
-+ err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
-+ dcmap = &cfb->fb.cmap;
-+ }
-+
-+ if (!err)
-+ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
-+
-+ return err;
-+}
-+
-+/*
-+ * Set the User Defined Part of the Display
-+ */
-+static int
-+clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info)
-+{
-+ struct display *display;
-+ unsigned int lcdcon, syscon, pixclock;
-+ int chgvar = 0;
-+
-+ if (var->activate & FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
-+ return -EINVAL;
-+
-+ if (cfb->fb.var.xres != var->xres)
-+ chgvar = 1;
-+ if (cfb->fb.var.yres != var->yres)
-+ chgvar = 1;
-+ if (cfb->fb.var.xres_virtual != var->xres_virtual)
-+ chgvar = 1;
-+ if (cfb->fb.var.yres_virtual != var->yres_virtual)
-+ chgvar = 1;
-+ if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
-+ chgvar = 1;
-+
-+ if (con < 0) {
-+ display = cfb->fb.disp;
-+ chgvar = 0;
-+ } else {
-+ display = fb_display + con;
-+ }
-+
-+ var->transp.msb_right = 0;
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.msb_right = 0;
-+ var->red.offset = 0;
-+ var->red.length = var->bits_per_pixel;
-+ var->green = var->red;
-+ var->blue = var->red;
-+
-+ switch (var->bits_per_pixel) {
-+#ifdef FBCON_HAS_MFB
-+ case 1:
-+ cfb->fb.fix.visual = FB_VISUAL_MONO01;
-+ display->dispsw = &fbcon_mfb;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB2
-+ case 2:
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->dispsw = &fbcon_cfb2;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ display->dispsw = &fbcon_cfb4;
-+ display->dispsw_data = NULL;
-+ break;
-+#endif
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ display->next_line = var->xres_virtual * var->bits_per_pixel / 8;
-+
-+ cfb->fb.fix.line_length = display->next_line;
-+
-+ display->screen_base = cfb->fb.screen_base;
-+ display->line_length = cfb->fb.fix.line_length;
-+ display->visual = cfb->fb.fix.visual;
-+ display->type = cfb->fb.fix.type;
-+ display->type_aux = cfb->fb.fix.type_aux;
-+ display->ypanstep = cfb->fb.fix.ypanstep;
-+ display->ywrapstep = cfb->fb.fix.ywrapstep;
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ cfb->fb.var = *var;
-+ cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
-+
-+ /*
-+ * Update the old var. The fbcon drivers still use this.
-+ * Once they are using cfb->fb.var, this can be dropped.
-+ * --rmk
-+ */
-+ display->var = cfb->fb.var;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ if (var->activate & FB_ACTIVATE_ALL)
-+ cfb->fb.disp->var = cfb->fb.var;
-+
-+ if (chgvar && info && cfb->fb.changevar)
-+ cfb->fb.changevar(con);
-+
-+ lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
-+ lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
-+ lcdcon |= lcd_ac_prescale << 25;
-+
-+ /*
-+ * Calculate pixel prescale value from the pixclock. This is:
-+ * 36.864MHz / pixclock_mhz - 1.
-+ * However, pixclock is in picoseconds, so this ends up being:
-+ * 36864000 * pixclock_ps / 10^12 - 1
-+ * and this will overflow the 32-bit math. We perform this as
-+ * (9 * 4096000 == 36864000):
-+ * pixclock_ps * 9 * (4096000 / 10^12) - 1
-+ */
-+ pixclock = 9 * info->var.pixclock / 244140 - 1;
-+ lcdcon |= pixclock << 19;
-+
-+ if (info->var.bits_per_pixel == 4)
-+ lcdcon |= LCDCON_GSMD;
-+ if (info->var.bits_per_pixel >= 2)
-+ lcdcon |= LCDCON_GSEN;
-+
-+ /*
-+ * LCDCON must only be changed while the LCD is disabled
-+ */
-+ syscon = clps_readl(SYSCON1);
-+ clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
-+ clps_writel(lcdcon, LCDCON);
-+ clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
-+
-+ fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Get the currently displayed virtual consoles colormap.
-+ */
-+static int
-+gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
-+ return 0;
-+}
-+
-+/*
-+ * Get the currently displayed virtual consoles fixed part of the display.
-+ */
-+static int
-+gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ *fix = info->fix;
-+ return 0;
-+}
-+
-+/*
-+ * Get the current user defined part of the display.
-+ */
-+static int
-+gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ *var = info->var;
-+ return 0;
-+}
-+
-+static struct fb_ops clps7111fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_set_var: clps7111fb_set_var,
-+ fb_set_cmap: clps7111fb_set_cmap,
-+ fb_get_fix: gen_get_fix,
-+ fb_get_var: gen_get_var,
-+ fb_get_cmap: gen_get_cmap,
-+};
-+
-+static int clps7111fb_switch(int con, struct fb_info *info)
-+{
-+ struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
-+ struct display *disp;
-+ struct fb_cmap *cmap;
-+
-+ if (cfb->currcon >= 0) {
-+ disp = fb_display + cfb->currcon;
-+
-+ /*
-+ * Save the old colormap and video mode.
-+ */
-+ disp->var = cfb->fb.var;
-+ if (disp->cmap.len)
-+ fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
-+ }
-+
-+ cfb->currcon = con;
-+ disp = fb_display + con;
-+
-+ /*
-+ * Install the new colormap and change the video mode. By default,
-+ * fbcon sets all the colormaps and video modes to the default
-+ * values at bootup.
-+ */
-+ if (disp->cmap.len)
-+ cmap = &disp->cmap;
-+ else
-+ cmap = fb_default_cmap(CMAP_MAX_SIZE);
-+
-+ fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
-+
-+ cfb->fb.var = disp->var;
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
-+
-+ return 0;
-+}
-+
-+static int clps7111fb_updatevar(int con, struct fb_info *info)
-+{
-+ return -EINVAL;
-+}
-+
-+static void clps7111fb_blank(int blank, struct fb_info *info)
-+{
-+ if (blank) {
-+ if (machine_is_edb7211()) {
-+ /* Turn off the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
-+
-+ /* Power off the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
-+
-+ /* Delay for a little while (half a second). */
-+ udelay(100);
-+
-+ /* Power off the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
-+
-+ /* Power off the LCD controller. */
-+ clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
-+ SYSCON1);
-+ }
-+ } else {
-+ if (machine_is_edb7211()) {
-+ /* Power up the LCD controller. */
-+ clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
-+ SYSCON1);
-+
-+ /* Power up the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-+
-+ /* Delay for a little while. */
-+ udelay(100);
-+
-+ /* Power up the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
-+ PDDR);
-+
-+ /* Turn on the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-+ }
-+ }
-+}
-+
-+static int
-+clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-+ int count, int *eof, void *data)
-+{
-+ /* We need at least two characters, one for the digit, and one for
-+ * the terminating NULL. */
-+ if (count < 2)
-+ return -EINVAL;
-+
-+ if (machine_is_edb7211()) {
-+ return sprintf(page, "%d\n",
-+ (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ unsigned char char_value;
-+ int value;
-+
-+ if (count < 1) {
-+ return -EINVAL;
-+ }
-+
-+ if (copy_from_user(&char_value, buffer, 1))
-+ return -EFAULT;
-+
-+ value = char_value - '0';
-+
-+ if (machine_is_edb7211()) {
-+ unsigned char port_d;
-+
-+ port_d = clps_readb(PDDR);
-+
-+ if (value) {
-+ port_d |= EDB_PD3_LCDBL;
-+ } else {
-+ port_d &= ~EDB_PD3_LCDBL;
-+ }
-+
-+ clps_writeb(port_d, PDDR);
-+ }
-+
-+ return count;
-+}
-+
-+static void __init clps711x_guess_lcd_params(struct fb_info *info)
-+{
-+ unsigned int lcdcon, syscon, size;
-+ unsigned long phys_base = PHYS_OFFSET;
-+ void *virt_base = (void *)PAGE_OFFSET;
-+
-+ info->var.xres_virtual = 640;
-+ info->var.yres_virtual = 240;
-+ info->var.bits_per_pixel = 4;
-+ info->var.activate = FB_ACTIVATE_NOW;
-+ info->var.height = -1;
-+ info->var.width = -1;
-+ info->var.pixclock = 93006; /* 10.752MHz pixel clock */
-+
-+ /*
-+ * If the LCD controller is already running, decode the values
-+ * in LCDCON to xres/yres/bpp/pixclock/acprescale
-+ */
-+ syscon = clps_readl(SYSCON1);
-+ if (syscon & SYSCON1_LCDEN) {
-+ lcdcon = clps_readl(LCDCON);
-+
-+ /*
-+ * Decode GSMD and GSEN bits to bits per pixel
-+ * (in cs89712 docs, GSEN is GSMD1, GSMD is GSMD2)
-+ */
-+ switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
-+ case LCDCON_GSMD | LCDCON_GSEN:
-+ info->var.bits_per_pixel = 4;
-+ break;
-+
-+ case LCDCON_GSEN:
-+ info->var.bits_per_pixel = 2;
-+ break;
-+
-+ default:
-+ info->var.bits_per_pixel = 1;
-+ break;
-+ }
-+
-+ /*
-+ * Decode xres/yres
-+ */
-+ info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
-+ info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
-+ (info->var.xres_virtual *
-+ info->var.bits_per_pixel);
-+
-+ /*
-+ * Calculate pixclock
-+ */
-+ info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
-+
-+ /*
-+ * Grab AC prescale
-+ */
-+ lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
-+ }
-+
-+ info->var.xres = info->var.xres_virtual;
-+ info->var.yres = info->var.yres_virtual;
-+ info->var.grayscale = info->var.bits_per_pixel > 1;
-+
-+ size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
-+
-+ /*
-+ * Might be worth checking to see if we can use the on-board
-+ * RAM if size here...
-+ * CLPS7110 - no on-board SRAM
-+ * EP7212 - 38400 bytes
-+ */
-+ if (size <= 38400) {
-+ printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
-+ }
-+
-+ if ((syscon & SYSCON1_LCDEN) == 0) {
-+ /*
-+ * The display isn't running. Ensure that
-+ * the display memory is empty.
-+ */
-+ memset(virt_base, 0, size);
-+ }
-+
-+ info->screen_base = virt_base;
-+ info->fix.smem_start = phys_base;
-+ info->fix.smem_len = PAGE_ALIGN(size);
-+ info->fix.type = FB_TYPE_PACKED_PIXELS;
-+}
-+
-+/* this function initializes the LCD registers as required by the Guide A07
-+*/
-+int __init clps711xfb_guidea07_init(void)
-+{
-+ unsigned long videomem, videosize;
-+ unsigned int lcdcon, syscon;
-+
-+ //LCDCON must only be changed while the LCD is disabled
-+ syscon = clps_readl(SYSCON1);
-+ clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
-+
-+ printk(KERN_INFO "CLPS711xFB: setting up cs89712 SRAM as QVGA video framebuffer\n");
-+ clps_writel(0x6, FBADDR); //internal SRAM location
-+ videomem = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
-+ if (!videomem) {
-+ printk("ioremap failed!\n");
-+ kfree(cfb);
-+ return -EIO;
-+ }
-+
-+ videosize = (320*240 * 4 / 8); //ie. 38400 or 0x9600
-+ memset((void *)videomem, 0, videosize); //clear the vid memory
-+
-+ cfb->fb.screen_base = (void *)videomem;
-+ cfb->fb.fix.smem_start = SRAM_START; //must be physical address
-+ cfb->fb.fix.smem_len = videosize;
-+
-+ cfb->fb.var.grayscale = 1;
-+ cfb->fb.var.bits_per_pixel = 4;
-+ cfb->fb.var.xres_virtual = 320;
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+
-+ // change to 4bpp mode
-+ lcdcon = clps_readl(LCDCON);
-+ lcdcon |= LCDCON_GSMD | LCDCON_GSEN; //4bpp
-+ //lcdcon |= 5 << 19; //pixel prescale value (pixclock)
-+ //lcdcon |= 13 << 25; //AC prescale value
-+ clps_writel(lcdcon, LCDCON);
-+
-+ //reenable LCD
-+ clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
-+
-+ return 0;
-+}
-+
-+int __init clps711xfb_init(void)
-+{
-+ int err = -ENOMEM;
-+
-+ cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
-+ if (!cfb)
-+ goto out;
-+
-+ memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
-+ strcpy(cfb->fb.fix.id, "clps7111");
-+
-+ cfb->currcon = -1;
-+ cfb->fb.screen_base = (void *)PAGE_OFFSET;
-+ cfb->fb.fix.smem_start = PAGE_OFFSET;
-+ cfb->fb.fix.smem_len = 0x14000;
-+ cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
-+
-+ cfb->fb.fbops = &clps7111fb_ops;
-+ cfb->fb.changevar = NULL;
-+ cfb->fb.switch_con = clps7111fb_switch;
-+ cfb->fb.updatevar = clps7111fb_updatevar;
-+ cfb->fb.blank = clps7111fb_blank;
-+ cfb->fb.flags = FBINFO_FLAG_DEFAULT;
-+ cfb->fb.disp = (struct display *)(cfb + 1);
-+
-+ clps711x_guess_lcd_params(&cfb->fb);
-+
-+ if (machine_is_guidea07()) {
-+ clps711xfb_guidea07_init();
-+ }
-+
-+ if (machine_is_fortunet()) {
-+ cfb->fb.fix.smem_len = 0x20000;
-+ }
-+
-+ fb_alloc_cmap(&cfb->fb.cmap, CMAP_MAX_SIZE, 0);
-+
-+ /* Register the /proc entries. */
-+ clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
-+ &proc_root);
-+ if (clps7111fb_backlight_proc_entry == NULL) {
-+ printk("Couldn't create the /proc entry for the backlight.\n");
-+ return -EINVAL;
-+ }
-+
-+ clps7111fb_backlight_proc_entry->read_proc =
-+ &clps7111fb_proc_backlight_read;
-+ clps7111fb_backlight_proc_entry->write_proc =
-+ &clps7111fb_proc_backlight_write;
-+
-+ /*
-+ * Power up the LCD
-+ */
-+ if (machine_is_p720t()) {
-+ PLD_LCDEN = PLD_LCDEN_EN;
-+ PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-+ }
-+
-+ if (machine_is_edb7211()) {
-+ /* Power up the LCD panel. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-+
-+ /* Delay for a little while. */
-+ udelay(100);
-+
-+ /* Power up the LCD DC-DC converter. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
-+
-+ /* Turn on the LCD backlight. */
-+ clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
-+ }
-+
-+ clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+ err = register_framebuffer(&cfb->fb);
-+
-+out: return err;
-+}
-+
-+static void __exit clps711xfb_exit(void)
-+{
-+ unregister_framebuffer(&cfb->fb);
-+ kfree(cfb);
-+
-+ /*
-+ * Power down the LCD
-+ */
-+ if (machine_is_p720t()) {
-+ PLD_LCDEN = 0;
-+ PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
-+ }
-+}
-+
-+#ifdef MODULE
-+module_init(clps711xfb_init);
-+#endif
-+module_exit(clps711xfb_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("CLPS711x framebuffer driver");
-+MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/video/cyber2000fb.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/cyber2000fb.c
-@@ -1,7 +1,7 @@
- /*
- * linux/drivers/video/cyber2000fb.c
- *
-- * Copyright (C) 1998-2000 Russell King
-+ * Copyright (C) 1998-2002 Russell King
- *
- * MIPS and 50xx clock support
- * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
-@@ -13,22 +13,28 @@
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-- * Intergraphics CyberPro 2000, 2010 and 5000 frame buffer device
-+ * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
- *
- * Based on cyberfb.c.
- *
-- * Note that we now use the new fbcon fix, var and cmap scheme. We do still
-- * have to check which console is the currently displayed one however, since
-- * especially for the colourmap stuff. Once fbcon has been fully migrated,
-- * we can kill the last 5 references to cfb->currcon.
-+ * Note that we now use the new fbcon fix, var and cmap scheme. We do
-+ * still have to check which console is the currently displayed one
-+ * however, especially for the colourmap stuff.
- *
-- * We also use the new hotplug PCI subsystem. I'm not sure if there are any
-- * such cards, but I'm erring on the side of caution. We don't want to go
-- * pop just because someone does have one.
-+ * We also use the new hotplug PCI subsystem. I'm not sure if there
-+ * are any such cards, but I'm erring on the side of caution. We don't
-+ * want to go pop just because someone does have one.
- *
-- * Note that this doesn't work fully in the case of multiple CyberPro cards
-- * with grabbers. We currently can only attach to the first CyberPro card
-- * found.
-+ * Note that this doesn't work fully in the case of multiple CyberPro
-+ * cards with grabbers. We currently can only attach to the first
-+ * CyberPro card found.
-+ *
-+ * When we're in truecolour mode, we power down the LUT RAM as a power
-+ * saving feature. Also, when we enter any of the powersaving modes
-+ * (except soft blanking) we power down the RAMDACs. This saves about
-+ * 1W, which is roughly 8% of the power consumption of a NetWinder
-+ * (which, incidentally, is about the same saving as a 2.5in hard disk
-+ * entering standby mode.)
- */
- #include <linux/config.h>
- #include <linux/module.h>
-@@ -55,20 +61,16 @@
- #include <video/fbcon-cfb24.h>
- #include <video/fbcon-cfb32.h>
-
--/*
-- * Define this if you don't want RGB565, but RGB555 for 16bpp displays.
-- */
--/*#define CFB16_IS_CFB15*/
--
- #include "cyber2000fb.h"
-
- struct cfb_info {
- struct fb_info fb;
- struct display_switch *dispsw;
-+ struct display *display;
- struct pci_dev *dev;
- unsigned char *region;
- unsigned char *regs;
-- signed int currcon;
-+ u_int id;
- int func_use_count;
- u_long ref_ps;
-
-@@ -81,10 +83,16 @@
- u8 red, green, blue;
- } palette[NR_PALETTE];
-
-+ u_char mem_ctl0;
- u_char mem_ctl1;
- u_char mem_ctl2;
- u_char mclk_mult;
- u_char mclk_div;
-+ /*
-+ * RAMDAC control register is both of these or'ed together
-+ */
-+ u_char ramdac_ctrl;
-+ u_char ramdac_powerdown;
- };
-
- static char default_font_storage[40];
-@@ -144,7 +152,7 @@
- {
- int count = 100000;
-
-- while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
-+ while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
- if (!count--) {
- debug_printf("accel_wait timed out\n");
- cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
-@@ -154,24 +162,23 @@
- }
- }
-
--static void cyber2000_accel_setup(struct display *p)
-+static void cyber2000_accel_setup(struct display *display)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
-- cfb->dispsw->setup(p);
-+ cfb->dispsw->setup(display);
- }
-
- static void
--cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
-+cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
- int height, int width)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-- struct fb_var_screeninfo *var = &p->fb_info->var;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-+ struct fb_var_screeninfo *var = &display->var;
- u_long src, dst;
-- u_int fh, fw;
-- int cmd = CO_CMD_L_PATTERN_FGCOL;
-+ u_int fh, fw, cmd = CO_CMD_L_PATTERN_FGCOL;
-
-- fw = fontwidth(p);
-+ fw = fontwidth(display);
- sx *= fw;
- dx *= fw;
- width *= fw;
-@@ -183,7 +190,7 @@
- cmd |= CO_CMD_L_INC_LEFT;
- }
-
-- fh = fontheight(p);
-+ fh = fontheight(display);
- sy *= fh;
- dy *= fh;
- height *= fh;
-@@ -199,227 +206,265 @@
- dst = dx + dy * var->xres_virtual;
-
- cyber2000_accel_wait(cfb);
-- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
-- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
-+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
-+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
-
-- if (var->bits_per_pixel != 24) {
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
-- } else {
-- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
-- cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-- cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
-+ if (var->bits_per_pixel == 24) {
-+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-+ dst *= 3;
-+ src *= 3;
- }
-
-- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
-- cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
-- cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
-+ cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
-+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
-+ cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
-+ cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
- }
-
- static void
--cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-- int height, int width)
-+cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
-+ int sx, int height, int width)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-- struct fb_var_screeninfo *var = &p->fb_info->var;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-+ struct fb_var_screeninfo *var = &display->var;
- u_long dst;
- u_int fw, fh;
-- u32 bgx = attr_bgcol_ec(p, conp);
-+ u32 bgx = attr_bgcol_ec(display, conp);
-
-- fw = fontwidth(p);
-- fh = fontheight(p);
-+ fw = fontwidth(display);
-+ fh = fontheight(display);
-
- dst = sx * fw + sy * var->xres_virtual * fh;
- width = width * fw - 1;
- height = height * fh - 1;
-
- cyber2000_accel_wait(cfb);
-- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
-- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
-- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
--
-- switch (var->bits_per_pixel) {
-- case 15:
-- case 16:
-- bgx = ((u16 *)p->dispsw_data)[bgx];
-- case 8:
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- break;
-+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
-+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
-+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
-
-- case 24:
-- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
-+ if (var->bits_per_pixel == 24) {
- cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-- bgx = ((u32 *)p->dispsw_data)[bgx];
-- break;
--
-- case 32:
-- bgx = ((u32 *)p->dispsw_data)[bgx];
-- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-- break;
-+ dst *= 3;
- }
-
-- cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
-+ if (var->bits_per_pixel == 16)
-+ bgx = ((u16 *)display->dispsw_data)[bgx];
-+ else if (var->bits_per_pixel >= 24)
-+ bgx = ((u32 *)display->dispsw_data)[bgx];
-+
-+ cyber2000fb_writel(bgx, CO_REG_FGCOLOUR, cfb);
-+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
-+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
- cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
-- cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
-+ cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
- }
-
- static void
--cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
-+cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
- int yy, int xx)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->putc(conp, p, c, yy, xx);
-+ cfb->dispsw->putc(conp, display, c, yy, xx);
- }
-
- static void
--cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
-+cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
- const unsigned short *s, int count, int yy, int xx)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->putcs(conp, p, s, count, yy, xx);
-+ cfb->dispsw->putcs(conp, display, s, count, yy, xx);
- }
-
--static void cyber2000_accel_revc(struct display *p, int xx, int yy)
-+static void cyber2000_accel_revc(struct display *display, int xx, int yy)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
- cyber2000_accel_wait(cfb);
-- cfb->dispsw->revc(p, xx, yy);
-+ cfb->dispsw->revc(display, xx, yy);
- }
-
- static void
--cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
-+cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
- int bottom_only)
- {
-- struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-+ struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
-
-- cfb->dispsw->clear_margins(conp, p, bottom_only);
-+ cfb->dispsw->clear_margins(conp, display, bottom_only);
- }
-
- static struct display_switch fbcon_cyber_accel = {
-- setup: cyber2000_accel_setup,
-- bmove: cyber2000_accel_bmove,
-- clear: cyber2000_accel_clear,
-- putc: cyber2000_accel_putc,
-- putcs: cyber2000_accel_putcs,
-- revc: cyber2000_accel_revc,
-- clear_margins: cyber2000_accel_clear_margins,
-- fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
-+ .setup = cyber2000_accel_setup,
-+ .bmove = cyber2000_accel_bmove,
-+ .clear = cyber2000_accel_clear,
-+ .putc = cyber2000_accel_putc,
-+ .putcs = cyber2000_accel_putcs,
-+ .revc = cyber2000_accel_revc,
-+ .clear_margins = cyber2000_accel_clear_margins,
-+ .fontwidthmask = FONTWIDTH(8)|FONTWIDTH(16)
- };
-
-+static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
-+{
-+ u_int mask = (1 << bf->length) - 1;
-+
-+ return (val >> (16 - bf->length) & mask) << bf->offset;
-+}
-+
- /*
- * Set a single color register. Return != 0 for invalid regno.
- */
- static int
--cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-- u_int transp, struct fb_info *info)
-+cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int transp, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-+ struct fb_var_screeninfo *var = &cfb->display->var;
-+ u32 pseudo_val;
-+ int ret = 1;
-
-- u_int alpha = transp ^ 0xFFFF;
--
-- if (regno >= NR_PALETTE)
-+ switch (cfb->fb.fix.visual) {
-+ default:
- return 1;
-
-- red >>= 8;
-- green >>= 8;
-- blue >>= 8;
-- alpha >>= 8;
-+#ifdef FBCON_HAS_CFB8
-+ /*
-+ * Pseudocolour:
-+ * 8 8
-+ * pixel --/--+--/--> red lut --> red dac
-+ * | 8
-+ * +--/--> green lut --> green dac
-+ * | 8
-+ * +--/--> blue lut --> blue dac
-+ */
-+ case FB_VISUAL_PSEUDOCOLOR:
-+ if (regno >= NR_PALETTE)
-+ return 1;
-
-- cfb->palette[regno].red = red;
-- cfb->palette[regno].green = green;
-- cfb->palette[regno].blue = blue;
-+ red >>= 8;
-+ green >>= 8;
-+ blue >>= 8;
-+
-+ cfb->palette[regno].red = red;
-+ cfb->palette[regno].green = green;
-+ cfb->palette[regno].blue = blue;
-
-- switch (cfb->fb.var.bits_per_pixel) {
--#ifdef FBCON_HAS_CFB8
-- case 8:
- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-+ cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
-- break;
-+ cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ return 0;
- #endif
-
--#ifdef FBCON_HAS_CFB16
-- case 16:
--#ifndef CFB16_IS_CFB15
-- if (regno < 64) {
-- /* write green */
-+ /*
-+ * Direct colour:
-+ * n rl
-+ * pixel --/--+--/--> red lut --> red dac
-+ * | gl
-+ * +--/--> green lut --> green dac
-+ * | bl
-+ * +--/--> blue lut --> blue dac
-+ * n = bpp, rl = red length, gl = green length, bl = blue length
-+ */
-+ case FB_VISUAL_DIRECTCOLOR:
-+ red >>= 8;
-+ green >>= 8;
-+ blue >>= 8;
-+
-+ if (var->green.length == 6 && regno < 64) {
-+ cfb->palette[regno << 2].green = green;
-+
-+ /*
-+ * The 6 bits of the green component are applied
-+ * to the high 6 bits of the LUT.
-+ */
- cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
-+
-+ green = cfb->palette[regno << 3].green;
-+
-+ ret = 0;
- }
-
-- if (regno < 32) {
-- /* write red,blue */
-+ if (var->green.length >= 5 && regno < 32) {
-+ cfb->palette[regno << 3].red = red;
-+ cfb->palette[regno << 3].green = green;
-+ cfb->palette[regno << 3].blue = blue;
-+
-+ /*
-+ * The 5 bits of each colour component are
-+ * applied to the high 5 bits of the LUT.
-+ */
- cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
-+ cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ ret = 0;
- }
-
-- if (regno < 16)
-- ((u16 *)cfb->fb.pseudo_palette)[regno] =
-- ((red << 8) & 0xf800) |
-- ((green << 3) & 0x07e0) |
-- ((blue >> 3));
-- break;
--#endif
-+ if (var->green.length == 4 && regno < 16) {
-+ cfb->palette[regno << 4].red = red;
-+ cfb->palette[regno << 4].green = green;
-+ cfb->palette[regno << 4].blue = blue;
-
-- case 15:
-- if (regno < 32) {
-- cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
-+ /*
-+ * The 5 bits of each colour component are
-+ * applied to the high 5 bits of the LUT.
-+ */
-+ cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
-+ ret = 0;
- }
-- if (regno < 16)
-- ((u16 *)cfb->fb.pseudo_palette)[regno] =
-- ((red << 7) & 0x7c00) |
-- ((green << 2) & 0x03e0) |
-- ((blue >> 3));
-- break;
--
--#endif
--
--#ifdef FBCON_HAS_CFB24
-- case 24:
-- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
-
-- if (regno < 16)
-- ((u32 *)cfb->fb.pseudo_palette)[regno] =
-- (red << 16) | (green << 8) | blue;
-+ /*
-+ * Since this is only used for the first 16 colours, we
-+ * don't have to care about overflowing for regno >= 32
-+ */
-+ pseudo_val = regno << var->red.offset |
-+ regno << var->green.offset |
-+ regno << var->blue.offset;
- break;
--#endif
-
--#ifdef FBCON_HAS_CFB32
-- case 32:
-- cyber2000fb_writeb(regno, 0x3c8, cfb);
-- cyber2000fb_writeb(red, 0x3c9, cfb);
-- cyber2000fb_writeb(green, 0x3c9, cfb);
-- cyber2000fb_writeb(blue, 0x3c9, cfb);
--
-- if (regno < 16)
-- ((u32 *)cfb->fb.pseudo_palette)[regno] =
-- (alpha << 24) | (red << 16) | (green << 8) | blue;
-+ /*
-+ * True colour:
-+ * n rl
-+ * pixel --/--+--/--> red dac
-+ * | gl
-+ * +--/--> green dac
-+ * | bl
-+ * +--/--> blue dac
-+ * n = bpp, rl = red length, gl = green length, bl = blue length
-+ */
-+ case FB_VISUAL_TRUECOLOR:
-+ pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
-+ pseudo_val |= convert_bitfield(red, &var->red);
-+ pseudo_val |= convert_bitfield(green, &var->green);
-+ pseudo_val |= convert_bitfield(blue, &var->blue);
- break;
--#endif
-+ }
-
-- default:
-- return 1;
-+ /*
-+ * Now set our pseudo palette for the CFB16/24/32 drivers.
-+ */
-+ if (regno < 16) {
-+ if (var->bits_per_pixel == 16)
-+ ((u16 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
-+ else
-+ ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
-+ ret = 0;
- }
-
-- return 0;
-+ return ret;
- }
-
- struct par_info {
-@@ -428,8 +473,8 @@
- */
- u_char clock_mult;
- u_char clock_div;
-- u_char visualid;
-- u_char pixformat;
-+ u_char extseqmisc;
-+ u_char co_pixfmt;
- u_char crtc_ofl;
- u_char crtc[19];
- u_int width;
-@@ -439,8 +484,7 @@
- /*
- * Other
- */
-- u_char palette_ctrl;
-- u_int vmode;
-+ u_char ramdac;
- };
-
- static const u_char crtc_idx[] = {
-@@ -449,6 +493,18 @@
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
- };
-
-+static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
-+{
-+ unsigned int i;
-+ unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
-+
-+ cyber2000fb_writeb(0x56, 0x3ce, cfb);
-+ i = cyber2000fb_readb(0x3cf, cfb);
-+ cyber2000fb_writeb(i | 4, 0x3cf, cfb);
-+ cyber2000fb_writeb(val, 0x3c6, cfb);
-+ cyber2000fb_writeb(i, 0x3cf, cfb);
-+}
-+
- static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
- {
- u_int i;
-@@ -480,7 +536,7 @@
- for (i = 0x0a; i < 0x10; i++)
- cyber2000_crtcw(i, 0, cfb);
-
-- cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
-+ cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
- cyber2000_grphw(0x00, 0x00, cfb);
- cyber2000_grphw(0x01, 0x00, cfb);
- cyber2000_grphw(0x02, 0x00, cfb);
-@@ -501,30 +557,17 @@
- cyber2000_attrw(0x13, 0x00, cfb);
- cyber2000_attrw(0x14, 0x00, cfb);
-
-- /* woody: set the interlaced bit... */
-- /* FIXME: what about doublescan? */
-- cyber2000fb_writeb(0x11, 0x3ce, cfb);
-- i = cyber2000fb_readb(0x3cf, cfb);
-- if (hw->vmode == FB_VMODE_INTERLACED)
-- i |= 0x20;
-- else
-- i &= ~0x20;
-- cyber2000fb_writeb(i, 0x3cf, cfb);
--
- /* PLL registers */
-- cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
-- cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
-- cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
-- cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
-+ cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
-+ cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
-+ cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
-+ cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
- cyber2000_grphw(0x90, 0x01, cfb);
- cyber2000_grphw(0xb9, 0x80, cfb);
- cyber2000_grphw(0xb9, 0x00, cfb);
-
-- cyber2000fb_writeb(0x56, 0x3ce, cfb);
-- i = cyber2000fb_readb(0x3cf, cfb);
-- cyber2000fb_writeb(i | 4, 0x3cf, cfb);
-- cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
-- cyber2000fb_writeb(i, 0x3cf, cfb);
-+ cfb->ramdac_ctrl = hw->ramdac;
-+ cyber2000fb_write_ramdac_ctrl(cfb);
-
- cyber2000fb_writeb(0x20, 0x3c0, cfb);
- cyber2000fb_writeb(0xff, 0x3c6, cfb);
-@@ -532,31 +575,32 @@
- cyber2000_grphw(0x14, hw->fetch, cfb);
- cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
- ((hw->pitch >> 4) & 0x30), cfb);
-- cyber2000_grphw(0x77, hw->visualid, cfb);
-+ cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
-
-- /* make sure we stay in linear mode */
-- cyber2000_grphw(0x33, 0x0d, cfb);
-+// cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
-+// EXT_BIU_MISC_COP_ENABLE |
-+// EXT_BIU_MISC_COP_BFC, cfb);
-
- /*
- * Set up accelerator registers
- */
- cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
- cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
-- cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
-+ cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
- }
-
- static inline int
- cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
- {
-- u_int base;
--
-- base = var->yoffset * var->xres_virtual + var->xoffset;
-+ u_int base = var->yoffset * var->xres_virtual + var->xoffset;
-
-- /* have to be careful, because bits_per_pixel might be 15
-- in this version of the driver -- dok@directfb.org 2002/06/13 */
-- base *= (var->bits_per_pixel + 7) >> 3;
-+ base *= var->bits_per_pixel;
-
-- base >>= 2;
-+ /*
-+ * Convert to bytes and shift two extra bits because DAC
-+ * can only start on 4 byte aligned data.
-+ */
-+ base >>= 5;
-
- if (base >= 1 << 20)
- return -EINVAL;
-@@ -576,27 +620,20 @@
- struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-- struct fb_cmap *dcmap = &fb_display[con].cmap;
-+ struct display *display = fb_display + con;
-+ struct fb_cmap *dcmap = &display->cmap;
- int err = 0;
-
- /* no colormap allocated? */
-- if (!dcmap->len) {
-- int size;
--
-- if (cfb->fb.var.bits_per_pixel == 16)
-- size = 32;
-- else
-- size = 256;
--
-- err = fb_alloc_cmap(dcmap, size, 0);
-- }
-+ if (!dcmap->len)
-+ err = fb_alloc_cmap(dcmap, 256, 0);
-
- /*
- * we should be able to remove this test once fbcon has been
- * "improved" --rmk
- */
-- if (!err && con == cfb->currcon) {
-- err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
-+ if (!err && display == cfb->display) {
-+ err = fb_set_cmap(cmap, kspc, cyber2000fb_setcolreg, &cfb->fb);
- dcmap = &cfb->fb.cmap;
- }
-
-@@ -672,8 +709,9 @@
- hw->crtc[16] = Vblankend;
- hw->crtc[18] = 0xff;
-
-- /* overflow - graphics reg 0x11 */
-- /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
-+ /*
-+ * overflow - graphics reg 0x11
-+ * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
- * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
- */
- hw->crtc_ofl =
-@@ -681,7 +719,12 @@
- BIT(Vdispend, 10, 0x01, 1) |
- BIT(Vsyncstart, 10, 0x01, 2) |
- BIT(Vblankstart,10, 0x01, 3) |
-- 1 << 4;
-+ EXT_CRT_VRTOFL_LINECOMP10;
-+
-+ /* woody: set the interlaced bit... */
-+ /* FIXME: what about doublescan? */
-+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-+ hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
-
- return 0;
- }
-@@ -787,7 +830,7 @@
- vco = ref_ps * best_div1 / best_mult;
- if ((ref_ps == 40690) && (vco < 5556))
- /* Set VFSEL when VCO > 180MHz (5.556 ps). */
-- hw->clock_div |= DCLK_DIV_VFSEL;
-+ hw->clock_div |= EXT_DCLK_DIV_VFSEL;
-
- return 0;
- }
-@@ -801,58 +844,131 @@
- cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
- struct par_info *hw)
- {
-+ unsigned int mem;
- int err;
-
- hw->width = var->xres_virtual;
-- hw->palette_ctrl = 0x06;
-- hw->vmode = var->vmode;
-+ hw->ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
-+
-+ var->transp.msb_right = 0;
-+ var->red.msb_right = 0;
-+ var->green.msb_right = 0;
-+ var->blue.msb_right = 0;
-
- switch (var->bits_per_pixel) {
- #ifdef FBCON_HAS_CFB8
- case 8: /* PSEUDOCOLOUR, 256 */
-- hw->pixformat = PIXFORMAT_8BPP;
-- hw->visualid = VISUALID_256;
-+ hw->co_pixfmt = CO_PIXFMT_8BPP;
- hw->pitch = hw->width >> 3;
-+ hw->extseqmisc = EXT_SEQ_MISC_8;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 0;
-+ var->red.length = 8;
-+ var->green.offset = 0;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
-- case 16:/* DIRECTCOLOUR, 64k */
--#ifndef CFB16_IS_CFB15
-- hw->pixformat = PIXFORMAT_16BPP;
-- hw->visualid = VISUALID_64K;
-- hw->pitch = hw->width >> 2;
-- hw->palette_ctrl |= 0x10;
-- break;
--#endif
-- case 15:/* DIRECTCOLOUR, 32k */
-- hw->pixformat = PIXFORMAT_16BPP;
-- hw->visualid = VISUALID_32K;
-+ case 16:/* DIRECTCOLOUR, 64k or 32k */
-+ hw->co_pixfmt = CO_PIXFMT_16BPP;
- hw->pitch = hw->width >> 2;
-- hw->palette_ctrl |= 0x10;
-- break;
-
-+ switch (var->green.length) {
-+ case 6: /* RGB565, 64k */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 11;
-+ var->red.length = 5;
-+ var->green.offset = 5;
-+ var->green.length = 6;
-+ var->blue.offset = 0;
-+ var->blue.length = 5;
-+ break;
-+
-+ default:
-+ case 5: /* RGB555, 32k */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 10;
-+ var->red.length = 5;
-+ var->green.offset = 5;
-+ var->green.length = 5;
-+ var->blue.offset = 0;
-+ var->blue.length = 5;
-+ break;
-+
-+ case 4: /* RGB444, 4k + transparency? */
-+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB444;
-+
-+ var->transp.offset = 12;
-+ var->transp.length = 4;
-+ var->red.offset = 8;
-+ var->red.length = 4;
-+ var->green.offset = 4;
-+ var->green.length = 4;
-+ var->blue.offset = 0;
-+ var->blue.length = 4;
-+ break;
-+ }
-+ break;
- #endif
- #ifdef FBCON_HAS_CFB24
- case 24:/* TRUECOLOUR, 16m */
-- hw->pixformat = PIXFORMAT_24BPP;
-- hw->visualid = VISUALID_16M;
-+ hw->co_pixfmt = CO_PIXFMT_24BPP;
- hw->width *= 3;
- hw->pitch = hw->width >> 3;
-- hw->palette_ctrl |= 0x10;
-+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
-+
-+ var->transp.offset = 0;
-+ var->transp.length = 0;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:/* TRUECOLOUR, 16m */
-- hw->pixformat = PIXFORMAT_32BPP;
-- hw->visualid = VISUALID_16M_32;
-+ hw->co_pixfmt = CO_PIXFMT_32BPP;
- hw->pitch = hw->width >> 1;
-- hw->palette_ctrl |= 0x10;
-+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ hw->extseqmisc = EXT_SEQ_MISC_32;
-+
-+ var->transp.offset = 24;
-+ var->transp.length = 8;
-+ var->red.offset = 16;
-+ var->red.length = 8;
-+ var->green.offset = 8;
-+ var->green.length = 8;
-+ var->blue.offset = 0;
-+ var->blue.length = 8;
- break;
- #endif
- default:
- return -EINVAL;
- }
-
-+ mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
-+ if (mem > cfb->fb.fix.smem_len)
-+ var->yres_virtual = cfb->fb.fix.smem_len * 8 /
-+ (var->bits_per_pixel * var->xres_virtual);
-+
-+ if (var->yres > var->yres_virtual)
-+ var->yres = var->yres_virtual;
-+ if (var->xres > var->xres_virtual)
-+ var->xres = var->xres_virtual;
-+
- err = cyber2000fb_decode_clock(hw, cfb, var);
- if (err)
- return err;
-@@ -880,7 +996,7 @@
- struct cfb_info *cfb = (struct cfb_info *)info;
- struct display *display;
- struct par_info hw;
-- int err, chgvar = 0;
-+ int err, chgvar;
-
- /*
- * CONUPDATE and SMOOTH_XPAN are equal. However,
-@@ -888,11 +1004,11 @@
- */
- if (var->vmode & FB_VMODE_CONUPDATE) {
- var->vmode |= FB_VMODE_YWRAP;
-- var->xoffset = cfb->fb.var.xoffset;
-- var->yoffset = cfb->fb.var.yoffset;
-+ var->xoffset = cfb->display->var.xoffset;
-+ var->yoffset = cfb->display->var.yoffset;
- }
-
-- err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
-+ err = cyber2000fb_decode_var(var, cfb, &hw);
- if (err)
- return err;
-
-@@ -902,105 +1018,61 @@
- if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
- return -EINVAL;
-
-- if (cfb->fb.var.xres != var->xres)
-- chgvar = 1;
-- if (cfb->fb.var.yres != var->yres)
-- chgvar = 1;
-- if (cfb->fb.var.xres_virtual != var->xres_virtual)
-- chgvar = 1;
-- if (cfb->fb.var.yres_virtual != var->yres_virtual)
-- chgvar = 1;
-- if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
-- chgvar = 1;
--
- if (con < 0) {
- display = cfb->fb.disp;
-- chgvar = 0;
- } else {
- display = fb_display + con;
- }
-
-- var->red.msb_right = 0;
-- var->green.msb_right = 0;
-- var->blue.msb_right = 0;
-+ chgvar = cfb->fb.var.xres != var->xres ||
-+ cfb->fb.var.yres != var->yres ||
-+ cfb->fb.var.xres_virtual != var->xres_virtual ||
-+ cfb->fb.var.yres_virtual != var->yres_virtual ||
-+ cfb->fb.var.bits_per_pixel != var->bits_per_pixel;
-+
-+ if (memcmp(&cfb->fb.var.red, &var->red, sizeof(var->red)) ||
-+ memcmp(&cfb->fb.var.green, &var->green, sizeof(var->green)) ||
-+ memcmp(&cfb->fb.var.blue, &var->blue, sizeof(var->blue)))
-+ chgvar = 1;
-+
-+ if (con < 0)
-+ chgvar = 0;
-+
-+ /*
-+ * If we are setting all the virtual consoles, also set the
-+ * defaults used to create new consoles.
-+ */
-+ err = var->activate;
-+ var->activate = FB_ACTIVATE_NOW;
-+ if (err & FB_ACTIVATE_ALL)
-+ cfb->fb.disp->var = *var;
-+
-+ cfb->fb.var = *var;
-+ cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
- switch (var->bits_per_pixel) {
- #ifdef FBCON_HAS_CFB8
- case 8: /* PSEUDOCOLOUR, 256 */
-- var->red.offset = 0;
-- var->red.length = 8;
-- var->green.offset = 0;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
- cfb->dispsw = &fbcon_cfb8;
- display->dispsw_data = NULL;
-- display->next_line = var->xres_virtual;
- break;
- #endif
- #ifdef FBCON_HAS_CFB16
-- case 16:/* DIRECTCOLOUR, 64k */
--#ifndef CFB16_IS_CFB15
-- var->red.offset = 11;
-- var->red.length = 5;
-- var->green.offset = 5;
-- var->green.length = 6;
-- var->blue.offset = 0;
-- var->blue.length = 5;
--
-- cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ case 16:/* DIRECTCOLOUR */
- cfb->dispsw = &fbcon_cfb16;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 2;
-- break;
--#endif
-- case 15:/* DIRECTCOLOUR, 32k */
-- var->bits_per_pixel = 15;
-- var->red.offset = 10;
-- var->red.length = 5;
-- var->green.offset = 5;
-- var->green.length = 5;
-- var->blue.offset = 0;
-- var->blue.length = 5;
--
-- cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-- cfb->dispsw = &fbcon_cfb16;
-- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 2;
- break;
- #endif
- #ifdef FBCON_HAS_CFB24
- case 24:/* TRUECOLOUR, 16m */
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
- cfb->dispsw = &fbcon_cfb24;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 3;
- break;
- #endif
- #ifdef FBCON_HAS_CFB32
- case 32:/* TRUECOLOUR, 16m */
-- var->transp.offset = 24;
-- var->transp.length = 8;
-- var->red.offset = 16;
-- var->red.length = 8;
-- var->green.offset = 8;
-- var->green.length = 8;
-- var->blue.offset = 0;
-- var->blue.length = 8;
--
-- cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
- cfb->dispsw = &fbcon_cfb32;
- display->dispsw_data = cfb->fb.pseudo_palette;
-- display->next_line = var->xres_virtual * 4;
- break;
- #endif
- default:/* in theory this should never happen */
-@@ -1010,15 +1082,27 @@
- break;
- }
-
-+ /*
-+ * 8bpp displays are always pseudo colour.
-+ * 16bpp and above are direct colour or true colour, depending
-+ * on whether the RAMDAC palettes are bypassed. (Direct colour
-+ * has palettes, true colour does not.)
-+ */
-+ if (var->bits_per_pixel == 8)
-+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ else if (hw.ramdac & RAMDAC_BYPASS)
-+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
-+ else
-+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+
- if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)
- display->dispsw = &fbcon_cyber_accel;
- else
- display->dispsw = cfb->dispsw;
-
-- cfb->fb.fix.line_length = display->next_line;
--
- display->screen_base = cfb->fb.screen_base;
- display->line_length = cfb->fb.fix.line_length;
-+ display->next_line = cfb->fb.fix.line_length;
- display->visual = cfb->fb.fix.visual;
- display->type = cfb->fb.fix.type;
- display->type_aux = cfb->fb.fix.type_aux;
-@@ -1026,31 +1110,15 @@
- display->ywrapstep = cfb->fb.fix.ywrapstep;
- display->can_soft_blank = 1;
- display->inverse = 0;
-+ display->var = *var;
-
-- cfb->fb.var = *var;
-- cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
--
-- /*
-- * Update the old var. The fbcon drivers still use this.
-- * Once they are using cfb->fb.var, this can be dropped.
-- * --rmk
-- */
-- display->var = cfb->fb.var;
--
-- /*
-- * If we are setting all the virtual consoles, also set the
-- * defaults used to create new consoles.
-- */
-- if (var->activate & FB_ACTIVATE_ALL)
-- cfb->fb.disp->var = cfb->fb.var;
-+ cyber2000fb_set_timing(cfb, &hw);
-+ cyber2000fb_update_start(cfb, var);
-+ fb_set_cmap(&cfb->fb.cmap, 1, cyber2000fb_setcolreg, &cfb->fb);
-
-- if (chgvar && info && cfb->fb.changevar)
-+ if (chgvar && cfb->fb.changevar)
- cfb->fb.changevar(con);
-
-- cyber2000fb_update_start(cfb, var);
-- cyber2000fb_set_timing(cfb, &hw);
-- fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb);
--
- return 0;
- }
-
-@@ -1072,18 +1140,18 @@
-
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
-- if (y_bottom > cfb->fb.var.yres_virtual)
-+ if (y_bottom > cfb->display->var.yres_virtual)
- return -EINVAL;
-
- if (cyber2000fb_update_start(cfb, var))
- return -EINVAL;
-
-- cfb->fb.var.xoffset = var->xoffset;
-- cfb->fb.var.yoffset = var->yoffset;
-+ cfb->display->var.xoffset = var->xoffset;
-+ cfb->display->var.yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP) {
-- cfb->fb.var.vmode |= FB_VMODE_YWRAP;
-+ cfb->display->var.vmode |= FB_VMODE_YWRAP;
- } else {
-- cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
-+ cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
- }
-
- return 0;
-@@ -1106,22 +1174,18 @@
- static int cyber2000fb_switch(int con, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-- struct display *disp;
-+ struct display *display = cfb->display;
- struct fb_cmap *cmap;
-
-- if (cfb->currcon >= 0) {
-- disp = fb_display + cfb->currcon;
--
-+ if (display) {
- /*
- * Save the old colormap and video mode.
- */
-- disp->var = cfb->fb.var;
-- if (disp->cmap.len)
-- fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
-+ if (display->cmap.len)
-+ fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
- }
-
-- cfb->currcon = con;
-- disp = fb_display + con;
-+ cfb->display = display = fb_display + con;
-
- /*
- * Install the new colormap and change the video mode. By default,
-@@ -1132,73 +1196,88 @@
- * depth of the new video mode. For now, we leave it at its
- * default 256 entry.
- */
-- if (disp->cmap.len)
-- cmap = &disp->cmap;
-+ if (display->cmap.len)
-+ cmap = &display->cmap;
- else
-- cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
-+ cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
-
- fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
-
-- cfb->fb.var = disp->var;
-- cfb->fb.var.activate = FB_ACTIVATE_NOW;
--
-- cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
-+ display->var.activate = FB_ACTIVATE_NOW;
-+ cyber2000fb_set_var(&display->var, con, &cfb->fb);
-
- return 0;
- }
-
- /*
- * (Un)Blank the display.
-+ *
-+ * Blank the screen if blank_mode != 0, else unblank. If
-+ * blank == NULL then the caller blanks by setting the CLUT
-+ * (Color Look Up Table) to all black. Return 0 if blanking
-+ * succeeded, != 0 if un-/blanking failed due to e.g. a
-+ * video mode which doesn't support it. Implements VESA
-+ * suspend and powerdown modes on hardware that supports
-+ * disabling hsync/vsync:
-+ * blank_mode == 2: suspend vsync
-+ * blank_mode == 3: suspend hsync
-+ * blank_mode == 4: powerdown
-+ *
-+ * wms...Enable VESA DMPS compatible powerdown mode
-+ * run "setterm -powersave powerdown" to take advantage
- */
- static void cyber2000fb_blank(int blank, struct fb_info *info)
- {
- struct cfb_info *cfb = (struct cfb_info *)info;
-+ unsigned int sync = 0;
- int i;
-
-- /*
-- * Blank the screen if blank_mode != 0, else unblank. If
-- * blank == NULL then the caller blanks by setting the CLUT
-- * (Color Look Up Table) to all black. Return 0 if blanking
-- * succeeded, != 0 if un-/blanking failed due to e.g. a
-- * video mode which doesn't support it. Implements VESA
-- * suspend and powerdown modes on hardware that supports
-- * disabling hsync/vsync:
-- * blank_mode == 2: suspend vsync
-- * blank_mode == 3: suspend hsync
-- * blank_mode == 4: powerdown
-- *
-- * wms...Enable VESA DMPS compatible powerdown mode
-- * run "setterm -powersave powerdown" to take advantage
-- */
--
- switch (blank) {
- case 4: /* powerdown - both sync lines down */
-- cyber2000_grphw(0x16, 0x05, cfb);
-+ sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
- break;
- case 3: /* hsync off */
-- cyber2000_grphw(0x16, 0x01, cfb);
-+ sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
- break;
- case 2: /* vsync off */
-- cyber2000_grphw(0x16, 0x04, cfb);
-- break;
-+ sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
-+ break;
- case 1: /* soft blank */
-- cyber2000_grphw(0x16, 0x00, cfb);
-+ default: /* unblank */
-+ break;
-+ }
-+
-+ cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
-+
-+ if (blank <= 1) {
-+ /* turn on ramdacs */
-+ cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
-+ cyber2000fb_write_ramdac_ctrl(cfb);
-+ }
-+
-+ /*
-+ * Soft blank/unblank the display.
-+ */
-+ if (blank) { /* soft blank */
- for (i = 0; i < NR_PALETTE; i++) {
- cyber2000fb_writeb(i, 0x3c8, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- cyber2000fb_writeb(0, 0x3c9, cfb);
- }
-- break;
-- default: /* unblank */
-- cyber2000_grphw(0x16, 0x00, cfb);
-+ } else { /* unblank */
- for (i = 0; i < NR_PALETTE; i++) {
- cyber2000fb_writeb(i, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
- }
-- break;
-+ }
-+
-+ if (blank >= 2) {
-+ /* turn off ramdacs */
-+ cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
-+ cyber2000fb_write_ramdac_ctrl(cfb);
- }
- }
-
-@@ -1233,51 +1312,61 @@
- }
-
- static struct fb_ops cyber2000fb_ops = {
-- owner: THIS_MODULE,
-- fb_set_var: cyber2000fb_set_var,
-- fb_set_cmap: cyber2000fb_set_cmap,
-- fb_pan_display: cyber2000fb_pan_display,
-- fb_get_fix: gen_get_fix,
-- fb_get_var: gen_get_var,
-- fb_get_cmap: gen_get_cmap,
-+ .owner = THIS_MODULE,
-+ .fb_set_var = cyber2000fb_set_var,
-+ .fb_set_cmap = cyber2000fb_set_cmap,
-+ .fb_pan_display = cyber2000fb_pan_display,
-+ .fb_get_fix = gen_get_fix,
-+ .fb_get_var = gen_get_var,
-+ .fb_get_cmap = gen_get_cmap,
- };
-
- /*
-+ * This is the only "static" reference to the internal data structures
-+ * of this driver. It is here solely at the moment to support the other
-+ * CyberPro modules external to this driver.
-+ */
-+static struct cfb_info *int_cfb_info;
-+
-+/*
- * Enable access to the extended registers
- */
--static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
-+void cyber2000fb_enable_extregs(struct cfb_info *cfb)
- {
- cfb->func_use_count += 1;
-
- if (cfb->func_use_count == 1) {
- int old;
-
-- old = cyber2000_grphr(FUNC_CTL, cfb);
-- cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
-+ old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-+ old |= EXT_FUNC_CTL_EXTREGENBL;
-+ cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
- }
- }
-
- /*
- * Disable access to the extended registers
- */
--static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
-+void cyber2000fb_disable_extregs(struct cfb_info *cfb)
- {
- if (cfb->func_use_count == 1) {
- int old;
-
-- old = cyber2000_grphr(FUNC_CTL, cfb);
-- cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
-+ old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
-+ old &= ~EXT_FUNC_CTL_EXTREGENBL;
-+ cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
- }
-
-- cfb->func_use_count -= 1;
-+ if (cfb->func_use_count == 0)
-+ printk(KERN_ERR "disable_extregs: count = 0\n");
-+ else
-+ cfb->func_use_count -= 1;
- }
-
--/*
-- * This is the only "static" reference to the internal data structures
-- * of this driver. It is here solely at the moment to support the other
-- * CyberPro modules external to this driver.
-- */
--static struct cfb_info *int_cfb_info;
-+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
-+{
-+ memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
-+}
-
- /*
- * Attach a capture/tv driver to the core CyberX0X0 driver.
-@@ -1311,164 +1400,102 @@
-
- EXPORT_SYMBOL(cyber2000fb_attach);
- EXPORT_SYMBOL(cyber2000fb_detach);
-+EXPORT_SYMBOL(cyber2000fb_enable_extregs);
-+EXPORT_SYMBOL(cyber2000fb_disable_extregs);
-+EXPORT_SYMBOL(cyber2000fb_get_fb_var);
-
- /*
- * These parameters give
- * 640x480, hsync 31.5kHz, vsync 60Hz
- */
- static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
-- refresh: 60,
-- xres: 640,
-- yres: 480,
-- pixclock: 39722,
-- left_margin: 56,
-- right_margin: 16,
-- upper_margin: 34,
-- lower_margin: 9,
-- hsync_len: 88,
-- vsync_len: 2,
-- sync: FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-- vmode: FB_VMODE_NONINTERLACED
-+ .refresh = 60,
-+ .xres = 640,
-+ .yres = 480,
-+ .pixclock = 39722,
-+ .left_margin = 56,
-+ .right_margin = 16,
-+ .upper_margin = 34,
-+ .lower_margin = 9,
-+ .hsync_len = 88,
-+ .vsync_len = 2,
-+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+ .vmode = FB_VMODE_NONINTERLACED
- };
-
-+/* static register programming for all chips */
- static char igs_regs[] __devinitdata = {
-- 0x12, 0x00, 0x13, 0x00,
-- 0x16, 0x00,
-- 0x31, 0x00, 0x32, 0x00,
-- 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
-- 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
-- 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
-- 0x70, 0x0b, 0x73, 0x30,
-- 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8
-+ EXT_CRT_IRQ, 0,
-+ EXT_CRT_TEST, 0,
-+ EXT_SYNC_CTL, 0,
-+ EXT_SEG_WRITE_PTR, 0,
-+ EXT_SEG_READ_PTR, 0,
-+ EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
-+ EXT_BIU_MISC_COP_ENABLE |
-+ EXT_BIU_MISC_COP_BFC,
-+ EXT_FUNC_CTL, 0,
-+ CURS_H_START, 0,
-+ CURS_H_START + 1, 0,
-+ CURS_H_PRESET, 0,
-+ CURS_V_START, 0,
-+ CURS_V_START + 1, 0,
-+ CURS_V_PRESET, 0,
-+ CURS_CTL, 0,
-+ EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
-+ EXT_OVERSCAN_RED, 0,
-+ EXT_OVERSCAN_GREEN, 0,
-+ EXT_OVERSCAN_BLUE, 0,
-+};
-+
-+/* specific register setting for the 2000 series */
-+static char igs_2000_regs[] __devinitdata = {
-+ /* some of these are questionable when we have a BIOS */
-+ EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
-+ EXT_MEM_CTL0_RAS_1 |
-+ EXT_MEM_CTL0_MULTCAS,
-+ EXT_HIDDEN_CTL1, 0x30,
-+ EXT_FIFO_CTL, 0x0b,
-+ EXT_FIFO_CTL + 1, 0x17,
-+ 0x76, 0x00,
-+ EXT_HIDDEN_CTL4, 0xc8
- };
-
- /*
-- * We need to wake up the CyberPro, and make sure its in linear memory
-- * mode. Unfortunately, this is specific to the platform and card that
-- * we are running on.
-- *
-- * On x86 and ARM, should we be initialising the CyberPro first via the
-- * IO registers, and then the MMIO registers to catch all cases? Can we
-- * end up in the situation where the chip is in MMIO mode, but not awake
-- * on an x86 system?
-- *
-- * Note that on the NetWinder, the firmware automatically detects the
-- * type, width and size, and leaves this in extended registers 0x71 and
-- * 0x72 for us.
-+ * Initialise the CyberPro hardware.
- */
--static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
-+static void cyberpro_init_hw(struct cfb_info *cfb)
- {
- int i;
-
-- /*
-- * Wake up the CyberPro.
-- */
--#ifdef __sparc__
--#ifdef __sparc_v9__
--#error "You loose, consult DaveM."
--#else
-- /*
-- * SPARC does not have an "outb" instruction, so we generate
-- * I/O cycles storing into a reserved memory space at
-- * physical address 0x3000000
-- */
-- {
-- unsigned char *iop;
--
-- iop = ioremap(0x3000000, 0x5000);
-- if (iop == NULL) {
-- prom_printf("iga5000: cannot map I/O\n");
-- return -ENOMEM;
-- }
--
-- writeb(0x18, iop + 0x46e8);
-- writeb(0x01, iop + 0x102);
-- writeb(0x08, iop + 0x46e8);
-- writeb(0x33, iop + 0x3ce);
-- writeb(0x01, iop + 0x3cf);
--
-- iounmap((void *)iop);
-- }
--#endif
--
-- if (at_boot) {
-- /*
-- * Use mclk from BIOS. Only read this if we're
-- * initialising this card for the first time.
-- * FIXME: what about hotplug?
-- */
-- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-- cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
-- }
--#endif
--#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
-- /*
-- * x86 and MIPS are simple, we just do regular
-- * outb's instead of cyber2000fb_writeb.
-- */
-- outb(0x18, 0x46e8);
-- outb(0x01, 0x102);
-- outb(0x08, 0x46e8);
-- outb(0x33, 0x3ce);
-- outb(0x01, 0x3cf);
--
-- if (at_boot) {
-- /*
-- * Use mclk from BIOS. Only read this if we're
-- * initialising this card for the first time.
-- * FIXME: what about hotplug?
-- */
-- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-- cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
-- }
--#endif
--#ifdef __arm__
-- cyber2000fb_writeb(0x18, 0x46e8, cfb);
-- cyber2000fb_writeb(0x01, 0x102, cfb);
-- cyber2000fb_writeb(0x08, 0x46e8, cfb);
-- cyber2000fb_writeb(0x33, 0x3ce, cfb);
-- cyber2000fb_writeb(0x01, 0x3cf, cfb);
--
-- /*
-- * MCLK on the NetWinder and the Shark is fixed at 75MHz
-- */
-- cfb->mclk_mult = 0xdb;
-- cfb->mclk_div = 0x54;
--#endif
--
-- /*
-- * Initialise the CyberPro
-- */
- for (i = 0; i < sizeof(igs_regs); i += 2)
- cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
-
-- if (at_boot) {
-+ if (cfb->id == ID_CYBERPRO_5000) {
- /*
-- * get the video RAM size and width from the VGA register.
-- * This should have been already initialised by the BIOS,
-- * but if it's garbage, claim default 1MB VRAM (woody)
-+ * On the CyberPro5XXXX, ensure that we're using the correct
-+ * PLL (5XXX's may be programmed to use an additional set of
-+ * PLLs.)
- */
-- cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
-- cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
-+ unsigned char val;
-+ cyber2000fb_writeb(0xba, 0x3ce, cfb);
-+ val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
-+ cyber2000fb_writeb(val, 0x3cf, cfb);
-+ cyber2000fb_ops.fb_pan_display = NULL; /* FIXME: panning broken */
- } else {
- /*
-- * Reprogram the MEM_CTL1 and MEM_CTL2 registers
-+ * Other supported chips (2000 series) appear to need
-+ * these registers programming
- */
-- cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
-- cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
-+ for (i = 0; i < sizeof(igs_2000_regs); i += 2)
-+ cyber2000_grphw(igs_2000_regs[i],
-+ igs_2000_regs[i+1],
-+ cfb);
- }
-
-- /*
-- * Ensure thatwe are using the correct PLL.
-- * (CyberPro 5000's may be programmed to use
-- * an additional set of PLLs.
-- */
-- cyber2000fb_writeb(0xba, 0x3ce, cfb);
-- cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
- }
-
- static struct cfb_info * __devinit
--cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
-+cyberpro_alloc_fb_info(unsigned int id, char *name)
- {
- struct cfb_info *cfb;
-
-@@ -1480,10 +1507,9 @@
-
- memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
-
-- cfb->currcon = -1;
-- cfb->dev = dev;
-+ cfb->id = id;
-
-- if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
-+ if (id == ID_CYBERPRO_5000)
- cfb->ref_ps = 40690; // 24.576 MHz
- else
- cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
-@@ -1492,7 +1518,7 @@
- cfb->divisors[1] = 2;
- cfb->divisors[2] = 4;
-
-- if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
-+ if (id == ID_CYBERPRO_2000)
- cfb->divisors[3] = 8;
- else
- cfb->divisors[3] = 6;
-@@ -1504,7 +1530,24 @@
- cfb->fb.fix.xpanstep = 0;
- cfb->fb.fix.ypanstep = 1;
- cfb->fb.fix.ywrapstep = 0;
-- cfb->fb.fix.accel = id->driver_data;
-+
-+ switch (id) {
-+ case ID_IGA_1682:
-+ cfb->fb.fix.accel = 0;
-+ break;
-+
-+ case ID_CYBERPRO_2000:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
-+ break;
-+
-+ case ID_CYBERPRO_2010:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
-+ break;
-+
-+ case ID_CYBERPRO_5000:
-+ cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
-+ break;
-+ }
-
- cfb->fb.var.nonstd = 0;
- cfb->fb.var.activate = FB_ACTIVATE_NOW;
-@@ -1569,55 +1612,46 @@
- return 0;
- }
-
--static int __devinit
--cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
-+/*
-+ * The CyberPro chips can be placed on many different bus types.
-+ * This probe function is common to all bus types. The bus-specific
-+ * probe function is expected to have:
-+ * - enabled access to the linear memory region
-+ * - memory mapped access to the registers
-+ * - initialised mem_ctl1 and mem_ctl2 appropriately.
-+ */
-+static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
- {
-- struct cfb_info *cfb;
-- u_int h_sync, v_sync;
- u_long smem_size;
-- char name[16];
-+ u_int h_sync, v_sync;
- int err;
-
-- sprintf(name, "CyberPro%4X", id->device);
--
-- err = pci_enable_device(dev);
-- if (err)
-- return err;
--
-- err = pci_request_regions(dev, name);
-- if (err)
-- return err;
--
-- err = -ENOMEM;
-- cfb = cyberpro_alloc_fb_info(dev, id, name);
-- if (!cfb)
-- goto failed_release;
--
-- cfb->region = ioremap(pci_resource_start(dev, 0),
-- pci_resource_len(dev, 0));
-- if (!cfb->region)
-- goto failed_ioremap;
--
-- cfb->regs = cfb->region + MMIO_OFFSET;
-+ cyberpro_init_hw(cfb);
-
-- cyberpro_init_hw(cfb, 1);
-+ /*
-+ * Get the video RAM size and width from the VGA register.
-+ * This should have been already initialised by the BIOS,
-+ * but if it's garbage, claim default 1MB VRAM (woody)
-+ */
-+ cfb->mem_ctl0 = cyber2000_grphr(EXT_MEM_CTL0, cfb);
-+ cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
-+ cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
-
-+ /*
-+ * Determine the size of the memory.
-+ */
- switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
- case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
- case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
-+ case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
- default: smem_size = 0x00100000; break;
- }
-
-- /*
-- * Hmm, we _need_ a portable way of finding the address for
-- * the remap stuff, both for mmio and for smem.
-- */
-- cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-- cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-- cfb->fb.fix.mmio_len = MMIO_SIZE;
- cfb->fb.fix.smem_len = smem_size;
-+ cfb->fb.fix.mmio_len = MMIO_SIZE;
- cfb->fb.screen_base = cfb->region;
-
-+ err = -EINVAL;
- if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
- &cyber2000fb_default_mode, 8)) {
- printk("%s: no valid mode found\n", cfb->fb.fix.id);
-@@ -1644,13 +1678,181 @@
- v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
- cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
-
-- printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-+ printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
- cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
- cfb->fb.var.xres, cfb->fb.var.yres,
- h_sync / 1000, h_sync % 1000, v_sync);
-
- err = register_framebuffer(&cfb->fb);
-- if (err < 0)
-+
-+failed:
-+ return err;
-+}
-+
-+static void cyberpro_common_resume(struct cfb_info *cfb)
-+{
-+ cyberpro_init_hw(cfb);
-+
-+ /*
-+ * Reprogram the MEM_CTL0, 1 and 2 registers
-+ */
-+ cyber2000_grphw(EXT_MEM_CTL0, cfb->mem_ctl0, cfb);
-+ cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
-+ cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
-+
-+ /*
-+ * Restore the old video mode and the palette.
-+ * We also need to tell fbcon to redraw the console.
-+ */
-+ cfb->fb.var.activate = FB_ACTIVATE_NOW;
-+ cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+}
-+
-+
-+
-+
-+/*
-+ * PCI specific support.
-+ */
-+
-+/*
-+ * We need to wake up the CyberPro, and make sure its in linear memory
-+ * mode. Unfortunately, this is specific to the platform and card that
-+ * we are running on.
-+ *
-+ * On x86 and ARM, should we be initialising the CyberPro first via the
-+ * IO registers, and then the MMIO registers to catch all cases? Can we
-+ * end up in the situation where the chip is in MMIO mode, but not awake
-+ * on an x86 system?
-+ */
-+static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
-+{
-+ unsigned char val;
-+
-+#if defined(__sparc_v9__)
-+#error "You loose, consult DaveM."
-+#elif defined(__sparc__)
-+ /*
-+ * SPARC does not have an "outb" instruction, so we generate
-+ * I/O cycles storing into a reserved memory space at
-+ * physical address 0x3000000
-+ */
-+ unsigned char *iop;
-+
-+ iop = ioremap(0x3000000, 0x5000);
-+ if (iop == NULL) {
-+ prom_printf("iga5000: cannot map I/O\n");
-+ return -ENOMEM;
-+ }
-+
-+ writeb(0x18, iop + 0x46e8);
-+ writeb(0x01, iop + 0x102);
-+ writeb(0x08, iop + 0x46e8);
-+ writeb(EXT_BIU_MISC, iop + 0x3ce);
-+ writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
-+
-+ iounmap((void *)iop);
-+#elif defined(CONFIG_ARCH_SHARK)
-+ /*
-+ * Shark probably needs to do it this way rather than use the
-+ * IO method below. Since the CyberPro on the Shark isn't a
-+ * PCI device, we probably want to move this to a bus-specific
-+ * probe function. Do we even need to do this?
-+ */
-+ cyber2000fb_writeb(0x18, 0x46e8, cfb);
-+ cyber2000fb_writeb(0x01, 0x102, cfb);
-+ cyber2000fb_writeb(0x08, 0x46e8, cfb);
-+ cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
-+ cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
-+#else
-+ /*
-+ * Most other machine types are "normal", so
-+ * we use the standard IO-based wakeup.
-+ */
-+ outb(0x18, 0x46e8);
-+ outb(0x01, 0x102);
-+ outb(0x08, 0x46e8);
-+ outb(EXT_BIU_MISC, 0x3ce);
-+ outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
-+#endif
-+
-+ /*
-+ * Allow the CyberPro to accept PCI burst accesses
-+ */
-+ val = cyber2000_grphr(EXT_BUS_CTL, cfb);
-+ if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
-+ printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
-+
-+ val |= EXT_BUS_CTL_PCIBURST_WRITE;
-+
-+ if (cfb->id == ID_CYBERPRO_5000)
-+ val |= EXT_BUS_CTL_PCIBURST_READ;
-+
-+ cyber2000_grphw(EXT_BUS_CTL, val, cfb);
-+ }
-+
-+ return 0;
-+}
-+
-+static int __devinit
-+cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-+{
-+ struct cfb_info *cfb;
-+ char name[16];
-+ int err;
-+
-+ sprintf(name, "CyberPro%4X", id->device);
-+
-+ err = pci_enable_device(dev);
-+ if (err)
-+ return err;
-+
-+ err = pci_request_regions(dev, name);
-+ if (err)
-+ return err;
-+
-+ err = -ENOMEM;
-+ cfb = cyberpro_alloc_fb_info(id->driver_data, name);
-+ if (!cfb)
-+ goto failed_release;
-+
-+ cfb->dev = dev;
-+ cfb->region = ioremap(pci_resource_start(dev, 0),
-+ pci_resource_len(dev, 0));
-+ if (!cfb->region)
-+ goto failed_ioremap;
-+
-+ cfb->regs = cfb->region + MMIO_OFFSET;
-+ cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-+ cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-+
-+ /*
-+ * Bring up the hardware. This is expected to enable access
-+ * to the linear memory region, and allow access to the memory
-+ * mapped registers. Also, mem_ctl1 and mem_ctl2 must be
-+ * initialised.
-+ */
-+ err = cyberpro_pci_enable_mmio(cfb);
-+ if (err)
-+ goto failed;
-+
-+ /*
-+ * Use MCLK from BIOS. FIXME: what about hotplug?
-+ */
-+ cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
-+ cfb->mclk_div = cyber2000_grphr(EXT_MCLK_DIV, cfb);
-+#ifdef __arm__
-+ if (machine_is_netwinder() || machine_is_shark()) {
-+ /*
-+ * MCLK on the NetWinder and the Shark is fixed at 75MHz
-+ */
-+ cfb->mclk_mult = 0xdb;
-+ cfb->mclk_div = 0x54;
-+ }
-+#endif
-+
-+ err = cyberpro_common_probe(cfb);
-+ if (err)
- goto failed;
-
- /*
-@@ -1672,7 +1874,7 @@
- return err;
- }
-
--static void __devexit cyberpro_remove(struct pci_dev *dev)
-+static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
- {
- struct cfb_info *cfb = pci_get_drvdata(dev);
-
-@@ -1701,7 +1903,7 @@
- }
- }
-
--static int cyberpro_suspend(struct pci_dev *dev, u32 state)
-+static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
- {
- return 0;
- }
-@@ -1709,41 +1911,44 @@
- /*
- * Re-initialise the CyberPro hardware
- */
--static int cyberpro_resume(struct pci_dev *dev)
-+static int cyberpro_pci_resume(struct pci_dev *dev)
- {
- struct cfb_info *cfb = pci_get_drvdata(dev);
-
- if (cfb) {
-- cyberpro_init_hw(cfb, 0);
--
-- /*
-- * Restore the old video mode and the palette.
-- * We also need to tell fbcon to redraw the console.
-- */
-- cfb->fb.var.activate = FB_ACTIVATE_NOW;
-- cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
-+ cyberpro_pci_enable_mmio(cfb);
-+ cyberpro_common_resume(cfb);
- }
-
- return 0;
- }
-
- static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
-+// Not yet
-+// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
-+// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
- { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
-- PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
-+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
- { 0, }
- };
-
-+MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
-+
-+#ifndef __devexit_p
-+#define __devexit_p(x) (x)
-+#endif
-+
- static struct pci_driver cyberpro_driver = {
-- name: "CyberPro",
-- probe: cyberpro_probe,
-- remove: __devexit_p(cyberpro_remove),
-- suspend: cyberpro_suspend,
-- resume: cyberpro_resume,
-- id_table: cyberpro_pci_table
-+ .name = "CyberPro",
-+ .probe = cyberpro_pci_probe,
-+ .remove = __devexit_p(cyberpro_pci_remove),
-+ .suspend = cyberpro_pci_suspend,
-+ .resume = cyberpro_pci_resume,
-+ .id_table = cyberpro_pci_table
- };
-
- /*
-@@ -1768,5 +1973,4 @@
-
- MODULE_AUTHOR("Russell King");
- MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
--MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
- MODULE_LICENSE("GPL");
---- linux-2.4.27/drivers/video/cyber2000fb.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/cyber2000fb.h
-@@ -36,24 +36,55 @@
- #define debug_printf(x...) do { } while (0)
- #endif
-
--#define PIXFORMAT_8BPP 0
--#define PIXFORMAT_16BPP 1
--#define PIXFORMAT_24BPP 2
--#define PIXFORMAT_32BPP 3
-+#define RAMDAC_RAMPWRDN 0x01
-+#define RAMDAC_DAC8BIT 0x02
-+#define RAMDAC_VREFEN 0x04
-+#define RAMDAC_BYPASS 0x10
-+#define RAMDAC_DACPWRDN 0x40
-
--#define VISUALID_256 1
--#define VISUALID_64K 2
--#define VISUALID_16M_32 3
--#define VISUALID_16M 4
--#define VISUALID_32K 6
-+#define EXT_CRT_VRTOFL 0x11
-+#define EXT_CRT_VRTOFL_LINECOMP10 0x10
-+#define EXT_CRT_VRTOFL_INTERLACE 0x20
-
--#define FUNC_CTL 0x3c
--#define FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
-+#define EXT_CRT_IRQ 0x12
-+#define EXT_CRT_IRQ_ENABLE 0x01
-+#define EXT_CRT_IRQ_ACT_HIGH 0x04
-
--#define BIU_BM_CONTROL 0x3e
--#define BIU_BM_CONTROL_ENABLE 0x01 /* enable bus-master */
--#define BIU_BM_CONTROL_BURST 0x02 /* enable burst */
--#define BIU_BM_CONTROL_BACK2BACK 0x04 /* enable back to back */
-+#define EXT_CRT_TEST 0x13
-+
-+#define EXT_SYNC_CTL 0x16
-+#define EXT_SYNC_CTL_HS_NORMAL 0x00
-+#define EXT_SYNC_CTL_HS_0 0x01
-+#define EXT_SYNC_CTL_HS_1 0x02
-+#define EXT_SYNC_CTL_HS_HSVS 0x03
-+#define EXT_SYNC_CTL_VS_NORMAL 0x00
-+#define EXT_SYNC_CTL_VS_0 0x04
-+#define EXT_SYNC_CTL_VS_1 0x08
-+#define EXT_SYNC_CTL_VS_COMP 0x0c
-+
-+#define EXT_BUS_CTL 0x30
-+#define EXT_BUS_CTL_LIN_1MB 0x00
-+#define EXT_BUS_CTL_LIN_2MB 0x01
-+#define EXT_BUS_CTL_LIN_4MB 0x02
-+#define EXT_BUS_CTL_ZEROWAIT 0x04
-+#define EXT_BUS_CTL_PCIBURST_WRITE 0x20
-+#define EXT_BUS_CTL_PCIBURST_READ 0x80 /* CyberPro 5000 only */
-+
-+#define EXT_SEG_WRITE_PTR 0x31
-+#define EXT_SEG_READ_PTR 0x32
-+#define EXT_BIU_MISC 0x33
-+#define EXT_BIU_MISC_LIN_ENABLE 0x01
-+#define EXT_BIU_MISC_COP_ENABLE 0x04
-+#define EXT_BIU_MISC_COP_BFC 0x08
-+
-+#define EXT_FUNC_CTL 0x3c
-+#define EXT_FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
-+
-+#define PCI_BM_CTL 0x3e
-+#define PCI_BM_CTL_ENABLE 0x01 /* enable bus-master */
-+#define PCI_BM_CTL_BURST 0x02 /* enable burst */
-+#define PCI_BM_CTL_BACK2BACK 0x04 /* enable back to back */
-+#define PCI_BM_CTL_DUMMY 0x08 /* insert dummy cycle */
-
- #define X_V2_VID_MEM_START 0x40
- #define X_V2_VID_SRC_WIDTH 0x43
-@@ -87,6 +118,19 @@
-
- #define K_CAP_X2_CTL1 0x49
-
-+#define CURS_H_START 0x50
-+#define CURS_H_PRESET 0x52
-+#define CURS_V_START 0x53
-+#define CURS_V_PRESET 0x55
-+#define CURS_CTL 0x56
-+
-+#define EXT_ATTRIB_CTL 0x57
-+#define EXT_ATTRIB_CTL_EXT 0x01
-+
-+#define EXT_OVERSCAN_RED 0x58
-+#define EXT_OVERSCAN_GREEN 0x59
-+#define EXT_OVERSCAN_BLUE 0x5a
-+
- #define CAP_X_START 0x60
- #define CAP_X_END 0x62
- #define CAP_Y_START 0x64
-@@ -96,46 +140,112 @@
- #define CAP_DDA_Y_INIT 0x6c
- #define CAP_DDA_Y_INC 0x6e
-
--#define MEM_CTL1 0x71
-+#define EXT_MEM_CTL0 0x70
-+#define EXT_MEM_CTL0_7CLK 0x01
-+#define EXT_MEM_CTL0_RAS_1 0x02
-+#define EXT_MEM_CTL0_RAS2CAS_1 0x04
-+#define EXT_MEM_CTL0_MULTCAS 0x08
-+#define EXT_MEM_CTL0_ASYM 0x10
-+#define EXT_MEM_CTL0_CAS1ON 0x20
-+#define EXT_MEM_CTL0_FIFOFLUSH 0x40
-+#define EXT_MEM_CTL0_SEQRESET 0x80
-
--#define MEM_CTL2 0x72
-+#define EXT_MEM_CTL1 0x71
-+#define EXT_MEM_CTL1_PAR 0x00
-+#define EXT_MEM_CTL1_SERPAR 0x01
-+#define EXT_MEM_CTL1_SER 0x03
-+#define EXT_MEM_CTL1_SYNC 0x04
-+#define EXT_MEM_CTL1_VRAM 0x08
-+#define EXT_MEM_CTL1_4K_REFRESH 0x10
-+#define EXT_MEM_CTL1_256Kx4 0x00
-+#define EXT_MEM_CTL1_512Kx8 0x40
-+#define EXT_MEM_CTL1_1Mx16 0x60
-+
-+#define EXT_MEM_CTL2 0x72
-+#define MEM_CTL2_SIZE_1MB 0x00
- #define MEM_CTL2_SIZE_2MB 0x01
- #define MEM_CTL2_SIZE_4MB 0x02
- #define MEM_CTL2_SIZE_MASK 0x03
- #define MEM_CTL2_64BIT 0x04
-
-+#define EXT_HIDDEN_CTL1 0x73
-+
- #define EXT_FIFO_CTL 0x74
-
-+#define EXT_SEQ_MISC 0x77
-+#define EXT_SEQ_MISC_8 0x01
-+#define EXT_SEQ_MISC_16_RGB565 0x02
-+#define EXT_SEQ_MISC_32 0x03
-+#define EXT_SEQ_MISC_24_RGB888 0x04
-+#define EXT_SEQ_MISC_16_RGB555 0x06
-+#define EXT_SEQ_MISC_8_RGB332 0x09
-+#define EXT_SEQ_MISC_16_RGB444 0x0a
-+
-+#define EXT_HIDDEN_CTL4 0x7a
-+
-+#define CURS_MEM_START 0x7e /* bits 23..12 */
-+
- #define CAP_PIP_X_START 0x80
- #define CAP_PIP_X_END 0x82
- #define CAP_PIP_Y_START 0x84
- #define CAP_PIP_Y_END 0x86
-
--#define CAP_NEW_CTL1 0x88
-+#define EXT_CAP_CTL1 0x88
-
--#define CAP_NEW_CTL2 0x89
-+#define EXT_CAP_CTL2 0x89
-+#define EXT_CAP_CTL2_ODDFRAMEIRQ 0x01
-+#define EXT_CAP_CTL2_ANYFRAMEIRQ 0x02
-
- #define BM_CTRL0 0x9c
- #define BM_CTRL1 0x9d
-
--#define CAP_MODE1 0xa4
--#define CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
--#define CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
--#define CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
--#define CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
--#define CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
--#define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
--#define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
-+#define EXT_CAP_MODE1 0xa4
-+#define EXT_CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
-+#define EXT_CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
-+#define EXT_CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
-+#define EXT_CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
-+#define EXT_CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
-+#define EXT_CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
-+#define EXT_CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
-
--#define DCLK_MULT 0xb0
--#define DCLK_DIV 0xb1
--#define DCLK_DIV_VFSEL 0x20
--#define MCLK_MULT 0xb2
--#define MCLK_DIV 0xb3
-+#define EXT_CAP_MODE2 0xa5
-+#define EXT_CAP_MODE2_CCIRINVOE 0x01
-+#define EXT_CAP_MODE2_CCIRINVVGT 0x02
-+#define EXT_CAP_MODE2_CCIRINVHGT 0x04
-+#define EXT_CAP_MODE2_CCIRINVDG 0x08
-+#define EXT_CAP_MODE2_DATEND 0x10
-+#define EXT_CAP_MODE2_CCIRDGH 0x20
-+#define EXT_CAP_MODE2_FIXSONY 0x40
-+#define EXT_CAP_MODE2_SYNCFREEZE 0x80
-
--#define CAP_MODE2 0xa5
-+#define EXT_TV_CTL 0xae
-
--#define Y_TV_CTL 0xae
-+#define EXT_DCLK_MULT 0xb0
-+#define EXT_DCLK_DIV 0xb1
-+#define EXT_DCLK_DIV_VFSEL 0x20
-+#define EXT_MCLK_MULT 0xb2
-+#define EXT_MCLK_DIV 0xb3
-+
-+#define EXT_LATCH1 0xb5
-+#define EXT_LATCH1_VAFC_EN 0x01 /* enable VAFC */
-+
-+#define EXT_FEATURE 0xb7
-+#define EXT_FEATURE_BUS_MASK 0x07 /* host bus mask */
-+#define EXT_FEATURE_BUS_PCI 0x00
-+#define EXT_FEATURE_BUS_VL_STD 0x04
-+#define EXT_FEATURE_BUS_VL_LINEAR 0x05
-+#define EXT_FEATURE_1682 0x20 /* IGS 1682 compatibility */
-+
-+#define EXT_LATCH2 0xb6
-+#define EXT_LATCH2_I2C_CLKEN 0x10
-+#define EXT_LATCH2_I2C_CLK 0x20
-+#define EXT_LATCH2_I2C_DATEN 0x40
-+#define EXT_LATCH2_I2C_DAT 0x80
-+
-+#define EXT_XT_CTL 0xbe
-+#define EXT_XT_CAP16 0x04
-+#define EXT_XT_LINEARFB 0x08
-+#define EXT_XT_PAL 0x10
-
- #define EXT_MEM_START 0xc0 /* ext start address 21 bits */
- #define HOR_PHASE_SHIFT 0xc2 /* high 3 bits */
-@@ -160,25 +270,37 @@
- #define EXT_VID_FMT_RGB565 0x02
- #define EXT_VID_FMT_RGB888_24 0x03
- #define EXT_VID_FMT_RGB888_32 0x04
-+#define EXT_VID_FMT_RGB8 0x05
-+#define EXT_VID_FMT_RGB4444 0x06
-+#define EXT_VID_FMT_RGB8T 0x07
- #define EXT_VID_FMT_DUP_PIX_ZOON 0x08 /* duplicate pixel zoom */
- #define EXT_VID_FMT_MOD_3RD_PIX 0x20 /* modify 3rd duplicated pixel */
- #define EXT_VID_FMT_DBL_H_PIX 0x40 /* double horiz pixels */
--#define EXT_VID_FMT_UV128 0x80 /* UV data offset by 128 */
-+#define EXT_VID_FMT_YUV128 0x80 /* YUV data offset by 128 */
-
- #define EXT_VID_DISP_CTL1 0xdc
- #define EXT_VID_DISP_CTL1_INTRAM 0x01 /* video pixels go to internal RAM */
- #define EXT_VID_DISP_CTL1_IGNORE_CCOMP 0x02 /* ignore colour compare registers */
- #define EXT_VID_DISP_CTL1_NOCLIP 0x04 /* do not clip to 16235,16240 */
- #define EXT_VID_DISP_CTL1_UV_AVG 0x08 /* U/V data is averaged */
--#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 */
--#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* vertical interpolation off */
-+#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 (if YUV128 set) */
-+#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* disable vertical interpolation */
- #define EXT_VID_DISP_CTL1_FULL_WIN 0x40 /* video out window full */
- #define EXT_VID_DISP_CTL1_ENABLE_WINDOW 0x80 /* enable video window */
-
- #define EXT_VID_FIFO_CTL1 0xdd
-+#define EXT_VID_FIFO_CTL1_OE_HIGH 0x02
-+#define EXT_VID_FIFO_CTL1_INTERLEAVE 0x04 /* enable interleaved memory read */
-+
-+#define EXT_ROM_UCB4GH 0xe5
-+#define EXT_ROM_UCB4GH_FREEZE 0x02 /* capture frozen */
-+#define EXT_ROM_UCB4GH_ODDFRAME 0x04 /* 1 = odd frame captured */
-+#define EXT_ROM_UCB4GH_1HL 0x08 /* first horizonal line after VGT falling edge */
-+#define EXT_ROM_UCB4GH_ODD 0x10 /* odd frame indicator */
-+#define EXT_ROM_UCB4GH_INTSTAT 0x20 /* video interrupt */
-
- #define VFAC_CTL1 0xe8
--#define VFAC_CTL1_CAPTURE 0x01 /* capture enable */
-+#define VFAC_CTL1_CAPTURE 0x01 /* capture enable (only when VSYNC high)*/
- #define VFAC_CTL1_VFAC_ENABLE 0x02 /* vfac enable */
- #define VFAC_CTL1_FREEZE_CAPTURE 0x04 /* freeze capture */
- #define VFAC_CTL1_FREEZE_CAPTURE_SYNC 0x08 /* sync freeze capture */
-@@ -197,6 +319,13 @@
- #define VFAC_CTL2_INVERT_OVSYNC 0x80 /* invert other vsync input */
-
- #define VFAC_CTL3 0xea
-+#define VFAC_CTL3_CAP_LARGE_FIFO 0x01 /* large capture fifo */
-+#define VFAC_CTL3_CAP_INTERLACE 0x02 /* capture odd and even fields */
-+#define VFAC_CTL3_CAP_HOLD_4NS 0x00 /* hold capture data for 4ns */
-+#define VFAC_CTL3_CAP_HOLD_2NS 0x04 /* hold capture data for 2ns */
-+#define VFAC_CTL3_CAP_HOLD_6NS 0x08 /* hold capture data for 6ns */
-+#define VFAC_CTL3_CAP_HOLD_0NS 0x0c /* hold capture data for 0ns */
-+#define VFAC_CTL3_CHROMAKEY 0x20 /* capture data will be chromakeyed */
- #define VFAC_CTL3_CAP_IRQ 0x40 /* enable capture interrupt */
-
- #define CAP_MEM_START 0xeb /* 18 bits */
-@@ -235,26 +364,98 @@
- #define BM_COUNT 0xbc090 /* read-only */
-
- /*
-- * Graphics Co-processor
-+ * TV registers
- */
--#define CO_CMD_L_PATTERN_FGCOL 0x8000
--#define CO_CMD_L_INC_LEFT 0x0004
--#define CO_CMD_L_INC_UP 0x0002
--
--#define CO_CMD_H_SRC_PIXMAP 0x2000
--#define CO_CMD_H_BLITTER 0x0800
-+#define TV_VBLANK_EVEN_START 0xbe43c
-+#define TV_VBLANK_EVEN_END 0xbe440
-+#define TV_VBLANK_ODD_START 0xbe444
-+#define TV_VBLANK_ODD_END 0xbe448
-+#define TV_SYNC_YGAIN 0xbe44c
-+#define TV_UV_GAIN 0xbe450
-+#define TV_PED_UVDET 0xbe454
-+#define TV_UV_BURST_AMP 0xbe458
-+#define TV_HSYNC_START 0xbe45c
-+#define TV_HSYNC_END 0xbe460
-+#define TV_Y_DELAY1 0xbe464
-+#define TV_Y_DELAY2 0xbe468
-+#define TV_UV_DELAY1 0xbe46c
-+#define TV_BURST_START 0xbe470
-+#define TV_BURST_END 0xbe474
-+#define TV_HBLANK_START 0xbe478
-+#define TV_HBLANK_END 0xbe47c
-+#define TV_PED_EVEN_START 0xbe480
-+#define TV_PED_EVEN_END 0xbe484
-+#define TV_PED_ODD_START 0xbe488
-+#define TV_PED_ODD_END 0xbe48c
-+#define TV_VSYNC_EVEN_START 0xbe490
-+#define TV_VSYNC_EVEN_END 0xbe494
-+#define TV_VSYNC_ODD_START 0xbe498
-+#define TV_VSYNC_ODD_END 0xbe49c
-+#define TV_SCFL 0xbe4a0
-+#define TV_SCFH 0xbe4a4
-+#define TV_SCP 0xbe4a8
-+#define TV_DELAYBYPASS 0xbe4b4
-+#define TV_EQL_END 0xbe4bc
-+#define TV_SERR_START 0xbe4c0
-+#define TV_SERR_END 0xbe4c4
-+#define TV_CTL 0xbe4dc /* reflects a previous register- MVFCLR, MVPCLR etc P241*/
-+#define TV_VSYNC_VGA_HS 0xbe4e8
-+#define TV_FLICK_XMIN 0xbe514
-+#define TV_FLICK_XMAX 0xbe518
-+#define TV_FLICK_YMIN 0xbe51c
-+#define TV_FLICK_YMAX 0xbe520
-
-+/*
-+ * Graphics Co-processor
-+ */
- #define CO_REG_CONTROL 0xbf011
-+#define CO_CTRL_BUSY 0x80
-+#define CO_CTRL_CMDFULL 0x04
-+#define CO_CTRL_FIFOEMPTY 0x02
-+#define CO_CTRL_READY 0x01
-+
- #define CO_REG_SRC_WIDTH 0xbf018
--#define CO_REG_PIX_FORMAT 0xbf01c
--#define CO_REG_FORE_MIX 0xbf048
--#define CO_REG_FOREGROUND 0xbf058
--#define CO_REG_WIDTH 0xbf060
--#define CO_REG_HEIGHT 0xbf062
-+#define CO_REG_PIXFMT 0xbf01c
-+#define CO_PIXFMT_32BPP 0x03
-+#define CO_PIXFMT_24BPP 0x02
-+#define CO_PIXFMT_16BPP 0x01
-+#define CO_PIXFMT_8BPP 0x00
-+
-+#define CO_REG_FGMIX 0xbf048
-+#define CO_FG_MIX_ZERO 0x00
-+#define CO_FG_MIX_SRC_AND_DST 0x01
-+#define CO_FG_MIX_SRC_AND_NDST 0x02
-+#define CO_FG_MIX_SRC 0x03
-+#define CO_FG_MIX_NSRC_AND_DST 0x04
-+#define CO_FG_MIX_DST 0x05
-+#define CO_FG_MIX_SRC_XOR_DST 0x06
-+#define CO_FG_MIX_SRC_OR_DST 0x07
-+#define CO_FG_MIX_NSRC_AND_NDST 0x08
-+#define CO_FG_MIX_SRC_XOR_NDST 0x09
-+#define CO_FG_MIX_NDST 0x0a
-+#define CO_FG_MIX_SRC_OR_NDST 0x0b
-+#define CO_FG_MIX_NSRC 0x0c
-+#define CO_FG_MIX_NSRC_OR_DST 0x0d
-+#define CO_FG_MIX_NSRC_OR_NDST 0x0e
-+#define CO_FG_MIX_ONES 0x0f
-+
-+#define CO_REG_FGCOLOUR 0xbf058
-+#define CO_REG_BGCOLOUR 0xbf05c
-+#define CO_REG_PIXWIDTH 0xbf060
-+#define CO_REG_PIXHEIGHT 0xbf062
- #define CO_REG_X_PHASE 0xbf078
- #define CO_REG_CMD_L 0xbf07c
-+#define CO_CMD_L_PATTERN_FGCOL 0x8000
-+#define CO_CMD_L_INC_LEFT 0x0004
-+#define CO_CMD_L_INC_UP 0x0002
-+
- #define CO_REG_CMD_H 0xbf07e
--#define CO_REG_SRC_PTR 0xbf170
-+#define CO_CMD_H_BGSRCMAP 0x8000 /* otherwise bg colour */
-+#define CO_CMD_H_FGSRCMAP 0x2000 /* otherwise fg colour */
-+#define CO_CMD_H_BLITTER 0x0800
-+
-+#define CO_REG_SRC1_PTR 0xbf170
-+#define CO_REG_SRC2_PTR 0xbf174
- #define CO_REG_DEST_PTR 0xbf178
- #define CO_REG_DEST_WIDTH 0xbf218
-
-@@ -269,6 +470,7 @@
- char *fb;
- char dev_name[32];
- unsigned int fb_size;
-+ unsigned int chip_id;
-
- /*
- * The following is a pointer to be passed into the
-@@ -288,10 +490,19 @@
- void (*disable_extregs)(struct cfb_info *);
- };
-
-+#define ID_IGA_1682 0
-+#define ID_CYBERPRO_2000 1
-+#define ID_CYBERPRO_2010 2
-+#define ID_CYBERPRO_5000 3
-+
-+struct fb_var_screeninfo;
-+
- /*
- * Note! Writing to the Cyber20x0 registers from an interrupt
- * routine is definitely a bad idea atm.
- */
- int cyber2000fb_attach(struct cyberpro_info *info, int idx);
- void cyber2000fb_detach(int idx);
--
-+void cyber2000fb_enable_extregs(struct cfb_info *cfb);
-+void cyber2000fb_disable_extregs(struct cfb_info *cfb);
-+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
---- /dev/null
-+++ linux-2.4.27/drivers/video/dbmx1fb.c
-@@ -0,0 +1,2002 @@
-+/******************************************************************************
-+ Copyright (C) 2002 Motorola GSG-China
-+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License
-+ as published by the Free Software Foundation; either version 2
-+ of the License, or (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+*******************************************************************************/
-+/*****************************************************************************
-+ * File Name: dbmx1fb.c
-+ *
-+ * Progammers: Chen Ning, Zhang Juan
-+ *
-+ * Date of Creations: 10 DEC,2001
-+ *
-+ * Synopsis:
-+ *
-+ * Descirption: DB-MX1 LCD controller Linux frame buffer driver
-+ * This file is subject to the terms and conditions of the
-+ * GNU General Public License. See the file COPYING in the main
-+ * directory of this archive for more details.
-+ *
-+ * Modification History:
-+ * 10 DEC, 2001, initialization version, frame work for frame buffer driver
-+ *
-+*******************************************************************************/
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include <linux/ctype.h>
-+#include <linux/mm.h>
-+#include <linux/tty.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/fb.h>
-+#include <linux/delay.h>
-+#include <linux/wrapper.h>
-+#include <linux/selection.h>
-+#include <linux/console.h>
-+#include <linux/kd.h>
-+#include <linux/vt_kern.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/irq.h>
-+#include <asm/mach-types.h>
-+#include <asm/uaccess.h>
-+#include <asm/proc/pgtable.h>
-+
-+#include <video/fbcon.h>
-+#include <video/fbcon-mfb.h>
-+#include <video/fbcon-cfb4.h>
-+#include <video/fbcon-cfb8.h>
-+#include <video/fbcon-cfb16.h>
-+
-+#include "asm/arch/hardware.h"
-+#include "asm/arch/platform.h"
-+#include "asm/arch/memory.h"
-+
-+#include "dbmx1fb.h"
-+
-+#undef SUP_TTY0
-+
-+#define LCD_PM
-+#ifdef LCD_PM
-+#include <linux/pm.h>
-+struct pm_dev *pm;
-+#endif
-+
-+// PLAM - make sure fbmem.c also has this defined for full screen frame
-+// buffer support in SDRAM
-+#define FULL_SCREEN
-+
-+#undef HARDWARE_CURSOR
-+// #undef HARDWARE_CURSOR
-+#undef DEBUG
-+
-+
-+/********************************************************************************/
-+#ifdef DEBUG
-+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
-+#define FUNC_START DPRINTK(KERN_ERR"start\n");
-+#define FUNC_END DPRINTK(KERN_ERR"end\n");
-+#else
-+# define DPRINTK(fmt, args...)
-+#define FUNC_START
-+#define FUNC_END
-+#endif
-+
-+#define _IO_ADDRESS(r) ((r)+0xf0000000)
-+unsigned int READREG(unsigned int r)
-+{
-+ volatile unsigned int * reg;
-+ reg = (volatile unsigned int*) _IO_ADDRESS(r);
-+ return *reg;
-+}
-+void WRITEREG(unsigned int r, unsigned int val)
-+{
-+ volatile unsigned int *reg;
-+ reg = (volatile unsigned int*) _IO_ADDRESS(r);
-+ *reg = val;
-+ return;
-+}
-+
-+#define FONT_DATA ((unsigned char *)font->data)
-+struct fbcon_font_desc *font;
-+
-+/* Local LCD controller parameters */
-+struct dbmx1fb_par{
-+ u_char *screen_start_address; /* Screen Start Address */
-+ u_char *v_screen_start_address;/* Virtul Screen Start Address */
-+ unsigned long screen_memory_size; /* screen memory size */
-+ unsigned int palette_size;
-+ unsigned int max_xres;
-+ unsigned int max_yres;
-+ unsigned int xres;
-+ unsigned int yres;
-+ unsigned int xres_virtual;
-+ unsigned int yres_virtual;
-+ unsigned int max_bpp;
-+ unsigned int bits_per_pixel;
-+ unsigned int currcon;
-+ unsigned int visual;
-+ unsigned int TFT :1;
-+ unsigned int color :1 ;
-+ unsigned int sharp :1 ;
-+
-+ unsigned short cfb16[16];
-+};
-+
-+#ifdef HARDWARE_CURSOR
-+/* hardware cursor parameters */
-+struct dbmx1fb_cursor{
-+ // int enable;
-+ int startx;
-+ int starty;
-+ int blinkenable;
-+ int blink_rate;
-+ int width;
-+ int height;
-+ int color[3];
-+ int state;
-+};
-+
-+/* Frame buffer of LCD information */
-+struct dbmx1fb_info{
-+ struct display_switch dispsw;
-+ struct dbmx1fb_cursor cursor;
-+};
-+#endif // HARDWARE_CURSOR
-+
-+static u_char* p_framebuffer_memory_address;
-+static u_char* v_framebuffer_memory_address;
-+
-+/* Fake monspecs to fill in fbinfo structure */
-+static struct fb_monspecs monspecs __initdata = {
-+ 30000, 70000, 50, 65, 0 /* Generic */
-+};
-+
-+/* color map initial */
-+static unsigned short __attribute__((unused)) color4map[16] = {
-+ 0x0000, 0x000f, 0x00f0, 0x0f2a, 0x0f00, 0x0f0f, 0x0f88, 0x0ccc,
-+ 0x0888, 0x00ff, 0x00f8, 0x0f44, 0x0fa6, 0x0f22, 0x0ff0, 0x0fff
-+};
-+
-+static unsigned short gray4map[16] = {
-+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
-+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f
-+};
-+
-+static struct display global_disp; /* Initial (default) Display Settings */
-+static struct fb_info fb_info;
-+static struct fb_var_screeninfo init_var = {};
-+static struct dbmx1fb_par current_par={ };
-+
-+/* Frame buffer device API */
-+static int dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_get_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_set_var(struct fb_var_screeninfo *var, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info);
-+static int dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info);
-+
-+/* Interface to the low level driver */
-+static int dbmx1fb_switch(int con, struct fb_info *info);
-+static void dbmx1fb_blank(int blank, struct fb_info *info);
-+static int dbmx1fb_updatevar(int con, struct fb_info *info);
-+
-+/* Internal routines */
-+static int _reserve_fb_memory(void);
-+static void _install_cmap(int con, struct fb_info *info);
-+static void _enable_lcd_controller(void);
-+static void _disable_lcd_controller(void);
-+static int _encode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par);
-+static int _decode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par);
-+
-+/* initialization routines */
-+static void __init _init_lcd_system(void);
-+static int __init _init_lcd(void);
-+static void __init _init_fbinfo(void);
-+static int __init _reserve_fb_memory(void);
-+
-+/* frame buffer ops */
-+static struct fb_ops dbmx1fb_ops = {
-+ owner: THIS_MODULE,
-+ fb_get_fix: dbmx1fb_get_fix,
-+ fb_get_var: dbmx1fb_get_var,
-+ fb_set_var: dbmx1fb_set_var,
-+ fb_get_cmap: dbmx1fb_get_cmap,
-+ fb_set_cmap: dbmx1fb_set_cmap,
-+};
-+
-+#ifdef HARDWARE_CURSOR
-+/* Hardware Cursor */
-+static void dbmx1fb_cursor(struct display *p, int mode, int x, int y);
-+static int dbmx1fb_set_font(struct display *d, int width, int height);
-+static UINT8 cursor_color_map[] = {0xf8};
-+static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state);
-+static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb);
-+static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink);
-+
-+struct display_switch dbmx1fb_cfb4 = {
-+ setup: fbcon_cfb4_setup,
-+ bmove: fbcon_cfb4_bmove,
-+ clear: fbcon_cfb4_clear,
-+ putc: fbcon_cfb4_putc,
-+ putcs: fbcon_cfb4_putcs,
-+ revc: fbcon_cfb4_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+
-+struct display_switch dbmx1fb_cfb8 = {
-+ setup: fbcon_cfb8_setup,
-+ bmove: fbcon_cfb8_bmove,
-+ clear: fbcon_cfb8_clear,
-+ putc: fbcon_cfb8_putc,
-+ putcs: fbcon_cfb8_putcs,
-+ revc: fbcon_cfb8_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+
-+struct display_switch dbmx1fb_cfb16 = {
-+ setup: fbcon_cfb16_setup,
-+ bmove: fbcon_cfb16_bmove,
-+ clear: fbcon_cfb16_clear,
-+ putc: fbcon_cfb16_putc,
-+ putcs: fbcon_cfb16_putcs,
-+ revc: fbcon_cfb16_revc,
-+ cursor: dbmx1fb_cursor,
-+ set_font: dbmx1fb_set_font,
-+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(16)
-+};
-+#endif // HARDWARE_CURSOR
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_getcolreg()
-+ *
-+ * Input: regno : Color register ID
-+ * red : Color map red[]
-+ * green : Color map green[]
-+ * blue : Color map blue[]
-+ * transparent : Flag
-+ * info : Fb_info database
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Transfer to fb_xxx_cmap handlers as parameters to
-+ * control color registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+#define RED 0xf00
-+#define GREEN 0xf0
-+#define BLUE 0x0f
-+static int dbmx1fb_getcolreg(u_int regno, u_int *red, u_int *green,
-+ u_int *blue, u_int *trans, struct fb_info *info)
-+{
-+ unsigned int val;
-+
-+ FUNC_START;
-+
-+ if(regno >= current_par.palette_size)
-+ return 1;
-+
-+ val = READREG(DBMX1_LCD_MAPRAM+regno);
-+
-+ if((current_par.bits_per_pixel == 4)&&(!current_par.color))
-+ {
-+ *red = *green = *blue = (val & BLUE) << 4;//TODO:
-+ *trans = 0;
-+ }
-+ else
-+ {
-+ *red = (val & RED) << 4;
-+ *green = (val & GREEN) << 8;
-+ *blue = (val & BLUE) << 12;
-+ *trans = 0;
-+ }
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_setcolreg()
-+ *
-+ * Input: regno : Color register ID
-+ * red : Color map red[]
-+ * green : Color map green[]
-+ * blue : Color map blue[]
-+ * transparent : Flag
-+ * info : Fb_info database
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Transfer to fb_xxx_cmap handlers as parameters to
-+ * control color registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+ *****************************************************************************/
-+static int
-+dbmx1fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-+ u_int trans, struct fb_info *info)
-+{
-+ unsigned int val=0;
-+ FUNC_START
-+ if(regno >= current_par.palette_size)
-+ return 1;
-+
-+ if((current_par.bits_per_pixel == 4)&&(!current_par.color))
-+ val = (blue & 0x00f) << 12;//TODO:
-+ else
-+ {
-+ val = (blue >> 12 ) & BLUE;
-+ val |= (green >> 8) & GREEN;
-+ val |= (red >> 4) & RED;
-+ }
-+
-+ if (regno < 16) {
-+ current_par.cfb16[regno] =
-+ regno | regno << 5 | regno << 10;
-+}
-+
-+ WRITEREG(DBMX1_LCD_MAPRAM+regno, val);
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_cmap()
-+ *
-+ * Input: cmap : Ouput data pointer
-+ * kspc : Kernel space flag
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Data is copied from hardware or local or system DISPAY,
-+ * and copied to cmap.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-+ struct fb_info *info)
-+{
-+ int err = 0;
-+
-+ FUNC_START;
-+ DPRINTK("current_par.visual=%d\n", current_par.visual);
-+ if (con == current_par.currcon)
-+ err = fb_get_cmap(cmap, kspc, dbmx1fb_getcolreg, info);
-+ else if (fb_display[con].cmap.len)
-+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-+ else
-+ fb_copy_cmap(fb_default_cmap(current_par.palette_size),
-+ cmap, kspc ? 0 : 2);
-+ FUNC_END;
-+ return err;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_cmap()
-+ *
-+ * Input: cmap : Ouput data pointer
-+ * kspc : Kernel space flag
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Description: Copy data from cmap and copy to DISPLAY. If DISPLAy has no cmap,
-+ * allocate memory for it. If DISPLAY is current console and visible,
-+ * then hardware color map shall be set.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-+{
-+ int err = 0;
-+
-+ FUNC_START;
-+ DPRINTK("current_par.visual=%d\n", current_par.visual);
-+ if (!fb_display[con].cmap.len)
-+ err = fb_alloc_cmap(&fb_display[con].cmap,
-+ current_par.palette_size, 0);
-+
-+ if (!err) {
-+ if (con == current_par.currcon)
-+ err = fb_set_cmap(cmap, kspc, dbmx1fb_setcolreg,
-+ info);
-+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-+ }
-+ FUNC_END;
-+ return err;
-+}
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_var()
-+ *
-+ * Input: var : Iuput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: _encode_var()
-+ *
-+ * Description: Get color map from current, or global display[console]
-+ * used by ioctl
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ if (con == -1) {
-+ _encode_var(var, &current_par);
-+ } else
-+ *var = fb_display[con].var;
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_updatevar()
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Fill in display switch with LCD information,
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int dbmx1fb_updatevar(int con, struct fb_info *info)
-+{
-+ DPRINTK("entered\n");
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_dispsw()
-+ *
-+ * Input: display : Iuput data pointer
-+ * dbmx1fb_info : Frame buffer of LCD information
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Fill in display switch with LCD information,
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void dbmx1fb_set_dispsw(struct display *disp
-+#ifdef HARDWARE_CURSOR
-+ ,struct dbmx1fb_info *info
-+#endif
-+ )
-+{
-+ FUNC_START;
-+ switch (disp->var.bits_per_pixel) {
-+#ifdef HARDWARE_CURSOR
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ info->dispsw = dbmx1fb_cfb4;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ info->dispsw = dbmx1fb_cfb8;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ info->dispsw = dbmx1fb_cfb16;
-+ disp->dispsw = &info->dispsw;
-+ disp->dispsw_data = current_par.cfb16;
-+ break;
-+#endif
-+#else //!HARDWARE_CURSOR
-+ /* first step disable the hardware cursor */
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ disp->dispsw = &fbcon_cfb4;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ fb_info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
-+ disp->dispsw = &fbcon_cfb8;
-+ disp->dispsw_data = NULL;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12:
-+ case 16:
-+ fb_info.fix.visual = FB_VISUAL_DIRECTCOLOR;
-+ disp->dispsw = &fbcon_cfb16;
-+ disp->dispsw_data = current_par.cfb16;
-+ break;
-+#endif
-+
-+#endif // HARDWARE_CURSOR
-+ default:
-+ disp->dispsw = &fbcon_dummy;
-+ disp->dispsw_data = NULL;
-+ }
-+#ifdef HARDWARE_CURSOR
-+ if (&info->cursor)
-+ {
-+ info->dispsw.cursor = dbmx1fb_cursor;
-+ info->dispsw.set_font = dbmx1fb_set_font;
-+ }
-+#endif // HARDWARE_CURSOR
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_var()
-+ *
-+ * Input: var : Iuput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: dbmx1fb_decode_var()
-+ * dbmx1fb_encode_var()
-+ * dbmx1fb_set_dispsw()
-+ *
-+ * Description: set current_par by var, also set display data, specially the console
-+ * related fileops, then enable the lcd controller, and set cmap to
-+ * hardware.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-+{
-+ struct display *display;
-+ int err, chgvar = 0;
-+ struct dbmx1fb_par par;
-+
-+ FUNC_START;
-+ if (con >= 0)
-+ display = &fb_display[con]; /* Display settings for console */
-+ else
-+ display = &global_disp; /* Default display settings */
-+
-+ /* Decode var contents into a par structure, adjusting any */
-+ /* out of range values. */
-+ if ((err = _decode_var(var, &par))){
-+ DPRINTK("decode var error!");
-+ return err;
-+ }
-+
-+ // Store adjusted par values into var structure
-+ _encode_var(var, &par);
-+
-+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
-+ return 0;
-+
-+ else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
-+ ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
-+ return -EINVAL;
-+
-+ if (con >= 0) {
-+ if ((display->var.xres != var->xres) ||
-+ (display->var.yres != var->yres) ||
-+ (display->var.xres_virtual != var->xres_virtual) ||
-+ (display->var.yres_virtual != var->yres_virtual) ||
-+ (display->var.sync != var->sync) ||
-+ (display->var.bits_per_pixel != var->bits_per_pixel) ||
-+ (memcmp(&display->var.red, &var->red, sizeof(var->red))) ||
-+ (memcmp(&display->var.green, &var->green, sizeof(var->green)
-+ )) ||
-+ (memcmp(&display->var.blue, &var->blue, sizeof(var->blue))))
-+ chgvar = 1;
-+ }
-+
-+ display->var = *var;
-+ display->screen_base = par.v_screen_start_address;
-+ display->visual = par.visual;
-+ display->type = FB_TYPE_PACKED_PIXELS;
-+ display->type_aux = 0;
-+ display->ypanstep = 0;
-+ display->ywrapstep = 0;
-+ display->line_length =
-+ display->next_line = (var->xres * 16) / 8;
-+
-+ display->can_soft_blank = 1;
-+ display->inverse = 0;
-+
-+ dbmx1fb_set_dispsw(display
-+#ifdef HARDWARE_CURSOR
-+ , (struct dbmx1fb_info *)info
-+#endif // HARDWARE_CURSOR
-+ );
-+
-+ /* If the console has changed and the console has defined */
-+ /* a changevar function, call that function. */
-+ if (chgvar && info && info->changevar)
-+ info->changevar(con); // TODO:
-+
-+ /* If the current console is selected and it's not truecolor,
-+ * update the palette
-+ */
-+ if ((con == current_par.currcon) &&
-+ (current_par.visual != FB_VISUAL_TRUECOLOR)) {
-+ struct fb_cmap *cmap;
-+
-+ current_par = par; // TODO ?
-+ if (display->cmap.len)
-+ cmap = &display->cmap;
-+ else
-+ cmap = fb_default_cmap(current_par.palette_size);
-+
-+ fb_set_cmap(cmap, 1, dbmx1fb_setcolreg, info);
-+ }
-+
-+ /* If the current console is selected, activate the new var. */
-+ if (con == current_par.currcon){
-+ init_var = *var; // TODO:gcc support structure copy?
-+ _enable_lcd_controller();
-+ }
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_get_fix()
-+ *
-+ * Input: fix : Ouput data pointer
-+ * con : Console ID
-+ * info : Frame buffer information
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: get fix from display data, current_par data
-+ * used by ioctl
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int
-+dbmx1fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-+{
-+ struct display *display;
-+
-+ FUNC_START;
-+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-+ strcpy(fix->id, DBMX1_NAME);
-+
-+ if (con >= 0)
-+ {
-+ DPRINTK("Using console specific display for con=%d\n",con);
-+ display = &fb_display[con]; /* Display settings for console */
-+ }
-+ else
-+ display = &global_disp; /* Default display settings */
-+
-+ fix->smem_start = (unsigned long)current_par.screen_start_address;
-+ fix->smem_len = current_par.screen_memory_size;
-+//printk("dbmx1fb_get_fix, pointer fix: 0x%08x, smem_len: 0x%08x\n",fix,fix->smem_len);
-+ fix->type = display->type;
-+ fix->type_aux = display->type_aux;
-+ fix->xpanstep = 0;
-+ fix->ypanstep = display->ypanstep;
-+ fix->ywrapstep = display->ywrapstep;
-+ fix->visual = display->visual;
-+ fix->line_length = display->line_length;
-+ fix->accel = FB_ACCEL_NONE;
-+
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_inter_handler()
-+ *
-+ * Input:
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Interrupt handler
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void dbmx1fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ unsigned int intsr;
-+ FUNC_START;
-+ intsr = READREG(DBMX1_LCD_INTSR); // read to clear status
-+ printk(KERN_ERR"lcd interrupt!\n");
-+ FUNC_END;
-+ // handle
-+}
-+
-+#ifdef LCD_PM
-+#define PM_OPT " [pm]"
-+#define LCD_PMST_RESUME 0
-+#define LCD_PMST_SUSPEND 1
-+static unsigned int lcd_pm_status = LCD_PMST_RESUME;
-+
-+void lcd_pm_resume(void)
-+{
-+ if(lcd_pm_status == LCD_PMST_RESUME)
-+ return;
-+ WRITEREG(0x21c21c, 0x10000); // light on
-+ WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00a9008a);
-+ lcd_pm_status = LCD_PMST_RESUME;
-+// printk(KERN_ERR"lcd resumed\n");
-+}
-+
-+void lcd_pm_suspend(void)
-+{
-+ unsigned val;
-+ if(lcd_pm_status == LCD_PMST_SUSPEND)
-+ return;
-+ val = READREG(0x20502c);
-+ val |= 0x8000;
-+ WRITEREG(0x20502c, val);
-+ //To produce enough dealy time before trun off the LCDC.
-+ for(val=0;val<=600000;val++);
-+ val = READREG(0x21c21c);
-+ val &= ~0x10000;
-+ WRITEREG(0x21c21c, val); // light off
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ lcd_pm_status = LCD_PMST_SUSPEND;
-+// printk(KERN_ERR"lcd suspended\n");
-+}
-+
-+int lcd_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
-+{
-+ switch(rqst){
-+ case PM_RESUME:
-+ lcd_pm_resume();
-+ break;
-+ case PM_SUSPEND:
-+ lcd_pm_suspend();
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+#endif // LCD_PM
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_init()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: _init_fbinfo()
-+ * disable_irq()
-+ * enable_irq()
-+ * _init_lcd()
-+ * dbmx1fb_init_cursor()
-+ *
-+ * Description: initialization module, all of init routine's entry point
-+ * initialize fb_info, init_var, current_par
-+ * and setup interrupt, memory, lcd controller
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+int __init dbmx1fb_init(void)
-+{
-+ int ret;
-+#ifdef HARDWARE_CURSOR
-+ struct dbmx1fb_info *info;
-+#endif // HARDWARE_CURSOR
-+
-+ _init_lcd_system();
-+
-+ _init_fbinfo();
-+
-+ if ((ret = _reserve_fb_memory()) != 0){
-+ printk(KERN_ERR"failed for reserved DBMX frame buffer memory\n");
-+ return ret;
-+ }
-+
-+#if 0
-+ if (request_irq(IRQ_LCD,
-+ dbmx1fb_inter_handler,
-+ SA_INTERRUPT,
-+ DEV_NAME,
-+ NULL) != 0) {
-+ printk(KERN_ERR "dbmx1fb: failed in request_irq\n");
-+ return -EBUSY;
-+ }
-+
-+ disable_irq(IRQ_LCD);
-+#endif
-+ if (dbmx1fb_set_var(&init_var, -1, &fb_info))
-+ ; //current_par.allow_modeset = 0;
-+
-+ _init_lcd();
-+ _enable_lcd_controller();
-+
-+#ifdef HARDWARE_CURSOR
-+ info = kmalloc(sizeof(struct dbmx1fb_info), GFP_KERNEL);
-+ if(info == NULL){
-+ printk(KERN_ERR"can not kmalloc dbmx1fb_info memory\n");
-+ return -1;
-+ }
-+
-+ memset(info,0,sizeof(struct dbmx1fb_info));
-+
-+ info->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-+ info->cursor.blinkenable = 0;
-+ info->cursor.state = LCD_CURSOR_OFF;
-+ WRITEREG(DBMX1_LCD_LCXYP,0x90010001);
-+ WRITEREG(DBMX1_LCD_CURBLKCR,0x1F1F0000);
-+ WRITEREG(DBMX1_LCD_LCHCC,0x0000F800);
-+
-+ DPRINTK(KERN_ERR"LCXYP = %x\n",READREG(DBMX1_LCD_LCXYP));
-+ DPRINTK(KERN_ERR"CURBLICR = %x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ DPRINTK(KERN_ERR"LCHCC = %x\n",READREG(DBMX1_LCD_LCHCC));
-+
-+ //dbmx1fb_set_cursor(info);
-+ //info->cursor = dbmx1fb_init_cursor(info);
-+#endif // HARDWARE_CURSOR
-+
-+ register_framebuffer(&fb_info);
-+
-+#ifdef LCD_PM
-+ pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, lcd_pm_handler);
-+ printk("register LCD power management successfully.\n");
-+#endif
-+#if 0
-+ enable_irq(IRQ_LCD); // TODO:
-+#endif
-+ /* This driver cannot be unloaded at the moment */
-+ MOD_INC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_setup()
-+ *
-+ * Input: info : VOID
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: basically, this routine used to parse command line parameters, which
-+ * is initialization parameters for lcd controller, such as freq, xres,
-+ * yres, and so on
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+int __init dbmx1fb_setup(char *options)
-+{
-+ FUNC_START;
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_fbinfo()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: while 16bpp is used to store a 12 bits pixels packet, but
-+ * it is not a really 16bpp system. maybe in-compatiable with
-+ * other system or GUI.There are some field in var which specify
-+ * the red/green/blue offset in a 16bit word, just little endian is
-+ * concerned
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void __init _init_fbinfo(void)
-+{
-+// Thomas Wong add this for debugging
-+// *((unsigned char *)0xF5000008) = '&';
-+
-+ FUNC_START;
-+ strcpy(fb_info.modename, DBMX1_NAME);
-+ strcpy(fb_info.fontname, "Acorn8x8");
-+
-+ fb_info.node = -1;
-+ fb_info.flags = FBINFO_FLAG_DEFAULT; // Low-level driver is not a module
-+ fb_info.fbops = &dbmx1fb_ops;
-+ fb_info.monspecs = monspecs;
-+ fb_info.disp = &global_disp;
-+ fb_info.changevar = NULL;
-+ fb_info.switch_con = dbmx1fb_switch;
-+ fb_info.updatevar = dbmx1fb_updatevar;
-+ fb_info.blank = dbmx1fb_blank;
-+
-+/*
-+ * * setup initial parameters
-+ * */
-+ memset(&init_var, 0, sizeof(init_var));
-+
-+ init_var.transp.length = 0;
-+ init_var.nonstd = 0;
-+ init_var.activate = FB_ACTIVATE_NOW;
-+ init_var.xoffset = 0;
-+ init_var.yoffset = 0;
-+ init_var.height = -1;
-+ init_var.width = -1;
-+ init_var.vmode = FB_VMODE_NONINTERLACED;
-+
-+ if (1) {
-+ current_par.max_xres = LCD_MAXX;
-+ current_par.max_yres = LCD_MAXY;
-+ current_par.max_bpp = LCD_MAX_BPP; // 12
-+ init_var.red.length = 5; // 5;
-+ init_var.green.length = 6; // 6;
-+ init_var.blue.length = 5; // 5;
-+#ifdef __LITTLE_ENDIAN
-+ init_var.red.offset = 11;
-+ init_var.green.offset = 5;
-+ init_var.blue.offset = 0;
-+#endif //__LITTLE_ENDIAN
-+ init_var.grayscale = 16; // i suppose, TODO
-+ init_var.sync = 0;
-+ init_var.pixclock = 171521; // TODO
-+ }
-+
-+ current_par.screen_start_address = NULL;
-+ current_par.v_screen_start_address = NULL;
-+ current_par.screen_memory_size = MAX_PIXEL_MEM_SIZE;
-+// Thomas Wong add this for debugging
-+//printk("_init_fbinfo, pointer to current_par: 0x%08x, screen_memory_size: 0x%08x\n", &current_par,current_par.screen_memory_size);
-+ current_par.currcon = -1; // TODO
-+
-+ init_var.xres = current_par.max_xres;
-+ init_var.yres = current_par.max_yres;
-+ init_var.xres_virtual = init_var.xres;
-+ init_var.yres_virtual = init_var.yres;
-+ init_var.bits_per_pixel = current_par.max_bpp;
-+
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_blank()
-+ *
-+ * Input: blank : Blank flag
-+ * info : Frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: _enable_lcd_controller()
-+ * _disable_lcd_controller()
-+ *
-+ * Description: blank the screen, if blank, disable lcd controller, while if no blank
-+ * set cmap and enable lcd controller
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void
-+dbmx1fb_blank(int blank, struct fb_info *info)
-+{
-+#ifdef SUP_TTY0
-+ int i;
-+
-+ FUNC_START;
-+ DPRINTK("blank=%d info->modename=%s\n", blank, info->modename);
-+ if (blank) {
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR)
-+ for (i = 0; i < current_par.palette_size; i++)
-+ ; // TODO
-+//printk("Disable LCD\n");
-+ _disable_lcd_controller();
-+ }
-+ else {
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR)
-+ dbmx1fb_set_cmap(&fb_display[current_par.currcon].cmap,
-+ 1,
-+ current_par.currcon, info);
-+//printk("Enable LCD\n");
-+ _enable_lcd_controller();
-+ }
-+ FUNC_END;
-+#endif //SUP_TTY0
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_switch()
-+ *
-+ * Input: info : Frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: Switch to another console
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int dbmx1fb_switch(int con, struct fb_info *info)
-+{
-+ FUNC_START;
-+ if (current_par.visual != FB_VISUAL_TRUECOLOR) {
-+ struct fb_cmap *cmap;
-+ if (current_par.currcon >= 0) {
-+ // Get the colormap for the selected console
-+ cmap = &fb_display[current_par.currcon].cmap;
-+
-+ if (cmap->len)
-+ fb_get_cmap(cmap, 1, dbmx1fb_getcolreg, info);
-+ }
-+ }
-+
-+ current_par.currcon = con;
-+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
-+ dbmx1fb_set_var(&fb_display[con].var, con, info);
-+ FUNC_END;
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _encode_par()
-+ *
-+ * Input: var : Input var data
-+ * par : LCD controller parameters
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: use current_par to set a var structure
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int _encode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par)
-+{
-+ // Don't know if really want to zero var on entry.
-+ // Look at set_var to see. If so, may need to add extra params to par
-+
-+ // memset(var, 0, sizeof(struct fb_var_screeninfo));
-+
-+ var->xres = par->xres;
-+ var->yres = par->yres;
-+ var->xres_virtual = par->xres_virtual;
-+ var->yres_virtual = par->yres_virtual;
-+
-+ var->bits_per_pixel = par->bits_per_pixel;
-+
-+ DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-+ switch(var->bits_per_pixel) {
-+ case 2:
-+ case 4:
-+ case 8:
-+ var->red.length = 4;
-+ var->green = var->red;
-+ var->blue = var->red;
-+ var->transp.length = 0;
-+ break;
-+ case 12: // This case should differ for Active/Passive mode
-+ case 16:
-+ if (1) {
-+ var->red.length = 4;
-+ var->blue.length = 4;
-+ var->green.length = 4;
-+ var->transp.length = 0;
-+#ifdef __LITTLE_ENDIAN
-+ var->red.offset = 8;
-+ var->green.offset = 4;
-+ var->blue.offset = 0;
-+ var->transp.offset = 0;
-+#endif // __LITTLE_ENDIAN
-+ }
-+ else
-+ {
-+ var->red.length = 5;
-+ var->blue.length = 5;
-+ var->green.length = 6;
-+ var->transp.length = 0;
-+ var->red.offset = 11;
-+ var->green.offset = 5;
-+ var->blue.offset = 0;
-+ var->transp.offset = 0;
-+ }
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _decode_var
-+ *
-+ * Input: var : Input var data
-+ * par : LCD controller parameters
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Get the video params out of 'var'. If a value doesn't fit,
-+ * round it up,if it's too big, return -EINVAL.
-+ *
-+ * Cautions: Round up in the following order: bits_per_pixel, xres,
-+ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
-+ * bitfields, horizontal timing, vertical timing.
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int _decode_var(struct fb_var_screeninfo *var,
-+ struct dbmx1fb_par *par)
-+{
-+ *par = current_par;
-+
-+ if ((par->xres = var->xres) < MIN_XRES)
-+ par->xres = MIN_XRES;
-+ if ((par->yres = var->yres) < MIN_YRES)
-+ par->yres = MIN_YRES;
-+ if (par->xres > current_par.max_xres)
-+ par->xres = current_par.max_xres;
-+ if (par->yres > current_par.max_yres)
-+ par->yres = current_par.max_yres;
-+ par->xres_virtual =
-+ var->xres_virtual < par->xres ? par->xres : var->xres_virtual;
-+ par->yres_virtual =
-+ var->yres_virtual < par->yres ? par->yres : var->yres_virtual;
-+ par->bits_per_pixel = var->bits_per_pixel;
-+
-+ switch (par->bits_per_pixel) {
-+#ifdef FBCON_HAS_CFB4
-+ case 4:
-+ par->visual = FB_VISUAL_PSEUDOCOLOR;
-+ par->palette_size = 16;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB8
-+ case 8:
-+ par->visual = FB_VISUAL_PSEUDOCOLOR;
-+ par->palette_size = 256;
-+ break;
-+#endif
-+#ifdef FBCON_HAS_CFB16
-+ case 12: // RGB 444
-+ case 16: /* RGB 565 */
-+ par->visual = FB_VISUAL_TRUECOLOR;
-+ par->palette_size = 0;
-+ break;
-+#endif
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ par->screen_start_address =(u_char*)(
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+ par->v_screen_start_address =(u_char*)(
-+ (u_long)v_framebuffer_memory_address+PAGE_SIZE);
-+
-+// Thomas Wong - try to change start address here (map to SRAM, instead of SDRAM)
-+#ifndef FULL_SCREEN
-+ par->screen_start_address =(u_char*)(0x00300000);
-+ par->v_screen_start_address =(u_char*)(0xF0300000);
-+#endif
-+
-+// par->screen_start_address =(u_char*)(0x0BE00000);
-+// par->v_screen_start_address =(u_char*)(0xFBE00000);
-+
-+// par->screen_start_address =(u_char*)(0x12000000);
-+// par->v_screen_start_address =(u_char*)(0xF2000000);
-+
-+ return 0;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: _reserve_fb_memory()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: get data out of var structure and set related LCD controller registers
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int __init _reserve_fb_memory(void)
-+{
-+ u_int required_pages;
-+ u_int extra_pages;
-+ u_int order;
-+ struct page *page;
-+ char *allocated_region;
-+
-+ DPRINTK("frame buffer memory size = %x\n", (unsigned int)ALLOCATED_FB_MEM_SIZE);
-+ if (v_framebuffer_memory_address != NULL)
-+ return -EINVAL;
-+
-+ /* Find order required to allocate enough memory for framebuffer */
-+ required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT;
-+ for (order = 0 ; required_pages >> order ; order++) {;}
-+ extra_pages = (1 << order) - required_pages;
-+
-+ if ((allocated_region =
-+ (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL){
-+
-+ DPRINTK("can not allocated memory\n");
-+ return -ENOMEM;
-+ }
-+
-+
-+ v_framebuffer_memory_address = (u_char *)allocated_region +
-+ (extra_pages << PAGE_SHIFT);
-+ p_framebuffer_memory_address = (u_char *)__virt_to_phys(
-+ (u_long)v_framebuffer_memory_address);
-+#if 0
-+ printk(KERN_ERR"Frame buffer __get_free_pages vd:= %x, pd= %x",
-+ (unsigned int)v_framebuffer_memory_address,
-+ (unsigned int)p_framebuffer_memory_address);
-+#endif
-+ /* Free all pages that we don't need but were given to us because */
-+ /* __get_free_pages() works on powers of 2. */
-+ for (;extra_pages;extra_pages--)
-+ free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
-+
-+ /* Set reserved flag for fb memory to allow it to be remapped into */
-+ /* user space by the common fbmem driver using remap_page_range(). */
-+ for(page = virt_to_page(v_framebuffer_memory_address);
-+ page < virt_to_page(v_framebuffer_memory_address
-+ + ALLOCATED_FB_MEM_SIZE);
-+ page++)
-+ mem_map_reserve(page);
-+#if 0
-+ /* Remap the fb memory to a non-buffered, non-cached region */
-+ v_framebuffer_memory_address = (u_char *)__ioremap(
-+ (u_long)p_framebuffer_memory_address,
-+ ALLOCATED_FB_MEM_SIZE,
-+ L_PTE_PRESENT |
-+ L_PTE_YOUNG |
-+ L_PTE_DIRTY |
-+ L_PTE_WRITE);
-+#endif
-+ current_par.screen_start_address =(u_char*)(
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+ current_par.v_screen_start_address =(u_char*)(
-+ (u_long)v_framebuffer_memory_address+PAGE_SIZE);
-+
-+ DPRINTK("physical screen start addres: %x\n",
-+ (u_long)p_framebuffer_memory_address+PAGE_SIZE);
-+
-+#ifndef FULL_SCREEN
-+// Thomas Wong - we'll try to change the screen start address here
-+// printk("\n\rMap LCD screen to SDRAM.\n\r");
-+
-+ printk("\n\rMap LCD screen to embedded SRAM.\n\r");
-+ current_par.screen_start_address =(u_char*)(0x00300000);
-+ current_par.v_screen_start_address =(u_char*)(0xF0300000);
-+#endif
-+
-+// printk("\n\rMap LCD screen to SDRAM 0xFBE00000.\n\r");
-+// current_par.screen_start_address =(u_char*)(0x0BE00000);
-+// current_par.v_screen_start_address =(u_char*)(0xFBE00000);
-+
-+// printk("\n\rMap LCD screen to SRAM 0x12000000.\n\r");
-+// current_par.screen_start_address =(u_char*)(0x12000000);
-+// current_par.v_screen_start_address =(u_char*)(0xF2000000);
-+
-+ return (v_framebuffer_memory_address == NULL ? -EINVAL : 0);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _enable_lcd_controller()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: enable Lcd controller, setup registers,
-+ * base on current_par value
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _enable_lcd_controller(void)
-+{
-+ unsigned int val;
-+#if 0
-+ int i;
-+ val =0;
-+
-+ FUNC_START;
-+ _decode_var(&init_var, &current_par);
-+
-+ val = current_par.xres/16;
-+ val <<= 20;
-+ val += current_par.yres;
-+ WRITEREG(DBMX1_LCD_XYMAX, val);
-+
-+ val=0;
-+ val=current_par.xres_virtual /2;
-+ WRITEREG(DBMX1_LCD_VPW, val);
-+
-+ switch(current_par.bits_per_pixel ){
-+ case 4: // for gray only
-+ for(i=0; i<16; i++){
-+ WRITEREG(DBMX1_LCD_MAPRAM+i, gray4map[i]);
-+ }
-+ WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_4);
-+ WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_4); // no interrupt
-+ WRITEREG(DBMX1_LCD_REFMCR, REFMCR_VAL_4);
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_4);
-+ WRITEREG(DBMX1_LCD_PWMR, PWMR_VAL);
-+ break;
-+ case 12:
-+ case 16:
-+ WRITEREG(DBMX1_LCD_PANELCFG, PANELCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_HCFG, HCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_VCFG, VCFG_VAL_12);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
-+
-+ break;
-+ }
-+#else
-+ val = READREG(0x21c21c);
-+ val |= 0x0010000;
-+ WRITEREG(0x21c21c, val);
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x8200);
-+ WRITEREG(DBMX1_LCD_REFMCR, 0xf000002);
-+
-+ // Thomas Wong - we want 0x8A not 0x200
-+// WRITEREG(DBMX1_LCD_PWMR, 0x200);
-+// PLAM -- for rev2 (endian bit)
-+// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00A9008A);
-+// end PLAM
-+#endif
-+
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _disable_lcd_controller()
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: just disable the LCD controller
-+ * disable lcd interrupt. others, i have no ideas
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _disable_lcd_controller(void)
-+{
-+ unsigned int val;
-+ val = READREG(0x21c21c);
-+ val &= ~0x0010000;
-+ WRITEREG(0x21c21c, val);
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x8200);
-+// WRITEREG(DBMX1_LCD_REFMCR, DISABLELCD_VAL);
-+ WRITEREG(0x205034, 0x0);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _install_cmap
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: set color map to hardware
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void _install_cmap(int con, struct fb_info *info)
-+{
-+ if (con != current_par.currcon)
-+ return ;
-+ if (fb_display[con].cmap.len)
-+ fb_set_cmap(&fb_display[con].cmap, 1, dbmx1fb_setcolreg, info);
-+ else
-+ fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-+ 1,
-+ dbmx1fb_setcolreg,
-+ info);
-+ return ;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_lcd_system
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called:
-+ *
-+ * Description: initialize the gpio port C and port D with DMA enable
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static void __init _init_lcd_system(void)
-+{
-+unsigned int val;
-+
-+/* Thomas Wong - we don't need DMA here
-+ // dma reset & enable
-+ val = READREG(0x209000);
-+ val |= 0x02;
-+ WRITEREG(0x209000, val);
-+ val = READREG(0x209000);
-+ val |= 0x01;
-+ WRITEREG(0x209000, val);
-+*/
-+ // gpio
-+ //clear port D for LCD signal
-+ WRITEREG(0x21c320, 0x0);
-+ WRITEREG(0x21c338, 0x0);
-+
-+ val = READREG(0x21c220);
-+ val |= 0x10000;
-+ WRITEREG(0x21c220, val);
-+ val = READREG(0x21c208);
-+ val |= 0x03;
-+ WRITEREG(0x21c208, val);
-+ val = READREG(0x21c200);
-+ val |= 0x10000;
-+ WRITEREG(0x21c200, val);
-+ val = READREG(0x21c238);
-+ val |= 0x10000;
-+ WRITEREG(0x21c238, val);
-+ val = READREG(0x21c21c);
-+ val |= 0x10000;
-+ WRITEREG(0x21c21c, val);
-+
-+}
-+
-+static void set_pclk(unsigned int fmhz)
-+{
-+ unsigned int div= 96/fmhz;
-+ unsigned int reg;
-+ reg = READREG(0x21b020);
-+ reg &= ~0xf0;
-+ WRITEREG(0x21b020, reg);
-+ reg |= ((div-1)<<4) &0xf0;
-+ WRITEREG(0x21b020, reg);
-+}
-+
-+/*****************************************************************************
-+ * Function Name: _init_lcd
-+ *
-+ * Input: VOID
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: _decode_var()
-+ *
-+ * Description: initialize the LCD controller, use current_par for 12bpp
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Chen Ning
-+******************************************************************************/
-+static int __init _init_lcd()
-+{
-+
-+ unsigned int val, rate;
-+ int i;
-+ unsigned char * pscr;
-+ //unsigned long pclk,temp,PCLKDIV2;
-+ //unsigned long MFI,MFN,PD,MFD,tempReg,MCUPLLCLK;
-+
-+
-+ _decode_var(&init_var, &current_par);
-+
-+ // gpio begin
-+ val = READREG(0x21c21c);
-+ val &= ~0x00010000;
-+ WRITEREG(0x21c21c, val);
-+ DPRINTK(KERN_ERR"DR=%x\n", READREG(0x21c21c));
-+
-+ // LCD regs
-+ DPRINTK(KERN_ERR"write SSA by %x\n",
-+ (unsigned int)current_par.screen_start_address);
-+ WRITEREG(DBMX1_LCD_SSA, (unsigned int)current_par.screen_start_address);
-+ DPRINTK(KERN_ERR"SSA=%x\n", READREG(DBMX1_LCD_SSA));
-+
-+ val =0;
-+ val = current_par.xres/16;
-+ val = val<<20;
-+ val += current_par.yres;
-+ DPRINTK(KERN_ERR"par.x=%x, y=%x\n",
-+ current_par.xres,
-+ current_par.yres);
-+ WRITEREG(DBMX1_LCD_XYMAX, val);
-+ DPRINTK(KERN_ERR"XYMAX=%x\n", READREG(DBMX1_LCD_XYMAX));
-+
-+ val=0;
-+ val=current_par.xres_virtual/2;
-+ WRITEREG(DBMX1_LCD_VPW, val);
-+ DPRINTK(KERN_ERR"VPW=%x\n", READREG(DBMX1_LCD_VPW));
-+
-+ set_pclk(4);
-+
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PANELCFG=%x\n",
-+ READREG(DBMX1_LCD_PANELCFG));
-+
-+ WRITEREG(DBMX1_LCD_HCFG, 0x04000f06);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_HCFG=%x\n",
-+ READREG(DBMX1_LCD_HCFG));
-+
-+ WRITEREG(DBMX1_LCD_VCFG, 0x04000907);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_VCFG=%x\n",
-+ READREG(DBMX1_LCD_VCFG));
-+
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
-+ READREG(DBMX1_LCD_REFMCR));
-+
-+ WRITEREG(DBMX1_LCD_DMACR, DMACR_VAL_12);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_DMACR=%x\n",
-+ READREG(DBMX1_LCD_DMACR));
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x00008200);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
-+ READREG(DBMX1_LCD_PWMR));
-+
-+ // Thomas Wong - we don't want to turn it on here
-+ /*
-+ WRITEREG(DBMX1_LCD_REFMCR, 0x0f000002)
-+ DPRINTK(KERN_ERR"DBMX1_LCD_REFMCR=%x\n",
-+ READREG(DBMX1_LCD_REFMCR));
-+ */
-+
-+ WRITEREG(DBMX1_LCD_PWMR, 0x0000008a);
-+ DPRINTK(KERN_ERR"DBMX1_LCD_PWMR=%x\n",
-+ READREG(DBMX1_LCD_PWMR));
-+
-+ // Thomas Wong
-+ WRITEREG(0x21B020, 0x000B005B);
-+// PLAM -- for rev2 (new register and endian bits)
-+ WRITEREG(DBMX1_LCD_PANELCFG, 0xF8008B42); // little endian
-+// WRITEREG(DBMX1_LCD_PANELCFG, 0xF8048B42); // big endian
-+ WRITEREG(DBMX1_LCD_LGPMR, 0x00090300);
-+// WRITEREG(DBMX1_LCD_PWMR, 0x0000008A);
-+ WRITEREG (DBMX1_LCD_PWMR, 0x009A008A);
-+// end PLAM
-+
-+// PLAM -- for rev2 (new DMACR setting)
-+// WRITEREG(DBMX1_LCD_DMACR, 0x800C0002);
-+ WRITEREG(DBMX1_LCD_DMACR, 0x00040008);
-+//end PLAM
-+
-+
-+#define DMACR_VAL_12 0x800C0002
-+
-+
-+// WRITEREG(DBMX1_LCD_INTCR, INTCR_VAL_12);
-+// DPRINTK(KERN_ERR"DBMX1_LCD_INTCR=%x\n",
-+// READREG(DBMX1_LCD_INTCR));
-+
-+ // warm up LCD
-+ for(i=0;i<10000000;i++) ;
-+
-+ // gpio end
-+ val = READREG(0x21c21c);
-+ val |= 0x00010000;
-+ WRITEREG(0x21c21c, val);
-+ DPRINTK(KERN_ERR"DR=%x\n",
-+ READREG(0x21c21c));
-+#if 0
-+ // clear screen
-+ pscr = current_par.v_screen_start_address;
-+ for(i=0; i< (current_par.screen_memory_size - 2*PAGE_SIZE); i++){
-+ *pscr++ = 0xff;
-+ }
-+#endif
-+ DPRINTK(KERN_ERR"_init_lcd end \n");
-+
-+ return 0;
-+}
-+
-+#ifdef HARDWARE_CURSOR
-+
-+/*
-+ * Hardware cursor support
-+ */
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_color()
-+ *
-+ * Input: fb : frame buffer database
-+ * red : red component level in the cursor
-+ * green : green component level in the cursor
-+ * blue : blue component level in the cursor
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set color of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_color(struct dbmx1fb_info *fb, UINT8 *red, UINT8 *green, UINT8 *blue)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 color;
-+
-+ FUNC_START;
-+ c->color[0] = *red;
-+ c->color[1] = *green;
-+ c->color[2] = *blue;
-+ color = (UINT32)*red;
-+ color |= (UINT32)(*green>>5);
-+ color |= (UINT32)(*blue>>11);
-+
-+ WRITEREG(DBMX1_LCD_LCHCC, color);
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor()
-+ *
-+ * Input: fb : frame buffer database
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Load information of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor(struct dbmx1fb_info *fb)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 temp,tempReg,x,y;
-+
-+ FUNC_START;
-+ //DPRINTK(KERN_ERR"BLINK_RATE=%x\n",c->blink_rate);
-+// DPRINTK(KERN_ERR"width=%x\n",c->width);
-+// DPRINTK(KERN_ERR"height=%x\n",c->height);
-+
-+ x = c->startx << 16;
-+ if (c->state == LCD_CURSOR_ON)
-+ x |= CURSOR_ON_MASK;
-+
-+#ifdef FBCON_HAS_CFB4
-+ else if(c->state == LCD_CURSOR_REVERSED)
-+ x |= CURSOR_REVERSED_MASK;
-+ else if(c->state == LCD_CURSOR_ON_WHITE)
-+ x |= CURSOR_WHITE_MASK;
-+#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
-+ else if(c->state == LCD_CURSOR_INVERT_BGD)
-+ x |= CURSOR_INVERT_MASK;
-+ else if(c->state == LCD_CURSOR_AND_BGD)
-+ x |= CURSOR_AND_BGD_MASK;
-+ else if(c->state == LCD_CURSOR_OR_BGD)
-+ x |= CURSOR_OR_BGD_MASK;
-+ else if(c->state == LCD_CURSOR_XOR_BGD)
-+ x |= CURSOR_XOR_BGD_MASK;
-+#endif
-+ else
-+ x = c->startx;
-+
-+ y = c->starty;
-+
-+ temp = (UINT32)x | (UINT32)y;
-+ WRITEREG(DBMX1_LCD_LCXYP, temp);
-+ //DPRINTK(KERN_ERR"lcxyp=%x\n",READREG(DBMX1_LCD_LCXYP));
-+
-+ temp = (UINT32)((c->width<<8) | (c->height));
-+ tempReg = (UINT32)((temp<<16) | c->blink_rate);
-+
-+ WRITEREG(DBMX1_LCD_CURBLKCR, tempReg);
-+
-+ //c->blink_rate = 10;
-+ if (c->blinkenable)
-+ dbmx1fb_set_cursor_blink(fb,c->blink_rate);
-+ DPRINTK(KERN_ERR"CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_blink()
-+ *
-+ * Input: fb : frame buffer database
-+ * blink : input blink frequency of cursor
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set blink frequency of hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_blink(struct dbmx1fb_info *fb,int blink)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ unsigned long temp,tempReg;
-+ unsigned long PCD, XMAX, YMAX, PCLKDIV2;
-+ unsigned long tempMicroPeriod;
-+
-+ FUNC_START;
-+ DPRINTK(KERN_ERR"dbmx1fb_set_cursor_blink\n");
-+
-+ if(!c){
-+ DPRINTK(KERN_ERR"dangerouts, for c == null\n");
-+ }
-+ c->blink_rate = blink;
-+
-+ tempReg = READREG(DBMX1_LCD_XYMAX);
-+ XMAX = (tempReg & XMAX_MASK) >> 20;
-+ YMAX = tempReg & YMAX_MASK;
-+ //XMAX = 240;
-+ //YMAX = 320;
-+ tempReg = READREG(PCDR);
-+ PCLKDIV2 = (tempReg & PCLKDIV2_MASK) >> 4;
-+ tempReg = READREG(DBMX1_LCD_PANELCFG);
-+ PCD = tempReg & PCD_MASK;
-+
-+ temp = (PCLKDIV2 + 1);
-+
-+ if (!blink)
-+ {
-+ /* disable the blinking cursor function when frequency is 0 */
-+ tempReg = READREG(DBMX1_LCD_CURBLKCR);
-+ tempReg &= CURSORBLINK_DIS_MASK;
-+ WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
-+ }
-+ else
-+ {
-+
-+ tempMicroPeriod = temp * XMAX * YMAX * (PCD + 1);
-+ temp = 96*10000000/(blink * tempMicroPeriod);
-+ tempReg = READREG(DBMX1_LCD_CURBLKCR);
-+ tempReg |= CURSORBLINK_EN_MASK;
-+ tempReg |= temp;
-+ WRITEREG(DBMX1_LCD_CURBLKCR,tempReg);
-+ DPRINTK(KERN_ERR"Inter_CURBLKCR=%x\n",READREG(DBMX1_LCD_CURBLKCR));
-+ }
-+
-+ FUNC_END;
-+}
-+
-+ /*****************************************************************************
-+ * Function Name: dbmx1fb_set_cursor_state()
-+ *
-+ * Input: fb : frame buffer database
-+ * state : The status of the cursor to be set. e.g.
-+ * LCD_CURSOR_OFF
-+ * LCD_CURSOR_ON
-+ * LCD_CURSOR_REVERSED
-+ * LCD_CURSOR_ON_WHITE
-+ * LCD_CURSOR_OR_BGD
-+ * LCD_CURSOR_XOR_BGD
-+ * LCD_CURSOR_AND_BGD
-+ *
-+ * Value Returned: VOID
-+ *
-+ * Functions Called: VOID
-+ *
-+ * Description: Set state of cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_set_cursor_state(struct dbmx1fb_info *fb,UINT32 state)
-+{
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+ UINT32 temp;
-+
-+ FUNC_START;
-+ c->state = state;
-+ temp = READREG(DBMX1_LCD_LCXYP);
-+ temp &= CURSOR_OFF_MASK;
-+
-+ if (state == LCD_CURSOR_OFF)
-+ temp = temp;
-+ else if (state == LCD_CURSOR_ON)
-+ temp |= CURSOR_ON_MASK;
-+#ifdef FBCON_HAS_CFB4
-+ else if (state == LCD_CURSOR_REVERSED)
-+ temp |= CURSOR_REVERSED_MASK;
-+ else if (state == LCD_CURSOR_ON_WHITE)
-+ temp |= CURSOR_WHITE_MASK;
-+#elif defined(FBCON_HAS_CFB8)||defined(FBCON_HAS_CFB16)
-+ else if(state == LCD_CURSOR_INVERT_BGD)
-+ temp |= CURSOR_INVERT_MASK;
-+ else if (state == LCD_CURSOR_OR_BGD)
-+ temp |= CURSOR_OR_BGD_MASK;
-+ else if (state == LCD_CURSOR_XOR_BGD)
-+ temp |= CURSOR_XOR_BGD_MASK;
-+ else if (state == LCD_CURSOR_AND_BGD)
-+ temp |= CURSOR_AND_BGD_MASK;
-+#endif
-+ WRITEREG(DBMX1_LCD_LCXYP,temp);
-+ DPRINTK(KERN_ERR"LCDXYP=%x\n",READREG(DBMX1_LCD_LCXYP));
-+ FUNC_END;
-+}
-+
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_cursor()
-+ *
-+ * Input: fb : frame buffer database
-+ *
-+ * Value Returned: cursor : The structure of hardware cursor
-+ *
-+ * Functions Called: dbmx1fb_set_cursor()
-+ * dbmx1fb_set_cursor_state()
-+ *
-+ * Description: The entry for display switch to operate hardware cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static void dbmx1fb_cursor(struct display *p, int mode, int x, int y)
-+{
-+ struct dbmx1fb_info *fb = (struct dbmx1fb_info *)p->fb_info;
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ FUNC_START;
-+ if (c==0) return;
-+
-+
-+ x *= fontwidth(p);
-+ y *= fontheight(p);
-+
-+ c->startx = x;
-+ c->starty = y;
-+
-+ switch (mode) {
-+ case CM_ERASE:
-+ dbmx1fb_set_cursor_state(fb,LCD_CURSOR_OFF);
-+ break;
-+
-+ case CM_DRAW:
-+ case CM_MOVE:
-+ c->state = LCD_CURSOR_ON;
-+ dbmx1fb_set_cursor(fb);
-+ dbmx1fb_set_cursor_state(fb, c->state);
-+ break;
-+ }
-+ FUNC_END;
-+}
-+
-+/*****************************************************************************
-+ * Function Name: dbmx1fb_set_font()
-+ *
-+ * Input: display : console datebase
-+ * width : The new width of cursor to be set.
-+ * height : The new height of cursor position to be set
-+ *
-+ * Value Returned: int : Return status.If no error, return 0.
-+ *
-+ * Functions Called: dbmx1fb_set_cursor()
-+ * dbmx1fb_set_cursor_color()
-+ *
-+ * Description: Set font for cursor
-+ *
-+ * Modification History:
-+ * 10 DEC,2001, Zhang Juan
-+******************************************************************************/
-+static int dbmx1fb_set_font(struct display *d, int width, int height)
-+{
-+ struct dbmx1fb_info *fb=(struct dbmx1fb_info *)d->fb_info;
-+ struct dbmx1fb_cursor *c = &fb->cursor;
-+
-+ FUNC_START;
-+ if(!d){
-+ printk(KERN_ERR"dbmx1fb_set_font d=null\n");
-+ return -1;
-+ }
-+
-+ if (c) {
-+ if (!width || !height) {
-+ width = 16;
-+ height = 16;
-+ }
-+
-+ c->width = width;
-+ c->height = height;
-+
-+ DPRINTK(KERN_ERR"set cursor\n");
-+ dbmx1fb_set_cursor(fb);
-+ DPRINTK(KERN_ERR"set color cursor\n");
-+ dbmx1fb_set_cursor_color(fb, cursor_color_map,
-+ cursor_color_map, cursor_color_map);
-+ }else{
-+ DPRINTK(KERN_ERR"set cursor failed, cursor == null\n");
-+ }
-+
-+ FUNC_END;
-+ return 1;
-+}
-+#endif // HARDWARE_CURSOR
-+/* end of file */
-+
---- /dev/null
-+++ linux-2.4.27/drivers/video/dbmx1fb.h
-@@ -0,0 +1,213 @@
-+/****************************************************************************
-+ *
-+ * Copyright (C) 2001, Chen Ning All Rights Reserved
-+ *
-+ * File Name: dbmx1fb.h
-+ *
-+ * Progammers: Chen Ning, Zhang Juan
-+ *
-+ * Date of Creations: 10 DEC,2001
-+ *
-+ * Synopsis:
-+ *
-+ * Descirption:
-+ *
-+ * Modification History:
-+ * 10 DEC, 2001, initialization version, frame work for frame buffer driver
-+ *
-+*******************************************************************************/
-+
-+#ifndef LCDFB_H
-+#define LCDFB_H
-+#include "asm/arch/hardware.h"
-+#include "asm/arch/platform.h"
-+
-+typedef signed char BOOLEAN;
-+typedef unsigned char UINT8; /* Unsigned 8 bit quantity */
-+typedef signed char SINT8; /* Signed 8 bit quantity */
-+typedef unsigned short UINT16; /* Unsigned 16 bit quantity */
-+typedef signed short SINT16; /* Signed 16 bit quantity */
-+typedef unsigned long UINT32; /* Unsigned 32 bit quantity */
-+typedef signed long SINT32; /* Signed 32 bit quantity */
-+
-+typedef volatile BOOLEAN VBOOLEAN;
-+typedef volatile UINT8 VUINT8; /* Unsigned 8 bit quantity */
-+typedef volatile SINT8 VSINT8; /* Signed 8 bit quantity */
-+typedef volatile UINT16 VUINT16; /* Unsigned 16 bit quantity */
-+typedef volatile SINT16 VSINT16; /* Signed 16 bit quantity */
-+typedef volatile UINT32 VUINT32; /* Unsigned 32 bit quantity */
-+typedef volatile SINT32 VSINT32; /* Signed 32 bit quantity */
-+
-+#define LCDBASE 0x00205000
-+#define LCD_REGIONSIZE 0xc00
-+
-+#define DBMX1_LCD_SSA 0x00205000
-+#define DBMX1_LCD_XYMAX 0x00205004
-+#define DBMX1_LCD_VPW 0x00205008
-+#define DBMX1_LCD_LCXYP 0x0020500c
-+#define DBMX1_LCD_CURBLKCR 0x00205010
-+#define DBMX1_LCD_LCHCC 0x00205014
-+#define DBMX1_LCD_PANELCFG 0x00205018
-+#define DBMX1_LCD_HCFG 0x0020501c
-+#define DBMX1_LCD_VCFG 0x00205020
-+#define DBMX1_LCD_POS 0x00205024
-+#define DBMX1_LCD_LGPMR 0x00205028
-+#define DBMX1_LCD_PWMR 0x0020502c
-+#define DBMX1_LCD_DMACR 0x00205030
-+#define DBMX1_LCD_REFMCR 0x00205034
-+#define DBMX1_LCD_INTCR 0x00205038
-+#define DBMX1_LCD_INTSR 0x00205040
-+#define DBMX1_LCD_MAPRAM 0x00205800
-+
-+#define MPCTL0 0x0021B004
-+#define PCDR 0X0021B020
-+
-+#define SSA DBMX1_LCD_SSA
-+#define XYMAX DBMX1_LCD_XYMAX
-+#define VPW DBMX1_LCD_VPW
-+#define LCXYP DBMX1_LCD_LCXYP
-+#define CURBLKCR DBMX1_LCD_CURBLKCR
-+#define LCHCC DBMX1_LCD_LCHCC
-+#define PANELCFG DBMX1_LCD_PANELCFG
-+#define VCFG DBMX1_LCD_VCFG
-+#define HCFG DBMX1_LCD_HCFG
-+#define POS DBMX1_LCD_POS
-+#define LGPMR DBMX1_LCD_LGPMR
-+#define PWMR DBMX1_LCD_PWMR
-+#define DMACR DBMX1_LCD_DMACR
-+#define REFMCR DBMX1_LCD_REFMCR
-+#define INTCR DBMX1_LCD_INTCR
-+#define INTSR DBMX1_LCD_INTSR
-+#define MAPRAM DBMX1_LCD_MAPRAM
-+// default value
-+#define SHARP_TFT_240x320
-+
-+#ifdef SHARP_TFT_240x320
-+#define PANELCFG_VAL_12 0xf8008b48
-+#define HCFG_VAL_12 0x04000f06
-+#define VCFG_VAL_12 0x04000907
-+#define PWMR_VAL 0x0000008a
-+#define LCD_MAXX 240
-+#define LCD_MAXY 320
-+#else //SHARP_TFT_240x320
-+
-+#define PANELCFG_VAL_12 0xf8088c6b
-+#define HCFG_VAL_12 0x04000f06
-+#define VCFG_VAL_12 0x04010c03
-+#define PWMR_VAL 0x00000200
-+#define LCD_MAXX 320
-+#define LCD_MAXY 240
-+#endif // SHARP_TFT_240x320
-+
-+#define PANELCFG_VAL_4 0x20008c09
-+#define PANELCFG_VAL_4C 0x60008c09
-+
-+#define HCFG_VAL_4 0x04000f07
-+
-+#define VCFG_VAL_4 0x04010c03
-+
-+
-+#define REFMCR_VAL_4 0x00000003
-+#define REFMCR_VAL_12 0x00000003
-+#define DISABLELCD_VAL 0x00000000
-+
-+#define DMACR_VAL_4 0x800c0003 // 12 & 3 TRIGGER
-+#define DMACR_VAL_12 0x00020008
-+
-+#define INTCR_VAL_4 0x00000000
-+#define INTCR_VAL_12 0x00000000
-+
-+#define INTSR_UDRERR 0x00000008
-+#define INTSR_ERRRESP 0x00000004
-+#define INTSR_EOF 0x00000002
-+#define INTSR_BOF 0x00000001
-+
-+#define MIN_XRES 64
-+#define MIN_YRES 64
-+
-+#define LCD_MAX_BPP 16
-+
-+#if 0
-+#define READREG(r) \
-+ inl(IO_ADDRESS(r))
-+
-+#define WRITEREG(r, val) \
-+ outl(val, IO_ADDRESS(r))
-+#else
-+#endif // 0
-+
-+#define MAX_PALETTE_NUM_ENTRIES 256
-+#define MAX_PIXEL_MEM_SIZE \
-+ ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8)
-+#define MAX_FRAMEBUFFER_MEM_SIZE \
-+ (MAX_PIXEL_MEM_SIZE + 32)
-+#define ALLOCATED_FB_MEM_SIZE \
-+ (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2))
-+
-+ // TODO:
-+#define FBCON_HAS_CFB4
-+#define FBCON_HAS_CFB8
-+#define FBCON_HAS_CFB16
-+
-+#define IRQ_LCD 12 // TODO: which irq?
-+#define DBMX1_NAME "DBMX1FB"
-+#define DEV_NAME DBMX1_NAME
-+#define MAX_PALETTE_NUM_ENTRIES 256
-+#define DEFAULT_CURSOR_BLINK_RATE (20)
-+#define CURSOR_DRAW_DELAY (2)
-+/*cursor status*/
-+#define LCD_CURSOR_OFF 0
-+#define LCD_CURSOR_ON 1
-+
-+#ifdef FBCON_HAS_CFB4
-+ #define LCD_CURSOR_REVERSED 2
-+ #define LCD_CURSOR_ON_WHITE 3
-+#elif defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16)
-+ #define LCD_CURSOR_INVERT_BGD 2
-+ #define LCD_CURSOR_AND_BGD 3
-+ #define LCD_CURSOR_OR_BGD 4
-+ #define LCD_CURSOR_XOR_BGD 5
-+#endif //FBCON_HAS_CFB4
-+
-+/* MASK use for caculating MCDUPLLCLK */
-+#define MFI_MASK 0x00003C00
-+#define MFN_MASK 0x000003FF
-+#define PD_MASK 0x3C000000
-+#define MFD_MASK 0x03FF0000
-+#define PCLKDIV2_MASK 0x000000F0
-+#define PCD_MASK 0x0000003F
-+#define XMAX_MASK 0xF3F00000
-+#define YMAX_MASK 0x000001FF
-+#define HWAIT1_MASK 0x0000FF00
-+#define HWAIT2_MASK 0x000000FF
-+#define HWIDTH_MASK 0xFC000000
-+#define PASSDIV_MASK 0x00FF0000
-+#define VWAIT1_MASK 0x0000FF00
-+#define VWAIT2_MASK 0x000000FF
-+#define VWIDTH_MASK 0xFC000000
-+#define CURSORBLINK_DIS_MASK 0x80000000
-+
-+#define DISPLAY_MODE_MASK 0x80000000
-+
-+#define MCU_FREQUENCE 32768
-+#define COLOR_MASK 0x40000000
-+
-+/* MASK use for indicating the cursor status */
-+#define CURSOR_ON_MASK 0x40000000
-+#define CURSOR_OFF_MASK 0x0FFFFFFF
-+#define MAX_CURSOR_WIDTH 31
-+#define MAX_CURSOR_HEIGHT 31
-+#define CURSORBLINK_EN_MASK 0x80000000
-+
-+#ifdef FBCON_HAS_CFB4
-+#define CURSOR_REVERSED_MASK 0x80000000
-+#define CURSOR_WHITE_MASK 0xC0000000
-+#else
-+#define CURSOR_INVERT_MASK 0x80000000
-+#define CURSOR_AND_BGD_MASK 0xC0000000
-+#define CURSOR_OR_BGD_MASK 0x50000000
-+#define CURSOR_XOR_BGD_MASK 0x90000000
-+#endif // FBCON_HAS_CFB4
-+
-+#endif //LCDFB_H
-+
---- linux-2.4.27/drivers/video/fbmem.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/fbmem.c
-@@ -61,7 +61,9 @@
- extern int pm2fb_setup(char*);
- extern int pm3fb_init(void);
- extern int pm3fb_setup(char*);
-+extern int clps711xfb_init(void);
- extern int cyber2000fb_init(void);
-+extern int cyber2000fb_setup(char*);
- extern int retz3fb_init(void);
- extern int retz3fb_setup(char*);
- extern int clgenfb_init(void);
-@@ -145,6 +147,8 @@
- extern int sstfb_setup(char*);
- extern int it8181fb_init(void);
- extern int it8181fb_setup(char*);
-+extern int anakinfb_init(void);
-+extern int dbmx1fb_init(void);
-
- static struct {
- const char *name;
-@@ -170,11 +174,14 @@
- #ifdef CONFIG_FB_AMIGA
- { "amifb", amifb_init, amifb_setup },
- #endif
-+#ifdef CONFIG_FB_CLPS711X
-+ { "clps711xfb", clps711xfb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_CYBER
- { "cyber", cyberfb_init, cyberfb_setup },
- #endif
- #ifdef CONFIG_FB_CYBER2000
-- { "cyber2000", cyber2000fb_init, NULL },
-+ { "cyber2000", cyber2000fb_init, cyber2000fb_setup },
- #endif
- #ifdef CONFIG_FB_PM2
- { "pm2fb", pm2fb_init, pm2fb_setup },
-@@ -226,10 +233,10 @@
- #endif
- #ifdef CONFIG_FB_S3TRIO
- { "s3trio", s3triofb_init, NULL },
--#endif
-+#endif
- #ifdef CONFIG_FB_FM2
- { "fm2fb", fm2fb_init, fm2fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_SIS
- { "sisfb", sisfb_init, sisfb_setup },
- #endif
-@@ -242,7 +249,7 @@
-
- /*
- * Generic drivers that are used as fallbacks
-- *
-+ *
- * These depend on resource management and must be initialized
- * _after_ all other frame buffer devices that use resource
- * management!
-@@ -253,7 +260,7 @@
- #endif
- #ifdef CONFIG_FB_VESA
- { "vesa", vesafb_init, vesafb_setup },
--#endif
-+#endif
-
- /*
- * Chipset specific drivers that don't use resource management (yet)
-@@ -276,7 +283,7 @@
- #endif
- #ifdef CONFIG_FB_HGA
- { "hga", hgafb_init, hgafb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_IGA
- { "igafb", igafb_init, igafb_setup },
- #endif
-@@ -291,7 +298,7 @@
- #endif
- #ifdef CONFIG_FB_HP300
- { "hpfb", hpfb_init, NULL },
--#endif
-+#endif
- #ifdef CONFIG_FB_G364
- { "g364", g364fb_init, NULL },
- #endif
-@@ -307,6 +314,9 @@
- #ifdef CONFIG_FB_TX3912
- { "tx3912", tx3912fb_init, NULL },
- #endif
-+#ifdef CONFIG_FB_ANAKIN
-+ { "anakinfb", anakinfb_init, NULL },
-+#endif
- #ifdef CONFIG_FB_E1355
- { "e1355fb", e1355fb_init, e1355fb_setup },
- #endif
-@@ -330,10 +340,13 @@
- #endif
- #ifdef CONFIG_FB_AU1100
- { "au1100fb", au1100fb_init, au1100fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_IT8181
- { "it8181fb", it8181fb_init, it8181fb_setup },
- #endif
-+#ifdef CONFIG_FB_DBMX1
-+ { "dbmx1fb", dbmx1fb_init, NULL },
-+#endif
-
-
- /*
-@@ -342,7 +355,7 @@
-
- #ifdef CONFIG_FB_VGA16
- { "vga16", vga16fb_init, vga16fb_setup },
--#endif
-+#endif
- #ifdef CONFIG_FB_STI
- { "stifb", stifb_init, stifb_setup },
- #endif
-@@ -371,7 +384,7 @@
-
- struct fb_info *registered_fb[FB_MAX];
- int num_registered_fb;
--extern int fbcon_softback_size;
-+extern int fbcon_softback_size;
-
- static int first_fb_vc;
- static int last_fb_vc = MAX_NR_CONSOLES-1;
-@@ -482,7 +495,7 @@
- }
- #endif /* CONFIG_KMOD */
-
--static int
-+static int
- fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
- {
-@@ -494,7 +507,7 @@
- struct fb_fix_screeninfo fix;
- struct fb_con2fbmap con2fb;
- int i;
--
-+
- if (! fb)
- return -ENODEV;
- switch (cmd) {
-@@ -578,7 +591,7 @@
- }
- }
-
--static int
-+static int
- fb_mmap(struct file *file, struct vm_area_struct * vma)
- {
- int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
-@@ -669,11 +682,11 @@
- #elif defined(__sh__)
- pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
- #elif defined(__hppa__)
-- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
- #elif defined(__ia64__)
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- #elif defined(__hppa__)
-- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
- #else
- #warning What do we have to do here??
- #endif
-@@ -726,7 +739,7 @@
- return res;
- }
-
--static int
-+static int
- fb_release(struct inode *inode, struct file *file)
- {
- int fbidx = GET_FB_IDX(inode->i_rdev);
-@@ -858,7 +871,7 @@
- *
- */
-
--void __init
-+void __init
- fbmem_init(void)
- {
- int i;
-@@ -906,7 +919,7 @@
-
- if (!options || !*options)
- return 0;
--
-+
- if (!strncmp(options, "scrollback:", 11)) {
- options += 11;
- if (*options) {
-@@ -932,7 +945,7 @@
- }
- return 0;
- }
--
-+
- if (!strncmp(options, "vc:", 3)) {
- options += 3;
- if (*options)
---- linux-2.4.27/drivers/video/font_acorn_8x8.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/font_acorn_8x8.c
-@@ -11,33 +11,33 @@
- /* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */
- /* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */
- /* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */
--/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 06 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 07 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 08 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 09 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 0F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */
- /* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */
--/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 12 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 13 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 14 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 15 */ 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x06, 0x3c, 0x00,
-+/* 16 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 17 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 18 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 19 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1A */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1B */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1C */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 1D */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */
- /* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */
--/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
-+/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */
- /* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */
- /* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */
- /* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */
-@@ -132,55 +132,55 @@
- /* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */
- /* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */
- /* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */
--/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
--/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*  */
-+/* 80 */ 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x30, 0x60,
-+/* 81 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 82 */ 0x0c, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 83 */ 0x18, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 84 */ 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 85 */ 0x30, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 86 */ 0x3c, 0x66, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* 87 */ 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x60,
-+/* 88 */ 0x3c, 0x66, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 89 */ 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 8A */ 0x30, 0x18, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
-+/* 8B */ 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8C */ 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8D */ 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* 8E */ 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
-+/* 8F */ 0x18, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x66, 0x00,
-+/* 90 */ 0x0c, 0x18, 0x7e, 0x60, 0x7c, 0x60, 0x7e, 0x00,
-+/* 91 */ 0x00, 0x00, 0x3f, 0x0d, 0x3f, 0x6c, 0x3f, 0x00,
-+/* 92 */ 0x3f, 0x66, 0x66, 0x7f, 0x66, 0x66, 0x67, 0x00,
-+/* 93 */ 0x3c, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 94 */ 0x66, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 95 */ 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* 96 */ 0x3c, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 97 */ 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* 98 */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c,
-+/* 99 */ 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00,
-+/* 9A */ 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00,
-+/* 9B */ 0x08, 0x3e, 0x6b, 0x68, 0x6b, 0x3e, 0x08, 0x00,
-+/* 9C */ 0x1c, 0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00,
-+/* 9D */ 0x66, 0x3c, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
-+/* 9E */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* 9F */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* A0 */ 0x0c, 0x18, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00,
-+/* A1 */ 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00,
-+/* A2 */ 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00,
-+/* A3 */ 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00,
-+/* A4 */ 0x36, 0x6c, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x00,
-+/* A5 */ 0x36, 0x6c, 0x00, 0x66, 0x76, 0x6e, 0x66, 0x00,
-+/* A6 */ 0x1c, 0x06, 0x1e, 0x36, 0x1e, 0x00, 0x3e, 0x00,
-+/* A7 */ 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00,
-+/* A8 */ 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3c, 0x00,
-+/* A9 */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* AA */ 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* AB */ 0x40, 0xc0, 0x40, 0x4f, 0x41, 0x0f, 0x08, 0x0f,
-+/* AC */ 0x40, 0xc0, 0x40, 0x48, 0x48, 0x0a, 0x0f, 0x02,
-+/* AD */ 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
-+/* AE */ 0x00, 0x33, 0x66, 0xcc, 0xcc, 0x66, 0x33, 0x00,
-+/* AF */ 0x00, 0xcc, 0x66, 0x33, 0x33, 0x66, 0xcc, 0x00,
- /* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
- /* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
- /* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
-@@ -229,37 +229,37 @@
- /* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
- /* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
- /* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
--/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* E0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E1 */ 0x3c, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x6c, 0xc0,
-+/* E2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E6 */ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x60,
-+/* E7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E8 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* E9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EA */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* ED */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* EF */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F0 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F1 */ 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
-+/* F2 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F3 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F4 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F5 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F6 */ 0x00, 0x18, 0x00, 0xff, 0x00, 0x18, 0x00, 0x00,
-+/* F7 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* F8 */ 0x3c, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
-+/* F9 */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FA */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
-+/* FB */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FC */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
-+/* FD */ 0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00,
-+/* FE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
- /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
---- linux-2.4.27/drivers/video/pm3fb.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/pm3fb.c
-@@ -5,7 +5,6 @@
- * Based on code written by:
- * Sven Luther, <luther@dpt-info.u-strasbg.fr>
- * Alan Hourihane, <alanh@fairlite.demon.co.uk>
-- * Russel King, <rmk@arm.linux.org.uk>
- * Based on linux/drivers/video/skeletonfb.c:
- * Copyright (C) 1997 Geert Uytterhoeven
- * Based on linux/driver/video/pm2fb.c:
-@@ -16,14 +15,9 @@
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
-- * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
-+ * $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $
- *
- * CHANGELOG:
-- * Wed Nov 13 11:19:34 MET 2002, v 1.4.11C: option flatpanel: wasn't available in module, fixed.
-- * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
-- * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
-- * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
-- * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
- * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
- * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
- * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
-@@ -54,8 +48,8 @@
- */
-
- #include <linux/config.h>
--#include <linux/module.h>
- #include <linux/version.h>
-+#include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/string.h>
-@@ -81,7 +75,6 @@
-
- #include <asm/io.h>
- #include <asm/uaccess.h>
--
- #ifdef CONFIG_FB_OF
- #include <asm/prom.h>
- #endif
-@@ -129,7 +122,6 @@
- unsigned long refresh;
- unsigned long powerdown;
- };
--typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
- #define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
- #define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
-
-@@ -192,21 +184,13 @@
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}}, {
- "1024x768-74-32", {
-- 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-- 806, 1024, 0, 32,
-- PM3VideoControl_ENABLE |
-- PM3VideoControl_HSYNC_ACTIVE_HIGH
-- |
-- PM3VideoControl_VSYNC_ACTIVE_HIGH
-- | PM3VideoControl_PIXELSIZE_32BIT}},
--/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
-- {
-- "SGI1600SW", {
-- 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
-- 1056, 1600, 0, 8,
-- PM3VideoControl_ENABLE|
-- PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
-- PM3VideoControl_PIXELSIZE_32BIT}},
-+ 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-+ 806, 1024, 0, 32,
-+ PM3VideoControl_ENABLE |
-+ PM3VideoControl_HSYNC_ACTIVE_HIGH
-+ |
-+ PM3VideoControl_VSYNC_ACTIVE_HIGH
-+ | PM3VideoControl_PIXELSIZE_32BIT}},
- /* ##### auto-generated mode, by fbtimings2pm3 */
- /* Generated mode : "640x480-60" */
- {
-@@ -555,11 +539,9 @@
- short noaccel[PM3_MAX_BOARD];
- char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
- short depth[PM3_MAX_BOARD];
--short flatpanel[PM3_MAX_BOARD];
- static struct display disp[PM3_MAX_BOARD];
- static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
- short printtimings = 0;
--short forcesize[PM3_MAX_BOARD];
-
- /* ********************* */
- /* ***** prototype ***** */
-@@ -567,8 +549,7 @@
- /* card-specific */
- static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
- /* permedia3-specific */
--static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
--static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
-+static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
- static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
- static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r);
-@@ -684,7 +665,7 @@
- NULL, NULL
- };
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- struct fbgen_hwswitch pm3fb_switch = {
- pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
- pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, pm3fb_setcolreg,
-@@ -697,7 +678,7 @@
- fbgen_get_fix, fbgen_get_var, fbgen_set_var,
- fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, pm3fb_ioctl, NULL, NULL
- };
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- #ifdef PM3FB_USE_ACCEL
- #ifdef FBCON_HAS_CFB32
- static struct display_switch pm3fb_cfb32 = {
-@@ -728,75 +709,52 @@
- #endif /* FBCON_HAS_CFB8 */
- #endif /* PM3FB_USE_ACCEL */
-
--/* ****************************** */
--/* ***** card-specific data ***** */
--/* ****************************** */
--struct pm3fb_card_timings {
-- unsigned long memsize; /* 0 for last value (i.e. default) */
-- struct pm3fb_timings memt;
--};
--
--static struct pm3fb_card_timings t_FormacProFormance3[] = {
-- { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
-- { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
--};
--
--static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
-- { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
-- { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
--};
--
--static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
-- { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
-- { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
--};
--
-+/* ********************************** */
-+/* ***** card-specific function ***** */
-+/* ********************************** */
- static struct {
- char cardname[32]; /* recognized card name */
- u16 subvendor; /* subvendor of the card */
- u16 subdevice; /* subdevice of the card */
- u8 func; /* function of the card to which the extra init apply */
- void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
-- struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
-+ struct pm3fb_timings memt; /* default timing for the board WARNING : might be *card* - specific */
- } cardbase[] = {
-- { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
-- { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
-- t_AppianJeronimo2000
-- },
-+ { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL, PM3FB_UNKNOWN_TIMINGS },
- { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
-- t_AppianJeronimo2000
-+ {0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} /* also in pm3fb_j2000_setup */
- },
- { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
-- t_FormacProFormance3
-+ { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} /* from the 16Mb ProFormance 3 */
- },
-- { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
-+ { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
- { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
-- t_3DLabsOxygenVX1
-+ { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000 }
- },
-- { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
-- { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
-- { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
-- { "\0", 0x0, 0x0, 0, NULL, NULL }
-+ { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, PM3FB_UNKNOWN_TIMINGS },
-+ { "\0", 0x0, 0x0, 0, NULL, PM3FB_UNKNOWN_TIMINGS }
- };
-
--/* ********************************** */
--/* ***** card-specific function ***** */
--/* ********************************** */
- static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
- { /* the appian j2000 require more initialization of the second head */
- /* l_fb_info must point to the _second_ head of the J2000 */
-
- DTRACE;
--
-- l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
-+
-+ /* Memory timings for the Appian J2000 board. also in cardbase */
-+ l_fb_info->memt.caps = 0x02e311B8;
-+ l_fb_info->memt.timings = 0x07424905;
-+ l_fb_info->memt.control = 0x0c000003;
-+ l_fb_info->memt.refresh = 0x00000061;
-+ l_fb_info->memt.powerdown = 0x00000000;
-
- pm3fb_write_memory_timings(l_fb_info);
- }
-
--/* *************************************** */
--/* ***** permedia3-specific function ***** */
--/* *************************************** */
--static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
-+static int pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
- {
- l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
- l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
-@@ -811,35 +769,20 @@
- (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
- {
- printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
-- return(pm3fb_try_memory_timings(l_fb_info));
-- }
-- return(pm3fb_timing_ok);
--}
--
--static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
--{
-- if (cardbase[l_fb_info->board_type].c_memt)
-- {
-- int i = 0, done = 0;
-- while (!done)
-+ if ((cardbase[l_fb_info->board_type].memt.caps != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.timings != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.control != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.refresh != PM3FB_UNKNOWN_TIMING_VALUE) &&
-+ (cardbase[l_fb_info->board_type].memt.powerdown != PM3FB_UNKNOWN_TIMING_VALUE))
- {
-- if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
-- || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
-- { /* will use the 0-sized timings by default */
-- done = 1;
-- l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
-- printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
-- l_fb_info->board_num,
-- cardbase[l_fb_info->board_type].cardname,
-- cardbase[l_fb_info->board_type].c_memt[i].memsize);
-- pm3fb_write_memory_timings(l_fb_info);
-- return(pm3fb_timing_retry);
-- }
-- i++;
-+ l_fb_info->memt = cardbase[l_fb_info->board_type].memt;
-+ printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s)\n", l_fb_info->board_num, cardbase[l_fb_info->board_type].cardname);
-+ pm3fb_write_memory_timings(l_fb_info);
- }
-- } else
-- return(pm3fb_timing_problem);
-- return(pm3fb_timing_ok);
-+ else
-+ return(1);
-+ }
-+ return(0);
- }
-
- static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
-@@ -874,6 +817,10 @@
- PM3RD_SClkControl_ENABLE);
- }
-
-+/* *************************************** */
-+/* ***** permedia3-specific function ***** */
-+/* *************************************** */
-+
- static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r)
- {
-@@ -1068,7 +1015,6 @@
- /* write the mode to registers */
- static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
- {
-- char tempsync = 0x00, tempmisc = 0x00;
- DTRACE;
-
- PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
-@@ -1198,26 +1144,22 @@
- /*
- PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
- */
-- if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
-- PM3VideoControl_HSYNC_ACTIVE_HIGH)
-- tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-- if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
-- PM3VideoControl_VSYNC_ACTIVE_HIGH)
-- tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
--
-- PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
-- DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
--
-- if (flatpanel[l_fb_info->board_num])
- {
-- PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
-- PM3_WAIT(2);
-- PM3_WRITE_REG(PM3VSConfiguration, 0x06);
-- PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
-- tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
-+ char tempsync = 0x00;
-+
-+ if ((l_fb_info->current_par->
-+ video & PM3VideoControl_HSYNC_MASK) ==
-+ PM3VideoControl_HSYNC_ACTIVE_HIGH)
-+ tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-+ if ((l_fb_info->current_par->
-+ video & PM3VideoControl_VSYNC_MASK) ==
-+ PM3VideoControl_VSYNC_ACTIVE_HIGH)
-+ tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
-+
-+ PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
-+ DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
- }
-- else
-- PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
-+ PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
-
- switch (l_fb_info->current_par->depth) {
- case 8:
-@@ -1226,7 +1168,8 @@
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
- PM3RD_ColorFormat_CI8_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-- tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 12:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1235,8 +1178,9 @@
- PM3RD_ColorFormat_4444_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 15:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1245,8 +1189,9 @@
- PM3RD_ColorFormat_5551_FRONT_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 16:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1255,8 +1200,9 @@
- PM3RD_ColorFormat_565_FRONT_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
- PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- case 32:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
-@@ -1264,12 +1210,12 @@
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
- PM3RD_ColorFormat_8888_COLOR |
- PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
-- tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-- PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-+ PM3_WRITE_DAC_REG(PM3RD_MiscControl,
-+ PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
-+ PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE);
- break;
- }
-- PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
--
-+
- PM3_SHOW_CUR_MODE;
- }
-
-@@ -1391,9 +1337,8 @@
-
- static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
- {
-- unsigned long memsize = 0, tempBypass, i, temp1, temp2;
-+ unsigned long memsize, tempBypass, i, temp1, temp2;
- u16 subvendor, subdevice;
-- pm3fb_timing_result ptr;
-
- DTRACE;
-
-@@ -1439,7 +1384,7 @@
-
- /* card-specific setup is done, we preserve the final
- memory timing for future reference */
-- if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
-+ if (pm3fb_preserve_memory_timings(l_fb_info)) { /* memory timings were wrong ! oops.... */
- return(0);
- }
-
-@@ -1465,12 +1410,12 @@
- temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
- #endif
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
- temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- /* Let's check for wrapover, write will fail at 16MB boundary */
- if (temp1 == (i * 0x00345678))
- memsize = i;
-@@ -1513,7 +1458,7 @@
- ((i - 32) * 1048576)));
- #endif
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
-@@ -1522,7 +1467,7 @@
- temp2 =
- fb_readl((l_fb_info->v_fb +
- ((i - 32) * 1048576)));
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
- memsize = i;
- else
-@@ -1539,21 +1484,8 @@
-
- DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
-
-- if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
-- {
-- printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
-- memsize = 1048576 * forcesize[l_fb_info->board_num];
-- }
--
- l_fb_info->fb_size = memsize;
--
-- if (ptr == pm3fb_timing_retry)
-- {
-- printk(KERN_WARNING "pm3fb: retrying memory timings check");
-- if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
-- return(0);
-- }
--
-+
- return (memsize);
- }
-
-@@ -1572,7 +1504,7 @@
- writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
- #endif
- #endif
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
- #endif
- }
-@@ -1601,7 +1533,7 @@
- disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
- l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
- l_fb_info->gen.info.changevar = NULL;
-- l_fb_info->gen.info.node = B_FREE;
-+ l_fb_info->gen.info.node = -1;
- l_fb_info->gen.info.fbops = &pm3fb_ops;
- l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
- if (fontn[l_fb_info->board_num][0])
-@@ -1766,7 +1698,6 @@
- }
-
- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(PM3FBWriteMode,
- PM3FBWriteMode_WriteEnable |
- PM3FBWriteMode_OpaqueSpan |
-@@ -1787,7 +1718,9 @@
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
- else
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
--
-+
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
-+
- switch (l_fb_info->current_par->depth) {
- case 8:
- PM3_SLOW_WRITE_REG(PM3DitherMode,
-@@ -1843,10 +1776,7 @@
- height = height * fontheight(p);
- c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
-- /* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
-- we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */
-- if ((l_fb_info->current_par->width > 1600) ||
-- (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
-+ if (l_fb_info->current_par->width > 1600) {
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
-@@ -1868,7 +1798,7 @@
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
-- } else {
-+ } else { /* block fills in 32bpp are hard, but in low res (width <= 1600 :-) we can use 16bpp operations */
- PM3_WAIT(8);
-
- PM3_WRITE_REG(PM3FBBlockColor, c);
-@@ -1993,10 +1923,7 @@
-
- PM3_WAIT(4);
-
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
-@@ -2007,23 +1934,14 @@
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(width)) |
-- (PM3Render2D_Height(height)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(width)) |
-- (PM3Render2D_Height(height)));
--
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(width)) |
-+ (PM3Render2D_Height(height)));
-+
- pm3fb_wait_pm3(l_fb_info);
- }
-
-@@ -2049,69 +1967,45 @@
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
--
-+
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-+
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset
- (p->var.xoffset +
- sx)) | (PM3RectanglePosition_YOffset(p->
- var.
- yoffset)));
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(p->var.xres - sx)) |
-- (PM3Render2D_Height(p->var.yres)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(p->var.xres - sx)) |
-- (PM3Render2D_Height(p->var.yres)));
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(p->var.xres - sx)) |
-+ (PM3Render2D_Height(p->var.yres)));
- }
--
-+
- /* bottom margin left -> right */
- PM3_WAIT(4);
--
-+
- PM3_WRITE_REG(PM3Config2D,
-- PM3Config2D_UseConstantSource |
-- PM3Config2D_ForegroundROPEnable |
-- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
-- PM3Config2D_FBWriteEnable);
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3ForegroundColor, c);
-- else
-- PM3_WRITE_REG(PM3FBBlockColor, c);
--
--
-+ PM3Config2D_UseConstantSource |
-+ PM3Config2D_ForegroundROPEnable |
-+ (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
-+ PM3Config2D_FBWriteEnable);
-+
-+ PM3_WRITE_REG(PM3FBBlockColor, c);
-+
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(p->var.xoffset)) |
- (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
--
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- PM3Render2D_SpanOperation |
-- (PM3Render2D_Width(p->var.xres)) |
-- (PM3Render2D_Height(p->var.yres - sy)));
-- else
-- PM3_WRITE_REG(PM3Render2D,
-- PM3Render2D_XPositive |
-- PM3Render2D_YPositive |
-- PM3Render2D_Operation_Normal |
-- (PM3Render2D_Width(p->var.xres)) |
-- (PM3Render2D_Height(p->var.yres - sy)));
-+
-+ PM3_WRITE_REG(PM3Render2D,
-+ PM3Render2D_XPositive |
-+ PM3Render2D_YPositive |
-+ PM3Render2D_Operation_Normal |
-+ (PM3Render2D_Width(p->var.xres)) |
-+ (PM3Render2D_Height(p->var.yres - sy)));
-
- pm3fb_wait_pm3(l_fb_info);
- }
-@@ -2289,7 +2183,7 @@
- int c, int yy, int xx)
- {
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-+ u8 *cdat, asx = 0, asy = 0, o_x, o_y;
- u32 fgx, bgx, ldat;
- int sx, sy, i;
-
-@@ -2399,7 +2293,7 @@
- int xx)
- {
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-+ u8 *cdat, asx = 0, asy = 0, o_x, o_y;
- u32 fgx, bgx, ldat;
- int sx, sy, i, j;
- u16 sc;
-@@ -2517,12 +2411,7 @@
- yy = yy * fontheight(p);
-
- if (l_fb_info->current_par->depth == 8)
-- {
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
-- else
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
-- }
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
-
- PM3_WAIT(3);
-
-@@ -2548,12 +2437,7 @@
- pm3fb_wait_pm3(l_fb_info);
-
- if (l_fb_info->current_par->depth == 8)
-- {
-- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
-- else
-- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
-- }
-+ PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
- }
-
- #endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-@@ -2641,25 +2525,12 @@
- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
- if (!(depth_supported(bd))) {
-- printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
-- bds, board_num);
-+ DPRINTK(1, "Invalid depth: %s\n", bds);
- return;
- }
- depth[board_num] = bd;
- }
-
--static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
--{
-- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
--
-- if (bd > 64) {
-- printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
-- bds, board_num);
-- return;
-- }
-- forcesize[board_num] = bd;
--}
--
- static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
- {
- char *next;
-@@ -2753,12 +2624,6 @@
- pm3fb_bootdepth_setup(options, bn);
- } else if (!strncmp(options, "printtimings", 12)) {
- printtimings = 1;
-- } else if (!strncmp(options, "flatpanel:", 10)) {
-- options = pm3fb_boardnum_setup(options + 10, &bn);
-- flatpanel[bn] = 1;
-- } else if (!strncmp(options, "forcesize:", 10)) {
-- options = pm3fb_boardnum_setup(options + 10, &bn);
-- pm3fb_forcesize_setup(options, bn);
- }
- options = next;
- }
-@@ -3496,7 +3361,7 @@
- pci_resource_start(l_fb_info->dev, 1);
- l_fb_info->v_fb = (unsigned char *) -1;
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* full resource management, new in linux-2.4.x */
-+#ifdef KERNEL_2_4 /* full resource management, new in linux-2.4.x */
- if (!request_mem_region
- ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
- "pm3fb")) {
-@@ -3513,10 +3378,8 @@
- l_fb_info->board_num);
- continue;
- }
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-- if (forcesize[l_fb_info->board_num])
-- l_fb_info->fb_size = forcesize[l_fb_info->board_num];
--
-+#endif /* KERNEL_2_4 */
-+
- l_fb_info->fb_size =
- pm3fb_size_memory(l_fb_info);
-
-@@ -3612,7 +3475,7 @@
- /* ***** standard FB API init functions ***** */
- /* ****************************************** */
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- int __init pm3fb_setup(char *options)
- #endif
- #ifdef KERNEL_2_2
-@@ -3628,12 +3491,12 @@
- PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
- g_options[PM3_OPTIONS_SIZE - 1] = 0;
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- return (0);
- #endif
- }
-
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- int __init pm3fb_init(void)
- #endif
- #ifdef KERNEL_2_2
-@@ -3642,7 +3505,7 @@
- {
- DTRACE;
-
-- DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
-+ DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /home/pm3fb/pm3fb/pm3fb.c,v 1.139 2001/08/28 08:13:54 dolbeau Exp $");
-
- pm3fb_real_setup(g_options);
-
-@@ -3651,7 +3514,7 @@
- if (!fb_info[0].dev) { /* not even one board ??? */
- DPRINTK(1, "No PCI Permedia3 board detected\n");
- }
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- return (0);
- #endif
- }
-@@ -3754,11 +3617,7 @@
- MODULE_PARM(depth,PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
- MODULE_PARM_DESC(depth,"boot-time depth");
- MODULE_PARM(printtimings, "h");
--MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
--MODULE_PARM(forcesize, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
--MODULE_PARM_DESC(forcesize, "force specified memory size");
--MODULE_PARM(flatpanel, PM3_MAX_BOARD_MODULE_ARRAY_SHORT);
--MODULE_PARM_DESC(flatpanel, "flatpanel (LCD) support (preliminary)");
-+MODULE_PARM_DESC(printtimings, "print the memory timngs of the card(s)");
- /*
- MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
- MODULE_GENERIC_TABLE(gtype,name)
-@@ -3803,11 +3662,6 @@
- sprintf(ts, ",depth:%d:%d", i, depth[i]);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
-- if (flatpanel[i])
-- {
-- sprintf(ts, ",flatpanel:%d:", i);
-- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-- }
- }
- g_options[PM3_OPTIONS_SIZE - 1] = '\0';
- DPRINTK(1, "pm3fb use options: %s\n", g_options);
-@@ -3837,14 +3691,14 @@
- if (l_fb_info->vIOBase !=
- (unsigned char *) -1) {
- pm3fb_unmapIO(l_fb_info);
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-+#ifdef KERNEL_2_4
- release_mem_region(l_fb_info->p_fb,
- l_fb_info->
- fb_size);
- release_mem_region(l_fb_info->
- pIOBase,
- PM3_REGS_SIZE);
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
- }
- unregister_framebuffer(&l_fb_info->gen.
- info);
---- linux-2.4.27/drivers/video/pm3fb.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/pm3fb.h
-@@ -8,7 +8,7 @@
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
-- * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
-+ * $Header: /home/pm3fb/pm3fb/pm3fb.h,v 1.30 2001/08/22 09:13:46 dolbeau Exp $
- *
- */
-
-@@ -92,7 +92,6 @@
- #define PM3MemBypassWriteMask 0x1008
- #define PM3MemScratch 0x1010
- #define PM3LocalMemCaps 0x1018
-- #define PM3LocalMemCaps_NoWriteMask (1 << 28)
- #define PM3LocalMemTimings 0x1020
- #define PM3LocalMemControl 0x1028
- #define PM3LocalMemRefresh 0x1030
-@@ -1121,10 +1120,6 @@
-
- /* kernel -specific definitions */
- /* what kernel is this ? */
--#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
--#define KERNEL_2_5
--#endif
--
- #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
- #define KERNEL_2_4
- #endif
-@@ -1138,8 +1133,8 @@
- #endif
- #endif
-
--#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
--#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
-+#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4))
-+#error "Only kernel 2.2.x and kernel 2.4.y might work"
- #endif
-
- /* not sure if/why it's needed. doesn't work without on my PowerMac... */
-@@ -1147,11 +1142,6 @@
- #define MUST_BYTESWAP
- #endif
-
--/* for compatibility between 2.5, 2.4 and 2.2 */
--#ifndef B_FREE
--#define B_FREE -1
--#endif
--
- /* permedia3 -specific definitions */
- #define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
- #define PICOS2KHZ(a) (1000000000UL/(a))
-@@ -1219,10 +1209,10 @@
- #define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
- #endif /* MUST_BYTESWAP */
- #endif /* KERNEL_2_2 */
--#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
-+#ifdef KERNEL_2_4 /* native-endian access */
- #define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
- #define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
--#endif /* KERNEL_2_4 or KERNEL_2_5 */
-+#endif /* KERNEL_2_4 */
-
-
- #define depth2bpp(d) ((d + 7L) & ~7L)
---- linux-2.4.27/drivers/video/sa1100fb.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/sa1100fb.c
-@@ -23,11 +23,11 @@
- * Thank you.
- *
- * Known problems:
-- * - With the Neponset plugged into an Assabet, LCD powerdown
-- * doesn't work (LCD stays powered up). Therefore we shouldn't
-- * blank the screen.
-- * - We don't limit the CPU clock rate nor the mode selection
-- * according to the available SDRAM bandwidth.
-+ * - With the Neponset plugged into an Assabet, LCD powerdown
-+ * doesn't work (LCD stays powered up). Therefore we shouldn't
-+ * blank the screen.
-+ * - We don't limit the CPU clock rate nor the mode selection
-+ * according to the available SDRAM bandwidth.
- *
- * Other notes:
- * - Linear grayscale palettes and the kernel.
-@@ -41,6 +41,17 @@
- * David Neuer. It's around 8 lines of C code, plus another 4 to
- * detect if we are using grayscale.
- *
-+ * - The following must never be specified in a panel definition:
-+ * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
-+ *
-+ * - The following should be specified:
-+ * either LCCR0_Color or LCCR0_Mono
-+ * either LCCR0_Sngl or LCCR0_Dual
-+ * either LCCR0_Act or LCCR0_Pas
-+ * either LCCR3_OutEnH or LCCD3_OutEnL
-+ * either LCCR3_PixRsEdg or LCCR3_PixFlEdg
-+ * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
-+ *
- * Code Status:
- * 1999/04/01:
- * - Driver appears to be working for Brutus 320x200x8bpp mode. Other
-@@ -147,6 +158,10 @@
- *
- * 2001/10/12: <rmk@arm.linux.org.uk>
- * - Add patch 681/1 and clean up stork definitions.
-+ *
-+ * 2002/02/21: <abraham@2d3d.co.za>
-+ * - Added support for ICP LCD-Kit01 on Frodo.
-+ * - Added support for backlight via CPLDs on Frodo.
- */
-
- #include <linux/config.h>
-@@ -169,6 +184,7 @@
- #include <asm/mach-types.h>
- #include <asm/uaccess.h>
- #include <asm/arch/assabet.h>
-+#include <asm/arch/shannon.h>
-
- #include <video/fbcon.h>
- #include <video/fbcon-mfb.h>
-@@ -177,11 +193,6 @@
- #include <video/fbcon-cfb16.h>
-
- /*
-- * enable this if your panel appears to have broken
-- */
--#undef CHECK_COMPAT
--
--/*
- * debugging?
- */
- #define DEBUG 0
-@@ -197,243 +208,6 @@
- void (*sa1100fb_blank_helper)(int blank);
- EXPORT_SYMBOL(sa1100fb_blank_helper);
-
--
--#ifdef CHECK_COMPAT
--static void
--sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
-- struct fb_var_screeninfo *var, u_int pcd)
--{
-- struct sa1100fb_lcd_reg shadow;
-- int different = 0;
--
-- /*
-- * These machines are good machines!
-- */
-- if (machine_is_assabet() || machine_is_h3600())
-- return;
--
-- /*
-- * The following ones are bad, bad, bad.
-- * Please make yours good!
-- */
-- if (machine_is_pangolin()) {
-- DPRINTK("Configuring Pangolin LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
-- LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
-- LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
-- LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
-- LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
--
-- DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
-- pcd, LCCR3_PixClkDiv(pcd));
-- }
-- if (machine_is_freebird()) {
-- DPRINTK("Configuring Freebird LCD\n");
--#if 1
-- shadow.lccr0 = 0x00000038;
-- shadow.lccr1 = 0x010108e0;
-- shadow.lccr2 = 0x0000053f;
-- shadow.lccr3 = 0x00000c20;
--#else
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
-- LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_DMADel(0);
-- /* Check ,Chester */
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
-- LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
-- /* Check ,Chester */
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
-- /* Check ,Chester */
-- shadow.lccr3 =
-- LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-- LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
--#endif
-- }
-- if (machine_is_brutus()) {
-- DPRINTK("Configuring Brutus LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
-- LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-- shadow.lccr3 =
-- LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-- LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
-- }
-- if (machine_is_huw_webpanel()) {
-- DPRINTK("Configuring HuW LCD\n");
-- shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
-- shadow.lccr1 = LCCR1_DisWdth(var->xres) +
-- LCCR1_HorSnchWdth(3) +
-- LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-- shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
-- shadow.lccr3 = 8 + LCCR3_OutEnH +
-- LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-- LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
-- }
-- if (machine_is_lart()) {
-- DPRINTK("Configuring LART LCD\n");
--#if defined LART_GREY_LCD
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
-- LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-- LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
--#endif
--#if defined LART_COLOR_LCD
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
-- LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
-- LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
-- LCCR3_PixFlEdg;
--#endif
--#if defined LART_VIDEO_OUT
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-- LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
-- LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
-- shadow.lccr2 =
-- LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
-- LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
-- LCCR3_PixFlEdg + LCCR3_OutEnL;
--#endif
-- }
-- if (machine_is_graphicsclient()) {
-- DPRINTK("Configuring GraphicsClient LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
-- LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
-- LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
-- LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-- }
-- if (machine_is_omnimeter()) {
-- DPRINTK("Configuring OMNI LCD\n");
-- shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
-- shadow.lccr1 =
-- LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
-- LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
-- shadow.lccr2 = LCCR2_DisHght(var->yres);
-- shadow.lccr3 =
-- LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
--//jca (GetPCD(25) << LCD3_V_PCD);
-- }
-- if (machine_is_xp860()) {
-- DPRINTK("Configuring XP860 LCD\n");
-- shadow.lccr0 =
-- LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-- LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
-- shadow.lccr1 =
-- LCCR1_DisWdth(var->xres) +
-- LCCR1_HorSnchWdth(var->hsync_len) +
-- LCCR1_BegLnDel(var->left_margin) +
-- LCCR1_EndLnDel(var->right_margin);
-- shadow.lccr2 =
-- LCCR2_DisHght(var->yres) +
-- LCCR2_VrtSnchWdth(var->vsync_len) +
-- LCCR2_BegFrmDel(var->upper_margin) +
-- LCCR2_EndFrmDel(var->lower_margin);
-- shadow.lccr3 =
-- LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-- }
--
-- /*
-- * Ok, since we're calculating these values, we want to know
-- * if the calculation is correct. If you see any of these
-- * messages _PLEASE_ report the incident to me for diagnosis,
-- * including details about what was happening when the
-- * messages appeared. --rmk, 30 March 2001
-- */
-- if (shadow.lccr0 != new_regs->lccr0) {
-- printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr1, new_regs->lccr1);
-- different = 1;
-- }
-- if (shadow.lccr1 != new_regs->lccr1) {
-- printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr1, new_regs->lccr1);
-- different = 1;
-- }
-- if (shadow.lccr2 != new_regs->lccr2) {
-- printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr2, new_regs->lccr2);
-- different = 1;
-- }
-- if (shadow.lccr3 != new_regs->lccr3) {
-- printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
-- shadow.lccr3, new_regs->lccr3);
-- different = 1;
-- }
-- if (different) {
-- printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
-- var->xres, var->hsync_len,
-- var->left_margin, var->right_margin);
-- printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
-- var->yres, var->vsync_len,
-- var->upper_margin, var->lower_margin);
--
-- printk(KERN_ERR "Please report this to Russell King "
-- "<rmk@arm.linux.org.uk>\n");
-- }
--
-- DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
-- DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
-- DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
-- DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
--}
--#else
--#define sa1100fb_check_shadow(regs,var,pcd)
--#endif
--
--
--
- /*
- * IMHO this looks wrong. In 8BPP, length should be 8.
- */
-@@ -488,42 +262,56 @@
- #endif
- #endif
-
--#ifdef CONFIG_SA1100_H3600
--static struct sa1100fb_mach_info h3600_info __initdata = {
--#ifdef CONFIG_IPAQ_H3100
-- pixclock: 407766, bpp: 4,
-+#ifdef CONFIG_SA1100_H3XXX
-+static struct sa1100fb_mach_info h3800_info __initdata = {
-+ pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
-
-- hsync_len: 26, vsync_len: 41,
-- left_margin: 4, upper_margin: 0,
-- right_margin: 4, lower_margin: 0,
-+ hsync_len: 3, vsync_len: 3,
-+ left_margin: 12, upper_margin: 10,
-+ right_margin: 17, lower_margin: 1,
-
-- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-- cmap_greyscale: 1, cmap_static: 1,
-- cmap_inverse: 1,
-+ sync: 0, cmap_static: 1,
-
-- lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
--#else
-- pixclock: 174757, bpp: 16,
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
-+};
-+
-+static struct sa1100fb_mach_info h3600_info __initdata = {
-+ pixclock: 174757, bpp: 16,
- xres: 320, yres: 240,
-
- hsync_len: 3, vsync_len: 3,
- left_margin: 12, upper_margin: 10,
- right_margin: 17, lower_margin: 1,
-
-- sync: 0,
-+ sync: 0, cmap_static: 1,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-- lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
--#endif
-+ lccr3: LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
- };
-
- static struct sa1100fb_rgb h3600_rgb_16 = {
- red: { offset: 12, length: 4, },
- green: { offset: 7, length: 4, },
- blue: { offset: 1, length: 4, },
-- transp: { offset: 0, length: 0, },
-+ transp: { offset: 0, length: 0, },
-+};
-+
-+static struct sa1100fb_mach_info h3100_info __initdata = {
-+ pixclock: 406977, bpp: 4,
-+ xres: 320, yres: 240,
-+
-+ hsync_len: 26, vsync_len: 41,
-+ left_margin: 4, upper_margin: 0,
-+ right_margin: 4, lower_margin: 0,
-+
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+ cmap_greyscale: 1,
-+ cmap_inverse: 1,
-+
-+ lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
- };
- #endif
-
-@@ -618,6 +406,58 @@
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
- static struct sa1100fb_mach_info graphicsclient_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+static struct sa1100fb_mach_info graphicsmaster_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSBITSY
-+static struct sa1100fb_mach_info adsbitsy_info __initdata = {
-+// for LQ64D343
-+ pixclock: 53500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 9, vsync_len: 9,
-+ left_margin: 54, upper_margin: 24,
-+ right_margin: 54, lower_margin: 32,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+static struct sa1100fb_mach_info adsbitsyplus_info __initdata = {
-+// for LQ64D343
- pixclock: 53500, bpp: 8,
- xres: 640, yres: 480,
-
-@@ -699,7 +539,6 @@
- lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
- };
- #endif
--
- #ifdef LART_KIT01_LCD
- static struct sa1100fb_mach_info lart_kit01_info __initdata =
- {
-@@ -707,7 +546,7 @@
- xres: 640, yres: 480,
-
- hsync_len: 64, vsync_len: 3,
-- left_margin: 122, upper_margin: 45,
-+ left_margin: 122, upper_margin: 45,
- right_margin: 10, lower_margin: 10,
-
- sync: 0,
-@@ -717,6 +556,40 @@
- };
- #endif
-
-+#ifdef CONFIG_SA1100_FRODO
-+static struct sa1100fb_mach_info frodo_kit01_info __initdata =
-+{
-+ /* best would be 41731 (25.8mhz), but we can only do 14.743mhz at 191.7mhz clock speed */
-+ pixclock: 73030, bpp: 16,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 32, vsync_len: 19,
-+ left_margin: 120, upper_margin: 33,
-+ right_margin: 17, lower_margin: 12,
-+
-+ sync: 0,
-+
-+ lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_SHANNON
-+static struct sa1100fb_mach_info shannon_info __initdata = {
-+ pixclock: 152500, bpp: 8,
-+ xres: 640, yres: 480,
-+
-+ hsync_len: 4, vsync_len: 3,
-+ left_margin: 2, upper_margin: 0,
-+ right_margin: 1, lower_margin: 0,
-+
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-+
-+ lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
-+ lccr3: LCCR3_ACBsDiv(512),
-+};
-+#endif
-+
- #ifdef CONFIG_SA1100_OMNIMETER
- static struct sa1100fb_mach_info omnimeter_info __initdata = {
- pixclock: 0, bpp: 4,
-@@ -752,7 +625,24 @@
- sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
- lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-- lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
-+};
-+#endif
-+
-+#ifdef CONFIG_SA1100_SIMPUTER
-+static struct sa1100fb_mach_info simputer_info __initdata = {
-+ pixclock: 70000, bpp: 4,
-+ xres: 320, yres: 240,
-+
-+ hsync_len: 9, vsync_len: 2,
-+ left_margin: 9, upper_margin: 0,
-+ right_margin: 2, lower_margin: 0,
-+
-+ cmap_greyscale: 1,
-+ sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT ,
-+
-+ lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
-+ lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(202),
- };
- #endif
-
-@@ -828,7 +718,6 @@
- #endif
-
-
--
- static struct sa1100fb_mach_info * __init
- sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
- {
-@@ -849,11 +738,17 @@
- #endif
- }
- #endif
--#ifdef CONFIG_SA1100_H3600
-+#ifdef CONFIG_SA1100_H3XXX
- if (machine_is_h3600()) {
- inf = &h3600_info;
- fbi->rgb[RGB_16] = &h3600_rgb_16;
- }
-+ if (machine_is_h3100()) {
-+ inf = &h3100_info;
-+ }
-+ if (machine_is_h3800()) {
-+ inf = &h3800_info;
-+ }
- #endif
- #ifdef CONFIG_SA1100_BRUTUS
- if (machine_is_brutus()) {
-@@ -876,6 +771,22 @@
- inf = &graphicsclient_info;
- }
- #endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ inf = &graphicsmaster_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSY
-+ if (machine_is_adsbitsy()) {
-+ inf = &adsbitsy_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ inf = &adsbitsyplus_info;
-+ }
-+ }
-+#endif
- #ifdef CONFIG_SA1100_HUW_WEBPANEL
- if (machine_is_huw_webpanel()) {
- inf = &huw_webpanel_info;
-@@ -897,6 +808,21 @@
- #endif
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo()) {
-+ inf = &frodo_kit01_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_SHANNON
-+ if (machine_is_shannon()) {
-+ inf = &shannon_info;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_SIMPUTER
-+ if (machine_is_simputer()) {
-+ inf = &simputer_info;
-+ }
-+#endif
- #ifdef CONFIG_SA1100_OMNIMETER
- if (machine_is_omnimeter()) {
- inf = &omnimeter_info;
-@@ -1556,7 +1482,8 @@
- unsigned int pcd;
-
- if (pixclock) {
-- pcd = get_cclk_frequency() * pixclock;
-+ pcd = cpufreq_get(0) / 100;
-+ pcd *= pixclock;
- pcd /= 10000000;
- pcd += 1; /* make up for integer math truncations */
- } else {
-@@ -1580,6 +1507,7 @@
- return pcd;
- }
-
-+
- /*
- * sa1100fb_activate_var():
- * Configures LCD Controller based on entries in var parameter. Settings are
-@@ -1659,8 +1587,6 @@
- if (pcd)
- new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
-
-- sa1100fb_check_shadow(&new_regs, var, pcd);
--
- DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
- DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
- DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-@@ -1733,6 +1659,10 @@
- if (machine_is_omnimeter())
- LEDBacklightOn();
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ frodo_cpld_set (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
-+#endif
- }
-
- /*
-@@ -1755,6 +1685,10 @@
- if (machine_is_omnimeter())
- LEDBacklightOff();
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ frodo_cpld_clear (FRODO_CPLD_GENERAL,FRODO_LCD_BACKLIGHT);
-+#endif
- }
-
- static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
-@@ -1773,20 +1707,25 @@
- if (machine_is_omnimeter())
- LCDPowerOn();
- #endif
--#ifdef CONFIG_SA1100_H3600
-- if (machine_is_h3600()) {
-- set_h3600_egpio(EGPIO_H3600_LCD_ON |
-- EGPIO_H3600_LCD_PCI |
-- EGPIO_H3600_LCD_5V_ON |
-- EGPIO_H3600_LVDD_ON);
-- }
--#endif
-+ if (machine_is_h3xxx())
-+ set_h3600_egpio( IPAQ_EGPIO_LCD_ON ); /* Turn on power to the LCD */
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 1);
- storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ sa1100fb_backlight_on(fbi);
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ ADS_CPLD_PCON &= ~ADS_PCON_PANEL_ON;
-+ ADS_CPLD_SUPPC |= ADS_SUPPC_VEE_ON;
-+ }
-+#endif
-+
- }
-
- static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
-@@ -1802,20 +1741,24 @@
- if (machine_is_huw_webpanel())
- BCR_set(BCR_TFT_NPWR);
- #endif
--#ifdef CONFIG_SA1100_H3600
-- if (machine_is_h3600()) {
-- clr_h3600_egpio(EGPIO_H3600_LCD_ON |
-- EGPIO_H3600_LCD_PCI |
-- EGPIO_H3600_LCD_5V_ON |
-- EGPIO_H3600_LVDD_ON);
-- }
--#endif
-+ if (machine_is_h3xxx())
-+ clr_h3600_egpio( IPAQ_EGPIO_LCD_ON );
- #ifdef CONFIG_SA1100_STORK
- if (machine_is_stork()) {
- storkSetLCDCPLD(0, 0);
- storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON);
- }
- #endif
-+#ifdef CONFIG_SA1100_FRODO
-+ if (machine_is_frodo())
-+ sa1100fb_backlight_off(fbi);
-+#endif
-+#ifdef CONFIG_SA1100_ADSBITSYPLUS
-+ if (machine_is_adsbitsyplus()) {
-+ ADS_CPLD_PCON |= ADS_PCON_PANEL_ON;
-+ ADS_CPLD_SUPPC &= ~ADS_SUPPC_VEE_ON;
-+ }
-+#endif
- }
-
- static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
-@@ -1911,15 +1854,29 @@
- LCCR0 |= LCCR0_LEN;
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
--#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- // From ADS doc again...same as disable
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
-- GPSR |= GPIO_GPIO24;
-+ GPDR |= GPIO_GPIO24;
-+ GPSR = GPIO_GPIO24;
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ // From ADS doc again...same as disable
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(20 * HZ / 1000);
-+ GPDR |= GPIO_GPIO24;
-+ GPSR = GPIO_GPIO24;
- }
- #endif
-
-+ if (machine_is_shannon()) {
-+ GPDR |= SHANNON_GPIO_DISP_EN;
-+ GPSR |= SHANNON_GPIO_DISP_EN;
-+ }
-+
- DPRINTK("DBAR1 = %p\n", DBAR1);
- DPRINTK("DBAR2 = %p\n", DBAR2);
- DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
-@@ -1935,7 +1892,6 @@
- DPRINTK("Disabling LCD controller\n");
-
- #ifdef CONFIG_SA1100_GRAPHICSCLIENT
--#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- /*
- * From ADS internal document:
-@@ -1944,6 +1900,22 @@
- *
- * We'll wait 20msec.
- */
-+ GPDR |= GPIO_GPIO24;
-+ GPCR |= GPIO_GPIO24;
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(20 * HZ / 1000);
-+ }
-+#endif
-+#ifdef CONFIG_SA1100_GRAPHICSMASTER
-+ if (machine_is_graphicsmaster()) {
-+ /*
-+ * From ADS internal document:
-+ * GPIO24 should be LOW at least 10msec prior to disabling
-+ * the LCD interface.
-+ *
-+ * We'll wait 20msec.
-+ */
-+ GPDR |= GPIO_GPIO24;
- GPCR |= GPIO_GPIO24;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
-@@ -1958,12 +1930,15 @@
- }
- #endif
-
-+ if (machine_is_shannon()) {
-+ GPCR |= SHANNON_GPIO_DISP_EN;
-+ }
-+
- add_wait_queue(&fbi->ctrlr_wait, &wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
-
- LCSR = 0xffffffff; /* Clear LCD Status Register */
- LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
-- enable_irq(IRQ_LCD); /* Enable LCD IRQ */
- LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */
-
- schedule_timeout(20 * HZ / 1000);
-@@ -2006,12 +1981,13 @@
- * Disable controller for clock change. If the
- * controller is already disabled, then do nothing.
- */
-- if (old_state != C_DISABLE) {
-+ if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
- fbi->state = state;
- sa1100fb_disable_controller(fbi);
- }
- break;
-
-+ case C_DISABLE_PM:
- case C_DISABLE:
- /*
- * Disable controller
-@@ -2050,6 +2026,16 @@
- }
- break;
-
-+ case C_ENABLE_PM:
-+ /*
-+ * Re-enable the controller after PM. This is not
-+ * perfect - think about the case where we were doing
-+ * a clock change, and we suspended half-way through.
-+ */
-+ if (old_state != C_DISABLE_PM)
-+ break;
-+ /* fall through */
-+
- case C_ENABLE:
- /*
- * Power up the LCD screen, enable controller, and
-@@ -2162,10 +2148,10 @@
-
- if (state == 0) {
- /* Enter D0. */
-- set_ctrlr_state(fbi, C_ENABLE);
-+ set_ctrlr_state(fbi, C_ENABLE_PM);
- } else {
- /* Enter D1-D3. Disable the LCD controller. */
-- set_ctrlr_state(fbi, C_DISABLE);
-+ set_ctrlr_state(fbi, C_DISABLE_PM);
- }
- }
- DPRINTK("done\n");
-@@ -2304,7 +2290,7 @@
- goto failed;
-
- ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
-- fbi->fb.fix.id, fbi);
-+ "LCD", fbi);
- if (ret) {
- printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
- goto failed;
---- linux-2.4.27/drivers/video/sa1100fb.h~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/sa1100fb.h
-@@ -127,6 +127,8 @@
- #define C_DISABLE_CLKCHANGE (2)
- #define C_ENABLE_CLKCHANGE (3)
- #define C_REENABLE (4)
-+#define C_DISABLE_PM (5)
-+#define C_ENABLE_PM (6)
-
- #define SA1100_NAME "SA1100"
-
---- linux-2.4.27/drivers/video/vga16fb.c~2.4.27-vrs1
-+++ linux-2.4.27/drivers/video/vga16fb.c
-@@ -142,7 +142,7 @@
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id,"VGA16 VGA");
-
-- fix->smem_start = VGA_FB_PHYS;
-+ fix->smem_start = VGA_MAP_MEM(VGA_FB_PHYS);
- fix->smem_len = VGA_FB_PHYS_LEN;
- fix->type = FB_TYPE_VGA_PLANES;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
-@@ -896,7 +896,7 @@
-
- /* XXX share VGA_FB_PHYS region with vgacon */
-
-- vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN);
-+ vga16fb.video_vbase = ioremap(VGA_MAP_MEM(VGA_FB_PHYS), VGA_FB_PHYS_LEN);
- if (!vga16fb.video_vbase) {
- printk(KERN_ERR "vga16fb: unable to map device\n");
- return -ENOMEM;
---- linux-2.4.27/fs/adfs/dir.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/adfs/dir.c
-@@ -23,7 +23,7 @@
- /*
- * For future. This should probably be per-directory.
- */
--static rwlock_t adfs_dir_lock;
-+static rwlock_t adfs_dir_lock = RW_LOCK_UNLOCKED;
-
- static int
- adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
---- linux-2.4.27/fs/adfs/map.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/adfs/map.c
-@@ -13,24 +13,27 @@
- #include <linux/adfs_fs.h>
- #include <linux/spinlock.h>
-
-+#include <asm/unaligned.h>
-+
- #include "adfs.h"
-
- /*
- * For the future...
- */
--static rwlock_t adfs_map_lock;
-+static rwlock_t adfs_map_lock = RW_LOCK_UNLOCKED;
-
-+/*
-+ * This is fun. We need to load up to 19 bits from the map at an
-+ * arbitary bit alignment. (We're limited to 19 bits by F+ version
-+ * 2).
-+ */
- #define GET_FRAG_ID(_map,_start,_idmask) \
- ({ \
-- unsigned long _v2, _frag; \
-- unsigned int _tmp; \
-- _tmp = _start >> 5; \
-- _frag = le32_to_cpu(_map[_tmp]); \
-- _v2 = le32_to_cpu(_map[_tmp + 1]); \
-- _tmp = start & 31; \
-- _frag = (_frag >> _tmp) | (_v2 << (32 - _tmp)); \
-+ unsigned char *_m = _map + (_start >> 3); \
-+ u32 _frag = get_unaligned((u32 *)_m); \
-+ _frag >>= (_start & 7); \
- _frag & _idmask; \
-- })
-+ })
-
- /*
- * return the map bit offset of the fragment frag_id in
-@@ -44,14 +47,13 @@
- const unsigned int frag_id, unsigned int *offset)
- {
- const unsigned int mapsize = dm->dm_endbit;
-- const unsigned int idmask = (1 << idlen) - 1;
-- unsigned long *map = ((unsigned long *)dm->dm_bh->b_data) + 1;
-+ const u32 idmask = (1 << idlen) - 1;
-+ unsigned char *map = dm->dm_bh->b_data + 4;
- unsigned int start = dm->dm_startbit;
- unsigned int mapptr;
-+ u32 frag;
-
- do {
-- unsigned long frag;
--
- frag = GET_FRAG_ID(map, start, idmask);
- mapptr = start + idlen;
-
-@@ -59,15 +61,17 @@
- * find end of fragment
- */
- {
-- unsigned long v2;
-+ u32 v, *_map = (u32 *)map;
-
-- while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
-+ v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
-+ while (v == 0) {
- mapptr = (mapptr & ~31) + 32;
- if (mapptr >= mapsize)
- goto error;
-+ v = le32_to_cpu(_map[mapptr >> 5]);
- }
-
-- mapptr += 1 + ffz(~v2);
-+ mapptr += 1 + ffz(~v);
- }
-
- if (frag == frag_id)
-@@ -75,8 +79,11 @@
- again:
- start = mapptr;
- } while (mapptr < mapsize);
-+ return -1;
-
- error:
-+ printk(KERN_ERR "adfs: oversized fragment 0x%x at 0x%x-0x%x\n",
-+ frag, start, mapptr);
- return -1;
-
- found:
-@@ -102,10 +109,10 @@
- const unsigned int mapsize = dm->dm_endbit + 32;
- const unsigned int idlen = asb->s_idlen;
- const unsigned int frag_idlen = idlen <= 15 ? idlen : 15;
-- const unsigned int idmask = (1 << frag_idlen) - 1;
-- unsigned long *map = (unsigned long *)dm->dm_bh->b_data;
-+ const u32 idmask = (1 << frag_idlen) - 1;
-+ unsigned char *map = dm->dm_bh->b_data;
- unsigned int start = 8, mapptr;
-- unsigned long frag;
-+ u32 frag;
- unsigned long total = 0;
-
- /*
-@@ -133,15 +140,17 @@
- * find end of fragment
- */
- {
-- unsigned long v2;
-+ u32 v, *_map = (u32 *)map;
-
-- while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
-+ v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
-+ while (v == 0) {
- mapptr = (mapptr & ~31) + 32;
- if (mapptr >= mapsize)
- goto error;
-+ v = le32_to_cpu(_map[mapptr >> 5]);
- }
-
-- mapptr += 1 + ffz(~v2);
-+ mapptr += 1 + ffz(~v);
- }
-
- total += mapptr - start;
---- linux-2.4.27/fs/adfs/super.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/adfs/super.c
-@@ -386,6 +386,14 @@
- sb->u.adfs_sb.s_size = adfs_discsize(dr, sb->s_blocksize_bits);
- sb->u.adfs_sb.s_version = dr->format_version;
- sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize;
-+
-+ printk(KERN_DEBUG "ADFS: idlen %d map bit size %d sector size %d\n",
-+ dr->idlen, 1 << dr->log2bpmb, 1 << dr->log2secsize);
-+ printk(KERN_DEBUG "ADFS: map size %d map2blk %d version %d share size %d\n",
-+ sb->u.adfs_sb.s_map_size,
-+ sb->u.adfs_sb.s_map2blk,
-+ sb->u.adfs_sb.s_version,
-+ 1 << sb->u.adfs_sb.s_log2sharesize);
-
- sb->u.adfs_sb.s_map = adfs_read_map(sb, dr);
- if (!sb->u.adfs_sb.s_map)
-@@ -393,6 +401,8 @@
-
- brelse(bh);
-
-+ printk(KERN_DEBUG "ADFS: ids per zone %d\n", sb->u.adfs_sb.s_ids_per_zone);
-+
- /*
- * set up enough so that we can read an inode
- */
---- linux-2.4.27/fs/binfmt_aout.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/binfmt_aout.c
-@@ -422,7 +422,11 @@
- start_thread(regs, ex.a_entry, current->mm->start_stack);
- if (current->ptrace & PT_PTRACED)
- send_sig(SIGTRAP, current, 0);
-+#ifndef __arm__
- return 0;
-+#else
-+ return regs->ARM_r0;
-+#endif
- }
-
- static int load_aout_library(struct file *file)
-@@ -452,8 +456,11 @@
-
- /* For QMAGIC, the starting address is 0x20 into the page. We mask
- this off to get the starting address for the page */
--
-- start_addr = ex.a_entry & 0xfffff000;
-+#ifndef __arm__
-+ start_addr = ex.a_entry & 0xfffff000;
-+#else
-+ start_addr = ex.a_entry & 0xffff8000;
-+#endif
-
- if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
- static unsigned long error_time;
---- linux-2.4.27/fs/binfmt_elf.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/binfmt_elf.c
-@@ -636,7 +636,6 @@
- }
-
- current->mm->start_stack = bprm->p;
--
- /* Now we do a little grungy work by mmaping the ELF image into
- the correct location in memory. At this point, we assume that
- the image should be loaded at fixed address, not at a variable
---- linux-2.4.27/fs/exec.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/exec.c
-@@ -315,6 +315,7 @@
- spin_unlock(&tsk->mm->page_table_lock);
-
- /* no need for flush_tlb */
-+ memc_update_addr(tsk->mm, *pte, address);
- return;
- out:
- spin_unlock(&tsk->mm->page_table_lock);
---- linux-2.4.27/fs/jffs/inode-v23.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/jffs/inode-v23.c
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
-+ * $Id: inode-v23.c,v 1.72 2002/01/31 11:42:57 cdavies Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -48,6 +48,7 @@
- #include <linux/stat.h>
- #include <linux/blkdev.h>
- #include <linux/quotaops.h>
-+#include <linux/compatmac.h>
- #include <asm/semaphore.h>
- #include <asm/byteorder.h>
- #include <asm/uaccess.h>
-@@ -58,6 +59,11 @@
- #include "jffs_proc.h"
- #endif
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
-+#define minor(x) MINOR(x)
-+#define major(x) MAJOR(x)
-+#endif
-+
- static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-
- static struct super_operations jffs_ops;
-@@ -81,7 +87,7 @@
- D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
- kdevname(dev)));
-
-- if (MAJOR(dev) != MTD_BLOCK_MAJOR) {
-+ if (major(dev) != MTD_BLOCK_MAJOR) {
- printk(KERN_WARNING "JFFS: Trying to mount a "
- "non-mtd device.\n");
- return 0;
-@@ -358,7 +364,7 @@
- inode->i_nlink = raw_inode->nlink;
- inode->i_uid = raw_inode->uid;
- inode->i_gid = raw_inode->gid;
-- inode->i_rdev = 0;
-+ inode->i_rdev = NODEV;
- inode->i_size = raw_inode->dsize;
- inode->i_atime = raw_inode->atime;
- inode->i_mtime = raw_inode->mtime;
---- linux-2.4.27/fs/jffs/intrep.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/jffs/intrep.c
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
-+ * $Id: intrep.c,v 1.104 2002/03/05 14:07:39 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -772,6 +772,9 @@
- __u32 free_chunk_size1;
- __u32 free_chunk_size2;
-
-+ __u32 largest_hole = 0;
-+ __u32 hole_end_offset = 0;
-+ __u32 head_offset;
-
- #define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
- int num_free_space = 0; /* Flag err if more than TWO
-@@ -884,6 +887,21 @@
- (unsigned int) start,
- (unsigned int)(test_start - start)));
-
-+ D1(printk("Reducing start to 0x%x from 0x%x\n",
-+ test_start, start));
-+ if (largest_hole < test_start - start){
-+
-+ D3(printk("was hole = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ if (fmc->head) {
-+ largest_hole = test_start - start;
-+ hole_end_offset = test_start;
-+ }
-+ }
-+
-+ D3(printk("now = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+
- /* below, space from "start" to "pos" will be marked dirty. */
- start = test_start;
-
-@@ -956,6 +974,19 @@
- num_free_space++;
- D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start, (unsigned int) (pos - start)));
-+
-+ if (largest_hole < pos - start) {
-+
-+ D3(printk("was hole = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ if (fmc->head){
-+ largest_hole = pos - start;
-+ hole_end_offset = pos;
-+ }
-+
-+ D3(printk("now = %x end_offset = %x\n",
-+ largest_hole, hole_end_offset));
-+ }
- }else{
- num_free_spc_not_accp++;
- D1(printk("Free space (#%i) found but *Not* accepted: Starting "
-@@ -968,7 +999,7 @@
- (unsigned int) start, (unsigned int) (pos - start)));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), 0);
-- }
-+ }
-
- }
- if(num_free_space > NUMFREEALLOWED){
-@@ -1002,9 +1033,11 @@
- to scan for the magic pattern. */
- D1(printk("*************** Dirty flash memory or "
- "bad inode: "
-- "hexdump(pos = 0x%lx, len = 128):\n",
-- (long)pos));
-- D1(jffs_hexdump(fmc->mtd, pos, 128));
-+ "hexdump(pos = 0x%lx, len = %d):\n",
-+ (long)pos,
-+ end - pos > 128 ? 128 : end - pos));
-+ D1(jffs_hexdump(fmc->mtd, pos,
-+ end - pos > 128 ? 128 : end - pos));
-
- for (pos += 4; pos < end; pos += 4) {
- switch (flash_read_u32(fmc->mtd, pos)) {
-@@ -1197,12 +1230,6 @@
-
- return -ENOMEM;
- }
-- if ((err = jffs_insert_node(c, 0, &raw_inode,
-- name, node)) < 0) {
-- printk("JFFS: Failed to handle raw inode. "
-- "(err = %d)\n", err);
-- break;
-- }
- if (raw_inode.rename) {
- struct jffs_delete_list *dl
- = (struct jffs_delete_list *)
-@@ -1226,6 +1253,12 @@
- c->delete_list = dl;
- node->data_size = 0;
- }
-+ if ((err = jffs_insert_node(c, 0, &raw_inode,
-+ name, node)) < 0) {
-+ printk("JFFS: Failed to handle raw inode. "
-+ "(err = %d)\n", err);
-+ break;
-+ }
- D3(jffs_print_node(node));
- node = 0; /* Don't free the node! */
- }
-@@ -1242,7 +1275,19 @@
- jffs_free_node(node);
- DJM(no_jffs_node--);
- }
-- jffs_build_end(fmc);
-+ if (fmc->head && fmc->tail_extra &&
-+ fmc->head->offset + fmc->flash_size -
-+ fmc->tail_extra->offset - fmc->tail_extra->size > largest_hole) {
-+ head_offset = fmc->head->offset;
-+ }
-+ else {
-+ head_offset = hole_end_offset;
-+ }
-+
-+ if (jffs_build_end(fmc, head_offset) < 0) {
-+ D(printk("jffs_build_end() failed\n"));
-+ return -ENOMEM;
-+ }
-
- /* Free read buffer */
- kfree (read_buf);
---- linux-2.4.27/fs/jffs/jffs_fm.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/jffs/jffs_fm.c
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
-+ * $Id: jffs_fm.c,v 1.29 2002/01/22 09:48:16 cdavies Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -20,8 +20,14 @@
- #include <linux/slab.h>
- #include <linux/blkdev.h>
- #include <linux/jffs.h>
-+#include <linux/compatmac.h>
- #include "jffs_fm.h"
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)
-+#define minor(x) MINOR(x)
-+#define major(x) MAJOR(x)
-+#endif
-+
- #if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
- static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
- #endif
-@@ -46,7 +52,7 @@
- }
- DJM(no_jffs_fmcontrol++);
-
-- mtd = get_mtd_device(NULL, MINOR(dev));
-+ mtd = get_mtd_device(NULL, minor(dev));
-
- if (!mtd) {
- kfree(fmc);
-@@ -89,8 +95,8 @@
-
- /* When the flash memory scan has completed, this function should be called
- before use of the control structure. */
--void
--jffs_build_end(struct jffs_fmcontrol *fmc)
-+int
-+jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset)
- {
- D3(printk("jffs_build_end()\n"));
-
-@@ -99,13 +105,100 @@
- fmc->tail = fmc->tail_extra;
- }
- else if (fmc->head_extra) {
-- fmc->tail_extra->next = fmc->head;
-- fmc->head->prev = fmc->tail_extra;
-- fmc->head = fmc->head_extra;
-+ struct jffs_fm *fm, *cur;
-+
-+ if (head_offset == fmc->head->offset){
-+ fmc->tail->next = fmc->head_extra;
-+ fmc->head_extra->prev = fmc->tail;
-+ fmc->tail = fmc->tail_extra;
-+ }
-+ else {
-+ fmc->tail_extra->next = fmc->head;
-+ fmc->head->prev = fmc->tail_extra;
-+ fmc->head = fmc->head_extra;
-+ while (fmc->head->offset != head_offset){
-+ fmc->tail->next = fmc->head;
-+ fmc->head = fmc->head->next;
-+ fmc->head->prev = 0;
-+ fmc->tail->next->prev = fmc->tail;
-+ fmc->tail = fmc->tail->next;
-+ fmc->tail->next = 0;
-+ }
-+ }
-+ /* Make sure the only free space we have is between tail and head.
-+ */
-+ for (cur = fmc->head; cur && cur != fmc->tail;) {
-+ if (cur->offset + cur->size < cur->next->offset) {
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = cur->next->offset - cur->offset - cur->size;
-+ fm->offset = cur->offset + cur->size;
-+ fm->nodes = 0;
-+ fm->next = cur->next;
-+ fm->prev = cur;
-+ cur->next->prev = fm;
-+ cur->next = fm;
-+ cur = fm->next;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ else if (cur->offset > cur->next->offset) {
-+ if (cur->offset + cur->size < fmc->flash_size){
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))){
-+
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = fmc->flash_size -
-+ cur->offset - cur->size;
-+ fm->nodes = 0;
-+ fm->offset = cur->offset + cur->size;
-+ fm->next = cur->next;
-+ fm->prev = cur;
-+ cur->next->prev = fm;
-+ cur->next = fm;
-+ cur = fm->next;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ else {
-+ cur = cur->next;
-+ }
-+ if (cur->offset > 0) {
-+
-+ if (!(fm = kmalloc(sizeof(struct jffs_fm), GFP_KERNEL))) {
-+ D(printk("jffs_buid_end(): kmalloc failed!\n"));
-+ return -ENOMEM;
-+ }
-+ DJM(no_jffs_fm++);
-+ fm->size = cur->offset;
-+ fm->nodes = 0;
-+ fm->offset = 0;
-+ fm->next = cur;
-+ fm->prev = cur->prev;
-+ cur->prev->next = fm;
-+ cur->prev = fm;
-+ fmc->free_size -= fm->size;
-+ fmc->dirty_size += fm->size;
-+ }
-+ }
-+ else if (cur->offset + cur->size != cur->next->offset) {
-+ printk("jffs_build_end(): Internal error.\n");
-+ return -EINVAL;
-+ }
-+ else {
-+ cur = cur->next;
-+ }
-+ }
- }
- fmc->head_extra = 0; /* These two instructions should be omitted. */
- fmc->tail_extra = 0;
- D3(jffs_print_fmcontrol(fmc));
-+ return 0;
- }
-
-
---- linux-2.4.27/fs/jffs/jffs_fm.h~2.4.27-vrs1
-+++ linux-2.4.27/fs/jffs/jffs_fm.h
-@@ -10,7 +10,7 @@
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
-- * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
-+ * $Id: jffs_fm.h,v 1.14 2001/12/10 17:37:12 asanochkin Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
-@@ -123,7 +123,7 @@
-
-
- struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, kdev_t dev);
--void jffs_build_end(struct jffs_fmcontrol *fmc);
-+int jffs_build_end(struct jffs_fmcontrol *fmc, __u32 head_offset);
- void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
-
- int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
---- linux-2.4.27/fs/partitions/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/fs/partitions/Config.in
-@@ -6,6 +6,7 @@
- bool ' Acorn partition support' CONFIG_ACORN_PARTITION
- if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
- # bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
-+ bool ' EESOX partition support' CONFIG_ACORN_PARTITION_EESOX
- bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
- bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
- bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
-@@ -52,6 +53,7 @@
- define_bool CONFIG_ACORN_PARTITION y
- define_bool CONFIG_ACORN_PARTITION_ADFS y
- # define_bool CONFIG_ACORN_PARTITION_CUMANA y
-+ define_bool CONFIG_ACORN_PARTITION_EESOX y
- define_bool CONFIG_ACORN_PARTITION_ICS y
- define_bool CONFIG_ACORN_PARTITION_POWERTEC y
- define_bool CONFIG_ACORN_PARTITION_RISCIX y
---- linux-2.4.27/fs/partitions/acorn.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/partitions/acorn.c
-@@ -7,7 +7,10 @@
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-- * Scan ADFS partitions on hard disk drives.
-+ * Scan ADFS partitions on hard disk drives. Unfortunately, there
-+ * isn't a standard for partitioning drives on Acorn machines, so
-+ * every single manufacturer of SCSI and IDE cards created their own
-+ * method.
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
-@@ -18,10 +21,18 @@
- #include <linux/genhd.h>
- #include <linux/fs.h>
- #include <linux/pagemap.h>
-+#include <linux/adfs_fs.h>
-
- #include "check.h"
- #include "acorn.h"
-
-+/*
-+ * Partition types. (Oh for reusability)
-+ */
-+#define PARTITION_RISCIX_MFM 1
-+#define PARTITION_RISCIX_SCSI 2
-+#define PARTITION_LINUX 9
-+
- static void
- adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
- {
-@@ -61,6 +72,21 @@
- }
-
- #ifdef CONFIG_ACORN_PARTITION_RISCIX
-+
-+struct riscix_part {
-+ __u32 start;
-+ __u32 length;
-+ __u32 one;
-+ char name[16];
-+};
-+
-+struct riscix_record {
-+ __u32 magic;
-+#define RISCIX_MAGIC (0x4a657320)
-+ __u32 date;
-+ struct riscix_part part[8];
-+};
-+
- static int
- riscix_partition(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sect, int minor, unsigned long nr_sects)
-@@ -102,6 +128,15 @@
- }
- #endif
-
-+#define LINUX_NATIVE_MAGIC 0xdeafa1de
-+#define LINUX_SWAP_MAGIC 0xdeafab1e
-+
-+struct linux_part {
-+ __u32 magic;
-+ __u32 start_sect;
-+ __u32 nr_sects;
-+};
-+
- static int
- linux_partition(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sect, int minor, unsigned long nr_sects)
-@@ -136,7 +171,7 @@
- }
-
- #ifdef CONFIG_ACORN_PARTITION_CUMANA
--static int
-+int
- adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-@@ -147,7 +182,7 @@
- int first = 1;
-
- /*
-- * Try Cumana style partitions - sector 3 contains ADFS boot block
-+ * Try Cumana style partitions - sector 6 contains ADFS boot block
- * with pointer to next 'drive'.
- *
- * There are unknowns in this code - is the 'cylinder number' of the
-@@ -163,13 +198,13 @@
- struct adfs_discrecord *dr;
- unsigned int nr_sects;
-
-- if (!(minor & mask))
-- break;
--
- data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
- if (!data)
- return -1;
-
-+ if (!(minor & mask))
-+ break;
-+
- dr = adfs_partition(hd, name, data, first_sector, minor++);
- if (!dr)
- break;
-@@ -229,7 +264,7 @@
- * hda1 = ADFS partition on first drive.
- * hda2 = non-ADFS partition.
- */
--static int
-+int
- adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-@@ -282,11 +317,18 @@
- break;
- }
- }
-+ printk("\n");
- return 1;
- }
- #endif
-
- #ifdef CONFIG_ACORN_PARTITION_ICS
-+
-+struct ics_part {
-+ __u32 start;
-+ __s32 size;
-+};
-+
- static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
- {
- Sector sect;
-@@ -303,6 +345,22 @@
- }
-
- /*
-+ * Check for a valid ICS partition using the checksum.
-+ */
-+static inline int valid_ics_sector(const unsigned char *data)
-+{
-+ unsigned long sum;
-+ int i;
-+
-+ for (i = 0, sum = 0x50617274; i < 508; i++)
-+ sum += data[i];
-+
-+ sum -= le32_to_cpu(*(__u32 *)(&data[508]));
-+
-+ return sum == 0;
-+}
-+
-+/*
- * Purpose: allocate ICS partitions.
- * Params : hd - pointer to gendisk structure to store partition info.
- * dev - device number to access.
-@@ -314,15 +372,14 @@
- * hda2 = ADFS partition 1 on first drive.
- * ..etc..
- */
--static int
-+int
- adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
-+ const unsigned char *data;
-+ const struct ics_part *p;
-+ unsigned int mask = (1 << hd->minor_shift) - 1;
- Sector sect;
-- unsigned char *data;
-- unsigned long sum;
-- unsigned int i, mask = (1 << hd->minor_shift) - 1;
-- struct ics_part *p;
-
- /*
- * Try ICS style partitions - sector 0 contains partition info.
-@@ -331,21 +388,14 @@
- if (!data)
- return -1;
-
-- /*
-- * check for a valid checksum
-- */
-- for (i = 0, sum = 0x50617274; i < 508; i++)
-- sum += data[i];
--
-- sum -= le32_to_cpu(*(__u32 *)(&data[508]));
-- if (sum) {
-- put_dev_sector(sect);
-- return 0; /* not ICS partition table */
-+ if (!valid_ics_sector(data)) {
-+ put_dev_sector(sect);
-+ return 0;
- }
-
- printk(" [ICS]");
-
-- for (p = (struct ics_part *)data; p->size; p++) {
-+ for (p = (const struct ics_part *)data; p->size; p++) {
- unsigned long start;
- long size;
-
-@@ -355,12 +405,19 @@
- start = le32_to_cpu(p->start);
- size = le32_to_cpu(p->size);
-
-+ /*
-+ * Negative sizes tell the RISC OS ICS driver to ignore
-+ * this partition - in effect it says that this does not
-+ * contain an ADFS filesystem.
-+ */
- if (size < 0) {
- size = -size;
-
- /*
-- * We use the first sector to identify what type
-- * this partition is...
-+ * Our own extension - We use the first sector
-+ * of the partition to identify what type this
-+ * partition is. We must not make this visible
-+ * to the filesystem.
- */
- if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
- start += 1;
-@@ -375,10 +432,32 @@
- }
-
- put_dev_sector(sect);
-+ printk("\n");
- return 1;
- }
- #endif
-
-+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-+struct ptec_part {
-+ __u32 unused1;
-+ __u32 unused2;
-+ __u32 start;
-+ __u32 size;
-+ __u32 unused5;
-+ char type[8];
-+};
-+
-+static inline int valid_ptec_sector(const unsigned char *data)
-+{
-+ unsigned char checksum = 0x2a;
-+ int i;
-+
-+ for (i = 0; i < 511; i++)
-+ checksum += data[i];
-+
-+ return checksum == data[511];
-+}
-+
- /*
- * Purpose: allocate ICS partitions.
- * Params : hd - pointer to gendisk structure to store partition info.
-@@ -391,32 +470,27 @@
- * hda2 = ADFS partition 1 on first drive.
- * ..etc..
- */
--#ifdef CONFIG_ACORN_PARTITION_POWERTEC
--static int
-+int
- adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
- unsigned long first_sector, int minor)
- {
- Sector sect;
-- unsigned char *data;
-- struct ptec_partition *p;
-- unsigned char checksum;
-+ const unsigned char *data;
-+ const struct ptec_part *p;
- int i;
-
- data = read_dev_sector(bdev, 0, &sect);
- if (!data)
- return -1;
-
-- for (checksum = 0x2a, i = 0; i < 511; i++)
-- checksum += data[i];
--
-- if (checksum != data[511]) {
-+ if (!valid_ptec_sector(data)) {
- put_dev_sector(sect);
- return 0;
- }
-
- printk(" [POWERTEC]");
-
-- for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
-+ for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
- unsigned long start;
- unsigned long size;
-
-@@ -430,49 +504,82 @@
- }
-
- put_dev_sector(sect);
-+ printk("\n");
- return 1;
- }
- #endif
-
--static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
--#ifdef CONFIG_ACORN_PARTITION_ICS
-- adfspart_check_ICS,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-- adfspart_check_POWERTEC,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_CUMANA
-- adfspart_check_CUMANA,
--#endif
--#ifdef CONFIG_ACORN_PARTITION_ADFS
-- adfspart_check_ADFS,
--#endif
-- NULL
-+#ifdef CONFIG_ACORN_PARTITION_EESOX
-+struct eesox_part {
-+ char magic[6];
-+ char name[10];
-+ u32 start;
-+ u32 unused6;
-+ u32 unused7;
-+ u32 unused8;
- };
-+
- /*
-- * Purpose: initialise all the partitions on an ADFS drive.
-- * These may be other ADFS partitions or a Linux/RiscBSD/RISCiX
-- * partition.
-+ * Guess who created this format?
-+ */
-+static const char eesox_name[] = {
-+ 'N', 'e', 'i', 'l', ' ',
-+ 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
-+};
-+
-+/*
-+ * EESOX SCSI partition format.
- *
-- * Params : hd - pointer to gendisk structure
-- * dev - device number to access
-- * first_sect - first available sector on the disk.
-- * first_minor - first available minor on this device.
-+ * This is a goddamned awful partition format. We don't seem to store
-+ * the size of the partition in this table, only the start addresses.
- *
-- * Returns: -1 on error, 0 if not ADFS format, 1 if ok.
-+ * There are two possibilities where the size comes from:
-+ * 1. The individual ADFS boot block entries that are placed on the disk.
-+ * 2. The start address of the next entry.
- */
--int acorn_partition(struct gendisk *hd, struct block_device *bdev,
-- unsigned long first_sect, int first_minor)
-+int
-+adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor)
- {
-+ Sector sect;
-+ const unsigned char *data;
-+ unsigned char buffer[256];
-+ struct eesox_part *p;
-+ u32 start = first_sector;
- int i;
-
-- for (i = 0; partfn[i]; i++) {
-- int r = partfn[i](hd, bdev, first_sect, first_minor);
-- if (r) {
-- if (r > 0)
-- printk("\n");
-- return r;
-- }
-+ data = read_dev_sector(bdev, 7, &sect);
-+ if (!data)
-+ return -1;
-+
-+ /*
-+ * "Decrypt" the partition table. God knows why...
-+ */
-+ for (i = 0; i < 256; i++)
-+ buffer[i] = data[i] ^ eesox_name[i & 15];
-+
-+ put_dev_sector(sect);
-+
-+ for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
-+ u32 next;
-+
-+ if (memcmp(p->magic, "Eesox", 6))
-+ break;
-+
-+ next = le32_to_cpu(p->start) + first_sector;
-+ if (i)
-+ add_gd_partition(hd, minor++, start, next - start);
-+ start = next;
- }
-- return 0;
-+
-+ if (i != 0) {
-+ unsigned long size;
-+
-+ size = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects;
-+ add_gd_partition(hd, minor++, start, size - start);
-+ printk("\n");
-+ }
-+
-+ return i ? 1 : 0;
- }
-+#endif
---- linux-2.4.27/fs/partitions/acorn.h~2.4.27-vrs1
-+++ linux-2.4.27/fs/partitions/acorn.h
-@@ -1,55 +1,28 @@
- /*
-- * fs/partitions/acorn.h
-+ * linux/fs/partitions/acorn.h
- *
-- * Copyright (C) 1996-1998 Russell King
-- */
--#include <linux/adfs_fs.h>
--
--/*
-- * Partition types. (Oh for reusability)
-+ * Copyright (C) 1996-2001 Russell King.
-+ *
-+ * I _hate_ this partitioning mess - why can't we have one defined
-+ * format, and everyone stick to it?
- */
--#define PARTITION_RISCIX_MFM 1
--#define PARTITION_RISCIX_SCSI 2
--#define PARTITION_LINUX 9
--
--struct riscix_part {
-- __u32 start;
-- __u32 length;
-- __u32 one;
-- char name[16];
--};
-
--struct riscix_record {
-- __u32 magic;
--#define RISCIX_MAGIC (0x4a657320)
-- __u32 date;
-- struct riscix_part part[8];
--};
--
--#define LINUX_NATIVE_MAGIC 0xdeafa1de
--#define LINUX_SWAP_MAGIC 0xdeafab1e
--
--struct linux_part {
-- __u32 magic;
-- __u32 start_sect;
-- __u32 nr_sects;
--};
-+int
-+adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--struct ics_part {
-- __u32 start;
-- __s32 size;
--};
-+int
-+adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--struct ptec_partition {
-- __u32 unused1;
-- __u32 unused2;
-- __u32 start;
-- __u32 size;
-- __u32 unused5;
-- char type[8];
--};
--
-+int
-+adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
--int acorn_partition(struct gendisk *hd, struct block_device *bdev,
-- unsigned long first_sect, int first_minor);
-+int
-+adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
-
-+int
-+adfspart_check_EESOX(struct gendisk *hd, struct block_device *bdev,
-+ unsigned long first_sector, int minor);
---- linux-2.4.27/fs/partitions/check.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/partitions/check.c
-@@ -40,8 +40,30 @@
- int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
-
- static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
--#ifdef CONFIG_ACORN_PARTITION
-- acorn_partition,
-+ /*
-+ * Probe partition formats with tables at disk address 0
-+ * that also have an ADFS boot block at 0xdc0.
-+ */
-+#ifdef CONFIG_ACORN_PARTITION_ICS
-+ adfspart_check_ICS,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
-+ adfspart_check_POWERTEC,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_EESOX
-+ adfspart_check_EESOX,
-+#endif
-+
-+ /*
-+ * Now move on to formats that only have partition info at
-+ * disk address 0xdc0. These should come before MSDOS
-+ * partition tables.
-+ */
-+#ifdef CONFIG_ACORN_PARTITION_CUMANA
-+ adfspart_check_CUMANA,
-+#endif
-+#ifdef CONFIG_ACORN_PARTITION_ADFS
-+ adfspart_check_ADFS,
- #endif
- #ifdef CONFIG_SGI_PARTITION
- sgi_partition,
-@@ -79,13 +101,25 @@
- NULL
- };
-
-+static char *raid_name (struct gendisk *hd, unsigned int unit, unsigned int part,
-+ int major_base, char *buf)
-+{
-+ int ctlr = hd->major - major_base;
-+ if (part == 0)
-+ sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, unit);
-+ else
-+ sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, unit,
-+ part);
-+ return buf;
-+}
-+
- /*
- * This is ucking fugly but its probably the best thing for 2.4.x
- * Take it as a clear reminder that: 1) we should put the device name
- * generation in the object kdev_t points to in 2.5.
- * and 2) ioctls better work on half-opened devices.
- */
--
-+
- #ifdef CONFIG_ARCH_S390
- int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
- int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
-@@ -104,10 +138,11 @@
- char *disk_name (struct gendisk *hd, int minor, char *buf)
- {
- const char *maj = hd->major_name;
-- unsigned int unit = (minor >> hd->minor_shift);
-- unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
-+ unsigned int unit = minor >> hd->minor_shift;
-+ unsigned int part = minor & (( 1 << hd->minor_shift) - 1);
-+ char *p;
-
-- if ((unit < hd->nr_real) && hd->part[minor].de) {
-+ if (unit < hd->nr_real && hd->part[minor].de) {
- int pos;
-
- pos = devfs_generate_path (hd->part[minor].de, buf, 64);
-@@ -153,51 +188,32 @@
- }
- if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
- unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
-- if (unit+'a' > 'z') {
-- unit -= 26;
-- sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
-- if (part)
-- sprintf(buf + 4, "%d", part);
-- return buf;
-- }
- }
- if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
-- int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
-- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-- return buf;
-- }
-+ return raid_name(hd, unit, part, COMPAQ_SMART2_MAJOR, buf);
-+ }
- if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
-- int ctlr = hd->major - COMPAQ_CISS_MAJOR;
-- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-- return buf;
-+ return raid_name(hd, unit, part, COMPAQ_CISS_MAJOR, buf);
- }
- if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
-- int ctlr = hd->major - DAC960_MAJOR;
-+ return raid_name(hd, unit, part, DAC960_MAJOR, buf);
-+ }
-+ if (hd->major == ATARAID_MAJOR) {
-+ int disk = minor >> hd->minor_shift;
-+ int part = minor & (( 1 << hd->minor_shift) - 1);
- if (part == 0)
-- sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
-+ sprintf(buf, "%s/d%d", maj, disk);
- else
-- sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
-+ sprintf(buf, "%s/d%dp%d", maj, disk, part);
- return buf;
- }
-- if (hd->major == ATARAID_MAJOR) {
-- int disk = minor >> hd->minor_shift;
-- int part = minor & (( 1 << hd->minor_shift) - 1);
-- if (part == 0)
-- sprintf(buf, "%s/d%d", maj, disk);
-- else
-- sprintf(buf, "%s/d%dp%d", maj, disk, part);
-- return buf;
-- }
-- if (part)
-- sprintf(buf, "%s%c%d", maj, unit+'a', part);
-+ p = buf;
-+ if (unit <= 26)
-+ p += sprintf(buf, "%s%c", maj, 'a' + unit);
- else
-- sprintf(buf, "%s%c", maj, unit+'a');
-+ p += sprintf(buf, "%s%c%c", maj, 'a' + unit / 26, 'a' + unit % 26);
-+ if (part)
-+ sprintf(p, "%d", part);
- return buf;
- }
-
-@@ -207,7 +223,7 @@
- void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
- {
- #ifndef CONFIG_DEVFS_FS
-- char buf[40];
-+ char buf[MAX_DISKNAME_LEN];
- #endif
-
- hd->part[minor].start_sect = start;
-@@ -229,7 +245,7 @@
- static int first_time = 1;
- unsigned long first_sector;
- struct block_device *bdev;
-- char buf[64];
-+ char buf[MAX_DISKNAME_LEN];
- int i;
-
- if (first_time)
---- linux-2.4.27/fs/proc/array.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/proc/array.c
-@@ -362,15 +362,15 @@
- task->cmin_flt,
- task->maj_flt,
- task->cmaj_flt,
-- task->times.tms_utime,
-- task->times.tms_stime,
-- task->times.tms_cutime,
-- task->times.tms_cstime,
-+ hz_to_std(task->times.tms_utime),
-+ hz_to_std(task->times.tms_stime),
-+ hz_to_std(task->times.tms_cutime),
-+ hz_to_std(task->times.tms_cstime),
- priority,
- nice,
- 0UL /* removed */,
- task->it_real_value,
-- task->start_time,
-+ hz_to_std(task->start_time),
- vsize,
- mm ? mm->rss : 0, /* you might want to shift this left 3 */
- task->rlim[RLIMIT_RSS].rlim_cur,
-@@ -417,6 +417,7 @@
- end = PMD_SIZE;
- do {
- pte_t page = *pte;
-+ unsigned long pfn;
- struct page *ptpage;
-
- address += PAGE_SIZE;
-@@ -426,8 +427,11 @@
- ++*total;
- if (!pte_present(page))
- continue;
-- ptpage = pte_page(page);
-- if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
-+ pfn = pte_pfn(page);
-+ if (!pfn_valid(pfn))
-+ continue;
-+ ptpage = pfn_to_page(pfn);
-+ if (PageReserved(ptpage))
- continue;
- ++*pages;
- if (pte_dirty(page))
-@@ -609,14 +613,14 @@
-
- len = sprintf(buffer,
- "cpu %lu %lu\n",
-- task->times.tms_utime,
-- task->times.tms_stime);
-+ hz_to_std(task->times.tms_utime),
-+ hz_to_std(task->times.tms_stime));
-
- for (i = 0 ; i < smp_num_cpus; i++)
- len += sprintf(buffer + len, "cpu%d %lu %lu\n",
- i,
-- task->per_cpu_utime[cpu_logical_map(i)],
-- task->per_cpu_stime[cpu_logical_map(i)]);
-+ hz_to_std(task->per_cpu_utime[cpu_logical_map(i)]),
-+ hz_to_std(task->per_cpu_stime[cpu_logical_map(i)]));
-
- return len;
- }
---- linux-2.4.27/fs/proc/proc_misc.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/proc/proc_misc.c
-@@ -308,16 +308,16 @@
- {
- int i, len = 0;
- extern unsigned long total_forks;
-- unsigned long jif = jiffies;
-+ unsigned long jif = hz_to_std(jiffies);
- unsigned int sum = 0, user = 0, nice = 0, system = 0;
- int major, disk;
-
- for (i = 0 ; i < smp_num_cpus; i++) {
- int cpu = cpu_logical_map(i), j;
-
-- user += kstat.per_cpu_user[cpu];
-- nice += kstat.per_cpu_nice[cpu];
-- system += kstat.per_cpu_system[cpu];
-+ user += hz_to_std(kstat.per_cpu_user[cpu]);
-+ nice += hz_to_std(kstat.per_cpu_nice[cpu]);
-+ system += hz_to_std(kstat.per_cpu_system[cpu]);
- #if !defined(CONFIG_ARCH_S390)
- for (j = 0 ; j < NR_IRQS ; j++)
- sum += kstat.irqs[cpu][j];
-@@ -331,10 +331,10 @@
- proc_sprintf(page, &off, &len,
- "cpu%d %u %u %u %lu\n",
- i,
-- kstat.per_cpu_user[cpu_logical_map(i)],
-- kstat.per_cpu_nice[cpu_logical_map(i)],
-- kstat.per_cpu_system[cpu_logical_map(i)],
-- jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
-+ hz_to_std(kstat.per_cpu_user[cpu_logical_map(i)]),
-+ hz_to_std(kstat.per_cpu_nice[cpu_logical_map(i)]),
-+ hz_to_std(kstat.per_cpu_system[cpu_logical_map(i)]),
-+ jif - hz_to_std( kstat.per_cpu_user[cpu_logical_map(i)] \
- + kstat.per_cpu_nice[cpu_logical_map(i)] \
- + kstat.per_cpu_system[cpu_logical_map(i)]));
- proc_sprintf(page, &off, &len,
-@@ -440,12 +440,14 @@
- return proc_calc_metrics(page, start, off, count, eof, len);
- }
-
-+#ifdef CONFIG_GENERIC_ISA_DMA
- static int dma_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- int len = get_dma_list(page);
- return proc_calc_metrics(page, start, off, count, eof, len);
- }
-+#endif
-
- static int cmdline_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-@@ -614,7 +616,9 @@
- {"interrupts", interrupts_read_proc},
- #endif
- {"filesystems", filesystems_read_proc},
-+#ifdef CONFIG_GENERIC_ISA_DMA
- {"dma", dma_read_proc},
-+#endif
- {"cmdline", cmdline_read_proc},
- #ifdef CONFIG_SGI_DS1286
- {"rtc", ds1286_read_proc},
---- linux-2.4.27/fs/stat.c~2.4.27-vrs1
-+++ linux-2.4.27/fs/stat.c
-@@ -26,7 +26,9 @@
- }
-
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
-@@ -38,7 +40,7 @@
- struct __old_kernel_stat tmp;
-
- memset(&tmp, 0, sizeof(struct __old_kernel_stat));
--
-+
- if (warncount > 0) {
- warncount--;
- printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
-@@ -60,7 +62,7 @@
- #if BITS_PER_LONG == 32
- if (inode->i_size > MAX_NON_LFS)
- return -EOVERFLOW;
--#endif
-+#endif
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
-@@ -88,7 +90,7 @@
- #if BITS_PER_LONG == 32
- if (inode->i_size > MAX_NON_LFS)
- return -EOVERFLOW;
--#endif
-+#endif
- tmp.st_size = inode->i_size;
- tmp.st_atime = inode->i_atime;
- tmp.st_mtime = inode->i_mtime;
-@@ -133,7 +135,9 @@
- }
-
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
- /*
- * For backward compatibility? Maybe this should be moved
- * into arch/i386 instead?
-@@ -169,7 +173,9 @@
- return error;
- }
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
-@@ -207,7 +213,9 @@
- return error;
- }
-
--#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && \
-+ !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && \
-+ !defined(__x86_64__) && !defined(__mips__)
-
- /*
- * For backward compatibility? Maybe this should be moved
---- linux-2.4.27/include/asm-alpha/ide.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-alpha/ide.h
-@@ -19,35 +19,15 @@
- #define MAX_HWIFS 4
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- switch (base) {
-- case 0x1f0: return 14;
-- case 0x170: return 15;
-- case 0x1e8: return 11;
-- case 0x168: return 10;
-- default:
-- return 0;
-- }
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- switch (index) {
-- case 0: return 0x1f0;
-- case 1: return 0x170;
-- case 2: return 0x1e8;
-- case 3: return 0x168;
-- default:
-- return 0;
-- }
--}
-+#define ide_default_io_base(i) ((ide_ioreg_t)0)
-+#define ide_default_irq(b) (0)
-
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
- ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(hw, 0, sizeof(*hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -55,7 +35,7 @@
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
-- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-+ hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
- }
- if (irq != NULL)
- *irq = 0;
-@@ -70,13 +50,19 @@
- {
- #ifndef CONFIG_BLK_DEV_IDEPCI
- hw_regs_t hw;
-- int index;
-
-- for (index = 0; index < MAX_HWIFS; index++) {
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
-+ ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
-+ hw.irq = 14;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
-+ hw.irq = 15;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
-+ hw.irq = 11;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
-+ hw.irq = 10;
-+ ide_register_hw(&hw, NULL);
- #endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
---- linux-2.4.27/include/asm-alpha/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-alpha/param.h
-@@ -13,6 +13,9 @@
- # else
- # define HZ 1200
- # endif
-+#ifdef __KERNEL__
-+# define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192
---- linux-2.4.27/include/asm-arm/arch-at91rm9200/AT91RM9200.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/AT91RM9200.h
-@@ -171,7 +171,7 @@
- #define AT91C_PA23_TXD2 (AT91C_PIO_PA23) // USART 2 Transmit Data
- #define AT91C_PA23_IRQ3 (AT91C_PIO_PA23) // Interrupt input 3
- #define AT91C_PIO_PA24 (1 << 24)
--#define AT91C_PA24_SCK2 (AT91C_PIO_PA24) // USART2 Serial Clock
-+#define AT91C_PA24_SCK2 (AT91C_PIO_PA24) // USART 2 Serial Clock
- #define AT91C_PA24_PCK1 (AT91C_PIO_PA24) // PMC Programmable Clock Output 1
- #define AT91C_PIO_PA25 (1 << 25)
- #define AT91C_PA25_TWD (AT91C_PIO_PA25) // TWI Two-wire Serial Data
-@@ -260,7 +260,7 @@
- #define AT91C_PIO_PB21 (1 << 21)
- #define AT91C_PB21_RXD1 (AT91C_PIO_PB21) // USART 1 Receive Data
- #define AT91C_PIO_PB22 (1 << 22)
--#define AT91C_PB22_SCK1 (AT91C_PIO_PB22) // USART1 Serial Clock
-+#define AT91C_PB22_SCK1 (AT91C_PIO_PB22) // USART 1 Serial Clock
- #define AT91C_PIO_PB23 (1 << 23)
- #define AT91C_PB23_DCD1 (AT91C_PIO_PB23) // USART 1 Data Carrier Detect
- #define AT91C_PIO_PB24 (1 << 24)
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/AT91RM9200_MCI.h
-@@ -0,0 +1,127 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 / MCI definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_MCI_H
-+#define AT91RM9200_MCI_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Multimedia Card Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_MCI {
-+ AT91_REG MCI_CR; // MCI Control Register
-+ AT91_REG MCI_MR; // MCI Mode Register
-+ AT91_REG MCI_DTOR; // MCI Data Timeout Register
-+ AT91_REG MCI_SDCR; // MCI SD Card Register
-+ AT91_REG MCI_ARGR; // MCI Argument Register
-+ AT91_REG MCI_CMDR; // MCI Command Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG MCI_RSPR[4]; // MCI Response Register
-+ AT91_REG MCI_RDR; // MCI Receive Data Register
-+ AT91_REG MCI_TDR; // MCI Transmit Data Register
-+ AT91_REG Reserved1[2]; //
-+ AT91_REG MCI_SR; // MCI Status Register
-+ AT91_REG MCI_IER; // MCI Interrupt Enable Register
-+ AT91_REG MCI_IDR; // MCI Interrupt Disable Register
-+ AT91_REG MCI_IMR; // MCI Interrupt Mask Register
-+ AT91_REG Reserved2[44]; //
-+ AT91_REG MCI_RPR; // Receive Pointer Register
-+ AT91_REG MCI_RCR; // Receive Counter Register
-+ AT91_REG MCI_TPR; // Transmit Pointer Register
-+ AT91_REG MCI_TCR; // Transmit Counter Register
-+ AT91_REG MCI_RNPR; // Receive Next Pointer Register
-+ AT91_REG MCI_RNCR; // Receive Next Counter Register
-+ AT91_REG MCI_TNPR; // Transmit Next Pointer Register
-+ AT91_REG MCI_TNCR; // Transmit Next Counter Register
-+ AT91_REG MCI_PTCR; // PDC Transfer Control Register
-+ AT91_REG MCI_PTSR; // PDC Transfer Status Register
-+} AT91S_MCI, *AT91PS_MCI;
-+
-+#endif
-+
-+// -------- MCI_CR : (MCI Offset: 0x0) MCI Control Register --------
-+#define AT91C_MCI_MCIEN ((unsigned int) 0x1 << 0) // (MCI) Multimedia Interface Enable
-+#define AT91C_MCI_MCIDIS ((unsigned int) 0x1 << 1) // (MCI) Multimedia Interface Disable
-+#define AT91C_MCI_PWSEN ((unsigned int) 0x1 << 2) // (MCI) Power Save Mode Enable
-+#define AT91C_MCI_PWSDIS ((unsigned int) 0x1 << 3) // (MCI) Power Save Mode Disable
-+// -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register --------
-+#define AT91C_MCI_CLKDIV ((unsigned int) 0x1 << 0) // (MCI) Clock Divider
-+#define AT91C_MCI_PWSDIV ((unsigned int) 0x1 << 8) // (MCI) Power Saving Divider
-+#define AT91C_MCI_PDCPADV ((unsigned int) 0x1 << 14) // (MCI) PDC Padding Value
-+#define AT91C_MCI_PDCMODE ((unsigned int) 0x1 << 15) // (MCI) PDC Oriented Mode
-+#define AT91C_MCI_BLKLEN ((unsigned int) 0x1 << 18) // (MCI) Data Block Length
-+// -------- MCI_DTOR : (MCI Offset: 0x8) MCI Data Timeout Register --------
-+#define AT91C_MCI_DTOCYC ((unsigned int) 0x1 << 0) // (MCI) Data Timeout Cycle Number
-+#define AT91C_MCI_DTOMUL ((unsigned int) 0x7 << 4) // (MCI) Data Timeout Multiplier
-+#define AT91C_MCI_DTOMUL_1 ((unsigned int) 0x0 << 4) // (MCI) DTOCYC x 1
-+#define AT91C_MCI_DTOMUL_16 ((unsigned int) 0x1 << 4) // (MCI) DTOCYC x 16
-+#define AT91C_MCI_DTOMUL_128 ((unsigned int) 0x2 << 4) // (MCI) DTOCYC x 128
-+#define AT91C_MCI_DTOMUL_256 ((unsigned int) 0x3 << 4) // (MCI) DTOCYC x 256
-+#define AT91C_MCI_DTOMUL_1024 ((unsigned int) 0x4 << 4) // (MCI) DTOCYC x 1024
-+#define AT91C_MCI_DTOMUL_4096 ((unsigned int) 0x5 << 4) // (MCI) DTOCYC x 4096
-+#define AT91C_MCI_DTOMUL_65536 ((unsigned int) 0x6 << 4) // (MCI) DTOCYC x 65536
-+#define AT91C_MCI_DTOMUL_1048576 ((unsigned int) 0x7 << 4) // (MCI) DTOCYC x 1048576
-+// -------- MCI_SDCR : (MCI Offset: 0xc) MCI SD Card Register --------
-+#define AT91C_MCI_SCDSEL ((unsigned int) 0x1 << 0) // (MCI) SD Card Selector
-+#define AT91C_MCI_SCDBUS ((unsigned int) 0x1 << 7) // (MCI) SD Card Bus Width
-+// -------- MCI_CMDR : (MCI Offset: 0x14) MCI Command Register --------
-+#define AT91C_MCI_CMDNB ((unsigned int) 0x1F << 0) // (MCI) Command Number
-+#define AT91C_MCI_RSPTYP ((unsigned int) 0x3 << 6) // (MCI) Response Type
-+#define AT91C_MCI_RSPTYP_NO ((unsigned int) 0x0 << 6) // (MCI) No response
-+#define AT91C_MCI_RSPTYP_48 ((unsigned int) 0x1 << 6) // (MCI) 48-bit response
-+#define AT91C_MCI_RSPTYP_136 ((unsigned int) 0x2 << 6) // (MCI) 136-bit response
-+#define AT91C_MCI_SPCMD ((unsigned int) 0x7 << 8) // (MCI) Special CMD
-+#define AT91C_MCI_SPCMD_NONE ((unsigned int) 0x0 << 8) // (MCI) Not a special CMD
-+#define AT91C_MCI_SPCMD_INIT ((unsigned int) 0x1 << 8) // (MCI) Initialization CMD
-+#define AT91C_MCI_SPCMD_SYNC ((unsigned int) 0x2 << 8) // (MCI) Synchronized CMD
-+#define AT91C_MCI_SPCMD_IT_CMD ((unsigned int) 0x4 << 8) // (MCI) Interrupt command
-+#define AT91C_MCI_SPCMD_IT_REP ((unsigned int) 0x5 << 8) // (MCI) Interrupt response
-+#define AT91C_MCI_OPDCMD ((unsigned int) 0x1 << 11) // (MCI) Open Drain Command
-+#define AT91C_MCI_MAXLAT ((unsigned int) 0x1 << 12) // (MCI) Maximum Latency for Command to respond
-+#define AT91C_MCI_TRCMD ((unsigned int) 0x3 << 16) // (MCI) Transfer CMD
-+#define AT91C_MCI_TRCMD_NO ((unsigned int) 0x0 << 16) // (MCI) No transfer
-+#define AT91C_MCI_TRCMD_START ((unsigned int) 0x1 << 16) // (MCI) Start transfer
-+#define AT91C_MCI_TRCMD_STOP ((unsigned int) 0x2 << 16) // (MCI) Stop transfer
-+#define AT91C_MCI_TRDIR ((unsigned int) 0x1 << 18) // (MCI) Transfer Direction
-+#define AT91C_MCI_TRTYP ((unsigned int) 0x3 << 19) // (MCI) Transfer Type
-+#define AT91C_MCI_TRTYP_BLOCK ((unsigned int) 0x0 << 19) // (MCI) Block Transfer type
-+#define AT91C_MCI_TRTYP_MULTIPLE ((unsigned int) 0x1 << 19) // (MCI) Multiple Block transfer type
-+#define AT91C_MCI_TRTYP_STREAM ((unsigned int) 0x2 << 19) // (MCI) Stream transfer type
-+// -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------
-+#define AT91C_MCI_CMDRDY ((unsigned int) 0x1 << 0) // (MCI) Command Ready flag
-+#define AT91C_MCI_RXRDY ((unsigned int) 0x1 << 1) // (MCI) RX Ready flag
-+#define AT91C_MCI_TXRDY ((unsigned int) 0x1 << 2) // (MCI) TX Ready flag
-+#define AT91C_MCI_BLKE ((unsigned int) 0x1 << 3) // (MCI) Data Block Transfer Ended flag
-+#define AT91C_MCI_DTIP ((unsigned int) 0x1 << 4) // (MCI) Data Transfer in Progress flag
-+#define AT91C_MCI_NOTBUSY ((unsigned int) 0x1 << 5) // (MCI) Data Line Not Busy flag
-+#define AT91C_MCI_ENDRX ((unsigned int) 0x1 << 6) // (MCI) End of RX Buffer flag
-+#define AT91C_MCI_ENDTX ((unsigned int) 0x1 << 7) // (MCI) End of TX Buffer flag
-+#define AT91C_MCI_RXBUFF ((unsigned int) 0x1 << 14) // (MCI) RX Buffer Full flag
-+#define AT91C_MCI_TXBUFE ((unsigned int) 0x1 << 15) // (MCI) TX Buffer Empty flag
-+#define AT91C_MCI_RINDE ((unsigned int) 0x1 << 16) // (MCI) Response Index Error flag
-+#define AT91C_MCI_RDIRE ((unsigned int) 0x1 << 17) // (MCI) Response Direction Error flag
-+#define AT91C_MCI_RCRCE ((unsigned int) 0x1 << 18) // (MCI) Response CRC Error flag
-+#define AT91C_MCI_RENDE ((unsigned int) 0x1 << 19) // (MCI) Response End Bit Error flag
-+#define AT91C_MCI_RTOE ((unsigned int) 0x1 << 20) // (MCI) Response Time-out Error flag
-+#define AT91C_MCI_DCRCE ((unsigned int) 0x1 << 21) // (MCI) data CRC Error flag
-+#define AT91C_MCI_DTOE ((unsigned int) 0x1 << 22) // (MCI) Data timeout Error flag
-+#define AT91C_MCI_OVRE ((unsigned int) 0x1 << 30) // (MCI) Overrun flag
-+#define AT91C_MCI_UNRE ((unsigned int) 0x1 << 31) // (MCI) Underrun flag
-+// -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register --------
-+// -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register --------
-+// -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register --------
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/AT91RM9200_SSC.h
-@@ -0,0 +1,129 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 / SSC definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_SSC_H
-+#define AT91RM9200_SSC_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Synchronous Serial Controller Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_SSC {
-+ AT91_REG SSC_CR; // Control Register
-+ AT91_REG SSC_CMR; // Clock Mode Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG SSC_RCMR; // Receive Clock ModeRegister
-+ AT91_REG SSC_RFMR; // Receive Frame Mode Register
-+ AT91_REG SSC_TCMR; // Transmit Clock Mode Register
-+ AT91_REG SSC_TFMR; // Transmit Frame Mode Register
-+ AT91_REG SSC_RHR; // Receive Holding Register
-+ AT91_REG SSC_THR; // Transmit Holding Register
-+ AT91_REG Reserved1[2]; //
-+ AT91_REG SSC_RSHR; // Receive Sync Holding Register
-+ AT91_REG SSC_TSHR; // Transmit Sync Holding Register
-+ AT91_REG SSC_RC0R; // Receive Compare 0 Register
-+ AT91_REG SSC_RC1R; // Receive Compare 1 Register
-+ AT91_REG SSC_SR; // Status Register
-+ AT91_REG SSC_IER; // Interrupt Enable Register
-+ AT91_REG SSC_IDR; // Interrupt Disable Register
-+ AT91_REG SSC_IMR; // Interrupt Mask Register
-+ AT91_REG Reserved2[44]; //
-+ AT91_REG SSC_RPR; // Receive Pointer Register
-+ AT91_REG SSC_RCR; // Receive Counter Register
-+ AT91_REG SSC_TPR; // Transmit Pointer Register
-+ AT91_REG SSC_TCR; // Transmit Counter Register
-+ AT91_REG SSC_RNPR; // Receive Next Pointer Register
-+ AT91_REG SSC_RNCR; // Receive Next Counter Register
-+ AT91_REG SSC_TNPR; // Transmit Next Pointer Register
-+ AT91_REG SSC_TNCR; // Transmit Next Counter Register
-+ AT91_REG SSC_PTCR; // PDC Transfer Control Register
-+ AT91_REG SSC_PTSR; // PDC Transfer Status Register
-+} AT91S_SSC, *AT91PS_SSC;
-+
-+#endif
-+
-+// -------- SSC_CR : (SSC Offset: 0x0) SSC Control Register --------
-+#define AT91C_SSC_RXEN ( 0x1 << 0) // (SSC) Receive Enable
-+#define AT91C_SSC_RXDIS ( 0x1 << 1) // (SSC) Receive Disable
-+#define AT91C_SSC_TXEN ( 0x1 << 8) // (SSC) Transmit Enable
-+#define AT91C_SSC_TXDIS ( 0x1 << 9) // (SSC) Transmit Disable
-+#define AT91C_SSC_SWRST ( 0x1 << 15) // (SSC) Software Reset
-+// -------- SSC_RCMR : (SSC Offset: 0x10) SSC Receive Clock Mode Register --------
-+#define AT91C_SSC_CKS ( 0x3 << 0) // (SSC) Receive/Transmit Clock Selection
-+#define AT91C_SSC_CKS_DIV ( 0x0) // (SSC) Divided Clock
-+#define AT91C_SSC_CKS_TK ( 0x1) // (SSC) TK Clock signal
-+#define AT91C_SSC_CKS_RK ( 0x2) // (SSC) RK pin
-+#define AT91C_SSC_CKO ( 0x7 << 2) // (SSC) Receive/Transmit Clock Output Mode Selection
-+#define AT91C_SSC_CKO_NONE ( 0x0 << 2) // (SSC) Receive/Transmit Clock Output Mode: None RK pin: Input-only
-+#define AT91C_SSC_CKO_CONTINOUS ( 0x1 << 2) // (SSC) Continuous Receive/Transmit Clock RK pin: Output
-+#define AT91C_SSC_CKO_DATA_TX ( 0x2 << 2) // (SSC) Receive/Transmit Clock only during data transfers RK pin: Output
-+#define AT91C_SSC_CKI ( 0x1 << 5) // (SSC) Receive/Transmit Clock Inversion
-+#define AT91C_SSC_CKG ( 0x3 << 6) // (SSC) Receive/Transmit Clock Gating Selection
-+#define AT91C_SSC_CKG_NONE ( 0x0 << 6) // (SSC) Receive/Transmit Clock Gating: None, continuous clock
-+#define AT91C_SSC_CKG_LOW ( 0x1 << 6) // (SSC) Receive/Transmit Clock enabled only if RF Low
-+#define AT91C_SSC_CKG_HIGH ( 0x2 << 6) // (SSC) Receive/Transmit Clock enabled only if RF High
-+#define AT91C_SSC_START ( 0xF << 8) // (SSC) Receive/Transmit Start Selection
-+#define AT91C_SSC_START_CONTINOUS ( 0x0 << 8) // (SSC) Continuous, as soon as the receiver is enabled, and immediately after the end of transfer of the previous data.
-+#define AT91C_SSC_START_TX ( 0x1 << 8) // (SSC) Transmit/Receive start
-+#define AT91C_SSC_START_LOW_RF ( 0x2 << 8) // (SSC) Detection of a low level on RF input
-+#define AT91C_SSC_START_HIGH_RF ( 0x3 << 8) // (SSC) Detection of a high level on RF input
-+#define AT91C_SSC_START_FALL_RF ( 0x4 << 8) // (SSC) Detection of a falling edge on RF input
-+#define AT91C_SSC_START_RISE_RF ( 0x5 << 8) // (SSC) Detection of a rising edge on RF input
-+#define AT91C_SSC_START_LEVEL_RF ( 0x6 << 8) // (SSC) Detection of any level change on RF input
-+#define AT91C_SSC_START_EDGE_RF ( 0x7 << 8) // (SSC) Detection of any edge on RF input
-+#define AT91C_SSC_START_0 ( 0x8 << 8) // (SSC) Compare 0
-+#define AT91C_SSC_STOP ( 0x1 << 12) // (SSC) Receive Stop Selection
-+#define AT91C_SSC_STTOUT ( 0x1 << 15) // (SSC) Receive/Transmit Start Output Selection
-+#define AT91C_SSC_STTDLY ( 0xFF << 16) // (SSC) Receive/Transmit Start Delay
-+#define AT91C_SSC_PERIOD ( 0xFF << 24) // (SSC) Receive/Transmit Period Divider Selection
-+// -------- SSC_RFMR : (SSC Offset: 0x14) SSC Receive Frame Mode Register --------
-+#define AT91C_SSC_DATLEN ( 0x1F << 0) // (SSC) Data Length
-+#define AT91C_SSC_LOOP ( 0x1 << 5) // (SSC) Loop Mode
-+#define AT91C_SSC_MSBF ( 0x1 << 7) // (SSC) Most Significant Bit First
-+#define AT91C_SSC_DATNB ( 0xF << 8) // (SSC) Data Number per Frame
-+#define AT91C_SSC_FSLEN ( 0xF << 16) // (SSC) Receive/Transmit Frame Sync length
-+#define AT91C_SSC_FSOS ( 0x7 << 20) // (SSC) Receive/Transmit Frame Sync Output Selection
-+#define AT91C_SSC_FSOS_NONE ( 0x0 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: None RK pin Input-only
-+#define AT91C_SSC_FSOS_NEGATIVE ( 0x1 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Negative Pulse
-+#define AT91C_SSC_FSOS_POSITIVE ( 0x2 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Positive Pulse
-+#define AT91C_SSC_FSOS_LOW ( 0x3 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver Low during data transfer
-+#define AT91C_SSC_FSOS_HIGH ( 0x4 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Driver High during data transfer
-+#define AT91C_SSC_FSOS_TOGGLE ( 0x5 << 20) // (SSC) Selected Receive/Transmit Frame Sync Signal: Toggling at each start of data transfer
-+#define AT91C_SSC_FSEDGE ( 0x1 << 24) // (SSC) Frame Sync Edge Detection
-+// -------- SSC_TCMR : (SSC Offset: 0x18) SSC Transmit Clock Mode Register --------
-+// -------- SSC_TFMR : (SSC Offset: 0x1c) SSC Transmit Frame Mode Register --------
-+#define AT91C_SSC_DATDEF ( 0x1 << 5) // (SSC) Data Default Value
-+#define AT91C_SSC_FSDEN ( 0x1 << 23) // (SSC) Frame Sync Data Enable
-+// -------- SSC_SR : (SSC Offset: 0x40) SSC Status Register --------
-+#define AT91C_SSC_TXRDY ( 0x1 << 0) // (SSC) Transmit Ready
-+#define AT91C_SSC_TXEMPTY ( 0x1 << 1) // (SSC) Transmit Empty
-+#define AT91C_SSC_ENDTX ( 0x1 << 2) // (SSC) End Of Transmission
-+#define AT91C_SSC_TXBUFE ( 0x1 << 3) // (SSC) Transmit Buffer Empty
-+#define AT91C_SSC_RXRDY ( 0x1 << 4) // (SSC) Receive Ready
-+#define AT91C_SSC_OVRUN ( 0x1 << 5) // (SSC) Receive Overrun
-+#define AT91C_SSC_ENDRX ( 0x1 << 6) // (SSC) End of Reception
-+#define AT91C_SSC_RXBUFF ( 0x1 << 7) // (SSC) Receive Buffer Full
-+#define AT91C_SSC_CP0 ( 0x1 << 8) // (SSC) Compare 0
-+#define AT91C_SSC_CP1 ( 0x1 << 9) // (SSC) Compare 1
-+#define AT91C_SSC_TXSYN ( 0x1 << 10) // (SSC) Transmit Sync
-+#define AT91C_SSC_RXSYN ( 0x1 << 11) // (SSC) Receive Sync
-+#define AT91C_SSC_TXENA ( 0x1 << 16) // (SSC) Transmit Enable
-+#define AT91C_SSC_RXENA ( 0x1 << 17) // (SSC) Receive Enable
-+// -------- SSC_IER : (SSC Offset: 0x44) SSC Interrupt Enable Register --------
-+// -------- SSC_IDR : (SSC Offset: 0x48) SSC Interrupt Disable Register --------
-+// -------- SSC_IMR : (SSC Offset: 0x4c) SSC Interrupt Mask Register --------
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/AT91RM9200_TC.h
-@@ -0,0 +1,165 @@
-+// ----------------------------------------------------------------------------
-+// ATMEL Microcontroller Software Support - ROUSSET -
-+// ----------------------------------------------------------------------------
-+// The software is delivered "AS IS" without warranty or condition of any
-+// kind, either express, implied or statutory. This includes without
-+// limitation any warranty or condition with respect to merchantability or
-+// fitness for any particular purpose, or against the infringements of
-+// intellectual property rights of others.
-+// ----------------------------------------------------------------------------
-+// File Name : AT91RM9200.h
-+// Object : AT91RM9200 definitions
-+// Generated : AT91 SW Application Group 12/03/2002 (10:48:02)
-+//
-+// ----------------------------------------------------------------------------
-+
-+#ifndef AT91RM9200_TC_H
-+#define AT91RM9200_TC_H
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Timer Counter Channel Interface
-+// *****************************************************************************
-+#ifndef __ASSEMBLY__
-+
-+typedef struct _AT91S_TC {
-+ AT91_REG TC_CCR; // Channel Control Register
-+ AT91_REG TC_CMR; // Channel Mode Register
-+ AT91_REG Reserved0[2]; //
-+ AT91_REG TC_CV; // Counter Value
-+ AT91_REG TC_RA; // Register A
-+ AT91_REG TC_RB; // Register B
-+ AT91_REG TC_RC; // Register C
-+ AT91_REG TC_SR; // Status Register
-+ AT91_REG TC_IER; // Interrupt Enable Register
-+ AT91_REG TC_IDR; // Interrupt Disable Register
-+ AT91_REG TC_IMR; // Interrupt Mask Register
-+} AT91S_TC, *AT91PS_TC;
-+
-+typedef struct _AT91S_TCB {
-+ AT91S_TC TCB_TC0; // TC Channel 0
-+ AT91_REG Reserved0[4]; //
-+ AT91S_TC TCB_TC1; // TC Channel 1
-+ AT91_REG Reserved1[4]; //
-+ AT91S_TC TCB_TC2; // TC Channel 2
-+ AT91_REG Reserved2[4]; //
-+ AT91_REG TCB_BCR; // TC Block Control Register
-+ AT91_REG TCB_BMR; // TC Block Mode Register
-+} AT91S_TCB, *AT91PS_TCB;
-+
-+#endif
-+
-+// -------- TC_CCR : (TC Offset: 0x0) TC Channel Control Register --------
-+#define AT91C_TC_CLKEN ( 0x1 << 0) // (TC) Counter Clock Enable Command
-+#define AT91C_TC_CLKDIS ( 0x1 << 1) // (TC) Counter Clock Disable Command
-+#define AT91C_TC_SWTRG ( 0x1 << 2) // (TC) Software Trigger Command
-+// -------- TC_CMR : (TC Offset: 0x4) TC Channel Mode Register: Capture Mode / Waveform Mode --------
-+#define AT91C_TC_TCCLKS ( 0x7 << 0) // (TC) Clock Selection
-+#define AT91C_TC_TIMER_DIV1_CLOCK ( 0x0 << 0) // (TC) MCK/2
-+#define AT91C_TC_TIMER_DIV2_CLOCK ( 0x1 << 0) // (TC) MCK/8
-+#define AT91C_TC_TIMER_DIV3_CLOCK ( 0x2 << 0) // (TC) MCK/32
-+#define AT91C_TC_TIMER_DIV4_CLOCK ( 0x3 << 0) // (TC) MCK/128
-+#define AT91C_TC_TIMER_DIV5_CLOCK ( 0x4 << 0) // (TC) MCK/256 = SLOW CLOCK
-+#define AT91C_TC_TIMER_XC0 ( 0x5 << 0) // (TC) XC0
-+#define AT91C_TC_TIMER_XC1 ( 0x6 << 0) // (TC) XC1
-+#define AT91C_TC_TIMER_XC2 ( 0x7 << 0) // (TC) XC2
-+#define AT91C_TC_CLKI ( 0x1 << 3) // (TC) Clock Invert
-+#define AT91C_TC_BURST ( 0x3 << 4) // (TC) Burst Signal Selection
-+#define AT91C_TC_CPCSTOP ( 0x1 << 6) // (TC) Counter Clock Stopped with RC Compare
-+#define AT91C_TC_CPCDIS ( 0x1 << 7) // (TC) Counter Clock Disable with RC Compare
-+#define AT91C_TC_EEVTEDG ( 0x3 << 8) // (TC) External Event Edge Selection
-+#define AT91C_TC_EEVTEDG_NONE ( 0x0 << 8) // (TC) Edge: None
-+#define AT91C_TC_EEVTEDG_RISING ( 0x1 << 8) // (TC) Edge: rising edge
-+#define AT91C_TC_EEVTEDG_FALLING ( 0x2 << 8) // (TC) Edge: falling edge
-+#define AT91C_TC_EEVTEDG_BOTH ( 0x3 << 8) // (TC) Edge: each edge
-+#define AT91C_TC_EEVT ( 0x3 << 10) // (TC) External Event Selection
-+#define AT91C_TC_EEVT_NONE ( 0x0 << 10) // (TC) Signal selected as external event: TIOB TIOB direction: input
-+#define AT91C_TC_EEVT_RISING ( 0x1 << 10) // (TC) Signal selected as external event: XC0 TIOB direction: output
-+#define AT91C_TC_EEVT_FALLING ( 0x2 << 10) // (TC) Signal selected as external event: XC1 TIOB direction: output
-+#define AT91C_TC_EEVT_BOTH ( 0x3 << 10) // (TC) Signal selected as external event: XC2 TIOB direction: output
-+#define AT91C_TC_ENETRG ( 0x1 << 12) // (TC) External Event Trigger enable
-+#define AT91C_TC_WAVESEL ( 0x3 << 13) // (TC) Waveform Selection
-+#define AT91C_TC_WAVESEL_UP ( 0x0 << 13) // (TC) UP mode without atomatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UP_AUTO ( 0x1 << 13) // (TC) UP mode with automatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UPDOWN ( 0x2 << 13) // (TC) UPDOWN mode without automatic trigger on RC Compare
-+#define AT91C_TC_WAVESEL_UPDOWN_AUTO ( 0x3 << 13) // (TC) UPDOWN mode with automatic trigger on RC Compare
-+#define AT91C_TC_CPCTRG ( 0x1 << 14) // (TC) RC Compare Trigger Enable
-+#define AT91C_TC_WAVE ( 0x1 << 15) // (TC)
-+#define AT91C_TC_ACPA ( 0x3 << 16) // (TC) RA Compare Effect on TIOA
-+#define AT91C_TC_ACPA_NONE ( 0x0 << 16) // (TC) Effect: none
-+#define AT91C_TC_ACPA_SET ( 0x1 << 16) // (TC) Effect: set
-+#define AT91C_TC_ACPA_CLEAR ( 0x2 << 16) // (TC) Effect: clear
-+#define AT91C_TC_ACPA_TOGGLE ( 0x3 << 16) // (TC) Effect: toggle
-+#define AT91C_TC_ACPC ( 0x3 << 18) // (TC) RC Compare Effect on TIOA
-+#define AT91C_TC_ACPC_NONE ( 0x0 << 18) // (TC) Effect: none
-+#define AT91C_TC_ACPC_SET ( 0x1 << 18) // (TC) Effect: set
-+#define AT91C_TC_ACPC_CLEAR ( 0x2 << 18) // (TC) Effect: clear
-+#define AT91C_TC_ACPC_TOGGLE ( 0x3 << 18) // (TC) Effect: toggle
-+#define AT91C_TC_AEEVT ( 0x3 << 20) // (TC) External Event Effect on TIOA
-+#define AT91C_TC_AEEVT_NONE ( 0x0 << 20) // (TC) Effect: none
-+#define AT91C_TC_AEEVT_SET ( 0x1 << 20) // (TC) Effect: set
-+#define AT91C_TC_AEEVT_CLEAR ( 0x2 << 20) // (TC) Effect: clear
-+#define AT91C_TC_AEEVT_TOGGLE ( 0x3 << 20) // (TC) Effect: toggle
-+#define AT91C_TC_ASWTRG ( 0x3 << 22) // (TC) Software Trigger Effect on TIOA
-+#define AT91C_TC_ASWTRG_NONE ( 0x0 << 22) // (TC) Effect: none
-+#define AT91C_TC_ASWTRG_SET ( 0x1 << 22) // (TC) Effect: set
-+#define AT91C_TC_ASWTRG_CLEAR ( 0x2 << 22) // (TC) Effect: clear
-+#define AT91C_TC_ASWTRG_TOGGLE ( 0x3 << 22) // (TC) Effect: toggle
-+#define AT91C_TC_BCPB ( 0x3 << 24) // (TC) RB Compare Effect on TIOB
-+#define AT91C_TC_BCPB_NONE ( 0x0 << 24) // (TC) Effect: none
-+#define AT91C_TC_BCPB_SET ( 0x1 << 24) // (TC) Effect: set
-+#define AT91C_TC_BCPB_CLEAR ( 0x2 << 24) // (TC) Effect: clear
-+#define AT91C_TC_BCPB_TOGGLE ( 0x3 << 24) // (TC) Effect: toggle
-+#define AT91C_TC_BCPC ( 0x3 << 26) // (TC) RC Compare Effect on TIOB
-+#define AT91C_TC_BCPC_NONE ( 0x0 << 26) // (TC) Effect: none
-+#define AT91C_TC_BCPC_SET ( 0x1 << 26) // (TC) Effect: set
-+#define AT91C_TC_BCPC_CLEAR ( 0x2 << 26) // (TC) Effect: clear
-+#define AT91C_TC_BCPC_TOGGLE ( 0x3 << 26) // (TC) Effect: toggle
-+#define AT91C_TC_BEEVT ( 0x3 << 28) // (TC) External Event Effect on TIOB
-+#define AT91C_TC_BEEVT_NONE ( 0x0 << 28) // (TC) Effect: none
-+#define AT91C_TC_BEEVT_SET ( 0x1 << 28) // (TC) Effect: set
-+#define AT91C_TC_BEEVT_CLEAR ( 0x2 << 28) // (TC) Effect: clear
-+#define AT91C_TC_BEEVT_TOGGLE ( 0x3 << 28) // (TC) Effect: toggle
-+#define AT91C_TC_BSWTRG ( 0x3 << 30) // (TC) Software Trigger Effect on TIOB
-+#define AT91C_TC_BSWTRG_NONE ( 0x0 << 30) // (TC) Effect: none
-+#define AT91C_TC_BSWTRG_SET ( 0x1 << 30) // (TC) Effect: set
-+#define AT91C_TC_BSWTRG_CLEAR ( 0x2 << 30) // (TC) Effect: clear
-+#define AT91C_TC_BSWTRG_TOGGLE ( 0x3 << 30) // (TC) Effect: toggle
-+// -------- TC_SR : (TC Offset: 0x20) TC Channel Status Register --------
-+#define AT91C_TC_COVFS ( 0x1 << 0) // (TC) Counter Overflow
-+#define AT91C_TC_LOVRS ( 0x1 << 1) // (TC) Load Overrun
-+#define AT91C_TC_CPAS ( 0x1 << 2) // (TC) RA Compare
-+#define AT91C_TC_CPBS ( 0x1 << 3) // (TC) RB Compare
-+#define AT91C_TC_CPCS ( 0x1 << 4) // (TC) RC Compare
-+#define AT91C_TC_LDRAS ( 0x1 << 5) // (TC) RA Loading
-+#define AT91C_TC_LDRBS ( 0x1 << 6) // (TC) RB Loading
-+#define AT91C_TC_ETRCS ( 0x1 << 7) // (TC) External Trigger
-+#define AT91C_TC_ETRGS ( 0x1 << 16) // (TC) Clock Enabling
-+#define AT91C_TC_MTIOA ( 0x1 << 17) // (TC) TIOA Mirror
-+#define AT91C_TC_MTIOB ( 0x1 << 18) // (TC) TIOA Mirror
-+// -------- TC_IER : (TC Offset: 0x24) TC Channel Interrupt Enable Register --------
-+// -------- TC_IDR : (TC Offset: 0x28) TC Channel Interrupt Disable Register --------
-+// -------- TC_IMR : (TC Offset: 0x2c) TC Channel Interrupt Mask Register --------
-+
-+// *****************************************************************************
-+// SOFTWARE API DEFINITION FOR Timer Counter Interface
-+// *****************************************************************************
-+// -------- TCB_BCR : (TCB Offset: 0xc0) TC Block Control Register --------
-+#define AT91C_TCB_SYNC ( 0x1 << 0) // (TCB) Synchro Command
-+// -------- TCB_BMR : (TCB Offset: 0xc4) TC Block Mode Register --------
-+#define AT91C_TCB_TC0XC0S ( 0x1 << 0) // (TCB) External Clock Signal 0 Selection
-+#define AT91C_TCB_TC0XC0S_TCLK0 ( 0x0) // (TCB) TCLK0 connected to XC0
-+#define AT91C_TCB_TC0XC0S_NONE ( 0x1) // (TCB) None signal connected to XC0
-+#define AT91C_TCB_TC0XC0S_TIOA1 ( 0x2) // (TCB) TIOA1 connected to XC0
-+#define AT91C_TCB_TC0XC0S_TIOA2 ( 0x3) // (TCB) TIOA2 connected to XC0
-+#define AT91C_TCB_TC1XC1S ( 0x1 << 2) // (TCB) External Clock Signal 1 Selection
-+#define AT91C_TCB_TC1XC1S_TCLK1 ( 0x0 << 2) // (TCB) TCLK1 connected to XC1
-+#define AT91C_TCB_TC1XC1S_NONE ( 0x1 << 2) // (TCB) None signal connected to XC1
-+#define AT91C_TCB_TC1XC1S_TIOA0 ( 0x2 << 2) // (TCB) TIOA0 connected to XC1
-+#define AT91C_TCB_TC1XC1S_TIOA2 ( 0x3 << 2) // (TCB) TIOA2 connected to XC1
-+#define AT91C_TCB_TC2XC2S ( 0x1 << 4) // (TCB) External Clock Signal 2 Selection
-+#define AT91C_TCB_TC2XC2S_TCLK2 ( 0x0 << 4) // (TCB) TCLK2 connected to XC2
-+#define AT91C_TCB_TC2XC2S_NONE ( 0x1 << 4) // (TCB) None signal connected to XC2
-+#define AT91C_TCB_TC2XC2S_TIOA0 ( 0x2 << 4) // (TCB) TIOA0 connected to XC2
-+#define AT91C_TCB_TC2XC2S_TIOA2 ( 0x3 << 4) // (TCB) TIOA2 connected to XC2
-+
-+#endif
---- linux-2.4.27/include/asm-arm/arch-at91rm9200/at91rm9200dk.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/at91rm9200dk.h
-@@ -17,9 +17,9 @@
-
- /* AT91RM92000 clocks */
- #define AT91C_MAIN_CLOCK 179712000 /* from 18.432 MHz crystal (18432000 / 4 * 39) */
--#define AT91C_MASTER_CLOCK 59904000 /* peripheral clock (AT91C_MASTER_CLOCK / 3) */
-+#define AT91C_MASTER_CLOCK 59904000 /* peripheral clock (AT91C_MAIN_CLOCK / 3) */
- #define AT91C_SLOW_CLOCK 32768 /* slow clock */
--
-+#define AT91_PLLB_INIT 0x1048be0e /* (18.432 / 14 * 73) /2 = 47.9714 */
-
- /* FLASH */
- #define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
-@@ -68,6 +68,7 @@
- #define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
- #define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
-
-+#define AT91C_CONSOLE_DEFAULT_BAUDRATE 115200 /* default serial console baud-rate */
-
- /*
- * Serial port configuration.
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/csb337.h
-@@ -0,0 +1,82 @@
-+/*
-+ * linux/include/asm-arm/arch-at91rm9200/csb337.h
-+ *
-+ * Copyright (c) 2003 Christopher Bahns & David Knickerbocker
-+ * Polaroid Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef __ASM_ARCH_HARDWARE_CSB337_H
-+#define __ASM_ARCH_HARDWARE_CSB337_H
-+
-+
-+/* AT91RM92000 clocks on CSB337 */
-+#define AT91C_MAIN_CLOCK 184320000
-+#define AT91C_MASTER_CLOCK 46080000 /* peripheral clock (AT91C_MAIN_CLOCK / 4) */
-+#define AT91C_SLOW_CLOCK 32768 /* slow clock */
-+#define AT91_PLLB_INIT 0x128a3e19 /* (3.6864 * (650+1) / 25) /2 = 47.9969 */
-+
-+/* FLASH */
-+#define AT91_FLASH_BASE 0x10000000 // NCS0: Flash physical base address
-+
-+/* SDRAM */
-+#define AT91_SDRAM_BASE 0x20000000 // NCS1: SDRAM physical base address
-+
-+/* SmartMedia */
-+#define AT91_SMARTMEDIA_BASE 0x40000000 // NCS3: Smartmedia physical base address
-+
-+/* Multi-Master Memory controller */
-+#define AT91_UHP_BASE 0x00300000 // USB Host controller
-+
-+
-+/* Peripheral interrupt configuration */
-+#define AT91_SMR_FIQ (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (FIQ)
-+#define AT91_SMR_SYS (AT91C_AIC_PRIOR_HIGHEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // System Peripheral
-+#define AT91_SMR_PIOA (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller A
-+#define AT91_SMR_PIOB (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller B
-+#define AT91_SMR_PIOC (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller C
-+#define AT91_SMR_PIOD (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Parallel IO Controller D
-+#define AT91_SMR_US0 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 0
-+#define AT91_SMR_US1 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 1
-+#define AT91_SMR_US2 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 2
-+#define AT91_SMR_US3 (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USART 3
-+#define AT91_SMR_MCI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Multimedia Card Interface
-+#define AT91_SMR_UDP (AT91C_AIC_PRIOR_4 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Device Port
-+#define AT91_SMR_TWI (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Two-Wire Interface
-+#define AT91_SMR_SPI (AT91C_AIC_PRIOR_6 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Peripheral Interface
-+#define AT91_SMR_SSC0 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 0
-+#define AT91_SMR_SSC1 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 1
-+#define AT91_SMR_SSC2 (AT91C_AIC_PRIOR_5 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Serial Synchronous Controller 2
-+#define AT91_SMR_TC0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 0
-+#define AT91_SMR_TC1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 1
-+#define AT91_SMR_TC2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 2
-+#define AT91_SMR_TC3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 3
-+#define AT91_SMR_TC4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 4
-+#define AT91_SMR_TC5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Timer Counter 5
-+#define AT91_SMR_UHP (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // USB Host port
-+#define AT91_SMR_EMAC (AT91C_AIC_PRIOR_3 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Ethernet MAC
-+#define AT91_SMR_IRQ0 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ0)
-+#define AT91_SMR_IRQ1 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ1)
-+#define AT91_SMR_IRQ2 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ2)
-+#define AT91_SMR_IRQ3 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ3)
-+#define AT91_SMR_IRQ4 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ4)
-+#define AT91_SMR_IRQ5 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ5)
-+#define AT91_SMR_IRQ6 (AT91C_AIC_PRIOR_LOWEST | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE) // Advanced Interrupt Controller (IRQ6)
-+
-+
-+#define AT91C_CONSOLE_DEFAULT_BAUDRATE 38400
-+
-+/*
-+ * Serial port configuration.
-+ * 0 .. 3 = USART0 .. USART3
-+ * 4 = DBGU
-+ */
-+#define AT91C_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
-+#define AT91C_CONSOLE 0 /* ttyS0 */
-+
-+#endif
---- linux-2.4.27/include/asm-arm/arch-at91rm9200/hardware.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/hardware.h
-@@ -60,6 +60,7 @@
-
-
- #define AT91C_BASE_SRAM 0x00200000 /* Internal SRAM base address */
-+#define AT91C_SRAM_SIZE 0x00004000 /* Internal SRAM SIZE (16Kb) */
-
- #define AT91C_NR_UART 5 /* 4 USART3's and one DBGU port */
-
-@@ -82,5 +83,8 @@
- #include <asm/arch/at91rm9200dk.h>
- #endif
-
-+#ifdef CONFIG_MACH_CSB337
-+#include <asm/arch/csb337.h>
-+#endif
-
- #endif
---- linux-2.4.27/include/asm-arm/arch-at91rm9200/pio.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/pio.h
-@@ -17,7 +17,15 @@
-
- static inline void AT91_CfgPIO_USART0(void) {
- AT91_SYS->PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0
-- | AT91C_PA20_CTS0 | AT91C_PA21_RTS0;
-+ | AT91C_PA20_CTS0;
-+
-+ /*
-+ * Errata #39 - RTS0 is not internally connected to PA21. We need to drive
-+ * the pin manually. Default is off (RTS is active low).
-+ */
-+ AT91_SYS->PIOA_PER = AT91C_PA21_RTS0;
-+ AT91_SYS->PIOA_OER = AT91C_PA21_RTS0;
-+ AT91_SYS->PIOA_SODR = AT91C_PA21_RTS0;
- }
-
- static inline void AT91_CfgPIO_USART1(void) {
-@@ -66,6 +74,18 @@
- }
-
- /*
-+ * Configure interrupt from Ethernet PHY.
-+ */
-+static inline void AT91_CfgPIO_EMAC_PHY(void) {
-+ AT91_SYS->PMC_PCER = 1 << AT91C_ID_PIOC; /* enable peripheral clock */
-+#ifdef CONFIG_MACH_CSB337
-+ AT91_SYS->PIOC_ODR = AT91C_PIO_PC2;
-+#else
-+ AT91_SYS->PIOC_ODR = AT91C_PIO_PC4;
-+#endif
-+}
-+
-+/*
- * Enable the Two-Wire interface.
- */
- static inline void AT91_CfgPIO_TWI(void) {
---- linux-2.4.27/include/asm-arm/arch-at91rm9200/time.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-at91rm9200/time.h
-@@ -27,6 +27,21 @@
- extern unsigned long (*gettimeoffset)(void);
-
- /*
-+ * The ST_CRTR is updated asynchronously to the master clock. It is therefore
-+ * necessary to read it twice (with the same value) to ensure accuracy.
-+ */
-+static inline unsigned long read_CRTR(void) {
-+ unsigned long x1, x2;
-+
-+ do {
-+ x1 = AT91_SYS->ST_CRTR;
-+ x2 = AT91_SYS->ST_CRTR;
-+ } while (x1 != x2);
-+
-+ return x1;
-+}
-+
-+/*
- * Returns number of microseconds since last timer interrupt. Note that interrupts
- * will have been disabled by do_gettimeofday()
- * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
-@@ -36,7 +51,7 @@
- {
- unsigned long elapsed;
-
-- elapsed = (AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
-+ elapsed = (read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV;
-
- return (unsigned long)(elapsed * tick) / LATCH;
- }
-@@ -48,11 +63,12 @@
- {
- if (AT91_SYS->ST_SR & AT91C_ST_PITS) { /* This is a shared interrupt */
- do {
-+ do_leds();
- do_timer(regs);
-
- AT91_SYS->ST_RTAR = (AT91_SYS->ST_RTAR + LATCH) & AT91C_ST_ALMV;
-
-- } while (((AT91_SYS->ST_CRTR - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
-+ } while (((read_CRTR() - AT91_SYS->ST_RTAR) & AT91C_ST_ALMV) >= LATCH);
-
- do_profile(regs);
- }
---- linux-2.4.27/include/asm-arm/arch-clps711x/system.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-clps711x/system.h
-@@ -28,8 +28,8 @@
- {
- clps_writel(1, HALT);
- __asm__ __volatile__(
-- "mov r0, r0
-- mov r0, r0");
-+ "mov r0, r0\n\t"
-+ "mov r0, r0");
- }
-
- static inline void arch_reset(char mode)
---- linux-2.4.27/include/asm-arm/arch-integrator/uncompress.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-integrator/uncompress.h
-@@ -18,6 +18,8 @@
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-+#include <asm/hardware/serial_amba.h>
-+
- #define AMBA_UART_DR (*(volatile unsigned char *)0x16000000)
- #define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
- #define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
-@@ -30,21 +32,25 @@
- */
- static void puts(const char *s)
- {
-+ /* Do nothing if the UART is not enabled. */
-+ if (!(AMBA_UART_CR & AMBA_UARTCR_UARTEN))
-+ return;
-+
- while (*s) {
-- while (AMBA_UART_FR & (1 << 5))
-+ while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
- barrier();
-
- AMBA_UART_DR = *s;
-
- if (*s == '\n') {
-- while (AMBA_UART_FR & (1 << 5))
-+ while (AMBA_UART_FR & AMBA_UARTFR_TXFF)
- barrier();
-
- AMBA_UART_DR = '\r';
- }
- s++;
- }
-- while (AMBA_UART_FR & (1 << 3));
-+ while (AMBA_UART_FR & AMBA_UARTFR_BUSY);
- }
-
- /*
---- linux-2.4.27/include/asm-arm/arch-riscstation/system.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-riscstation/system.h
-@@ -1,5 +1,5 @@
- /*
-- * linux/include/asm-arm/arch-rpc/system.h
-+ * linux/include/asm-arm/arch-riscstation/system.h
- *
- * Copyright (C) 1996-1999 Russell King.
- *
-@@ -18,7 +18,7 @@
-
- static inline void arch_reset(char mode)
- {
-- iomd_writeb(0, IOMD_ROMCR0);
-+ iomd_writeb(0x40, IOMD_ROMCR0);
-
- /*
- * Jump into the ROM
---- linux-2.4.27/include/asm-arm/arch-rpc/uncompress.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/arch-rpc/uncompress.h
-@@ -11,29 +11,12 @@
-
- #include <asm/hardware.h>
- #include <asm/io.h>
-+#include <asm/setup.h>
-
- int video_num_columns, video_num_lines, video_size_row;
- int white, bytes_per_char_h;
- extern unsigned long con_charconvtable[256];
-
--struct param_struct {
-- unsigned long page_size;
-- unsigned long nr_pages;
-- unsigned long ramdisk_size;
-- unsigned long mountrootrdonly;
-- unsigned long rootdev;
-- unsigned long video_num_cols;
-- unsigned long video_num_rows;
-- unsigned long video_x;
-- unsigned long video_y;
-- unsigned long memc_control_reg;
-- unsigned char sounddefault;
-- unsigned char adfsdrives;
-- unsigned char bytes_per_char_h;
-- unsigned char bytes_per_char_v;
-- unsigned long unused[256/4-11];
--};
--
- static const unsigned long palette_4[16] = {
- 0x00000000,
- 0x000000cc,
-@@ -69,8 +52,12 @@
- unsigned char c;
- char *ptr;
-
-- x = params->video_x;
-- y = params->video_y;
-+ /* Don't bother when using a tagged list */
-+ if (((struct tag *)params)->hdr.tag == ATAG_CORE)
-+ return;
-+
-+ x = params->u1.s.video_x;
-+ y = params->u1.s.video_y;
-
- while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
- if ( c == '\n' ) {
-@@ -79,7 +66,7 @@
- y--;
- }
- } else {
-- ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
-+ ptr = VIDMEM + ((y*video_num_columns*params->u1.s.bytes_per_char_v+x)*bytes_per_char_h);
- ll_write_char(ptr, c, white);
- if ( ++x >= video_num_columns ) {
- x = 0;
-@@ -90,8 +77,6 @@
- }
- }
-
-- params->video_x = x;
-- params->video_y = y;
- }
-
- static void error(char *x);
-@@ -103,9 +88,13 @@
- {
- int i;
-
-- video_num_lines = params->video_num_rows;
-- video_num_columns = params->video_num_cols;
-- bytes_per_char_h = params->bytes_per_char_h;
-+ /* Don't bother when using a tagged list */
-+ if (((struct tag *)params)->hdr.tag == ATAG_CORE)
-+ return;
-+
-+ video_num_lines = params->u1.s.video_num_rows;
-+ video_num_columns = params->u1.s.video_num_cols;
-+ bytes_per_char_h = params->u1.s.bytes_per_char_h;
- video_size_row = video_num_columns * bytes_per_char_h;
- if (bytes_per_char_h == 4)
- for (i = 0; i < 256; i++)
-@@ -140,7 +129,7 @@
- white = 7;
- }
-
-- if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
-+ if (params->u1.s.nr_pages * params->u1.s.page_size < 4096*1024) error("<4M of mem\n");
- }
- #endif
-
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-clock.h
-@@ -0,0 +1,76 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-clock.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 clock register definitions
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_CLOCK_H
-+#define ASMARM_ARCH_S3C2410_CLOCK_H
-+
-+#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
-+
-+#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
-+
-+#define S3C2410_LOCKTIME S3C2410_CLKREG(0x00)
-+#define S3C2410_MPLLCON S3C2410_CLKREG(0x04)
-+#define S3C2410_UPLLCON S3C2410_CLKREG(0x08)
-+#define S3C2410_CLKCON S3C2410_CLKREG(0x0C)
-+#define S3C2410_CLKSLOW S3C2410_CLKREG(0x10)
-+#define S3C2410_CLKDIVN S3C2410_CLKREG(0x14)
-+
-+#define S3C2410_PLLCON_MDIVSHIFT 12
-+#define S3C2410_PLLCON_PDIVSHIFT 4
-+#define S3C2410_PLLCON_SDIVSHIFT 0
-+#define S3C2410_PLLCON_MDIVMASK ((1<<(1+(19-12)))-1)
-+#define S3C2410_PLLCON_PDIVMASK ((1<<5)-1)
-+#define S3C2410_PLLCON_SDIVMASK 3
-+
-+/* DCLKCON register addresses in gpio.h */
-+
-+#define S3C2410_DCLKCON_DCLK0EN (1<<0)
-+#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
-+#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
-+#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
-+#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
-+
-+#define S3C2410_DCLKCON_DCLK1EN (1<<16)
-+#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
-+#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
-+#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
-+
-+#define S3C2410_CLKDIVN_PDIVN (1<<0)
-+#define S3C2410_CLKDIVN_HDIVN (1<<1)
-+
-+static inline unsigned int
-+s3c2410_get_pll(int pllval, int baseclk)
-+{
-+ int mdiv, pdiv, sdiv;
-+
-+ mdiv = pllval >> S3C2410_PLLCON_MDIVSHIFT;
-+ pdiv = pllval >> S3C2410_PLLCON_PDIVSHIFT;
-+ sdiv = pllval >> S3C2410_PLLCON_SDIVSHIFT;
-+
-+ mdiv &= S3C2410_PLLCON_MDIVMASK;
-+ pdiv &= S3C2410_PLLCON_PDIVMASK;
-+ sdiv &= S3C2410_PLLCON_SDIVMASK;
-+
-+ return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
-+}
-+
-+#endif /* ASMARM_ARCH_S3C2410_CLOCK_H */
-+
-+
-+
-+
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
-@@ -0,0 +1,602 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-gpio.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 GPIO register definitions
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ * 23-06-2003 BJD Updated GSTATUS registers
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_GPIO_H
-+#define ASMARM_ARCH_S3C2410_GPIO_H
-+
-+/* configure GPIO ports A..G */
-+
-+#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
-+
-+/* port A - 22bits, zero in bit X makes pin X output
-+ * 1 makes port special function, this is default
-+*/
-+#define S3C2410_GPACON S3C2410_GPIOREG(0x00)
-+#define S3C2410_GPADAT S3C2410_GPIOREG(0x04)
-+
-+/* 0x08 and 0x0c are reserved */
-+
-+/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
-+ * 00 = input, 01 = output, 10=special function, 11=reserved
-+ * bit 0,1 = pin 0, 2,3= pin 1...
-+ *
-+ * CPBUP = pull up resistor control, 1=disabled, 0=enabled
-+*/
-+
-+#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
-+#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
-+#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
-+
-+/* no i/o pin in port b can have value 3! */
-+
-+#define S3C2410_GPB0_INP (0x00 << 0)
-+#define S3C2410_GPB0_OUTP (0x01 << 0)
-+#define S3C2410_GPB0_TOUT0 (0x02 << 0)
-+
-+#define S3C2410_GPB1_INP (0x00 << 2)
-+#define S3C2410_GPB1_OUTP (0x01 << 2)
-+#define S3C2410_GPB1_TOUT1 (0x02 << 2)
-+
-+#define S3C2410_GPB2_INP (0x00 << 4)
-+#define S3C2410_GPB2_OUTP (0x01 << 4)
-+#define S3C2410_GPB2_TOUT2 (0x02 << 4)
-+
-+#define S3C2410_GPB3_INP (0x00 << 6)
-+#define S3C2410_GPB3_OUTP (0x01 << 6)
-+#define S3C2410_GPB3_TOUT3 (0x02 << 6)
-+
-+#define S3C2410_GPB4_INP (0x00 << 8)
-+#define S3C2410_GPB4_OUTP (0x01 << 8)
-+#define S3C2410_GPB4_TCLK0 (0x02 << 8)
-+#define S3C2410_GPB4_MASK (0x03 << 8)
-+
-+#define S3C2410_GPB5_INP (0x00 << 10)
-+#define S3C2410_GPB5_OUTP (0x01 << 10)
-+#define S3C2410_GPB5_nXBACK (0x02 << 10)
-+
-+#define S3C2410_GPB6_INP (0x00 << 12)
-+#define S3C2410_GPB6_OUTP (0x01 << 12)
-+#define S3C2410_GPB6_nXBREQ (0x02 << 12)
-+
-+#define S3C2410_GPB7_INP (0x00 << 14)
-+#define S3C2410_GPB7_OUTP (0x01 << 14)
-+#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
-+
-+#define S3C2410_GPB8_INP (0x00 << 16)
-+#define S3C2410_GPB8_OUTP (0x01 << 16)
-+#define S3C2410_GPB8_nXDREQ1 (0x02 << 16)
-+
-+#define S3C2410_GPB9_INP (0x00 << 18)
-+#define S3C2410_GPB9_OUTP (0x01 << 18)
-+#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
-+
-+#define S3C2410_GPB10_INP (0x00 << 18)
-+#define S3C2410_GPB10_OUTP (0x01 << 18)
-+#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
-+
-+/* Port C consits of 16 GPIO/Special function
-+ *
-+ * almost identical setup to port b, but the special functions are mostly
-+ * to do with the video system's sync/etc.
-+*/
-+
-+#define S3C2410_GPCCON S3C2410_GPIOREG(0x20)
-+#define S3C2410_GPCDAT S3C2410_GPIOREG(0x24)
-+#define S3C2410_GPCUP S3C2410_GPIOREG(0x28)
-+
-+#define S3C2410_GPC0_INP (0x00 << 0)
-+#define S3C2410_GPC0_OUTP (0x01 << 0)
-+#define S3C2410_GPC0_LEND (0x02 << 0)
-+
-+#define S3C2410_GPC1_INP (0x00 << 2)
-+#define S3C2410_GPC1_OUTP (0x01 << 2)
-+#define S3C2410_GPC1_VCLK (0x02 << 2)
-+
-+#define S3C2410_GPC2_INP (0x00 << 4)
-+#define S3C2410_GPC2_OUTP (0x01 << 4)
-+#define S3C2410_GPC2_VLINE (0x02 << 4)
-+
-+#define S3C2410_GPC3_INP (0x00 << 6)
-+#define S3C2410_GPC3_OUTP (0x01 << 6)
-+#define S3C2410_GPC3_VFRAME (0x02 << 6)
-+
-+#define S3C2410_GPC4_INP (0x00 << 8)
-+#define S3C2410_GPC4_OUTP (0x01 << 8)
-+#define S3C2410_GPC4_VM (0x02 << 8)
-+
-+#define S3C2410_GPC5_INP (0x00 << 10)
-+#define S3C2410_GPC5_OUTP (0x01 << 10)
-+#define S3C2410_GPC5_LCDVF0 (0x02 << 10)
-+
-+#define S3C2410_GPC6_INP (0x00 << 12)
-+#define S3C2410_GPC6_OUTP (0x01 << 12)
-+#define S3C2410_GPC6_LCDVF1 (0x02 << 12)
-+
-+#define S3C2410_GPC7_INP (0x00 << 14)
-+#define S3C2410_GPC7_OUTP (0x01 << 14)
-+#define S3C2410_GPC7_LCDVF2 (0x02 << 14)
-+
-+#define S3C2410_GPC8_INP (0x00 << 16)
-+#define S3C2410_GPC8_OUTP (0x01 << 16)
-+#define S3C2410_GPC8_VD0 (0x02 << 16)
-+
-+#define S3C2410_GPC9_INP (0x00 << 18)
-+#define S3C2410_GPC9_OUTP (0x01 << 18)
-+#define S3C2410_GPC9_VD1 (0x02 << 18)
-+
-+#define S3C2410_GPC10_INP (0x00 << 20)
-+#define S3C2410_GPC10_OUTP (0x01 << 20)
-+#define S3C2410_GPC10_VD2 (0x02 << 20)
-+
-+#define S3C2410_GPC11_INP (0x00 << 22)
-+#define S3C2410_GPC11_OUTP (0x01 << 22)
-+#define S3C2410_GPC11_VD3 (0x02 << 22)
-+
-+#define S3C2410_GPC12_INP (0x00 << 24)
-+#define S3C2410_GPC12_OUTP (0x01 << 24)
-+#define S3C2410_GPC12_VD4 (0x02 << 24)
-+
-+#define S3C2410_GPC13_INP (0x00 << 26)
-+#define S3C2410_GPC13_OUTP (0x01 << 26)
-+#define S3C2410_GPC13_VD5 (0x02 << 26)
-+
-+#define S3C2410_GPC14_INP (0x00 << 28)
-+#define S3C2410_GPC14_OUTP (0x01 << 28)
-+#define S3C2410_GPC14_VD6 (0x02 << 28)
-+
-+#define S3C2410_GPC15_INP (0x00 << 30)
-+#define S3C2410_GPC15_OUTP (0x01 << 30)
-+#define S3C2410_GPC15_VD7 (0x02 << 30)
-+
-+/* Port D consists of 16 GPIO/Special function
-+ *
-+ * almost identical setup to port b, but the special functions are mostly
-+ * to do with the video system's data.
-+*/
-+
-+#define S3C2410_GPDCON S3C2410_GPIOREG(0x30)
-+#define S3C2410_GPDDAT S3C2410_GPIOREG(0x34)
-+#define S3C2410_GPDUP S3C2410_GPIOREG(0x38)
-+
-+#define S3C2410_GPD0_INP (0x00 << 0)
-+#define S3C2410_GPD0_OUTP (0x01 << 0)
-+#define S3C2410_GPD0_VD8 (0x02 << 0)
-+
-+#define S3C2410_GPD1_INP (0x00 << 2)
-+#define S3C2410_GPD1_OUTP (0x01 << 2)
-+#define S3C2410_GPD1_VD9 (0x02 << 2)
-+
-+#define S3C2410_GPD2_INP (0x00 << 4)
-+#define S3C2410_GPD2_OUTP (0x01 << 4)
-+#define S3C2410_GPD2_VD10 (0x02 << 4)
-+
-+#define S3C2410_GPD3_INP (0x00 << 6)
-+#define S3C2410_GPD3_OUTP (0x01 << 6)
-+#define S3C2410_GPD3_VD11 (0x02 << 6)
-+
-+#define S3C2410_GPD4_INP (0x00 << 8)
-+#define S3C2410_GPD4_OUTP (0x01 << 8)
-+#define S3C2410_GPD4_VD12 (0x02 << 8)
-+
-+#define S3C2410_GPD5_INP (0x00 << 10)
-+#define S3C2410_GPD5_OUTP (0x01 << 10)
-+#define S3C2410_GPD5_VD13 (0x02 << 10)
-+
-+#define S3C2410_GPD6_INP (0x00 << 12)
-+#define S3C2410_GPD6_OUTP (0x01 << 12)
-+#define S3C2410_GPD6_VD14 (0x02 << 12)
-+
-+#define S3C2410_GPD7_INP (0x00 << 14)
-+#define S3C2410_GPD7_OUTP (0x01 << 14)
-+#define S3C2410_GPD7_VD15 (0x02 << 14)
-+
-+#define S3C2410_GPD8_INP (0x00 << 16)
-+#define S3C2410_GPD8_OUTP (0x01 << 16)
-+#define S3C2410_GPD8_VD16 (0x02 << 16)
-+
-+#define S3C2410_GPD9_INP (0x00 << 18)
-+#define S3C2410_GPD9_OUTP (0x01 << 18)
-+#define S3C2410_GPD9_VD17 (0x02 << 18)
-+
-+#define S3C2410_GPD10_INP (0x00 << 20)
-+#define S3C2410_GPD10_OUTP (0x01 << 20)
-+#define S3C2410_GPD10_VD18 (0x02 << 20)
-+
-+#define S3C2410_GPD11_INP (0x00 << 22)
-+#define S3C2410_GPD11_OUTP (0x01 << 22)
-+#define S3C2410_GPD11_VD19 (0x02 << 22)
-+
-+#define S3C2410_GPD12_INP (0x00 << 24)
-+#define S3C2410_GPD12_OUTP (0x01 << 24)
-+#define S3C2410_GPD12_VD20 (0x02 << 24)
-+
-+#define S3C2410_GPD13_INP (0x00 << 26)
-+#define S3C2410_GPD13_OUTP (0x01 << 26)
-+#define S3C2410_GPD13_VD21 (0x02 << 26)
-+
-+#define S3C2410_GPD14_INP (0x00 << 28)
-+#define S3C2410_GPD14_OUTP (0x01 << 28)
-+#define S3C2410_GPD14_VD22 (0x02 << 28)
-+
-+#define S3C2410_GPD15_INP (0x00 << 30)
-+#define S3C2410_GPD15_OUTP (0x01 << 30)
-+#define S3C2410_GPD15_VD23 (0x02 << 30)
-+
-+/* Port E consists of 16 GPIO/Special function
-+ *
-+ * again, the same as port B, but dealing with I2S, SDI, and
-+ * more miscellaneous functions
-+*/
-+
-+#define S3C2410_GPECON S3C2410_GPIOREG(0x40)
-+#define S3C2410_GPEDAT S3C2410_GPIOREG(0x44)
-+#define S3C2410_GPEUP S3C2410_GPIOREG(0x48)
-+
-+#define S3C2410_GPE0_INP (0x00 << 0)
-+#define S3C2410_GPE0_OUTP (0x01 << 0)
-+#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
-+#define S3C2410_GPE0_MASK (0x03 << 0)
-+
-+#define S3C2410_GPE1_INP (0x00 << 2)
-+#define S3C2410_GPE1_OUTP (0x01 << 2)
-+#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
-+#define S3C2410_GPE1_MASK (0x03 << 2)
-+
-+#define S3C2410_GPE2_INP (0x00 << 4)
-+#define S3C2410_GPE2_OUTP (0x01 << 4)
-+#define S3C2410_GPE2_CDCLK (0x02 << 4)
-+
-+#define S3C2410_GPE3_INP (0x00 << 6)
-+#define S3C2410_GPE3_OUTP (0x01 << 6)
-+#define S3C2410_GPE3_I2SSDI (0x02 << 6)
-+#define S3C2410_GPE3_MASK (0x03 << 6)
-+
-+#define S3C2410_GPE4_INP (0x00 << 8)
-+#define S3C2410_GPE4_OUTP (0x01 << 8)
-+#define S3C2410_GPE4_I2SSDO (0x02 << 8)
-+#define S3C2410_GPE4_MASK (0x03 << 8)
-+
-+#define S3C2410_GPE5_INP (0x00 << 10)
-+#define S3C2410_GPE5_OUTP (0x01 << 10)
-+#define S3C2410_GPE5_SDCLK (0x02 << 10)
-+
-+#define S3C2410_GPE6_INP (0x00 << 12)
-+#define S3C2410_GPE6_OUTP (0x01 << 12)
-+#define S3C2410_GPE6_SDCLK (0x02 << 12)
-+
-+#define S3C2410_GPE7_INP (0x00 << 14)
-+#define S3C2410_GPE7_OUTP (0x01 << 14)
-+#define S3C2410_GPE7_SDCMD (0x02 << 14)
-+
-+#define S3C2410_GPE8_INP (0x00 << 16)
-+#define S3C2410_GPE8_OUTP (0x01 << 16)
-+#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
-+
-+#define S3C2410_GPE9_INP (0x00 << 18)
-+#define S3C2410_GPE9_OUTP (0x01 << 18)
-+#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
-+
-+#define S3C2410_GPE10_INP (0x00 << 20)
-+#define S3C2410_GPE10_OUTP (0x01 << 20)
-+#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
-+
-+#define S3C2410_GPE11_INP (0x00 << 22)
-+#define S3C2410_GPE11_OUTP (0x01 << 22)
-+#define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
-+
-+#define S3C2410_GPE12_INP (0x00 << 24)
-+#define S3C2410_GPE12_OUTP (0x01 << 24)
-+#define S3C2410_GPE12_SPIMOSI0 (0x02 << 24)
-+
-+#define S3C2410_GPE13_INP (0x00 << 26)
-+#define S3C2410_GPE13_OUTP (0x01 << 26)
-+#define S3C2410_GPE13_SPICLK0 (0x02 << 26)
-+
-+#define S3C2410_GPE14_INP (0x00 << 28)
-+#define S3C2410_GPE14_OUTP (0x01 << 28)
-+#define S3C2410_GPE14_IICSCL (0x02 << 28)
-+#define S3C2410_GPE14_MASK (0x03 << 28)
-+
-+#define S3C2410_GPE15_INP (0x00 << 30)
-+#define S3C2410_GPE15_OUTP (0x01 << 30)
-+#define S3C2410_GPE15_IICSDA (0x02 << 30)
-+#define S3C2410_GPE15_MASK (0x03 << 30)
-+
-+#define S3C2410_GPE_PUPDIS(x) (1<<(x))
-+
-+/* Port F consists of 8 GPIO/Special function
-+ *
-+ * GPIO / interrupt inputs
-+ *
-+ * GPFCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 undefined
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPFCON S3C2410_GPIOREG(0x50)
-+#define S3C2410_GPFDAT S3C2410_GPIOREG(0x54)
-+#define S3C2410_GPFUP S3C2410_GPIOREG(0x58)
-+
-+
-+#define S3C2410_GPF0_INP (0x00 << 0)
-+#define S3C2410_GPF0_OUTP (0x01 << 0)
-+#define S3C2410_GPF0_EINT0 (0x02 << 0)
-+
-+#define S3C2410_GPF1_INP (0x00 << 2)
-+#define S3C2410_GPF1_OUTP (0x01 << 2)
-+#define S3C2410_GPF1_EINT1 (0x02 << 2)
-+
-+#define S3C2410_GPF2_INP (0x00 << 4)
-+#define S3C2410_GPF2_OUTP (0x01 << 4)
-+#define S3C2410_GPF2_EINT2 (0x02 << 4)
-+
-+#define S3C2410_GPF3_INP (0x00 << 6)
-+#define S3C2410_GPF3_OUTP (0x01 << 6)
-+#define S3C2410_GPF3_EINT3 (0x02 << 6)
-+
-+#define S3C2410_GPF4_INP (0x00 << 8)
-+#define S3C2410_GPF4_OUTP (0x01 << 8)
-+#define S3C2410_GPF4_EINT4 (0x02 << 8)
-+
-+#define S3C2410_GPF5_INP (0x00 << 10)
-+#define S3C2410_GPF5_OUTP (0x01 << 10)
-+#define S3C2410_GPF5_EINT5 (0x02 << 10)
-+
-+#define S3C2410_GPF6_INP (0x00 << 12)
-+#define S3C2410_GPF6_OUTP (0x01 << 12)
-+#define S3C2410_GPF6_EINT6 (0x02 << 12)
-+
-+#define S3C2410_GPF7_INP (0x00 << 14)
-+#define S3C2410_GPF7_OUTP (0x01 << 14)
-+#define S3C2410_GPF7_EINT7 (0x02 << 14)
-+
-+/* Port G consists of 8 GPIO/IRQ/Special function
-+ *
-+ * GPGCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPGCON S3C2410_GPIOREG(0x60)
-+#define S3C2410_GPGDAT S3C2410_GPIOREG(0x64)
-+#define S3C2410_GPGUP S3C2410_GPIOREG(0x68)
-+
-+#define S3C2410_GPG0_INP (0x00 << 0)
-+#define S3C2410_GPG0_OUTP (0x01 << 0)
-+#define S3C2410_GPG0_EINT8 (0x02 << 0)
-+
-+#define S3C2410_GPG1_INP (0x00 << 2)
-+#define S3C2410_GPG1_OUTP (0x01 << 2)
-+#define S3C2410_GPG1_EINT9 (0x02 << 2)
-+
-+#define S3C2410_GPG2_INP (0x00 << 4)
-+#define S3C2410_GPG2_OUTP (0x01 << 4)
-+#define S3C2410_GPG2_EINT10 (0x02 << 4)
-+
-+#define S3C2410_GPG3_INP (0x00 << 6)
-+#define S3C2410_GPG3_OUTP (0x01 << 6)
-+#define S3C2410_GPG3_EINT11 (0x02 << 6)
-+
-+#define S3C2410_GPG4_INP (0x00 << 8)
-+#define S3C2410_GPG4_OUTP (0x01 << 8)
-+#define S3C2410_GPG4_EINT12 (0x02 << 8)
-+#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
-+
-+#define S3C2410_GPG5_INP (0x00 << 10)
-+#define S3C2410_GPG5_OUTP (0x01 << 10)
-+#define S3C2410_GPG5_EINT13 (0x02 << 10)
-+#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
-+
-+#define S3C2410_GPG6_INP (0x00 << 12)
-+#define S3C2410_GPG6_OUTP (0x01 << 12)
-+#define S3C2410_GPG6_EINT14 (0x02 << 12)
-+#define S3C2410_GPG6_SPIMOSI1 (0x03 << 12)
-+
-+#define S3C2410_GPG7_INP (0x00 << 14)
-+#define S3C2410_GPG7_OUTP (0x01 << 14)
-+#define S3C2410_GPG7_EINT15 (0x02 << 14)
-+#define S3C2410_GPG7_SPICLK1 (0x03 << 14)
-+
-+#define S3C2410_GPG8_INP (0x00 << 16)
-+#define S3C2410_GPG8_OUTP (0x01 << 16)
-+#define S3C2410_GPG8_EINT16 (0x02 << 16)
-+
-+#define S3C2410_GPG9_INP (0x00 << 18)
-+#define S3C2410_GPG9_OUTP (0x01 << 18)
-+#define S3C2410_GPG9_EINT17 (0x02 << 18)
-+
-+#define S3C2410_GPG10_INP (0x00 << 20)
-+#define S3C2410_GPG10_OUTP (0x01 << 20)
-+#define S3C2410_GPG10_EINT18 (0x02 << 20)
-+
-+#define S3C2410_GPG11_INP (0x00 << 22)
-+#define S3C2410_GPG11_OUTP (0x01 << 22)
-+#define S3C2410_GPG11_EINT19 (0x02 << 22)
-+#define S3C2410_GPG11_TCLK1 (0x03 << 22)
-+
-+#define S3C2410_GPG12_INP (0x00 << 24)
-+#define S3C2410_GPG12_OUTP (0x01 << 24)
-+#define S3C2410_GPG12_EINT18 (0x02 << 24)
-+#define S3C2410_GPG12_XMON (0x03 << 24)
-+
-+#define S3C2410_GPG13_INP (0x00 << 26)
-+#define S3C2410_GPG13_OUTP (0x01 << 26)
-+#define S3C2410_GPG13_EINT18 (0x02 << 26)
-+#define S3C2410_GPG13_nXPON (0x03 << 26)
-+
-+#define S3C2410_GPG14_INP (0x00 << 28)
-+#define S3C2410_GPG14_OUTP (0x01 << 28)
-+#define S3C2410_GPG14_EINT18 (0x02 << 28)
-+#define S3C2410_GPG14_YMON (0x03 << 28)
-+
-+#define S3C2410_GPG15_INP (0x00 << 30)
-+#define S3C2410_GPG15_OUTP (0x01 << 30)
-+#define S3C2410_GPG15_EINT18 (0x02 << 30)
-+#define S3C2410_GPG15_nYPON (0x03 << 30)
-+
-+
-+#define S3C2410_GPG_PUPDIS(x) (1<<(x))
-+
-+/* Port H consists of11 GPIO/serial/Misc pins
-+ *
-+ * GPGCON has 2 bits for each of the input pins on port F
-+ * 00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
-+ *
-+ * pull up works like all other ports.
-+*/
-+
-+#define S3C2410_GPHCON S3C2410_GPIOREG(0x70)
-+#define S3C2410_GPHDAT S3C2410_GPIOREG(0x74)
-+#define S3C2410_GPHUP S3C2410_GPIOREG(0x78)
-+
-+#define S3C2410_GPH0_INP (0x00 << 0)
-+#define S3C2410_GPH0_OUTP (0x01 << 0)
-+#define S3C2410_GPH0_nCTS0 (0x02 << 0)
-+
-+#define S3C2410_GPH1_INP (0x00 << 2)
-+#define S3C2410_GPH1_OUTP (0x01 << 2)
-+#define S3C2410_GPH1_nRTS0 (0x02 << 2)
-+
-+#define S3C2410_GPH2_INP (0x00 << 4)
-+#define S3C2410_GPH2_OUTP (0x01 << 4)
-+#define S3C2410_GPH2_TXD0 (0x02 << 4)
-+
-+#define S3C2410_GPH3_INP (0x00 << 6)
-+#define S3C2410_GPH3_OUTP (0x01 << 6)
-+#define S3C2410_GPH3_RXD0 (0x02 << 6)
-+
-+#define S3C2410_GPH4_INP (0x00 << 8)
-+#define S3C2410_GPH4_OUTP (0x01 << 8)
-+#define S3C2410_GPH4_TXD1 (0x02 << 8)
-+
-+#define S3C2410_GPH5_INP (0x00 << 10)
-+#define S3C2410_GPH5_OUTP (0x01 << 10)
-+#define S3C2410_GPH5_RXD1 (0x02 << 10)
-+
-+#define S3C2410_GPH6_INP (0x00 << 12)
-+#define S3C2410_GPH6_OUTP (0x01 << 12)
-+#define S3C2410_GPH6_TXD2 (0x02 << 12)
-+#define S3C2410_GPH6_nRTS1 (0x03 << 12)
-+
-+#define S3C2410_GPH7_INP (0x00 << 14)
-+#define S3C2410_GPH7_OUTP (0x01 << 14)
-+#define S3C2410_GPH7_RXD2 (0x02 << 14)
-+#define S3C2410_GPH7_nCTS1 (0x03 << 14)
-+
-+#define S3C2410_GPH8_INP (0x00 << 16)
-+#define S3C2410_GPH8_OUTP (0x01 << 16)
-+#define S3C2410_GPH8_UCLK (0x02 << 16)
-+
-+#define S3C2410_GPH9_INP (0x00 << 18)
-+#define S3C2410_GPH9_OUTP (0x01 << 18)
-+#define S3C2410_GPH9_CLKOUT0 (0x02 << 18)
-+
-+#define S3C2410_GPH10_INP (0x00 << 20)
-+#define S3C2410_GPH10_OUTP (0x01 << 20)
-+#define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
-+
-+/* miscellaneous control */
-+
-+#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
-+#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
-+
-+/* see clock.h for dclk definitions */
-+
-+/* pullup control on databus */
-+#define S3C2410_MISCCR_SPUCR_HEN (0)
-+#define S3C2410_MISCCR_SPUCR_HDIS (1<<0)
-+#define S3C2410_MISCCR_SPUCR_LEN (0)
-+#define S3C2410_MISCCR_SPUCR_LDIS (1<<1)
-+
-+#define S3C2410_MISCCR_USBDEV (0)
-+#define S3C2410_MISCCR_USBHOST (1<<3)
-+
-+#define S3C2410_MISCCR_CLK0_MPLL (0<<4)
-+#define S3C2410_MISCCR_CLK0_UPLL (1<<4)
-+#define S3C2410_MISCCR_CLK0_FCLK (2<<4)
-+#define S3C2410_MISCCR_CLK0_HCLK (3<<4)
-+#define S3C2410_MISCCR_CLK0_PCLK (4<<4)
-+#define S3C2410_MISCCR_CLK0_DCLK0 (5<<4)
-+
-+#define S3C2410_MISCCR_CLK1_MPLL (0<<8)
-+#define S3C2410_MISCCR_CLK1_UPLL (1<<8)
-+#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
-+#define S3C2410_MISCCR_CLK1_HCLK (3<<8)
-+#define S3C2410_MISCCR_CLK1_PCLK (4<<8)
-+#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
-+
-+#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
-+#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
-+
-+#define S3C2410_MISCCR_nRSTCON (1<<16)
-+
-+/* external interrupt control... */
-+/* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
-+ * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
-+ * S3C2410_EXTINT2 -> irq sense control for EINT16..EINT23
-+ *
-+ * note S3C2410_EXTINT2 has filtering options for EINT16..EINT23
-+ *
-+ * Samsung datasheet p9-25
-+*/
-+
-+#define S3C2410_EXTINT0 S3C2410_GPIOREG(0x88)
-+#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
-+#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
-+
-+/* values for S3C2410_EXTINT0/1/2 */
-+#define S3C2410_EXTINT_LOWLEV (0x00)
-+#define S3C2410_EXTINT_HILEV (0x01)
-+#define S3C2410_EXTINT_FALLEDGE (0x02)
-+#define S3C2410_EXTINT_RISEEDGE (0x04)
-+#define S3C2410_EXTINT_BOTHEDGE (0x06)
-+
-+/* interrupt filtering conrrol for EINT16..EINT23 */
-+#define S3C2410_EINFLT0 S3C2410_GPIOREG(0x94)
-+#define S3C2410_EINFLT1 S3C2410_GPIOREG(0x98)
-+#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
-+#define S3C2410_EINFLT3 S3C2410_GPIOREG(0xA0)
-+
-+/* mask: 0=enable, 1=disable
-+ * 1 bit EINT, 4=EINT4, 23=EINT23
-+ * EINT0,1,2,3 are not handled here.
-+*/
-+#define S3C2410_EINTMASK S3C2410_GPIOREG(0xA4)
-+#define S3C2410_EINTPEND S3C2410_GPIOREG(0xA8)
-+
-+/* GSTATUS have miscellaneous information in them
-+ *
-+ */
-+
-+#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
-+#define S3C2410_GSTATUS1 S3C2410_GPIOREG(0x0B0)
-+#define S3C2410_GSTATUS2 S3C2410_GPIOREG(0x0B4)
-+#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
-+#define S3C2410_GSTATUS4 S3C2410_GPIOREG(0x0BC)
-+
-+#define S3C2410_GSTATUS0_nWAIT (1<<3)
-+#define S3C2410_GSTATUS0_NCON (1<<2)
-+#define S3C2410_GSTATUS0_RnB (1<<1)
-+#define S3C2410_GSTATUS0_nBATTFLT (1<<0)
-+
-+#define S3C2410_GSTATUS2_WTRESET (1<<2)
-+#define S3C2410_GSTATUs2_OFFRESET (1<<1)
-+#define S3C2410_GSTATUS2_PONRESET (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_GPIO_H */
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-iis.h
-@@ -0,0 +1,61 @@
-+/* linux/include/asm/hardware/s3c2410/iis.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 IIS register definition
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ * 26-06-2003 BJD Finished off definitions for register addresses
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_IIS_H
-+#define ASMARM_ARCH_S3C2410_IIS_H
-+
-+#define S3C2410_IISCON (S3C2410_VA_IIS + 0x00)
-+
-+#define S3C2410_IISCON_LRINDEX (1<<8)
-+#define S3C2410_IISCON_TXFIFORDY (1<<7)
-+#define S3C2410_IISCON_RXFIFORDY (1<<6)
-+#define S3C2410_IISCON_TXDMAEN (1<<5)
-+#define S3C2410_IISCON_RXDMAEN (1<<4)
-+#define S3C2410_IISCON_TXIDLE (1<<3)
-+#define S3C2410_IISCON_RXIDLE (1<<2)
-+#define S3C2410_IISCON_IISEN (1<<0)
-+
-+#define S3C2410_IISMOD (S3C2410_VA_IIS + 0x04)
-+
-+#define S3C2410_IISMOD_SLAVE (1<<8)
-+#define S3C2410_IISMOD_NOXFER (0<<6)
-+#define S3C2410_IISMOD_RXMODE (1<<6)
-+#define S3C2410_IISMOD_TXMODE (2<<6)
-+#define S3C2410_IISMOD_TXRXMODE (3<<6)
-+#define S3C2410_IISMOD_LR_LLOW (0<<5)
-+#define S3C2410_IISMOD_LR_RLOW (1<<5)
-+#define S3C2410_IISMOD_IIS (0<<4)
-+#define S3C2410_IISMOD_MSB (1<<4)
-+#define S3C2410_IISMOD_8BIT (0<<3)
-+#define S3C2410_IISMOD_16BIT (1<<3)
-+#define S3C2410_IISMOD_256FS (0<<1)
-+#define S3C2410_IISMOD_384FS (1<<1)
-+#define S3C2410_IISMOD_16FS (0<<0)
-+#define S3C2410_IISMOD_32FS (1<<0)
-+#define S3C2410_IISMOD_48FS (2<<0)
-+
-+#define S3C2410_IISPSR (S3C2410_VA_IIS + 0x08)
-+
-+#define S3C2410_IISFCON (S3C2410_VA_IIS + 0x0c)
-+
-+#define S3C2410_IISFCON_TXDMA (1<<15)
-+#define S3C2410_IISFCON_RXDMA (1<<14)
-+#define S3C2410_IISFCON_TXENABLE (1<<13)
-+#define S3C2410_IISFCON_RXENABLE (1<<12)
-+
-+#define S3C2410_IISFIFO (S3C2410_VA_IIS + 0x10)
-+
-+#endif /* ASMARM_ARCH_S3C2410_IIS_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-irq.h
-@@ -0,0 +1,34 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-irq.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Changelog:
-+ * 19-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_IRQ_H
-+#define ASMARM_ARCH_S3C2410_IRQ_H
-+
-+/* interrupt controller */
-+
-+#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
-+#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
-+
-+#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
-+#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
-+#define S3C2410_INTMSK S3C2410_IRQREG(0x008)
-+#define S3C2410_PRIORITY S3C2410_IRQREG(0x00C)
-+#define S3C2410_INTPND S3C2410_IRQREG(0x010)
-+#define S3C2410_INTOFFSET S3C2410_IRQREG(0x014)
-+#define S3C2410_SUBSRCPND S3C2410_IRQREG(0x018)
-+#define S3C2410_INTSUBMSK S3C2410_IRQREG(0x01C)
-+
-+#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
-+#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
-+
-+#endif /* ASMARM_ARCH_S3C2410_IRQ_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
-@@ -0,0 +1,107 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-lcd.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ *
-+ *
-+ * Changelog:
-+ * 12-06-2003 BJD Created file
-+ * 26-06-2003 BJD Updated LCDCON register definitions
-+*/
-+
-+#ifndef ASMARM_ARCH_S3C2410_LCD_H
-+#define ASMARM_ARCH_S3C2410_LCD_H
-+
-+#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
-+
-+/* LCD control registers */
-+#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
-+#define S3C2410_LCDCON2 S3C2410_LCDREG(0x04)
-+#define S3C2410_LCDCON3 S3C2410_LCDREG(0x08)
-+#define S3C2410_LCDCON4 S3C2410_LCDREG(0x0C)
-+#define S3C2410_LCDCON5 S3C2410_LCDREG(0x10)
-+
-+#define S3C2410_LCDCON1_CLKVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON1_MMODE (1<<7)
-+#define S3C2410_LCDCON1_DSCAN4 (0<<5)
-+#define S3C2410_LCDCON1_STN4 (1<<5)
-+#define S3C2410_LCDCON1_STN8 (2<<5)
-+#define S3C2410_LCDCON1_TFT (3<<5)
-+
-+#define S3C2410_LCDCON1_STN1BPP (0<<1)
-+#define S3C2410_LCDCON1_STN2GREY (1<<1)
-+#define S3C2410_LCDCON1_STN4GREY (2<<1)
-+#define S3C2410_LCDCON1_STN8BPP (3<<1)
-+#define S3C2410_LCDCON1_STN12BPP (4<<1)
-+
-+#define S3C2410_LCDCON1_TFT1BPP (8<<1)
-+#define S3C2410_LCDCON1_TFT2BPP (9<<1)
-+#define S3C2410_LCDCON1_TFT4BPP (10<<1)
-+#define S3C2410_LCDCON1_TFT8BPP (11<<1)
-+#define S3C2410_LCDCON1_TFT16BPP (12<<1)
-+#define S3C2410_LCDCON1_TFT24BPP (13<<1)
-+
-+#define S3C2410_LCDCON1_ENVDI (1)
-+
-+#define S3C2410_LCDCON2_VBPD(x) ((x) << 24)
-+#define S3C2410_LCDCON2_LINEVAL(x) ((x) << 14)
-+#define S3C2410_LCDCON2_VFPD(x) ((x) << 6)
-+#define S3C2410_LCDCON2_VSPW(x) ((x) << 0)
-+
-+#define S3C2410_LCDCON3_HBPD(x) ((x) << 19)
-+#define S3C2410_LCDCON3_WDLY(x) ((x) << 19)
-+#define S3C2410_LCDCON3_HOZVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON3_HFPD(x) ((x) << 0)
-+#define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
-+
-+#define S3C2410_LCDCON4_MVAL(x) ((x) << 8)
-+#define S3C2410_LCDCON4_HSPW(x) ((x) << 0)
-+#define S3C2410_LCDCON4_WLH(x) ((x) << 0)
-+
-+#define S3C2410_LCDCON5_BPP24BL (1<<12)
-+#define S3C2410_LCDCON5_FRM565 (1<<11)
-+#define S3C2410_LCDCON5_INVVCLK (1<<10)
-+#define S3C2410_LCDCON5_INVVLINE (1<<9)
-+#define S3C2410_LCDCON5_INVVFRAME (1<<8)
-+#define S3C2410_LCDCON5_INVVD (1<<7)
-+#define S3C2410_LCDCON5_INVVSYNC (1<<8)
-+#define S3C2410_LCDCON5_INVHSYNC (1<<9)
-+#define S3C2410_LCDCON5_INVVDEN (1<<6)
-+#define S3C2410_LCDCON5_INVPWREN (1<<5)
-+#define S3C2410_LCDCON5_INVLEND (1<<4)
-+#define S3C2410_LCDCON5_PWREN (1<<3)
-+#define S3C2410_LCDCON5_ENLEND (1<<2)
-+#define S3C2410_LCDCON5_BSWP (1<<1)
-+#define S3C2410_LCDCON5_HWSWP (1<<0)
-+
-+/* framebuffer start addressed */
-+#define S3C2410_LCDSADDR1 S3C2410_LCDREG(0x14)
-+#define S3C2410_LCDSADDR2 S3C2410_LCDREG(0x18)
-+#define S3C2410_LCDSADDR3 S3C2410_LCDREG(0x1C)
-+
-+/* colour lookup and miscellaneous controls */
-+
-+#define S3C2410_REDLUT S3C2410_LCDREG(0x20)
-+#define S3C2410_GREENLUT S3C2410_LCDREG(0x24)
-+#define S3C2410_BLUELUT S3C2410_LCDREG(0x28)
-+
-+#define S3C2410_DITHMODE S3C2410_LCDREG(0x4C)
-+#define S3C2410_TPAL S3C2410_LCDREG(0x50)
-+
-+/* interrupt info */
-+#define S3C2410_LCDINTPND S3C2410_LCDREG(0x54)
-+#define S3C2410_LCDSRCPND S3C2410_LCDREG(0x58)
-+#define S3C2410_LCDINTMSK S3C2410_LCDREG(0x5C)
-+#define S3C2410_LPCSEL S3C2410_LCDREG(0x60)
-+
-+#define S3C2410_TFTPAL(x) S3C2410_LCDREG((0x400 + (x)*4))
-+
-+#endif /* ASMARM_ARCH_S3C2410_LCD_H */
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
-@@ -0,0 +1,61 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-rtc.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Timer configuration
-+ *
-+ * Changelog:
-+ * 05-06-2003 BJD Created file
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_RTC_H
-+#define ASMARM_ARCH_S3C2410_RTC_H
-+
-+#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
-+
-+#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
-+#define S3C2410_RTCCON_RTCEN (1<<0)
-+#define S3C2410_RTCCON_CLKRST (1<<3)
-+
-+#define S3C2410_TICNT S3C2410_RTCREG(0x44)
-+#define S3C2410_TICNT_ENABLE (1<<7)
-+
-+#define S3C2410_RTCALM S3C2410_RTCREG(0x50)
-+#define S3C2410_RTCALM_ALMEN (1<<6)
-+#define S3C2410_RTCALM_YEAREN (1<<5)
-+#define S3C2410_RTCALM_MONEN (1<<4)
-+#define S3C2410_RTCALM_DAYEN (1<<3)
-+#define S3C2410_RTCALM_HOUREN (1<<2)
-+#define S3C2410_RTCALM_MINEN (1<<1)
-+#define S3C2410_RTCALM_SECEN (1<<0)
-+
-+#define S3C2410_RTCALM_ALL \
-+ S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
-+ S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
-+ S3C2410_RTCALM_SECEN
-+
-+
-+#define S3C2410_ALMSEC S3C2410_RTCREG(0x54)
-+#define S3C2410_ALMMIN S3C2410_RTCREG(0x58)
-+#define S3C2410_ALMHOUR S3C2410_RTCREG(0x5c)
-+
-+#define S3C2410_ALMDATE S3C2410_RTCREG(0x60)
-+#define S3C2410_ALMMON S3C2410_RTCREG(0x64)
-+#define S3C2410_ALMYEAR S3C2410_RTCREG(0x68)
-+
-+#define S3C2410_RTCRST S3C2410_RTCREG(0x6c)
-+
-+#define S3C2410_RTCSEC S3C2410_RTCREG(0x70)
-+#define S3C2410_RTCMIN S3C2410_RTCREG(0x74)
-+#define S3C2410_RTCHOUR S3C2410_RTCREG(0x78)
-+#define S3C2410_RTCDATE S3C2410_RTCREG(0x7c)
-+#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
-+#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
-+#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
-+
-+#endif /* ASMARM_ARCH_S3C2410_RTC_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-serial.h
-@@ -0,0 +1,98 @@
-+/*
-+ * linux/include/asm-arm/arch-s3c2410/S3C2410-serial.h
-+ *
-+ * Internal header file for Samsung S3C2410 serial ports (UART0-2)
-+ *
-+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
-+ *
-+ * Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
-+ *
-+ * Adapted from:
-+ *
-+ * Internal header file for MX1ADS serial ports (UART1 & 2)
-+ *
-+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_SERIAL_H
-+#define ASMARM_ARCH_S3C2410_SERIAL_H
-+
-+#define S3C2410_UARTRXH0_OFF (0x24)
-+#define S3C2410_UARTTXH0_OFF (0x20)
-+#define S3C2410_UARTLCON_OFF (0x00)
-+#define S3C2410_UARTCON_OFF (0x04)
-+#define S3C2410_UARTFCON_OFF (0x08)
-+#define S3C2410_UARTMCON_OFF (0x0C)
-+#define S3C2410_UARTBRDIV_OFF (0x28)
-+#define S3C2410_UARTTRSTAT_OFF (0x10)
-+#define S3C2410_UARTERSTAT_OFF (0x14)
-+#define S3C2410_UARTFSTAT_OFF (0x18)
-+#define S3C2410_UARTMSTAT_OFF (0x1C)
-+
-+
-+#define S3C2410_UART1_OFF (0x4000)
-+#define S3C2410_UART2_OFF (0x8000)
-+
-+#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
-+
-+#define S3C2410_LCON_CS5 (0x0)
-+#define S3C2410_LCON_CS6 (0x1)
-+#define S3C2410_LCON_CS7 (0x2)
-+#define S3C2410_LCON_CS8 (0x3)
-+
-+#define S3C2410_LCON_PNONE (0x0)
-+#define S3C2410_LCON_PEVEN ((0x5)<<3)
-+#define S3C2410_LCON_PODD ((0x4)<<3)
-+
-+#define S3C2410_UMCON_AFC (0x10)
-+#define S3C2410_UMCON_RTS (0x1)
-+
-+#define S3C2410_UMSTAT_CTS (0x1)
-+
-+#define S3C2410_UCON_SBREAK (1<<4)
-+
-+#define S3C2410_UCON_TXILEVEL (1<<9)
-+#define S3C2410_UCON_RXILEVEL (1<<8)
-+#define S3C2410_UCON_TXIRQMODE (1<<2)
-+#define S3C2410_UCON_RXIRQMODE (1<<0)
-+#define S3C2410_UCON_RXFIFO_TOI (1<<7)
-+
-+#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL \
-+ | S3C2410_UCON_TXIRQMODE | S3C2410_UCON_RXIRQMODE \
-+ | S3C2410_UCON_RXFIFO_TOI)
-+
-+#define S3C2410_UFCON_FIFOMODE (1<<0)
-+#define S3C2410_UFCON_TXTRIG0 (0<<6)
-+#define S3C2410_UFCON_RXTRIG8 (1<<4)
-+#define S3C2410_UFCON_RXTRIG12 (2<<4)
-+
-+#define S3C2410_UFCON_RESETBOTH (3<<1)
-+
-+#define S3C2410_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | S3C2410_UFCON_TXTRIG0 \
-+ | S3C2410_UFCON_RXTRIG8 )
-+
-+#define S3C2410_UFSTAT_TXFULL (1<<9)
-+#define S3C2410_UFSTAT_RXFULL (1<<8)
-+#define S3C2410_UFSTAT_TXMASK (15<<4)
-+#define S3C2410_UFSTAT_TXSHIFT (4)
-+#define S3C2410_UFSTAT_RXMASK (15<<0)
-+#define S3C2410_UFSTAT_RXSHIFT (0)
-+
-+#define S3C2410_UTRSTAT_TXFE (1<<1)
-+#define S3C2410_UTRSTAT_RXDR (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_SERIAL_H */
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-timer.h
-@@ -0,0 +1,81 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-timer.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Timer configuration
-+ *
-+ * Changelog:
-+ * 05-06-2003 BJD Created file
-+ * 26-06-2003 BJD Added more timer definitions to mux / control
-+ */
-+
-+#ifndef ASMARM_ARCH_S3C2410_TIMER_H
-+#define ASMARM_ARCH_S3C2410_TIMER_H
-+
-+#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
-+#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
-+
-+#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
-+#define S3C2410_TCFG1 S3C2410_TIMERREG(0x04)
-+#define S3C2410_TCON S3C2410_TIMERREG(0x08)
-+
-+
-+#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
-+#define S3C2410_TCFG1_MUX4_MASK (15<<16)
-+
-+#define S3C2410_TCFG1_MUX3_TCLK1 (4<<12)
-+#define S3C2410_TCFG1_MUX3_MASK (15<<12)
-+
-+#define S3C2410_TCFG1_MUX2_TCLK1 (4<<8)
-+#define S3C2410_TCFG1_MUX2_MASK (15<<8)
-+
-+#define S3C2410_TCFG1_MUX1_TCLK0 (4<<4)
-+#define S3C2410_TCFG1_MUX1_MASK (15<<4)
-+
-+#define S3C2410_TCFG1_MUX0_TCLK0 (4<<0)
-+#define S3C2410_TCFG1_MUX0_MASK (15<<0)
-+
-+/* for each timer, we have an count buffer, an compare buffer and an
-+ * observation buffer
-+ */
-+
-+/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
-+
-+#define S3C2410_TCNTB(tmr) S3C2410_TIMERREG2(tmr, 0x00)
-+#define S3C2410_TCMPB(tmr) S3C2410_TIMERREG2(tmr, 0x04)
-+#define S3C2410_TCNTO(tmr) S3C2410_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
-+
-+#define S3C2410_TCON_T4RELOAD (1<<22)
-+#define S3C2410_TCON_T4MANUALUPD (1<<21)
-+#define S3C2410_TCON_T4START (1<<20)
-+
-+#define S3C2410_TCON_T3RELOAD (1<<19)
-+#define S3C2410_TCON_T3INVERT (1<<18)
-+#define S3C2410_TCON_T3MANUALUPD (1<<17)
-+#define S3C2410_TCON_T3START (1<<16)
-+
-+#define S3C2410_TCON_T2RELOAD (1<<15)
-+#define S3C2410_TCON_T2INVERT (1<<14)
-+#define S3C2410_TCON_T2MANUALUPD (1<<13)
-+#define S3C2410_TCON_T2START (1<<12)
-+
-+#define S3C2410_TCON_T1RELOAD (1<<11)
-+#define S3C2410_TCON_T1INVERT (1<<10)
-+#define S3C2410_TCON_T1MANUALUPD (1<<9)
-+#define S3C2410_TCON_T1START (1<<8)
-+
-+#define S3C2410_TCON_T0DEADZONE (1<<4)
-+#define S3C2410_TCON_T0RELOAD (1<<3)
-+#define S3C2410_TCON_T0INVERT (1<<2)
-+#define S3C2410_TCON_T0MANUALUPD (1<<1)
-+#define S3C2410_TCON_T0START (1<<0)
-+
-+#endif /* ASMARM_ARCH_S3C2410_TIMER_H */
-+
-+
-+
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
-@@ -0,0 +1,40 @@
-+/* linux/include/asm-arm/arch-s3c2410/S3C2410-watchdog.h
-+ *
-+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
-+ * http://www.simtec.co.uk/products/SWLINUX/
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * S3C2410 Watchdog timer control
-+ *
-+ * Changelog:
-+ * 21-06-2003 BJD Created file
-+*/
-+
-+#ifndef ASMARM_ARCH_S3C2410_WATCHDOG_H
-+#define ASMARM_ARCH_S3C2410_WATCHDOG_H
-+
-+#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
-+
-+#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
-+#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
-+#define S3C2410_WTCNT S3C2410_WDOGREG(0x08)
-+
-+/* the watchdog can either generate a reset pulse, or an interrupt. */
-+
-+#define S3C2410_WTCON_RSTEN (0x01)
-+#define S3C2410_WTCON_INTEN (1<<2)
-+#define S3C2410_WTCON_ENABLE (1<<5)
-+
-+#define S3C2410_WTCON_DIV16 (0<<3)
-+#define S3C2410_WTCON_DIV32 (1<<3)
-+#define S3C2410_WTCON_DIV64 (2<<3)
-+#define S3C2410_WTCON_DIV128 (3<<3)
-+
-+#define S3C2410_WTCON_PRESCALE(x) ((x) << 8)
-+
-+#endif /* ASMARM_ARCH_S3C2410_WATCHDOG_H */
-+
-+
---- linux-2.4.27/include/asm-arm/bugs.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/bugs.h
-@@ -10,8 +10,17 @@
- #ifndef __ASM_BUGS_H
- #define __ASM_BUGS_H
-
-+#include <linux/config.h>
- #include <asm/proc-fns.h>
-
--#define check_bugs() cpu_check_bugs()
-+extern void check_writebuffer_bugs(void);
-+
-+static inline void check_bugs(void)
-+{
-+#ifdef CONFIG_CPU_32
-+ check_writebuffer_bugs();
-+#endif
-+ cpu_check_bugs();
-+}
-
- #endif
---- linux-2.4.27/include/asm-arm/div64.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/div64.h
-@@ -4,9 +4,13 @@
- /* We're not 64-bit, but... */
- #define do_div(n,base) \
- ({ \
-- int __res; \
-- __res = ((unsigned long)n) % (unsigned int)base; \
-- n = ((unsigned long)n) / (unsigned int)base; \
-+ register int __res asm("r2") = base; \
-+ register unsigned long long __n asm("r0") = n; \
-+ asm("bl do_div64" \
-+ : "=r" (__n), "=r" (__res) \
-+ : "0" (__n), "1" (__res) \
-+ : "r3", "ip", "lr", "cc"); \
-+ n = __n; \
- __res; \
- })
-
---- linux-2.4.27/include/asm-arm/elf.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/elf.h
-@@ -45,8 +45,8 @@
-
- #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
-
--/* When the program starts, a1 contains a pointer to a function to be
-- registered with atexit, as per the SVR4 ABI. A value of 0 means we
-+/* When the program starts, a1 contains a pointer to a function to be
-+ registered with atexit, as per the SVR4 ABI. A value of 0 means we
- have no such handler. */
- #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0
-
---- linux-2.4.27/include/asm-arm/hc_sl811-hw.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/hc_sl811-hw.h
-@@ -38,7 +38,7 @@
- */
- static void inline sl811_write_index (hcipriv_t *hp, __u8 index)
- {
-- writeb (offset, hp->hcport);
-+ writeb (index, hp->hcport);
- wmb ();
- }
-
-@@ -55,7 +55,7 @@
- */
- static void inline sl811_write_index_data (hcipriv_t *hp, __u8 index, __u8 data)
- {
-- writeb (offset, hp->hcport);
-+ writeb (index, hp->hcport);
- writeb (data, hp->hcport2);
- wmb ();
- }
---- linux-2.4.27/include/asm-arm/mach/dma.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/mach/dma.h
-@@ -41,6 +41,7 @@
- unsigned int dma_base; /* Controller base address */
- int dma_irq; /* Controller IRQ */
- struct scatterlist cur_sg; /* Current controller buffer */
-+ unsigned int state; /* RiscPC DMA status */
-
- struct dma_ops *d_ops;
- };
---- linux-2.4.27/include/asm-arm/mach/serial_at91rm9200.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/mach/serial_at91rm9200.h
-@@ -10,7 +10,6 @@
- #include <linux/config.h>
-
- struct uart_port;
--struct uart_info;
-
- /*
- * This is a temporary structure for registering these
-@@ -22,11 +21,11 @@
- void (*enable_ms)(struct uart_port *);
- void (*pm)(struct uart_port *, u_int, u_int);
- int (*set_wake)(struct uart_port *, u_int);
-- int (*open)(struct uart_port *, struct uart_info *);
-- void (*close)(struct uart_port *, struct uart_info *);
-+ int (*open)(struct uart_port *);
-+ void (*close)(struct uart_port *);
- };
-
--#if defined(CONFIG_SERIAL_AT91RM9200)
-+#if defined(CONFIG_SERIAL_AT91)
- void at91rm9200_register_uart_fns(struct at91rm9200_port_fns *fns);
- void at91rm9200_register_uart(int idx, int port);
- #else
---- linux-2.4.27/include/asm-arm/pci.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/pci.h
-@@ -113,6 +113,28 @@
- /* nothing to do */
- }
-
-+/*
-+ * pci_{map,unmap}_page maps a kernel page to a dma_addr_t. identical
-+ * to pci_map_single, but takes a struct page instead of a virtual address
-+ */
-+static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-+ unsigned long offset, size_t size,
-+ int direction)
-+{
-+ void *start;
-+ BUG_ON(direction == PCI_DMA_NONE);
-+ start = page_address(page) + offset;
-+ consistent_sync(start, size, direction);
-+ return virt_to_bus(start);
-+}
-+
-+static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
-+ size_t size, int direction)
-+{
-+ BUG_ON(direction == PCI_DMA_NONE);
-+ /* Nothing to do */
-+}
-+
- /* Whether pci_unmap_{single,page} is a nop depends upon the
- * configuration.
- */
---- linux-2.4.27/include/asm-arm/proc-armv/processor.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/proc-armv/processor.h
-@@ -54,7 +54,9 @@
- regs->ARM_cpsr = USR_MODE; \
- else \
- regs->ARM_cpsr = USR26_MODE; \
-- regs->ARM_pc = pc; /* pc */ \
-+ if (elf_hwcap & HWCAP_THUMB && pc & 1) \
-+ regs->ARM_cpsr |= PSR_T_BIT; \
-+ regs->ARM_pc = pc & ~1; /* pc */ \
- regs->ARM_sp = sp; /* sp */ \
- regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
- regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
---- linux-2.4.27/include/asm-arm/proc-armv/ptrace.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/proc-armv/ptrace.h
-@@ -33,6 +33,16 @@
- #define CC_N_BIT (1 << 31)
- #define PCMASK 0
-
-+/* 2.5 versions */
-+#define PSR_T_BIT 0x00000020
-+#define PSR_F_BIT 0x00000040
-+#define PSR_I_BIT 0x00000080
-+#define PSR_J_BIT 0x01000000
-+#define PSR_V_BIT 0x10000000
-+#define PSR_C_BIT 0x20000000
-+#define PSR_Z_BIT 0x40000000
-+#define PSR_N_BIT 0x80000000
-+
- #ifndef __ASSEMBLY__
-
- /* this struct defines the way the registers are stored on the
---- linux-2.4.27/include/asm-arm/proc-armv/uaccess.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/proc-armv/uaccess.h
-@@ -12,12 +12,11 @@
- * Note that this is actually 0x1,0000,0000
- */
- #define KERNEL_DS 0x00000000
--#define USER_DS PAGE_OFFSET
-+#define USER_DS TASK_SIZE
-
- static inline void set_fs (mm_segment_t fs)
- {
- current->addr_limit = fs;
--
- modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
- }
-
-@@ -38,7 +37,7 @@
- : "cc"); \
- (flag == 0); })
-
--#define __put_user_asm_byte(x,addr,err) \
-+#define __put_user_asm_byte(x,__pu_addr,err) \
- __asm__ __volatile__( \
- "1: strbt %1,[%2],#0\n" \
- "2:\n" \
-@@ -51,18 +50,18 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err) \
-- : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err) \
-+ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
-+ : "cc")
-
--#define __put_user_asm_half(x,addr,err) \
-+#define __put_user_asm_half(x,__pu_addr,err) \
- ({ \
- unsigned long __temp = (unsigned long)(x); \
-- unsigned long __ptr = (unsigned long)(addr); \
-- __put_user_asm_byte(__temp, __ptr, err); \
-- __put_user_asm_byte(__temp >> 8, __ptr + 1, err); \
-+ __put_user_asm_byte(__temp, __pu_addr, err); \
-+ __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
- })
-
--#define __put_user_asm_word(x,addr,err) \
-+#define __put_user_asm_word(x,__pu_addr,err) \
- __asm__ __volatile__( \
- "1: strt %1,[%2],#0\n" \
- "2:\n" \
-@@ -75,8 +74,28 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err) \
-- : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err) \
-+ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
-+ : "cc")
-+
-+#define __put_user_asm_dword(x,__pu_addr,err) \
-+ __asm__ __volatile__( \
-+ "1: strt %R2, [%1], #4\n" \
-+ "2: strt %Q2, [%1], #0\n" \
-+ "3:\n" \
-+ " .section .fixup,\"ax\"\n" \
-+ " .align 2\n" \
-+ "4: mov %0, %3\n" \
-+ " b 3b\n" \
-+ " .previous\n" \
-+ " .section __ex_table,\"a\"\n" \
-+ " .align 3\n" \
-+ " .long 1b, 4b\n" \
-+ " .long 2b, 4b\n" \
-+ " .previous" \
-+ : "+r" (err), "+r" (__pu_addr) \
-+ : "r" (x), "i" (-EFAULT) \
-+ : "cc")
-
- #define __get_user_asm_byte(x,addr,err) \
- __asm__ __volatile__( \
-@@ -92,18 +111,18 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err), "=&r" (x) \
-- : "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err), "=&r" (x) \
-+ : "r" (addr), "i" (-EFAULT) \
-+ : "cc")
-
--#define __get_user_asm_half(x,addr,err) \
-+#define __get_user_asm_half(x,__gu_addr,err) \
- ({ \
-- unsigned long __b1, __b2, __ptr = (unsigned long)addr; \
-- __get_user_asm_byte(__b1, __ptr, err); \
-- __get_user_asm_byte(__b2, __ptr + 1, err); \
-+ unsigned long __b1, __b2; \
-+ __get_user_asm_byte(__b1, __gu_addr, err); \
-+ __get_user_asm_byte(__b2, __gu_addr + 1, err); \
- (x) = __b1 | (__b2 << 8); \
- })
-
--
- #define __get_user_asm_word(x,addr,err) \
- __asm__ __volatile__( \
- "1: ldrt %1,[%2],#0\n" \
-@@ -118,8 +137,9 @@
- " .align 3\n" \
- " .long 1b, 3b\n" \
- " .previous" \
-- : "=r" (err), "=&r" (x) \
-- : "r" (addr), "i" (-EFAULT), "0" (err))
-+ : "+r" (err), "=&r" (x) \
-+ : "r" (addr), "i" (-EFAULT) \
-+ : "cc")
-
- extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
- #define __do_copy_from_user(to,from,n) \
---- linux-2.4.27/include/asm-arm/proc-fns.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/proc-fns.h
-@@ -76,6 +76,30 @@
- # define CPU_NAME arm926
- # endif
- # endif
-+# ifdef CONFIG_CPU_ARM1020
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1020
-+# endif
-+# endif
-+# ifdef CONFIG_CPU_ARM1020E
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1020E
-+# endif
-+# endif
-+# ifdef CONFIG_CPU_ARM1022
-+# ifdef CPU_NAME
-+# undef MULTI_CPU
-+# define MULTI_CPU
-+# else
-+# define CPU_NAME arm1022
-+# endif
-+# endif
- # ifdef CONFIG_CPU_ARM1026
- # ifdef CPU_NAME
- # undef MULTI_CPU
---- linux-2.4.27/include/asm-arm/processor.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/processor.h
-@@ -43,6 +43,7 @@
- #include <asm/atomic.h>
- #include <asm/ptrace.h>
- #include <asm/arch/memory.h>
-+#include <asm/elf.h>
- #include <asm/proc/processor.h>
- #include <asm/types.h>
-
---- linux-2.4.27/include/asm-arm/system.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/system.h
-@@ -29,6 +29,10 @@
-
- void die_if_kernel(const char *str, struct pt_regs *regs, int err);
-
-+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
-+ struct pt_regs *),
-+ int sig, const char *name);
-+
- #include <asm/proc-fns.h>
-
- #define xchg(ptr,x) \
-@@ -89,6 +93,14 @@
- #define sti() local_irq_enable()
- #define clf() __clf()
- #define stf() __stf()
-+
-+#define irqs_disabled() \
-+({ \
-+ unsigned long flags; \
-+ local_save_flags(flags); \
-+ flags & PSR_I_BIT; \
-+})
-+
- #define save_flags(x) local_save_flags(x)
- #define restore_flags(x) local_irq_restore(x)
- #define save_flags_cli(x) local_irq_save(x)
---- linux-2.4.27/include/asm-arm/termios.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/termios.h
-@@ -47,6 +47,8 @@
- #define TIOCM_OUT2 0x4000
- #define TIOCM_LOOP 0x8000
-
-+#define TIOCM_MODEM_BITS TIOCM_OUT2 /* IRDA support */
-+
- /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
- /* line disciplines */
---- linux-2.4.27/include/asm-arm/uaccess.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/uaccess.h
-@@ -74,14 +74,14 @@
- __asm__ __volatile__ ("bl __get_user_" #__s \
- : "=&r" (__e), "=r" (__r1) \
- : "0" (__p) \
-- : __i)
-+ : __i, "cc")
-
- #define get_user(x,p) \
- ({ \
- const register typeof(*(p)) *__p asm("r0") = (p); \
- register typeof(*(p)) __r1 asm("r1"); \
- register int __e asm("r0"); \
-- switch (sizeof(*(p))) { \
-+ switch (sizeof(*(__p))) { \
- case 1: \
- __get_user_x(__r1, __p, __e, 1, "lr"); \
- break; \
-@@ -100,8 +100,31 @@
- __e; \
- })
-
--#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p)))
--#define __get_user_error(x,p,e) __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-+#define __get_user(x,ptr) \
-+({ \
-+ long __gu_err = 0; \
-+ __get_user_err((x),(ptr),__gu_err); \
-+ __gu_err; \
-+})
-+
-+#define __get_user_error(x,ptr,err) \
-+({ \
-+ __get_user_err((x),(ptr),err); \
-+ (void) 0; \
-+})
-+
-+#define __get_user_err(x,ptr,err) \
-+do { \
-+ unsigned long __gu_addr = (unsigned long)(ptr); \
-+ unsigned long __gu_val; \
-+ switch (sizeof(*(ptr))) { \
-+ case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
-+ case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
-+ case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
-+ default: (__gu_val) = __get_user_bad(); \
-+ } \
-+ (x) = (__typeof__(*(ptr)))__gu_val; \
-+} while (0)
-
- extern int __put_user_1(void *, unsigned int);
- extern int __put_user_2(void *, unsigned int);
-@@ -113,22 +136,22 @@
- __asm__ __volatile__ ("bl __put_user_" #__s \
- : "=&r" (__e) \
- : "0" (__p), "r" (__r1) \
-- : __i)
-+ : __i, "cc")
-
- #define put_user(x,p) \
- ({ \
- const register typeof(*(p)) __r1 asm("r1") = (x); \
- const register typeof(*(p)) *__p asm("r0") = (p); \
- register int __e asm("r0"); \
-- switch (sizeof(*(p))) { \
-+ switch (sizeof(*(__p))) { \
- case 1: \
-- __put_user_x(__r1, __p, __e, 1, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 1, "ip", "lr"); \
- break; \
- case 2: \
-- __put_user_x(__r1, __p, __e, 2, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 2, "ip", "lr"); \
- break; \
- case 4: \
-- __put_user_x(__r1, __p, __e, 4, "r2", "lr"); \
-+ __put_user_x(__r1, __p, __e, 4, "ip", "lr"); \
- break; \
- case 8: \
- __put_user_x(__r1, __p, __e, 8, "ip", "lr"); \
-@@ -138,8 +161,31 @@
- __e; \
- })
-
--#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
--#define __put_user_error(x,p,e) __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
-+#define __put_user(x,ptr) \
-+({ \
-+ long __pu_err = 0; \
-+ __put_user_err((x),(ptr),__pu_err); \
-+ __pu_err; \
-+})
-+
-+#define __put_user_error(x,ptr,err) \
-+({ \
-+ __put_user_err((x),(ptr),err); \
-+ (void) 0; \
-+})
-+
-+#define __put_user_err(x,ptr,err) \
-+do { \
-+ unsigned long __pu_addr = (unsigned long)(ptr); \
-+ __typeof__(*(ptr)) __pu_val = (x); \
-+ switch (sizeof(*(ptr))) { \
-+ case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
-+ case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
-+ case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
-+ case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
-+ default: __put_user_bad(); \
-+ } \
-+} while (0)
-
- static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
- {
-@@ -209,82 +255,4 @@
- return res;
- }
-
--/*
-- * These are the work horses of the get/put_user functions
-- */
--#if 0
--#define __get_user_check(x,ptr,size) \
--({ \
-- long __gu_err = -EFAULT, __gu_val = 0; \
-- const __typeof__(*(ptr)) *__gu_addr = (ptr); \
-- if (access_ok(VERIFY_READ,__gu_addr,size)) { \
-- __gu_err = 0; \
-- __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
-- } \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- __gu_err; \
--})
--#endif
--
--#define __get_user_nocheck(x,ptr,size) \
--({ \
-- long __gu_err = 0, __gu_val; \
-- __get_user_size(__gu_val,(ptr),(size),__gu_err); \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- __gu_err; \
--})
--
--#define __get_user_nocheck_error(x,ptr,size,err) \
--({ \
-- long __gu_val; \
-- __get_user_size(__gu_val,(ptr),(size),(err)); \
-- (x) = (__typeof__(*(ptr)))__gu_val; \
-- (void) 0; \
--})
--
--#define __put_user_check(x,ptr,size) \
--({ \
-- long __pu_err = -EFAULT; \
-- __typeof__(*(ptr)) *__pu_addr = (ptr); \
-- if (access_ok(VERIFY_WRITE,__pu_addr,size)) { \
-- __pu_err = 0; \
-- __put_user_size((x),__pu_addr,(size),__pu_err); \
-- } \
-- __pu_err; \
--})
--
--#define __put_user_nocheck(x,ptr,size) \
--({ \
-- long __pu_err = 0; \
-- __typeof__(*(ptr)) *__pu_addr = (ptr); \
-- __put_user_size((x),__pu_addr,(size),__pu_err); \
-- __pu_err; \
--})
--
--#define __put_user_nocheck_error(x,ptr,size,err) \
--({ \
-- __put_user_size((x),(ptr),(size),err); \
-- (void) 0; \
--})
--
--#define __get_user_size(x,ptr,size,retval) \
--do { \
-- switch (size) { \
-- case 1: __get_user_asm_byte(x,ptr,retval); break; \
-- case 2: __get_user_asm_half(x,ptr,retval); break; \
-- case 4: __get_user_asm_word(x,ptr,retval); break; \
-- default: (x) = __get_user_bad(); \
-- } \
--} while (0)
--
--#define __put_user_size(x,ptr,size,retval) \
--do { \
-- switch (size) { \
-- case 1: __put_user_asm_byte(x,ptr,retval); break; \
-- case 2: __put_user_asm_half(x,ptr,retval); break; \
-- case 4: __put_user_asm_word(x,ptr,retval); break; \
-- default: __put_user_bad(); \
-- } \
--} while (0)
--
- #endif /* _ASMARM_UACCESS_H */
---- linux-2.4.27/include/asm-arm/unistd.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-arm/unistd.h
-@@ -31,7 +31,7 @@
- #define __NR_write (__NR_SYSCALL_BASE+ 4)
- #define __NR_open (__NR_SYSCALL_BASE+ 5)
- #define __NR_close (__NR_SYSCALL_BASE+ 6)
--#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
-+ /* 7 was sys_waitpid */
- #define __NR_creat (__NR_SYSCALL_BASE+ 8)
- #define __NR_link (__NR_SYSCALL_BASE+ 9)
- #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
-@@ -41,8 +41,8 @@
- #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
- #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
- #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
--#define __NR_break (__NR_SYSCALL_BASE+ 17)
--
-+ /* 17 was sys_break */
-+ /* 18 was sys_stat */
- #define __NR_lseek (__NR_SYSCALL_BASE+ 19)
- #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
- #define __NR_mount (__NR_SYSCALL_BASE+ 21)
-@@ -52,14 +52,14 @@
- #define __NR_stime (__NR_SYSCALL_BASE+ 25)
- #define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
- #define __NR_alarm (__NR_SYSCALL_BASE+ 27)
--
-+ /* 28 was sys_fstat */
- #define __NR_pause (__NR_SYSCALL_BASE+ 29)
- #define __NR_utime (__NR_SYSCALL_BASE+ 30)
--#define __NR_stty (__NR_SYSCALL_BASE+ 31)
--#define __NR_gtty (__NR_SYSCALL_BASE+ 32)
-+ /* 31 was sys_stty */
-+ /* 32 was sys_gtty */
- #define __NR_access (__NR_SYSCALL_BASE+ 33)
- #define __NR_nice (__NR_SYSCALL_BASE+ 34)
--#define __NR_ftime (__NR_SYSCALL_BASE+ 35)
-+ /* 35 was sys_ftime */
- #define __NR_sync (__NR_SYSCALL_BASE+ 36)
- #define __NR_kill (__NR_SYSCALL_BASE+ 37)
- #define __NR_rename (__NR_SYSCALL_BASE+ 38)
-@@ -68,22 +68,23 @@
- #define __NR_dup (__NR_SYSCALL_BASE+ 41)
- #define __NR_pipe (__NR_SYSCALL_BASE+ 42)
- #define __NR_times (__NR_SYSCALL_BASE+ 43)
--#define __NR_prof (__NR_SYSCALL_BASE+ 44)
-+ /* 44 was sys_prof */
- #define __NR_brk (__NR_SYSCALL_BASE+ 45)
- #define __NR_setgid (__NR_SYSCALL_BASE+ 46)
- #define __NR_getgid (__NR_SYSCALL_BASE+ 47)
--#define __NR_signal (__NR_SYSCALL_BASE+ 48)
-+ /* 48 was sys_signal */
- #define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
- #define __NR_getegid (__NR_SYSCALL_BASE+ 50)
- #define __NR_acct (__NR_SYSCALL_BASE+ 51)
- #define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
--#define __NR_lock (__NR_SYSCALL_BASE+ 53)
-+ /* 53 was sys_lock */
- #define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
- #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
--#define __NR_mpx (__NR_SYSCALL_BASE+ 56)
-+ /* 56 was sys_mpx */
- #define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
- #define __NR_ulimit (__NR_SYSCALL_BASE+ 58)
--
-+ /* 58 was sys_ulimit */
-+ /* 59 was sys_olduname */
- #define __NR_umask (__NR_SYSCALL_BASE+ 60)
- #define __NR_chroot (__NR_SYSCALL_BASE+ 61)
- #define __NR_ustat (__NR_SYSCALL_BASE+ 62)
-@@ -92,8 +93,8 @@
- #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
- #define __NR_setsid (__NR_SYSCALL_BASE+ 66)
- #define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
--#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68)
--#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69)
-+ /* 68 was sys_sgetmask */
-+ /* 69 was sys_ssetmask */
- #define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
- #define __NR_setregid (__NR_SYSCALL_BASE+ 71)
- #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
-@@ -108,7 +109,7 @@
- #define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
- #define __NR_select (__NR_SYSCALL_BASE+ 82)
- #define __NR_symlink (__NR_SYSCALL_BASE+ 83)
--
-+ /* 84 was sys_lstat */
- #define __NR_readlink (__NR_SYSCALL_BASE+ 85)
- #define __NR_uselib (__NR_SYSCALL_BASE+ 86)
- #define __NR_swapon (__NR_SYSCALL_BASE+ 87)
-@@ -122,10 +123,10 @@
- #define __NR_fchown (__NR_SYSCALL_BASE+ 95)
- #define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
- #define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
--#define __NR_profil (__NR_SYSCALL_BASE+ 98)
-+ /* 98 was sys_profil */
- #define __NR_statfs (__NR_SYSCALL_BASE+ 99)
- #define __NR_fstatfs (__NR_SYSCALL_BASE+100)
--#define __NR_ioperm (__NR_SYSCALL_BASE+101)
-+ /* 101 was sys_ioperm */
- #define __NR_socketcall (__NR_SYSCALL_BASE+102)
- #define __NR_syslog (__NR_SYSCALL_BASE+103)
- #define __NR_setitimer (__NR_SYSCALL_BASE+104)
-@@ -133,10 +134,10 @@
- #define __NR_stat (__NR_SYSCALL_BASE+106)
- #define __NR_lstat (__NR_SYSCALL_BASE+107)
- #define __NR_fstat (__NR_SYSCALL_BASE+108)
--
--
-+ /* 109 was sys_uname */
-+ /* 110 was sys_iopl */
- #define __NR_vhangup (__NR_SYSCALL_BASE+111)
--#define __NR_idle (__NR_SYSCALL_BASE+112)
-+ /* 112 was sys_idle */
- #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
- #define __NR_wait4 (__NR_SYSCALL_BASE+114)
- #define __NR_swapoff (__NR_SYSCALL_BASE+115)
-@@ -147,7 +148,7 @@
- #define __NR_clone (__NR_SYSCALL_BASE+120)
- #define __NR_setdomainname (__NR_SYSCALL_BASE+121)
- #define __NR_uname (__NR_SYSCALL_BASE+122)
--#define __NR_modify_ldt (__NR_SYSCALL_BASE+123)
-+ /* 123 was sys_modify_ldt */
- #define __NR_adjtimex (__NR_SYSCALL_BASE+124)
- #define __NR_mprotect (__NR_SYSCALL_BASE+125)
- #define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
-@@ -161,7 +162,7 @@
- #define __NR_bdflush (__NR_SYSCALL_BASE+134)
- #define __NR_sysfs (__NR_SYSCALL_BASE+135)
- #define __NR_personality (__NR_SYSCALL_BASE+136)
--#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */
-+ /* 137 was sys_afs_syscall */
- #define __NR_setfsuid (__NR_SYSCALL_BASE+138)
- #define __NR_setfsgid (__NR_SYSCALL_BASE+139)
- #define __NR__llseek (__NR_SYSCALL_BASE+140)
-@@ -190,7 +191,7 @@
- #define __NR_mremap (__NR_SYSCALL_BASE+163)
- #define __NR_setresuid (__NR_SYSCALL_BASE+164)
- #define __NR_getresuid (__NR_SYSCALL_BASE+165)
--#define __NR_vm86 (__NR_SYSCALL_BASE+166)
-+ /* 166 was sys_vm86 */
- #define __NR_query_module (__NR_SYSCALL_BASE+167)
- #define __NR_poll (__NR_SYSCALL_BASE+168)
- #define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
---- linux-2.4.27/include/asm-i386/ide.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-i386/ide.h
-@@ -23,39 +23,15 @@
- # endif
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- switch (base) {
-- case 0x1f0: return 14;
-- case 0x170: return 15;
-- case 0x1e8: return 11;
-- case 0x168: return 10;
-- case 0x1e0: return 8;
-- case 0x160: return 12;
-- default:
-- return 0;
-- }
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- switch (index) {
-- case 0: return 0x1f0;
-- case 1: return 0x170;
-- case 2: return 0x1e8;
-- case 3: return 0x168;
-- case 4: return 0x1e0;
-- case 5: return 0x160;
-- default:
-- return 0;
-- }
--}
-+#define ide_default_io_base(i) ((ide_ioreg_t)0)
-+#define ide_default_irq(b) (0)
-
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
- ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(hw, 0, sizeof(*hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -63,7 +39,7 @@
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
-- hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-+ hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
- }
- if (irq != NULL)
- *irq = 0;
-@@ -74,14 +50,25 @@
- {
- #ifndef CONFIG_BLK_DEV_IDEPCI
- hw_regs_t hw;
-- int index;
-
-- for(index = 0; index < MAX_HWIFS; index++) {
-- memset(&hw, 0, sizeof hw);
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
-+ ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
-+ hw.irq = 14;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x170, 0x376, NULL);
-+ hw.irq = 15;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e8, 0x3ee, NULL);
-+ hw.irq = 11;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x168, 0x36e, NULL);
-+ hw.irq = 10;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x1e0, 0x3e6, NULL);
-+ hw.irq = 8;
-+ ide_register_hw(&hw, NULL);
-+ ide_init_hwif_ports(&hw, 0x160, 0x366, NULL);
-+ hw.irq = 12;
-+ ide_register_hw(&hw, NULL);
- #endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
---- linux-2.4.27/include/asm-i386/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-i386/param.h
-@@ -3,6 +3,16 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#if HZ == 100
-+/* X86 is defined to provide userspace with a world where HZ=100
-+ We have to do this, (x*const)/const2 isnt optimised out because its not
-+ a null operation as it might overflow.. */
-+#define hz_to_std(a) (a)
-+#else
-+#define hz_to_std(a) ((a)*(100/HZ)+((a)*(100%HZ))/HZ)
-+#endif
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.27/include/asm-i386/pgtable.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-i386/pgtable.h
-@@ -361,7 +361,6 @@
- #endif /* !__ASSEMBLY__ */
-
- /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
--#define PageSkip(page) (0)
- #define kern_addr_valid(addr) (1)
-
- #define io_remap_page_range remap_page_range
---- linux-2.4.27/include/asm-ia64/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-ia64/param.h
-@@ -4,12 +4,14 @@
- /*
- * Fundamental kernel parameters.
- *
-- * Based on <asm-i386/param.h>.
-- *
-- * Modified 1998, 1999, 2002-2003
-- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
-+ * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
-+ * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
-+
- #define EXEC_PAGESIZE 65536
-
- #ifndef NGROUPS
---- linux-2.4.27/include/asm-m68k/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-m68k/param.h
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192
---- linux-2.4.27/include/asm-mips/ide.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-mips/ide.h
-@@ -27,7 +27,7 @@
- int (*ide_default_irq)(ide_ioreg_t base);
- ide_ioreg_t (*ide_default_io_base)(int index);
- void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port,
-- ide_ioreg_t ctrl_port, int *irq);
-+ ide_ioreg_t ctrl_port, int *irq);
- };
-
- extern struct ide_ops *ide_ops;
---- linux-2.4.27/include/asm-ppc/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-ppc/param.h
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.27/include/asm-s390/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-s390/param.h
-@@ -11,6 +11,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.27/include/asm-sh/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-sh/param.h
-@@ -3,6 +3,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 4096
---- linux-2.4.27/include/asm-sparc/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-sparc/param.h
-@@ -4,6 +4,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
---- linux-2.4.27/include/asm-sparc64/ide.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-sparc64/ide.h
-@@ -25,21 +25,12 @@
- # endif
- #endif
-
--static __inline__ int ide_default_irq(ide_ioreg_t base)
--{
-- return 0;
--}
--
--static __inline__ ide_ioreg_t ide_default_io_base(int index)
--{
-- return 0;
--}
--
- static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
- {
-- ide_ioreg_t reg = data_port;
-+ ide_ioreg_t reg = data_port;
- int i;
-
-+ memset(&hw, 0, sizeof(hw));
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
-@@ -60,16 +51,6 @@
- */
- static __inline__ void ide_init_default_hwifs(void)
- {
--#ifndef CONFIG_BLK_DEV_IDEPCI
-- hw_regs_t hw;
-- int index;
--
-- for (index = 0; index < MAX_HWIFS; index++) {
-- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-- hw.irq = ide_default_irq(ide_default_io_base(index));
-- ide_register_hw(&hw, NULL);
-- }
--#endif /* CONFIG_BLK_DEV_IDEPCI */
- }
-
- #undef SUPPORT_SLOW_DATA_PORTS
---- linux-2.4.27/include/asm-sparc64/param.h~2.4.27-vrs1
-+++ linux-2.4.27/include/asm-sparc64/param.h
-@@ -4,6 +4,9 @@
-
- #ifndef HZ
- #define HZ 100
-+#ifdef __KERNEL__
-+#define hz_to_std(a) (a)
-+#endif
- #endif
-
- #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
---- linux-2.4.27/include/linux/console_struct.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/console_struct.h
-@@ -7,6 +7,8 @@
- * Fields marked with [#] must be set by the low-level driver.
- * Fields marked with [!] can be changed by the low-level driver
- * to achieve effects such as fast scrolling by changing the origin.
-+ *
-+ * 11/07/1998 RMK Changed vc_state to be a function pointer
- */
-
- #ifndef _LINUX_CONSOLE_STRUCT_H_
-@@ -34,7 +36,11 @@
- unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
- unsigned int vc_x, vc_y; /* Cursor position */
- unsigned int vc_top, vc_bottom; /* Scrolling region */
-+#ifdef CONSOLE_WIP
-+ int (*vc_state)(int currcons, struct tty_struct *tty, unsigned int c);
-+#else
- unsigned int vc_state; /* Escape sequence parser state */
-+#endif
- unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
- unsigned long vc_origin; /* [!] Start of real screen */
- unsigned long vc_scr_end; /* [!] End of real screen */
---- /dev/null
-+++ linux-2.4.27/include/linux/cpufreq.h
-@@ -0,0 +1,94 @@
-+/*
-+ * linux/include/linux/cpufreq.h
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * $Id: cpufreq.h,v 1.5.2.1 2002/05/03 13:26:27 rmk Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#ifndef _LINUX_CPUFREQ_H
-+#define _LINUX_CPUFREQ_H
-+
-+#include <linux/config.h>
-+#include <linux/notifier.h>
-+
-+#ifndef CONFIG_SMP
-+#define cpufreq_current(cpu) ((void)(cpu), __cpufreq_cur)
-+#define cpufreq_max(cpu) ((void)(cpu), __cpufreq_max)
-+#define cpufreq_min(cpu) ((void)(cpu), __cpufreq_min)
-+#else
-+/*
-+ * Should be something like:
-+ *
-+ * typedef struct {
-+ * u_int current;
-+ * u_int max;
-+ * u_int min;
-+ * } __cacheline_aligned cpufreq_info_t;
-+ *
-+ * static cpufreq_info_t cpufreq_info;
-+ *
-+ * #define cpufreq_current(cpu) (cpufreq_info[cpu].current)
-+ * #define cpufreq_max(cpu) (cpufreq_info[cpu].max)
-+ * #define cpufreq_min(cpu) (cpufreq_info[cpu].min)
-+ *
-+ * Maybe we should find some other per-cpu structure to
-+ * bury this in?
-+ */
-+#error fill in SMP version
-+#endif
-+
-+struct cpufreq_info {
-+ unsigned int old_freq;
-+ unsigned int new_freq;
-+};
-+
-+/*
-+ * The max and min frequency rates that the registered device
-+ * can tolerate. Never set any element this structure directly -
-+ * always use cpu_updateminmax.
-+ */
-+struct cpufreq_minmax {
-+ unsigned int min_freq;
-+ unsigned int max_freq;
-+ unsigned int cur_freq;
-+ unsigned int new_freq;
-+};
-+
-+static inline
-+void cpufreq_updateminmax(void *arg, unsigned int min, unsigned int max)
-+{
-+ struct cpufreq_minmax *minmax = arg;
-+
-+ if (minmax->min_freq < min)
-+ minmax->min_freq = min;
-+ if (minmax->max_freq > max)
-+ minmax->max_freq = max;
-+}
-+
-+#define CPUFREQ_MINMAX (0)
-+#define CPUFREQ_PRECHANGE (1)
-+#define CPUFREQ_POSTCHANGE (2)
-+
-+int cpufreq_register_notifier(struct notifier_block *nb);
-+int cpufreq_unregister_notifier(struct notifier_block *nb);
-+
-+int cpufreq_setmax(void);
-+int cpufreq_restore(void);
-+int cpufreq_set(unsigned int khz);
-+unsigned int cpufreq_get(int cpu);
-+
-+/*
-+ * These two functions are only available at init time.
-+ */
-+void cpufreq_init(unsigned int khz,
-+ unsigned int min_freq,
-+ unsigned int max_freq);
-+
-+void cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
-+ void (*setspeed)(unsigned int));
-+
-+#endif
---- linux-2.4.27/include/linux/i2c-id.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/i2c-id.h
-@@ -20,16 +20,16 @@
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* ------------------------------------------------------------------------- */
-
--/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
-+/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
-
- #ifndef I2C_ID_H
- #define I2C_ID_H
- /*
- * This file is part of the i2c-bus package and contains the identifier
- * values for drivers, adapters and other folk populating these serial
-- * worlds.
-+ * worlds.
- *
-- * These will change often (i.e. additions) , therefore this has been
-+ * These will change often (i.e. additions) , therefore this has been
- * separated from the functional interface definitions of the i2c api.
- *
- */
-@@ -38,10 +38,10 @@
- * ---- Driver types -----------------------------------------------------
- * device id name + number function description, i2c address(es)
- *
-- * Range 1000-1999 range is defined in sensors/sensors.h
-- * Range 0x100 - 0x1ff is for V4L2 Common Components
-+ * Range 1000-1999 range is defined in sensors/sensors.h
-+ * Range 0x100 - 0x1ff is for V4L2 Common Components
- * Range 0xf000 - 0xffff is reserved for local experimentation, and should
-- * never be used in official drivers
-+ * never be used in official drivers
- */
-
- #define I2C_DRIVERID_MSP3400 1
-@@ -90,7 +90,12 @@
- #define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */
- #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
- #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
-+#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */
-+#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */
- #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */
-+#define I2C_DRIVERID_ZR36067 49 /* Zoran 36067 video encoder */
-+#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
-+#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
- #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
- #define I2C_DRIVERID_SAA7191 57 /* video decoder */
- #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
-@@ -102,8 +107,10 @@
-
- #define I2C_DRIVERID_I2CDEV 900
- #define I2C_DRIVERID_I2CPROC 901
-+#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
-+#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
-
--/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
-+/* IDs -- Use DRIVERIDs 1000-1999 for sensors.
- These were originally in sensors.h in the lm_sensors package */
- #define I2C_DRIVERID_LM78 1002
- #define I2C_DRIVERID_LM75 1003
-@@ -131,6 +138,12 @@
- #define I2C_DRIVERID_ADM1024 1025
- #define I2C_DRIVERID_IT87 1026
- #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
-+#define I2C_DRIVERID_FSCPOS 1028
-+#define I2C_DRIVERID_FSCSCY 1029
-+#define I2C_DRIVERID_PCF8591 1030
-+#define I2C_DRIVERID_SMSC47M1 1031
-+#define I2C_DRIVERID_VT1211 1032
-+#define I2C_DRIVERID_LM92 1033
-
- /*
- * ---- Adapter types ----------------------------------------------------
-@@ -147,7 +160,8 @@
- #define I2C_ALGO_ISA 0x050000 /* lm_sensors ISA pseudo-adapter */
- #define I2C_ALGO_SAA7146 0x060000 /* SAA 7146 video decoder bus */
- #define I2C_ALGO_ACB 0x070000 /* ACCESS.bus algorithm */
--
-+#define I2C_ALGO_IIC 0x080000 /* ITE IIC bus */
-+#define I2C_ALGO_SAA7134 0x090000
- #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
-
- #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
-@@ -156,13 +170,15 @@
-
- #define I2C_ALGO_SGI 0x130000 /* SGI algorithm */
-
-+#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
-+
- #define I2C_ALGO_EXP 0x800000 /* experimental */
-
- #define I2C_ALGO_MASK 0xff0000 /* Mask for algorithms */
- #define I2C_ALGO_SHIFT 0x10 /* right shift to get index values */
-
- #define I2C_HW_ADAPS 0x10000 /* # adapter types */
--#define I2C_HW_MASK 0xffff
-+#define I2C_HW_MASK 0xffff
-
-
- /* hw specific modules that are defined per algorithm layer
-@@ -182,9 +198,13 @@
- #define I2C_HW_B_I810 0x0a /* Intel I810 */
- #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
- #define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */
-+#define I2C_HW_B_SAVG 0x0d /* Savage 4 */
- #define I2C_HW_B_RIVA 0x10 /* Riva based graphics cards */
- #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
- #define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */
-+#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
-+#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface */
-+#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
-
- /* --- PCF 8584 based algorithms */
- #define I2C_HW_P_LP 0x00 /* Parallel port interface */
-@@ -197,6 +217,12 @@
- /* --- MPC8xx PowerPC adapters */
- #define I2C_HW_MPC8XX_EPON 0x00 /* Eponymous MPC8xx I2C adapter */
-
-+/* --- ITE based algorithms */
-+#define I2C_HW_I_IIC 0x00 /* controller on the ITE */
-+
-+/* --- PowerPC on-chip adapters */
-+#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
-+
- /* --- Broadcom SiByte adapters */
- #define I2C_HW_SIBYTE 0x00
-
---- linux-2.4.27/include/linux/ide.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/ide.h
-@@ -287,7 +287,9 @@
- * Check for an interrupt and acknowledge the interrupt status
- */
- struct hwif_s;
-+struct ide_drive_s;
- typedef int (ide_ack_intr_t)(struct hwif_s *);
-+typedef void (ide_xfer_data_t)(struct ide_drive_s *, void *, unsigned int);
-
- #ifndef NO_DMA
- #define NO_DMA 255
-@@ -311,10 +313,14 @@
- typedef struct hw_regs_s {
- ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */
- int irq; /* our irq number */
-- int dma; /* our dma entry */
-+ int dma; /* our dma number */
- ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
-+ ide_xfer_data_t *ide_output_data; /* write data to i/face */
-+ ide_xfer_data_t *ide_input_data; /* read data from i/face */
-+ ide_xfer_data_t *atapi_output_bytes; /* write bytes to i/face */
-+ ide_xfer_data_t *atapi_input_bytes; /* read bytes from i/face */
- void *priv; /* interface specific data */
-- hwif_chipset_t chipset;
-+ hwif_chipset_t chipset;
- sata_ioreg_t sata_scr[SATA_NR_PORTS];
- sata_ioreg_t sata_misc[SATA_NR_PORTS];
- } hw_regs_t;
---- /dev/null
-+++ linux-2.4.27/include/linux/l3/algo-bit.h
-@@ -0,0 +1,39 @@
-+/*
-+ * linux/include/linux/l3/algo-bit.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * L3 Bus bit-banging algorithm. Derived from i2c-algo-bit.h by
-+ * Simon G. Vogl.
-+ */
-+#ifndef L3_ALGO_BIT_H
-+#define L3_ALGO_BIT_H 1
-+
-+#include <linux/l3/l3.h>
-+
-+struct l3_algo_bit_data {
-+ void (*setdat) (void *data, int state);
-+ void (*setclk) (void *data, int state);
-+ void (*setmode)(void *data, int state);
-+ void (*setdir) (void *data, int in); /* set data direction */
-+ int (*getdat) (void *data);
-+
-+ void *data;
-+
-+ /* bus timings (us) */
-+ int data_hold;
-+ int data_setup;
-+ int clock_high;
-+ int mode_hold;
-+ int mode_setup;
-+ int mode;
-+};
-+
-+int l3_bit_add_bus(struct l3_adapter *);
-+int l3_bit_del_bus(struct l3_adapter *);
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/linux/l3/l3.h
-@@ -0,0 +1,208 @@
-+/*
-+ * linux/include/linux/l3/l3.h
-+ *
-+ * Copyright (C) 2001 Russell King, All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License.
-+ *
-+ * Derived from i2c.h by Simon G. Vogl
-+ */
-+#ifndef L3_H
-+#define L3_H
-+
-+struct l3_msg {
-+ unsigned char addr; /* slave address */
-+ unsigned char flags;
-+#define L3_M_RD 0x01
-+#define L3_M_NOADDR 0x02
-+ unsigned short len; /* msg length */
-+ unsigned char *buf; /* pointer to msg data */
-+};
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+#include <linux/list.h>
-+
-+struct l3_client;
-+
-+struct l3_ops {
-+ int (*open)(struct l3_client *);
-+ int (*command)(struct l3_client *, int cmd, void *arg);
-+ void (*close)(struct l3_client *);
-+};
-+
-+/*
-+ * A driver is capable of handling one or more physical devices present on
-+ * L3 adapters. This information is used to inform the driver of adapter
-+ * events.
-+ */
-+struct l3_driver {
-+ /*
-+ * This name is used to uniquely identify the driver.
-+ * It should be the same as the module name.
-+ */
-+ char name[32];
-+
-+ /*
-+ * Notifies the driver that a new client wishes to use its
-+ * services. Note that the module use count will be increased
-+ * prior to this function being called. In addition, the
-+ * clients driver and adapter fields will have been setup.
-+ */
-+ int (*attach_client)(struct l3_client *);
-+
-+ /*
-+ * Notifies the driver that the client has finished with its
-+ * services, and any memory that it allocated for this client
-+ * should be cleaned up. In addition the chip should be
-+ * shut down.
-+ */
-+ void (*detach_client)(struct l3_client *);
-+
-+ /*
-+ * Possible operations on the driver.
-+ */
-+ struct l3_ops *ops;
-+
-+ /*
-+ * Module structure, if any.
-+ */
-+ struct module *owner;
-+
-+ /*
-+ * drivers list
-+ */
-+ struct list_head drivers;
-+};
-+
-+struct l3_adapter;
-+
-+struct l3_algorithm {
-+ /* textual description */
-+ char name[32];
-+
-+ /* perform bus transactions */
-+ int (*xfer)(struct l3_adapter *, struct l3_msg msgs[], int num);
-+};
-+
-+struct semaphore;
-+
-+/*
-+ * l3_adapter is the structure used to identify a physical L3 bus along
-+ * with the access algorithms necessary to access it.
-+ */
-+struct l3_adapter {
-+ /*
-+ * This name is used to uniquely identify the adapter.
-+ * It should be the same as the module name.
-+ */
-+ char name[32];
-+
-+ /*
-+ * the algorithm to access the bus
-+ */
-+ struct l3_algorithm *algo;
-+
-+ /*
-+ * Algorithm specific data
-+ */
-+ void *algo_data;
-+
-+ /*
-+ * This may be NULL, or should point to the module struct
-+ */
-+ struct module *owner;
-+
-+ /*
-+ * private data for the adapter
-+ */
-+ void *data;
-+
-+ /*
-+ * Our lock. Unlike the i2c layer, we allow this to be used for
-+ * other stuff, like the i2c layer lock. Some people implement
-+ * i2c stuff using the same signals as the l3 bus.
-+ */
-+ struct semaphore *lock;
-+
-+ /*
-+ * List of attached clients.
-+ */
-+ struct list_head clients;
-+
-+ /*
-+ * List of all adapters.
-+ */
-+ struct list_head adapters;
-+};
-+
-+/*
-+ * l3_client identifies a single device (i.e. chip) that is connected to an
-+ * L3 bus. The behaviour is defined by the routines of the driver. This
-+ * function is mainly used for lookup & other admin. functions.
-+ */
-+struct l3_client {
-+ struct l3_adapter *adapter; /* the adapter we sit on */
-+ struct l3_driver *driver; /* and our access routines */
-+ void *driver_data; /* private driver data */
-+ struct list_head __adap;
-+};
-+
-+
-+extern int l3_add_adapter(struct l3_adapter *);
-+extern int l3_del_adapter(struct l3_adapter *);
-+
-+extern int l3_add_driver(struct l3_driver *);
-+extern int l3_del_driver(struct l3_driver *);
-+
-+extern int l3_attach_client(struct l3_client *, const char *, const char *);
-+extern int l3_detach_client(struct l3_client *);
-+
-+extern int l3_transfer(struct l3_adapter *, struct l3_msg msgs[], int);
-+extern int l3_write(struct l3_client *, int, const char *, int);
-+extern int l3_read(struct l3_client *, int, char *, int);
-+
-+/**
-+ * l3_command - send a command to a L3 device driver
-+ * @client: registered client structure
-+ * @cmd: device driver command
-+ * @arg: device driver arguments
-+ *
-+ * Ask the L3 device driver to perform some function. Further information
-+ * should be sought from the device driver in question.
-+ *
-+ * Returns negative error code on failure.
-+ */
-+static inline int l3_command(struct l3_client *clnt, int cmd, void *arg)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ int ret = -EINVAL;
-+
-+ if (ops && ops->command)
-+ ret = ops->command(clnt, cmd, arg);
-+
-+ return ret;
-+}
-+
-+static inline int l3_open(struct l3_client *clnt)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ int ret = 0;
-+
-+ if (ops && ops->open)
-+ ret = ops->open(clnt);
-+ return ret;
-+}
-+
-+static inline void l3_close(struct l3_client *clnt)
-+{
-+ struct l3_ops *ops = clnt->driver->ops;
-+ if (ops && ops->close)
-+ ops->close(clnt);
-+}
-+#endif
-+
-+#endif /* L3_H */
---- /dev/null
-+++ linux-2.4.27/include/linux/l3/uda1341.h
-@@ -0,0 +1,50 @@
-+/*
-+ * linux/include/linux/l3/uda1341.h
-+ *
-+ * Philips UDA1341 mixer device driver
-+ *
-+ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ */
-+
-+#define UDA1341_NAME "uda1341"
-+
-+struct uda1341_cfg {
-+ unsigned int fs:16;
-+ unsigned int format:3;
-+};
-+
-+#define FMT_I2S 0
-+#define FMT_LSB16 1
-+#define FMT_LSB18 2
-+#define FMT_LSB20 3
-+#define FMT_MSB 4
-+#define FMT_LSB16MSB 5
-+#define FMT_LSB18MSB 6
-+#define FMT_LSB20MSB 7
-+
-+#define L3_UDA1341_CONFIGURE 0x13410001
-+
-+struct l3_gain {
-+ unsigned int left:8;
-+ unsigned int right:8;
-+ unsigned int unused:8;
-+ unsigned int channel:8;
-+};
-+
-+#define L3_SET_VOLUME 0x13410002
-+#define L3_SET_TREBLE 0x13410003
-+#define L3_SET_BASS 0x13410004
-+#define L3_SET_GAIN 0x13410005
-+
-+struct l3_agc {
-+ unsigned int level:8;
-+ unsigned int enable:1;
-+ unsigned int attack:7;
-+ unsigned int decay:8;
-+ unsigned int channel:8;
-+};
-+
-+#define L3_INPUT_AGC 0x13410006
---- linux-2.4.27/include/linux/mm.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/mm.h
-@@ -685,6 +685,12 @@
-
- extern struct page * vmalloc_to_page(void *addr);
-
-+#ifndef __arm__
-+#define memc_update_addr(x,y,z)
-+#define memc_update_mm(x)
-+#define memc_clear(x,y)
-+#endif
-+
- #endif /* __KERNEL__ */
-
- #endif
---- linux-2.4.27/include/linux/mtd/cfi.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/mtd/cfi.h
-@@ -287,8 +287,10 @@
- #define P_ID_AMD_STD 2
- #define P_ID_INTEL_STD 3
- #define P_ID_AMD_EXT 4
-+#define P_ID_ST_ADV 32
- #define P_ID_MITSUBISHI_STD 256
- #define P_ID_MITSUBISHI_EXT 257
-+#define P_ID_SST_PAGE 258
- #define P_ID_RESERVED 65535
-
-
---- linux-2.4.27/include/linux/pci.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/pci.h
-@@ -413,6 +413,7 @@
-
- char name[90]; /* device name */
- char slot_name[8]; /* slot name */
-+ u32 saved_state[16]; /* for saving the config space before suspend */
- int active; /* ISAPnP: device is active */
- int ro; /* ISAPnP: read only */
- unsigned short regs; /* ISAPnP: supported registers */
-@@ -499,6 +500,8 @@
-
- struct pbus_set_ranges_data
- {
-+ int found_vga:1;
-+ int prefetch_valid:1;
- unsigned long io_start, io_end;
- unsigned long mem_start, mem_end;
- unsigned long prefetch_start, prefetch_end;
-@@ -641,6 +644,8 @@
- int pci_restore_state(struct pci_dev *dev, u32 *buffer);
- int pci_set_power_state(struct pci_dev *dev, int state);
- int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
-+int pci_generic_suspend_save(struct pci_dev *pdev, u32 state);
-+int pci_generic_resume_restore(struct pci_dev *pdev);
-
- /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
-
---- /dev/null
-+++ linux-2.4.27/include/linux/pld/pld_epxa.h
-@@ -0,0 +1,35 @@
-+#ifndef __LINUX_EPXAPLD_H
-+#define __LINUX_EPXAPLD_H
-+
-+/*
-+ * linux/drivers/char/pld/epxapld.h
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+#define PLD_IOC_MAGIC 'p'
-+#if !defined(KERNEL) || defined(CONFIG_PLD_HOTSWAP)
-+#define PLD_IOC_ADD_PLD_DEV _IOW(PLD_IOC_MAGIC, 0xa0, struct pldhs_dev_desc)
-+#define PLD_IOC_REMOVE_PLD_DEVS _IO(PLD_IOC_MAGIC, 0xa1)
-+#define PLD_IOC_SET_INT_MODE _IOW(PLD_IOC_MAGIC, 0xa2, int)
-+#endif
-+
-+#endif
---- /dev/null
-+++ linux-2.4.27/include/linux/pld/pld_hotswap.h
-@@ -0,0 +1,87 @@
-+#ifndef __LINUX_PLD_HOTSWAP_H
-+#define __LINUX_PLD_HOTSWAP_H
-+/*
-+ * linux/drivers/char/pld/pld_hotswap.h
-+ *
-+ * Pld driver for Altera EPXA Excalibur devices
-+ *
-+ * Copyright 2001 Altera Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: $
-+ *
-+ */
-+
-+/*
-+ * The pld_hotswap ops contain the basic operation required for adding
-+ * and removing devices from the system.
-+ */
-+
-+struct pldhs_dev_info{
-+ unsigned int size;
-+ unsigned short vendor_id;
-+ unsigned short product_id;
-+ unsigned char fsize;
-+ unsigned char nsize;
-+ unsigned short pssize;
-+ unsigned short cmdsize;
-+ unsigned char irq;
-+ unsigned char version;
-+ unsigned int base_addr;
-+ unsigned int reg_size;
-+};
-+
-+struct pldhs_dev_desc{
-+ struct pldhs_dev_info* info;
-+ char* name;
-+ void* data;
-+};
-+
-+#include <linux/pld/pld_epxa.h>
-+
-+
-+#ifdef __KERNEL__
-+struct pld_hotswap_ops{
-+ struct list_head list;
-+ char* name;
-+ int (*add_device)(struct pldhs_dev_info *dev_info, void* dev_ps_data);
-+ int (*remove_devices)(void);
-+ int (*proc_read)(char* buf,char** start,off_t offset,int count,int *eof,void *data);
-+};
-+
-+/*
-+ * These functions are called by the device drivers to register functions
-+ * which should be called when devices are added and removed
-+ */
-+extern int pldhs_register_driver(struct pld_hotswap_ops *drv);
-+extern int pldhs_unregister_driver(char *driver);
-+
-+/*
-+ * These functions are called by the pld loader to add and remove
-+ * device instances from the system. The call the functions regsistered
-+ * the the particular deriver for this purpose
-+ */
-+extern int pldhs_add_device(struct pldhs_dev_info* dev_info,char *drv_name, void* dev_ps_data);
-+extern int pldhs_remove_devices(void);
-+
-+/* Macro for formatting data to appear in the proc/pld file */
-+#define PLDHS_READ_PROC_DATA(buf,name,index,base,irq,ps_string) \
-+ sprintf(buf,":%s:%d Base Address, %#lx, IRQ, %d#\n%s\n",\
-+ name,index,base,irq,ps_string)
-+
-+#endif
-+
-+#endif
---- linux-2.4.27/include/linux/serial.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/serial.h
-@@ -48,7 +48,7 @@
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned int port_high;
-- int reserved[1];
-+ unsigned long iomap_base; /* cookie passed into ioremap */
- };
-
- /*
---- linux-2.4.27/include/linux/serialP.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/serialP.h
-@@ -157,8 +157,8 @@
- struct pci_dev *dev;
- };
-
--extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
--extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-+//extern int pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-+//extern int pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable);
-
- #ifndef PCI_ANY_ID
- #define PCI_ANY_ID (~0)
---- /dev/null
-+++ linux-2.4.27/include/linux/serial_core.h
-@@ -0,0 +1,441 @@
-+/*
-+ * linux/drivers/char/serial_core.h
-+ *
-+ * Copyright (C) 2000 Deep Blue Solutions Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * $Id: serial_core.h,v 1.9.2.3 2001/11/26 22:32:45 rmk Exp $
-+ */
-+
-+/*
-+ * The type definitions. These are from Ted Ts'o's serial.h
-+ */
-+#define PORT_UNKNOWN 0
-+#define PORT_8250 1
-+#define PORT_16450 2
-+#define PORT_16550 3
-+#define PORT_16550A 4
-+#define PORT_CIRRUS 5
-+#define PORT_16650 6
-+#define PORT_16650V2 7
-+#define PORT_16750 8
-+#define PORT_STARTECH 9
-+#define PORT_16C950 10
-+#define PORT_16654 11
-+#define PORT_16850 12
-+#define PORT_RSA 13
-+#define PORT_NS16550A 14
-+#define PORT_MAX_8250 14 /* max port ID */
-+
-+/*
-+ * ARM specific type numbers. These are not currently guaranteed
-+ * to be implemented, and will change in the future. These are
-+ * separate so any additions to the old serial.c that occur before
-+ * we are merged can be easily merged here.
-+ */
-+#define PORT_AMBA 32
-+#define PORT_CLPS711X 33
-+#define PORT_SA1100 34
-+#define PORT_UART00 35
-+#define PORT_21285 37
-+
-+/* Sparc type numbers. */
-+#define PORT_SUNZILOG 38
-+#define PORT_SUNSAB 39
-+
-+/* NEC v850. */
-+#define PORT_NB85E_UART 40
-+
-+/* NEC PC-9800 */
-+#define PORT_8251_PC98 41
-+#define PORT_19K_PC98 42
-+#define PORT_FIFO_PC98 43
-+#define PORT_VFAST_PC98 44
-+#define PORT_PC9861 45
-+#define PORT_PC9801_101 46
-+
-+/* DZ */
-+#define PORT_DZ 47
-+
-+#define PORT_OMAHA 48
-+#define PORT_AT91RM9200 49
-+
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/config.h>
-+#include <linux/interrupt.h>
-+#include <linux/circ_buf.h>
-+#include <linux/serial.h>
-+#include <linux/spinlock.h>
-+
-+struct uart_port;
-+struct uart_info;
-+struct serial_struct;
-+
-+/*
-+ * This structure describes all the operations that can be
-+ * done on the physical hardware.
-+ */
-+struct uart_ops {
-+ unsigned int (*tx_empty)(struct uart_port *);
-+ void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
-+ unsigned int (*get_mctrl)(struct uart_port *);
-+ void (*stop_tx)(struct uart_port *, unsigned int tty_stop);
-+ void (*start_tx)(struct uart_port *, unsigned int tty_start);
-+ void (*send_xchar)(struct uart_port *, char ch);
-+ void (*stop_rx)(struct uart_port *);
-+ void (*enable_ms)(struct uart_port *);
-+ void (*break_ctl)(struct uart_port *, int ctl);
-+ int (*startup)(struct uart_port *);
-+ void (*shutdown)(struct uart_port *);
-+ void (*change_speed)(struct uart_port *, unsigned int cflag, unsigned int iflag, unsigned int quot);
-+ void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate);
-+ int (*set_wake)(struct uart_port *, unsigned int state);
-+
-+ /*
-+ * Return a string describing the type of the port
-+ */
-+ const char *(*type)(struct uart_port *);
-+
-+ /*
-+ * Release IO and memory resources used by the port.
-+ * This includes iounmap if necessary.
-+ */
-+ void (*release_port)(struct uart_port *);
-+
-+ /*
-+ * Request IO and memory resources used by the port.
-+ * This includes iomapping the port if necessary.
-+ */
-+ int (*request_port)(struct uart_port *);
-+ void (*config_port)(struct uart_port *, int);
-+ int (*verify_port)(struct uart_port *, struct serial_struct *);
-+ int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
-+};
-+
-+#define UART_CONFIG_TYPE (1 << 0)
-+#define UART_CONFIG_IRQ (1 << 1)
-+
-+struct uart_icount {
-+ __u32 cts;
-+ __u32 dsr;
-+ __u32 rng;
-+ __u32 dcd;
-+ __u32 rx;
-+ __u32 tx;
-+ __u32 frame;
-+ __u32 overrun;
-+ __u32 parity;
-+ __u32 brk;
-+ __u32 buf_overrun;
-+};
-+
-+struct uart_port {
-+ spinlock_t lock; /* port lock */
-+ unsigned int iobase; /* in/out[bwl] */
-+ char *membase; /* read/write[bwl] */
-+ unsigned char fifosize; /* tx fifo size */
-+ unsigned char x_char; /* xon/xoff char */
-+ unsigned char regshift; /* reg offset shift */
-+ unsigned char iotype; /* io access style */
-+
-+#define UPIO_PORT (0)
-+#define UPIO_HUB6 (1)
-+#define UPIO_MEM (2)
-+
-+ unsigned int read_status_mask; /* driver specific */
-+ unsigned int ignore_status_mask; /* driver specific */
-+
-+ struct uart_info *info; /* pointer to parent info */
-+ struct uart_icount icount; /* statistics */
-+
-+ struct console *cons; /* struct console, if any */
-+ unsigned long sysrq; /* sysrq timeout */
-+
-+ unsigned int flags;
-+
-+#define UPF_HUP_NOTIFY ASYNC_HUP_NOTIFY
-+#define UPF_FOURPORT ASYNC_FOURPORT
-+#define UPF_SAK ASYNC_SAK
-+#define UPF_SPLIT_TERMIOS ASYNC_SPLIT_TERMIOS
-+#define UPF_SPD_MASK (0x1030)
-+#define UPF_SPD_HI (0x0010)
-+#define UPF_SPD_VHI (0x0020)
-+#define UPF_SPD_CUST (0x0030)
-+#define UPF_SPD_SHI (0x1000)
-+#define UPF_SPD_WARP (0x1010)
-+#define UPF_SKIP_TEST ASYNC_SKIP_TEST
-+#define UPF_AUTO_IRQ ASYNC_AUTO_IRQ
-+#define UPF_SESSION_LOCKOUT ASYNC_SESSION_LOCKOUT
-+#define UPF_PGRP_LOCKOUT ASYNCPGRP_LOCKOUT
-+#define UPF_CALLOUT_NOHUP ASYNC_CALLOUT_NOHUP
-+#define UPF_HARDPPS_CD ASYNC_HARDPPS_CD
-+ /* 12 */
-+#define UPF_LOW_LATENCY ASYNC_LOW_LATENCY
-+#define UPF_BUGGY_UART ASYNC_BUGGY_UART
-+#define UPF_AUTOPROBE ASYNC_AUTOPROBE
-+#define UPF_MAGIC_MULTIPLIER (1 << 16)
-+#define UPF_BOOT_ONLYMCA ASYNC_BOOT_ONLYMCA
-+#define UPF_CONS_FLOW ASYNC_CONS_FLOW
-+#define UPF_SHARE_IRQ ASYNC_SHARE_IRQ
-+#define UPF_BOOT_AUTOCONF ASYNC_BOOT_AUTOCONF
-+#define UPF_RESOURCES (1 << 30)
-+#define UPF_IOREMAP (1 << 31)
-+
-+#define UPF_CHANGE_MASK (0x17fff)
-+#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY)
-+
-+ unsigned int mctrl; /* current modem ctrl settings */
-+ unsigned int timeout; /* character-based timeout */
-+ unsigned int type; /* port type */
-+ struct uart_ops *ops;
-+ unsigned int uartclk; /* base uart clock */
-+ unsigned int custom_divisor;
-+ unsigned int irq; /* irq number */
-+ unsigned int line; /* port index */
-+ unsigned long mapbase; /* for ioremap */
-+ unsigned char hub6; /* this should be in the 8250 driver */
-+ unsigned char unused[7];
-+};
-+
-+/*
-+ * This is the state information which is persistent across opens.
-+ * The low level driver must not to touch any elements contained
-+ * within.
-+ */
-+struct uart_state {
-+ unsigned int close_delay;
-+ unsigned int closing_wait;
-+
-+#define USF_CLOSING_WAIT_INF (0)
-+#define USF_CLOSING_WAIT_NONE (65535)
-+
-+ struct termios normal_termios;
-+ struct termios callout_termios;
-+
-+ int count;
-+ struct uart_info *info;
-+ struct uart_port *port;
-+
-+ struct semaphore sem;
-+#ifdef CONFIG_PM
-+ struct pm_dev *pm;
-+#endif
-+};
-+
-+#define UART_XMIT_SIZE 1024
-+/*
-+ * This is the state information which is only valid when the port
-+ * is open; it may be freed by the core driver once the device has
-+ * been closed. Either the low level driver or the core can modify
-+ * stuff here.
-+ */
-+struct uart_info {
-+ struct tty_struct *tty;
-+ struct circ_buf xmit;
-+ unsigned int flags;
-+
-+/*
-+ * These are the flags that specific to info->flags, and reflect our
-+ * internal state. They can not be accessed via port->flags. Low
-+ * level drivers must not change these, but may query them instead.
-+ */
-+#define UIF_CHECK_CD ASYNC_CHECK_CD
-+#define UIF_CTS_FLOW ASYNC_CTS_FLOW
-+#define UIF_CALLOUT_ACTIVE ASYNC_CALLOUT_ACTIVE
-+#define UIF_NORMAL_ACTIVE ASYNC_NORMAL_ACTIVE
-+#define UIF_INITIALIZED ASYNC_INITIALIZED
-+
-+ unsigned char *tmpbuf;
-+ struct semaphore tmpbuf_sem;
-+
-+ unsigned int driver_priv;
-+ int blocked_open;
-+ pid_t session;
-+ pid_t pgrp;
-+
-+ struct tasklet_struct tlet;
-+
-+ wait_queue_head_t open_wait;
-+ wait_queue_head_t delta_msr_wait;
-+};
-+
-+/* number of characters left in xmit buffer before we ask for more */
-+#define WAKEUP_CHARS 256
-+
-+struct module;
-+struct tty_driver;
-+
-+struct uart_driver {
-+ struct module *owner;
-+ int normal_major;
-+ const char *normal_name;
-+ struct tty_driver *normal_driver;
-+ int callout_major;
-+ const char *callout_name;
-+ struct tty_driver *callout_driver;
-+ struct tty_struct **table;
-+ struct termios **termios;
-+ struct termios **termios_locked;
-+ int minor;
-+ int nr;
-+ struct console *cons;
-+
-+ /*
-+ * these are private; the low level driver should not
-+ * touch these; they should be initialised to NULL
-+ */
-+ struct uart_state *state;
-+};
-+
-+void uart_write_wakeup(struct uart_port *port);
-+struct uart_port *uart_get_console(struct uart_port *ports, int nr,
-+ struct console *c);
-+void uart_parse_options(char *options, int *baud, int *parity, int *bits,
-+ int *flow);
-+int uart_set_options(struct uart_port *port, struct console *co, int baud,
-+ int parity, int bits, int flow);
-+
-+/*
-+ * Port/driver registration/removal
-+ */
-+int uart_register_driver(struct uart_driver *uart);
-+void uart_unregister_driver(struct uart_driver *uart);
-+void uart_unregister_port(struct uart_driver *reg, int line);
-+int uart_register_port(struct uart_driver *reg, struct uart_port *port);
-+int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
-+int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
-+
-+#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
-+#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
-+
-+#define uart_circ_chars_pending(circ) \
-+ (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-+
-+#define uart_circ_chars_free(circ) \
-+ (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-+
-+#define uart_tx_stopped(port) \
-+ ((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
-+
-+/*
-+ * The following are helper functions for the low level drivers.
-+ */
-+#ifdef SUPPORT_SYSRQ
-+static inline int
-+uart_handle_sysrq_char(struct uart_port *port, unsigned int ch,
-+ struct pt_regs *regs)
-+{
-+ if (port->sysrq) {
-+ if (ch && time_before(jiffies, port->sysrq)) {
-+ handle_sysrq(ch, regs, NULL, NULL);
-+ port->sysrq = 0;
-+ return 1;
-+ }
-+ port->sysrq = 0;
-+ }
-+ return 0;
-+}
-+#else
-+#define uart_handle_sysrq_char(port,ch,regs) (0)
-+#endif
-+
-+/*
-+ * We do the SysRQ and SAK checking like this...
-+ */
-+static inline int uart_handle_break(struct uart_port *port)
-+{
-+ struct uart_info *info = port->info;
-+#ifdef SUPPORT_SYSRQ
-+ if (port->cons && port->cons->index == port->line) {
-+ if (!port->sysrq) {
-+ port->sysrq = jiffies + HZ*5;
-+ return 1;
-+ }
-+ port->sysrq = 0;
-+ }
-+#endif
-+ if (port->flags & UPF_SAK)
-+ do_SAK(info->tty);
-+ return 0;
-+}
-+
-+/**
-+ * uart_handle_dcd_change - handle a change of carrier detect state
-+ * @port: uart_port structure for the open port
-+ * @status: new carrier detect status, nonzero if active
-+ */
-+static inline void
-+uart_handle_dcd_change(struct uart_port *port, unsigned int status)
-+{
-+ struct uart_info *info = port->info;
-+
-+ port->icount.dcd++;
-+
-+#ifdef CONFIG_HARD_PPS
-+ if ((port->flags & UPF_HARDPPS_CD) && status)
-+ hardpps();
-+#endif
-+
-+ if (info->flags & UIF_CHECK_CD) {
-+ if (status)
-+ wake_up_interruptible(&info->open_wait);
-+ else if (!((info->flags & UIF_CALLOUT_ACTIVE) &&
-+ (port->flags & UPF_CALLOUT_NOHUP))) {
-+ if (info->tty)
-+ tty_hangup(info->tty);
-+ }
-+ }
-+}
-+
-+/**
-+ * uart_handle_cts_change - handle a change of clear-to-send state
-+ * @port: uart_port structure for the open port
-+ * @status: new clear to send status, nonzero if active
-+ */
-+static inline void
-+uart_handle_cts_change(struct uart_port *port, unsigned int status)
-+{
-+ struct uart_info *info = port->info;
-+ struct tty_struct *tty = info->tty;
-+
-+ port->icount.cts++;
-+
-+ if (info->flags & UIF_CTS_FLOW) {
-+ if (tty->hw_stopped) {
-+ if (status) {
-+ tty->hw_stopped = 0;
-+ port->ops->start_tx(port, 0);
-+ uart_write_wakeup(port);
-+ }
-+ } else {
-+ if (!status) {
-+ tty->hw_stopped = 1;
-+ port->ops->stop_tx(port, 0);
-+ }
-+ }
-+ }
-+}
-+
-+/*
-+ * UART_ENABLE_MS - determine if port should enable modem status irqs
-+ */
-+#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
-+ (cflag) & CRTSCTS || \
-+ !((cflag) & CLOCAL))
-+
-+#endif
---- linux-2.4.27/include/linux/serial_reg.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/serial_reg.h
-@@ -121,6 +121,7 @@
- /*
- * These are the definitions for the Modem Control Register
- */
-+#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS (TI16C750) */
- #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
- #define UART_MCR_OUT2 0x08 /* Out2 complement */
- #define UART_MCR_OUT1 0x04 /* Out1 complement */
---- linux-2.4.27/include/linux/zlib.h~2.4.27-vrs1
-+++ linux-2.4.27/include/linux/zlib.h
-@@ -31,7 +31,7 @@
- #ifndef _ZLIB_H
- #define _ZLIB_H
-
--#include <linux/zconf.h>
-+#include "zconf.h"
-
- #ifdef __cplusplus
- extern "C" {
---- linux-2.4.27/init/do_mounts.c~2.4.27-vrs1
-+++ linux-2.4.27/init/do_mounts.c
-@@ -888,7 +888,7 @@
- */
- void prepare_namespace(void)
- {
-- int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
-+ int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
- #ifdef CONFIG_ALL_PPC
- extern void arch_discover_root(void);
- arch_discover_root();
-@@ -951,6 +951,7 @@
- static unsigned inptr; /* index of next byte to be processed in inbuf */
- static unsigned outcnt; /* bytes in output buffer */
- static int exit_code;
-+static int unzip_error;
- static long bytes_out;
- static int crd_infd, crd_outfd;
-
-@@ -998,13 +999,17 @@
- /* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
-+ * Returning -1 does not guarantee that gunzip() will ever return.
- */
- static int __init fill_inbuf(void)
- {
- if (exit_code) return -1;
-
- insize = read(crd_infd, inbuf, INBUFSIZ);
-- if (insize == 0) return -1;
-+ if (insize == 0) {
-+ error("RAMDISK: ran out of compressed data\n");
-+ return -1;
-+ }
-
- inptr = 1;
-
-@@ -1018,10 +1023,15 @@
- static void __init flush_window(void)
- {
- ulg c = crc; /* temporary variable */
-- unsigned n;
-+ unsigned n, written;
- uch *in, ch;
-
-- write(crd_outfd, window, outcnt);
-+ written = write(crd_outfd, window, outcnt);
-+ if (written != outcnt && unzip_error == 0) {
-+ printk(KERN_ERR "RAMDISK: incomplete write (%d != %d), "
-+ "only wrote %ld\n", written, outcnt, bytes_out);
-+ unzip_error = 1;
-+ }
- in = window;
- for (n = 0; n < outcnt; n++) {
- ch = *in++;
-@@ -1036,6 +1046,7 @@
- {
- printk(KERN_ERR "%s", x);
- exit_code = 1;
-+ unzip_error = 1;
- }
-
- static int __init crd_load(int in_fd, int out_fd)
-@@ -1064,6 +1075,8 @@
- }
- makecrc();
- result = gunzip();
-+ if (unzip_error)
-+ result = 1;
- kfree(inbuf);
- kfree(window);
- return result;
---- linux-2.4.27/kernel/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/kernel/Makefile
-@@ -9,16 +9,19 @@
-
- O_TARGET := kernel.o
-
--export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
-+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
-+ printk.o fork.o cpufreq.o
-
--obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
-+obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
- module.o exit.o itimer.o info.o time.o softirq.o resource.o \
- sysctl.o acct.o capability.o ptrace.o timer.o user.o \
- signal.o sys.o kmod.o context.o
-
-+obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += ksyms.o
- obj-$(CONFIG_PM) += pm.o
-+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
---- /dev/null
-+++ linux-2.4.27/kernel/cpufreq.c
-@@ -0,0 +1,536 @@
-+/*
-+ * linux/kernel/cpufreq.c
-+ *
-+ * Copyright (C) 2001 Russell King
-+ *
-+ * $Id: cpufreq.c,v 1.17.2.2 2002/05/03 13:26:27 rmk Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * CPU speed changing core functionality. We provide the following
-+ * services to the system:
-+ * - notifier lists to inform other code of the freq change both
-+ * before and after the freq change.
-+ * - the ability to change the freq speed
-+ *
-+ * ** You'll need to add CTL_CPU = 10 to include/linux/sysctl.h if
-+ * it's not already present.
-+ *
-+ * When this appears in the kernel, the sysctl enums will move to
-+ * include/linux/sysctl.h
-+ */
-+#include <linux/config.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/notifier.h>
-+#include <linux/cpufreq.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/smp.h>
-+#include <linux/fs.h>
-+#include <linux/sysctl.h>
-+
-+#include <asm/semaphore.h>
-+#include <asm/system.h>
-+#include <asm/uaccess.h>
-+#include <linux/interrupt.h> /* requires system.h */
-+
-+/*
-+ * This list is for kernel code that needs to handle
-+ * changes to devices when the CPU clock speed changes.
-+ */
-+static struct notifier_block *cpufreq_notifier_list;
-+static DECLARE_MUTEX_LOCKED(cpufreq_sem);
-+static unsigned long cpufreq_ref_loops;
-+static unsigned int cpufreq_ref_freq;
-+static int cpufreq_initialised;
-+static unsigned int (*cpufreq_validatespeed)(unsigned int);
-+static void (*cpufreq_setspeed)(unsigned int);
-+
-+#ifndef CONFIG_SMP
-+static unsigned int __cpufreq_max;
-+static unsigned int __cpufreq_min;
-+static unsigned int __cpufreq_cur;
-+#endif
-+
-+static unsigned long scale(unsigned long ref, u_int div, u_int mult)
-+{
-+ unsigned long new_jiffy_l, new_jiffy_h;
-+
-+ /*
-+ * Recalculate loops_per_jiffy. We do it this way to
-+ * avoid math overflow on 32-bit machines. Maybe we
-+ * should make this architecture dependent? If you have
-+ * a better way of doing this, please replace!
-+ *
-+ * new = old * mult / div
-+ */
-+ new_jiffy_h = ref / div;
-+ new_jiffy_l = (ref % div) / 100;
-+ new_jiffy_h *= mult;
-+ new_jiffy_l = new_jiffy_l * mult / div;
-+
-+ return new_jiffy_h + new_jiffy_l * 100;
-+}
-+
-+/*
-+ * cpufreq_max command line parameter. Use:
-+ * cpufreq=59000-221000
-+ * to set the CPU frequency to 59 to 221MHz.
-+ */
-+static int __init cpufreq_setup(char *str)
-+{
-+ unsigned int min, max;
-+ int i;
-+
-+ min = 0;
-+ max = simple_strtoul(str, &str, 0);
-+ if (*str == '-') {
-+ min = max;
-+ max = simple_strtoul(str + 1, NULL, 0);
-+ }
-+
-+ for (i = 0; i < smp_num_cpus; i++) {
-+ cpufreq_max(i) = max;
-+ cpufreq_min(i) = min;
-+ }
-+
-+ return 1;
-+}
-+
-+__setup("cpufreq=", cpufreq_setup);
-+
-+/**
-+ * cpufreq_register_notifier - register a driver with cpufreq
-+ * @nb: notifier function to register
-+ *
-+ * Add a driver to the list of drivers that which to be notified about
-+ * CPU clock rate changes. The driver will be called three times on
-+ * clock change.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_register.
-+ */
-+int cpufreq_register_notifier(struct notifier_block *nb)
-+{
-+ int ret;
-+
-+ down(&cpufreq_sem);
-+ ret = notifier_chain_register(&cpufreq_notifier_list, nb);
-+ up(&cpufreq_sem);
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL(cpufreq_register_notifier);
-+
-+/**
-+ * cpufreq_unregister_notifier - unregister a driver with cpufreq
-+ * @nb: notifier block to be unregistered
-+ *
-+ * Remove a driver from the CPU frequency notifier lists.
-+ *
-+ * This function may sleep, and has the same return conditions as
-+ * notifier_chain_unregister.
-+ */
-+int cpufreq_unregister_notifier(struct notifier_block *nb)
-+{
-+ int ret;
-+
-+ down(&cpufreq_sem);
-+ ret = notifier_chain_unregister(&cpufreq_notifier_list, nb);
-+ up(&cpufreq_sem);
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL(cpufreq_unregister_notifier);
-+
-+/*
-+ * This notifier alters the system "loops_per_jiffy" for the clock
-+ * speed change. We ignore CPUFREQ_MINMAX here.
-+ */
-+static void adjust_jiffies(unsigned long val, struct cpufreq_info *ci)
-+{
-+ if ((val == CPUFREQ_PRECHANGE && ci->old_freq < ci->new_freq) ||
-+ (val == CPUFREQ_POSTCHANGE && ci->old_freq > ci->new_freq))
-+ loops_per_jiffy = scale(cpufreq_ref_loops, cpufreq_ref_freq,
-+ ci->new_freq);
-+}
-+
-+#ifdef CONFIG_PM
-+/**
-+ * cpufreq_restore - restore the CPU clock frequency after resume
-+ *
-+ * Restore the CPU clock frequency so that our idea of the current
-+ * frequency reflects the actual hardware.
-+ */
-+int cpufreq_restore(void)
-+{
-+ unsigned long old_cpus;
-+ int cpu = smp_processor_id();
-+ int ret;
-+
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_restore() called before initialisation!");
-+ if (in_interrupt())
-+ panic("cpufreq_restore() called from interrupt context!");
-+
-+ /*
-+ * Bind to the current CPU.
-+ */
-+ old_cpus = current->cpus_allowed;
-+ current->cpus_allowed = 1UL << cpu_logical_map(cpu);
-+
-+ down(&cpufreq_sem);
-+
-+ ret = -ENXIO;
-+ if (cpufreq_setspeed) {
-+ cpufreq_setspeed(cpufreq_current(cpu));
-+ ret = 0;
-+ }
-+
-+ up(&cpufreq_sem);
-+
-+ current->cpus_allowed = old_cpus;
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_restore);
-+#endif
-+
-+/**
-+ * cpu_setfreq - change the CPU clock frequency.
-+ * @freq: frequency (in kHz) at which we should run.
-+ *
-+ * Set the CPU clock frequency, informing all registered users of
-+ * the change. We bound the frequency according to the cpufreq_max
-+ * command line parameter, and the parameters the registered users
-+ * will allow.
-+ *
-+ * This function must be called from process context, and on the
-+ * cpu that we wish to change the frequency of.
-+ *
-+ * We return 0 if successful. (we are currently always successful).
-+ */
-+int cpufreq_set(unsigned int freq)
-+{
-+ unsigned long old_cpus;
-+ struct cpufreq_info clkinfo;
-+ struct cpufreq_minmax minmax;
-+ int cpu = smp_processor_id();
-+ int ret;
-+
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_set() called before initialisation!");
-+ if (in_interrupt())
-+ panic("cpufreq_set() called from interrupt context!");
-+
-+ /*
-+ * Bind to the current CPU.
-+ */
-+ old_cpus = current->cpus_allowed;
-+ current->cpus_allowed = 1UL << cpu_logical_map(cpu);
-+
-+ down(&cpufreq_sem);
-+ ret = -ENXIO;
-+ if (!cpufreq_setspeed || !cpufreq_validatespeed)
-+ goto out;
-+
-+ /*
-+ * Don't allow the CPU to be clocked over the limit.
-+ */
-+ minmax.min_freq = cpufreq_min(cpu);
-+ minmax.max_freq = cpufreq_max(cpu);
-+ minmax.cur_freq = cpufreq_current(cpu);
-+ minmax.new_freq = freq;
-+
-+ /*
-+ * Find out what the registered devices will currently tolerate,
-+ * and limit the requested clock rate to these values. Drivers
-+ * must not rely on the 'new_freq' value - it is only a guide.
-+ */
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_MINMAX, &minmax);
-+ if (freq < minmax.min_freq)
-+ freq = minmax.min_freq;
-+ if (freq > minmax.max_freq)
-+ freq = minmax.max_freq;
-+
-+ /*
-+ * Ask the CPU specific code to validate the speed. If the speed
-+ * is not acceptable, make it acceptable. Current policy is to
-+ * round the frequency down to the value the processor actually
-+ * supports.
-+ */
-+ freq = cpufreq_validatespeed(freq);
-+
-+ if (cpufreq_current(cpu) != freq) {
-+ clkinfo.old_freq = cpufreq_current(cpu);
-+ clkinfo.new_freq = freq;
-+
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_PRECHANGE,
-+ &clkinfo);
-+
-+ adjust_jiffies(CPUFREQ_PRECHANGE, &clkinfo);
-+
-+ /*
-+ * Actually set the CPU frequency.
-+ */
-+ cpufreq_setspeed(freq);
-+ cpufreq_current(cpu) = freq;
-+ adjust_jiffies(CPUFREQ_POSTCHANGE, &clkinfo);
-+
-+ notifier_call_chain(&cpufreq_notifier_list, CPUFREQ_POSTCHANGE,
-+ &clkinfo);
-+ }
-+
-+ ret = 0;
-+
-+ out:
-+ up(&cpufreq_sem);
-+
-+ current->cpus_allowed = old_cpus;
-+
-+ return ret;
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_set);
-+
-+/**
-+ * cpufreq_setmax - set the CPU to maximum frequency
-+ *
-+ * Sets the CPU this function is executed on to maximum frequency.
-+ */
-+int cpufreq_setmax(void)
-+{
-+ return cpufreq_set(cpufreq_max(smp_processor_id()));
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_setmax);
-+
-+/**
-+ * cpufreq_get - return the current CPU clock frequency in 1kHz
-+ * @cpu: cpu number to obtain frequency for
-+ *
-+ * Returns the specified CPUs frequency in kHz.
-+ */
-+unsigned int cpufreq_get(int cpu)
-+{
-+ if (!cpufreq_initialised)
-+ panic("cpufreq_get() called before initialisation!");
-+ return cpufreq_current(cpu);
-+}
-+
-+EXPORT_SYMBOL(cpufreq_get);
-+
-+#ifdef CONFIG_SYSCTL
-+
-+static int
-+cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
-+ void *buffer, size_t *lenp)
-+{
-+ char buf[16], *p;
-+ int cpu = 0, len, left = *lenp;
-+
-+ if (!left || (filp->f_pos && !write)) {
-+ *lenp = 0;
-+ return 0;
-+ }
-+
-+ if (write) {
-+ unsigned int freq;
-+
-+ len = left;
-+ if (left > sizeof(buf))
-+ left = sizeof(buf);
-+ if (copy_from_user(buf, buffer, left))
-+ return -EFAULT;
-+ buf[sizeof(buf) - 1] = '\0';
-+
-+ freq = simple_strtoul(buf, &p, 0);
-+ cpufreq_set(freq);
-+ } else {
-+ len = sprintf(buf, "%d\n", cpufreq_get(cpu));
-+ if (len > left)
-+ len = left;
-+ if (copy_to_user(buffer, buf, len))
-+ return -EFAULT;
-+ }
-+
-+ *lenp = len;
-+ filp->f_pos += len;
-+ return 0;
-+}
-+
-+static int
-+cpufreq_sysctl(ctl_table *table, int *name, int nlen,
-+ void *oldval, size_t *oldlenp,
-+ void *newval, size_t newlen, void **context)
-+{
-+ int cpu = 0;
-+
-+ if (oldval && oldlenp) {
-+ size_t oldlen;
-+
-+ if (get_user(oldlen, oldlenp))
-+ return -EFAULT;
-+
-+ if (oldlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (put_user(cpufreq_get(cpu), (unsigned int *)oldval) ||
-+ put_user(sizeof(unsigned int), oldlenp))
-+ return -EFAULT;
-+ }
-+ if (newval && newlen) {
-+ unsigned int freq;
-+
-+ if (newlen != sizeof(unsigned int))
-+ return -EINVAL;
-+
-+ if (get_user(freq, (unsigned int *)newval))
-+ return -EFAULT;
-+
-+ cpufreq_set(freq);
-+ }
-+ return 1;
-+}
-+
-+enum {
-+ CPU_NR_FREQ_MAX = 1,
-+ CPU_NR_FREQ_MIN = 2,
-+ CPU_NR_FREQ = 3
-+};
-+
-+static ctl_table ctl_cpu_vars[4] = {
-+ {
-+ ctl_name: CPU_NR_FREQ_MAX,
-+ procname: "speed-max",
-+ data: &cpufreq_max(0),
-+ maxlen: sizeof(cpufreq_max(0)),
-+ mode: 0444,
-+ proc_handler: proc_dointvec,
-+ },
-+ {
-+ ctl_name: CPU_NR_FREQ_MIN,
-+ procname: "speed-min",
-+ data: &cpufreq_min(0),
-+ maxlen: sizeof(cpufreq_min(0)),
-+ mode: 0444,
-+ proc_handler: proc_dointvec,
-+ },
-+ {
-+ ctl_name: CPU_NR_FREQ,
-+ procname: "speed",
-+ mode: 0644,
-+ proc_handler: cpufreq_procctl,
-+ strategy: cpufreq_sysctl,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+enum {
-+ CPU_NR = 1,
-+};
-+
-+static ctl_table ctl_cpu_nr[2] = {
-+ {
-+ ctl_name: CPU_NR,
-+ procname: "0",
-+ mode: 0555,
-+ child: ctl_cpu_vars,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+static ctl_table ctl_cpu[2] = {
-+ {
-+ ctl_name: CTL_CPU,
-+ procname: "cpu",
-+ mode: 0555,
-+ child: ctl_cpu_nr,
-+ },
-+ {
-+ ctl_name: 0,
-+ }
-+};
-+
-+static inline void cpufreq_sysctl_init(void)
-+{
-+ register_sysctl_table(ctl_cpu, 0);
-+}
-+
-+#else
-+#define cpufreq_sysctl_init()
-+#endif
-+
-+/**
-+ * cpufreq_setfunctions - Set CPU clock functions
-+ * @validate: pointer to validation function
-+ * @setspeed: pointer to setspeed function
-+ */
-+void
-+cpufreq_setfunctions(unsigned int (*validate)(unsigned int),
-+ void (*setspeed)(unsigned int))
-+{
-+ down(&cpufreq_sem);
-+ cpufreq_validatespeed = validate;
-+ cpufreq_setspeed = setspeed;
-+ up(&cpufreq_sem);
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_setfunctions);
-+
-+/**
-+ * cpufreq_init - Initialise the cpufreq core
-+ * @freq: current CPU clock speed.
-+ * @min_freq: minimum CPU clock speed.
-+ * @max_freq: maximum CPU clock speed.
-+ *
-+ * Initialise the cpufreq core. If the cpufreq_max command line
-+ * parameter has not been specified, we set the maximum clock rate
-+ * to the current CPU clock rate.
-+ */
-+void cpufreq_init(unsigned int freq,
-+ unsigned int min_freq,
-+ unsigned int max_freq)
-+{
-+ /*
-+ * If the user doesn't tell us their maximum frequency,
-+ * or if it is invalid, use the values determined
-+ * by the cpufreq-arch-specific initialization functions.
-+ * The validatespeed code is responsible for limiting
-+ * this further.
-+ */
-+ if (max_freq && ((cpufreq_max(0) == 0) || (cpufreq_max(0) > max_freq)))
-+ cpufreq_max(0) = max_freq;
-+ if (min_freq && ((cpufreq_min(0) == 0) || (cpufreq_min(0) < min_freq)))
-+ cpufreq_min(0) = min_freq;
-+
-+ if (cpufreq_max(0) == 0)
-+ cpufreq_max(0) = freq;
-+
-+ printk(KERN_INFO "CPU clock: %d.%03d MHz (%d.%03d-%d.%03d MHz)\n",
-+ freq / 1000, freq % 1000,
-+ cpufreq_min(0) / 1000, cpufreq_min(0) % 1000,
-+ cpufreq_max(0) / 1000, cpufreq_max(0) % 1000);
-+
-+ cpufreq_ref_loops = loops_per_jiffy;
-+ cpufreq_ref_freq = freq;
-+ cpufreq_current(smp_processor_id()) = freq;
-+
-+ cpufreq_initialised = 1;
-+ up(&cpufreq_sem);
-+
-+ cpufreq_sysctl_init();
-+}
-+
-+EXPORT_SYMBOL_GPL(cpufreq_init);
---- linux-2.4.27/kernel/exit.c~2.4.27-vrs1
-+++ linux-2.4.27/kernel/exit.c
-@@ -587,7 +587,7 @@
- return retval;
- }
-
--#if !defined(__alpha__) && !defined(__ia64__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
-
- /*
- * sys_waitpid() remains for compatibility. waitpid() should be
---- linux-2.4.27/kernel/fork.c~2.4.27-vrs1
-+++ linux-2.4.27/kernel/fork.c
-@@ -75,7 +75,11 @@
- * value: the thread structures can take up at most half
- * of memory.
- */
-+#if THREAD_SIZE > PAGE_SIZE
- max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8;
-+#else
-+ max_threads = (mempages * PAGE_SIZE) / (8 * THREAD_SIZE);
-+#endif
-
- init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
- init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
-@@ -220,6 +224,7 @@
-
- fail_nomem:
- flush_tlb_mm(current->mm);
-+ memc_update_mm(mm);
- return retval;
- }
-
---- linux-2.4.27/kernel/ksyms.c~2.4.27-vrs1
-+++ linux-2.4.27/kernel/ksyms.c
-@@ -345,6 +345,7 @@
-
- /* tty routines */
- EXPORT_SYMBOL(tty_hangup);
-+EXPORT_SYMBOL(tty_vhangup);
- EXPORT_SYMBOL(tty_wait_until_sent);
- EXPORT_SYMBOL(tty_check_change);
- EXPORT_SYMBOL(tty_hung_up_p);
-@@ -439,9 +440,11 @@
- EXPORT_SYMBOL(kiobuf_wait_for_io);
-
- /* dma handling */
-+#ifdef CONFIG_GENERIC_ISA_DMA
- EXPORT_SYMBOL(request_dma);
- EXPORT_SYMBOL(free_dma);
- EXPORT_SYMBOL(dma_spin_lock);
-+#endif
- #ifdef HAVE_DISABLE_HLT
- EXPORT_SYMBOL(disable_hlt);
- EXPORT_SYMBOL(enable_hlt);
---- linux-2.4.27/kernel/signal.c~2.4.27-vrs1
-+++ linux-2.4.27/kernel/signal.c
-@@ -778,8 +778,8 @@
- info.si_uid = tsk->uid;
-
- /* FIXME: find out whether or not this is supposed to be c*time. */
-- info.si_utime = tsk->times.tms_utime;
-- info.si_stime = tsk->times.tms_stime;
-+ info.si_utime = hz_to_std(tsk->times.tms_utime);
-+ info.si_stime = hz_to_std(tsk->times.tms_stime);
-
- status = tsk->exit_code & 0x7f;
- why = SI_KERNEL; /* shouldn't happen */
-@@ -1277,7 +1277,7 @@
- #endif /* __sparc__ */
- #endif
-
--#if !defined(__alpha__) && !defined(__ia64__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
- /*
- * For backwards compatibility. Functionality superseded by sigprocmask.
- */
-@@ -1305,7 +1305,8 @@
- }
- #endif /* !defined(__alpha__) */
-
--#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__)
-+#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \
-+ !defined(__arm__)
- /*
- * For backwards compatibility. Functionality superseded by sigaction.
- */
-@@ -1322,4 +1323,4 @@
-
- return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
- }
--#endif /* !alpha && !__ia64__ && !defined(__mips__) */
-+#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */
---- linux-2.4.27/kernel/sys.c~2.4.27-vrs1
-+++ linux-2.4.27/kernel/sys.c
-@@ -801,16 +801,23 @@
-
- asmlinkage long sys_times(struct tms * tbuf)
- {
-+ struct tms temp;
-+
- /*
- * In the SMP world we might just be unlucky and have one of
- * the times increment as we use it. Since the value is an
- * atomically safe type this is just fine. Conceptually its
- * as if the syscall took an instant longer to occur.
- */
-- if (tbuf)
-- if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
-+ if (tbuf) {
-+ temp.tms_utime = hz_to_std(current->times.tms_utime);
-+ temp.tms_stime = hz_to_std(current->times.tms_stime);
-+ temp.tms_cutime = hz_to_std(current->times.tms_cutime);
-+ temp.tms_cstime = hz_to_std(current->times.tms_cstime);
-+ if (copy_to_user(tbuf, &temp, sizeof(struct tms)))
- return -EFAULT;
-- return jiffies;
-+ }
-+ return hz_to_std(jiffies);
- }
-
- /*
---- linux-2.4.27/lib/string.c~2.4.27-vrs1
-+++ linux-2.4.27/lib/string.c
-@@ -188,10 +188,10 @@
- */
- char * strchr(const char * s, int c)
- {
-- for(; *s != (char) c; ++s)
-- if (*s == '\0')
-- return NULL;
-- return (char *) s;
-+ for(; *s != '\0'; ++s)
-+ if (*s == (char) c)
-+ return (char *) s;
-+ return NULL;
- }
- #endif
-
---- linux-2.4.27/mm/Makefile~2.4.27-vrs1
-+++ linux-2.4.27/mm/Makefile
-@@ -18,4 +18,5 @@
-
- obj-$(CONFIG_HIGHMEM) += highmem.o
-
-+obj-y += debug.o
- include $(TOPDIR)/Rules.make
---- /dev/null
-+++ linux-2.4.27/mm/debug.c
-@@ -0,0 +1,159 @@
-+/*
-+ * linux/mm/debug.c
-+ *
-+ * Copyright (C) 2001 Russell King.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Dump out page information on SysRQ-G, and provide show_page_info()
-+ *
-+ * You are advised to use a serial console with this patch - it
-+ * saturates a 38400baud link for 1 minute on a 32MB machine.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/pagemap.h>
-+#include <linux/sysrq.h>
-+#include <linux/init.h>
-+
-+/*
-+ * We print out the following information for each page in the system:
-+ * address: use count, age, mapping, [RSsr] rD [acd]
-+ *
-+ * The flags are:
-+ * R - reserved
-+ * S - in swapcache
-+ * s - slab page
-+ *
-+ * r - referenced
-+ * D - dirty
-+ *
-+ * a - active page
-+ */
-+static void page_detail(struct page *page)
-+{
-+ if (!page)
-+ return;
-+
-+ printk("%p: %2d %p [%c%c%c] %c%c [%c]\n",
-+ page_address(page),
-+ page_count(page),
-+ page->mapping,
-+
-+ PageReserved(page) ? 'R' : '-',
-+ PageSwapCache(page) ? 'S' : '-',
-+ PageSlab(page) ? 's' : '-',
-+
-+ PageReferenced(page) ? 'r' : '-',
-+ PageDirty(page) ? 'D' : '-',
-+
-+ PageActive(page) ? 'a' : '-');
-+}
-+
-+/*
-+ * This version collects statistics
-+ */
-+static int anon_pages, slab_pages, resvd_pages, unused_pages;
-+
-+static void page_statistics(struct page *page)
-+{
-+ if (page) {
-+ if (PageReserved(page))
-+ resvd_pages++;
-+ else if (PageSlab(page))
-+ slab_pages++;
-+ else if (!page_count(page))
-+ unused_pages ++;
-+ else if (!page->mapping)
-+ anon_pages ++;
-+ return;
-+ }
-+
-+ printk(" anon: %d, slab: %d, reserved: %d, free: %d\n",
-+ anon_pages, slab_pages, resvd_pages, unused_pages);
-+}
-+
-+static void show_zone_info(zone_t *zone, void (*fn)(struct page *))
-+{
-+ int i;
-+
-+ printk(" total %ld, free %ld\n",
-+ zone->size, zone->free_pages);
-+
-+ anon_pages = 0;
-+ slab_pages = 0;
-+ resvd_pages = 0;
-+ unused_pages = 0;
-+
-+ for (i = 0; i < zone->size; i++) {
-+ struct page *page = zone->zone_mem_map + i;
-+
-+ fn(page);
-+ }
-+
-+ fn(NULL);
-+}
-+
-+static void show_node_info(pg_data_t *pg, void (*fn)(struct page *))
-+{
-+ int type;
-+
-+ for (type = 0; type < MAX_NR_ZONES; type++) {
-+ zone_t *zone = pg->node_zones + type;
-+
-+ if (zone->size == 0)
-+ continue;
-+
-+ printk("----- Zone %d ------\n", type);
-+
-+ show_zone_info(zone, fn);
-+ }
-+}
-+
-+static void __show_page_info(void (*fn)(struct page *))
-+{
-+ pg_data_t *pg;
-+ int pgdat = 0;
-+
-+ for (pg = pgdat_list; pg; pg = pg->node_next) {
-+
-+ printk("===== Node %d =====\n", pgdat++);
-+
-+ show_node_info(pg, fn);
-+ }
-+}
-+
-+void show_page_info(void)
-+{
-+ __show_page_info(page_detail);
-+}
-+
-+static void
-+show_pg_info(int key, struct pt_regs *regs, struct kbd_struct *kd,
-+ struct tty_struct *tty)
-+{
-+ void (*fn)(struct page *);
-+ show_mem();
-+ if (key == 'g')
-+ fn = page_detail;
-+ else
-+ fn = page_statistics;
-+ __show_page_info(fn);
-+}
-+
-+static struct sysrq_key_op page_info_op = {
-+ handler: show_pg_info,
-+ help_msg: "paGeinfo",
-+ action_msg: "Page Info",
-+};
-+
-+static int __init debug_mm_init(void)
-+{
-+ register_sysrq_key('g', &page_info_op);
-+ register_sysrq_key('h', &page_info_op);
-+ return 0;
-+}
-+
-+__initcall(debug_mm_init);
---- linux-2.4.27/mm/filemap.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/filemap.c
-@@ -2210,10 +2210,14 @@
- pte_t pte = *ptep;
-
- if (pte_present(pte)) {
-- struct page *page = pte_page(pte);
-- if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
-- flush_tlb_page(vma, address);
-- set_page_dirty(page);
-+ unsigned long pfn = pte_pfn(pte);
-+
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
-+ flush_tlb_page(vma, address);
-+ set_page_dirty(page);
-+ }
- }
- }
- return 0;
---- linux-2.4.27/mm/memory.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/memory.c
-@@ -77,8 +77,13 @@
- */
- void __free_pte(pte_t pte)
- {
-- struct page *page = pte_page(pte);
-- if ((!VALID_PAGE(page)) || PageReserved(page))
-+ unsigned long pfn = pte_pfn(pte);
-+ struct page *page;
-+
-+ if (!pfn_valid(pfn))
-+ return;
-+ page = pfn_to_page(pfn);
-+ if (PageReserved(page))
- return;
- if (pte_dirty(pte))
- set_page_dirty(page);
-@@ -232,6 +237,7 @@
- do {
- pte_t pte = *src_pte;
- struct page *ptepage;
-+ unsigned long pfn;
-
- /* copy_one_pte */
-
-@@ -241,9 +247,11 @@
- swap_duplicate(pte_to_swp_entry(pte));
- goto cont_copy_pte_range;
- }
-- ptepage = pte_page(pte);
-- if ((!VALID_PAGE(ptepage)) ||
-- PageReserved(ptepage))
-+ pfn = pte_pfn(pte);
-+ if (!pfn_valid(pfn))
-+ goto cont_copy_pte_range;
-+ ptepage = pfn_to_page(pfn);
-+ if (PageReserved(ptepage))
- goto cont_copy_pte_range;
-
- /* If it's a COW mapping, write protect it both in the parent and the child */
-@@ -314,9 +322,13 @@
- if (pte_none(pte))
- continue;
- if (pte_present(pte)) {
-- struct page *page = pte_page(pte);
-- if (VALID_PAGE(page) && !PageReserved(page))
-- freed ++;
-+ unsigned long pfn = pte_pfn(pte);
-+
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page))
-+ freed ++;
-+ }
- /* This will eventually call __free_pte on the pte. */
- tlb_remove_page(tlb, ptep, address + offset);
- } else {
-@@ -354,17 +366,37 @@
- return freed;
- }
-
-+void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long address, unsigned long end)
-+{
-+ int freed = 0;
-+ pgd_t * dir;
-+
-+ if (address >= end)
-+ BUG();
-+ dir = pgd_offset(mm, address);
-+ do {
-+ freed += zap_pmd_range(tlb, dir, address, end - address);
-+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
-+ dir++;
-+ } while (address && (address < end));
-+
-+ /*
-+ * Update rss for the mm_struct (not necessarily current->mm)
-+ * Notice that rss is an unsigned long.
-+ */
-+ if (mm->rss > freed)
-+ mm->rss -= freed;
-+ else
-+ mm->rss = 0;
-+}
-+
- /*
- * remove user pages in a given range.
- */
- void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
- {
-- mmu_gather_t *tlb;
-- pgd_t * dir;
- unsigned long start = address, end = address + size;
-- int freed = 0;
--
-- dir = pgd_offset(mm, address);
-+ mmu_gather_t *tlb;
-
- /*
- * This is a long-lived spinlock. That's fine.
-@@ -377,25 +409,10 @@
- BUG();
- spin_lock(&mm->page_table_lock);
- flush_cache_range(mm, address, end);
-- tlb = tlb_gather_mmu(mm);
-
-- do {
-- freed += zap_pmd_range(tlb, dir, address, end - address);
-- address = (address + PGDIR_SIZE) & PGDIR_MASK;
-- dir++;
-- } while (address && (address < end));
--
-- /* this will flush any remaining tlb entries */
-+ tlb = tlb_gather_mmu(mm);
-+ unmap_page_range(tlb, mm, address, end);
- tlb_finish_mmu(tlb, start, end);
--
-- /*
-- * Update rss for the mm_struct (not necessarily current->mm)
-- * Notice that rss is an unsigned long.
-- */
-- if (mm->rss > freed)
-- mm->rss -= freed;
-- else
-- mm->rss = 0;
- spin_unlock(&mm->page_table_lock);
- }
-
-@@ -407,6 +424,7 @@
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *ptep, pte;
-+ unsigned long pfn;
-
- pgd = pgd_offset(mm, address);
- if (pgd_none(*pgd) || pgd_bad(*pgd))
-@@ -423,8 +441,11 @@
- pte = *ptep;
- if (pte_present(pte)) {
- if (!write ||
-- (pte_write(pte) && pte_dirty(pte)))
-- return pte_page(pte);
-+ (pte_write(pte) && pte_dirty(pte))) {
-+ pfn = pte_pfn(pte);
-+ if (pfn_valid(pfn))
-+ return pfn_to_page(pfn);
-+ }
- }
-
- out:
-@@ -439,7 +460,8 @@
-
- static inline struct page * get_page_map(struct page *page)
- {
-- if (!VALID_PAGE(page))
-+ unsigned long pfn = page_to_pfn(page);
-+ if (!pfn_valid(pfn))
- return 0;
- return page;
- }
-@@ -826,22 +848,22 @@
- unsigned long 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 {
-- struct page *page;
- pte_t oldpage;
- oldpage = ptep_get_and_clear(pte);
-
-- page = virt_to_page(__va(phys_addr));
-- if ((!VALID_PAGE(page)) || PageReserved(page))
-- set_pte(pte, mk_pte_phys(phys_addr, prot));
-+ if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
-+ set_pte(pte, pfn_pte(pfn, prot));
- forget_pte(oldpage);
- address += PAGE_SIZE;
-- phys_addr += PAGE_SIZE;
-+ pfn++;
- pte++;
- } while (address && (address < end));
- }
-@@ -949,10 +971,11 @@
- unsigned long address, pte_t *page_table, pte_t pte)
- {
- struct page *old_page, *new_page;
-+ unsigned long pfn = pte_pfn(pte);
-
-- old_page = pte_page(pte);
-- if (!VALID_PAGE(old_page))
-+ if (!pfn_valid(pfn))
- goto bad_wp_page;
-+ old_page = pte_page(pte);
-
- if (!TryLockPage(old_page)) {
- int reuse = can_share_swap_page(old_page);
-@@ -996,7 +1019,7 @@
-
- bad_wp_page:
- spin_unlock(&mm->page_table_lock);
-- printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
-+ printk("do_wp_page: bogus page at address %08lx\n", address);
- return -1;
- no_mem:
- page_cache_release(old_page);
---- linux-2.4.27/mm/mmap.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/mmap.c
-@@ -18,6 +18,9 @@
-
- #include <asm/uaccess.h>
- #include <asm/pgalloc.h>
-+#include <asm/tlb.h>
-+
-+extern void unmap_page_range(mmu_gather_t *tlb, struct mm_struct *mm, unsigned long start, unsigned long end);
-
- /*
- * WARNING: the debugging will use recursive algorithms so never enable this
-@@ -915,6 +918,8 @@
- * old method of shifting the VA >> by PGDIR_SHIFT doesn't work.
- */
- start_index = pgd_index(first);
-+ if (start_index < FIRST_USER_PGD_NR)
-+ start_index = FIRST_USER_PGD_NR;
- end_index = pgd_index(last);
- if (end_index > start_index) {
- clear_page_tables(mm, start_index, end_index - start_index);
-@@ -1046,7 +1051,6 @@
- len = PAGE_ALIGN(len);
- if (!len)
- return addr;
--
- if ((addr + len) > TASK_SIZE || (addr + len) < addr)
- return -EINVAL;
-
-@@ -1135,45 +1139,58 @@
- /* Release all mmaps. */
- void exit_mmap(struct mm_struct * mm)
- {
-+ mmu_gather_t *tlb;
- struct vm_area_struct * mpnt;
-
- release_segments(mm);
- spin_lock(&mm->page_table_lock);
-+
-+ tlb = tlb_gather_mmu(mm);
-+
-+ flush_cache_mm(mm);
-+ mpnt = mm->mmap;
-+ while (mpnt) {
-+ unsigned long start = mpnt->vm_start;
-+ unsigned long end = mpnt->vm_end;
-+
-+ mm->map_count--;
-+ remove_shared_vm_struct(mpnt);
-+ unmap_page_range(tlb, mm, start, end);
-+ mpnt = mpnt->vm_next;
-+ }
-+
-+ /* This is just debugging */
-+ if (mm->map_count)
-+ BUG();
-+
-+ tlb_finish_mmu(tlb, 0, TASK_SIZE);
-+
- mpnt = mm->mmap;
- mm->mmap = mm->mmap_cache = NULL;
- mm->mm_rb = RB_ROOT;
- mm->rss = 0;
-- spin_unlock(&mm->page_table_lock);
- mm->total_vm = 0;
- mm->locked_vm = 0;
-
-- flush_cache_mm(mm);
-+ spin_unlock(&mm->page_table_lock);
-+
-+ clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
-+
-+ /*
-+ * Walk the list again, actually closing and freeing it
-+ * without holding any MM locks.
-+ */
- while (mpnt) {
- struct vm_area_struct * next = mpnt->vm_next;
-- unsigned long start = mpnt->vm_start;
-- unsigned long end = mpnt->vm_end;
-- unsigned long size = end - start;
--
- if (mpnt->vm_ops) {
- if (mpnt->vm_ops->close)
- mpnt->vm_ops->close(mpnt);
- }
-- mm->map_count--;
-- remove_shared_vm_struct(mpnt);
-- zap_page_range(mm, start, size);
- if (mpnt->vm_file)
- fput(mpnt->vm_file);
- kmem_cache_free(vm_area_cachep, mpnt);
- mpnt = next;
- }
--
-- /* This is just debugging */
-- if (mm->map_count)
-- BUG();
--
-- clear_page_tables(mm, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
--
-- flush_tlb_mm(mm);
- }
-
- /* Insert vm structure into process list sorted by address
---- linux-2.4.27/mm/slab.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/slab.c
-@@ -1391,7 +1391,7 @@
- #if DEBUG
- # define CHECK_NR(pg) \
- do { \
-- if (!VALID_PAGE(pg)) { \
-+ if (!virt_addr_valid(pg)) { \
- printk(KERN_ERR "kfree: out of range ptr %lxh.\n", \
- (unsigned long)objp); \
- BUG(); \
-@@ -1950,12 +1950,12 @@
- name = cachep->name;
- {
- char tmp;
-- mm_segment_t old_fs;
-+ mm_segment_t old_fs;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- if (__get_user(tmp, name))
- name = "broken";
-- set_fs(old_fs);
-+ set_fs (old_fs);
- }
-
- seq_printf(m, "%-17s %6lu %6lu %6u %4lu %4lu %4u",
---- linux-2.4.27/mm/vmalloc.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/vmalloc.c
-@@ -44,8 +44,13 @@
- if (pte_none(page))
- continue;
- if (pte_present(page)) {
-- struct page *ptpage = pte_page(page);
-- if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))
-+ unsigned long pfn = pte_pfn(page);
-+ struct page *ptpage;
-+
-+ if (!pfn_valid(pfn))
-+ continue;
-+ ptpage = pfn_to_page(pfn);
-+ if (!PageReserved(ptpage))
- __free_page(ptpage);
- continue;
- }
---- linux-2.4.27/mm/vmscan.c~2.4.27-vrs1
-+++ linux-2.4.27/mm/vmscan.c
-@@ -121,6 +121,7 @@
- drop_pte:
- mm->rss--;
- UnlockPage(page);
-+ memc_clear(vma->vm_mm, page);
- {
- int freeable = page_count(page) - !!page->buffers <= 2;
- page_cache_release(page);
-@@ -206,13 +207,16 @@
-
- do {
- if (pte_present(*pte)) {
-- struct page *page = pte_page(*pte);
-+ unsigned long pfn = pte_pfn(*pte);
-
-- if (VALID_PAGE(page) && !PageReserved(page)) {
-- count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
-- if (!count) {
-- address += PAGE_SIZE;
-- break;
-+ if (pfn_valid(pfn)) {
-+ struct page *page = pfn_to_page(pfn);
-+ if (!PageReserved(page)) {
-+ count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
-+ if (!count) {
-+ address += PAGE_SIZE;
-+ break;
-+ }
- }
- }
- }
---- linux-2.4.27/net/irda/af_irda.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/af_irda.c
-@@ -1176,7 +1176,7 @@
- #endif /* CONFIG_IRDA_ULTRA */
- kfree(self);
- MOD_DEC_USE_COUNT;
--
-+
- return;
- }
-
-@@ -2571,19 +2571,15 @@
- sock_register(&irda_family_ops);
-
- irda_packet_type.type = htons(ETH_P_IRDA);
-- dev_add_pack(&irda_packet_type);
-+ dev_add_pack(&irda_packet_type);
-
- register_netdevice_notifier(&irda_dev_notifier);
--
- irda_init();
- #ifdef MODULE
-- irda_device_init(); /* Called by init/main.c when non-modular */
-+ irda_device_init(); /* Called by init/main.c when non-modular */
- #endif
- return 0;
- }
--#ifdef MODULE
--module_init(irda_proto_init); /* If non-module, called from init/main.c */
--#endif
-
- /*
- * Function irda_proto_cleanup (void)
-@@ -2591,25 +2587,27 @@
- * Remove IrDA protocol layer
- *
- */
--#ifdef MODULE
--void irda_proto_cleanup(void)
-+static void __exit irda_proto_cleanup(void)
- {
- irda_packet_type.type = htons(ETH_P_IRDA);
-- dev_remove_pack(&irda_packet_type);
-+ dev_remove_pack(&irda_packet_type);
-+
-+ unregister_netdevice_notifier(&irda_dev_notifier);
-
-- unregister_netdevice_notifier(&irda_dev_notifier);
--
- sock_unregister(PF_IRDA);
-+
- irda_cleanup();
--
-- return;
- }
-+
-+#ifdef MODULE
-+module_init(irda_proto_init);
- module_exit(irda_proto_cleanup);
--
-+
- MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
--MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
-+MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem");
- MODULE_LICENSE("GPL");
- #ifdef CONFIG_IRDA_DEBUG
- MODULE_PARM(irda_debug, "1l");
- #endif
--#endif /* MODULE */
-+#endif
-+
---- linux-2.4.27/net/irda/iriap.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/iriap.c
-@@ -1004,18 +1004,20 @@
-
- switch (attrib->value->type) {
- case IAS_INTEGER:
-- len += sprintf(buf+len, "%d\n",
-+ len += sprintf(buf+len, "%d",
- attrib->value->t.integer);
- break;
- case IAS_STRING:
-- len += sprintf(buf+len, "\"%s\"\n",
-+ len += sprintf(buf+len, "\"%s\"",
- attrib->value->t.string);
- break;
- case IAS_OCT_SEQ:
-- len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
-+ len += sprintf(buf+len,
-+ "octet sequence (%d bytes)",
-+ attrib->value->len);
- break;
- case IAS_MISSING:
-- len += sprintf(buf+len, "missing\n");
-+ len += sprintf(buf+len, "missing");
- break;
- default:
- IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
-@@ -1027,6 +1029,7 @@
- hashbin_get_next(obj->attribs);
- }
- obj = (struct ias_object *) hashbin_get_next(objects);
-+ len += sprintf(buf+len, "\n");
- }
- restore_flags(flags);
-
---- linux-2.4.27/net/irda/irlan/irlan_common.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/irlan/irlan_common.c
-@@ -317,6 +317,9 @@
-
- del_timer(&self->watchdog_timer);
-
-+ /* since irlan_do_*_event gobble the skb, we must get it once -- rmk */
-+ skb_get(skb);
-+
- /* If you want to pass the skb to *both* state machines, you will
- * need to skb_clone() it, so that you don't free it twice.
- * As the state machines don't need it, git rid of it here...
---- linux-2.4.27/net/irda/irlap_event.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/irlap_event.c
-@@ -532,7 +532,7 @@
- #endif /* CONFIG_IRDA_ULTRA */
- case RECV_TEST_CMD:
- /* Remove test frame header */
-- skb_pull(skb, sizeof(struct test_frame));
-+ skb_pull(skb, 10 /*sizeof(struct test_frame)*/);
-
- /*
- * Send response. This skb will not be sent out again, and
-@@ -740,7 +740,7 @@
-
- switch (event) {
- case CONNECT_RESPONSE:
-- skb_pull(skb, sizeof(struct snrm_frame));
-+ skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
-
- ASSERT(self->netdev != NULL, return -1;);
-
-@@ -870,7 +870,7 @@
-
- ASSERT(self->netdev != NULL, return -1;);
-
-- skb_pull(skb, sizeof(struct snrm_frame));
-+ skb_pull(skb, 11 /*sizeof(struct snrm_frame)*/);
-
- irlap_qos_negotiate(self, skb);
-
-@@ -902,7 +902,7 @@
- /* Negotiate connection parameters */
- ASSERT(skb->len > 10, return -1;);
-
-- skb_pull(skb, sizeof(struct ua_frame));
-+ skb_pull(skb, 10 /*sizeof(struct ua_frame)*/);
-
- ASSERT(self->netdev != NULL, return -1;);
-
---- linux-2.4.27/net/irda/irlap_frame.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/irlap_frame.c
-@@ -1,5 +1,5 @@
- /*********************************************************************
-- *
-+ *
- * Filename: irlap_frame.c
- * Version: 1.0
- * Description: Build and transmit IrLAP frames
-@@ -8,18 +8,18 @@
- * Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Wed Jan 5 08:59:04 2000
- * Modified by: Dag Brattli <dagb@cs.uit.no>
-- *
-- * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
-+ *
-+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
- * All Rights Reserved.
- * Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.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
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Neither Dag Brattli nor University of Tromsø admit liability nor
-- * provide warranty for any of this software. This material is
-+ * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-@@ -29,11 +29,12 @@
- #include <linux/if_ether.h>
- #include <linux/netdevice.h>
- #include <linux/irda.h>
--
-+
- #include <net/pkt_sched.h>
- #include <net/sock.h>
--
-+
- #include <asm/byteorder.h>
-+#include <asm/unaligned.h>
-
- #include <net/irda/irda.h>
- #include <net/irda/irda_device.h>
-@@ -46,18 +47,18 @@
- /*
- * Function irlap_insert_info (self, skb)
- *
-- * Insert minimum turnaround time and speed information into the skb. We
-+ * Insert minimum turnaround time and speed information into the skb. We
- * need to do this since it's per packet relevant information. Safe to
- * have this function inlined since it's only called from one place
- */
--static inline void irlap_insert_info(struct irlap_cb *self,
-+static inline void irlap_insert_info(struct irlap_cb *self,
- struct sk_buff *skb)
- {
- struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
-
-- /*
-+ /*
- * Insert MTT (min. turn time) and speed into skb, so that the
-- * device driver knows which settings to use
-+ * device driver knows which settings to use
- */
- cb->magic = LAP_MAGIC;
- cb->mtt = self->mtt_required;
-@@ -65,15 +66,15 @@
-
- /* Reset */
- self->mtt_required = 0;
--
-- /*
-- * Delay equals negotiated BOFs count, plus the number of BOFs to
-- * force the negotiated minimum turnaround time
-+
-+ /*
-+ * Delay equals negotiated BOFs count, plus the number of BOFs to
-+ * force the negotiated minimum turnaround time
- */
- cb->xbofs = self->bofs_count;
- cb->next_xbofs = self->next_bofs;
- cb->xbofs_delay = self->xbofs_delay;
--
-+
- /* Reset XBOF's delay (used only for getting min turn time) */
- self->xbofs_delay = 0;
- /* Put the correct xbofs value for the next packet */
-@@ -104,7 +105,7 @@
- *
- * Transmits a connect SNRM command frame
- */
--void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
-+void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
- {
- struct sk_buff *skb;
- struct snrm_frame *frame;
-@@ -118,7 +119,7 @@
- if (!skb)
- return;
-
-- frame = (struct snrm_frame *) skb_put(skb, 2);
-+ frame = (struct snrm_frame *) skb_put(skb, 2);
-
- /* Insert connection address field */
- if (qos)
-@@ -128,17 +129,17 @@
-
- /* Insert control field */
- frame->control = SNRM_CMD | PF_BIT;
--
-+
- /*
-- * If we are establishing a connection then insert QoS paramerters
-+ * If we are establishing a connection then insert QoS paramerters
- */
- if (qos) {
- skb_put(skb, 9); /* 21 left */
-- frame->saddr = cpu_to_le32(self->saddr);
-- frame->daddr = cpu_to_le32(self->daddr);
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
-
- frame->ncaddr = self->caddr;
--
-+
- ret = irlap_insert_qos_negotiation_params(self, skb);
- if (ret < 0) {
- dev_kfree_skb(skb);
-@@ -154,13 +155,13 @@
- * Received SNRM (Set Normal Response Mode) command frame
- *
- */
--static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct snrm_frame *frame;
-
- frame = (struct snrm_frame *) skb->data;
--
-+
- if (skb->len >= sizeof(struct snrm_frame)) {
- /* Copy the new connection address ignoring the C/R bit */
- info->caddr = frame->ncaddr & 0xFE;
-@@ -170,11 +171,11 @@
- IRDA_DEBUG(3, "%s(), invalid connection address!\n", __FUNCTION__);
- return;
- }
--
-+
- /* Copy peer device address */
-- info->daddr = le32_to_cpu(frame->saddr);
-- info->saddr = le32_to_cpu(frame->daddr);
--
-+ info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
-+
- /* Only accept if addressed directly to us */
- if (info->saddr != self->saddr) {
- IRDA_DEBUG(2, "%s(), not addressed to us!\n", __FUNCTION__);
-@@ -198,9 +199,9 @@
- struct sk_buff *skb;
- struct ua_frame *frame;
- int ret;
--
-+
- IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
-
-@@ -212,13 +213,13 @@
- return;
-
- frame = (struct ua_frame *) skb_put(skb, 10);
--
-+
- /* Build UA response */
- frame->caddr = self->caddr;
- frame->control = UA_RSP | PF_BIT;
-
-- frame->saddr = cpu_to_le32(self->saddr);
-- frame->daddr = cpu_to_le32(self->daddr);
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(self->daddr), &frame->daddr);
-
- /* Should we send QoS negotiation parameters? */
- if (qos) {
-@@ -243,7 +244,7 @@
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
-
-@@ -252,7 +253,7 @@
- return;
-
- frame = skb_put( skb, 2);
--
-+
- if (self->state == LAP_NDM)
- frame[0] = CBROADCAST;
- else
-@@ -260,7 +261,7 @@
-
- frame[1] = DM_RSP | PF_BIT;
-
-- irlap_queue_xmit(self, skb);
-+ irlap_queue_xmit(self, skb);
- }
-
- /*
-@@ -269,11 +270,11 @@
- * Send disconnect (DISC) frame
- *
- */
--void irlap_send_disc_frame(struct irlap_cb *self)
-+void irlap_send_disc_frame(struct irlap_cb *self)
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
-
- ASSERT(self != NULL, return;);
-@@ -284,7 +285,7 @@
- return;
-
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr | CMD_FRAME;
- frame[1] = DISC_CMD | PF_BIT;
-
-@@ -295,17 +296,17 @@
- * Function irlap_send_discovery_xid_frame (S, s, command)
- *
- * Build and transmit a XID (eXchange station IDentifier) discovery
-- * frame.
-+ * frame.
- */
--void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
-- __u8 command, discovery_t *discovery)
-+void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
-+ __u8 command, discovery_t *discovery)
- {
- struct sk_buff *skb = NULL;
- struct xid_frame *frame;
-- __u32 bcast = BROADCAST;
-+ __u32 bcast = BROADCAST, daddr;
- __u8 *info;
-
-- IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
-+ IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__, s, S,
- command);
-
- ASSERT(self != NULL, return;);
-@@ -328,13 +329,14 @@
- }
- frame->ident = XID_FORMAT;
-
-- frame->saddr = cpu_to_le32(self->saddr);
--
- if (command)
-- frame->daddr = cpu_to_le32(bcast);
-+ daddr = bcast;
- else
-- frame->daddr = cpu_to_le32(discovery->daddr);
--
-+ daddr = discovery->daddr;
-+
-+ put_unaligned(cpu_to_le32(self->saddr), &frame->saddr);
-+ put_unaligned(cpu_to_le32(daddr), &frame->daddr);
-+
- switch (S) {
- case 1:
- frame->flags = 0x00;
-@@ -353,10 +355,10 @@
- break;
- }
-
-- frame->slotnr = s;
-+ frame->slotnr = s;
- frame->version = 0x00;
-
-- /*
-+ /*
- * Provide info for final slot only in commands, and for all
- * responses. Send the second byte of the hint only if the
- * EXTENSION bit is set in the first byte.
-@@ -365,7 +367,7 @@
- int len;
-
- if (discovery->hints.byte[0] & HINT_EXTENSION) {
-- info = skb_put(skb, 2);
-+ info = skb_put(skb, 2);
- info[0] = discovery->hints.byte[0];
- info[1] = discovery->hints.byte[1];
- } else {
-@@ -378,7 +380,7 @@
- len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
- info = skb_put(skb, len);
- memcpy(info, discovery->nickname, len);
-- }
-+ }
- irlap_queue_xmit(self, skb);
- }
-
-@@ -388,9 +390,9 @@
- * Received a XID discovery response
- *
- */
--static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct xid_frame *xid;
- discovery_t *discovery = NULL;
-@@ -404,8 +406,8 @@
-
- xid = (struct xid_frame *) skb->data;
-
-- info->daddr = le32_to_cpu(xid->saddr);
-- info->saddr = le32_to_cpu(xid->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
-
- /* Make sure frame is addressed to us */
- if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-@@ -439,11 +441,11 @@
- discovery->charset = discovery_info[1];
- text = (char *) &discovery_info[2];
- }
-- /*
-- * Terminate info string, should be safe since this is where the
-+ /*
-+ * Terminate info string, should be safe since this is where the
- * FCS bytes resides.
- */
-- skb->data[skb->len] = '\0';
-+ skb->data[skb->len] = '\0';
- strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
- discovery->name_len = strlen(discovery->nickname);
-
-@@ -458,9 +460,9 @@
- * Received a XID discovery command
- *
- */
--static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- struct xid_frame *xid;
- discovery_t *discovery = NULL;
-@@ -469,8 +471,8 @@
-
- xid = (struct xid_frame *) skb->data;
-
-- info->daddr = le32_to_cpu(xid->saddr);
-- info->saddr = le32_to_cpu(xid->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&xid->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&xid->daddr));
-
- /* Make sure frame is addressed to us */
- if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-@@ -497,11 +499,11 @@
- return;
- }
- info->s = xid->slotnr;
--
-+
- discovery_info = skb_pull(skb, sizeof(struct xid_frame));
-
-- /*
-- * Check if last frame
-+ /*
-+ * Check if last frame
- */
- if (info->s == 0xff) {
- /* Check if things are sane at this point... */
-@@ -518,7 +520,7 @@
- WARNING("%s(), unable to malloc!\n", __FUNCTION__);
- return;
- }
--
-+
- discovery->daddr = info->daddr;
- discovery->saddr = self->saddr;
- discovery->timestamp = jiffies;
-@@ -533,11 +535,11 @@
- discovery->charset = discovery_info[1];
- text = (char *) &discovery_info[2];
- }
-- /*
-- * Terminate string, should be safe since this is where the
-+ /*
-+ * Terminate string, should be safe since this is where the
- * FCS bytes resides.
- */
-- skb->data[skb->len] = '\0';
-+ skb->data[skb->len] = '\0';
- strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
- discovery->name_len = strlen(discovery->nickname);
-
-@@ -554,7 +556,7 @@
- * Build and transmit RR (Receive Ready) frame. Notice that it is currently
- * only possible to send RR frames with the poll bit set.
- */
--void irlap_send_rr_frame(struct irlap_cb *self, int command)
-+void irlap_send_rr_frame(struct irlap_cb *self, int command)
- {
- struct sk_buff *skb;
- __u8 *frame;
-@@ -562,9 +564,9 @@
- skb = dev_alloc_skb(16);
- if (!skb)
- return;
--
-+
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[0] |= (command) ? CMD_FRAME : 0;
-
-@@ -576,7 +578,7 @@
- /*
- * Function irlap_send_rd_frame (self)
- *
-- * Request disconnect. Used by a secondary station to request the
-+ * Request disconnect. Used by a secondary station to request the
- * disconnection of the link.
- */
- void irlap_send_rd_frame(struct irlap_cb *self)
-@@ -587,9 +589,9 @@
- skb = dev_alloc_skb(16);
- if (!skb)
- return;
--
-+
- frame = skb_put(skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[1] = RD_RSP | PF_BIT;
-
-@@ -603,8 +605,8 @@
- * making it inline since its called only from one single place
- * (irlap_driver_rcv).
- */
--static inline void irlap_recv_rr_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-+static inline void irlap_recv_rr_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5;
-@@ -620,7 +622,7 @@
- {
- struct sk_buff *skb = NULL;
- __u8 *frame;
--
-+
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-
-@@ -629,7 +631,7 @@
- return;
-
- frame = skb_put( skb, 2);
--
-+
- frame[0] = self->caddr;
- frame[0] |= (command) ? CMD_FRAME : 0;
-
-@@ -639,7 +641,7 @@
-
- frame[2] = 0;
-
-- IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
-+ IRDA_DEBUG(4, "%s(), vr=%d, %ld\n", __FUNCTION__, self->vr, jiffies);
-
- irlap_queue_xmit(self, skb);
- }
-@@ -650,8 +652,8 @@
- * Received RNR (Receive Not Ready) frame from peer station
- *
- */
--static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info, int command)
-+static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5;
-
-@@ -663,13 +665,13 @@
- irlap_do_event(self, RECV_RNR_RSP, skb, info);
- }
-
--static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
-
- info->nr = skb->data[1] >> 5;
--
-+
- /* Check if this is a command or a response frame */
- if (command)
- irlap_do_event(self, RECV_REJ_CMD, skb, info);
-@@ -677,13 +679,13 @@
- irlap_do_event(self, RECV_REJ_RSP, skb, info);
- }
-
--static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
-
- info->nr = skb->data[1] >> 5;
--
-+
- /* Check if this is a command or a response frame */
- if (command)
- irlap_do_event(self, RECV_SREJ_CMD, skb, info);
-@@ -691,7 +693,7 @@
- irlap_do_event(self, RECV_SREJ_RSP, skb, info);
- }
-
--static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
-@@ -709,9 +711,9 @@
- * Received UA (Unnumbered Acknowledgement) frame
- *
- */
--static inline void irlap_recv_ua_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info)
-+static inline void irlap_recv_ua_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- irlap_do_event(self, RECV_UA_RSP, skb, info);
- }
-@@ -728,25 +730,25 @@
-
- if (skb->data[1] == I_FRAME) {
-
-- /*
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- /* Copy buffer */
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
- }
--
-- /*
-- * Insert frame in store, in case of retransmissions
-+
-+ /*
-+ * Insert frame in store, in case of retransmissions
- */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- self->vs = (self->vs + 1) % 8;
-- self->ack_required = FALSE;
-+ self->ack_required = FALSE;
- self->window -= 1;
-
- irlap_send_i_frame( self, tx_skb, CMD_FRAME);
-@@ -761,40 +763,40 @@
- *
- * Send I(nformation) frame as primary with poll bit set
- */
--void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
-+void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
- {
- struct sk_buff *tx_skb;
-
- /* Stop P timer */
- del_timer(&self->poll_timer);
--
-+
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
--
-- /*
-+
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- /* Copy buffer */
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
- }
--
-- /*
-- * Insert frame in store, in case of retransmissions
-+
-+ /*
-+ * Insert frame in store, in case of retransmissions
- */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-- /*
-+
-+ /*
- * Set poll bit if necessary. We do this to the copied
- * skb, since retransmitted need to set or clear the poll
-- * bit depending on when they are sent.
-+ * bit depending on when they are sent.
- */
- tx_skb->data[1] |= PF_BIT;
--
-+
- self->vs = (self->vs + 1) % 8;
- self->ack_required = FALSE;
-
-@@ -827,8 +829,8 @@
- * Send I(nformation) frame as secondary with final bit set
- *
- */
--void irlap_send_data_secondary_final(struct irlap_cb *self,
-- struct sk_buff *skb)
-+void irlap_send_data_secondary_final(struct irlap_cb *self,
-+ struct sk_buff *skb)
- {
- struct sk_buff *tx_skb = NULL;
-
-@@ -839,26 +841,26 @@
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
-
-- /*
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
-- }
-+ }
-
- /* Insert frame in store */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- tx_skb->data[1] |= PF_BIT;
--
-- self->vs = (self->vs + 1) % 8;
-+
-+ self->vs = (self->vs + 1) % 8;
- self->ack_required = FALSE;
--
-- irlap_send_i_frame(self, tx_skb, RSP_FRAME);
-+
-+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
- } else {
- if (self->ack_required) {
- irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
-@@ -885,32 +887,32 @@
- * Send I(nformation) frame as secondary without final bit set
- *
- */
--void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
-+void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
- {
- struct sk_buff *tx_skb = NULL;
-
- /* Is this reliable or unreliable data? */
- if (skb->data[1] == I_FRAME) {
--
-- /*
-+
-+ /*
- * Insert frame sequence number (Vs) in control field before
- * inserting into transmit window queue.
- */
- skb->data[1] = I_FRAME | (self->vs << 1);
--
-+
- tx_skb = skb_clone(skb, GFP_ATOMIC);
- if (tx_skb == NULL) {
- return;
-- }
--
-+ }
-+
- /* Insert frame in store */
- skb_queue_tail(&self->wx_list, skb_get(skb));
--
-+
- self->vs = (self->vs + 1) % 8;
-- self->ack_required = FALSE;
-+ self->ack_required = FALSE;
- self->window -= 1;
-
-- irlap_send_i_frame(self, tx_skb, RSP_FRAME);
-+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
- } else {
- irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);
- self->window -= 1;
-@@ -920,8 +922,8 @@
- /*
- * Function irlap_resend_rejected_frames (nr)
- *
-- * Resend frames which has not been acknowledged. Should be safe to
-- * traverse the list without locking it since this function will only be
-+ * Resend frames which has not been acknowledged. Should be safe to
-+ * traverse the list without locking it since this function will only be
- * called from interrupt context (BH)
- */
- void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
-@@ -943,8 +945,8 @@
- while (skb != NULL) {
- irlap_wait_min_turn_around(self, &self->qos_tx);
-
-- /* We copy the skb to be retransmitted since we will have to
-- * modify it. Cloning will confuse packet sniffers
-+ /* We copy the skb to be retransmitted since we will have to
-+ * modify it. Cloning will confuse packet sniffers
- */
- /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
- tx_skb = skb_copy(skb, GFP_ATOMIC);
-@@ -959,17 +961,17 @@
- /* Clear old Nr field + poll bit */
- tx_skb->data[1] &= 0x0f;
-
-- /*
-+ /*
- * Set poll bit on the last frame retransmitted
- */
- if (count-- == 1)
- tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
- else
- tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
--
-+
- irlap_send_i_frame(self, tx_skb, command);
-
-- /*
-+ /*
- * If our skb is the last buffer in the list, then
- * we are finished, if not, move to the next sk-buffer
- */
-@@ -979,23 +981,23 @@
- skb = skb->next;
- }
- #if 0 /* Not yet */
-- /*
-+ /*
- * We can now fill the window with additinal data frames
- */
- while (skb_queue_len( &self->txq) > 0) {
--
-+
- IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
-- if ((skb_queue_len( &self->txq) > 0) &&
-+ if ((skb_queue_len( &self->txq) > 0) &&
- (self->window > 0)) {
-- skb = skb_dequeue( &self->txq);
-+ skb = skb_dequeue( &self->txq);
- ASSERT(skb != NULL, return;);
-
- /*
-- * If send window > 1 then send frame with pf
-+ * If send window > 1 then send frame with pf
- * bit cleared
-- */
-- if ((self->window > 1) &&
-- skb_queue_len(&self->txq) > 0)
-+ */
-+ if ((self->window > 1) &&
-+ skb_queue_len(&self->txq) > 0)
- {
- irlap_send_data_primary(self, skb);
- } else {
-@@ -1023,14 +1025,14 @@
- if (skb != NULL) {
- irlap_wait_min_turn_around(self, &self->qos_tx);
-
-- /* We copy the skb to be retransmitted since we will have to
-- * modify it. Cloning will confuse packet sniffers
-+ /* We copy the skb to be retransmitted since we will have to
-+ * modify it. Cloning will confuse packet sniffers
- */
- /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
- tx_skb = skb_copy(skb, GFP_ATOMIC);
- if (!tx_skb) {
- IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
-- return;
-+ return;
- }
- /* Unlink tx_skb from list */
- tx_skb->next = tx_skb->prev = NULL;
-@@ -1041,7 +1043,7 @@
-
- /* Set poll/final bit */
- tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
--
-+
- irlap_send_i_frame(self, tx_skb, command);
- }
- }
-@@ -1052,15 +1054,15 @@
- * Contruct and transmit an Unnumbered Information (UI) frame
- *
- */
--void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
-+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
- __u8 caddr, int command)
- {
- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
--
-+
- /* Insert connection address */
- skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
-
-@@ -1072,13 +1074,13 @@
- *
- * Contruct and transmit Information (I) frame
- */
--void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
-- int command)
-+void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ int command)
- {
- /* Insert connection address */
- skb->data[0] = self->caddr;
- skb->data[0] |= (command) ? CMD_FRAME : 0;
--
-+
- /* Insert next to receive (Vr) */
- skb->data[1] |= (self->vr << 5); /* insert nr */
-
-@@ -1091,9 +1093,9 @@
- * Receive and parse an I (Information) frame, no harm in making it inline
- * since it's called only from one single place (irlap_driver_rcv).
- */
--static inline void irlap_recv_i_frame(struct irlap_cb *self,
-- struct sk_buff *skb,
-- struct irlap_info *info, int command)
-+static inline void irlap_recv_i_frame(struct irlap_cb *self,
-+ struct sk_buff *skb,
-+ struct irlap_info *info, int command)
- {
- info->nr = skb->data[1] >> 5; /* Next to receive */
- info->pf = skb->data[1] & PF_BIT; /* Final bit */
-@@ -1112,7 +1114,7 @@
- * Receive and parse an Unnumbered Information (UI) frame
- *
- */
--static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info)
- {
- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
-@@ -1128,19 +1130,19 @@
- * Received Frame Reject response.
- *
- */
--static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
-- struct irlap_info *info)
-+static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
-+ struct irlap_info *info)
- {
- __u8 *frame;
- int w, x, y, z;
-
- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
--
-+
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
--
-+
- frame = skb->data;
-
- info->nr = frame[2] >> 5; /* Next to receive */
-@@ -1151,11 +1153,11 @@
- x = frame[3] & 0x02;
- y = frame[3] & 0x04;
- z = frame[3] & 0x08;
--
-+
- if (w) {
- IRDA_DEBUG(0, "Rejected control field is undefined or not "
- "implemented.\n");
-- }
-+ }
- if (x) {
- IRDA_DEBUG(0, "Rejected control field was invalid because it "
- "contained a non permitted I field.\n");
-@@ -1178,7 +1180,7 @@
- * Send a test frame response
- *
- */
--void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
-+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
- struct sk_buff *cmd)
- {
- struct sk_buff *skb;
-@@ -1191,7 +1193,7 @@
-
- /* Broadcast frames must include saddr and daddr fields */
- if (caddr == CBROADCAST) {
-- frame = (struct test_frame *)
-+ frame = (struct test_frame *)
- skb_put(skb, sizeof(struct test_frame));
-
- /* Insert the swapped addresses */
-@@ -1218,28 +1220,28 @@
- * Receive a test frame
- *
- */
--static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
-+static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info, int command)
- {
- struct test_frame *frame;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
--
-+
- frame = (struct test_frame *) skb->data;
--
-+
- /* Broadcast frames must carry saddr and daddr fields */
- if (info->caddr == CBROADCAST) {
- if (skb->len < sizeof(struct test_frame)) {
- IRDA_DEBUG(0, "%s() test frame to short!\n", __FUNCTION__);
- return;
- }
--
-+
- /* Read and swap addresses */
-- info->daddr = le32_to_cpu(frame->saddr);
-- info->saddr = le32_to_cpu(frame->daddr);
-+ info->daddr = le32_to_cpu(get_unaligned(&frame->saddr));
-+ info->saddr = le32_to_cpu(get_unaligned(&frame->daddr));
-
- /* Make sure frame is addressed to us */
-- if ((info->saddr != self->saddr) &&
-+ if ((info->saddr != self->saddr) &&
- (info->saddr != BROADCAST)) {
- return;
- }
-@@ -1254,18 +1256,18 @@
- /*
- * Function irlap_driver_rcv (skb, netdev, ptype)
- *
-- * Called when a frame is received. Dispatches the right receive function
-+ * Called when a frame is received. Dispatches the right receive function
- * for processing of the frame.
- *
- */
--int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
-+int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype)
- {
- struct irlap_info info;
- struct irlap_cb *self;
- int command;
- __u8 control;
--
-+
- /* FIXME: should we get our own field? */
- self = (struct irlap_cb *) dev->atalk_ptr;
-
-@@ -1281,10 +1283,10 @@
- dev_kfree_skb(skb);
- return -1;
- }
--
-+
- command = skb->data[0] & CMD_FRAME;
- info.caddr = skb->data[0] & CBROADCAST;
--
-+
- info.pf = skb->data[1] & PF_BIT;
- info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
-
-@@ -1295,7 +1297,7 @@
- IRDA_DEBUG(0, "%s(), wrong connection address!\n", __FUNCTION__);
- goto out;
- }
-- /*
-+ /*
- * Optimize for the common case and check if the frame is an
- * I(nformation) frame. Only I-frames have bit 0 set to 0
- */
-@@ -1304,11 +1306,11 @@
- goto out;
- }
- /*
-- * We now check is the frame is an S(upervisory) frame. Only
-+ * We now check is the frame is an S(upervisory) frame. Only
- * S-frames have bit 0 set to 1 and bit 1 set to 0
- */
- if (~control & 0x02) {
-- /*
-+ /*
- * Received S(upervisory) frame, check which frame type it is
- * only the first nibble is of interest
- */
-@@ -1332,8 +1334,8 @@
- }
- goto out;
- }
-- /*
-- * This must be a C(ontrol) frame
-+ /*
-+ * This must be a C(ontrol) frame
- */
- switch (control) {
- case XID_RSP:
-@@ -1369,6 +1371,6 @@
- break;
- }
- out:
-- dev_kfree_skb(skb);
-+ dev_kfree_skb(skb);
- return 0;
- }
---- linux-2.4.27/net/irda/irttp.c~2.4.27-vrs1
-+++ linux-2.4.27/net/irda/irttp.c
-@@ -1665,8 +1665,8 @@
- }
- self->rx_sdu_size = 0;
- }
--
-- /*
-+
-+ /*
- * It's not trivial to keep track of how many credits are available
- * by incrementing at each packet, because delivery may fail
- * (irttp_do_data_indication() may requeue the frame) and because
-@@ -1676,7 +1676,7 @@
- * to send remote_credit.
- * No need to spinlock, write is atomic and self correcting...
- * Jean II
-- */
-+ */
- self->avail_credit = (self->initial_credit -
- (self->remote_credit +
- skb_queue_len(&self->rx_queue) +
---- linux-2.4.27/net/sched/Config.in~2.4.27-vrs1
-+++ linux-2.4.27/net/sched/Config.in
-@@ -3,9 +3,9 @@
- #
- tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ
- tristate ' HTB packet scheduler' CONFIG_NET_SCH_HTB
--tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ
-+dep_tristate ' CSZ packet scheduler (experimental)' CONFIG_NET_SCH_CSZ $CONFIG_EXPERIMENTAL
- #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ
--tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFSC
-+tristate ' H-FSC packet scheduler' CONFIG_NET_SCH_HFCS
- if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
- dep_tristate ' ATM pseudo-scheduler' CONFIG_NET_SCH_ATM $CONFIG_ATM
- fi
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/defconfig-simpad b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/defconfig-simpad
deleted file mode 100644
index ed09ffbf0a..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/defconfig-simpad
+++ /dev/null
@@ -1,1302 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_ANAKIN is not set
-# CONFIG_ARCH_ARCA5K is not set
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_OMAHA is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_MX1ADS is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_RISCSTATION is not set
-CONFIG_ARCH_SA1100=y
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_AT91RM9200 is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
-
-#
-# SA11x0 Implementations
-#
-# CONFIG_SA1100_ACCELENT is not set
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSAGC is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_ADSBITSYPLUS is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CEP is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_H3600_SLEEVE is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_FRODO is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_BADGE4 is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-CONFIG_SA1100_SIMPAD=y
-# CONFIG_SA1100_SIMPUTER is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_HOTPLUG=y
-CONFIG_SA1100_USB_NETLINK=m
-CONFIG_SA1100_USB_CHAR=m
-# CONFIG_SA1100_SSP is not set
-
-#
-# AT91RM9200 Implementations
-#
-# CONFIG_ARCH_AT91RM9200DK is not set
-# CONFIG_MACH_CSB337 is not set
-
-#
-# Intel PXA250/210 Implementations
-#
-# CONFIG_ARCH_LUBBOCK is not set
-# CONFIG_ARCH_PXA_IDP is not set
-# CONFIG_ARCH_PXA_CERF is not set
-# CONFIG_ARCH_TRIZEPS2 is not set
-# CONFIG_PXA_USB is not set
-# CONFIG_PXA_USB_NETLINK is not set
-# CONFIG_PXA_USB_CHAR is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_GUIDEA07 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_PLD is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_ARM1020E is not set
-# CONFIG_CPU_ARM1022 is not set
-# CONFIG_CPU_ARM1026 is not set
-# CONFIG_CPU_SA110 is not set
-CONFIG_CPU_SA1100=y
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-
-#
-# Processor Features
-#
-CONFIG_DISCONTIGMEM=y
-
-#
-# General setup
-#
-# CONFIG_PCI is not set
-CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CPU_FREQ=y
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/CardBus support
-#
-CONFIG_PCMCIA=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_CLPS6700 is not set
-CONFIG_PCMCIA_SA1100=y
-# CONFIG_PCMCIA_PXA is not set
-
-#
-# MMC device drivers
-#
-# CONFIG_MMC is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-
-#
-# At least one math emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_PM=y
-CONFIG_APM=y
-CONFIG_SIMPAD_PM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mtdparts=sa1100:512k(boot),1m(kernel),14848k(root),-(home) console=ttySA root=1f02 noinitrd jffs2_orphaned_inodes=delete rootfstype=jffs2 mem=32M"
-CONFIG_LEDS=y
-# CONFIG_LEDS_TIMER is not set
-# CONFIG_LEDS_CPU is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CONCAT=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-CONFIG_MTD_CFI_B2=y
-# CONFIG_MTD_CFI_B4 is not set
-# CONFIG_MTD_CFI_B8 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_NORA is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
-CONFIG_MTD_SA1100=y
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-# CONFIG_MTD_FORTUNET is not set
-# CONFIG_MTD_EPXA is not set
-# CONFIG_MTD_AUTCPU12 is not set
-# CONFIG_MTD_EDB7312 is not set
-# CONFIG_MTD_IMPA7 is not set
-# CONFIG_MTD_CEIVA is not set
-# CONFIG_MTD_PCI is not set
-# CONFIG_MTD_PCMCIA is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_MMC=m
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_CISS_MONITOR_THREAD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_STATS is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-# CONFIG_NET_IPGRE_BROADCAST is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_ARPD=y
-CONFIG_INET_ECN=y
-CONFIG_SYN_COOKIES=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_SUBTREES=y
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_MOBILITY=m
-CONFIG_IPV6_MOBILITY_MN=m
-CONFIG_IPV6_MOBILITY_HA=m
-CONFIG_IPV6_MOBILITY_DEBUG=y
-
-#
-# IPv6: Netfilter Configuration
-#
-# CONFIG_IP6_NF_QUEUE is not set
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-# CONFIG_KHTTPD is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=m
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-CONFIG_VLAN_8021Q=m
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_IPSEC=y
-
-#
-# IPSec options (Openswan)
-#
-CONFIG_IPSEC_IPIP=y
-CONFIG_IPSEC_AH=y
-CONFIG_IPSEC_AUTH_HMAC_MD5=y
-CONFIG_IPSEC_AUTH_HMAC_SHA1=y
-CONFIG_IPSEC_ESP=y
-CONFIG_IPSEC_ENC_3DES=y
-CONFIG_IPSEC_ENC_AES=y
-CONFIG_IPSEC_ALG=y
-CONFIG_IPSEC_ALG_AES=y
-# CONFIG_IPSEC_ALG_CRYPTOAPI is not set
-CONFIG_IPSEC_IPCOMP=y
-CONFIG_IPSEC_DEBUG=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
-# CONFIG_ARM_CIRRUS is not set
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_B44 is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_TULIP is not set
-# CONFIG_DM9102 is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_SUNDANCE_MMIO is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
-# CONFIG_WINBOND_840 is not set
-CONFIG_NET_POCKET=y
-# CONFIG_DE600 is not set
-# CONFIG_DE620 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_STRIP is not set
-# CONFIG_WAVELAN is not set
-# CONFIG_ARLAN is not set
-# CONFIG_AIRONET4500 is not set
-# CONFIG_AIRONET4500_NONCS is not set
-# CONFIG_AIRONET4500_PROC is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-
-#
-# Wireless Pcmcia cards support
-#
-# CONFIG_PCMCIA_HERMES is not set
-# CONFIG_AIRO_CS is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network device support
-#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_AXNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_NET_PCMCIA_RADIO=y
-# CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_AIRONET4500_CS is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-CONFIG_IRPORT_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-# CONFIG_NSC_FIR is not set
-# CONFIG_WINBOND_FIR is not set
-# CONFIG_TOSHIBA_OLD is not set
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-# CONFIG_ALI_FIR is not set
-# CONFIG_VLSI_FIR is not set
-# CONFIG_VIA_IRCC_FIR is not set
-CONFIG_SA1100_FIR=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
-# CONFIG_BLK_DEV_ATARAID_SII is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input core support
-#
-CONFIG_INPUT=y
-CONFIG_INPUT_KEYBDEV=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-CONFIG_INPUT_EVDEV=m
-CONFIG_INPUT_UINPUT=y
-# CONFIG_INPUT_MX1TS is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_ANAKIN is not set
-# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-# CONFIG_SERIAL_OMAHA is not set
-# CONFIG_SERIAL_OMAHA_CONSOLE is not set
-# CONFIG_SERIAL_AT91 is not set
-# CONFIG_SERIAL_AT91_CONSOLE is not set
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-
-#
-# Other L3 adapters
-#
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_NS558 is not set
-# CONFIG_INPUT_LIGHTNING is not set
-# CONFIG_INPUT_PCIGAME is not set
-# CONFIG_INPUT_CS461X is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_INPUT_SERIO is not set
-# CONFIG_INPUT_SERPORT is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_ANALOG is not set
-# CONFIG_INPUT_A3D is not set
-# CONFIG_INPUT_ADI is not set
-# CONFIG_INPUT_COBRA is not set
-# CONFIG_INPUT_GF2K is not set
-# CONFIG_INPUT_GRIP is not set
-# CONFIG_INPUT_INTERACT is not set
-# CONFIG_INPUT_TMDC is not set
-# CONFIG_INPUT_SIDEWINDER is not set
-# CONFIG_INPUT_IFORCE_USB is not set
-# CONFIG_INPUT_IFORCE_232 is not set
-# CONFIG_INPUT_WARRIOR is not set
-# CONFIG_INPUT_MAGELLAN is not set
-# CONFIG_INPUT_SPACEORB is not set
-# CONFIG_INPUT_SPACEBALL is not set
-# CONFIG_INPUT_STINGER is not set
-# CONFIG_INPUT_DB9 is not set
-# CONFIG_INPUT_GAMECON is not set
-# CONFIG_INPUT_TURBOGRAFX is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_IPMI_PANIC_EVENT is not set
-# CONFIG_IPMI_DEVICE_INTERFACE is not set
-# CONFIG_IPMI_KCS is not set
-# CONFIG_IPMI_WATCHDOG is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_SCx200 is not set
-# CONFIG_SCx200_GPIO is not set
-# CONFIG_AMD_PM768 is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_SA1100_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-
-#
-# Direct Rendering Manager (XFree86 DRI support)
-#
-# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-CONFIG_PCMCIA_SERIAL_CS=m
-# CONFIG_SYNCLINK_CS is not set
-CONFIG_TDA8007=m
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BEFS_DEBUG is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=m
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_UMSDOS_FS=m
-CONFIG_VFAT_FS=y
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_CRAMFS=m
-# CONFIG_CRAMFS_LINEAR is not set
-# CONFIG_CRAMFS_LINEAR_XIP is not set
-# CONFIG_ROOT_CRAMFS_LINEAR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_TRACE is not set
-# CONFIG_XFS_DEBUG is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_SMB_UNIX=y
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=y
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=y
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_ANAKIN is not set
-# CONFIG_FB_CLPS711X is not set
-# CONFIG_FB_SA1100 is not set
-# CONFIG_FB_DBMX1 is not set
-# CONFIG_FB_PXA is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_MQ200=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-# CONFIG_FBCON_CFB24 is not set
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-CONFIG_SOUND_SA1100=y
-# CONFIG_SOUND_UDA1341 is not set
-# CONFIG_SOUND_ASSABET_UDA1341 is not set
-# CONFIG_SOUND_H3600_UDA1341 is not set
-# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-# CONFIG_SOUND_SA1111_UDA1341 is not set
-# CONFIG_SOUND_SA1111_AC97 is not set
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_VIDC is not set
-# CONFIG_SOUND_WAVEARTIST is not set
-# CONFIG_SOUND_PXA_AC97 is not set
-# CONFIG_SOUND_TVMIXER is not set
-# CONFIG_SOUND_AD1980 is not set
-# CONFIG_SOUND_WM97XX is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-CONFIG_MCP_UCB1200=y
-CONFIG_MCP_UCB1200_AUDIO=y
-CONFIG_MCP_UCB1200_TS=y
-# CONFIG_MCP_UCB1400_TS is not set
-
-#
-# Console Switches
-#
-CONFIG_SWITCHES=y
-CONFIG_SWITCHES_SA1100=y
-CONFIG_SWITCHES_UCB1X00=y
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Support for USB gadgets
-#
-# CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_N9604 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_SUPERH is not set
-# CONFIG_USB_GADGET_GOKU is not set
-CONFIG_USB_GADGET_SA1100=y
-# CONFIG_USB_GADGET_CONTROLLER is not set
-# CONFIG_USB_PXA2XX is not set
-# CONFIG_USB_GADGET_CONTROLLER is not set
-# CONFIG_USB_GADGET_DUALSPEED is not set
-
-#
-# USB Gadget Drivers
-#
-CONFIG_USB_ZERO=m
-CONFIG_USB_ETH=m
-# CONFIG_USB_ETH_RNDIS is not set
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-# CONFIG_USB_FILE_STORAGE_TEST is not set
-CONFIG_USB_G_SERIAL=m
-
-#
-# Bluetooth support
-#
-CONFIG_BLUEZ=m
-CONFIG_BLUEZ_L2CAP=m
-CONFIG_BLUEZ_SCO=m
-CONFIG_BLUEZ_RFCOMM=m
-CONFIG_BLUEZ_RFCOMM_TTY=y
-CONFIG_BLUEZ_BNEP=m
-CONFIG_BLUEZ_BNEP_MC_FILTER=y
-CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
-CONFIG_BLUEZ_HIDP=m
-
-#
-# Bluetooth device drivers
-#
-# CONFIG_BLUEZ_HCIUSB is not set
-CONFIG_BLUEZ_HCIUART=m
-CONFIG_BLUEZ_HCIUART_H4=y
-CONFIG_BLUEZ_HCIUART_BCSP=y
-CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y
-# CONFIG_BLUEZ_HCIBFUSB is not set
-CONFIG_BLUEZ_HCIDTL1=m
-CONFIG_BLUEZ_HCIBT3C=m
-CONFIG_BLUEZ_HCIBLUECARD=m
-CONFIG_BLUEZ_HCIBTUART=m
-CONFIG_BLUEZ_HCIVHCI=m
-
-#
-# Kernel hacking
-#
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_NO_PGT_CACHE is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-# CONFIG_FW_LOADER is not set
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-apm.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-apm.patch
deleted file mode 100644
index 1446bc2eb7..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-apm.patch
+++ /dev/null
@@ -1,805 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/pm-common.c
-@@ -0,0 +1,268 @@
-+/*
-+ * SA1100 Power Management Routines
-+ *
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-02-06: Cliff Brake Initial code
-+ *
-+ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
-+ * Chester Kuo <chester@linux.org.tw>
-+ * Save more value for the resume function! Support
-+ * Bitsy/Assabet/Freebird board
-+ *
-+ * 2001-08-29: Nicolas Pitre <nico@cam.org>
-+ * Cleaned up, pushed platform dependent stuff
-+ * in the platform specific files.
-+ *
-+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
-+ * Storage is local on the stack now.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+#include <asm/uaccess.h>
-+
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch-sa1100/h3600_asic.h>
-+#endif
-+
-+#define __KERNEL_SYSCALLS__
-+#include <linux/unistd.h>
-+
-+/*
-+ * Debug macros
-+ */
-+#undef DEBUG
-+
-+
-+
-+static char pm_helper_path[128] = "/sbin/pm_helper";
-+extern int exec_usermodehelper(char *path, char **argv, char **envp);
-+int debug_pm = 0;
-+static int pm_helper_veto = 0;
-+
-+static int
-+run_sbin_pm_helper( pm_request_t action )
-+{
-+ int i;
-+ char *argv[3], *envp[8];
-+
-+ if (!pm_helper_path[0])
-+ return 2;
-+
-+ if ( action != PM_SUSPEND && action != PM_RESUME )
-+ return 1;
-+
-+ /* Be root */
-+ current->uid = current->gid = 0;
-+
-+ i = 0;
-+ argv[i++] = pm_helper_path;
-+ argv[i++] = (action == PM_RESUME ? "resume" : "suspend");
-+ argv[i] = 0;
-+
-+ i = 0;
-+ /* minimal command environment */
-+ envp[i++] = "HOME=/";
-+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+ envp[i] = 0;
-+
-+ /* other stuff we want to pass to /sbin/pm_helper */
-+ return exec_usermodehelper (argv [0], argv, envp);
-+}
-+
-+/*
-+ * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend.
-+ */
-+int (*pm_suggest_suspend_hook)(int state);
-+EXPORT_SYMBOL(pm_suggest_suspend_hook);
-+
-+/*
-+ * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume
-+ */
-+int pm_use_sbin_pm_helper = 1;
-+EXPORT_SYMBOL(pm_use_sbin_pm_helper);
-+
-+/*
-+ * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend.
-+ * If it returns a true value, then pm_suspend is not called.
-+ * Use this to hook in apmd, for now.
-+ */
-+int (*pm_sysctl_suspend_hook)(int state);
-+EXPORT_SYMBOL(pm_sysctl_suspend_hook);
-+
-+int pm_suspend(void);
-+
-+int pm_suggest_suspend(void)
-+{
-+ int retval;
-+
-+ if (pm_suggest_suspend_hook) {
-+ if (pm_suggest_suspend_hook(PM_SUSPEND))
-+ return 0;
-+ }
-+
-+ if (pm_use_sbin_pm_helper) {
-+ pid_t pid;
-+ int res;
-+ int status = 0;
-+ unsigned int old_fs;
-+
-+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 );
-+ if ( pid < 0 )
-+ return pid;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid);
-+
-+ old_fs = get_fs ();
-+ set_fs (get_ds ());
-+ res = waitpid(pid, &status, __WCLONE);
-+ set_fs (old_fs);
-+
-+ if ( pid != res ) {
-+ if (debug_pm)
-+ printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status );
-+
-+ return -1;
-+ }
-+
-+ /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/
-+ if (( status & 0xff7f ) != 0 ) {
-+ if (pm_helper_veto) {
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8);
-+ return -1;
-+ } else {
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8);
-+ }
-+ }
-+ }
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ );
-+
-+ if (pm_sysctl_suspend_hook) {
-+ if (pm_sysctl_suspend_hook(PM_SUSPEND))
-+ return 0;
-+ }
-+
-+ retval = pm_suspend();
-+ if (retval) {
-+ if (debug_pm)
-+ printk(KERN_CRIT "pm_suspend returned %d\n", retval);
-+ return retval;
-+ }
-+
-+ if (pm_use_sbin_pm_helper) {
-+ pid_t pid;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__);
-+
-+ pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 );
-+ if ( pid < 0 )
-+ return pid;
-+
-+ if ( pid != waitpid ( pid, NULL, __WCLONE ))
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+EXPORT_SYMBOL(pm_suggest_suspend);
-+
-+
-+/*
-+ * Send us to sleep.
-+ */
-+int pm_suspend(void)
-+{
-+ int retval;
-+
-+ retval = pm_send_all(PM_SUSPEND, (void *)3);
-+ if ( retval )
-+ return retval;
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ retval = h3600_power_management(PM_SUSPEND);
-+ if (retval) {
-+ pm_send_all(PM_RESUME, (void *)0);
-+ return retval;
-+ }
-+#endif
-+
-+ retval = pm_do_suspend();
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ /* Allow the power management routines to override resuming */
-+ while ( h3600_power_management(PM_RESUME) )
-+ retval = pm_do_suspend();
-+#endif
-+
-+ pm_send_all(PM_RESUME, (void *)0);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(pm_suspend);
-+
-+#ifdef CONFIG_SYSCTL
-+/*
-+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
-+ * linux/sysctl.h.
-+ *
-+ * This means our interface here won't survive long - it needs a new
-+ * interface. Quick hack to get this working - use sysctl id 9999.
-+ */
-+#warning ACPI broke the kernel, this interface needs to be fixed up.
-+#define CTL_ACPI 9999
-+#define ACPI_S1_SLP_TYP 19
-+
-+static struct ctl_table pm_table[] =
-+{
-+/* {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_suspend},*/
-+ {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring},
-+ {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec},
-+ {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec},
-+ {0}
-+};
-+
-+static struct ctl_table pm_dir_table[] =
-+{
-+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
-+ {0}
-+};
-+
-+/*
-+ * Initialize power interface
-+ */
-+static int __init pm_init(void)
-+{
-+ register_sysctl_table(pm_dir_table, 1);
-+ return 0;
-+}
-+
-+__initcall(pm_init);
-+
-+#endif
-+
---- linux-2.4.27/arch/arm/mach-sa1100/apm.c~simpad-apm
-+++ linux-2.4.27/arch/arm/mach-sa1100/apm.c
-@@ -32,9 +32,7 @@
-
- #include <asm/system.h>
- #include <asm/hardware.h>
--#if FIXME
- #include <asm/arch-sa1100/pm.h>
--#endif
-
- #ifdef CONFIG_IPAQ_HANDHELD
- #include <asm/arch-sa1100/h3600_hal.h>
-@@ -92,6 +90,8 @@
- int magic;
- struct apm_user * next;
- int suser: 1;
-+ int writer: 1;
-+ int reader: 1;
- int suspend_wait: 1;
- int suspend_result;
- int suspends_pending;
-@@ -111,7 +111,7 @@
- /*
- * Local variables
- */
--//static int suspends_pending;
-+static int suspends_pending;
- //static int standbys_pending;
- //static int ignore_normal_resume;
-
-@@ -129,8 +129,6 @@
- #else
- static int power_off = 1;
- #endif
--static int exit_kapmd;
--static int kapmd_running;
-
- static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
- static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-@@ -190,6 +188,42 @@
- return as->events[as->event_tail];
- }
-
-+static void queue_event(apm_event_t event, struct apm_user *sender)
-+{
-+ struct apm_user * as;
-+
-+ if (user_list == NULL)
-+ return;
-+ for (as = user_list; as != NULL; as = as->next) {
-+ if ((as == sender) || (!as->reader))
-+ continue;
-+ as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-+ if (as->event_head == as->event_tail) {
-+ static int notified;
-+
-+ if (notified++ == 0)
-+ printk(KERN_ERR "apm: an event queue overflowed\n");
-+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-+ }
-+ as->events[as->event_head] = event;
-+ if ((!as->suser) || (!as->writer))
-+ continue;
-+ switch (event) {
-+ case APM_SYS_SUSPEND:
-+ case APM_USER_SUSPEND:
-+ as->suspends_pending++;
-+ suspends_pending++;
-+ break;
-+
-+ case APM_SYS_STANDBY:
-+ case APM_USER_STANDBY:
-+ as->standbys_pending++;
-+ break;
-+ }
-+ }
-+ wake_up_interruptible(&apm_waitqueue);
-+}
-+
- static int check_apm_user(struct apm_user *as, const char *func)
- {
- if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-@@ -228,7 +262,6 @@
- i = count;
- while ((i >= sizeof(event)) && !queue_empty(as)) {
- event = get_queued_event(as);
-- printk(" do_read: event=%d\n", event);
- if (copy_to_user(buf, &event, sizeof(event))) {
- if (i < count)
- break;
-@@ -280,9 +313,17 @@
- return -EPERM;
- switch (cmd) {
- case APM_IOC_SUSPEND:
--#if FIXME
-- pm_suggest_suspend();
--#endif
-+ if (as->suspends_read > 0) {
-+ as->suspends_read--;
-+ as->suspends_pending--;
-+ suspends_pending--;
-+ } else {
-+ queue_event(APM_USER_SUSPEND, as);
-+ }
-+
-+ if (suspends_pending <= 0)
-+ wake_up(&apm_suspend_waitqueue);
-+
- break;
- default:
- return -EINVAL;
-@@ -299,6 +340,20 @@
- return 0;
- filp->private_data = NULL;
- lock_kernel();
-+ if (user_list == as)
-+ user_list = as->next;
-+ else {
-+ struct apm_user * as1;
-+
-+ for (as1 = user_list;
-+ (as1 != NULL) && (as1->next != as);
-+ as1 = as1->next)
-+ ;
-+ if (as1 == NULL)
-+ printk(KERN_ERR "apm: filp not in user list\n");
-+ else
-+ as1->next = as->next;
-+ }
- unlock_kernel();
- kfree(as);
- return 0;
-@@ -326,6 +381,8 @@
- * privileged operation -- cevans
- */
- as->suser = capable(CAP_SYS_ADMIN);
-+ as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-+ as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
- as->next = user_list;
- user_list = as;
- filp->private_data = as;
-@@ -409,34 +466,6 @@
- return p - buf;
- }
-
--#ifndef MODULE
--static int __init apm_setup(char *str)
--{
-- int invert;
--
-- while ((str != NULL) && (*str != '\0')) {
-- if (strncmp(str, "off", 3) == 0)
-- apm_disabled = 1;
-- if (strncmp(str, "on", 2) == 0)
-- apm_disabled = 0;
-- invert = (strncmp(str, "no-", 3) == 0);
-- if (invert)
-- str += 3;
-- if (strncmp(str, "debug", 5) == 0)
-- debug = !invert;
-- if ((strncmp(str, "power-off", 9) == 0) ||
-- (strncmp(str, "power_off", 9) == 0))
-- power_off = !invert;
-- str = strchr(str, ',');
-- if (str != NULL)
-- str += strspn(str, ", \t");
-- }
-- return 1;
--}
--
--__setup("apm=", apm_setup);
--#endif
--
- static struct file_operations apm_bios_fops = {
- owner: THIS_MODULE,
- read: do_read,
-@@ -454,6 +483,50 @@
-
- #define APM_INIT_ERROR_RETURN return -1
-
-+static pid_t apmd_pid;
-+static DECLARE_COMPLETION(apmd_exited);
-+
-+static int apm(void *unused)
-+{
-+ unsigned short bx;
-+ unsigned short cx;
-+ unsigned short dx;
-+ int error;
-+ char * power_stat;
-+ char * bat_stat;
-+ DECLARE_WAITQUEUE(wait, current);
-+ struct apm_user au, *as;
-+
-+ lock_kernel();
-+
-+ daemonize();
-+
-+ strcpy(current->comm, "kapmd");
-+
-+ as = &au;
-+ as->magic = APM_BIOS_MAGIC;
-+ as->event_tail = as->event_head = 0;
-+ as->suspends_pending = as->standbys_pending = 0;
-+ as->suspends_read = as->standbys_read = 0;
-+ as->suser = 1;
-+ as->writer = 1;
-+ as->reader = 0;
-+
-+ for (;;) {
-+ interruptible_sleep_on(&apm_suspend_waitqueue);
-+ if (signal_pending (current))
-+ break;
-+
-+ pm_suggest_suspend();
-+
-+ queue_event(APM_NORMAL_RESUME, as);
-+ }
-+
-+ unlock_kernel();
-+
-+ complete_and_exit(&apmd_exited, 0);
-+}
-+
- /*
- * Just start the APM thread. We do NOT want to do APM BIOS
- * calls from anything but the APM thread, if for no other reason
-@@ -492,6 +563,8 @@
-
- misc_register(&apm_device);
-
-+ apmd_pid = kernel_thread(apm, NULL, 0);
-+
- return 0;
- }
-
-@@ -499,11 +572,10 @@
- {
- misc_deregister(&apm_device);
- remove_proc_entry("apm", NULL);
-+ kill_proc (apmd_pid, SIGTERM, 1);
-+ wait_for_completion(&apmd_exited);
- if (power_off)
- pm_power_off = NULL;
-- exit_kapmd = 1;
-- while (kapmd_running)
-- schedule();
- pm_active = 0;
- }
-
-@@ -512,6 +584,7 @@
-
- MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
- MODULE_DESCRIPTION("A minimal emulation of APM");
-+MODULE_LICENSE("GPL");
- MODULE_PARM(debug, "i");
- MODULE_PARM_DESC(debug, "Enable debug mode");
- MODULE_PARM(power_off, "i");
---- /dev/null
-+++ linux-2.4.27/include/asm-arm/arch-sa1100/pm.h
-@@ -0,0 +1,20 @@
-+/*
-+ *
-+ * Declarations for ARM Linux Power Management
-+ *
-+ * Copyright 2002 Compaq Computer Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * Author: Jamey Hicks.
-+ *
-+ */
-+
-+
-+extern int (*pm_suggest_suspend_hook)(int state);
-+extern int (*pm_sysctl_suspend_hook)(int state);
-+extern int pm_use_sbin_pm_helper;
-+extern int pm_suspend(void);
-+extern int pm_suggest_suspend(void); /* triggers /sbin/pm_helper or queueing event to apmd */
---- linux-2.4.27/arch/arm/mach-sa1100/Makefile~simpad-apm
-+++ linux-2.4.27/arch/arm/mach-sa1100/Makefile
-@@ -19,7 +19,7 @@
- flexanet.o freebird.o frodo.o generic.o h3600.o \
- huw_webpanel.o irq.o sa1111.o sa1111-pcibuf.o \
- system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o simputer.o ssp.o \
-- simpad.o
-+ simpad.o pm-sa1100.o
-
- # These aren't present yet, and prevents a plain -ac kernel building.
- # hwtimer.o
-@@ -105,7 +105,7 @@
- obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
-
- # Miscelaneous functions
--obj-$(CONFIG_PM) += pm.o sleep.o
-+obj-$(CONFIG_PM) += pm-sa1100.o sleep.o
- obj-$(CONFIG_APM) += apm.o
-
- # SIMpad specific
---- /dev/null
-+++ linux-2.4.27/arch/arm/mach-sa1100/pm-sa1100.c
-@@ -0,0 +1,225 @@
-+/*
-+ * SA1100 Power Management Routines
-+ *
-+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License.
-+ *
-+ * History:
-+ *
-+ * 2001-02-06: Cliff Brake Initial code
-+ *
-+ * 2001-02-25: Sukjae Cho <sjcho@east.isi.edu> &
-+ * Chester Kuo <chester@linux.org.tw>
-+ * Save more value for the resume function! Support
-+ * Bitsy/Assabet/Freebird board
-+ *
-+ * 2001-08-29: Nicolas Pitre <nico@cam.org>
-+ * Cleaned up, pushed platform dependent stuff
-+ * in the platform specific files.
-+ *
-+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
-+ * Storage is local on the stack now.
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/pm.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/sysctl.h>
-+#include <linux/errno.h>
-+#include <linux/cpufreq.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/memory.h>
-+#include <asm/system.h>
-+#include <asm/leds.h>
-+
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+#include <asm/arch/h3600_asic.h>
-+#endif
-+
-+#define __KERNEL_SYSCALLS__
-+#include <linux/unistd.h>
-+
-+extern void sa1100_cpu_suspend(void);
-+extern void sa1100_cpu_resume(void);
-+extern int debug_pm;
-+
-+#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
-+#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
-+
-+/*
-+ * List of global SA11x0 peripheral registers to preserve.
-+ * More ones like CP and general purpose register values are preserved
-+ * with the stack location in sleep.S.
-+ */
-+enum { SLEEP_SAVE_START = 0,
-+
-+ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
-+ SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
-+
-+ SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
-+ SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
-+
-+ SLEEP_SAVE_ICMR,
-+#ifdef CONFIG_SA1100_SIMPAD
-+ SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
-+#endif
-+ SLEEP_SAVE_Ser1SDCR0,
-+
-+ SLEEP_SAVE_PWER,
-+ SLEEP_SAVE_MSC1, SLEEP_SAVE_MSC2,
-+
-+ SLEEP_SAVE_SIZE
-+};
-+
-+
-+int pm_do_suspend(void)
-+{
-+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
-+
-+ cli();
-+
-+ leds_event(led_stop);
-+
-+ /* preserve current time */
-+ RCNR = xtime.tv_sec;
-+
-+ /* save vital registers */
-+ SAVE(OSCR);
-+ SAVE(OSMR0);
-+ SAVE(OSMR1);
-+ SAVE(OSMR2);
-+ SAVE(OSMR3);
-+ SAVE(OIER);
-+
-+ SAVE(GPDR);
-+ SAVE(GRER);
-+ SAVE(GFER);
-+ SAVE(GAFR);
-+
-+ SAVE(PPDR);
-+ SAVE(PPSR);
-+ SAVE(PPAR);
-+ SAVE(PSDR);
-+
-+ SAVE(Ser1SDCR0);
-+
-+ SAVE(ICMR);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ SAVE(MECR);
-+#endif
-+ SAVE(PWER);
-+ SAVE(MSC1);
-+ SAVE(MSC2);
-+
-+ /* ... maybe a global variable initialized by arch code to set this? */
-+ GRER &= PWER;
-+ GFER &= PWER;
-+ // Ugly, but I need the AC inserted event
-+ // In the future, we're going to care about DCD and USB interrupts as well
-+ if ( machine_is_h3800()) {
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ GFER = GPIO_H3800_AC_IN;
-+#endif
-+ } else {
-+ GFER = 0;
-+ if (machine_is_jornada56x()) {
-+ /* jca */
-+ GFER = PWER;
-+ ICMR |= PWER;
-+ }
-+ }
-+ GEDR = GEDR;
-+
-+ /* Clear previous reset status */
-+ RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
-+
-+ /* set resume return address */
-+ PSPR = virt_to_phys(sa1100_cpu_resume);
-+
-+ /* go zzz */
-+ sa1100_cpu_suspend();
-+
-+ /* ensure not to come back here if it wasn't intended */
-+ PSPR = 0;
-+
-+ if (debug_pm)
-+ printk(KERN_CRIT "*** made it back from resume\n");
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+ if ( machine_is_ipaq()) {
-+ ipaq_model_ops.gedr = GEDR;
-+ ipaq_model_ops.icpr = ICPR;
-+ }
-+#endif
-+
-+ /* restore registers */
-+ RESTORE(GPDR);
-+ RESTORE(GRER);
-+ RESTORE(GFER);
-+ RESTORE(GAFR);
-+
-+ /* clear any edge detect bit */
-+ GEDR = GEDR;
-+
-+ RESTORE(PPDR);
-+ RESTORE(PPSR);
-+ RESTORE(PPAR);
-+ RESTORE(PSDR);
-+
-+ RESTORE(Ser1SDCR0);
-+
-+ PSSR = PSSR_PH;
-+
-+ RESTORE(OSMR0);
-+ RESTORE(OSMR1);
-+ RESTORE(OSMR2);
-+ RESTORE(OSMR3);
-+ RESTORE(OSCR);
-+ RESTORE(OIER);
-+
-+#ifdef CONFIG_IPAQ_HANDHELD
-+/* OSMR0 may have fired before we went to sleep, but after interrupts
-+ were shut off. Set OSMR0 to something plausible */
-+ OSMR0 = OSCR + LATCH;
-+#endif
-+ ICLR = 0;
-+ ICCR = 1;
-+ RESTORE(ICMR);
-+#ifdef CONFIG_SA1100_SIMPAD
-+ RESTORE(MECR);
-+#endif
-+ RESTORE(PWER);
-+ RESTORE(MSC1);
-+ RESTORE(MSC2);
-+ /* restore current time */
-+ xtime.tv_sec = RCNR;
-+
-+ leds_event(led_start);
-+
-+ sti();
-+
-+ if (debug_pm)
-+ printk("interrupts are enabled\n");
-+
-+ /*
-+ * Restore the CPU frequency settings.
-+ */
-+#ifdef CONFIG_CPU_FREQ
-+ cpufreq_restore();
-+#endif
-+ return 0;
-+}
-+
-+unsigned long sleep_phys_sp(void *sp)
-+{
-+ return virt_to_phys(sp);
-+}
-+
-+#include "pm-common.c"
diff --git a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-pm-updates.patch b/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-pm-updates.patch
deleted file mode 100644
index 020a625029..0000000000
--- a/recipes/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/simpad-pm-updates.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/arch/arm/mach-sa1100/pm-sa1100.c~simpad-pm-updates
-+++ linux-2.4.27/arch/arm/mach-sa1100/pm-sa1100.c
-@@ -69,6 +69,7 @@
- SLEEP_SAVE_ICMR,
- #ifdef CONFIG_SA1100_SIMPAD
- SLEEP_SAVE_MECR, /* needed by SIMpad to get PCMCIA working after resume */
-+ SLEEP_SAVE_Ser4MCCR0, SLEEP_SAVE_Ser4MCSR, SLEEP_SAVE_Ser4MCCR1, /* touchscreen */
- #endif
- SLEEP_SAVE_Ser1SDCR0,
-
-@@ -113,6 +114,9 @@
- SAVE(ICMR);
- #ifdef CONFIG_SA1100_SIMPAD
- SAVE(MECR);
-+ SAVE(Ser4MCCR0);
-+ SAVE(Ser4MCSR);
-+ SAVE(Ser4MCCR1);
- #endif
- SAVE(PWER);
- SAVE(MSC1);
-@@ -194,6 +198,9 @@
- RESTORE(ICMR);
- #ifdef CONFIG_SA1100_SIMPAD
- RESTORE(MECR);
-+ RESTORE(Ser4MCCR0);
-+ RESTORE(Ser4MCSR);
-+ RESTORE(Ser4MCCR1);
- #endif
- RESTORE(PWER);
- RESTORE(MSC1);
diff --git a/recipes/linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb b/recipes/linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb
deleted file mode 100644
index a27f8e47f9..0000000000
--- a/recipes/linux/opensimpad-64+0_2.4.25-vrs2-pxa1-jpm1.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-SECTION = "kernel"
-require opensimpad_${PV}.bb
-
-SIMPAD_MEM = "64"
-SIMPAD_RD = "0"
-
-SRC_URI[kernel.md5sum] = "5fc8e9f43fa44ac29ddf9a9980af57d8"
-SRC_URI[kernel.sha256sum] = "877af8ed89e56af004bb0662c1a9cfc785b40c602f71a8bf81521991026cf2f0"
-SRC_URI[patch.md5sum] = "5c54040bba6fea2bfb47df01056e953f"
-SRC_URI[patch.sha256sum] = "d35213dc854f1e1a08512154c7a92fb94d9f0506cc5107f8b2f248412679fb53"
diff --git a/recipes/linux/opensimpad-64+0_2.4.27-vrs1-pxa1-jpm1.bb b/recipes/linux/opensimpad-64+0_2.4.27-vrs1-pxa1-jpm1.bb
deleted file mode 100644
index 27d268bc45..0000000000
--- a/recipes/linux/opensimpad-64+0_2.4.27-vrs1-pxa1-jpm1.bb
+++ /dev/null
@@ -1,14 +0,0 @@
-# to use another configuration, duplicate this file, change the sizes,
-# change the filename accordingly, and add the followin line to local.conf:
-# PREFERRED_PROVIDER_virtual/kernel_kernel24 = "opensimpad-64+0"
-
-SECTION = "kernel"
-require opensimpad_${PV}.bb
-
-# fraction of the memory (in Mb) used for RAM
-SIMPAD_MEM = "64"
-# fraction of the memory (in Mb) used as a ramdisk
-SIMPAD_RD = "0"
-
-SRC_URI[patch.md5sum] = "5c54040bba6fea2bfb47df01056e953f"
-SRC_URI[patch.sha256sum] = "d35213dc854f1e1a08512154c7a92fb94d9f0506cc5107f8b2f248412679fb53"
diff --git a/recipes/linux/opensimpad/disable-pcmcia-probe.patch b/recipes/linux/opensimpad/disable-pcmcia-probe.patch
deleted file mode 100644
index 0ab9439982..0000000000
--- a/recipes/linux/opensimpad/disable-pcmcia-probe.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/pcmcia/Config.in~disable-pcmcia-probe
-+++ linux-2.4.27/drivers/pcmcia/Config.in
-@@ -15,9 +15,6 @@
- tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA
- if [ "$CONFIG_PCMCIA" != "n" ]; then
- # yes, I really mean the following...
-- if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then
-- define_bool CONFIG_PCMCIA_PROBE y
-- fi
- if [ "$CONFIG_PCI" != "n" ]; then
- bool ' CardBus support' CONFIG_CARDBUS
- fi
diff --git a/recipes/linux/opensimpad/mkdep.patch b/recipes/linux/opensimpad/mkdep.patch
deleted file mode 100644
index 6dc51403b2..0000000000
--- a/recipes/linux/opensimpad/mkdep.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/Makefile~mkdep
-+++ linux-2.4.27/Makefile
-@@ -501,7 +501,7 @@
- ifdef CONFIG_MODVERSIONS
- $(MAKE) update-modverfile
- endif
-- scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
-+ $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend)
- scripts/mkdep -- init/*.c > .depend
-
- ifdef CONFIG_MODVERSIONS
diff --git a/recipes/linux/opensimpad/mmc-spi.patch b/recipes/linux/opensimpad/mmc-spi.patch
deleted file mode 100644
index 1841b45fbd..0000000000
--- a/recipes/linux/opensimpad/mmc-spi.patch
+++ /dev/null
@@ -1,885 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- /dev/null
-+++ linux-2.4.27/drivers/block/mmc.c
-@@ -0,0 +1,857 @@
-+/*
-+ * Copyright (c) Clément Ballabriga, 2005 - GPL
-+ * Copyright (c) Guylhem Aznar, 2005 - GPL
-+ *
-+ * Please check http://externe.net/zaurus/simpad-bluetooth reference design first.
-+ *
-+ * Based on Madsuk/Rohde work on a MMC driver for the WRT54G.
-+ *
-+ * This is an ugly hack of a driver. I am surprised if it ever works!
-+ * So please use a real driver or contribute one to the 2.4/2.6 mmc framework
-+ */
-+
-+#include <linux/stddef.h>
-+#include <linux/delay.h>
-+#include <linux/timer.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/blkpg.h>
-+#include <linux/hdreg.h>
-+#include <linux/major.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/uaccess.h>
-+#include <asm/io.h>
-+
-+/*
-+ * *******************************************************************
-+ *
-+ * This is the only configurable part.
-+ *
-+ * *******************************************************************
-+ *
-+ */
-+
-+// #define DEBUG 1
-+
-+#define DEVICE_NAME "mmc"
-+#define DEVICE_NR(device) (MINOR(device))
-+#define DEVICE_ON(device)
-+#define DEVICE_OFF(device)
-+#define MAJOR_NR 121
-+
-+/* Let that include where it is or compilation fails on INIT_REQUEST/CURRENT */
-+
-+#include <linux/blk.h>
-+
-+MODULE_AUTHOR("Guylhem Aznar <mmc-driver @externe.net>");
-+MODULE_DESCRIPTION("Driver for MMC/SD-Cards in SPI mode by GPIO");
-+MODULE_SUPPORTED_DEVICE("Simpad");
-+MODULE_LICENSE("GPL");
-+
-+/* Registers should be architecture independant - but it's not ! */
-+
-+#define MAP_START 0x90040000
-+#define MAP_SIZE 0x00001000
-+
-+#define MY_GPLR 0
-+#define MY_GPDR 1
-+#define MY_GPSR 2
-+#define MY_GPCR 3
-+#define MY_GRER 4
-+#define MY_GFER 5
-+#define MY_GEDR 6
-+#define MY_GAFR 7
-+
-+/*
-+ * If you are using different GPIOs in your hardware hack, you must
-+ * first make sure they are unused for other functions and then
-+ * configure them here.
-+ *
-+ * On the simpad I use spare pins from the UART1 (internal serial port):
-+ * - DCD (in) : GPIO 23 : DO
-+ * - DTR (out) : GPIO 07 : CS
-+ * - RI (in) : GPIO 19 : CLK
-+ * - DSR (in) : GPIO 06 : DI
-+ *
-+ * Don't worry about in/out original function - the GPIOs will be
-+ * reprogrammed.
-+ */
-+
-+#define GPIO_SD_DO 23
-+#define GPIO_SD_CS 7
-+#define GPIO_SD_CLK 19
-+#define GPIO_SD_DI 6
-+
-+/*
-+ * *******************************************************************
-+ *
-+ * Do not change anything below !
-+ *
-+ * *******************************************************************
-+ *
-+ */
-+
-+
-+/* GPIO states */
-+#define LOW 0
-+#define HIGH 1
-+
-+#define INPUT 0
-+#define OUTPUT 1
-+
-+#define PRESENT 1
-+#define ABSENT 0
-+
-+typedef unsigned int uint32;
-+typedef unsigned long u32_t;
-+typedef unsigned short u16_t;
-+typedef unsigned char u8_t;
-+
-+/* we have only one device */
-+static int hd_sizes[1 << 6];
-+static int hd_blocksizes[1 << 6];
-+static int hd_hardsectsizes[1 << 6];
-+static int hd_maxsect[1 << 6];
-+static struct hd_struct hd[1 << 6];
-+
-+static struct timer_list mmc_timer;
-+
-+/* start with no card */
-+static int mmc_media_detect = 0;
-+static int mmc_media_changed = 1;
-+
-+extern struct gendisk hd_gendisk;
-+
-+/* Use only one global device */
-+typedef struct gpio_s gpio_t;
-+struct gpio_s {
-+ volatile u32_t *base;
-+};
-+
-+static gpio_t gp = {
-+ (void *) io_p2v(MAP_START)
-+};
-+
-+/*
-+ * *******************************************************************
-+ *
-+ * Begin GPIO hardware access functions.
-+ *
-+ * *******************************************************************
-+ *
-+ */
-+
-+gpio_t *gpio_open(void)
-+{
-+ static gpio_t tmp;
-+ tmp.base = (void *) io_p2v(MAP_START);
-+ return (&tmp);
-+}
-+
-+void gpio_setdir(gpio_t * g, int num, int dir)
-+{
-+ if (dir == 1) {
-+ g->base[MY_GPDR] |= (1 << num);
-+ } else {
-+ g->base[MY_GPDR] &= ~(1 << num);
-+
-+ }
-+}
-+
-+void gpio_setalt(gpio_t * g, int num, int alt)
-+{
-+ if (alt == 1) {
-+ g->base[MY_GAFR] |= (1 << num);
-+ } else {
-+ g->base[MY_GAFR] &= ~(1 << num);
-+ }
-+}
-+
-+int gpio_getdir(gpio_t * g, int num)
-+{
-+ return ((g->base[MY_GPDR] & (1 << num)) ? 1 : 0);
-+}
-+
-+int gpio_getalt(gpio_t * g, int num)
-+{
-+ return ((g->base[MY_GAFR] & (1 << num)) ? 1 : 0);
-+}
-+
-+static int gpio_read(gpio_t * g, int num)
-+{
-+ int what;
-+
-+ what=(g->base[MY_GPLR] & (1 << num)) ? 1 : 0;
-+
-+#ifdef DEBUG
-+ if (num == GPIO_SD_DO) {
-+ printk ("GPIO_SD_DO read: %u\n", what);
-+ }
-+#endif
-+ return (what);
-+}
-+
-+static int gpio_write(gpio_t * g, int num, int val)
-+{
-+#ifdef DEBUG
-+ int check;
-+#endif
-+
-+ if (val == 1) {
-+ g->base[MY_GPSR] = 1 << num;
-+ } else {
-+ g->base[MY_GPCR] = 1 << num;
-+ }
-+#ifdef DEBUG
-+ check=gpio_read(g,num);
-+ if (check != val)
-+ {
-+ printk ("Error while write to %d: found %d after writing %d\n",num, check, val);
-+ return (1);
-+ }
-+ else return(0);
-+#endif
-+
-+}
-+
-+/*
-+ * *******************************************************************
-+ *
-+ * Begin SPI hardware access functions.
-+ *
-+ * *******************************************************************
-+ *
-+ */
-+static int mmc_spi_media_detect(void)
-+{
-+// FIXME: add card detection/test by SPI
-+
-+ return 1;
-+}
-+
-+static int mmc_spi_hardware_init(void)
-+{
-+ /*unsigned char gpio_outen;*/
-+
-+ printk("mmc: GPIO init\n");
-+
-+ /* Now global
-+ * gp = gpio_open(); */
-+
-+ /* Cut existing functions */
-+ gpio_setalt(&gp, GPIO_SD_CLK, 0);
-+ gpio_setalt(&gp, GPIO_SD_DI, 0);
-+ gpio_setalt(&gp, GPIO_SD_DO, 0);
-+ gpio_setalt(&gp, GPIO_SD_CS, 0);
-+
-+ /* Remap directions */
-+ gpio_setdir(&gp, GPIO_SD_CLK, OUTPUT);
-+ gpio_setdir(&gp, GPIO_SD_DI, OUTPUT);
-+ gpio_setdir(&gp, GPIO_SD_DO, INPUT);
-+ gpio_setdir(&gp, GPIO_SD_CS, OUTPUT);
-+
-+ printk("mmc: initialising MMC\n");
-+
-+ /* Start */
-+ gpio_write(&gp, GPIO_SD_CLK, LOW);
-+ gpio_write(&gp, GPIO_SD_DI, LOW);
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+ return 0;
-+}
-+
-+/* return what has been read, write the parameter */
-+
-+static unsigned char mmc_spi_readwrite(unsigned char data_out)
-+{
-+ int i;
-+ unsigned char result = 0/*, tmp_data = 0*/;
-+
-+ for (i = 0; i < 8; i++) {
-+ if (data_out & (0x01 << (7 - i)))
-+ gpio_write(&gp, GPIO_SD_DI, HIGH);
-+ else
-+ gpio_write(&gp, GPIO_SD_DI, LOW);
-+
-+ gpio_write(&gp, GPIO_SD_CLK, HIGH);
-+
-+ result <<= 1;
-+
-+ if (gpio_read(&gp, GPIO_SD_DO) == 1)
-+ result |= 1;
-+
-+ gpio_write(&gp, GPIO_SD_CLK, LOW);
-+ }
-+
-+ return (result);
-+}
-+
-+static int mmc_spi_card_init(void)
-+{
-+ unsigned char result = 0;
-+ short i, j;
-+ unsigned long flags;
-+
-+ save_flags(flags);
-+ cli();
-+
-+ printk("GPIO_SD_CS dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_CS), gpio_getalt(&gp, GPIO_SD_CS));
-+ printk("GPIO_SD_DI dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_DI), gpio_getalt(&gp, GPIO_SD_DI));
-+ printk("GPIO_SD_DO dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_DO), gpio_getalt(&gp, GPIO_SD_DO));
-+ printk("GPIO_SD_CS dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_CLK), gpio_getalt(&gp, GPIO_SD_CLK));
-+
-+ printk("mmc: card init 1/2\n");
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ for (i = 0; i < 20; i++)
-+ mmc_spi_readwrite(0xff);
-+
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+
-+ mmc_spi_readwrite(0x40);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0x00);
-+ mmc_spi_readwrite(0x95);
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0x01)
-+ break;
-+ }
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ if (result != 0x01) {
-+ printk("mmc: card init %d error\n", result);
-+ restore_flags(flags);
-+ return (1);
-+ }
-+
-+ printk("mmc: card init 2/2\n");
-+ for (j = 0; j < 10000; j++) {
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+
-+ mmc_spi_readwrite(0x41);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0x00);
-+ mmc_spi_readwrite(0xff);
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0x00)
-+ break;
-+ }
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ if (result == 0x00) {
-+ restore_flags(flags);
-+ printk("mmc: card init 3/3\n");
-+ return (0);
-+ }
-+ }
-+ restore_flags(flags);
-+
-+ return (2);
-+}
-+
-+
-+static int mmc_spi_card_config(void)
-+{
-+ unsigned char result = 0;
-+ short i;
-+ unsigned char csd[32];
-+ unsigned int c_size;
-+ unsigned int c_size_mult;
-+ unsigned int mult;
-+ unsigned int read_bl_len;
-+ unsigned int blocknr = 0;
-+ unsigned int block_len = 0;
-+ unsigned int size = 0;
-+
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0xff);
-+ mmc_spi_readwrite(0x49);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0x00);
-+ mmc_spi_readwrite(0xff);
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0x00)
-+ break;
-+ }
-+ if (result != 0x00) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (1);
-+ }
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0xfe)
-+ break;
-+ }
-+ if (result != 0xfe) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (2);
-+ }
-+ for (i = 0; i < 16; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ csd[i] = result;
-+ }
-+ for (i = 0; i < 2; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ }
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ if (result == 0x00)
-+ return (3);
-+
-+ c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256;
-+ c_size >>= 6;
-+ c_size_mult = csd[10] + (csd[9] & 0x03) * 256;
-+ c_size_mult >>= 7;
-+ read_bl_len = csd[5] & 0x0f;
-+ mult = 1;
-+ mult <<= c_size_mult + 2;
-+ blocknr = (c_size + 1) * mult;
-+ block_len = 1;
-+ block_len <<= read_bl_len;
-+ size = block_len * blocknr;
-+ size >>= 10;
-+
-+ for (i = 0; i < (1 << 6); i++) {
-+ hd_blocksizes[i] = 1024;
-+ hd_hardsectsizes[i] = block_len;
-+ hd_maxsect[i] = 256;
-+ }
-+ hd_sizes[0] = size;
-+ hd[0].nr_sects = blocknr;
-+
-+
-+ printk("Size = %d, hardsectsize = %d, sectors = %d\n",
-+ size, block_len, blocknr);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * *******************************************************************
-+ *
-+ * End of SPI hardware access functions.
-+ *
-+ * *******************************************************************
-+ */
-+
-+
-+static int mmc_write_block(unsigned int dest_addr, unsigned char *data)
-+{
-+ unsigned int address;
-+ unsigned char result = 0;
-+ unsigned char ab0, ab1, ab2, ab3;
-+ int i;
-+
-+ address = dest_addr;
-+
-+ ab3 = 0xff & (address >> 24);
-+ ab2 = 0xff & (address >> 16);
-+ ab1 = 0xff & (address >> 8);
-+ ab0 = 0xff & address;
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0xff);
-+ mmc_spi_readwrite(0x58);
-+ mmc_spi_readwrite(ab3); /* msb */
-+ mmc_spi_readwrite(ab2);
-+ mmc_spi_readwrite(ab1);
-+ mmc_spi_readwrite(ab0); /* lsb */
-+ mmc_spi_readwrite(0xff);
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0x00)
-+ break;
-+ }
-+ if (result != 0x00) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (1);
-+ }
-+
-+ mmc_spi_readwrite(0xfe);
-+ for (i = 0; i < 512; i++)
-+ mmc_spi_readwrite(data[i]);
-+ for (i = 0; i < 2; i++)
-+ mmc_spi_readwrite(0xff);
-+
-+ for (i = 0; i < 1000000; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0xff)
-+ break;
-+ }
-+ if (result != 0xff) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (3);
-+ }
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (0);
-+}
-+
-+static int mmc_read_block(unsigned char *data, unsigned int src_addr)
-+{
-+ unsigned int address;
-+ unsigned char result = 0;
-+ unsigned char ab0, ab1, ab2, ab3;
-+ int i;
-+
-+ address = src_addr;
-+
-+ ab3 = 0xff & (address >> 24);
-+ ab2 = 0xff & (address >> 16);
-+ ab1 = 0xff & (address >> 8);
-+ ab0 = 0xff & address;
-+
-+ gpio_write(&gp, GPIO_SD_CS, LOW);
-+ for (i = 0; i < 4; i++)
-+ mmc_spi_readwrite(0xff);
-+ mmc_spi_readwrite(0x51);
-+ mmc_spi_readwrite(ab3); /* msb */
-+ mmc_spi_readwrite(ab2);
-+ mmc_spi_readwrite(ab1);
-+ mmc_spi_readwrite(ab0); /* lsb */
-+
-+ mmc_spi_readwrite(0xff);
-+ for (i = 0; i < 8; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0x00)
-+ break;
-+ }
-+ if (result != 0x00) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (1);
-+ }
-+ for (i = 0; i < 100000; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ if (result == 0xfe)
-+ break;
-+ }
-+ if (result != 0xfe) {
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+ return (2);
-+ }
-+ for (i = 0; i < 512; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ data[i] = result;
-+ }
-+ for (i = 0; i < 2; i++) {
-+ result = mmc_spi_readwrite(0xff);
-+ }
-+ gpio_write(&gp, GPIO_SD_CS, HIGH);
-+ mmc_spi_readwrite(0xff);
-+
-+ return (0);
-+}
-+
-+static void mmc_request(request_queue_t * q)
-+{
-+ unsigned int mmc_address;
-+ unsigned char *buffer_address;
-+ int nr_sectors;
-+ int i;
-+ int cmd;
-+ int result, code;
-+
-+ (void) q;
-+ while (1) {
-+ code = 1; // Default is success
-+ INIT_REQUEST;
-+ mmc_address =
-+ (CURRENT->sector +
-+ hd[MINOR(CURRENT->rq_dev)].start_sect) * hd_hardsectsizes[0];
-+ buffer_address = CURRENT->buffer;
-+ nr_sectors = CURRENT->current_nr_sectors;
-+ cmd = CURRENT->cmd;
-+ if (((CURRENT->sector + CURRENT->current_nr_sectors +
-+ hd[MINOR(CURRENT->rq_dev)].start_sect) > hd[0].nr_sects)
-+ || (mmc_media_detect == 0)) {
-+ code = 0;
-+ } else if (cmd == READ) {
-+ spin_unlock_irq(&io_request_lock);
-+ for (i = 0; i < nr_sectors; i++) {
-+ result = mmc_read_block(buffer_address, mmc_address);
-+ if (result != 0) {
-+ printk("mmc: error %d in mmc_read_block\n", result);
-+ code = 0;
-+ break;
-+ } else {
-+ mmc_address += hd_hardsectsizes[0];
-+ buffer_address += hd_hardsectsizes[0];
-+ }
-+ }
-+ spin_lock_irq(&io_request_lock);
-+ } else if (cmd == WRITE) {
-+ spin_unlock_irq(&io_request_lock);
-+ for (i = 0; i < nr_sectors; i++) {
-+ result = mmc_write_block(mmc_address, buffer_address);
-+ if (result != 0) {
-+ printk("mmc: error %d in mmc_write_block\n", result);
-+ code = 0;
-+ break;
-+ } else {
-+ mmc_address += hd_hardsectsizes[0];
-+ buffer_address += hd_hardsectsizes[0];
-+ }
-+ }
-+ spin_lock_irq(&io_request_lock);
-+ } else {
-+ code = 0;
-+ }
-+ end_request(code);
-+ }
-+}
-+
-+
-+static int mmc_open(struct inode *inode, struct file *filp)
-+{
-+ /*int device;*/
-+ (void) filp;
-+ mmc_media_detect = mmc_spi_media_detect();
-+
-+ if (mmc_media_detect == 0)
-+ return -ENODEV;
-+
-+#if defined(MODULE)
-+ MOD_INC_USE_COUNT;
-+#endif
-+ return 0;
-+}
-+
-+static int mmc_release(struct inode *inode, struct file *filp)
-+{
-+ (void) filp;
-+ fsync_dev(inode->i_rdev);
-+ invalidate_buffers(inode->i_rdev);
-+
-+#if defined(MODULE)
-+ MOD_DEC_USE_COUNT;
-+#endif
-+ return 0;
-+}
-+
-+static int mmc_revalidate(kdev_t dev)
-+{
-+ int target, max_p, start, i;
-+
-+ mmc_media_detect = mmc_spi_media_detect();
-+
-+ if (mmc_media_detect == 0)
-+ return -ENODEV;
-+
-+ target = DEVICE_NR(dev);
-+
-+ max_p = hd_gendisk.max_p;
-+ start = target << 6;
-+ for (i = max_p - 1; i >= 0; i--) {
-+ int minor = start + i;
-+ invalidate_device(MKDEV(MAJOR_NR, minor), 1);
-+ hd_gendisk.part[minor].start_sect = 0;
-+ hd_gendisk.part[minor].nr_sects = 0;
-+ }
-+
-+ grok_partitions(&hd_gendisk, target, 1 << 6, hd_sizes[0] * 2);
-+
-+ return 0;
-+}
-+
-+static int mmc_ioctl(struct inode *inode, struct file *filp,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ if (!inode || !inode->i_rdev)
-+ return -EINVAL;
-+
-+ switch (cmd) {
-+ case BLKGETSIZE:
-+ return put_user(hd[MINOR(inode->i_rdev)].nr_sects,
-+ (unsigned long *) arg);
-+ case BLKGETSIZE64:
-+ return put_user((u64) hd[MINOR(inode->i_rdev)].
-+ nr_sects, (u64 *) arg);
-+ case BLKRRPART:
-+ if (!capable(CAP_SYS_ADMIN))
-+ return -EACCES;
-+
-+ return mmc_revalidate(inode->i_rdev);
-+ case HDIO_GETGEO:
-+ {
-+ struct hd_geometry *loc, g;
-+ loc = (struct hd_geometry *) arg;
-+ if (!loc)
-+ return -EINVAL;
-+ g.heads = 4;
-+ g.sectors = 16;
-+ g.cylinders = hd[0].nr_sects / (4 * 16);
-+ g.start = hd[MINOR(inode->i_rdev)].start_sect;
-+ return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0;
-+ }
-+ default:
-+ return blk_ioctl(inode->i_rdev, cmd, arg);
-+ }
-+}
-+
-+
-+/*
-+static int mmc_check_media_change(kdev_t dev)
-+{
-+ (void) dev;
-+ if (mmc_media_changed == 1) {
-+ mmc_media_changed = 0;
-+ return 1;
-+ } else
-+ return 0;
-+}
-+*/
-+
-+static struct block_device_operations mmc_bdops = {
-+ open:mmc_open,
-+ release:mmc_release,
-+ ioctl:mmc_ioctl,
-+/* FIXME: add media change support
-+ * check_media_change: mmc_check_media_change,
-+ * revalidate: mmc_revalidate,
-+ */
-+};
-+
-+static struct gendisk hd_gendisk = {
-+ major:MAJOR_NR,
-+ major_name:DEVICE_NAME,
-+ minor_shift:6,
-+ max_p:1 << 6,
-+ part:hd,
-+ sizes:hd_sizes,
-+ fops:&mmc_bdops,
-+};
-+
-+static int mmc_init(void)
-+{
-+ int result;
-+
-+ result = mmc_spi_hardware_init();
-+
-+ if (result != 0) {
-+ printk("mmc: error %d in mmc_spi_hardware_init\n", result);
-+ return -1;
-+ }
-+
-+ result = mmc_spi_card_init();
-+ if (result != 0) {
-+ // Give it an extra shot
-+ result = mmc_spi_card_init();
-+ if (result != 0) {
-+ printk("mmc: error %d in mmc_card_init\n", result);
-+ return -1;
-+ }
-+ }
-+
-+ memset(hd_sizes, 0, sizeof(hd_sizes));
-+ result = mmc_spi_card_config();
-+ if (result != 0) {
-+ printk("mmc: error %d in mmc_card_config\n", result);
-+ return -1;
-+ }
-+
-+
-+ blk_size[MAJOR_NR] = hd_sizes;
-+
-+ memset(hd, 0, sizeof(hd));
-+ hd[0].nr_sects = hd_sizes[0] * 2;
-+
-+ blksize_size[MAJOR_NR] = hd_blocksizes;
-+ hardsect_size[MAJOR_NR] = hd_hardsectsizes;
-+ max_sectors[MAJOR_NR] = hd_maxsect;
-+
-+ hd_gendisk.nr_real = 1;
-+
-+ register_disk(&hd_gendisk, MKDEV(MAJOR_NR, 0), 1 << 6,
-+ &mmc_bdops, hd_sizes[0] * 2);
-+
-+ return 0;
-+}
-+
-+static void mmc_exit(void)
-+{
-+ blk_size[MAJOR_NR] = NULL;
-+ blksize_size[MAJOR_NR] = NULL;
-+ hardsect_size[MAJOR_NR] = NULL;
-+ max_sectors[MAJOR_NR] = NULL;
-+ hd[0].nr_sects = 0;
-+}
-+
-+static void mmc_check_media(void)
-+{
-+ int old_state, new_state;
-+ int result;
-+
-+ old_state = mmc_media_detect;
-+ new_state = mmc_spi_media_detect();
-+
-+ if (old_state != new_state) {
-+ mmc_media_changed = 1;
-+ if (new_state == PRESENT) {
-+ result = mmc_init();
-+ if (result != 0)
-+ printk("mmc: error %d in mmc_init\n", result);
-+ } else {
-+ mmc_exit();
-+ }
-+ }
-+
-+ /* del_timer(&mmc_timer);
-+ mmc_timer.expires = jiffies + 10*HZ;
-+ add_timer(&mmc_timer); */
-+}
-+
-+static int __init mmc_driver_init(void)
-+{
-+ int result;
-+
-+ result = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops);
-+ if (result < 0) {
-+ printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR);
-+ return result;
-+ }
-+
-+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request);
-+
-+ mmc_check_media();
-+
-+ /*init_timer(&mmc_timer);
-+ mmc_timer.expires = jiffies + HZ;
-+ mmc_timer.function = (void *)mmc_check_media;
-+ add_timer(&mmc_timer); */
-+
-+
-+ read_ahead[MAJOR_NR] = 8;
-+ add_gendisk(&hd_gendisk);
-+
-+
-+ return 0;
-+}
-+
-+static void __exit mmc_driver_exit(void)
-+{
-+ int i;
-+ del_timer(&mmc_timer);
-+
-+ for (i = 0; i < (1 << 6); i++)
-+ fsync_dev(MKDEV(MAJOR_NR, i));
-+
-+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-+ del_gendisk(&hd_gendisk);
-+ devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME);
-+ mmc_exit();
-+}
-+
-+module_init(mmc_driver_init);
-+module_exit(mmc_driver_exit);
---- linux-2.4.27/drivers/block/Config.in~mmc-spi
-+++ linux-2.4.27/drivers/block/Config.in
-@@ -4,6 +4,7 @@
- mainmenu_option next_comment
- comment 'Block devices'
-
-+tristate 'MMC SPI driver' CONFIG_BLK_DEV_MMC
- tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
- if [ "$CONFIG_AMIGA" = "y" ]; then
- tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
---- linux-2.4.27/drivers/block/Makefile~mmc-spi
-+++ linux-2.4.27/drivers/block/Makefile
-@@ -15,6 +15,7 @@
- obj-y := ll_rw_blk.o blkpg.o genhd.o elevator.o
-
- obj-$(CONFIG_MAC_FLOPPY) += swim3.o
-+obj-$(CONFIG_BLK_DEV_MMC) += mmc.o
- obj-$(CONFIG_BLK_DEV_FD) += floppy.o
- obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
- obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
diff --git a/recipes/linux/opensimpad/mppe-20040216.patch b/recipes/linux/opensimpad/mppe-20040216.patch
deleted file mode 100644
index c4195c1420..0000000000
--- a/recipes/linux/opensimpad/mppe-20040216.patch
+++ /dev/null
@@ -1,1225 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/net/Config.in~mppe-20040216
-+++ linux-2.4.27/drivers/net/Config.in
-@@ -332,6 +332,7 @@
- dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
- dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
- dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
-+ dep_tristate ' PPP MPPE compression (encryption)' CONFIG_PPP_MPPE $CONFIG_PPP
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
- fi
---- /dev/null
-+++ linux-2.4.27/drivers/net/arcfour.c
-@@ -0,0 +1,75 @@
-+/*
-+ * arcfour.c
-+ * by Frank Cusack <frank@google.com>
-+ * 100% public domain
-+ *
-+ * Implemented from the description in _Applied Cryptography_, 2nd ed.
-+ *
-+ * ** Distribution ** of this software is unlimited and unrestricted.
-+ *
-+ * ** Use ** of this software is almost certainly legal; however, refer
-+ * to <http://theory.lcs.mit.edu/~rivest/faq.html>.
-+ */
-+
-+#include "arcfour.h"
-+#if defined(__linux__)
-+#include <linux/string.h>
-+#endif
-+
-+#define swap(a, b) \
-+{ \
-+ unsigned char t = b; \
-+ b = a; \
-+ a = t; \
-+}
-+
-+/*
-+ * Initialize arcfour from a key.
-+ */
-+void
-+arcfour_setkey(arcfour_context *context, const unsigned char *key,
-+ unsigned keylen)
-+{
-+ unsigned i, j;
-+ unsigned char K[256];
-+
-+ context->i = context->j = 0;
-+
-+ for (i = 0; i < 256; i++) {
-+ context->S[i] = i;
-+ K[i] = key[i % keylen];
-+ }
-+
-+ j = 0;
-+ for (i = 0; i < 256; i++) {
-+ j = (j + context->S[i] + K[i]) % 256;
-+ swap(context->S[i], context->S[j]);
-+ }
-+
-+ memset(K, 0, sizeof(K));
-+}
-+
-+/*
-+ * plaintext -> ciphertext (or vice versa)
-+ */
-+void
-+arcfour_encrypt(arcfour_context *context, const unsigned char *in, unsigned len,
-+ unsigned char *out)
-+{
-+ unsigned i = context->i;
-+ unsigned j = context->j;
-+ unsigned char *S = context->S;
-+ unsigned char K;
-+
-+ while (len--) {
-+ i = (i + 1) % 256;
-+ j = (j + S[i]) % 256;
-+ swap(S[i], S[j]);
-+ K = S[(S[i] + S[j]) % 256];
-+ *out++ = *in++ ^ K;
-+ }
-+
-+ context->i = i;
-+ context->j = j;
-+}
-+
---- /dev/null
-+++ linux-2.4.27/drivers/net/arcfour.h
-@@ -0,0 +1,17 @@
-+/* arcfour.h */
-+
-+#ifndef _ARCFOUR_H
-+#define _ARCFOUR_H
-+
-+typedef struct {
-+ unsigned i;
-+ unsigned j;
-+ unsigned char S[256];
-+} arcfour_context;
-+
-+extern void arcfour_setkey(arcfour_context *, const unsigned char *, unsigned);
-+extern void arcfour_encrypt(arcfour_context *, const unsigned char *, unsigned,
-+ unsigned char *);
-+#define arcfour_decrypt arcfour_encrypt
-+
-+#endif /* _ARCFOUR_H */
---- linux-2.4.27/drivers/net/ppp_generic.c~mppe-20040216
-+++ linux-2.4.27/drivers/net/ppp_generic.c
-@@ -102,6 +102,7 @@
- spinlock_t rlock; /* lock for receive side 58 */
- spinlock_t wlock; /* lock for transmit side 5c */
- int mru; /* max receive unit 60 */
-+ int mru_alloc; /* MAX(1500,MRU) for dev_alloc_skb() */
- unsigned int flags; /* control bits 64 */
- unsigned int xstate; /* transmit state bits 68 */
- unsigned int rstate; /* receive state bits 6c */
-@@ -129,6 +130,7 @@
- struct sock_fprog pass_filter; /* filter for packets to pass */
- struct sock_fprog active_filter;/* filter for pkts to reset idle */
- #endif /* CONFIG_PPP_FILTER */
-+ int xpad; /* ECP or CCP (MPPE) transmit padding */
- };
-
- /*
-@@ -552,7 +554,9 @@
- case PPPIOCSMRU:
- if (get_user(val, (int *) arg))
- break;
-- ppp->mru = val;
-+ ppp->mru_alloc = ppp->mru = val;
-+ if (ppp->mru_alloc < PPP_MRU)
-+ ppp->mru_alloc = PPP_MRU; /* increase for broken peers */
- err = 0;
- break;
-
-@@ -1031,8 +1035,8 @@
- /* try to do packet compression */
- if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
- && proto != PPP_LCP && proto != PPP_CCP) {
-- new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len,
-- GFP_ATOMIC);
-+ new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len
-+ + ppp->xpad, GFP_ATOMIC);
- if (new_skb == 0) {
- printk(KERN_ERR "PPP: no memory (comp pkt)\n");
- goto drop;
-@@ -1044,15 +1048,28 @@
- /* compressor still expects A/C bytes in hdr */
- len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2,
- new_skb->data, skb->len + 2,
-- ppp->dev->mtu + PPP_HDRLEN);
-+ ppp->dev->mtu + ppp->xpad
-+ + PPP_HDRLEN);
- if (len > 0 && (ppp->flags & SC_CCP_UP)) {
- kfree_skb(skb);
- skb = new_skb;
- skb_put(skb, len);
- skb_pull(skb, 2); /* pull off A/C bytes */
-- } else {
-+ } else if (len == 0) {
- /* didn't compress, or CCP not up yet */
- kfree_skb(new_skb);
-+ } else {
-+ /*
-+ * (len < 0)
-+ * MPPE requires that we do not send unencrypted
-+ * frames. The compressor will return -1 if we
-+ * should drop the frame. We cannot simply test
-+ * the compress_proto because MPPE and MPPC share
-+ * the same number.
-+ */
-+ printk(KERN_ERR "ppp: compressor dropped pkt\n");
-+ kfree_skb(new_skb);
-+ goto drop;
- }
- }
-
-@@ -1540,14 +1557,15 @@
- int len;
-
- if (proto == PPP_COMP) {
-- ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
-+ ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN);
- if (ns == 0) {
- printk(KERN_ERR "ppp_decompress_frame: no memory\n");
- goto err;
- }
- /* the decompressor still expects the A/C bytes in the hdr */
- len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
-- skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN);
-+ skb->len + 2, ns->data,
-+ ppp->mru_alloc + PPP_HDRLEN);
- if (len < 0) {
- /* Pass the compressed frame to pppd as an
- error indication. */
-@@ -1982,6 +2000,20 @@
- ocomp->comp_free(ostate);
- err = 0;
- }
-+ if (ccp_option[0] == CI_MPPE)
-+ /*
-+ * pppd (userland) has reduced the MTU by MPPE_PAD,
-+ * to accomodate "compressor" growth. We must
-+ * increase the space allocated for compressor
-+ * output in ppp_send_frame() accordingly. Note
-+ * that from a purist's view, it may be more correct
-+ * to require multilink and fragment large packets,
-+ * but that seems inefficient compared to this
-+ * little trick.
-+ */
-+ ppp->xpad = MPPE_PAD;
-+ else
-+ ppp->xpad = 0;
-
- } else {
- state = cp->decomp_alloc(ccp_option, data.length);
-@@ -2253,6 +2285,7 @@
- /* Initialize the new ppp unit */
- ppp->file.index = unit;
- ppp->mru = PPP_MRU;
-+ ppp->mru_alloc = PPP_MRU;
- init_ppp_file(&ppp->file, INTERFACE);
- ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
- for (i = 0; i < NUM_NP; ++i)
---- /dev/null
-+++ linux-2.4.27/drivers/net/ppp_mppe_compress.c
-@@ -0,0 +1,643 @@
-+/*
-+ * ==FILEVERSION 20020521==
-+ *
-+ * ppp_mppe_compress.c - interface MPPE to the PPP code.
-+ * This version is for use with Linux kernel 2.2.19+ and 2.4.x.
-+ *
-+ * By Frank Cusack <frank@google.com>.
-+ * Copyright (c) 2002 Google, Inc.
-+ * All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and distribute this software and its
-+ * documentation is hereby granted, provided that the above copyright
-+ * notice appears in all copies. This software is provided without any
-+ * warranty, express or implied.
-+ *
-+ * Changelog:
-+ * 2/15/04 - TS: added #include <version.h> and testing for Kernel
-+ * version before using
-+ * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are
-+ * depreciated in 2.6
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+
-+#include <linux/ppp_defs.h>
-+#include <linux/ppp-comp.h>
-+
-+#include "arcfour.h"
-+#include "sha1.h"
-+
-+/*
-+ * State for an MPPE (de)compressor.
-+ */
-+typedef struct ppp_mppe_state {
-+ unsigned char master_key[MPPE_MAX_KEY_LEN];
-+ unsigned char session_key[MPPE_MAX_KEY_LEN];
-+ arcfour_context arcfour_context; /* encryption state */
-+ unsigned keylen; /* key length in bytes */
-+ /* NB: 128-bit == 16, 40-bit == 8! */
-+ /* If we want to support 56-bit, */
-+ /* the unit has to change to bits */
-+ unsigned char bits; /* MPPE control bits */
-+ unsigned ccount; /* 12-bit coherency count (seqno) */
-+ unsigned stateful; /* stateful mode flag */
-+ int discard; /* stateful mode packet loss flag */
-+ int sanity_errors; /* take down LCP if too many */
-+ int unit;
-+ int debug;
-+ struct compstat stats;
-+} ppp_mppe_state;
-+
-+/* ppp_mppe_state.bits definitions */
-+#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */
-+#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */
-+#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */
-+#define MPPE_BIT_D 0x10 /* This is an encrypted frame */
-+
-+#define MPPE_BIT_FLUSHED MPPE_BIT_A
-+#define MPPE_BIT_ENCRYPTED MPPE_BIT_D
-+
-+#define MPPE_BITS(p) ((p)[4] & 0xf0)
-+#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5])
-+#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */
-+
-+#define MPPE_OVHD 2 /* MPPE overhead/packet */
-+#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */
-+
-+static void GetNewKeyFromSHA __P((unsigned char *StartKey,
-+ unsigned char *SessionKey,
-+ unsigned SessionKeyLength,
-+ unsigned char *InterimKey));
-+static void mppe_rekey __P((ppp_mppe_state *state, int));
-+static void *mppe_alloc __P((unsigned char *options, int optlen));
-+static void mppe_free __P((void *state));
-+static int mppe_init __P((void *state, unsigned char *options,
-+ int optlen, int unit, int debug, const char *));
-+static int mppe_comp_init __P((void *state, unsigned char *options,
-+ int optlen,
-+ int unit, int hdrlen, int debug));
-+static int mppe_decomp_init __P((void *state, unsigned char *options,
-+ int optlen, int unit,
-+ int hdrlen, int mru, int debug));
-+static int mppe_compress __P((void *state, unsigned char *ibuf,
-+ unsigned char *obuf,
-+ int isize, int osize));
-+static void mppe_incomp __P((void *state, unsigned char *ibuf, int icnt));
-+static int mppe_decompress __P((void *state, unsigned char *ibuf,
-+ int isize, unsigned char *obuf,int osize));
-+static void mppe_comp_reset __P((void *state));
-+static void mppe_decomp_reset __P((void *state));
-+static void mppe_comp_stats __P((void *state, struct compstat *stats));
-+
-+
-+/*
-+ * Key Derivation, from RFC 3078, RFC 3079.
-+ * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
-+ */
-+static void
-+GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey,
-+ unsigned SessionKeyLength, unsigned char *InterimKey)
-+{
-+ SHA1_CTX Context;
-+ unsigned char Digest[SHA1_SIGNATURE_SIZE];
-+
-+ unsigned char SHApad1[40] =
-+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-+ unsigned char SHApad2[40] =
-+ { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-+ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
-+
-+ /* assert(SessionKeyLength <= SHA1_SIGNATURE_SIZE); */
-+
-+ SHA1_Init(&Context);
-+ SHA1_Update(&Context, MasterKey, SessionKeyLength);
-+ SHA1_Update(&Context, SHApad1, sizeof(SHApad1));
-+ SHA1_Update(&Context, SessionKey, SessionKeyLength);
-+ SHA1_Update(&Context, SHApad2, sizeof(SHApad2));
-+ SHA1_Final(Digest, &Context);
-+
-+ memcpy(InterimKey, Digest, SessionKeyLength);
-+}
-+
-+/*
-+ * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3.
-+ * Well, not what's written there, but rather what they meant.
-+ */
-+static void
-+mppe_rekey(ppp_mppe_state *state, int initial_key)
-+{
-+ unsigned char InterimKey[MPPE_MAX_KEY_LEN];
-+
-+ GetNewKeyFromSHA(state->master_key, state->session_key,
-+ state->keylen, InterimKey);
-+ if (!initial_key) {
-+ arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen);
-+ arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen,
-+ state->session_key);
-+ } else {
-+ memcpy(state->session_key, InterimKey, state->keylen);
-+ }
-+ if (state->keylen == 8) {
-+ /* See RFC 3078 */
-+ state->session_key[0] = 0xd1;
-+ state->session_key[1] = 0x26;
-+ state->session_key[2] = 0x9e;
-+ }
-+ arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen);
-+}
-+
-+
-+/*
-+ * Allocate space for a (de)compressor.
-+ */
-+static void *
-+mppe_alloc(unsigned char *options, int optlen)
-+{
-+ ppp_mppe_state *state;
-+
-+ if (optlen != CILEN_MPPE + sizeof(state->master_key)
-+ || options[0] != CI_MPPE
-+ || options[1] != CILEN_MPPE)
-+ return NULL;
-+
-+ state = (ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL);
-+ if (state == NULL)
-+ return NULL;
-+
-+/*
-+ Added to avoid module warnings about MOD_INC
-+ being depreciated in 2.6.x
-+*/
-+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) )
-+ try_module_get(THIS_MODULE);
-+#else
-+ MOD_INC_USE_COUNT;
-+#endif
-+ memset(state, 0, sizeof(*state));
-+
-+ /* Save keys. */
-+ memcpy(state->master_key, &options[CILEN_MPPE], sizeof(state->master_key));
-+ memcpy(state->session_key, state->master_key, sizeof(state->master_key));
-+ /*
-+ * We defer initial key generation until mppe_init(), as mppe_alloc()
-+ * is called frequently during negotiation.
-+ */
-+
-+ return (void *) state;
-+}
-+
-+/*
-+ * Deallocate space for a (de)compressor.
-+ */
-+static void
-+mppe_free(void *arg)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ if (state) {
-+ kfree(state);
-+/*
-+ Added to avoid module warnings about MOD_DEC_USE_COUNT
-+ being depreciated in 2.6.x
-+*/
-+#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) )
-+ module_put(THIS_MODULE);
-+#else
-+ MOD_DEC_USE_COUNT;
-+#endif
-+ }
-+}
-+
-+
-+/*
-+ * Initialize (de)compressor state.
-+ */
-+static int
-+mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug,
-+ const char *debugstr)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ unsigned char mppe_opts;
-+
-+ if (optlen != CILEN_MPPE
-+ || options[0] != CI_MPPE
-+ || options[1] != CILEN_MPPE)
-+ return 0;
-+
-+ MPPE_CI_TO_OPTS(&options[2], mppe_opts);
-+ if (mppe_opts & MPPE_OPT_128)
-+ state->keylen = 16;
-+ else if (mppe_opts & MPPE_OPT_40)
-+ state->keylen = 8;
-+ else {
-+ printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, unit);
-+ return 0;
-+ }
-+ if (mppe_opts & MPPE_OPT_STATEFUL)
-+ state->stateful = 1;
-+
-+ /* Generate the initial session key. */
-+ mppe_rekey(state, 1);
-+
-+ if (debug) {
-+ int i;
-+ char mkey[sizeof(state->master_key) * 2 + 1];
-+ char skey[sizeof(state->session_key) * 2 + 1];
-+
-+ printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr,
-+ unit, (state->keylen == 16)? 128: 40,
-+ (state->stateful)? "stateful": "stateless");
-+
-+ for (i = 0; i < sizeof(state->master_key); i++)
-+ sprintf(mkey + i * 2, "%.2x", state->master_key[i]);
-+ for (i = 0; i < sizeof(state->session_key); i++)
-+ sprintf(skey + i * 2, "%.2x", state->session_key[i]);
-+ printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n",
-+ debugstr, unit, mkey, skey);
-+ }
-+
-+ /*
-+ * Initialize the coherency count. The initial value is not specified
-+ * in RFC 3078, but we can make a reasonable assumption that it will
-+ * start at 0. Setting it to the max here makes the comp/decomp code
-+ * do the right thing (determined through experiment).
-+ */
-+ state->ccount = MPPE_CCOUNT_SPACE - 1;
-+
-+ /*
-+ * Note that even though we have initialized the key table, we don't
-+ * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1.
-+ */
-+ state->bits = MPPE_BIT_ENCRYPTED;
-+
-+ state->unit = unit;
-+ state->debug = debug;
-+
-+ return 1;
-+}
-+
-+
-+
-+static int
-+mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit,
-+ int hdrlen, int debug)
-+{
-+ /* ARGSUSED */
-+ return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init");
-+}
-+
-+/*
-+ * We received a CCP Reset-Request (actually, we are sending a Reset-Ack),
-+ * tell the compressor to rekey. Note that we MUST NOT rekey for
-+ * every CCP Reset-Request; we only rekey on the next xmit packet.
-+ * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost.
-+ * So, rekeying for every CCP Reset-Request is broken as the peer will not
-+ * know how many times we've rekeyed. (If we rekey and THEN get another
-+ * CCP Reset-Request, we must rekey again.)
-+ */
-+static void
-+mppe_comp_reset(void *arg)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ state->bits |= MPPE_BIT_FLUSHED;
-+}
-+
-+/*
-+ * Compress (encrypt) a packet.
-+ * It's strange to call this a compressor, since the output is always
-+ * MPPE_OVHD + 2 bytes larger than the input.
-+ */
-+int
-+mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
-+ int isize, int osize)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ int proto;
-+
-+ /*
-+ * Check that the protocol is in the range we handle.
-+ */
-+ proto = PPP_PROTOCOL(ibuf);
-+ if (proto < 0x0021 || proto > 0x00fa)
-+ return 0;
-+
-+ /* Make sure we have enough room to generate an encrypted packet. */
-+ if (osize < isize + MPPE_OVHD + 2) {
-+ /* Drop the packet if we should encrypt it, but can't. */
-+ printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "
-+ "(have: %d need: %d)\n", state->unit,
-+ osize, osize + MPPE_OVHD + 2);
-+ return -1;
-+ }
-+
-+ osize = isize + MPPE_OVHD + 2;
-+
-+ /*
-+ * Copy over the PPP header and set control bits.
-+ */
-+ obuf[0] = PPP_ADDRESS(ibuf);
-+ obuf[1] = PPP_CONTROL(ibuf);
-+ obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */
-+ obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */
-+ obuf += PPP_HDRLEN;
-+
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ if (state->debug >= 7)
-+ printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
-+ state->ccount);
-+ obuf[0] = state->ccount >> 8;
-+ obuf[1] = state->ccount & 0xff;
-+
-+ if (!state->stateful || /* stateless mode */
-+ ((state->ccount & 0xff) == 0xff) || /* "flag" packet */
-+ (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */
-+ /* We must rekey */
-+ if (state->debug && state->stateful)
-+ printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", state->unit);
-+ mppe_rekey(state, 0);
-+ state->bits |= MPPE_BIT_FLUSHED;
-+ }
-+ obuf[0] |= state->bits;
-+ state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */
-+
-+ obuf += MPPE_OVHD;
-+ ibuf += 2; /* skip to proto field */
-+ isize -= 2;
-+
-+ /* Encrypt packet */
-+ arcfour_encrypt(&state->arcfour_context, ibuf, isize, obuf);
-+
-+ state->stats.unc_bytes += isize;
-+ state->stats.unc_packets++;
-+ state->stats.comp_bytes += osize;
-+ state->stats.comp_packets++;
-+
-+ return osize;
-+}
-+
-+/*
-+ * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going
-+ * to look bad ... and the longer the link is up the worse it will get.
-+ */
-+static void
-+mppe_comp_stats(void *arg, struct compstat *stats)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ *stats = state->stats;
-+}
-+
-+
-+static int
-+mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit,
-+ int hdrlen, int mru, int debug)
-+{
-+ /* ARGSUSED */
-+ return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init");
-+}
-+
-+/*
-+ * We received a CCP Reset-Ack. Just ignore it.
-+ */
-+static void
-+mppe_decomp_reset(void *arg)
-+{
-+ /* ARGSUSED */
-+ return;
-+}
-+
-+/*
-+ * Decompress (decrypt) an MPPE packet.
-+ */
-+int
-+mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
-+ int osize)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+ unsigned ccount;
-+ int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
-+ int sanity = 0;
-+
-+ if (isize <= PPP_HDRLEN + MPPE_OVHD) {
-+ if (state->debug)
-+ printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n",
-+ state->unit, isize);
-+ return DECOMP_ERROR;
-+ }
-+
-+ /* Make sure we have enough room to decrypt the packet. */
-+ if (osize < isize - MPPE_OVHD - 2) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "
-+ "(have: %d need: %d)\n", state->unit,
-+ osize, isize - MPPE_OVHD - 2);
-+ return DECOMP_ERROR;
-+ }
-+ osize = isize - MPPE_OVHD - 2;
-+
-+ ccount = MPPE_CCOUNT(ibuf);
-+ if (state->debug >= 7)
-+ printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", state->unit,
-+ ccount);
-+
-+ /* sanity checks -- terminate with extreme prejudice */
-+ if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
-+ state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+ if (!state->stateful && !flushed) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
-+ "stateless mode!\n", state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+ if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
-+ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
-+ "flag packet!\n", state->unit);
-+ state->sanity_errors += 100;
-+ sanity = 1;
-+ }
-+
-+ if (sanity) {
-+ if (state->sanity_errors < SANITY_MAX)
-+ return DECOMP_ERROR;
-+ else
-+ /*
-+ * Take LCP down if the peer is sending too many bogons.
-+ * We don't want to do this for a single or just a few
-+ * instances since it could just be due to packet corruption.
-+ */
-+ return DECOMP_FATALERROR;
-+ }
-+
-+ /*
-+ * Check the coherency count.
-+ */
-+
-+ if (!state->stateful) {
-+ /* RFC 3078, sec 8.1. Rekey for every packet. */
-+ while (state->ccount != ccount) {
-+ mppe_rekey(state, 0);
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ }
-+ } else {
-+ /* RFC 3078, sec 8.2. */
-+ if (!state->discard) {
-+ /* normal state */
-+ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-+ if (ccount != state->ccount) {
-+ /*
-+ * (ccount > state->ccount)
-+ * Packet loss detected, enter the discard state.
-+ * Signal the peer to rekey (by sending a CCP Reset-Request).
-+ */
-+ state->discard = 1;
-+ return DECOMP_ERROR;
-+ }
-+ } else {
-+ /* discard state */
-+ if (!flushed) {
-+ /* ccp.c will be silent (no additional CCP Reset-Requests). */
-+ return DECOMP_ERROR;
-+ } else {
-+ /* Rekey for every missed "flag" packet. */
-+ while ((ccount & ~0xff) != (state->ccount & ~0xff)) {
-+ mppe_rekey(state, 0);
-+ state->ccount = (state->ccount + 256) % MPPE_CCOUNT_SPACE;
-+ }
-+
-+ /* reset */
-+ state->discard = 0;
-+ state->ccount = ccount;
-+ /*
-+ * Another problem with RFC 3078 here. It implies that the
-+ * peer need not send a Reset-Ack packet. But RFC 1962
-+ * requires it. Hopefully, M$ does send a Reset-Ack; even
-+ * though it isn't required for MPPE synchronization, it is
-+ * required to reset CCP state.
-+ */
-+ }
-+ }
-+ if (flushed)
-+ mppe_rekey(state, 0);
-+ }
-+
-+ /*
-+ * Fill in the first part of the PPP header. The protocol field
-+ * comes from the decrypted data.
-+ */
-+ obuf[0] = PPP_ADDRESS(ibuf); /* +1 */
-+ obuf[1] = PPP_CONTROL(ibuf); /* +1 */
-+ obuf += 2;
-+ ibuf += PPP_HDRLEN + MPPE_OVHD;
-+ isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */
-+ /* net osize: isize-4 */
-+
-+ /* And finally, decrypt the packet. */
-+ arcfour_decrypt(&state->arcfour_context, ibuf, isize, obuf);
-+
-+ state->stats.unc_bytes += osize;
-+ state->stats.unc_packets++;
-+ state->stats.comp_bytes += isize;
-+ state->stats.comp_packets++;
-+
-+ /* good packet credit */
-+ state->sanity_errors >>= 1;
-+
-+ return osize;
-+}
-+
-+/*
-+ * Incompressible data has arrived (this should never happen!).
-+ * We should probably drop the link if the protocol is in the range
-+ * of what should be encrypted. At the least, we should drop this
-+ * packet. (How to do this?)
-+ */
-+static void
-+mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
-+{
-+ ppp_mppe_state *state = (ppp_mppe_state *) arg;
-+
-+ if (state->debug &&
-+ (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))
-+ printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! "
-+ "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));
-+
-+ state->stats.inc_bytes += icnt;
-+ state->stats.inc_packets++;
-+ state->stats.unc_bytes += icnt;
-+ state->stats.unc_packets++;
-+}
-+
-+/*************************************************************
-+ * Module interface table
-+ *************************************************************/
-+
-+/* These are in ppp.c (2.2.x) or ppp_generic.c (2.4.x) */
-+extern int ppp_register_compressor (struct compressor *cp);
-+extern void ppp_unregister_compressor (struct compressor *cp);
-+
-+/*
-+ * Procedures exported to if_ppp.c.
-+ */
-+struct compressor ppp_mppe = {
-+ CI_MPPE, /* compress_proto */
-+ mppe_alloc, /* comp_alloc */
-+ mppe_free, /* comp_free */
-+ mppe_comp_init, /* comp_init */
-+ mppe_comp_reset, /* comp_reset */
-+ mppe_compress, /* compress */
-+ mppe_comp_stats, /* comp_stat */
-+ mppe_alloc, /* decomp_alloc */
-+ mppe_free, /* decomp_free */
-+ mppe_decomp_init, /* decomp_init */
-+ mppe_decomp_reset, /* decomp_reset */
-+ mppe_decompress, /* decompress */
-+ mppe_incomp, /* incomp */
-+ mppe_comp_stats, /* decomp_stat */
-+};
-+
-+/* 2.2 compatibility defines */
-+#ifndef __init
-+#define __init
-+#endif
-+#ifndef __exit
-+#define __exit
-+#endif
-+#ifndef MODULE_LICENSE
-+#define MODULE_LICENSE(license)
-+#endif
-+
-+int __init
-+ppp_mppe_init(void)
-+{
-+ int answer = ppp_register_compressor(&ppp_mppe);
-+
-+ if (answer == 0)
-+ printk(KERN_INFO "PPP MPPE Compression module registered\n");
-+ return answer;
-+}
-+
-+void __exit
-+ppp_mppe_cleanup(void)
-+{
-+ ppp_unregister_compressor(&ppp_mppe);
-+}
-+
-+module_init(ppp_mppe_init);
-+module_exit(ppp_mppe_cleanup);
-+MODULE_LICENSE("BSD without advertisement clause");
---- /dev/null
-+++ linux-2.4.27/drivers/net/sha1.c
-@@ -0,0 +1,185 @@
-+/*
-+ * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
-+ *
-+ * SHA-1 in C
-+ * By Steve Reid <steve@edmweb.com>
-+ * 100% Public Domain
-+ *
-+ * Test Vectors (from FIPS PUB 180-1)
-+ * "abc"
-+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-+ * A million repetitions of "a"
-+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-+ */
-+
-+/* #define SHA1HANDSOFF * Copies data before messing with it. */
-+
-+#if defined(__linux__)
-+#include <asm/byteorder.h>
-+#include <linux/string.h>
-+#elif defined(__solaris__)
-+#include <sys/isa_defs.h>
-+#include <sys/ddi.h>
-+#include <sys/sunddi.h>
-+#define memcpy(d, s, c) bcopy(s, d, c)
-+#define memset(d, b, c) bzero(d, c)
-+#endif
-+
-+#include "sha1.h"
-+
-+static void SHA1_Transform(unsigned long[5], const unsigned char[64]);
-+
-+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-+
-+/* blk0() and blk() perform the initial expand. */
-+/* I got the idea of expanding during the round function from SSLeay */
-+#if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)
-+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-+ |(rol(block->l[i],8)&0x00FF00FF))
-+#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)
-+#define blk0(i) block->l[i]
-+#else
-+#error Endianness not defined
-+#endif
-+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-+ ^block->l[(i+2)&15]^block->l[i&15],1))
-+
-+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-+
-+
-+/* Hash a single 512-bit block. This is the core of the algorithm. */
-+
-+static void
-+SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
-+{
-+ unsigned long a, b, c, d, e;
-+ typedef union {
-+ unsigned char c[64];
-+ unsigned long l[16];
-+ } CHAR64LONG16;
-+ CHAR64LONG16 *block;
-+
-+#ifdef SHA1HANDSOFF
-+ static unsigned char workspace[64];
-+ block = (CHAR64LONG16 *) workspace;
-+ memcpy(block, buffer, 64);
-+#else
-+ block = (CHAR64LONG16 *) buffer;
-+#endif
-+ /* Copy context->state[] to working vars */
-+ a = state[0];
-+ b = state[1];
-+ c = state[2];
-+ d = state[3];
-+ e = state[4];
-+ /* 4 rounds of 20 operations each. Loop unrolled. */
-+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-+ /* Add the working vars back into context.state[] */
-+ state[0] += a;
-+ state[1] += b;
-+ state[2] += c;
-+ state[3] += d;
-+ state[4] += e;
-+ /* Wipe variables */
-+ a = b = c = d = e = 0;
-+}
-+
-+
-+/* SHA1Init - Initialize new context */
-+
-+void
-+SHA1_Init(SHA1_CTX *context)
-+{
-+ /* SHA1 initialization constants */
-+ context->state[0] = 0x67452301;
-+ context->state[1] = 0xEFCDAB89;
-+ context->state[2] = 0x98BADCFE;
-+ context->state[3] = 0x10325476;
-+ context->state[4] = 0xC3D2E1F0;
-+ context->count[0] = context->count[1] = 0;
-+}
-+
-+
-+/* Run your data through this. */
-+
-+void
-+SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
-+{
-+ unsigned int i, j;
-+
-+ j = (context->count[0] >> 3) & 63;
-+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-+ context->count[1] += (len >> 29);
-+ if ((j + len) > 63) {
-+ memcpy(&context->buffer[j], data, (i = 64-j));
-+ SHA1_Transform(context->state, context->buffer);
-+ for ( ; i + 63 < len; i += 64) {
-+ SHA1_Transform(context->state, &data[i]);
-+ }
-+ j = 0;
-+ }
-+ else
-+ i = 0;
-+
-+ memcpy(&context->buffer[j], &data[i], len - i);
-+}
-+
-+
-+/* Add padding and return the message digest. */
-+
-+void
-+SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
-+{
-+ unsigned long i, j;
-+ unsigned char finalcount[8];
-+
-+ for (i = 0; i < 8; i++) {
-+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
-+ }
-+ SHA1_Update(context, (unsigned char *) "\200", 1);
-+ while ((context->count[0] & 504) != 448) {
-+ SHA1_Update(context, (unsigned char *) "\0", 1);
-+ }
-+ SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
-+ for (i = 0; i < 20; i++) {
-+ digest[i] = (unsigned char)
-+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-+ }
-+ /* Wipe variables */
-+ i = j = 0;
-+ memset(context->buffer, 0, 64);
-+ memset(context->state, 0, 20);
-+ memset(context->count, 0, 8);
-+ memset(&finalcount, 0, 8);
-+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
-+ SHA1Transform(context->state, context->buffer);
-+#endif
-+}
-+
---- /dev/null
-+++ linux-2.4.27/drivers/net/sha1.h
-@@ -0,0 +1,18 @@
-+/* sha1.h */
-+
-+#ifndef _SHA1_H
-+#define _SHA1_H
-+
-+typedef struct {
-+ unsigned long state[5];
-+ unsigned long count[2];
-+ unsigned char buffer[64];
-+} SHA1_CTX;
-+
-+#define SHA1_SIGNATURE_SIZE 20
-+
-+extern void SHA1_Init(SHA1_CTX *);
-+extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
-+extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *);
-+
-+#endif /* _SHA1_H */
---- linux-2.4.27/include/linux/ppp-comp.h~mppe-20040216
-+++ linux-2.4.27/include/linux/ppp-comp.h
-@@ -187,6 +187,100 @@
- #define DEFLATE_CHK_SEQUENCE 0
-
- /*
-+ * Definitions for MPPE.
-+ */
-+
-+#define CI_MPPE 18 /* config option for MPPE */
-+#define CILEN_MPPE 6 /* length of config option */
-+
-+#define MPPE_PAD 4 /* MPPE growth per frame */
-+#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */
-+
-+/* option bits for ccp_options.mppe */
-+#define MPPE_OPT_40 0x01 /* 40 bit */
-+#define MPPE_OPT_128 0x02 /* 128 bit */
-+#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */
-+/* unsupported opts */
-+#define MPPE_OPT_56 0x08 /* 56 bit */
-+#define MPPE_OPT_MPPC 0x10 /* MPPC compression */
-+#define MPPE_OPT_D 0x20 /* Unknown */
-+#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
-+#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */
-+
-+/*
-+ * This is not nice ... the alternative is a bitfield struct though.
-+ * And unfortunately, we cannot share the same bits for the option
-+ * names above since C and H are the same bit. We could do a u_int32
-+ * but then we have to do a htonl() all the time and/or we still need
-+ * to know which octet is which.
-+ */
-+#define MPPE_C_BIT 0x01 /* MPPC */
-+#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */
-+#define MPPE_L_BIT 0x20 /* 40-bit */
-+#define MPPE_S_BIT 0x40 /* 128-bit */
-+#define MPPE_M_BIT 0x80 /* 56-bit, not supported */
-+#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */
-+
-+/* Does not include H bit; used for least significant octet only. */
-+#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
-+
-+/* Build a CI from mppe opts (see RFC 3078) */
-+#define MPPE_OPTS_TO_CI(opts, ci) \
-+ do { \
-+ u_char *ptr = ci; /* u_char[4] */ \
-+ \
-+ /* H bit */ \
-+ if (opts & MPPE_OPT_STATEFUL) \
-+ *ptr++ = 0x0; \
-+ else \
-+ *ptr++ = MPPE_H_BIT; \
-+ *ptr++ = 0; \
-+ *ptr++ = 0; \
-+ \
-+ /* S,L bits */ \
-+ *ptr = 0; \
-+ if (opts & MPPE_OPT_128) \
-+ *ptr |= MPPE_S_BIT; \
-+ if (opts & MPPE_OPT_40) \
-+ *ptr |= MPPE_L_BIT; \
-+ /* M,D,C bits not supported */ \
-+ } while (/* CONSTCOND */ 0)
-+
-+/* The reverse of the above */
-+#define MPPE_CI_TO_OPTS(ci, opts) \
-+ do { \
-+ u_char *ptr = ci; /* u_char[4] */ \
-+ \
-+ opts = 0; \
-+ \
-+ /* H bit */ \
-+ if (!(ptr[0] & MPPE_H_BIT)) \
-+ opts |= MPPE_OPT_STATEFUL; \
-+ \
-+ /* S,L bits */ \
-+ if (ptr[3] & MPPE_S_BIT) \
-+ opts |= MPPE_OPT_128; \
-+ if (ptr[3] & MPPE_L_BIT) \
-+ opts |= MPPE_OPT_40; \
-+ \
-+ /* M,D,C bits */ \
-+ if (ptr[3] & MPPE_M_BIT) \
-+ opts |= MPPE_OPT_56; \
-+ if (ptr[3] & MPPE_D_BIT) \
-+ opts |= MPPE_OPT_D; \
-+ if (ptr[3] & MPPE_C_BIT) \
-+ opts |= MPPE_OPT_MPPC; \
-+ \
-+ /* Other bits */ \
-+ if (ptr[0] & ~MPPE_H_BIT) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ if (ptr[1] || ptr[2]) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ if (ptr[3] & ~MPPE_ALL_BITS) \
-+ opts |= MPPE_OPT_UNKNOWN; \
-+ } while (/* CONSTCOND */ 0)
-+
-+/*
- * Definitions for other, as yet unsupported, compression methods.
- */
-
---- linux-2.4.27/drivers/net/Makefile~mppe-20040216
-+++ linux-2.4.27/drivers/net/Makefile
-@@ -18,8 +18,9 @@
- export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \
- ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
- net_init.o mii.o
--list-multi := rcpci.o
-+list-multi := rcpci.o ppp_mppe.o
- rcpci-objs := rcpci45.o rclanmtl.o
-+ppp_mppe-objs := ppp_mppe_compress.o sha1.o arcfour.o
-
- ifeq ($(CONFIG_TULIP),y)
- obj-y += tulip/tulip.o
-@@ -164,6 +165,14 @@
- obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
- obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
-
-+ifeq ($(CONFIG_PPP_MPPE),y)
-+ obj-y += $(ppp_mppe-objs)
-+else
-+ ifeq ($(CONFIG_PPP_MPPE),m)
-+ obj-m += ppp_mppe.o
-+ endif
-+endif
-+
- obj-$(CONFIG_SLIP) += slip.o
- ifeq ($(CONFIG_SLIP_COMPRESSED),y)
- obj-$(CONFIG_SLIP) += slhc.o
-@@ -272,3 +281,7 @@
-
- rcpci.o: $(rcpci-objs)
- $(LD) -r -o $@ $(rcpci-objs)
-+
-+ppp_mppe.o: $(ppp_mppe-objs)
-+ $(LD) -r -o $@ $(ppp_mppe-objs)
-+
diff --git a/recipes/linux/opensimpad/sa1100-usb-tcl1.patch b/recipes/linux/opensimpad/sa1100-usb-tcl1.patch
deleted file mode 100644
index da7f50d120..0000000000
--- a/recipes/linux/opensimpad/sa1100-usb-tcl1.patch
+++ /dev/null
@@ -1,216 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/arch/arm/mach-sa1100/sa1100_usb.h~sa1100-usb
-+++ linux-2.4.27/arch/arm/mach-sa1100/sa1100_usb.h
-@@ -10,6 +10,11 @@
- #define _SA1100_USB_H
- #include <asm/byteorder.h>
-
-+#define SA1100_USB_DEBUG
-+#ifdef SA1100_USB_DEBUG
-+extern int sa1100_usb_debug;
-+#endif
-+
- typedef void (*usb_callback_t)(int flag, int size);
-
- /* in usb_ctl.c (see also descriptor methods at bottom of file) */
---- linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.c~sa1100-usb
-+++ linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.c
-@@ -28,6 +28,12 @@
- #include "sa1100_usb.h"
- #include "usb_ctl.h"
-
-+// Toby Churchill Ltd modification to re assert Ser0UDCOMP when it gets corrupted (why?)
-+// Identified by Chris Jones for TCL.
-+// Added 25/3/2004 N C Bane for balloon board.
-+#define TCL_FIX
-+
-+
- //////////////////////////////////////////////////////////////////////////////
- // Prototypes
- //////////////////////////////////////////////////////////////////////////////
-@@ -109,6 +115,45 @@
- //////////////////////////////////////////////////////////////////////////////
- // Async
- //////////////////////////////////////////////////////////////////////////////
-+
-+#ifdef CONFIG_SA1100_USB_HOTPLUG
-+// user space notification support for sa1100 usb state change
-+// Copyright (c) 2003 N C Bane
-+#include <linux/kmod.h>
-+#include <linux/interrupt.h>
-+//static int usb_hotplug_state=USB_STATE_DEFAULT;
-+
-+static void do_usb_helper (void *status)
-+{
-+ char *argv [3], *envp [3];
-+ int v;
-+
-+ argv [0] = "/sbin/sausb-hotplug";
-+
-+ argv [1] = device_state_names[(int)status];
-+ argv [2] = NULL;
-+
-+ envp [0] = "HOME=/";
-+ envp [1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-+ envp [2] = NULL;
-+
-+ v = call_usermodehelper (argv [0], argv, envp);
-+
-+ if (v != 0)
-+ printk ("sausb hotplug returned 0x%x", v);
-+}
-+
-+static struct tq_struct usb_task;
-+
-+static void usb_helper (int status) {
-+// usb_hotplug_state = status;
-+ usb_task.routine=do_usb_helper;
-+ usb_task.data=(void *)status;
-+ schedule_task(&usb_task);
-+}
-+
-+#endif
-+
- static void core_kicker(void);
-
- static inline void enable_resume_mask_suspend( void );
-@@ -119,6 +164,7 @@
- {
- __u32 status = Ser0UDCSR;
-
-+//static int reset;
- /* ReSeT Interrupt Request - UDC has been reset */
- if ( status & UDCSR_RSTIR )
- {
-@@ -133,6 +179,7 @@
- // mask reset ints, they flood during sequence, enable
- // suspend and resume
- Ser0UDCCR |= UDCCR_REM; // mask reset
-+//reset=true;
- Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume
- UDC_flip( Ser0UDCSR, status ); // clear all pending sources
- return; // <-- no reason to continue if resetting
-@@ -160,6 +207,13 @@
- if (status & UDCSR_EIR)
- ep0_int_hndlr();
-
-+#ifdef TCL_FIX
-+ if (Ser0UDCOMP!=63) {
-+ printk("%s: Ser0UDCOMP = %d. Reset to 63\n",__FUNCTION__,Ser0UDCOMP);
-+ Ser0UDCOMP=63;
-+ }
-+#endif
-+
- if (status & UDCSR_RIR)
- ep1_int_hndlr(status);
-
-@@ -443,6 +497,12 @@
- ) {
- configured_callback();
- }
-+#ifdef CONFIG_SA1100_USB_HOTPLUG
-+ if (next_device_state == USB_STATE_CONFIGURED)
-+ usb_helper(next_device_state);
-+ if ((next_device_state == USB_STATE_SUSPENDED) && (usbd_info.state == USB_STATE_CONFIGURED))
-+ usb_helper(next_device_state);
-+#endif
- usbd_info.state = next_device_state;
- ep1_state_change_notify( next_device_state );
- ep2_state_change_notify( next_device_state );
-@@ -683,6 +743,43 @@
- return len;
- }
-
-+#ifdef SA1100_USB_DEBUG
-+#include <asm/uaccess.h> /* to copy to/from userspace */
-+struct proc_dir_entry *debug_entry;
-+
-+static int proc_debug_read (struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ char outputbuf[8];
-+ int count;
-+ // read completed?
-+ if (*ppos)
-+ return 0;
-+ count=sprintf(outputbuf, "%d\n",sa1100_usb_debug);
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+ return count;
-+}
-+
-+static ssize_t proc_debug_write(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ char *endp;
-+ if (*ppos)
-+ return -EINVAL;
-+ sa1100_usb_debug = simple_strtoul(buffer,&endp,0);
-+ // we claim all is read
-+ return count;
-+}
-+
-+
-+
-+static struct file_operations proc_debug_operations = {
-+ read: proc_debug_read,
-+ write: proc_debug_write
-+};
-+
-+#endif
- #endif /* CONFIG_PROC_FS */
-
- //////////////////////////////////////////////////////////////////////////////
-@@ -703,6 +800,15 @@
-
- #if CONFIG_PROC_FS
- create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL);
-+#ifdef SA1100_USB_DEBUG
-+ {
-+ debug_entry = create_proc_entry("sa1100_usb_debug",
-+ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH,
-+ &proc_root);
-+ if (debug_entry)
-+ debug_entry->proc_fops = &proc_debug_operations;
-+ }
-+#endif
- #endif
-
- /* setup rx dma */
-@@ -751,6 +857,9 @@
-
- #if CONFIG_PROC_FS
- remove_proc_entry ( PROC_NODE_NAME, NULL);
-+#ifdef SA1100_USB_DEBUG
-+ remove_proc_entry("sa1100_usb_debug",&proc_root);
-+#endif
- #endif
-
- sa1100_free_dma(usbd_info.dmach_rx);
-@@ -769,6 +878,10 @@
- EXPORT_SYMBOL( sa1100_usb_get_string_descriptor );
- EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor );
-
-+#ifdef SA1100_USB_DEBUG
-+int sa1100_usb_debug=0;
-+EXPORT_SYMBOL(sa1100_usb_debug);
-+#endif
-
- module_init( usbctl_init );
- module_exit( usbctl_exit );
---- linux-2.4.27/arch/arm/config.in~sa1100-usb
-+++ linux-2.4.27/arch/arm/config.in
-@@ -138,6 +138,9 @@
- dep_bool ' Yopy' CONFIG_SA1100_YOPY $CONFIG_ARCH_SA1100
-
- dep_tristate 'SA1100 USB function support' CONFIG_SA1100_USB $CONFIG_ARCH_SA1100
-+if [ "$CONFIG_SA1100_USB" != "n" ]; then
-+ bool ' Support for SA11x0 USB usb-hotplug' CONFIG_SA1100_USB_HOTPLUG
-+fi
- dep_tristate ' Support for SA11x0 USB network link function' CONFIG_SA1100_USB_NETLINK $CONFIG_SA1100_USB
- dep_tristate ' Support for SA11x0 USB character device emulation' CONFIG_SA1100_USB_CHAR $CONFIG_SA1100_USB
-
diff --git a/recipes/linux/opensimpad/simpad-backlight-if.patch b/recipes/linux/opensimpad/simpad-backlight-if.patch
deleted file mode 100644
index 4e04afb5e9..0000000000
--- a/recipes/linux/opensimpad/simpad-backlight-if.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/video/mq200fb.c~simpad-backlight-if
-+++ linux-2.4.27/drivers/video/mq200fb.c
-@@ -82,6 +82,20 @@
- write: proc_write_reg
- };
-
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+static ssize_t proc_read_light(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos);
-+static ssize_t proc_write_light(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos);
-+
-+static struct file_operations proc_light_operations = {
-+ read: proc_read_light,
-+ write: proc_write_light
-+};
-+#endif
-+
-+
- typedef struct sa1110_reg_entry {
- u32 phyaddr;
- char* name;
-@@ -622,6 +636,20 @@
- }
- }
-
-+#ifdef CONFIG_SA1100_SIMPAD
-+ entry = create_proc_entry("backlight",
-+ S_IRWXU | S_IRWXG | S_IRWXO,
-+ mq200dir);
-+ if(entry) {
-+ entry->proc_fops = &proc_light_operations;
-+ }
-+ else {
-+ printk( KERN_ERR
-+ "mq200fb: can't create /proc/" MQ200_DIRNAME
-+ "/backlight\n");
-+ return(-ENOMEM);
-+ }
-+ #endif
-
- #ifdef MQ_SA1110
-
-@@ -1879,7 +1907,7 @@
- static void writeBrightness(void *pMQMMIO, int brightness)
- {
- unsigned long dutyCycle, pwmcontrol;
-- int MAX_BRIGHT_REG = 0x000000fc; /* int 254 */
-+ int MAX_BRIGHT_REG = 0x000000fe; /* int 254 */
-
- if(brightness > MAX_BRIGHT_REG)
- return;
-@@ -1961,3 +1989,43 @@
- return (count+endp-buffer);
- }
-
-+#ifdef CONFIG_SA1100_SIMPAD
-+
-+#define SIMPAD_BACKLIGHT_MASK 0x00a10044
-+
-+static int proc_read_light(struct file * file, char * buf,
-+ size_t nbytes, loff_t *ppos)
-+{
-+ char outputbuf[15];
-+ int count;
-+ u32 pwmctl;
-+ if (*ppos>0) /* Assume reading completed in previous read*/
-+ return 0;
-+
-+ pwmctl = *((volatile *) mq200_p2v(0x4be0e03c));
-+ pwmctl &= ~SIMPAD_BACKLIGHT_MASK;
-+ pwmctl = pwmctl >> 8;
-+ pwmctl = 254 - pwmctl;
-+
-+ count = sprintf(outputbuf, "%d\n",pwmctl);
-+ *ppos+=count;
-+ if (count>nbytes) /* Assume output can be read at one time */
-+ return -EINVAL;
-+ if (copy_to_user(buf, outputbuf, count))
-+ return -EFAULT;
-+ return count;
-+}
-+
-+static ssize_t proc_write_light(struct file * file, const char * buffer,
-+ size_t count, loff_t *ppos)
-+{
-+ void * pMQMMIO = (void *) mqMmioAddr;
-+ char *endp;
-+ unsigned long newvalue = simple_strtoul(buffer,&endp,0);
-+ if (newvalue > 254)
-+ newvalue = 254;
-+ writeBrightness(pMQMMIO,newvalue);
-+ mq200_backlight(pMQMMIO,(int)newvalue);
-+ return (count+endp-buffer);
-+}
-+#endif
diff --git a/recipes/linux/opensimpad/simpad-proc-sys-board.patch b/recipes/linux/opensimpad/simpad-proc-sys-board.patch
deleted file mode 100644
index e6a7e12e5e..0000000000
--- a/recipes/linux/opensimpad/simpad-proc-sys-board.patch
+++ /dev/null
@@ -1,317 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/char/Makefile~simpad-proc-sys-board
-+++ linux-2.4.27/drivers/char/Makefile
-@@ -134,6 +134,9 @@
- ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
- KEYBD += cerf_keyb.o
- endif
-+ ifeq ($(CONFIG_SA1100_SIMPAD),y)
-+ obj-$(CONFIG_SA1100_SIMPAD) += sysctl.o
-+ endif
- ifeq ($(CONFIG_ARCH_FORTUNET),y)
- KEYMAP := defkeymap.o
- endif
---- /dev/null
-+++ linux-2.4.27/drivers/char/sysctl.c
-@@ -0,0 +1,297 @@
-+/*
-+ * /proc/sys/board - Interface to the SIMpad cs3 register
-+ *
-+ * (c) 2004 by Till Harbaum, BeeCon GmbH, <harbaum@beecon.de>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/sysctl.h>
-+#include <linux/crc32.h>
-+#include <linux/delay.h>
-+#include <linux/pm.h>
-+
-+#include <asm/io.h>
-+#include <asm/arch/simpad.h>
-+#include <asm/uaccess.h>
-+
-+extern long get_cs3_shadow(void);
-+extern void set_cs3_bit(int value);
-+extern void clear_cs3_bit(int value);
-+
-+/*
-+ * This is the number for the "board" entry in /proc/sys:
-+ */
-+#define SIMPAD_SYSCTL 1312
-+
-+/*
-+ * These are the numbers for the entries in /etc/sys/board
-+ */
-+enum {
-+ CTL_NAME=991,
-+ CTL_CS3, // the complete latch
-+ CTL_VCC_5V_EN, // For 5V PCMCIA
-+ CTL_VCC_3V_EN, // FOR 3.3V PCMCIA
-+ CTL_EN1, // This is only for EPROM's
-+ CTL_EN0, // Both should be enable for 3.3V or 5V
-+ CTL_DISPLAY_ON,
-+ CTL_PCMCIA_BUFF_DIS,
-+ CTL_MQ_RESET,
-+ CTL_PCMCIA_RESET,
-+ CTL_DECT_POWER_ON,
-+ CTL_IRDA_SD, // Shutdown for powersave
-+ CTL_RS232_ON,
-+ CTL_SD_MEDIAQ, // Shutdown for powersave
-+ CTL_LED2_ON,
-+ CTL_IRDA_MODE, // Fast/Slow IrDA mode
-+ CTL_ENABLE_5V, // Enable 5V circuit
-+ CTL_RESET_SIMCARD
-+};
-+
-+static const char simpad_board_name[] = "SIMpad";
-+static int dummy_int;
-+static char dummy_str[80];
-+
-+static int
-+simpad_sysctl_handler(ctl_table * ctl, int write, struct file *filp,
-+ void *buffer, size_t * lenp)
-+{
-+ int *valp = ctl->data;
-+ int val;
-+ int ret;
-+
-+ // Update parameters from the real registers
-+ switch (ctl->ctl_name) {
-+ case CTL_CS3:
-+ sprintf(dummy_str, "0x%04lx", get_cs3_shadow());
-+ return proc_dostring(ctl,write,filp,buffer,lenp);
-+ break;
-+
-+ // the 16 control bits of the cs3 register
-+ case CTL_VCC_5V_EN:
-+ case CTL_VCC_3V_EN:
-+ case CTL_EN1:
-+ case CTL_EN0:
-+ case CTL_DISPLAY_ON:
-+ case CTL_PCMCIA_BUFF_DIS:
-+ case CTL_MQ_RESET:
-+ case CTL_PCMCIA_RESET:
-+ case CTL_DECT_POWER_ON:
-+ case CTL_IRDA_SD:
-+ case CTL_RS232_ON:
-+ case CTL_SD_MEDIAQ:
-+ case CTL_LED2_ON:
-+ case CTL_IRDA_MODE:
-+ case CTL_ENABLE_5V:
-+ case CTL_RESET_SIMCARD:
-+ *valp = (get_cs3_shadow() &
-+ (1u << (ctl->ctl_name-CTL_VCC_5V_EN)))?1:0;
-+ break;
-+
-+ default:
-+ // Just ignore unsupported parameters
-+ break;
-+ }
-+
-+ // the strings are all handled now and ran onto a return;
-+
-+ // Save old state
-+ val = *valp;
-+
-+ // Perform the generic integer operation
-+ if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0)
-+ return (ret);
-+
-+ // Write changes out to the registers
-+ if (write && *valp != val) {
-+
-+ val = *valp;
-+ switch (ctl->ctl_name) {
-+
-+ // the 16 control bits of the cs3 register
-+ case CTL_DISPLAY_ON:
-+ case CTL_DECT_POWER_ON:
-+ case CTL_IRDA_SD:
-+ case CTL_SD_MEDIAQ:
-+ case CTL_LED2_ON:
-+ case CTL_IRDA_MODE:
-+ case CTL_RESET_SIMCARD:
-+ if (val)
-+ set_cs3_bit(1u << (ctl->ctl_name-CTL_VCC_5V_EN));
-+ else
-+ clear_cs3_bit(1u << (ctl->ctl_name-CTL_VCC_5V_EN));
-+ break;
-+
-+ default:
-+ // Just ignore unsupported parameters
-+ break;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+#define PROC_RDONLY 0444
-+#define PROC_RDWR 0664
-+
-+static ctl_table simpad_table[] = {
-+ {
-+ procname: "sys_name",
-+ ctl_name: CTL_NAME,
-+ data: &simpad_board_name,
-+ maxlen: sizeof(simpad_board_name),
-+ proc_handler: &proc_dostring,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "cs3",
-+ ctl_name: CTL_CS3,
-+ data: &dummy_str,
-+ maxlen: sizeof(dummy_str),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "vcc_5v_en",
-+ ctl_name: CTL_VCC_5V_EN,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "vcc_3v_en",
-+ ctl_name: CTL_VCC_3V_EN,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "en1",
-+ ctl_name: CTL_EN1,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "en0",
-+ ctl_name: CTL_EN0,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "display_on",
-+ ctl_name: CTL_DISPLAY_ON,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "pcmcia_buff_dis",
-+ ctl_name: CTL_PCMCIA_BUFF_DIS,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "mq_reset",
-+ ctl_name: CTL_MQ_RESET,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "pcmcia_reset",
-+ ctl_name: CTL_PCMCIA_RESET,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "dect_power_on",
-+ ctl_name: CTL_DECT_POWER_ON,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "irda_sd",
-+ ctl_name: CTL_IRDA_SD,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "rs232_on",
-+ ctl_name: CTL_RS232_ON,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "sd_mediaq",
-+ ctl_name: CTL_SD_MEDIAQ,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "led2_on",
-+ ctl_name: CTL_LED2_ON,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "irda_mode",
-+ ctl_name: CTL_IRDA_MODE,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ }, {
-+ procname: "enable_5v",
-+ ctl_name: CTL_ENABLE_5V,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDONLY,
-+ }, {
-+ procname: "reset_simcard",
-+ ctl_name: CTL_RESET_SIMCARD,
-+ data: &dummy_int,
-+ maxlen: sizeof(int),
-+ proc_handler: &simpad_sysctl_handler,
-+ mode: PROC_RDWR,
-+ },
-+ {0}
-+ };
-+
-+static ctl_table simpad_root_table[] = {
-+ {SIMPAD_SYSCTL, "board", NULL, 0, 0555, simpad_table},
-+ {0}
-+ };
-+
-+
-+static struct ctl_table_header *simpad_table_header;
-+
-+
-+static int __init simpad_sysctl_init(void)
-+{
-+ simpad_table_header = register_sysctl_table(simpad_root_table, 0);
-+ if (!simpad_table_header)
-+ return -ENOMEM;
-+ return 0;
-+}
-+
-+static void __exit simpad_sysctl_exit(void)
-+{
-+ unregister_sysctl_table(simpad_table_header);
-+}
-+
-+
-+module_init(simpad_sysctl_init);
-+module_exit(simpad_sysctl_exit);
-+
-+MODULE_AUTHOR("Till Harbaum <harbaum@beecon.de>");
-+MODULE_DESCRIPTION("Implements /proc/sys/board");
-+MODULE_LICENSE("GPL");
diff --git a/recipes/linux/opensimpad/simpad-serial.patch b/recipes/linux/opensimpad/simpad-serial.patch
deleted file mode 100644
index e54c682a06..0000000000
--- a/recipes/linux/opensimpad/simpad-serial.patch
+++ /dev/null
@@ -1,267 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h~simpad-serial
-+++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h
-@@ -16,7 +16,7 @@
- #error "include <asm/hardware.h> instead"
- #endif
-
--#define GPIO_UART1_RTS GPIO_GPIO14
-+#define GPIO_UART1_RTS GPIO_GPIO9
- #define GPIO_UART1_DTR GPIO_GPIO7
- #define GPIO_UART1_CTS GPIO_GPIO8
- #define GPIO_UART1_DCD GPIO_GPIO23
-@@ -31,12 +31,12 @@
- #define GPIO_POWER_BUTTON GPIO_GPIO0
- #define GPIO_UCB1300_IRQ GPIO_GPIO (22) /* UCB GPIO and touchscreen */
-
--#define IRQ_UART1_CTS IRQ_GPIO15
--#define IRQ_UART1_DCD GPIO_GPIO23
--#define IRQ_UART1_DSR GPIO_GPIO6
--#define IRQ_UART3_CTS GPIO_GPIO13
--#define IRQ_UART3_DCD GPIO_GPIO18
--#define IRQ_UART3_DSR GPIO_GPIO17
-+#define IRQ_GPIO_UART1_CTS IRQ_GPIO8
-+#define IRQ_GPIO_UART1_DCD IRQ_GPIO23
-+#define IRQ_GPIO_UART1_DSR IRQ_GPIO6
-+#define IRQ_GPIO_UART3_CTS IRQ_GPIO13
-+#define IRQ_GPIO_UART3_DCD IRQ_GPIO18
-+#define IRQ_GPIO_UART3_DSR IRQ_GPIO17
-
- #define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22
- #define IRQ_GPIO_POWER_BUTTON IRQ_GPIO0
---- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~simpad-serial
-+++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c
-@@ -22,9 +22,11 @@
-
- #include "generic.h"
-
-+#undef SIMPAD_UART_USE_IRQ // irq handling on CTS/DCD doesn't work yet
-+
- long cs3_shadow;
-
--long get_cs3_shadow()
-+long get_cs3_shadow(void)
- {
- return cs3_shadow;
- }
-@@ -107,18 +109,170 @@
- LAST_DESC
- };
-
-+#define SER_INFO(fmt, arg...) printk(KERN_INFO fmt "\n" , ## arg)
-+
-+static void simpad_uart_set_mctrl(struct uart_port *port, u_int mctrl)
-+{
-+ if (port->mapbase == _Ser1UTCR0) {
-+ /* internal serial port (ttySA1, DECT/Bluetooth) */
-+ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART1_RTS;
-+ else GPSR = GPIO_UART1_RTS;
-+
-+ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART1_DTR;
-+ else GPSR = GPIO_UART1_DTR;
-+ }
-+
-+ else if (port->mapbase == _Ser3UTCR0) {
-+ /* external serial port (ttySA0, RS232) */
-+ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART3_RTS;
-+ else GPSR = GPIO_UART3_RTS;
-+
-+ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART3_DTR;
-+ else GPSR = GPIO_UART3_DTR;
-+ }
-+}
-+
-+static u_int simpad_uart_get_mctrl(struct uart_port *port)
-+{
-+ u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-+
-+ if (port->mapbase == _Ser1UTCR0) {
-+ /* internal serial port (ttySA1, DECT/Bluetooth) */
-+ int gplr = GPLR;
-+ if (gplr & GPIO_UART1_DCD) ret &= ~TIOCM_CD;
-+ if (gplr & GPIO_UART1_CTS) ret &= ~TIOCM_CTS;
-+ if (gplr & GPIO_UART1_DSR) ret &= ~TIOCM_DSR;
-+ }
-+
-+ else if (port->mapbase == _Ser3UTCR0) {
-+ /* external serial port (ttySA0, RS232) */
-+ int gplr = GPLR;
-+ if (gplr & GPIO_UART3_DCD) ret &= ~TIOCM_CD;
-+ if (gplr & GPIO_UART3_CTS) ret &= ~TIOCM_CTS;
-+ if (gplr & GPIO_UART3_DSR) ret &= ~TIOCM_DSR;
-+ }
-+ return ret;
-+}
-+
- static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
- {
-- if (port->mapbase == (u_int)&Ser1UTCR0) {
-+ if (port->mapbase == (u_int)&Ser3UTCR0) {
- if (state)
- clear_cs3_bit(RS232_ON);
- else
- set_cs3_bit(RS232_ON);
- }
- }
-+/*
-+ * Enable/Disable wake up events for this serial port.
-+ * Obviously, we only support this on the normal COM port.
-+ */
-+static int simpad_uart_set_wake(struct uart_port *port, u_int enable)
-+{
-+ int err = -EINVAL;
-+
-+#if 0 // TODO: port management
-+ if (port->mapbase == _Ser3UTCR0) {
-+ if (enable)
-+ PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
-+ else
-+ PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
-+ err = 0;
-+ }
-+#endif
-+
-+ return err;
-+}
-+
-+#ifdef SIMPAD_UART_USE_IRQ
-+static void simpad_uart1_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ /* Note: should only call this if something has changed */
-+ uart_handle_dcd_change(port, !(GPLR & GPIO_UART1_DCD));
-+}
-+
-+static void simpad_uart1_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ /* Note: should only call this if something has changed */
-+ uart_handle_cts_change(port, !(GPLR & GPIO_UART1_CTS));
-+}
-+
-+static void simpad_uart3_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ /* Note: should only call this if something has changed */
-+ uart_handle_dcd_change(port, !(GPLR & GPIO_UART3_DCD));
-+}
-+
-+static void simpad_uart3_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-+{
-+ struct uart_port *port = dev_id;
-+ /* Note: should only call this if something has changed */
-+ uart_handle_cts_change(port, !(GPLR & GPIO_UART3_CTS));
-+}
-+#endif
-+
-+static int simpad_uart_open(struct uart_port *port)
-+{
-+ int ret = 0;
-+#ifdef SIMPAD_UART_USE_IRQ
-+ if (port->mapbase == _Ser1UTCR0) {
-+ set_GPIO_IRQ_edge(GPIO_UART1_DCD|GPIO_UART1_CTS,
-+ GPIO_BOTH_EDGES);
-+
-+ ret = request_irq(IRQ_GPIO_UART1_DCD, simpad_uart1_dcd_intr,
-+ 0, "UART1 DCD", port);
-+ if (ret)
-+ return ret;
-+
-+ ret = request_irq(IRQ_GPIO_UART1_CTS, simpad_uart1_cts_intr,
-+ 0, "UART1 CTS", port);
-+ if (ret)
-+ free_irq(IRQ_GPIO_UART1_DCD, port);
-+ }
-+
-+ else if (port->mapbase == _Ser3UTCR0) {
-+ set_GPIO_IRQ_edge(GPIO_UART3_DCD|GPIO_UART3_CTS,
-+ GPIO_BOTH_EDGES);
-+
-+ ret = request_irq(IRQ_GPIO_UART3_DCD, simpad_uart3_dcd_intr,
-+ 0, "UART3 DCD", port);
-+ if (ret)
-+ return ret;
-+
-+ ret = request_irq(IRQ_GPIO_UART3_CTS, simpad_uart3_cts_intr,
-+ 0, "UART3 CTS", port);
-+ if (ret)
-+ free_irq(IRQ_GPIO_UART3_DCD, port);
-+ }
-+#endif
-+ return ret;
-+}
-+
-+static void simpad_uart_close(struct uart_port *port)
-+{
-+#ifdef SIMPAD_UART_USE_IRQ
-+ if (port->mapbase == _Ser1UTCR0) {
-+ free_irq(IRQ_GPIO_UART1_DCD, port);
-+ free_irq(IRQ_GPIO_UART1_CTS, port);
-+ }
-+
-+ else if (port->mapbase == _Ser3UTCR0) {
-+ free_irq(IRQ_GPIO_UART3_DCD, port);
-+ free_irq(IRQ_GPIO_UART3_CTS, port);
-+ }
-+#endif
-+}
-
- static struct sa1100_port_fns simpad_port_fns __initdata = {
-- .pm = simpad_uart_pm,
-+ .set_mctrl = simpad_uart_set_mctrl,
-+ .get_mctrl = simpad_uart_get_mctrl,
-+ .pm = simpad_uart_pm,
-+ .set_wake = simpad_uart_set_wake,
-+ .open = simpad_uart_open,
-+ .close = simpad_uart_close,
- };
-
- static void __init simpad_map_io(void)
-@@ -129,13 +283,32 @@
- set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
- ENABLE_5V | nRESET_SIMCARD);
-
-+ sa1100_register_uart_fns(&simpad_port_fns);
-+
- //It is only possible to register 3 UART in serial_sa1100.c
- sa1100_register_uart(0, 3);
- sa1100_register_uart(1, 1);
-
-+ // txd and rxd use their alternate function
- GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
-+
-+ // the control lines are gpio
-+ GAFR &= ~(GPIO_UART1_RTS | GPIO_UART1_CTS | GPIO_UART1_DCD);
-+ GAFR &= ~(GPIO_UART1_DSR | GPIO_UART1_DTR);
-+ GAFR &= ~(GPIO_UART3_RTS | GPIO_UART3_CTS | GPIO_UART3_DCD);
-+ GAFR &= ~(GPIO_UART3_DSR | GPIO_UART3_DTR);
-+
-+ // txd, rts and dtr are outputs
- GPDR |= GPIO_UART_TXD;
-+ GPDR |= GPIO_UART1_RTS | GPIO_UART3_RTS;
-+ GPDR |= GPIO_UART1_DTR | GPIO_UART3_DTR;
-+
-+ // cts, dcd, dsr and rxd are inputs
-+ GPDR &= ~(GPIO_UART1_CTS | GPIO_UART3_CTS);
-+ GPDR &= ~(GPIO_UART1_DCD | GPIO_UART3_DCD);
-+ GPDR &= ~(GPIO_UART1_DSR | GPIO_UART3_DSR);
- GPDR &= ~GPIO_UART_RXD;
-+
- PPAR |= PPAR_UPR;
-
- set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE);
---- linux-2.4.27/drivers/video/mq200fb.c~simpad-serial
-+++ linux-2.4.27/drivers/video/mq200fb.c
-@@ -672,7 +672,7 @@
-
- #ifdef CONFIG_SA1100_SIMPAD
- GPDR |= (1<<3);
-- GAFR |= ~(1<<3);
-+ GAFR &= ~(1<<3);
- GPSR |= (1<<3);
- #endif
-
diff --git a/recipes/linux/opensimpad/simpad-switches-input.patch b/recipes/linux/opensimpad/simpad-switches-input.patch
deleted file mode 100644
index 792b1af427..0000000000
--- a/recipes/linux/opensimpad/simpad-switches-input.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/misc/switches.h~simpad-switches-input
-+++ linux-2.4.27/drivers/misc/switches.h
-@@ -25,4 +25,14 @@
- extern int switches_ucb1x00_init(void);
- extern void switches_ucb1x00_exit(void);
-
-+#ifdef CONFIG_SA1100_SIMPAD
-+#define SIMPAD_KEY_SUSPEND 0x0002
-+#define SIMPAD_KEY_WWW 0x0008
-+#define SIMPAD_KEY_ENTER 0x0010
-+#define SIMPAD_KEY_UP 0x0020
-+#define SIMPAD_KEY_DOWN 0x0040
-+#define SIMPAD_KEY_LEFT 0x0080
-+#define SIMPAD_KEY_RIGHT 0x0100
-+#endif
-+
- #endif /* !defined(_SWITCHES_H) */
---- linux-2.4.27/drivers/misc/switches-core.c~simpad-switches-input
-+++ linux-2.4.27/drivers/misc/switches-core.c
-@@ -16,6 +16,9 @@
- * 11 September 2001 - UCB1200 driver framework support added.
- *
- * 19 December 2001 - separated out SA-1100 and UCB1x00 code.
-+ *
-+ * 3 July 2004 - Added generating of keyboard events.
-+ * Florian Boor <florian@handhelds.org>
- */
-
- #include <linux/config.h>
-@@ -30,7 +33,11 @@
- #include <linux/slab.h>
- #include <linux/wait.h>
-
-+#include <linux/input.h>
-+
- #include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/keyboard.h>
-
- #include "switches.h"
-
-@@ -53,6 +60,19 @@
- DECLARE_WAIT_QUEUE_HEAD(switches_wait);
- LIST_HEAD(switches_event_queue);
-
-+#ifdef CONFIG_INPUT
-+static struct input_dev idev;
-+
-+int
-+dummy_k_translate(unsigned char scancode, unsigned char *keycode, char raw_mode)
-+{
-+ *keycode = scancode;
-+ return 1;
-+}
-+
-+extern int (*k_translate)(unsigned char, unsigned char *, char);
-+
-+#endif
-
- static ssize_t switches_read(struct file *file, char *buffer,
- size_t count, loff_t *pos)
-@@ -148,6 +168,31 @@
- {
- struct switches_action *action;
-
-+#ifdef CONFIG_INPUT
-+ /* create input events, the events to send depends on the platform */
-+#ifdef CONFIG_SA1100_SIMPAD
-+ if (machine_is_simpad()) {
-+ if (SWITCHES_COUNT(mask) > 0)
-+ {
-+ if (mask->events[0] & SIMPAD_KEY_SUSPEND)
-+ input_report_key(&idev, KEY_POWER, (mask->states[0] & SIMPAD_KEY_SUSPEND) ? 0 : 1);
-+ if (mask->events[0] & SIMPAD_KEY_ENTER)
-+ input_report_key(&idev, KEY_ENTER, (mask->states[0] & SIMPAD_KEY_ENTER) ? 1 : 0);
-+ if (mask->events[0] & SIMPAD_KEY_UP)
-+ input_report_key(&idev, KEY_UP, (mask->states[0] & SIMPAD_KEY_UP) ? 1 : 0);
-+ if (mask->events[0] & SIMPAD_KEY_DOWN)
-+ input_report_key(&idev, KEY_DOWN, (mask->states[0] & SIMPAD_KEY_DOWN) ? 1 : 0);
-+ if (mask->events[0] & SIMPAD_KEY_LEFT)
-+ input_report_key(&idev, KEY_LEFT, (mask->states[0] & SIMPAD_KEY_LEFT) ? 1 : 0);
-+ if (mask->events[0] & SIMPAD_KEY_RIGHT)
-+ input_report_key(&idev, KEY_RIGHT, (mask->states[0] & SIMPAD_KEY_RIGHT) ? 1 : 0);
-+ if (mask->events[0] & SIMPAD_KEY_WWW)
-+ input_report_key(&idev, KEY_F10, (mask->states[0] & SIMPAD_KEY_WWW) ? 1 : 0);
-+ }
-+ }
-+#endif
-+#endif
-+ /* take care of switches device */
- if ((switches_users > 0) && (SWITCHES_COUNT(mask) > 0)) {
-
- if ((action = (struct switches_action *)
-@@ -197,6 +242,21 @@
- return -EIO;
- }
-
-+#ifdef CONFIG_INPUT
-+ /* init input driver stuff */
-+ k_translate = dummy_k_translate;
-+ idev.evbit[0] = BIT(EV_KEY); /* handle key events */
-+
-+ idev.keybit[LONG(KEY_POWER)] |= BIT(KEY_POWER);
-+ idev.keybit[LONG(KEY_UP)] |= BIT(KEY_UP);
-+ idev.keybit[LONG(KEY_DOWN)] |= BIT(KEY_DOWN);
-+ idev.keybit[LONG(KEY_LEFT)] |= BIT(KEY_LEFT);
-+ idev.keybit[LONG(KEY_RIGHT)] |= BIT(KEY_RIGHT);
-+ idev.keybit[LONG(KEY_ENTER)] |= BIT(KEY_ENTER);
-+ idev.keybit[LONG(KEY_F10)] |= BIT(KEY_F10);
-+
-+ input_register_device(&idev);
-+#endif
- printk("Console switches initialized\n");
-
- return 0;
-@@ -214,6 +274,10 @@
- switches_ucb1x00_exit();
- #endif
-
-+#ifdef CONFIG_INPUT
-+ input_unregister_device(&idev);
-+#endif
-+
- if (misc_deregister(&switches_misc) < 0)
- printk(KERN_ERR "%s: unable to deregister misc device\n",
- SWITCHES_NAME);
diff --git a/recipes/linux/opensimpad/simpad-switches-input2.patch b/recipes/linux/opensimpad/simpad-switches-input2.patch
deleted file mode 100644
index 34529acabb..0000000000
--- a/recipes/linux/opensimpad/simpad-switches-input2.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/misc/switches-core.c~simpad-switches-input2
-+++ linux-2.4.27/drivers/misc/switches-core.c
-@@ -66,7 +66,32 @@
- int
- dummy_k_translate(unsigned char scancode, unsigned char *keycode, char raw_mode)
- {
-- *keycode = scancode;
-+ if (scancode == KEY_UP)
-+ *keycode = 144;
-+ else if (scancode == KEY_LEFT)
-+ *keycode = 146;
-+ else if (scancode == KEY_RIGHT)
-+ *keycode = 151;
-+ else if (scancode == KEY_DOWN)
-+ *keycode = 161;
-+ else if (scancode == 144)
-+ *keycode = KEY_UP;
-+ else if (scancode == 146)
-+ *keycode = KEY_LEFT;
-+ else if (scancode == 151)
-+ *keycode = KEY_RIGHT;
-+ else if (scancode == 161)
-+ *keycode = KEY_DOWN;
-+ else if (scancode == KEY_KP8)
-+ *keycode = KEY_UP;
-+ else if (scancode == KEY_KP4)
-+ *keycode = KEY_LEFT;
-+ else if (scancode == KEY_KP6)
-+ *keycode = KEY_RIGHT;
-+ else if (scancode == KEY_KP2)
-+ *keycode = KEY_DOWN;
-+ else
-+ *keycode = scancode;
- return 1;
- }
-
diff --git a/recipes/linux/opensimpad/simpad-ts-noninput.patch b/recipes/linux/opensimpad/simpad-ts-noninput.patch
deleted file mode 100644
index 20a908ea8c..0000000000
--- a/recipes/linux/opensimpad/simpad-ts-noninput.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/misc/ucb1x00-ts.c~simpad-ts-noninput
-+++ linux-2.4.27/drivers/misc/ucb1x00-ts.c
-@@ -35,7 +35,7 @@
- /*
- * Define this if you want the UCB1x00 stuff to talk to the input layer
- */
--#ifdef CONFIG_INPUT
-+#if defined(CONFIG_INPUT) && !defined(CONFIG_SA1100_SIMPAD)
- #define USE_INPUT
- #else
- #undef USE_INPUT
diff --git a/recipes/linux/opensimpad/sound-volume-reversed.patch b/recipes/linux/opensimpad/sound-volume-reversed.patch
deleted file mode 100644
index 495d8f9404..0000000000
--- a/recipes/linux/opensimpad/sound-volume-reversed.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/drivers/misc/ucb1x00-audio.c~sound-volume-reversed
-+++ linux-2.4.27/drivers/misc/ucb1x00-audio.c
-@@ -97,7 +97,7 @@
- ucba->output_level = gain | gain << 8;
- ucba->mod_cnt++;
- ucba->ctrl_b = (ucba->ctrl_b & 0xff00) |
-- ((gain * 31) / 100);
-+ (((100-gain) * 31) / 100);
- ucb1x00_reg_write(ucba->ucb, UCB_AC_B,
- ucba->ctrl_b);
- ret = 0;
diff --git a/recipes/linux/opensimpad/support-128mb-ram.patch b/recipes/linux/opensimpad/support-128mb-ram.patch
deleted file mode 100644
index f0cde06b57..0000000000
--- a/recipes/linux/opensimpad/support-128mb-ram.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#
-# Patch managed by http://www.holgerschurig.de/patcher.html
-#
-
---- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~support-128mb-ram
-+++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c
-@@ -83,11 +83,16 @@
- {
- #ifdef CONFIG_SA1100_SIMPAD_SINUSPAD
- SET_BANK( 0, 0xc0000000, 32*1024*1024 );
-+ mi->nr_banks = 1;
- #else
- SET_BANK( 0, 0xc0000000, 64*1024*1024 );
--#endif
- mi->nr_banks = 1;
-+#endif
-
-+#ifdef CONFIG_SA1100_SIMPAD_128M
-+ SET_BANK( 1, 0xc8000000, 64*1024*1024 );
-+ mi->nr_banks = 2;
-+#endif
- setup_ramdisk( 1, 0, 0, 8192 );
- setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
- }
---- linux-2.4.27/arch/arm/config.in~support-128mb-ram
-+++ linux-2.4.27/arch/arm/config.in
-@@ -130,6 +130,7 @@
- dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100
- if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then
- bool ' T-Sinus PAD' CONFIG_SA1100_SIMPAD_SINUSPAD
-+ bool ' Simpad with 128Mb RAM' CONFIG_SA1100_SIMPAD_128M
- fi
- dep_bool ' Simputer' CONFIG_SA1100_SIMPUTER $CONFIG_ARCH_SA1100
- dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100
diff --git a/recipes/linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb b/recipes/linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb
deleted file mode 100644
index 54be4f606b..0000000000
--- a/recipes/linux/opensimpad_2.4.25-vrs2-pxa1-jpm1.bb
+++ /dev/null
@@ -1,87 +0,0 @@
-DESCRIPTION = "Linux kernel for the SIEMENS SIMpad family of devices."
-SECTION = "kernel"
-LICENSE = "GPLv2"
-KV = "${@bb.data.getVar('PV',d,True).split('-')[0]}"
-VRSV = "${@bb.data.getVar('PV',d,True).split('-')[1]}"
-PXAV = "${@bb.data.getVar('PV',d,True).split('-')[2]}"
-JPMV = "${@bb.data.getVar('PV',d,True).split('-')[3]}"
-PR = "r22"
-
-COMPATIBLE_MACHINE = 'simpad'
-
-FILESPATHPKG =. "opensimpad-${PV}:opensimpad:"
-
-SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.4/linux-${KV}.tar.bz2;name=kernel \
- file://${KV}-${VRSV}.patch \
- file://${KV}-${VRSV}-${PXAV}.patch \
- file://${KV}-${VRSV}-${PXAV}-${JPMV}.patch \
- file://sound-volume-reversed.patch \
- file://disable-pcmcia-probe.patch \
- file://mkdep.patch \
- file://defconfig-${MACHINE} \
- http://www.openswan.org/download/old/openswan-2.2.0-kernel-2.4-klips.patch.gz;name=patch \
- file://mipv6-1.1-v2.4.25.patch \
- file://simpad-backlight-if.patch \
- file://simpad-switches-input.patch \
- file://simpad-switches-input2.patch \
- file://simpad-apm.diff;striplevel=0 \
- file://simpad-ts-noninput.patch \
- file://simpad-pm-updates.patch;striplevel=0 \
- file://support-128mb-ram.patch \
- file://mmc-spi.patch \
- file://iw249_we17-13.diff \
- file://iw240_we18-5.diff \
-"
-
-S = "${WORKDIR}/linux-${KV}"
-
-inherit kernel
-
-KERNEL_CCSUFFIX = "-3.3.4"
-COMPATIBLE_HOST = "arm.*-linux"
-
-SIMPAD_MEM = '${@bb.data.getVar("SIMPAD_MEMORY_SIZE",d,1) or "32"}'
-SIMPAD_RD = '${@bb.data.getVar("SIMPAD_RAMDISK_SIZE",d,1) or "32"}'
-export CMDLINE = '${@bb.data.getVar("SIMPAD_CMDLINE",d,1) or "mtdparts=sa1100:512k(boot),1m(kernel),14848k(root),-(home) console=ttySA root=1f02 noinitrd jffs2_orphaned_inodes=delete rootfstype=jffs2 "}'
-EXTRA_OEMAKE = ""
-
-module_conf_sa1100_ir = "alias irda0 sa1100_ir"
-
-do_configure() {
- install -m 0644 ${WORKDIR}/defconfig-${MACHINE} ${S}/.config || die "No default configuration for ${MACHINE} available."
-
- mem=${SIMPAD_MEM}
- rd=${SIMPAD_RD}
- mempos=`echo "obase=16; $mem * 1024 * 1024" | bc`
- rdsize=`echo "$rd * 1024" | bc`
- total=`expr $mem + $rd`
- addr=`echo "obase=16; ibase=16; C0000000 + $mempos" | bc`
-
- if [ "$rd" == "0" ]
- then
- echo "# CONFIG_MTD_MTDRAM is not set" >> ${S}/.config
- else
- echo "CONFIG_MTD_MTDRAM=y" >> ${S}/.config
- echo "CONFIG_MTDRAM_TOTAL_SIZE=$rdsize" >> ${S}/.config
- echo "CONFIG_MTDRAM_ERASE_SIZE=1" >> ${S}/.config
- echo "CONFIG_MTDRAM_ABS_POS=$addr" >> ${S}/.config
- fi
- if [ "$total" == "128" ]
- then
- echo "CCONFIG_SA1100_SIMPAD_128M=y" >> ${S}/.config
- else
- echo "# CONFIG_SA1100_SIMPAD_128M is not set" >> ${S}/.config
- fi
- if [ "$total" == "32" ]
- then
- echo "CONFIG_SA1100_SIMPAD_SINUSPAD=y" >> ${S}/.config
- else
- echo "# CONFIG_SA1100_SIMPAD_SINUSPAD is not set" >> ${S}/.config
- fi
- echo "CONFIG_CMDLINE=\"${CMDLINE} mem=${mem}M\"" >> ${S}/.config
- oe_runmake oldconfig
-}
-SRC_URI[kernel.md5sum] = "5fc8e9f43fa44ac29ddf9a9980af57d8"
-SRC_URI[kernel.sha256sum] = "877af8ed89e56af004bb0662c1a9cfc785b40c602f71a8bf81521991026cf2f0"
-SRC_URI[patch.md5sum] = "5c54040bba6fea2bfb47df01056e953f"
-SRC_URI[patch.sha256sum] = "d35213dc854f1e1a08512154c7a92fb94d9f0506cc5107f8b2f248412679fb53"
diff --git a/recipes/linux/opensimpad_2.4.27-vrs1-pxa1-jpm1.bb b/recipes/linux/opensimpad_2.4.27-vrs1-pxa1-jpm1.bb
deleted file mode 100644
index d93abc60a6..0000000000
--- a/recipes/linux/opensimpad_2.4.27-vrs1-pxa1-jpm1.bb
+++ /dev/null
@@ -1,96 +0,0 @@
-DESCRIPTION = "Linux kernel for the SIEMENS SIMpad family of devices."
-SECTION = "kernel"
-LICENSE = "GPLv2"
-KV = "${@bb.data.getVar('PV',d,True).split('-')[0]}"
-VRSV = "${@bb.data.getVar('PV',d,True).split('-')[1]}"
-PXAV = "${@bb.data.getVar('PV',d,True).split('-')[2]}"
-JPMV = "${@bb.data.getVar('PV',d,True).split('-')[3]}"
-USBV= "usb20040610"
-PR = "r4"
-
-COMPATIBLE_MACHINE = 'simpad'
-
-FILESPATHPKG =. "opensimpad-${PV}:opensimpad:"
-
-SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.4/linux-${KV}.tar.bz2;name=kernel \
- file://${KV}-${VRSV}.patch \
- file://${KV}-${VRSV}-${PXAV}.patch \
- file://${KV}-${VRSV}-${PXAV}-${JPMV}.patch \
- file://${KV}-mh1.patch \
- file://sound-volume-reversed.patch \
- file://disable-pcmcia-probe.patch \
- file://mkdep.patch \
- file://defconfig-${MACHINE} \
- http://www.openswan.org/download/old/openswan-2.2.0-kernel-2.4-klips.patch.gz;name=patch \
- file://mipv6-1.1-v${KV}.patch \
- file://simpad-backlight-if.patch \
- file://simpad-switches-input.patch \
- file://simpad-switches-input2.patch \
- file://simpad-apm.patch \
- file://simpad-ts-noninput.patch \
- file://simpad-pm-updates.patch \
- file://support-128mb-ram.patch \
- file://simpad-proc-sys-board.patch \
- file://simpad-serial.patch \
- file://mppe-20040216.patch \
- file://sa1100-usb-tcl1.patch \
- file://mmc-spi.patch \
- file://iw249_we17-13.diff \
- file://iw240_we18-5.diff \
-"
-# This applies right after the jpm patch but is useless until we
-# have sa1100_udc.c
-# file://${KV}-${VRSV}-${USBV}.patch \
-
-S = "${WORKDIR}/linux-${KV}"
-
-inherit kernel
-
-KERNEL_CCSUFFIX = "-3.3.4"
-COMPATIBLE_HOST = "arm.*-linux"
-
-SIMPAD_MEM = '${@bb.data.getVar("SIMPAD_MEMORY_SIZE",d,1) or "32"}'
-SIMPAD_RD = '${@bb.data.getVar("SIMPAD_RAMDISK_SIZE",d,1) or "32"}'
-export CMDLINE = '${@bb.data.getVar("SIMPAD_CMDLINE",d,1) or "mtdparts=sa1100:512k(boot),1m(kernel),14848k(root),-(home) console=ttySA root=1f02 noinitrd jffs2_orphaned_inodes=delete rootfstype=jffs2 "}'
-#EXTRA_OEMAKE = ""
-
-module_conf_sa1100_ir = "alias irda0 sa1100_ir"
-
-do_configure() {
- install -m 0644 ${WORKDIR}/defconfig-${MACHINE} ${S}/.config || die "No default configuration for ${MACHINE} available."
-
- mem=${SIMPAD_MEM}
- rd=${SIMPAD_RD}
- mempos=`echo "obase=16; $mem * 1024 * 1024" | bc`
- rdsize=`echo "$rd * 1024" | bc`
- total=`expr $mem + $rd`
- addr=`echo "obase=16; ibase=16; C0000000 + $mempos" | bc`
-
- if [ "$rd" == "0" ]
- then
- echo "# CONFIG_MTD_MTDRAM is not set" >> ${S}/.config
- else
- echo "CONFIG_MTD_MTDRAM=y" >> ${S}/.config
- echo "CONFIG_MTDRAM_TOTAL_SIZE=$rdsize" >> ${S}/.config
- echo "CONFIG_MTDRAM_ERASE_SIZE=1" >> ${S}/.config
- echo "CONFIG_MTDRAM_ABS_POS=$addr" >> ${S}/.config
- fi
- if [ "$total" == "128" ]
- then
- echo "CONFIG_SA1100_SIMPAD_128M=y" >> ${S}/.config
- else
- echo "# CONFIG_SA1100_SIMPAD_128M is not set" >> ${S}/.config
- fi
- if [ "$total" == "32" ]
- then
- echo "CONFIG_SA1100_SIMPAD_SINUSPAD=y" >> ${S}/.config
- else
- echo "# CONFIG_SA1100_SIMPAD_SINUSPAD is not set" >> ${S}/.config
- fi
- echo "CONFIG_CMDLINE=\"${CMDLINE} mem=${mem}M\"" >> ${S}/.config
- oe_runmake oldconfig
-}
-SRC_URI[kernel.md5sum] = "59a2e6fde1d110e2ffa20351ac8b4d9e"
-SRC_URI[kernel.sha256sum] = "4e4976724fb4c9340d5e9acc69f9d99789641384a6e1bbcc5323fc8832d6661a"
-SRC_URI[patch.md5sum] = "5c54040bba6fea2bfb47df01056e953f"
-SRC_URI[patch.sha256sum] = "d35213dc854f1e1a08512154c7a92fb94d9f0506cc5107f8b2f248412679fb53"